papergod 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +244 -0
  3. package/ROADMAP.md +171 -0
  4. package/example/main.tex +360 -0
  5. package/frontend/src/components/ui/badge.jsx +5 -0
  6. package/frontend/src/components/ui/button.jsx +24 -0
  7. package/frontend/src/components/workbench.jsx +182 -0
  8. package/frontend/src/lib/utils.js +6 -0
  9. package/frontend/src/main.jsx +19 -0
  10. package/frontend/src/theme.css +256 -0
  11. package/frontend/vite.config.js +23 -0
  12. package/package.json +73 -0
  13. package/papergod-demo.png +0 -0
  14. package/public/app.js +5480 -0
  15. package/public/brand/papergod-logo.png +0 -0
  16. package/public/i18n.js +95 -0
  17. package/public/index.html +480 -0
  18. package/public/pdf-sentence-mapping.js +142 -0
  19. package/public/react/app.js +209 -0
  20. package/public/react/assets/addon-fit-YJmn1quW.js +12 -0
  21. package/public/react/assets/addon-web-links-BWjmmSgS.js +12 -0
  22. package/public/react/assets/main.css +32 -0
  23. package/public/react/assets/xterm-BqvuqXEL.js +27 -0
  24. package/public/style.css +1462 -0
  25. package/src/cli.js +128 -0
  26. package/src/server/agent-adapters.js +1240 -0
  27. package/src/server/agent-errors.js +105 -0
  28. package/src/server/agent-runtime.js +81 -0
  29. package/src/server/agent.js +173 -0
  30. package/src/server/app-version.js +86 -0
  31. package/src/server/change-history.js +114 -0
  32. package/src/server/document-structure.js +174 -0
  33. package/src/server/index.js +1442 -0
  34. package/src/server/latex-structure.js +344 -0
  35. package/src/server/latex.js +67 -0
  36. package/src/server/library-engine.js +193 -0
  37. package/src/server/library-files.js +134 -0
  38. package/src/server/literature-review.js +122 -0
  39. package/src/server/orchestration-engine.js +662 -0
  40. package/src/server/paragraph-analysis.js +300 -0
  41. package/src/server/project-resources.js +290 -0
  42. package/src/server/project-store.js +808 -0
  43. package/src/server/prompt-manifest.js +300 -0
  44. package/src/server/references.js +425 -0
  45. package/src/server/review-panel.js +263 -0
  46. package/src/server/revise-workflow.js +278 -0
  47. package/src/server/revision-engine.js +607 -0
  48. package/src/server/security.js +16 -0
  49. package/src/server/text-extraction.js +149 -0
  50. package/src/server/workspace-browser.js +49 -0
  51. package/src/server/workspace-registry.js +143 -0
  52. package/src/server/workspace-terminal.js +99 -0
  53. package/src/server/workspace.js +223 -0
  54. package/src/server/zotero.js +98 -0
@@ -0,0 +1,182 @@
1
+ import {
2
+ BarChart3, BookMarked, BookOpen, Bot, Braces, FileCode, FolderKanban, FolderOpen,
3
+ Bug, Download, GitPullRequest, History, Library, Network, Play, PlayCircle, RefreshCw, Rocket, Save, ScanText,
4
+ Settings, Sparkles, SquareTerminal, Users, X,
5
+ } from 'lucide-react';
6
+ import { Button } from './ui/button.jsx';
7
+ import packageData from '../../../package.json';
8
+
9
+ function ProductHeader() {
10
+ return (
11
+ <header id="header">
12
+ <div className="brand-mark"><img className="brand-logo" src="/brand/papergod-logo.png" alt="" aria-hidden="true" /><span className="logo">Papergod</span><span id="active-workspace-name" title="Current workspace">Workspace</span></div>
13
+ <nav className="header-actions" aria-label="Workspace tools">
14
+ <Button id="library-open" variant="ghost" size="sm"><BookOpen size={14} /><span data-i18n="header.libraries">Writing libraries</span></Button>
15
+ <Button id="focus-annotation-open" variant="ghost" size="sm"><ScanText size={14} /><span data-i18n="header.focus">Focus annotation</span></Button>
16
+ <Button id="review-open" variant="ghost" size="sm"><GitPullRequest size={14} /><span data-i18n="header.review">Review &amp; revise</span></Button>
17
+ <Button id="peer-review-open" variant="ghost" size="sm"><Users size={14} /><span data-i18n="header.peerReview">Peer review</span></Button>
18
+ </nav>
19
+ <span id="status" role="status" aria-live="polite" />
20
+ <label className="language-control"><span data-i18n="language.label">Language</span><select id="language-select" aria-label="Language"><option value="en">English</option><option value="zh-CN">简体中文</option></select></label>
21
+ </header>
22
+ );
23
+ }
24
+
25
+ function Navigator() {
26
+ return (
27
+ <aside id="sidebar">
28
+ <div id="navigator-tabs" role="tablist" aria-label="Paper navigation"><button id="navigator-outline-tab" className="active" type="button" role="tab" aria-selected="true" data-i18n="nav.outline">Outline</button><button id="navigator-tools-tab" type="button" role="tab" aria-selected="false" data-i18n="nav.tools">Tools</button></div>
29
+ <section id="navigator-outline-panel" className="navigator-panel" role="tabpanel">
30
+ <div className="sidebar-heading"><h3 data-i18n="nav.paperOutline">Paper outline</h3><Button id="sync-outline" variant="ghost" size="icon" title="Synchronize outline" aria-label="Synchronize outline"><RefreshCw size={14} /></Button></div>
31
+ <div id="outline-tree"><div className="outline-empty" data-i18n="nav.openPaper">Open a paper</div></div>
32
+ </section>
33
+ <section id="navigator-tools-panel" className="navigator-panel hidden" role="tabpanel">
34
+ <div className="sidebar-heading"><h3 data-i18n="nav.workspaceTools">Workspace tools</h3></div>
35
+ <div className="tool-group">
36
+ <div className="tool-group-title" data-i18n="tools.group.workspace">Workspace</div>
37
+ <button id="tool-workspaces" type="button"><FolderKanban size={13} /><span data-i18n="tools.workspaces">Workspaces</span></button>
38
+ <button id="tool-references" type="button"><BookMarked size={13} /><span data-i18n="tools.references">References</span></button>
39
+ <button id="tool-terminal" type="button"><SquareTerminal size={13} /><span data-i18n="tools.terminal">Terminal</span></button>
40
+ <button id="tool-open-folder" type="button"><FolderOpen size={13} /><span data-i18n="tools.openFolder">Open paper folder</span></button>
41
+ </div>
42
+ <div className="tool-group">
43
+ <div className="tool-group-title" data-i18n="tools.group.ai">AI assistants</div>
44
+ <button id="tool-orchestration" type="button"><Network size={13} /><span data-i18n="tools.orchestration">Agent orchestration</span></button>
45
+ <button id="tool-analysis" type="button"><BarChart3 size={13} /><span data-i18n="tools.analysis">Paragraph analysis</span></button>
46
+ <button id="tool-agent-config" type="button"><Settings size={13} /><span data-i18n="tools.agentConfig">Agent configuration</span></button>
47
+ </div>
48
+ <div className="tool-group">
49
+ <div className="tool-group-title" data-i18n="tools.group.document">Document</div>
50
+ <button id="tool-show-source" type="button"><FileCode size={13} /><span data-i18n="tools.source">LaTeX source</span></button>
51
+ <button id="tool-compile" type="button"><PlayCircle size={13} /><span data-i18n="tools.compile">Compile PDF</span></button>
52
+ <button id="tool-change-history" type="button"><History size={13} /><span data-i18n="tools.changeHistory">Change history</span></button>
53
+ <button id="tool-libraries" type="button"><Library size={13} /><span data-i18n="tools.libraries">Writing libraries</span></button>
54
+ </div>
55
+ <div className="sidebar-heading tool-files-heading"><h3 data-i18n="tools.backendFiles">Backend files</h3></div><ul id="file-tree" />
56
+ </section>
57
+ <button id="version-status" className="version-status" type="button" aria-haspopup="dialog" aria-controls="version-overlay">
58
+ <span className="version-status-icon"><Download size={13} /></span>
59
+ <span className="version-status-copy"><span data-i18n="version.product">Papergod</span><strong id="current-version" data-current-version={packageData.version}>v{packageData.version}</strong></span>
60
+ <span id="version-update-badge" className="version-update-badge hidden" data-i18n="version.available">Update</span>
61
+ </button>
62
+ </aside>
63
+ );
64
+ }
65
+
66
+ function EditorWorkspace() {
67
+ return (
68
+ <main id="editor-panel">
69
+ <div id="editor-toolbar">
70
+ <div className="file-context"><Braces size={14} /><span id="current-file">main.tex</span></div>
71
+ <div id="workspace-view-switch" role="tablist" aria-label="Document view">
72
+ <button id="source-view-btn" className="view-tab active" type="button" role="tab" aria-selected="true" aria-controls="source-view" data-i18n="editor.source">Source</button>
73
+ <button id="preview-view-btn" className="view-tab" type="button" role="tab" aria-selected="false" aria-controls="preview-panel" disabled data-i18n="editor.preview">PDF Preview</button>
74
+ </div>
75
+ <Button id="history-open" variant="outline" size="sm" title="Change history"><History size={14} /><span data-i18n="history.title">Change history</span></Button>
76
+ <Button id="save-btn" variant="outline" size="sm" title="Save (Ctrl+S)"><Save size={14} /><span data-i18n="editor.save">Save</span></Button>
77
+ <Button id="compile-btn" variant="primary" size="sm" title="Compile LaTeX"><Play size={14} /><span data-i18n="editor.compile">Compile</span></Button>
78
+ </div>
79
+ <div id="workspace-view">
80
+ <section id="source-view" className="workspace-pane" role="tabpanel" aria-labelledby="source-view-btn"><textarea id="editor" /></section>
81
+ <section id="preview-panel" className="workspace-pane hidden" role="tabpanel" aria-labelledby="preview-view-btn">
82
+ <div id="pdf-preview" aria-label="Rendered PDF pages" />
83
+ <div id="preview-placeholder">Compile to render the paper</div>
84
+ </section>
85
+ </div>
86
+ </main>
87
+ );
88
+ }
89
+
90
+ function AssistantPanel() {
91
+ return (
92
+ <aside id="right-panel">
93
+ <div id="ai-panel">
94
+ <div id="ai-header"><span><Bot size={15} /><span data-i18n="ai.title">AI Assistant</span></span><select id="agent-provider-quick" aria-label="Active AI Agent"><option value="mock">Mock</option></select></div>
95
+ <div id="ai-module-list">
96
+ <section className="ai-module" id="agent-config-module">
97
+ <div className="ai-module-head"><div><span className="module-index">1</span><strong data-i18n="ai.agentConfig">Agent Configuration</strong></div><Button id="agent-config-open" variant="ghost" size="sm"><span data-i18n="ai.configure">Configure</span></Button></div>
98
+ <div id="agent-config-summary" data-i18n="ai.detecting">Detecting local Agents…</div>
99
+ </section>
100
+ <section className="ai-module" id="prompt-management-module">
101
+ <div className="ai-module-head"><div><span className="module-index">2</span><strong data-i18n="ai.promptManagement">Prompt Management</strong></div></div>
102
+ <details id="modification-intent-module">
103
+ <summary><span data-i18n="ai.intents">Modification intents</span><span id="modification-intent-count">0 queued</span></summary>
104
+ <div id="modification-intent-list"><div className="outline-empty" data-i18n="ai.intentsEmpty">Click PDF text to add revision comments.</div></div>
105
+ </details>
106
+ <div id="temporary-prompt-module">
107
+ <div className="prompt-management-label"><strong data-i18n="ai.tempPrompt">Temporary prompt</strong><span data-i18n="ai.thisRun">This run only</span></div>
108
+ <textarea id="ai-prompt" rows="4" placeholder="Add a one-time goal, constraint, or instruction…" data-i18n-placeholder="ai.tempPlaceholder" />
109
+ </div>
110
+ <Button id="prompt-preview-open" variant="outline" size="sm"><span data-i18n="ai.previewPrompt">Preview final prompt</span></Button>
111
+ </section>
112
+ <div id="prompt-context-compat" className="hidden" aria-hidden="true">
113
+ <div id="prompt-context-module"><div id="context-title">Whole document</div><div id="prompt-context-meta" /><pre id="prompt-context-excerpt" /></div>
114
+ <div id="context-definition-editor"><textarea id="context-summary" /><textarea id="context-prompt" /><div id="intent-field" className="hidden"><textarea id="context-intent" /></div><Button id="save-context">Save</Button><Button id="clear-context">Whole document</Button><span id="library-selection-status">Resources: auto</span></div>
115
+ </div>
116
+ <section className="ai-module invoke-module">
117
+ <Button id="ai-invoke" variant="primary"><Sparkles size={16} /><span data-i18n="ai.invoke">Invoke Agent</span><span id="ai-invoke-intent-count" className="hidden" /></Button>
118
+ </section>
119
+ </div>
120
+ <div id="library-usage" className="hidden" />
121
+ <div id="paragraph-draft" className="hidden" />
122
+ <div id="ai-suggestions" />
123
+ <div id="agent-activity" className="agent-activity idle">
124
+ <button id="agent-activity-toggle" type="button" aria-haspopup="dialog" aria-controls="agent-activity-details-overlay">
125
+ <span className="agent-activity-dot" aria-hidden="true" />
126
+ <span className="agent-activity-heading"><span id="agent-activity-label" data-i18n="activity.idle">Agent idle</span><span id="agent-activity-subtitle" data-i18n="activity.none">No Agent task has run in this session.</span></span>
127
+ <span id="agent-activity-elapsed">—</span>
128
+ <span className="agent-activity-detail-hint" data-i18n="activity.viewCli">View CLI</span>
129
+ </button>
130
+ <div id="agent-activity-panel">
131
+ <ol id="agent-activity-stages">
132
+ <li data-stage="prepare"><span className="activity-stage-index" /><span data-i18n="activity.context">Context</span></li>
133
+ <li data-stage="run"><span className="activity-stage-index" /><span data-i18n="activity.agent">Agent</span></li>
134
+ <li data-stage="apply"><span className="activity-stage-index" /><span data-i18n="activity.apply">Apply</span></li>
135
+ <li data-stage="compile"><span className="activity-stage-index" /><span data-i18n="activity.compile">Compile</span></li>
136
+ </ol>
137
+ <pre id="agent-activity-log" className="hidden" aria-hidden="true" data-i18n="activity.liveOutput">Live CLI output will appear here.</pre>
138
+ <div className="agent-activity-result hidden" id="agent-activity-result" />
139
+ <div className="agent-activity-actions"><button id="agent-activity-details" type="button" data-i18n="activity.details">CLI details</button><button id="agent-activity-cancel" className="hidden" type="button" data-i18n="activity.cancel">Cancel</button><button id="agent-activity-undo" className="hidden" type="button" data-i18n="activity.undo">Undo this revision</button></div>
140
+ </div>
141
+ </div>
142
+ </div>
143
+ </aside>
144
+ );
145
+ }
146
+
147
+ function VersionDialog() {
148
+ return (
149
+ <div id="version-overlay" className="compact-overlay hidden" role="dialog" aria-modal="true" aria-labelledby="version-title">
150
+ <section id="version-dialog" className="compact-dialog">
151
+ <header className="version-dialog-header">
152
+ <div className="version-dialog-heading">
153
+ <span className="version-dialog-icon"><Rocket size={20} /></span>
154
+ <div><span className="version-eyebrow" data-i18n="version.releaseNotes">Release notes</span><h2 id="version-title" data-i18n="version.upToDate">You’re up to date</h2></div>
155
+ </div>
156
+ <button id="version-close" type="button" aria-label="Close" data-i18n-aria-label="common.close"><X size={17} /></button>
157
+ </header>
158
+ <div className="version-dialog-body">
159
+ <div className="version-summary">
160
+ <div><span data-i18n="version.installed">Installed</span><strong id="version-installed">v{packageData.version}</strong></div>
161
+ <span className="version-arrow">→</span>
162
+ <div><span data-i18n="version.latest">Latest</span><strong id="version-latest">v{packageData.version}</strong></div>
163
+ <span id="version-date" className="version-date" />
164
+ </div>
165
+ <p id="version-check-note" className="version-check-note" data-i18n="version.checking">Checking for updates…</p>
166
+ <div id="version-notes" className="version-notes hidden">
167
+ <section><div className="version-section-title"><Rocket size={15} /><h3 data-i18n="version.whatsNew">What’s new</h3></div><ul id="version-highlights" /></section>
168
+ <section><div className="version-section-title version-section-title--fix"><Bug size={15} /><h3 data-i18n="version.fixes">Bug fixes</h3></div><ul id="version-fixes" /></section>
169
+ </div>
170
+ </div>
171
+ <footer className="version-dialog-footer">
172
+ <span data-i18n="version.safeNote">Review the release details before updating.</span>
173
+ <a id="version-release-link" className="ui-button ui-button--primary ui-button--sm hidden" target="_blank" rel="noreferrer"><Download size={14} /><span data-i18n="version.viewUpdate">View update</span></a>
174
+ </footer>
175
+ </section>
176
+ </div>
177
+ );
178
+ }
179
+
180
+ export function Workbench() {
181
+ return <div id="app"><ProductHeader /><Navigator /><EditorWorkspace /><AssistantPanel /><VersionDialog /></div>;
182
+ }
@@ -0,0 +1,6 @@
1
+ import { clsx } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+
4
+ export function cn(...inputs) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import { flushSync } from 'react-dom';
4
+ import { Workbench } from './components/workbench.jsx';
5
+ import '@xterm/xterm/css/xterm.css';
6
+ import './theme.css';
7
+
8
+ let terminalApiPromise;
9
+ globalThis.loadPapergodTerminal = () => {
10
+ terminalApiPromise ||= Promise.all([import('@xterm/xterm'), import('@xterm/addon-fit'), import('@xterm/addon-web-links')]).then(([xterm, fit, webLinks]) => ({ Terminal: xterm.Terminal, FitAddon: fit.FitAddon, WebLinksAddon: webLinks.WebLinksAddon }));
11
+ return terminalApiPromise;
12
+ };
13
+
14
+ const root = createRoot(document.getElementById('root'));
15
+ flushSync(() => root.render(<Workbench />));
16
+
17
+ import(/* @vite-ignore */ '/app.js').catch((error) => {
18
+ console.error('Papergod workflow failed to initialize', error);
19
+ });
@@ -0,0 +1,256 @@
1
+ :root {
2
+ color-scheme: light;
3
+ --sidebar-w: 244px;
4
+ --right-w: 380px;
5
+ --header-h: 56px;
6
+ --background: #ffffff;
7
+ --foreground: #18181b;
8
+ --card: #ffffff;
9
+ --muted: #f6f7f9;
10
+ --muted-foreground: #71717a;
11
+ --primary: #2563eb;
12
+ --primary-foreground: #ffffff;
13
+ --border: #e4e4e7;
14
+ --ring: rgba(37, 99, 235, .22);
15
+ --radius: 8px;
16
+ --bg-dark: var(--background);
17
+ --bg-panel: #fafafa;
18
+ --bg-input: #f4f4f5;
19
+ --text: var(--foreground);
20
+ --text-dim: var(--muted-foreground);
21
+ --accent: var(--primary);
22
+ --accent-hover: #1d4ed8;
23
+ --success: #15803d;
24
+ --error: #dc2626;
25
+ --warn: #b45309;
26
+ --badge-style: #7c3aed;
27
+ --badge-grammar: #a16207;
28
+ --badge-structure: #2563eb;
29
+ }
30
+
31
+ html, body, #root { height: 100%; }
32
+
33
+ body {
34
+ background: var(--background);
35
+ color: var(--foreground);
36
+ font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
37
+ -webkit-font-smoothing: antialiased;
38
+ }
39
+
40
+ button, input, textarea, select { font: inherit; }
41
+
42
+ button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible, summary:focus-visible {
43
+ outline: 2px solid var(--ring);
44
+ outline-offset: 1px;
45
+ }
46
+
47
+ #app { background: var(--background); }
48
+
49
+ #header {
50
+ gap: 6px;
51
+ padding: 0 14px;
52
+ background: rgba(255, 255, 255, .96);
53
+ border-color: var(--border);
54
+ }
55
+
56
+ .brand-mark { display: flex; align-items: center; gap: 8px; min-width: calc(var(--sidebar-w) - 14px); color: #27272a; }
57
+ .brand-logo { width: 32px; height: 32px; flex: none; object-fit: contain; }
58
+ .logo { color: #18181b; font-size: 15px; letter-spacing: -.02em; }
59
+ .header-actions { display: flex; align-items: center; gap: 2px; }
60
+
61
+ .ui-button {
62
+ display: inline-flex;
63
+ align-items: center;
64
+ justify-content: center;
65
+ gap: 6px;
66
+ border: 1px solid transparent;
67
+ border-radius: 7px;
68
+ white-space: nowrap;
69
+ font-weight: 500;
70
+ cursor: pointer;
71
+ transition: color .15s ease, background .15s ease, border-color .15s ease, box-shadow .15s ease;
72
+ }
73
+ .ui-button:disabled { pointer-events: none; opacity: .45; }
74
+ .ui-button--md { min-height: 36px; padding: 8px 13px; font-size: 12px; }
75
+ .ui-button--sm { min-height: 30px; padding: 6px 9px; font-size: 11px; }
76
+ .ui-button--icon { width: 30px; height: 30px; padding: 0; }
77
+ .ui-button--default, .ui-button--outline { color: #3f3f46; background: #fff; border-color: var(--border); }
78
+ .ui-button--default:hover, .ui-button--outline:hover { background: #f4f4f5; border-color: #d4d4d8; }
79
+ .ui-button--ghost { color: #52525b; background: transparent; }
80
+ .ui-button--ghost:hover { color: #18181b; background: #f4f4f5; }
81
+ .ui-button--primary { color: #fff; background: var(--primary); border-color: var(--primary); box-shadow: 0 1px 2px rgba(37, 99, 235, .12); }
82
+ .ui-button--primary:hover { background: #1d4ed8; border-color: #1d4ed8; }
83
+
84
+ .ui-badge {
85
+ display: inline-flex;
86
+ align-items: center;
87
+ border: 1px solid var(--border);
88
+ border-radius: 999px;
89
+ padding: 3px 8px;
90
+ color: #71717a;
91
+ background: #fff;
92
+ font-size: 10px;
93
+ font-weight: 500;
94
+ line-height: 1;
95
+ }
96
+
97
+ #status { margin-left: auto; }
98
+ #status.success { color: var(--success); background: #f0fdf4; }
99
+ #status.error { color: var(--error); background: #fef2f2; }
100
+ .language-control { display: inline-flex; align-items: center; gap: 5px; color: #71717a; font-size: 10px; }
101
+ .language-control select { min-height: 26px; padding: 3px 22px 3px 7px; border: 1px solid var(--border); border-radius: 6px; color: #3f3f46; background: #fff; font-size: 10px; }
102
+
103
+ #sidebar {
104
+ padding: 12px 10px;
105
+ background: #fafafa;
106
+ border-color: var(--border);
107
+ scrollbar-width: thin;
108
+ }
109
+ #sidebar h3 { color: #a1a1aa; font-size: 10px; letter-spacing: .08em; }
110
+ .sidebar-heading { padding: 0 8px; }
111
+ .outline-heading { margin-top: 18px; padding-top: 14px; }
112
+ #sync-outline { color: #71717a; font-size: inherit; }
113
+ #file-tree li { margin: 2px 0; padding: 7px 9px; border-radius: 6px; color: #52525b; font-size: 12px; }
114
+ #file-tree li:hover { background: #f0f0f2; }
115
+ #file-tree li.active { color: #1d4ed8; background: #eff6ff; font-weight: 600; }
116
+ .outline-document { color: #1d4ed8; }
117
+ .outline-node.selected, .outline-document.selected { color: #1d4ed8; background: #eff6ff; }
118
+ .outline-node:hover, .outline-document:hover { background: #f0f0f2; }
119
+
120
+ #editor-panel { background: #fff; }
121
+ #editor-toolbar { min-height: 48px; padding: 7px 12px; background: #fff; border-color: var(--border); }
122
+ .file-context { display: flex; align-items: center; gap: 7px; flex: 1; color: #a1a1aa; }
123
+ #current-file { flex: initial; color: #52525b; font-size: 12px; }
124
+ #workspace-view-switch { padding: 3px; background: #f4f4f5; border: 0; border-radius: 7px; }
125
+ #editor-toolbar #workspace-view-switch .view-tab { min-height: 27px; padding: 4px 10px; border-radius: 5px; color: #71717a; }
126
+ #editor-toolbar #workspace-view-switch .view-tab:hover:not(:disabled) { color: #3f3f46; background: #e9e9ec; }
127
+ #editor-toolbar #workspace-view-switch .view-tab.active { color: #27272a; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .08); }
128
+ #editor-toolbar > button { padding: 6px 9px; border-radius: 7px; background: #fff; color: #3f3f46; }
129
+ #editor-toolbar > button:hover { color: #18181b; background: #f4f4f5; border-color: #d4d4d8; }
130
+ #editor-toolbar > #compile-btn { color: #fff; background: var(--primary); border-color: var(--primary); }
131
+ #editor-toolbar > #compile-btn:hover { color: #fff; background: #1d4ed8; border-color: #1d4ed8; }
132
+
133
+ .CodeMirror { background: #fff; color: #27272a; font-size: 13px; line-height: 1.65; }
134
+ .CodeMirror-gutters { background: #fafafa; border-color: #eeeeef; }
135
+ .CodeMirror-linenumber { color: #b4b4bc; }
136
+ .CodeMirror-cursor { border-left-color: #18181b; }
137
+ .CodeMirror-selected { background: #dbeafe !important; }
138
+ .cm-s-default .cm-keyword { color: #7c3aed; }
139
+ .cm-s-default .cm-tag { color: #2563eb; }
140
+ .cm-s-default .cm-bracket { color: #71717a; }
141
+ .cm-s-default .cm-comment { color: #16a34a; }
142
+ .cm-s-default .cm-string { color: #b45309; }
143
+
144
+ #right-panel { background: #fafafa; border-color: var(--border); }
145
+ #ai-header { display: flex; align-items: center; min-height: 48px; padding: 8px 12px; color: #52525b; background: #fafafa; border-color: var(--border); }
146
+ #ai-header > span:first-child { display: inline-flex; align-items: center; gap: 7px; font-size: 11px; font-weight: 600; }
147
+ #agent-provider-quick { color: #2563eb; background-color: #eff6ff; border-color: #dbeafe; }
148
+ #ai-module-list { max-height: 72%; background: #fafafa; border-color: var(--border); }
149
+ .ai-module { padding: 13px 12px; border-color: var(--border); }
150
+ .ai-module-head { margin-bottom: 8px; }
151
+ .ai-module-head strong { color: #3f3f46; font-size: 11px; }
152
+ .ai-module-head > span, #agent-config-summary, #prompt-context-meta { font-size: 10px; }
153
+ .module-index { width: 19px; height: 19px; color: #52525b; background: #eeeeef; }
154
+ .ai-module-head button, #context-definition-editor button { min-height: 26px; border-color: transparent; background: transparent; color: #71717a; }
155
+ .ai-module-head button:hover, #context-definition-editor button:hover { color: #18181b; background: #eeeeef; border-color: transparent; }
156
+ #agent-config-summary { color: #2563eb; }
157
+ #prompt-management-module #modification-intent-module { background: #fff; border-color: #e4e4e7; }
158
+ #prompt-management-module #prompt-preview-open { color: #3f3f46; background: #fff; border-color: #d4d4d8; }
159
+ #prompt-management-module #prompt-preview-open:hover { color: #18181b; background: #f4f4f5; }
160
+ #context-title { color: #27272a; }
161
+ #prompt-context-excerpt { color: #71717a; background: #f4f4f5; border: 1px solid #eeeeef; }
162
+ #context-definition-editor textarea, #temporary-prompt-module textarea,
163
+ #context-panel textarea, #ai-prompt { color: #27272a; background: #fff; border-color: #d4d4d8; border-radius: 7px; }
164
+ #context-definition-editor textarea:focus, #temporary-prompt-module textarea:focus,
165
+ #context-panel textarea:focus, #ai-prompt:focus { border-color: #93c5fd; box-shadow: 0 0 0 3px var(--ring); outline: none; }
166
+ #ai-invoke { min-height: 38px; border-radius: 7px; color: #fff; background: #18181b; border-color: #18181b; font-size: 12px; }
167
+ #ai-invoke:hover { background: #27272a; border-color: #27272a; }
168
+ #ai-suggestions { background: #fff; }
169
+
170
+ #preview-panel, #preview-placeholder { background: #f1f5f9; }
171
+ .pdf-page { box-shadow: 0 1px 3px rgba(15, 23, 42, .12), 0 10px 30px rgba(15, 23, 42, .06); }
172
+
173
+ .compact-overlay, #focus-annotation-overlay, #library-overlay, #review-overlay, #peer-review-overlay { background: rgba(24, 24, 27, .28); backdrop-filter: blur(2px); }
174
+ .compact-dialog, #focus-annotation-dialog, #library-drawer, #review-drawer, #peer-review-drawer { background: #fff; border-color: var(--border); box-shadow: 0 20px 60px rgba(24, 24, 27, .14); }
175
+ .library-header { background: #fff; border-color: var(--border); }
176
+ .library-header h2 { color: #18181b; }
177
+ .library-header button { color: #71717a; }
178
+ .library-toolbar, #review-workflow-tabs, .focus-column-heading { background: #fafafa; }
179
+ #prompt-preview-content, #prompt-preview-manifest, .focus-reading-text, .suggestion .diff, .annotation-item blockquote,
180
+ .change-before, .peer-finding, .peer-finding blockquote, .response-letter-form, .mini-diff del,
181
+ .mini-diff ins, #paper-generation-preview pre { color: #334155; background: #f8fafc; }
182
+ .prompt-manifest-details { border-color: var(--border); background: #fff; }
183
+ .prompt-manifest-details summary { color: #2563eb; background: #f8fafc; }
184
+ .prompt-manifest-details summary:hover { color: #1d4ed8; background: #eff6ff; }
185
+ #prompt-preview-manifest { border-top: 1px solid #e4e4e7; }
186
+ .focus-sentence-card, .agent-provider-card, .annotation-item, .revision-card, .reviewer-draft,
187
+ .rubric-draft, .peer-review-card, .self-revision-card, .library-item, .candidate-item { background: #fff; }
188
+ .focus-paragraph-button:hover, .focus-paragraph-button.active, .revision-head, .peer-review-head,
189
+ .self-revision-head { background: #f4f4f5; }
190
+ #library-usage, .peer-synthesis { background: #eff6ff; }
191
+ #paragraph-draft, #paper-generation-preview, .verification.complete { background: #f0fdf4; }
192
+ .verification.incomplete { background: #fffbeb; }
193
+
194
+ input, textarea, select { accent-color: var(--primary); }
195
+ input::placeholder, textarea::placeholder { color: #a1a1aa; }
196
+
197
+ #sidebar { display: flex; flex-direction: column; overflow: hidden; }
198
+ #navigator-tabs { flex: none; }
199
+ .navigator-panel { flex: 1; }
200
+ .version-status {
201
+ display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; align-items: center; gap: 8px;
202
+ width: 100%; margin-top: 10px; padding: 9px 8px; border: 1px solid transparent; border-radius: 8px;
203
+ color: #71717a; background: transparent; text-align: left; cursor: pointer;
204
+ }
205
+ .version-status:hover { color: #3f3f46; background: #f4f4f5; border-color: #e4e4e7; }
206
+ .version-status.has-update { color: #1e40af; background: #eff6ff; border-color: #bfdbfe; }
207
+ .version-status.has-update:hover { background: #dbeafe; border-color: #93c5fd; }
208
+ .version-status-icon { display: grid; width: 28px; height: 28px; place-items: center; border-radius: 7px; color: #71717a; background: #eeeeef; }
209
+ .version-status.has-update .version-status-icon { color: #2563eb; background: #dbeafe; }
210
+ .version-status-copy { display: grid; gap: 2px; min-width: 0; }
211
+ .version-status-copy > span { font-size: 9px; font-weight: 500; }
212
+ .version-status-copy strong { color: #3f3f46; font-size: 11px; font-weight: 650; }
213
+ .version-update-badge { padding: 4px 7px; border-radius: 999px; color: #fff; background: #2563eb; font-size: 9px; font-weight: 700; }
214
+
215
+ #version-dialog { width: min(620px, 94vw); border-radius: 14px; }
216
+ .version-dialog-header { display: flex; align-items: center; justify-content: space-between; padding: 20px 22px; border-bottom: 1px solid var(--border); }
217
+ .version-dialog-heading { display: flex; align-items: center; gap: 12px; }
218
+ .version-dialog-icon { display: grid; width: 40px; height: 40px; place-items: center; border-radius: 10px; color: #2563eb; background: #eff6ff; }
219
+ .version-eyebrow { display: block; margin-bottom: 3px; color: #2563eb; font-size: 9px; font-weight: 750; letter-spacing: .08em; text-transform: uppercase; }
220
+ .version-dialog-header h2 { color: #18181b; font-size: 18px; letter-spacing: -.02em; }
221
+ #version-close { display: grid; width: 32px; height: 32px; place-items: center; border: 0; border-radius: 7px; color: #71717a; background: transparent; cursor: pointer; }
222
+ #version-close:hover { color: #18181b; background: #f4f4f5; }
223
+ .version-dialog-body { padding: 20px 22px 24px; overflow-y: auto; }
224
+ .version-summary { display: grid; grid-template-columns: 1fr auto 1fr auto; align-items: center; gap: 14px; padding: 14px 16px; border: 1px solid #e4e4e7; border-radius: 10px; background: #fafafa; }
225
+ .version-summary > div { display: grid; gap: 3px; }
226
+ .version-summary span { color: #71717a; font-size: 9px; }
227
+ .version-summary strong { color: #27272a; font-size: 13px; }
228
+ .version-arrow { color: #a1a1aa !important; font-size: 14px !important; }
229
+ .version-date { justify-self: end; }
230
+ .version-check-note { margin: 16px 2px 0; color: #71717a; font-size: 11px; line-height: 1.55; }
231
+ .version-check-note.success { color: #15803d; }
232
+ .version-check-note.warning { color: #b45309; }
233
+ .version-notes { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 18px; }
234
+ .version-notes section { padding: 15px; border: 1px solid #e4e4e7; border-radius: 10px; background: #fff; }
235
+ .version-section-title { display: flex; align-items: center; gap: 7px; color: #2563eb; }
236
+ .version-section-title--fix { color: #7c3aed; }
237
+ .version-section-title h3 { color: #27272a; font-size: 11px; }
238
+ .version-notes ul { display: grid; gap: 8px; margin: 12px 0 0; padding-left: 17px; color: #52525b; font-size: 10px; line-height: 1.5; }
239
+ .version-notes li::marker { color: #93c5fd; }
240
+ .version-dialog-footer { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 13px 22px; border-top: 1px solid #e4e4e7; background: #fafafa; }
241
+ .version-dialog-footer > span { color: #71717a; font-size: 9px; }
242
+ .version-dialog-footer a { text-decoration: none; }
243
+
244
+ @media (max-width: 1120px) {
245
+ :root { --sidebar-w: 210px; --right-w: 330px; }
246
+ .brand-mark { min-width: 150px; }
247
+ .header-actions .ui-button { font-size: 0; gap: 0; }
248
+ }
249
+
250
+ @media (max-width: 820px) {
251
+ :root { --sidebar-w: 190px; --right-w: 300px; }
252
+ .brand-mark { min-width: auto; margin-right: 8px; }
253
+ .version-notes { grid-template-columns: 1fr; }
254
+ .version-summary { grid-template-columns: 1fr auto 1fr; }
255
+ .version-date { display: none; }
256
+ }
@@ -0,0 +1,23 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+ import { resolve } from 'node:path';
4
+
5
+ export default defineConfig({
6
+ root: resolve(import.meta.dirname),
7
+ publicDir: false,
8
+ plugins: [react()],
9
+ build: {
10
+ outDir: resolve(import.meta.dirname, '../public/react'),
11
+ emptyOutDir: true,
12
+ sourcemap: false,
13
+ rollupOptions: {
14
+ input: resolve(import.meta.dirname, 'src/main.jsx'),
15
+ external: ['/app.js'],
16
+ output: {
17
+ entryFileNames: 'app.js',
18
+ chunkFileNames: 'assets/[name]-[hash].js',
19
+ assetFileNames: 'assets/[name][extname]',
20
+ },
21
+ },
22
+ },
23
+ });
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "papergod",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "AI-powered local-first LaTeX writing platform and CLI",
6
+ "keywords": [
7
+ "latex",
8
+ "academic-writing",
9
+ "paper-writing",
10
+ "ai",
11
+ "editor",
12
+ "cli",
13
+ "overleaf",
14
+ "research"
15
+ ],
16
+ "license": "MIT",
17
+ "author": {
18
+ "name": "SHENGYU LIU",
19
+ "url": "https://github.com/LiuShengyu-Tech"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/LiuShengyu-Tech/papergod.git"
24
+ },
25
+ "bugs": {
26
+ "url": "https://github.com/LiuShengyu-Tech/papergod/issues"
27
+ },
28
+ "homepage": "https://github.com/LiuShengyu-Tech/papergod#readme",
29
+ "publishConfig": {
30
+ "access": "public",
31
+ "registry": "https://registry.npmjs.org/"
32
+ },
33
+ "bin": {
34
+ "papergod": "src/cli.js"
35
+ },
36
+ "files": [
37
+ "src",
38
+ "frontend",
39
+ "public",
40
+ "example/main.tex",
41
+ "papergod-demo.png",
42
+ "README.md",
43
+ "ROADMAP.md"
44
+ ],
45
+ "scripts": {
46
+ "papergod": "node src/cli.js --resume",
47
+ "build:web": "vite build --config frontend/vite.config.js",
48
+ "prepack": "npm run build:web",
49
+ "test": "node --test tests/api.test.js"
50
+ },
51
+ "dependencies": {
52
+ "@xterm/addon-fit": "^0.11.0",
53
+ "@xterm/addon-web-links": "^0.12.0",
54
+ "@xterm/xterm": "^6.0.0",
55
+ "class-variance-authority": "^0.7.1",
56
+ "clsx": "^2.1.1",
57
+ "codemirror": "^5.65.16",
58
+ "express": "^4.21.0",
59
+ "lucide-react": "^1.31.0",
60
+ "node-pty": "^1.1.0",
61
+ "pdfjs-dist": "^4.8.69",
62
+ "react": "^19.2.8",
63
+ "react-dom": "^19.2.8",
64
+ "tailwind-merge": "^3.6.0"
65
+ },
66
+ "engines": {
67
+ "node": ">=18.0.0"
68
+ },
69
+ "devDependencies": {
70
+ "@vitejs/plugin-react": "^4.7.0",
71
+ "vite": "^6.4.3"
72
+ }
73
+ }
Binary file