@vladar107/claudescope 0.1.0 → 0.2.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 +282 -0
- package/cli.js +9 -8
- package/package.json +21 -3
- package/server.js +1 -1
- package/web/assets/index-D2huyx2f.js +199 -0
- package/web/assets/index-DhAND_LO.css +1 -0
- package/web/assets/{index-C1L5Vfvl.js → index-_Et9upO3.js} +1 -1
- package/web/index.html +2 -2
- package/web/assets/index-BCsCuBGo.js +0 -199
- package/web/assets/index-kyAQXqln.css +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# Claudescope
|
|
2
|
+
|
|
3
|
+
[](https://github.com/vladar107/claudescope/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@vladar107/claudescope)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
|
|
8
|
+
*A scope for your Claude Code sessions.*
|
|
9
|
+
|
|
10
|
+
A local, **read-only** web app to browse, read, search, and analyze your
|
|
11
|
+
[Claude Code](https://claude.com/claude-code) session transcripts
|
|
12
|
+
(`~/.claude/projects/**/*.jsonl`).
|
|
13
|
+
|
|
14
|
+
- **Browse** every session grouped by project — titles, dates, message/tool counts, token totals, cost, git branch, PR links.
|
|
15
|
+
- **Read** a session as a clean threaded conversation: markdown, syntax-highlighted code, collapsible thinking, paired tool calls + results, **syntax-highlighted red/green diffs** for `Edit`/`MultiEdit`, attachments, and sidechain/subagent turns. A built-in **find-in-session** bar (⌘/Ctrl+F) searches the whole transcript — including collapsed thinking, tool, and subagent content — auto-expanding and highlighting matches, with a user/assistant filter.
|
|
16
|
+
- **Review changes** via a **Files changed** tab that aggregates every `Edit`/`MultiEdit`/`Write` in the session by file, with per-file diffs and +/− counts (diffs load lazily per file).
|
|
17
|
+
- **Export / share** a session to Markdown — download or copy it, with an optional toggle to **redact** home-dir paths and likely secrets.
|
|
18
|
+
- **Search** full-text across all sessions (DuckDB BM25), with highlighted snippets that deep-link to the exact message.
|
|
19
|
+
- **Analyze** token usage and cost over time, by project, and by model — including cache-hit ratio.
|
|
20
|
+
|
|
21
|
+
> **Privacy:** Everything runs locally on `127.0.0.1`. The app **never** writes to
|
|
22
|
+
> `~/.claude`. Its only persistent state lives in `~/.claudescope/` — a DuckDB
|
|
23
|
+
> index and a copy of the pricing file, both safe to delete anytime. The sole
|
|
24
|
+
> outbound request is an optional daily check for a newer published version
|
|
25
|
+
> (`claudescope update`); nothing about your transcripts ever leaves your machine.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Screenshots
|
|
30
|
+
|
|
31
|
+
> The screenshots below use **synthetic demo data** — every project name, path,
|
|
32
|
+
> and message is fabricated. Reproduce it locally with:
|
|
33
|
+
> `node scripts/demo-seed.mjs && CLAUDE_PROJECTS_DIR=.demo/projects npm start`.
|
|
34
|
+
|
|
35
|
+
**Browse** — every project and its sessions at a glance: titles, dates, message &
|
|
36
|
+
tool counts, token totals, cost, git branch, and PR links.
|
|
37
|
+
|
|
38
|
+

|
|
39
|
+
|
|
40
|
+
**Read** — a session as a clean threaded conversation: markdown, collapsible
|
|
41
|
+
thinking, **syntax-highlighted red/green diffs** for `Edit`/`MultiEdit`, nested
|
|
42
|
+
**subagent** runs, per-message token chips, and a **find-in-session** bar (⌘/Ctrl+F)
|
|
43
|
+
that auto-expands and highlights matches. **Conversation / Files-changed** tabs and
|
|
44
|
+
an **⤓ Export** (Markdown, optional redaction) sit in the header.
|
|
45
|
+
|
|
46
|
+

|
|
47
|
+
|
|
48
|
+
**Search** — full-text across every session (DuckDB BM25) with highlighted
|
|
49
|
+
snippets and user/assistant filters; each result deep-links to the exact message.
|
|
50
|
+
|
|
51
|
+

|
|
52
|
+
|
|
53
|
+
**Analyze** — token & cost analytics over time, by project, and by model, with a
|
|
54
|
+
cache-read breakdown. Click a chart legend to toggle a series.
|
|
55
|
+
|
|
56
|
+

|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Quick start
|
|
61
|
+
|
|
62
|
+
**Prerequisite:** [Node.js](https://nodejs.org) **20 or newer** (`node -v`).
|
|
63
|
+
|
|
64
|
+
### Install (recommended)
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npm install -g @vladar107/claudescope
|
|
68
|
+
claudescope # starts the app in the background and opens your browser
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`claudescope` serves the whole app (UI + API) from a single port
|
|
72
|
+
(**http://localhost:4317** by default), runs in the **background**, and opens
|
|
73
|
+
your browser. Run it once and forget it; new sessions appear automatically.
|
|
74
|
+
|
|
75
|
+
Try it without installing:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npx @vladar107/claudescope
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Commands
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
claudescope # = claudescope start
|
|
85
|
+
claudescope start # start in the background (idempotent), open the browser
|
|
86
|
+
claudescope stop # stop the background server
|
|
87
|
+
claudescope restart # restart it
|
|
88
|
+
claudescope status # is it running? is an update available?
|
|
89
|
+
claudescope open # open the running app in your browser
|
|
90
|
+
claudescope logs -f # tail the server log
|
|
91
|
+
claudescope update # upgrade to the latest published version and restart
|
|
92
|
+
claudescope help # full usage
|
|
93
|
+
|
|
94
|
+
# options: --port <n> (default 4317, or $PORT)
|
|
95
|
+
# --no-open (don't open the browser on start)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Updating later is just `claudescope update` (or `npm i -g @vladar107/claudescope@latest`).
|
|
99
|
+
|
|
100
|
+
### Run from source
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
git clone https://github.com/vladar107/claudescope && cd claudescope
|
|
104
|
+
npm install # installs all workspace dependencies
|
|
105
|
+
npm start # builds on first run, then serves the app in the foreground
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`npm start` runs in the foreground (`Ctrl-C` to stop) — handy for development.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Configuration
|
|
113
|
+
|
|
114
|
+
All optional — set via environment variables.
|
|
115
|
+
|
|
116
|
+
| Variable | Default | Description |
|
|
117
|
+
| --------------------- | ---------------------- | ---------------------------------------------------------------------- |
|
|
118
|
+
| `PORT` | `4317` | Port the app listens on (or `--port <n>`). |
|
|
119
|
+
| `CLAUDE_PROJECTS_DIR` | `~/.claude/projects` | Where to read session transcripts from. A leading `~` is expanded. |
|
|
120
|
+
| `CLAUDESCOPE_HOME` | `~/.claudescope` | Where the app keeps its own state (index, pricing copy, logs, PID). |
|
|
121
|
+
| `REINDEX_INTERVAL_MS` | `15000` | How often to auto-pick-up new/updated sessions. Set `0` to disable. |
|
|
122
|
+
|
|
123
|
+
Examples:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
claudescope --port 8080 # custom port
|
|
127
|
+
CLAUDE_PROJECTS_DIR=/path/to/exported/projects claudescope # view someone else's transcripts
|
|
128
|
+
claudescope --no-open # don't pop a browser tab
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The startup banner prints the resolved URL and the sessions directory in use, so
|
|
132
|
+
you can always confirm what it's reading.
|
|
133
|
+
|
|
134
|
+
### Cost methodology
|
|
135
|
+
|
|
136
|
+
Cost is an **estimate computed locally** from token usage — Claudescope has no
|
|
137
|
+
access to your real billing. For every **assistant** event (the events that carry
|
|
138
|
+
`usage`), it sums each token type times its per-million-token rate:
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
cost = ( input_tokens × input_rate
|
|
142
|
+
+ output_tokens × output_rate
|
|
143
|
+
+ cache_creation_tokens × cache_write_rate
|
|
144
|
+
+ cache_read_tokens × cache_read_rate ) ÷ 1,000,000
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The per-event cost is computed once at index time and stored, so analytics is
|
|
148
|
+
just a `SUM` over events; a project/session total is the sum of its events.
|
|
149
|
+
|
|
150
|
+
Rates live in `~/.claudescope/pricing.json` (seeded on first run from the copy
|
|
151
|
+
shipped with the package; when running from source, `packages/server/pricing.json`).
|
|
152
|
+
A model id resolves in this order:
|
|
153
|
+
exact `models` entry → **family** match (`opus` / `sonnet` / `haiku` substring) →
|
|
154
|
+
`default`. The family step means version- or date-suffixed ids (e.g.
|
|
155
|
+
`claude-haiku-4-5-20251001`) still price correctly. Shipped rates (USD per 1M tokens,
|
|
156
|
+
from Anthropic's published API pricing):
|
|
157
|
+
|
|
158
|
+
| family / model | input | output | cache write (5m) | cache read |
|
|
159
|
+
| ------------------- | ----- | ------ | ---------------- | ---------- |
|
|
160
|
+
| Opus 4.5–4.8 | $5 | $25 | $6.25 | $0.50 |
|
|
161
|
+
| Opus 4.1 / 4 | $15 | $75 | $18.75 | $1.50 |
|
|
162
|
+
| Sonnet 4.x | $3 | $15 | $3.75 | $0.30 |
|
|
163
|
+
| Haiku 4.5 | $1 | $5 | $1.25 | $0.10 |
|
|
164
|
+
| `<synthetic>` | $0 | $0 | $0 | $0 |
|
|
165
|
+
|
|
166
|
+
- Edit `~/.claudescope/pricing.json` to update prices or add models, then re-index
|
|
167
|
+
(`POST /api/reindex` or `claudescope restart`) to recompute.
|
|
168
|
+
- Or run **`npm run update-pricing`** to refresh `pricing.json` from Anthropic's
|
|
169
|
+
published pricing page. There's no official pricing *API*, so this is a
|
|
170
|
+
best-effort scrape (it validates what it parses and won't write garbage) —
|
|
171
|
+
review the diff afterwards. Use `--dry-run` to preview without writing.
|
|
172
|
+
- The `opus`/`sonnet`/`haiku` family rules use **current** pricing; the deprecated
|
|
173
|
+
Opus 4 / 4.1 ($15/$75) are pinned via exact `models` entries. Add an exact entry
|
|
174
|
+
to override any specific model.
|
|
175
|
+
|
|
176
|
+
> **Caveat:** these are **list-price estimates** — they ignore any discounts,
|
|
177
|
+
> service tier, or batch pricing, and the cache-write rate assumes the 5-minute
|
|
178
|
+
> TTL. Treat totals as approximate and best for *relative* comparison
|
|
179
|
+
> (project vs project, day vs day), not as an invoice.
|
|
180
|
+
|
|
181
|
+
The **"Input from cache"** stat is a separate metric:
|
|
182
|
+
`cache_read ÷ (cache_read + cache_creation + input)` — the share of prompt tokens
|
|
183
|
+
served from cache (legitimately high for Claude Code, which re-reads cached context each turn).
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Usage notes
|
|
188
|
+
|
|
189
|
+
- **First launch** builds the app and indexes your transcripts in the background
|
|
190
|
+
(a few seconds). The browse/search/analytics views populate once indexing
|
|
191
|
+
finishes — `/api/health` reports `{"ready":true}` when it's done.
|
|
192
|
+
- **New sessions appear automatically.** The app re-scans on an interval
|
|
193
|
+
(`REINDEX_INTERVAL_MS`, default 15s) and incrementally picks up new or updated
|
|
194
|
+
transcripts — including the session you're currently running — without a
|
|
195
|
+
restart. In an open session, hit **⟳ Refresh** (or ⌘R / Ctrl+R) to pull the
|
|
196
|
+
latest messages in place without losing your scroll position. Each scan is
|
|
197
|
+
near-free when nothing changed; you can also force one with `POST /api/reindex`.
|
|
198
|
+
- **Thinking blocks** appear empty because Claude Code stores only a signature,
|
|
199
|
+
not the reasoning text — the app notes this explicitly. (Not a bug.)
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## How it works
|
|
204
|
+
|
|
205
|
+
npm-workspaces monorepo:
|
|
206
|
+
|
|
207
|
+
| Package | Role |
|
|
208
|
+
| ------------------ | --------------------------------------------------------------------- |
|
|
209
|
+
| `packages/shared` | TypeScript types — the API + data contract shared by server and web. |
|
|
210
|
+
| `packages/server` | Fastify API + DuckDB index (`@duckdb/node-api`). Serves the built UI. |
|
|
211
|
+
| `packages/web` | Vite + React UI (react-markdown, Shiki, Recharts). |
|
|
212
|
+
|
|
213
|
+
DuckDB reads the JSONL natively (`read_ndjson`) for indexing, full-text search,
|
|
214
|
+
and analytics; a small TypeScript parser assembles the threaded view for a single
|
|
215
|
+
session. The index is a derived cache — if it's ever corrupted (e.g. the process
|
|
216
|
+
is killed mid-write) the app discards and rebuilds it automatically.
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Development
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
npm run dev # server (watch) on :4317 + Vite dev server on :5317 with HMR
|
|
224
|
+
npm run typecheck # tsc -b across all packages
|
|
225
|
+
npm run build # production build (shared → web → server)
|
|
226
|
+
npm run serve # run the built server without rebuilding
|
|
227
|
+
npm test # run the test suite (Vitest)
|
|
228
|
+
npm run test:watch # watch mode
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Tests use [Vitest](https://vitest.dev). Unit tests cover the thread/subagent
|
|
232
|
+
parser and pure helpers; the **integration suite** builds a real DuckDB index
|
|
233
|
+
from synthetic fixtures (in a temp dir / temp DB — your real `~/.claude` is never
|
|
234
|
+
touched) and exercises every API endpoint end-to-end via Fastify `inject()`.
|
|
235
|
+
|
|
236
|
+
In dev, open the **Vite** URL (http://localhost:5317); it proxies `/api` to the
|
|
237
|
+
server.
|
|
238
|
+
|
|
239
|
+
### Releasing
|
|
240
|
+
|
|
241
|
+
The published package is a single bundle assembled by `npm run bundle` (esbuild
|
|
242
|
+
inlines the server + shared lib; the web build and a default pricing file are
|
|
243
|
+
copied alongside; only `@duckdb/node-api` stays an external native dependency).
|
|
244
|
+
Releases are **tag-only** — never published from a laptop:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
npm version patch # bumps package.json + creates the vX.Y.Z tag
|
|
248
|
+
git push --follow-tags # the tag triggers .github/workflows/release.yml → npm publish
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
The release workflow verifies the tag matches `package.json`, runs the tests,
|
|
252
|
+
bundles, and publishes. Auth uses npm **Trusted Publishing** (OIDC) — no
|
|
253
|
+
`NPM_TOKEN` secret — and provenance is attached automatically.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Security & privacy
|
|
258
|
+
|
|
259
|
+
Claudescope runs entirely on your machine. It treats `~/.claude` as **read-only**,
|
|
260
|
+
**binds to `127.0.0.1` only**, sends **no telemetry**, and its sole outbound
|
|
261
|
+
request is a cached npm-registry version check for the update notice. See
|
|
262
|
+
[`SECURITY.md`](./SECURITY.md) for the full breakdown of filesystem, network,
|
|
263
|
+
shell, and self-update behavior — and how to report a vulnerability.
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Troubleshooting
|
|
268
|
+
|
|
269
|
+
- **App is empty / "sessions directory not found"** — `CLAUDE_PROJECTS_DIR`
|
|
270
|
+
doesn't point at real transcripts. Check the banner and set it correctly.
|
|
271
|
+
- **`Error: listen EADDRINUSE :4317`** — the port is taken; run `claudescope --port <n>`.
|
|
272
|
+
- **Node version errors** — you need Node ≥ 20 (`node -v`).
|
|
273
|
+
- **Stale or wrong data** — delete `~/.claudescope/index.duckdb*` and
|
|
274
|
+
`claudescope restart` to rebuild the index from scratch.
|
|
275
|
+
- **`@duckdb/node-api` install issues** — it ships prebuilt native binaries;
|
|
276
|
+
re-run `npm install` on a supported platform (macOS, Linux, Windows x64/arm64).
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## License
|
|
281
|
+
|
|
282
|
+
[MIT](./LICENSE) © Vladislav Ramazaev
|
package/cli.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __cr } from 'node:module';
|
|
3
3
|
const require = __cr(import.meta.url);
|
|
4
|
-
import{spawn as
|
|
4
|
+
import{spawn as $,spawnSync as y}from"node:child_process";import{existsSync as R,mkdirSync as N,openSync as F,readFileSync as C,rmSync as S,writeFileSync as x}from"node:fs";import{dirname as M,join as g}from"node:path";import{createInterface as V}from"node:readline/promises";import{parseArgs as J}from"node:util";import{fileURLToPath as G}from"node:url";import{copyFileSync as re,existsSync as j,mkdirSync as se}from"node:fs";import{homedir as d}from"node:os";import{dirname as H,join as s}from"node:path";import{fileURLToPath as B}from"node:url";var v=H(B(import.meta.url));function D(e,t){return e.find(o=>j(o))??t}var w=Number(process.env.PORT??4317),f=s(v,"..");function A(e){return e==="~"?d():e.startsWith("~/")?s(d(),e.slice(2)):e}var E=A(process.env.CLAUDE_PROJECTS_DIR??s(d(),".claude","projects")),le=process.env.OPEN_BROWSER==="1",pe=Number(process.env.REINDEX_INTERVAL_MS??15e3),a=A(process.env.CLAUDESCOPE_HOME??s(d(),".claudescope")),ue=process.env.DUCKDB_PATH??s(a,"index.duckdb"),de=D([s(v,"pricing.default.json"),s(f,"pricing.json")],s(f,"pricing.json")),fe=process.env.PRICING_PATH??s(a,"pricing.json"),me=process.env.WEB_DIST_DIR??D([s(v,"web"),s(f,"..","web","dist")],s(f,"..","web","dist")),i="0.2.0";var W=M(G(import.meta.url)),K=g(W,"server.js"),c=g(a,"daemon.json"),m=g(a,"daemon.log"),_=g(a,"update-check.json"),p="@vladar107/claudescope",X=24*60*60*1e3;function h(){if(!R(c))return null;try{return JSON.parse(C(c,"utf8"))}catch{return null}}function u(e){try{return process.kill(e,0),!0}catch{return!1}}async function O(e){try{return(await fetch(`http://127.0.0.1:${e}/api/health`,{signal:AbortSignal.timeout(1500)})).ok}catch{return!1}}async function q(e,t){let o=Date.now()+t;for(;Date.now()<o;){if(await O(e))return!0;process.stdout.write("."),await new Promise(r=>setTimeout(r,500))}return!1}function b(e){let t=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{$(t,[e],{stdio:"ignore",detached:!0,shell:process.platform==="win32"}).unref()}catch{}}async function I(e,t){N(a,{recursive:!0});let o=h();if(o&&u(o.pid)&&await O(o.port)){console.log(`\u2713 claudescope is already running \u2192 ${o.url}`),t&&b(o.url);return}o&&!u(o.pid)&&S(c,{force:!0});let r=`http://localhost:${e}`,n=F(m,"a"),l=$(process.execPath,[K],{detached:!0,stdio:["ignore",n,n],env:{...process.env,PORT:String(e),OPEN_BROWSER:"0"}});if(l.unref(),x(c,JSON.stringify({pid:l.pid,port:e,url:r,version:i,startedAt:new Date().toISOString()},null,2)),process.stdout.write("\u203A Starting claudescope"),!await q(e,2e4)){console.error(`
|
|
5
5
|
\u2717 Server did not become healthy in time. Inspect: claudescope logs`),process.exitCode=1;return}console.log(`
|
|
6
|
-
\u2713 claudescope running \u2192 ${r}`),console.log(` Sessions: ${
|
|
7
|
-
\u2B06 Update available: v${
|
|
6
|
+
\u2713 claudescope running \u2192 ${r}`),console.log(` Sessions: ${E} (read-only)`),t&&b(r),await L(!1)}function P(){let e=h();if(!e||!u(e.pid)){console.log("claudescope is not running."),S(c,{force:!0});return}try{process.kill(e.pid,"SIGTERM")}catch{}S(c,{force:!0}),console.log(`\u2713 Stopped claudescope (pid ${e.pid}).`)}async function Y(){let e=h();e&&u(e.pid)&&await O(e.port)?console.log(`\u25CF running ${e.url} (pid ${e.pid}, v${e.version})`):console.log(`\u25CB stopped (installed v${i})`),await L(!0)}function z(){let e=h();e&&u(e.pid)?b(e.url):console.log("claudescope is not running. Start it with: claudescope start")}function Q(e){if(!R(m)){console.log("No logs yet.");return}e&&process.platform!=="win32"?y("tail",["-f",m],{stdio:"inherit"}):process.stdout.write(C(m,"utf8"))}async function Z(e,t){if(!process.stdin.isTTY)return t;let o=V({input:process.stdin,output:process.stdout});try{let r=(await o.question(`${e} ${t?"[Y/n]":"[y/N]"} `)).trim().toLowerCase();return r?r==="y"||r==="yes":t}finally{o.close()}}async function ee(e){let t=await U(!0);if(t&&!k(t,i)){console.log(`\u2713 Already on the latest version (v${i}).`);return}t||console.log("\u26A0 Could not reach the npm registry to confirm the latest version.");let o=t?`v${i} \u2192 v${t}`:`v${i} \u2192 latest`;if(console.log(`\u203A Will run: npm install -g ${p}@latest (${o})`),!e&&!await Z("Proceed?",!0)){console.log("Aborted.");return}console.log(`\u203A Updating ${p}\u2026`);let r=process.platform==="win32"?"npm.cmd":"npm";if(y(r,["install","-g",`${p}@latest`],{stdio:"inherit"}).status!==0){console.error(`\u2717 Update failed. If you run via npx, just re-run \`npx ${p}\` to get the latest.`),process.exitCode=1;return}P(),console.log("\u2713 Updated. Restarting\u2026"),y("claudescope",["start"],{stdio:"inherit",shell:process.platform==="win32"})}function k(e,t){let o=e.split(".").map(n=>Number.parseInt(n,10)||0),r=t.split(".").map(n=>Number.parseInt(n,10)||0);for(let n=0;n<3;n++){if((o[n]??0)>(r[n]??0))return!0;if((o[n]??0)<(r[n]??0))return!1}return!1}async function U(e){let t=Date.now();if(!e&&R(_))try{let l=JSON.parse(C(_,"utf8"));if(t-l.lastCheck<X)return l.latest}catch{}let o=`https://registry.npmjs.org/${p.replace("/","%2f")}/latest`,r=await fetch(o,{signal:AbortSignal.timeout(2500)});if(!r.ok)return null;let n=await r.json();return n.version?(N(a,{recursive:!0}),x(_,JSON.stringify({lastCheck:t,latest:n.version})),n.version):null}async function L(e){try{let t=await U(e);t&&k(t,i)&&console.log(`
|
|
7
|
+
\u2B06 Update available: v${i} \u2192 v${t}. Run: claudescope update`)}catch{}}function T(){console.log(`claudescope v${i} \u2014 local viewer for Claude Code transcripts
|
|
8
8
|
|
|
9
9
|
Usage: claudescope [command] [options]
|
|
10
10
|
|
|
@@ -15,15 +15,16 @@ Commands:
|
|
|
15
15
|
status Show whether the server is running and if an update exists
|
|
16
16
|
open Open the running app in your browser
|
|
17
17
|
logs [-f] Print the server log (-f / --follow to tail it)
|
|
18
|
-
update
|
|
18
|
+
update [-y] Upgrade to the latest published version and restart
|
|
19
19
|
help Show this help
|
|
20
20
|
version Print the installed version
|
|
21
21
|
|
|
22
22
|
Options:
|
|
23
|
-
--port <n> Port to listen on (default ${
|
|
23
|
+
--port <n> Port to listen on (default ${w}, or $PORT)
|
|
24
24
|
--no-open Don't open the browser on start
|
|
25
|
+
-y, --yes Skip the confirmation prompt (for \`update\`)
|
|
25
26
|
|
|
26
|
-
State (index, pricing, logs, PID) lives in ${
|
|
27
|
+
State (index, pricing, logs, PID) lives in ${a}
|
|
27
28
|
(override with $CLAUDESCOPE_HOME). Sessions are read from
|
|
28
|
-
${
|
|
29
|
-
`),T(),process.exitCode=1}}
|
|
29
|
+
${E} (override with $CLAUDE_PROJECTS_DIR).`)}async function te(){let{values:e,positionals:t}=J({allowPositionals:!0,options:{port:{type:"string"},follow:{type:"boolean",short:"f"},help:{type:"boolean",short:"h"},version:{type:"boolean",short:"v"},yes:{type:"boolean",short:"y"},"no-open":{type:"boolean"}}}),o=e.port?Number(e.port):w,r=!e["no-open"],n=t[0];switch(n||(n=e.help?"help":e.version?"version":"start"),n){case"start":await I(o,r);break;case"stop":P();break;case"restart":P(),await I(o,r);break;case"status":await Y();break;case"open":z();break;case"logs":Q(!!e.follow);break;case"update":await ee(!!e.yes);break;case"version":console.log(i);break;case"help":T();break;default:console.error(`Unknown command: ${n}
|
|
30
|
+
`),T(),process.exitCode=1}}te().catch(e=>{console.error(e),process.exit(1)});
|
package/package.json
CHANGED
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vladar107/claudescope",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Local
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Local, read-only web app to browse, read, search, and analyze your Claude Code session transcripts.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude",
|
|
7
|
+
"claude-code",
|
|
8
|
+
"anthropic",
|
|
9
|
+
"transcripts",
|
|
10
|
+
"sessions",
|
|
11
|
+
"viewer",
|
|
12
|
+
"cli",
|
|
13
|
+
"duckdb"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://github.com/vladar107/claudescope#readme",
|
|
16
|
+
"bugs": "https://github.com/vladar107/claudescope/issues",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/vladar107/claudescope.git"
|
|
20
|
+
},
|
|
21
|
+
"author": "Vladislav Ramazaev",
|
|
5
22
|
"license": "MIT",
|
|
6
23
|
"type": "module",
|
|
7
24
|
"bin": {
|
|
@@ -11,7 +28,8 @@
|
|
|
11
28
|
"cli.js",
|
|
12
29
|
"server.js",
|
|
13
30
|
"web",
|
|
14
|
-
"pricing.default.json"
|
|
31
|
+
"pricing.default.json",
|
|
32
|
+
"README.md"
|
|
15
33
|
],
|
|
16
34
|
"engines": {
|
|
17
35
|
"node": ">=20"
|
package/server.js
CHANGED
|
@@ -389,7 +389,7 @@ globstar while`,O,X,N,re,fe),this.matchOne(O.slice(X),N.slice(re),L))return this
|
|
|
389
389
|
\x1B[36mat `+r[n].toString()+"\x1B[39m";return i}return t&&(i+=" \x1B[36m"+Gg(t)+"\x1B[39m"),i}function Gg(e){return T7(O7,e[0])+":"+e[1]+":"+e[2]}function gu(){var e=Error.stackTraceLimit,t={},r=Error.prepareStackTrace;Error.prepareStackTrace=j7,Error.stackTraceLimit=Math.max(10,e),Error.captureStackTrace(t);var i=t.stack.slice(1);return Error.prepareStackTrace=r,Error.stackTraceLimit=e,i}function j7(e,t){return t}function D7(e,t){if(typeof e!="function")throw new TypeError("argument fn must be a function");var r=P7(e.length),i=gu(),n=hs(i[1]);n.name=e.name;var s=new Function("fn","log","deprecate","message","site",`"use strict"
|
|
390
390
|
return function (`+r+`) {log.call(deprecate, message, site)
|
|
391
391
|
return fn.apply(this, arguments)
|
|
392
|
-
}`)(e,mu,this,t,n);return s}function q7(e,t,r){if(!e||typeof e!="object"&&typeof e!="function")throw new TypeError("argument obj must be object");var i=Object.getOwnPropertyDescriptor(e,t);if(!i)throw new TypeError("must call property on owner object");if(!i.configurable)throw new TypeError("property must be configurable");var n=this,s=gu(),o=hs(s[1]);o.name=t,"value"in i&&(i=x7(e,t,r));var a=i.get,l=i.set;typeof a=="function"&&(i.get=function(){return mu.call(n,r,o),a.apply(this,arguments)}),typeof l=="function"&&(i.set=function(){return mu.call(n,r,o),l.apply(this,arguments)}),Object.defineProperty(e,t,i)}function D$(e,t,r){var i=new Error,n;return Object.defineProperty(i,"constructor",{value:D$}),Object.defineProperty(i,"message",{configurable:!0,enumerable:!1,value:t,writable:!0}),Object.defineProperty(i,"name",{enumerable:!1,configurable:!0,value:"DeprecationError",writable:!0}),Object.defineProperty(i,"namespace",{configurable:!0,enumerable:!1,value:e,writable:!0}),Object.defineProperty(i,"stack",{configurable:!0,enumerable:!1,get:function(){return n!==void 0?n:n=A7.call(this,r)},set:function(o){n=o}}),i}});var z$=E((Gne,M$)=>{"use strict";M$.exports=Object.setPrototypeOf||({__proto__:[]}instanceof Array?F7:M7);function F7(e,t){return e.__proto__=t,e}function M7(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(e,r)||(e[r]=t[r]);return e}});var H$=E((Wne,z7)=>{z7.exports={"100":"Continue","101":"Switching Protocols","102":"Processing","103":"Early Hints","200":"OK","201":"Created","202":"Accepted","203":"Non-Authoritative Information","204":"No Content","205":"Reset Content","206":"Partial Content","207":"Multi-Status","208":"Already Reported","226":"IM Used","300":"Multiple Choices","301":"Moved Permanently","302":"Found","303":"See Other","304":"Not Modified","305":"Use Proxy","307":"Temporary Redirect","308":"Permanent Redirect","400":"Bad Request","401":"Unauthorized","402":"Payment Required","403":"Forbidden","404":"Not Found","405":"Method Not Allowed","406":"Not Acceptable","407":"Proxy Authentication Required","408":"Request Timeout","409":"Conflict","410":"Gone","411":"Length Required","412":"Precondition Failed","413":"Payload Too Large","414":"URI Too Long","415":"Unsupported Media Type","416":"Range Not Satisfiable","417":"Expectation Failed","418":"I'm a Teapot","421":"Misdirected Request","422":"Unprocessable Entity","423":"Locked","424":"Failed Dependency","425":"Too Early","426":"Upgrade Required","428":"Precondition Required","429":"Too Many Requests","431":"Request Header Fields Too Large","451":"Unavailable For Legal Reasons","500":"Internal Server Error","501":"Not Implemented","502":"Bad Gateway","503":"Service Unavailable","504":"Gateway Timeout","505":"HTTP Version Not Supported","506":"Variant Also Negotiates","507":"Insufficient Storage","508":"Loop Detected","509":"Bandwidth Limit Exceeded","510":"Not Extended","511":"Network Authentication Required"}});var B$=E((Jne,V$)=>{"use strict";var Wg=H$();V$.exports=yr;yr.message=Wg;yr.code=H7(Wg);yr.codes=U7(Wg);yr.redirect={300:!0,301:!0,302:!0,303:!0,305:!0,307:!0,308:!0};yr.empty={204:!0,205:!0,304:!0};yr.retry={502:!0,503:!0,504:!0};function H7(e){var t={};return Object.keys(e).forEach(function(i){var n=e[i],s=Number(i);t[n.toLowerCase()]=s}),t}function U7(e){return Object.keys(e).map(function(r){return Number(r)})}function V7(e){var t=e.toLowerCase();if(!Object.prototype.hasOwnProperty.call(yr.code,t))throw new Error('invalid status message: "'+e+'"');return yr.code[t]}function U$(e){if(!Object.prototype.hasOwnProperty.call(yr.message,e))throw new Error("invalid status code: "+e);return yr.message[e]}function yr(e){if(typeof e=="number")return U$(e);if(typeof e!="string")throw new TypeError("code must be a number or string");var t=parseInt(e,10);return isNaN(t)?V7(e):U$(t)}});var G$=E((Kne,Jg)=>{typeof Object.create=="function"?Jg.exports=function(t,r){r&&(t.super_=r,t.prototype=Object.create(r.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}))}:Jg.exports=function(t,r){if(r){t.super_=r;var i=function(){};i.prototype=r.prototype,t.prototype=new i,t.prototype.constructor=t}}});var W$=E((Yne,Yg)=>{try{if(Kg=ee("util"),typeof Kg.inherits!="function")throw"";Yg.exports=Kg.inherits}catch{Yg.exports=G$()}var Kg});var K$=E((Xne,J$)=>{"use strict";J$.exports=B7;function B7(e){return e.split(" ").map(function(t){return t.slice(0,1).toUpperCase()+t.slice(1)}).join("").replace(/[^ _0-9a-z]/gi,"")}});var eC=E((Qne,on)=>{"use strict";var G7=F$()("http-errors"),Y$=z$(),ps=B$(),Xg=W$(),W7=K$();on.exports=yu;on.exports.HttpError=J7();on.exports.isHttpError=Y7(on.exports.HttpError);Q7(on.exports,ps.codes,on.exports.HttpError);function X$(e){return+(String(e).charAt(0)+"00")}function yu(){for(var e,t,r=500,i={},n=0;n<arguments.length;n++){var s=arguments[n],o=typeof s;if(o==="object"&&s instanceof Error)e=s,r=e.status||e.statusCode||r;else if(o==="number"&&n===0)r=s;else if(o==="string")t=s;else if(o==="object")i=s;else throw new TypeError("argument #"+(n+1)+" unsupported type "+o)}typeof r=="number"&&(r<400||r>=600)&&G7("non-error status code; use only 4xx or 5xx status codes"),(typeof r!="number"||!ps.message[r]&&(r<400||r>=600))&&(r=500);var a=yu[r]||yu[X$(r)];e||(e=a?new a(t):new Error(t||ps.message[r]),Error.captureStackTrace(e,yu)),(!a||!(e instanceof a)||e.status!==r)&&(e.expose=r<500,e.status=e.statusCode=r);for(var l in i)l!=="status"&&l!=="statusCode"&&(e[l]=i[l]);return e}function J7(){function e(){throw new TypeError("cannot construct abstract class")}return Xg(e,Error),e}function K7(e,t,r){var i=Z$(t);function n(s){var o=s??ps.message[r],a=new Error(o);return Error.captureStackTrace(a,n),Y$(a,n.prototype),Object.defineProperty(a,"message",{enumerable:!0,configurable:!0,value:o,writable:!0}),Object.defineProperty(a,"name",{enumerable:!1,configurable:!0,value:i,writable:!0}),a}return Xg(n,e),Q$(n,i),n.prototype.status=r,n.prototype.statusCode=r,n.prototype.expose=!0,n}function Y7(e){return function(r){return!r||typeof r!="object"?!1:r instanceof e?!0:r instanceof Error&&typeof r.expose=="boolean"&&typeof r.statusCode=="number"&&r.status===r.statusCode}}function X7(e,t,r){var i=Z$(t);function n(s){var o=s??ps.message[r],a=new Error(o);return Error.captureStackTrace(a,n),Y$(a,n.prototype),Object.defineProperty(a,"message",{enumerable:!0,configurable:!0,value:o,writable:!0}),Object.defineProperty(a,"name",{enumerable:!1,configurable:!0,value:i,writable:!0}),a}return Xg(n,e),Q$(n,i),n.prototype.status=r,n.prototype.statusCode=r,n.prototype.expose=!1,n}function Q$(e,t){var r=Object.getOwnPropertyDescriptor(e,"name");r&&r.configurable&&(r.value=t,Object.defineProperty(e,"name",r))}function Q7(e,t,r){t.forEach(function(n){var s,o=W7(ps.message[n]);switch(X$(n)){case 400:s=K7(r,o,n);break;case 500:s=X7(r,o,n);break}s&&(e[n]=s,e[o]=s)})}function Z$(e){return e.slice(-5)==="Error"?e:e+"Error"}});var rC=E((Zne,tC)=>{"use strict";var Qg=eC();function Z7(e,t){return t?t instanceof Error?Qg(e,t,{expose:!1}):Qg(e,t):Qg(e)}tC.exports.createHttpError=Z7});var hC=E((ese,dC)=>{"use strict";var aC=ee("node:fs"),sa=ee("node:path"),eX=ee("node:stream"),Pt=ee("node:util").debuglog("send"),tX=zm(),rX=_$(),iC=Ug(),iX=v$(),{collapseLeadingSlashes:nX}=S$(),{containsDotFile:sX}=E$(),{contentRange:nC}=T$(),{createHtmlDocument:an}=x$(),{isUtf8MimeType:oX}=Hg(),{normalizeList:sC}=A$(),{parseBytesRange:aX}=C$(),{parseTokenList:lC}=N$(),{createHttpError:lX}=rC(),cX=sa.extname,cC=sa.join,Zg=sa.normalize,uC=sa.resolve,_u=sa.sep,vu=eX.Readable,uX=/^ *bytes=/,fX=60*60*24*365*1e3,oC=/(?:^|[\\/])\.\.(?:[\\/]|$)/,dX={400:an("Error","Bad Request"),403:an("Error","Forbidden"),404:an("Error","Not Found"),412:an("Error","Precondition Failed"),416:an("Error","Range Not Satisfiable"),500:an("Error","Internal Server Error")},hX=["allow","ignore","deny"];function pX(e){let t;return typeof e=="string"?t=iX.parse(e):t=Number(e),t!==t?0:Math.min(Math.max(0,t),fX)}function mX(e){e=e??{};let t=e.acceptRanges!==void 0?!!e.acceptRanges:!0,r=e.cacheControl!==void 0?!!e.cacheControl:!0,i=e.contentType!==void 0?!!e.contentType:!0,n=e.etag!==void 0?!!e.etag:!0,s=e.dotfiles!==void 0?hX.indexOf(e.dotfiles):1;if(s===-1)throw new TypeError('dotfiles option must be "allow", "deny", or "ignore"');let o=e.extensions!==void 0?sC(e.extensions,"extensions option"):[],a=e.immutable!==void 0?!!e.immutable:!1,l=e.index!==void 0?sC(e.index,"index option"):["index.html"],c=e.lastModified!==void 0?!!e.lastModified:!0,u=pX(e.maxAge??e.maxage),d=e.maxContentRangeChunkSize!==void 0?Number(e.maxContentRangeChunkSize):null,m=e.root?uC(e.root):null,h=Number.isSafeInteger(e.highWaterMark)&&e.highWaterMark>0?e.highWaterMark:null;return{acceptRanges:t,cacheControl:r,contentType:i,etag:n,dotfiles:s,extensions:o,immutable:a,index:l,lastModified:c,maxage:u,maxContentRangeChunkSize:d,root:m,highWaterMark:h,start:e.start,end:e.end}}function gX(e,t){let r=tX(e);if(r==null)return{statusCode:400};if(~r.indexOf("\0"))return{statusCode:400};let i;if(t!==null){if(r&&(r=Zg("."+_u+r)),oC.test(r))return Pt('malicious path "%s"',r),{statusCode:403};i=r.split(_u),r=Zg(cC(t,r))}else{if(oC.test(r))return Pt('malicious path "%s"',r),{statusCode:403};i=Zg(r).split(_u),r=uC(r)}return{path:r,parts:i}}function fC(e){return e[e.length-1]==="/"}function yX(e){return e.headers["if-match"]||e.headers["if-unmodified-since"]||e.headers["if-none-match"]||e.headers["if-modified-since"]}function _X(e,t){if("cache-control"in e.headers&&e.headers["cache-control"].indexOf("no-cache")!==-1)return!1;if("if-none-match"in e.headers){let r=e.headers["if-none-match"];if(r==="*")return!0;let i=t.ETag;if(typeof i!="string")return!1;let n=i.length;return!!lC(r,function(o){let a=o.length;if(n===a&&o===i||n>a&&"W/"+o===i)return!0})}if("if-modified-since"in e.headers){let r=e.headers["if-modified-since"],i=t["Last-Modified"];if(!i||Date.parse(i)<=Date.parse(r))return!0}return!1}function vX(e,t){let r=e.headers["if-match"];if(r){let i=t.ETag;if(r!=="*"&&(lC(r,function(s){if(s===i||"W/"+s===i)return!0})||!1)!==!0)return!0}if("if-unmodified-since"in e.headers){let i=e.headers["if-unmodified-since"],n=Date.parse(i);if(n===n){let s=Date.parse(t["Last-Modified"]);if(s!==s||s>n)return!0}}return!1}function wX(e,t){if(!("if-range"in e.headers))return!0;let r=e.headers["if-range"];if(r.indexOf('"')!==-1){let s=t.ETag;return s&&r.indexOf(s)!==-1||!1}let i=Date.parse(r);if(i!==i)return!1;let n=Date.parse(t["Last-Modified"]);return n!==n||n<=i}function ey(e){return new Promise(t=>{aC.stat(e,function(i,n){t({error:i,stat:n})})})}function Ir(e,t){let r={};if(t&&t.headers)for(let n in t.headers)r[n]=t.headers[n];let i=dX[e];return r["Content-Type"]="text/html; charset=utf-8",r["Content-Length"]=i[1],r["Content-Security-Policy"]="default-src 'none'",r["X-Content-Type-Options"]="nosniff",{statusCode:e,headers:r,stream:vu.from(i[0]),type:"error",metadata:{error:lX(e,t)}}}function ty(e){switch(e.code){case"ENAMETOOLONG":case"ENOTDIR":case"ENOENT":return Ir(404,e);default:return Ir(500,e)}}function SX(e,t,r){return Pt("not modified"),delete e["Content-Encoding"],delete e["Content-Language"],delete e["Content-Length"],delete e["Content-Range"],delete e["Content-Type"],{statusCode:304,headers:e,stream:vu.from(""),type:"file",metadata:{path:t,stat:r}}}function ry(e,t,r,i){let n=r.size,s=i.start??0,o=200,a={};if(Pt('send "%s"',t),i.acceptRanges&&(Pt("accept ranges"),a["Accept-Ranges"]="bytes"),i.cacheControl){let c="public, max-age="+Math.floor(i.maxage/1e3);i.immutable&&(c+=", immutable"),Pt("cache-control %s",c),a["Cache-Control"]=c}if(i.lastModified){let c=r.mtime.toUTCString();Pt("modified %s",c),a["Last-Modified"]=c}if(i.etag){let c='W/"'+r.size.toString(16)+"-"+r.mtime.getTime().toString(16)+'"';Pt("etag %s",c),a.ETag=c}if(i.contentType){let c=iC.getType(t)||iC.default_type;Pt("content-type %s",c),c&&oX(c)&&(c+="; charset=utf-8"),c&&(a["Content-Type"]=c)}if(yX(e)){if(vX(e,a))return Ir(412);if(_X(e,a))return SX(a,t,r)}if(n=Math.max(0,n-s),i.end!==void 0){let c=i.end-s+1;n>c&&(n=c)}if(i.acceptRanges){let c=e.headers.range;if(c!==void 0&&uX.test(c))if(wX(e,a)){let u=aX(n,c);if(u.length===0)return Pt("range unsatisfiable"),a["Content-Range"]=nC("bytes",n),Ir(416,{headers:{"Content-Range":a["Content-Range"]}});u.length===1&&(Pt("range %j",u),o=206,i.maxContentRangeChunkSize&&(u[0].end=Math.min(u[0].end,u[0].start+i.maxContentRangeChunkSize-1)),a["Content-Range"]=nC("bytes",n,u[0]),s+=u[0].start,n=u[0].end-u[0].start+1)}else Pt("range stale")}if(a["Content-Length"]=n,e.method==="HEAD")return{statusCode:o,headers:a,stream:vu.from(""),type:"file",metadata:{path:t,stat:r}};let l=aC.createReadStream(t,{highWaterMark:i.highWaterMark,start:s,end:Math.max(s,s+n-1)});return{statusCode:o,headers:a,stream:l,type:"file",metadata:{path:t,stat:r}}}function bX(e,t){if(fC(t.path))return Ir(403);let r=encodeURI(nX(t.path+"/")),i=an("Redirecting","Redirecting to "+rX(r)),n={};return n["Content-Type"]="text/html; charset=utf-8",n["Content-Length"]=i[1],n["Content-Security-Policy"]="default-src 'none'",n["X-Content-Type-Options"]="nosniff",n.Location=r,{statusCode:301,headers:n,stream:vu.from(i[0]),type:"directory",metadata:{requestPath:t.path,path:e}}}async function EX(e,t,r){let i;for(let n=0;n<r.index.length;n++){let s=r.index[n],o=cC(t,s),{error:a,stat:l}=await ey(o);if(a){i=a;continue}if(!l.isDirectory())return ry(e,o,l,r)}return i?ty(i):Ir(404)}async function RX(e,t,r){let{error:i,stat:n}=await ey(t);if(i&&i.code==="ENOENT"&&!cX(t)&&t[t.length-1]!==_u){let s=i;for(let o=0;o<r.extensions.length;o++){let a=r.extensions[o],l=t+"."+a,{error:c,stat:u}=await ey(l);if(c){s=c;continue}if(u.isDirectory()){s=null;continue}return ry(e,l,u,r)}return s?ty(s):Ir(404)}return i?ty(i):n.isDirectory()?bX(t,r):ry(e,t,n,r)}async function TX(e,t,r){let i=mX(r);i.path=t;let n=gX(t,i.root),{path:s,parts:o}=n;if(n.statusCode!==void 0)return Ir(n.statusCode);if((Pt.enabled||i.dotfiles!==0)&&sX(o))switch(i.dotfiles){case 0:Pt('allow dotfile "%s"',s);break;case 2:return Pt('deny dotfile "%s"',s),Ir(403);case 1:default:return Pt('ignore dotfile "%s"',s),Ir(404)}return i.index.length&&fC(t)?EX(e,s,i):RX(e,s,i)}dC.exports.send=TX});var pC=E((tse,ms)=>{"use strict";var OX=Hg().isUtf8MimeType,xX=Ug(),iy=hC().send;ms.exports=iy;ms.exports.default=iy;ms.exports.send=iy;ms.exports.isUtf8MimeType=OX;ms.exports.mime=xX});var mC=E((rse,ca)=>{"use strict";function sy(e){if(!new.target)return new sy(e);let{supportedValues:t=[],cache:r}=e&&typeof e=="object"&&e||{};this.supportedValues=t,this.cache=r}sy.prototype.negotiate=function(e){return typeof e!="string"?null:this.cache?(this.cache.has(e)||this.cache.set(e,la(e,this.supportedValues)),this.cache.get(e)):la(e,this.supportedValues)};function la(e,t){if(!e||!Array.isArray(t)||t.length===0)return null;if(e==="*")return t[0];let r=null,i=1/0,n=0;function s(o,a){if(a===0||n>a)return!1;let l=o==="*"&&t[0]||o,c=t.indexOf(l);return c===-1?!1:c===0&&a===1?(r=l,!0):((n<a||i>c)&&(r=l,i=c,n=a),!1)}return PX(e,s),r}var oa=0,aa=1,wu=2,ny=3;function PX(e,t){let r="",i,n=oa;for(let s=0,o=e.length;s<o;++s){let a=e[s];if(!(a===" "||a===" ")){if(a===";"){n===aa&&(n=wu,i="");continue}else if(a===","){if(n===aa){if(t(r,1)){n=ny;break}n=oa,r=""}else if(n===wu){if(t(r,parseFloat(i)||0)){n=ny;break}n=oa,r="",i=""}continue}else if(n===wu){if(a==="q"||a==="=")continue;if(a==="."||a==="1"||a==="0"||a==="2"||a==="3"||a==="4"||a==="5"||a==="6"||a==="7"||a==="8"||a==="9"){i+=a;continue}}else if(n===oa){n=aa,r+=a;continue}if(n===aa){let l=e[s-1];(l===" "||l===" ")&&(r=""),r+=a;continue}if(t(r,parseFloat(i)||0)){n=ny;break}n=oa,r=a,i=""}}n===aa?t(r,1):n===wu&&t(r,parseFloat(i)||0)}ca.exports=la;ca.exports.default=la;ca.exports.negotiate=la;ca.exports.Negotiator=sy});var bC=E((ise,oy)=>{"use strict";oy.exports=DX;oy.exports.parse=zX;var AX=new TextDecoder("utf-8"),$X=/[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g,vC=/[^\x20-\x7e\xa0-\xff]/g,CX=/\\([\u0000-\u007f])/g,kX=/([\\"])/g,gC=/;[\x09\x20]*([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*=[\x09\x20]*("(?:[\x20!\x23-\x5b\x5d-\x7e\x80-\xff]|\\[\x20-\x7e])*"|[!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*/g,IX=/^[\x20-\x7e\x80-\xff]+$/,NX=/^[!#$%&'*+.0-9A-Z^_`a-z|~-]+$/,LX=/^([A-Za-z0-9!#$%&+\-^_`{}~]+)'(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8}|)'((?:%[0-9A-Fa-f]{2}|[A-Za-z0-9!#$&+.^_`|~-])+)$/,jX=/^([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*(?:$|;)/;function DX(e,t){var r=t||{},i=r.type||"attachment",n=qX(e,r.fallback);return FX(new SC(i,n))}function qX(e,t){if(e!==void 0){var r={};if(typeof e!="string")throw new TypeError("filename must be a string");if(t===void 0&&(t=!0),typeof t!="string"&&typeof t!="boolean")throw new TypeError("fallback must be a string or boolean");if(typeof t=="string"&&vC.test(t))throw new TypeError("fallback must be ISO-8859-1 string");var i=yC(e),n=IX.test(i),s=typeof t!="string"?t&&wC(i):yC(t),o=typeof s=="string"&&s!==i;return(o||!n||BX(i))&&(r["filename*"]=i),(n||o)&&(r.filename=o?s:i),r}}function FX(e){var t=e.parameters,r=e.type;if(!r||typeof r!="string"||!NX.test(r))throw new TypeError("invalid type");var i=String(r).toLowerCase();if(t&&typeof t=="object")for(var n,s=Object.keys(t).sort(),o=0;o<s.length;o++){n=s[o];var a=n.slice(-1)==="*"?VX(t[n]):UX(t[n]);i+="; "+n+"="+a}return i}function MX(e){let t=LX.exec(e);if(!t)throw new TypeError("invalid extended field value");let r=t[1].toLowerCase(),i=t[2];switch(r){case"iso-8859-1":{let n=_C(i);return wC(n)}case"utf-8":case"utf8":try{return decodeURIComponent(i)}catch{let n=_C(i),s=new Uint8Array(n.length);for(let o=0;o<n.length;o++)s[o]=n.charCodeAt(o);return AX.decode(s)}}throw new TypeError("unsupported charset in extended field")}function wC(e){return String(e).replace(vC,"?")}function zX(e){if(!e||typeof e!="string")throw new TypeError("argument string is required");var t=jX.exec(e);if(!t)throw new TypeError("invalid type format");var r=t[0].length,i=t[1].toLowerCase(),n,s=[],o={},a;for(r=gC.lastIndex=t[0].slice(-1)===";"?r-1:r;t=gC.exec(e);){if(t.index!==r)throw new TypeError("invalid parameter format");if(r+=t[0].length,n=t[1].toLowerCase(),a=t[2],s.indexOf(n)!==-1)throw new TypeError("invalid duplicate parameter");if(s.push(n),n.indexOf("*")+1===n.length){n=n.slice(0,-1),a=MX(a),o[n]=a;continue}typeof o[n]!="string"&&(a[0]==='"'&&(a=a.slice(1,-1).replace(CX,"$1")),o[n]=a)}if(r!==-1&&r!==e.length)throw new TypeError("invalid parameter format");return new SC(i,o)}function HX(e){return"%"+String(e).charCodeAt(0).toString(16).toUpperCase()}function UX(e){var t=String(e);return'"'+t.replace(kX,"\\$1")+'"'}function VX(e){var t=String(e),r=encodeURIComponent(t).replace($X,HX);return"UTF-8''"+r}function SC(e,t){this.type=e,this.parameters=t}function yC(e){let t=e.replaceAll("\\","/"),r=t.length;for(;r>0&&t[r-1]==="/";)r--;if(r===0)return"";let i=r-1;for(;i>=0&&t[i]!=="/";)i--;return t.slice(i+1,r)}function Su(e){let t=e.charCodeAt(0);return t>=48&&t<=57||t>=65&&t<=70||t>=97&&t<=102}function BX(e){let t=e.length-3,r=-1;for(;(r=e.indexOf("%",r+1))!==-1&&r<=t;)if(Su(e[r+1])&&Su(e[r+2]))return!0;return!1}function _C(e){let t=e.indexOf("%");if(t===-1)return e;let r=e.slice(0,t);for(let i=t;i<e.length;i++)e[i]==="%"&&i+2<e.length&&Su(e[i+1])&&Su(e[i+2])?(r+=String.fromCharCode(Number.parseInt(e[i+1]+e[i+2],16)),i+=2):r+=e[i];return r}});var OC=E((nse,TC)=>{"use strict";var GX=ee("node:os"),vt=ee("node:path"),bu=ee("node:fs/promises"),EC=ku(),RC=Math.max(1,GX.cpus().length-1);function WX(e,t){let r=vt.relative(e,t);return r===""||r!==".."&&!r.startsWith(`..${vt.sep}`)&&!vt.isAbsolute(r)}var ln={_getExtendedInfo:async function(e,t){let r=e.split(vt.sep).length,i=await bu.readdir(e),n=async o=>{let a=vt.join(e,o),l;try{l=await bu.stat(a)}catch{return}l.isDirectory()?(t.totalFolderCount++,a.split(vt.sep).length===r+1&&t.folderCount++,await ln._getExtendedInfo(a,t)):(t.totalSize+=l.size,t.totalFileCount++,a.split(vt.sep).length===r+1&&t.fileCount++,t.lastModified=Math.max(t.lastModified,l.mtimeMs))},s=EC.promise(n,RC);await Promise.all(i.map(o=>s.push(o)))},getExtendedInfo:async function(e){let t={totalSize:0,fileCount:0,totalFileCount:0,folderCount:0,totalFolderCount:0,lastModified:0};return await ln._getExtendedInfo(e,t),t},list:async function(e,t,r){let i={dirs:[],files:[]},n=await bu.readdir(e);if((r==="deny"||r==="ignore")&&(n=n.filter(a=>a.charAt(0)!==".")),n.length<1)return i;let s=async a=>{let l;try{l=await bu.stat(vt.join(e,a))}catch{return}let c={name:a,stats:l};l.isDirectory()?(t.extendedFolderInfo&&(c.extendedInfo=await ln.getExtendedInfo(vt.join(e,a))),i.dirs.push(c)):i.files.push(c)},o=EC.promise(s,RC);return await Promise.all(n.map(a=>o.push(a))),i.dirs.sort((a,l)=>a.name.localeCompare(l.name)),i.files.sort((a,l)=>a.name.localeCompare(l.name)),i},send:async function({reply:e,dir:t,options:r,route:i,prefix:n,dotfiles:s}){if(e.request.query.format==="html"&&typeof r.render!="function")throw new TypeError("The `list.render` option must be a function and is required with the URL parameter `format=html`");let o;try{o=await ln.list(t,r,s)}catch{return e.callNotFound()}if((e.request.query.format||r.format)!=="html"){if(r.jsonFormat!=="extended"){let c={dirs:[],files:[]};o.dirs.forEach(u=>c.dirs.push(u.name)),o.files.forEach(u=>c.files.push(u.name)),await e.send(c)}else await e.send(o);return}let l=r.render(o.dirs.map(c=>ln.htmlInfo(c,i,n,r)),o.files.map(c=>ln.htmlInfo(c,i,n,r)));await e.type("text/html").send(l)},htmlInfo:function(e,t,r,i){return i.names?.includes(vt.basename(t))&&(t=vt.posix.normalize(vt.posix.join(t,".."))),{href:encodeURI(vt.posix.join(r,t,e.name)),name:e.name,stats:e.stats,extendedInfo:e.extendedInfo}},handle:function(e,t){return t.names?.includes(vt.basename(e))||((t.names?.includes("/")&&e[e.length-1]==="/")??!1)},path:function(e,t){let r=t[t.length-1]==="/"?"."+t+"none":"."+t,i=vt.resolve(e),n=vt.dirname(vt.resolve(i,r));return WX(i,n)?n:null},validateOptions:function(e){if(e.list){if(Array.isArray(e.root))return new TypeError("multi-root with list option is not supported");if(e.list.format&&e.list.format!=="json"&&e.list.format!=="html")return new TypeError("The `list.format` option must be json or html");if(e.list.names&&!Array.isArray(e.list.names))return new TypeError("The `list.names` option must be an array");if(e.list.jsonFormat!=null&&e.list.jsonFormat!=="names"&&e.list.jsonFormat!=="extended")return new TypeError("The `list.jsonFormat` option must be name or extended");if(e.list.format==="html"&&typeof e.list.render!="function")return new TypeError("The `list.render` option must be a function and is required with html format")}}};TC.exports=ln});var IC=E((sse,Eu)=>{"use strict";var Xr=ee("node:path"),{fileURLToPath:xC}=ee("node:url"),{statSync:kC}=ee("node:fs"),{glob:JX}=i$(),KX=l$(),fa=pC(),YX=mC(),XX=bC(),ua=OC(),PC=/\/$/u,QX=/\*/gu,ZX=["br","gzip","deflate"];fa.mime.default_type="application/octet-stream";var AC={br:".br",gzip:".gz"};async function ly(e,t){(t.serve!==!1||t.root!==void 0)&&(t.root=eQ(t.root),tQ(e,t.root));let r=t.setHeaders;if(r!==void 0&&typeof r!="function")throw new TypeError("The `setHeaders` option must be a function");let i=ua.validateOptions(t);if(i)throw i;t.dotfiles??="allow";let n={root:t.root,acceptRanges:t.acceptRanges,contentType:t.contentType,cacheControl:t.cacheControl,dotfiles:t.dotfiles,etag:t.etag,extensions:t.extensions,immutable:t.immutable,index:t.index,lastModified:t.lastModified,maxAge:t.maxAge},s=t.prefix??="/";t.prefixAvoidTrailingSlash||(s=s[s.length-1]==="/"?s:s+"/");let o={constraints:t.constraints,schema:{hide:t.schemaHide??!0},logLevel:t.logLevel,errorHandler(m,h,f){if(m?.code==="ERR_STREAM_PREMATURE_CLOSE"){f.request.raw.destroy();return}e.errorHandler(m,h,f)}};if(t.decorateReply!==!1&&(e.decorateReply("sendFile",function(m,h,f){let p=typeof h=="object"?h:f,g=typeof h=="string"?h:p?.root;return c(this.request,this,m,g||n.root,0,p),this}),e.decorateReply("download",function(m,h,f={}){let{root:p,...g}=typeof h=="object"?h:f;return h=typeof h=="string"?h:m,this.header("content-disposition",XX(h)),c(this.request,this,m,p,0,g),this})),t.serve!==!1){if(t.wildcard&&typeof t.wildcard!="boolean")throw new TypeError('"wildcard" option must be a boolean');if(t.wildcard===void 0||t.wildcard===!0){let m;e.route({...o,method:["HEAD","GET"],path:s+"*",handler(h,f){m??=oQ(h.routeOptions.url);let p=aQ(h.raw.url,m);if(!p)return f.callNotFound();c(h,f,p,n.root)}}),t.redirect===!0&&s!==t.prefix&&e.get(t.prefix,o,(h,f)=>{f.redirect(CC(h.raw.url),301)})}else{let m=new Set(t.index===void 0?["index.html"]:[].concat(t.index)),h=new Map,f=new Set,p=Array.isArray(n.root)?n.root:[n.root];for(let g of p){g=g.split(Xr.win32.sep).join(Xr.posix.sep),!g.endsWith("/")&&(g+="/");let _=await JX("**/**",{cwd:g,absolute:!1,follow:!0,nodir:!0,dot:t.serveDotFiles,ignore:t.globIgnore});for(let S of _){S=S.split(Xr.win32.sep).join(Xr.posix.sep);let w=s+S;if(f.has(w))continue;f.add(w),u(o,w,`/${S}`,g);let v=Xr.posix.basename(w);m.has(v)&&!h.has(v)&&h.set(Xr.posix.dirname(w),g)}}for(let[g,_]of h.entries()){let S=g+(g.endsWith("/")?"":"/"),w="/"+S.replace(s,"");u(o,S,w,_),t.redirect===!0&&u(o,S.replace(PC,""),w.replace(PC,""),_)}}}let a=t.allowedPath;async function l(m,h){let f=ua.path(t.root,h);return f?(await ua.send({reply:m,dir:f,options:t.list,route:h,prefix:s,dotfiles:t.dotfiles}).catch(p=>m.send(p)),!0):!1}async function c(m,h,f,p,g=0,_,S){let w=f,v=Object.assign({},n,_);if(p)Array.isArray(p)?v.root=p[g]:v.root=p;else if(Xr.isAbsolute(f)===!1)return h.callNotFound();if(a&&!a(f,v.root,m))return h.callNotFound();let R,$=f;if(t.preCompressed&&(S??=new Set,R=iQ(m.headers,S),R))if(f.endsWith("/")){if(f=ay(f,v.root,v.index),!f)return h.callNotFound();$=$+f+AC[R]}else $=f+AC[R];let{statusCode:P,headers:T,stream:k,type:x,metadata:C}=await fa(m.raw,encodeURI($),v);switch(x){case"directory":{let I=C.path;if(t.list&&await ua.send({reply:h,dir:I,options:t.list,route:f,prefix:s,dotfiles:t.dotfiles}).catch(j=>h.send(j)),t.redirect===!0)try{h.redirect(CC(m.raw.url),301)}catch(j){await h.send(j)}else{if(!f.endsWith("/")&&ay(f,v.root,v.index))return c(m,h,f+"/",p,void 0,_,S);h.callNotFound()}break}case"error":{if(P===403&&(!v.index||!v.index.length)&&$[$.length-1]==="/"&&t.list&&await l(h,f))return;if(C.error.code==="ENOENT")return t.preCompressed&&R&&t.redirect!==!0&&ay(f,v.root,v.index)?c(m,h,f+"/",p,void 0,_,S):t.list&&ua.handle(f,t.list)&&await l(h,f)?void 0:Array.isArray(p)&&g<p.length-1?c(m,h,f,p,g+1,_,void 0):t.preCompressed&&!S.has(R)?(S.add(R),c(m,h,w,p,g,_,S)):h.callNotFound();if(C.error.status===404)return h.callNotFound();await h.send(C.error);break}case"file":{let I=h.statusCode!==200?h.statusCode:P;h.code(I),r?.(h.raw,C.path,C.stat),h.headers(T),R&&(h.header("content-type",rQ(f)),h.header("content-encoding",R)),await h.send(k);break}}}function u(m,h,f,p){let g=Object.assign({},m,{method:["HEAD","GET"],url:h,handler:d});g.config??={},g.config.file=f,g.config.rootPath=p,e.route(g)}async function d(m,h){let f=m.routeOptions?.config;return c(m,h,f.file,f.rootPath)}}function eQ(e){if(e===void 0)return e;if(e instanceof URL&&e.protocol==="file:")return xC(e);if(Array.isArray(e)){let t=[];for(let r=0,i=e.length;r<i;++r)e[r]instanceof URL&&e[r].protocol==="file:"?t.push(xC(e[r])):t.push(e[r]);return t}return e}function tQ(e,t){if(t===void 0)throw new Error('"root" option is required');if(Array.isArray(t)){if(!t.length)throw new Error('"root" option array requires one or more paths');if(new Set(t).size!==t.length)throw new Error('"root" option array contains one or more duplicate paths');t.map(r=>$C(e,r));return}if(typeof t=="string")return $C(e,t);throw new Error('"root" option must be a string or array of strings')}function $C(e,t){if(typeof t!="string")throw new TypeError('"root" option must be a string');if(Xr.isAbsolute(t)===!1)throw new Error('"root" option must be an absolute path');let r;try{r=kC(t)}catch(i){if(i.code==="ENOENT"){e.log.warn(`"root" path "${t}" must exist`);return}throw i}if(r.isDirectory()===!1)throw new Error('"root" option must point to a directory')}function rQ(e){let t=fa.mime.getType(e)||fa.mime.default_type;return fa.isUtf8MimeType(t)?`${t}; charset=utf-8`:t}function ay(e,t,r=["index.html"]){return Array.isArray(r)?r.find(i=>{let n=Xr.join(t,e,i);try{return!kC(n).isDirectory()}catch{return!1}}):!1}function iQ(e,t){if(!("accept-encoding"in e))return;let r=e["accept-encoding"].toLowerCase().replace(QX,"gzip");return YX.negotiate(r,ZX.filter(i=>!t.has(i)))}function nQ(e){let t=[],r=0,i=0;for(;r<e.length;){if(e[r]!==":"){r++;continue}for(i!==r&&t.push(e.slice(i,r)),r++;r<e.length&&e[r]!=="/";)r++;t.push(void 0),i=r}return i!==e.length&&t.push(e.slice(i)),t}function sQ(e,t,r){let i=0;for(let n of r){if(n===void 0){let o=i,a=e.indexOf("/",i);if(i=a===-1||a>t?t:a,i===o)return;continue}let s=i+n.length;if(s>t||!e.startsWith(n,i))return;i=s}return i}function oQ(e){let t=e.replace(/\*$/u,""),r=t.length;if(t==="/")return()=>0;if(t.includes(":")===!1)return(n,s)=>r<=s&&n.startsWith(t)?r:void 0;let i=nQ(t);return(n,s)=>sQ(n,s,i)}function aQ(e,t){let r=e.indexOf("?"),i=r===-1?e.length:r,n=t(e,i);if(n===void 0)return;let s=e.slice(n,i);s===""?s="/":s.startsWith("/")||(s="/"+s);try{return decodeURI(s)}catch{}}function CC(e){let t=0;for(let r=e.length;t<r&&!(e[t]!=="/"&&e[t]!=="\\");++t);e="/"+e.slice(t);try{let r=new URL(e,"http://localhost.com/"),i=r.pathname;return i+(i[i.length-1]!=="/"?"/":"")+(r.search||"")}catch{let r=new Error(`Invalid redirect URL: ${e}`);throw r.statusCode=400,r}}Eu.exports=KX(ly,{fastify:"5.x",name:"@fastify/static"});Eu.exports.default=ly;Eu.exports.fastifyStatic=ly});var nk=vy(MA(),1),sk=vy(IC(),1);import{existsSync as yy}from"node:fs";import{spawn as KQ}from"node:child_process";import{copyFileSync as lQ,existsSync as cy,mkdirSync as cQ}from"node:fs";import{homedir as Ru}from"node:os";import{dirname as uQ,join as or}from"node:path";import{fileURLToPath as fQ}from"node:url";var uy=uQ(fQ(import.meta.url));function NC(e,t){return e.find(r=>cy(r))??t}var fy=Number(process.env.PORT??4317),Tu=or(uy,"..");function LC(e){return e==="~"?Ru():e.startsWith("~/")?or(Ru(),e.slice(2)):e}var gs=LC(process.env.CLAUDE_PROJECTS_DIR??or(Ru(),".claude","projects")),jC=process.env.OPEN_BROWSER==="1",dy=Number(process.env.REINDEX_INTERVAL_MS??15e3),hy=LC(process.env.CLAUDESCOPE_HOME??or(Ru(),".claudescope")),ha=process.env.DUCKDB_PATH??or(hy,"index.duckdb"),Ou=NC([or(uy,"pricing.default.json"),or(Tu,"pricing.json")],or(Tu,"pricing.json")),da=process.env.PRICING_PATH??or(hy,"pricing.json"),xu=process.env.WEB_DIST_DIR??NC([or(uy,"web"),or(Tu,"..","web","dist")],or(Tu,"..","web","dist")),Pu="0.1.0";function DC(){cQ(hy,{recursive:!0}),!cy(da)&&cy(Ou)&&lQ(Ou,da)}import{readdirSync as wQ,statSync as SQ}from"node:fs";import{join as bQ}from"node:path";import{mkdirSync as dQ,rmSync as hQ}from"node:fs";import{dirname as pQ}from"node:path";import{DuckDBInstance as mQ}from"@duckdb/node-api";var qC=[`CREATE TABLE IF NOT EXISTS files (
|
|
392
|
+
}`)(e,mu,this,t,n);return s}function q7(e,t,r){if(!e||typeof e!="object"&&typeof e!="function")throw new TypeError("argument obj must be object");var i=Object.getOwnPropertyDescriptor(e,t);if(!i)throw new TypeError("must call property on owner object");if(!i.configurable)throw new TypeError("property must be configurable");var n=this,s=gu(),o=hs(s[1]);o.name=t,"value"in i&&(i=x7(e,t,r));var a=i.get,l=i.set;typeof a=="function"&&(i.get=function(){return mu.call(n,r,o),a.apply(this,arguments)}),typeof l=="function"&&(i.set=function(){return mu.call(n,r,o),l.apply(this,arguments)}),Object.defineProperty(e,t,i)}function D$(e,t,r){var i=new Error,n;return Object.defineProperty(i,"constructor",{value:D$}),Object.defineProperty(i,"message",{configurable:!0,enumerable:!1,value:t,writable:!0}),Object.defineProperty(i,"name",{enumerable:!1,configurable:!0,value:"DeprecationError",writable:!0}),Object.defineProperty(i,"namespace",{configurable:!0,enumerable:!1,value:e,writable:!0}),Object.defineProperty(i,"stack",{configurable:!0,enumerable:!1,get:function(){return n!==void 0?n:n=A7.call(this,r)},set:function(o){n=o}}),i}});var z$=E((Gne,M$)=>{"use strict";M$.exports=Object.setPrototypeOf||({__proto__:[]}instanceof Array?F7:M7);function F7(e,t){return e.__proto__=t,e}function M7(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(e,r)||(e[r]=t[r]);return e}});var H$=E((Wne,z7)=>{z7.exports={"100":"Continue","101":"Switching Protocols","102":"Processing","103":"Early Hints","200":"OK","201":"Created","202":"Accepted","203":"Non-Authoritative Information","204":"No Content","205":"Reset Content","206":"Partial Content","207":"Multi-Status","208":"Already Reported","226":"IM Used","300":"Multiple Choices","301":"Moved Permanently","302":"Found","303":"See Other","304":"Not Modified","305":"Use Proxy","307":"Temporary Redirect","308":"Permanent Redirect","400":"Bad Request","401":"Unauthorized","402":"Payment Required","403":"Forbidden","404":"Not Found","405":"Method Not Allowed","406":"Not Acceptable","407":"Proxy Authentication Required","408":"Request Timeout","409":"Conflict","410":"Gone","411":"Length Required","412":"Precondition Failed","413":"Payload Too Large","414":"URI Too Long","415":"Unsupported Media Type","416":"Range Not Satisfiable","417":"Expectation Failed","418":"I'm a Teapot","421":"Misdirected Request","422":"Unprocessable Entity","423":"Locked","424":"Failed Dependency","425":"Too Early","426":"Upgrade Required","428":"Precondition Required","429":"Too Many Requests","431":"Request Header Fields Too Large","451":"Unavailable For Legal Reasons","500":"Internal Server Error","501":"Not Implemented","502":"Bad Gateway","503":"Service Unavailable","504":"Gateway Timeout","505":"HTTP Version Not Supported","506":"Variant Also Negotiates","507":"Insufficient Storage","508":"Loop Detected","509":"Bandwidth Limit Exceeded","510":"Not Extended","511":"Network Authentication Required"}});var B$=E((Jne,V$)=>{"use strict";var Wg=H$();V$.exports=yr;yr.message=Wg;yr.code=H7(Wg);yr.codes=U7(Wg);yr.redirect={300:!0,301:!0,302:!0,303:!0,305:!0,307:!0,308:!0};yr.empty={204:!0,205:!0,304:!0};yr.retry={502:!0,503:!0,504:!0};function H7(e){var t={};return Object.keys(e).forEach(function(i){var n=e[i],s=Number(i);t[n.toLowerCase()]=s}),t}function U7(e){return Object.keys(e).map(function(r){return Number(r)})}function V7(e){var t=e.toLowerCase();if(!Object.prototype.hasOwnProperty.call(yr.code,t))throw new Error('invalid status message: "'+e+'"');return yr.code[t]}function U$(e){if(!Object.prototype.hasOwnProperty.call(yr.message,e))throw new Error("invalid status code: "+e);return yr.message[e]}function yr(e){if(typeof e=="number")return U$(e);if(typeof e!="string")throw new TypeError("code must be a number or string");var t=parseInt(e,10);return isNaN(t)?V7(e):U$(t)}});var G$=E((Kne,Jg)=>{typeof Object.create=="function"?Jg.exports=function(t,r){r&&(t.super_=r,t.prototype=Object.create(r.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}))}:Jg.exports=function(t,r){if(r){t.super_=r;var i=function(){};i.prototype=r.prototype,t.prototype=new i,t.prototype.constructor=t}}});var W$=E((Yne,Yg)=>{try{if(Kg=ee("util"),typeof Kg.inherits!="function")throw"";Yg.exports=Kg.inherits}catch{Yg.exports=G$()}var Kg});var K$=E((Xne,J$)=>{"use strict";J$.exports=B7;function B7(e){return e.split(" ").map(function(t){return t.slice(0,1).toUpperCase()+t.slice(1)}).join("").replace(/[^ _0-9a-z]/gi,"")}});var eC=E((Qne,on)=>{"use strict";var G7=F$()("http-errors"),Y$=z$(),ps=B$(),Xg=W$(),W7=K$();on.exports=yu;on.exports.HttpError=J7();on.exports.isHttpError=Y7(on.exports.HttpError);Q7(on.exports,ps.codes,on.exports.HttpError);function X$(e){return+(String(e).charAt(0)+"00")}function yu(){for(var e,t,r=500,i={},n=0;n<arguments.length;n++){var s=arguments[n],o=typeof s;if(o==="object"&&s instanceof Error)e=s,r=e.status||e.statusCode||r;else if(o==="number"&&n===0)r=s;else if(o==="string")t=s;else if(o==="object")i=s;else throw new TypeError("argument #"+(n+1)+" unsupported type "+o)}typeof r=="number"&&(r<400||r>=600)&&G7("non-error status code; use only 4xx or 5xx status codes"),(typeof r!="number"||!ps.message[r]&&(r<400||r>=600))&&(r=500);var a=yu[r]||yu[X$(r)];e||(e=a?new a(t):new Error(t||ps.message[r]),Error.captureStackTrace(e,yu)),(!a||!(e instanceof a)||e.status!==r)&&(e.expose=r<500,e.status=e.statusCode=r);for(var l in i)l!=="status"&&l!=="statusCode"&&(e[l]=i[l]);return e}function J7(){function e(){throw new TypeError("cannot construct abstract class")}return Xg(e,Error),e}function K7(e,t,r){var i=Z$(t);function n(s){var o=s??ps.message[r],a=new Error(o);return Error.captureStackTrace(a,n),Y$(a,n.prototype),Object.defineProperty(a,"message",{enumerable:!0,configurable:!0,value:o,writable:!0}),Object.defineProperty(a,"name",{enumerable:!1,configurable:!0,value:i,writable:!0}),a}return Xg(n,e),Q$(n,i),n.prototype.status=r,n.prototype.statusCode=r,n.prototype.expose=!0,n}function Y7(e){return function(r){return!r||typeof r!="object"?!1:r instanceof e?!0:r instanceof Error&&typeof r.expose=="boolean"&&typeof r.statusCode=="number"&&r.status===r.statusCode}}function X7(e,t,r){var i=Z$(t);function n(s){var o=s??ps.message[r],a=new Error(o);return Error.captureStackTrace(a,n),Y$(a,n.prototype),Object.defineProperty(a,"message",{enumerable:!0,configurable:!0,value:o,writable:!0}),Object.defineProperty(a,"name",{enumerable:!1,configurable:!0,value:i,writable:!0}),a}return Xg(n,e),Q$(n,i),n.prototype.status=r,n.prototype.statusCode=r,n.prototype.expose=!1,n}function Q$(e,t){var r=Object.getOwnPropertyDescriptor(e,"name");r&&r.configurable&&(r.value=t,Object.defineProperty(e,"name",r))}function Q7(e,t,r){t.forEach(function(n){var s,o=W7(ps.message[n]);switch(X$(n)){case 400:s=K7(r,o,n);break;case 500:s=X7(r,o,n);break}s&&(e[n]=s,e[o]=s)})}function Z$(e){return e.slice(-5)==="Error"?e:e+"Error"}});var rC=E((Zne,tC)=>{"use strict";var Qg=eC();function Z7(e,t){return t?t instanceof Error?Qg(e,t,{expose:!1}):Qg(e,t):Qg(e)}tC.exports.createHttpError=Z7});var hC=E((ese,dC)=>{"use strict";var aC=ee("node:fs"),sa=ee("node:path"),eX=ee("node:stream"),Pt=ee("node:util").debuglog("send"),tX=zm(),rX=_$(),iC=Ug(),iX=v$(),{collapseLeadingSlashes:nX}=S$(),{containsDotFile:sX}=E$(),{contentRange:nC}=T$(),{createHtmlDocument:an}=x$(),{isUtf8MimeType:oX}=Hg(),{normalizeList:sC}=A$(),{parseBytesRange:aX}=C$(),{parseTokenList:lC}=N$(),{createHttpError:lX}=rC(),cX=sa.extname,cC=sa.join,Zg=sa.normalize,uC=sa.resolve,_u=sa.sep,vu=eX.Readable,uX=/^ *bytes=/,fX=60*60*24*365*1e3,oC=/(?:^|[\\/])\.\.(?:[\\/]|$)/,dX={400:an("Error","Bad Request"),403:an("Error","Forbidden"),404:an("Error","Not Found"),412:an("Error","Precondition Failed"),416:an("Error","Range Not Satisfiable"),500:an("Error","Internal Server Error")},hX=["allow","ignore","deny"];function pX(e){let t;return typeof e=="string"?t=iX.parse(e):t=Number(e),t!==t?0:Math.min(Math.max(0,t),fX)}function mX(e){e=e??{};let t=e.acceptRanges!==void 0?!!e.acceptRanges:!0,r=e.cacheControl!==void 0?!!e.cacheControl:!0,i=e.contentType!==void 0?!!e.contentType:!0,n=e.etag!==void 0?!!e.etag:!0,s=e.dotfiles!==void 0?hX.indexOf(e.dotfiles):1;if(s===-1)throw new TypeError('dotfiles option must be "allow", "deny", or "ignore"');let o=e.extensions!==void 0?sC(e.extensions,"extensions option"):[],a=e.immutable!==void 0?!!e.immutable:!1,l=e.index!==void 0?sC(e.index,"index option"):["index.html"],c=e.lastModified!==void 0?!!e.lastModified:!0,u=pX(e.maxAge??e.maxage),d=e.maxContentRangeChunkSize!==void 0?Number(e.maxContentRangeChunkSize):null,m=e.root?uC(e.root):null,h=Number.isSafeInteger(e.highWaterMark)&&e.highWaterMark>0?e.highWaterMark:null;return{acceptRanges:t,cacheControl:r,contentType:i,etag:n,dotfiles:s,extensions:o,immutable:a,index:l,lastModified:c,maxage:u,maxContentRangeChunkSize:d,root:m,highWaterMark:h,start:e.start,end:e.end}}function gX(e,t){let r=tX(e);if(r==null)return{statusCode:400};if(~r.indexOf("\0"))return{statusCode:400};let i;if(t!==null){if(r&&(r=Zg("."+_u+r)),oC.test(r))return Pt('malicious path "%s"',r),{statusCode:403};i=r.split(_u),r=Zg(cC(t,r))}else{if(oC.test(r))return Pt('malicious path "%s"',r),{statusCode:403};i=Zg(r).split(_u),r=uC(r)}return{path:r,parts:i}}function fC(e){return e[e.length-1]==="/"}function yX(e){return e.headers["if-match"]||e.headers["if-unmodified-since"]||e.headers["if-none-match"]||e.headers["if-modified-since"]}function _X(e,t){if("cache-control"in e.headers&&e.headers["cache-control"].indexOf("no-cache")!==-1)return!1;if("if-none-match"in e.headers){let r=e.headers["if-none-match"];if(r==="*")return!0;let i=t.ETag;if(typeof i!="string")return!1;let n=i.length;return!!lC(r,function(o){let a=o.length;if(n===a&&o===i||n>a&&"W/"+o===i)return!0})}if("if-modified-since"in e.headers){let r=e.headers["if-modified-since"],i=t["Last-Modified"];if(!i||Date.parse(i)<=Date.parse(r))return!0}return!1}function vX(e,t){let r=e.headers["if-match"];if(r){let i=t.ETag;if(r!=="*"&&(lC(r,function(s){if(s===i||"W/"+s===i)return!0})||!1)!==!0)return!0}if("if-unmodified-since"in e.headers){let i=e.headers["if-unmodified-since"],n=Date.parse(i);if(n===n){let s=Date.parse(t["Last-Modified"]);if(s!==s||s>n)return!0}}return!1}function wX(e,t){if(!("if-range"in e.headers))return!0;let r=e.headers["if-range"];if(r.indexOf('"')!==-1){let s=t.ETag;return s&&r.indexOf(s)!==-1||!1}let i=Date.parse(r);if(i!==i)return!1;let n=Date.parse(t["Last-Modified"]);return n!==n||n<=i}function ey(e){return new Promise(t=>{aC.stat(e,function(i,n){t({error:i,stat:n})})})}function Ir(e,t){let r={};if(t&&t.headers)for(let n in t.headers)r[n]=t.headers[n];let i=dX[e];return r["Content-Type"]="text/html; charset=utf-8",r["Content-Length"]=i[1],r["Content-Security-Policy"]="default-src 'none'",r["X-Content-Type-Options"]="nosniff",{statusCode:e,headers:r,stream:vu.from(i[0]),type:"error",metadata:{error:lX(e,t)}}}function ty(e){switch(e.code){case"ENAMETOOLONG":case"ENOTDIR":case"ENOENT":return Ir(404,e);default:return Ir(500,e)}}function SX(e,t,r){return Pt("not modified"),delete e["Content-Encoding"],delete e["Content-Language"],delete e["Content-Length"],delete e["Content-Range"],delete e["Content-Type"],{statusCode:304,headers:e,stream:vu.from(""),type:"file",metadata:{path:t,stat:r}}}function ry(e,t,r,i){let n=r.size,s=i.start??0,o=200,a={};if(Pt('send "%s"',t),i.acceptRanges&&(Pt("accept ranges"),a["Accept-Ranges"]="bytes"),i.cacheControl){let c="public, max-age="+Math.floor(i.maxage/1e3);i.immutable&&(c+=", immutable"),Pt("cache-control %s",c),a["Cache-Control"]=c}if(i.lastModified){let c=r.mtime.toUTCString();Pt("modified %s",c),a["Last-Modified"]=c}if(i.etag){let c='W/"'+r.size.toString(16)+"-"+r.mtime.getTime().toString(16)+'"';Pt("etag %s",c),a.ETag=c}if(i.contentType){let c=iC.getType(t)||iC.default_type;Pt("content-type %s",c),c&&oX(c)&&(c+="; charset=utf-8"),c&&(a["Content-Type"]=c)}if(yX(e)){if(vX(e,a))return Ir(412);if(_X(e,a))return SX(a,t,r)}if(n=Math.max(0,n-s),i.end!==void 0){let c=i.end-s+1;n>c&&(n=c)}if(i.acceptRanges){let c=e.headers.range;if(c!==void 0&&uX.test(c))if(wX(e,a)){let u=aX(n,c);if(u.length===0)return Pt("range unsatisfiable"),a["Content-Range"]=nC("bytes",n),Ir(416,{headers:{"Content-Range":a["Content-Range"]}});u.length===1&&(Pt("range %j",u),o=206,i.maxContentRangeChunkSize&&(u[0].end=Math.min(u[0].end,u[0].start+i.maxContentRangeChunkSize-1)),a["Content-Range"]=nC("bytes",n,u[0]),s+=u[0].start,n=u[0].end-u[0].start+1)}else Pt("range stale")}if(a["Content-Length"]=n,e.method==="HEAD")return{statusCode:o,headers:a,stream:vu.from(""),type:"file",metadata:{path:t,stat:r}};let l=aC.createReadStream(t,{highWaterMark:i.highWaterMark,start:s,end:Math.max(s,s+n-1)});return{statusCode:o,headers:a,stream:l,type:"file",metadata:{path:t,stat:r}}}function bX(e,t){if(fC(t.path))return Ir(403);let r=encodeURI(nX(t.path+"/")),i=an("Redirecting","Redirecting to "+rX(r)),n={};return n["Content-Type"]="text/html; charset=utf-8",n["Content-Length"]=i[1],n["Content-Security-Policy"]="default-src 'none'",n["X-Content-Type-Options"]="nosniff",n.Location=r,{statusCode:301,headers:n,stream:vu.from(i[0]),type:"directory",metadata:{requestPath:t.path,path:e}}}async function EX(e,t,r){let i;for(let n=0;n<r.index.length;n++){let s=r.index[n],o=cC(t,s),{error:a,stat:l}=await ey(o);if(a){i=a;continue}if(!l.isDirectory())return ry(e,o,l,r)}return i?ty(i):Ir(404)}async function RX(e,t,r){let{error:i,stat:n}=await ey(t);if(i&&i.code==="ENOENT"&&!cX(t)&&t[t.length-1]!==_u){let s=i;for(let o=0;o<r.extensions.length;o++){let a=r.extensions[o],l=t+"."+a,{error:c,stat:u}=await ey(l);if(c){s=c;continue}if(u.isDirectory()){s=null;continue}return ry(e,l,u,r)}return s?ty(s):Ir(404)}return i?ty(i):n.isDirectory()?bX(t,r):ry(e,t,n,r)}async function TX(e,t,r){let i=mX(r);i.path=t;let n=gX(t,i.root),{path:s,parts:o}=n;if(n.statusCode!==void 0)return Ir(n.statusCode);if((Pt.enabled||i.dotfiles!==0)&&sX(o))switch(i.dotfiles){case 0:Pt('allow dotfile "%s"',s);break;case 2:return Pt('deny dotfile "%s"',s),Ir(403);case 1:default:return Pt('ignore dotfile "%s"',s),Ir(404)}return i.index.length&&fC(t)?EX(e,s,i):RX(e,s,i)}dC.exports.send=TX});var pC=E((tse,ms)=>{"use strict";var OX=Hg().isUtf8MimeType,xX=Ug(),iy=hC().send;ms.exports=iy;ms.exports.default=iy;ms.exports.send=iy;ms.exports.isUtf8MimeType=OX;ms.exports.mime=xX});var mC=E((rse,ca)=>{"use strict";function sy(e){if(!new.target)return new sy(e);let{supportedValues:t=[],cache:r}=e&&typeof e=="object"&&e||{};this.supportedValues=t,this.cache=r}sy.prototype.negotiate=function(e){return typeof e!="string"?null:this.cache?(this.cache.has(e)||this.cache.set(e,la(e,this.supportedValues)),this.cache.get(e)):la(e,this.supportedValues)};function la(e,t){if(!e||!Array.isArray(t)||t.length===0)return null;if(e==="*")return t[0];let r=null,i=1/0,n=0;function s(o,a){if(a===0||n>a)return!1;let l=o==="*"&&t[0]||o,c=t.indexOf(l);return c===-1?!1:c===0&&a===1?(r=l,!0):((n<a||i>c)&&(r=l,i=c,n=a),!1)}return PX(e,s),r}var oa=0,aa=1,wu=2,ny=3;function PX(e,t){let r="",i,n=oa;for(let s=0,o=e.length;s<o;++s){let a=e[s];if(!(a===" "||a===" ")){if(a===";"){n===aa&&(n=wu,i="");continue}else if(a===","){if(n===aa){if(t(r,1)){n=ny;break}n=oa,r=""}else if(n===wu){if(t(r,parseFloat(i)||0)){n=ny;break}n=oa,r="",i=""}continue}else if(n===wu){if(a==="q"||a==="=")continue;if(a==="."||a==="1"||a==="0"||a==="2"||a==="3"||a==="4"||a==="5"||a==="6"||a==="7"||a==="8"||a==="9"){i+=a;continue}}else if(n===oa){n=aa,r+=a;continue}if(n===aa){let l=e[s-1];(l===" "||l===" ")&&(r=""),r+=a;continue}if(t(r,parseFloat(i)||0)){n=ny;break}n=oa,r=a,i=""}}n===aa?t(r,1):n===wu&&t(r,parseFloat(i)||0)}ca.exports=la;ca.exports.default=la;ca.exports.negotiate=la;ca.exports.Negotiator=sy});var bC=E((ise,oy)=>{"use strict";oy.exports=DX;oy.exports.parse=zX;var AX=new TextDecoder("utf-8"),$X=/[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g,vC=/[^\x20-\x7e\xa0-\xff]/g,CX=/\\([\u0000-\u007f])/g,kX=/([\\"])/g,gC=/;[\x09\x20]*([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*=[\x09\x20]*("(?:[\x20!\x23-\x5b\x5d-\x7e\x80-\xff]|\\[\x20-\x7e])*"|[!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*/g,IX=/^[\x20-\x7e\x80-\xff]+$/,NX=/^[!#$%&'*+.0-9A-Z^_`a-z|~-]+$/,LX=/^([A-Za-z0-9!#$%&+\-^_`{}~]+)'(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8}|)'((?:%[0-9A-Fa-f]{2}|[A-Za-z0-9!#$&+.^_`|~-])+)$/,jX=/^([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*(?:$|;)/;function DX(e,t){var r=t||{},i=r.type||"attachment",n=qX(e,r.fallback);return FX(new SC(i,n))}function qX(e,t){if(e!==void 0){var r={};if(typeof e!="string")throw new TypeError("filename must be a string");if(t===void 0&&(t=!0),typeof t!="string"&&typeof t!="boolean")throw new TypeError("fallback must be a string or boolean");if(typeof t=="string"&&vC.test(t))throw new TypeError("fallback must be ISO-8859-1 string");var i=yC(e),n=IX.test(i),s=typeof t!="string"?t&&wC(i):yC(t),o=typeof s=="string"&&s!==i;return(o||!n||BX(i))&&(r["filename*"]=i),(n||o)&&(r.filename=o?s:i),r}}function FX(e){var t=e.parameters,r=e.type;if(!r||typeof r!="string"||!NX.test(r))throw new TypeError("invalid type");var i=String(r).toLowerCase();if(t&&typeof t=="object")for(var n,s=Object.keys(t).sort(),o=0;o<s.length;o++){n=s[o];var a=n.slice(-1)==="*"?VX(t[n]):UX(t[n]);i+="; "+n+"="+a}return i}function MX(e){let t=LX.exec(e);if(!t)throw new TypeError("invalid extended field value");let r=t[1].toLowerCase(),i=t[2];switch(r){case"iso-8859-1":{let n=_C(i);return wC(n)}case"utf-8":case"utf8":try{return decodeURIComponent(i)}catch{let n=_C(i),s=new Uint8Array(n.length);for(let o=0;o<n.length;o++)s[o]=n.charCodeAt(o);return AX.decode(s)}}throw new TypeError("unsupported charset in extended field")}function wC(e){return String(e).replace(vC,"?")}function zX(e){if(!e||typeof e!="string")throw new TypeError("argument string is required");var t=jX.exec(e);if(!t)throw new TypeError("invalid type format");var r=t[0].length,i=t[1].toLowerCase(),n,s=[],o={},a;for(r=gC.lastIndex=t[0].slice(-1)===";"?r-1:r;t=gC.exec(e);){if(t.index!==r)throw new TypeError("invalid parameter format");if(r+=t[0].length,n=t[1].toLowerCase(),a=t[2],s.indexOf(n)!==-1)throw new TypeError("invalid duplicate parameter");if(s.push(n),n.indexOf("*")+1===n.length){n=n.slice(0,-1),a=MX(a),o[n]=a;continue}typeof o[n]!="string"&&(a[0]==='"'&&(a=a.slice(1,-1).replace(CX,"$1")),o[n]=a)}if(r!==-1&&r!==e.length)throw new TypeError("invalid parameter format");return new SC(i,o)}function HX(e){return"%"+String(e).charCodeAt(0).toString(16).toUpperCase()}function UX(e){var t=String(e);return'"'+t.replace(kX,"\\$1")+'"'}function VX(e){var t=String(e),r=encodeURIComponent(t).replace($X,HX);return"UTF-8''"+r}function SC(e,t){this.type=e,this.parameters=t}function yC(e){let t=e.replaceAll("\\","/"),r=t.length;for(;r>0&&t[r-1]==="/";)r--;if(r===0)return"";let i=r-1;for(;i>=0&&t[i]!=="/";)i--;return t.slice(i+1,r)}function Su(e){let t=e.charCodeAt(0);return t>=48&&t<=57||t>=65&&t<=70||t>=97&&t<=102}function BX(e){let t=e.length-3,r=-1;for(;(r=e.indexOf("%",r+1))!==-1&&r<=t;)if(Su(e[r+1])&&Su(e[r+2]))return!0;return!1}function _C(e){let t=e.indexOf("%");if(t===-1)return e;let r=e.slice(0,t);for(let i=t;i<e.length;i++)e[i]==="%"&&i+2<e.length&&Su(e[i+1])&&Su(e[i+2])?(r+=String.fromCharCode(Number.parseInt(e[i+1]+e[i+2],16)),i+=2):r+=e[i];return r}});var OC=E((nse,TC)=>{"use strict";var GX=ee("node:os"),vt=ee("node:path"),bu=ee("node:fs/promises"),EC=ku(),RC=Math.max(1,GX.cpus().length-1);function WX(e,t){let r=vt.relative(e,t);return r===""||r!==".."&&!r.startsWith(`..${vt.sep}`)&&!vt.isAbsolute(r)}var ln={_getExtendedInfo:async function(e,t){let r=e.split(vt.sep).length,i=await bu.readdir(e),n=async o=>{let a=vt.join(e,o),l;try{l=await bu.stat(a)}catch{return}l.isDirectory()?(t.totalFolderCount++,a.split(vt.sep).length===r+1&&t.folderCount++,await ln._getExtendedInfo(a,t)):(t.totalSize+=l.size,t.totalFileCount++,a.split(vt.sep).length===r+1&&t.fileCount++,t.lastModified=Math.max(t.lastModified,l.mtimeMs))},s=EC.promise(n,RC);await Promise.all(i.map(o=>s.push(o)))},getExtendedInfo:async function(e){let t={totalSize:0,fileCount:0,totalFileCount:0,folderCount:0,totalFolderCount:0,lastModified:0};return await ln._getExtendedInfo(e,t),t},list:async function(e,t,r){let i={dirs:[],files:[]},n=await bu.readdir(e);if((r==="deny"||r==="ignore")&&(n=n.filter(a=>a.charAt(0)!==".")),n.length<1)return i;let s=async a=>{let l;try{l=await bu.stat(vt.join(e,a))}catch{return}let c={name:a,stats:l};l.isDirectory()?(t.extendedFolderInfo&&(c.extendedInfo=await ln.getExtendedInfo(vt.join(e,a))),i.dirs.push(c)):i.files.push(c)},o=EC.promise(s,RC);return await Promise.all(n.map(a=>o.push(a))),i.dirs.sort((a,l)=>a.name.localeCompare(l.name)),i.files.sort((a,l)=>a.name.localeCompare(l.name)),i},send:async function({reply:e,dir:t,options:r,route:i,prefix:n,dotfiles:s}){if(e.request.query.format==="html"&&typeof r.render!="function")throw new TypeError("The `list.render` option must be a function and is required with the URL parameter `format=html`");let o;try{o=await ln.list(t,r,s)}catch{return e.callNotFound()}if((e.request.query.format||r.format)!=="html"){if(r.jsonFormat!=="extended"){let c={dirs:[],files:[]};o.dirs.forEach(u=>c.dirs.push(u.name)),o.files.forEach(u=>c.files.push(u.name)),await e.send(c)}else await e.send(o);return}let l=r.render(o.dirs.map(c=>ln.htmlInfo(c,i,n,r)),o.files.map(c=>ln.htmlInfo(c,i,n,r)));await e.type("text/html").send(l)},htmlInfo:function(e,t,r,i){return i.names?.includes(vt.basename(t))&&(t=vt.posix.normalize(vt.posix.join(t,".."))),{href:encodeURI(vt.posix.join(r,t,e.name)),name:e.name,stats:e.stats,extendedInfo:e.extendedInfo}},handle:function(e,t){return t.names?.includes(vt.basename(e))||((t.names?.includes("/")&&e[e.length-1]==="/")??!1)},path:function(e,t){let r=t[t.length-1]==="/"?"."+t+"none":"."+t,i=vt.resolve(e),n=vt.dirname(vt.resolve(i,r));return WX(i,n)?n:null},validateOptions:function(e){if(e.list){if(Array.isArray(e.root))return new TypeError("multi-root with list option is not supported");if(e.list.format&&e.list.format!=="json"&&e.list.format!=="html")return new TypeError("The `list.format` option must be json or html");if(e.list.names&&!Array.isArray(e.list.names))return new TypeError("The `list.names` option must be an array");if(e.list.jsonFormat!=null&&e.list.jsonFormat!=="names"&&e.list.jsonFormat!=="extended")return new TypeError("The `list.jsonFormat` option must be name or extended");if(e.list.format==="html"&&typeof e.list.render!="function")return new TypeError("The `list.render` option must be a function and is required with html format")}}};TC.exports=ln});var IC=E((sse,Eu)=>{"use strict";var Xr=ee("node:path"),{fileURLToPath:xC}=ee("node:url"),{statSync:kC}=ee("node:fs"),{glob:JX}=i$(),KX=l$(),fa=pC(),YX=mC(),XX=bC(),ua=OC(),PC=/\/$/u,QX=/\*/gu,ZX=["br","gzip","deflate"];fa.mime.default_type="application/octet-stream";var AC={br:".br",gzip:".gz"};async function ly(e,t){(t.serve!==!1||t.root!==void 0)&&(t.root=eQ(t.root),tQ(e,t.root));let r=t.setHeaders;if(r!==void 0&&typeof r!="function")throw new TypeError("The `setHeaders` option must be a function");let i=ua.validateOptions(t);if(i)throw i;t.dotfiles??="allow";let n={root:t.root,acceptRanges:t.acceptRanges,contentType:t.contentType,cacheControl:t.cacheControl,dotfiles:t.dotfiles,etag:t.etag,extensions:t.extensions,immutable:t.immutable,index:t.index,lastModified:t.lastModified,maxAge:t.maxAge},s=t.prefix??="/";t.prefixAvoidTrailingSlash||(s=s[s.length-1]==="/"?s:s+"/");let o={constraints:t.constraints,schema:{hide:t.schemaHide??!0},logLevel:t.logLevel,errorHandler(m,h,f){if(m?.code==="ERR_STREAM_PREMATURE_CLOSE"){f.request.raw.destroy();return}e.errorHandler(m,h,f)}};if(t.decorateReply!==!1&&(e.decorateReply("sendFile",function(m,h,f){let p=typeof h=="object"?h:f,g=typeof h=="string"?h:p?.root;return c(this.request,this,m,g||n.root,0,p),this}),e.decorateReply("download",function(m,h,f={}){let{root:p,...g}=typeof h=="object"?h:f;return h=typeof h=="string"?h:m,this.header("content-disposition",XX(h)),c(this.request,this,m,p,0,g),this})),t.serve!==!1){if(t.wildcard&&typeof t.wildcard!="boolean")throw new TypeError('"wildcard" option must be a boolean');if(t.wildcard===void 0||t.wildcard===!0){let m;e.route({...o,method:["HEAD","GET"],path:s+"*",handler(h,f){m??=oQ(h.routeOptions.url);let p=aQ(h.raw.url,m);if(!p)return f.callNotFound();c(h,f,p,n.root)}}),t.redirect===!0&&s!==t.prefix&&e.get(t.prefix,o,(h,f)=>{f.redirect(CC(h.raw.url),301)})}else{let m=new Set(t.index===void 0?["index.html"]:[].concat(t.index)),h=new Map,f=new Set,p=Array.isArray(n.root)?n.root:[n.root];for(let g of p){g=g.split(Xr.win32.sep).join(Xr.posix.sep),!g.endsWith("/")&&(g+="/");let _=await JX("**/**",{cwd:g,absolute:!1,follow:!0,nodir:!0,dot:t.serveDotFiles,ignore:t.globIgnore});for(let S of _){S=S.split(Xr.win32.sep).join(Xr.posix.sep);let w=s+S;if(f.has(w))continue;f.add(w),u(o,w,`/${S}`,g);let v=Xr.posix.basename(w);m.has(v)&&!h.has(v)&&h.set(Xr.posix.dirname(w),g)}}for(let[g,_]of h.entries()){let S=g+(g.endsWith("/")?"":"/"),w="/"+S.replace(s,"");u(o,S,w,_),t.redirect===!0&&u(o,S.replace(PC,""),w.replace(PC,""),_)}}}let a=t.allowedPath;async function l(m,h){let f=ua.path(t.root,h);return f?(await ua.send({reply:m,dir:f,options:t.list,route:h,prefix:s,dotfiles:t.dotfiles}).catch(p=>m.send(p)),!0):!1}async function c(m,h,f,p,g=0,_,S){let w=f,v=Object.assign({},n,_);if(p)Array.isArray(p)?v.root=p[g]:v.root=p;else if(Xr.isAbsolute(f)===!1)return h.callNotFound();if(a&&!a(f,v.root,m))return h.callNotFound();let R,$=f;if(t.preCompressed&&(S??=new Set,R=iQ(m.headers,S),R))if(f.endsWith("/")){if(f=ay(f,v.root,v.index),!f)return h.callNotFound();$=$+f+AC[R]}else $=f+AC[R];let{statusCode:P,headers:T,stream:k,type:x,metadata:C}=await fa(m.raw,encodeURI($),v);switch(x){case"directory":{let I=C.path;if(t.list&&await ua.send({reply:h,dir:I,options:t.list,route:f,prefix:s,dotfiles:t.dotfiles}).catch(j=>h.send(j)),t.redirect===!0)try{h.redirect(CC(m.raw.url),301)}catch(j){await h.send(j)}else{if(!f.endsWith("/")&&ay(f,v.root,v.index))return c(m,h,f+"/",p,void 0,_,S);h.callNotFound()}break}case"error":{if(P===403&&(!v.index||!v.index.length)&&$[$.length-1]==="/"&&t.list&&await l(h,f))return;if(C.error.code==="ENOENT")return t.preCompressed&&R&&t.redirect!==!0&&ay(f,v.root,v.index)?c(m,h,f+"/",p,void 0,_,S):t.list&&ua.handle(f,t.list)&&await l(h,f)?void 0:Array.isArray(p)&&g<p.length-1?c(m,h,f,p,g+1,_,void 0):t.preCompressed&&!S.has(R)?(S.add(R),c(m,h,w,p,g,_,S)):h.callNotFound();if(C.error.status===404)return h.callNotFound();await h.send(C.error);break}case"file":{let I=h.statusCode!==200?h.statusCode:P;h.code(I),r?.(h.raw,C.path,C.stat),h.headers(T),R&&(h.header("content-type",rQ(f)),h.header("content-encoding",R)),await h.send(k);break}}}function u(m,h,f,p){let g=Object.assign({},m,{method:["HEAD","GET"],url:h,handler:d});g.config??={},g.config.file=f,g.config.rootPath=p,e.route(g)}async function d(m,h){let f=m.routeOptions?.config;return c(m,h,f.file,f.rootPath)}}function eQ(e){if(e===void 0)return e;if(e instanceof URL&&e.protocol==="file:")return xC(e);if(Array.isArray(e)){let t=[];for(let r=0,i=e.length;r<i;++r)e[r]instanceof URL&&e[r].protocol==="file:"?t.push(xC(e[r])):t.push(e[r]);return t}return e}function tQ(e,t){if(t===void 0)throw new Error('"root" option is required');if(Array.isArray(t)){if(!t.length)throw new Error('"root" option array requires one or more paths');if(new Set(t).size!==t.length)throw new Error('"root" option array contains one or more duplicate paths');t.map(r=>$C(e,r));return}if(typeof t=="string")return $C(e,t);throw new Error('"root" option must be a string or array of strings')}function $C(e,t){if(typeof t!="string")throw new TypeError('"root" option must be a string');if(Xr.isAbsolute(t)===!1)throw new Error('"root" option must be an absolute path');let r;try{r=kC(t)}catch(i){if(i.code==="ENOENT"){e.log.warn(`"root" path "${t}" must exist`);return}throw i}if(r.isDirectory()===!1)throw new Error('"root" option must point to a directory')}function rQ(e){let t=fa.mime.getType(e)||fa.mime.default_type;return fa.isUtf8MimeType(t)?`${t}; charset=utf-8`:t}function ay(e,t,r=["index.html"]){return Array.isArray(r)?r.find(i=>{let n=Xr.join(t,e,i);try{return!kC(n).isDirectory()}catch{return!1}}):!1}function iQ(e,t){if(!("accept-encoding"in e))return;let r=e["accept-encoding"].toLowerCase().replace(QX,"gzip");return YX.negotiate(r,ZX.filter(i=>!t.has(i)))}function nQ(e){let t=[],r=0,i=0;for(;r<e.length;){if(e[r]!==":"){r++;continue}for(i!==r&&t.push(e.slice(i,r)),r++;r<e.length&&e[r]!=="/";)r++;t.push(void 0),i=r}return i!==e.length&&t.push(e.slice(i)),t}function sQ(e,t,r){let i=0;for(let n of r){if(n===void 0){let o=i,a=e.indexOf("/",i);if(i=a===-1||a>t?t:a,i===o)return;continue}let s=i+n.length;if(s>t||!e.startsWith(n,i))return;i=s}return i}function oQ(e){let t=e.replace(/\*$/u,""),r=t.length;if(t==="/")return()=>0;if(t.includes(":")===!1)return(n,s)=>r<=s&&n.startsWith(t)?r:void 0;let i=nQ(t);return(n,s)=>sQ(n,s,i)}function aQ(e,t){let r=e.indexOf("?"),i=r===-1?e.length:r,n=t(e,i);if(n===void 0)return;let s=e.slice(n,i);s===""?s="/":s.startsWith("/")||(s="/"+s);try{return decodeURI(s)}catch{}}function CC(e){let t=0;for(let r=e.length;t<r&&!(e[t]!=="/"&&e[t]!=="\\");++t);e="/"+e.slice(t);try{let r=new URL(e,"http://localhost.com/"),i=r.pathname;return i+(i[i.length-1]!=="/"?"/":"")+(r.search||"")}catch{let r=new Error(`Invalid redirect URL: ${e}`);throw r.statusCode=400,r}}Eu.exports=KX(ly,{fastify:"5.x",name:"@fastify/static"});Eu.exports.default=ly;Eu.exports.fastifyStatic=ly});var nk=vy(MA(),1),sk=vy(IC(),1);import{existsSync as yy}from"node:fs";import{spawn as KQ}from"node:child_process";import{copyFileSync as lQ,existsSync as cy,mkdirSync as cQ}from"node:fs";import{homedir as Ru}from"node:os";import{dirname as uQ,join as or}from"node:path";import{fileURLToPath as fQ}from"node:url";var uy=uQ(fQ(import.meta.url));function NC(e,t){return e.find(r=>cy(r))??t}var fy=Number(process.env.PORT??4317),Tu=or(uy,"..");function LC(e){return e==="~"?Ru():e.startsWith("~/")?or(Ru(),e.slice(2)):e}var gs=LC(process.env.CLAUDE_PROJECTS_DIR??or(Ru(),".claude","projects")),jC=process.env.OPEN_BROWSER==="1",dy=Number(process.env.REINDEX_INTERVAL_MS??15e3),hy=LC(process.env.CLAUDESCOPE_HOME??or(Ru(),".claudescope")),ha=process.env.DUCKDB_PATH??or(hy,"index.duckdb"),Ou=NC([or(uy,"pricing.default.json"),or(Tu,"pricing.json")],or(Tu,"pricing.json")),da=process.env.PRICING_PATH??or(hy,"pricing.json"),xu=process.env.WEB_DIST_DIR??NC([or(uy,"web"),or(Tu,"..","web","dist")],or(Tu,"..","web","dist")),Pu="0.2.0";function DC(){cQ(hy,{recursive:!0}),!cy(da)&&cy(Ou)&&lQ(Ou,da)}import{readdirSync as wQ,statSync as SQ}from"node:fs";import{join as bQ}from"node:path";import{mkdirSync as dQ,rmSync as hQ}from"node:fs";import{dirname as pQ}from"node:path";import{DuckDBInstance as mQ}from"@duckdb/node-api";var qC=[`CREATE TABLE IF NOT EXISTS files (
|
|
393
393
|
path VARCHAR PRIMARY KEY,
|
|
394
394
|
mtime_ms BIGINT NOT NULL,
|
|
395
395
|
size_bytes BIGINT NOT NULL,
|