threadshelf 1.2.0 → 1.2.2
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/CHANGELOG.md +29 -1
- package/README.md +10 -1
- package/bin/threadshelf.js +59 -10
- package/dist/src/cli.js +2 -1
- package/dist/src/ingest-cli.js +2 -1
- package/dist/src/paths.js +19 -5
- package/dist/src/search-cli.js +2 -1
- package/package.json +1 -1
- package/public/assets/{index-CIm_Idqi.js → index-TIPW3iTR.js} +1 -1
- package/public/index.html +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to ThreadShelf are documented here.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 1.2.2 — 2026-09-20
|
|
6
|
+
|
|
7
|
+
### Packaging review follow-ups
|
|
8
|
+
|
|
9
|
+
- Resolve the package root by looking for the manifest rather than for a
|
|
10
|
+
directory named `dist`, so a repository cloned into a directory called `dist`
|
|
11
|
+
no longer anchors every path one level too high. `dist/` must stay free of a
|
|
12
|
+
stray `package.json` for this, which `test/packaging.test.js` now asserts.
|
|
13
|
+
- Detect a checkout by the presence of `src/` rather than of `src/server.ts`,
|
|
14
|
+
so renaming or splitting an entry point cannot silently move a developer's
|
|
15
|
+
archive out of the repository.
|
|
16
|
+
- Add `npx threadshelf mcp` next to the existing `threadshelf-mcp` executable.
|
|
17
|
+
It starts the server explicitly instead of relying on the MCP module's own
|
|
18
|
+
entry-point detection, which compares URLs in a way that is fragile on
|
|
19
|
+
Windows.
|
|
20
|
+
- Widen the `process.cwd()` guard in `test/packaging.test.js` to cover `bin/`
|
|
21
|
+
(the npx entry point) and `src/paths.ts`. It previously scanned only `.ts`
|
|
22
|
+
files and exempted `paths.ts` outright, so it would have passed while the two
|
|
23
|
+
files most able to break every path did the wrong thing.
|
|
24
|
+
- Exercise the compiled `dist/src/paths.js` from `npm test`, and the `mcp`
|
|
25
|
+
subcommand from `npm run pack:verify`. Both were previously covered only by
|
|
26
|
+
the five-minute packaging run, or not at all.
|
|
27
|
+
|
|
28
|
+
## 1.2.1 — 2026-09-20
|
|
6
29
|
|
|
7
30
|
### Install with `npx threadshelf`
|
|
8
31
|
|
|
@@ -37,6 +60,11 @@ All notable changes to ThreadShelf are documented here.
|
|
|
37
60
|
- Add `.github/workflows/publish.yml`: tag-driven release on `v*` that runs the
|
|
38
61
|
test suite and publishes through npm Trusted Publishing (OIDC), with no npm
|
|
39
62
|
token stored in the repository.
|
|
63
|
+
- Reach the bundled CLIs from an installed package:
|
|
64
|
+
`npx threadshelf search|ingest|parse`. They were compiled into the tarball but
|
|
65
|
+
had no entry point, so only a clone could run them. Their usage messages now
|
|
66
|
+
name the invocation that applies — `npm run search --` from a checkout,
|
|
67
|
+
`npx threadshelf search` from an install.
|
|
40
68
|
|
|
41
69
|
## 1.2.0 — 2026-09-13
|
|
42
70
|
|
package/README.md
CHANGED
|
@@ -290,6 +290,15 @@ That is the whole install. The package ships the prebuilt web UI, so there is
|
|
|
290
290
|
nothing to compile and no repository to clone. Pick another port with
|
|
291
291
|
`npx threadshelf 3001`, and see `npx threadshelf --help` for the rest.
|
|
292
292
|
|
|
293
|
+
The terminal tools come with it:
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
npx threadshelf search "what did I decide about caching?"
|
|
297
|
+
npx threadshelf ingest ./my-exports my-collection
|
|
298
|
+
npx threadshelf parse ./chatgpt-export.json
|
|
299
|
+
npx threadshelf-mcp # stdio MCP server
|
|
300
|
+
```
|
|
301
|
+
|
|
293
302
|
Your archive is **never** stored inside the npm package: an `npx` install
|
|
294
303
|
directory is disposable and npm may wipe it at any time. Persistent data lives
|
|
295
304
|
in a per-user directory instead, so upgrading or clearing the npm cache leaves
|
|
@@ -576,7 +585,7 @@ ThreadShelf exposes your local index to MCP clients (e.g. Claude Desktop, or any
|
|
|
576
585
|
MCP-capable agent) over stdio — so a model can search your past chats as a tool.
|
|
577
586
|
|
|
578
587
|
```bash
|
|
579
|
-
npx threadshelf
|
|
588
|
+
npx threadshelf mcp # installed package (npx threadshelf-mcp is equivalent)
|
|
580
589
|
npm run mcp # from a clone
|
|
581
590
|
```
|
|
582
591
|
|
package/bin/threadshelf.js
CHANGED
|
@@ -3,30 +3,63 @@
|
|
|
3
3
|
* `npx threadshelf` entrypoint.
|
|
4
4
|
*
|
|
5
5
|
* Plain JavaScript on purpose: the published package must not need tsx or a
|
|
6
|
-
* TypeScript toolchain at runtime. It
|
|
7
|
-
* to the
|
|
6
|
+
* TypeScript toolchain at runtime. It dispatches to one of the compiled CLIs in
|
|
7
|
+
* dist/, defaulting to the web server.
|
|
8
|
+
*
|
|
9
|
+
* The subcommands exist so an installed package is not poorer than a clone:
|
|
10
|
+
* from the repository these are `npm run parse|ingest|search|mcp`, and without
|
|
11
|
+
* them the compiled CLIs would ship but be unreachable.
|
|
8
12
|
*/
|
|
9
13
|
import { createRequire } from 'node:module';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
10
15
|
|
|
11
16
|
const require = createRequire(import.meta.url);
|
|
12
17
|
const pkg = require('../package.json');
|
|
13
18
|
|
|
19
|
+
const SUBCOMMANDS = {
|
|
20
|
+
parse: '../dist/src/cli.js',
|
|
21
|
+
ingest: '../dist/src/ingest-cli.js',
|
|
22
|
+
search: '../dist/src/search-cli.js',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// `mcp` is handled separately: dist/mcp/server.js only starts itself when it
|
|
26
|
+
// decides it is the process entry point, and that check compares URLs in a way
|
|
27
|
+
// that is easy to get wrong on Windows. Start it explicitly instead, exactly as
|
|
28
|
+
// bin/threadshelf-mcp.js does.
|
|
29
|
+
const startMcpServer = async () => {
|
|
30
|
+
const [{ runServer }, { startIndexRecovery }] = await Promise.all([
|
|
31
|
+
import('../dist/mcp/server.js'),
|
|
32
|
+
import('../dist/src/store.js'),
|
|
33
|
+
]);
|
|
34
|
+
const stopRecovery = startIndexRecovery();
|
|
35
|
+
process.stdin.once('end', stopRecovery);
|
|
36
|
+
runServer();
|
|
37
|
+
};
|
|
38
|
+
|
|
14
39
|
const args = process.argv.slice(2);
|
|
15
40
|
|
|
16
41
|
const usage = `ThreadShelf ${pkg.version} - local semantic search for your AI chats
|
|
17
42
|
|
|
18
43
|
Usage:
|
|
19
|
-
npx threadshelf [port]
|
|
44
|
+
npx threadshelf [port] Start the web UI and API (default port 3000)
|
|
45
|
+
npx threadshelf search "<query>" [...] Search the archive from the terminal
|
|
46
|
+
npx threadshelf ingest <folder> [...] Ingest a folder of exports
|
|
47
|
+
npx threadshelf parse <file> [...] Parse one export to normalized JSON
|
|
48
|
+
npx threadshelf mcp Start the MCP stdio server
|
|
49
|
+
(npx threadshelf-mcp is equivalent)
|
|
20
50
|
|
|
21
51
|
Options:
|
|
22
52
|
-p, --port <port> Port to listen on (default 3000, or $PORT)
|
|
23
53
|
--host <host> Interface to bind (default 127.0.0.1, loopback only)
|
|
24
54
|
--data-dir <d> Directory for persistent data
|
|
25
|
-
(default: %LOCALAPPDATA
|
|
55
|
+
(default: %LOCALAPPDATA%\\ThreadShelf on Windows, ~/.threadshelf elsewhere)
|
|
26
56
|
--where Print the resolved data and package directories, then exit
|
|
27
57
|
-v, --version Print the version
|
|
28
58
|
-h, --help Show this help
|
|
29
59
|
|
|
60
|
+
Each subcommand takes its own flags; run it with --help for those. Pass
|
|
61
|
+
--data-dir before the subcommand, e.g. npx threadshelf --data-dir D:\\shelf search "x".
|
|
62
|
+
|
|
30
63
|
Environment:
|
|
31
64
|
PORT, HOST, THREADSHELF_DATA_DIR, LANCEDB_PATH and the other documented
|
|
32
65
|
overrides keep working and take precedence over the defaults.
|
|
@@ -34,6 +67,8 @@ Environment:
|
|
|
34
67
|
|
|
35
68
|
let port = '';
|
|
36
69
|
let showWhere = false;
|
|
70
|
+
let subcommand = '';
|
|
71
|
+
let subcommandArgs = [];
|
|
37
72
|
|
|
38
73
|
const takeValue = (flag, index) => {
|
|
39
74
|
const value = args[index + 1];
|
|
@@ -46,7 +81,12 @@ const takeValue = (flag, index) => {
|
|
|
46
81
|
|
|
47
82
|
for (let i = 0; i < args.length; i += 1) {
|
|
48
83
|
const arg = args[i];
|
|
49
|
-
if (arg === '
|
|
84
|
+
if (arg === 'mcp' || Object.hasOwn(SUBCOMMANDS, arg)) {
|
|
85
|
+
// Everything after the subcommand belongs to it, untouched.
|
|
86
|
+
subcommand = arg;
|
|
87
|
+
subcommandArgs = args.slice(i + 1);
|
|
88
|
+
break;
|
|
89
|
+
} else if (arg === '-h' || arg === '--help') {
|
|
50
90
|
console.log(usage);
|
|
51
91
|
process.exit(0);
|
|
52
92
|
} else if (arg === '-v' || arg === '--version') {
|
|
@@ -80,8 +120,17 @@ if (showWhere) {
|
|
|
80
120
|
process.exit(0);
|
|
81
121
|
}
|
|
82
122
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
123
|
+
if (subcommand === 'mcp') {
|
|
124
|
+
await startMcpServer();
|
|
125
|
+
} else if (subcommand) {
|
|
126
|
+
// The compiled CLIs read process.argv.slice(2) at module load, so present
|
|
127
|
+
// them the argv they would have seen if they had been invoked directly.
|
|
128
|
+
const entry = fileURLToPath(new URL(SUBCOMMANDS[subcommand], import.meta.url));
|
|
129
|
+
process.argv = [process.argv[0], entry, ...subcommandArgs];
|
|
130
|
+
await import(SUBCOMMANDS[subcommand]);
|
|
131
|
+
} else {
|
|
132
|
+
// server.ts reads process.argv[2] as a port; it is already normalised into
|
|
133
|
+
// process.env.PORT above, so hide the raw argv from it.
|
|
134
|
+
process.argv = [process.argv[0], process.argv[1]];
|
|
135
|
+
await import('../dist/src/server.js');
|
|
136
|
+
}
|
package/dist/src/cli.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { parseFile } from './parser.js';
|
|
3
|
+
import { invocation } from './paths.js';
|
|
3
4
|
const file = process.argv[2];
|
|
4
5
|
if (!file) {
|
|
5
|
-
console.error(
|
|
6
|
+
console.error(`Usage: ${invocation('parse')} <file> -- [--no-user] [--no-thinking] [--no-ai]`);
|
|
6
7
|
process.exit(1);
|
|
7
8
|
}
|
|
8
9
|
const options = {
|
package/dist/src/ingest-cli.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { basename, resolve } from 'path';
|
|
3
3
|
import { ingestFolder } from './ingest.js';
|
|
4
|
+
import { invocation } from './paths.js';
|
|
4
5
|
import { watchFolder } from './watch.js';
|
|
5
6
|
import { normalizeCollectionName } from './validation.js';
|
|
6
7
|
import { recoverPendingIndexes, startIndexRecovery } from './store.js';
|
|
@@ -33,7 +34,7 @@ for (let i = 0; i < args.length; i++) {
|
|
|
33
34
|
const folder = positional[0];
|
|
34
35
|
const collectionArg = positional[1] ?? 'chunks';
|
|
35
36
|
if (!folder || positional.length > 2) {
|
|
36
|
-
console.error(
|
|
37
|
+
console.error(`Usage: ${invocation('ingest')} <folder> [collection] -- [--clear] [--watch] [--debounce <ms>]`);
|
|
37
38
|
process.exit(1);
|
|
38
39
|
}
|
|
39
40
|
let collection;
|
package/dist/src/paths.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
|
-
import {
|
|
3
|
+
import { dirname, join, resolve } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
/**
|
|
6
6
|
* Single source of truth for "where does ThreadShelf read and write things".
|
|
@@ -24,10 +24,16 @@ const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
|
24
24
|
* This module lives at `<root>/src/paths.ts` in development and at
|
|
25
25
|
* `<root>/dist/src/paths.js` once compiled, so the package root is one or two
|
|
26
26
|
* levels up depending on which copy is running.
|
|
27
|
+
*
|
|
28
|
+
* The two cases are told apart by which candidate holds the manifest, not by
|
|
29
|
+
* the directory being named `dist`: a repository cloned into a directory that
|
|
30
|
+
* happens to be called `dist` would fool a name check and send every path one
|
|
31
|
+
* level too high. The build must therefore keep `dist/` free of a stray
|
|
32
|
+
* `package.json` — `test/packaging.test.js` asserts that.
|
|
27
33
|
*/
|
|
28
34
|
const resolvePackageRoot = (dir) => {
|
|
29
35
|
const parent = dirname(dir);
|
|
30
|
-
return
|
|
36
|
+
return existsSync(join(parent, 'package.json')) ? parent : dirname(parent);
|
|
31
37
|
};
|
|
32
38
|
const PACKAGE_ROOT = resolvePackageRoot(moduleDir);
|
|
33
39
|
/** Root of the installed package (or the repo in development). Static assets only. */
|
|
@@ -36,10 +42,12 @@ export const packageRoot = () => PACKAGE_ROOT;
|
|
|
36
42
|
export const packagePath = (...segments) => join(PACKAGE_ROOT, ...segments);
|
|
37
43
|
/**
|
|
38
44
|
* True when running from a source checkout rather than an installed package.
|
|
39
|
-
* The published tarball ships `dist
|
|
40
|
-
*
|
|
45
|
+
* The published tarball ships `dist/` and never `src/`, so an end user's
|
|
46
|
+
* install cannot be mistaken for a checkout. The whole directory is the marker
|
|
47
|
+
* rather than one file inside it, so renaming or splitting an entry point
|
|
48
|
+
* cannot silently move every developer's data out of their repository.
|
|
41
49
|
*/
|
|
42
|
-
export const isRepoCheckout = () => existsSync(join(PACKAGE_ROOT, 'src'
|
|
50
|
+
export const isRepoCheckout = () => existsSync(join(PACKAGE_ROOT, 'src'));
|
|
43
51
|
/** Per-user data directory for an installed package. */
|
|
44
52
|
export const userDataDir = (env = process.env, platform = process.platform, home = homedir()) => {
|
|
45
53
|
if (platform === 'win32') {
|
|
@@ -72,6 +80,12 @@ const LAYOUT = {
|
|
|
72
80
|
modelCache: { repo: ['.threadshelf', 'model-cache'], user: ['model-cache'] },
|
|
73
81
|
env: { repo: ['.env'], user: ['.env'] },
|
|
74
82
|
};
|
|
83
|
+
/**
|
|
84
|
+
* How the user would invoke one of the bundled CLIs, for usage messages.
|
|
85
|
+
* `npm run search --` is right from a clone and meaningless to somebody who
|
|
86
|
+
* installed the package, so print whichever actually applies.
|
|
87
|
+
*/
|
|
88
|
+
export const invocation = (command) => isRepoCheckout() ? `npm run ${command} --` : `npx threadshelf ${command}`;
|
|
75
89
|
/** Absolute path of a persistent file or directory. Callers still apply their own env overrides. */
|
|
76
90
|
export const dataPath = (key) => {
|
|
77
91
|
const entry = LAYOUT[key];
|
package/dist/src/search-cli.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
|
+
import { invocation } from './paths.js';
|
|
2
3
|
import { searchAcrossCollections } from './services/search.js';
|
|
3
4
|
import { recoverPendingIndexes } from './store.js';
|
|
4
5
|
import { normalizeCollectionSelector, normalizeCount, normalizeDateRange, normalizeOptionalString, normalizeQuery, normalizeRoles, normalizeSearchMode, } from './validation.js';
|
|
5
|
-
const USAGE = `Usage:
|
|
6
|
+
const USAGE = `Usage: ${invocation('search')} "<query>" -- [options]
|
|
6
7
|
|
|
7
8
|
Options:
|
|
8
9
|
--collection <name> Collection to search, or "all" (default: all)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "threadshelf",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Local semantic search, backup, and RAG for your AI chats — ChatGPT, Claude, Google AI Studio, OpenRouter, LM Studio, and Grok — searchable from a web UI, HTTP API, or MCP",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -14,7 +14,7 @@ Error generating stack: `+e.message+`
|
|
|
14
14
|
`).trim()+`
|
|
15
15
|
`},_o=e=>(e||`conversation`).toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,60)||`conversation`,vo=(e,t,n=`text/markdown;charset=utf-8`)=>{let r=new Blob([t],{type:n}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.href=i,a.download=e,document.body.appendChild(a),a.click(),a.remove(),URL.revokeObjectURL(i)},yo=e=>!e||e<=0?`—`:e>=1024**3?`${(e/1024**3).toFixed(e>=10*1024**3?0:1)} GB`:e>=1024**2?`${Math.round(e/1024**2)} MB`:`${Math.round(e/1024)} KB`,bo=e=>!e||e<=0?`0`:e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${Math.round(e/1e3)}k`:String(e);function xo({variant:e=`full`}){let t=B(e=>e.theme),n=B(e=>e.toggleTheme),r=t===`dark`,i=r?`light`:`dark`;return(0,R.jsxs)(`button`,{className:`theme-toggle ${e}`,onClick:n,title:`Switch to ${i} theme`,"aria-label":`Switch to ${i} theme`,children:[(0,R.jsx)(`span`,{className:`tt-ico`,children:r?W.sun:W.moon}),e===`full`&&(0,R.jsx)(`span`,{className:`tt-label`,children:r?`Light`:`Dark`})]})}var So=1,Co=4e3,wo=Ta((e,t)=>({toasts:[],confirmState:null,pushToast:(n,r=`info`)=>{let i=So++;e(e=>({toasts:[...e.toasts,{id:i,type:r,text:n}]})),setTimeout(()=>t().dismissToast(i),Co)},dismissToast:t=>{e(e=>({toasts:e.toasts.filter(e=>e.id!==t)}))},confirm:n=>new Promise(r=>{let i=t().confirmState;i&&i.resolve(!1),e({confirmState:{...n,id:So++,resolve:r}})}),resolveConfirm:n=>{let r=t().confirmState;r&&r.resolve(n),e({confirmState:null})}})),q={info:e=>wo.getState().pushToast(e,`info`),success:e=>wo.getState().pushToast(e,`success`),error:e=>wo.getState().pushToast(e,`error`)},To=e=>wo.getState().confirm(e),Eo=e=>{if(!e)return``;let t=e.split(/[\\/]/);return t[t.length-1]||e};function Do({detailed:e=!1}){let[t,n]=(0,L.useState)(null),[r,i]=(0,L.useState)(null),[a,o]=(0,L.useState)(!1),s=(0,L.useCallback)(async()=>{try{let[e,t]=await Promise.all([H.generationRuntime(),H.generationLlamaLogs().catch(()=>null)]);n(e.runtime),t&&i(t)}catch{n(null)}},[]);(0,L.useEffect)(()=>{let e=window.setTimeout(()=>void s(),0),t=window.setInterval(()=>void s(),3e3),r=e=>{if(e instanceof CustomEvent&&e.detail){n(e.detail),H.generationLlamaLogs().then(i).catch(()=>void 0);return}s()};return window.addEventListener(`threadshelf:generation-runtime-changed`,r),()=>{window.clearTimeout(e),window.clearInterval(t),window.removeEventListener(`threadshelf:generation-runtime-changed`,r)}},[s]);let c=async()=>{o(!0);try{let e=await H.ejectGenerationModel(t?.model);n(e.runtime),window.dispatchEvent(new Event(`threadshelf:generation-runtime-changed`)),q.success(`llama.cpp model ejected from memory.`)}catch(e){q.error(e instanceof Error?e.message:`Could not eject the model.`)}finally{o(!1)}},l=t&&(t.state===`starting`||t.state===`ready`||t.state===`external`&&!!t.model),u=r?.devices[0]?.id.replace(/\d+$/,``).toUpperCase(),d=!t||!r?`unknown`:t.state===`stopped`?r.devices.length>0?`idle · GPU (${u||`accelerator`})`:`idle · CPU`:r.offload.mode===`hybrid`?`hybrid ${r.offload.gpuPercent}% GPU`:r.offload.mode===`gpu`?`GPU · ${u||`accelerator`}`:r.offload.mode===`cpu`?`CPU`:r.devices.length>0?`GPU · ${u||`accelerator`}`:r.deviceDetectionSupported?`CPU`:`unknown`,f=[r?.executable?`Selected executable: ${r.executable}`:void 0,`Detected compute: ${d}`,``,`Check for a newer stable llama.cpp build:`,`npm run setup:llama -- -- --check`,``,`Install CPU:`,`npm run setup:llama -- -- --install --variant cpu`,``,`Install NVIDIA CUDA:`,`npm run setup:llama -- -- --install --variant cuda`,``,`Install Vulkan GPU:`,`npm run setup:llama -- -- --install --variant vulkan`,``,`macOS: use the cpu variant; Metal is included automatically.`].filter(e=>e!==void 0).join(`
|
|
16
16
|
`),p=Object.entries(r?.offload.deviceBufferMiB??{}).filter(([e])=>!e.toUpperCase().startsWith(`CPU`)).reduce((e,[,t])=>e+t,0),m=(r?.profile??[]).filter(e=>e.applied),h=m.length>0&&t?.state!==`stopped`?[d,...m.map(e=>`${e.setting} ${e.value}`),p>0?`GPU weights ${(p/1024).toFixed(1)} GiB`:``].filter(Boolean).join(` · `):``,g=(r?.profile??[]).filter(e=>e.note).map(e=>`${e.setting}: ${e.applied?``:`skipped, `}${e.note}`).join(`
|
|
17
|
-
`);return(0,R.jsxs)(`div`,{className:`global-runtime`,"data-state":t?.state||`unknown`,title:t?.detail,children:[(0,R.jsx)(`span`,{className:`runtime-dot`,"aria-hidden":`true`}),(0,R.jsxs)(`span`,{className:`global-runtime-copy`,children:[(0,R.jsxs)(`b`,{children:[(0,R.jsx)(`span`,{children:t?.state===`starting`?`llama.cpp · loading`:`llama.cpp`}),(0,R.jsx)(`em`,{children:d}),(0,R.jsx)(`span`,{className:`runtime-install-help`,tabIndex:0,role:`img`,"aria-label":`llama.cpp CPU and GPU install commands`,title:f,children:`?`})]}),(0,R.jsx)(`span`,{children:t?.model?Eo(t.model):t?`no model loaded`:`status unavailable`}),e&&t?.detail&&(0,R.jsx)(`small`,{children:t.detail}),e&&h&&(0,R.jsx)(`small`,{className:`runtime-profile`,title:g||void 0,children:h})]}),l&&(0,R.jsx)(`button`,{type:`button`,disabled:a,onClick:()=>void c(),children:a?`…`:`Eject`})]})}var Oo=[{id:`/search`,viewKey:`search`,label:`Search archive`,icon:W.search},{id:`/insights`,viewKey:`insights`,label:`Insights`,icon:W.chart}],ko=[{id:`/indexing`,viewKey:`indexing`,label:`Add data`,icon:W.download},{id:`/mcp`,viewKey:`mcp`,label:`MCP`,icon:W.plug},{id:`/settings`,viewKey:`settings`,label:`Settings`,icon:W.settings}];function Ao({view:e,setView:t,activeColl:n,setActiveColl:r,onNewChat:i,onNewPrivateChat:a,onOpenChat:o,activeChatId:s,onCmdK:c,onNewColl:l,onDeleteCollection:u,collections:d,stats:f}){let[p,m]=(0,L.useState)(!1),[h,g]=(0,L.useState)(e===`chat`),{data:_,isLoading:v,refetch:y}=Ha(),b=_?.threads??[],x=d.filter(e=>e!==`all`),S=x.reduce((e,t)=>e+(f[t]?.files??0),0),C=x.reduce((e,t)=>e+(f[t]?.chunks??0),0),w=e=>{let t=f[e];return(t?.chunks??0)===0&&(t?.files??0)===0&&(t?.conversations??0)===0},T=x.filter(e=>w(e)&&e!==n),E=x.filter(e=>p||!w(e)||e===n),D=e=>{let t=e?.conversations??0;return t>0?`${t.toLocaleString()} thread${t===1?``:`s`}`:`${(e?.files??0).toLocaleString()} files`},O=e=>{let t=e?.conversations??0;return`${t>0?`${t.toLocaleString()} conversation${t===1?``:`s`}`:`${(e?.files??0).toLocaleString()} files`} · ${(e?.chunks??0).toLocaleString()} indexed chunks`};return(0,R.jsxs)(`aside`,{className:`sidebar`,children:[(0,R.jsxs)(`div`,{className:`sb-brand`,children:[(0,R.jsx)(`div`,{className:`sb-logo`,"aria-hidden":`true`}),(0,R.jsxs)(`div`,{className:`sb-name`,children:[(0,R.jsx)(`b`,{children:`ThreadShelf`}),(0,R.jsxs)(`span`,{children:[`v`,`1.2.0`,` · local`]})]})]}),(0,R.jsxs)(`section`,{className:`sb-chat-panel`,"aria-label":`Conversations`,children:[(0,R.jsxs)(`div`,{className:`sb-chat-create`,children:[(0,R.jsxs)(`button`,{id:`sidebarNewChatButton`,className:`sb-new-chat`,onClick:i,children:[W.spark,(0,R.jsx)(`span`,{children:`New chat`})]}),(0,R.jsx)(`button`,{id:`sidebarPrivateChatButton`,className:`sb-private-chat`,"aria-label":`Start private conversation`,title:`Start a private chat that is cleared with this tab`,onClick:a,children:W.ghost})]}),(0,R.jsxs)(`div`,{className:`sb-chat-history`,children:[(0,R.jsxs)(`button`,{id:`sidebarChatHistoryToggle`,className:`sb-chat-history-toggle`,"aria-expanded":h,onClick:()=>{let e=!h;g(e),e&&y()},children:[(0,R.jsx)(`span`,{className:`ico`,children:W.chat}),(0,R.jsx)(`span`,{className:`label`,children:`Your chats`}),b.length>0&&(0,R.jsx)(`em`,{children:b.length}),(0,R.jsx)(`span`,{className:`sb-chat-chevron`,"aria-hidden":`true`,children:`▾`})]}),h&&(0,R.jsxs)(`div`,{className:`sb-chat-history-list`,children:[v&&(0,R.jsx)(`span`,{className:`sb-chat-history-empty`,children:`Loading chats…`}),!v&&b.length===0&&(0,R.jsx)(`span`,{className:`sb-chat-history-empty`,children:`No saved chats yet.`}),b.map(e=>(0,R.jsxs)(`button`,{className:`sb-chat-item`,"data-active":e.id===s,title:e.title,onClick:()=>o(e.id),children:[(0,R.jsx)(`strong`,{children:e.title}),(0,R.jsx)(`span`,{title:`${e.model?`${no(e.model)} · `:``}${e.turnCount} messages`,children:oo(e.updatedAt)||`just now`})]},e.id))]})]})]}),(0,R.jsxs)(`button`,{className:`sb-cmdk`,onClick:c,children:[W.search,(0,R.jsx)(`span`,{children:`Quick jump…`}),(0,R.jsx)(`kbd`,{children:`Ctrl+K`})]}),(0,R.jsx)(`div`,{className:`sb-section`,children:(0,R.jsx)(`span`,{children:`Library`})}),(0,R.jsx)(`nav`,{className:`sb-list`,style:{flex:`0 0 auto`},children:Oo.map(n=>(0,R.jsxs)(`button`,{id:n.viewKey===`indexing`?`indexingNavBtn`:void 0,className:`sb-item`,"data-active":e===n.viewKey,onClick:()=>t(n.id),children:[(0,R.jsx)(`span`,{className:`ico`,children:n.icon}),(0,R.jsx)(`span`,{className:`label`,children:n.label})]},n.id))}),(0,R.jsxs)(`div`,{className:`sb-section`,children:[(0,R.jsx)(`span`,{children:`Archive collections`}),(0,R.jsx)(`button`,{title:`New collection`,onClick:l,children:W.plus})]}),(0,R.jsxs)(`div`,{className:`sb-list sb-collections`,children:[(0,R.jsxs)(`button`,{id:`collection-all`,className:`sb-coll`,"data-active":n===`all`,onClick:()=>r(`all`),children:[(0,R.jsx)(`span`,{className:`sb-coll-dot`,style:{background:`var(--accent)`}}),(0,R.jsxs)(`span`,{className:`sb-coll-meta`,children:[(0,R.jsx)(`b`,{children:`All collections`}),(0,R.jsxs)(`span`,{children:[S,` files · `,C.toLocaleString(),` chunks`]})]})]}),E.map(e=>{let t=f[e];return(0,R.jsxs)(`div`,{className:`sb-coll-row`,children:[(0,R.jsxs)(`button`,{id:`collection-${e}`,className:`sb-coll`,"data-active":n===e,onClick:()=>r(e),children:[(0,R.jsx)(`span`,{className:`sb-coll-dot`}),(0,R.jsxs)(`span`,{className:`sb-coll-meta`,children:[(0,R.jsx)(`b`,{children:Za(e)}),(0,R.jsxs)(`span`,{title:O(t),children:[D(t),` · `,(t?.chunks??0).toLocaleString(),` chunks`]})]})]}),e!==`chunks`&&e!==`threadshelf_conversations`&&(0,R.jsx)(`button`,{id:`delete-collection-${e}`,className:`sb-coll-delete`,title:`Delete ${Za(e)}`,"aria-label":`Delete ${Za(e)}`,onClick:t=>{t.stopPropagation(),u(e)},children:W.trash})]},e)}),T.length>0&&(0,R.jsx)(`button`,{id:`toggleEmptyCollections`,className:`sb-coll-empty-toggle`,onClick:()=>m(e=>!e),children:p?`Hide empty collections`:`Show ${T.length} empty`})]}),(0,R.jsx)(`div`,{className:`sb-section sb-manage-section`,children:(0,R.jsx)(`span`,{children:`Manage`})}),(0,R.jsx)(`nav`,{className:`sb-list sb-manage-list`,children:ko.map(n=>(0,R.jsxs)(`button`,{id:n.viewKey===`indexing`?`indexingNavBtn`:void 0,className:`sb-item`,"data-active":e===n.viewKey,onClick:()=>t(n.id),children:[(0,R.jsx)(`span`,{className:`ico`,children:n.icon}),(0,R.jsx)(`span`,{className:`label`,children:n.label})]},n.id))}),(0,R.jsxs)(`div`,{className:`sb-footer`,children:[(0,R.jsx)(Do,{}),(0,R.jsxs)(`div`,{className:`sb-footer-row`,children:[(0,R.jsxs)(`span`,{className:`sb-status`,title:`Local backend · paraphrase-multilingual embeddings · LanceDB storage. Model runtime and eject live in the chat model menu.`,children:[`local · :`,window.location.port||`80`]}),(0,R.jsx)(xo,{variant:`icon`})]})]})]})}function jo({open:e,onClose:t,setView:n,onNewChat:r,setActiveColl:i,collections:a,stats:o,onNewColl:s,onRefresh:c}){let[l,u]=(0,L.useState)(``),[d,f]=(0,L.useState)(0),p=(0,L.useRef)(null);if((0,L.useEffect)(()=>{if(e){let e=window.setTimeout(()=>{u(``),f(0),p.current?.focus()},30);return()=>window.clearTimeout(e)}},[e]),!e)return null;let m=[{label:`Go to`,items:[{id:`go-search`,label:`Search archive`,icon:W.search,action:()=>n(`/search`)},{id:`go-chat`,label:`Chat history`,icon:W.chat,action:()=>n(`/chat`)},{id:`go-insights`,label:`Insights`,icon:W.chart,action:()=>n(`/insights`)},{id:`go-indexing`,label:`Indexing`,icon:W.download,action:()=>n(`/indexing`)},{id:`go-mcp`,label:`MCP`,icon:W.plug,action:()=>n(`/mcp`)},{id:`go-settings`,label:`Settings`,icon:W.settings,action:()=>n(`/settings`)}]},{label:`Collections`,items:[{id:`coll-all`,label:`All collections`,icon:W.scope,action:()=>i(`all`)},...a.filter(e=>e!==`all`).map(e=>({id:`coll-${e}`,label:Za(e),icon:W.database,meta:`${o[e]?.files??0} files`,action:()=>i(e)}))]},{label:`Actions`,items:[{id:`a-chat`,label:`New chat`,icon:W.spark,action:r},{id:`a-new`,label:`New collection…`,icon:W.plus,action:s},{id:`a-index`,label:`Index a folder`,icon:W.folder,action:()=>n(`/indexing`)},{id:`a-refresh`,label:`Refresh stats`,icon:W.refresh,action:c}]}].map(e=>({...e,items:e.items.filter(e=>!l||e.label.toLowerCase().includes(l.toLowerCase()))})).filter(e=>e.items.length>0),h=m.flatMap(e=>e.items),g=Math.min(d,h.length-1),_=e=>{e.key===`ArrowDown`?(e.preventDefault(),f(e=>(e+1)%Math.max(1,h.length))):e.key===`ArrowUp`?(e.preventDefault(),f(e=>(e-1+h.length)%Math.max(1,h.length))):e.key===`Enter`?(e.preventDefault(),h[g]?.action(),t()):e.key===`Escape`&&t()},v=0;return(0,R.jsx)(`div`,{className:`scrim`,onClick:t,children:(0,R.jsxs)(`div`,{className:`cmdk`,onClick:e=>e.stopPropagation(),children:[(0,R.jsxs)(`div`,{className:`cmdk-input`,children:[W.searchLg,(0,R.jsx)(`input`,{ref:p,value:l,onChange:e=>{u(e.target.value),f(0)},onKeyDown:_,placeholder:`Search commands, collections, or actions…`}),(0,R.jsx)(`kbd`,{children:`ESC`})]}),(0,R.jsxs)(`div`,{className:`cmdk-list`,children:[m.map(e=>(0,R.jsxs)(`div`,{children:[(0,R.jsx)(`div`,{className:`cmdk-group-h`,children:e.label}),e.items.map(e=>{let n=v++;return(0,R.jsxs)(`button`,{className:`cmdk-item`,"data-active":n===g,onMouseEnter:()=>f(n),onClick:()=>{e.action(),t()},children:[(0,R.jsx)(`span`,{className:`ico`,children:e.icon}),(0,R.jsx)(`span`,{children:e.label}),e.meta&&(0,R.jsx)(`span`,{className:`meta`,children:e.meta})]},e.id)})]},e.label)),h.length===0&&(0,R.jsx)(`div`,{style:{padding:24,textAlign:`center`,color:`var(--text-3)`,fontSize:12},children:`No matches`})]})]})})}function Mo({open:e,onClose:t,onCreated:n}){let[r,i]=(0,L.useState)(``),a=Ya(),o=(0,L.useCallback)(async()=>{if(r)try{let e=await a.mutateAsync(r);i(``),t(),n(e.collection??r),q.success(`Created collection "${e.collection??r}".`)}catch(e){q.error(e instanceof Error?e.message:`Unknown error`)}},[r,t,n,a]);return e?(0,R.jsx)(`div`,{className:`scrim`,onClick:t,children:(0,R.jsxs)(`div`,{className:`modal-card`,onClick:e=>e.stopPropagation(),children:[(0,R.jsxs)(`div`,{className:`modal-head`,children:[(0,R.jsx)(`h3`,{children:`New collection`}),(0,R.jsx)(`p`,{children:`Collections are local LanceDB tables. Use lowercase, alphanumeric, hyphens, underscores.`})]}),(0,R.jsxs)(`div`,{className:`modal-body`,children:[(0,R.jsx)(`label`,{children:`Name`}),(0,R.jsx)(`input`,{autoFocus:!0,value:r,onChange:e=>i(e.target.value.replace(/[^a-z0-9_-]/g,``).toLowerCase()),onKeyDown:e=>e.key===`Enter`&&r&&void o(),placeholder:`my-archive`})]}),(0,R.jsxs)(`div`,{className:`modal-foot`,children:[(0,R.jsx)(`button`,{className:`btn ghost`,onClick:t,children:`Cancel`}),(0,R.jsx)(`button`,{className:`btn primary`,onClick:()=>void o(),disabled:!r,children:`Create`})]})]})}):null}var No={info:W.info,success:W.check,error:W.warn};function Po(){let e=wo(e=>e.toasts),t=wo(e=>e.dismissToast);return e.length===0?null:(0,R.jsx)(`div`,{className:`toaster`,role:`status`,"aria-live":`polite`,children:e.map(e=>(0,R.jsxs)(`button`,{className:`toast`,"data-type":e.type,onClick:()=>t(e.id),title:`Dismiss`,children:[(0,R.jsx)(`span`,{className:`toast-ico`,children:No[e.type]}),(0,R.jsx)(`span`,{className:`toast-text`,children:e.text})]},e.id))})}function Fo(){let e=wo(e=>e.confirmState),t=wo(e=>e.resolveConfirm);if((0,L.useEffect)(()=>{if(!e)return;let n=e=>{e.key===`Escape`&&(e.preventDefault(),e.stopPropagation(),t(!1))};return window.addEventListener(`keydown`,n,!0),()=>window.removeEventListener(`keydown`,n,!0)},[e,t]),!e)return null;let{title:n,message:r,confirmLabel:i,cancelLabel:a,danger:o}=e;return(0,R.jsx)(`div`,{className:`scrim`,onClick:()=>t(!1),children:(0,R.jsxs)(`div`,{className:`modal-card`,onClick:e=>e.stopPropagation(),role:`alertdialog`,"aria-modal":`true`,children:[(0,R.jsxs)(`div`,{className:`modal-head`,children:[(0,R.jsx)(`h3`,{children:n}),r&&(0,R.jsx)(`p`,{children:r})]}),(0,R.jsxs)(`div`,{className:`modal-foot`,children:[(0,R.jsx)(`button`,{className:`btn ghost`,onClick:()=>t(!1),children:a??`Cancel`}),(0,R.jsx)(`button`,{className:`btn ${o?`danger`:`primary`}`,onClick:()=>t(!0),autoFocus:!0,children:i??`Confirm`})]})]})})}function Io(){let e=Qr(),t=Ke(),n=fa(),r=n.some(e=>e.pathname===`/thread`),i=B(e=>e.theme),a=B(e=>e.activeColl),o=B(e=>e.setActiveColl),s=B(e=>e.sidebarOpen),c=B(e=>e.setSidebarOpen),l=B(e=>e.cmdkOpen),u=B(e=>e.setCmdkOpen),d=B(e=>e.newCollOpen),f=B(e=>e.setNewCollOpen),{data:p}=za(),m=p?.collections??[`all`,`chunks`],h=p?.stats??{},g=qa(),_=(0,L.useCallback)(()=>c(!1),[c]),v=(0,L.useCallback)(async()=>{await Promise.all([t.invalidateQueries({queryKey:[`collections`]}),t.invalidateQueries({queryKey:[`files`]}),t.invalidateQueries({queryKey:[`search`]}),t.invalidateQueries({queryKey:[`thread`]})]),q.success(`Local index data refreshed.`)},[t]);(0,L.useEffect)(()=>{document.documentElement.dataset.theme=i},[i]);let y=(0,L.useCallback)(async t=>{if(t!==`chunks`&&t!==`threadshelf_conversations`&&await To({title:`Delete collection "${Za(t)}"?`,message:`The index and copies previously uploaded through ThreadShelf are deleted. Files in the original folder you selected remain untouched.`,confirmLabel:`Delete`,danger:!0}))try{await g.mutateAsync(t),a===t&&(o(`all`),e.navigate({to:`/search/$collection`,params:{collection:`all`}})),q.success(`Deleted collection "${Za(t)}".`)}catch(e){q.error(e instanceof Error?e.message:`Unknown error`)}},[a,o,g,e]),b=(0,L.useCallback)(t=>{t===`/search`?e.navigate({to:`/search/$collection`,params:{collection:a}}):t===`/chat`?e.navigate({to:`/chat`,search:{}}):e.navigate({to:t}),_()},[e,_,a]),x=(0,L.useCallback)(()=>{e.navigate({to:`/chat`,search:{draft:Date.now().toString(36)}}),_()},[e,_]),S=(0,L.useCallback)(()=>{e.navigate({to:`/chat`,search:{private:Date.now().toString(36)}}),_()},[e,_]),C=(0,L.useCallback)(t=>{e.navigate({to:`/chat`,search:{thread:t}}),_()},[e,_]),w=(0,L.useCallback)(t=>{o(t),e.navigate({to:`/search/$collection`,params:{collection:t}}),_()},[o,e,_]);(0,L.useEffect)(()=>{let t=t=>{let n=t.target.tagName.toLowerCase(),i=n===`input`||n===`textarea`;if((t.metaKey||t.ctrlKey)&&t.key.toLowerCase()===`k`){t.preventDefault(),u(!l);return}if(t.key===`Escape`){l?u(!1):d?f(!1):r?e.history.back():s&&_();return}!i&&t.key===`/`&&(t.preventDefault(),document.querySelector(`.search-card input`)?.focus())};return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[l,d,r,u,f,e,s,_]);let T=n[n.length-1]?.pathname??`/search`,E=r||T.startsWith(`/search`)?`search`:T.split(`/`)[1]||`search`,D=n.find(e=>e.pathname===`/chat`)?.search,O=typeof D?.thread==`string`?D.thread:``;return(0,R.jsxs)(`div`,{className:`app`,"data-reading":r,"data-sidebar-open":s,children:[(0,R.jsx)(Ao,{view:E,setView:b,activeColl:a,setActiveColl:w,onNewChat:x,onNewPrivateChat:S,onOpenChat:C,activeChatId:O,onCmdK:()=>{u(!0),_()},onNewColl:()=>{f(!0),_()},onDeleteCollection:y,collections:m,stats:h}),(0,R.jsx)(`button`,{className:`sidebar-scrim`,onClick:_,"aria-label":`Close sidebar`,tabIndex:s?0:-1}),(0,R.jsx)(`div`,{className:`main`,children:(0,R.jsx)(ca,{})}),(0,R.jsx)(jo,{open:l,onClose:()=>u(!1),setView:b,onNewChat:x,setActiveColl:w,collections:m,stats:h,onNewColl:()=>{u(!1),f(!0)},onRefresh:()=>void v()}),d&&(0,R.jsx)(Mo,{open:!0,onClose:()=>f(!1),onCreated:e=>{w(e)}}),(0,R.jsx)(Fo,{}),(0,R.jsx)(Po,{})]})}var Lo={"google-ai-studio":{label:`Google AI Studio`,short:`AI Studio`,color:`var(--p-google)`},google:{label:`Google AI Studio`,short:`AI Studio`,color:`var(--p-google)`},openrouter:{label:`OpenRouter`,short:`OpenRouter`,color:`var(--p-openrouter)`},openai:{label:`ChatGPT`,short:`ChatGPT`,color:`var(--p-openai)`},anthropic:{label:`Claude`,short:`Claude`,color:`var(--p-claude)`},claude:{label:`Claude`,short:`Claude`,color:`var(--p-claude)`},"lm-studio":{label:`LM Studio`,short:`LM Studio`,color:`var(--p-lmstudio)`},grok:{label:`Grok`,short:`Grok`,color:`var(--p-grok)`},threadshelf:{label:`ThreadShelf`,short:`ThreadShelf`,color:`oklch(0.74 0.16 165)`}},Ro={label:`Unknown`,short:`—`,color:`var(--border-2)`},zo=e=>e?Lo[e]??Ro:Ro,Bo=[`paper chromatography household experiment`,`fact-checking workflow with citations`,`sauna rules and temperature`,`openrouter export json schema`,`ablation study sample size`,`polish translation tone register`];function Vo({onPick:e}){return(0,R.jsxs)(`div`,{className:`empty`,children:[(0,R.jsx)(`h3`,{children:`Ask your archive in plain language.`}),(0,R.jsx)(`p`,{children:`ThreadShelf runs locally — your queries embed on this machine and search a local LanceDB. Try a topic, a draft you half-remember, or the shape of an answer you're looking for.`}),(0,R.jsx)(`div`,{className:`examples`,children:Bo.map(t=>(0,R.jsxs)(`button`,{className:`example-chip`,onClick:()=>e(t),children:[W.spark,(0,R.jsx)(`span`,{children:t})]},t))})]})}function Ho(e,t){let n=G(t);if(!n)return e;try{return K(e,t).map((e,t)=>n.test(e)?(0,R.jsx)(`mark`,{children:e},t):e)}catch{return e}}function Uo({result:e,query:t,onClick:n,selected:r,onMoreLikeThis:i}){let{metadata:a}=e,o=a.role??`ai`,s={user:`user`,thinking:`reasoning`,ai:`response`}[o]??o,c=zo(a.provider),l=$a(a.model),u=ao(a.createdAt),d=e.distance==null?``:(1-e.distance).toFixed(3),f=e.distance==null?0:Math.round((1-e.distance)*100),p=(0,L.useMemo)(()=>Ho(e.document,t),[e.document,t]),m=a.title?.trim()||Qa(a.sourceFile);return(0,R.jsxs)(`button`,{className:`result`,"data-selected":r,"aria-selected":r,onClick:n,children:[(0,R.jsxs)(`div`,{className:`result-head`,children:[(0,R.jsx)(`span`,{className:`r-role`,"data-role":o,children:s}),(0,R.jsxs)(`span`,{className:`r-provider`,children:[(0,R.jsx)(`span`,{className:`pdot`,style:{background:c.color}}),(0,R.jsx)(`span`,{children:c.short})]}),a.createdInThreadShelf&&(0,R.jsx)(`span`,{className:`threadshelf-turn-badge`,children:`ThreadShelf`}),e.distance!=null&&(0,R.jsx)(`div`,{className:`r-meta-right`,children:(0,R.jsxs)(`span`,{className:`r-score`,children:[(0,R.jsx)(`span`,{className:`r-score-bar`,children:(0,R.jsx)(`i`,{style:{width:`${f}%`}})}),(0,R.jsx)(`span`,{children:d})]})})]}),(0,R.jsx)(`div`,{className:`r-title`,title:m,children:m}),(0,R.jsx)(`div`,{className:`r-snippet`,children:p}),(0,R.jsxs)(`div`,{className:`r-foot`,children:[(0,R.jsxs)(`span`,{className:`r-source`,title:a.sourceFile,children:[W.folder,(0,R.jsx)(`span`,{className:`r-source-coll`,children:Za(a.collection??``)}),(0,R.jsx)(`span`,{className:`slash`,children:`/`}),(0,R.jsx)(`span`,{className:`r-source-file`,children:Qa(a.sourceFile)})]}),(0,R.jsx)(`span`,{className:`dot`}),l&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{className:`mono`,children:l}),(0,R.jsx)(`span`,{className:`dot`})]}),u&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{children:u}),(0,R.jsx)(`span`,{className:`dot`})]}),a.turnIndex!=null&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`span`,{children:[`turn `,(0,R.jsxs)(`b`,{className:`mono`,children:[`#`,a.turnIndex]})]}),(0,R.jsx)(`span`,{className:`dot`})]}),i&&(0,R.jsx)(`span`,{className:`more-like-this`,role:`button`,tabIndex:0,title:`Search for similar passages`,onClick:e=>{e.stopPropagation(),i()},onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),e.stopPropagation(),i())},children:`more like this`}),(0,R.jsxs)(`span`,{className:`open-thread`,children:[`open thread `,W.arrowRight]})]})]})}var Wo={search:`Archive`,insights:`Insights`,indexing:`Add data`,mcp:`MCP`,settings:`Settings`,chat:`Chat`};function Go({view:e,activeColl:t,onMenu:n,actions:r}){return(0,R.jsxs)(`div`,{className:`topbar`,children:[(0,R.jsx)(`button`,{className:`icon-btn mobile-menu-btn`,onClick:n,"aria-label":`Open sidebar`,children:W.menu}),(0,R.jsxs)(`div`,{className:`crumbs`,children:[(0,R.jsx)(`span`,{children:Wo[e]}),e===`search`&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{className:`sep`,children:`/`}),(0,R.jsx)(`b`,{children:Za(t)})]})]}),(0,R.jsx)(`div`,{className:`topbar-spacer`}),r&&(0,R.jsx)(`div`,{className:`topbar-actions`,children:r})]})}var Ko=100,qo=e=>{switch(e){case`recent`:return(e,t)=>(t.lastTurnAt??``).localeCompare(e.lastTurnAt??``);case`longest`:return(e,t)=>(t.turnCount??0)-(e.turnCount??0);case`title`:return(e,t)=>(e.title||e.sourceFile).localeCompare(t.title||t.sourceFile,void 0,{sensitivity:`base`})}},Jo=[{id:`user`,label:`User`,key:`user`},{id:`reasoning`,label:`Reasoning`,key:`thinking`},{id:`response`,label:`Response`,key:`ai`}];function Yo(){return(0,R.jsx)(`div`,{className:`result-list`,style:{marginTop:16},children:[0,1,2].map(e=>(0,R.jsx)(`div`,{className:`shimmer-card`},e))})}function Xo(){let e=Ni(),{collection:t}=ji({from:`/search/$collection`}),{q:n,model:r,from:i,to:a,mode:o}=Mi({from:`/search/$collection`}),s=t?decodeURIComponent(t):`all`,c=B(e=>e.setActiveColl);(0,L.useEffect)(()=>{c(s)},[s,c]);let l=B(e=>e.roles),u=B(e=>e.toggleRole),d=B(e=>e.modelFilter),f=B(e=>e.setModelFilter),p=B(e=>e.setSidebarOpen),m=B(e=>e.savedSearches),h=B(e=>e.addSavedSearch),g=B(e=>e.removeSavedSearch),_=B(e=>e.pinnedConversations),v=B(e=>e.togglePinned),[y,b]=(0,L.useState)(n??``),[x,S]=(0,L.useState)(n??``),[C,w]=(0,L.useState)(i??``),[T,E]=(0,L.useState)(a??``),[D,O]=(0,L.useState)(o===`keyword`?`keyword`:`semantic`),[ee,te]=(0,L.useState)(15),[k,ne]=(0,L.useState)(-1),[re,ie]=(0,L.useState)(``),[A,j]=(0,L.useState)(`recent`),[M,ae]=(0,L.useState)(Ko),[oe,se]=(0,L.useState)(`all`),N=(0,L.useRef)(n??``),P=(0,L.useRef)(null),F=(0,L.useRef)(null),{data:ce}=Ra(),le=ce??!0,ue=(0,L.useMemo)(()=>{let e=[];return l.user&&e.push(`user`),l.thinking&&e.push(`thinking`),l.ai&&e.push(`ai`),e.length>0&&e.length<3?e.join(`,`):void 0},[l]),{data:de,isFetching:fe}=Ua((0,L.useMemo)(()=>({q:x.trim(),collection:s,n:ee,roles:ue,keywordBoost:D===`semantic`&&x.trim().length<=40,model:(r??d).trim()||void 0,from:C.trim()||void 0,to:T.trim()||void 0,mode:D,origin:oe===`all`?void 0:oe}),[x,s,ee,ue,r,d,C,T,D,oe])),{data:pe,isLoading:me}=Va(s,!x.trim()&&le),he=(0,L.useMemo)(()=>{let e=pe?.files??[],t=re.trim().toLowerCase();return[...(t?e.filter(e=>[e.title,e.sourceFile,e.conversationKey,e.collection].some(e=>(e??``).toLowerCase().includes(t))):e).filter(e=>oe===`threadshelf`?e.createdInThreadShelf===!0||e.hasThreadShelfTurns===!0:oe!==`archive`||e.hasThreadShelfTurns!==!0)].sort(qo(A))},[pe?.files,re,A,oe]),I=(0,L.useMemo)(()=>he.slice(0,M),[he,M]);(0,L.useEffect)(()=>{let e=window.setTimeout(()=>ae(Ko),0);return()=>window.clearTimeout(e)},[s,re,A,oe]),(0,L.useEffect)(()=>{P.current?.focus()},[]),(0,L.useEffect)(()=>{let e=n??``;if(e!==N.current){let t=window.setTimeout(()=>{N.current=e,b(e),S(e),w(i??``),E(a??``),O(o===`keyword`?`keyword`:`semantic`)},0);return()=>window.clearTimeout(t)}},[n,i,a,o]),(0,L.useEffect)(()=>{let e=window.setTimeout(()=>{w(i??``),E(a??``)},0);return()=>window.clearTimeout(e)},[i,a]),(0,L.useEffect)(()=>{let e=window.setTimeout(()=>te(15),0);return()=>window.clearTimeout(e)},[x,s,ue,r,d,C,T,D,oe]);let ge=(0,L.useCallback)(t=>{let n=y.trim(),r=t??D;N.current=n,S(n),e({to:`/search/$collection`,params:{collection:s},search:n?{q:n,model:d.trim()||void 0,from:C.trim()||void 0,to:T.trim()||void 0,mode:r===`keyword`?`keyword`:void 0}:{},replace:!0})},[y,d,C,T,e,s,D]),_e=(0,L.useCallback)(()=>{N.current=``,b(``),S(``),P.current?.focus(),e({to:`/search/$collection`,params:{collection:s},search:{},replace:!0})},[e,s]),ve=(0,L.useCallback)(e=>{O(e),ge(e)},[ge]),ye=(0,L.useCallback)(t=>{e({to:`/thread`,search:{sourceFile:t.metadata.sourceFile,collection:t.metadata.collection??s,conversationKey:t.metadata.conversationKey,q:x.trim()||void 0,title:t.metadata.title,matchIdx:t.metadata.turnIndex,provider:t.metadata.provider,model:t.metadata.model}})},[s,x,e]),be=(0,L.useCallback)(t=>{let n=lo(t.document);n&&(O(`semantic`),N.current=n,b(n),S(n),e({to:`/search/$collection`,params:{collection:s},search:{q:n,model:d.trim()||void 0,from:C.trim()||void 0,to:T.trim()||void 0}}))},[s,d,C,T,e]),xe=(0,L.useCallback)(t=>{e({to:`/thread`,search:{sourceFile:t.sourceFile,collection:t.collection,conversationKey:t.conversationKey,title:t.title}})},[e]),Se=x.trim().length>0,Ce=(0,L.useMemo)(()=>({q:x.trim(),collection:s,mode:D,model:(r??d).trim()||void 0,from:C.trim()||void 0,to:T.trim()||void 0}),[x,s,D,r,d,C,T]),we=(0,L.useMemo)(()=>{let e=ka(Ce);return m.find(t=>ka(t)===e)},[m,Ce]),Te=(0,L.useCallback)(()=>{we?g(we.id):h(Ce)},[we,g,h,Ce]),Ee=(0,L.useCallback)(t=>{O(t.mode),N.current=t.q,b(t.q),S(t.q),e({to:`/search/$collection`,params:{collection:t.collection},search:{q:t.q,model:t.model,from:t.from,to:t.to,mode:t.mode===`keyword`?`keyword`:void 0}})},[e]),De=(0,L.useMemo)(()=>s===`all`?_:_.filter(e=>e.collection===s),[_,s]),Oe=(0,L.useMemo)(()=>new Set(_.map(e=>Aa(e))),[_]),ke=e=>({collection:e.collection,sourceFile:e.sourceFile,conversationKey:e.conversationKey,title:e.title,provider:e.provider}),Ae=(0,L.useMemo)(()=>de?.results??[],[de?.results]),je=Se&&!fe&&Ae.length>=ee&&ee<50,Me=s===`all`?`Conversations`:`${Za(s)} conversations`,Ne=Se?Ae.length:I.length,Pe=(0,L.useCallback)(e=>{if(Se){let t=Ae[e];t&&ye(t)}else{let t=I[e];t&&xe(t)}},[Se,Ae,I,ye,xe]);return(0,L.useEffect)(()=>{let e=window.setTimeout(()=>ne(-1),0);return()=>window.clearTimeout(e)},[x,s,Se]),(0,L.useEffect)(()=>{let e=e=>{let t=e.target,n=t.tagName?.toLowerCase(),r=t===P.current;if((n===`input`||n===`textarea`)&&!r||Ne===0)return;let i=e.key===`ArrowDown`||e.key===`j`&&!r,a=e.key===`ArrowUp`||e.key===`k`&&!r;i?(e.preventDefault(),r&&P.current?.blur(),ne(e=>Math.min(Ne-1,e+1))):a?(e.preventDefault(),ne(e=>e<=0?0:e-1)):e.key===`Enter`&&!r&&k>=0&&(e.preventDefault(),Pe(k))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[Ne,k,Pe]),(0,L.useEffect)(()=>{k<0||F.current?.querySelector(`[data-selected="true"]`)?.scrollIntoView({block:`nearest`})},[k]),(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(Go,{view:`search`,activeColl:s,onMenu:()=>p(!0)}),(0,R.jsx)(`div`,{className:`main-scroll`,children:(0,R.jsxs)(`div`,{className:`view`,children:[!le&&(0,R.jsxs)(`div`,{className:`banner err`,children:[(0,R.jsx)(`span`,{className:`ico`,children:W.warn}),(0,R.jsxs)(`div`,{className:`grow`,children:[(0,R.jsx)(`b`,{style:{fontWeight:500},children:`Backend unreachable.`}),` `,(0,R.jsxs)(`span`,{style:{color:`var(--text-2)`},children:[`Run `,(0,R.jsx)(`code`,{children:`npm start`}),` in the project root.`]})]})]}),(0,R.jsxs)(`div`,{className:`search-card`,children:[(0,R.jsx)(`span`,{className:`search-ico`,children:W.searchLg}),(0,R.jsx)(`input`,{id:`searchInput`,ref:P,value:y,onChange:e=>b(e.target.value),onKeyDown:e=>{e.key===`Enter`?ge():e.key===`Escape`&&y&&(e.preventDefault(),e.stopPropagation(),_e())},placeholder:D===`keyword`?`Exact match: identifiers, error strings, code…`:`Search by meaning across your archive…`}),y&&(0,R.jsx)(`button`,{id:`clearSearch`,type:`button`,className:`search-clear`,"aria-label":`Clear search`,title:`Clear search (Esc)`,onClick:_e,children:W.close})]}),(0,R.jsxs)(`div`,{className:`search-toolbar`,children:[(0,R.jsxs)(`div`,{className:`mode-toggle`,role:`group`,"aria-label":`Search mode`,children:[(0,R.jsx)(`button`,{type:`button`,className:`mode-btn`,"data-on":D===`semantic`,title:`Rank by meaning (local embeddings)`,onClick:()=>ve(`semantic`),children:`Semantic`}),(0,R.jsx)(`button`,{type:`button`,className:`mode-btn`,"data-on":D===`keyword`,title:`Exact substring match (case-insensitive)`,onClick:()=>ve(`keyword`),children:`Exact`})]}),(0,R.jsx)(`div`,{className:`role-chips`,children:Jo.map(e=>(0,R.jsxs)(`button`,{className:`role-chip`,"data-role":e.id,"data-on":l[e.key],onClick:()=>u(e.key),children:[(0,R.jsx)(`span`,{className:`dot`}),e.label]},e.id))}),(0,R.jsxs)(`label`,{className:`origin-filter`,children:[(0,R.jsx)(`span`,{children:`origin`}),(0,R.jsxs)(`select`,{"aria-label":`Filter by conversation origin`,value:oe,onChange:e=>se(e.target.value),children:[(0,R.jsx)(`option`,{value:`all`,children:`All`}),(0,R.jsx)(`option`,{value:`threadshelf`,children:`ThreadShelf`}),(0,R.jsx)(`option`,{value:`archive`,children:`Clean archive`})]})]}),(0,R.jsxs)(`label`,{className:`model-filter`,children:[(0,R.jsx)(`span`,{children:`model`}),(0,R.jsx)(`input`,{value:d,onChange:e=>f(e.target.value),onKeyDown:e=>e.key===`Enter`&&ge(),placeholder:`gpt-5, claude, gemini...`})]}),(0,R.jsxs)(`label`,{className:`date-filter`,children:[(0,R.jsx)(`span`,{children:`from`}),(0,R.jsx)(`input`,{type:`date`,value:C,onChange:e=>w(e.target.value),onKeyDown:e=>e.key===`Enter`&&ge()})]}),(0,R.jsxs)(`label`,{className:`date-filter`,children:[(0,R.jsx)(`span`,{children:`to`}),(0,R.jsx)(`input`,{type:`date`,value:T,onChange:e=>E(e.target.value),onKeyDown:e=>e.key===`Enter`&&ge()})]}),(0,R.jsx)(`span`,{className:`toolbar-spacer`}),(0,R.jsxs)(`span`,{className:`toolbar-hint`,children:[(0,R.jsx)(`kbd`,{children:`/`}),` focus · `,(0,R.jsx)(`kbd`,{children:`↑↓`}),` navigate · `,(0,R.jsx)(`kbd`,{children:`↵`}),` open · `,(0,R.jsx)(`kbd`,{children:`Ctrl+K`}),` `,`commands`]})]}),!Se&&(0,R.jsxs)(R.Fragment,{children:[s===`all`&&(0,R.jsx)(Vo,{onPick:t=>{N.current=t,b(t),S(t),e({to:`/search/$collection`,params:{collection:s},search:{q:t},replace:!0})}}),m.length>0&&(0,R.jsxs)(`div`,{className:`saved-searches`,children:[(0,R.jsxs)(`span`,{className:`ss-label`,children:[W.star,` Saved`]}),m.map(e=>(0,R.jsxs)(`span`,{className:`ss-chip`,children:[(0,R.jsxs)(`button`,{type:`button`,className:`ss-run`,title:`Run: ${e.q}`,onClick:()=>Ee(e),children:[(0,R.jsx)(`span`,{className:`ss-q`,children:e.q}),e.collection!==`all`&&(0,R.jsx)(`span`,{className:`ss-tag`,children:Za(e.collection)}),e.mode===`keyword`&&(0,R.jsx)(`span`,{className:`ss-tag`,children:`exact`})]}),(0,R.jsx)(`button`,{type:`button`,className:`ss-del`,"aria-label":`Delete saved search "${e.q}"`,onClick:()=>g(e.id),children:`×`})]},e.id))]}),De.length>0&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`div`,{className:`results-meta-bar`,children:(0,R.jsxs)(`span`,{className:`h`,children:[`Pinned `,(0,R.jsx)(`b`,{children:De.length})]})}),(0,R.jsx)(`div`,{className:`result-list`,children:De.map(e=>{let t=e.provider?zo(e.provider):null,n=Qa(e.sourceFile);return(0,R.jsxs)(`button`,{className:`result`,onClick:()=>xe(e),children:[(0,R.jsxs)(`div`,{className:`result-head`,children:[(0,R.jsx)(`span`,{className:`r-role`,"data-role":`user`,children:`pinned`}),(0,R.jsxs)(`span`,{className:`r-provider`,children:[(0,R.jsx)(`span`,{className:`pdot`,style:{background:t?.color??`var(--accent)`}}),(0,R.jsx)(`span`,{children:t?.short??Za(e.collection)})]}),(0,R.jsx)(`span`,{className:`pin-toggle`,role:`button`,tabIndex:0,"data-on":`true`,title:`Unpin`,onClick:t=>{t.stopPropagation(),v(e)},onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),t.stopPropagation(),v(e))},children:W.pinFilled})]}),(0,R.jsx)(`div`,{className:`r-title`,title:e.title||n,children:e.title||n}),(0,R.jsxs)(`div`,{className:`r-foot`,children:[(0,R.jsxs)(`span`,{className:`r-source`,title:e.sourceFile,children:[W.folder,(0,R.jsx)(`span`,{className:`r-source-coll`,children:Za(e.collection)}),(0,R.jsx)(`span`,{className:`slash`,children:`/`}),(0,R.jsx)(`span`,{className:`r-source-file`,children:n})]}),(0,R.jsxs)(`span`,{className:`open-thread`,children:[`open thread `,W.arrowRight]})]})]},Aa(e))})})]}),(0,R.jsxs)(`div`,{className:`results-meta-bar`,children:[(0,R.jsxs)(`span`,{className:`h`,children:[Me,` `,(0,R.jsx)(`b`,{children:he.length})]}),(0,R.jsxs)(`label`,{className:`conv-sort`,children:[(0,R.jsx)(`span`,{children:`sort`}),(0,R.jsxs)(`select`,{value:A,onChange:e=>j(e.target.value),"aria-label":`Sort conversations`,children:[(0,R.jsx)(`option`,{value:`recent`,children:`Recent`}),(0,R.jsx)(`option`,{value:`longest`,children:`Longest`}),(0,R.jsx)(`option`,{value:`title`,children:`Title`})]})]}),(0,R.jsx)(`input`,{className:`conv-filter`,value:re,onChange:e=>ie(e.target.value),placeholder:`Filter by title or file…`,"aria-label":`Filter conversations`})]}),me?(0,R.jsx)(Yo,{}):he.length>0?(0,R.jsxs)(`div`,{className:`result-list`,ref:F,children:[I.map((e,t)=>{let n=Qa(e.sourceFile),r=e.title||n,i=e.provider?zo(e.provider):null,a=ao(e.lastTurnAt),o=ke(e),s=Oe.has(Aa(o));return(0,R.jsxs)(`button`,{className:`result`,"data-selected":t===k,"aria-selected":t===k,onClick:()=>xe(e),children:[(0,R.jsxs)(`div`,{className:`result-head`,children:[(0,R.jsx)(`span`,{className:`r-role`,"data-role":`ai`,children:`thread`}),e.hasThreadShelfTurns&&(0,R.jsx)(`span`,{className:`threadshelf-turn-badge`,children:e.createdInThreadShelf?`Created in ThreadShelf`:`Continued in ThreadShelf`}),(0,R.jsxs)(`span`,{className:`r-provider`,children:[(0,R.jsx)(`span`,{className:`pdot`,style:{background:i?.color??`var(--accent)`}}),(0,R.jsx)(`span`,{children:i?.short??Za(e.collection)})]}),(0,R.jsx)(`span`,{className:`pin-toggle`,role:`button`,tabIndex:0,"data-on":s,title:s?`Unpin`:`Pin conversation`,onClick:e=>{e.stopPropagation(),v(o)},onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),e.stopPropagation(),v(o))},children:s?W.pinFilled:W.pin})]}),(0,R.jsx)(`div`,{className:`r-title`,title:r,children:r}),(0,R.jsxs)(`div`,{className:`r-foot`,children:[(0,R.jsxs)(`span`,{className:`r-source`,title:e.sourceFile,children:[W.folder,(0,R.jsx)(`span`,{className:`r-source-coll`,children:Za(e.collection)}),(0,R.jsx)(`span`,{className:`slash`,children:`/`}),(0,R.jsx)(`span`,{className:`r-source-file`,children:n})]}),e.turnCount!=null&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{className:`dot`}),(0,R.jsxs)(`span`,{children:[e.turnCount,` turns`]})]}),a&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{className:`dot`}),(0,R.jsx)(`span`,{children:a})]}),(0,R.jsxs)(`span`,{className:`open-thread`,children:[`open thread `,W.arrowRight]})]})]},`${e.collection}:${e.sourceFile}:${t}`)}),he.length>M&&(0,R.jsx)(`div`,{className:`load-more-row`,children:(0,R.jsxs)(`button`,{type:`button`,className:`load-more-button`,onClick:()=>ae(e=>e+Ko),children:[`Show more (`,he.length-M,` left)`]})})]}):re.trim()?(0,R.jsxs)(`div`,{className:`empty`,children:[(0,R.jsx)(`h3`,{children:`No conversations match the filter.`}),(0,R.jsx)(`p`,{children:`Try a different phrase or clear the filter box.`})]}):s===`all`?null:(0,R.jsxs)(`div`,{className:`empty`,children:[(0,R.jsx)(`h3`,{children:`No conversations indexed.`}),(0,R.jsx)(`p`,{children:`Index a folder into this collection or switch to another collection.`})]})]}),Se&&fe&&(0,R.jsx)(Yo,{}),Se&&!fe&&Ae.length===0&&(0,R.jsxs)(`div`,{className:`empty`,children:[(0,R.jsx)(`h3`,{children:`No results found.`}),(0,R.jsx)(`p`,{children:`Try another query, broaden your role filters, or index more files.`})]}),Se&&!fe&&Ae.length>0&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`div`,{className:`results-meta-bar`,children:[(0,R.jsxs)(`span`,{className:`h`,children:[`Results `,(0,R.jsx)(`b`,{children:Ae.length}),(0,R.jsxs)(`span`,{style:{marginLeft:14,color:`var(--text-3)`},children:[`in `,Za(s)]})]}),(0,R.jsxs)(`button`,{type:`button`,className:`save-search`,"data-on":!!we,title:we?`Remove from saved searches`:`Save this search`,onClick:Te,children:[we?W.starFilled:W.star,(0,R.jsx)(`span`,{children:we?`Saved`:`Save search`})]})]}),(0,R.jsx)(`div`,{className:`result-list`,ref:F,children:Ae.map((e,t)=>(0,R.jsx)(Uo,{result:e,query:x,selected:t===k,onClick:()=>ye(e),onMoreLikeThis:()=>be(e)},t))}),je&&(0,R.jsx)(`div`,{className:`load-more-row`,children:(0,R.jsx)(`button`,{type:`button`,className:`load-more-button`,onClick:()=>te(e=>Math.min(e+15,50)),children:`Load more`})})]})]})})]})}var Zo=/^(\s*)([-*+]|\d+[.)])\s+(.*)$/,Qo=/^\s*\d+[.)]\s+/,$o=e=>{let t=e.trim();return/^(?:https?:\/\/|mailto:|#|\/)/i.test(t)?t:null},es=e=>{let t=[],n=``,r=()=>{n&&=(t.push({type:`text`,value:n}),``)},i=0;for(;i<e.length;){let a=e[i];if(a==="`"){let n=e.indexOf("`",i+1);if(n>i){r(),t.push({type:`code`,value:e.slice(i+1,n)}),i=n+1;continue}}if(a===`[`){let n=e.indexOf(`]`,i+1);if(n>i&&e[n+1]===`(`){let a=e.indexOf(`)`,n+2);if(a>n){let o=$o(e.slice(n+2,a));if(o){r(),t.push({type:`link`,href:o,children:es(e.slice(i+1,n))}),i=a+1;continue}}}}if(a===`*`&&e[i+1]===`*`||a===`_`&&e[i+1]===`_`){let n=e.slice(i,i+2),a=e.indexOf(n,i+2);if(a>i+1){r(),t.push({type:`strong`,children:es(e.slice(i+2,a))}),i=a+2;continue}}if(a===`*`){let n=e.indexOf(`*`,i+1);if(n>i+1){r(),t.push({type:`em`,children:es(e.slice(i+1,n))}),i=n+1;continue}}n+=a,i+=1}return r(),t},ts=e=>{let t=e.replace(/\r\n?/g,`
|
|
17
|
+
`);return(0,R.jsxs)(`div`,{className:`global-runtime`,"data-state":t?.state||`unknown`,title:t?.detail,children:[(0,R.jsx)(`span`,{className:`runtime-dot`,"aria-hidden":`true`}),(0,R.jsxs)(`span`,{className:`global-runtime-copy`,children:[(0,R.jsxs)(`b`,{children:[(0,R.jsx)(`span`,{children:t?.state===`starting`?`llama.cpp · loading`:`llama.cpp`}),(0,R.jsx)(`em`,{children:d}),(0,R.jsx)(`span`,{className:`runtime-install-help`,tabIndex:0,role:`img`,"aria-label":`llama.cpp CPU and GPU install commands`,title:f,children:`?`})]}),(0,R.jsx)(`span`,{children:t?.model?Eo(t.model):t?`no model loaded`:`status unavailable`}),e&&t?.detail&&(0,R.jsx)(`small`,{children:t.detail}),e&&h&&(0,R.jsx)(`small`,{className:`runtime-profile`,title:g||void 0,children:h})]}),l&&(0,R.jsx)(`button`,{type:`button`,disabled:a,onClick:()=>void c(),children:a?`…`:`Eject`})]})}var Oo=[{id:`/search`,viewKey:`search`,label:`Search archive`,icon:W.search},{id:`/insights`,viewKey:`insights`,label:`Insights`,icon:W.chart}],ko=[{id:`/indexing`,viewKey:`indexing`,label:`Add data`,icon:W.download},{id:`/mcp`,viewKey:`mcp`,label:`MCP`,icon:W.plug},{id:`/settings`,viewKey:`settings`,label:`Settings`,icon:W.settings}];function Ao({view:e,setView:t,activeColl:n,setActiveColl:r,onNewChat:i,onNewPrivateChat:a,onOpenChat:o,activeChatId:s,onCmdK:c,onNewColl:l,onDeleteCollection:u,collections:d,stats:f}){let[p,m]=(0,L.useState)(!1),[h,g]=(0,L.useState)(e===`chat`),{data:_,isLoading:v,refetch:y}=Ha(),b=_?.threads??[],x=d.filter(e=>e!==`all`),S=x.reduce((e,t)=>e+(f[t]?.files??0),0),C=x.reduce((e,t)=>e+(f[t]?.chunks??0),0),w=e=>{let t=f[e];return(t?.chunks??0)===0&&(t?.files??0)===0&&(t?.conversations??0)===0},T=x.filter(e=>w(e)&&e!==n),E=x.filter(e=>p||!w(e)||e===n),D=e=>{let t=e?.conversations??0;return t>0?`${t.toLocaleString()} thread${t===1?``:`s`}`:`${(e?.files??0).toLocaleString()} files`},O=e=>{let t=e?.conversations??0;return`${t>0?`${t.toLocaleString()} conversation${t===1?``:`s`}`:`${(e?.files??0).toLocaleString()} files`} · ${(e?.chunks??0).toLocaleString()} indexed chunks`};return(0,R.jsxs)(`aside`,{className:`sidebar`,children:[(0,R.jsxs)(`div`,{className:`sb-brand`,children:[(0,R.jsx)(`div`,{className:`sb-logo`,"aria-hidden":`true`}),(0,R.jsxs)(`div`,{className:`sb-name`,children:[(0,R.jsx)(`b`,{children:`ThreadShelf`}),(0,R.jsxs)(`span`,{children:[`v`,`1.2.2`,` · local`]})]})]}),(0,R.jsxs)(`section`,{className:`sb-chat-panel`,"aria-label":`Conversations`,children:[(0,R.jsxs)(`div`,{className:`sb-chat-create`,children:[(0,R.jsxs)(`button`,{id:`sidebarNewChatButton`,className:`sb-new-chat`,onClick:i,children:[W.spark,(0,R.jsx)(`span`,{children:`New chat`})]}),(0,R.jsx)(`button`,{id:`sidebarPrivateChatButton`,className:`sb-private-chat`,"aria-label":`Start private conversation`,title:`Start a private chat that is cleared with this tab`,onClick:a,children:W.ghost})]}),(0,R.jsxs)(`div`,{className:`sb-chat-history`,children:[(0,R.jsxs)(`button`,{id:`sidebarChatHistoryToggle`,className:`sb-chat-history-toggle`,"aria-expanded":h,onClick:()=>{let e=!h;g(e),e&&y()},children:[(0,R.jsx)(`span`,{className:`ico`,children:W.chat}),(0,R.jsx)(`span`,{className:`label`,children:`Your chats`}),b.length>0&&(0,R.jsx)(`em`,{children:b.length}),(0,R.jsx)(`span`,{className:`sb-chat-chevron`,"aria-hidden":`true`,children:`▾`})]}),h&&(0,R.jsxs)(`div`,{className:`sb-chat-history-list`,children:[v&&(0,R.jsx)(`span`,{className:`sb-chat-history-empty`,children:`Loading chats…`}),!v&&b.length===0&&(0,R.jsx)(`span`,{className:`sb-chat-history-empty`,children:`No saved chats yet.`}),b.map(e=>(0,R.jsxs)(`button`,{className:`sb-chat-item`,"data-active":e.id===s,title:e.title,onClick:()=>o(e.id),children:[(0,R.jsx)(`strong`,{children:e.title}),(0,R.jsx)(`span`,{title:`${e.model?`${no(e.model)} · `:``}${e.turnCount} messages`,children:oo(e.updatedAt)||`just now`})]},e.id))]})]})]}),(0,R.jsxs)(`button`,{className:`sb-cmdk`,onClick:c,children:[W.search,(0,R.jsx)(`span`,{children:`Quick jump…`}),(0,R.jsx)(`kbd`,{children:`Ctrl+K`})]}),(0,R.jsx)(`div`,{className:`sb-section`,children:(0,R.jsx)(`span`,{children:`Library`})}),(0,R.jsx)(`nav`,{className:`sb-list`,style:{flex:`0 0 auto`},children:Oo.map(n=>(0,R.jsxs)(`button`,{id:n.viewKey===`indexing`?`indexingNavBtn`:void 0,className:`sb-item`,"data-active":e===n.viewKey,onClick:()=>t(n.id),children:[(0,R.jsx)(`span`,{className:`ico`,children:n.icon}),(0,R.jsx)(`span`,{className:`label`,children:n.label})]},n.id))}),(0,R.jsxs)(`div`,{className:`sb-section`,children:[(0,R.jsx)(`span`,{children:`Archive collections`}),(0,R.jsx)(`button`,{title:`New collection`,onClick:l,children:W.plus})]}),(0,R.jsxs)(`div`,{className:`sb-list sb-collections`,children:[(0,R.jsxs)(`button`,{id:`collection-all`,className:`sb-coll`,"data-active":n===`all`,onClick:()=>r(`all`),children:[(0,R.jsx)(`span`,{className:`sb-coll-dot`,style:{background:`var(--accent)`}}),(0,R.jsxs)(`span`,{className:`sb-coll-meta`,children:[(0,R.jsx)(`b`,{children:`All collections`}),(0,R.jsxs)(`span`,{children:[S,` files · `,C.toLocaleString(),` chunks`]})]})]}),E.map(e=>{let t=f[e];return(0,R.jsxs)(`div`,{className:`sb-coll-row`,children:[(0,R.jsxs)(`button`,{id:`collection-${e}`,className:`sb-coll`,"data-active":n===e,onClick:()=>r(e),children:[(0,R.jsx)(`span`,{className:`sb-coll-dot`}),(0,R.jsxs)(`span`,{className:`sb-coll-meta`,children:[(0,R.jsx)(`b`,{children:Za(e)}),(0,R.jsxs)(`span`,{title:O(t),children:[D(t),` · `,(t?.chunks??0).toLocaleString(),` chunks`]})]})]}),e!==`chunks`&&e!==`threadshelf_conversations`&&(0,R.jsx)(`button`,{id:`delete-collection-${e}`,className:`sb-coll-delete`,title:`Delete ${Za(e)}`,"aria-label":`Delete ${Za(e)}`,onClick:t=>{t.stopPropagation(),u(e)},children:W.trash})]},e)}),T.length>0&&(0,R.jsx)(`button`,{id:`toggleEmptyCollections`,className:`sb-coll-empty-toggle`,onClick:()=>m(e=>!e),children:p?`Hide empty collections`:`Show ${T.length} empty`})]}),(0,R.jsx)(`div`,{className:`sb-section sb-manage-section`,children:(0,R.jsx)(`span`,{children:`Manage`})}),(0,R.jsx)(`nav`,{className:`sb-list sb-manage-list`,children:ko.map(n=>(0,R.jsxs)(`button`,{id:n.viewKey===`indexing`?`indexingNavBtn`:void 0,className:`sb-item`,"data-active":e===n.viewKey,onClick:()=>t(n.id),children:[(0,R.jsx)(`span`,{className:`ico`,children:n.icon}),(0,R.jsx)(`span`,{className:`label`,children:n.label})]},n.id))}),(0,R.jsxs)(`div`,{className:`sb-footer`,children:[(0,R.jsx)(Do,{}),(0,R.jsxs)(`div`,{className:`sb-footer-row`,children:[(0,R.jsxs)(`span`,{className:`sb-status`,title:`Local backend · paraphrase-multilingual embeddings · LanceDB storage. Model runtime and eject live in the chat model menu.`,children:[`local · :`,window.location.port||`80`]}),(0,R.jsx)(xo,{variant:`icon`})]})]})]})}function jo({open:e,onClose:t,setView:n,onNewChat:r,setActiveColl:i,collections:a,stats:o,onNewColl:s,onRefresh:c}){let[l,u]=(0,L.useState)(``),[d,f]=(0,L.useState)(0),p=(0,L.useRef)(null);if((0,L.useEffect)(()=>{if(e){let e=window.setTimeout(()=>{u(``),f(0),p.current?.focus()},30);return()=>window.clearTimeout(e)}},[e]),!e)return null;let m=[{label:`Go to`,items:[{id:`go-search`,label:`Search archive`,icon:W.search,action:()=>n(`/search`)},{id:`go-chat`,label:`Chat history`,icon:W.chat,action:()=>n(`/chat`)},{id:`go-insights`,label:`Insights`,icon:W.chart,action:()=>n(`/insights`)},{id:`go-indexing`,label:`Indexing`,icon:W.download,action:()=>n(`/indexing`)},{id:`go-mcp`,label:`MCP`,icon:W.plug,action:()=>n(`/mcp`)},{id:`go-settings`,label:`Settings`,icon:W.settings,action:()=>n(`/settings`)}]},{label:`Collections`,items:[{id:`coll-all`,label:`All collections`,icon:W.scope,action:()=>i(`all`)},...a.filter(e=>e!==`all`).map(e=>({id:`coll-${e}`,label:Za(e),icon:W.database,meta:`${o[e]?.files??0} files`,action:()=>i(e)}))]},{label:`Actions`,items:[{id:`a-chat`,label:`New chat`,icon:W.spark,action:r},{id:`a-new`,label:`New collection…`,icon:W.plus,action:s},{id:`a-index`,label:`Index a folder`,icon:W.folder,action:()=>n(`/indexing`)},{id:`a-refresh`,label:`Refresh stats`,icon:W.refresh,action:c}]}].map(e=>({...e,items:e.items.filter(e=>!l||e.label.toLowerCase().includes(l.toLowerCase()))})).filter(e=>e.items.length>0),h=m.flatMap(e=>e.items),g=Math.min(d,h.length-1),_=e=>{e.key===`ArrowDown`?(e.preventDefault(),f(e=>(e+1)%Math.max(1,h.length))):e.key===`ArrowUp`?(e.preventDefault(),f(e=>(e-1+h.length)%Math.max(1,h.length))):e.key===`Enter`?(e.preventDefault(),h[g]?.action(),t()):e.key===`Escape`&&t()},v=0;return(0,R.jsx)(`div`,{className:`scrim`,onClick:t,children:(0,R.jsxs)(`div`,{className:`cmdk`,onClick:e=>e.stopPropagation(),children:[(0,R.jsxs)(`div`,{className:`cmdk-input`,children:[W.searchLg,(0,R.jsx)(`input`,{ref:p,value:l,onChange:e=>{u(e.target.value),f(0)},onKeyDown:_,placeholder:`Search commands, collections, or actions…`}),(0,R.jsx)(`kbd`,{children:`ESC`})]}),(0,R.jsxs)(`div`,{className:`cmdk-list`,children:[m.map(e=>(0,R.jsxs)(`div`,{children:[(0,R.jsx)(`div`,{className:`cmdk-group-h`,children:e.label}),e.items.map(e=>{let n=v++;return(0,R.jsxs)(`button`,{className:`cmdk-item`,"data-active":n===g,onMouseEnter:()=>f(n),onClick:()=>{e.action(),t()},children:[(0,R.jsx)(`span`,{className:`ico`,children:e.icon}),(0,R.jsx)(`span`,{children:e.label}),e.meta&&(0,R.jsx)(`span`,{className:`meta`,children:e.meta})]},e.id)})]},e.label)),h.length===0&&(0,R.jsx)(`div`,{style:{padding:24,textAlign:`center`,color:`var(--text-3)`,fontSize:12},children:`No matches`})]})]})})}function Mo({open:e,onClose:t,onCreated:n}){let[r,i]=(0,L.useState)(``),a=Ya(),o=(0,L.useCallback)(async()=>{if(r)try{let e=await a.mutateAsync(r);i(``),t(),n(e.collection??r),q.success(`Created collection "${e.collection??r}".`)}catch(e){q.error(e instanceof Error?e.message:`Unknown error`)}},[r,t,n,a]);return e?(0,R.jsx)(`div`,{className:`scrim`,onClick:t,children:(0,R.jsxs)(`div`,{className:`modal-card`,onClick:e=>e.stopPropagation(),children:[(0,R.jsxs)(`div`,{className:`modal-head`,children:[(0,R.jsx)(`h3`,{children:`New collection`}),(0,R.jsx)(`p`,{children:`Collections are local LanceDB tables. Use lowercase, alphanumeric, hyphens, underscores.`})]}),(0,R.jsxs)(`div`,{className:`modal-body`,children:[(0,R.jsx)(`label`,{children:`Name`}),(0,R.jsx)(`input`,{autoFocus:!0,value:r,onChange:e=>i(e.target.value.replace(/[^a-z0-9_-]/g,``).toLowerCase()),onKeyDown:e=>e.key===`Enter`&&r&&void o(),placeholder:`my-archive`})]}),(0,R.jsxs)(`div`,{className:`modal-foot`,children:[(0,R.jsx)(`button`,{className:`btn ghost`,onClick:t,children:`Cancel`}),(0,R.jsx)(`button`,{className:`btn primary`,onClick:()=>void o(),disabled:!r,children:`Create`})]})]})}):null}var No={info:W.info,success:W.check,error:W.warn};function Po(){let e=wo(e=>e.toasts),t=wo(e=>e.dismissToast);return e.length===0?null:(0,R.jsx)(`div`,{className:`toaster`,role:`status`,"aria-live":`polite`,children:e.map(e=>(0,R.jsxs)(`button`,{className:`toast`,"data-type":e.type,onClick:()=>t(e.id),title:`Dismiss`,children:[(0,R.jsx)(`span`,{className:`toast-ico`,children:No[e.type]}),(0,R.jsx)(`span`,{className:`toast-text`,children:e.text})]},e.id))})}function Fo(){let e=wo(e=>e.confirmState),t=wo(e=>e.resolveConfirm);if((0,L.useEffect)(()=>{if(!e)return;let n=e=>{e.key===`Escape`&&(e.preventDefault(),e.stopPropagation(),t(!1))};return window.addEventListener(`keydown`,n,!0),()=>window.removeEventListener(`keydown`,n,!0)},[e,t]),!e)return null;let{title:n,message:r,confirmLabel:i,cancelLabel:a,danger:o}=e;return(0,R.jsx)(`div`,{className:`scrim`,onClick:()=>t(!1),children:(0,R.jsxs)(`div`,{className:`modal-card`,onClick:e=>e.stopPropagation(),role:`alertdialog`,"aria-modal":`true`,children:[(0,R.jsxs)(`div`,{className:`modal-head`,children:[(0,R.jsx)(`h3`,{children:n}),r&&(0,R.jsx)(`p`,{children:r})]}),(0,R.jsxs)(`div`,{className:`modal-foot`,children:[(0,R.jsx)(`button`,{className:`btn ghost`,onClick:()=>t(!1),children:a??`Cancel`}),(0,R.jsx)(`button`,{className:`btn ${o?`danger`:`primary`}`,onClick:()=>t(!0),autoFocus:!0,children:i??`Confirm`})]})]})})}function Io(){let e=Qr(),t=Ke(),n=fa(),r=n.some(e=>e.pathname===`/thread`),i=B(e=>e.theme),a=B(e=>e.activeColl),o=B(e=>e.setActiveColl),s=B(e=>e.sidebarOpen),c=B(e=>e.setSidebarOpen),l=B(e=>e.cmdkOpen),u=B(e=>e.setCmdkOpen),d=B(e=>e.newCollOpen),f=B(e=>e.setNewCollOpen),{data:p}=za(),m=p?.collections??[`all`,`chunks`],h=p?.stats??{},g=qa(),_=(0,L.useCallback)(()=>c(!1),[c]),v=(0,L.useCallback)(async()=>{await Promise.all([t.invalidateQueries({queryKey:[`collections`]}),t.invalidateQueries({queryKey:[`files`]}),t.invalidateQueries({queryKey:[`search`]}),t.invalidateQueries({queryKey:[`thread`]})]),q.success(`Local index data refreshed.`)},[t]);(0,L.useEffect)(()=>{document.documentElement.dataset.theme=i},[i]);let y=(0,L.useCallback)(async t=>{if(t!==`chunks`&&t!==`threadshelf_conversations`&&await To({title:`Delete collection "${Za(t)}"?`,message:`The index and copies previously uploaded through ThreadShelf are deleted. Files in the original folder you selected remain untouched.`,confirmLabel:`Delete`,danger:!0}))try{await g.mutateAsync(t),a===t&&(o(`all`),e.navigate({to:`/search/$collection`,params:{collection:`all`}})),q.success(`Deleted collection "${Za(t)}".`)}catch(e){q.error(e instanceof Error?e.message:`Unknown error`)}},[a,o,g,e]),b=(0,L.useCallback)(t=>{t===`/search`?e.navigate({to:`/search/$collection`,params:{collection:a}}):t===`/chat`?e.navigate({to:`/chat`,search:{}}):e.navigate({to:t}),_()},[e,_,a]),x=(0,L.useCallback)(()=>{e.navigate({to:`/chat`,search:{draft:Date.now().toString(36)}}),_()},[e,_]),S=(0,L.useCallback)(()=>{e.navigate({to:`/chat`,search:{private:Date.now().toString(36)}}),_()},[e,_]),C=(0,L.useCallback)(t=>{e.navigate({to:`/chat`,search:{thread:t}}),_()},[e,_]),w=(0,L.useCallback)(t=>{o(t),e.navigate({to:`/search/$collection`,params:{collection:t}}),_()},[o,e,_]);(0,L.useEffect)(()=>{let t=t=>{let n=t.target.tagName.toLowerCase(),i=n===`input`||n===`textarea`;if((t.metaKey||t.ctrlKey)&&t.key.toLowerCase()===`k`){t.preventDefault(),u(!l);return}if(t.key===`Escape`){l?u(!1):d?f(!1):r?e.history.back():s&&_();return}!i&&t.key===`/`&&(t.preventDefault(),document.querySelector(`.search-card input`)?.focus())};return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[l,d,r,u,f,e,s,_]);let T=n[n.length-1]?.pathname??`/search`,E=r||T.startsWith(`/search`)?`search`:T.split(`/`)[1]||`search`,D=n.find(e=>e.pathname===`/chat`)?.search,O=typeof D?.thread==`string`?D.thread:``;return(0,R.jsxs)(`div`,{className:`app`,"data-reading":r,"data-sidebar-open":s,children:[(0,R.jsx)(Ao,{view:E,setView:b,activeColl:a,setActiveColl:w,onNewChat:x,onNewPrivateChat:S,onOpenChat:C,activeChatId:O,onCmdK:()=>{u(!0),_()},onNewColl:()=>{f(!0),_()},onDeleteCollection:y,collections:m,stats:h}),(0,R.jsx)(`button`,{className:`sidebar-scrim`,onClick:_,"aria-label":`Close sidebar`,tabIndex:s?0:-1}),(0,R.jsx)(`div`,{className:`main`,children:(0,R.jsx)(ca,{})}),(0,R.jsx)(jo,{open:l,onClose:()=>u(!1),setView:b,onNewChat:x,setActiveColl:w,collections:m,stats:h,onNewColl:()=>{u(!1),f(!0)},onRefresh:()=>void v()}),d&&(0,R.jsx)(Mo,{open:!0,onClose:()=>f(!1),onCreated:e=>{w(e)}}),(0,R.jsx)(Fo,{}),(0,R.jsx)(Po,{})]})}var Lo={"google-ai-studio":{label:`Google AI Studio`,short:`AI Studio`,color:`var(--p-google)`},google:{label:`Google AI Studio`,short:`AI Studio`,color:`var(--p-google)`},openrouter:{label:`OpenRouter`,short:`OpenRouter`,color:`var(--p-openrouter)`},openai:{label:`ChatGPT`,short:`ChatGPT`,color:`var(--p-openai)`},anthropic:{label:`Claude`,short:`Claude`,color:`var(--p-claude)`},claude:{label:`Claude`,short:`Claude`,color:`var(--p-claude)`},"lm-studio":{label:`LM Studio`,short:`LM Studio`,color:`var(--p-lmstudio)`},grok:{label:`Grok`,short:`Grok`,color:`var(--p-grok)`},threadshelf:{label:`ThreadShelf`,short:`ThreadShelf`,color:`oklch(0.74 0.16 165)`}},Ro={label:`Unknown`,short:`—`,color:`var(--border-2)`},zo=e=>e?Lo[e]??Ro:Ro,Bo=[`paper chromatography household experiment`,`fact-checking workflow with citations`,`sauna rules and temperature`,`openrouter export json schema`,`ablation study sample size`,`polish translation tone register`];function Vo({onPick:e}){return(0,R.jsxs)(`div`,{className:`empty`,children:[(0,R.jsx)(`h3`,{children:`Ask your archive in plain language.`}),(0,R.jsx)(`p`,{children:`ThreadShelf runs locally — your queries embed on this machine and search a local LanceDB. Try a topic, a draft you half-remember, or the shape of an answer you're looking for.`}),(0,R.jsx)(`div`,{className:`examples`,children:Bo.map(t=>(0,R.jsxs)(`button`,{className:`example-chip`,onClick:()=>e(t),children:[W.spark,(0,R.jsx)(`span`,{children:t})]},t))})]})}function Ho(e,t){let n=G(t);if(!n)return e;try{return K(e,t).map((e,t)=>n.test(e)?(0,R.jsx)(`mark`,{children:e},t):e)}catch{return e}}function Uo({result:e,query:t,onClick:n,selected:r,onMoreLikeThis:i}){let{metadata:a}=e,o=a.role??`ai`,s={user:`user`,thinking:`reasoning`,ai:`response`}[o]??o,c=zo(a.provider),l=$a(a.model),u=ao(a.createdAt),d=e.distance==null?``:(1-e.distance).toFixed(3),f=e.distance==null?0:Math.round((1-e.distance)*100),p=(0,L.useMemo)(()=>Ho(e.document,t),[e.document,t]),m=a.title?.trim()||Qa(a.sourceFile);return(0,R.jsxs)(`button`,{className:`result`,"data-selected":r,"aria-selected":r,onClick:n,children:[(0,R.jsxs)(`div`,{className:`result-head`,children:[(0,R.jsx)(`span`,{className:`r-role`,"data-role":o,children:s}),(0,R.jsxs)(`span`,{className:`r-provider`,children:[(0,R.jsx)(`span`,{className:`pdot`,style:{background:c.color}}),(0,R.jsx)(`span`,{children:c.short})]}),a.createdInThreadShelf&&(0,R.jsx)(`span`,{className:`threadshelf-turn-badge`,children:`ThreadShelf`}),e.distance!=null&&(0,R.jsx)(`div`,{className:`r-meta-right`,children:(0,R.jsxs)(`span`,{className:`r-score`,children:[(0,R.jsx)(`span`,{className:`r-score-bar`,children:(0,R.jsx)(`i`,{style:{width:`${f}%`}})}),(0,R.jsx)(`span`,{children:d})]})})]}),(0,R.jsx)(`div`,{className:`r-title`,title:m,children:m}),(0,R.jsx)(`div`,{className:`r-snippet`,children:p}),(0,R.jsxs)(`div`,{className:`r-foot`,children:[(0,R.jsxs)(`span`,{className:`r-source`,title:a.sourceFile,children:[W.folder,(0,R.jsx)(`span`,{className:`r-source-coll`,children:Za(a.collection??``)}),(0,R.jsx)(`span`,{className:`slash`,children:`/`}),(0,R.jsx)(`span`,{className:`r-source-file`,children:Qa(a.sourceFile)})]}),(0,R.jsx)(`span`,{className:`dot`}),l&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{className:`mono`,children:l}),(0,R.jsx)(`span`,{className:`dot`})]}),u&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{children:u}),(0,R.jsx)(`span`,{className:`dot`})]}),a.turnIndex!=null&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`span`,{children:[`turn `,(0,R.jsxs)(`b`,{className:`mono`,children:[`#`,a.turnIndex]})]}),(0,R.jsx)(`span`,{className:`dot`})]}),i&&(0,R.jsx)(`span`,{className:`more-like-this`,role:`button`,tabIndex:0,title:`Search for similar passages`,onClick:e=>{e.stopPropagation(),i()},onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),e.stopPropagation(),i())},children:`more like this`}),(0,R.jsxs)(`span`,{className:`open-thread`,children:[`open thread `,W.arrowRight]})]})]})}var Wo={search:`Archive`,insights:`Insights`,indexing:`Add data`,mcp:`MCP`,settings:`Settings`,chat:`Chat`};function Go({view:e,activeColl:t,onMenu:n,actions:r}){return(0,R.jsxs)(`div`,{className:`topbar`,children:[(0,R.jsx)(`button`,{className:`icon-btn mobile-menu-btn`,onClick:n,"aria-label":`Open sidebar`,children:W.menu}),(0,R.jsxs)(`div`,{className:`crumbs`,children:[(0,R.jsx)(`span`,{children:Wo[e]}),e===`search`&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{className:`sep`,children:`/`}),(0,R.jsx)(`b`,{children:Za(t)})]})]}),(0,R.jsx)(`div`,{className:`topbar-spacer`}),r&&(0,R.jsx)(`div`,{className:`topbar-actions`,children:r})]})}var Ko=100,qo=e=>{switch(e){case`recent`:return(e,t)=>(t.lastTurnAt??``).localeCompare(e.lastTurnAt??``);case`longest`:return(e,t)=>(t.turnCount??0)-(e.turnCount??0);case`title`:return(e,t)=>(e.title||e.sourceFile).localeCompare(t.title||t.sourceFile,void 0,{sensitivity:`base`})}},Jo=[{id:`user`,label:`User`,key:`user`},{id:`reasoning`,label:`Reasoning`,key:`thinking`},{id:`response`,label:`Response`,key:`ai`}];function Yo(){return(0,R.jsx)(`div`,{className:`result-list`,style:{marginTop:16},children:[0,1,2].map(e=>(0,R.jsx)(`div`,{className:`shimmer-card`},e))})}function Xo(){let e=Ni(),{collection:t}=ji({from:`/search/$collection`}),{q:n,model:r,from:i,to:a,mode:o}=Mi({from:`/search/$collection`}),s=t?decodeURIComponent(t):`all`,c=B(e=>e.setActiveColl);(0,L.useEffect)(()=>{c(s)},[s,c]);let l=B(e=>e.roles),u=B(e=>e.toggleRole),d=B(e=>e.modelFilter),f=B(e=>e.setModelFilter),p=B(e=>e.setSidebarOpen),m=B(e=>e.savedSearches),h=B(e=>e.addSavedSearch),g=B(e=>e.removeSavedSearch),_=B(e=>e.pinnedConversations),v=B(e=>e.togglePinned),[y,b]=(0,L.useState)(n??``),[x,S]=(0,L.useState)(n??``),[C,w]=(0,L.useState)(i??``),[T,E]=(0,L.useState)(a??``),[D,O]=(0,L.useState)(o===`keyword`?`keyword`:`semantic`),[ee,te]=(0,L.useState)(15),[k,ne]=(0,L.useState)(-1),[re,ie]=(0,L.useState)(``),[A,j]=(0,L.useState)(`recent`),[M,ae]=(0,L.useState)(Ko),[oe,se]=(0,L.useState)(`all`),N=(0,L.useRef)(n??``),P=(0,L.useRef)(null),F=(0,L.useRef)(null),{data:ce}=Ra(),le=ce??!0,ue=(0,L.useMemo)(()=>{let e=[];return l.user&&e.push(`user`),l.thinking&&e.push(`thinking`),l.ai&&e.push(`ai`),e.length>0&&e.length<3?e.join(`,`):void 0},[l]),{data:de,isFetching:fe}=Ua((0,L.useMemo)(()=>({q:x.trim(),collection:s,n:ee,roles:ue,keywordBoost:D===`semantic`&&x.trim().length<=40,model:(r??d).trim()||void 0,from:C.trim()||void 0,to:T.trim()||void 0,mode:D,origin:oe===`all`?void 0:oe}),[x,s,ee,ue,r,d,C,T,D,oe])),{data:pe,isLoading:me}=Va(s,!x.trim()&&le),he=(0,L.useMemo)(()=>{let e=pe?.files??[],t=re.trim().toLowerCase();return[...(t?e.filter(e=>[e.title,e.sourceFile,e.conversationKey,e.collection].some(e=>(e??``).toLowerCase().includes(t))):e).filter(e=>oe===`threadshelf`?e.createdInThreadShelf===!0||e.hasThreadShelfTurns===!0:oe!==`archive`||e.hasThreadShelfTurns!==!0)].sort(qo(A))},[pe?.files,re,A,oe]),I=(0,L.useMemo)(()=>he.slice(0,M),[he,M]);(0,L.useEffect)(()=>{let e=window.setTimeout(()=>ae(Ko),0);return()=>window.clearTimeout(e)},[s,re,A,oe]),(0,L.useEffect)(()=>{P.current?.focus()},[]),(0,L.useEffect)(()=>{let e=n??``;if(e!==N.current){let t=window.setTimeout(()=>{N.current=e,b(e),S(e),w(i??``),E(a??``),O(o===`keyword`?`keyword`:`semantic`)},0);return()=>window.clearTimeout(t)}},[n,i,a,o]),(0,L.useEffect)(()=>{let e=window.setTimeout(()=>{w(i??``),E(a??``)},0);return()=>window.clearTimeout(e)},[i,a]),(0,L.useEffect)(()=>{let e=window.setTimeout(()=>te(15),0);return()=>window.clearTimeout(e)},[x,s,ue,r,d,C,T,D,oe]);let ge=(0,L.useCallback)(t=>{let n=y.trim(),r=t??D;N.current=n,S(n),e({to:`/search/$collection`,params:{collection:s},search:n?{q:n,model:d.trim()||void 0,from:C.trim()||void 0,to:T.trim()||void 0,mode:r===`keyword`?`keyword`:void 0}:{},replace:!0})},[y,d,C,T,e,s,D]),_e=(0,L.useCallback)(()=>{N.current=``,b(``),S(``),P.current?.focus(),e({to:`/search/$collection`,params:{collection:s},search:{},replace:!0})},[e,s]),ve=(0,L.useCallback)(e=>{O(e),ge(e)},[ge]),ye=(0,L.useCallback)(t=>{e({to:`/thread`,search:{sourceFile:t.metadata.sourceFile,collection:t.metadata.collection??s,conversationKey:t.metadata.conversationKey,q:x.trim()||void 0,title:t.metadata.title,matchIdx:t.metadata.turnIndex,provider:t.metadata.provider,model:t.metadata.model}})},[s,x,e]),be=(0,L.useCallback)(t=>{let n=lo(t.document);n&&(O(`semantic`),N.current=n,b(n),S(n),e({to:`/search/$collection`,params:{collection:s},search:{q:n,model:d.trim()||void 0,from:C.trim()||void 0,to:T.trim()||void 0}}))},[s,d,C,T,e]),xe=(0,L.useCallback)(t=>{e({to:`/thread`,search:{sourceFile:t.sourceFile,collection:t.collection,conversationKey:t.conversationKey,title:t.title}})},[e]),Se=x.trim().length>0,Ce=(0,L.useMemo)(()=>({q:x.trim(),collection:s,mode:D,model:(r??d).trim()||void 0,from:C.trim()||void 0,to:T.trim()||void 0}),[x,s,D,r,d,C,T]),we=(0,L.useMemo)(()=>{let e=ka(Ce);return m.find(t=>ka(t)===e)},[m,Ce]),Te=(0,L.useCallback)(()=>{we?g(we.id):h(Ce)},[we,g,h,Ce]),Ee=(0,L.useCallback)(t=>{O(t.mode),N.current=t.q,b(t.q),S(t.q),e({to:`/search/$collection`,params:{collection:t.collection},search:{q:t.q,model:t.model,from:t.from,to:t.to,mode:t.mode===`keyword`?`keyword`:void 0}})},[e]),De=(0,L.useMemo)(()=>s===`all`?_:_.filter(e=>e.collection===s),[_,s]),Oe=(0,L.useMemo)(()=>new Set(_.map(e=>Aa(e))),[_]),ke=e=>({collection:e.collection,sourceFile:e.sourceFile,conversationKey:e.conversationKey,title:e.title,provider:e.provider}),Ae=(0,L.useMemo)(()=>de?.results??[],[de?.results]),je=Se&&!fe&&Ae.length>=ee&&ee<50,Me=s===`all`?`Conversations`:`${Za(s)} conversations`,Ne=Se?Ae.length:I.length,Pe=(0,L.useCallback)(e=>{if(Se){let t=Ae[e];t&&ye(t)}else{let t=I[e];t&&xe(t)}},[Se,Ae,I,ye,xe]);return(0,L.useEffect)(()=>{let e=window.setTimeout(()=>ne(-1),0);return()=>window.clearTimeout(e)},[x,s,Se]),(0,L.useEffect)(()=>{let e=e=>{let t=e.target,n=t.tagName?.toLowerCase(),r=t===P.current;if((n===`input`||n===`textarea`)&&!r||Ne===0)return;let i=e.key===`ArrowDown`||e.key===`j`&&!r,a=e.key===`ArrowUp`||e.key===`k`&&!r;i?(e.preventDefault(),r&&P.current?.blur(),ne(e=>Math.min(Ne-1,e+1))):a?(e.preventDefault(),ne(e=>e<=0?0:e-1)):e.key===`Enter`&&!r&&k>=0&&(e.preventDefault(),Pe(k))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[Ne,k,Pe]),(0,L.useEffect)(()=>{k<0||F.current?.querySelector(`[data-selected="true"]`)?.scrollIntoView({block:`nearest`})},[k]),(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(Go,{view:`search`,activeColl:s,onMenu:()=>p(!0)}),(0,R.jsx)(`div`,{className:`main-scroll`,children:(0,R.jsxs)(`div`,{className:`view`,children:[!le&&(0,R.jsxs)(`div`,{className:`banner err`,children:[(0,R.jsx)(`span`,{className:`ico`,children:W.warn}),(0,R.jsxs)(`div`,{className:`grow`,children:[(0,R.jsx)(`b`,{style:{fontWeight:500},children:`Backend unreachable.`}),` `,(0,R.jsxs)(`span`,{style:{color:`var(--text-2)`},children:[`Run `,(0,R.jsx)(`code`,{children:`npm start`}),` in the project root.`]})]})]}),(0,R.jsxs)(`div`,{className:`search-card`,children:[(0,R.jsx)(`span`,{className:`search-ico`,children:W.searchLg}),(0,R.jsx)(`input`,{id:`searchInput`,ref:P,value:y,onChange:e=>b(e.target.value),onKeyDown:e=>{e.key===`Enter`?ge():e.key===`Escape`&&y&&(e.preventDefault(),e.stopPropagation(),_e())},placeholder:D===`keyword`?`Exact match: identifiers, error strings, code…`:`Search by meaning across your archive…`}),y&&(0,R.jsx)(`button`,{id:`clearSearch`,type:`button`,className:`search-clear`,"aria-label":`Clear search`,title:`Clear search (Esc)`,onClick:_e,children:W.close})]}),(0,R.jsxs)(`div`,{className:`search-toolbar`,children:[(0,R.jsxs)(`div`,{className:`mode-toggle`,role:`group`,"aria-label":`Search mode`,children:[(0,R.jsx)(`button`,{type:`button`,className:`mode-btn`,"data-on":D===`semantic`,title:`Rank by meaning (local embeddings)`,onClick:()=>ve(`semantic`),children:`Semantic`}),(0,R.jsx)(`button`,{type:`button`,className:`mode-btn`,"data-on":D===`keyword`,title:`Exact substring match (case-insensitive)`,onClick:()=>ve(`keyword`),children:`Exact`})]}),(0,R.jsx)(`div`,{className:`role-chips`,children:Jo.map(e=>(0,R.jsxs)(`button`,{className:`role-chip`,"data-role":e.id,"data-on":l[e.key],onClick:()=>u(e.key),children:[(0,R.jsx)(`span`,{className:`dot`}),e.label]},e.id))}),(0,R.jsxs)(`label`,{className:`origin-filter`,children:[(0,R.jsx)(`span`,{children:`origin`}),(0,R.jsxs)(`select`,{"aria-label":`Filter by conversation origin`,value:oe,onChange:e=>se(e.target.value),children:[(0,R.jsx)(`option`,{value:`all`,children:`All`}),(0,R.jsx)(`option`,{value:`threadshelf`,children:`ThreadShelf`}),(0,R.jsx)(`option`,{value:`archive`,children:`Clean archive`})]})]}),(0,R.jsxs)(`label`,{className:`model-filter`,children:[(0,R.jsx)(`span`,{children:`model`}),(0,R.jsx)(`input`,{value:d,onChange:e=>f(e.target.value),onKeyDown:e=>e.key===`Enter`&&ge(),placeholder:`gpt-5, claude, gemini...`})]}),(0,R.jsxs)(`label`,{className:`date-filter`,children:[(0,R.jsx)(`span`,{children:`from`}),(0,R.jsx)(`input`,{type:`date`,value:C,onChange:e=>w(e.target.value),onKeyDown:e=>e.key===`Enter`&&ge()})]}),(0,R.jsxs)(`label`,{className:`date-filter`,children:[(0,R.jsx)(`span`,{children:`to`}),(0,R.jsx)(`input`,{type:`date`,value:T,onChange:e=>E(e.target.value),onKeyDown:e=>e.key===`Enter`&&ge()})]}),(0,R.jsx)(`span`,{className:`toolbar-spacer`}),(0,R.jsxs)(`span`,{className:`toolbar-hint`,children:[(0,R.jsx)(`kbd`,{children:`/`}),` focus · `,(0,R.jsx)(`kbd`,{children:`↑↓`}),` navigate · `,(0,R.jsx)(`kbd`,{children:`↵`}),` open · `,(0,R.jsx)(`kbd`,{children:`Ctrl+K`}),` `,`commands`]})]}),!Se&&(0,R.jsxs)(R.Fragment,{children:[s===`all`&&(0,R.jsx)(Vo,{onPick:t=>{N.current=t,b(t),S(t),e({to:`/search/$collection`,params:{collection:s},search:{q:t},replace:!0})}}),m.length>0&&(0,R.jsxs)(`div`,{className:`saved-searches`,children:[(0,R.jsxs)(`span`,{className:`ss-label`,children:[W.star,` Saved`]}),m.map(e=>(0,R.jsxs)(`span`,{className:`ss-chip`,children:[(0,R.jsxs)(`button`,{type:`button`,className:`ss-run`,title:`Run: ${e.q}`,onClick:()=>Ee(e),children:[(0,R.jsx)(`span`,{className:`ss-q`,children:e.q}),e.collection!==`all`&&(0,R.jsx)(`span`,{className:`ss-tag`,children:Za(e.collection)}),e.mode===`keyword`&&(0,R.jsx)(`span`,{className:`ss-tag`,children:`exact`})]}),(0,R.jsx)(`button`,{type:`button`,className:`ss-del`,"aria-label":`Delete saved search "${e.q}"`,onClick:()=>g(e.id),children:`×`})]},e.id))]}),De.length>0&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`div`,{className:`results-meta-bar`,children:(0,R.jsxs)(`span`,{className:`h`,children:[`Pinned `,(0,R.jsx)(`b`,{children:De.length})]})}),(0,R.jsx)(`div`,{className:`result-list`,children:De.map(e=>{let t=e.provider?zo(e.provider):null,n=Qa(e.sourceFile);return(0,R.jsxs)(`button`,{className:`result`,onClick:()=>xe(e),children:[(0,R.jsxs)(`div`,{className:`result-head`,children:[(0,R.jsx)(`span`,{className:`r-role`,"data-role":`user`,children:`pinned`}),(0,R.jsxs)(`span`,{className:`r-provider`,children:[(0,R.jsx)(`span`,{className:`pdot`,style:{background:t?.color??`var(--accent)`}}),(0,R.jsx)(`span`,{children:t?.short??Za(e.collection)})]}),(0,R.jsx)(`span`,{className:`pin-toggle`,role:`button`,tabIndex:0,"data-on":`true`,title:`Unpin`,onClick:t=>{t.stopPropagation(),v(e)},onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),t.stopPropagation(),v(e))},children:W.pinFilled})]}),(0,R.jsx)(`div`,{className:`r-title`,title:e.title||n,children:e.title||n}),(0,R.jsxs)(`div`,{className:`r-foot`,children:[(0,R.jsxs)(`span`,{className:`r-source`,title:e.sourceFile,children:[W.folder,(0,R.jsx)(`span`,{className:`r-source-coll`,children:Za(e.collection)}),(0,R.jsx)(`span`,{className:`slash`,children:`/`}),(0,R.jsx)(`span`,{className:`r-source-file`,children:n})]}),(0,R.jsxs)(`span`,{className:`open-thread`,children:[`open thread `,W.arrowRight]})]})]},Aa(e))})})]}),(0,R.jsxs)(`div`,{className:`results-meta-bar`,children:[(0,R.jsxs)(`span`,{className:`h`,children:[Me,` `,(0,R.jsx)(`b`,{children:he.length})]}),(0,R.jsxs)(`label`,{className:`conv-sort`,children:[(0,R.jsx)(`span`,{children:`sort`}),(0,R.jsxs)(`select`,{value:A,onChange:e=>j(e.target.value),"aria-label":`Sort conversations`,children:[(0,R.jsx)(`option`,{value:`recent`,children:`Recent`}),(0,R.jsx)(`option`,{value:`longest`,children:`Longest`}),(0,R.jsx)(`option`,{value:`title`,children:`Title`})]})]}),(0,R.jsx)(`input`,{className:`conv-filter`,value:re,onChange:e=>ie(e.target.value),placeholder:`Filter by title or file…`,"aria-label":`Filter conversations`})]}),me?(0,R.jsx)(Yo,{}):he.length>0?(0,R.jsxs)(`div`,{className:`result-list`,ref:F,children:[I.map((e,t)=>{let n=Qa(e.sourceFile),r=e.title||n,i=e.provider?zo(e.provider):null,a=ao(e.lastTurnAt),o=ke(e),s=Oe.has(Aa(o));return(0,R.jsxs)(`button`,{className:`result`,"data-selected":t===k,"aria-selected":t===k,onClick:()=>xe(e),children:[(0,R.jsxs)(`div`,{className:`result-head`,children:[(0,R.jsx)(`span`,{className:`r-role`,"data-role":`ai`,children:`thread`}),e.hasThreadShelfTurns&&(0,R.jsx)(`span`,{className:`threadshelf-turn-badge`,children:e.createdInThreadShelf?`Created in ThreadShelf`:`Continued in ThreadShelf`}),(0,R.jsxs)(`span`,{className:`r-provider`,children:[(0,R.jsx)(`span`,{className:`pdot`,style:{background:i?.color??`var(--accent)`}}),(0,R.jsx)(`span`,{children:i?.short??Za(e.collection)})]}),(0,R.jsx)(`span`,{className:`pin-toggle`,role:`button`,tabIndex:0,"data-on":s,title:s?`Unpin`:`Pin conversation`,onClick:e=>{e.stopPropagation(),v(o)},onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),e.stopPropagation(),v(o))},children:s?W.pinFilled:W.pin})]}),(0,R.jsx)(`div`,{className:`r-title`,title:r,children:r}),(0,R.jsxs)(`div`,{className:`r-foot`,children:[(0,R.jsxs)(`span`,{className:`r-source`,title:e.sourceFile,children:[W.folder,(0,R.jsx)(`span`,{className:`r-source-coll`,children:Za(e.collection)}),(0,R.jsx)(`span`,{className:`slash`,children:`/`}),(0,R.jsx)(`span`,{className:`r-source-file`,children:n})]}),e.turnCount!=null&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{className:`dot`}),(0,R.jsxs)(`span`,{children:[e.turnCount,` turns`]})]}),a&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{className:`dot`}),(0,R.jsx)(`span`,{children:a})]}),(0,R.jsxs)(`span`,{className:`open-thread`,children:[`open thread `,W.arrowRight]})]})]},`${e.collection}:${e.sourceFile}:${t}`)}),he.length>M&&(0,R.jsx)(`div`,{className:`load-more-row`,children:(0,R.jsxs)(`button`,{type:`button`,className:`load-more-button`,onClick:()=>ae(e=>e+Ko),children:[`Show more (`,he.length-M,` left)`]})})]}):re.trim()?(0,R.jsxs)(`div`,{className:`empty`,children:[(0,R.jsx)(`h3`,{children:`No conversations match the filter.`}),(0,R.jsx)(`p`,{children:`Try a different phrase or clear the filter box.`})]}):s===`all`?null:(0,R.jsxs)(`div`,{className:`empty`,children:[(0,R.jsx)(`h3`,{children:`No conversations indexed.`}),(0,R.jsx)(`p`,{children:`Index a folder into this collection or switch to another collection.`})]})]}),Se&&fe&&(0,R.jsx)(Yo,{}),Se&&!fe&&Ae.length===0&&(0,R.jsxs)(`div`,{className:`empty`,children:[(0,R.jsx)(`h3`,{children:`No results found.`}),(0,R.jsx)(`p`,{children:`Try another query, broaden your role filters, or index more files.`})]}),Se&&!fe&&Ae.length>0&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`div`,{className:`results-meta-bar`,children:[(0,R.jsxs)(`span`,{className:`h`,children:[`Results `,(0,R.jsx)(`b`,{children:Ae.length}),(0,R.jsxs)(`span`,{style:{marginLeft:14,color:`var(--text-3)`},children:[`in `,Za(s)]})]}),(0,R.jsxs)(`button`,{type:`button`,className:`save-search`,"data-on":!!we,title:we?`Remove from saved searches`:`Save this search`,onClick:Te,children:[we?W.starFilled:W.star,(0,R.jsx)(`span`,{children:we?`Saved`:`Save search`})]})]}),(0,R.jsx)(`div`,{className:`result-list`,ref:F,children:Ae.map((e,t)=>(0,R.jsx)(Uo,{result:e,query:x,selected:t===k,onClick:()=>ye(e),onMoreLikeThis:()=>be(e)},t))}),je&&(0,R.jsx)(`div`,{className:`load-more-row`,children:(0,R.jsx)(`button`,{type:`button`,className:`load-more-button`,onClick:()=>te(e=>Math.min(e+15,50)),children:`Load more`})})]})]})})]})}var Zo=/^(\s*)([-*+]|\d+[.)])\s+(.*)$/,Qo=/^\s*\d+[.)]\s+/,$o=e=>{let t=e.trim();return/^(?:https?:\/\/|mailto:|#|\/)/i.test(t)?t:null},es=e=>{let t=[],n=``,r=()=>{n&&=(t.push({type:`text`,value:n}),``)},i=0;for(;i<e.length;){let a=e[i];if(a==="`"){let n=e.indexOf("`",i+1);if(n>i){r(),t.push({type:`code`,value:e.slice(i+1,n)}),i=n+1;continue}}if(a===`[`){let n=e.indexOf(`]`,i+1);if(n>i&&e[n+1]===`(`){let a=e.indexOf(`)`,n+2);if(a>n){let o=$o(e.slice(n+2,a));if(o){r(),t.push({type:`link`,href:o,children:es(e.slice(i+1,n))}),i=a+1;continue}}}}if(a===`*`&&e[i+1]===`*`||a===`_`&&e[i+1]===`_`){let n=e.slice(i,i+2),a=e.indexOf(n,i+2);if(a>i+1){r(),t.push({type:`strong`,children:es(e.slice(i+2,a))}),i=a+2;continue}}if(a===`*`){let n=e.indexOf(`*`,i+1);if(n>i+1){r(),t.push({type:`em`,children:es(e.slice(i+1,n))}),i=n+1;continue}}n+=a,i+=1}return r(),t},ts=e=>{let t=e.replace(/\r\n?/g,`
|
|
18
18
|
`).split(`
|
|
19
19
|
`),n=[],r=0;for(;r<t.length;){let e=t[r];if(!e.trim()){r+=1;continue}let i=/^```(\w+)?\s*$/.exec(e);if(i){let e=[];for(r+=1;r<t.length&&!/^```\s*$/.test(t[r]);)e.push(t[r]),r+=1;r+=1,n.push({type:`code`,value:e.join(`
|
|
20
20
|
`),lang:i[1]});continue}let a=/^(#{1,6})\s+(.*)$/.exec(e);if(a){n.push({type:`heading`,level:a[1].length,children:es(a[2].trim())}),r+=1;continue}if(/^>\s?/.test(e)){let e=[];for(;r<t.length&&/^>\s?/.test(t[r]);)e.push(t[r].replace(/^>\s?/,``)),r+=1;n.push({type:`quote`,children:es(e.join(`
|
package/public/index.html
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
name="description"
|
|
10
10
|
content="Local-first semantic search and backup tool for AI chat exports (Google AI Studio, OpenRouter, LM Studio, ChatGPT, Claude)."
|
|
11
11
|
/>
|
|
12
|
-
<script type="module" crossorigin src="/assets/index-
|
|
12
|
+
<script type="module" crossorigin src="/assets/index-TIPW3iTR.js"></script>
|
|
13
13
|
<link rel="stylesheet" crossorigin href="/assets/index-Dv09K2vS.css">
|
|
14
14
|
</head>
|
|
15
15
|
<body>
|