chat-logbook 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/dist/index.js +861 -765
- package/package.json +1 -1
- package/web/dist/assets/index-BJlGZyK5.js +57 -0
- package/web/dist/index.html +1 -1
- package/web/dist/assets/index-DHnNZHtV.js +0 -57
package/api/dist/index.js
CHANGED
|
@@ -5,11 +5,11 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// src/index.ts
|
|
8
|
-
import
|
|
8
|
+
import fs6 from "fs";
|
|
9
9
|
import os from "os";
|
|
10
|
-
import
|
|
10
|
+
import path4 from "path";
|
|
11
11
|
import { exec } from "child_process";
|
|
12
|
-
import { fileURLToPath as
|
|
12
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
13
13
|
|
|
14
14
|
// ../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.9/node_modules/@hono/node-server/dist/index.mjs
|
|
15
15
|
import { createServer as createServerHTTP } from "http";
|
|
@@ -705,26 +705,26 @@ var handleParsingNestedValues = (form, key, value) => {
|
|
|
705
705
|
};
|
|
706
706
|
|
|
707
707
|
// ../node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/utils/url.js
|
|
708
|
-
var splitPath = (
|
|
709
|
-
const paths =
|
|
708
|
+
var splitPath = (path5) => {
|
|
709
|
+
const paths = path5.split("/");
|
|
710
710
|
if (paths[0] === "") {
|
|
711
711
|
paths.shift();
|
|
712
712
|
}
|
|
713
713
|
return paths;
|
|
714
714
|
};
|
|
715
715
|
var splitRoutingPath = (routePath) => {
|
|
716
|
-
const { groups, path:
|
|
717
|
-
const paths = splitPath(
|
|
716
|
+
const { groups, path: path5 } = extractGroupsFromPath(routePath);
|
|
717
|
+
const paths = splitPath(path5);
|
|
718
718
|
return replaceGroupMarks(paths, groups);
|
|
719
719
|
};
|
|
720
|
-
var extractGroupsFromPath = (
|
|
720
|
+
var extractGroupsFromPath = (path5) => {
|
|
721
721
|
const groups = [];
|
|
722
|
-
|
|
722
|
+
path5 = path5.replace(/\{[^}]+\}/g, (match2, index) => {
|
|
723
723
|
const mark = `@${index}`;
|
|
724
724
|
groups.push([mark, match2]);
|
|
725
725
|
return mark;
|
|
726
726
|
});
|
|
727
|
-
return { groups, path:
|
|
727
|
+
return { groups, path: path5 };
|
|
728
728
|
};
|
|
729
729
|
var replaceGroupMarks = (paths, groups) => {
|
|
730
730
|
for (let i = groups.length - 1; i >= 0; i--) {
|
|
@@ -781,8 +781,8 @@ var getPath = (request) => {
|
|
|
781
781
|
const queryIndex = url.indexOf("?", i);
|
|
782
782
|
const hashIndex = url.indexOf("#", i);
|
|
783
783
|
const end = queryIndex === -1 ? hashIndex === -1 ? void 0 : hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);
|
|
784
|
-
const
|
|
785
|
-
return tryDecodeURI(
|
|
784
|
+
const path5 = url.slice(start, end);
|
|
785
|
+
return tryDecodeURI(path5.includes("%25") ? path5.replace(/%25/g, "%2525") : path5);
|
|
786
786
|
} else if (charCode === 63 || charCode === 35) {
|
|
787
787
|
break;
|
|
788
788
|
}
|
|
@@ -799,11 +799,11 @@ var mergePath = (base, sub, ...rest) => {
|
|
|
799
799
|
}
|
|
800
800
|
return `${base?.[0] === "/" ? "" : "/"}${base}${sub === "/" ? "" : `${base?.at(-1) === "/" ? "" : "/"}${sub?.[0] === "/" ? sub.slice(1) : sub}`}`;
|
|
801
801
|
};
|
|
802
|
-
var checkOptionalParameter = (
|
|
803
|
-
if (
|
|
802
|
+
var checkOptionalParameter = (path5) => {
|
|
803
|
+
if (path5.charCodeAt(path5.length - 1) !== 63 || !path5.includes(":")) {
|
|
804
804
|
return null;
|
|
805
805
|
}
|
|
806
|
-
const segments =
|
|
806
|
+
const segments = path5.split("/");
|
|
807
807
|
const results = [];
|
|
808
808
|
let basePath = "";
|
|
809
809
|
segments.forEach((segment) => {
|
|
@@ -944,9 +944,9 @@ var HonoRequest = class {
|
|
|
944
944
|
*/
|
|
945
945
|
path;
|
|
946
946
|
bodyCache = {};
|
|
947
|
-
constructor(request,
|
|
947
|
+
constructor(request, path5 = "/", matchResult = [[]]) {
|
|
948
948
|
this.raw = request;
|
|
949
|
-
this.path =
|
|
949
|
+
this.path = path5;
|
|
950
950
|
this.#matchResult = matchResult;
|
|
951
951
|
this.#validatedData = {};
|
|
952
952
|
}
|
|
@@ -1683,8 +1683,8 @@ var Hono = class _Hono {
|
|
|
1683
1683
|
return this;
|
|
1684
1684
|
};
|
|
1685
1685
|
});
|
|
1686
|
-
this.on = (method,
|
|
1687
|
-
for (const p of [
|
|
1686
|
+
this.on = (method, path5, ...handlers) => {
|
|
1687
|
+
for (const p of [path5].flat()) {
|
|
1688
1688
|
this.#path = p;
|
|
1689
1689
|
for (const m of [method].flat()) {
|
|
1690
1690
|
handlers.map((handler) => {
|
|
@@ -1741,8 +1741,8 @@ var Hono = class _Hono {
|
|
|
1741
1741
|
* app.route("/api", app2) // GET /api/user
|
|
1742
1742
|
* ```
|
|
1743
1743
|
*/
|
|
1744
|
-
route(
|
|
1745
|
-
const subApp = this.basePath(
|
|
1744
|
+
route(path5, app2) {
|
|
1745
|
+
const subApp = this.basePath(path5);
|
|
1746
1746
|
app2.routes.map((r) => {
|
|
1747
1747
|
let handler;
|
|
1748
1748
|
if (app2.errorHandler === errorHandler) {
|
|
@@ -1768,9 +1768,9 @@ var Hono = class _Hono {
|
|
|
1768
1768
|
* const api = new Hono().basePath('/api')
|
|
1769
1769
|
* ```
|
|
1770
1770
|
*/
|
|
1771
|
-
basePath(
|
|
1771
|
+
basePath(path5) {
|
|
1772
1772
|
const subApp = this.#clone();
|
|
1773
|
-
subApp._basePath = mergePath(this._basePath,
|
|
1773
|
+
subApp._basePath = mergePath(this._basePath, path5);
|
|
1774
1774
|
return subApp;
|
|
1775
1775
|
}
|
|
1776
1776
|
/**
|
|
@@ -1844,7 +1844,7 @@ var Hono = class _Hono {
|
|
|
1844
1844
|
* })
|
|
1845
1845
|
* ```
|
|
1846
1846
|
*/
|
|
1847
|
-
mount(
|
|
1847
|
+
mount(path5, applicationHandler, options) {
|
|
1848
1848
|
let replaceRequest;
|
|
1849
1849
|
let optionHandler;
|
|
1850
1850
|
if (options) {
|
|
@@ -1871,7 +1871,7 @@ var Hono = class _Hono {
|
|
|
1871
1871
|
return [c.env, executionContext];
|
|
1872
1872
|
};
|
|
1873
1873
|
replaceRequest ||= (() => {
|
|
1874
|
-
const mergedPath = mergePath(this._basePath,
|
|
1874
|
+
const mergedPath = mergePath(this._basePath, path5);
|
|
1875
1875
|
const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
|
|
1876
1876
|
return (request) => {
|
|
1877
1877
|
const url = new URL(request.url);
|
|
@@ -1886,14 +1886,14 @@ var Hono = class _Hono {
|
|
|
1886
1886
|
}
|
|
1887
1887
|
await next();
|
|
1888
1888
|
};
|
|
1889
|
-
this.#addRoute(METHOD_NAME_ALL, mergePath(
|
|
1889
|
+
this.#addRoute(METHOD_NAME_ALL, mergePath(path5, "*"), handler);
|
|
1890
1890
|
return this;
|
|
1891
1891
|
}
|
|
1892
|
-
#addRoute(method,
|
|
1892
|
+
#addRoute(method, path5, handler) {
|
|
1893
1893
|
method = method.toUpperCase();
|
|
1894
|
-
|
|
1895
|
-
const r = { basePath: this._basePath, path:
|
|
1896
|
-
this.router.add(method,
|
|
1894
|
+
path5 = mergePath(this._basePath, path5);
|
|
1895
|
+
const r = { basePath: this._basePath, path: path5, method, handler };
|
|
1896
|
+
this.router.add(method, path5, [handler, r]);
|
|
1897
1897
|
this.routes.push(r);
|
|
1898
1898
|
}
|
|
1899
1899
|
#handleError(err, c) {
|
|
@@ -1906,10 +1906,10 @@ var Hono = class _Hono {
|
|
|
1906
1906
|
if (method === "HEAD") {
|
|
1907
1907
|
return (async () => new Response(null, await this.#dispatch(request, executionCtx, env, "GET")))();
|
|
1908
1908
|
}
|
|
1909
|
-
const
|
|
1910
|
-
const matchResult = this.router.match(method,
|
|
1909
|
+
const path5 = this.getPath(request, { env });
|
|
1910
|
+
const matchResult = this.router.match(method, path5);
|
|
1911
1911
|
const c = new Context(request, {
|
|
1912
|
-
path:
|
|
1912
|
+
path: path5,
|
|
1913
1913
|
matchResult,
|
|
1914
1914
|
env,
|
|
1915
1915
|
executionCtx,
|
|
@@ -2009,7 +2009,7 @@ var Hono = class _Hono {
|
|
|
2009
2009
|
|
|
2010
2010
|
// ../node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/router/reg-exp-router/matcher.js
|
|
2011
2011
|
var emptyParam = [];
|
|
2012
|
-
function match(method,
|
|
2012
|
+
function match(method, path5) {
|
|
2013
2013
|
const matchers = this.buildAllMatchers();
|
|
2014
2014
|
const match2 = ((method2, path22) => {
|
|
2015
2015
|
const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
|
|
@@ -2025,7 +2025,7 @@ function match(method, path6) {
|
|
|
2025
2025
|
return [matcher[1][index], match3];
|
|
2026
2026
|
});
|
|
2027
2027
|
this.match = match2;
|
|
2028
|
-
return match2(method,
|
|
2028
|
+
return match2(method, path5);
|
|
2029
2029
|
}
|
|
2030
2030
|
|
|
2031
2031
|
// ../node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/router/reg-exp-router/node.js
|
|
@@ -2140,12 +2140,12 @@ var Node = class _Node {
|
|
|
2140
2140
|
var Trie = class {
|
|
2141
2141
|
#context = { varIndex: 0 };
|
|
2142
2142
|
#root = new Node();
|
|
2143
|
-
insert(
|
|
2143
|
+
insert(path5, index, pathErrorCheckOnly) {
|
|
2144
2144
|
const paramAssoc = [];
|
|
2145
2145
|
const groups = [];
|
|
2146
2146
|
for (let i = 0; ; ) {
|
|
2147
2147
|
let replaced = false;
|
|
2148
|
-
|
|
2148
|
+
path5 = path5.replace(/\{[^}]+\}/g, (m) => {
|
|
2149
2149
|
const mark = `@\\${i}`;
|
|
2150
2150
|
groups[i] = [mark, m];
|
|
2151
2151
|
i++;
|
|
@@ -2156,7 +2156,7 @@ var Trie = class {
|
|
|
2156
2156
|
break;
|
|
2157
2157
|
}
|
|
2158
2158
|
}
|
|
2159
|
-
const tokens =
|
|
2159
|
+
const tokens = path5.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
|
|
2160
2160
|
for (let i = groups.length - 1; i >= 0; i--) {
|
|
2161
2161
|
const [mark] = groups[i];
|
|
2162
2162
|
for (let j = tokens.length - 1; j >= 0; j--) {
|
|
@@ -2195,9 +2195,9 @@ var Trie = class {
|
|
|
2195
2195
|
// ../node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/router/reg-exp-router/router.js
|
|
2196
2196
|
var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
|
|
2197
2197
|
var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
|
|
2198
|
-
function buildWildcardRegExp(
|
|
2199
|
-
return wildcardRegExpCache[
|
|
2200
|
-
|
|
2198
|
+
function buildWildcardRegExp(path5) {
|
|
2199
|
+
return wildcardRegExpCache[path5] ??= new RegExp(
|
|
2200
|
+
path5 === "*" ? "" : `^${path5.replace(
|
|
2201
2201
|
/\/\*$|([.\\+*[^\]$()])/g,
|
|
2202
2202
|
(_, metaChar) => metaChar ? `\\${metaChar}` : "(?:|/.*)"
|
|
2203
2203
|
)}$`
|
|
@@ -2219,17 +2219,17 @@ function buildMatcherFromPreprocessedRoutes(routes) {
|
|
|
2219
2219
|
);
|
|
2220
2220
|
const staticMap = /* @__PURE__ */ Object.create(null);
|
|
2221
2221
|
for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
|
|
2222
|
-
const [pathErrorCheckOnly,
|
|
2222
|
+
const [pathErrorCheckOnly, path5, handlers] = routesWithStaticPathFlag[i];
|
|
2223
2223
|
if (pathErrorCheckOnly) {
|
|
2224
|
-
staticMap[
|
|
2224
|
+
staticMap[path5] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
|
|
2225
2225
|
} else {
|
|
2226
2226
|
j++;
|
|
2227
2227
|
}
|
|
2228
2228
|
let paramAssoc;
|
|
2229
2229
|
try {
|
|
2230
|
-
paramAssoc = trie.insert(
|
|
2230
|
+
paramAssoc = trie.insert(path5, j, pathErrorCheckOnly);
|
|
2231
2231
|
} catch (e) {
|
|
2232
|
-
throw e === PATH_ERROR ? new UnsupportedPathError(
|
|
2232
|
+
throw e === PATH_ERROR ? new UnsupportedPathError(path5) : e;
|
|
2233
2233
|
}
|
|
2234
2234
|
if (pathErrorCheckOnly) {
|
|
2235
2235
|
continue;
|
|
@@ -2263,12 +2263,12 @@ function buildMatcherFromPreprocessedRoutes(routes) {
|
|
|
2263
2263
|
}
|
|
2264
2264
|
return [regexp, handlerMap, staticMap];
|
|
2265
2265
|
}
|
|
2266
|
-
function findMiddleware(middleware,
|
|
2266
|
+
function findMiddleware(middleware, path5) {
|
|
2267
2267
|
if (!middleware) {
|
|
2268
2268
|
return void 0;
|
|
2269
2269
|
}
|
|
2270
2270
|
for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) {
|
|
2271
|
-
if (buildWildcardRegExp(k).test(
|
|
2271
|
+
if (buildWildcardRegExp(k).test(path5)) {
|
|
2272
2272
|
return [...middleware[k]];
|
|
2273
2273
|
}
|
|
2274
2274
|
}
|
|
@@ -2282,7 +2282,7 @@ var RegExpRouter = class {
|
|
|
2282
2282
|
this.#middleware = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
|
|
2283
2283
|
this.#routes = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
|
|
2284
2284
|
}
|
|
2285
|
-
add(method,
|
|
2285
|
+
add(method, path5, handler) {
|
|
2286
2286
|
const middleware = this.#middleware;
|
|
2287
2287
|
const routes = this.#routes;
|
|
2288
2288
|
if (!middleware || !routes) {
|
|
@@ -2297,18 +2297,18 @@ var RegExpRouter = class {
|
|
|
2297
2297
|
});
|
|
2298
2298
|
});
|
|
2299
2299
|
}
|
|
2300
|
-
if (
|
|
2301
|
-
|
|
2300
|
+
if (path5 === "/*") {
|
|
2301
|
+
path5 = "*";
|
|
2302
2302
|
}
|
|
2303
|
-
const paramCount = (
|
|
2304
|
-
if (/\*$/.test(
|
|
2305
|
-
const re = buildWildcardRegExp(
|
|
2303
|
+
const paramCount = (path5.match(/\/:/g) || []).length;
|
|
2304
|
+
if (/\*$/.test(path5)) {
|
|
2305
|
+
const re = buildWildcardRegExp(path5);
|
|
2306
2306
|
if (method === METHOD_NAME_ALL) {
|
|
2307
2307
|
Object.keys(middleware).forEach((m) => {
|
|
2308
|
-
middleware[m][
|
|
2308
|
+
middleware[m][path5] ||= findMiddleware(middleware[m], path5) || findMiddleware(middleware[METHOD_NAME_ALL], path5) || [];
|
|
2309
2309
|
});
|
|
2310
2310
|
} else {
|
|
2311
|
-
middleware[method][
|
|
2311
|
+
middleware[method][path5] ||= findMiddleware(middleware[method], path5) || findMiddleware(middleware[METHOD_NAME_ALL], path5) || [];
|
|
2312
2312
|
}
|
|
2313
2313
|
Object.keys(middleware).forEach((m) => {
|
|
2314
2314
|
if (method === METHOD_NAME_ALL || method === m) {
|
|
@@ -2326,7 +2326,7 @@ var RegExpRouter = class {
|
|
|
2326
2326
|
});
|
|
2327
2327
|
return;
|
|
2328
2328
|
}
|
|
2329
|
-
const paths = checkOptionalParameter(
|
|
2329
|
+
const paths = checkOptionalParameter(path5) || [path5];
|
|
2330
2330
|
for (let i = 0, len = paths.length; i < len; i++) {
|
|
2331
2331
|
const path22 = paths[i];
|
|
2332
2332
|
Object.keys(routes).forEach((m) => {
|
|
@@ -2353,13 +2353,13 @@ var RegExpRouter = class {
|
|
|
2353
2353
|
const routes = [];
|
|
2354
2354
|
let hasOwnRoute = method === METHOD_NAME_ALL;
|
|
2355
2355
|
[this.#middleware, this.#routes].forEach((r) => {
|
|
2356
|
-
const ownRoute = r[method] ? Object.keys(r[method]).map((
|
|
2356
|
+
const ownRoute = r[method] ? Object.keys(r[method]).map((path5) => [path5, r[method][path5]]) : [];
|
|
2357
2357
|
if (ownRoute.length !== 0) {
|
|
2358
2358
|
hasOwnRoute ||= true;
|
|
2359
2359
|
routes.push(...ownRoute);
|
|
2360
2360
|
} else if (method !== METHOD_NAME_ALL) {
|
|
2361
2361
|
routes.push(
|
|
2362
|
-
...Object.keys(r[METHOD_NAME_ALL]).map((
|
|
2362
|
+
...Object.keys(r[METHOD_NAME_ALL]).map((path5) => [path5, r[METHOD_NAME_ALL][path5]])
|
|
2363
2363
|
);
|
|
2364
2364
|
}
|
|
2365
2365
|
});
|
|
@@ -2379,13 +2379,13 @@ var SmartRouter = class {
|
|
|
2379
2379
|
constructor(init) {
|
|
2380
2380
|
this.#routers = init.routers;
|
|
2381
2381
|
}
|
|
2382
|
-
add(method,
|
|
2382
|
+
add(method, path5, handler) {
|
|
2383
2383
|
if (!this.#routes) {
|
|
2384
2384
|
throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
|
|
2385
2385
|
}
|
|
2386
|
-
this.#routes.push([method,
|
|
2386
|
+
this.#routes.push([method, path5, handler]);
|
|
2387
2387
|
}
|
|
2388
|
-
match(method,
|
|
2388
|
+
match(method, path5) {
|
|
2389
2389
|
if (!this.#routes) {
|
|
2390
2390
|
throw new Error("Fatal error");
|
|
2391
2391
|
}
|
|
@@ -2400,7 +2400,7 @@ var SmartRouter = class {
|
|
|
2400
2400
|
for (let i2 = 0, len2 = routes.length; i2 < len2; i2++) {
|
|
2401
2401
|
router.add(...routes[i2]);
|
|
2402
2402
|
}
|
|
2403
|
-
res = router.match(method,
|
|
2403
|
+
res = router.match(method, path5);
|
|
2404
2404
|
} catch (e) {
|
|
2405
2405
|
if (e instanceof UnsupportedPathError) {
|
|
2406
2406
|
continue;
|
|
@@ -2450,10 +2450,10 @@ var Node2 = class _Node2 {
|
|
|
2450
2450
|
}
|
|
2451
2451
|
this.#patterns = [];
|
|
2452
2452
|
}
|
|
2453
|
-
insert(method,
|
|
2453
|
+
insert(method, path5, handler) {
|
|
2454
2454
|
this.#order = ++this.#order;
|
|
2455
2455
|
let curNode = this;
|
|
2456
|
-
const parts = splitRoutingPath(
|
|
2456
|
+
const parts = splitRoutingPath(path5);
|
|
2457
2457
|
const possibleKeys = [];
|
|
2458
2458
|
for (let i = 0, len = parts.length; i < len; i++) {
|
|
2459
2459
|
const p = parts[i];
|
|
@@ -2502,12 +2502,12 @@ var Node2 = class _Node2 {
|
|
|
2502
2502
|
}
|
|
2503
2503
|
}
|
|
2504
2504
|
}
|
|
2505
|
-
search(method,
|
|
2505
|
+
search(method, path5) {
|
|
2506
2506
|
const handlerSets = [];
|
|
2507
2507
|
this.#params = emptyParams;
|
|
2508
2508
|
const curNode = this;
|
|
2509
2509
|
let curNodes = [curNode];
|
|
2510
|
-
const parts = splitPath(
|
|
2510
|
+
const parts = splitPath(path5);
|
|
2511
2511
|
const curNodesQueue = [];
|
|
2512
2512
|
const len = parts.length;
|
|
2513
2513
|
let partOffsets = null;
|
|
@@ -2549,13 +2549,13 @@ var Node2 = class _Node2 {
|
|
|
2549
2549
|
if (matcher instanceof RegExp) {
|
|
2550
2550
|
if (partOffsets === null) {
|
|
2551
2551
|
partOffsets = new Array(len);
|
|
2552
|
-
let offset =
|
|
2552
|
+
let offset = path5[0] === "/" ? 1 : 0;
|
|
2553
2553
|
for (let p = 0; p < len; p++) {
|
|
2554
2554
|
partOffsets[p] = offset;
|
|
2555
2555
|
offset += parts[p].length + 1;
|
|
2556
2556
|
}
|
|
2557
2557
|
}
|
|
2558
|
-
const restPathString =
|
|
2558
|
+
const restPathString = path5.substring(partOffsets[i]);
|
|
2559
2559
|
const m = matcher.exec(restPathString);
|
|
2560
2560
|
if (m) {
|
|
2561
2561
|
params[name] = m[0];
|
|
@@ -2608,18 +2608,18 @@ var TrieRouter = class {
|
|
|
2608
2608
|
constructor() {
|
|
2609
2609
|
this.#node = new Node2();
|
|
2610
2610
|
}
|
|
2611
|
-
add(method,
|
|
2612
|
-
const results = checkOptionalParameter(
|
|
2611
|
+
add(method, path5, handler) {
|
|
2612
|
+
const results = checkOptionalParameter(path5);
|
|
2613
2613
|
if (results) {
|
|
2614
2614
|
for (let i = 0, len = results.length; i < len; i++) {
|
|
2615
2615
|
this.#node.insert(method, results[i], handler);
|
|
2616
2616
|
}
|
|
2617
2617
|
return;
|
|
2618
2618
|
}
|
|
2619
|
-
this.#node.insert(method,
|
|
2619
|
+
this.#node.insert(method, path5, handler);
|
|
2620
2620
|
}
|
|
2621
|
-
match(method,
|
|
2622
|
-
return this.#node.search(method,
|
|
2621
|
+
match(method, path5) {
|
|
2622
|
+
return this.#node.search(method, path5);
|
|
2623
2623
|
}
|
|
2624
2624
|
};
|
|
2625
2625
|
|
|
@@ -2750,10 +2750,10 @@ var createStreamBody = (stream) => {
|
|
|
2750
2750
|
});
|
|
2751
2751
|
return body;
|
|
2752
2752
|
};
|
|
2753
|
-
var getStats = (
|
|
2753
|
+
var getStats = (path5) => {
|
|
2754
2754
|
let stats;
|
|
2755
2755
|
try {
|
|
2756
|
-
stats = statSync(
|
|
2756
|
+
stats = statSync(path5);
|
|
2757
2757
|
} catch {
|
|
2758
2758
|
}
|
|
2759
2759
|
return stats;
|
|
@@ -2796,21 +2796,21 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
2796
2796
|
return next();
|
|
2797
2797
|
}
|
|
2798
2798
|
}
|
|
2799
|
-
let
|
|
2799
|
+
let path5 = join(
|
|
2800
2800
|
root,
|
|
2801
2801
|
!optionPath && options.rewriteRequestPath ? options.rewriteRequestPath(filename, c) : filename
|
|
2802
2802
|
);
|
|
2803
|
-
let stats = getStats(
|
|
2803
|
+
let stats = getStats(path5);
|
|
2804
2804
|
if (stats && stats.isDirectory()) {
|
|
2805
2805
|
const indexFile = options.index ?? "index.html";
|
|
2806
|
-
|
|
2807
|
-
stats = getStats(
|
|
2806
|
+
path5 = join(path5, indexFile);
|
|
2807
|
+
stats = getStats(path5);
|
|
2808
2808
|
}
|
|
2809
2809
|
if (!stats) {
|
|
2810
|
-
await options.onNotFound?.(
|
|
2810
|
+
await options.onNotFound?.(path5, c);
|
|
2811
2811
|
return next();
|
|
2812
2812
|
}
|
|
2813
|
-
const mimeType = getMimeType(
|
|
2813
|
+
const mimeType = getMimeType(path5);
|
|
2814
2814
|
c.header("Content-Type", mimeType || "application/octet-stream");
|
|
2815
2815
|
if (options.precompressed && (!mimeType || COMPRESSIBLE_CONTENT_TYPE_REGEX.test(mimeType))) {
|
|
2816
2816
|
const acceptEncodingSet = new Set(
|
|
@@ -2820,12 +2820,12 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
2820
2820
|
if (!acceptEncodingSet.has(encoding)) {
|
|
2821
2821
|
continue;
|
|
2822
2822
|
}
|
|
2823
|
-
const precompressedStats = getStats(
|
|
2823
|
+
const precompressedStats = getStats(path5 + ENCODINGS[encoding]);
|
|
2824
2824
|
if (precompressedStats) {
|
|
2825
2825
|
c.header("Content-Encoding", encoding);
|
|
2826
2826
|
c.header("Vary", "Accept-Encoding", { append: true });
|
|
2827
2827
|
stats = precompressedStats;
|
|
2828
|
-
|
|
2828
|
+
path5 = path5 + ENCODINGS[encoding];
|
|
2829
2829
|
break;
|
|
2830
2830
|
}
|
|
2831
2831
|
}
|
|
@@ -2839,7 +2839,7 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
2839
2839
|
result = c.body(null);
|
|
2840
2840
|
} else if (!range) {
|
|
2841
2841
|
c.header("Content-Length", size.toString());
|
|
2842
|
-
result = c.body(createStreamBody(createReadStream(
|
|
2842
|
+
result = c.body(createStreamBody(createReadStream(path5)), 200);
|
|
2843
2843
|
} else {
|
|
2844
2844
|
c.header("Accept-Ranges", "bytes");
|
|
2845
2845
|
c.header("Date", stats.birthtime.toUTCString());
|
|
@@ -2850,16 +2850,217 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
2850
2850
|
end = size - 1;
|
|
2851
2851
|
}
|
|
2852
2852
|
const chunksize = end - start + 1;
|
|
2853
|
-
const stream = createReadStream(
|
|
2853
|
+
const stream = createReadStream(path5, { start, end });
|
|
2854
2854
|
c.header("Content-Length", chunksize.toString());
|
|
2855
2855
|
c.header("Content-Range", `bytes ${start}-${end}/${stats.size}`);
|
|
2856
2856
|
result = c.body(createStreamBody(stream), 206);
|
|
2857
2857
|
}
|
|
2858
|
-
await options.onFound?.(
|
|
2858
|
+
await options.onFound?.(path5, c);
|
|
2859
2859
|
return result;
|
|
2860
2860
|
};
|
|
2861
2861
|
};
|
|
2862
2862
|
|
|
2863
|
+
// src/archive/chat-id.ts
|
|
2864
|
+
import crypto3 from "crypto";
|
|
2865
|
+
var CROCKFORD_ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz";
|
|
2866
|
+
var CHAT_ID_LENGTH = 6;
|
|
2867
|
+
var MAX_RETRIES = 5;
|
|
2868
|
+
var CHAT_ID_PREFIX = "clog_";
|
|
2869
|
+
var WIRE_FORM_RE = new RegExp(
|
|
2870
|
+
`^${CHAT_ID_PREFIX}[${CROCKFORD_ALPHABET}]{${CHAT_ID_LENGTH}}$`
|
|
2871
|
+
);
|
|
2872
|
+
function formatChatId(code) {
|
|
2873
|
+
return `${CHAT_ID_PREFIX}${code}`;
|
|
2874
|
+
}
|
|
2875
|
+
function parseChatId(wire) {
|
|
2876
|
+
if (!WIRE_FORM_RE.test(wire)) return null;
|
|
2877
|
+
return wire.slice(CHAT_ID_PREFIX.length);
|
|
2878
|
+
}
|
|
2879
|
+
function generateChatId({
|
|
2880
|
+
isTaken,
|
|
2881
|
+
randomIndex = () => crypto3.randomInt(CROCKFORD_ALPHABET.length)
|
|
2882
|
+
}) {
|
|
2883
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
2884
|
+
let code = "";
|
|
2885
|
+
for (let i = 0; i < CHAT_ID_LENGTH; i++) {
|
|
2886
|
+
code += CROCKFORD_ALPHABET[randomIndex()];
|
|
2887
|
+
}
|
|
2888
|
+
if (!isTaken(code)) {
|
|
2889
|
+
return code;
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
throw new Error(
|
|
2893
|
+
`Failed to generate unique chat_id after ${MAX_RETRIES + 1} attempts`
|
|
2894
|
+
);
|
|
2895
|
+
}
|
|
2896
|
+
|
|
2897
|
+
// src/visibility.ts
|
|
2898
|
+
function loadChatVisibility(metadata2, opts) {
|
|
2899
|
+
const deleted = metadata2.listDeleted();
|
|
2900
|
+
const trashed = new Set(deleted.map((r) => r.id));
|
|
2901
|
+
const deletedAtById = new Map(
|
|
2902
|
+
deleted.map((r) => [r.id, r.deletedAt?.getTime() ?? null])
|
|
2903
|
+
);
|
|
2904
|
+
const showTrashed = opts.includeTrashed === true;
|
|
2905
|
+
return {
|
|
2906
|
+
isTrashed: (internalId) => trashed.has(internalId),
|
|
2907
|
+
isVisible: (internalId) => showTrashed || !trashed.has(internalId),
|
|
2908
|
+
deletedAt: (internalId) => deletedAtById.get(internalId) ?? null
|
|
2909
|
+
};
|
|
2910
|
+
}
|
|
2911
|
+
|
|
2912
|
+
// src/chat-reader.ts
|
|
2913
|
+
function toApiBlock(block) {
|
|
2914
|
+
if (block.type === "tool_result") {
|
|
2915
|
+
return {
|
|
2916
|
+
type: "tool_result",
|
|
2917
|
+
tool_use_id: String(block.toolUseId ?? ""),
|
|
2918
|
+
content: block.content
|
|
2919
|
+
};
|
|
2920
|
+
}
|
|
2921
|
+
return block;
|
|
2922
|
+
}
|
|
2923
|
+
function createChatReader({
|
|
2924
|
+
archive: archive2,
|
|
2925
|
+
metadata: metadata2
|
|
2926
|
+
}) {
|
|
2927
|
+
function findChat(id) {
|
|
2928
|
+
const code = parseChatId(id);
|
|
2929
|
+
if (code === null) return null;
|
|
2930
|
+
return archive2.read.findChatByChatId(code);
|
|
2931
|
+
}
|
|
2932
|
+
function deriveTitle(customTitle, firstUserText) {
|
|
2933
|
+
if (customTitle && customTitle.trim()) return customTitle;
|
|
2934
|
+
const text2 = firstUserText?.trim().split("\n")[0]?.trim();
|
|
2935
|
+
return text2 && text2.length > 0 ? text2 : "Untitled";
|
|
2936
|
+
}
|
|
2937
|
+
function key(agent, sourceId) {
|
|
2938
|
+
return [agent, sourceId].join("\0");
|
|
2939
|
+
}
|
|
2940
|
+
function listChats({
|
|
2941
|
+
includeTrashed
|
|
2942
|
+
}) {
|
|
2943
|
+
const visibility = loadChatVisibility(metadata2, { includeTrashed });
|
|
2944
|
+
const rows = archive2.read.listChatRows();
|
|
2945
|
+
const tsRangeByKey = new Map(
|
|
2946
|
+
archive2.read.listChatTsRanges().map((r) => [key(r.agent, r.sourceId), r])
|
|
2947
|
+
);
|
|
2948
|
+
const sourcePathByKey = new Map(
|
|
2949
|
+
archive2.read.listLatestRawSourcePaths().map((r) => [key(r.agent, r.sourceId), r.sourcePath])
|
|
2950
|
+
);
|
|
2951
|
+
const firstUserTextByKey = new Map(
|
|
2952
|
+
archive2.read.listFirstUserTexts().map((r) => [key(r.agent, r.sourceId), r.text])
|
|
2953
|
+
);
|
|
2954
|
+
const customTitleById = metadata2.listCustomTitles();
|
|
2955
|
+
const chats2 = [];
|
|
2956
|
+
for (const row of rows) {
|
|
2957
|
+
if (!visibility.isVisible(row.id)) continue;
|
|
2958
|
+
const isDeleted = visibility.isTrashed(row.id);
|
|
2959
|
+
const rowKey = key(row.agent, row.sourceId);
|
|
2960
|
+
const tsRange = tsRangeByKey.get(rowKey);
|
|
2961
|
+
const firstSeenAtMs = row.firstSeenAt.getTime();
|
|
2962
|
+
const chat = {
|
|
2963
|
+
id: formatChatId(row.chatId),
|
|
2964
|
+
sourceId: row.sourceId,
|
|
2965
|
+
agent: row.agent,
|
|
2966
|
+
title: deriveTitle(
|
|
2967
|
+
customTitleById.get(row.id),
|
|
2968
|
+
firstUserTextByKey.get(rowKey)
|
|
2969
|
+
),
|
|
2970
|
+
project: row.project ?? "",
|
|
2971
|
+
projectPath: row.projectPath ?? null,
|
|
2972
|
+
sourceFilePath: sourcePathByKey.get(rowKey) ?? null,
|
|
2973
|
+
createdAt: tsRange?.minTs ?? firstSeenAtMs,
|
|
2974
|
+
updatedAt: tsRange?.maxTs ?? firstSeenAtMs,
|
|
2975
|
+
deletedAt: visibility.deletedAt(row.id)
|
|
2976
|
+
};
|
|
2977
|
+
if (isDeleted) chat.isDeleted = true;
|
|
2978
|
+
chats2.push(chat);
|
|
2979
|
+
}
|
|
2980
|
+
return chats2;
|
|
2981
|
+
}
|
|
2982
|
+
function getMessages(id, { includeTrashed }) {
|
|
2983
|
+
const row = findChat(id);
|
|
2984
|
+
if (!row) return null;
|
|
2985
|
+
const visibility = loadChatVisibility(metadata2, { includeTrashed });
|
|
2986
|
+
if (!visibility.isVisible(row.id)) return null;
|
|
2987
|
+
const rows = archive2.read.listMessagesByChat(row.agent, row.sourceId);
|
|
2988
|
+
return rows.map((m) => ({
|
|
2989
|
+
role: m.role,
|
|
2990
|
+
content: m.blocks.map(toApiBlock),
|
|
2991
|
+
timestamp: m.ts.toISOString()
|
|
2992
|
+
}));
|
|
2993
|
+
}
|
|
2994
|
+
return { listChats, getMessages, findChat };
|
|
2995
|
+
}
|
|
2996
|
+
|
|
2997
|
+
// src/app.ts
|
|
2998
|
+
function createApp({ archive: archive2, metadata: metadata2, webDistDir: webDistDir2 }) {
|
|
2999
|
+
const app2 = new Hono2();
|
|
3000
|
+
const reader = createChatReader({ archive: archive2, metadata: metadata2 });
|
|
3001
|
+
app2.get("/api/chats", (c) => {
|
|
3002
|
+
const chats2 = reader.listChats({
|
|
3003
|
+
includeTrashed: c.req.query("includeTrashed") === "true"
|
|
3004
|
+
});
|
|
3005
|
+
return c.json({ chats: chats2 });
|
|
3006
|
+
});
|
|
3007
|
+
app2.delete("/api/chats/:id", (c) => {
|
|
3008
|
+
const row = reader.findChat(c.req.param("id"));
|
|
3009
|
+
if (!row) {
|
|
3010
|
+
return c.json({ error: "Chat not found" }, 404);
|
|
3011
|
+
}
|
|
3012
|
+
metadata2.softDelete(row.id);
|
|
3013
|
+
return c.body(null, 204);
|
|
3014
|
+
});
|
|
3015
|
+
app2.post("/api/chats/:id/restore", (c) => {
|
|
3016
|
+
const row = reader.findChat(c.req.param("id"));
|
|
3017
|
+
if (!row) {
|
|
3018
|
+
return c.json({ error: "Chat not found" }, 404);
|
|
3019
|
+
}
|
|
3020
|
+
metadata2.restore(row.id);
|
|
3021
|
+
return c.body(null, 204);
|
|
3022
|
+
});
|
|
3023
|
+
app2.patch("/api/chats/:id/title", async (c) => {
|
|
3024
|
+
const row = reader.findChat(c.req.param("id"));
|
|
3025
|
+
if (!row) {
|
|
3026
|
+
return c.json({ error: "Chat not found" }, 404);
|
|
3027
|
+
}
|
|
3028
|
+
let body;
|
|
3029
|
+
try {
|
|
3030
|
+
body = await c.req.json();
|
|
3031
|
+
} catch {
|
|
3032
|
+
return c.json({ error: "Invalid JSON body" }, 400);
|
|
3033
|
+
}
|
|
3034
|
+
if (!body || typeof body !== "object" || typeof body.title !== "string") {
|
|
3035
|
+
return c.json({ error: "Invalid title" }, 400);
|
|
3036
|
+
}
|
|
3037
|
+
const raw2 = body.title;
|
|
3038
|
+
if (raw2.length > 200) {
|
|
3039
|
+
return c.json({ error: "Title too long" }, 400);
|
|
3040
|
+
}
|
|
3041
|
+
const trimmed = raw2.trim();
|
|
3042
|
+
metadata2.setCustomTitle(row.id, trimmed.length > 0 ? trimmed : null);
|
|
3043
|
+
return c.body(null, 204);
|
|
3044
|
+
});
|
|
3045
|
+
app2.get("/api/chats/:id", (c) => {
|
|
3046
|
+
const messages2 = reader.getMessages(c.req.param("id"), {
|
|
3047
|
+
includeTrashed: c.req.query("includeTrashed") === "true"
|
|
3048
|
+
});
|
|
3049
|
+
if (messages2 === null) {
|
|
3050
|
+
return c.json({ error: "Chat not found" }, 404);
|
|
3051
|
+
}
|
|
3052
|
+
return c.json({ messages: messages2 });
|
|
3053
|
+
});
|
|
3054
|
+
if (webDistDir2) {
|
|
3055
|
+
app2.use("*", serveStatic({ root: webDistDir2 }));
|
|
3056
|
+
app2.use("*", serveStatic({ root: webDistDir2, path: "index.html" }));
|
|
3057
|
+
}
|
|
3058
|
+
return app2;
|
|
3059
|
+
}
|
|
3060
|
+
|
|
3061
|
+
// src/archive/repository.ts
|
|
3062
|
+
import crypto5 from "crypto";
|
|
3063
|
+
|
|
2863
3064
|
// ../node_modules/.pnpm/drizzle-orm@0.45.2_@types+better-sqlite3@7.6.13_better-sqlite3@12.9.0/node_modules/drizzle-orm/entity.js
|
|
2864
3065
|
var entityKind = /* @__PURE__ */ Symbol.for("drizzle:entityKind");
|
|
2865
3066
|
function is(value, type) {
|
|
@@ -4173,7 +4374,7 @@ var QueryPromise = class {
|
|
|
4173
4374
|
function mapResultRow(columns, row, joinsNotNullableMap) {
|
|
4174
4375
|
const nullifyMap = {};
|
|
4175
4376
|
const result = columns.reduce(
|
|
4176
|
-
(result2, { path:
|
|
4377
|
+
(result2, { path: path5, field }, columnIndex) => {
|
|
4177
4378
|
let decoder;
|
|
4178
4379
|
if (is(field, Column)) {
|
|
4179
4380
|
decoder = field;
|
|
@@ -4185,8 +4386,8 @@ function mapResultRow(columns, row, joinsNotNullableMap) {
|
|
|
4185
4386
|
decoder = field.sql.decoder;
|
|
4186
4387
|
}
|
|
4187
4388
|
let node = result2;
|
|
4188
|
-
for (const [pathChunkIndex, pathChunk] of
|
|
4189
|
-
if (pathChunkIndex <
|
|
4389
|
+
for (const [pathChunkIndex, pathChunk] of path5.entries()) {
|
|
4390
|
+
if (pathChunkIndex < path5.length - 1) {
|
|
4190
4391
|
if (!(pathChunk in node)) {
|
|
4191
4392
|
node[pathChunk] = {};
|
|
4192
4393
|
}
|
|
@@ -4194,8 +4395,8 @@ function mapResultRow(columns, row, joinsNotNullableMap) {
|
|
|
4194
4395
|
} else {
|
|
4195
4396
|
const rawValue = row[columnIndex];
|
|
4196
4397
|
const value = node[pathChunk] = rawValue === null ? null : decoder.mapFromDriverValue(rawValue);
|
|
4197
|
-
if (joinsNotNullableMap && is(field, Column) &&
|
|
4198
|
-
const objectName =
|
|
4398
|
+
if (joinsNotNullableMap && is(field, Column) && path5.length === 2) {
|
|
4399
|
+
const objectName = path5[0];
|
|
4199
4400
|
if (!(objectName in nullifyMap)) {
|
|
4200
4401
|
nullifyMap[objectName] = value === null ? getTableName(field.table) : false;
|
|
4201
4402
|
} else if (typeof nullifyMap[objectName] === "string" && nullifyMap[objectName] !== getTableName(field.table)) {
|
|
@@ -4754,16 +4955,82 @@ function mapRelationalRow(tablesConfig, tableConfig, row, buildQueryResultSelect
|
|
|
4754
4955
|
return result;
|
|
4755
4956
|
}
|
|
4756
4957
|
|
|
4757
|
-
// src/
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4958
|
+
// src/storage/openStore.ts
|
|
4959
|
+
import fs2 from "fs";
|
|
4960
|
+
import path from "path";
|
|
4961
|
+
import { fileURLToPath } from "url";
|
|
4962
|
+
import Database from "better-sqlite3";
|
|
4963
|
+
|
|
4964
|
+
// ../node_modules/.pnpm/drizzle-orm@0.45.2_@types+better-sqlite3@7.6.13_better-sqlite3@12.9.0/node_modules/drizzle-orm/better-sqlite3/driver.js
|
|
4965
|
+
import Client from "better-sqlite3";
|
|
4966
|
+
|
|
4967
|
+
// ../node_modules/.pnpm/drizzle-orm@0.45.2_@types+better-sqlite3@7.6.13_better-sqlite3@12.9.0/node_modules/drizzle-orm/selection-proxy.js
|
|
4968
|
+
var SelectionProxyHandler = class _SelectionProxyHandler {
|
|
4969
|
+
static [entityKind] = "SelectionProxyHandler";
|
|
4970
|
+
config;
|
|
4971
|
+
constructor(config) {
|
|
4972
|
+
this.config = { ...config };
|
|
4973
|
+
}
|
|
4974
|
+
get(subquery, prop) {
|
|
4975
|
+
if (prop === "_") {
|
|
4976
|
+
return {
|
|
4977
|
+
...subquery["_"],
|
|
4978
|
+
selectedFields: new Proxy(
|
|
4979
|
+
subquery._.selectedFields,
|
|
4980
|
+
this
|
|
4981
|
+
)
|
|
4982
|
+
};
|
|
4983
|
+
}
|
|
4984
|
+
if (prop === ViewBaseConfig) {
|
|
4985
|
+
return {
|
|
4986
|
+
...subquery[ViewBaseConfig],
|
|
4987
|
+
selectedFields: new Proxy(
|
|
4988
|
+
subquery[ViewBaseConfig].selectedFields,
|
|
4989
|
+
this
|
|
4990
|
+
)
|
|
4991
|
+
};
|
|
4992
|
+
}
|
|
4993
|
+
if (typeof prop === "symbol") {
|
|
4994
|
+
return subquery[prop];
|
|
4995
|
+
}
|
|
4996
|
+
const columns = is(subquery, Subquery) ? subquery._.selectedFields : is(subquery, View) ? subquery[ViewBaseConfig].selectedFields : subquery;
|
|
4997
|
+
const value = columns[prop];
|
|
4998
|
+
if (is(value, SQL.Aliased)) {
|
|
4999
|
+
if (this.config.sqlAliasedBehavior === "sql" && !value.isSelectionField) {
|
|
5000
|
+
return value.sql;
|
|
5001
|
+
}
|
|
5002
|
+
const newValue = value.clone();
|
|
5003
|
+
newValue.isSelectionField = true;
|
|
5004
|
+
return newValue;
|
|
5005
|
+
}
|
|
5006
|
+
if (is(value, SQL)) {
|
|
5007
|
+
if (this.config.sqlBehavior === "sql") {
|
|
5008
|
+
return value;
|
|
5009
|
+
}
|
|
5010
|
+
throw new Error(
|
|
5011
|
+
`You tried to reference "${prop}" field from a subquery, which is a raw SQL field, but it doesn't have an alias declared. Please add an alias to the field using ".as('alias')" method.`
|
|
5012
|
+
);
|
|
5013
|
+
}
|
|
5014
|
+
if (is(value, Column)) {
|
|
5015
|
+
if (this.config.alias) {
|
|
5016
|
+
return new Proxy(
|
|
5017
|
+
value,
|
|
5018
|
+
new ColumnAliasProxyHandler(
|
|
5019
|
+
new Proxy(
|
|
5020
|
+
value.table,
|
|
5021
|
+
new TableAliasProxyHandler(this.config.alias, this.config.replaceOriginalName ?? false)
|
|
5022
|
+
)
|
|
5023
|
+
)
|
|
5024
|
+
);
|
|
5025
|
+
}
|
|
5026
|
+
return value;
|
|
5027
|
+
}
|
|
5028
|
+
if (typeof value !== "object" || value === null) {
|
|
5029
|
+
return value;
|
|
5030
|
+
}
|
|
5031
|
+
return new Proxy(value, new _SelectionProxyHandler(this.config));
|
|
5032
|
+
}
|
|
5033
|
+
};
|
|
4767
5034
|
|
|
4768
5035
|
// ../node_modules/.pnpm/drizzle-orm@0.45.2_@types+better-sqlite3@7.6.13_better-sqlite3@12.9.0/node_modules/drizzle-orm/sqlite-core/foreign-keys.js
|
|
4769
5036
|
var ForeignKeyBuilder2 = class {
|
|
@@ -5317,74 +5584,6 @@ function text(a, b = {}) {
|
|
|
5317
5584
|
return new SQLiteTextBuilder(name, config);
|
|
5318
5585
|
}
|
|
5319
5586
|
|
|
5320
|
-
// ../node_modules/.pnpm/drizzle-orm@0.45.2_@types+better-sqlite3@7.6.13_better-sqlite3@12.9.0/node_modules/drizzle-orm/selection-proxy.js
|
|
5321
|
-
var SelectionProxyHandler = class _SelectionProxyHandler {
|
|
5322
|
-
static [entityKind] = "SelectionProxyHandler";
|
|
5323
|
-
config;
|
|
5324
|
-
constructor(config) {
|
|
5325
|
-
this.config = { ...config };
|
|
5326
|
-
}
|
|
5327
|
-
get(subquery, prop) {
|
|
5328
|
-
if (prop === "_") {
|
|
5329
|
-
return {
|
|
5330
|
-
...subquery["_"],
|
|
5331
|
-
selectedFields: new Proxy(
|
|
5332
|
-
subquery._.selectedFields,
|
|
5333
|
-
this
|
|
5334
|
-
)
|
|
5335
|
-
};
|
|
5336
|
-
}
|
|
5337
|
-
if (prop === ViewBaseConfig) {
|
|
5338
|
-
return {
|
|
5339
|
-
...subquery[ViewBaseConfig],
|
|
5340
|
-
selectedFields: new Proxy(
|
|
5341
|
-
subquery[ViewBaseConfig].selectedFields,
|
|
5342
|
-
this
|
|
5343
|
-
)
|
|
5344
|
-
};
|
|
5345
|
-
}
|
|
5346
|
-
if (typeof prop === "symbol") {
|
|
5347
|
-
return subquery[prop];
|
|
5348
|
-
}
|
|
5349
|
-
const columns = is(subquery, Subquery) ? subquery._.selectedFields : is(subquery, View) ? subquery[ViewBaseConfig].selectedFields : subquery;
|
|
5350
|
-
const value = columns[prop];
|
|
5351
|
-
if (is(value, SQL.Aliased)) {
|
|
5352
|
-
if (this.config.sqlAliasedBehavior === "sql" && !value.isSelectionField) {
|
|
5353
|
-
return value.sql;
|
|
5354
|
-
}
|
|
5355
|
-
const newValue = value.clone();
|
|
5356
|
-
newValue.isSelectionField = true;
|
|
5357
|
-
return newValue;
|
|
5358
|
-
}
|
|
5359
|
-
if (is(value, SQL)) {
|
|
5360
|
-
if (this.config.sqlBehavior === "sql") {
|
|
5361
|
-
return value;
|
|
5362
|
-
}
|
|
5363
|
-
throw new Error(
|
|
5364
|
-
`You tried to reference "${prop}" field from a subquery, which is a raw SQL field, but it doesn't have an alias declared. Please add an alias to the field using ".as('alias')" method.`
|
|
5365
|
-
);
|
|
5366
|
-
}
|
|
5367
|
-
if (is(value, Column)) {
|
|
5368
|
-
if (this.config.alias) {
|
|
5369
|
-
return new Proxy(
|
|
5370
|
-
value,
|
|
5371
|
-
new ColumnAliasProxyHandler(
|
|
5372
|
-
new Proxy(
|
|
5373
|
-
value.table,
|
|
5374
|
-
new TableAliasProxyHandler(this.config.alias, this.config.replaceOriginalName ?? false)
|
|
5375
|
-
)
|
|
5376
|
-
)
|
|
5377
|
-
);
|
|
5378
|
-
}
|
|
5379
|
-
return value;
|
|
5380
|
-
}
|
|
5381
|
-
if (typeof value !== "object" || value === null) {
|
|
5382
|
-
return value;
|
|
5383
|
-
}
|
|
5384
|
-
return new Proxy(value, new _SelectionProxyHandler(this.config));
|
|
5385
|
-
}
|
|
5386
|
-
};
|
|
5387
|
-
|
|
5388
5587
|
// ../node_modules/.pnpm/drizzle-orm@0.45.2_@types+better-sqlite3@7.6.13_better-sqlite3@12.9.0/node_modules/drizzle-orm/sqlite-core/columns/all.js
|
|
5389
5588
|
function getSQLiteColumnBuilders() {
|
|
5390
5589
|
return {
|
|
@@ -8168,242 +8367,6 @@ var SQLiteTransaction = class extends BaseSQLiteDatabase {
|
|
|
8168
8367
|
}
|
|
8169
8368
|
};
|
|
8170
8369
|
|
|
8171
|
-
// src/archive/schema.ts
|
|
8172
|
-
var archiveMeta = sqliteTable("archive_meta", {
|
|
8173
|
-
id: integer("id").primaryKey(),
|
|
8174
|
-
archiveUuid: text("archive_uuid").notNull(),
|
|
8175
|
-
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull()
|
|
8176
|
-
});
|
|
8177
|
-
var schemaVersion = sqliteTable("schema_version", {
|
|
8178
|
-
version: integer("version").primaryKey(),
|
|
8179
|
-
appliedAt: integer("applied_at", { mode: "timestamp_ms" }).notNull()
|
|
8180
|
-
});
|
|
8181
|
-
var chats = sqliteTable(
|
|
8182
|
-
"chats",
|
|
8183
|
-
{
|
|
8184
|
-
id: text("id").primaryKey(),
|
|
8185
|
-
chatId: text("chat_id").notNull().unique(),
|
|
8186
|
-
agent: text("agent").notNull(),
|
|
8187
|
-
sourceId: text("source_id").notNull(),
|
|
8188
|
-
firstSeenAt: integer("first_seen_at", { mode: "timestamp_ms" }).notNull(),
|
|
8189
|
-
project: text("project"),
|
|
8190
|
-
projectPath: text("project_path")
|
|
8191
|
-
},
|
|
8192
|
-
(t) => [uniqueIndex("chats_agent_source_idx").on(t.agent, t.sourceId)]
|
|
8193
|
-
);
|
|
8194
|
-
var rawMessages = sqliteTable(
|
|
8195
|
-
"raw_messages",
|
|
8196
|
-
{
|
|
8197
|
-
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
8198
|
-
agent: text("agent").notNull(),
|
|
8199
|
-
sourceId: text("source_id").notNull(),
|
|
8200
|
-
sourcePath: text("source_path").notNull(),
|
|
8201
|
-
sourceLocator: text("source_locator").notNull(),
|
|
8202
|
-
rawPayload: text("raw_payload").notNull(),
|
|
8203
|
-
payloadHash: text("payload_hash").notNull(),
|
|
8204
|
-
ingestedAt: integer("ingested_at", { mode: "timestamp_ms" }).notNull()
|
|
8205
|
-
},
|
|
8206
|
-
(t) => [
|
|
8207
|
-
uniqueIndex("raw_messages_idem_idx").on(t.agent, t.sourceId, t.payloadHash)
|
|
8208
|
-
]
|
|
8209
|
-
);
|
|
8210
|
-
var messages = sqliteTable(
|
|
8211
|
-
"messages",
|
|
8212
|
-
{
|
|
8213
|
-
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
8214
|
-
agent: text("agent").notNull(),
|
|
8215
|
-
sourceId: text("source_id").notNull(),
|
|
8216
|
-
messageId: text("message_id").notNull(),
|
|
8217
|
-
role: text("role").notNull(),
|
|
8218
|
-
ts: integer("ts", { mode: "timestamp_ms" }).notNull(),
|
|
8219
|
-
text: text("text").notNull(),
|
|
8220
|
-
blocks: text("blocks", { mode: "json" }).notNull(),
|
|
8221
|
-
rawId: integer("raw_id").notNull().references(() => rawMessages.id)
|
|
8222
|
-
},
|
|
8223
|
-
(t) => [
|
|
8224
|
-
uniqueIndex("messages_canonical_idx").on(t.agent, t.sourceId, t.messageId)
|
|
8225
|
-
]
|
|
8226
|
-
);
|
|
8227
|
-
var ingestionEvents = sqliteTable("ingestion_events", {
|
|
8228
|
-
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
8229
|
-
agent: text("agent").notNull(),
|
|
8230
|
-
sourceId: text("source_id").notNull(),
|
|
8231
|
-
sourcePath: text("source_path").notNull(),
|
|
8232
|
-
eventType: text("event_type").notNull(),
|
|
8233
|
-
detail: text("detail", { mode: "json" }).notNull(),
|
|
8234
|
-
observedAt: integer("observed_at", { mode: "timestamp_ms" }).notNull()
|
|
8235
|
-
});
|
|
8236
|
-
|
|
8237
|
-
// src/visibility.ts
|
|
8238
|
-
function loadChatVisibility(metadata2, opts) {
|
|
8239
|
-
const deleted = metadata2.listDeleted();
|
|
8240
|
-
const trashed = new Set(deleted.map((r) => r.id));
|
|
8241
|
-
const deletedAtById = new Map(
|
|
8242
|
-
deleted.map((r) => [r.id, r.deletedAt?.getTime() ?? null])
|
|
8243
|
-
);
|
|
8244
|
-
const showTrashed = opts.includeTrashed === true;
|
|
8245
|
-
return {
|
|
8246
|
-
isTrashed: (internalId) => trashed.has(internalId),
|
|
8247
|
-
isVisible: (internalId) => showTrashed || !trashed.has(internalId),
|
|
8248
|
-
deletedAt: (internalId) => deletedAtById.get(internalId) ?? null
|
|
8249
|
-
};
|
|
8250
|
-
}
|
|
8251
|
-
|
|
8252
|
-
// src/app.ts
|
|
8253
|
-
function toApiBlock(block) {
|
|
8254
|
-
if (block.type === "tool_result") {
|
|
8255
|
-
return {
|
|
8256
|
-
type: "tool_result",
|
|
8257
|
-
tool_use_id: String(block.toolUseId ?? ""),
|
|
8258
|
-
content: block.content
|
|
8259
|
-
};
|
|
8260
|
-
}
|
|
8261
|
-
return block;
|
|
8262
|
-
}
|
|
8263
|
-
var CLAUDE_CODE_AGENT = "claude-code";
|
|
8264
|
-
function createApp({ archive: archive2, metadata: metadata2, webDistDir: webDistDir2 }) {
|
|
8265
|
-
const app2 = new Hono2();
|
|
8266
|
-
function findArchiveChatBySourceId(sourceId) {
|
|
8267
|
-
return archive2.db.select().from(chats).where(eq(chats.sourceId, sourceId)).get();
|
|
8268
|
-
}
|
|
8269
|
-
app2.get("/api/chats", (c) => {
|
|
8270
|
-
const visibility = loadChatVisibility(metadata2, {
|
|
8271
|
-
includeTrashed: c.req.query("includeTrashed") === "true"
|
|
8272
|
-
});
|
|
8273
|
-
const rows = archive2.db.select().from(chats).all();
|
|
8274
|
-
const chats2 = [];
|
|
8275
|
-
for (const row of rows) {
|
|
8276
|
-
if (!visibility.isVisible(row.id)) continue;
|
|
8277
|
-
const isDeleted = visibility.isTrashed(row.id);
|
|
8278
|
-
const latestRaw = archive2.db.select({ sourcePath: rawMessages.sourcePath }).from(rawMessages).where(
|
|
8279
|
-
and(
|
|
8280
|
-
eq(rawMessages.agent, CLAUDE_CODE_AGENT),
|
|
8281
|
-
eq(rawMessages.sourceId, row.sourceId)
|
|
8282
|
-
)
|
|
8283
|
-
).orderBy(desc(rawMessages.ingestedAt)).limit(1).get();
|
|
8284
|
-
const tsRange = archive2.db.select({
|
|
8285
|
-
minTs: sql`min(${messages.ts})`,
|
|
8286
|
-
maxTs: sql`max(${messages.ts})`
|
|
8287
|
-
}).from(messages).where(
|
|
8288
|
-
and(
|
|
8289
|
-
eq(messages.agent, CLAUDE_CODE_AGENT),
|
|
8290
|
-
eq(messages.sourceId, row.sourceId)
|
|
8291
|
-
)
|
|
8292
|
-
).get();
|
|
8293
|
-
const firstSeenAtMs = row.firstSeenAt.getTime();
|
|
8294
|
-
const chat = {
|
|
8295
|
-
id: row.sourceId,
|
|
8296
|
-
chatId: row.chatId,
|
|
8297
|
-
agent: row.agent,
|
|
8298
|
-
title: deriveTitle(archive2, metadata2, row),
|
|
8299
|
-
project: row.project ?? "",
|
|
8300
|
-
projectPath: row.projectPath ?? null,
|
|
8301
|
-
sourceFilePath: latestRaw?.sourcePath ?? null,
|
|
8302
|
-
createdAt: tsRange?.minTs ?? firstSeenAtMs,
|
|
8303
|
-
updatedAt: tsRange?.maxTs ?? firstSeenAtMs,
|
|
8304
|
-
deletedAt: visibility.deletedAt(row.id)
|
|
8305
|
-
};
|
|
8306
|
-
if (isDeleted) chat.isDeleted = true;
|
|
8307
|
-
chats2.push(chat);
|
|
8308
|
-
}
|
|
8309
|
-
return c.json({ chats: chats2 });
|
|
8310
|
-
});
|
|
8311
|
-
app2.delete("/api/chats/:id", (c) => {
|
|
8312
|
-
const id = c.req.param("id");
|
|
8313
|
-
const row = findArchiveChatBySourceId(id);
|
|
8314
|
-
if (!row) {
|
|
8315
|
-
return c.json({ error: "Chat not found" }, 404);
|
|
8316
|
-
}
|
|
8317
|
-
metadata2.softDelete(row.id);
|
|
8318
|
-
return c.body(null, 204);
|
|
8319
|
-
});
|
|
8320
|
-
app2.post("/api/chats/:id/restore", (c) => {
|
|
8321
|
-
const id = c.req.param("id");
|
|
8322
|
-
const row = findArchiveChatBySourceId(id);
|
|
8323
|
-
if (!row) {
|
|
8324
|
-
return c.json({ error: "Chat not found" }, 404);
|
|
8325
|
-
}
|
|
8326
|
-
metadata2.restore(row.id);
|
|
8327
|
-
return c.body(null, 204);
|
|
8328
|
-
});
|
|
8329
|
-
app2.patch("/api/chats/:id/title", async (c) => {
|
|
8330
|
-
const id = c.req.param("id");
|
|
8331
|
-
const row = findArchiveChatBySourceId(id);
|
|
8332
|
-
if (!row) {
|
|
8333
|
-
return c.json({ error: "Chat not found" }, 404);
|
|
8334
|
-
}
|
|
8335
|
-
let body;
|
|
8336
|
-
try {
|
|
8337
|
-
body = await c.req.json();
|
|
8338
|
-
} catch {
|
|
8339
|
-
return c.json({ error: "Invalid JSON body" }, 400);
|
|
8340
|
-
}
|
|
8341
|
-
if (!body || typeof body !== "object" || typeof body.title !== "string") {
|
|
8342
|
-
return c.json({ error: "Invalid title" }, 400);
|
|
8343
|
-
}
|
|
8344
|
-
const raw2 = body.title;
|
|
8345
|
-
if (raw2.length > 200) {
|
|
8346
|
-
return c.json({ error: "Title too long" }, 400);
|
|
8347
|
-
}
|
|
8348
|
-
const trimmed = raw2.trim();
|
|
8349
|
-
metadata2.setCustomTitle(row.id, trimmed.length > 0 ? trimmed : null);
|
|
8350
|
-
return c.body(null, 204);
|
|
8351
|
-
});
|
|
8352
|
-
app2.get("/api/chats/:id", (c) => {
|
|
8353
|
-
const id = c.req.param("id");
|
|
8354
|
-
const row = findArchiveChatBySourceId(id);
|
|
8355
|
-
if (!row) {
|
|
8356
|
-
return c.json({ error: "Chat not found" }, 404);
|
|
8357
|
-
}
|
|
8358
|
-
const visibility = loadChatVisibility(metadata2, {
|
|
8359
|
-
includeTrashed: c.req.query("includeTrashed") === "true"
|
|
8360
|
-
});
|
|
8361
|
-
if (!visibility.isVisible(row.id)) {
|
|
8362
|
-
return c.json({ error: "Chat not found" }, 404);
|
|
8363
|
-
}
|
|
8364
|
-
const rows = archive2.db.select().from(messages).where(
|
|
8365
|
-
and(
|
|
8366
|
-
eq(messages.agent, CLAUDE_CODE_AGENT),
|
|
8367
|
-
eq(messages.sourceId, id)
|
|
8368
|
-
)
|
|
8369
|
-
).orderBy(asc(messages.ts)).all();
|
|
8370
|
-
const messages2 = rows.map((m) => ({
|
|
8371
|
-
role: m.role,
|
|
8372
|
-
content: m.blocks.map(toApiBlock),
|
|
8373
|
-
timestamp: m.ts.toISOString()
|
|
8374
|
-
}));
|
|
8375
|
-
return c.json({ messages: messages2 });
|
|
8376
|
-
});
|
|
8377
|
-
function deriveTitle(archive3, metadata3, row) {
|
|
8378
|
-
const custom = metadata3.getCustomTitle(row.id);
|
|
8379
|
-
if (custom && custom.trim()) return custom;
|
|
8380
|
-
const firstUser = archive3.db.select({ text: messages.text }).from(messages).where(
|
|
8381
|
-
and(
|
|
8382
|
-
eq(messages.agent, CLAUDE_CODE_AGENT),
|
|
8383
|
-
eq(messages.sourceId, row.sourceId),
|
|
8384
|
-
eq(messages.role, "user")
|
|
8385
|
-
)
|
|
8386
|
-
).orderBy(asc(messages.ts)).limit(1).get();
|
|
8387
|
-
const text2 = firstUser?.text?.trim().split("\n")[0]?.trim();
|
|
8388
|
-
return text2 && text2.length > 0 ? text2 : "Untitled";
|
|
8389
|
-
}
|
|
8390
|
-
if (webDistDir2) {
|
|
8391
|
-
app2.use("*", serveStatic({ root: webDistDir2 }));
|
|
8392
|
-
app2.use("*", serveStatic({ root: webDistDir2, path: "index.html" }));
|
|
8393
|
-
}
|
|
8394
|
-
return app2;
|
|
8395
|
-
}
|
|
8396
|
-
|
|
8397
|
-
// src/archive/repository.ts
|
|
8398
|
-
import crypto5 from "crypto";
|
|
8399
|
-
import fs2 from "fs";
|
|
8400
|
-
import path from "path";
|
|
8401
|
-
import { fileURLToPath } from "url";
|
|
8402
|
-
import Database from "better-sqlite3";
|
|
8403
|
-
|
|
8404
|
-
// ../node_modules/.pnpm/drizzle-orm@0.45.2_@types+better-sqlite3@7.6.13_better-sqlite3@12.9.0/node_modules/drizzle-orm/better-sqlite3/driver.js
|
|
8405
|
-
import Client from "better-sqlite3";
|
|
8406
|
-
|
|
8407
8370
|
// ../node_modules/.pnpm/drizzle-orm@0.45.2_@types+better-sqlite3@7.6.13_better-sqlite3@12.9.0/node_modules/drizzle-orm/better-sqlite3/session.js
|
|
8408
8371
|
var BetterSQLiteSession = class extends SQLiteSession {
|
|
8409
8372
|
constructor(client, dialect, schema, options = {}) {
|
|
@@ -8563,7 +8526,7 @@ function drizzle(...params) {
|
|
|
8563
8526
|
})(drizzle || (drizzle = {}));
|
|
8564
8527
|
|
|
8565
8528
|
// ../node_modules/.pnpm/drizzle-orm@0.45.2_@types+better-sqlite3@7.6.13_better-sqlite3@12.9.0/node_modules/drizzle-orm/migrator.js
|
|
8566
|
-
import
|
|
8529
|
+
import crypto4 from "crypto";
|
|
8567
8530
|
import fs from "fs";
|
|
8568
8531
|
function readMigrationFiles(config) {
|
|
8569
8532
|
const migrationFolderTo = config.migrationsFolder;
|
|
@@ -8585,7 +8548,7 @@ function readMigrationFiles(config) {
|
|
|
8585
8548
|
sql: result,
|
|
8586
8549
|
bps: journalEntry.breakpoints,
|
|
8587
8550
|
folderMillis: journalEntry.when,
|
|
8588
|
-
hash:
|
|
8551
|
+
hash: crypto4.createHash("sha256").update(query).digest("hex")
|
|
8589
8552
|
});
|
|
8590
8553
|
} catch {
|
|
8591
8554
|
throw new Error(`No file ${migrationPath} found in ${migrationFolderTo} folder`);
|
|
@@ -8600,49 +8563,184 @@ function migrate(db, config) {
|
|
|
8600
8563
|
db.dialect.migrate(migrations, db.session, config);
|
|
8601
8564
|
}
|
|
8602
8565
|
|
|
8603
|
-
// src/
|
|
8604
|
-
|
|
8605
|
-
|
|
8606
|
-
var CHAT_ID_LENGTH = 6;
|
|
8607
|
-
var MAX_RETRIES = 5;
|
|
8608
|
-
function generateChatId({
|
|
8609
|
-
isTaken,
|
|
8610
|
-
randomIndex = () => crypto4.randomInt(CROCKFORD_ALPHABET.length)
|
|
8611
|
-
}) {
|
|
8612
|
-
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
8613
|
-
let code = "";
|
|
8614
|
-
for (let i = 0; i < CHAT_ID_LENGTH; i++) {
|
|
8615
|
-
code += CROCKFORD_ALPHABET[randomIndex()];
|
|
8616
|
-
}
|
|
8617
|
-
if (!isTaken(code)) {
|
|
8618
|
-
return code;
|
|
8619
|
-
}
|
|
8620
|
-
}
|
|
8621
|
-
throw new Error(
|
|
8622
|
-
`Failed to generate unique chat_id after ${MAX_RETRIES + 1} attempts`
|
|
8623
|
-
);
|
|
8624
|
-
}
|
|
8625
|
-
|
|
8626
|
-
// src/archive/repository.ts
|
|
8627
|
-
function resolveMigrationsFolder() {
|
|
8628
|
-
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
8566
|
+
// src/storage/openStore.ts
|
|
8567
|
+
function resolveMigrationsFolder(callerUrl, migrationsSubdir) {
|
|
8568
|
+
const here = path.dirname(fileURLToPath(callerUrl));
|
|
8629
8569
|
const candidates = [
|
|
8630
|
-
path.join(here, "
|
|
8631
|
-
path.join(here, "
|
|
8570
|
+
path.join(here, "../..", migrationsSubdir),
|
|
8571
|
+
path.join(here, ".", migrationsSubdir)
|
|
8632
8572
|
];
|
|
8633
8573
|
const found = candidates.find((p) => fs2.existsSync(p));
|
|
8634
8574
|
if (!found) {
|
|
8635
|
-
throw new Error(
|
|
8575
|
+
throw new Error(`Could not locate migrations folder "${migrationsSubdir}"`);
|
|
8636
8576
|
}
|
|
8637
8577
|
return found;
|
|
8638
8578
|
}
|
|
8579
|
+
function openStore({
|
|
8580
|
+
dataDir: dataDir2,
|
|
8581
|
+
dbFile,
|
|
8582
|
+
callerUrl,
|
|
8583
|
+
migrationsSubdir,
|
|
8584
|
+
schema
|
|
8585
|
+
}) {
|
|
8586
|
+
const migrationsFolder = resolveMigrationsFolder(callerUrl, migrationsSubdir);
|
|
8587
|
+
fs2.mkdirSync(dataDir2, { recursive: true });
|
|
8588
|
+
const sqlite = new Database(path.join(dataDir2, dbFile));
|
|
8589
|
+
const db = drizzle(sqlite, { schema });
|
|
8590
|
+
migrate(db, { migrationsFolder });
|
|
8591
|
+
return { db, sqlite };
|
|
8592
|
+
}
|
|
8593
|
+
|
|
8594
|
+
// src/archive/schema.ts
|
|
8595
|
+
var schema_exports = {};
|
|
8596
|
+
__export(schema_exports, {
|
|
8597
|
+
archiveMeta: () => archiveMeta,
|
|
8598
|
+
chats: () => chats,
|
|
8599
|
+
ingestionEvents: () => ingestionEvents,
|
|
8600
|
+
messages: () => messages,
|
|
8601
|
+
rawMessages: () => rawMessages,
|
|
8602
|
+
schemaVersion: () => schemaVersion
|
|
8603
|
+
});
|
|
8604
|
+
var archiveMeta = sqliteTable("archive_meta", {
|
|
8605
|
+
id: integer("id").primaryKey(),
|
|
8606
|
+
archiveUuid: text("archive_uuid").notNull(),
|
|
8607
|
+
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull()
|
|
8608
|
+
});
|
|
8609
|
+
var schemaVersion = sqliteTable("schema_version", {
|
|
8610
|
+
version: integer("version").primaryKey(),
|
|
8611
|
+
appliedAt: integer("applied_at", { mode: "timestamp_ms" }).notNull()
|
|
8612
|
+
});
|
|
8613
|
+
var chats = sqliteTable(
|
|
8614
|
+
"chats",
|
|
8615
|
+
{
|
|
8616
|
+
id: text("id").primaryKey(),
|
|
8617
|
+
chatId: text("chat_id").notNull().unique(),
|
|
8618
|
+
agent: text("agent").notNull(),
|
|
8619
|
+
sourceId: text("source_id").notNull(),
|
|
8620
|
+
firstSeenAt: integer("first_seen_at", { mode: "timestamp_ms" }).notNull(),
|
|
8621
|
+
project: text("project"),
|
|
8622
|
+
projectPath: text("project_path")
|
|
8623
|
+
},
|
|
8624
|
+
(t) => [uniqueIndex("chats_agent_source_idx").on(t.agent, t.sourceId)]
|
|
8625
|
+
);
|
|
8626
|
+
var rawMessages = sqliteTable(
|
|
8627
|
+
"raw_messages",
|
|
8628
|
+
{
|
|
8629
|
+
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
8630
|
+
agent: text("agent").notNull(),
|
|
8631
|
+
sourceId: text("source_id").notNull(),
|
|
8632
|
+
sourcePath: text("source_path").notNull(),
|
|
8633
|
+
sourceLocator: text("source_locator").notNull(),
|
|
8634
|
+
rawPayload: text("raw_payload").notNull(),
|
|
8635
|
+
payloadHash: text("payload_hash").notNull(),
|
|
8636
|
+
ingestedAt: integer("ingested_at", { mode: "timestamp_ms" }).notNull()
|
|
8637
|
+
},
|
|
8638
|
+
(t) => [
|
|
8639
|
+
uniqueIndex("raw_messages_idem_idx").on(t.agent, t.sourceId, t.payloadHash)
|
|
8640
|
+
]
|
|
8641
|
+
);
|
|
8642
|
+
var messages = sqliteTable(
|
|
8643
|
+
"messages",
|
|
8644
|
+
{
|
|
8645
|
+
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
8646
|
+
agent: text("agent").notNull(),
|
|
8647
|
+
sourceId: text("source_id").notNull(),
|
|
8648
|
+
messageId: text("message_id").notNull(),
|
|
8649
|
+
role: text("role").notNull(),
|
|
8650
|
+
ts: integer("ts", { mode: "timestamp_ms" }).notNull(),
|
|
8651
|
+
text: text("text").notNull(),
|
|
8652
|
+
blocks: text("blocks", { mode: "json" }).notNull(),
|
|
8653
|
+
rawId: integer("raw_id").notNull().references(() => rawMessages.id)
|
|
8654
|
+
},
|
|
8655
|
+
(t) => [
|
|
8656
|
+
uniqueIndex("messages_canonical_idx").on(t.agent, t.sourceId, t.messageId)
|
|
8657
|
+
]
|
|
8658
|
+
);
|
|
8659
|
+
var ingestionEvents = sqliteTable("ingestion_events", {
|
|
8660
|
+
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
8661
|
+
agent: text("agent").notNull(),
|
|
8662
|
+
sourceId: text("source_id").notNull(),
|
|
8663
|
+
sourcePath: text("source_path").notNull(),
|
|
8664
|
+
eventType: text("event_type").notNull(),
|
|
8665
|
+
detail: text("detail", { mode: "json" }).notNull(),
|
|
8666
|
+
observedAt: integer("observed_at", { mode: "timestamp_ms" }).notNull()
|
|
8667
|
+
});
|
|
8668
|
+
|
|
8669
|
+
// src/archive/read-seam.ts
|
|
8670
|
+
function createArchiveReadSeam(db) {
|
|
8671
|
+
return {
|
|
8672
|
+
listChatRows() {
|
|
8673
|
+
return db.select().from(chats).all();
|
|
8674
|
+
},
|
|
8675
|
+
findChatBySourceId(sourceId) {
|
|
8676
|
+
return db.select().from(chats).where(eq(chats.sourceId, sourceId)).get() ?? null;
|
|
8677
|
+
},
|
|
8678
|
+
findChatByChatId(chatId) {
|
|
8679
|
+
return db.select().from(chats).where(eq(chats.chatId, chatId)).get() ?? null;
|
|
8680
|
+
},
|
|
8681
|
+
listMessagesByChat(agent, sourceId) {
|
|
8682
|
+
return db.select().from(messages).where(and(eq(messages.agent, agent), eq(messages.sourceId, sourceId))).orderBy(asc(messages.ts)).all();
|
|
8683
|
+
},
|
|
8684
|
+
listChatTsRanges() {
|
|
8685
|
+
return db.select({
|
|
8686
|
+
agent: messages.agent,
|
|
8687
|
+
sourceId: messages.sourceId,
|
|
8688
|
+
minTs: sql`min(${messages.ts})`,
|
|
8689
|
+
maxTs: sql`max(${messages.ts})`
|
|
8690
|
+
}).from(messages).groupBy(messages.agent, messages.sourceId).all();
|
|
8691
|
+
},
|
|
8692
|
+
listLatestRawSourcePaths() {
|
|
8693
|
+
const ranked = db.select({
|
|
8694
|
+
agent: rawMessages.agent,
|
|
8695
|
+
sourceId: rawMessages.sourceId,
|
|
8696
|
+
sourcePath: rawMessages.sourcePath,
|
|
8697
|
+
rn: sql`row_number() over (partition by ${rawMessages.agent}, ${rawMessages.sourceId} order by ${rawMessages.ingestedAt} desc)`.as(
|
|
8698
|
+
"rn"
|
|
8699
|
+
)
|
|
8700
|
+
}).from(rawMessages).as("ranked_raw");
|
|
8701
|
+
return db.select({
|
|
8702
|
+
agent: ranked.agent,
|
|
8703
|
+
sourceId: ranked.sourceId,
|
|
8704
|
+
sourcePath: ranked.sourcePath
|
|
8705
|
+
}).from(ranked).where(eq(ranked.rn, 1)).all();
|
|
8706
|
+
},
|
|
8707
|
+
listFirstUserTexts() {
|
|
8708
|
+
const ranked = db.select({
|
|
8709
|
+
agent: messages.agent,
|
|
8710
|
+
sourceId: messages.sourceId,
|
|
8711
|
+
text: messages.text,
|
|
8712
|
+
rn: sql`row_number() over (partition by ${messages.agent}, ${messages.sourceId} order by ${messages.ts} asc)`.as(
|
|
8713
|
+
"rn"
|
|
8714
|
+
)
|
|
8715
|
+
}).from(messages).where(eq(messages.role, "user")).as("ranked_user");
|
|
8716
|
+
return db.select({
|
|
8717
|
+
agent: ranked.agent,
|
|
8718
|
+
sourceId: ranked.sourceId,
|
|
8719
|
+
text: ranked.text
|
|
8720
|
+
}).from(ranked).where(eq(ranked.rn, 1)).all();
|
|
8721
|
+
},
|
|
8722
|
+
listIngestionEvents() {
|
|
8723
|
+
return db.select().from(ingestionEvents).all();
|
|
8724
|
+
}
|
|
8725
|
+
};
|
|
8726
|
+
}
|
|
8727
|
+
|
|
8728
|
+
// src/archive/repository.ts
|
|
8729
|
+
function parseTs(ts) {
|
|
8730
|
+
const d = new Date(ts);
|
|
8731
|
+
if (Number.isNaN(d.getTime())) return /* @__PURE__ */ new Date(0);
|
|
8732
|
+
return d;
|
|
8733
|
+
}
|
|
8639
8734
|
function createArchiveRepository({
|
|
8640
8735
|
dataDir: dataDir2
|
|
8641
8736
|
}) {
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
|
|
8737
|
+
const { db, sqlite } = openStore({
|
|
8738
|
+
dataDir: dataDir2,
|
|
8739
|
+
dbFile: "archive.db",
|
|
8740
|
+
callerUrl: import.meta.url,
|
|
8741
|
+
migrationsSubdir: "drizzle/archive",
|
|
8742
|
+
schema: schema_exports
|
|
8743
|
+
});
|
|
8646
8744
|
const drizzleMigrations = sqlite.prepare("SELECT id, created_at FROM __drizzle_migrations ORDER BY id ASC").all();
|
|
8647
8745
|
for (const m of drizzleMigrations) {
|
|
8648
8746
|
db.insert(schemaVersion).values({ version: m.id, appliedAt: new Date(m.created_at) }).onConflictDoNothing().run();
|
|
@@ -8655,8 +8753,13 @@ function createArchiveRepository({
|
|
|
8655
8753
|
createdAt: /* @__PURE__ */ new Date()
|
|
8656
8754
|
}).run();
|
|
8657
8755
|
}
|
|
8756
|
+
function nextChatId() {
|
|
8757
|
+
return generateChatId({
|
|
8758
|
+
isTaken: (candidate) => db.select({ id: chats.id }).from(chats).where(eq(chats.chatId, candidate)).get() !== void 0
|
|
8759
|
+
});
|
|
8760
|
+
}
|
|
8658
8761
|
return {
|
|
8659
|
-
db,
|
|
8762
|
+
read: createArchiveReadSeam(db),
|
|
8660
8763
|
getArchiveUuid() {
|
|
8661
8764
|
const row = db.select().from(archiveMeta).get();
|
|
8662
8765
|
if (!row) {
|
|
@@ -8668,9 +8771,100 @@ function createArchiveRepository({
|
|
|
8668
8771
|
return db.select().from(schemaVersion).all().map((r) => ({ version: r.version, appliedAt: r.appliedAt }));
|
|
8669
8772
|
},
|
|
8670
8773
|
generateChatId() {
|
|
8671
|
-
return
|
|
8672
|
-
|
|
8673
|
-
|
|
8774
|
+
return nextChatId();
|
|
8775
|
+
},
|
|
8776
|
+
ensureChat(agent, sourceId, firstSeenAt, project, projectPath) {
|
|
8777
|
+
const existingChat = db.select().from(chats).where(and(eq(chats.agent, agent), eq(chats.sourceId, sourceId))).get();
|
|
8778
|
+
if (existingChat) {
|
|
8779
|
+
const updates = {};
|
|
8780
|
+
if (project && existingChat.project !== project) {
|
|
8781
|
+
updates.project = project;
|
|
8782
|
+
}
|
|
8783
|
+
if (projectPath && existingChat.projectPath !== projectPath) {
|
|
8784
|
+
updates.projectPath = projectPath;
|
|
8785
|
+
}
|
|
8786
|
+
if (Object.keys(updates).length > 0) {
|
|
8787
|
+
db.update(chats).set(updates).where(eq(chats.id, existingChat.id)).run();
|
|
8788
|
+
}
|
|
8789
|
+
return existingChat.id;
|
|
8790
|
+
}
|
|
8791
|
+
const id = crypto5.randomUUID();
|
|
8792
|
+
db.insert(chats).values({
|
|
8793
|
+
id,
|
|
8794
|
+
chatId: nextChatId(),
|
|
8795
|
+
agent,
|
|
8796
|
+
sourceId,
|
|
8797
|
+
firstSeenAt,
|
|
8798
|
+
project: project ?? null,
|
|
8799
|
+
projectPath: projectPath ?? null
|
|
8800
|
+
}).run();
|
|
8801
|
+
return id;
|
|
8802
|
+
},
|
|
8803
|
+
insertRawMessage(input) {
|
|
8804
|
+
const payloadJson = JSON.stringify(input.payload);
|
|
8805
|
+
const payloadHash = crypto5.createHash("sha256").update(payloadJson).digest("hex");
|
|
8806
|
+
const existing2 = db.select({ id: rawMessages.id }).from(rawMessages).where(
|
|
8807
|
+
and(
|
|
8808
|
+
eq(rawMessages.agent, input.agent),
|
|
8809
|
+
eq(rawMessages.sourceId, input.sourceId),
|
|
8810
|
+
eq(rawMessages.payloadHash, payloadHash)
|
|
8811
|
+
)
|
|
8812
|
+
).get();
|
|
8813
|
+
if (existing2) return { id: existing2.id, inserted: false };
|
|
8814
|
+
const inserted = db.insert(rawMessages).values({
|
|
8815
|
+
agent: input.agent,
|
|
8816
|
+
sourceId: input.sourceId,
|
|
8817
|
+
sourcePath: input.sourcePath,
|
|
8818
|
+
sourceLocator: input.sourceLocator,
|
|
8819
|
+
rawPayload: payloadJson,
|
|
8820
|
+
payloadHash,
|
|
8821
|
+
ingestedAt: input.ingestedAt
|
|
8822
|
+
}).returning({ id: rawMessages.id }).get();
|
|
8823
|
+
return { id: inserted.id, inserted: true };
|
|
8824
|
+
},
|
|
8825
|
+
upsertNormalizedMessage({ agent, sourceId, message, rawId }) {
|
|
8826
|
+
const existing2 = db.select().from(messages).where(
|
|
8827
|
+
and(
|
|
8828
|
+
eq(messages.agent, agent),
|
|
8829
|
+
eq(messages.sourceId, sourceId),
|
|
8830
|
+
eq(messages.messageId, message.messageId)
|
|
8831
|
+
)
|
|
8832
|
+
).get();
|
|
8833
|
+
const ts = parseTs(message.ts);
|
|
8834
|
+
if (!existing2) {
|
|
8835
|
+
db.insert(messages).values({
|
|
8836
|
+
agent,
|
|
8837
|
+
sourceId,
|
|
8838
|
+
messageId: message.messageId,
|
|
8839
|
+
role: message.role,
|
|
8840
|
+
ts,
|
|
8841
|
+
text: message.text,
|
|
8842
|
+
blocks: message.blocks,
|
|
8843
|
+
rawId
|
|
8844
|
+
}).run();
|
|
8845
|
+
return true;
|
|
8846
|
+
}
|
|
8847
|
+
if (ts.getTime() >= existing2.ts.getTime()) {
|
|
8848
|
+
db.update(messages).set({
|
|
8849
|
+
role: message.role,
|
|
8850
|
+
ts,
|
|
8851
|
+
text: message.text,
|
|
8852
|
+
blocks: message.blocks,
|
|
8853
|
+
rawId
|
|
8854
|
+
}).where(eq(messages.id, existing2.id)).run();
|
|
8855
|
+
return true;
|
|
8856
|
+
}
|
|
8857
|
+
return false;
|
|
8858
|
+
},
|
|
8859
|
+
recordIngestionEvent(event) {
|
|
8860
|
+
db.insert(ingestionEvents).values({
|
|
8861
|
+
agent: event.agent,
|
|
8862
|
+
sourceId: event.sourceId,
|
|
8863
|
+
sourcePath: event.sourcePath,
|
|
8864
|
+
eventType: event.eventType,
|
|
8865
|
+
detail: event.detail,
|
|
8866
|
+
observedAt: event.observedAt ?? /* @__PURE__ */ new Date()
|
|
8867
|
+
}).run();
|
|
8674
8868
|
},
|
|
8675
8869
|
close() {
|
|
8676
8870
|
sqlite.close();
|
|
@@ -8678,12 +8872,6 @@ function createArchiveRepository({
|
|
|
8678
8872
|
};
|
|
8679
8873
|
}
|
|
8680
8874
|
|
|
8681
|
-
// src/checkpoint/repository.ts
|
|
8682
|
-
import fs3 from "fs";
|
|
8683
|
-
import path2 from "path";
|
|
8684
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8685
|
-
import Database2 from "better-sqlite3";
|
|
8686
|
-
|
|
8687
8875
|
// src/checkpoint/schema.ts
|
|
8688
8876
|
var schema_exports2 = {};
|
|
8689
8877
|
__export(schema_exports2, {
|
|
@@ -8706,25 +8894,16 @@ var chatScanState = sqliteTable(
|
|
|
8706
8894
|
);
|
|
8707
8895
|
|
|
8708
8896
|
// src/checkpoint/repository.ts
|
|
8709
|
-
function resolveMigrationsFolder2() {
|
|
8710
|
-
const here = path2.dirname(fileURLToPath2(import.meta.url));
|
|
8711
|
-
const candidates = [
|
|
8712
|
-
path2.join(here, "../../drizzle/checkpoint"),
|
|
8713
|
-
path2.join(here, "./drizzle/checkpoint")
|
|
8714
|
-
];
|
|
8715
|
-
const found = candidates.find((p) => fs3.existsSync(p));
|
|
8716
|
-
if (!found) {
|
|
8717
|
-
throw new Error("Could not locate checkpoint drizzle migrations folder");
|
|
8718
|
-
}
|
|
8719
|
-
return found;
|
|
8720
|
-
}
|
|
8721
8897
|
function createCheckpointRepository({
|
|
8722
8898
|
dataDir: dataDir2
|
|
8723
8899
|
}) {
|
|
8724
|
-
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
|
|
8900
|
+
const { db, sqlite } = openStore({
|
|
8901
|
+
dataDir: dataDir2,
|
|
8902
|
+
dbFile: "checkpoint.db",
|
|
8903
|
+
callerUrl: import.meta.url,
|
|
8904
|
+
migrationsSubdir: "drizzle/checkpoint",
|
|
8905
|
+
schema: schema_exports2
|
|
8906
|
+
});
|
|
8728
8907
|
return {
|
|
8729
8908
|
db,
|
|
8730
8909
|
getScanState(agent, sourceId) {
|
|
@@ -8772,12 +8951,14 @@ function createCheckpointRepository({
|
|
|
8772
8951
|
}
|
|
8773
8952
|
|
|
8774
8953
|
// src/metadata/repository.ts
|
|
8775
|
-
import
|
|
8776
|
-
import
|
|
8777
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
8778
|
-
import Database3 from "better-sqlite3";
|
|
8954
|
+
import fs3 from "fs";
|
|
8955
|
+
import path2 from "path";
|
|
8779
8956
|
|
|
8780
8957
|
// src/metadata/schema.ts
|
|
8958
|
+
var schema_exports3 = {};
|
|
8959
|
+
__export(schema_exports3, {
|
|
8960
|
+
chatsMeta: () => chatsMeta
|
|
8961
|
+
});
|
|
8781
8962
|
var chatsMeta = sqliteTable("chats_meta", {
|
|
8782
8963
|
id: text("id").primaryKey(),
|
|
8783
8964
|
isDeleted: integer("is_deleted", { mode: "boolean" }).notNull().default(false),
|
|
@@ -8790,40 +8971,31 @@ var chatsMeta = sqliteTable("chats_meta", {
|
|
|
8790
8971
|
});
|
|
8791
8972
|
|
|
8792
8973
|
// src/metadata/repository.ts
|
|
8793
|
-
function resolveMigrationsFolder3() {
|
|
8794
|
-
const here = path3.dirname(fileURLToPath3(import.meta.url));
|
|
8795
|
-
const candidates = [
|
|
8796
|
-
path3.join(here, "../../drizzle"),
|
|
8797
|
-
path3.join(here, "./drizzle")
|
|
8798
|
-
];
|
|
8799
|
-
const found = candidates.find((p) => fs4.existsSync(p));
|
|
8800
|
-
if (!found) {
|
|
8801
|
-
throw new Error("Could not locate drizzle migrations folder");
|
|
8802
|
-
}
|
|
8803
|
-
return found;
|
|
8804
|
-
}
|
|
8805
8974
|
var DB_FILE = "metadata.db";
|
|
8806
8975
|
var LEGACY_DB_FILE = "data.db";
|
|
8807
8976
|
function migrateLegacyDbFile(dataDir2) {
|
|
8808
|
-
const legacy =
|
|
8809
|
-
const current =
|
|
8810
|
-
if (!
|
|
8811
|
-
if (
|
|
8812
|
-
|
|
8977
|
+
const legacy = path2.join(dataDir2, LEGACY_DB_FILE);
|
|
8978
|
+
const current = path2.join(dataDir2, DB_FILE);
|
|
8979
|
+
if (!fs3.existsSync(legacy)) return;
|
|
8980
|
+
if (fs3.existsSync(current)) return;
|
|
8981
|
+
fs3.renameSync(legacy, current);
|
|
8813
8982
|
}
|
|
8814
|
-
var
|
|
8983
|
+
var CLAUDE_CODE_AGENT = "claude-code";
|
|
8815
8984
|
function createMetadataRepository({
|
|
8816
8985
|
dataDir: dataDir2,
|
|
8817
8986
|
lookupInternalId,
|
|
8818
|
-
ensureChat
|
|
8987
|
+
ensureChat
|
|
8819
8988
|
}) {
|
|
8820
|
-
fs4.mkdirSync(dataDir2, { recursive: true });
|
|
8821
8989
|
migrateLegacyDbFile(dataDir2);
|
|
8822
|
-
const sqlite =
|
|
8823
|
-
|
|
8824
|
-
|
|
8990
|
+
const { db, sqlite } = openStore({
|
|
8991
|
+
dataDir: dataDir2,
|
|
8992
|
+
dbFile: DB_FILE,
|
|
8993
|
+
callerUrl: import.meta.url,
|
|
8994
|
+
migrationsSubdir: "drizzle",
|
|
8995
|
+
schema: schema_exports3
|
|
8996
|
+
});
|
|
8825
8997
|
if (lookupInternalId) {
|
|
8826
|
-
rekeyLegacyRows(sqlite, db, lookupInternalId,
|
|
8998
|
+
rekeyLegacyRows(sqlite, db, lookupInternalId, ensureChat);
|
|
8827
8999
|
}
|
|
8828
9000
|
return {
|
|
8829
9001
|
softDelete(internalId) {
|
|
@@ -8859,6 +9031,14 @@ function createMetadataRepository({
|
|
|
8859
9031
|
const row = db.select({ customTitle: chatsMeta.customTitle }).from(chatsMeta).where(eq(chatsMeta.id, internalId)).get();
|
|
8860
9032
|
return row?.customTitle ?? null;
|
|
8861
9033
|
},
|
|
9034
|
+
listCustomTitles() {
|
|
9035
|
+
const rows = db.select({ id: chatsMeta.id, customTitle: chatsMeta.customTitle }).from(chatsMeta).where(isNotNull(chatsMeta.customTitle)).all();
|
|
9036
|
+
const byId = /* @__PURE__ */ new Map();
|
|
9037
|
+
for (const row of rows) {
|
|
9038
|
+
if (row.customTitle !== null) byId.set(row.id, row.customTitle);
|
|
9039
|
+
}
|
|
9040
|
+
return byId;
|
|
9041
|
+
},
|
|
8862
9042
|
setCustomTitle(internalId, title) {
|
|
8863
9043
|
const now = /* @__PURE__ */ new Date();
|
|
8864
9044
|
db.insert(chatsMeta).values({
|
|
@@ -8874,15 +9054,15 @@ function createMetadataRepository({
|
|
|
8874
9054
|
};
|
|
8875
9055
|
}
|
|
8876
9056
|
var REKEY_USER_VERSION = 4;
|
|
8877
|
-
function rekeyLegacyRows(sqlite, db, lookupInternalId,
|
|
9057
|
+
function rekeyLegacyRows(sqlite, db, lookupInternalId, ensureChat) {
|
|
8878
9058
|
const current = sqlite.pragma("user_version", { simple: true });
|
|
8879
9059
|
if (current >= REKEY_USER_VERSION) return;
|
|
8880
9060
|
const rows = db.select({ id: chatsMeta.id }).from(chatsMeta).all();
|
|
8881
9061
|
for (const row of rows) {
|
|
8882
|
-
let target = lookupInternalId(
|
|
9062
|
+
let target = lookupInternalId(CLAUDE_CODE_AGENT, row.id);
|
|
8883
9063
|
if (target === null) {
|
|
8884
|
-
if (!
|
|
8885
|
-
target =
|
|
9064
|
+
if (!ensureChat) continue;
|
|
9065
|
+
target = ensureChat(CLAUDE_CODE_AGENT, row.id);
|
|
8886
9066
|
}
|
|
8887
9067
|
if (target === row.id) continue;
|
|
8888
9068
|
db.update(chatsMeta).set({ id: target, updatedAt: /* @__PURE__ */ new Date() }).where(eq(chatsMeta.id, row.id)).run();
|
|
@@ -8891,8 +9071,7 @@ function rekeyLegacyRows(sqlite, db, lookupInternalId, ensureChat2) {
|
|
|
8891
9071
|
}
|
|
8892
9072
|
|
|
8893
9073
|
// src/ingestion/ingest.ts
|
|
8894
|
-
import
|
|
8895
|
-
import fs5 from "fs";
|
|
9074
|
+
import fs4 from "fs";
|
|
8896
9075
|
async function runIngestion(opts) {
|
|
8897
9076
|
const now = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
8898
9077
|
const result = {
|
|
@@ -8906,8 +9085,7 @@ async function runIngestion(opts) {
|
|
|
8906
9085
|
result.scanned += 1;
|
|
8907
9086
|
const stat4 = safeStat(ref.sourcePath);
|
|
8908
9087
|
const prior = opts.checkpoint.getScanState(plugin.id, ref.sourceId);
|
|
8909
|
-
ensureChat(
|
|
8910
|
-
opts.archive,
|
|
9088
|
+
opts.archive.ensureChat(
|
|
8911
9089
|
plugin.id,
|
|
8912
9090
|
ref.sourceId,
|
|
8913
9091
|
now(),
|
|
@@ -8919,40 +9097,23 @@ async function runIngestion(opts) {
|
|
|
8919
9097
|
continue;
|
|
8920
9098
|
}
|
|
8921
9099
|
for await (const raw2 of plugin.extractRaw(ref)) {
|
|
8922
|
-
const
|
|
8923
|
-
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
).
|
|
8931
|
-
let rawId;
|
|
8932
|
-
if (existing) {
|
|
8933
|
-
rawId = existing.id;
|
|
8934
|
-
} else {
|
|
8935
|
-
const inserted = opts.archive.db.insert(rawMessages).values({
|
|
8936
|
-
agent: plugin.id,
|
|
8937
|
-
sourceId: ref.sourceId,
|
|
8938
|
-
sourcePath: raw2.sourcePath,
|
|
8939
|
-
sourceLocator: raw2.sourceLocator,
|
|
8940
|
-
rawPayload: payloadJson,
|
|
8941
|
-
payloadHash,
|
|
8942
|
-
ingestedAt: now()
|
|
8943
|
-
}).returning({ id: rawMessages.id }).get();
|
|
8944
|
-
rawId = inserted.id;
|
|
8945
|
-
result.rawInserted += 1;
|
|
8946
|
-
}
|
|
9100
|
+
const { id: rawId, inserted } = opts.archive.insertRawMessage({
|
|
9101
|
+
agent: plugin.id,
|
|
9102
|
+
sourceId: ref.sourceId,
|
|
9103
|
+
sourcePath: raw2.sourcePath,
|
|
9104
|
+
sourceLocator: raw2.sourceLocator,
|
|
9105
|
+
payload: raw2.payload,
|
|
9106
|
+
ingestedAt: now()
|
|
9107
|
+
});
|
|
9108
|
+
if (inserted) result.rawInserted += 1;
|
|
8947
9109
|
const normalized = plugin.normalize(raw2);
|
|
8948
9110
|
if (!normalized) continue;
|
|
8949
|
-
const upserted =
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
8953
|
-
normalized,
|
|
9111
|
+
const upserted = opts.archive.upsertNormalizedMessage({
|
|
9112
|
+
agent: plugin.id,
|
|
9113
|
+
sourceId: ref.sourceId,
|
|
9114
|
+
message: normalized,
|
|
8954
9115
|
rawId
|
|
8955
|
-
);
|
|
9116
|
+
});
|
|
8956
9117
|
if (upserted) result.normalizedUpserted += 1;
|
|
8957
9118
|
}
|
|
8958
9119
|
if (stat4) {
|
|
@@ -8970,76 +9131,11 @@ async function runIngestion(opts) {
|
|
|
8970
9131
|
}
|
|
8971
9132
|
function safeStat(p) {
|
|
8972
9133
|
try {
|
|
8973
|
-
return
|
|
9134
|
+
return fs4.statSync(p);
|
|
8974
9135
|
} catch {
|
|
8975
9136
|
return null;
|
|
8976
9137
|
}
|
|
8977
9138
|
}
|
|
8978
|
-
function ensureChat(archive2, agent, sourceId, firstSeenAt, project, projectPath) {
|
|
8979
|
-
const existing = archive2.db.select().from(chats).where(and(eq(chats.agent, agent), eq(chats.sourceId, sourceId))).get();
|
|
8980
|
-
if (existing) {
|
|
8981
|
-
const updates = {};
|
|
8982
|
-
if (project && existing.project !== project) updates.project = project;
|
|
8983
|
-
if (projectPath && existing.projectPath !== projectPath) {
|
|
8984
|
-
updates.projectPath = projectPath;
|
|
8985
|
-
}
|
|
8986
|
-
if (Object.keys(updates).length > 0) {
|
|
8987
|
-
archive2.db.update(chats).set(updates).where(eq(chats.id, existing.id)).run();
|
|
8988
|
-
}
|
|
8989
|
-
return existing.id;
|
|
8990
|
-
}
|
|
8991
|
-
const id = crypto6.randomUUID();
|
|
8992
|
-
const chatId = archive2.generateChatId();
|
|
8993
|
-
archive2.db.insert(chats).values({
|
|
8994
|
-
id,
|
|
8995
|
-
chatId,
|
|
8996
|
-
agent,
|
|
8997
|
-
sourceId,
|
|
8998
|
-
firstSeenAt,
|
|
8999
|
-
project: project ?? null,
|
|
9000
|
-
projectPath: projectPath ?? null
|
|
9001
|
-
}).run();
|
|
9002
|
-
return id;
|
|
9003
|
-
}
|
|
9004
|
-
function upsertNormalized(archive2, agent, sourceId, msg, rawId) {
|
|
9005
|
-
const existing = archive2.db.select().from(messages).where(
|
|
9006
|
-
and(
|
|
9007
|
-
eq(messages.agent, agent),
|
|
9008
|
-
eq(messages.sourceId, sourceId),
|
|
9009
|
-
eq(messages.messageId, msg.messageId)
|
|
9010
|
-
)
|
|
9011
|
-
).get();
|
|
9012
|
-
const ts = parseTs(msg.ts);
|
|
9013
|
-
if (!existing) {
|
|
9014
|
-
archive2.db.insert(messages).values({
|
|
9015
|
-
agent,
|
|
9016
|
-
sourceId,
|
|
9017
|
-
messageId: msg.messageId,
|
|
9018
|
-
role: msg.role,
|
|
9019
|
-
ts,
|
|
9020
|
-
text: msg.text,
|
|
9021
|
-
blocks: msg.blocks,
|
|
9022
|
-
rawId
|
|
9023
|
-
}).run();
|
|
9024
|
-
return true;
|
|
9025
|
-
}
|
|
9026
|
-
if (ts.getTime() >= existing.ts.getTime()) {
|
|
9027
|
-
archive2.db.update(messages).set({
|
|
9028
|
-
role: msg.role,
|
|
9029
|
-
ts,
|
|
9030
|
-
text: msg.text,
|
|
9031
|
-
blocks: msg.blocks,
|
|
9032
|
-
rawId
|
|
9033
|
-
}).where(eq(messages.id, existing.id)).run();
|
|
9034
|
-
return true;
|
|
9035
|
-
}
|
|
9036
|
-
return false;
|
|
9037
|
-
}
|
|
9038
|
-
function parseTs(ts) {
|
|
9039
|
-
const d = new Date(ts);
|
|
9040
|
-
if (Number.isNaN(d.getTime())) return /* @__PURE__ */ new Date(0);
|
|
9041
|
-
return d;
|
|
9042
|
-
}
|
|
9043
9139
|
|
|
9044
9140
|
// src/ingestion/background.ts
|
|
9045
9141
|
function startIngestionInBackground(opts, bg = {}) {
|
|
@@ -9144,7 +9240,7 @@ var ReaddirpStream = class extends Readable3 {
|
|
|
9144
9240
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
9145
9241
|
const statMethod = opts.lstat ? lstat : stat;
|
|
9146
9242
|
if (wantBigintFsStats) {
|
|
9147
|
-
this._stat = (
|
|
9243
|
+
this._stat = (path5) => statMethod(path5, { bigint: true });
|
|
9148
9244
|
} else {
|
|
9149
9245
|
this._stat = statMethod;
|
|
9150
9246
|
}
|
|
@@ -9169,8 +9265,8 @@ var ReaddirpStream = class extends Readable3 {
|
|
|
9169
9265
|
const par = this.parent;
|
|
9170
9266
|
const fil = par && par.files;
|
|
9171
9267
|
if (fil && fil.length > 0) {
|
|
9172
|
-
const { path:
|
|
9173
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
9268
|
+
const { path: path5, depth } = par;
|
|
9269
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path5));
|
|
9174
9270
|
const awaited = await Promise.all(slice);
|
|
9175
9271
|
for (const entry of awaited) {
|
|
9176
9272
|
if (!entry)
|
|
@@ -9210,20 +9306,20 @@ var ReaddirpStream = class extends Readable3 {
|
|
|
9210
9306
|
this.reading = false;
|
|
9211
9307
|
}
|
|
9212
9308
|
}
|
|
9213
|
-
async _exploreDir(
|
|
9309
|
+
async _exploreDir(path5, depth) {
|
|
9214
9310
|
let files;
|
|
9215
9311
|
try {
|
|
9216
|
-
files = await readdir(
|
|
9312
|
+
files = await readdir(path5, this._rdOptions);
|
|
9217
9313
|
} catch (error) {
|
|
9218
9314
|
this._onError(error);
|
|
9219
9315
|
}
|
|
9220
|
-
return { files, depth, path:
|
|
9316
|
+
return { files, depth, path: path5 };
|
|
9221
9317
|
}
|
|
9222
|
-
async _formatEntry(dirent,
|
|
9318
|
+
async _formatEntry(dirent, path5) {
|
|
9223
9319
|
let entry;
|
|
9224
9320
|
const basename3 = this._isDirent ? dirent.name : dirent;
|
|
9225
9321
|
try {
|
|
9226
|
-
const fullPath = presolve(pjoin(
|
|
9322
|
+
const fullPath = presolve(pjoin(path5, basename3));
|
|
9227
9323
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename3 };
|
|
9228
9324
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
9229
9325
|
} catch (err) {
|
|
@@ -9623,16 +9719,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
9623
9719
|
};
|
|
9624
9720
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
9625
9721
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
9626
|
-
function createFsWatchInstance(
|
|
9722
|
+
function createFsWatchInstance(path5, options, listener, errHandler, emitRaw) {
|
|
9627
9723
|
const handleEvent = (rawEvent, evPath) => {
|
|
9628
|
-
listener(
|
|
9629
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
9630
|
-
if (evPath &&
|
|
9631
|
-
fsWatchBroadcast(sp.resolve(
|
|
9724
|
+
listener(path5);
|
|
9725
|
+
emitRaw(rawEvent, evPath, { watchedPath: path5 });
|
|
9726
|
+
if (evPath && path5 !== evPath) {
|
|
9727
|
+
fsWatchBroadcast(sp.resolve(path5, evPath), KEY_LISTENERS, sp.join(path5, evPath));
|
|
9632
9728
|
}
|
|
9633
9729
|
};
|
|
9634
9730
|
try {
|
|
9635
|
-
return fs_watch(
|
|
9731
|
+
return fs_watch(path5, {
|
|
9636
9732
|
persistent: options.persistent
|
|
9637
9733
|
}, handleEvent);
|
|
9638
9734
|
} catch (error) {
|
|
@@ -9648,12 +9744,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
9648
9744
|
listener(val1, val2, val3);
|
|
9649
9745
|
});
|
|
9650
9746
|
};
|
|
9651
|
-
var setFsWatchListener = (
|
|
9747
|
+
var setFsWatchListener = (path5, fullPath, options, handlers) => {
|
|
9652
9748
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
9653
9749
|
let cont = FsWatchInstances.get(fullPath);
|
|
9654
9750
|
let watcher2;
|
|
9655
9751
|
if (!options.persistent) {
|
|
9656
|
-
watcher2 = createFsWatchInstance(
|
|
9752
|
+
watcher2 = createFsWatchInstance(path5, options, listener, errHandler, rawEmitter);
|
|
9657
9753
|
if (!watcher2)
|
|
9658
9754
|
return;
|
|
9659
9755
|
return watcher2.close.bind(watcher2);
|
|
@@ -9664,7 +9760,7 @@ var setFsWatchListener = (path6, fullPath, options, handlers) => {
|
|
|
9664
9760
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
9665
9761
|
} else {
|
|
9666
9762
|
watcher2 = createFsWatchInstance(
|
|
9667
|
-
|
|
9763
|
+
path5,
|
|
9668
9764
|
options,
|
|
9669
9765
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
9670
9766
|
errHandler,
|
|
@@ -9679,7 +9775,7 @@ var setFsWatchListener = (path6, fullPath, options, handlers) => {
|
|
|
9679
9775
|
cont.watcherUnusable = true;
|
|
9680
9776
|
if (isWindows && error.code === "EPERM") {
|
|
9681
9777
|
try {
|
|
9682
|
-
const fd = await open(
|
|
9778
|
+
const fd = await open(path5, "r");
|
|
9683
9779
|
await fd.close();
|
|
9684
9780
|
broadcastErr(error);
|
|
9685
9781
|
} catch (err) {
|
|
@@ -9710,7 +9806,7 @@ var setFsWatchListener = (path6, fullPath, options, handlers) => {
|
|
|
9710
9806
|
};
|
|
9711
9807
|
};
|
|
9712
9808
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
9713
|
-
var setFsWatchFileListener = (
|
|
9809
|
+
var setFsWatchFileListener = (path5, fullPath, options, handlers) => {
|
|
9714
9810
|
const { listener, rawEmitter } = handlers;
|
|
9715
9811
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
9716
9812
|
const copts = cont && cont.options;
|
|
@@ -9732,7 +9828,7 @@ var setFsWatchFileListener = (path6, fullPath, options, handlers) => {
|
|
|
9732
9828
|
});
|
|
9733
9829
|
const currmtime = curr.mtimeMs;
|
|
9734
9830
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
9735
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
9831
|
+
foreach(cont.listeners, (listener2) => listener2(path5, curr));
|
|
9736
9832
|
}
|
|
9737
9833
|
})
|
|
9738
9834
|
};
|
|
@@ -9762,13 +9858,13 @@ var NodeFsHandler = class {
|
|
|
9762
9858
|
* @param listener on fs change
|
|
9763
9859
|
* @returns closer for the watcher instance
|
|
9764
9860
|
*/
|
|
9765
|
-
_watchWithNodeFs(
|
|
9861
|
+
_watchWithNodeFs(path5, listener) {
|
|
9766
9862
|
const opts = this.fsw.options;
|
|
9767
|
-
const directory = sp.dirname(
|
|
9768
|
-
const basename3 = sp.basename(
|
|
9863
|
+
const directory = sp.dirname(path5);
|
|
9864
|
+
const basename3 = sp.basename(path5);
|
|
9769
9865
|
const parent = this.fsw._getWatchedDir(directory);
|
|
9770
9866
|
parent.add(basename3);
|
|
9771
|
-
const absolutePath = sp.resolve(
|
|
9867
|
+
const absolutePath = sp.resolve(path5);
|
|
9772
9868
|
const options = {
|
|
9773
9869
|
persistent: opts.persistent
|
|
9774
9870
|
};
|
|
@@ -9778,12 +9874,12 @@ var NodeFsHandler = class {
|
|
|
9778
9874
|
if (opts.usePolling) {
|
|
9779
9875
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
9780
9876
|
options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
|
|
9781
|
-
closer = setFsWatchFileListener(
|
|
9877
|
+
closer = setFsWatchFileListener(path5, absolutePath, options, {
|
|
9782
9878
|
listener,
|
|
9783
9879
|
rawEmitter: this.fsw._emitRaw
|
|
9784
9880
|
});
|
|
9785
9881
|
} else {
|
|
9786
|
-
closer = setFsWatchListener(
|
|
9882
|
+
closer = setFsWatchListener(path5, absolutePath, options, {
|
|
9787
9883
|
listener,
|
|
9788
9884
|
errHandler: this._boundHandleError,
|
|
9789
9885
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -9805,7 +9901,7 @@ var NodeFsHandler = class {
|
|
|
9805
9901
|
let prevStats = stats;
|
|
9806
9902
|
if (parent.has(basename3))
|
|
9807
9903
|
return;
|
|
9808
|
-
const listener = async (
|
|
9904
|
+
const listener = async (path5, newStats) => {
|
|
9809
9905
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
9810
9906
|
return;
|
|
9811
9907
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -9819,11 +9915,11 @@ var NodeFsHandler = class {
|
|
|
9819
9915
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
9820
9916
|
}
|
|
9821
9917
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
9822
|
-
this.fsw._closeFile(
|
|
9918
|
+
this.fsw._closeFile(path5);
|
|
9823
9919
|
prevStats = newStats2;
|
|
9824
9920
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
9825
9921
|
if (closer2)
|
|
9826
|
-
this.fsw._addPathCloser(
|
|
9922
|
+
this.fsw._addPathCloser(path5, closer2);
|
|
9827
9923
|
} else {
|
|
9828
9924
|
prevStats = newStats2;
|
|
9829
9925
|
}
|
|
@@ -9855,7 +9951,7 @@ var NodeFsHandler = class {
|
|
|
9855
9951
|
* @param item basename of this item
|
|
9856
9952
|
* @returns true if no more processing is needed for this entry.
|
|
9857
9953
|
*/
|
|
9858
|
-
async _handleSymlink(entry, directory,
|
|
9954
|
+
async _handleSymlink(entry, directory, path5, item) {
|
|
9859
9955
|
if (this.fsw.closed) {
|
|
9860
9956
|
return;
|
|
9861
9957
|
}
|
|
@@ -9865,7 +9961,7 @@ var NodeFsHandler = class {
|
|
|
9865
9961
|
this.fsw._incrReadyCount();
|
|
9866
9962
|
let linkPath;
|
|
9867
9963
|
try {
|
|
9868
|
-
linkPath = await fsrealpath(
|
|
9964
|
+
linkPath = await fsrealpath(path5);
|
|
9869
9965
|
} catch (e) {
|
|
9870
9966
|
this.fsw._emitReady();
|
|
9871
9967
|
return true;
|
|
@@ -9875,12 +9971,12 @@ var NodeFsHandler = class {
|
|
|
9875
9971
|
if (dir.has(item)) {
|
|
9876
9972
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
9877
9973
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
9878
|
-
this.fsw._emit(EV.CHANGE,
|
|
9974
|
+
this.fsw._emit(EV.CHANGE, path5, entry.stats);
|
|
9879
9975
|
}
|
|
9880
9976
|
} else {
|
|
9881
9977
|
dir.add(item);
|
|
9882
9978
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
9883
|
-
this.fsw._emit(EV.ADD,
|
|
9979
|
+
this.fsw._emit(EV.ADD, path5, entry.stats);
|
|
9884
9980
|
}
|
|
9885
9981
|
this.fsw._emitReady();
|
|
9886
9982
|
return true;
|
|
@@ -9910,9 +10006,9 @@ var NodeFsHandler = class {
|
|
|
9910
10006
|
return;
|
|
9911
10007
|
}
|
|
9912
10008
|
const item = entry.path;
|
|
9913
|
-
let
|
|
10009
|
+
let path5 = sp.join(directory, item);
|
|
9914
10010
|
current.add(item);
|
|
9915
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
10011
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path5, item)) {
|
|
9916
10012
|
return;
|
|
9917
10013
|
}
|
|
9918
10014
|
if (this.fsw.closed) {
|
|
@@ -9921,8 +10017,8 @@ var NodeFsHandler = class {
|
|
|
9921
10017
|
}
|
|
9922
10018
|
if (item === target || !target && !previous.has(item)) {
|
|
9923
10019
|
this.fsw._incrReadyCount();
|
|
9924
|
-
|
|
9925
|
-
this._addToNodeFs(
|
|
10020
|
+
path5 = sp.join(dir, sp.relative(dir, path5));
|
|
10021
|
+
this._addToNodeFs(path5, initialAdd, wh, depth + 1);
|
|
9926
10022
|
}
|
|
9927
10023
|
}).on(EV.ERROR, this._boundHandleError);
|
|
9928
10024
|
return new Promise((resolve3, reject) => {
|
|
@@ -9991,13 +10087,13 @@ var NodeFsHandler = class {
|
|
|
9991
10087
|
* @param depth Child path actually targeted for watch
|
|
9992
10088
|
* @param target Child path actually targeted for watch
|
|
9993
10089
|
*/
|
|
9994
|
-
async _addToNodeFs(
|
|
10090
|
+
async _addToNodeFs(path5, initialAdd, priorWh, depth, target) {
|
|
9995
10091
|
const ready = this.fsw._emitReady;
|
|
9996
|
-
if (this.fsw._isIgnored(
|
|
10092
|
+
if (this.fsw._isIgnored(path5) || this.fsw.closed) {
|
|
9997
10093
|
ready();
|
|
9998
10094
|
return false;
|
|
9999
10095
|
}
|
|
10000
|
-
const wh = this.fsw._getWatchHelpers(
|
|
10096
|
+
const wh = this.fsw._getWatchHelpers(path5);
|
|
10001
10097
|
if (priorWh) {
|
|
10002
10098
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
10003
10099
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -10013,8 +10109,8 @@ var NodeFsHandler = class {
|
|
|
10013
10109
|
const follow = this.fsw.options.followSymlinks;
|
|
10014
10110
|
let closer;
|
|
10015
10111
|
if (stats.isDirectory()) {
|
|
10016
|
-
const absPath = sp.resolve(
|
|
10017
|
-
const targetPath = follow ? await fsrealpath(
|
|
10112
|
+
const absPath = sp.resolve(path5);
|
|
10113
|
+
const targetPath = follow ? await fsrealpath(path5) : path5;
|
|
10018
10114
|
if (this.fsw.closed)
|
|
10019
10115
|
return;
|
|
10020
10116
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -10024,29 +10120,29 @@ var NodeFsHandler = class {
|
|
|
10024
10120
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
10025
10121
|
}
|
|
10026
10122
|
} else if (stats.isSymbolicLink()) {
|
|
10027
|
-
const targetPath = follow ? await fsrealpath(
|
|
10123
|
+
const targetPath = follow ? await fsrealpath(path5) : path5;
|
|
10028
10124
|
if (this.fsw.closed)
|
|
10029
10125
|
return;
|
|
10030
10126
|
const parent = sp.dirname(wh.watchPath);
|
|
10031
10127
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
10032
10128
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
10033
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
10129
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path5, wh, targetPath);
|
|
10034
10130
|
if (this.fsw.closed)
|
|
10035
10131
|
return;
|
|
10036
10132
|
if (targetPath !== void 0) {
|
|
10037
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
10133
|
+
this.fsw._symlinkPaths.set(sp.resolve(path5), targetPath);
|
|
10038
10134
|
}
|
|
10039
10135
|
} else {
|
|
10040
10136
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
10041
10137
|
}
|
|
10042
10138
|
ready();
|
|
10043
10139
|
if (closer)
|
|
10044
|
-
this.fsw._addPathCloser(
|
|
10140
|
+
this.fsw._addPathCloser(path5, closer);
|
|
10045
10141
|
return false;
|
|
10046
10142
|
} catch (error) {
|
|
10047
10143
|
if (this.fsw._handleError(error)) {
|
|
10048
10144
|
ready();
|
|
10049
|
-
return
|
|
10145
|
+
return path5;
|
|
10050
10146
|
}
|
|
10051
10147
|
}
|
|
10052
10148
|
}
|
|
@@ -10089,24 +10185,24 @@ function createPattern(matcher) {
|
|
|
10089
10185
|
}
|
|
10090
10186
|
return () => false;
|
|
10091
10187
|
}
|
|
10092
|
-
function normalizePath(
|
|
10093
|
-
if (typeof
|
|
10188
|
+
function normalizePath(path5) {
|
|
10189
|
+
if (typeof path5 !== "string")
|
|
10094
10190
|
throw new Error("string expected");
|
|
10095
|
-
|
|
10096
|
-
|
|
10191
|
+
path5 = sp2.normalize(path5);
|
|
10192
|
+
path5 = path5.replace(/\\/g, "/");
|
|
10097
10193
|
let prepend = false;
|
|
10098
|
-
if (
|
|
10194
|
+
if (path5.startsWith("//"))
|
|
10099
10195
|
prepend = true;
|
|
10100
|
-
|
|
10196
|
+
path5 = path5.replace(DOUBLE_SLASH_RE, "/");
|
|
10101
10197
|
if (prepend)
|
|
10102
|
-
|
|
10103
|
-
return
|
|
10198
|
+
path5 = "/" + path5;
|
|
10199
|
+
return path5;
|
|
10104
10200
|
}
|
|
10105
10201
|
function matchPatterns(patterns, testString, stats) {
|
|
10106
|
-
const
|
|
10202
|
+
const path5 = normalizePath(testString);
|
|
10107
10203
|
for (let index = 0; index < patterns.length; index++) {
|
|
10108
10204
|
const pattern = patterns[index];
|
|
10109
|
-
if (pattern(
|
|
10205
|
+
if (pattern(path5, stats)) {
|
|
10110
10206
|
return true;
|
|
10111
10207
|
}
|
|
10112
10208
|
}
|
|
@@ -10144,19 +10240,19 @@ var toUnix = (string) => {
|
|
|
10144
10240
|
}
|
|
10145
10241
|
return str;
|
|
10146
10242
|
};
|
|
10147
|
-
var normalizePathToUnix = (
|
|
10148
|
-
var normalizeIgnored = (cwd = "") => (
|
|
10149
|
-
if (typeof
|
|
10150
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
10243
|
+
var normalizePathToUnix = (path5) => toUnix(sp2.normalize(toUnix(path5)));
|
|
10244
|
+
var normalizeIgnored = (cwd = "") => (path5) => {
|
|
10245
|
+
if (typeof path5 === "string") {
|
|
10246
|
+
return normalizePathToUnix(sp2.isAbsolute(path5) ? path5 : sp2.join(cwd, path5));
|
|
10151
10247
|
} else {
|
|
10152
|
-
return
|
|
10248
|
+
return path5;
|
|
10153
10249
|
}
|
|
10154
10250
|
};
|
|
10155
|
-
var getAbsolutePath = (
|
|
10156
|
-
if (sp2.isAbsolute(
|
|
10157
|
-
return
|
|
10251
|
+
var getAbsolutePath = (path5, cwd) => {
|
|
10252
|
+
if (sp2.isAbsolute(path5)) {
|
|
10253
|
+
return path5;
|
|
10158
10254
|
}
|
|
10159
|
-
return sp2.join(cwd,
|
|
10255
|
+
return sp2.join(cwd, path5);
|
|
10160
10256
|
};
|
|
10161
10257
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
10162
10258
|
var DirEntry = class {
|
|
@@ -10221,10 +10317,10 @@ var WatchHelper = class {
|
|
|
10221
10317
|
dirParts;
|
|
10222
10318
|
followSymlinks;
|
|
10223
10319
|
statMethod;
|
|
10224
|
-
constructor(
|
|
10320
|
+
constructor(path5, follow, fsw) {
|
|
10225
10321
|
this.fsw = fsw;
|
|
10226
|
-
const watchPath =
|
|
10227
|
-
this.path =
|
|
10322
|
+
const watchPath = path5;
|
|
10323
|
+
this.path = path5 = path5.replace(REPLACER_RE, "");
|
|
10228
10324
|
this.watchPath = watchPath;
|
|
10229
10325
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
10230
10326
|
this.dirParts = [];
|
|
@@ -10364,20 +10460,20 @@ var FSWatcher = class extends EventEmitter {
|
|
|
10364
10460
|
this._closePromise = void 0;
|
|
10365
10461
|
let paths = unifyPaths(paths_);
|
|
10366
10462
|
if (cwd) {
|
|
10367
|
-
paths = paths.map((
|
|
10368
|
-
const absPath = getAbsolutePath(
|
|
10463
|
+
paths = paths.map((path5) => {
|
|
10464
|
+
const absPath = getAbsolutePath(path5, cwd);
|
|
10369
10465
|
return absPath;
|
|
10370
10466
|
});
|
|
10371
10467
|
}
|
|
10372
|
-
paths.forEach((
|
|
10373
|
-
this._removeIgnoredPath(
|
|
10468
|
+
paths.forEach((path5) => {
|
|
10469
|
+
this._removeIgnoredPath(path5);
|
|
10374
10470
|
});
|
|
10375
10471
|
this._userIgnored = void 0;
|
|
10376
10472
|
if (!this._readyCount)
|
|
10377
10473
|
this._readyCount = 0;
|
|
10378
10474
|
this._readyCount += paths.length;
|
|
10379
|
-
Promise.all(paths.map(async (
|
|
10380
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
10475
|
+
Promise.all(paths.map(async (path5) => {
|
|
10476
|
+
const res = await this._nodeFsHandler._addToNodeFs(path5, !_internal, void 0, 0, _origAdd);
|
|
10381
10477
|
if (res)
|
|
10382
10478
|
this._emitReady();
|
|
10383
10479
|
return res;
|
|
@@ -10399,17 +10495,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
10399
10495
|
return this;
|
|
10400
10496
|
const paths = unifyPaths(paths_);
|
|
10401
10497
|
const { cwd } = this.options;
|
|
10402
|
-
paths.forEach((
|
|
10403
|
-
if (!sp2.isAbsolute(
|
|
10498
|
+
paths.forEach((path5) => {
|
|
10499
|
+
if (!sp2.isAbsolute(path5) && !this._closers.has(path5)) {
|
|
10404
10500
|
if (cwd)
|
|
10405
|
-
|
|
10406
|
-
|
|
10501
|
+
path5 = sp2.join(cwd, path5);
|
|
10502
|
+
path5 = sp2.resolve(path5);
|
|
10407
10503
|
}
|
|
10408
|
-
this._closePath(
|
|
10409
|
-
this._addIgnoredPath(
|
|
10410
|
-
if (this._watched.has(
|
|
10504
|
+
this._closePath(path5);
|
|
10505
|
+
this._addIgnoredPath(path5);
|
|
10506
|
+
if (this._watched.has(path5)) {
|
|
10411
10507
|
this._addIgnoredPath({
|
|
10412
|
-
path:
|
|
10508
|
+
path: path5,
|
|
10413
10509
|
recursive: true
|
|
10414
10510
|
});
|
|
10415
10511
|
}
|
|
@@ -10473,38 +10569,38 @@ var FSWatcher = class extends EventEmitter {
|
|
|
10473
10569
|
* @param stats arguments to be passed with event
|
|
10474
10570
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
10475
10571
|
*/
|
|
10476
|
-
async _emit(event,
|
|
10572
|
+
async _emit(event, path5, stats) {
|
|
10477
10573
|
if (this.closed)
|
|
10478
10574
|
return;
|
|
10479
10575
|
const opts = this.options;
|
|
10480
10576
|
if (isWindows)
|
|
10481
|
-
|
|
10577
|
+
path5 = sp2.normalize(path5);
|
|
10482
10578
|
if (opts.cwd)
|
|
10483
|
-
|
|
10484
|
-
const args = [
|
|
10579
|
+
path5 = sp2.relative(opts.cwd, path5);
|
|
10580
|
+
const args = [path5];
|
|
10485
10581
|
if (stats != null)
|
|
10486
10582
|
args.push(stats);
|
|
10487
10583
|
const awf = opts.awaitWriteFinish;
|
|
10488
10584
|
let pw;
|
|
10489
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
10585
|
+
if (awf && (pw = this._pendingWrites.get(path5))) {
|
|
10490
10586
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
10491
10587
|
return this;
|
|
10492
10588
|
}
|
|
10493
10589
|
if (opts.atomic) {
|
|
10494
10590
|
if (event === EVENTS.UNLINK) {
|
|
10495
|
-
this._pendingUnlinks.set(
|
|
10591
|
+
this._pendingUnlinks.set(path5, [event, ...args]);
|
|
10496
10592
|
setTimeout(() => {
|
|
10497
|
-
this._pendingUnlinks.forEach((entry,
|
|
10593
|
+
this._pendingUnlinks.forEach((entry, path6) => {
|
|
10498
10594
|
this.emit(...entry);
|
|
10499
10595
|
this.emit(EVENTS.ALL, ...entry);
|
|
10500
|
-
this._pendingUnlinks.delete(
|
|
10596
|
+
this._pendingUnlinks.delete(path6);
|
|
10501
10597
|
});
|
|
10502
10598
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
10503
10599
|
return this;
|
|
10504
10600
|
}
|
|
10505
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
10601
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path5)) {
|
|
10506
10602
|
event = EVENTS.CHANGE;
|
|
10507
|
-
this._pendingUnlinks.delete(
|
|
10603
|
+
this._pendingUnlinks.delete(path5);
|
|
10508
10604
|
}
|
|
10509
10605
|
}
|
|
10510
10606
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -10522,16 +10618,16 @@ var FSWatcher = class extends EventEmitter {
|
|
|
10522
10618
|
this.emitWithAll(event, args);
|
|
10523
10619
|
}
|
|
10524
10620
|
};
|
|
10525
|
-
this._awaitWriteFinish(
|
|
10621
|
+
this._awaitWriteFinish(path5, awf.stabilityThreshold, event, awfEmit);
|
|
10526
10622
|
return this;
|
|
10527
10623
|
}
|
|
10528
10624
|
if (event === EVENTS.CHANGE) {
|
|
10529
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
10625
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path5, 50);
|
|
10530
10626
|
if (isThrottled)
|
|
10531
10627
|
return this;
|
|
10532
10628
|
}
|
|
10533
10629
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
10534
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
10630
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path5) : path5;
|
|
10535
10631
|
let stats2;
|
|
10536
10632
|
try {
|
|
10537
10633
|
stats2 = await stat3(fullPath);
|
|
@@ -10562,23 +10658,23 @@ var FSWatcher = class extends EventEmitter {
|
|
|
10562
10658
|
* @param timeout duration of time to suppress duplicate actions
|
|
10563
10659
|
* @returns tracking object or false if action should be suppressed
|
|
10564
10660
|
*/
|
|
10565
|
-
_throttle(actionType,
|
|
10661
|
+
_throttle(actionType, path5, timeout) {
|
|
10566
10662
|
if (!this._throttled.has(actionType)) {
|
|
10567
10663
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
10568
10664
|
}
|
|
10569
10665
|
const action2 = this._throttled.get(actionType);
|
|
10570
10666
|
if (!action2)
|
|
10571
10667
|
throw new Error("invalid throttle");
|
|
10572
|
-
const actionPath = action2.get(
|
|
10668
|
+
const actionPath = action2.get(path5);
|
|
10573
10669
|
if (actionPath) {
|
|
10574
10670
|
actionPath.count++;
|
|
10575
10671
|
return false;
|
|
10576
10672
|
}
|
|
10577
10673
|
let timeoutObject;
|
|
10578
10674
|
const clear = () => {
|
|
10579
|
-
const item = action2.get(
|
|
10675
|
+
const item = action2.get(path5);
|
|
10580
10676
|
const count = item ? item.count : 0;
|
|
10581
|
-
action2.delete(
|
|
10677
|
+
action2.delete(path5);
|
|
10582
10678
|
clearTimeout(timeoutObject);
|
|
10583
10679
|
if (item)
|
|
10584
10680
|
clearTimeout(item.timeoutObject);
|
|
@@ -10586,7 +10682,7 @@ var FSWatcher = class extends EventEmitter {
|
|
|
10586
10682
|
};
|
|
10587
10683
|
timeoutObject = setTimeout(clear, timeout);
|
|
10588
10684
|
const thr = { timeoutObject, clear, count: 0 };
|
|
10589
|
-
action2.set(
|
|
10685
|
+
action2.set(path5, thr);
|
|
10590
10686
|
return thr;
|
|
10591
10687
|
}
|
|
10592
10688
|
_incrReadyCount() {
|
|
@@ -10600,44 +10696,44 @@ var FSWatcher = class extends EventEmitter {
|
|
|
10600
10696
|
* @param event
|
|
10601
10697
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
10602
10698
|
*/
|
|
10603
|
-
_awaitWriteFinish(
|
|
10699
|
+
_awaitWriteFinish(path5, threshold, event, awfEmit) {
|
|
10604
10700
|
const awf = this.options.awaitWriteFinish;
|
|
10605
10701
|
if (typeof awf !== "object")
|
|
10606
10702
|
return;
|
|
10607
10703
|
const pollInterval = awf.pollInterval;
|
|
10608
10704
|
let timeoutHandler;
|
|
10609
|
-
let fullPath =
|
|
10610
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
10611
|
-
fullPath = sp2.join(this.options.cwd,
|
|
10705
|
+
let fullPath = path5;
|
|
10706
|
+
if (this.options.cwd && !sp2.isAbsolute(path5)) {
|
|
10707
|
+
fullPath = sp2.join(this.options.cwd, path5);
|
|
10612
10708
|
}
|
|
10613
10709
|
const now = /* @__PURE__ */ new Date();
|
|
10614
10710
|
const writes = this._pendingWrites;
|
|
10615
10711
|
function awaitWriteFinishFn(prevStat) {
|
|
10616
10712
|
statcb(fullPath, (err, curStat) => {
|
|
10617
|
-
if (err || !writes.has(
|
|
10713
|
+
if (err || !writes.has(path5)) {
|
|
10618
10714
|
if (err && err.code !== "ENOENT")
|
|
10619
10715
|
awfEmit(err);
|
|
10620
10716
|
return;
|
|
10621
10717
|
}
|
|
10622
10718
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
10623
10719
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
10624
|
-
writes.get(
|
|
10720
|
+
writes.get(path5).lastChange = now2;
|
|
10625
10721
|
}
|
|
10626
|
-
const pw = writes.get(
|
|
10722
|
+
const pw = writes.get(path5);
|
|
10627
10723
|
const df = now2 - pw.lastChange;
|
|
10628
10724
|
if (df >= threshold) {
|
|
10629
|
-
writes.delete(
|
|
10725
|
+
writes.delete(path5);
|
|
10630
10726
|
awfEmit(void 0, curStat);
|
|
10631
10727
|
} else {
|
|
10632
10728
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
10633
10729
|
}
|
|
10634
10730
|
});
|
|
10635
10731
|
}
|
|
10636
|
-
if (!writes.has(
|
|
10637
|
-
writes.set(
|
|
10732
|
+
if (!writes.has(path5)) {
|
|
10733
|
+
writes.set(path5, {
|
|
10638
10734
|
lastChange: now,
|
|
10639
10735
|
cancelWait: () => {
|
|
10640
|
-
writes.delete(
|
|
10736
|
+
writes.delete(path5);
|
|
10641
10737
|
clearTimeout(timeoutHandler);
|
|
10642
10738
|
return event;
|
|
10643
10739
|
}
|
|
@@ -10648,8 +10744,8 @@ var FSWatcher = class extends EventEmitter {
|
|
|
10648
10744
|
/**
|
|
10649
10745
|
* Determines whether user has asked to ignore this path.
|
|
10650
10746
|
*/
|
|
10651
|
-
_isIgnored(
|
|
10652
|
-
if (this.options.atomic && DOT_RE.test(
|
|
10747
|
+
_isIgnored(path5, stats) {
|
|
10748
|
+
if (this.options.atomic && DOT_RE.test(path5))
|
|
10653
10749
|
return true;
|
|
10654
10750
|
if (!this._userIgnored) {
|
|
10655
10751
|
const { cwd } = this.options;
|
|
@@ -10659,17 +10755,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
10659
10755
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
10660
10756
|
this._userIgnored = anymatch(list, void 0);
|
|
10661
10757
|
}
|
|
10662
|
-
return this._userIgnored(
|
|
10758
|
+
return this._userIgnored(path5, stats);
|
|
10663
10759
|
}
|
|
10664
|
-
_isntIgnored(
|
|
10665
|
-
return !this._isIgnored(
|
|
10760
|
+
_isntIgnored(path5, stat4) {
|
|
10761
|
+
return !this._isIgnored(path5, stat4);
|
|
10666
10762
|
}
|
|
10667
10763
|
/**
|
|
10668
10764
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
10669
10765
|
* @param path file or directory pattern being watched
|
|
10670
10766
|
*/
|
|
10671
|
-
_getWatchHelpers(
|
|
10672
|
-
return new WatchHelper(
|
|
10767
|
+
_getWatchHelpers(path5) {
|
|
10768
|
+
return new WatchHelper(path5, this.options.followSymlinks, this);
|
|
10673
10769
|
}
|
|
10674
10770
|
// Directory helpers
|
|
10675
10771
|
// -----------------
|
|
@@ -10701,63 +10797,63 @@ var FSWatcher = class extends EventEmitter {
|
|
|
10701
10797
|
* @param item base path of item/directory
|
|
10702
10798
|
*/
|
|
10703
10799
|
_remove(directory, item, isDirectory) {
|
|
10704
|
-
const
|
|
10705
|
-
const fullPath = sp2.resolve(
|
|
10706
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
10707
|
-
if (!this._throttle("remove",
|
|
10800
|
+
const path5 = sp2.join(directory, item);
|
|
10801
|
+
const fullPath = sp2.resolve(path5);
|
|
10802
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path5) || this._watched.has(fullPath);
|
|
10803
|
+
if (!this._throttle("remove", path5, 100))
|
|
10708
10804
|
return;
|
|
10709
10805
|
if (!isDirectory && this._watched.size === 1) {
|
|
10710
10806
|
this.add(directory, item, true);
|
|
10711
10807
|
}
|
|
10712
|
-
const wp = this._getWatchedDir(
|
|
10808
|
+
const wp = this._getWatchedDir(path5);
|
|
10713
10809
|
const nestedDirectoryChildren = wp.getChildren();
|
|
10714
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
10810
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path5, nested));
|
|
10715
10811
|
const parent = this._getWatchedDir(directory);
|
|
10716
10812
|
const wasTracked = parent.has(item);
|
|
10717
10813
|
parent.remove(item);
|
|
10718
10814
|
if (this._symlinkPaths.has(fullPath)) {
|
|
10719
10815
|
this._symlinkPaths.delete(fullPath);
|
|
10720
10816
|
}
|
|
10721
|
-
let relPath =
|
|
10817
|
+
let relPath = path5;
|
|
10722
10818
|
if (this.options.cwd)
|
|
10723
|
-
relPath = sp2.relative(this.options.cwd,
|
|
10819
|
+
relPath = sp2.relative(this.options.cwd, path5);
|
|
10724
10820
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
10725
10821
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
10726
10822
|
if (event === EVENTS.ADD)
|
|
10727
10823
|
return;
|
|
10728
10824
|
}
|
|
10729
|
-
this._watched.delete(
|
|
10825
|
+
this._watched.delete(path5);
|
|
10730
10826
|
this._watched.delete(fullPath);
|
|
10731
10827
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
10732
|
-
if (wasTracked && !this._isIgnored(
|
|
10733
|
-
this._emit(eventName,
|
|
10734
|
-
this._closePath(
|
|
10828
|
+
if (wasTracked && !this._isIgnored(path5))
|
|
10829
|
+
this._emit(eventName, path5);
|
|
10830
|
+
this._closePath(path5);
|
|
10735
10831
|
}
|
|
10736
10832
|
/**
|
|
10737
10833
|
* Closes all watchers for a path
|
|
10738
10834
|
*/
|
|
10739
|
-
_closePath(
|
|
10740
|
-
this._closeFile(
|
|
10741
|
-
const dir = sp2.dirname(
|
|
10742
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
10835
|
+
_closePath(path5) {
|
|
10836
|
+
this._closeFile(path5);
|
|
10837
|
+
const dir = sp2.dirname(path5);
|
|
10838
|
+
this._getWatchedDir(dir).remove(sp2.basename(path5));
|
|
10743
10839
|
}
|
|
10744
10840
|
/**
|
|
10745
10841
|
* Closes only file-specific watchers
|
|
10746
10842
|
*/
|
|
10747
|
-
_closeFile(
|
|
10748
|
-
const closers = this._closers.get(
|
|
10843
|
+
_closeFile(path5) {
|
|
10844
|
+
const closers = this._closers.get(path5);
|
|
10749
10845
|
if (!closers)
|
|
10750
10846
|
return;
|
|
10751
10847
|
closers.forEach((closer) => closer());
|
|
10752
|
-
this._closers.delete(
|
|
10848
|
+
this._closers.delete(path5);
|
|
10753
10849
|
}
|
|
10754
|
-
_addPathCloser(
|
|
10850
|
+
_addPathCloser(path5, closer) {
|
|
10755
10851
|
if (!closer)
|
|
10756
10852
|
return;
|
|
10757
|
-
let list = this._closers.get(
|
|
10853
|
+
let list = this._closers.get(path5);
|
|
10758
10854
|
if (!list) {
|
|
10759
10855
|
list = [];
|
|
10760
|
-
this._closers.set(
|
|
10856
|
+
this._closers.set(path5, list);
|
|
10761
10857
|
}
|
|
10762
10858
|
list.push(closer);
|
|
10763
10859
|
}
|
|
@@ -10826,14 +10922,14 @@ function startWatcher(opts) {
|
|
|
10826
10922
|
const binding = pathBindings.get(removedPath);
|
|
10827
10923
|
if (!binding) return;
|
|
10828
10924
|
try {
|
|
10829
|
-
opts.archive.
|
|
10925
|
+
opts.archive.recordIngestionEvent({
|
|
10830
10926
|
agent: binding.plugin.id,
|
|
10831
10927
|
sourceId: binding.ref.sourceId,
|
|
10832
10928
|
sourcePath: removedPath,
|
|
10833
10929
|
eventType: "unlink_observed",
|
|
10834
10930
|
detail: { path: removedPath },
|
|
10835
10931
|
observedAt: /* @__PURE__ */ new Date()
|
|
10836
|
-
})
|
|
10932
|
+
});
|
|
10837
10933
|
} catch (err) {
|
|
10838
10934
|
onError(err);
|
|
10839
10935
|
}
|
|
@@ -10855,13 +10951,13 @@ function startWatcher(opts) {
|
|
|
10855
10951
|
}
|
|
10856
10952
|
return {
|
|
10857
10953
|
ready,
|
|
10858
|
-
notifyChange(
|
|
10859
|
-
if (watcher2) watcher2.emit("change",
|
|
10860
|
-
else scheduleIngest(
|
|
10954
|
+
notifyChange(path5) {
|
|
10955
|
+
if (watcher2) watcher2.emit("change", path5);
|
|
10956
|
+
else scheduleIngest(path5);
|
|
10861
10957
|
},
|
|
10862
|
-
notifyUnlink(
|
|
10863
|
-
if (watcher2) watcher2.emit("unlink",
|
|
10864
|
-
else recordUnlink(
|
|
10958
|
+
notifyUnlink(path5) {
|
|
10959
|
+
if (watcher2) watcher2.emit("unlink", path5);
|
|
10960
|
+
else recordUnlink(path5);
|
|
10865
10961
|
},
|
|
10866
10962
|
async close() {
|
|
10867
10963
|
closed = true;
|
|
@@ -10873,38 +10969,38 @@ function startWatcher(opts) {
|
|
|
10873
10969
|
}
|
|
10874
10970
|
|
|
10875
10971
|
// src/plugins/claude-code/plugin.ts
|
|
10876
|
-
import
|
|
10877
|
-
import
|
|
10972
|
+
import fs5 from "fs";
|
|
10973
|
+
import path3 from "path";
|
|
10878
10974
|
import readline from "readline";
|
|
10879
10975
|
var ClaudeCodePlugin = class {
|
|
10880
10976
|
id = "claude-code";
|
|
10881
10977
|
displayName = "Claude Code";
|
|
10882
10978
|
async *discover(env) {
|
|
10883
|
-
const projectsDir =
|
|
10884
|
-
if (!
|
|
10885
|
-
const projects =
|
|
10979
|
+
const projectsDir = path3.join(env.homeDir, ".claude", "projects");
|
|
10980
|
+
if (!fs5.existsSync(projectsDir)) return;
|
|
10981
|
+
const projects = fs5.readdirSync(projectsDir, { withFileTypes: true });
|
|
10886
10982
|
for (const project of projects) {
|
|
10887
10983
|
if (!project.isDirectory()) continue;
|
|
10888
|
-
const projectPath =
|
|
10889
|
-
const files =
|
|
10984
|
+
const projectPath = path3.join(projectsDir, project.name);
|
|
10985
|
+
const files = fs5.readdirSync(projectPath, { withFileTypes: true });
|
|
10890
10986
|
for (const file of files) {
|
|
10891
10987
|
if (!file.isFile() || !file.name.endsWith(".jsonl")) continue;
|
|
10892
|
-
const sourcePath =
|
|
10988
|
+
const sourcePath = path3.join(projectPath, file.name);
|
|
10893
10989
|
const sourceId = file.name.replace(/\.jsonl$/, "");
|
|
10894
10990
|
const cwd = await readCwdFromJsonl(sourcePath);
|
|
10895
10991
|
yield {
|
|
10896
10992
|
sourceId,
|
|
10897
10993
|
sourcePath,
|
|
10898
10994
|
watchPaths: [sourcePath],
|
|
10899
|
-
project: cwd ?
|
|
10995
|
+
project: cwd ? path3.basename(cwd) : void 0,
|
|
10900
10996
|
projectPath: cwd ?? void 0
|
|
10901
10997
|
};
|
|
10902
10998
|
}
|
|
10903
10999
|
}
|
|
10904
11000
|
}
|
|
10905
11001
|
async *extractRaw(ref) {
|
|
10906
|
-
if (!
|
|
10907
|
-
const stream =
|
|
11002
|
+
if (!fs5.existsSync(ref.sourcePath)) return;
|
|
11003
|
+
const stream = fs5.createReadStream(ref.sourcePath, { encoding: "utf-8" });
|
|
10908
11004
|
const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
|
|
10909
11005
|
let lineNo = 0;
|
|
10910
11006
|
for await (const line of rl) {
|
|
@@ -10953,7 +11049,7 @@ var ClaudeCodePlugin = class {
|
|
|
10953
11049
|
};
|
|
10954
11050
|
async function readCwdFromJsonl(sourcePath) {
|
|
10955
11051
|
try {
|
|
10956
|
-
const stream =
|
|
11052
|
+
const stream = fs5.createReadStream(sourcePath, { encoding: "utf-8" });
|
|
10957
11053
|
const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
|
|
10958
11054
|
try {
|
|
10959
11055
|
for await (const line of rl) {
|
|
@@ -11060,9 +11156,9 @@ Environment:
|
|
|
11060
11156
|
`;
|
|
11061
11157
|
|
|
11062
11158
|
// src/index.ts
|
|
11063
|
-
var __dirname =
|
|
11064
|
-
var pkgPath =
|
|
11065
|
-
var pkg = JSON.parse(
|
|
11159
|
+
var __dirname = path4.dirname(fileURLToPath2(import.meta.url));
|
|
11160
|
+
var pkgPath = path4.join(__dirname, "../../package.json");
|
|
11161
|
+
var pkg = JSON.parse(fs6.readFileSync(pkgPath, "utf-8"));
|
|
11066
11162
|
var action = parseCliArgs(process.argv.slice(2), {
|
|
11067
11163
|
PORT: process.env.PORT
|
|
11068
11164
|
});
|
|
@@ -11079,8 +11175,8 @@ if (action.kind === "error") {
|
|
|
11079
11175
|
process.exit(1);
|
|
11080
11176
|
}
|
|
11081
11177
|
updateNotifier({ pkg }).notify({ defer: false, isGlobal: true });
|
|
11082
|
-
var dataDir =
|
|
11083
|
-
var webDistDir =
|
|
11178
|
+
var dataDir = path4.join(os.homedir(), ".chat-logbook");
|
|
11179
|
+
var webDistDir = path4.join(__dirname, "../../web/dist");
|
|
11084
11180
|
var port = action.port;
|
|
11085
11181
|
var archive = createArchiveRepository({ dataDir });
|
|
11086
11182
|
var checkpoint = createCheckpointRepository({ dataDir });
|