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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
pull_request:

jobs:
typecheck:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -17,7 +17,7 @@ jobs:
node-version-file: .nvmrc
cache: npm
- run: npm ci
- run: npm run typecheck
- run: npm test

package-macos:
runs-on: macos-14
Expand Down
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.webpack
node_modules
out
5 changes: 5 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"semi": true,
"singleQuote": false,
"trailingComma": "none"
}
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
.PHONY: help setup dev start test check typecheck clean clean-dev clean-all package package-mac make make-mac install uninstall reinstall open-data create-release deploy-release release
.PHONY: help setup dev start lint test check typecheck clean clean-dev clean-all package package-mac make make-mac install uninstall reinstall open-data create-release deploy-release release

help:
@echo "Robin - Available commands:"
@echo ""
@echo "Development:"
@echo " make setup - Check local prerequisites"
@echo " make dev - Start Robin in development mode"
@echo " make test - Run the current smoke gate (typecheck)"
@echo " make lint - Run ESLint across src/ and test/"
@echo " make test - Run lint, typecheck, unit tests, and format checks"
@echo " make clean - Remove build artifacts"
@echo " make clean-dev - Remove app data and stop Robin"
@echo " make clean-all - Remove artifacts and local app data"
Expand Down Expand Up @@ -37,6 +38,9 @@ dev:
start:
@./scripts/npmw run start

lint:
@./scripts/npmw run lint

typecheck:
@./scripts/npmw run typecheck

Expand Down
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,19 @@ npm start
npm run typecheck
```

5. Run the full quality gate:

```bash
npm test
```

## Common Commands

```bash
make help
make setup
make dev
make lint
make test
make package
make install
Expand All @@ -57,6 +64,7 @@ If you prefer npm directly:
```bash
npm run setup
npm run dev
npm run lint
npm run test
npm run package:mac
npm run make:mac
Expand Down Expand Up @@ -86,10 +94,11 @@ After bootstrap, the repo-level wrappers [scripts/nodew](/Users/karansingh/proje

## Testing

Robin currently has a strong smoke-test workflow rather than a full automated test suite.
Robin now has a baseline automated quality gate plus a manual desktop smoke pass.

1. Run `npm install`
2. Run `npm run test`
This executes ESLint, `tsc --noEmit`, the Node-based unit tests under [test](/Users/karansingh/projects/robin/test), and Prettier checks.
3. Run `npm run dev`
4. Verify manually:
- Tray icon appears
Expand Down Expand Up @@ -167,6 +176,7 @@ Robin uses the standard Electron architecture with a **main process** (Node.js)
### Local-first persistence

All data is stored as JSON files in Electron's `userData` directory:

- `settings.json` — app config, provider preferences, model selections
- `threads.json` — full conversation history with messages and attachments
- `todos.json` — todo items with ordering
Expand All @@ -176,8 +186,8 @@ API keys are encrypted at rest using Electron's `safeStorage` API (macOS Keychai
### Multi-provider abstraction

Robin supports multiple AI providers through a uniform streaming interface:

- **OpenAI** — GPT models with mode support (chat/responses)
- **Anthropic** — Claude models
- **Google** — Gemini models with native image support
- **Perplexity** — Search-grounded answers with citations
- **OpenRouter** — Proxy to any model via user-provided model IDs
Expand All @@ -188,6 +198,7 @@ Each provider implements `streamReply()` with delta callbacks. The `ProviderServ
### Context management

Before sending messages to any provider, Robin optimises the payload:

1. **Image stripping** — only the most recent user message retains image attachments. Older images remain in the thread for display but are excluded from API calls to avoid payload bloat.
2. **Context truncation** — if total message content exceeds ~100K characters (~25K tokens), the oldest messages are dropped while preserving at least the last 4 messages (2 turns).
3. **Model-agnostic threads** — threads store raw messages without model metadata. The model selection is applied at call time, so you can switch providers mid-conversation.
Expand All @@ -198,6 +209,6 @@ The sidebar uses a 2x2 navigation grid (Chats, Todos, Notes, Calendar) that swit

## Next Steps

- Add real renderer/main-process automated tests
- Add Electron-level integration tests for IPC and window lifecycle
- Add a richer settings surface for provider management
- Add update distribution after the first beta
37 changes: 37 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";

export default tseslint.config(
{
ignores: [".webpack/**", "node_modules/**", "out/**"]
},
js.configs.recommended,
...tseslint.configs.recommended,
{
files: ["src/renderer/**/*.{ts,tsx}"],
languageOptions: {
globals: {
...globals.browser
}
}
},
{
files: [
"src/main/**/*.{ts,tsx}",
"src/preload/**/*.{ts,tsx}",
"src/shared/**/*.{ts,tsx}",
"test/**/*.ts"
],
languageOptions: {
globals: {
...globals.node
}
}
},
{
rules: {
"@typescript-eslint/no-explicit-any": "off"
}
}
);
Loading
Loading