chat-logbook 0.22.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 +864 -405
- 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-COvlJg8P.css +0 -2
- package/web/dist/assets/index-DavBxOby.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
|
};
|
|
@@ -3239,7 +3242,8 @@ function toApiBlock(block) {
|
|
|
3239
3242
|
type: "tool_result",
|
|
3240
3243
|
tool_use_id: String(block.toolUseId ?? ""),
|
|
3241
3244
|
content: block.content,
|
|
3242
|
-
...block.isError === true ? { is_error: true } : {}
|
|
3245
|
+
...block.isError === true ? { is_error: true } : {},
|
|
3246
|
+
...typeof block.filePath === "string" && Array.isArray(block.patch) ? { file_path: block.filePath, patch: block.patch } : {}
|
|
3243
3247
|
};
|
|
3244
3248
|
}
|
|
3245
3249
|
return block;
|
|
@@ -3378,7 +3382,9 @@ function createChatReader({
|
|
|
3378
3382
|
id: m.messageId,
|
|
3379
3383
|
role: m.role,
|
|
3380
3384
|
content: m.blocks.map(toApiBlock),
|
|
3381
|
-
timestamp: m.ts.toISOString()
|
|
3385
|
+
timestamp: m.ts.toISOString(),
|
|
3386
|
+
...m.model === null ? {} : { model: m.model },
|
|
3387
|
+
...m.effort === null ? {} : { effort: m.effort }
|
|
3382
3388
|
}));
|
|
3383
3389
|
}
|
|
3384
3390
|
return {
|
|
@@ -3393,6 +3399,450 @@ function createChatReader({
|
|
|
3393
3399
|
// src/list-contract.ts
|
|
3394
3400
|
var MAX_PAGE_LIMIT = 200;
|
|
3395
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
|
+
|
|
3396
3846
|
// src/app.ts
|
|
3397
3847
|
var STREAM_HEARTBEAT_MS = 25e3;
|
|
3398
3848
|
function createApp({
|
|
@@ -3663,6 +4113,52 @@ function createApp({
|
|
|
3663
4113
|
}
|
|
3664
4114
|
return c.json({ messages: messages2 });
|
|
3665
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
|
+
});
|
|
3666
4162
|
app2.get("/api/tags", (c) => {
|
|
3667
4163
|
return c.json({ tags: tags3.listTags() });
|
|
3668
4164
|
});
|
|
@@ -5065,7 +5561,7 @@ var QueryPromise = class {
|
|
|
5065
5561
|
function mapResultRow(columns, row, joinsNotNullableMap) {
|
|
5066
5562
|
const nullifyMap = {};
|
|
5067
5563
|
const result = columns.reduce(
|
|
5068
|
-
(result2, { path:
|
|
5564
|
+
(result2, { path: path9, field }, columnIndex) => {
|
|
5069
5565
|
let decoder;
|
|
5070
5566
|
if (is(field, Column)) {
|
|
5071
5567
|
decoder = field;
|
|
@@ -5077,8 +5573,8 @@ function mapResultRow(columns, row, joinsNotNullableMap) {
|
|
|
5077
5573
|
decoder = field.sql.decoder;
|
|
5078
5574
|
}
|
|
5079
5575
|
let node = result2;
|
|
5080
|
-
for (const [pathChunkIndex, pathChunk] of
|
|
5081
|
-
if (pathChunkIndex <
|
|
5576
|
+
for (const [pathChunkIndex, pathChunk] of path9.entries()) {
|
|
5577
|
+
if (pathChunkIndex < path9.length - 1) {
|
|
5082
5578
|
if (!(pathChunk in node)) {
|
|
5083
5579
|
node[pathChunk] = {};
|
|
5084
5580
|
}
|
|
@@ -5086,8 +5582,8 @@ function mapResultRow(columns, row, joinsNotNullableMap) {
|
|
|
5086
5582
|
} else {
|
|
5087
5583
|
const rawValue = row[columnIndex];
|
|
5088
5584
|
const value = node[pathChunk] = rawValue === null ? null : decoder.mapFromDriverValue(rawValue);
|
|
5089
|
-
if (joinsNotNullableMap && is(field, Column) &&
|
|
5090
|
-
const objectName =
|
|
5585
|
+
if (joinsNotNullableMap && is(field, Column) && path9.length === 2) {
|
|
5586
|
+
const objectName = path9[0];
|
|
5091
5587
|
if (!(objectName in nullifyMap)) {
|
|
5092
5588
|
nullifyMap[objectName] = value === null ? getTableName(field.table) : false;
|
|
5093
5589
|
} else if (typeof nullifyMap[objectName] === "string" && nullifyMap[objectName] !== getTableName(field.table)) {
|
|
@@ -5647,8 +6143,8 @@ function mapRelationalRow(tablesConfig, tableConfig, row, buildQueryResultSelect
|
|
|
5647
6143
|
}
|
|
5648
6144
|
|
|
5649
6145
|
// src/storage/openStore.ts
|
|
5650
|
-
import
|
|
5651
|
-
import
|
|
6146
|
+
import fs4 from "fs";
|
|
6147
|
+
import path4 from "path";
|
|
5652
6148
|
import { fileURLToPath } from "url";
|
|
5653
6149
|
import Database2 from "better-sqlite3";
|
|
5654
6150
|
|
|
@@ -9257,20 +9753,20 @@ function drizzle(...params) {
|
|
|
9257
9753
|
|
|
9258
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
|
|
9259
9755
|
import crypto4 from "crypto";
|
|
9260
|
-
import
|
|
9756
|
+
import fs3 from "fs";
|
|
9261
9757
|
function readMigrationFiles(config) {
|
|
9262
9758
|
const migrationFolderTo = config.migrationsFolder;
|
|
9263
9759
|
const migrationQueries = [];
|
|
9264
9760
|
const journalPath = `${migrationFolderTo}/meta/_journal.json`;
|
|
9265
|
-
if (!
|
|
9761
|
+
if (!fs3.existsSync(journalPath)) {
|
|
9266
9762
|
throw new Error(`Can't find meta/_journal.json file`);
|
|
9267
9763
|
}
|
|
9268
|
-
const journalAsString =
|
|
9764
|
+
const journalAsString = fs3.readFileSync(`${migrationFolderTo}/meta/_journal.json`).toString();
|
|
9269
9765
|
const journal = JSON.parse(journalAsString);
|
|
9270
9766
|
for (const journalEntry of journal.entries) {
|
|
9271
9767
|
const migrationPath = `${migrationFolderTo}/${journalEntry.tag}.sql`;
|
|
9272
9768
|
try {
|
|
9273
|
-
const query =
|
|
9769
|
+
const query = fs3.readFileSync(`${migrationFolderTo}/${journalEntry.tag}.sql`).toString();
|
|
9274
9770
|
const result = query.split("--> statement-breakpoint").map((it) => {
|
|
9275
9771
|
return it;
|
|
9276
9772
|
});
|
|
@@ -9295,12 +9791,12 @@ function migrate(db, config) {
|
|
|
9295
9791
|
|
|
9296
9792
|
// src/storage/openStore.ts
|
|
9297
9793
|
function resolveMigrationsFolder(callerUrl, migrationsSubdir) {
|
|
9298
|
-
const here =
|
|
9794
|
+
const here = path4.dirname(fileURLToPath(callerUrl));
|
|
9299
9795
|
const candidates = [
|
|
9300
|
-
|
|
9301
|
-
|
|
9796
|
+
path4.join(here, "../..", migrationsSubdir),
|
|
9797
|
+
path4.join(here, ".", migrationsSubdir)
|
|
9302
9798
|
];
|
|
9303
|
-
const found = candidates.find((p) =>
|
|
9799
|
+
const found = candidates.find((p) => fs4.existsSync(p));
|
|
9304
9800
|
if (!found) {
|
|
9305
9801
|
throw new Error(`Could not locate migrations folder "${migrationsSubdir}"`);
|
|
9306
9802
|
}
|
|
@@ -9314,8 +9810,8 @@ function openStore({
|
|
|
9314
9810
|
schema
|
|
9315
9811
|
}) {
|
|
9316
9812
|
const migrationsFolder = resolveMigrationsFolder(callerUrl, migrationsSubdir);
|
|
9317
|
-
|
|
9318
|
-
const sqlite = new Database2(
|
|
9813
|
+
fs4.mkdirSync(dataDir2, { recursive: true });
|
|
9814
|
+
const sqlite = new Database2(path4.join(dataDir2, dbFile));
|
|
9319
9815
|
const db = drizzle(sqlite, { schema });
|
|
9320
9816
|
migrate(db, { migrationsFolder });
|
|
9321
9817
|
return { db, sqlite };
|
|
@@ -9334,7 +9830,12 @@ __export(schema_exports, {
|
|
|
9334
9830
|
var archiveMeta = sqliteTable("archive_meta", {
|
|
9335
9831
|
id: integer("id").primaryKey(),
|
|
9336
9832
|
archiveUuid: text("archive_uuid").notNull(),
|
|
9337
|
-
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)
|
|
9338
9839
|
});
|
|
9339
9840
|
var schemaVersion = sqliteTable("schema_version", {
|
|
9340
9841
|
version: integer("version").primaryKey(),
|
|
@@ -9403,6 +9904,13 @@ var messages = sqliteTable(
|
|
|
9403
9904
|
ts: integer("ts", { mode: "timestamp_ms" }).notNull(),
|
|
9404
9905
|
text: text("text").notNull(),
|
|
9405
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"),
|
|
9406
9914
|
rawId: integer("raw_id").notNull().references(() => rawMessages.id)
|
|
9407
9915
|
},
|
|
9408
9916
|
(t) => [
|
|
@@ -9442,6 +9950,16 @@ function createArchiveReadSeam(db) {
|
|
|
9442
9950
|
listMessagesByChat(agent, sourceId) {
|
|
9443
9951
|
return db.select().from(messages).where(and(eq(messages.agent, agent), eq(messages.sourceId, sourceId))).orderBy(asc(messages.ts)).all();
|
|
9444
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
|
+
},
|
|
9445
9963
|
listChatTsRanges(opts) {
|
|
9446
9964
|
const scope = opts?.sourceIds !== void 0 ? inArray(messages.sourceId, opts.sourceIds) : sql`1 = 1`;
|
|
9447
9965
|
return db.select({
|
|
@@ -9488,6 +10006,15 @@ function createArchiveReadSeam(db) {
|
|
|
9488
10006
|
},
|
|
9489
10007
|
listIngestionEvents() {
|
|
9490
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();
|
|
9491
10018
|
}
|
|
9492
10019
|
};
|
|
9493
10020
|
}
|
|
@@ -9534,6 +10061,16 @@ function createArchiveRepository({
|
|
|
9534
10061
|
}
|
|
9535
10062
|
return row.archiveUuid;
|
|
9536
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
|
+
},
|
|
9537
10074
|
getAppliedMigrations() {
|
|
9538
10075
|
return db.select().from(schemaVersion).all().map((r) => ({ version: r.version, appliedAt: r.appliedAt }));
|
|
9539
10076
|
},
|
|
@@ -9617,6 +10154,8 @@ function createArchiveRepository({
|
|
|
9617
10154
|
ts,
|
|
9618
10155
|
text: message.text,
|
|
9619
10156
|
blocks: message.blocks,
|
|
10157
|
+
model: message.model ?? null,
|
|
10158
|
+
effort: message.effort ?? null,
|
|
9620
10159
|
rawId
|
|
9621
10160
|
}).run();
|
|
9622
10161
|
return true;
|
|
@@ -9627,6 +10166,8 @@ function createArchiveRepository({
|
|
|
9627
10166
|
ts,
|
|
9628
10167
|
text: message.text,
|
|
9629
10168
|
blocks: message.blocks,
|
|
10169
|
+
model: message.model ?? null,
|
|
10170
|
+
effort: message.effort ?? null,
|
|
9630
10171
|
rawId
|
|
9631
10172
|
}).where(eq(messages.id, existing2.id)).run();
|
|
9632
10173
|
return true;
|
|
@@ -9728,8 +10269,8 @@ function createCheckpointRepository({
|
|
|
9728
10269
|
}
|
|
9729
10270
|
|
|
9730
10271
|
// src/metadata/repository.ts
|
|
9731
|
-
import
|
|
9732
|
-
import
|
|
10272
|
+
import fs5 from "fs";
|
|
10273
|
+
import path5 from "path";
|
|
9733
10274
|
|
|
9734
10275
|
// src/metadata/schema.ts
|
|
9735
10276
|
var schema_exports3 = {};
|
|
@@ -9809,11 +10350,11 @@ function computeSortKey(input) {
|
|
|
9809
10350
|
var DB_FILE = "metadata.db";
|
|
9810
10351
|
var LEGACY_DB_FILE = "data.db";
|
|
9811
10352
|
function migrateLegacyDbFile(dataDir2) {
|
|
9812
|
-
const legacy =
|
|
9813
|
-
const current =
|
|
9814
|
-
if (!
|
|
9815
|
-
if (
|
|
9816
|
-
|
|
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);
|
|
9817
10358
|
}
|
|
9818
10359
|
var CLAUDE_CODE_AGENT = "claude-code";
|
|
9819
10360
|
function createMetadataRepository({
|
|
@@ -10057,7 +10598,7 @@ function createTagRepository({
|
|
|
10057
10598
|
}
|
|
10058
10599
|
|
|
10059
10600
|
// src/ingestion/ingest.ts
|
|
10060
|
-
import
|
|
10601
|
+
import fs6 from "fs";
|
|
10061
10602
|
async function runIngestion(opts) {
|
|
10062
10603
|
const now = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
10063
10604
|
const changedChatIds = /* @__PURE__ */ new Set();
|
|
@@ -10127,7 +10668,7 @@ async function runIngestion(opts) {
|
|
|
10127
10668
|
}
|
|
10128
10669
|
function safeStat(p) {
|
|
10129
10670
|
try {
|
|
10130
|
-
return
|
|
10671
|
+
return fs6.statSync(p);
|
|
10131
10672
|
} catch {
|
|
10132
10673
|
return null;
|
|
10133
10674
|
}
|
|
@@ -10146,6 +10687,55 @@ function startIngestionInBackground(opts, bg = {}) {
|
|
|
10146
10687
|
return { done };
|
|
10147
10688
|
}
|
|
10148
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
|
+
|
|
10149
10739
|
// ../node_modules/.pnpm/chokidar@5.0.0/node_modules/chokidar/index.js
|
|
10150
10740
|
import { EventEmitter } from "events";
|
|
10151
10741
|
import { stat as statcb, Stats } from "fs";
|
|
@@ -10236,7 +10826,7 @@ var ReaddirpStream = class extends Readable3 {
|
|
|
10236
10826
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
10237
10827
|
const statMethod = opts.lstat ? lstat : stat;
|
|
10238
10828
|
if (wantBigintFsStats) {
|
|
10239
|
-
this._stat = (
|
|
10829
|
+
this._stat = (path9) => statMethod(path9, { bigint: true });
|
|
10240
10830
|
} else {
|
|
10241
10831
|
this._stat = statMethod;
|
|
10242
10832
|
}
|
|
@@ -10261,8 +10851,8 @@ var ReaddirpStream = class extends Readable3 {
|
|
|
10261
10851
|
const par = this.parent;
|
|
10262
10852
|
const fil = par && par.files;
|
|
10263
10853
|
if (fil && fil.length > 0) {
|
|
10264
|
-
const { path:
|
|
10265
|
-
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));
|
|
10266
10856
|
const awaited = await Promise.all(slice);
|
|
10267
10857
|
for (const entry of awaited) {
|
|
10268
10858
|
if (!entry)
|
|
@@ -10302,20 +10892,20 @@ var ReaddirpStream = class extends Readable3 {
|
|
|
10302
10892
|
this.reading = false;
|
|
10303
10893
|
}
|
|
10304
10894
|
}
|
|
10305
|
-
async _exploreDir(
|
|
10895
|
+
async _exploreDir(path9, depth) {
|
|
10306
10896
|
let files;
|
|
10307
10897
|
try {
|
|
10308
|
-
files = await readdir(
|
|
10898
|
+
files = await readdir(path9, this._rdOptions);
|
|
10309
10899
|
} catch (error) {
|
|
10310
10900
|
this._onError(error);
|
|
10311
10901
|
}
|
|
10312
|
-
return { files, depth, path:
|
|
10902
|
+
return { files, depth, path: path9 };
|
|
10313
10903
|
}
|
|
10314
|
-
async _formatEntry(dirent,
|
|
10904
|
+
async _formatEntry(dirent, path9) {
|
|
10315
10905
|
let entry;
|
|
10316
10906
|
const basename3 = this._isDirent ? dirent.name : dirent;
|
|
10317
10907
|
try {
|
|
10318
|
-
const fullPath = presolve(pjoin(
|
|
10908
|
+
const fullPath = presolve(pjoin(path9, basename3));
|
|
10319
10909
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename3 };
|
|
10320
10910
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
10321
10911
|
} catch (err) {
|
|
@@ -10715,16 +11305,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
10715
11305
|
};
|
|
10716
11306
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
10717
11307
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
10718
|
-
function createFsWatchInstance(
|
|
11308
|
+
function createFsWatchInstance(path9, options, listener, errHandler, emitRaw) {
|
|
10719
11309
|
const handleEvent = (rawEvent, evPath) => {
|
|
10720
|
-
listener(
|
|
10721
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
10722
|
-
if (evPath &&
|
|
10723
|
-
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));
|
|
10724
11314
|
}
|
|
10725
11315
|
};
|
|
10726
11316
|
try {
|
|
10727
|
-
return fs_watch(
|
|
11317
|
+
return fs_watch(path9, {
|
|
10728
11318
|
persistent: options.persistent
|
|
10729
11319
|
}, handleEvent);
|
|
10730
11320
|
} catch (error) {
|
|
@@ -10740,12 +11330,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
10740
11330
|
listener(val1, val2, val3);
|
|
10741
11331
|
});
|
|
10742
11332
|
};
|
|
10743
|
-
var setFsWatchListener = (
|
|
11333
|
+
var setFsWatchListener = (path9, fullPath, options, handlers) => {
|
|
10744
11334
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
10745
11335
|
let cont = FsWatchInstances.get(fullPath);
|
|
10746
11336
|
let watcher2;
|
|
10747
11337
|
if (!options.persistent) {
|
|
10748
|
-
watcher2 = createFsWatchInstance(
|
|
11338
|
+
watcher2 = createFsWatchInstance(path9, options, listener, errHandler, rawEmitter);
|
|
10749
11339
|
if (!watcher2)
|
|
10750
11340
|
return;
|
|
10751
11341
|
return watcher2.close.bind(watcher2);
|
|
@@ -10756,7 +11346,7 @@ var setFsWatchListener = (path8, fullPath, options, handlers) => {
|
|
|
10756
11346
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
10757
11347
|
} else {
|
|
10758
11348
|
watcher2 = createFsWatchInstance(
|
|
10759
|
-
|
|
11349
|
+
path9,
|
|
10760
11350
|
options,
|
|
10761
11351
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
10762
11352
|
errHandler,
|
|
@@ -10771,7 +11361,7 @@ var setFsWatchListener = (path8, fullPath, options, handlers) => {
|
|
|
10771
11361
|
cont.watcherUnusable = true;
|
|
10772
11362
|
if (isWindows && error.code === "EPERM") {
|
|
10773
11363
|
try {
|
|
10774
|
-
const fd = await open(
|
|
11364
|
+
const fd = await open(path9, "r");
|
|
10775
11365
|
await fd.close();
|
|
10776
11366
|
broadcastErr(error);
|
|
10777
11367
|
} catch (err) {
|
|
@@ -10802,7 +11392,7 @@ var setFsWatchListener = (path8, fullPath, options, handlers) => {
|
|
|
10802
11392
|
};
|
|
10803
11393
|
};
|
|
10804
11394
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
10805
|
-
var setFsWatchFileListener = (
|
|
11395
|
+
var setFsWatchFileListener = (path9, fullPath, options, handlers) => {
|
|
10806
11396
|
const { listener, rawEmitter } = handlers;
|
|
10807
11397
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
10808
11398
|
const copts = cont && cont.options;
|
|
@@ -10824,7 +11414,7 @@ var setFsWatchFileListener = (path8, fullPath, options, handlers) => {
|
|
|
10824
11414
|
});
|
|
10825
11415
|
const currmtime = curr.mtimeMs;
|
|
10826
11416
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
10827
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
11417
|
+
foreach(cont.listeners, (listener2) => listener2(path9, curr));
|
|
10828
11418
|
}
|
|
10829
11419
|
})
|
|
10830
11420
|
};
|
|
@@ -10854,13 +11444,13 @@ var NodeFsHandler = class {
|
|
|
10854
11444
|
* @param listener on fs change
|
|
10855
11445
|
* @returns closer for the watcher instance
|
|
10856
11446
|
*/
|
|
10857
|
-
_watchWithNodeFs(
|
|
11447
|
+
_watchWithNodeFs(path9, listener) {
|
|
10858
11448
|
const opts = this.fsw.options;
|
|
10859
|
-
const directory = sp.dirname(
|
|
10860
|
-
const basename3 = sp.basename(
|
|
11449
|
+
const directory = sp.dirname(path9);
|
|
11450
|
+
const basename3 = sp.basename(path9);
|
|
10861
11451
|
const parent = this.fsw._getWatchedDir(directory);
|
|
10862
11452
|
parent.add(basename3);
|
|
10863
|
-
const absolutePath = sp.resolve(
|
|
11453
|
+
const absolutePath = sp.resolve(path9);
|
|
10864
11454
|
const options = {
|
|
10865
11455
|
persistent: opts.persistent
|
|
10866
11456
|
};
|
|
@@ -10870,12 +11460,12 @@ var NodeFsHandler = class {
|
|
|
10870
11460
|
if (opts.usePolling) {
|
|
10871
11461
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
10872
11462
|
options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
|
|
10873
|
-
closer = setFsWatchFileListener(
|
|
11463
|
+
closer = setFsWatchFileListener(path9, absolutePath, options, {
|
|
10874
11464
|
listener,
|
|
10875
11465
|
rawEmitter: this.fsw._emitRaw
|
|
10876
11466
|
});
|
|
10877
11467
|
} else {
|
|
10878
|
-
closer = setFsWatchListener(
|
|
11468
|
+
closer = setFsWatchListener(path9, absolutePath, options, {
|
|
10879
11469
|
listener,
|
|
10880
11470
|
errHandler: this._boundHandleError,
|
|
10881
11471
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -10897,7 +11487,7 @@ var NodeFsHandler = class {
|
|
|
10897
11487
|
let prevStats = stats;
|
|
10898
11488
|
if (parent.has(basename3))
|
|
10899
11489
|
return;
|
|
10900
|
-
const listener = async (
|
|
11490
|
+
const listener = async (path9, newStats) => {
|
|
10901
11491
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
10902
11492
|
return;
|
|
10903
11493
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -10911,11 +11501,11 @@ var NodeFsHandler = class {
|
|
|
10911
11501
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
10912
11502
|
}
|
|
10913
11503
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
10914
|
-
this.fsw._closeFile(
|
|
11504
|
+
this.fsw._closeFile(path9);
|
|
10915
11505
|
prevStats = newStats2;
|
|
10916
11506
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
10917
11507
|
if (closer2)
|
|
10918
|
-
this.fsw._addPathCloser(
|
|
11508
|
+
this.fsw._addPathCloser(path9, closer2);
|
|
10919
11509
|
} else {
|
|
10920
11510
|
prevStats = newStats2;
|
|
10921
11511
|
}
|
|
@@ -10947,7 +11537,7 @@ var NodeFsHandler = class {
|
|
|
10947
11537
|
* @param item basename of this item
|
|
10948
11538
|
* @returns true if no more processing is needed for this entry.
|
|
10949
11539
|
*/
|
|
10950
|
-
async _handleSymlink(entry, directory,
|
|
11540
|
+
async _handleSymlink(entry, directory, path9, item) {
|
|
10951
11541
|
if (this.fsw.closed) {
|
|
10952
11542
|
return;
|
|
10953
11543
|
}
|
|
@@ -10957,7 +11547,7 @@ var NodeFsHandler = class {
|
|
|
10957
11547
|
this.fsw._incrReadyCount();
|
|
10958
11548
|
let linkPath;
|
|
10959
11549
|
try {
|
|
10960
|
-
linkPath = await fsrealpath(
|
|
11550
|
+
linkPath = await fsrealpath(path9);
|
|
10961
11551
|
} catch (e) {
|
|
10962
11552
|
this.fsw._emitReady();
|
|
10963
11553
|
return true;
|
|
@@ -10967,12 +11557,12 @@ var NodeFsHandler = class {
|
|
|
10967
11557
|
if (dir.has(item)) {
|
|
10968
11558
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
10969
11559
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
10970
|
-
this.fsw._emit(EV.CHANGE,
|
|
11560
|
+
this.fsw._emit(EV.CHANGE, path9, entry.stats);
|
|
10971
11561
|
}
|
|
10972
11562
|
} else {
|
|
10973
11563
|
dir.add(item);
|
|
10974
11564
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
10975
|
-
this.fsw._emit(EV.ADD,
|
|
11565
|
+
this.fsw._emit(EV.ADD, path9, entry.stats);
|
|
10976
11566
|
}
|
|
10977
11567
|
this.fsw._emitReady();
|
|
10978
11568
|
return true;
|
|
@@ -11002,9 +11592,9 @@ var NodeFsHandler = class {
|
|
|
11002
11592
|
return;
|
|
11003
11593
|
}
|
|
11004
11594
|
const item = entry.path;
|
|
11005
|
-
let
|
|
11595
|
+
let path9 = sp.join(directory, item);
|
|
11006
11596
|
current.add(item);
|
|
11007
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
11597
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path9, item)) {
|
|
11008
11598
|
return;
|
|
11009
11599
|
}
|
|
11010
11600
|
if (this.fsw.closed) {
|
|
@@ -11013,8 +11603,8 @@ var NodeFsHandler = class {
|
|
|
11013
11603
|
}
|
|
11014
11604
|
if (item === target || !target && !previous.has(item)) {
|
|
11015
11605
|
this.fsw._incrReadyCount();
|
|
11016
|
-
|
|
11017
|
-
this._addToNodeFs(
|
|
11606
|
+
path9 = sp.join(dir, sp.relative(dir, path9));
|
|
11607
|
+
this._addToNodeFs(path9, initialAdd, wh, depth + 1);
|
|
11018
11608
|
}
|
|
11019
11609
|
}).on(EV.ERROR, this._boundHandleError);
|
|
11020
11610
|
return new Promise((resolve3, reject) => {
|
|
@@ -11083,13 +11673,13 @@ var NodeFsHandler = class {
|
|
|
11083
11673
|
* @param depth Child path actually targeted for watch
|
|
11084
11674
|
* @param target Child path actually targeted for watch
|
|
11085
11675
|
*/
|
|
11086
|
-
async _addToNodeFs(
|
|
11676
|
+
async _addToNodeFs(path9, initialAdd, priorWh, depth, target) {
|
|
11087
11677
|
const ready = this.fsw._emitReady;
|
|
11088
|
-
if (this.fsw._isIgnored(
|
|
11678
|
+
if (this.fsw._isIgnored(path9) || this.fsw.closed) {
|
|
11089
11679
|
ready();
|
|
11090
11680
|
return false;
|
|
11091
11681
|
}
|
|
11092
|
-
const wh = this.fsw._getWatchHelpers(
|
|
11682
|
+
const wh = this.fsw._getWatchHelpers(path9);
|
|
11093
11683
|
if (priorWh) {
|
|
11094
11684
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
11095
11685
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -11105,8 +11695,8 @@ var NodeFsHandler = class {
|
|
|
11105
11695
|
const follow = this.fsw.options.followSymlinks;
|
|
11106
11696
|
let closer;
|
|
11107
11697
|
if (stats.isDirectory()) {
|
|
11108
|
-
const absPath = sp.resolve(
|
|
11109
|
-
const targetPath = follow ? await fsrealpath(
|
|
11698
|
+
const absPath = sp.resolve(path9);
|
|
11699
|
+
const targetPath = follow ? await fsrealpath(path9) : path9;
|
|
11110
11700
|
if (this.fsw.closed)
|
|
11111
11701
|
return;
|
|
11112
11702
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -11116,29 +11706,29 @@ var NodeFsHandler = class {
|
|
|
11116
11706
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
11117
11707
|
}
|
|
11118
11708
|
} else if (stats.isSymbolicLink()) {
|
|
11119
|
-
const targetPath = follow ? await fsrealpath(
|
|
11709
|
+
const targetPath = follow ? await fsrealpath(path9) : path9;
|
|
11120
11710
|
if (this.fsw.closed)
|
|
11121
11711
|
return;
|
|
11122
11712
|
const parent = sp.dirname(wh.watchPath);
|
|
11123
11713
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
11124
11714
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
11125
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
11715
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path9, wh, targetPath);
|
|
11126
11716
|
if (this.fsw.closed)
|
|
11127
11717
|
return;
|
|
11128
11718
|
if (targetPath !== void 0) {
|
|
11129
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
11719
|
+
this.fsw._symlinkPaths.set(sp.resolve(path9), targetPath);
|
|
11130
11720
|
}
|
|
11131
11721
|
} else {
|
|
11132
11722
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
11133
11723
|
}
|
|
11134
11724
|
ready();
|
|
11135
11725
|
if (closer)
|
|
11136
|
-
this.fsw._addPathCloser(
|
|
11726
|
+
this.fsw._addPathCloser(path9, closer);
|
|
11137
11727
|
return false;
|
|
11138
11728
|
} catch (error) {
|
|
11139
11729
|
if (this.fsw._handleError(error)) {
|
|
11140
11730
|
ready();
|
|
11141
|
-
return
|
|
11731
|
+
return path9;
|
|
11142
11732
|
}
|
|
11143
11733
|
}
|
|
11144
11734
|
}
|
|
@@ -11181,24 +11771,24 @@ function createPattern(matcher) {
|
|
|
11181
11771
|
}
|
|
11182
11772
|
return () => false;
|
|
11183
11773
|
}
|
|
11184
|
-
function normalizePath(
|
|
11185
|
-
if (typeof
|
|
11774
|
+
function normalizePath(path9) {
|
|
11775
|
+
if (typeof path9 !== "string")
|
|
11186
11776
|
throw new Error("string expected");
|
|
11187
|
-
|
|
11188
|
-
|
|
11777
|
+
path9 = sp2.normalize(path9);
|
|
11778
|
+
path9 = path9.replace(/\\/g, "/");
|
|
11189
11779
|
let prepend = false;
|
|
11190
|
-
if (
|
|
11780
|
+
if (path9.startsWith("//"))
|
|
11191
11781
|
prepend = true;
|
|
11192
|
-
|
|
11782
|
+
path9 = path9.replace(DOUBLE_SLASH_RE, "/");
|
|
11193
11783
|
if (prepend)
|
|
11194
|
-
|
|
11195
|
-
return
|
|
11784
|
+
path9 = "/" + path9;
|
|
11785
|
+
return path9;
|
|
11196
11786
|
}
|
|
11197
11787
|
function matchPatterns(patterns, testString, stats) {
|
|
11198
|
-
const
|
|
11788
|
+
const path9 = normalizePath(testString);
|
|
11199
11789
|
for (let index2 = 0; index2 < patterns.length; index2++) {
|
|
11200
11790
|
const pattern = patterns[index2];
|
|
11201
|
-
if (pattern(
|
|
11791
|
+
if (pattern(path9, stats)) {
|
|
11202
11792
|
return true;
|
|
11203
11793
|
}
|
|
11204
11794
|
}
|
|
@@ -11236,19 +11826,19 @@ var toUnix = (string) => {
|
|
|
11236
11826
|
}
|
|
11237
11827
|
return str;
|
|
11238
11828
|
};
|
|
11239
|
-
var normalizePathToUnix = (
|
|
11240
|
-
var normalizeIgnored = (cwd = "") => (
|
|
11241
|
-
if (typeof
|
|
11242
|
-
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));
|
|
11243
11833
|
} else {
|
|
11244
|
-
return
|
|
11834
|
+
return path9;
|
|
11245
11835
|
}
|
|
11246
11836
|
};
|
|
11247
|
-
var getAbsolutePath = (
|
|
11248
|
-
if (sp2.isAbsolute(
|
|
11249
|
-
return
|
|
11837
|
+
var getAbsolutePath = (path9, cwd) => {
|
|
11838
|
+
if (sp2.isAbsolute(path9)) {
|
|
11839
|
+
return path9;
|
|
11250
11840
|
}
|
|
11251
|
-
return sp2.join(cwd,
|
|
11841
|
+
return sp2.join(cwd, path9);
|
|
11252
11842
|
};
|
|
11253
11843
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
11254
11844
|
var DirEntry = class {
|
|
@@ -11313,10 +11903,10 @@ var WatchHelper = class {
|
|
|
11313
11903
|
dirParts;
|
|
11314
11904
|
followSymlinks;
|
|
11315
11905
|
statMethod;
|
|
11316
|
-
constructor(
|
|
11906
|
+
constructor(path9, follow, fsw) {
|
|
11317
11907
|
this.fsw = fsw;
|
|
11318
|
-
const watchPath =
|
|
11319
|
-
this.path =
|
|
11908
|
+
const watchPath = path9;
|
|
11909
|
+
this.path = path9 = path9.replace(REPLACER_RE, "");
|
|
11320
11910
|
this.watchPath = watchPath;
|
|
11321
11911
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
11322
11912
|
this.dirParts = [];
|
|
@@ -11456,20 +12046,20 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11456
12046
|
this._closePromise = void 0;
|
|
11457
12047
|
let paths = unifyPaths(paths_);
|
|
11458
12048
|
if (cwd) {
|
|
11459
|
-
paths = paths.map((
|
|
11460
|
-
const absPath = getAbsolutePath(
|
|
12049
|
+
paths = paths.map((path9) => {
|
|
12050
|
+
const absPath = getAbsolutePath(path9, cwd);
|
|
11461
12051
|
return absPath;
|
|
11462
12052
|
});
|
|
11463
12053
|
}
|
|
11464
|
-
paths.forEach((
|
|
11465
|
-
this._removeIgnoredPath(
|
|
12054
|
+
paths.forEach((path9) => {
|
|
12055
|
+
this._removeIgnoredPath(path9);
|
|
11466
12056
|
});
|
|
11467
12057
|
this._userIgnored = void 0;
|
|
11468
12058
|
if (!this._readyCount)
|
|
11469
12059
|
this._readyCount = 0;
|
|
11470
12060
|
this._readyCount += paths.length;
|
|
11471
|
-
Promise.all(paths.map(async (
|
|
11472
|
-
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);
|
|
11473
12063
|
if (res)
|
|
11474
12064
|
this._emitReady();
|
|
11475
12065
|
return res;
|
|
@@ -11491,17 +12081,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11491
12081
|
return this;
|
|
11492
12082
|
const paths = unifyPaths(paths_);
|
|
11493
12083
|
const { cwd } = this.options;
|
|
11494
|
-
paths.forEach((
|
|
11495
|
-
if (!sp2.isAbsolute(
|
|
12084
|
+
paths.forEach((path9) => {
|
|
12085
|
+
if (!sp2.isAbsolute(path9) && !this._closers.has(path9)) {
|
|
11496
12086
|
if (cwd)
|
|
11497
|
-
|
|
11498
|
-
|
|
12087
|
+
path9 = sp2.join(cwd, path9);
|
|
12088
|
+
path9 = sp2.resolve(path9);
|
|
11499
12089
|
}
|
|
11500
|
-
this._closePath(
|
|
11501
|
-
this._addIgnoredPath(
|
|
11502
|
-
if (this._watched.has(
|
|
12090
|
+
this._closePath(path9);
|
|
12091
|
+
this._addIgnoredPath(path9);
|
|
12092
|
+
if (this._watched.has(path9)) {
|
|
11503
12093
|
this._addIgnoredPath({
|
|
11504
|
-
path:
|
|
12094
|
+
path: path9,
|
|
11505
12095
|
recursive: true
|
|
11506
12096
|
});
|
|
11507
12097
|
}
|
|
@@ -11565,38 +12155,38 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11565
12155
|
* @param stats arguments to be passed with event
|
|
11566
12156
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
11567
12157
|
*/
|
|
11568
|
-
async _emit(event,
|
|
12158
|
+
async _emit(event, path9, stats) {
|
|
11569
12159
|
if (this.closed)
|
|
11570
12160
|
return;
|
|
11571
12161
|
const opts = this.options;
|
|
11572
12162
|
if (isWindows)
|
|
11573
|
-
|
|
12163
|
+
path9 = sp2.normalize(path9);
|
|
11574
12164
|
if (opts.cwd)
|
|
11575
|
-
|
|
11576
|
-
const args = [
|
|
12165
|
+
path9 = sp2.relative(opts.cwd, path9);
|
|
12166
|
+
const args = [path9];
|
|
11577
12167
|
if (stats != null)
|
|
11578
12168
|
args.push(stats);
|
|
11579
12169
|
const awf = opts.awaitWriteFinish;
|
|
11580
12170
|
let pw;
|
|
11581
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
12171
|
+
if (awf && (pw = this._pendingWrites.get(path9))) {
|
|
11582
12172
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
11583
12173
|
return this;
|
|
11584
12174
|
}
|
|
11585
12175
|
if (opts.atomic) {
|
|
11586
12176
|
if (event === EVENTS.UNLINK) {
|
|
11587
|
-
this._pendingUnlinks.set(
|
|
12177
|
+
this._pendingUnlinks.set(path9, [event, ...args]);
|
|
11588
12178
|
setTimeout(() => {
|
|
11589
|
-
this._pendingUnlinks.forEach((entry,
|
|
12179
|
+
this._pendingUnlinks.forEach((entry, path10) => {
|
|
11590
12180
|
this.emit(...entry);
|
|
11591
12181
|
this.emit(EVENTS.ALL, ...entry);
|
|
11592
|
-
this._pendingUnlinks.delete(
|
|
12182
|
+
this._pendingUnlinks.delete(path10);
|
|
11593
12183
|
});
|
|
11594
12184
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
11595
12185
|
return this;
|
|
11596
12186
|
}
|
|
11597
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
12187
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path9)) {
|
|
11598
12188
|
event = EVENTS.CHANGE;
|
|
11599
|
-
this._pendingUnlinks.delete(
|
|
12189
|
+
this._pendingUnlinks.delete(path9);
|
|
11600
12190
|
}
|
|
11601
12191
|
}
|
|
11602
12192
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -11614,16 +12204,16 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11614
12204
|
this.emitWithAll(event, args);
|
|
11615
12205
|
}
|
|
11616
12206
|
};
|
|
11617
|
-
this._awaitWriteFinish(
|
|
12207
|
+
this._awaitWriteFinish(path9, awf.stabilityThreshold, event, awfEmit);
|
|
11618
12208
|
return this;
|
|
11619
12209
|
}
|
|
11620
12210
|
if (event === EVENTS.CHANGE) {
|
|
11621
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
12211
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path9, 50);
|
|
11622
12212
|
if (isThrottled)
|
|
11623
12213
|
return this;
|
|
11624
12214
|
}
|
|
11625
12215
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
11626
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
12216
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path9) : path9;
|
|
11627
12217
|
let stats2;
|
|
11628
12218
|
try {
|
|
11629
12219
|
stats2 = await stat3(fullPath);
|
|
@@ -11654,23 +12244,23 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11654
12244
|
* @param timeout duration of time to suppress duplicate actions
|
|
11655
12245
|
* @returns tracking object or false if action should be suppressed
|
|
11656
12246
|
*/
|
|
11657
|
-
_throttle(actionType,
|
|
12247
|
+
_throttle(actionType, path9, timeout) {
|
|
11658
12248
|
if (!this._throttled.has(actionType)) {
|
|
11659
12249
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
11660
12250
|
}
|
|
11661
12251
|
const action2 = this._throttled.get(actionType);
|
|
11662
12252
|
if (!action2)
|
|
11663
12253
|
throw new Error("invalid throttle");
|
|
11664
|
-
const actionPath = action2.get(
|
|
12254
|
+
const actionPath = action2.get(path9);
|
|
11665
12255
|
if (actionPath) {
|
|
11666
12256
|
actionPath.count++;
|
|
11667
12257
|
return false;
|
|
11668
12258
|
}
|
|
11669
12259
|
let timeoutObject;
|
|
11670
12260
|
const clear = () => {
|
|
11671
|
-
const item = action2.get(
|
|
12261
|
+
const item = action2.get(path9);
|
|
11672
12262
|
const count = item ? item.count : 0;
|
|
11673
|
-
action2.delete(
|
|
12263
|
+
action2.delete(path9);
|
|
11674
12264
|
clearTimeout(timeoutObject);
|
|
11675
12265
|
if (item)
|
|
11676
12266
|
clearTimeout(item.timeoutObject);
|
|
@@ -11678,7 +12268,7 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11678
12268
|
};
|
|
11679
12269
|
timeoutObject = setTimeout(clear, timeout);
|
|
11680
12270
|
const thr = { timeoutObject, clear, count: 0 };
|
|
11681
|
-
action2.set(
|
|
12271
|
+
action2.set(path9, thr);
|
|
11682
12272
|
return thr;
|
|
11683
12273
|
}
|
|
11684
12274
|
_incrReadyCount() {
|
|
@@ -11692,44 +12282,44 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11692
12282
|
* @param event
|
|
11693
12283
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
11694
12284
|
*/
|
|
11695
|
-
_awaitWriteFinish(
|
|
12285
|
+
_awaitWriteFinish(path9, threshold, event, awfEmit) {
|
|
11696
12286
|
const awf = this.options.awaitWriteFinish;
|
|
11697
12287
|
if (typeof awf !== "object")
|
|
11698
12288
|
return;
|
|
11699
12289
|
const pollInterval = awf.pollInterval;
|
|
11700
12290
|
let timeoutHandler;
|
|
11701
|
-
let fullPath =
|
|
11702
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
11703
|
-
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);
|
|
11704
12294
|
}
|
|
11705
12295
|
const now = /* @__PURE__ */ new Date();
|
|
11706
12296
|
const writes = this._pendingWrites;
|
|
11707
12297
|
function awaitWriteFinishFn(prevStat) {
|
|
11708
12298
|
statcb(fullPath, (err, curStat) => {
|
|
11709
|
-
if (err || !writes.has(
|
|
12299
|
+
if (err || !writes.has(path9)) {
|
|
11710
12300
|
if (err && err.code !== "ENOENT")
|
|
11711
12301
|
awfEmit(err);
|
|
11712
12302
|
return;
|
|
11713
12303
|
}
|
|
11714
12304
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
11715
12305
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
11716
|
-
writes.get(
|
|
12306
|
+
writes.get(path9).lastChange = now2;
|
|
11717
12307
|
}
|
|
11718
|
-
const pw = writes.get(
|
|
12308
|
+
const pw = writes.get(path9);
|
|
11719
12309
|
const df = now2 - pw.lastChange;
|
|
11720
12310
|
if (df >= threshold) {
|
|
11721
|
-
writes.delete(
|
|
12311
|
+
writes.delete(path9);
|
|
11722
12312
|
awfEmit(void 0, curStat);
|
|
11723
12313
|
} else {
|
|
11724
12314
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
11725
12315
|
}
|
|
11726
12316
|
});
|
|
11727
12317
|
}
|
|
11728
|
-
if (!writes.has(
|
|
11729
|
-
writes.set(
|
|
12318
|
+
if (!writes.has(path9)) {
|
|
12319
|
+
writes.set(path9, {
|
|
11730
12320
|
lastChange: now,
|
|
11731
12321
|
cancelWait: () => {
|
|
11732
|
-
writes.delete(
|
|
12322
|
+
writes.delete(path9);
|
|
11733
12323
|
clearTimeout(timeoutHandler);
|
|
11734
12324
|
return event;
|
|
11735
12325
|
}
|
|
@@ -11740,8 +12330,8 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11740
12330
|
/**
|
|
11741
12331
|
* Determines whether user has asked to ignore this path.
|
|
11742
12332
|
*/
|
|
11743
|
-
_isIgnored(
|
|
11744
|
-
if (this.options.atomic && DOT_RE.test(
|
|
12333
|
+
_isIgnored(path9, stats) {
|
|
12334
|
+
if (this.options.atomic && DOT_RE.test(path9))
|
|
11745
12335
|
return true;
|
|
11746
12336
|
if (!this._userIgnored) {
|
|
11747
12337
|
const { cwd } = this.options;
|
|
@@ -11751,17 +12341,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11751
12341
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
11752
12342
|
this._userIgnored = anymatch(list, void 0);
|
|
11753
12343
|
}
|
|
11754
|
-
return this._userIgnored(
|
|
12344
|
+
return this._userIgnored(path9, stats);
|
|
11755
12345
|
}
|
|
11756
|
-
_isntIgnored(
|
|
11757
|
-
return !this._isIgnored(
|
|
12346
|
+
_isntIgnored(path9, stat4) {
|
|
12347
|
+
return !this._isIgnored(path9, stat4);
|
|
11758
12348
|
}
|
|
11759
12349
|
/**
|
|
11760
12350
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
11761
12351
|
* @param path file or directory pattern being watched
|
|
11762
12352
|
*/
|
|
11763
|
-
_getWatchHelpers(
|
|
11764
|
-
return new WatchHelper(
|
|
12353
|
+
_getWatchHelpers(path9) {
|
|
12354
|
+
return new WatchHelper(path9, this.options.followSymlinks, this);
|
|
11765
12355
|
}
|
|
11766
12356
|
// Directory helpers
|
|
11767
12357
|
// -----------------
|
|
@@ -11793,63 +12383,63 @@ var FSWatcher = class extends EventEmitter {
|
|
|
11793
12383
|
* @param item base path of item/directory
|
|
11794
12384
|
*/
|
|
11795
12385
|
_remove(directory, item, isDirectory) {
|
|
11796
|
-
const
|
|
11797
|
-
const fullPath = sp2.resolve(
|
|
11798
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
11799
|
-
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))
|
|
11800
12390
|
return;
|
|
11801
12391
|
if (!isDirectory && this._watched.size === 1) {
|
|
11802
12392
|
this.add(directory, item, true);
|
|
11803
12393
|
}
|
|
11804
|
-
const wp = this._getWatchedDir(
|
|
12394
|
+
const wp = this._getWatchedDir(path9);
|
|
11805
12395
|
const nestedDirectoryChildren = wp.getChildren();
|
|
11806
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
12396
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path9, nested));
|
|
11807
12397
|
const parent = this._getWatchedDir(directory);
|
|
11808
12398
|
const wasTracked = parent.has(item);
|
|
11809
12399
|
parent.remove(item);
|
|
11810
12400
|
if (this._symlinkPaths.has(fullPath)) {
|
|
11811
12401
|
this._symlinkPaths.delete(fullPath);
|
|
11812
12402
|
}
|
|
11813
|
-
let relPath =
|
|
12403
|
+
let relPath = path9;
|
|
11814
12404
|
if (this.options.cwd)
|
|
11815
|
-
relPath = sp2.relative(this.options.cwd,
|
|
12405
|
+
relPath = sp2.relative(this.options.cwd, path9);
|
|
11816
12406
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
11817
12407
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
11818
12408
|
if (event === EVENTS.ADD)
|
|
11819
12409
|
return;
|
|
11820
12410
|
}
|
|
11821
|
-
this._watched.delete(
|
|
12411
|
+
this._watched.delete(path9);
|
|
11822
12412
|
this._watched.delete(fullPath);
|
|
11823
12413
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
11824
|
-
if (wasTracked && !this._isIgnored(
|
|
11825
|
-
this._emit(eventName,
|
|
11826
|
-
this._closePath(
|
|
12414
|
+
if (wasTracked && !this._isIgnored(path9))
|
|
12415
|
+
this._emit(eventName, path9);
|
|
12416
|
+
this._closePath(path9);
|
|
11827
12417
|
}
|
|
11828
12418
|
/**
|
|
11829
12419
|
* Closes all watchers for a path
|
|
11830
12420
|
*/
|
|
11831
|
-
_closePath(
|
|
11832
|
-
this._closeFile(
|
|
11833
|
-
const dir = sp2.dirname(
|
|
11834
|
-
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));
|
|
11835
12425
|
}
|
|
11836
12426
|
/**
|
|
11837
12427
|
* Closes only file-specific watchers
|
|
11838
12428
|
*/
|
|
11839
|
-
_closeFile(
|
|
11840
|
-
const closers = this._closers.get(
|
|
12429
|
+
_closeFile(path9) {
|
|
12430
|
+
const closers = this._closers.get(path9);
|
|
11841
12431
|
if (!closers)
|
|
11842
12432
|
return;
|
|
11843
12433
|
closers.forEach((closer) => closer());
|
|
11844
|
-
this._closers.delete(
|
|
12434
|
+
this._closers.delete(path9);
|
|
11845
12435
|
}
|
|
11846
|
-
_addPathCloser(
|
|
12436
|
+
_addPathCloser(path9, closer) {
|
|
11847
12437
|
if (!closer)
|
|
11848
12438
|
return;
|
|
11849
|
-
let list = this._closers.get(
|
|
12439
|
+
let list = this._closers.get(path9);
|
|
11850
12440
|
if (!list) {
|
|
11851
12441
|
list = [];
|
|
11852
|
-
this._closers.set(
|
|
12442
|
+
this._closers.set(path9, list);
|
|
11853
12443
|
}
|
|
11854
12444
|
list.push(closer);
|
|
11855
12445
|
}
|
|
@@ -11947,13 +12537,13 @@ function startWatcher(opts) {
|
|
|
11947
12537
|
}
|
|
11948
12538
|
return {
|
|
11949
12539
|
ready,
|
|
11950
|
-
notifyChange(
|
|
11951
|
-
if (watcher2) watcher2.emit("change",
|
|
11952
|
-
else scheduleIngest(
|
|
12540
|
+
notifyChange(path9) {
|
|
12541
|
+
if (watcher2) watcher2.emit("change", path9);
|
|
12542
|
+
else scheduleIngest(path9);
|
|
11953
12543
|
},
|
|
11954
|
-
notifyUnlink(
|
|
11955
|
-
if (watcher2) watcher2.emit("unlink",
|
|
11956
|
-
else recordUnlink(
|
|
12544
|
+
notifyUnlink(path9) {
|
|
12545
|
+
if (watcher2) watcher2.emit("unlink", path9);
|
|
12546
|
+
else recordUnlink(path9);
|
|
11957
12547
|
},
|
|
11958
12548
|
async close() {
|
|
11959
12549
|
closed = true;
|
|
@@ -11964,142 +12554,6 @@ function startWatcher(opts) {
|
|
|
11964
12554
|
};
|
|
11965
12555
|
}
|
|
11966
12556
|
|
|
11967
|
-
// src/plugins/claude-code/plugin.ts
|
|
11968
|
-
import fs6 from "fs";
|
|
11969
|
-
import path4 from "path";
|
|
11970
|
-
import readline from "readline";
|
|
11971
|
-
var ClaudeCodePlugin = class {
|
|
11972
|
-
id = "claude-code";
|
|
11973
|
-
displayName = "Claude Code";
|
|
11974
|
-
async *discover(env) {
|
|
11975
|
-
const projectsDir = path4.join(env.homeDir, ".claude", "projects");
|
|
11976
|
-
if (!fs6.existsSync(projectsDir)) return;
|
|
11977
|
-
const projects = fs6.readdirSync(projectsDir, { withFileTypes: true });
|
|
11978
|
-
for (const project of projects) {
|
|
11979
|
-
if (!project.isDirectory()) continue;
|
|
11980
|
-
const projectPath = path4.join(projectsDir, project.name);
|
|
11981
|
-
const files = fs6.readdirSync(projectPath, { withFileTypes: true });
|
|
11982
|
-
for (const file of files) {
|
|
11983
|
-
if (!file.isFile() || !file.name.endsWith(".jsonl")) continue;
|
|
11984
|
-
const sourcePath = path4.join(projectPath, file.name);
|
|
11985
|
-
const sourceId = file.name.replace(/\.jsonl$/, "");
|
|
11986
|
-
const cwd = await readCwdFromJsonl(sourcePath);
|
|
11987
|
-
yield {
|
|
11988
|
-
sourceId,
|
|
11989
|
-
sourcePath,
|
|
11990
|
-
watchPaths: [sourcePath],
|
|
11991
|
-
project: cwd ? path4.basename(cwd) : void 0,
|
|
11992
|
-
projectPath: cwd ?? void 0
|
|
11993
|
-
};
|
|
11994
|
-
}
|
|
11995
|
-
}
|
|
11996
|
-
}
|
|
11997
|
-
async *extractRaw(ref) {
|
|
11998
|
-
if (!fs6.existsSync(ref.sourcePath)) return;
|
|
11999
|
-
const stream2 = fs6.createReadStream(ref.sourcePath, { encoding: "utf-8" });
|
|
12000
|
-
const rl = readline.createInterface({ input: stream2, crlfDelay: Infinity });
|
|
12001
|
-
let lineNo = 0;
|
|
12002
|
-
for await (const line of rl) {
|
|
12003
|
-
lineNo += 1;
|
|
12004
|
-
if (!line) continue;
|
|
12005
|
-
yield {
|
|
12006
|
-
sourceId: ref.sourceId,
|
|
12007
|
-
sourcePath: ref.sourcePath,
|
|
12008
|
-
sourceLocator: `L${lineNo}`,
|
|
12009
|
-
payload: JSON.parse(line)
|
|
12010
|
-
};
|
|
12011
|
-
}
|
|
12012
|
-
}
|
|
12013
|
-
normalize(raw2) {
|
|
12014
|
-
const payload = raw2.payload;
|
|
12015
|
-
if (!payload || typeof payload !== "object") return null;
|
|
12016
|
-
if (payload.type !== "user" && payload.type !== "assistant") return null;
|
|
12017
|
-
if (payload.isMeta === true) return null;
|
|
12018
|
-
if (payload.isSidechain === true) return null;
|
|
12019
|
-
const message = payload.message;
|
|
12020
|
-
if (!message) return null;
|
|
12021
|
-
const role = message.role === "assistant" ? "assistant" : "user";
|
|
12022
|
-
const messageId = String(payload.uuid ?? "");
|
|
12023
|
-
const ts = String(payload.timestamp ?? "");
|
|
12024
|
-
if (typeof message.content === "string") {
|
|
12025
|
-
const text2 = message.content;
|
|
12026
|
-
return {
|
|
12027
|
-
messageId,
|
|
12028
|
-
role,
|
|
12029
|
-
ts,
|
|
12030
|
-
text: text2,
|
|
12031
|
-
blocks: [{ type: "text", text: text2 }]
|
|
12032
|
-
};
|
|
12033
|
-
}
|
|
12034
|
-
if (Array.isArray(message.content)) {
|
|
12035
|
-
const blocks = [];
|
|
12036
|
-
for (const block of message.content) {
|
|
12037
|
-
const normalized = normalizeBlock(block);
|
|
12038
|
-
if (normalized) blocks.push(normalized);
|
|
12039
|
-
}
|
|
12040
|
-
const text2 = blocks.filter((b) => b.type === "text").map((b) => b.text).join("\n");
|
|
12041
|
-
return { messageId, role, ts, text: text2, blocks };
|
|
12042
|
-
}
|
|
12043
|
-
return null;
|
|
12044
|
-
}
|
|
12045
|
-
};
|
|
12046
|
-
async function readCwdFromJsonl(sourcePath) {
|
|
12047
|
-
try {
|
|
12048
|
-
const stream2 = fs6.createReadStream(sourcePath, { encoding: "utf-8" });
|
|
12049
|
-
const rl = readline.createInterface({ input: stream2, crlfDelay: Infinity });
|
|
12050
|
-
try {
|
|
12051
|
-
for await (const line of rl) {
|
|
12052
|
-
if (!line) continue;
|
|
12053
|
-
let obj;
|
|
12054
|
-
try {
|
|
12055
|
-
obj = JSON.parse(line);
|
|
12056
|
-
} catch {
|
|
12057
|
-
continue;
|
|
12058
|
-
}
|
|
12059
|
-
if (typeof obj.cwd === "string" && obj.cwd.length > 0) {
|
|
12060
|
-
return obj.cwd;
|
|
12061
|
-
}
|
|
12062
|
-
}
|
|
12063
|
-
} finally {
|
|
12064
|
-
rl.close();
|
|
12065
|
-
stream2.destroy();
|
|
12066
|
-
}
|
|
12067
|
-
} catch {
|
|
12068
|
-
}
|
|
12069
|
-
return void 0;
|
|
12070
|
-
}
|
|
12071
|
-
function normalizeBlock(raw2) {
|
|
12072
|
-
if (!raw2 || typeof raw2 !== "object") return null;
|
|
12073
|
-
const b = raw2;
|
|
12074
|
-
switch (b.type) {
|
|
12075
|
-
case "text":
|
|
12076
|
-
return { type: "text", text: String(b.text ?? "") };
|
|
12077
|
-
case "thinking":
|
|
12078
|
-
return { type: "thinking", thinking: String(b.thinking ?? "") };
|
|
12079
|
-
case "tool_use":
|
|
12080
|
-
return {
|
|
12081
|
-
type: "tool_use",
|
|
12082
|
-
id: String(b.id ?? ""),
|
|
12083
|
-
name: String(b.name ?? ""),
|
|
12084
|
-
input: b.input
|
|
12085
|
-
};
|
|
12086
|
-
case "tool_result":
|
|
12087
|
-
return {
|
|
12088
|
-
type: "tool_result",
|
|
12089
|
-
toolUseId: String(b.tool_use_id ?? ""),
|
|
12090
|
-
content: b.content,
|
|
12091
|
-
// Only carried when the tool actually failed: a `false` on every
|
|
12092
|
-
// successful result would grow the stored block for nothing.
|
|
12093
|
-
...b.is_error === true ? { isError: true } : {}
|
|
12094
|
-
};
|
|
12095
|
-
default:
|
|
12096
|
-
return null;
|
|
12097
|
-
}
|
|
12098
|
-
}
|
|
12099
|
-
|
|
12100
|
-
// src/plugins/registry.ts
|
|
12101
|
-
var plugins = [new ClaudeCodePlugin()];
|
|
12102
|
-
|
|
12103
12557
|
// src/cli/argv.ts
|
|
12104
12558
|
var DEFAULT_PORT = 3100;
|
|
12105
12559
|
function parseCliArgs(argv, env = {}) {
|
|
@@ -12155,28 +12609,28 @@ Environment:
|
|
|
12155
12609
|
`;
|
|
12156
12610
|
|
|
12157
12611
|
// src/config/data-dir.ts
|
|
12158
|
-
import
|
|
12612
|
+
import path6 from "path";
|
|
12159
12613
|
function resolveDataDir(env, homeDir) {
|
|
12160
12614
|
const override = env.CHAT_LOGBOOK_DATA_DIR?.trim();
|
|
12161
12615
|
if (override) {
|
|
12162
|
-
return
|
|
12616
|
+
return path6.resolve(override);
|
|
12163
12617
|
}
|
|
12164
|
-
return
|
|
12618
|
+
return path6.join(homeDir, ".chat-logbook");
|
|
12165
12619
|
}
|
|
12166
12620
|
|
|
12167
12621
|
// src/list-counts.ts
|
|
12168
12622
|
import fs7 from "fs";
|
|
12169
|
-
import
|
|
12623
|
+
import path7 from "path";
|
|
12170
12624
|
import Database3 from "better-sqlite3";
|
|
12171
12625
|
var ARCHIVE_DB2 = "archive.db";
|
|
12172
12626
|
var METADATA_DB2 = "metadata.db";
|
|
12173
12627
|
function createChatCountsQuery({
|
|
12174
12628
|
dataDir: dataDir2
|
|
12175
12629
|
}) {
|
|
12176
|
-
const archive2 = new Database3(
|
|
12630
|
+
const archive2 = new Database3(path7.join(dataDir2, ARCHIVE_DB2), {
|
|
12177
12631
|
readonly: true
|
|
12178
12632
|
});
|
|
12179
|
-
const metadataPath =
|
|
12633
|
+
const metadataPath = path7.join(dataDir2, METADATA_DB2);
|
|
12180
12634
|
const hasMetadata = fs7.existsSync(metadataPath);
|
|
12181
12635
|
if (hasMetadata) {
|
|
12182
12636
|
archive2.prepare("ATTACH DATABASE ? AS meta").run(metadataPath);
|
|
@@ -12312,8 +12766,8 @@ function reconcileTitleSortKeys({
|
|
|
12312
12766
|
}
|
|
12313
12767
|
|
|
12314
12768
|
// src/index.ts
|
|
12315
|
-
var __dirname =
|
|
12316
|
-
var pkgPath =
|
|
12769
|
+
var __dirname = path8.dirname(fileURLToPath2(import.meta.url));
|
|
12770
|
+
var pkgPath = path8.join(__dirname, "../../package.json");
|
|
12317
12771
|
var pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
12318
12772
|
var action = parseCliArgs(process.argv.slice(2), {
|
|
12319
12773
|
PORT: process.env.PORT
|
|
@@ -12335,9 +12789,14 @@ var dataDir = resolveDataDir(
|
|
|
12335
12789
|
{ CHAT_LOGBOOK_DATA_DIR: process.env.CHAT_LOGBOOK_DATA_DIR },
|
|
12336
12790
|
os.homedir()
|
|
12337
12791
|
);
|
|
12338
|
-
var webDistDir =
|
|
12792
|
+
var webDistDir = path8.join(__dirname, "../../web/dist");
|
|
12339
12793
|
var port = action.port;
|
|
12340
12794
|
var archive = createArchiveRepository({ dataDir });
|
|
12795
|
+
try {
|
|
12796
|
+
runRenormalizeIfStale({ plugins, archive });
|
|
12797
|
+
} catch (err) {
|
|
12798
|
+
console.error("[renormalize] startup pass failed:", err);
|
|
12799
|
+
}
|
|
12341
12800
|
var checkpoint = createCheckpointRepository({ dataDir });
|
|
12342
12801
|
var metadata = createMetadataRepository({ dataDir });
|
|
12343
12802
|
var tags2 = createTagRepository({ dataDir });
|