noterai 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.
- package/README.md +368 -0
- package/bin/noter.js +218 -0
- package/bin/noter.js.map +1 -0
- package/package.json +73 -0
- package/packages/client/dist/assets/geist-mono-latin-400-normal-CoULgQGM.woff +0 -0
- package/packages/client/dist/assets/geist-mono-latin-400-normal-LC9RFr9I.woff2 +0 -0
- package/packages/client/dist/assets/index-CBiNAMaA.js +264 -0
- package/packages/client/dist/assets/index-u7i5Fle2.css +1 -0
- package/packages/client/dist/assets/space-grotesk-latin-500-normal-CNSSEhBt.woff +0 -0
- package/packages/client/dist/assets/space-grotesk-latin-500-normal-lFbtlQH6.woff2 +0 -0
- package/packages/client/dist/assets/space-grotesk-latin-600-normal-BflQw4A9.woff +0 -0
- package/packages/client/dist/assets/space-grotesk-latin-600-normal-DjKNqYRj.woff2 +0 -0
- package/packages/client/dist/assets/vendor-react-DHeZC_T5.js +17 -0
- package/packages/client/dist/index.html +14 -0
- package/packages/server/dist/adapters/claudeAdapter.d.ts +34 -0
- package/packages/server/dist/adapters/claudeAdapter.d.ts.map +1 -0
- package/packages/server/dist/adapters/claudeAdapter.js +281 -0
- package/packages/server/dist/adapters/claudeAdapter.js.map +1 -0
- package/packages/server/dist/adapters/codexAdapter.d.ts +39 -0
- package/packages/server/dist/adapters/codexAdapter.d.ts.map +1 -0
- package/packages/server/dist/adapters/codexAdapter.js +347 -0
- package/packages/server/dist/adapters/codexAdapter.js.map +1 -0
- package/packages/server/dist/adapters/droidAdapter.d.ts +34 -0
- package/packages/server/dist/adapters/droidAdapter.d.ts.map +1 -0
- package/packages/server/dist/adapters/droidAdapter.js +109 -0
- package/packages/server/dist/adapters/droidAdapter.js.map +1 -0
- package/packages/server/dist/adapters/genericAdapter.d.ts +50 -0
- package/packages/server/dist/adapters/genericAdapter.d.ts.map +1 -0
- package/packages/server/dist/adapters/genericAdapter.js +203 -0
- package/packages/server/dist/adapters/genericAdapter.js.map +1 -0
- package/packages/server/dist/adapters/index.d.ts +7 -0
- package/packages/server/dist/adapters/index.d.ts.map +1 -0
- package/packages/server/dist/adapters/index.js +7 -0
- package/packages/server/dist/adapters/index.js.map +1 -0
- package/packages/server/dist/adapters/opencodeAdapter.d.ts +28 -0
- package/packages/server/dist/adapters/opencodeAdapter.d.ts.map +1 -0
- package/packages/server/dist/adapters/opencodeAdapter.js +265 -0
- package/packages/server/dist/adapters/opencodeAdapter.js.map +1 -0
- package/packages/server/dist/adapters/opencodeSessionManager.d.ts +13 -0
- package/packages/server/dist/adapters/opencodeSessionManager.d.ts.map +1 -0
- package/packages/server/dist/adapters/opencodeSessionManager.js +230 -0
- package/packages/server/dist/adapters/opencodeSessionManager.js.map +1 -0
- package/packages/server/dist/adapters/pathUtils.d.ts +54 -0
- package/packages/server/dist/adapters/pathUtils.d.ts.map +1 -0
- package/packages/server/dist/adapters/pathUtils.js +86 -0
- package/packages/server/dist/adapters/pathUtils.js.map +1 -0
- package/packages/server/dist/adapters/piAdapter.d.ts +34 -0
- package/packages/server/dist/adapters/piAdapter.d.ts.map +1 -0
- package/packages/server/dist/adapters/piAdapter.js +307 -0
- package/packages/server/dist/adapters/piAdapter.js.map +1 -0
- package/packages/server/dist/autoDetect.d.ts +15 -0
- package/packages/server/dist/autoDetect.d.ts.map +1 -0
- package/packages/server/dist/autoDetect.js +102 -0
- package/packages/server/dist/autoDetect.js.map +1 -0
- package/packages/server/dist/config.d.ts +29 -0
- package/packages/server/dist/config.d.ts.map +1 -0
- package/packages/server/dist/config.js +96 -0
- package/packages/server/dist/config.js.map +1 -0
- package/packages/server/dist/eventStore.d.ts +14 -0
- package/packages/server/dist/eventStore.d.ts.map +1 -0
- package/packages/server/dist/eventStore.js +35 -0
- package/packages/server/dist/eventStore.js.map +1 -0
- package/packages/server/dist/hookWatcher.d.ts +24 -0
- package/packages/server/dist/hookWatcher.d.ts.map +1 -0
- package/packages/server/dist/hookWatcher.js +152 -0
- package/packages/server/dist/hookWatcher.js.map +1 -0
- package/packages/server/dist/index.d.ts +58 -0
- package/packages/server/dist/index.d.ts.map +1 -0
- package/packages/server/dist/index.js +527 -0
- package/packages/server/dist/index.js.map +1 -0
- package/packages/server/dist/llm/jsonExtractor.d.ts +39 -0
- package/packages/server/dist/llm/jsonExtractor.d.ts.map +1 -0
- package/packages/server/dist/llm/jsonExtractor.js +83 -0
- package/packages/server/dist/llm/jsonExtractor.js.map +1 -0
- package/packages/server/dist/llm/ollamaCache.d.ts +19 -0
- package/packages/server/dist/llm/ollamaCache.d.ts.map +1 -0
- package/packages/server/dist/llm/ollamaCache.js +31 -0
- package/packages/server/dist/llm/ollamaCache.js.map +1 -0
- package/packages/server/dist/llm/ollamaClient.d.ts +29 -0
- package/packages/server/dist/llm/ollamaClient.d.ts.map +1 -0
- package/packages/server/dist/llm/ollamaClient.js +117 -0
- package/packages/server/dist/llm/ollamaClient.js.map +1 -0
- package/packages/server/dist/llm/ollamaQueue.d.ts +7 -0
- package/packages/server/dist/llm/ollamaQueue.d.ts.map +1 -0
- package/packages/server/dist/llm/ollamaQueue.js +28 -0
- package/packages/server/dist/llm/ollamaQueue.js.map +1 -0
- package/packages/server/dist/llm/promptBuilder.d.ts +8 -0
- package/packages/server/dist/llm/promptBuilder.d.ts.map +1 -0
- package/packages/server/dist/llm/promptBuilder.js +85 -0
- package/packages/server/dist/llm/promptBuilder.js.map +1 -0
- package/packages/server/dist/llm/promptSections.d.ts +64 -0
- package/packages/server/dist/llm/promptSections.d.ts.map +1 -0
- package/packages/server/dist/llm/promptSections.js +128 -0
- package/packages/server/dist/llm/promptSections.js.map +1 -0
- package/packages/server/dist/llm/providerModels.d.ts +14 -0
- package/packages/server/dist/llm/providerModels.d.ts.map +1 -0
- package/packages/server/dist/llm/providerModels.js +67 -0
- package/packages/server/dist/llm/providerModels.js.map +1 -0
- package/packages/server/dist/llm/suggester.d.ts +12 -0
- package/packages/server/dist/llm/suggester.d.ts.map +1 -0
- package/packages/server/dist/llm/suggester.js +263 -0
- package/packages/server/dist/llm/suggester.js.map +1 -0
- package/packages/server/dist/llm/summarizer.d.ts +53 -0
- package/packages/server/dist/llm/summarizer.d.ts.map +1 -0
- package/packages/server/dist/llm/summarizer.js +174 -0
- package/packages/server/dist/llm/summarizer.js.map +1 -0
- package/packages/server/dist/persistence.d.ts +42 -0
- package/packages/server/dist/persistence.d.ts.map +1 -0
- package/packages/server/dist/persistence.js +103 -0
- package/packages/server/dist/persistence.js.map +1 -0
- package/packages/server/dist/repoContext.d.ts +60 -0
- package/packages/server/dist/repoContext.d.ts.map +1 -0
- package/packages/server/dist/repoContext.js +197 -0
- package/packages/server/dist/repoContext.js.map +1 -0
- package/packages/server/dist/routes/blueprint.d.ts +7 -0
- package/packages/server/dist/routes/blueprint.d.ts.map +1 -0
- package/packages/server/dist/routes/blueprint.js +529 -0
- package/packages/server/dist/routes/blueprint.js.map +1 -0
- package/packages/server/dist/routes/config.d.ts +17 -0
- package/packages/server/dist/routes/config.d.ts.map +1 -0
- package/packages/server/dist/routes/config.js +282 -0
- package/packages/server/dist/routes/config.js.map +1 -0
- package/packages/server/dist/routes/lmstudio.d.ts +4 -0
- package/packages/server/dist/routes/lmstudio.d.ts.map +1 -0
- package/packages/server/dist/routes/lmstudio.js +67 -0
- package/packages/server/dist/routes/lmstudio.js.map +1 -0
- package/packages/server/dist/routes/notes.d.ts +5 -0
- package/packages/server/dist/routes/notes.d.ts.map +1 -0
- package/packages/server/dist/routes/notes.js +60 -0
- package/packages/server/dist/routes/notes.js.map +1 -0
- package/packages/server/dist/routes/ollama.d.ts +4 -0
- package/packages/server/dist/routes/ollama.d.ts.map +1 -0
- package/packages/server/dist/routes/ollama.js +207 -0
- package/packages/server/dist/routes/ollama.js.map +1 -0
- package/packages/server/dist/routes/prompt.d.ts +4 -0
- package/packages/server/dist/routes/prompt.d.ts.map +1 -0
- package/packages/server/dist/routes/prompt.js +75 -0
- package/packages/server/dist/routes/prompt.js.map +1 -0
- package/packages/server/dist/routes/refineNotes.d.ts +4 -0
- package/packages/server/dist/routes/refineNotes.d.ts.map +1 -0
- package/packages/server/dist/routes/refineNotes.js +87 -0
- package/packages/server/dist/routes/refineNotes.js.map +1 -0
- package/packages/server/dist/routes/repoContext.d.ts +3 -0
- package/packages/server/dist/routes/repoContext.d.ts.map +1 -0
- package/packages/server/dist/routes/repoContext.js +15 -0
- package/packages/server/dist/routes/repoContext.js.map +1 -0
- package/packages/server/dist/routes/sessions.d.ts +15 -0
- package/packages/server/dist/routes/sessions.d.ts.map +1 -0
- package/packages/server/dist/routes/sessions.js +420 -0
- package/packages/server/dist/routes/sessions.js.map +1 -0
- package/packages/server/dist/routes/summarize.d.ts +6 -0
- package/packages/server/dist/routes/summarize.d.ts.map +1 -0
- package/packages/server/dist/routes/summarize.js +85 -0
- package/packages/server/dist/routes/summarize.js.map +1 -0
- package/packages/server/dist/server.d.ts +2 -0
- package/packages/server/dist/server.d.ts.map +1 -0
- package/packages/server/dist/server.js +6 -0
- package/packages/server/dist/server.js.map +1 -0
- package/packages/server/dist/sessionManager.d.ts +41 -0
- package/packages/server/dist/sessionManager.d.ts.map +1 -0
- package/packages/server/dist/sessionManager.js +493 -0
- package/packages/server/dist/sessionManager.js.map +1 -0
- package/packages/server/dist/sessionScanner.d.ts +22 -0
- package/packages/server/dist/sessionScanner.d.ts.map +1 -0
- package/packages/server/dist/sessionScanner.js +165 -0
- package/packages/server/dist/sessionScanner.js.map +1 -0
- package/packages/server/dist/sessionTitle.d.ts +17 -0
- package/packages/server/dist/sessionTitle.d.ts.map +1 -0
- package/packages/server/dist/sessionTitle.js +321 -0
- package/packages/server/dist/sessionTitle.js.map +1 -0
- package/packages/server/dist/stateManager.d.ts +38 -0
- package/packages/server/dist/stateManager.d.ts.map +1 -0
- package/packages/server/dist/stateManager.js +83 -0
- package/packages/server/dist/stateManager.js.map +1 -0
- package/packages/server/dist/wsServer.d.ts +27 -0
- package/packages/server/dist/wsServer.d.ts.map +1 -0
- package/packages/server/dist/wsServer.js +144 -0
- package/packages/server/dist/wsServer.js.map +1 -0
- package/packages/shared/dist/index.d.ts +3 -0
- package/packages/shared/dist/index.d.ts.map +1 -0
- package/packages/shared/dist/index.js +3 -0
- package/packages/shared/dist/index.js.map +1 -0
- package/packages/shared/dist/llm/mambaDetect.d.ts +84 -0
- package/packages/shared/dist/llm/mambaDetect.d.ts.map +1 -0
- package/packages/shared/dist/llm/mambaDetect.js +205 -0
- package/packages/shared/dist/llm/mambaDetect.js.map +1 -0
- package/packages/shared/dist/types.d.ts +184 -0
- package/packages/shared/dist/types.d.ts.map +1 -0
- package/packages/shared/dist/types.js +2 -0
- package/packages/shared/dist/types.js.map +1 -0
- package/scripts/postbuild.js +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
# Noter
|
|
2
|
+
|
|
3
|
+
A locally-run, browser-based AI agent dashboard that monitors AI agent activity, summarizes context using a local or cloud LLM, and generates next-step task suggestions and implementation prompts.
|
|
4
|
+
|
|
5
|
+
> **npm package:** [`noterai`](https://www.npmjs.com/package/noterai) — install with `npx noterai` or `npm install -g noterai`. The CLI command is `noter`.
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
┌─────────────────────────────────┐ ┌─────────────────────────────────┐
|
|
11
|
+
│ OpenCode (SSE port 4096) │ │ Claude Code (MCP stdio) │
|
|
12
|
+
└────────────┬────────────────────┘ └────────────┬────────────────────┘
|
|
13
|
+
│ SSE │ MCP
|
|
14
|
+
└────────────────┬──────────────────────┘
|
|
15
|
+
│
|
|
16
|
+
┌─────────▼──────────┐
|
|
17
|
+
│ Express Backend │ port 3000
|
|
18
|
+
│ (packages/server) │
|
|
19
|
+
│ │
|
|
20
|
+
│ • EventStore │ 200 events, FIFO ring buffer
|
|
21
|
+
│ • StateManager │ summary, suggestions, notes, prompts
|
|
22
|
+
│ • Summarizer │ Ollama + ai-sdk generateObject
|
|
23
|
+
│ • Suggester │ Ollama + ai-sdk generateObject
|
|
24
|
+
│ • PromptBuilder │ Ollama / Anthropic / OpenAI / Gemini
|
|
25
|
+
│ • OllamaQueue │ serialized inference queue
|
|
26
|
+
│ • OllamaCache │ memoized provider instances
|
|
27
|
+
│ • wsServer │ ping/pong heartbeat, 1MB msg limit
|
|
28
|
+
│ • MCP Server │ stdio transport, send_event + get_state
|
|
29
|
+
└─────────┬────────┘
|
|
30
|
+
│ WebSocket + HTTP
|
|
31
|
+
┌─────────▼──────────┐
|
|
32
|
+
│ React Frontend │ port 5173 (dev) / served static
|
|
33
|
+
│ (packages/client) │
|
|
34
|
+
│ │
|
|
35
|
+
│ • 2x2 grid layout│ Editorial Brutalism design system
|
|
36
|
+
│ • wsClient │ auto-reconnect, exponential backoff
|
|
37
|
+
│ • 4 panels │ Notes, Tasks, Context, Prompts
|
|
38
|
+
└──────────────────┘
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
### From npm (no clone needed)
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx noterai # Run without installing (opens browser automatically)
|
|
47
|
+
npx noterai serve # Production server without auto-opening browser
|
|
48
|
+
npx noterai serve --open # Production server + auto-open browser
|
|
49
|
+
npx noterai help # Show all commands
|
|
50
|
+
npx noterai version # Print version
|
|
51
|
+
|
|
52
|
+
# Or install globally:
|
|
53
|
+
npm install -g noterai
|
|
54
|
+
noter # Then run directly
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### From source (development)
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
git clone https://github.com/oniwakaa/noter.git && cd noter
|
|
61
|
+
pnpm install
|
|
62
|
+
pnpm run dev
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The dashboard opens at `http://localhost:5173`. The backend runs on `http://localhost:3000`.
|
|
66
|
+
|
|
67
|
+
> **Note:** `pnpm run dev` starts both the backend server (`:3000`) and the Vite dev client (`:5173`) concurrently.
|
|
68
|
+
|
|
69
|
+
## Prerequisites
|
|
70
|
+
|
|
71
|
+
- **Node.js** >= 20 (tested on v24.4.1)
|
|
72
|
+
- **pnpm** >= 10 (tested on v10.30.3)
|
|
73
|
+
- **Ollama** running locally with at least one model pulled (check `ollama list`)
|
|
74
|
+
- Default model in `.env.example` is `falcon-h1r:7b-q4_K_M` — **update `.env` to a model you have installed** (e.g. `deepseek-v4-flash:cloud` or `gemma4:e4b`)
|
|
75
|
+
- *(Optional)* **OpenCode** CLI for OpenCode SSE event ingestion
|
|
76
|
+
- *(Optional)* API keys if using cloud LLM providers for prompt generation (Anthropic, OpenAI, Gemini)
|
|
77
|
+
|
|
78
|
+
## Environment Variables
|
|
79
|
+
|
|
80
|
+
Copy `.env.example` to `.env` and adjust values:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
cp .env.example .env
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
| Variable | Default | Description |
|
|
87
|
+
|----------|---------|-------------|
|
|
88
|
+
| `PORT` | `3000` | Backend HTTP/WebSocket server port |
|
|
89
|
+
| `VITE_SERVER_PORT` | `3000` | **Must match `PORT`** — used by Vite proxy and WebSocket client |
|
|
90
|
+
| `OLLAMA_BASE_URL` | `http://localhost:11434` | Ollama API endpoint |
|
|
91
|
+
| `OLLAMA_MODEL` | `falcon-h1r:7b-q4_K_M` | Model for summarization & suggestions. **Must be a model you have pulled locally.** |
|
|
92
|
+
| `CONTEXT_OFFLOAD_THRESHOLD` | `0.8` | Auto-offload model when accumulated context exceeds this % of context window (0.0–1.0) |
|
|
93
|
+
| `VRAM_LIMIT_GB` | `6` | VRAM display limit for the Ollama status memory bar |
|
|
94
|
+
| `OPENCODE_PORT` | `4096` | OpenCode SSE stream port (only when `ACTIVE_SOURCE` includes `opencode`) |
|
|
95
|
+
| `ACTIVE_SOURCE` | `generic` | Event source: `opencode`, `claude-code`, `codex`, `factory-droid`, `pi`, `generic`, `auto`, `both`, or `all` |
|
|
96
|
+
| `NOTER_EVENT_LOG` | `/tmp/noter-events.jsonl` | Path to JSONL event log for file-based adapters (Droid, Pi) |
|
|
97
|
+
| `GENERIC_LOG_PATH` | `/tmp/noter-generic-events.jsonl` | Path to JSONL event log for the generic adapter |
|
|
98
|
+
| `LLM_PROVIDER` | `ollama` | Prompt generation provider: `ollama`, `anthropic`, `openai`, `gemini` |
|
|
99
|
+
| `ANTHROPIC_API_KEY` | *(empty)* | Required when `LLM_PROVIDER=anthropic` |
|
|
100
|
+
| `OPENAI_API_KEY` | *(empty)* | Required when `LLM_PROVIDER=openai` |
|
|
101
|
+
| `GEMINI_API_KEY` | *(empty)* | Required when `LLM_PROVIDER=gemini` |
|
|
102
|
+
|
|
103
|
+
## Scripts
|
|
104
|
+
|
|
105
|
+
### Root (`package.json`)
|
|
106
|
+
|
|
107
|
+
| Script | Description |
|
|
108
|
+
|--------|-------------|
|
|
109
|
+
| `pnpm run dev` | Start both server and client concurrently |
|
|
110
|
+
| `pnpm run dev:server` | Start backend only (Express + WebSocket on port 3000) |
|
|
111
|
+
| `pnpm run dev:client` | Start frontend only (Vite dev server on port 5173) |
|
|
112
|
+
| `pnpm run build` | Build shared + server + client + bin for production |
|
|
113
|
+
| `pnpm run typecheck` | TypeScript strict mode check (both packages) |
|
|
114
|
+
| `pnpm run test` | Run full Vitest suite (server + client workspaces) |
|
|
115
|
+
|
|
116
|
+
### Sub-package scripts
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Client build
|
|
120
|
+
cd packages/client && pnpm run build # tsc && vite build
|
|
121
|
+
cd packages/client && pnpm run preview # preview production build
|
|
122
|
+
|
|
123
|
+
# Server build
|
|
124
|
+
cd packages/server && pnpm run build # tsc
|
|
125
|
+
cd packages/server && pnpm run build:mcp # tsc, outputs dist/mcp-server.js
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### CLI (`bin/noter.ts` / `bin/noter.js`)
|
|
129
|
+
|
|
130
|
+
The package exposes a `noter` CLI via the `bin` field:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
noter --help # Show all commands
|
|
134
|
+
noter version # Print version
|
|
135
|
+
noter serve # Production server (serves static frontend + API)
|
|
136
|
+
noter serve --open # Production server + auto-open browser
|
|
137
|
+
noter dev # Development mode (hot-reload)
|
|
138
|
+
noter build # Build client & server for production
|
|
139
|
+
PORT=8080 noter serve # Custom port
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Project Structure
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
noter/
|
|
146
|
+
├── bin/
|
|
147
|
+
│ ├── noter.ts # CLI source (compiled to noter.js for publish)
|
|
148
|
+
│ ├── noter.js # Compiled CLI entry point (gitignored, built on publish)
|
|
149
|
+
│ └── tsconfig.json # Bin-specific tsconfig (node16 module resolution)
|
|
150
|
+
├── packages/
|
|
151
|
+
│ ├── server/ # Express + WebSocket backend
|
|
152
|
+
│ │ ├── src/
|
|
153
|
+
│ │ │ ├── adapters/
|
|
154
|
+
│ │ │ │ ├── opencodeAdapter.ts # OpenCode SSE → AgentEvent
|
|
155
|
+
│ │ │ │ ├── claudeAdapter.ts # Claude Code MCP → AgentEvent
|
|
156
|
+
│ │ │ │ ├── codexAdapter.ts # OpenAI Codex CLI MCP → AgentEvent
|
|
157
|
+
│ │ │ │ ├── droidAdapter.ts # Factory Droid hooks → AgentEvent
|
|
158
|
+
│ │ │ │ ├── piAdapter.ts # Pi (pi.dev) hooks → AgentEvent
|
|
159
|
+
│ │ │ │ └── genericAdapter.ts # Generic JSONL/webhook → AgentEvent
|
|
160
|
+
│ │ │ ├── llm/
|
|
161
|
+
│ │ │ │ ├── ollamaClient.ts # Low-level Ollama client (60s timeout, AbortController)
|
|
162
|
+
│ │ │ │ ├── ollamaCache.ts # Memoized createOllama() provider instances
|
|
163
|
+
│ │ │ │ ├── ollamaQueue.ts # Serialized inference queues (suggester + inference)
|
|
164
|
+
│ │ │ │ ├── summarizer.ts # ContextSummary generation from events
|
|
165
|
+
│ │ │ │ ├── suggester.ts # TaskSuggestion[] generation from context + notes
|
|
166
|
+
│ │ │ │ └── promptBuilder.ts # GeneratedPrompt from task + context + notes
|
|
167
|
+
│ │ │ ├── routes/
|
|
168
|
+
│ │ │ │ ├── notes.ts # POST /api/notes → save + fire-and-forget suggest
|
|
169
|
+
│ │ │ │ ├── prompt.ts # POST /api/prompt (by taskId) + GET /:taskId
|
|
170
|
+
│ │ │ │ ├── summarize.ts # POST /api/summarize (mutex-guarded)
|
|
171
|
+
│ │ │ │ └── ollama.ts # GET /api/ollama/status + POST /api/ollama/offload
|
|
172
|
+
│ │ │ ├── config.ts # AppConfig, types, loadConfig(), Zod-like validation
|
|
173
|
+
│ │ │ ├── eventStore.ts # In-memory FIFO ring buffer (200 max)
|
|
174
|
+
│ │ │ ├── stateManager.ts # Shared state + task→prompt map
|
|
175
|
+
│ │ │ ├── wsServer.ts # WebSocketServer wrapper (heartbeat, 1MB limit)
|
|
176
|
+
│ │ │ ├── mcp-server.ts # MCP stdio server (send_event, get_state tools)
|
|
177
|
+
│ │ │ └── index.ts # createApp() factory + listenServer() + startServer()
|
|
178
|
+
│ │ └── package.json
|
|
179
|
+
│ └── client/ # React + Vite frontend
|
|
180
|
+
│ ├── src/
|
|
181
|
+
│ │ ├── components/
|
|
182
|
+
│ │ │ ├── NotesPanel.tsx # Debounced textarea, drag-to-delete
|
|
183
|
+
│ │ │ ├── SuggestionsPanel.tsx # Task cards, priority badges, conflict warnings
|
|
184
|
+
│ │ │ ├── ContextPanel.tsx # Summary fields, Ollama status, activity log
|
|
185
|
+
│ │ │ ├── PromptsPanel.tsx # Build → expand prompt, copy to clipboard
|
|
186
|
+
│ │ │ └── OllamaStatus.tsx # Model name, connection, VRAM bar, offload
|
|
187
|
+
│ │ ├── styles/
|
|
188
|
+
│ │ │ └── tokens.css # DESIGN.md tokens: monochrome, zero-radius, no shadows
|
|
189
|
+
│ │ ├── App.tsx # 2x2 grid, top nav, dark/light toggle
|
|
190
|
+
│ │ ├── wsClient.ts # Singleton WebSocket client (reconnect backoff)
|
|
191
|
+
│ │ ├── localDeletions.ts # Drag-delete tracking set
|
|
192
|
+
│ │ ├── types.ts # Shared TypeScript interfaces
|
|
193
|
+
│ │ └── test/ # Component tests (RTL + jsdom)
|
|
194
|
+
│ └── package.json
|
|
195
|
+
├── .env.example # All environment variables with comments
|
|
196
|
+
├── vitest.workspace.ts # Server (node) + Client (jsdom) test workspaces
|
|
197
|
+
├── tsconfig.base.json # Shared TypeScript strict config
|
|
198
|
+
├── pnpm-workspace.yaml # Monorepo workspace definition
|
|
199
|
+
└── README.md # This file
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Frontend Panels
|
|
203
|
+
|
|
204
|
+
The UI is a fixed 2x2 viewport grid separated by 1px solid dividers (`outline_variant`).
|
|
205
|
+
|
|
206
|
+
| Panel | Grid Position | Description |
|
|
207
|
+
|-------|--------------|-------------|
|
|
208
|
+
| **Notes** | Top-left | Borderless textarea with debounced save (500ms POST to `/api/notes`). Supports drag-to-delete: drop a task card here to remove it. |
|
|
209
|
+
| **Suggested Tasks** | Top-right | Task cards (`TaskSuggestion[]`) with priority badges (high/medium/low), conflict warnings, and a **"Build →"** action to generate a prompt. |
|
|
210
|
+
| **Agent Context** | Bottom-left | `ContextSummary` fields: what's happening, files changed, current goal, blockers. Includes Ollama status (model, VRAM bar, offload button). Terminal-style activity log. |
|
|
211
|
+
| **Suggested Prompts** | Bottom-right | List of generated prompts. Click **"Build →"** to expand a prompt row (animated from `0fr` to `1fr`). Each prompt has a copy-to-clipboard button. |
|
|
212
|
+
|
|
213
|
+
**Design System:** High-End Editorial Brutalism — zero `border-radius`, no `box-shadow`, monochrome palette (`#131313` surface), Space Grotesk for labels, Geist Mono for data/code. See [`DESIGN.md`](./DESIGN.md) for full spec.
|
|
214
|
+
|
|
215
|
+
## WebSocket Message Types
|
|
216
|
+
|
|
217
|
+
All messages are typed as `WsMessage` union. The client auto-reconnects with exponential backoff (500ms → 30s max).
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
type WsMessage =
|
|
221
|
+
| { type: 'sync'; payload: { events: AgentEvent[]; summary: ContextSummary | null; suggestions: TaskSuggestion[]; notes: HumanNotes | null } }
|
|
222
|
+
| { type: 'event'; payload: AgentEvent }
|
|
223
|
+
| { type: 'summary'; payload: ContextSummary }
|
|
224
|
+
| { type: 'suggestions'; payload: TaskSuggestion[] }
|
|
225
|
+
| { type: 'notes'; payload: HumanNotes };
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
- **`sync`** — sent to every new WebSocket connection to hydrate frontend state.
|
|
229
|
+
- **`event`** — broadcast when a new agent event is ingested.
|
|
230
|
+
- **`summary`** — broadcast when the summarizer generates a new context summary.
|
|
231
|
+
- **`suggestions`** — broadcast when new task suggestions are generated.
|
|
232
|
+
- **`notes`** — broadcast when notes are updated.
|
|
233
|
+
|
|
234
|
+
**Server-side protections:** ping/pong heartbeat every 30s (stale connections terminated), maximum message size 1MB.
|
|
235
|
+
|
|
236
|
+
## API Endpoints
|
|
237
|
+
|
|
238
|
+
### `GET /health`
|
|
239
|
+
Returns `{"status":"ok"}` — used by services.yaml healthcheck and CLI startup verification.
|
|
240
|
+
|
|
241
|
+
### `POST /api/notes`
|
|
242
|
+
**Body:** `{ content: string, updatedAt: number }` (Zod-validated)
|
|
243
|
+
|
|
244
|
+
Saves notes, returns `{ saved: true }` immediately, then **fire-and-forget** generates `TaskSuggestion[]` via the suggester queue. Suggestions are broadcast via WebSocket.
|
|
245
|
+
|
|
246
|
+
### `POST /api/prompt`
|
|
247
|
+
**Body:** `{ taskId: string }` (Zod-validated)
|
|
248
|
+
|
|
249
|
+
Generates a `GeneratedPrompt` for the given task using the configured `LLM_PROVIDER`. Uses shared `INFERENCE_QUEUE` to serialize with summarization. Returns `404` if taskId not found, `500` if API key missing or generation fails.
|
|
250
|
+
|
|
251
|
+
**Also:** `GET /api/prompt/:taskId` — retrieve a previously generated prompt for a task.
|
|
252
|
+
|
|
253
|
+
### `POST /api/summarize`
|
|
254
|
+
**Body:** none required.
|
|
255
|
+
|
|
256
|
+
Triggers context summarization manually. Mutex-guarded: concurrent requests return `202` without duplicate Ollama calls. Returns `ContextSummary` with fields: `whatIsHappening`, `filesChanged`, `currentGoal`, `blockers`, `rawEventCount`.
|
|
257
|
+
|
|
258
|
+
### `GET /api/ollama/status`
|
|
259
|
+
Returns Ollama `/api/ps` response formatted with `models[]` and `memory{}` (totalSize, totalVram, usedPercent).
|
|
260
|
+
|
|
261
|
+
### `POST /api/ollama/offload`
|
|
262
|
+
Offloads all loaded Ollama models (sends `keep_alive: 0`).
|
|
263
|
+
|
|
264
|
+
## MCP Integration
|
|
265
|
+
|
|
266
|
+
Noter exposes an MCP server via stdio transport for use with Claude Code, Cursor, VS Code Copilot, Continue.dev, Windsurf, and OpenAI Codex CLI.
|
|
267
|
+
|
|
268
|
+
**Tools:**
|
|
269
|
+
- **`send_event`** — Push an agent event into the pipeline. Zod-validated against `AgentEvent` schema. Stored in `eventStore`, broadcast via WebSocket, and processed by the summarizer.
|
|
270
|
+
- **`get_state`** — Returns current application state (summary, suggestions, notes) as JSON.
|
|
271
|
+
|
|
272
|
+
**Configuration** — add to your agent's MCP settings (e.g. `~/.claude/mcp.json`, `.cursor/mcp.json`, or equivalent):
|
|
273
|
+
|
|
274
|
+
```json
|
|
275
|
+
{
|
|
276
|
+
"mcpServers": {
|
|
277
|
+
"noter": {
|
|
278
|
+
"command": "node",
|
|
279
|
+
"args": ["packages/server/dist/mcp-server.js"]
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Per-Harness Setup
|
|
286
|
+
|
|
287
|
+
**Claude Code & OpenAI Codex CLI:**
|
|
288
|
+
Both use the same MCP protocol. Add the MCP server config above to your agent's settings, then set `ACTIVE_SOURCE=claude-code` (or `codex`, or `all`).
|
|
289
|
+
|
|
290
|
+
**Factory Droid:**
|
|
291
|
+
Droid writes events to `/tmp/noter-events.jsonl` via its hooks system. The `droidAdapter.ts` watches this file automatically when `ACTIVE_SOURCE` includes `factory-droid`.
|
|
292
|
+
|
|
293
|
+
**Pi (pi.dev):**
|
|
294
|
+
Pi extensions can emit events to the same JSONL file. Install a `noter-bridge.ts` extension in Pi that writes `{ type, sessionId, payload, timestamp }` lines to `NOTER_EVENT_LOG`.
|
|
295
|
+
|
|
296
|
+
**OpenCode:**
|
|
297
|
+
Run `opencode` with the `--events` flag pointing to `http://localhost:${OPENCODE_PORT}`. The `opencodeAdapter.ts` connects via SSE.
|
|
298
|
+
|
|
299
|
+
**Generic (any harness):**
|
|
300
|
+
The generic adapter watches a JSONL file (default: `/tmp/noter-generic-events.jsonl`) for events from any agent harness. Zero-config — just write JSON events to the default path, or set `GENERIC_LOG_PATH` for a custom path. Set `ACTIVE_SOURCE=generic` (the default).
|
|
301
|
+
|
|
302
|
+
## Ollama Integration
|
|
303
|
+
|
|
304
|
+
- **Provider caching:** `ollamaCache.ts` memoizes `createOllama()` instances by `baseURL` so the same provider config is reused across summarizer, suggester, and prompt builder.
|
|
305
|
+
- **Queue serialization:** `ollamaQueue.ts` provides two queues:
|
|
306
|
+
- `INFERENCE_QUEUE` — shared between summarizer and prompt builder (prevents concurrent calls).
|
|
307
|
+
- `SUGGESTER_QUEUE` — dedicated queue for suggestion generation (runs independently).
|
|
308
|
+
- **Timeout:** `ollamaClient.ts` uses `AbortController` with a 60-second default timeout. Configurable via `OllamaClientOptions.timeout`.
|
|
309
|
+
- **Context auto-offload:** Tracks accumulated token usage and automatically offloads models when the context window threshold (`CONTEXT_OFFLOAD_THRESHOLD`) is exceeded.
|
|
310
|
+
|
|
311
|
+
## LLM Providers for Prompt Generation
|
|
312
|
+
|
|
313
|
+
| Provider | Model ID | Requires Key |
|
|
314
|
+
|----------|---------|-------------|
|
|
315
|
+
| `ollama` | Configured `OLLAMA_MODEL` | No |
|
|
316
|
+
| `anthropic` | `claude-sonnet-4-20250514` | `ANTHROPIC_API_KEY` |
|
|
317
|
+
| `openai` | `gpt-4o` | `OPENAI_API_KEY` |
|
|
318
|
+
| `gemini` | `gemini-2.5-flash` | `GEMINI_API_KEY` |
|
|
319
|
+
|
|
320
|
+
## Event Sources
|
|
321
|
+
|
|
322
|
+
| Source | Adapter | Transport | Trigger |
|
|
323
|
+
|--------|---------|-----------|---------|
|
|
324
|
+
| **OpenCode** | `opencodeAdapter.ts` | SSE (`http://localhost:${OPENCODE_PORT}`) | `session.idle`, `tool.before/after`, `message.updated` |
|
|
325
|
+
| **Claude Code** | `claudeAdapter.ts` | MCP stdio | `send_event` tool calls |
|
|
326
|
+
| **OpenAI Codex CLI** | `codexAdapter.ts` | MCP stdio | `send_event` tool calls |
|
|
327
|
+
| **Factory Droid** | `droidAdapter.ts` | File hooks (`AGENTDESK_EVENT_LOG`) | `tool.before/after`, `session.start/end` |
|
|
328
|
+
| **Pi (pi.dev)** | `piAdapter.ts` | File hooks (`AGENTDESK_EVENT_LOG`) | `tool_call`, `tool_result`, `agent_start/end` |
|
|
329
|
+
| **Generic** | `genericAdapter.ts` | JSONL file watcher + webhook | Any harness writing JSON events |
|
|
330
|
+
|
|
331
|
+
Set `ACTIVE_SOURCE=all` to ingest from all supported harnesses simultaneously.
|
|
332
|
+
|
|
333
|
+
## Testing
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
# Full suite (server + client)
|
|
337
|
+
pnpm run test
|
|
338
|
+
|
|
339
|
+
# Server only (node environment)
|
|
340
|
+
pnpm vitest run --project server
|
|
341
|
+
|
|
342
|
+
# Client only (jsdom environment)
|
|
343
|
+
pnpm vitest run --project client
|
|
344
|
+
|
|
345
|
+
# With coverage
|
|
346
|
+
pnpm vitest run --coverage
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
- **Server tests:** 30+ test files covering routes, adapters (5 harnesses), LLM pipeline, config validation, WebSocket server, MCP server, session management, and CLI.
|
|
350
|
+
- **Client tests:** 10+ component test files using React Testing Library + jsdom.
|
|
351
|
+
|
|
352
|
+
## TypeScript
|
|
353
|
+
|
|
354
|
+
Strict mode enabled across both packages. Root `tsconfig.base.json` provides shared compiler options.
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
pnpm run typecheck # Both packages
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Security
|
|
361
|
+
|
|
362
|
+
- No hardcoded secrets in source files.
|
|
363
|
+
- `.env` is in `.gitignore`.
|
|
364
|
+
- API keys are read exclusively via `loadConfig()` in `config.ts`.
|
|
365
|
+
|
|
366
|
+
## License
|
|
367
|
+
|
|
368
|
+
MIT
|
package/bin/noter.js
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// noter — CLI-first repo-aware startup
|
|
3
|
+
//
|
|
4
|
+
// When launched inside a git repository, automatically:
|
|
5
|
+
// 1. Detects the repository root
|
|
6
|
+
// 2. Loads AGENTS.md / AGENT.md as repo instructions
|
|
7
|
+
// 3. Matches active harness sessions for this repo
|
|
8
|
+
// 4. Injects all context into the running server
|
|
9
|
+
import { createApp, listenServer } from '../packages/server/dist/index.js';
|
|
10
|
+
import { loadConfig } from '../packages/server/dist/config.js';
|
|
11
|
+
import { resolveRepoContext, formatStartupLog } from '../packages/server/dist/repoContext.js';
|
|
12
|
+
import { stateManager } from '../packages/server/dist/stateManager.js';
|
|
13
|
+
import { execSync } from 'child_process';
|
|
14
|
+
import { resolve, dirname } from 'path';
|
|
15
|
+
import { fileURLToPath } from 'url';
|
|
16
|
+
import { existsSync, readFileSync } from 'fs';
|
|
17
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
+
const __dirname = dirname(__filename);
|
|
19
|
+
const ROOT = resolve(__dirname, '..');
|
|
20
|
+
const CLIENT_DIST = resolve(ROOT, 'packages/client/dist');
|
|
21
|
+
const PACKAGE_JSON = resolve(ROOT, 'package.json');
|
|
22
|
+
function log(msg) {
|
|
23
|
+
console.log(`[noter] ${msg}`);
|
|
24
|
+
}
|
|
25
|
+
function logError(msg) {
|
|
26
|
+
console.error(`[noter] ${msg}`);
|
|
27
|
+
}
|
|
28
|
+
function getVersion() {
|
|
29
|
+
const raw = readFileSync(PACKAGE_JSON, 'utf-8');
|
|
30
|
+
const pkg = JSON.parse(raw);
|
|
31
|
+
return pkg.version ?? '0.0.1';
|
|
32
|
+
}
|
|
33
|
+
function showHelp() {
|
|
34
|
+
const version = getVersion();
|
|
35
|
+
const help = `
|
|
36
|
+
noter v${version} — CLI-first repo-aware AI agent dashboard
|
|
37
|
+
|
|
38
|
+
Usage:
|
|
39
|
+
noter [command] [options]
|
|
40
|
+
|
|
41
|
+
Commands:
|
|
42
|
+
(default) Start with repo-aware context (auto-detect repo, load AGENTS.md)
|
|
43
|
+
serve Start the production server (serves frontend + API)
|
|
44
|
+
dev Start development mode (hot-reload client & server)
|
|
45
|
+
build Build client and server for production
|
|
46
|
+
help Show this help message
|
|
47
|
+
version Print the version number
|
|
48
|
+
|
|
49
|
+
Options:
|
|
50
|
+
serve --open Open the browser after starting the server
|
|
51
|
+
serve --no-open Do not open the browser (default for 'serve')
|
|
52
|
+
|
|
53
|
+
Repo-Aware Behavior:
|
|
54
|
+
When launched inside a git repository, noter automatically:
|
|
55
|
+
- Detects the repository root (walks up from CWD to find .git)
|
|
56
|
+
- Loads AGENTS.md or AGENT.md from the repo root (AGENTS.md takes precedence)
|
|
57
|
+
- Matches active harness sessions (Pi, Factory Droid) by repo path
|
|
58
|
+
- Injects repo instructions into summarization, suggestions, and prompts
|
|
59
|
+
When launched from a non-repo directory, all repo-specific features are skipped.
|
|
60
|
+
|
|
61
|
+
Environment Variables:
|
|
62
|
+
PORT Server port (default: 3000)
|
|
63
|
+
OLLAMA_BASE_URL Ollama API URL (default: http://localhost:11434)
|
|
64
|
+
OLLAMA_MODEL Ollama model name (default: falcon-h1r:7b-q4_K_M)
|
|
65
|
+
ACTIVE_SOURCE Event source: opencode | claude-code | codex | factory-droid | pi | generic | auto
|
|
66
|
+
LLM_PROVIDER LLM provider: ollama | anthropic | openai | gemini
|
|
67
|
+
OPENCODE_PORT OpenCode SSE port (default: 4096)
|
|
68
|
+
ANTHROPIC_API_KEY API key for Anthropic
|
|
69
|
+
OPENAI_API_KEY API key for OpenAI
|
|
70
|
+
GEMINI_API_KEY API key for Google Gemini
|
|
71
|
+
|
|
72
|
+
Examples:
|
|
73
|
+
noter Repo-aware startup + open browser
|
|
74
|
+
noter serve Start server without opening browser
|
|
75
|
+
noter serve --open Start server and open browser
|
|
76
|
+
noter dev Start development mode
|
|
77
|
+
noter build Build for production
|
|
78
|
+
PORT=8080 noter serve Start server on port 8080
|
|
79
|
+
`.trim();
|
|
80
|
+
console.log(help);
|
|
81
|
+
}
|
|
82
|
+
async function build() {
|
|
83
|
+
log('Building client...');
|
|
84
|
+
execSync('pnpm run build', { cwd: resolve(ROOT, 'packages/client'), stdio: 'inherit' });
|
|
85
|
+
log('Building server...');
|
|
86
|
+
execSync('pnpm run build', { cwd: resolve(ROOT, 'packages/server'), stdio: 'inherit' });
|
|
87
|
+
log('Build complete.');
|
|
88
|
+
}
|
|
89
|
+
async function serve(openBrowser) {
|
|
90
|
+
// Auto-build if client dist is missing
|
|
91
|
+
if (!existsSync(CLIENT_DIST)) {
|
|
92
|
+
log('Client build not found. Building...');
|
|
93
|
+
await build();
|
|
94
|
+
}
|
|
95
|
+
// Resolve repo context BEFORE starting the server
|
|
96
|
+
const cwd = process.cwd();
|
|
97
|
+
const repoCtx = resolveRepoContext(cwd);
|
|
98
|
+
// Log startup context
|
|
99
|
+
for (const line of formatStartupLog(repoCtx)) {
|
|
100
|
+
log(line);
|
|
101
|
+
}
|
|
102
|
+
// Store repo context in state manager so it's available to all routes/LLM prompts
|
|
103
|
+
stateManager.setRepoContext(repoCtx);
|
|
104
|
+
// Lazy-load config to pick up env vars (including PORT)
|
|
105
|
+
const cfg = loadConfig();
|
|
106
|
+
const { default: express } = await import('express');
|
|
107
|
+
const appServer = await createApp();
|
|
108
|
+
// Serve static frontend in production
|
|
109
|
+
appServer.app.use(express.static(CLIENT_DIST));
|
|
110
|
+
// Express v5 SPA fallback — catch-all route using {*path} parameter
|
|
111
|
+
appServer.app.get('{*path}', (_req, res) => {
|
|
112
|
+
res.sendFile(resolve(CLIENT_DIST, 'index.html'));
|
|
113
|
+
});
|
|
114
|
+
const port = cfg.port;
|
|
115
|
+
try {
|
|
116
|
+
await listenServer(appServer, port);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
logError(err.message);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
log(`Noter running at http://localhost:${port}`);
|
|
123
|
+
if (openBrowser) {
|
|
124
|
+
const url = `http://localhost:${port}`;
|
|
125
|
+
log(`Opening browser at ${url}`);
|
|
126
|
+
const opener = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
127
|
+
try {
|
|
128
|
+
execSync(`${opener} ${url}`);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
log(`Could not open browser. Visit ${url} manually.`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
log('Press Ctrl+C to stop.');
|
|
135
|
+
// Graceful shutdown handlers
|
|
136
|
+
const shutdown = async (signal) => {
|
|
137
|
+
log(`Received ${signal}, shutting down gracefully...`);
|
|
138
|
+
try {
|
|
139
|
+
await appServer.close();
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// Ignore errors during shutdown
|
|
143
|
+
}
|
|
144
|
+
process.exit(0);
|
|
145
|
+
};
|
|
146
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
147
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
148
|
+
}
|
|
149
|
+
async function main() {
|
|
150
|
+
const args = process.argv.slice(2);
|
|
151
|
+
const command = args[0];
|
|
152
|
+
switch (command) {
|
|
153
|
+
case 'help':
|
|
154
|
+
case '--help':
|
|
155
|
+
case '-h':
|
|
156
|
+
showHelp();
|
|
157
|
+
process.exit(0);
|
|
158
|
+
break;
|
|
159
|
+
case 'version':
|
|
160
|
+
case '--version':
|
|
161
|
+
case '-v':
|
|
162
|
+
console.log(`noter v${getVersion()}`);
|
|
163
|
+
process.exit(0);
|
|
164
|
+
break;
|
|
165
|
+
case 'build':
|
|
166
|
+
try {
|
|
167
|
+
await build();
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
logError(`Build failed: ${err.message}`);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
break;
|
|
174
|
+
case 'serve': {
|
|
175
|
+
const openBrowser = args.includes('--open');
|
|
176
|
+
try {
|
|
177
|
+
await serve(openBrowser);
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
logError(`Server error: ${err.message}`);
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
case 'dev':
|
|
186
|
+
log('Starting development mode...');
|
|
187
|
+
try {
|
|
188
|
+
execSync('pnpm run dev', { cwd: ROOT, stdio: 'inherit' });
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
logError(`Dev server error: ${err.message}`);
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
|
194
|
+
break;
|
|
195
|
+
case undefined:
|
|
196
|
+
// Default: repo-aware serve with browser open
|
|
197
|
+
try {
|
|
198
|
+
await serve(true);
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
logError(`Server error: ${err.message}`);
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
break;
|
|
205
|
+
default:
|
|
206
|
+
// Unknown command — show help and exit 1
|
|
207
|
+
logError(`Unknown command: ${command}`);
|
|
208
|
+
console.log();
|
|
209
|
+
showHelp();
|
|
210
|
+
process.exit(1);
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
main().catch((err) => {
|
|
215
|
+
logError(`Fatal error: ${err instanceof Error ? err.message : String(err)}`);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
});
|
|
218
|
+
//# sourceMappingURL=noter.js.map
|
package/bin/noter.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noter.js","sourceRoot":"","sources":["noter.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "noterai",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Locally-run, browser-based AI agent dashboard for developers using LLM coding assistants",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"ai",
|
|
9
|
+
"agent",
|
|
10
|
+
"dashboard",
|
|
11
|
+
"llm",
|
|
12
|
+
"claude",
|
|
13
|
+
"codex",
|
|
14
|
+
"opencode",
|
|
15
|
+
"developer-tools",
|
|
16
|
+
"cli"
|
|
17
|
+
],
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/oniwakaa/noter.git"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/oniwakaa/noter#readme",
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=20.0.0"
|
|
25
|
+
},
|
|
26
|
+
"bin": {
|
|
27
|
+
"noter": "./bin/noter.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"bin/noter.js",
|
|
31
|
+
"bin/noter.js.map",
|
|
32
|
+
"packages/client/dist",
|
|
33
|
+
"packages/server/dist",
|
|
34
|
+
"packages/shared/dist",
|
|
35
|
+
"scripts/postbuild.js"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"dev:server": "pnpm --filter @noter/server run dev",
|
|
39
|
+
"dev:client": "pnpm --filter @noter/client run dev",
|
|
40
|
+
"dev": "concurrently \"pnpm run dev:server\" \"pnpm run dev:client\"",
|
|
41
|
+
"build:shared": "pnpm --filter @noter/shared run build",
|
|
42
|
+
"build:server": "pnpm --filter @noter/server run build",
|
|
43
|
+
"build:client": "pnpm --filter @noter/client run build",
|
|
44
|
+
"build:bin": "tsc -p bin/tsconfig.json",
|
|
45
|
+
"postbuild": "node scripts/postbuild.js",
|
|
46
|
+
"build": "pnpm run build:shared && pnpm run build:server && pnpm run build:client && pnpm run build:bin && pnpm run postbuild",
|
|
47
|
+
"typecheck": "pnpm --filter @noter/server run typecheck && pnpm --filter @noter/client run typecheck",
|
|
48
|
+
"test": "vitest run",
|
|
49
|
+
"prepublishOnly": "pnpm run build && pnpm run typecheck && pnpm run test"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@ai-sdk/anthropic": "^3.0.74",
|
|
53
|
+
"@ai-sdk/google": "^3.0.67",
|
|
54
|
+
"@ai-sdk/openai": "^3.0.58",
|
|
55
|
+
"@opencode-ai/sdk": "^1.3.3",
|
|
56
|
+
"ai": "^6.0.174",
|
|
57
|
+
"ai-sdk-ollama": "^3.8.3",
|
|
58
|
+
"better-sqlite3": "^12.3.1",
|
|
59
|
+
"dotenv": "^17.3.1",
|
|
60
|
+
"express": "^5.0.1",
|
|
61
|
+
"ws": "^8.18.0",
|
|
62
|
+
"zod": "^3.25.76"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@playwright/test": "^1.60.0",
|
|
66
|
+
"@vitest/coverage-v8": "^4.1.5",
|
|
67
|
+
"concurrently": "^9.1.2",
|
|
68
|
+
"typescript": "^5.8.2",
|
|
69
|
+
"vite": "^6.4.2",
|
|
70
|
+
"vitest": "^4.1.5"
|
|
71
|
+
},
|
|
72
|
+
"packageManager": "pnpm@10.30.3"
|
|
73
|
+
}
|