chat-logbook 0.21.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/api/dist/drizzle/archive/0011_add_normalize_version.sql +7 -0
- package/api/dist/drizzle/archive/0012_add_message_model.sql +6 -0
- package/api/dist/drizzle/archive/0013_add_message_effort.sql +6 -0
- package/api/dist/drizzle/archive/meta/_journal.json +21 -0
- package/api/dist/index.js +866 -402
- package/package.json +1 -1
- package/web/dist/assets/common-vv-D-zLq.js +5 -0
- package/web/dist/assets/index-BDcwnucw.css +2 -0
- package/web/dist/assets/index-CaNxBq0o.js +56 -0
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-CoQQuTo9.css +0 -2
- package/web/dist/assets/index-Dc733mEt.js +0 -57
package/api/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ var __export = (target, all) => {
|
|
|
7
7
|
// src/index.ts
|
|
8
8
|
import fs8 from "fs";
|
|
9
9
|
import os from "os";
|
|
10
|
-
import
|
|
10
|
+
import path8 from "path";
|
|
11
11
|
import { exec } from "child_process";
|
|
12
12
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
13
13
|
|
|
@@ -585,6 +585,9 @@ var serve = (options, listeningListener) => {
|
|
|
585
585
|
// src/index.ts
|
|
586
586
|
import updateNotifier from "update-notifier";
|
|
587
587
|
|
|
588
|
+
// src/app.ts
|
|
589
|
+
import { createHash } from "crypto";
|
|
590
|
+
|
|
588
591
|
// ../node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/compose.js
|
|
589
592
|
var compose = (middleware, onError, onNotFound) => {
|
|
590
593
|
return (context, next) => {
|
|
@@ -705,26 +708,26 @@ var handleParsingNestedValues = (form, key, value) => {
|
|
|
705
708
|
};
|
|
706
709
|
|
|
707
710
|
// ../node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/utils/url.js
|
|
708
|
-
var splitPath = (
|
|
709
|
-
const paths =
|
|
711
|
+
var splitPath = (path9) => {
|
|
712
|
+
const paths = path9.split("/");
|
|
710
713
|
if (paths[0] === "") {
|
|
711
714
|
paths.shift();
|
|
712
715
|
}
|
|
713
716
|
return paths;
|
|
714
717
|
};
|
|
715
718
|
var splitRoutingPath = (routePath) => {
|
|
716
|
-
const { groups, path:
|
|
717
|
-
const paths = splitPath(
|
|
719
|
+
const { groups, path: path9 } = extractGroupsFromPath(routePath);
|
|
720
|
+
const paths = splitPath(path9);
|
|
718
721
|
return replaceGroupMarks(paths, groups);
|
|
719
722
|
};
|
|
720
|
-
var extractGroupsFromPath = (
|
|
723
|
+
var extractGroupsFromPath = (path9) => {
|
|
721
724
|
const groups = [];
|
|
722
|
-
|
|
725
|
+
path9 = path9.replace(/\{[^}]+\}/g, (match2, index2) => {
|
|
723
726
|
const mark = `@${index2}`;
|
|
724
727
|
groups.push([mark, match2]);
|
|
725
728
|
return mark;
|
|
726
729
|
});
|
|
727
|
-
return { groups, path:
|
|
730
|
+
return { groups, path: path9 };
|
|
728
731
|
};
|
|
729
732
|
var replaceGroupMarks = (paths, groups) => {
|
|
730
733
|
for (let i = groups.length - 1; i >= 0; i--) {
|
|
@@ -781,8 +784,8 @@ var getPath = (request) => {
|
|
|
781
784
|
const queryIndex = url.indexOf("?", i);
|
|
782
785
|
const hashIndex = url.indexOf("#", i);
|
|
783
786
|
const end = queryIndex === -1 ? hashIndex === -1 ? void 0 : hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);
|
|
784
|
-
const
|
|
785
|
-
return tryDecodeURI(
|
|
787
|
+
const path9 = url.slice(start, end);
|
|
788
|
+
return tryDecodeURI(path9.includes("%25") ? path9.replace(/%25/g, "%2525") : path9);
|
|
786
789
|
} else if (charCode === 63 || charCode === 35) {
|
|
787
790
|
break;
|
|
788
791
|
}
|
|
@@ -799,11 +802,11 @@ var mergePath = (base, sub, ...rest) => {
|
|
|
799
802
|
}
|
|
800
803
|
return `${base?.[0] === "/" ? "" : "/"}${base}${sub === "/" ? "" : `${base?.at(-1) === "/" ? "" : "/"}${sub?.[0] === "/" ? sub.slice(1) : sub}`}`;
|
|
801
804
|
};
|
|
802
|
-
var checkOptionalParameter = (
|
|
803
|
-
if (
|
|
805
|
+
var checkOptionalParameter = (path9) => {
|
|
806
|
+
if (path9.charCodeAt(path9.length - 1) !== 63 || !path9.includes(":")) {
|
|
804
807
|
return null;
|
|
805
808
|
}
|
|
806
|
-
const segments =
|
|
809
|
+
const segments = path9.split("/");
|
|
807
810
|
const results = [];
|
|
808
811
|
let basePath = "";
|
|
809
812
|
segments.forEach((segment) => {
|
|
@@ -944,9 +947,9 @@ var HonoRequest = class {
|
|
|
944
947
|
*/
|
|
945
948
|
path;
|
|
946
949
|
bodyCache = {};
|
|
947
|
-
constructor(request,
|
|
950
|
+
constructor(request, path9 = "/", matchResult = [[]]) {
|
|
948
951
|
this.raw = request;
|
|
949
|
-
this.path =
|
|
952
|
+
this.path = path9;
|
|
950
953
|
this.#matchResult = matchResult;
|
|
951
954
|
this.#validatedData = {};
|
|
952
955
|
}
|
|
@@ -1683,8 +1686,8 @@ var Hono = class _Hono {
|
|
|
1683
1686
|
return this;
|
|
1684
1687
|
};
|
|
1685
1688
|
});
|
|
1686
|
-
this.on = (method,
|
|
1687
|
-
for (const p of [
|
|
1689
|
+
this.on = (method, path9, ...handlers) => {
|
|
1690
|
+
for (const p of [path9].flat()) {
|
|
1688
1691
|
this.#path = p;
|
|
1689
1692
|
for (const m of [method].flat()) {
|
|
1690
1693
|
handlers.map((handler) => {
|
|
@@ -1741,8 +1744,8 @@ var Hono = class _Hono {
|
|
|
1741
1744
|
* app.route("/api", app2) // GET /api/user
|
|
1742
1745
|
* ```
|
|
1743
1746
|
*/
|
|
1744
|
-
route(
|
|
1745
|
-
const subApp = this.basePath(
|
|
1747
|
+
route(path9, app2) {
|
|
1748
|
+
const subApp = this.basePath(path9);
|
|
1746
1749
|
app2.routes.map((r) => {
|
|
1747
1750
|
let handler;
|
|
1748
1751
|
if (app2.errorHandler === errorHandler) {
|
|
@@ -1768,9 +1771,9 @@ var Hono = class _Hono {
|
|
|
1768
1771
|
* const api = new Hono().basePath('/api')
|
|
1769
1772
|
* ```
|
|
1770
1773
|
*/
|
|
1771
|
-
basePath(
|
|
1774
|
+
basePath(path9) {
|
|
1772
1775
|
const subApp = this.#clone();
|
|
1773
|
-
subApp._basePath = mergePath(this._basePath,
|
|
1776
|
+
subApp._basePath = mergePath(this._basePath, path9);
|
|
1774
1777
|
return subApp;
|
|
1775
1778
|
}
|
|
1776
1779
|
/**
|
|
@@ -1844,7 +1847,7 @@ var Hono = class _Hono {
|
|
|
1844
1847
|
* })
|
|
1845
1848
|
* ```
|
|
1846
1849
|
*/
|
|
1847
|
-
mount(
|
|
1850
|
+
mount(path9, applicationHandler, options) {
|
|
1848
1851
|
let replaceRequest;
|
|
1849
1852
|
let optionHandler;
|
|
1850
1853
|
if (options) {
|
|
@@ -1871,7 +1874,7 @@ var Hono = class _Hono {
|
|
|
1871
1874
|
return [c.env, executionContext];
|
|
1872
1875
|
};
|
|
1873
1876
|
replaceRequest ||= (() => {
|
|
1874
|
-
const mergedPath = mergePath(this._basePath,
|
|
1877
|
+
const mergedPath = mergePath(this._basePath, path9);
|
|
1875
1878
|
const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
|
|
1876
1879
|
return (request) => {
|
|
1877
1880
|
const url = new URL(request.url);
|
|
@@ -1886,14 +1889,14 @@ var Hono = class _Hono {
|
|
|
1886
1889
|
}
|
|
1887
1890
|
await next();
|
|
1888
1891
|
};
|
|
1889
|
-
this.#addRoute(METHOD_NAME_ALL, mergePath(
|
|
1892
|
+
this.#addRoute(METHOD_NAME_ALL, mergePath(path9, "*"), handler);
|
|
1890
1893
|
return this;
|
|
1891
1894
|
}
|
|
1892
|
-
#addRoute(method,
|
|
1895
|
+
#addRoute(method, path9, handler) {
|
|
1893
1896
|
method = method.toUpperCase();
|
|
1894
|
-
|
|
1895
|
-
const r = { basePath: this._basePath, path:
|
|
1896
|
-
this.router.add(method,
|
|
1897
|
+
path9 = mergePath(this._basePath, path9);
|
|
1898
|
+
const r = { basePath: this._basePath, path: path9, method, handler };
|
|
1899
|
+
this.router.add(method, path9, [handler, r]);
|
|
1897
1900
|
this.routes.push(r);
|
|
1898
1901
|
}
|
|
1899
1902
|
#handleError(err, c) {
|
|
@@ -1906,10 +1909,10 @@ var Hono = class _Hono {
|
|
|
1906
1909
|
if (method === "HEAD") {
|
|
1907
1910
|
return (async () => new Response(null, await this.#dispatch(request, executionCtx, env, "GET")))();
|
|
1908
1911
|
}
|
|
1909
|
-
const
|
|
1910
|
-
const matchResult = this.router.match(method,
|
|
1912
|
+
const path9 = this.getPath(request, { env });
|
|
1913
|
+
const matchResult = this.router.match(method, path9);
|
|
1911
1914
|
const c = new Context(request, {
|
|
1912
|
-
path:
|
|
1915
|
+
path: path9,
|
|
1913
1916
|
matchResult,
|
|
1914
1917
|
env,
|
|
1915
1918
|
executionCtx,
|
|
@@ -2009,7 +2012,7 @@ var Hono = class _Hono {
|
|
|
2009
2012
|
|
|
2010
2013
|
// ../node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/router/reg-exp-router/matcher.js
|
|
2011
2014
|
var emptyParam = [];
|
|
2012
|
-
function match(method,
|
|
2015
|
+
function match(method, path9) {
|
|
2013
2016
|
const matchers = this.buildAllMatchers();
|
|
2014
2017
|
const match2 = ((method2, path22) => {
|
|
2015
2018
|
const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
|
|
@@ -2025,7 +2028,7 @@ function match(method, path8) {
|
|
|
2025
2028
|
return [matcher[1][index2], match3];
|
|
2026
2029
|
});
|
|
2027
2030
|
this.match = match2;
|
|
2028
|
-
return match2(method,
|
|
2031
|
+
return match2(method, path9);
|
|
2029
2032
|
}
|
|
2030
2033
|
|
|
2031
2034
|
// ../node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/router/reg-exp-router/node.js
|
|
@@ -2140,12 +2143,12 @@ var Node = class _Node {
|
|
|
2140
2143
|
var Trie = class {
|
|
2141
2144
|
#context = { varIndex: 0 };
|
|
2142
2145
|
#root = new Node();
|
|
2143
|
-
insert(
|
|
2146
|
+
insert(path9, index2, pathErrorCheckOnly) {
|
|
2144
2147
|
const paramAssoc = [];
|
|
2145
2148
|
const groups = [];
|
|
2146
2149
|
for (let i = 0; ; ) {
|
|
2147
2150
|
let replaced = false;
|
|
2148
|
-
|
|
2151
|
+
path9 = path9.replace(/\{[^}]+\}/g, (m) => {
|
|
2149
2152
|
const mark = `@\\${i}`;
|
|
2150
2153
|
groups[i] = [mark, m];
|
|
2151
2154
|
i++;
|
|
@@ -2156,7 +2159,7 @@ var Trie = class {
|
|
|
2156
2159
|
break;
|
|
2157
2160
|
}
|
|
2158
2161
|
}
|
|
2159
|
-
const tokens =
|
|
2162
|
+
const tokens = path9.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
|
|
2160
2163
|
for (let i = groups.length - 1; i >= 0; i--) {
|
|
2161
2164
|
const [mark] = groups[i];
|
|
2162
2165
|
for (let j = tokens.length - 1; j >= 0; j--) {
|
|
@@ -2195,9 +2198,9 @@ var Trie = class {
|
|
|
2195
2198
|
// ../node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/router/reg-exp-router/router.js
|
|
2196
2199
|
var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
|
|
2197
2200
|
var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
|
|
2198
|
-
function buildWildcardRegExp(
|
|
2199
|
-
return wildcardRegExpCache[
|
|
2200
|
-
|
|
2201
|
+
function buildWildcardRegExp(path9) {
|
|
2202
|
+
return wildcardRegExpCache[path9] ??= new RegExp(
|
|
2203
|
+
path9 === "*" ? "" : `^${path9.replace(
|
|
2201
2204
|
/\/\*$|([.\\+*[^\]$()])/g,
|
|
2202
2205
|
(_, metaChar) => metaChar ? `\\${metaChar}` : "(?:|/.*)"
|
|
2203
2206
|
)}$`
|
|
@@ -2219,17 +2222,17 @@ function buildMatcherFromPreprocessedRoutes(routes) {
|
|
|
2219
2222
|
);
|
|
2220
2223
|
const staticMap = /* @__PURE__ */ Object.create(null);
|
|
2221
2224
|
for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
|
|
2222
|
-
const [pathErrorCheckOnly,
|
|
2225
|
+
const [pathErrorCheckOnly, path9, handlers] = routesWithStaticPathFlag[i];
|
|
2223
2226
|
if (pathErrorCheckOnly) {
|
|
2224
|
-
staticMap[
|
|
2227
|
+
staticMap[path9] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
|
|
2225
2228
|
} else {
|
|
2226
2229
|
j++;
|
|
2227
2230
|
}
|
|
2228
2231
|
let paramAssoc;
|
|
2229
2232
|
try {
|
|
2230
|
-
paramAssoc = trie.insert(
|
|
2233
|
+
paramAssoc = trie.insert(path9, j, pathErrorCheckOnly);
|
|
2231
2234
|
} catch (e) {
|
|
2232
|
-
throw e === PATH_ERROR ? new UnsupportedPathError(
|
|
2235
|
+
throw e === PATH_ERROR ? new UnsupportedPathError(path9) : e;
|
|
2233
2236
|
}
|
|
2234
2237
|
if (pathErrorCheckOnly) {
|
|
2235
2238
|
continue;
|
|
@@ -2263,12 +2266,12 @@ function buildMatcherFromPreprocessedRoutes(routes) {
|
|
|
2263
2266
|
}
|
|
2264
2267
|
return [regexp, handlerMap, staticMap];
|
|
2265
2268
|
}
|
|
2266
|
-
function findMiddleware(middleware,
|
|
2269
|
+
function findMiddleware(middleware, path9) {
|
|
2267
2270
|
if (!middleware) {
|
|
2268
2271
|
return void 0;
|
|
2269
2272
|
}
|
|
2270
2273
|
for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) {
|
|
2271
|
-
if (buildWildcardRegExp(k).test(
|
|
2274
|
+
if (buildWildcardRegExp(k).test(path9)) {
|
|
2272
2275
|
return [...middleware[k]];
|
|
2273
2276
|
}
|
|
2274
2277
|
}
|
|
@@ -2282,7 +2285,7 @@ var RegExpRouter = class {
|
|
|
2282
2285
|
this.#middleware = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
|
|
2283
2286
|
this.#routes = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
|
|
2284
2287
|
}
|
|
2285
|
-
add(method,
|
|
2288
|
+
add(method, path9, handler) {
|
|
2286
2289
|
const middleware = this.#middleware;
|
|
2287
2290
|
const routes = this.#routes;
|
|
2288
2291
|
if (!middleware || !routes) {
|
|
@@ -2297,18 +2300,18 @@ var RegExpRouter = class {
|
|
|
2297
2300
|
});
|
|
2298
2301
|
});
|
|
2299
2302
|
}
|
|
2300
|
-
if (
|
|
2301
|
-
|
|
2303
|
+
if (path9 === "/*") {
|
|
2304
|
+
path9 = "*";
|
|
2302
2305
|
}
|
|
2303
|
-
const paramCount = (
|
|
2304
|
-
if (/\*$/.test(
|
|
2305
|
-
const re = buildWildcardRegExp(
|
|
2306
|
+
const paramCount = (path9.match(/\/:/g) || []).length;
|
|
2307
|
+
if (/\*$/.test(path9)) {
|
|
2308
|
+
const re = buildWildcardRegExp(path9);
|
|
2306
2309
|
if (method === METHOD_NAME_ALL) {
|
|
2307
2310
|
Object.keys(middleware).forEach((m) => {
|
|
2308
|
-
middleware[m][
|
|
2311
|
+
middleware[m][path9] ||= findMiddleware(middleware[m], path9) || findMiddleware(middleware[METHOD_NAME_ALL], path9) || [];
|
|
2309
2312
|
});
|
|
2310
2313
|
} else {
|
|
2311
|
-
middleware[method][
|
|
2314
|
+
middleware[method][path9] ||= findMiddleware(middleware[method], path9) || findMiddleware(middleware[METHOD_NAME_ALL], path9) || [];
|
|
2312
2315
|
}
|
|
2313
2316
|
Object.keys(middleware).forEach((m) => {
|
|
2314
2317
|
if (method === METHOD_NAME_ALL || method === m) {
|
|
@@ -2326,7 +2329,7 @@ var RegExpRouter = class {
|
|
|
2326
2329
|
});
|
|
2327
2330
|
return;
|
|
2328
2331
|
}
|
|
2329
|
-
const paths = checkOptionalParameter(
|
|
2332
|
+
const paths = checkOptionalParameter(path9) || [path9];
|
|
2330
2333
|
for (let i = 0, len = paths.length; i < len; i++) {
|
|
2331
2334
|
const path22 = paths[i];
|
|
2332
2335
|
Object.keys(routes).forEach((m) => {
|
|
@@ -2353,13 +2356,13 @@ var RegExpRouter = class {
|
|
|
2353
2356
|
const routes = [];
|
|
2354
2357
|
let hasOwnRoute = method === METHOD_NAME_ALL;
|
|
2355
2358
|
[this.#middleware, this.#routes].forEach((r) => {
|
|
2356
|
-
const ownRoute = r[method] ? Object.keys(r[method]).map((
|
|
2359
|
+
const ownRoute = r[method] ? Object.keys(r[method]).map((path9) => [path9, r[method][path9]]) : [];
|
|
2357
2360
|
if (ownRoute.length !== 0) {
|
|
2358
2361
|
hasOwnRoute ||= true;
|
|
2359
2362
|
routes.push(...ownRoute);
|
|
2360
2363
|
} else if (method !== METHOD_NAME_ALL) {
|
|
2361
2364
|
routes.push(
|
|
2362
|
-
...Object.keys(r[METHOD_NAME_ALL]).map((
|
|
2365
|
+
...Object.keys(r[METHOD_NAME_ALL]).map((path9) => [path9, r[METHOD_NAME_ALL][path9]])
|
|
2363
2366
|
);
|
|
2364
2367
|
}
|
|
2365
2368
|
});
|
|
@@ -2379,13 +2382,13 @@ var SmartRouter = class {
|
|
|
2379
2382
|
constructor(init) {
|
|
2380
2383
|
this.#routers = init.routers;
|
|
2381
2384
|
}
|
|
2382
|
-
add(method,
|
|
2385
|
+
add(method, path9, handler) {
|
|
2383
2386
|
if (!this.#routes) {
|
|
2384
2387
|
throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
|
|
2385
2388
|
}
|
|
2386
|
-
this.#routes.push([method,
|
|
2389
|
+
this.#routes.push([method, path9, handler]);
|
|
2387
2390
|
}
|
|
2388
|
-
match(method,
|
|
2391
|
+
match(method, path9) {
|
|
2389
2392
|
if (!this.#routes) {
|
|
2390
2393
|
throw new Error("Fatal error");
|
|
2391
2394
|
}
|
|
@@ -2400,7 +2403,7 @@ var SmartRouter = class {
|
|
|
2400
2403
|
for (let i2 = 0, len2 = routes.length; i2 < len2; i2++) {
|
|
2401
2404
|
router.add(...routes[i2]);
|
|
2402
2405
|
}
|
|
2403
|
-
res = router.match(method,
|
|
2406
|
+
res = router.match(method, path9);
|
|
2404
2407
|
} catch (e) {
|
|
2405
2408
|
if (e instanceof UnsupportedPathError) {
|
|
2406
2409
|
continue;
|
|
@@ -2450,10 +2453,10 @@ var Node2 = class _Node2 {
|
|
|
2450
2453
|
}
|
|
2451
2454
|
this.#patterns = [];
|
|
2452
2455
|
}
|
|
2453
|
-
insert(method,
|
|
2456
|
+
insert(method, path9, handler) {
|
|
2454
2457
|
this.#order = ++this.#order;
|
|
2455
2458
|
let curNode = this;
|
|
2456
|
-
const parts = splitRoutingPath(
|
|
2459
|
+
const parts = splitRoutingPath(path9);
|
|
2457
2460
|
const possibleKeys = [];
|
|
2458
2461
|
for (let i = 0, len = parts.length; i < len; i++) {
|
|
2459
2462
|
const p = parts[i];
|
|
@@ -2502,12 +2505,12 @@ var Node2 = class _Node2 {
|
|
|
2502
2505
|
}
|
|
2503
2506
|
}
|
|
2504
2507
|
}
|
|
2505
|
-
search(method,
|
|
2508
|
+
search(method, path9) {
|
|
2506
2509
|
const handlerSets = [];
|
|
2507
2510
|
this.#params = emptyParams;
|
|
2508
2511
|
const curNode = this;
|
|
2509
2512
|
let curNodes = [curNode];
|
|
2510
|
-
const parts = splitPath(
|
|
2513
|
+
const parts = splitPath(path9);
|
|
2511
2514
|
const curNodesQueue = [];
|
|
2512
2515
|
const len = parts.length;
|
|
2513
2516
|
let partOffsets = null;
|
|
@@ -2549,13 +2552,13 @@ var Node2 = class _Node2 {
|
|
|
2549
2552
|
if (matcher instanceof RegExp) {
|
|
2550
2553
|
if (partOffsets === null) {
|
|
2551
2554
|
partOffsets = new Array(len);
|
|
2552
|
-
let offset =
|
|
2555
|
+
let offset = path9[0] === "/" ? 1 : 0;
|
|
2553
2556
|
for (let p = 0; p < len; p++) {
|
|
2554
2557
|
partOffsets[p] = offset;
|
|
2555
2558
|
offset += parts[p].length + 1;
|
|
2556
2559
|
}
|
|
2557
2560
|
}
|
|
2558
|
-
const restPathString =
|
|
2561
|
+
const restPathString = path9.substring(partOffsets[i]);
|
|
2559
2562
|
const m = matcher.exec(restPathString);
|
|
2560
2563
|
if (m) {
|
|
2561
2564
|
params[name] = m[0];
|
|
@@ -2608,18 +2611,18 @@ var TrieRouter = class {
|
|
|
2608
2611
|
constructor() {
|
|
2609
2612
|
this.#node = new Node2();
|
|
2610
2613
|
}
|
|
2611
|
-
add(method,
|
|
2612
|
-
const results = checkOptionalParameter(
|
|
2614
|
+
add(method, path9, handler) {
|
|
2615
|
+
const results = checkOptionalParameter(path9);
|
|
2613
2616
|
if (results) {
|
|
2614
2617
|
for (let i = 0, len = results.length; i < len; i++) {
|
|
2615
2618
|
this.#node.insert(method, results[i], handler);
|
|
2616
2619
|
}
|
|
2617
2620
|
return;
|
|
2618
2621
|
}
|
|
2619
|
-
this.#node.insert(method,
|
|
2622
|
+
this.#node.insert(method, path9, handler);
|
|
2620
2623
|
}
|
|
2621
|
-
match(method,
|
|
2622
|
-
return this.#node.search(method,
|
|
2624
|
+
match(method, path9) {
|
|
2625
|
+
return this.#node.search(method, path9);
|
|
2623
2626
|
}
|
|
2624
2627
|
};
|
|
2625
2628
|
|
|
@@ -2899,10 +2902,10 @@ var createStreamBody = (stream2) => {
|
|
|
2899
2902
|
});
|
|
2900
2903
|
return body;
|
|
2901
2904
|
};
|
|
2902
|
-
var getStats = (
|
|
2905
|
+
var getStats = (path9) => {
|
|
2903
2906
|
let stats;
|
|
2904
2907
|
try {
|
|
2905
|
-
stats = statSync(
|
|
2908
|
+
stats = statSync(path9);
|
|
2906
2909
|
} catch {
|
|
2907
2910
|
}
|
|
2908
2911
|
return stats;
|
|
@@ -2945,21 +2948,21 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
2945
2948
|
return next();
|
|
2946
2949
|
}
|
|
2947
2950
|
}
|
|
2948
|
-
let
|
|
2951
|
+
let path9 = join(
|
|
2949
2952
|
root,
|
|
2950
2953
|
!optionPath && options.rewriteRequestPath ? options.rewriteRequestPath(filename, c) : filename
|
|
2951
2954
|
);
|
|
2952
|
-
let stats = getStats(
|
|
2955
|
+
let stats = getStats(path9);
|
|
2953
2956
|
if (stats && stats.isDirectory()) {
|
|
2954
2957
|
const indexFile = options.index ?? "index.html";
|
|
2955
|
-
|
|
2956
|
-
stats = getStats(
|
|
2958
|
+
path9 = join(path9, indexFile);
|
|
2959
|
+
stats = getStats(path9);
|
|
2957
2960
|
}
|
|
2958
2961
|
if (!stats) {
|
|
2959
|
-
await options.onNotFound?.(
|
|
2962
|
+
await options.onNotFound?.(path9, c);
|
|
2960
2963
|
return next();
|
|
2961
2964
|
}
|
|
2962
|
-
const mimeType = getMimeType(
|
|
2965
|
+
const mimeType = getMimeType(path9);
|
|
2963
2966
|
c.header("Content-Type", mimeType || "application/octet-stream");
|
|
2964
2967
|
if (options.precompressed && (!mimeType || COMPRESSIBLE_CONTENT_TYPE_REGEX.test(mimeType))) {
|
|
2965
2968
|
const acceptEncodingSet = new Set(
|
|
@@ -2969,12 +2972,12 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
2969
2972
|
if (!acceptEncodingSet.has(encoding)) {
|
|
2970
2973
|
continue;
|
|
2971
2974
|
}
|
|
2972
|
-
const precompressedStats = getStats(
|
|
2975
|
+
const precompressedStats = getStats(path9 + ENCODINGS[encoding]);
|
|
2973
2976
|
if (precompressedStats) {
|
|
2974
2977
|
c.header("Content-Encoding", encoding);
|
|
2975
2978
|
c.header("Vary", "Accept-Encoding", { append: true });
|
|
2976
2979
|
stats = precompressedStats;
|
|
2977
|
-
|
|
2980
|
+
path9 = path9 + ENCODINGS[encoding];
|
|
2978
2981
|
break;
|
|
2979
2982
|
}
|
|
2980
2983
|
}
|
|
@@ -2988,7 +2991,7 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
2988
2991
|
result = c.body(null);
|
|
2989
2992
|
} else if (!range) {
|
|
2990
2993
|
c.header("Content-Length", size.toString());
|
|
2991
|
-
result = c.body(createStreamBody(createReadStream(
|
|
2994
|
+
result = c.body(createStreamBody(createReadStream(path9)), 200);
|
|
2992
2995
|
} else {
|
|
2993
2996
|
c.header("Accept-Ranges", "bytes");
|
|
2994
2997
|
c.header("Date", stats.birthtime.toUTCString());
|
|
@@ -2999,12 +3002,12 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
2999
3002
|
end = size - 1;
|
|
3000
3003
|
}
|
|
3001
3004
|
const chunksize = end - start + 1;
|
|
3002
|
-
const stream2 = createReadStream(
|
|
3005
|
+
const stream2 = createReadStream(path9, { start, end });
|
|
3003
3006
|
c.header("Content-Length", chunksize.toString());
|
|
3004
3007
|
c.header("Content-Range", `bytes ${start}-${end}/${stats.size}`);
|
|
3005
3008
|
result = c.body(createStreamBody(stream2), 206);
|
|
3006
3009
|
}
|
|
3007
|
-
await options.onFound?.(
|
|
3010
|
+
await options.onFound?.(path9, c);
|
|
3008
3011
|
return result;
|
|
3009
3012
|
};
|
|
3010
3013
|
};
|
|
@@ -3238,7 +3241,9 @@ function toApiBlock(block) {
|
|
|
3238
3241
|
return {
|
|
3239
3242
|
type: "tool_result",
|
|
3240
3243
|
tool_use_id: String(block.toolUseId ?? ""),
|
|
3241
|
-
content: block.content
|
|
3244
|
+
content: block.content,
|
|
3245
|
+
...block.isError === true ? { is_error: true } : {},
|
|
3246
|
+
...typeof block.filePath === "string" && Array.isArray(block.patch) ? { file_path: block.filePath, patch: block.patch } : {}
|
|
3242
3247
|
};
|
|
3243
3248
|
}
|
|
3244
3249
|
return block;
|
|
@@ -3374,9 +3379,12 @@ function createChatReader({
|
|
|
3374
3379
|
if (!visibility.isVisible(row.id)) return null;
|
|
3375
3380
|
const rows = archive2.read.listMessagesByChat(row.agent, row.sourceId);
|
|
3376
3381
|
return rows.map((m) => ({
|
|
3382
|
+
id: m.messageId,
|
|
3377
3383
|
role: m.role,
|
|
3378
3384
|
content: m.blocks.map(toApiBlock),
|
|
3379
|
-
timestamp: m.ts.toISOString()
|
|
3385
|
+
timestamp: m.ts.toISOString(),
|
|
3386
|
+
...m.model === null ? {} : { model: m.model },
|
|
3387
|
+
...m.effort === null ? {} : { effort: m.effort }
|
|
3380
3388
|
}));
|
|
3381
3389
|
}
|
|
3382
3390
|
return {
|
|
@@ -3391,6 +3399,450 @@ function createChatReader({
|
|
|
3391
3399
|
// src/list-contract.ts
|
|
3392
3400
|
var MAX_PAGE_LIMIT = 200;
|
|
3393
3401
|
|
|
3402
|
+
// src/plugins/claude-code/plugin.ts
|
|
3403
|
+
import fs2 from "fs";
|
|
3404
|
+
import path3 from "path";
|
|
3405
|
+
import readline from "readline";
|
|
3406
|
+
|
|
3407
|
+
// src/plugins/visualize-widget.ts
|
|
3408
|
+
var SHOW_WIDGET_TOOL = "mcp__visualize__show_widget";
|
|
3409
|
+
function svgWidgetCode(block) {
|
|
3410
|
+
if (!block || typeof block !== "object") return null;
|
|
3411
|
+
const b = block;
|
|
3412
|
+
if (b.type !== "tool_use" || b.name !== SHOW_WIDGET_TOOL) return null;
|
|
3413
|
+
const input = b.input;
|
|
3414
|
+
const code = input?.widget_code;
|
|
3415
|
+
if (typeof code !== "string") return null;
|
|
3416
|
+
return code.trimStart().startsWith("<svg") ? code : null;
|
|
3417
|
+
}
|
|
3418
|
+
var RAMPS = {
|
|
3419
|
+
"c-purple": { fill: "#3C3489", stroke: "#AFA9EC", title: "#CECBF6" },
|
|
3420
|
+
"c-teal": { fill: "#085041", stroke: "#5DCAA5", title: "#9FE1CB" },
|
|
3421
|
+
"c-coral": { fill: "#712B13", stroke: "#F0997B", title: "#F5C4B3" },
|
|
3422
|
+
"c-pink": { fill: "#72243E", stroke: "#ED93B1", title: "#F4C0D1" },
|
|
3423
|
+
"c-gray": { fill: "#444441", stroke: "#B4B2A9", title: "#D3D1C7" },
|
|
3424
|
+
"c-blue": { fill: "#0C447C", stroke: "#85B7EB", title: "#B5D4F4" },
|
|
3425
|
+
"c-green": { fill: "#27500A", stroke: "#97C459", title: "#C0DD97" },
|
|
3426
|
+
"c-amber": { fill: "#633806", stroke: "#EF9F27", title: "#FAC775" },
|
|
3427
|
+
"c-red": { fill: "#791F1F", stroke: "#F09595", title: "#F7C1C1" }
|
|
3428
|
+
};
|
|
3429
|
+
var TEXT_PRIMARY = "#eee8d5";
|
|
3430
|
+
var TEXT_SECONDARY = "#93a1a1";
|
|
3431
|
+
var FONT_SANS = "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif";
|
|
3432
|
+
function widgetStylesheet() {
|
|
3433
|
+
const ramps = Object.entries(RAMPS).map(
|
|
3434
|
+
([name, c]) => `.${name}>rect,.${name}>circle,.${name}>ellipse,rect.${name},circle.${name},ellipse.${name}{fill:${c.fill};stroke:${c.stroke};stroke-width:1.5}.${name}>text.t,.${name}>text.th{fill:${c.title}}.${name}>text.ts{fill:${c.stroke}}`
|
|
3435
|
+
).join("");
|
|
3436
|
+
return `text{font-family:${FONT_SANS}}.t{font-size:14px;fill:${TEXT_PRIMARY}}.th{font-size:14px;font-weight:500;fill:${TEXT_PRIMARY}}.ts{font-size:12px;fill:${TEXT_SECONDARY}}` + ramps;
|
|
3437
|
+
}
|
|
3438
|
+
function themeWidgetSvg(svg) {
|
|
3439
|
+
const root = /<svg\b[^>]*>/.exec(svg);
|
|
3440
|
+
if (!root) return svg;
|
|
3441
|
+
const sized = withIntrinsicSize(root[0]);
|
|
3442
|
+
const at = root.index + root[0].length;
|
|
3443
|
+
return svg.slice(0, root.index) + sized + `<style>${widgetStylesheet()}</style>` + svg.slice(at);
|
|
3444
|
+
}
|
|
3445
|
+
function withIntrinsicSize(rootTag) {
|
|
3446
|
+
if (/\s(width|height)\s*=/.test(rootTag)) return rootTag;
|
|
3447
|
+
const viewBox = /\bviewBox\s*=\s*"([^"]*)"/.exec(rootTag);
|
|
3448
|
+
if (!viewBox) return rootTag;
|
|
3449
|
+
const parts = viewBox[1].trim().split(/[\s,]+/).map(Number);
|
|
3450
|
+
if (parts.length !== 4 || parts.some((n) => !Number.isFinite(n))) {
|
|
3451
|
+
return rootTag;
|
|
3452
|
+
}
|
|
3453
|
+
const [, , width, height] = parts;
|
|
3454
|
+
if (width <= 0 || height <= 0) return rootTag;
|
|
3455
|
+
return `${rootTag.slice(0, -1)} width="${width}" height="${height}">`;
|
|
3456
|
+
}
|
|
3457
|
+
|
|
3458
|
+
// src/plugins/mcp-tool-name.ts
|
|
3459
|
+
var PREFIX = "mcp__";
|
|
3460
|
+
var SEPARATOR = "__";
|
|
3461
|
+
function mcpServerName(toolName) {
|
|
3462
|
+
if (!toolName.startsWith(PREFIX)) return null;
|
|
3463
|
+
const rest = toolName.slice(PREFIX.length);
|
|
3464
|
+
const end = rest.indexOf(SEPARATOR);
|
|
3465
|
+
const server2 = end === -1 ? rest : rest.slice(0, end);
|
|
3466
|
+
if (!server2) return null;
|
|
3467
|
+
return server2.replace(/_/g, " ");
|
|
3468
|
+
}
|
|
3469
|
+
|
|
3470
|
+
// src/plugins/claude-code/actions.ts
|
|
3471
|
+
function getString(input, key) {
|
|
3472
|
+
if (typeof input !== "object" || input === null) return void 0;
|
|
3473
|
+
const value = input[key];
|
|
3474
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
3475
|
+
}
|
|
3476
|
+
var FILE_KINDS = {
|
|
3477
|
+
Edit: "edit",
|
|
3478
|
+
MultiEdit: "edit",
|
|
3479
|
+
Write: "write",
|
|
3480
|
+
Read: "read"
|
|
3481
|
+
};
|
|
3482
|
+
var SEARCH_TOOLS = /* @__PURE__ */ new Set(["Grep", "Glob", "WebSearch", "ToolSearch"]);
|
|
3483
|
+
function firstLine(text2) {
|
|
3484
|
+
return text2?.split("\n", 1)[0];
|
|
3485
|
+
}
|
|
3486
|
+
function phrase(value) {
|
|
3487
|
+
return value ? { object: { type: "phrase", value } } : {};
|
|
3488
|
+
}
|
|
3489
|
+
function path2(value) {
|
|
3490
|
+
return value ? { object: { type: "path", value } } : {};
|
|
3491
|
+
}
|
|
3492
|
+
function detail(value) {
|
|
3493
|
+
return value ? { detail: value } : {};
|
|
3494
|
+
}
|
|
3495
|
+
function toolAction(name, input) {
|
|
3496
|
+
if (name === "Bash") {
|
|
3497
|
+
const command = getString(input, "command");
|
|
3498
|
+
const said = getString(input, "description") ?? firstLine(command);
|
|
3499
|
+
return { kind: "execute", ...phrase(said), ...detail(command) };
|
|
3500
|
+
}
|
|
3501
|
+
if (name === "Agent" || name === "SendMessage") {
|
|
3502
|
+
const task = getString(input, "description") ?? getString(input, "summary");
|
|
3503
|
+
return { kind: "delegate", ...phrase(task) };
|
|
3504
|
+
}
|
|
3505
|
+
if (SEARCH_TOOLS.has(name)) {
|
|
3506
|
+
const looked = getString(input, "pattern") ?? getString(input, "query");
|
|
3507
|
+
return { kind: "search", ...phrase(looked) };
|
|
3508
|
+
}
|
|
3509
|
+
const fileKind = FILE_KINDS[name];
|
|
3510
|
+
if (fileKind) {
|
|
3511
|
+
return { kind: fileKind, ...path2(getString(input, "file_path")) };
|
|
3512
|
+
}
|
|
3513
|
+
if (name === "WebFetch") {
|
|
3514
|
+
return { kind: "read", ...phrase(getString(input, "url")) };
|
|
3515
|
+
}
|
|
3516
|
+
return { kind: "other", ...phrase(mcpServerName(name) ?? name) };
|
|
3517
|
+
}
|
|
3518
|
+
|
|
3519
|
+
// src/plugins/claude-code/plugin.ts
|
|
3520
|
+
var ClaudeCodePlugin = class {
|
|
3521
|
+
id = "claude-code";
|
|
3522
|
+
displayName = "Claude Code";
|
|
3523
|
+
async *discover(env) {
|
|
3524
|
+
const projectsDir = path3.join(env.homeDir, ".claude", "projects");
|
|
3525
|
+
if (!fs2.existsSync(projectsDir)) return;
|
|
3526
|
+
const projects = fs2.readdirSync(projectsDir, { withFileTypes: true });
|
|
3527
|
+
for (const project of projects) {
|
|
3528
|
+
if (!project.isDirectory()) continue;
|
|
3529
|
+
const projectPath = path3.join(projectsDir, project.name);
|
|
3530
|
+
const files = fs2.readdirSync(projectPath, { withFileTypes: true });
|
|
3531
|
+
for (const file of files) {
|
|
3532
|
+
if (!file.isFile() || !file.name.endsWith(".jsonl")) continue;
|
|
3533
|
+
const sourcePath = path3.join(projectPath, file.name);
|
|
3534
|
+
const sourceId = file.name.replace(/\.jsonl$/, "");
|
|
3535
|
+
const cwd = await readCwdFromJsonl(sourcePath);
|
|
3536
|
+
yield {
|
|
3537
|
+
sourceId,
|
|
3538
|
+
sourcePath,
|
|
3539
|
+
watchPaths: [sourcePath],
|
|
3540
|
+
project: cwd ? path3.basename(cwd) : void 0,
|
|
3541
|
+
projectPath: cwd ?? void 0
|
|
3542
|
+
};
|
|
3543
|
+
}
|
|
3544
|
+
}
|
|
3545
|
+
}
|
|
3546
|
+
async *extractRaw(ref) {
|
|
3547
|
+
if (!fs2.existsSync(ref.sourcePath)) return;
|
|
3548
|
+
const stream2 = fs2.createReadStream(ref.sourcePath, { encoding: "utf-8" });
|
|
3549
|
+
const rl = readline.createInterface({ input: stream2, crlfDelay: Infinity });
|
|
3550
|
+
let lineNo = 0;
|
|
3551
|
+
for await (const line of rl) {
|
|
3552
|
+
lineNo += 1;
|
|
3553
|
+
if (!line) continue;
|
|
3554
|
+
yield {
|
|
3555
|
+
sourceId: ref.sourceId,
|
|
3556
|
+
sourcePath: ref.sourcePath,
|
|
3557
|
+
sourceLocator: `L${lineNo}`,
|
|
3558
|
+
payload: JSON.parse(line)
|
|
3559
|
+
};
|
|
3560
|
+
}
|
|
3561
|
+
}
|
|
3562
|
+
normalize(raw2) {
|
|
3563
|
+
const payload = raw2.payload;
|
|
3564
|
+
if (!payload || typeof payload !== "object") return null;
|
|
3565
|
+
if (payload.type !== "user" && payload.type !== "assistant") return null;
|
|
3566
|
+
if (payload.isMeta === true) return null;
|
|
3567
|
+
if (payload.isSidechain === true) return null;
|
|
3568
|
+
const message = payload.message;
|
|
3569
|
+
if (!message) return null;
|
|
3570
|
+
const role = message.role === "assistant" ? "assistant" : "user";
|
|
3571
|
+
const messageId = String(payload.uuid ?? "");
|
|
3572
|
+
const ts = String(payload.timestamp ?? "");
|
|
3573
|
+
const model = typeof message.model === "string" && message.model !== "" ? { model: message.model } : {};
|
|
3574
|
+
const effort = typeof payload.effort === "string" && payload.effort !== "" ? { effort: payload.effort } : {};
|
|
3575
|
+
const cwd = typeof payload.cwd === "string" ? payload.cwd : void 0;
|
|
3576
|
+
if (typeof message.content === "string") {
|
|
3577
|
+
const command = parseCommandMarkup(message.content);
|
|
3578
|
+
if (command) {
|
|
3579
|
+
const commandLine = `${command.name} ${command.args}`.trim();
|
|
3580
|
+
return {
|
|
3581
|
+
messageId,
|
|
3582
|
+
role,
|
|
3583
|
+
ts,
|
|
3584
|
+
text: commandLine,
|
|
3585
|
+
blocks: [{ type: "command", name: command.name, args: command.args }]
|
|
3586
|
+
};
|
|
3587
|
+
}
|
|
3588
|
+
const system = parseSystemNoise(message.content);
|
|
3589
|
+
if (system) {
|
|
3590
|
+
return {
|
|
3591
|
+
messageId,
|
|
3592
|
+
role,
|
|
3593
|
+
ts,
|
|
3594
|
+
text: system.summary,
|
|
3595
|
+
blocks: [system]
|
|
3596
|
+
};
|
|
3597
|
+
}
|
|
3598
|
+
return {
|
|
3599
|
+
messageId,
|
|
3600
|
+
role,
|
|
3601
|
+
ts,
|
|
3602
|
+
text: translateFileMentions(message.content, cwd, asPath),
|
|
3603
|
+
blocks: [
|
|
3604
|
+
{
|
|
3605
|
+
type: "text",
|
|
3606
|
+
text: translateFileMentions(message.content, cwd, asLink)
|
|
3607
|
+
}
|
|
3608
|
+
],
|
|
3609
|
+
...model,
|
|
3610
|
+
...effort
|
|
3611
|
+
};
|
|
3612
|
+
}
|
|
3613
|
+
if (Array.isArray(message.content)) {
|
|
3614
|
+
const raw3 = message.content.flatMap(
|
|
3615
|
+
(block, index2) => normalizeBlock(block, messageId, index2, payload.toolUseResult)
|
|
3616
|
+
);
|
|
3617
|
+
const blocks = raw3.map(
|
|
3618
|
+
(block) => block.type === "text" ? { ...block, text: translateFileMentions(block.text, cwd, asLink) } : block
|
|
3619
|
+
);
|
|
3620
|
+
const text2 = raw3.filter((b) => b.type === "text").map((b) => translateFileMentions(b.text, cwd, asPath)).join("\n");
|
|
3621
|
+
return { messageId, role, ts, text: text2, blocks, ...model, ...effort };
|
|
3622
|
+
}
|
|
3623
|
+
return null;
|
|
3624
|
+
}
|
|
3625
|
+
resolveImage(ref, loadPayload) {
|
|
3626
|
+
const address = parseImageRef(ref);
|
|
3627
|
+
if (!address) return null;
|
|
3628
|
+
const record = loadPayload(address.messageId);
|
|
3629
|
+
if (!record || typeof record !== "object") return null;
|
|
3630
|
+
const message = record.message;
|
|
3631
|
+
if (!message || !Array.isArray(message.content)) return null;
|
|
3632
|
+
const block = message.content[address.index];
|
|
3633
|
+
if (!block) return null;
|
|
3634
|
+
const widget = svgWidgetCode(block);
|
|
3635
|
+
if (widget) {
|
|
3636
|
+
return {
|
|
3637
|
+
mediaType: "image/svg+xml",
|
|
3638
|
+
bytes: Buffer.from(themeWidgetSvg(widget), "utf8"),
|
|
3639
|
+
rendered: true
|
|
3640
|
+
};
|
|
3641
|
+
}
|
|
3642
|
+
if (block.type !== "image") return null;
|
|
3643
|
+
const source = block.source;
|
|
3644
|
+
if (!source || source.type !== "base64") return null;
|
|
3645
|
+
const mediaType = String(source.media_type ?? "");
|
|
3646
|
+
const data = source.data;
|
|
3647
|
+
if (!mediaType || typeof data !== "string") return null;
|
|
3648
|
+
return { mediaType, bytes: Buffer.from(data, "base64") };
|
|
3649
|
+
}
|
|
3650
|
+
};
|
|
3651
|
+
async function readCwdFromJsonl(sourcePath) {
|
|
3652
|
+
try {
|
|
3653
|
+
const stream2 = fs2.createReadStream(sourcePath, { encoding: "utf-8" });
|
|
3654
|
+
const rl = readline.createInterface({ input: stream2, crlfDelay: Infinity });
|
|
3655
|
+
try {
|
|
3656
|
+
for await (const line of rl) {
|
|
3657
|
+
if (!line) continue;
|
|
3658
|
+
let obj;
|
|
3659
|
+
try {
|
|
3660
|
+
obj = JSON.parse(line);
|
|
3661
|
+
} catch {
|
|
3662
|
+
continue;
|
|
3663
|
+
}
|
|
3664
|
+
if (typeof obj.cwd === "string" && obj.cwd.length > 0) {
|
|
3665
|
+
return obj.cwd;
|
|
3666
|
+
}
|
|
3667
|
+
}
|
|
3668
|
+
} finally {
|
|
3669
|
+
rl.close();
|
|
3670
|
+
stream2.destroy();
|
|
3671
|
+
}
|
|
3672
|
+
} catch {
|
|
3673
|
+
}
|
|
3674
|
+
return void 0;
|
|
3675
|
+
}
|
|
3676
|
+
var COMMAND_NAME_RE = /<command-name>([\s\S]*?)<\/command-name>/;
|
|
3677
|
+
var COMMAND_ARGS_RE = /<command-args>([\s\S]*?)<\/command-args>/;
|
|
3678
|
+
function parseCommandMarkup(content) {
|
|
3679
|
+
const nameMatch = COMMAND_NAME_RE.exec(content);
|
|
3680
|
+
if (!nameMatch) return null;
|
|
3681
|
+
const name = nameMatch[1].trim();
|
|
3682
|
+
const argsMatch = COMMAND_ARGS_RE.exec(content);
|
|
3683
|
+
const args = argsMatch ? argsMatch[1].trim() : "";
|
|
3684
|
+
return { name, args };
|
|
3685
|
+
}
|
|
3686
|
+
var TASK_NOTIFICATION_RE = /<task-notification>[\s\S]*<\/task-notification>/;
|
|
3687
|
+
var TASK_SUMMARY_RE = /<summary>([\s\S]*?)<\/summary>/;
|
|
3688
|
+
var LOCAL_COMMAND_STDOUT_RE = /<local-command-stdout>([\s\S]*?)<\/local-command-stdout>/;
|
|
3689
|
+
var ANSI_SGR_RE = /\u001b\[[0-9;]*m/g;
|
|
3690
|
+
function stripAnsi(text2) {
|
|
3691
|
+
return text2.replace(ANSI_SGR_RE, "");
|
|
3692
|
+
}
|
|
3693
|
+
function parseSystemNoise(content) {
|
|
3694
|
+
const notification = TASK_NOTIFICATION_RE.exec(content);
|
|
3695
|
+
if (notification) {
|
|
3696
|
+
const summaryMatch = TASK_SUMMARY_RE.exec(notification[0]);
|
|
3697
|
+
return {
|
|
3698
|
+
type: "system",
|
|
3699
|
+
kind: "task-notification",
|
|
3700
|
+
summary: summaryMatch?.[1].trim() || "Task notification",
|
|
3701
|
+
detail: notification[0]
|
|
3702
|
+
};
|
|
3703
|
+
}
|
|
3704
|
+
const stdout = LOCAL_COMMAND_STDOUT_RE.exec(content);
|
|
3705
|
+
if (stdout) {
|
|
3706
|
+
return {
|
|
3707
|
+
type: "system",
|
|
3708
|
+
kind: "local-command-stdout",
|
|
3709
|
+
summary: stripAnsi(stdout[1]).trim(),
|
|
3710
|
+
detail: ""
|
|
3711
|
+
};
|
|
3712
|
+
}
|
|
3713
|
+
return null;
|
|
3714
|
+
}
|
|
3715
|
+
var FILE_MENTION_RE = /(^|\s)@(?:"([^"\n]+)"|(\S+))/g;
|
|
3716
|
+
var CODE_SEGMENT_RE = /```[\s\S]*?```|`[^`\n]*`/g;
|
|
3717
|
+
var asLink = (mentioned, cwd) => `[${mentioned}](${fileUrl(resolveAgainst(mentioned, cwd))})`;
|
|
3718
|
+
var asPath = (mentioned) => mentioned;
|
|
3719
|
+
function translateFileMentions(text2, cwd, write) {
|
|
3720
|
+
let out = "";
|
|
3721
|
+
let last = 0;
|
|
3722
|
+
for (const code of text2.matchAll(CODE_SEGMENT_RE)) {
|
|
3723
|
+
out += translateProse(text2.slice(last, code.index), cwd, write) + code[0];
|
|
3724
|
+
last = code.index + code[0].length;
|
|
3725
|
+
}
|
|
3726
|
+
return out + translateProse(text2.slice(last), cwd, write);
|
|
3727
|
+
}
|
|
3728
|
+
function translateProse(text2, cwd, write) {
|
|
3729
|
+
return text2.replace(
|
|
3730
|
+
FILE_MENTION_RE,
|
|
3731
|
+
(match2, lead, quoted, bare) => {
|
|
3732
|
+
const mentioned = quoted ?? bare;
|
|
3733
|
+
if (!looksLikeFilePath(mentioned)) return match2;
|
|
3734
|
+
return `${lead}${write(mentioned, cwd)}`;
|
|
3735
|
+
}
|
|
3736
|
+
);
|
|
3737
|
+
}
|
|
3738
|
+
function resolveAgainst(mentioned, cwd) {
|
|
3739
|
+
if (!cwd) return mentioned;
|
|
3740
|
+
if (mentioned.startsWith("/") || mentioned.startsWith("~")) return mentioned;
|
|
3741
|
+
return path3.posix.join(cwd, mentioned);
|
|
3742
|
+
}
|
|
3743
|
+
function looksLikeFilePath(mentioned) {
|
|
3744
|
+
if (mentioned.endsWith("/")) return true;
|
|
3745
|
+
const basename3 = mentioned.slice(mentioned.lastIndexOf("/") + 1);
|
|
3746
|
+
if (/^\.[A-Za-z0-9]/.test(basename3)) return true;
|
|
3747
|
+
return /^[^.].*\.[A-Za-z0-9]+$/.test(basename3);
|
|
3748
|
+
}
|
|
3749
|
+
function fileUrl(filePath) {
|
|
3750
|
+
return `file://${encodeURI(filePath).replace(/[()]/g, encodeURIComponent)}`;
|
|
3751
|
+
}
|
|
3752
|
+
function imageRef(messageId, index2) {
|
|
3753
|
+
return `${messageId}.${index2}`;
|
|
3754
|
+
}
|
|
3755
|
+
function parseImageRef(ref) {
|
|
3756
|
+
const dot = ref.lastIndexOf(".");
|
|
3757
|
+
if (dot <= 0) return null;
|
|
3758
|
+
const index2 = Number(ref.slice(dot + 1));
|
|
3759
|
+
if (!Number.isInteger(index2) || index2 < 0) return null;
|
|
3760
|
+
return { messageId: ref.slice(0, dot), index: index2 };
|
|
3761
|
+
}
|
|
3762
|
+
function normalizeBlock(raw2, messageId, index2, toolUseResult) {
|
|
3763
|
+
const one = normalizeOneBlock(raw2, messageId, index2, toolUseResult);
|
|
3764
|
+
if (!one) return [];
|
|
3765
|
+
if (one.type === "tool_use" && svgWidgetCode(raw2)) {
|
|
3766
|
+
return [
|
|
3767
|
+
one,
|
|
3768
|
+
{
|
|
3769
|
+
type: "image",
|
|
3770
|
+
mediaType: "image/svg+xml",
|
|
3771
|
+
ref: imageRef(messageId, index2)
|
|
3772
|
+
}
|
|
3773
|
+
];
|
|
3774
|
+
}
|
|
3775
|
+
return [one];
|
|
3776
|
+
}
|
|
3777
|
+
function editedFile(toolUseResult) {
|
|
3778
|
+
if (!toolUseResult || typeof toolUseResult !== "object") return {};
|
|
3779
|
+
const r = toolUseResult;
|
|
3780
|
+
if (typeof r.filePath !== "string" || !r.filePath) return {};
|
|
3781
|
+
if (!Array.isArray(r.structuredPatch)) return {};
|
|
3782
|
+
const patch = r.structuredPatch.filter(isPatchHunk);
|
|
3783
|
+
if (patch.length > 0) return { filePath: r.filePath, patch };
|
|
3784
|
+
const created = createdFilePatch(r);
|
|
3785
|
+
if (created) return { filePath: r.filePath, patch: created };
|
|
3786
|
+
return {};
|
|
3787
|
+
}
|
|
3788
|
+
function createdFilePatch(r) {
|
|
3789
|
+
if (r.type !== "create" || typeof r.content !== "string" || !r.content) {
|
|
3790
|
+
return null;
|
|
3791
|
+
}
|
|
3792
|
+
const content = r.content.endsWith("\n") ? r.content.slice(0, -1) : r.content;
|
|
3793
|
+
const lines = content.split("\n").map((line) => `+${line}`);
|
|
3794
|
+
return [
|
|
3795
|
+
{ oldStart: 0, oldLines: 0, newStart: 1, newLines: lines.length, lines }
|
|
3796
|
+
];
|
|
3797
|
+
}
|
|
3798
|
+
function isPatchHunk(hunk) {
|
|
3799
|
+
if (!hunk || typeof hunk !== "object") return false;
|
|
3800
|
+
const h = hunk;
|
|
3801
|
+
return typeof h.oldStart === "number" && typeof h.oldLines === "number" && typeof h.newStart === "number" && typeof h.newLines === "number" && Array.isArray(h.lines) && h.lines.every((line) => typeof line === "string");
|
|
3802
|
+
}
|
|
3803
|
+
function normalizeOneBlock(raw2, messageId, index2, toolUseResult) {
|
|
3804
|
+
if (!raw2 || typeof raw2 !== "object") return null;
|
|
3805
|
+
const b = raw2;
|
|
3806
|
+
switch (b.type) {
|
|
3807
|
+
case "image": {
|
|
3808
|
+
const source = b.source;
|
|
3809
|
+
if (!source || source.type !== "base64") return null;
|
|
3810
|
+
const mediaType = String(source.media_type ?? "");
|
|
3811
|
+
if (!mediaType) return null;
|
|
3812
|
+
return { type: "image", mediaType, ref: imageRef(messageId, index2) };
|
|
3813
|
+
}
|
|
3814
|
+
case "text":
|
|
3815
|
+
return { type: "text", text: String(b.text ?? "") };
|
|
3816
|
+
case "thinking":
|
|
3817
|
+
return { type: "thinking", thinking: String(b.thinking ?? "") };
|
|
3818
|
+
case "tool_use": {
|
|
3819
|
+
const name = String(b.name ?? "");
|
|
3820
|
+
return {
|
|
3821
|
+
type: "tool_use",
|
|
3822
|
+
id: String(b.id ?? ""),
|
|
3823
|
+
name,
|
|
3824
|
+
input: b.input,
|
|
3825
|
+
action: toolAction(name, b.input)
|
|
3826
|
+
};
|
|
3827
|
+
}
|
|
3828
|
+
case "tool_result":
|
|
3829
|
+
return {
|
|
3830
|
+
type: "tool_result",
|
|
3831
|
+
toolUseId: String(b.tool_use_id ?? ""),
|
|
3832
|
+
content: b.content,
|
|
3833
|
+
// Only carried when the tool actually failed: a `false` on every
|
|
3834
|
+
// successful result would grow the stored block for nothing.
|
|
3835
|
+
...b.is_error === true ? { isError: true } : {},
|
|
3836
|
+
...editedFile(toolUseResult)
|
|
3837
|
+
};
|
|
3838
|
+
default:
|
|
3839
|
+
return null;
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
|
|
3843
|
+
// src/plugins/registry.ts
|
|
3844
|
+
var plugins = [new ClaudeCodePlugin()];
|
|
3845
|
+
|
|
3394
3846
|
// src/app.ts
|
|
3395
3847
|
var STREAM_HEARTBEAT_MS = 25e3;
|
|
3396
3848
|
function createApp({
|
|
@@ -3661,6 +4113,52 @@ function createApp({
|
|
|
3661
4113
|
}
|
|
3662
4114
|
return c.json({ messages: messages2 });
|
|
3663
4115
|
});
|
|
4116
|
+
app2.get("/api/chats/:id/images/:ref", (c) => {
|
|
4117
|
+
const row = reader.findChat(c.req.param("id"));
|
|
4118
|
+
if (!row) return c.json({ error: "Chat not found" }, 404);
|
|
4119
|
+
const plugin = plugins.find((p) => p.id === row.agent);
|
|
4120
|
+
if (!plugin?.resolveImage) {
|
|
4121
|
+
return c.json({ error: "Image not found" }, 404);
|
|
4122
|
+
}
|
|
4123
|
+
const image = plugin.resolveImage(c.req.param("ref"), (messageId) => {
|
|
4124
|
+
const payload = archive2.read.findRawPayloadForMessage(
|
|
4125
|
+
row.agent,
|
|
4126
|
+
row.sourceId,
|
|
4127
|
+
messageId
|
|
4128
|
+
);
|
|
4129
|
+
if (payload === null) return null;
|
|
4130
|
+
try {
|
|
4131
|
+
return JSON.parse(payload);
|
|
4132
|
+
} catch {
|
|
4133
|
+
return null;
|
|
4134
|
+
}
|
|
4135
|
+
});
|
|
4136
|
+
if (!image) return c.json({ error: "Image not found" }, 404);
|
|
4137
|
+
if (image.rendered) {
|
|
4138
|
+
const etag = `"${createHash("sha256").update(image.bytes).digest("base64url").slice(0, 27)}"`;
|
|
4139
|
+
if (c.req.header("if-none-match") === etag) {
|
|
4140
|
+
return c.body(null, 304, { ETag: etag, "Cache-Control": "no-cache" });
|
|
4141
|
+
}
|
|
4142
|
+
return c.body(new Uint8Array(image.bytes), 200, {
|
|
4143
|
+
"Content-Type": image.mediaType,
|
|
4144
|
+
"Cache-Control": "no-cache",
|
|
4145
|
+
ETag: etag,
|
|
4146
|
+
"Content-Security-Policy": "default-src 'none'; style-src 'unsafe-inline'; sandbox",
|
|
4147
|
+
"X-Content-Type-Options": "nosniff"
|
|
4148
|
+
});
|
|
4149
|
+
}
|
|
4150
|
+
return c.body(new Uint8Array(image.bytes), 200, {
|
|
4151
|
+
"Content-Type": image.mediaType,
|
|
4152
|
+
// Verbatim archived bytes never change, so the browser keeps them forever.
|
|
4153
|
+
"Cache-Control": "public, max-age=31536000, immutable",
|
|
4154
|
+
// Archived bytes are the Agent's, not ours — an SVG widget may carry a
|
|
4155
|
+
// script. The pane renders these through `<img>`, which already refuses
|
|
4156
|
+
// to run scripts or load external resources; saying it again in the
|
|
4157
|
+
// headers keeps that true for anyone opening the URL on its own.
|
|
4158
|
+
"Content-Security-Policy": "default-src 'none'; style-src 'unsafe-inline'; sandbox",
|
|
4159
|
+
"X-Content-Type-Options": "nosniff"
|
|
4160
|
+
});
|
|
4161
|
+
});
|
|
3664
4162
|
app2.get("/api/tags", (c) => {
|
|
3665
4163
|
return c.json({ tags: tags3.listTags() });
|
|
3666
4164
|
});
|
|
@@ -5063,7 +5561,7 @@ var QueryPromise = class {
|
|
|
5063
5561
|
function mapResultRow(columns, row, joinsNotNullableMap) {
|
|
5064
5562
|
const nullifyMap = {};
|
|
5065
5563
|
const result = columns.reduce(
|
|
5066
|
-
(result2, { path:
|
|
5564
|
+
(result2, { path: path9, field }, columnIndex) => {
|
|
5067
5565
|
let decoder;
|
|
5068
5566
|
if (is(field, Column)) {
|
|
5069
5567
|
decoder = field;
|
|
@@ -5075,8 +5573,8 @@ function mapResultRow(columns, row, joinsNotNullableMap) {
|
|
|
5075
5573
|
decoder = field.sql.decoder;
|
|
5076
5574
|
}
|
|
5077
5575
|
let node = result2;
|
|
5078
|
-
for (const [pathChunkIndex, pathChunk] of
|
|
5079
|
-
if (pathChunkIndex <
|
|
5576
|
+
for (const [pathChunkIndex, pathChunk] of path9.entries()) {
|
|
5577
|
+
if (pathChunkIndex < path9.length - 1) {
|
|
5080
5578
|
if (!(pathChunk in node)) {
|
|
5081
5579
|
node[pathChunk] = {};
|
|
5082
5580
|
}
|
|
@@ -5084,8 +5582,8 @@ function mapResultRow(columns, row, joinsNotNullableMap) {
|
|
|
5084
5582
|
} else {
|
|
5085
5583
|
const rawValue = row[columnIndex];
|
|
5086
5584
|
const value = node[pathChunk] = rawValue === null ? null : decoder.mapFromDriverValue(rawValue);
|
|
5087
|
-
if (joinsNotNullableMap && is(field, Column) &&
|
|
5088
|
-
const objectName =
|
|
5585
|
+
if (joinsNotNullableMap && is(field, Column) && path9.length === 2) {
|
|
5586
|
+
const objectName = path9[0];
|
|
5089
5587
|
if (!(objectName in nullifyMap)) {
|
|
5090
5588
|
nullifyMap[objectName] = value === null ? getTableName(field.table) : false;
|
|
5091
5589
|
} else if (typeof nullifyMap[objectName] === "string" && nullifyMap[objectName] !== getTableName(field.table)) {
|
|
@@ -5645,8 +6143,8 @@ function mapRelationalRow(tablesConfig, tableConfig, row, buildQueryResultSelect
|
|
|
5645
6143
|
}
|
|
5646
6144
|
|
|
5647
6145
|
// src/storage/openStore.ts
|
|
5648
|
-
import
|
|
5649
|
-
import
|
|
6146
|
+
import fs4 from "fs";
|
|
6147
|
+
import path4 from "path";
|
|
5650
6148
|
import { fileURLToPath } from "url";
|
|
5651
6149
|
import Database2 from "better-sqlite3";
|
|
5652
6150
|
|
|
@@ -9255,20 +9753,20 @@ function drizzle(...params) {
|
|
|
9255
9753
|
|
|
9256
9754
|
// ../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
|
|
9257
9755
|
import crypto4 from "crypto";
|
|
9258
|
-
import
|
|
9756
|
+
import fs3 from "fs";
|
|
9259
9757
|
function readMigrationFiles(config) {
|
|
9260
9758
|
const migrationFolderTo = config.migrationsFolder;
|
|
9261
9759
|
const migrationQueries = [];
|
|
9262
9760
|
const journalPath = `${migrationFolderTo}/meta/_journal.json`;
|
|
9263
|
-
if (!
|
|
9761
|
+
if (!fs3.existsSync(journalPath)) {
|
|
9264
9762
|
throw new Error(`Can't find meta/_journal.json file`);
|
|
9265
9763
|
}
|
|
9266
|
-
const journalAsString =
|
|
9764
|
+
const journalAsString = fs3.readFileSync(`${migrationFolderTo}/meta/_journal.json`).toString();
|
|
9267
9765
|
const journal = JSON.parse(journalAsString);
|
|
9268
9766
|
for (const journalEntry of journal.entries) {
|
|
9269
9767
|
const migrationPath = `${migrationFolderTo}/${journalEntry.tag}.sql`;
|
|
9270
9768
|
try {
|
|
9271
|
-
const query =
|
|
9769
|
+
const query = fs3.readFileSync(`${migrationFolderTo}/${journalEntry.tag}.sql`).toString();
|
|
9272
9770
|
const result = query.split("--> statement-breakpoint").map((it) => {
|
|
9273
9771
|
return it;
|
|
9274
9772
|
});
|
|
@@ -9293,12 +9791,12 @@ function migrate(db, config) {
|
|
|
9293
9791
|
|
|
9294
9792
|
// src/storage/openStore.ts
|
|
9295
9793
|
function resolveMigrationsFolder(callerUrl, migrationsSubdir) {
|
|
9296
|
-
const here =
|
|
9794
|
+
const here = path4.dirname(fileURLToPath(callerUrl));
|
|
9297
9795
|
const candidates = [
|
|
9298
|
-
|
|
9299
|
-
|
|
9796
|
+
path4.join(here, "../..", migrationsSubdir),
|
|
9797
|
+
path4.join(here, ".", migrationsSubdir)
|
|
9300
9798
|
];
|
|
9301
|
-
const found = candidates.find((p) =>
|
|
9799
|
+
const found = candidates.find((p) => fs4.existsSync(p));
|
|
9302
9800
|
if (!found) {
|
|
9303
9801
|
throw new Error(`Could not locate migrations folder "${migrationsSubdir}"`);
|
|
9304
9802
|
}
|
|
@@ -9312,8 +9810,8 @@ function openStore({
|
|
|
9312
9810
|
schema
|
|
9313
9811
|
}) {
|
|
9314
9812
|
const migrationsFolder = resolveMigrationsFolder(callerUrl, migrationsSubdir);
|
|
9315
|
-
|
|
9316
|
-
const sqlite = new Database2(
|
|
9813
|
+
fs4.mkdirSync(dataDir2, { recursive: true });
|
|
9814
|
+
const sqlite = new Database2(path4.join(dataDir2, dbFile));
|
|
9317
9815
|
const db = drizzle(sqlite, { schema });
|
|
9318
9816
|
migrate(db, { migrationsFolder });
|
|
9319
9817
|
return { db, sqlite };
|
|
@@ -9332,7 +9830,12 @@ __export(schema_exports, {
|
|
|
9332
9830
|
var archiveMeta = sqliteTable("archive_meta", {
|
|
9333
9831
|
id: integer("id").primaryKey(),
|
|
9334
9832
|
archiveUuid: text("archive_uuid").notNull(),
|
|
9335
|
-
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull()
|
|
9833
|
+
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
|
|
9834
|
+
// The normalize-output version this archive's Normalized layer was last built
|
|
9835
|
+
// at. Startup compares it to the code's NORMALIZE_VERSION and re-normalizes
|
|
9836
|
+
// from Raw once per bump, so a new block kind reaches dormant chats without
|
|
9837
|
+
// re-reading Source (ADR-0023). Additive, default 0 for existing archives.
|
|
9838
|
+
normalizeVersion: integer("normalize_version").notNull().default(0)
|
|
9336
9839
|
});
|
|
9337
9840
|
var schemaVersion = sqliteTable("schema_version", {
|
|
9338
9841
|
version: integer("version").primaryKey(),
|
|
@@ -9401,6 +9904,13 @@ var messages = sqliteTable(
|
|
|
9401
9904
|
ts: integer("ts", { mode: "timestamp_ms" }).notNull(),
|
|
9402
9905
|
text: text("text").notNull(),
|
|
9403
9906
|
blocks: text("blocks", { mode: "json" }).notNull(),
|
|
9907
|
+
// The model id the Agent recorded on this message (ADR-0023). Nullable:
|
|
9908
|
+
// reader turns record none, and neither do rows normalized before #195 —
|
|
9909
|
+
// those get backfilled by the next re-normalize pass.
|
|
9910
|
+
model: text("model"),
|
|
9911
|
+
// The reasoning effort the Agent recorded for this message (ADR-0023).
|
|
9912
|
+
// Nullable on the same terms as `model`: many turns record none.
|
|
9913
|
+
effort: text("effort"),
|
|
9404
9914
|
rawId: integer("raw_id").notNull().references(() => rawMessages.id)
|
|
9405
9915
|
},
|
|
9406
9916
|
(t) => [
|
|
@@ -9440,6 +9950,16 @@ function createArchiveReadSeam(db) {
|
|
|
9440
9950
|
listMessagesByChat(agent, sourceId) {
|
|
9441
9951
|
return db.select().from(messages).where(and(eq(messages.agent, agent), eq(messages.sourceId, sourceId))).orderBy(asc(messages.ts)).all();
|
|
9442
9952
|
},
|
|
9953
|
+
findRawPayloadForMessage(agent, sourceId, messageId) {
|
|
9954
|
+
const row = db.select({ rawPayload: rawMessages.rawPayload }).from(messages).innerJoin(rawMessages, eq(messages.rawId, rawMessages.id)).where(
|
|
9955
|
+
and(
|
|
9956
|
+
eq(messages.agent, agent),
|
|
9957
|
+
eq(messages.sourceId, sourceId),
|
|
9958
|
+
eq(messages.messageId, messageId)
|
|
9959
|
+
)
|
|
9960
|
+
).get();
|
|
9961
|
+
return row?.rawPayload ?? null;
|
|
9962
|
+
},
|
|
9443
9963
|
listChatTsRanges(opts) {
|
|
9444
9964
|
const scope = opts?.sourceIds !== void 0 ? inArray(messages.sourceId, opts.sourceIds) : sql`1 = 1`;
|
|
9445
9965
|
return db.select({
|
|
@@ -9486,6 +10006,15 @@ function createArchiveReadSeam(db) {
|
|
|
9486
10006
|
},
|
|
9487
10007
|
listIngestionEvents() {
|
|
9488
10008
|
return db.select().from(ingestionEvents).all();
|
|
10009
|
+
},
|
|
10010
|
+
listRawMessages() {
|
|
10011
|
+
return db.select({
|
|
10012
|
+
id: rawMessages.id,
|
|
10013
|
+
agent: rawMessages.agent,
|
|
10014
|
+
sourceId: rawMessages.sourceId,
|
|
10015
|
+
sourcePath: rawMessages.sourcePath,
|
|
10016
|
+
rawPayload: rawMessages.rawPayload
|
|
10017
|
+
}).from(rawMessages).orderBy(asc(rawMessages.id)).all();
|
|
9489
10018
|
}
|
|
9490
10019
|
};
|
|
9491
10020
|
}
|
|
@@ -9532,6 +10061,16 @@ function createArchiveRepository({
|
|
|
9532
10061
|
}
|
|
9533
10062
|
return row.archiveUuid;
|
|
9534
10063
|
},
|
|
10064
|
+
getNormalizeVersion() {
|
|
10065
|
+
const row = db.select().from(archiveMeta).get();
|
|
10066
|
+
if (!row) {
|
|
10067
|
+
throw new Error("archive_meta row missing after initialization");
|
|
10068
|
+
}
|
|
10069
|
+
return row.normalizeVersion;
|
|
10070
|
+
},
|
|
10071
|
+
setNormalizeVersion(version2) {
|
|
10072
|
+
db.update(archiveMeta).set({ normalizeVersion: version2 }).where(eq(archiveMeta.id, 1)).run();
|
|
10073
|
+
},
|
|
9535
10074
|
getAppliedMigrations() {
|
|
9536
10075
|
return db.select().from(schemaVersion).all().map((r) => ({ version: r.version, appliedAt: r.appliedAt }));
|
|
9537
10076
|
},
|
|
@@ -9615,6 +10154,8 @@ function createArchiveRepository({
|
|
|
9615
10154
|
ts,
|
|
9616
10155
|
text: message.text,
|
|
9617
10156
|
blocks: message.blocks,
|
|
10157
|
+
model: message.model ?? null,
|
|
10158
|
+
effort: message.effort ?? null,
|
|
9618
10159
|
rawId
|
|
9619
10160
|
}).run();
|
|
9620
10161
|
return true;
|
|
@@ -9625,6 +10166,8 @@ function createArchiveRepository({
|
|
|
9625
10166
|
ts,
|
|
9626
10167
|
text: message.text,
|
|
9627
10168
|
blocks: message.blocks,
|
|
10169
|
+
model: message.model ?? null,
|
|
10170
|
+
effort: message.effort ?? null,
|
|
9628
10171
|
rawId
|
|
9629
10172
|
}).where(eq(messages.id, existing2.id)).run();
|
|
9630
10173
|
return true;
|
|
@@ -9726,8 +10269,8 @@ function createCheckpointRepository({
|
|
|
9726
10269
|
}
|
|
9727
10270
|
|
|
9728
10271
|
// src/metadata/repository.ts
|
|
9729
|
-
import
|
|
9730
|
-
import
|
|
10272
|
+
import fs5 from "fs";
|
|
10273
|
+
import path5 from "path";
|
|
9731
10274
|
|
|
9732
10275
|
// src/metadata/schema.ts
|
|
9733
10276
|
var schema_exports3 = {};
|
|
@@ -9807,11 +10350,11 @@ function computeSortKey(input) {
|
|
|
9807
10350
|
var DB_FILE = "metadata.db";
|
|
9808
10351
|
var LEGACY_DB_FILE = "data.db";
|
|
9809
10352
|
function migrateLegacyDbFile(dataDir2) {
|
|
9810
|
-
const legacy =
|
|
9811
|
-
const current =
|
|
9812
|
-
if (!
|
|
9813
|
-
if (
|
|
9814
|
-
|
|
10353
|
+
const legacy = path5.join(dataDir2, LEGACY_DB_FILE);
|
|
10354
|
+
const current = path5.join(dataDir2, DB_FILE);
|
|
10355
|
+
if (!fs5.existsSync(legacy)) return;
|
|
10356
|
+
if (fs5.existsSync(current)) return;
|
|
10357
|
+
fs5.renameSync(legacy, current);
|
|
9815
10358
|
}
|
|
9816
10359
|
var CLAUDE_CODE_AGENT = "claude-code";
|
|
9817
10360
|
function createMetadataRepository({
|
|
@@ -10055,7 +10598,7 @@ function createTagRepository({
|
|
|
10055
10598
|
}
|
|
10056
10599
|
|
|
10057
10600
|
// src/ingestion/ingest.ts
|
|
10058
|
-
import
|
|
10601
|
+
import fs6 from "fs";
|
|
10059
10602
|
async function runIngestion(opts) {
|
|
10060
10603
|
const now = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
10061
10604
|
const changedChatIds = /* @__PURE__ */ new Set();
|
|
@@ -10125,7 +10668,7 @@ async function runIngestion(opts) {
|
|
|
10125
10668
|
}
|
|
10126
10669
|
function safeStat(p) {
|
|
10127
10670
|
try {
|
|
10128
|
-
return
|
|
10671
|
+
return fs6.statSync(p);
|
|
10129
10672
|
} catch {
|
|
10130
10673
|
return null;
|
|
10131
10674
|
}
|
|
@@ -10144,6 +10687,55 @@ function startIngestionInBackground(opts, bg = {}) {
|
|
|
10144
10687
|
return { done };
|
|
10145
10688
|
}
|
|
10146
10689
|
|
|
10690
|
+
// src/ingestion/renormalize.ts
|
|
10691
|
+
function renormalizeFromRaw({
|
|
10692
|
+
plugins: plugins2,
|
|
10693
|
+
archive: archive2
|
|
10694
|
+
}) {
|
|
10695
|
+
const pluginById = new Map(plugins2.map((p) => [p.id, p]));
|
|
10696
|
+
const result = { scanned: 0, normalizedUpserted: 0 };
|
|
10697
|
+
for (const raw2 of archive2.read.listRawMessages()) {
|
|
10698
|
+
result.scanned += 1;
|
|
10699
|
+
const plugin = pluginById.get(raw2.agent);
|
|
10700
|
+
if (!plugin) continue;
|
|
10701
|
+
let payload;
|
|
10702
|
+
try {
|
|
10703
|
+
payload = JSON.parse(raw2.rawPayload);
|
|
10704
|
+
} catch {
|
|
10705
|
+
continue;
|
|
10706
|
+
}
|
|
10707
|
+
const record = {
|
|
10708
|
+
sourceId: raw2.sourceId,
|
|
10709
|
+
sourcePath: raw2.sourcePath,
|
|
10710
|
+
// Re-normalize works entirely off the stored payload; the plugin does not
|
|
10711
|
+
// read the file, so a synthetic locator is enough.
|
|
10712
|
+
sourceLocator: "renormalize",
|
|
10713
|
+
payload
|
|
10714
|
+
};
|
|
10715
|
+
const normalized = plugin.normalize(record);
|
|
10716
|
+
if (!normalized) continue;
|
|
10717
|
+
const upserted = archive2.upsertNormalizedMessage({
|
|
10718
|
+
agent: raw2.agent,
|
|
10719
|
+
sourceId: raw2.sourceId,
|
|
10720
|
+
message: normalized,
|
|
10721
|
+
rawId: raw2.id
|
|
10722
|
+
});
|
|
10723
|
+
if (upserted) result.normalizedUpserted += 1;
|
|
10724
|
+
}
|
|
10725
|
+
return result;
|
|
10726
|
+
}
|
|
10727
|
+
var NORMALIZE_VERSION = 11;
|
|
10728
|
+
function runRenormalizeIfStale({
|
|
10729
|
+
plugins: plugins2,
|
|
10730
|
+
archive: archive2,
|
|
10731
|
+
targetVersion = NORMALIZE_VERSION
|
|
10732
|
+
}) {
|
|
10733
|
+
if (archive2.getNormalizeVersion() >= targetVersion) return false;
|
|
10734
|
+
renormalizeFromRaw({ plugins: plugins2, archive: archive2 });
|
|
10735
|
+
archive2.setNormalizeVersion(targetVersion);
|
|
10736
|
+
return true;
|
|
10737
|
+
}
|
|
10738
|
+
|
|
10147
10739
|
// ../node_modules/.pnpm/chokidar@5.0.0/node_modules/chokidar/index.js
|
|
10148
10740
|
import { EventEmitter } from "events";
|
|
10149
10741
|
import { stat as statcb, Stats } from "fs";
|
|
@@ -10234,7 +10826,7 @@ var ReaddirpStream = class extends Readable3 {
|
|
|
10234
10826
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
10235
10827
|
const statMethod = opts.lstat ? lstat : stat;
|
|
10236
10828
|
if (wantBigintFsStats) {
|
|
10237
|
-
this._stat = (
|
|
10829
|
+
this._stat = (path9) => statMethod(path9, { bigint: true });
|
|
10238
10830
|
} else {
|
|
10239
10831
|
this._stat = statMethod;
|
|
10240
10832
|
}
|
|
@@ -10259,8 +10851,8 @@ var ReaddirpStream = class extends Readable3 {
|
|
|
10259
10851
|
const par = this.parent;
|
|
10260
10852
|
const fil = par && par.files;
|
|
10261
10853
|
if (fil && fil.length > 0) {
|
|
10262
|
-
const { path:
|
|
10263
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
10854
|
+
const { path: path9, depth } = par;
|
|
10855
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path9));
|
|
10264
10856
|
const awaited = await Promise.all(slice);
|
|
10265
10857
|
for (const entry of awaited) {
|
|
10266
10858
|
if (!entry)
|
|
@@ -10300,20 +10892,20 @@ var ReaddirpStream = class extends Readable3 {
|
|
|
10300
10892
|
this.reading = false;
|
|
10301
10893
|
}
|
|
10302
10894
|
}
|
|
10303
|
-
async _exploreDir(
|
|
10895
|
+
async _exploreDir(path9, depth) {
|
|
10304
10896
|
let files;
|
|
10305
10897
|
try {
|
|
10306
|
-
files = await readdir(
|
|
10898
|
+
files = await readdir(path9, this._rdOptions);
|
|
10307
10899
|
} catch (error) {
|
|
10308
10900
|
this._onError(error);
|
|
10309
10901
|
}
|
|
10310
|
-
return { files, depth, path:
|
|
10902
|
+
return { files, depth, path: path9 };
|
|
10311
10903
|
}
|
|
10312
|
-
async _formatEntry(dirent,
|
|
10904
|
+
async _formatEntry(dirent, path9) {
|
|
10313
10905
|
let entry;
|
|
10314
10906
|
const basename3 = this._isDirent ? dirent.name : dirent;
|
|
10315
10907
|
try {
|
|
10316
|
-
const fullPath = presolve(pjoin(
|
|
10908
|
+
const fullPath = presolve(pjoin(path9, basename3));
|
|
10317
10909
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename3 };
|
|
10318
10910
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
10319
10911
|
} catch (err) {
|
|
@@ -10713,16 +11305,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
10713
11305
|
};
|
|
10714
11306
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
10715
11307
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
10716
|
-
function createFsWatchInstance(
|
|
11308
|
+
function createFsWatchInstance(path9, options, listener, errHandler, emitRaw) {
|
|
10717
11309
|
const handleEvent = (rawEvent, evPath) => {
|
|
10718
|
-
listener(
|
|
10719
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
10720
|
-
if (evPath &&
|
|
10721
|
-
fsWatchBroadcast(sp.resolve(
|
|
11310
|
+
listener(path9);
|
|
11311
|
+
emitRaw(rawEvent, evPath, { watchedPath: path9 });
|
|
11312
|
+
if (evPath && path9 !== evPath) {
|
|
11313
|
+
fsWatchBroadcast(sp.resolve(path9, evPath), KEY_LISTENERS, sp.join(path9, evPath));
|
|
10722
11314
|
}
|
|
10723
11315
|
};
|
|
10724
11316
|
try {
|
|
10725
|
-
return fs_watch(
|
|
11317
|
+
return fs_watch(path9, {
|
|
10726
11318
|
persistent: options.persistent
|
|
10727
11319
|
}, handleEvent);
|
|
10728
11320
|
} catch (error) {
|
|
@@ -10738,12 +11330,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
10738
11330
|
listener(val1, val2, val3);
|
|
10739
11331
|
});
|
|
10740
11332
|
};
|
|
10741
|
-
var setFsWatchListener = (
|
|
11333
|
+
var setFsWatchListener = (path9, fullPath, options, handlers) => {
|
|
10742
11334
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
10743
11335
|
let cont = FsWatchInstances.get(fullPath);
|
|
10744
11336
|
let watcher2;
|
|
10745
11337
|
if (!options.persistent) {
|
|
10746
|
-
watcher2 = createFsWatchInstance(
|
|
11338
|
+
watcher2 = createFsWatchInstance(path9, options, listener, errHandler, rawEmitter);
|
|
10747
11339
|
if (!watcher2)
|
|
10748
11340
|
return;
|
|
10749
11341
|
return watcher2.close.bind(watcher2);
|
|
@@ -10754,7 +11346,7 @@ var setFsWatchListener = (path8, fullPath, options, handlers) => {
|
|
|
10754
11346
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
10755
11347
|
} else {
|
|
10756
11348
|
watcher2 = createFsWatchInstance(
|
|
10757
|
-
|
|
11349
|
+
path9,
|
|
10758
11350
|
options,
|
|
10759
11351
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
10760
11352
|
errHandler,
|
|
@@ -10769,7 +11361,7 @@ var setFsWatchListener = (path8, fullPath, options, handlers) => {
|
|
|
10769
11361
|
cont.watcherUnusable = true;
|
|
10770
11362
|
if (isWindows && error.code === "EPERM") {
|
|
10771
11363
|
try {
|
|
10772
|
-
const fd = await open(
|
|
11364
|
+
const fd = await open(path9, "r");
|
|
10773
11365
|
await fd.close();
|
|
10774
11366
|
broadcastErr(error);
|
|
10775
11367
|
} catch (err) {
|
|
@@ -10800,7 +11392,7 @@ var setFsWatchListener = (path8, fullPath, options, handlers) => {
|
|
|
10800
11392
|
};
|
|
10801
11393
|
};
|
|
10802
11394
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
10803
|
-
var setFsWatchFileListener = (
|
|
11395
|
+
var setFsWatchFileListener = (path9, fullPath, options, handlers) => {
|
|
10804
11396
|
const { listener, rawEmitter } = handlers;
|
|
10805
11397
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
10806
11398
|
const copts = cont && cont.options;
|
|
@@ -10822,7 +11414,7 @@ var setFsWatchFileListener = (path8, fullPath, options, handlers) => {
|
|
|
10822
11414
|
});
|
|
10823
11415
|
const currmtime = curr.mtimeMs;
|
|
10824
11416
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
10825
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
11417
|
+
foreach(cont.listeners, (listener2) => listener2(path9, curr));
|
|
10826
11418
|
}
|
|
10827
11419
|
})
|
|
10828
11420
|
};
|
|
@@ -10852,13 +11444,13 @@ var NodeFsHandler = class {
|
|
|
10852
11444
|
* @param listener on fs change
|
|
10853
11445
|
* @returns closer for the watcher instance
|
|
10854
11446
|
*/
|
|
10855
|
-
_watchWithNodeFs(
|
|
11447
|
+
_watchWithNodeFs(path9, listener) {
|
|
10856
11448
|
const opts = this.fsw.options;
|
|
10857
|
-
const directory = sp.dirname(
|
|
10858
|
-
const basename3 = sp.basename(
|
|
11449
|
+
const directory = sp.dirname(path9);
|
|
11450
|
+
const basename3 = sp.basename(path9);
|
|
10859
11451
|
const parent = this.fsw._getWatchedDir(directory);
|
|
10860
11452
|
parent.add(basename3);
|
|
10861
|
-
const absolutePath = sp.resolve(
|
|
11453
|
+
const absolutePath = sp.resolve(path9);
|
|
10862
11454
|
const options = {
|
|
10863
11455
|
persistent: opts.persistent
|
|
10864
11456
|
};
|
|
@@ -10868,12 +11460,12 @@ var NodeFsHandler = class {
|
|
|
10868
11460
|
if (opts.usePolling) {
|
|
10869
11461
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
10870
11462
|
options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
|
|
10871
|
-
closer = setFsWatchFileListener(
|
|
11463
|
+
closer = setFsWatchFileListener(path9, absolutePath, options, {
|
|
10872
11464
|
listener,
|
|
10873
11465
|
rawEmitter: this.fsw._emitRaw
|
|
10874
11466
|
});
|
|
10875
11467
|
} else {
|
|
10876
|
-
closer = setFsWatchListener(
|
|
11468
|
+
closer = setFsWatchListener(path9, absolutePath, options, {
|
|
10877
11469
|
listener,
|
|
10878
11470
|
errHandler: this._boundHandleError,
|
|
10879
11471
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -10895,7 +11487,7 @@ var NodeFsHandler = class {
|
|
|
10895
11487
|
let prevStats = stats;
|
|
10896
11488
|
if (parent.has(basename3))
|
|
10897
11489
|
return;
|
|
10898
|
-
const listener = async (
|
|
11490
|
+
const listener = async (path9, newStats) => {
|
|
10899
11491
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
10900
11492
|
return;
|
|
10901
11493
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -10909,11 +11501,11 @@ var NodeFsHandler = class {
|
|
|
10909
11501
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
10910
11502
|
}
|
|
10911
11503
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
10912
|
-
this.fsw._closeFile(
|
|
11504
|
+
this.fsw._closeFile(path9);
|
|
10913
11505
|
prevStats = newStats2;
|
|
10914
11506
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
10915
11507
|
if (closer2)
|
|
10916
|
-
this.fsw._addPathCloser(
|
|
11508
|
+
this.fsw._addPathCloser(path9, closer2);
|
|
10917
11509
|
} else {
|
|
10918
11510
|
prevStats = newStats2;
|
|
10919
11511
|
}
|
|
@@ -10945,7 +11537,7 @@ var NodeFsHandler = class {
|
|
|
10945
11537
|
* @param item basename of this item
|
|
10946
11538
|
* @returns true if no more processing is needed for this entry.
|
|
10947
11539
|
*/
|
|
10948
|
-
async _handleSymlink(entry, directory,
|
|
11540
|
+
async _handleSymlink(entry, directory, path9, item) {
|
|
10949
11541
|
if (this.fsw.closed) {
|
|
10950
11542
|
return;
|
|
10951
11543
|
}
|
|
@@ -10955,7 +11547,7 @@ var NodeFsHandler = class {
|
|
|
10955
11547
|
this.fsw._incrReadyCount();
|
|
10956
11548
|
let linkPath;
|
|
10957
11549
|
try {
|
|
10958
|
-
linkPath = await fsrealpath(
|
|
11550
|
+
linkPath = await fsrealpath(path9);
|
|
10959
11551
|
} catch (e) {
|
|
10960
11552
|
this.fsw._emitReady();
|
|
10961
11553
|
return true;
|
|
@@ -10965,12 +11557,12 @@ var NodeFsHandler = class {
|
|
|
10965
11557
|
if (dir.has(item)) {
|
|
10966
11558
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
10967
11559
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
10968
|
-
this.fsw._emit(EV.CHANGE,
|
|
11560
|
+
this.fsw._emit(EV.CHANGE, path9, entry.stats);
|
|
10969
11561
|
}
|
|
10970
11562
|
} else {
|
|
10971
11563
|
dir.add(item);
|
|
10972
11564
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
10973
|
-
this.fsw._emit(EV.ADD,
|
|
11565
|
+
this.fsw._emit(EV.ADD, path9, entry.stats);
|
|
10974
11566
|
}
|
|
10975
11567
|
this.fsw._emitReady();
|
|
10976
11568
|
return true;
|
|
@@ -11000,9 +11592,9 @@ var NodeFsHandler = class {
|
|
|
11000
11592
|
return;
|
|
11001
11593
|
}
|
|
11002
11594
|
const item = entry.path;
|
|
11003
|
-
let
|
|
11595
|
+
let path9 = sp.join(directory, item);
|
|
11004
11596
|
current.add(item);
|
|
11005
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
11597
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path9, item)) {
|
|
11006
11598
|
return;
|
|
11007
11599
|
}
|
|
11008
11600
|
if (this.fsw.closed) {
|
|
@@ -11011,8 +11603,8 @@ var NodeFsHandler = class {
|
|
|
11011
11603
|
}
|
|
11012
11604
|
if (item === target || !target && !previous.has(item)) {
|
|
11013
11605
|
this.fsw._incrReadyCount();
|
|
11014
|
-
|
|
11015
|
-
this._addToNodeFs(
|
|
11606
|
+
path9 = sp.join(dir, sp.relative(dir, path9));
|
|
11607
|
+
this._addToNodeFs(path9, initialAdd, wh, depth + 1);
|
|
11016
11608
|
}
|
|
11017
11609
|
}).on(EV.ERROR, this._boundHandleError);
|
|
11018
11610
|
return new Promise((resolve3, reject) => {
|
|
@@ -11081,13 +11673,13 @@ var NodeFsHandler = class {
|
|
|
11081
11673
|
* @param depth Child path actually targeted for watch
|
|
11082
11674
|
* @param target Child path actually targeted for watch
|
|
11083
11675
|
*/
|
|
11084
|
-
async _addToNodeFs(
|
|
11676
|
+
async _addToNodeFs(path9, initialAdd, priorWh, depth, target) {
|
|
11085
11677
|
const ready = this.fsw._emitReady;
|
|
11086
|
-
if (this.fsw._isIgnored(
|
|
11678
|
+
if (this.fsw._isIgnored(path9) || this.fsw.closed) {
|
|
11087
11679
|
ready();
|
|
11088
11680
|
return false;
|
|
11089
11681
|
}
|
|
11090
|
-
const wh = this.fsw._getWatchHelpers(
|
|
11682
|
+
const wh = this.fsw._getWatchHelpers(path9);
|
|
11091
11683
|
if (priorWh) {
|
|
11092
11684
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
11093
11685
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -11103,8 +11695,8 @@ var NodeFsHandler = class {
|
|
|
11103
11695
|
const follow = this.fsw.options.followSymlinks;
|
|
11104
11696
|
let closer;
|
|
11105
11697
|
if (stats.isDirectory()) {
|
|
11106
|
-
const absPath = sp.resolve(
|
|
11107
|
-
const targetPath = follow ? await fsrealpath(
|
|
11698
|
+
const absPath = sp.resolve(path9);
|
|
11699
|
+
const targetPath = follow ? await fsrealpath(path9) : path9;
|
|
11108
11700
|
if (this.fsw.closed)
|
|
11109
11701
|
return;
|
|
11110
11702
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -11114,29 +11706,29 @@ var NodeFsHandler = class {
|
|
|
11114
11706
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
11115
11707
|
}
|
|
11116
11708
|
} else if (stats.isSymbolicLink()) {
|
|
11117
|
-
const targetPath = follow ? await fsrealpath(
|
|
11709
|
+
const targetPath = follow ? await fsrealpath(path9) : path9;
|
|
11118
11710
|
if (this.fsw.closed)
|
|
11119
11711
|
return;
|
|
11120
11712
|
const parent = sp.dirname(wh.watchPath);
|
|
11121
11713
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
11122
11714
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
11123
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
11715
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path9, wh, targetPath);
|
|
11124
11716
|
if (this.fsw.closed)
|
|
11125
11717
|
return;
|
|
11126
11718
|
if (targetPath !== void 0) {
|
|
11127
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
11719
|
+
this.fsw._symlinkPaths.set(sp.resolve(path9), targetPath);
|
|
11128
11720
|
}
|
|
11129
11721
|
} else {
|
|
11130
11722
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
11131
11723
|
}
|
|
11132
11724
|
ready();
|
|
11133
11725
|
if (closer)
|
|
11134
|
-
this.fsw._addPathCloser(
|
|
11726
|
+
this.fsw._addPathCloser(path9, closer);
|
|
11135
11727
|
return false;
|
|
11136
11728
|
} catch (error) {
|
|
11137
11729
|
if (this.fsw._handleError(error)) {
|
|
11138
11730
|
ready();
|
|
11139
|
-
return
|
|
11731
|
+
return path9;
|
|
11140
11732
|
}
|
|
11141
11733
|
}
|
|
11142
11734
|
}
|
|
@@ -11179,24 +11771,24 @@ function createPattern(matcher) {
|
|
|
11179
11771
|
}
|
|
11180
11772
|
return () => false;
|
|
11181
11773
|
}
|
|
11182
|
-
function normalizePath(
|
|
11183
|
-
if (typeof
|
|
11774
|
+
function normalizePath(path9) {
|
|
11775
|
+
if (typeof path9 !== "string")
|
|
11184
11776
|
throw new Error("string expected");
|
|
11185
|
-
|
|
11186
|
-
|
|
11777
|
+
path9 = sp2.normalize(path9);
|
|
11778
|
+
path9 = path9.replace(/\\/g, "/");
|
|
11187
11779
|
let prepend = false;
|
|
11188
|
-
if (
|
|
11780
|
+
if (path9.startsWith("//"))
|
|
11189
11781
|
prepend = true;
|
|
11190
|
-
|
|
11782
|
+
path9 = path9.replace(DOUBLE_SLASH_RE, "/");
|
|
11191
11783
|
if (prepend)
|
|
11192
|
-
|
|
11193
|
-
return
|
|
11784
|
+
path9 = "/" + path9;
|
|
11785
|
+
return path9;
|
|
11194
11786
|
}
|
|
11195
11787
|
function matchPatterns(patterns, testString, stats) {
|
|
11196
|
-
const
|
|
11788
|
+
const path9 = normalizePath(testString);
|
|
11197
11789
|
for (let index2 = 0; index2 < patterns.length; index2++) {
|
|
11198
11790
|
const pattern = patterns[index2];
|
|
11199
|
-
if (pattern(
|
|
11791
|
+
if (pattern(path9, stats)) {
|
|
11200
11792
|
return true;
|
|
11201
11793
|
}
|
|
11202
11794
|
}
|
|
@@ -11234,19 +11826,19 @@ var toUnix = (string) => {
|
|
|
11234
11826
|
}
|
|
11235
11827
|
return str;
|
|
11236
11828
|
};
|
|
11237
|
-
var normalizePathToUnix = (
|
|
11238
|
-
var normalizeIgnored = (cwd = "") => (
|
|
11239
|
-
if (typeof
|
|
11240
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
11829
|
+
var normalizePathToUnix = (path9) => toUnix(sp2.normalize(toUnix(path9)));
|
|
11830
|
+
var normalizeIgnored = (cwd = "") => (path9) => {
|
|
11831
|
+
if (typeof path9 === "string") {
|
|
11832
|
+
return normalizePathToUnix(sp2.isAbsolute(path9) ? path9 : sp2.join(cwd, path9));
|
|
11241
11833
|
} else {
|
|
11242
|
-
return
|
|
11834
|
+
return path9;
|
|
11243
11835
|
}
|
|
11244
11836
|
};
|
|
11245
|
-
var getAbsolutePath = (
|
|
11246
|
-
if (sp2.isAbsolute(
|
|
11247
|
-
return
|
|
11837
|
+
var getAbsolutePath = (path9, cwd) => {
|
|
11838
|
+
if (sp2.isAbsolute(path9)) {
|
|
11839
|
+
return path9;
|
|
11248
11840
|
}
|
|
11249
|
-
return sp2.join(cwd,
|
|
11841
|
+
return sp2.join(cwd, path9);
|
|
11250
11842
|
};
|
|
11251
11843
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
11252
11844
|
var DirEntry = class {
|
|
@@ -11311,10 +11903,10 @@ var WatchHelper = class {
|
|
|
11311
11903
|
dirParts;
|
|
11312
11904
|
followSymlinks;
|
|
11313
11905
|
statMethod;
|
|
11314
|
-
constructor(
|
|
11906
|
+
constructor(path9, follow, fsw) {
|
|
11315
11907
|
this.fsw = fsw;
|
|
11316
|
-
const watchPath =
|
|
11317
|
-
this.path =
|
|
11908
|
+
const watchPath = path9;
|
|
11909
|
+
this.path = path9 = path9.replace(REPLACER_RE, "");
|
|
11318
11910
|
this.watchPath = watchPath;
|
|
11319
11911
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
11320
11912
|
this.dirParts = [];
|
|
@@ -11454,20 +12046,20 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11454
12046
|
this._closePromise = void 0;
|
|
11455
12047
|
let paths = unifyPaths(paths_);
|
|
11456
12048
|
if (cwd) {
|
|
11457
|
-
paths = paths.map((
|
|
11458
|
-
const absPath = getAbsolutePath(
|
|
12049
|
+
paths = paths.map((path9) => {
|
|
12050
|
+
const absPath = getAbsolutePath(path9, cwd);
|
|
11459
12051
|
return absPath;
|
|
11460
12052
|
});
|
|
11461
12053
|
}
|
|
11462
|
-
paths.forEach((
|
|
11463
|
-
this._removeIgnoredPath(
|
|
12054
|
+
paths.forEach((path9) => {
|
|
12055
|
+
this._removeIgnoredPath(path9);
|
|
11464
12056
|
});
|
|
11465
12057
|
this._userIgnored = void 0;
|
|
11466
12058
|
if (!this._readyCount)
|
|
11467
12059
|
this._readyCount = 0;
|
|
11468
12060
|
this._readyCount += paths.length;
|
|
11469
|
-
Promise.all(paths.map(async (
|
|
11470
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
12061
|
+
Promise.all(paths.map(async (path9) => {
|
|
12062
|
+
const res = await this._nodeFsHandler._addToNodeFs(path9, !_internal, void 0, 0, _origAdd);
|
|
11471
12063
|
if (res)
|
|
11472
12064
|
this._emitReady();
|
|
11473
12065
|
return res;
|
|
@@ -11489,17 +12081,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11489
12081
|
return this;
|
|
11490
12082
|
const paths = unifyPaths(paths_);
|
|
11491
12083
|
const { cwd } = this.options;
|
|
11492
|
-
paths.forEach((
|
|
11493
|
-
if (!sp2.isAbsolute(
|
|
12084
|
+
paths.forEach((path9) => {
|
|
12085
|
+
if (!sp2.isAbsolute(path9) && !this._closers.has(path9)) {
|
|
11494
12086
|
if (cwd)
|
|
11495
|
-
|
|
11496
|
-
|
|
12087
|
+
path9 = sp2.join(cwd, path9);
|
|
12088
|
+
path9 = sp2.resolve(path9);
|
|
11497
12089
|
}
|
|
11498
|
-
this._closePath(
|
|
11499
|
-
this._addIgnoredPath(
|
|
11500
|
-
if (this._watched.has(
|
|
12090
|
+
this._closePath(path9);
|
|
12091
|
+
this._addIgnoredPath(path9);
|
|
12092
|
+
if (this._watched.has(path9)) {
|
|
11501
12093
|
this._addIgnoredPath({
|
|
11502
|
-
path:
|
|
12094
|
+
path: path9,
|
|
11503
12095
|
recursive: true
|
|
11504
12096
|
});
|
|
11505
12097
|
}
|
|
@@ -11563,38 +12155,38 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11563
12155
|
* @param stats arguments to be passed with event
|
|
11564
12156
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
11565
12157
|
*/
|
|
11566
|
-
async _emit(event,
|
|
12158
|
+
async _emit(event, path9, stats) {
|
|
11567
12159
|
if (this.closed)
|
|
11568
12160
|
return;
|
|
11569
12161
|
const opts = this.options;
|
|
11570
12162
|
if (isWindows)
|
|
11571
|
-
|
|
12163
|
+
path9 = sp2.normalize(path9);
|
|
11572
12164
|
if (opts.cwd)
|
|
11573
|
-
|
|
11574
|
-
const args = [
|
|
12165
|
+
path9 = sp2.relative(opts.cwd, path9);
|
|
12166
|
+
const args = [path9];
|
|
11575
12167
|
if (stats != null)
|
|
11576
12168
|
args.push(stats);
|
|
11577
12169
|
const awf = opts.awaitWriteFinish;
|
|
11578
12170
|
let pw;
|
|
11579
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
12171
|
+
if (awf && (pw = this._pendingWrites.get(path9))) {
|
|
11580
12172
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
11581
12173
|
return this;
|
|
11582
12174
|
}
|
|
11583
12175
|
if (opts.atomic) {
|
|
11584
12176
|
if (event === EVENTS.UNLINK) {
|
|
11585
|
-
this._pendingUnlinks.set(
|
|
12177
|
+
this._pendingUnlinks.set(path9, [event, ...args]);
|
|
11586
12178
|
setTimeout(() => {
|
|
11587
|
-
this._pendingUnlinks.forEach((entry,
|
|
12179
|
+
this._pendingUnlinks.forEach((entry, path10) => {
|
|
11588
12180
|
this.emit(...entry);
|
|
11589
12181
|
this.emit(EVENTS.ALL, ...entry);
|
|
11590
|
-
this._pendingUnlinks.delete(
|
|
12182
|
+
this._pendingUnlinks.delete(path10);
|
|
11591
12183
|
});
|
|
11592
12184
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
11593
12185
|
return this;
|
|
11594
12186
|
}
|
|
11595
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
12187
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path9)) {
|
|
11596
12188
|
event = EVENTS.CHANGE;
|
|
11597
|
-
this._pendingUnlinks.delete(
|
|
12189
|
+
this._pendingUnlinks.delete(path9);
|
|
11598
12190
|
}
|
|
11599
12191
|
}
|
|
11600
12192
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -11612,16 +12204,16 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11612
12204
|
this.emitWithAll(event, args);
|
|
11613
12205
|
}
|
|
11614
12206
|
};
|
|
11615
|
-
this._awaitWriteFinish(
|
|
12207
|
+
this._awaitWriteFinish(path9, awf.stabilityThreshold, event, awfEmit);
|
|
11616
12208
|
return this;
|
|
11617
12209
|
}
|
|
11618
12210
|
if (event === EVENTS.CHANGE) {
|
|
11619
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
12211
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path9, 50);
|
|
11620
12212
|
if (isThrottled)
|
|
11621
12213
|
return this;
|
|
11622
12214
|
}
|
|
11623
12215
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
11624
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
12216
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path9) : path9;
|
|
11625
12217
|
let stats2;
|
|
11626
12218
|
try {
|
|
11627
12219
|
stats2 = await stat3(fullPath);
|
|
@@ -11652,23 +12244,23 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11652
12244
|
* @param timeout duration of time to suppress duplicate actions
|
|
11653
12245
|
* @returns tracking object or false if action should be suppressed
|
|
11654
12246
|
*/
|
|
11655
|
-
_throttle(actionType,
|
|
12247
|
+
_throttle(actionType, path9, timeout) {
|
|
11656
12248
|
if (!this._throttled.has(actionType)) {
|
|
11657
12249
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
11658
12250
|
}
|
|
11659
12251
|
const action2 = this._throttled.get(actionType);
|
|
11660
12252
|
if (!action2)
|
|
11661
12253
|
throw new Error("invalid throttle");
|
|
11662
|
-
const actionPath = action2.get(
|
|
12254
|
+
const actionPath = action2.get(path9);
|
|
11663
12255
|
if (actionPath) {
|
|
11664
12256
|
actionPath.count++;
|
|
11665
12257
|
return false;
|
|
11666
12258
|
}
|
|
11667
12259
|
let timeoutObject;
|
|
11668
12260
|
const clear = () => {
|
|
11669
|
-
const item = action2.get(
|
|
12261
|
+
const item = action2.get(path9);
|
|
11670
12262
|
const count = item ? item.count : 0;
|
|
11671
|
-
action2.delete(
|
|
12263
|
+
action2.delete(path9);
|
|
11672
12264
|
clearTimeout(timeoutObject);
|
|
11673
12265
|
if (item)
|
|
11674
12266
|
clearTimeout(item.timeoutObject);
|
|
@@ -11676,7 +12268,7 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11676
12268
|
};
|
|
11677
12269
|
timeoutObject = setTimeout(clear, timeout);
|
|
11678
12270
|
const thr = { timeoutObject, clear, count: 0 };
|
|
11679
|
-
action2.set(
|
|
12271
|
+
action2.set(path9, thr);
|
|
11680
12272
|
return thr;
|
|
11681
12273
|
}
|
|
11682
12274
|
_incrReadyCount() {
|
|
@@ -11690,44 +12282,44 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11690
12282
|
* @param event
|
|
11691
12283
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
11692
12284
|
*/
|
|
11693
|
-
_awaitWriteFinish(
|
|
12285
|
+
_awaitWriteFinish(path9, threshold, event, awfEmit) {
|
|
11694
12286
|
const awf = this.options.awaitWriteFinish;
|
|
11695
12287
|
if (typeof awf !== "object")
|
|
11696
12288
|
return;
|
|
11697
12289
|
const pollInterval = awf.pollInterval;
|
|
11698
12290
|
let timeoutHandler;
|
|
11699
|
-
let fullPath =
|
|
11700
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
11701
|
-
fullPath = sp2.join(this.options.cwd,
|
|
12291
|
+
let fullPath = path9;
|
|
12292
|
+
if (this.options.cwd && !sp2.isAbsolute(path9)) {
|
|
12293
|
+
fullPath = sp2.join(this.options.cwd, path9);
|
|
11702
12294
|
}
|
|
11703
12295
|
const now = /* @__PURE__ */ new Date();
|
|
11704
12296
|
const writes = this._pendingWrites;
|
|
11705
12297
|
function awaitWriteFinishFn(prevStat) {
|
|
11706
12298
|
statcb(fullPath, (err, curStat) => {
|
|
11707
|
-
if (err || !writes.has(
|
|
12299
|
+
if (err || !writes.has(path9)) {
|
|
11708
12300
|
if (err && err.code !== "ENOENT")
|
|
11709
12301
|
awfEmit(err);
|
|
11710
12302
|
return;
|
|
11711
12303
|
}
|
|
11712
12304
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
11713
12305
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
11714
|
-
writes.get(
|
|
12306
|
+
writes.get(path9).lastChange = now2;
|
|
11715
12307
|
}
|
|
11716
|
-
const pw = writes.get(
|
|
12308
|
+
const pw = writes.get(path9);
|
|
11717
12309
|
const df = now2 - pw.lastChange;
|
|
11718
12310
|
if (df >= threshold) {
|
|
11719
|
-
writes.delete(
|
|
12311
|
+
writes.delete(path9);
|
|
11720
12312
|
awfEmit(void 0, curStat);
|
|
11721
12313
|
} else {
|
|
11722
12314
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
11723
12315
|
}
|
|
11724
12316
|
});
|
|
11725
12317
|
}
|
|
11726
|
-
if (!writes.has(
|
|
11727
|
-
writes.set(
|
|
12318
|
+
if (!writes.has(path9)) {
|
|
12319
|
+
writes.set(path9, {
|
|
11728
12320
|
lastChange: now,
|
|
11729
12321
|
cancelWait: () => {
|
|
11730
|
-
writes.delete(
|
|
12322
|
+
writes.delete(path9);
|
|
11731
12323
|
clearTimeout(timeoutHandler);
|
|
11732
12324
|
return event;
|
|
11733
12325
|
}
|
|
@@ -11738,8 +12330,8 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11738
12330
|
/**
|
|
11739
12331
|
* Determines whether user has asked to ignore this path.
|
|
11740
12332
|
*/
|
|
11741
|
-
_isIgnored(
|
|
11742
|
-
if (this.options.atomic && DOT_RE.test(
|
|
12333
|
+
_isIgnored(path9, stats) {
|
|
12334
|
+
if (this.options.atomic && DOT_RE.test(path9))
|
|
11743
12335
|
return true;
|
|
11744
12336
|
if (!this._userIgnored) {
|
|
11745
12337
|
const { cwd } = this.options;
|
|
@@ -11749,17 +12341,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11749
12341
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
11750
12342
|
this._userIgnored = anymatch(list, void 0);
|
|
11751
12343
|
}
|
|
11752
|
-
return this._userIgnored(
|
|
12344
|
+
return this._userIgnored(path9, stats);
|
|
11753
12345
|
}
|
|
11754
|
-
_isntIgnored(
|
|
11755
|
-
return !this._isIgnored(
|
|
12346
|
+
_isntIgnored(path9, stat4) {
|
|
12347
|
+
return !this._isIgnored(path9, stat4);
|
|
11756
12348
|
}
|
|
11757
12349
|
/**
|
|
11758
12350
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
11759
12351
|
* @param path file or directory pattern being watched
|
|
11760
12352
|
*/
|
|
11761
|
-
_getWatchHelpers(
|
|
11762
|
-
return new WatchHelper(
|
|
12353
|
+
_getWatchHelpers(path9) {
|
|
12354
|
+
return new WatchHelper(path9, this.options.followSymlinks, this);
|
|
11763
12355
|
}
|
|
11764
12356
|
// Directory helpers
|
|
11765
12357
|
// -----------------
|
|
@@ -11791,63 +12383,63 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11791
12383
|
* @param item base path of item/directory
|
|
11792
12384
|
*/
|
|
11793
12385
|
_remove(directory, item, isDirectory) {
|
|
11794
|
-
const
|
|
11795
|
-
const fullPath = sp2.resolve(
|
|
11796
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
11797
|
-
if (!this._throttle("remove",
|
|
12386
|
+
const path9 = sp2.join(directory, item);
|
|
12387
|
+
const fullPath = sp2.resolve(path9);
|
|
12388
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path9) || this._watched.has(fullPath);
|
|
12389
|
+
if (!this._throttle("remove", path9, 100))
|
|
11798
12390
|
return;
|
|
11799
12391
|
if (!isDirectory && this._watched.size === 1) {
|
|
11800
12392
|
this.add(directory, item, true);
|
|
11801
12393
|
}
|
|
11802
|
-
const wp = this._getWatchedDir(
|
|
12394
|
+
const wp = this._getWatchedDir(path9);
|
|
11803
12395
|
const nestedDirectoryChildren = wp.getChildren();
|
|
11804
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
12396
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path9, nested));
|
|
11805
12397
|
const parent = this._getWatchedDir(directory);
|
|
11806
12398
|
const wasTracked = parent.has(item);
|
|
11807
12399
|
parent.remove(item);
|
|
11808
12400
|
if (this._symlinkPaths.has(fullPath)) {
|
|
11809
12401
|
this._symlinkPaths.delete(fullPath);
|
|
11810
12402
|
}
|
|
11811
|
-
let relPath =
|
|
12403
|
+
let relPath = path9;
|
|
11812
12404
|
if (this.options.cwd)
|
|
11813
|
-
relPath = sp2.relative(this.options.cwd,
|
|
12405
|
+
relPath = sp2.relative(this.options.cwd, path9);
|
|
11814
12406
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
11815
12407
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
11816
12408
|
if (event === EVENTS.ADD)
|
|
11817
12409
|
return;
|
|
11818
12410
|
}
|
|
11819
|
-
this._watched.delete(
|
|
12411
|
+
this._watched.delete(path9);
|
|
11820
12412
|
this._watched.delete(fullPath);
|
|
11821
12413
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
11822
|
-
if (wasTracked && !this._isIgnored(
|
|
11823
|
-
this._emit(eventName,
|
|
11824
|
-
this._closePath(
|
|
12414
|
+
if (wasTracked && !this._isIgnored(path9))
|
|
12415
|
+
this._emit(eventName, path9);
|
|
12416
|
+
this._closePath(path9);
|
|
11825
12417
|
}
|
|
11826
12418
|
/**
|
|
11827
12419
|
* Closes all watchers for a path
|
|
11828
12420
|
*/
|
|
11829
|
-
_closePath(
|
|
11830
|
-
this._closeFile(
|
|
11831
|
-
const dir = sp2.dirname(
|
|
11832
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
12421
|
+
_closePath(path9) {
|
|
12422
|
+
this._closeFile(path9);
|
|
12423
|
+
const dir = sp2.dirname(path9);
|
|
12424
|
+
this._getWatchedDir(dir).remove(sp2.basename(path9));
|
|
11833
12425
|
}
|
|
11834
12426
|
/**
|
|
11835
12427
|
* Closes only file-specific watchers
|
|
11836
12428
|
*/
|
|
11837
|
-
_closeFile(
|
|
11838
|
-
const closers = this._closers.get(
|
|
12429
|
+
_closeFile(path9) {
|
|
12430
|
+
const closers = this._closers.get(path9);
|
|
11839
12431
|
if (!closers)
|
|
11840
12432
|
return;
|
|
11841
12433
|
closers.forEach((closer) => closer());
|
|
11842
|
-
this._closers.delete(
|
|
12434
|
+
this._closers.delete(path9);
|
|
11843
12435
|
}
|
|
11844
|
-
_addPathCloser(
|
|
12436
|
+
_addPathCloser(path9, closer) {
|
|
11845
12437
|
if (!closer)
|
|
11846
12438
|
return;
|
|
11847
|
-
let list = this._closers.get(
|
|
12439
|
+
let list = this._closers.get(path9);
|
|
11848
12440
|
if (!list) {
|
|
11849
12441
|
list = [];
|
|
11850
|
-
this._closers.set(
|
|
12442
|
+
this._closers.set(path9, list);
|
|
11851
12443
|
}
|
|
11852
12444
|
list.push(closer);
|
|
11853
12445
|
}
|
|
@@ -11945,13 +12537,13 @@ function startWatcher(opts) {
|
|
|
11945
12537
|
}
|
|
11946
12538
|
return {
|
|
11947
12539
|
ready,
|
|
11948
|
-
notifyChange(
|
|
11949
|
-
if (watcher2) watcher2.emit("change",
|
|
11950
|
-
else scheduleIngest(
|
|
12540
|
+
notifyChange(path9) {
|
|
12541
|
+
if (watcher2) watcher2.emit("change", path9);
|
|
12542
|
+
else scheduleIngest(path9);
|
|
11951
12543
|
},
|
|
11952
|
-
notifyUnlink(
|
|
11953
|
-
if (watcher2) watcher2.emit("unlink",
|
|
11954
|
-
else recordUnlink(
|
|
12544
|
+
notifyUnlink(path9) {
|
|
12545
|
+
if (watcher2) watcher2.emit("unlink", path9);
|
|
12546
|
+
else recordUnlink(path9);
|
|
11955
12547
|
},
|
|
11956
12548
|
async close() {
|
|
11957
12549
|
closed = true;
|
|
@@ -11962,139 +12554,6 @@ function startWatcher(opts) {
|
|
|
11962
12554
|
};
|
|
11963
12555
|
}
|
|
11964
12556
|
|
|
11965
|
-
// src/plugins/claude-code/plugin.ts
|
|
11966
|
-
import fs6 from "fs";
|
|
11967
|
-
import path4 from "path";
|
|
11968
|
-
import readline from "readline";
|
|
11969
|
-
var ClaudeCodePlugin = class {
|
|
11970
|
-
id = "claude-code";
|
|
11971
|
-
displayName = "Claude Code";
|
|
11972
|
-
async *discover(env) {
|
|
11973
|
-
const projectsDir = path4.join(env.homeDir, ".claude", "projects");
|
|
11974
|
-
if (!fs6.existsSync(projectsDir)) return;
|
|
11975
|
-
const projects = fs6.readdirSync(projectsDir, { withFileTypes: true });
|
|
11976
|
-
for (const project of projects) {
|
|
11977
|
-
if (!project.isDirectory()) continue;
|
|
11978
|
-
const projectPath = path4.join(projectsDir, project.name);
|
|
11979
|
-
const files = fs6.readdirSync(projectPath, { withFileTypes: true });
|
|
11980
|
-
for (const file of files) {
|
|
11981
|
-
if (!file.isFile() || !file.name.endsWith(".jsonl")) continue;
|
|
11982
|
-
const sourcePath = path4.join(projectPath, file.name);
|
|
11983
|
-
const sourceId = file.name.replace(/\.jsonl$/, "");
|
|
11984
|
-
const cwd = await readCwdFromJsonl(sourcePath);
|
|
11985
|
-
yield {
|
|
11986
|
-
sourceId,
|
|
11987
|
-
sourcePath,
|
|
11988
|
-
watchPaths: [sourcePath],
|
|
11989
|
-
project: cwd ? path4.basename(cwd) : void 0,
|
|
11990
|
-
projectPath: cwd ?? void 0
|
|
11991
|
-
};
|
|
11992
|
-
}
|
|
11993
|
-
}
|
|
11994
|
-
}
|
|
11995
|
-
async *extractRaw(ref) {
|
|
11996
|
-
if (!fs6.existsSync(ref.sourcePath)) return;
|
|
11997
|
-
const stream2 = fs6.createReadStream(ref.sourcePath, { encoding: "utf-8" });
|
|
11998
|
-
const rl = readline.createInterface({ input: stream2, crlfDelay: Infinity });
|
|
11999
|
-
let lineNo = 0;
|
|
12000
|
-
for await (const line of rl) {
|
|
12001
|
-
lineNo += 1;
|
|
12002
|
-
if (!line) continue;
|
|
12003
|
-
yield {
|
|
12004
|
-
sourceId: ref.sourceId,
|
|
12005
|
-
sourcePath: ref.sourcePath,
|
|
12006
|
-
sourceLocator: `L${lineNo}`,
|
|
12007
|
-
payload: JSON.parse(line)
|
|
12008
|
-
};
|
|
12009
|
-
}
|
|
12010
|
-
}
|
|
12011
|
-
normalize(raw2) {
|
|
12012
|
-
const payload = raw2.payload;
|
|
12013
|
-
if (!payload || typeof payload !== "object") return null;
|
|
12014
|
-
if (payload.type !== "user" && payload.type !== "assistant") return null;
|
|
12015
|
-
if (payload.isMeta === true) return null;
|
|
12016
|
-
if (payload.isSidechain === true) return null;
|
|
12017
|
-
const message = payload.message;
|
|
12018
|
-
if (!message) return null;
|
|
12019
|
-
const role = message.role === "assistant" ? "assistant" : "user";
|
|
12020
|
-
const messageId = String(payload.uuid ?? "");
|
|
12021
|
-
const ts = String(payload.timestamp ?? "");
|
|
12022
|
-
if (typeof message.content === "string") {
|
|
12023
|
-
const text2 = message.content;
|
|
12024
|
-
return {
|
|
12025
|
-
messageId,
|
|
12026
|
-
role,
|
|
12027
|
-
ts,
|
|
12028
|
-
text: text2,
|
|
12029
|
-
blocks: [{ type: "text", text: text2 }]
|
|
12030
|
-
};
|
|
12031
|
-
}
|
|
12032
|
-
if (Array.isArray(message.content)) {
|
|
12033
|
-
const blocks = [];
|
|
12034
|
-
for (const block of message.content) {
|
|
12035
|
-
const normalized = normalizeBlock(block);
|
|
12036
|
-
if (normalized) blocks.push(normalized);
|
|
12037
|
-
}
|
|
12038
|
-
const text2 = blocks.filter((b) => b.type === "text").map((b) => b.text).join("\n");
|
|
12039
|
-
return { messageId, role, ts, text: text2, blocks };
|
|
12040
|
-
}
|
|
12041
|
-
return null;
|
|
12042
|
-
}
|
|
12043
|
-
};
|
|
12044
|
-
async function readCwdFromJsonl(sourcePath) {
|
|
12045
|
-
try {
|
|
12046
|
-
const stream2 = fs6.createReadStream(sourcePath, { encoding: "utf-8" });
|
|
12047
|
-
const rl = readline.createInterface({ input: stream2, crlfDelay: Infinity });
|
|
12048
|
-
try {
|
|
12049
|
-
for await (const line of rl) {
|
|
12050
|
-
if (!line) continue;
|
|
12051
|
-
let obj;
|
|
12052
|
-
try {
|
|
12053
|
-
obj = JSON.parse(line);
|
|
12054
|
-
} catch {
|
|
12055
|
-
continue;
|
|
12056
|
-
}
|
|
12057
|
-
if (typeof obj.cwd === "string" && obj.cwd.length > 0) {
|
|
12058
|
-
return obj.cwd;
|
|
12059
|
-
}
|
|
12060
|
-
}
|
|
12061
|
-
} finally {
|
|
12062
|
-
rl.close();
|
|
12063
|
-
stream2.destroy();
|
|
12064
|
-
}
|
|
12065
|
-
} catch {
|
|
12066
|
-
}
|
|
12067
|
-
return void 0;
|
|
12068
|
-
}
|
|
12069
|
-
function normalizeBlock(raw2) {
|
|
12070
|
-
if (!raw2 || typeof raw2 !== "object") return null;
|
|
12071
|
-
const b = raw2;
|
|
12072
|
-
switch (b.type) {
|
|
12073
|
-
case "text":
|
|
12074
|
-
return { type: "text", text: String(b.text ?? "") };
|
|
12075
|
-
case "thinking":
|
|
12076
|
-
return { type: "thinking", thinking: String(b.thinking ?? "") };
|
|
12077
|
-
case "tool_use":
|
|
12078
|
-
return {
|
|
12079
|
-
type: "tool_use",
|
|
12080
|
-
id: String(b.id ?? ""),
|
|
12081
|
-
name: String(b.name ?? ""),
|
|
12082
|
-
input: b.input
|
|
12083
|
-
};
|
|
12084
|
-
case "tool_result":
|
|
12085
|
-
return {
|
|
12086
|
-
type: "tool_result",
|
|
12087
|
-
toolUseId: String(b.tool_use_id ?? ""),
|
|
12088
|
-
content: b.content
|
|
12089
|
-
};
|
|
12090
|
-
default:
|
|
12091
|
-
return null;
|
|
12092
|
-
}
|
|
12093
|
-
}
|
|
12094
|
-
|
|
12095
|
-
// src/plugins/registry.ts
|
|
12096
|
-
var plugins = [new ClaudeCodePlugin()];
|
|
12097
|
-
|
|
12098
12557
|
// src/cli/argv.ts
|
|
12099
12558
|
var DEFAULT_PORT = 3100;
|
|
12100
12559
|
function parseCliArgs(argv, env = {}) {
|
|
@@ -12150,28 +12609,28 @@ Environment:
|
|
|
12150
12609
|
`;
|
|
12151
12610
|
|
|
12152
12611
|
// src/config/data-dir.ts
|
|
12153
|
-
import
|
|
12612
|
+
import path6 from "path";
|
|
12154
12613
|
function resolveDataDir(env, homeDir) {
|
|
12155
12614
|
const override = env.CHAT_LOGBOOK_DATA_DIR?.trim();
|
|
12156
12615
|
if (override) {
|
|
12157
|
-
return
|
|
12616
|
+
return path6.resolve(override);
|
|
12158
12617
|
}
|
|
12159
|
-
return
|
|
12618
|
+
return path6.join(homeDir, ".chat-logbook");
|
|
12160
12619
|
}
|
|
12161
12620
|
|
|
12162
12621
|
// src/list-counts.ts
|
|
12163
12622
|
import fs7 from "fs";
|
|
12164
|
-
import
|
|
12623
|
+
import path7 from "path";
|
|
12165
12624
|
import Database3 from "better-sqlite3";
|
|
12166
12625
|
var ARCHIVE_DB2 = "archive.db";
|
|
12167
12626
|
var METADATA_DB2 = "metadata.db";
|
|
12168
12627
|
function createChatCountsQuery({
|
|
12169
12628
|
dataDir: dataDir2
|
|
12170
12629
|
}) {
|
|
12171
|
-
const archive2 = new Database3(
|
|
12630
|
+
const archive2 = new Database3(path7.join(dataDir2, ARCHIVE_DB2), {
|
|
12172
12631
|
readonly: true
|
|
12173
12632
|
});
|
|
12174
|
-
const metadataPath =
|
|
12633
|
+
const metadataPath = path7.join(dataDir2, METADATA_DB2);
|
|
12175
12634
|
const hasMetadata = fs7.existsSync(metadataPath);
|
|
12176
12635
|
if (hasMetadata) {
|
|
12177
12636
|
archive2.prepare("ATTACH DATABASE ? AS meta").run(metadataPath);
|
|
@@ -12307,8 +12766,8 @@ function reconcileTitleSortKeys({
|
|
|
12307
12766
|
}
|
|
12308
12767
|
|
|
12309
12768
|
// src/index.ts
|
|
12310
|
-
var __dirname =
|
|
12311
|
-
var pkgPath =
|
|
12769
|
+
var __dirname = path8.dirname(fileURLToPath2(import.meta.url));
|
|
12770
|
+
var pkgPath = path8.join(__dirname, "../../package.json");
|
|
12312
12771
|
var pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
12313
12772
|
var action = parseCliArgs(process.argv.slice(2), {
|
|
12314
12773
|
PORT: process.env.PORT
|
|
@@ -12330,9 +12789,14 @@ var dataDir = resolveDataDir(
|
|
|
12330
12789
|
{ CHAT_LOGBOOK_DATA_DIR: process.env.CHAT_LOGBOOK_DATA_DIR },
|
|
12331
12790
|
os.homedir()
|
|
12332
12791
|
);
|
|
12333
|
-
var webDistDir =
|
|
12792
|
+
var webDistDir = path8.join(__dirname, "../../web/dist");
|
|
12334
12793
|
var port = action.port;
|
|
12335
12794
|
var archive = createArchiveRepository({ dataDir });
|
|
12795
|
+
try {
|
|
12796
|
+
runRenormalizeIfStale({ plugins, archive });
|
|
12797
|
+
} catch (err) {
|
|
12798
|
+
console.error("[renormalize] startup pass failed:", err);
|
|
12799
|
+
}
|
|
12336
12800
|
var checkpoint = createCheckpointRepository({ dataDir });
|
|
12337
12801
|
var metadata = createMetadataRepository({ dataDir });
|
|
12338
12802
|
var tags2 = createTagRepository({ dataDir });
|