Skip to content
Merged
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 CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ First of all, thank you for considering contributing to PaperCache!
npm ci
```

3. **Start the development server:**
3. **Start the Tauri development server:**
```bash
npm run dev
npm run tauri dev
```
> **Prerequisite:** A [Rust toolchain](https://rustup.rs) is required to compile the native backend.

## Development Guidelines
- **Pull Requests Required**: Never push new features directly to the `main` branch. Always create a new branch and push your changes as a Pull Request (PR) for review.
Expand Down
2 changes: 1 addition & 1 deletion features.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ This document outlines every feature available in the PaperCache codebase, organ
- **Note Context Injection**: Type `/ctx <prompt>` instead to automatically package the entire text of the current note along with your prompt, allowing the AI to read your document before answering.
- **Configurable Models & Custom Endpoints**: Easily switch out your API Key, System Prompt, API Base URL, and specific AI Model in the settings panel.
- **Free Top-Tier Defaults**: PaperCache comes fully pre-configured to point to OpenRouter's free tier, using powerful models like `nvidia/nemotron-3-super-120b-a12b:free` out of the box!
- **Secure API Storage**: API keys are securely encrypted at rest using your operating system's native keychain (via Electron's `safeStorage`).
- **Secure API Storage**: API keys are securely encrypted at rest using your operating system's native keychain (via the Rust `keyring` crate).

## Desktop System Integration

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"tauri": "tauri",
"lint": "eslint src --ext .ts,.tsx",
"lint:fix": "eslint src --ext .ts,.tsx --fix",
"format": "prettier --write src",
Expand Down
Binary file removed src-tauri/src-tauri/icons/icon.png
Binary file not shown.
2 changes: 1 addition & 1 deletion src-tauri/src/commands/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn get_safe_path(id: &str) -> Result<PathBuf, String> {

let parent = target.parent().ok_or("Invalid path parent")?;
if !parent.exists() {
fs::create_dir_all(&parent).map_err(|e| e.to_string())?;
fs::create_dir_all(parent).map_err(|e| e.to_string())?;
}
let canonical_parent = parent.canonicalize().map_err(|e| e.to_string())?;

Expand Down
6 changes: 2 additions & 4 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,8 @@ pub fn run() {
api.prevent_close();
let _ = w.hide();
}
tauri::WindowEvent::Focused(focused) => {
if !focused && !is_dialog_open.load(Ordering::SeqCst) {
let _ = w.hide();
}
tauri::WindowEvent::Focused(focused) if !focused && !is_dialog_open.load(Ordering::SeqCst) => {
let _ = w.hide();
}
_ => {}
}
Expand Down
Binary file removed src/assets/hero.png
Binary file not shown.
1 change: 0 additions & 1 deletion src/assets/react.svg

This file was deleted.

1 change: 0 additions & 1 deletion src/assets/vite.svg

This file was deleted.

3 changes: 2 additions & 1 deletion src/hooks/useVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ export function useVariables() {
while ((varMatch = reVar.exec(note.content)) !== null) {
const name = varMatch[1]
try {
globals[name] = parser.evaluate(varMatch[2], globals as any)
globals[name] = parser.evaluate(varMatch[2], globals as Record<string, unknown>)
} catch (e) {
// eslint-disable-next-line no-console
console.error(`useVariables evaluation error for ${name}:`, e)
globals[name] = varMatch[2].trim()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
import { describe, it, expect, vitest } from 'vitest'
import { evaluateMath } from '../src/lib/editor/MathEvaluator'
import { evaluateMath } from './MathEvaluator'

describe('MathEvaluator', () => {
it('evaluates new math expressions ending with =', () => {
const docStr = '1 + 2 =\n'
const scope = {}
const changes = evaluateMath(docStr, scope)
expect(changes).toEqual([
{ from: 7, to: 7, insert: '\u200B3' }
])
expect(changes).toEqual([{ from: 7, to: 7, insert: '\u200B3' }])
})

it('updates existing evaluations if they changed', () => {
const docStr = '1 + 3 =\u200B3'
const scope = {}
const changes = evaluateMath(docStr, scope)
expect(changes).toEqual([
{ from: 8, to: 9, insert: '4' }
])
expect(changes).toEqual([{ from: 8, to: 9, insert: '4' }])
})

it('ignores invalid expressions', () => {
Expand All @@ -40,8 +36,6 @@ describe('MathEvaluator', () => {
const docStr = 'x * 2 =\n'
const scope = { x: 5 }
const changes = evaluateMath(docStr, scope)
expect(changes).toEqual([
{ from: 7, to: 7, insert: '\u200B10' }
])
expect(changes).toEqual([{ from: 7, to: 7, insert: '\u200B10' }])
})
})
4 changes: 3 additions & 1 deletion src/lib/editor/MathEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Parser } from 'expr-eval'

export function evaluateMath(
docStr: string,
scope: Record<string, any>
scope: Record<string, unknown>
): { from: number; to: number; insert: string }[] {
const parser = new Parser()
const changes: { from: number; to: number; insert: string }[] = []
Expand All @@ -27,6 +27,7 @@ export function evaluateMath(
insert: '\u200B' + result,
})
} catch (e) {
// eslint-disable-next-line no-console
console.error(`MathEvaluator new evaluation error for ${expr}:`, e)
}
}
Expand Down Expand Up @@ -57,6 +58,7 @@ export function evaluateMath(
}
}
} catch (e) {
// eslint-disable-next-line no-console
console.error(`MathEvaluator old evaluation error for ${expr}:`, e)
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/lib/editor/VariableScope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ export class VariableScope {
const name = varMatch[1]
try {
const mergedScope = Object.assign({}, globalVars, newScope)
const val = parser.evaluate(varMatch[2], mergedScope as any)
const val = parser.evaluate(varMatch[2], mergedScope as Record<string, unknown>)
newScope[name] = val
} catch (e) {
// eslint-disable-next-line no-console
console.error(`VariableScope evaluation error for ${name}:`, e)
newScope[name] = varMatch[2].trim()
}
Expand Down
1 change: 1 addition & 0 deletions src/lib/editor/checkboxPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export const checkboxPlugin = ViewPlugin.fromClass(
const ranges = decos.map((d) => d.deco.range(d.from, d.to))
return Decoration.set(ranges, true)
} catch (e) {
// eslint-disable-next-line no-console
console.error('checkboxPlugin error:', e)
return Decoration.none
}
Expand Down
1 change: 1 addition & 0 deletions src/lib/editor/codeBlockPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export const codeBlockPlugin = ViewPlugin.fromClass(
const ranges = decos.map((d) => d.deco.range(d.from, d.to))
return Decoration.set(ranges, true)
} catch (e) {
// eslint-disable-next-line no-console
console.error('codeBlockPlugin error:', e)
return Decoration.none
}
Expand Down
7 changes: 5 additions & 2 deletions src/lib/editor/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,14 @@ export function useEditorExtensions() {

messages.push({ role: 'user', content: finalPrompt })

const completion: any = await window.electronAPI.openAIChat({
const completion = (await window.electronAPI.openAIChat({
model: apiModel.trim() || 'nvidia/nemotron-3-super-120b-a12b:free',
messages: messages,
baseUrl: finalBaseUrl || '',
})
})) as {
choices?: Array<{ message?: { content?: string } }>
error?: { message?: string }
}

let response: string
if (completion.choices && completion.choices.length > 0) {
Expand Down
Loading
Loading