@threadbase-sh/streamer 1.39.1 → 1.40.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/dist/cli.cjs +747 -341
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +575 -169
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +518 -112
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -4121,7 +4121,7 @@ var require_transport = __commonJS({
|
|
|
4121
4121
|
"node_modules/pino/lib/transport.js"(exports2, module2) {
|
|
4122
4122
|
"use strict";
|
|
4123
4123
|
var { createRequire } = require("module");
|
|
4124
|
-
var { existsSync:
|
|
4124
|
+
var { existsSync: existsSync16 } = require("fs");
|
|
4125
4125
|
var getCallers = require_caller();
|
|
4126
4126
|
var { join: join29, isAbsolute: isAbsolute2, sep: sep3 } = require("path");
|
|
4127
4127
|
var { fileURLToPath: fileURLToPath3 } = require("url");
|
|
@@ -4195,7 +4195,7 @@ var require_transport = __commonJS({
|
|
|
4195
4195
|
return false;
|
|
4196
4196
|
}
|
|
4197
4197
|
}
|
|
4198
|
-
return isAbsolute2(path2) && !
|
|
4198
|
+
return isAbsolute2(path2) && !existsSync16(path2);
|
|
4199
4199
|
}
|
|
4200
4200
|
function stripQuotes(value) {
|
|
4201
4201
|
const first = value[0];
|
|
@@ -5937,7 +5937,7 @@ var require_pino = __commonJS({
|
|
|
5937
5937
|
} = symbols;
|
|
5938
5938
|
var { epochTime, nullTime } = time3;
|
|
5939
5939
|
var { pid } = process;
|
|
5940
|
-
var
|
|
5940
|
+
var hostname6 = os2.hostname();
|
|
5941
5941
|
var defaultErrorSerializer = stdSerializers.err;
|
|
5942
5942
|
var defaultOptions2 = {
|
|
5943
5943
|
level: "info",
|
|
@@ -5947,7 +5947,7 @@ var require_pino = __commonJS({
|
|
|
5947
5947
|
errorKey: "err",
|
|
5948
5948
|
nestedKey: null,
|
|
5949
5949
|
enabled: true,
|
|
5950
|
-
base: { pid, hostname:
|
|
5950
|
+
base: { pid, hostname: hostname6 },
|
|
5951
5951
|
serializers: Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
5952
5952
|
err: defaultErrorSerializer
|
|
5953
5953
|
}),
|
|
@@ -38620,8 +38620,8 @@ var require_service_config = __commonJS({
|
|
|
38620
38620
|
}
|
|
38621
38621
|
if (Array.isArray(validatedConfig.clientHostname)) {
|
|
38622
38622
|
let hostnameMatched = false;
|
|
38623
|
-
for (const
|
|
38624
|
-
if (
|
|
38623
|
+
for (const hostname6 of validatedConfig.clientHostname) {
|
|
38624
|
+
if (hostname6 === os2.hostname()) {
|
|
38625
38625
|
hostnameMatched = true;
|
|
38626
38626
|
}
|
|
38627
38627
|
}
|
|
@@ -51190,8 +51190,8 @@ var require_single_subchannel_channel = __commonJS({
|
|
|
51190
51190
|
if (splitPath2.length >= 2) {
|
|
51191
51191
|
serviceName = splitPath2[1];
|
|
51192
51192
|
}
|
|
51193
|
-
const
|
|
51194
|
-
this.serviceUrl = `https://${
|
|
51193
|
+
const hostname6 = (_b = (_a3 = (0, uri_parser_1.splitHostPort)(this.options.host)) === null || _a3 === void 0 ? void 0 : _a3.host) !== null && _b !== void 0 ? _b : "localhost";
|
|
51194
|
+
this.serviceUrl = `https://${hostname6}/${serviceName}`;
|
|
51195
51195
|
const timeout = (0, deadline_1.getRelativeTimeout)(options.deadline);
|
|
51196
51196
|
if (timeout !== Infinity) {
|
|
51197
51197
|
if (timeout <= 0) {
|
|
@@ -51838,8 +51838,8 @@ var require_resolver_dns = __commonJS({
|
|
|
51838
51838
|
}
|
|
51839
51839
|
trace("Looking up DNS hostname " + this.dnsHostname);
|
|
51840
51840
|
this.latestLookupResult = null;
|
|
51841
|
-
const
|
|
51842
|
-
this.pendingLookupPromise = this.lookup(
|
|
51841
|
+
const hostname6 = this.dnsHostname;
|
|
51842
|
+
this.pendingLookupPromise = this.lookup(hostname6);
|
|
51843
51843
|
this.pendingLookupPromise.then((addressList) => {
|
|
51844
51844
|
if (this.pendingLookupPromise === null) {
|
|
51845
51845
|
return;
|
|
@@ -51862,7 +51862,7 @@ var require_resolver_dns = __commonJS({
|
|
|
51862
51862
|
this.listener((0, call_interface_1.statusOrFromError)(this.defaultResolutionError), {}, this.latestServiceConfigResult, "");
|
|
51863
51863
|
});
|
|
51864
51864
|
if (this.isServiceConfigEnabled && this.pendingTxtPromise === null) {
|
|
51865
|
-
this.pendingTxtPromise = this.resolveTxt(
|
|
51865
|
+
this.pendingTxtPromise = this.resolveTxt(hostname6);
|
|
51866
51866
|
this.pendingTxtPromise.then((txtRecord) => {
|
|
51867
51867
|
if (this.pendingTxtPromise === null) {
|
|
51868
51868
|
return;
|
|
@@ -51904,12 +51904,12 @@ var require_resolver_dns = __commonJS({
|
|
|
51904
51904
|
this.continueResolving = true;
|
|
51905
51905
|
}
|
|
51906
51906
|
}
|
|
51907
|
-
async lookup(
|
|
51907
|
+
async lookup(hostname6) {
|
|
51908
51908
|
if (environment_1.GRPC_NODE_USE_ALTERNATIVE_RESOLVER) {
|
|
51909
51909
|
trace("Using alternative DNS resolver.");
|
|
51910
51910
|
const records = await Promise.allSettled([
|
|
51911
|
-
this.alternativeResolver.resolve4(
|
|
51912
|
-
this.alternativeResolver.resolve6(
|
|
51911
|
+
this.alternativeResolver.resolve4(hostname6),
|
|
51912
|
+
this.alternativeResolver.resolve6(hostname6)
|
|
51913
51913
|
]);
|
|
51914
51914
|
if (records.every((result) => result.status === "rejected")) {
|
|
51915
51915
|
throw new Error(records[0].reason);
|
|
@@ -51921,15 +51921,15 @@ var require_resolver_dns = __commonJS({
|
|
|
51921
51921
|
port: +this.port
|
|
51922
51922
|
}));
|
|
51923
51923
|
}
|
|
51924
|
-
const addressList = await dns_1.promises.lookup(
|
|
51924
|
+
const addressList = await dns_1.promises.lookup(hostname6, { all: true });
|
|
51925
51925
|
return addressList.map((addr) => ({ host: addr.address, port: +this.port }));
|
|
51926
51926
|
}
|
|
51927
|
-
async resolveTxt(
|
|
51927
|
+
async resolveTxt(hostname6) {
|
|
51928
51928
|
if (environment_1.GRPC_NODE_USE_ALTERNATIVE_RESOLVER) {
|
|
51929
51929
|
trace("Using alternative DNS resolver.");
|
|
51930
|
-
return this.alternativeResolver.resolveTxt(
|
|
51930
|
+
return this.alternativeResolver.resolveTxt(hostname6);
|
|
51931
51931
|
}
|
|
51932
|
-
return dns_1.promises.resolveTxt(
|
|
51932
|
+
return dns_1.promises.resolveTxt(hostname6);
|
|
51933
51933
|
}
|
|
51934
51934
|
startNextResolutionTimer() {
|
|
51935
51935
|
var _a3, _b;
|
|
@@ -52057,13 +52057,13 @@ var require_http_proxy = __commonJS({
|
|
|
52057
52057
|
userCred = proxyUrl.username;
|
|
52058
52058
|
}
|
|
52059
52059
|
}
|
|
52060
|
-
const
|
|
52060
|
+
const hostname6 = proxyUrl.hostname;
|
|
52061
52061
|
let port = proxyUrl.port;
|
|
52062
52062
|
if (port === "") {
|
|
52063
52063
|
port = "80";
|
|
52064
52064
|
}
|
|
52065
52065
|
const result = {
|
|
52066
|
-
address: `${
|
|
52066
|
+
address: `${hostname6}:${port}`
|
|
52067
52067
|
};
|
|
52068
52068
|
if (userCred) {
|
|
52069
52069
|
result.creds = userCred;
|
|
@@ -53376,8 +53376,8 @@ var require_load_balancing_call = __commonJS({
|
|
|
53376
53376
|
if (splitPath2.length >= 2) {
|
|
53377
53377
|
serviceName = splitPath2[1];
|
|
53378
53378
|
}
|
|
53379
|
-
const
|
|
53380
|
-
this.serviceUrl = `https://${
|
|
53379
|
+
const hostname6 = (_b = (_a3 = (0, uri_parser_1.splitHostPort)(this.host)) === null || _a3 === void 0 ? void 0 : _a3.host) !== null && _b !== void 0 ? _b : "localhost";
|
|
53380
|
+
this.serviceUrl = `https://${hostname6}/${serviceName}`;
|
|
53381
53381
|
this.startTime = /* @__PURE__ */ new Date();
|
|
53382
53382
|
}
|
|
53383
53383
|
getDeadlineInfo() {
|
|
@@ -91186,9 +91186,9 @@ var require_parse_host_uri = __commonJS({
|
|
|
91186
91186
|
var ipv4Hostname = "(?:\\d{1,3}(?:\\.\\d{1,3}){3})";
|
|
91187
91187
|
var ipv6Hostname = "(?:\\[(?<ipv6>[0-9a-fA-F.:]+)\\])";
|
|
91188
91188
|
var dnsHostname = "(?:[^:/]+)";
|
|
91189
|
-
var
|
|
91189
|
+
var hostname6 = `(?:${ipv4Hostname}|${ipv6Hostname}|${dnsHostname})`;
|
|
91190
91190
|
var port = "(?::(?<port>\\d+))";
|
|
91191
|
-
var protoHostPortRegex = new RegExp(`^${scheme}??(?<hostname>${
|
|
91191
|
+
var protoHostPortRegex = new RegExp(`^${scheme}??(?<hostname>${hostname6})${port}?$`);
|
|
91192
91192
|
function splitProtoHostPort(uri) {
|
|
91193
91193
|
const match2 = protoHostPortRegex.exec(uri);
|
|
91194
91194
|
if (!match2?.groups)
|
|
@@ -91200,9 +91200,9 @@ var require_parse_host_uri = __commonJS({
|
|
|
91200
91200
|
};
|
|
91201
91201
|
}
|
|
91202
91202
|
function joinProtoHostPort(components) {
|
|
91203
|
-
const { scheme: scheme2, hostname:
|
|
91203
|
+
const { scheme: scheme2, hostname: hostname7, port: port2 } = components;
|
|
91204
91204
|
const schemeText = scheme2 ? `${scheme2}:` : "";
|
|
91205
|
-
const hostnameText =
|
|
91205
|
+
const hostnameText = hostname7.includes(":") ? `[${hostname7}]` : hostname7;
|
|
91206
91206
|
const portText = port2 !== void 0 ? `:${port2}` : "";
|
|
91207
91207
|
return `${schemeText}${hostnameText}${portText}`;
|
|
91208
91208
|
}
|
|
@@ -104140,11 +104140,11 @@ var require_pg_connection_string = __commonJS({
|
|
|
104140
104140
|
config2.client_encoding = result.searchParams.get("encoding");
|
|
104141
104141
|
return config2;
|
|
104142
104142
|
}
|
|
104143
|
-
const
|
|
104143
|
+
const hostname6 = dummyHost ? "" : result.hostname;
|
|
104144
104144
|
if (!config2.host) {
|
|
104145
|
-
config2.host = decodeURIComponent(
|
|
104146
|
-
} else if (
|
|
104147
|
-
result.pathname =
|
|
104145
|
+
config2.host = decodeURIComponent(hostname6);
|
|
104146
|
+
} else if (hostname6 && /^%2f/i.test(hostname6)) {
|
|
104147
|
+
result.pathname = hostname6 + result.pathname;
|
|
104148
104148
|
}
|
|
104149
104149
|
if (!config2.port) {
|
|
104150
104150
|
config2.port = result.port;
|
|
@@ -135423,10 +135423,10 @@ async function search(query, options, scanner) {
|
|
|
135423
135423
|
// src/server.ts
|
|
135424
135424
|
var import_crypto13 = require("crypto");
|
|
135425
135425
|
var import_events2 = require("events");
|
|
135426
|
-
var
|
|
135426
|
+
var import_fs30 = require("fs");
|
|
135427
135427
|
var import_promises16 = require("fs/promises");
|
|
135428
135428
|
var import_http = require("http");
|
|
135429
|
-
var
|
|
135429
|
+
var import_os13 = require("os");
|
|
135430
135430
|
var import_path29 = require("path");
|
|
135431
135431
|
var import_readline4 = require("readline");
|
|
135432
135432
|
|
|
@@ -138231,6 +138231,215 @@ var errorMiddleware = (err, c) => {
|
|
|
138231
138231
|
return c.json({ error: message }, 500);
|
|
138232
138232
|
};
|
|
138233
138233
|
|
|
138234
|
+
// src/api/routes/backup.routes.ts
|
|
138235
|
+
var import_os5 = require("os");
|
|
138236
|
+
|
|
138237
|
+
// src/services/backup/backup.ts
|
|
138238
|
+
var BACKUP_FORMAT_VERSION = 1;
|
|
138239
|
+
var BackupError = class extends Error {
|
|
138240
|
+
constructor(message, code) {
|
|
138241
|
+
super(message);
|
|
138242
|
+
this.code = code;
|
|
138243
|
+
}
|
|
138244
|
+
code;
|
|
138245
|
+
};
|
|
138246
|
+
function validateArchive(input) {
|
|
138247
|
+
if (!input || typeof input !== "object") {
|
|
138248
|
+
throw new BackupError("Backup is not an object", "INVALID_ARCHIVE");
|
|
138249
|
+
}
|
|
138250
|
+
const archive = input;
|
|
138251
|
+
const manifest = archive.manifest;
|
|
138252
|
+
if (!manifest || typeof manifest !== "object") {
|
|
138253
|
+
throw new BackupError("Backup is missing its manifest", "INVALID_ARCHIVE");
|
|
138254
|
+
}
|
|
138255
|
+
if (manifest.formatVersion !== BACKUP_FORMAT_VERSION) {
|
|
138256
|
+
throw new BackupError(
|
|
138257
|
+
`Unsupported backup format version ${String(manifest.formatVersion)}; this build reads version ${BACKUP_FORMAT_VERSION}`,
|
|
138258
|
+
"UNSUPPORTED_VERSION"
|
|
138259
|
+
);
|
|
138260
|
+
}
|
|
138261
|
+
if (!Array.isArray(archive.projects)) {
|
|
138262
|
+
throw new BackupError("Backup is missing its projects array", "INVALID_ARCHIVE");
|
|
138263
|
+
}
|
|
138264
|
+
for (const [i, p2] of archive.projects.entries()) {
|
|
138265
|
+
if (!p2 || typeof p2 !== "object") {
|
|
138266
|
+
throw new BackupError(`Project at index ${i} is not an object`, "INVALID_ARCHIVE");
|
|
138267
|
+
}
|
|
138268
|
+
if (typeof p2.id !== "string" || p2.id.length === 0) {
|
|
138269
|
+
throw new BackupError(`Project at index ${i} has no id`, "INVALID_ARCHIVE");
|
|
138270
|
+
}
|
|
138271
|
+
if (typeof p2.path !== "string" || p2.path.length === 0) {
|
|
138272
|
+
throw new BackupError(`Project at index ${i} has no path`, "INVALID_ARCHIVE");
|
|
138273
|
+
}
|
|
138274
|
+
}
|
|
138275
|
+
const ids = new Set(archive.projects.map((p2) => p2.id));
|
|
138276
|
+
if (ids.size !== archive.projects.length) {
|
|
138277
|
+
throw new BackupError("Backup contains duplicate project ids", "INVALID_ARCHIVE");
|
|
138278
|
+
}
|
|
138279
|
+
return archive;
|
|
138280
|
+
}
|
|
138281
|
+
function remapPaths(projects, rules) {
|
|
138282
|
+
const ordered = [...rules].sort((a, b2) => b2.from.length - a.from.length);
|
|
138283
|
+
return projects.map((p2) => {
|
|
138284
|
+
const rule = ordered.find((r) => p2.path === r.from || p2.path.startsWith(`${r.from}/`));
|
|
138285
|
+
if (!rule) return p2;
|
|
138286
|
+
return { ...p2, path: `${rule.to}${p2.path.slice(rule.from.length)}` };
|
|
138287
|
+
});
|
|
138288
|
+
}
|
|
138289
|
+
function planRestore(incoming, existing) {
|
|
138290
|
+
const byId = new Map(existing.map((e) => [e.id, e]));
|
|
138291
|
+
const byPath = new Map(existing.map((e) => [e.path, e]));
|
|
138292
|
+
const plan = { create: [], update: [], conflict: [] };
|
|
138293
|
+
for (const p2 of incoming) {
|
|
138294
|
+
const sameId = byId.get(p2.id);
|
|
138295
|
+
if (sameId) {
|
|
138296
|
+
if (sameId.path !== p2.path) plan.update.push(p2);
|
|
138297
|
+
continue;
|
|
138298
|
+
}
|
|
138299
|
+
const samePath = byPath.get(p2.path);
|
|
138300
|
+
if (samePath) {
|
|
138301
|
+
plan.conflict.push({ incoming: p2, existingId: samePath.id });
|
|
138302
|
+
continue;
|
|
138303
|
+
}
|
|
138304
|
+
plan.create.push(p2);
|
|
138305
|
+
}
|
|
138306
|
+
return plan;
|
|
138307
|
+
}
|
|
138308
|
+
|
|
138309
|
+
// src/version.ts
|
|
138310
|
+
var import_node_fs7 = require("fs");
|
|
138311
|
+
var import_node_path8 = require("path");
|
|
138312
|
+
var cached2;
|
|
138313
|
+
function getVersion() {
|
|
138314
|
+
if (cached2 !== void 0) return cached2;
|
|
138315
|
+
cached2 = resolveVersion();
|
|
138316
|
+
return cached2;
|
|
138317
|
+
}
|
|
138318
|
+
function resolveVersion() {
|
|
138319
|
+
const scriptPath = process.argv[1] ?? "";
|
|
138320
|
+
const here = scriptPath ? (0, import_node_path8.dirname)(scriptPath) : process.cwd();
|
|
138321
|
+
let realHere = here;
|
|
138322
|
+
try {
|
|
138323
|
+
realHere = (0, import_node_path8.dirname)((0, import_node_fs7.realpathSync)(scriptPath));
|
|
138324
|
+
} catch {
|
|
138325
|
+
}
|
|
138326
|
+
const searchDirs = realHere === here ? [here, (0, import_node_path8.join)(here, "..")] : [here, (0, import_node_path8.join)(here, ".."), realHere, (0, import_node_path8.join)(realHere, "..")];
|
|
138327
|
+
for (const dir of searchDirs) {
|
|
138328
|
+
try {
|
|
138329
|
+
const v2 = (0, import_node_fs7.readFileSync)((0, import_node_path8.join)(dir, "version.txt"), "utf8").trim();
|
|
138330
|
+
if (v2) return v2;
|
|
138331
|
+
} catch {
|
|
138332
|
+
}
|
|
138333
|
+
}
|
|
138334
|
+
try {
|
|
138335
|
+
const pkg = JSON.parse((0, import_node_fs7.readFileSync)((0, import_node_path8.join)(here, "..", "package.json"), "utf8"));
|
|
138336
|
+
if (pkg.version) return `${pkg.version}+source`;
|
|
138337
|
+
} catch {
|
|
138338
|
+
}
|
|
138339
|
+
return "0.0.0+unknown";
|
|
138340
|
+
}
|
|
138341
|
+
|
|
138342
|
+
// src/api/routes/backup.routes.ts
|
|
138343
|
+
function readBody(c) {
|
|
138344
|
+
return new Promise((resolve4, reject) => {
|
|
138345
|
+
const chunks = [];
|
|
138346
|
+
c.env.incoming.on("data", (chunk) => chunks.push(chunk));
|
|
138347
|
+
c.env.incoming.on("end", () => {
|
|
138348
|
+
try {
|
|
138349
|
+
const raw2 = Buffer.concat(chunks).toString("utf-8");
|
|
138350
|
+
resolve4(raw2 ? JSON.parse(raw2) : {});
|
|
138351
|
+
} catch {
|
|
138352
|
+
reject(new Error("Invalid JSON body"));
|
|
138353
|
+
}
|
|
138354
|
+
});
|
|
138355
|
+
c.env.incoming.on("error", reject);
|
|
138356
|
+
});
|
|
138357
|
+
}
|
|
138358
|
+
var createBackupRoutes = (deps) => {
|
|
138359
|
+
const app = new Hono2();
|
|
138360
|
+
app.get("/export", (c) => {
|
|
138361
|
+
const repo = deps.projectsRepo();
|
|
138362
|
+
if (!repo) {
|
|
138363
|
+
return c.json({ error: "Project store is unavailable", code: "STORE_UNAVAILABLE" }, 503);
|
|
138364
|
+
}
|
|
138365
|
+
const projects = repo.listProjects().map((p2) => ({
|
|
138366
|
+
id: p2.id,
|
|
138367
|
+
path: p2.path,
|
|
138368
|
+
name: p2.name ?? null,
|
|
138369
|
+
createdAt: p2.createdAt,
|
|
138370
|
+
updatedAt: p2.updatedAt
|
|
138371
|
+
}));
|
|
138372
|
+
return c.json({
|
|
138373
|
+
manifest: {
|
|
138374
|
+
formatVersion: BACKUP_FORMAT_VERSION,
|
|
138375
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
138376
|
+
streamerVersion: getVersion(),
|
|
138377
|
+
sourceHost: (0, import_os5.hostname)(),
|
|
138378
|
+
// No endpoint here exports the API key. The flag is recorded so an
|
|
138379
|
+
// archive is self-describing about its own sensitivity rather than
|
|
138380
|
+
// requiring a reader to infer it.
|
|
138381
|
+
includesSecrets: false,
|
|
138382
|
+
counts: { projects: projects.length }
|
|
138383
|
+
},
|
|
138384
|
+
projects
|
|
138385
|
+
});
|
|
138386
|
+
});
|
|
138387
|
+
app.post("/restore", async (c) => {
|
|
138388
|
+
const repo = deps.projectsRepo();
|
|
138389
|
+
if (!repo) {
|
|
138390
|
+
return c.json({ error: "Project store is unavailable", code: "STORE_UNAVAILABLE" }, 503);
|
|
138391
|
+
}
|
|
138392
|
+
let body;
|
|
138393
|
+
try {
|
|
138394
|
+
body = await readBody(c);
|
|
138395
|
+
} catch {
|
|
138396
|
+
return c.json({ error: "Invalid JSON body", code: "INVALID_BODY" }, 400);
|
|
138397
|
+
}
|
|
138398
|
+
let archive;
|
|
138399
|
+
try {
|
|
138400
|
+
archive = validateArchive(body.archive);
|
|
138401
|
+
} catch (err) {
|
|
138402
|
+
if (err instanceof BackupError) {
|
|
138403
|
+
return c.json({ error: err.message, code: err.code }, 400);
|
|
138404
|
+
}
|
|
138405
|
+
throw err;
|
|
138406
|
+
}
|
|
138407
|
+
const rules = Array.isArray(body.pathMap) ? body.pathMap.filter((r) => typeof r?.from === "string" && typeof r?.to === "string").map((r) => ({ from: r.from, to: r.to })) : [];
|
|
138408
|
+
const incoming = rules.length > 0 ? remapPaths(archive.projects, rules) : archive.projects;
|
|
138409
|
+
const existing = repo.listProjects().map((p2) => ({ id: p2.id, path: p2.path }));
|
|
138410
|
+
const plan = planRestore(incoming, existing);
|
|
138411
|
+
const summary = {
|
|
138412
|
+
create: plan.create.length,
|
|
138413
|
+
update: plan.update.length,
|
|
138414
|
+
conflict: plan.conflict.length
|
|
138415
|
+
};
|
|
138416
|
+
if (body.apply !== true) {
|
|
138417
|
+
return c.json({ applied: false, summary, plan });
|
|
138418
|
+
}
|
|
138419
|
+
if (plan.conflict.length > 0) {
|
|
138420
|
+
return c.json(
|
|
138421
|
+
{
|
|
138422
|
+
error: "Restore has unresolved conflicts",
|
|
138423
|
+
code: "RESTORE_CONFLICT",
|
|
138424
|
+
summary,
|
|
138425
|
+
plan
|
|
138426
|
+
},
|
|
138427
|
+
409
|
|
138428
|
+
);
|
|
138429
|
+
}
|
|
138430
|
+
let applied = 0;
|
|
138431
|
+
for (const p2 of [...plan.create, ...plan.update]) {
|
|
138432
|
+
try {
|
|
138433
|
+
repo.upsertProjectByPath(p2.path, { name: p2.name });
|
|
138434
|
+
applied++;
|
|
138435
|
+
} catch {
|
|
138436
|
+
}
|
|
138437
|
+
}
|
|
138438
|
+
return c.json({ applied: true, summary, appliedCount: applied });
|
|
138439
|
+
});
|
|
138440
|
+
return app;
|
|
138441
|
+
};
|
|
138442
|
+
|
|
138234
138443
|
// src/api/routes/browse.routes.ts
|
|
138235
138444
|
var ALREADY_HANDLED = 597;
|
|
138236
138445
|
var alreadyHandled = () => new Response(null, { status: ALREADY_HANDLED });
|
|
@@ -138413,38 +138622,251 @@ var createDeviceRoutes = (deps) => {
|
|
|
138413
138622
|
return app;
|
|
138414
138623
|
};
|
|
138415
138624
|
|
|
138416
|
-
// src/
|
|
138417
|
-
var
|
|
138418
|
-
|
|
138419
|
-
|
|
138420
|
-
|
|
138421
|
-
|
|
138422
|
-
|
|
138423
|
-
|
|
138424
|
-
|
|
138425
|
-
|
|
138426
|
-
|
|
138427
|
-
|
|
138428
|
-
|
|
138429
|
-
|
|
138430
|
-
|
|
138431
|
-
|
|
138625
|
+
// src/api/routes/diagnostics.routes.ts
|
|
138626
|
+
var import_fs14 = require("fs");
|
|
138627
|
+
|
|
138628
|
+
// src/platform.ts
|
|
138629
|
+
var import_child_process = require("child_process");
|
|
138630
|
+
var import_fs13 = require("fs");
|
|
138631
|
+
var import_os6 = require("os");
|
|
138632
|
+
var import_path13 = require("path");
|
|
138633
|
+
var isWindows2 = (0, import_os6.platform)() === "win32";
|
|
138634
|
+
var _claudeExe;
|
|
138635
|
+
function resolveClaudeExe() {
|
|
138636
|
+
if (_claudeExe !== void 0) return _claudeExe;
|
|
138637
|
+
if (isWindows2) {
|
|
138638
|
+
try {
|
|
138639
|
+
const found = (0, import_child_process.execFileSync)("where.exe", ["claude"], {
|
|
138640
|
+
encoding: "utf-8",
|
|
138641
|
+
windowsHide: true,
|
|
138642
|
+
timeout: 3e3
|
|
138643
|
+
}).trim().split("\n")[0].trim();
|
|
138644
|
+
if (found) {
|
|
138645
|
+
_claudeExe = found;
|
|
138646
|
+
return _claudeExe;
|
|
138647
|
+
}
|
|
138648
|
+
} catch {
|
|
138649
|
+
}
|
|
138650
|
+
const candidates = [
|
|
138651
|
+
(0, import_path13.join)((0, import_os6.homedir)(), ".local", "bin", "claude.exe"),
|
|
138652
|
+
(0, import_path13.join)(
|
|
138653
|
+
process.env.LOCALAPPDATA ?? (0, import_path13.join)((0, import_os6.homedir)(), "AppData", "Local"),
|
|
138654
|
+
"Microsoft",
|
|
138655
|
+
"WindowsApps",
|
|
138656
|
+
"claude.exe"
|
|
138657
|
+
)
|
|
138658
|
+
];
|
|
138659
|
+
for (const p2 of candidates) {
|
|
138660
|
+
if ((0, import_fs13.existsSync)(p2)) {
|
|
138661
|
+
_claudeExe = p2;
|
|
138662
|
+
return _claudeExe;
|
|
138663
|
+
}
|
|
138664
|
+
}
|
|
138665
|
+
} else {
|
|
138666
|
+
try {
|
|
138667
|
+
const found = (0, import_child_process.execFileSync)("/usr/bin/which", ["claude"], {
|
|
138668
|
+
encoding: "utf-8",
|
|
138669
|
+
timeout: 3e3
|
|
138670
|
+
}).trim().split("\n")[0].trim();
|
|
138671
|
+
if (found && (0, import_fs13.existsSync)(found)) {
|
|
138672
|
+
_claudeExe = found;
|
|
138673
|
+
return _claudeExe;
|
|
138674
|
+
}
|
|
138675
|
+
} catch {
|
|
138676
|
+
}
|
|
138677
|
+
const candidates = [
|
|
138678
|
+
"/opt/homebrew/bin/claude",
|
|
138679
|
+
"/usr/local/bin/claude",
|
|
138680
|
+
(0, import_path13.join)((0, import_os6.homedir)(), ".local", "bin", "claude")
|
|
138681
|
+
];
|
|
138682
|
+
for (const p2 of candidates) {
|
|
138683
|
+
if ((0, import_fs13.existsSync)(p2)) {
|
|
138684
|
+
_claudeExe = p2;
|
|
138685
|
+
return _claudeExe;
|
|
138686
|
+
}
|
|
138687
|
+
}
|
|
138432
138688
|
}
|
|
138433
|
-
|
|
138434
|
-
|
|
138689
|
+
_claudeExe = "claude";
|
|
138690
|
+
return _claudeExe;
|
|
138691
|
+
}
|
|
138692
|
+
var _codexExe;
|
|
138693
|
+
function resolveCodexExe() {
|
|
138694
|
+
if (_codexExe !== void 0) return _codexExe;
|
|
138695
|
+
if (isWindows2) {
|
|
138435
138696
|
try {
|
|
138436
|
-
const
|
|
138437
|
-
|
|
138697
|
+
const found = (0, import_child_process.execFileSync)("where.exe", ["codex"], {
|
|
138698
|
+
encoding: "utf-8",
|
|
138699
|
+
windowsHide: true,
|
|
138700
|
+
timeout: 3e3
|
|
138701
|
+
}).trim().split("\n")[0].trim();
|
|
138702
|
+
if (found) {
|
|
138703
|
+
_codexExe = found;
|
|
138704
|
+
return _codexExe;
|
|
138705
|
+
}
|
|
138706
|
+
} catch {
|
|
138707
|
+
}
|
|
138708
|
+
const candidates = [
|
|
138709
|
+
(0, import_path13.join)((0, import_os6.homedir)(), ".local", "bin", "codex.exe"),
|
|
138710
|
+
(0, import_path13.join)(
|
|
138711
|
+
process.env.LOCALAPPDATA ?? (0, import_path13.join)((0, import_os6.homedir)(), "AppData", "Local"),
|
|
138712
|
+
"Microsoft",
|
|
138713
|
+
"WindowsApps",
|
|
138714
|
+
"codex.exe"
|
|
138715
|
+
)
|
|
138716
|
+
];
|
|
138717
|
+
for (const p2 of candidates) {
|
|
138718
|
+
if ((0, import_fs13.existsSync)(p2)) {
|
|
138719
|
+
_codexExe = p2;
|
|
138720
|
+
return _codexExe;
|
|
138721
|
+
}
|
|
138722
|
+
}
|
|
138723
|
+
} else {
|
|
138724
|
+
try {
|
|
138725
|
+
const found = (0, import_child_process.execFileSync)("/usr/bin/which", ["codex"], {
|
|
138726
|
+
encoding: "utf-8",
|
|
138727
|
+
timeout: 3e3
|
|
138728
|
+
}).trim().split("\n")[0].trim();
|
|
138729
|
+
if (found && (0, import_fs13.existsSync)(found)) {
|
|
138730
|
+
_codexExe = found;
|
|
138731
|
+
return _codexExe;
|
|
138732
|
+
}
|
|
138438
138733
|
} catch {
|
|
138439
138734
|
}
|
|
138735
|
+
const candidates = [
|
|
138736
|
+
"/opt/homebrew/bin/codex",
|
|
138737
|
+
"/usr/local/bin/codex",
|
|
138738
|
+
(0, import_path13.join)((0, import_os6.homedir)(), ".local", "bin", "codex")
|
|
138739
|
+
];
|
|
138740
|
+
for (const p2 of candidates) {
|
|
138741
|
+
if ((0, import_fs13.existsSync)(p2)) {
|
|
138742
|
+
_codexExe = p2;
|
|
138743
|
+
return _codexExe;
|
|
138744
|
+
}
|
|
138745
|
+
}
|
|
138440
138746
|
}
|
|
138747
|
+
_codexExe = "codex";
|
|
138748
|
+
return _codexExe;
|
|
138749
|
+
}
|
|
138750
|
+
|
|
138751
|
+
// src/services/diagnostics/diagnostics.ts
|
|
138752
|
+
var DIAGNOSTICS_CONTRACT_VERSION = 1;
|
|
138753
|
+
function redactPath(path2) {
|
|
138754
|
+
if (!path2) return null;
|
|
138755
|
+
const parts = path2.split(/[/\\]/).filter(Boolean);
|
|
138756
|
+
if (parts.length <= 2) return parts.join("/");
|
|
138757
|
+
return `\u2026/${parts.slice(-2).join("/")}`;
|
|
138758
|
+
}
|
|
138759
|
+
function worstStatus(checks) {
|
|
138760
|
+
const rank = { ok: 0, unknown: 1, degraded: 2, failed: 3 };
|
|
138761
|
+
return checks.reduce(
|
|
138762
|
+
(worst, c) => rank[c.status] > rank[worst] ? c.status : worst,
|
|
138763
|
+
"ok"
|
|
138764
|
+
);
|
|
138765
|
+
}
|
|
138766
|
+
function buildReport(checks, now = /* @__PURE__ */ new Date()) {
|
|
138767
|
+
return {
|
|
138768
|
+
contractVersion: DIAGNOSTICS_CONTRACT_VERSION,
|
|
138769
|
+
generatedAt: now.toISOString(),
|
|
138770
|
+
overall: worstStatus(checks),
|
|
138771
|
+
checks
|
|
138772
|
+
};
|
|
138773
|
+
}
|
|
138774
|
+
var SECRET_KEY_RE = /(key|token|secret|password|passwd|credential|authorization|cookie)/i;
|
|
138775
|
+
function redactValue(value) {
|
|
138776
|
+
if (Array.isArray(value)) {
|
|
138777
|
+
return value.map((v2) => redactValue(v2));
|
|
138778
|
+
}
|
|
138779
|
+
if (value && typeof value === "object") {
|
|
138780
|
+
const out = {};
|
|
138781
|
+
for (const [k2, v2] of Object.entries(value)) {
|
|
138782
|
+
out[k2] = SECRET_KEY_RE.test(k2) ? "[redacted]" : redactValue(v2);
|
|
138783
|
+
}
|
|
138784
|
+
return out;
|
|
138785
|
+
}
|
|
138786
|
+
return value;
|
|
138787
|
+
}
|
|
138788
|
+
|
|
138789
|
+
// src/api/routes/diagnostics.routes.ts
|
|
138790
|
+
function providerCheck(name, resolve4) {
|
|
138441
138791
|
try {
|
|
138442
|
-
const
|
|
138443
|
-
|
|
138792
|
+
const exe = resolve4();
|
|
138793
|
+
return {
|
|
138794
|
+
id: `provider:${name}`,
|
|
138795
|
+
status: "ok",
|
|
138796
|
+
summary: `${name} CLI is installed.`,
|
|
138797
|
+
remediation: "NONE",
|
|
138798
|
+
detail: { location: redactPath(exe) }
|
|
138799
|
+
};
|
|
138444
138800
|
} catch {
|
|
138801
|
+
return {
|
|
138802
|
+
id: `provider:${name}`,
|
|
138803
|
+
status: "failed",
|
|
138804
|
+
summary: `${name} CLI could not be located. Sessions for this provider cannot start.`,
|
|
138805
|
+
remediation: "PROVIDER_NOT_INSTALLED"
|
|
138806
|
+
};
|
|
138445
138807
|
}
|
|
138446
|
-
return "0.0.0+unknown";
|
|
138447
138808
|
}
|
|
138809
|
+
var createDiagnosticsRoutes = (deps) => {
|
|
138810
|
+
const app = new Hono2();
|
|
138811
|
+
app.get("/", (c) => {
|
|
138812
|
+
const checks = [];
|
|
138813
|
+
checks.push({
|
|
138814
|
+
id: "streamer",
|
|
138815
|
+
status: "ok",
|
|
138816
|
+
summary: "Streamer is running.",
|
|
138817
|
+
remediation: "NONE",
|
|
138818
|
+
detail: { version: getVersion(), uptimeSeconds: Math.floor(process.uptime()) }
|
|
138819
|
+
});
|
|
138820
|
+
checks.push(providerCheck("claude-code", resolveClaudeExe));
|
|
138821
|
+
checks.push(providerCheck("codex-cli", resolveCodexExe));
|
|
138822
|
+
const cacheAlert = deps.cacheMonitor()?.healthzField();
|
|
138823
|
+
checks.push(
|
|
138824
|
+
cacheAlert ? {
|
|
138825
|
+
id: "cache",
|
|
138826
|
+
status: "degraded",
|
|
138827
|
+
summary: "Conversation cache reported an integrity alert.",
|
|
138828
|
+
remediation: "CACHE_DEGRADED"
|
|
138829
|
+
} : {
|
|
138830
|
+
id: "cache",
|
|
138831
|
+
status: "ok",
|
|
138832
|
+
summary: "Conversation cache is healthy.",
|
|
138833
|
+
remediation: "NONE"
|
|
138834
|
+
}
|
|
138835
|
+
);
|
|
138836
|
+
let ptyOk = true;
|
|
138837
|
+
try {
|
|
138838
|
+
require.resolve("node-pty");
|
|
138839
|
+
} catch {
|
|
138840
|
+
ptyOk = false;
|
|
138841
|
+
}
|
|
138842
|
+
checks.push(
|
|
138843
|
+
ptyOk ? { id: "pty", status: "ok", summary: "PTY subsystem is available.", remediation: "NONE" } : {
|
|
138844
|
+
id: "pty",
|
|
138845
|
+
status: "failed",
|
|
138846
|
+
summary: "node-pty failed to load, so no managed session can start.",
|
|
138847
|
+
remediation: "PTY_UNAVAILABLE"
|
|
138848
|
+
}
|
|
138849
|
+
);
|
|
138850
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
138851
|
+
const claudeProjects = home ? `${home}/.claude/projects` : "";
|
|
138852
|
+
checks.push(
|
|
138853
|
+
claudeProjects && (0, import_fs14.existsSync)(claudeProjects) ? {
|
|
138854
|
+
id: "filesystem",
|
|
138855
|
+
status: "ok",
|
|
138856
|
+
summary: "Provider history directory is present.",
|
|
138857
|
+
remediation: "NONE",
|
|
138858
|
+
detail: { location: redactPath(claudeProjects) }
|
|
138859
|
+
} : {
|
|
138860
|
+
id: "filesystem",
|
|
138861
|
+
status: "degraded",
|
|
138862
|
+
summary: "Provider history directory was not found; history may be unavailable.",
|
|
138863
|
+
remediation: "FS_SCOPE_MISSING"
|
|
138864
|
+
}
|
|
138865
|
+
);
|
|
138866
|
+
return c.json(redactValue(buildReport(checks)));
|
|
138867
|
+
});
|
|
138868
|
+
return app;
|
|
138869
|
+
};
|
|
138448
138870
|
|
|
138449
138871
|
// src/api/routes/health.routes.ts
|
|
138450
138872
|
var createHealthRoutes = (deps) => {
|
|
@@ -138579,7 +139001,7 @@ function createLogsRoutes() {
|
|
|
138579
139001
|
// src/api/routes/misc.routes.ts
|
|
138580
139002
|
var import_node_child_process2 = require("child_process");
|
|
138581
139003
|
var import_node_crypto = require("crypto");
|
|
138582
|
-
var
|
|
139004
|
+
var import_os7 = require("os");
|
|
138583
139005
|
|
|
138584
139006
|
// src/db/repositories/push.repository.ts
|
|
138585
139007
|
var FAILURE_STREAK_LIMIT = 5;
|
|
@@ -138879,7 +139301,7 @@ var createMiscRoutes = (deps) => {
|
|
|
138879
139301
|
const ptyIds = deps.ptyAttachedIds();
|
|
138880
139302
|
return c.json({
|
|
138881
139303
|
version: getVersion(),
|
|
138882
|
-
machineName: (0,
|
|
139304
|
+
machineName: (0, import_os7.hostname)(),
|
|
138883
139305
|
platform: process.platform,
|
|
138884
139306
|
activeSessions: deps.sessionStore.list(ptyIds).filter((s3) => s3.status === "running").length,
|
|
138885
139307
|
publicUrl: deps.publicUrl,
|
|
@@ -139168,129 +139590,6 @@ var createProjectRoutes = (deps) => {
|
|
|
139168
139590
|
return app;
|
|
139169
139591
|
};
|
|
139170
139592
|
|
|
139171
|
-
// src/platform.ts
|
|
139172
|
-
var import_child_process = require("child_process");
|
|
139173
|
-
var import_fs13 = require("fs");
|
|
139174
|
-
var import_os6 = require("os");
|
|
139175
|
-
var import_path13 = require("path");
|
|
139176
|
-
var isWindows2 = (0, import_os6.platform)() === "win32";
|
|
139177
|
-
var _claudeExe;
|
|
139178
|
-
function resolveClaudeExe() {
|
|
139179
|
-
if (_claudeExe !== void 0) return _claudeExe;
|
|
139180
|
-
if (isWindows2) {
|
|
139181
|
-
try {
|
|
139182
|
-
const found = (0, import_child_process.execFileSync)("where.exe", ["claude"], {
|
|
139183
|
-
encoding: "utf-8",
|
|
139184
|
-
windowsHide: true,
|
|
139185
|
-
timeout: 3e3
|
|
139186
|
-
}).trim().split("\n")[0].trim();
|
|
139187
|
-
if (found) {
|
|
139188
|
-
_claudeExe = found;
|
|
139189
|
-
return _claudeExe;
|
|
139190
|
-
}
|
|
139191
|
-
} catch {
|
|
139192
|
-
}
|
|
139193
|
-
const candidates = [
|
|
139194
|
-
(0, import_path13.join)((0, import_os6.homedir)(), ".local", "bin", "claude.exe"),
|
|
139195
|
-
(0, import_path13.join)(
|
|
139196
|
-
process.env.LOCALAPPDATA ?? (0, import_path13.join)((0, import_os6.homedir)(), "AppData", "Local"),
|
|
139197
|
-
"Microsoft",
|
|
139198
|
-
"WindowsApps",
|
|
139199
|
-
"claude.exe"
|
|
139200
|
-
)
|
|
139201
|
-
];
|
|
139202
|
-
for (const p2 of candidates) {
|
|
139203
|
-
if ((0, import_fs13.existsSync)(p2)) {
|
|
139204
|
-
_claudeExe = p2;
|
|
139205
|
-
return _claudeExe;
|
|
139206
|
-
}
|
|
139207
|
-
}
|
|
139208
|
-
} else {
|
|
139209
|
-
try {
|
|
139210
|
-
const found = (0, import_child_process.execFileSync)("/usr/bin/which", ["claude"], {
|
|
139211
|
-
encoding: "utf-8",
|
|
139212
|
-
timeout: 3e3
|
|
139213
|
-
}).trim().split("\n")[0].trim();
|
|
139214
|
-
if (found && (0, import_fs13.existsSync)(found)) {
|
|
139215
|
-
_claudeExe = found;
|
|
139216
|
-
return _claudeExe;
|
|
139217
|
-
}
|
|
139218
|
-
} catch {
|
|
139219
|
-
}
|
|
139220
|
-
const candidates = [
|
|
139221
|
-
"/opt/homebrew/bin/claude",
|
|
139222
|
-
"/usr/local/bin/claude",
|
|
139223
|
-
(0, import_path13.join)((0, import_os6.homedir)(), ".local", "bin", "claude")
|
|
139224
|
-
];
|
|
139225
|
-
for (const p2 of candidates) {
|
|
139226
|
-
if ((0, import_fs13.existsSync)(p2)) {
|
|
139227
|
-
_claudeExe = p2;
|
|
139228
|
-
return _claudeExe;
|
|
139229
|
-
}
|
|
139230
|
-
}
|
|
139231
|
-
}
|
|
139232
|
-
_claudeExe = "claude";
|
|
139233
|
-
return _claudeExe;
|
|
139234
|
-
}
|
|
139235
|
-
var _codexExe;
|
|
139236
|
-
function resolveCodexExe() {
|
|
139237
|
-
if (_codexExe !== void 0) return _codexExe;
|
|
139238
|
-
if (isWindows2) {
|
|
139239
|
-
try {
|
|
139240
|
-
const found = (0, import_child_process.execFileSync)("where.exe", ["codex"], {
|
|
139241
|
-
encoding: "utf-8",
|
|
139242
|
-
windowsHide: true,
|
|
139243
|
-
timeout: 3e3
|
|
139244
|
-
}).trim().split("\n")[0].trim();
|
|
139245
|
-
if (found) {
|
|
139246
|
-
_codexExe = found;
|
|
139247
|
-
return _codexExe;
|
|
139248
|
-
}
|
|
139249
|
-
} catch {
|
|
139250
|
-
}
|
|
139251
|
-
const candidates = [
|
|
139252
|
-
(0, import_path13.join)((0, import_os6.homedir)(), ".local", "bin", "codex.exe"),
|
|
139253
|
-
(0, import_path13.join)(
|
|
139254
|
-
process.env.LOCALAPPDATA ?? (0, import_path13.join)((0, import_os6.homedir)(), "AppData", "Local"),
|
|
139255
|
-
"Microsoft",
|
|
139256
|
-
"WindowsApps",
|
|
139257
|
-
"codex.exe"
|
|
139258
|
-
)
|
|
139259
|
-
];
|
|
139260
|
-
for (const p2 of candidates) {
|
|
139261
|
-
if ((0, import_fs13.existsSync)(p2)) {
|
|
139262
|
-
_codexExe = p2;
|
|
139263
|
-
return _codexExe;
|
|
139264
|
-
}
|
|
139265
|
-
}
|
|
139266
|
-
} else {
|
|
139267
|
-
try {
|
|
139268
|
-
const found = (0, import_child_process.execFileSync)("/usr/bin/which", ["codex"], {
|
|
139269
|
-
encoding: "utf-8",
|
|
139270
|
-
timeout: 3e3
|
|
139271
|
-
}).trim().split("\n")[0].trim();
|
|
139272
|
-
if (found && (0, import_fs13.existsSync)(found)) {
|
|
139273
|
-
_codexExe = found;
|
|
139274
|
-
return _codexExe;
|
|
139275
|
-
}
|
|
139276
|
-
} catch {
|
|
139277
|
-
}
|
|
139278
|
-
const candidates = [
|
|
139279
|
-
"/opt/homebrew/bin/codex",
|
|
139280
|
-
"/usr/local/bin/codex",
|
|
139281
|
-
(0, import_path13.join)((0, import_os6.homedir)(), ".local", "bin", "codex")
|
|
139282
|
-
];
|
|
139283
|
-
for (const p2 of candidates) {
|
|
139284
|
-
if ((0, import_fs13.existsSync)(p2)) {
|
|
139285
|
-
_codexExe = p2;
|
|
139286
|
-
return _codexExe;
|
|
139287
|
-
}
|
|
139288
|
-
}
|
|
139289
|
-
}
|
|
139290
|
-
_codexExe = "codex";
|
|
139291
|
-
return _codexExe;
|
|
139292
|
-
}
|
|
139293
|
-
|
|
139294
139593
|
// src/providers.ts
|
|
139295
139594
|
var CLAUDE_CODE_PROVIDER2 = "claude-code";
|
|
139296
139595
|
var CODEX_CLI_PROVIDER2 = "codex-cli";
|
|
@@ -139576,6 +139875,7 @@ var createHonoApp = (deps, upgradeWebSocket) => {
|
|
|
139576
139875
|
app.use("*", authMiddleware(deps));
|
|
139577
139876
|
app.onError(errorMiddleware);
|
|
139578
139877
|
app.route("/healthz", createHealthRoutes(deps));
|
|
139878
|
+
app.route("/api/diagnostics", createDiagnosticsRoutes(deps));
|
|
139579
139879
|
app.route("/", createMiscRoutes(deps));
|
|
139580
139880
|
app.route("/api/sessions", createSessionRoutes(deps));
|
|
139581
139881
|
app.route("/api/conversations", createConversationRoutes(deps));
|
|
@@ -139584,6 +139884,7 @@ var createHonoApp = (deps, upgradeWebSocket) => {
|
|
|
139584
139884
|
app.route("/api/projects", createProjectRoutes(deps));
|
|
139585
139885
|
app.route("/api/providers", createProviderRoutes());
|
|
139586
139886
|
app.route("/api/devices", createDeviceRoutes(deps));
|
|
139887
|
+
app.route("/api/backup", createBackupRoutes(deps));
|
|
139587
139888
|
app.route("/api/pair", createPairRoutes(deps));
|
|
139588
139889
|
app.route("/api", createBrowseRoutes(deps));
|
|
139589
139890
|
app.route("/", createScannerRoutes(deps));
|
|
@@ -139654,13 +139955,13 @@ init_claude_flags();
|
|
|
139654
139955
|
|
|
139655
139956
|
// src/conversation-cache.ts
|
|
139656
139957
|
var import_better_sqlite32 = __toESM(require("better-sqlite3"), 1);
|
|
139657
|
-
var
|
|
139958
|
+
var import_fs17 = require("fs");
|
|
139658
139959
|
var import_promises12 = require("fs/promises");
|
|
139659
139960
|
var import_path17 = require("path");
|
|
139660
139961
|
var import_promises13 = require("timers/promises");
|
|
139661
139962
|
|
|
139662
139963
|
// src/db/sqlite-migrate.ts
|
|
139663
|
-
var
|
|
139964
|
+
var import_fs15 = require("fs");
|
|
139664
139965
|
var import_path15 = require("path");
|
|
139665
139966
|
var import_url6 = require("url");
|
|
139666
139967
|
var import_meta2 = {};
|
|
@@ -139679,7 +139980,7 @@ CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
|
139679
139980
|
function runSqliteMigrations(db, migrationsDir) {
|
|
139680
139981
|
db.exec(SCHEMA_MIGRATIONS_SQL);
|
|
139681
139982
|
const dir = migrationsDir ?? (0, import_path15.join)(getMigrationsDir(), "migrations");
|
|
139682
|
-
const files = (0,
|
|
139983
|
+
const files = (0, import_fs15.readdirSync)(dir).filter((f2) => f2.endsWith(".sql")).sort();
|
|
139683
139984
|
const appliedRows = db.prepare("SELECT id FROM schema_migrations").all();
|
|
139684
139985
|
const appliedSet = new Set(appliedRows.map((r) => r.id));
|
|
139685
139986
|
const recordApplied = db.prepare("INSERT INTO schema_migrations (id, applied_at) VALUES (?, ?)");
|
|
@@ -139690,7 +139991,7 @@ function runSqliteMigrations(db, migrationsDir) {
|
|
|
139690
139991
|
skipped.push(file2);
|
|
139691
139992
|
continue;
|
|
139692
139993
|
}
|
|
139693
|
-
const sql = (0,
|
|
139994
|
+
const sql = (0, import_fs15.readFileSync)((0, import_path15.join)(dir, file2), "utf-8");
|
|
139694
139995
|
const tx = db.transaction(() => {
|
|
139695
139996
|
db.exec(sql);
|
|
139696
139997
|
recordApplied.run(file2, (/* @__PURE__ */ new Date()).toISOString());
|
|
@@ -139702,7 +140003,7 @@ function runSqliteMigrations(db, migrationsDir) {
|
|
|
139702
140003
|
}
|
|
139703
140004
|
|
|
139704
140005
|
// src/services/conversations/isAgentConversation.ts
|
|
139705
|
-
var
|
|
140006
|
+
var import_fs16 = require("fs");
|
|
139706
140007
|
var DEFAULT_AGENT_ENTRYPOINTS = /* @__PURE__ */ new Set(["sdk-cli", "claude-vscode"]);
|
|
139707
140008
|
var CHUNK_BYTES = 64 * 1024;
|
|
139708
140009
|
var ENTRYPOINT_PROBE = `"entrypoint":`;
|
|
@@ -139724,12 +140025,12 @@ function isAgentFile(filePath, entrypoints = DEFAULT_AGENT_ENTRYPOINTS) {
|
|
|
139724
140025
|
if (cached3 !== void 0) return cached3;
|
|
139725
140026
|
let fd;
|
|
139726
140027
|
try {
|
|
139727
|
-
fd = (0,
|
|
140028
|
+
fd = (0, import_fs16.openSync)(filePath, "r");
|
|
139728
140029
|
} catch {
|
|
139729
140030
|
return false;
|
|
139730
140031
|
}
|
|
139731
140032
|
try {
|
|
139732
|
-
const fileSize = (0,
|
|
140033
|
+
const fileSize = (0, import_fs16.statSync)(filePath).size;
|
|
139733
140034
|
if (fileSize === 0) {
|
|
139734
140035
|
fileDecisionCache.set(key, false);
|
|
139735
140036
|
return false;
|
|
@@ -139740,7 +140041,7 @@ function isAgentFile(filePath, entrypoints = DEFAULT_AGENT_ENTRYPOINTS) {
|
|
|
139740
140041
|
let carry = "";
|
|
139741
140042
|
while (offset < fileSize) {
|
|
139742
140043
|
const toRead = Math.min(CHUNK_BYTES, fileSize - offset);
|
|
139743
|
-
const got = (0,
|
|
140044
|
+
const got = (0, import_fs16.readSync)(fd, buf, 0, toRead, offset);
|
|
139744
140045
|
if (got <= 0) break;
|
|
139745
140046
|
const chunk = carry + buf.toString("utf8", 0, got);
|
|
139746
140047
|
for (const marker of markers) {
|
|
@@ -139761,7 +140062,7 @@ function isAgentFile(filePath, entrypoints = DEFAULT_AGENT_ENTRYPOINTS) {
|
|
|
139761
140062
|
} catch {
|
|
139762
140063
|
return false;
|
|
139763
140064
|
} finally {
|
|
139764
|
-
(0,
|
|
140065
|
+
(0, import_fs16.closeSync)(fd);
|
|
139765
140066
|
}
|
|
139766
140067
|
}
|
|
139767
140068
|
function parseAgentEntrypointsEnv(raw2) {
|
|
@@ -140336,7 +140637,7 @@ var ConversationCache = class _ConversationCache {
|
|
|
140336
140637
|
if (!fileState) return null;
|
|
140337
140638
|
let stat7;
|
|
140338
140639
|
try {
|
|
140339
|
-
stat7 = (0,
|
|
140640
|
+
stat7 = (0, import_fs17.statSync)(filePath);
|
|
140340
140641
|
} catch {
|
|
140341
140642
|
return null;
|
|
140342
140643
|
}
|
|
@@ -140357,17 +140658,17 @@ var ConversationCache = class _ConversationCache {
|
|
|
140357
140658
|
);
|
|
140358
140659
|
if (rows.length === 0) return { messages: [], total, fromIndex: from };
|
|
140359
140660
|
const messages = [];
|
|
140360
|
-
const fd = (0,
|
|
140661
|
+
const fd = (0, import_fs17.openSync)(filePath, "r");
|
|
140361
140662
|
try {
|
|
140362
140663
|
const state = initialConvState();
|
|
140363
140664
|
for (const row of rows) {
|
|
140364
140665
|
const buf = Buffer.alloc(row.byte_length);
|
|
140365
|
-
(0,
|
|
140666
|
+
(0, import_fs17.readSync)(fd, buf, 0, row.byte_length, row.byte_offset);
|
|
140366
140667
|
const msg = parseJsonlLine(buf.toString("utf-8"), state);
|
|
140367
140668
|
if (msg) messages.push(msg);
|
|
140368
140669
|
}
|
|
140369
140670
|
} finally {
|
|
140370
|
-
(0,
|
|
140671
|
+
(0, import_fs17.closeSync)(fd);
|
|
140371
140672
|
}
|
|
140372
140673
|
return { messages, total, fromIndex: from };
|
|
140373
140674
|
}
|
|
@@ -140395,14 +140696,14 @@ var ConversationCache = class _ConversationCache {
|
|
|
140395
140696
|
isAgentFileCached(filePath) {
|
|
140396
140697
|
let s3;
|
|
140397
140698
|
try {
|
|
140398
|
-
s3 = (0,
|
|
140699
|
+
s3 = (0, import_fs17.statSync)(filePath);
|
|
140399
140700
|
} catch {
|
|
140400
140701
|
return false;
|
|
140401
140702
|
}
|
|
140402
140703
|
return this.classifyAgentFile(filePath, s3.mtimeMs, s3.size);
|
|
140403
140704
|
}
|
|
140404
140705
|
static open(dbPath, tailSize = 10, migrationsDir, options) {
|
|
140405
|
-
(0,
|
|
140706
|
+
(0, import_fs17.mkdirSync)((0, import_path17.dirname)(dbPath), { recursive: true });
|
|
140406
140707
|
const db = new import_better_sqlite32.default(dbPath);
|
|
140407
140708
|
db.pragma("journal_mode = WAL");
|
|
140408
140709
|
db.pragma("foreign_keys = ON");
|
|
@@ -140589,7 +140890,7 @@ var ConversationCache = class _ConversationCache {
|
|
|
140589
140890
|
let mtimeMs = null;
|
|
140590
140891
|
let fileSize = null;
|
|
140591
140892
|
try {
|
|
140592
|
-
const s3 = (0,
|
|
140893
|
+
const s3 = (0, import_fs17.statSync)(m2.filePath);
|
|
140593
140894
|
mtimeMs = s3.mtimeMs;
|
|
140594
140895
|
fileSize = s3.size;
|
|
140595
140896
|
} catch {
|
|
@@ -140649,8 +140950,8 @@ var ConversationCache = class _ConversationCache {
|
|
|
140649
140950
|
let fileSize;
|
|
140650
140951
|
let fd;
|
|
140651
140952
|
try {
|
|
140652
|
-
fileSize = (0,
|
|
140653
|
-
fd = (0,
|
|
140953
|
+
fileSize = (0, import_fs17.statSync)(filePath).size;
|
|
140954
|
+
fd = (0, import_fs17.openSync)(filePath, "r");
|
|
140654
140955
|
} catch {
|
|
140655
140956
|
return false;
|
|
140656
140957
|
}
|
|
@@ -140663,7 +140964,7 @@ var ConversationCache = class _ConversationCache {
|
|
|
140663
140964
|
while (pos > 0 && lines.length < this.tailSize * 4) {
|
|
140664
140965
|
const toRead = Math.min(CHUNK, pos);
|
|
140665
140966
|
pos -= toRead;
|
|
140666
|
-
(0,
|
|
140967
|
+
(0, import_fs17.readSync)(fd, buf, 0, toRead, pos);
|
|
140667
140968
|
const chunk = buf.subarray(0, toRead).toString("utf8");
|
|
140668
140969
|
const combined = chunk + partial2;
|
|
140669
140970
|
const parts = combined.split("\n");
|
|
@@ -140674,7 +140975,7 @@ var ConversationCache = class _ConversationCache {
|
|
|
140674
140975
|
}
|
|
140675
140976
|
if (partial2) lines.push(partial2);
|
|
140676
140977
|
} finally {
|
|
140677
|
-
(0,
|
|
140978
|
+
(0, import_fs17.closeSync)(fd);
|
|
140678
140979
|
}
|
|
140679
140980
|
const msgs = [];
|
|
140680
140981
|
for (let i = 0; i < lines.length && msgs.length < this.tailSize; i++) {
|
|
@@ -140887,7 +141188,7 @@ var ConversationCache = class _ConversationCache {
|
|
|
140887
141188
|
* `handleGetConversation` can still serve the cached tail even when the
|
|
140888
141189
|
* JSONL has been deleted.
|
|
140889
141190
|
*/
|
|
140890
|
-
pruneGhostFiles(exists =
|
|
141191
|
+
pruneGhostFiles(exists = import_fs17.existsSync) {
|
|
140891
141192
|
const rows = this.stmts.allFilePaths.all();
|
|
140892
141193
|
const ghosts = [];
|
|
140893
141194
|
const prune = this.db.transaction((ids) => {
|
|
@@ -140942,7 +141243,7 @@ var ConversationCache = class _ConversationCache {
|
|
|
140942
141243
|
* Returns the removed IDs.
|
|
140943
141244
|
*/
|
|
140944
141245
|
reconcileDeletions(livePaths, opts) {
|
|
140945
|
-
const exists = opts?.exists ??
|
|
141246
|
+
const exists = opts?.exists ?? import_fs17.existsSync;
|
|
140946
141247
|
const rows = this.stmts.allFilePaths.all();
|
|
140947
141248
|
const removed = [];
|
|
140948
141249
|
const drop = this.db.transaction((ids) => {
|
|
@@ -140977,7 +141278,7 @@ var ConversationCache = class _ConversationCache {
|
|
|
140977
141278
|
* reports drift for the CacheIntegrityMonitor to classify. `tailed` flags
|
|
140978
141279
|
* rows that still have cached history (which pruneGhostFiles would keep).
|
|
140979
141280
|
*/
|
|
140980
|
-
listMissingFiles(exists =
|
|
141281
|
+
listMissingFiles(exists = import_fs17.existsSync) {
|
|
140981
141282
|
const rows = this.stmts.allFilePathsWithTitle.all();
|
|
140982
141283
|
const missing = [];
|
|
140983
141284
|
for (const row of rows) {
|
|
@@ -141062,7 +141363,7 @@ function getDbConfig() {
|
|
|
141062
141363
|
}
|
|
141063
141364
|
|
|
141064
141365
|
// src/db/migrations.ts
|
|
141065
|
-
var
|
|
141366
|
+
var import_fs18 = require("fs");
|
|
141066
141367
|
var import_path18 = require("path");
|
|
141067
141368
|
var import_url7 = require("url");
|
|
141068
141369
|
var import_meta3 = {};
|
|
@@ -141085,10 +141386,10 @@ async function runMigrations2(pool2, migrationsDir) {
|
|
|
141085
141386
|
);
|
|
141086
141387
|
const appliedSet = new Set(applied.map((r) => r.name));
|
|
141087
141388
|
const dir = migrationsDir ?? (0, import_path18.join)(getMigrationsDir2(), "pg-migrations");
|
|
141088
|
-
const files = (0,
|
|
141389
|
+
const files = (0, import_fs18.readdirSync)(dir).filter((f2) => f2.endsWith(".sql")).sort();
|
|
141089
141390
|
for (const file2 of files) {
|
|
141090
141391
|
if (appliedSet.has(file2)) continue;
|
|
141091
|
-
const sql = (0,
|
|
141392
|
+
const sql = (0, import_fs18.readFileSync)((0, import_path18.join)(dir, file2), "utf-8");
|
|
141092
141393
|
await pool2.query(sql);
|
|
141093
141394
|
await pool2.query("INSERT INTO _migrations (name) VALUES ($1)", [file2]);
|
|
141094
141395
|
}
|
|
@@ -141440,8 +141741,8 @@ async function recordUpload(pool2, instanceId, row) {
|
|
|
141440
141741
|
init_feature_flags();
|
|
141441
141742
|
|
|
141442
141743
|
// src/handlers/handleListProjects.ts
|
|
141443
|
-
var
|
|
141444
|
-
var
|
|
141744
|
+
var import_fs19 = require("fs");
|
|
141745
|
+
var import_os8 = require("os");
|
|
141445
141746
|
var import_path19 = require("path");
|
|
141446
141747
|
function decodeProjectPath(dirName) {
|
|
141447
141748
|
return dirName.replace(/-/g, "/");
|
|
@@ -141449,14 +141750,14 @@ function decodeProjectPath(dirName) {
|
|
|
141449
141750
|
function handleListProjects(url2, res) {
|
|
141450
141751
|
const limit = Math.max(1, parseInt(url2.searchParams.get("limit") ?? "50", 10) || 50);
|
|
141451
141752
|
const offset = Math.max(0, parseInt(url2.searchParams.get("offset") ?? "0", 10) || 0);
|
|
141452
|
-
const projectsDir = (0, import_path19.join)((0,
|
|
141753
|
+
const projectsDir = (0, import_path19.join)((0, import_os8.homedir)(), ".claude", "projects");
|
|
141453
141754
|
let entries;
|
|
141454
141755
|
try {
|
|
141455
|
-
entries = (0,
|
|
141756
|
+
entries = (0, import_fs19.readdirSync)(projectsDir).map((dirName) => {
|
|
141456
141757
|
const fullPath = (0, import_path19.join)(projectsDir, dirName);
|
|
141457
141758
|
let mtime = 0;
|
|
141458
141759
|
try {
|
|
141459
|
-
mtime = (0,
|
|
141760
|
+
mtime = (0, import_fs19.statSync)(fullPath).mtimeMs;
|
|
141460
141761
|
} catch {
|
|
141461
141762
|
}
|
|
141462
141763
|
const path2 = decodeProjectPath(dirName);
|
|
@@ -141492,21 +141793,21 @@ var import_path23 = require("path");
|
|
|
141492
141793
|
// src/codex-pty-runner.ts
|
|
141493
141794
|
var import_headless = __toESM(require_xterm_headless(), 1);
|
|
141494
141795
|
var import_crypto8 = require("crypto");
|
|
141495
|
-
var
|
|
141796
|
+
var import_fs21 = require("fs");
|
|
141496
141797
|
var import_path21 = require("path");
|
|
141497
141798
|
init_logger();
|
|
141498
141799
|
|
|
141499
141800
|
// src/services/questions/codexGateAnswers.ts
|
|
141500
|
-
var
|
|
141501
|
-
var
|
|
141801
|
+
var import_fs20 = require("fs");
|
|
141802
|
+
var import_os9 = require("os");
|
|
141502
141803
|
var import_path20 = require("path");
|
|
141503
141804
|
function gateAnswersPath() {
|
|
141504
|
-
const dir = process.env.THREADBASE_CONFIG_DIR ?? (0, import_path20.join)((0,
|
|
141805
|
+
const dir = process.env.THREADBASE_CONFIG_DIR ?? (0, import_path20.join)((0, import_os9.homedir)(), ".threadbase");
|
|
141505
141806
|
return (0, import_path20.join)(dir, "gate-answers.json");
|
|
141506
141807
|
}
|
|
141507
141808
|
function loadGateAnswers() {
|
|
141508
141809
|
try {
|
|
141509
|
-
const parsed = JSON.parse((0,
|
|
141810
|
+
const parsed = JSON.parse((0, import_fs20.readFileSync)(gateAnswersPath(), "utf-8"));
|
|
141510
141811
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
141511
141812
|
} catch {
|
|
141512
141813
|
return {};
|
|
@@ -141514,8 +141815,8 @@ function loadGateAnswers() {
|
|
|
141514
141815
|
}
|
|
141515
141816
|
function saveGateAnswer(key, value) {
|
|
141516
141817
|
const path2 = gateAnswersPath();
|
|
141517
|
-
(0,
|
|
141518
|
-
(0,
|
|
141818
|
+
(0, import_fs20.mkdirSync)((0, import_path20.dirname)(path2), { recursive: true });
|
|
141819
|
+
(0, import_fs20.writeFileSync)(path2, `${JSON.stringify({ ...loadGateAnswers(), [key]: value }, null, 2)}
|
|
141519
141820
|
`);
|
|
141520
141821
|
}
|
|
141521
141822
|
function rememberedGateDigit(gate) {
|
|
@@ -142191,7 +142492,7 @@ var CodexPtyRunner = class {
|
|
|
142191
142492
|
session.statusUpdatedAt = /* @__PURE__ */ new Date();
|
|
142192
142493
|
const elapsedMs = session.completedAt.getTime() - session.startedAt.getTime();
|
|
142193
142494
|
if (exitCode !== 0 && elapsedMs < 2e3 && session.lastOutput === "") {
|
|
142194
|
-
if (!(0,
|
|
142495
|
+
if (!(0, import_fs21.existsSync)(session.projectPath)) {
|
|
142195
142496
|
session.failureReason = `Project directory not found: ${session.projectPath}`;
|
|
142196
142497
|
} else {
|
|
142197
142498
|
session.failureReason = `Codex process exited immediately (code ${exitCode}).`;
|
|
@@ -142230,7 +142531,7 @@ function stripAnsi(str) {
|
|
|
142230
142531
|
// src/pty-manager.ts
|
|
142231
142532
|
var import_headless2 = __toESM(require_xterm_headless(), 1);
|
|
142232
142533
|
var import_crypto9 = require("crypto");
|
|
142233
|
-
var
|
|
142534
|
+
var import_fs22 = require("fs");
|
|
142234
142535
|
var import_path22 = require("path");
|
|
142235
142536
|
init_claude_flags();
|
|
142236
142537
|
init_logger();
|
|
@@ -143142,7 +143443,7 @@ var PTYManager = class {
|
|
|
143142
143443
|
session.statusUpdatedAt = /* @__PURE__ */ new Date();
|
|
143143
143444
|
const elapsedMs = session.completedAt.getTime() - session.startedAt.getTime();
|
|
143144
143445
|
if (exitCode !== 0 && elapsedMs < 2e3 && session.lastOutput === "") {
|
|
143145
|
-
if (!(0,
|
|
143446
|
+
if (!(0, import_fs22.existsSync)(session.projectPath)) {
|
|
143146
143447
|
session.failureReason = `Project directory not found: ${session.projectPath}`;
|
|
143147
143448
|
} else {
|
|
143148
143449
|
session.failureReason = `Process exited immediately (code ${exitCode}). Check that the Claude binary is installed and accessible.`;
|
|
@@ -143351,10 +143652,10 @@ var PairTokenStore = class {
|
|
|
143351
143652
|
|
|
143352
143653
|
// src/process-discovery.ts
|
|
143353
143654
|
var import_child_process3 = require("child_process");
|
|
143354
|
-
var
|
|
143655
|
+
var import_os10 = require("os");
|
|
143355
143656
|
var import_path24 = require("path");
|
|
143356
143657
|
async function discoverClaudeProcesses() {
|
|
143357
|
-
if ((0,
|
|
143658
|
+
if ((0, import_os10.platform)() === "win32") return discoverWindows();
|
|
143358
143659
|
return discoverUnix();
|
|
143359
143660
|
}
|
|
143360
143661
|
var CLAUDE_CLI_SCRIPT = /claude-code[\\/](?:cli|index)\.(?:js|mjs|cjs)$/i;
|
|
@@ -143494,7 +143795,7 @@ async function getProcessArgsUnix(pid) {
|
|
|
143494
143795
|
async function getProcessArgs(pid) {
|
|
143495
143796
|
if (!Number.isInteger(pid) || pid < 1) return "";
|
|
143496
143797
|
try {
|
|
143497
|
-
if ((0,
|
|
143798
|
+
if ((0, import_os10.platform)() === "win32") {
|
|
143498
143799
|
const info = await getProcessInfoWindows(pid);
|
|
143499
143800
|
return info?.args ?? "";
|
|
143500
143801
|
}
|
|
@@ -143645,19 +143946,19 @@ function setCacheMetadata(repo, key, value) {
|
|
|
143645
143946
|
|
|
143646
143947
|
// src/services/cache-integrity/cacheIntegrityMonitor.ts
|
|
143647
143948
|
var import_crypto11 = require("crypto");
|
|
143648
|
-
var
|
|
143949
|
+
var import_fs25 = require("fs");
|
|
143649
143950
|
|
|
143650
143951
|
// src/services/cache-integrity/alertStore.ts
|
|
143651
|
-
var
|
|
143652
|
-
var
|
|
143952
|
+
var import_fs23 = require("fs");
|
|
143953
|
+
var import_os11 = require("os");
|
|
143653
143954
|
var import_path25 = require("path");
|
|
143654
143955
|
function alertStatePath() {
|
|
143655
|
-
const dir = process.env.THREADBASE_CONFIG_DIR ?? (0, import_path25.join)((0,
|
|
143956
|
+
const dir = process.env.THREADBASE_CONFIG_DIR ?? (0, import_path25.join)((0, import_os11.homedir)(), ".threadbase");
|
|
143656
143957
|
return (0, import_path25.join)(dir, "cache-alert.json");
|
|
143657
143958
|
}
|
|
143658
143959
|
function loadAlertState() {
|
|
143659
143960
|
try {
|
|
143660
|
-
const parsed = JSON.parse((0,
|
|
143961
|
+
const parsed = JSON.parse((0, import_fs23.readFileSync)(alertStatePath(), "utf-8"));
|
|
143661
143962
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
143662
143963
|
} catch {
|
|
143663
143964
|
return {};
|
|
@@ -143665,13 +143966,13 @@ function loadAlertState() {
|
|
|
143665
143966
|
}
|
|
143666
143967
|
function saveAlertState(state) {
|
|
143667
143968
|
const path2 = alertStatePath();
|
|
143668
|
-
(0,
|
|
143669
|
-
(0,
|
|
143969
|
+
(0, import_fs23.mkdirSync)((0, import_path25.dirname)(path2), { recursive: true });
|
|
143970
|
+
(0, import_fs23.writeFileSync)(path2, `${JSON.stringify(state, null, 2)}
|
|
143670
143971
|
`);
|
|
143671
143972
|
}
|
|
143672
143973
|
|
|
143673
143974
|
// src/services/cache-integrity/backup.ts
|
|
143674
|
-
var
|
|
143975
|
+
var import_fs24 = require("fs");
|
|
143675
143976
|
var import_path26 = require("path");
|
|
143676
143977
|
var DEFAULT_RETAIN = 3;
|
|
143677
143978
|
function retainCount() {
|
|
@@ -143684,16 +143985,16 @@ function timestamp(d) {
|
|
|
143684
143985
|
}
|
|
143685
143986
|
async function backupCacheDb(db, cacheDir) {
|
|
143686
143987
|
const backupsDir = (0, import_path26.join)(cacheDir, "backups");
|
|
143687
|
-
(0,
|
|
143988
|
+
(0, import_fs24.mkdirSync)(backupsDir, { recursive: true });
|
|
143688
143989
|
const destPath = (0, import_path26.join)(backupsDir, `cache-${timestamp(/* @__PURE__ */ new Date())}.db`);
|
|
143689
143990
|
await db.backup(destPath);
|
|
143690
143991
|
const retain = retainCount();
|
|
143691
|
-
const backups = (0,
|
|
143992
|
+
const backups = (0, import_fs24.readdirSync)(backupsDir).filter((f2) => f2.startsWith("cache-") && f2.endsWith(".db")).map((f2) => {
|
|
143692
143993
|
const full = (0, import_path26.join)(backupsDir, f2);
|
|
143693
|
-
return { full, mtime: (0,
|
|
143994
|
+
return { full, mtime: (0, import_fs24.statSync)(full).mtimeMs };
|
|
143694
143995
|
}).sort((a, b2) => b2.mtime - a.mtime);
|
|
143695
143996
|
for (const stale of backups.slice(retain)) {
|
|
143696
|
-
if ((0,
|
|
143997
|
+
if ((0, import_fs24.existsSync)(stale.full)) (0, import_fs24.unlinkSync)(stale.full);
|
|
143697
143998
|
}
|
|
143698
143999
|
return destPath;
|
|
143699
144000
|
}
|
|
@@ -143790,7 +144091,7 @@ var CacheIntegrityMonitor = class {
|
|
|
143790
144091
|
* the pending record, back up on high severity, and broadcast the alert.
|
|
143791
144092
|
*/
|
|
143792
144093
|
async runDetection(detectedAt = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
143793
|
-
const all = this.cache.listMissingFiles(
|
|
144094
|
+
const all = this.cache.listMissingFiles(import_fs25.existsSync);
|
|
143794
144095
|
const missing = all.filter((m2) => !this.ignoredIds.has(m2.id));
|
|
143795
144096
|
if (missing.length === 0) {
|
|
143796
144097
|
if (this._pending) {
|
|
@@ -143894,7 +144195,7 @@ var CacheIntegrityMonitor = class {
|
|
|
143894
144195
|
case "prune_all": {
|
|
143895
144196
|
await this.ensureBackup(pending);
|
|
143896
144197
|
const backupPath = pending.backupPath;
|
|
143897
|
-
const stillMissing = pending.missing.filter((m2) => !(0,
|
|
144198
|
+
const stillMissing = pending.missing.filter((m2) => !(0, import_fs25.existsSync)(m2.filePath)).map((m2) => m2.id);
|
|
143898
144199
|
const pruned = this.cache.dropRowsById(stillMissing);
|
|
143899
144200
|
this.applyDeferredUnlinks();
|
|
143900
144201
|
this.clearPending();
|
|
@@ -143955,7 +144256,7 @@ var CacheIntegrityMonitor = class {
|
|
|
143955
144256
|
};
|
|
143956
144257
|
|
|
143957
144258
|
// src/services/conversations/conversationWatcher.ts
|
|
143958
|
-
var
|
|
144259
|
+
var import_fs26 = require("fs");
|
|
143959
144260
|
var import_promises14 = require("fs/promises");
|
|
143960
144261
|
var ConversationWatcher = class {
|
|
143961
144262
|
files = /* @__PURE__ */ new Map();
|
|
@@ -143981,7 +144282,7 @@ var ConversationWatcher = class {
|
|
|
143981
144282
|
if (this.files.has(key)) return;
|
|
143982
144283
|
let offset;
|
|
143983
144284
|
try {
|
|
143984
|
-
offset = (0,
|
|
144285
|
+
offset = (0, import_fs26.statSync)(filePath).size;
|
|
143985
144286
|
} catch {
|
|
143986
144287
|
offset = 0;
|
|
143987
144288
|
}
|
|
@@ -144163,14 +144464,14 @@ function findSearchTarget(messages, query) {
|
|
|
144163
144464
|
}
|
|
144164
144465
|
|
|
144165
144466
|
// src/services/conversations/pruneAgentConversations.ts
|
|
144166
|
-
var
|
|
144467
|
+
var import_fs27 = require("fs");
|
|
144167
144468
|
function pruneAgentConversations(cache) {
|
|
144168
144469
|
const db = cache.getDatabase();
|
|
144169
144470
|
const rows = db.prepare("SELECT id, file_path FROM conversation_meta").all();
|
|
144170
144471
|
let pruned = 0;
|
|
144171
144472
|
let missing = 0;
|
|
144172
144473
|
for (const row of rows) {
|
|
144173
|
-
if (!(0,
|
|
144474
|
+
if (!(0, import_fs27.existsSync)(row.file_path)) {
|
|
144174
144475
|
missing += 1;
|
|
144175
144476
|
continue;
|
|
144176
144477
|
}
|
|
@@ -144491,22 +144792,22 @@ function refreshConversationCache(deps) {
|
|
|
144491
144792
|
}
|
|
144492
144793
|
|
|
144493
144794
|
// src/services/conversations/shouldRefreshProjectsFromHdd.ts
|
|
144494
|
-
var
|
|
144495
|
-
var
|
|
144795
|
+
var import_fs28 = require("fs");
|
|
144796
|
+
var import_os12 = require("os");
|
|
144496
144797
|
var import_path27 = require("path");
|
|
144497
|
-
var DEFAULT_PROJECTS_DIR = (0, import_path27.join)((0,
|
|
144798
|
+
var DEFAULT_PROJECTS_DIR = (0, import_path27.join)((0, import_os12.homedir)(), ".claude", "projects");
|
|
144498
144799
|
function maxProjectsTreeMtimeMs(projectsDir) {
|
|
144499
144800
|
let maxMs;
|
|
144500
144801
|
try {
|
|
144501
|
-
maxMs = (0,
|
|
144802
|
+
maxMs = (0, import_fs28.statSync)(projectsDir).mtimeMs;
|
|
144502
144803
|
} catch {
|
|
144503
144804
|
return null;
|
|
144504
144805
|
}
|
|
144505
144806
|
try {
|
|
144506
|
-
for (const ent of (0,
|
|
144807
|
+
for (const ent of (0, import_fs28.readdirSync)(projectsDir, { withFileTypes: true })) {
|
|
144507
144808
|
if (!ent.isDirectory()) continue;
|
|
144508
144809
|
try {
|
|
144509
|
-
const childMs = (0,
|
|
144810
|
+
const childMs = (0, import_fs28.statSync)((0, import_path27.join)(projectsDir, ent.name)).mtimeMs;
|
|
144510
144811
|
if (childMs > maxMs) maxMs = childMs;
|
|
144511
144812
|
} catch {
|
|
144512
144813
|
}
|
|
@@ -145275,8 +145576,90 @@ function resolveAnswer(pending, body) {
|
|
|
145275
145576
|
}
|
|
145276
145577
|
}
|
|
145277
145578
|
|
|
145579
|
+
// src/services/search/searchQuery.ts
|
|
145580
|
+
var DEFAULT_SEARCH_LIMIT = 50;
|
|
145581
|
+
var MAX_SEARCH_LIMIT = 200;
|
|
145582
|
+
var MAX_QUERY_LENGTH = 256;
|
|
145583
|
+
var SearchQueryError = class extends Error {
|
|
145584
|
+
constructor(message, code) {
|
|
145585
|
+
super(message);
|
|
145586
|
+
this.code = code;
|
|
145587
|
+
}
|
|
145588
|
+
code;
|
|
145589
|
+
};
|
|
145590
|
+
function intOr(raw2, fallback) {
|
|
145591
|
+
if (raw2 === null) return fallback;
|
|
145592
|
+
const n = Number.parseInt(raw2, 10);
|
|
145593
|
+
return Number.isFinite(n) ? n : fallback;
|
|
145594
|
+
}
|
|
145595
|
+
function parseSearchQuery(params) {
|
|
145596
|
+
const q2 = (params.get("q") ?? "").trim();
|
|
145597
|
+
if (!q2) {
|
|
145598
|
+
throw new SearchQueryError("Missing query parameter: q", "invalid_query");
|
|
145599
|
+
}
|
|
145600
|
+
if (q2.length > MAX_QUERY_LENGTH) {
|
|
145601
|
+
throw new SearchQueryError(`Query exceeds ${MAX_QUERY_LENGTH} characters`, "query_too_long");
|
|
145602
|
+
}
|
|
145603
|
+
const limit = Math.min(
|
|
145604
|
+
Math.max(intOr(params.get("limit"), DEFAULT_SEARCH_LIMIT), 1),
|
|
145605
|
+
MAX_SEARCH_LIMIT
|
|
145606
|
+
);
|
|
145607
|
+
const offset = Math.max(intOr(params.get("offset"), 0), 0);
|
|
145608
|
+
const filters = {};
|
|
145609
|
+
const provider = params.get("provider");
|
|
145610
|
+
if (provider !== null) {
|
|
145611
|
+
if (!isProviderName(provider)) {
|
|
145612
|
+
throw new SearchQueryError(`Unknown provider: ${provider}`, "invalid_filter");
|
|
145613
|
+
}
|
|
145614
|
+
filters.provider = provider;
|
|
145615
|
+
}
|
|
145616
|
+
const projectPath = params.get("projectPath");
|
|
145617
|
+
if (projectPath) filters.projectPath = projectPath;
|
|
145618
|
+
const branch = params.get("branch");
|
|
145619
|
+
if (branch) filters.branch = branch;
|
|
145620
|
+
for (const [key, field] of [
|
|
145621
|
+
["since", "since"],
|
|
145622
|
+
["until", "until"]
|
|
145623
|
+
]) {
|
|
145624
|
+
const raw2 = params.get(key);
|
|
145625
|
+
if (raw2 === null) continue;
|
|
145626
|
+
const ms2 = Date.parse(raw2);
|
|
145627
|
+
if (Number.isNaN(ms2)) {
|
|
145628
|
+
throw new SearchQueryError(`Invalid ${key}: expected an ISO 8601 date`, "invalid_filter");
|
|
145629
|
+
}
|
|
145630
|
+
filters[field] = ms2;
|
|
145631
|
+
}
|
|
145632
|
+
if (filters.since != null && filters.until != null && filters.since > filters.until) {
|
|
145633
|
+
throw new SearchQueryError("`since` must not be after `until`", "invalid_filter");
|
|
145634
|
+
}
|
|
145635
|
+
return { q: q2, limit, offset, filters };
|
|
145636
|
+
}
|
|
145637
|
+
function applyFilters(results, filters) {
|
|
145638
|
+
return results.filter((r) => {
|
|
145639
|
+
if (filters.provider && r.provider !== filters.provider) return false;
|
|
145640
|
+
if (filters.projectPath && r.projectPath !== filters.projectPath) return false;
|
|
145641
|
+
if (filters.branch && r.branch !== filters.branch) return false;
|
|
145642
|
+
if (filters.since != null || filters.until != null) {
|
|
145643
|
+
const ts2 = r.lastActivity == null ? Number.NaN : new Date(r.lastActivity).getTime();
|
|
145644
|
+
if (Number.isNaN(ts2)) return false;
|
|
145645
|
+
if (filters.since != null && ts2 < filters.since) return false;
|
|
145646
|
+
if (filters.until != null && ts2 > filters.until) return false;
|
|
145647
|
+
}
|
|
145648
|
+
return true;
|
|
145649
|
+
});
|
|
145650
|
+
}
|
|
145651
|
+
function paginate(results, offset, limit) {
|
|
145652
|
+
const items = results.slice(offset, offset + limit);
|
|
145653
|
+
return {
|
|
145654
|
+
items,
|
|
145655
|
+
total: results.length,
|
|
145656
|
+
offset,
|
|
145657
|
+
hasMore: offset + items.length < results.length
|
|
145658
|
+
};
|
|
145659
|
+
}
|
|
145660
|
+
|
|
145278
145661
|
// src/services/sessions/conversationBusy.ts
|
|
145279
|
-
var
|
|
145662
|
+
var import_fs29 = require("fs");
|
|
145280
145663
|
var RESUME_BUSY_WINDOW_MS = 12e4;
|
|
145281
145664
|
function resolveResumeBusyWindowMs(env = process.env) {
|
|
145282
145665
|
const raw2 = env.THREADBASE_RESUME_BUSY_WINDOW_MS;
|
|
@@ -145293,7 +145676,7 @@ function conversationBusy(input) {
|
|
|
145293
145676
|
let lastActivityMs = null;
|
|
145294
145677
|
if (input.jsonlPath) {
|
|
145295
145678
|
try {
|
|
145296
|
-
const mtimeMs = (0,
|
|
145679
|
+
const mtimeMs = (0, import_fs29.statSync)(input.jsonlPath).mtimeMs;
|
|
145297
145680
|
const age = now - mtimeMs;
|
|
145298
145681
|
lastActivityMs = Math.max(0, age);
|
|
145299
145682
|
const isSelfEcho = input.selfPtyEndedAt != null && mtimeMs <= input.selfPtyEndedAt + SELF_ACTIVITY_SKEW_MS;
|
|
@@ -146003,6 +146386,8 @@ var DEFAULT_PTY_GRACE_PERIOD_MS = 27e4;
|
|
|
146003
146386
|
var GRACE_MAX_DEFERS = 4;
|
|
146004
146387
|
var IDLE_REAP_AFTER_MS = 6 * 60 * 60 * 1e3;
|
|
146005
146388
|
var IDLE_REAP_SWEEP_MS = 5 * 60 * 1e3;
|
|
146389
|
+
var SEARCH_OVERFETCH = 4;
|
|
146390
|
+
var SEARCH_MAX_SCAN = 1e3;
|
|
146006
146391
|
var RESUME_DISCOVERY_TIMEOUT_MS = 750;
|
|
146007
146392
|
var DISCOVERY_TTL_MS = 15e3;
|
|
146008
146393
|
var ADOPT_KILL_TIMEOUT_MS = 5e3;
|
|
@@ -146243,7 +146628,7 @@ var StreamerServer = class {
|
|
|
146243
146628
|
this.skipStartupWarmup = config2.skipStartupWarmup ?? false;
|
|
146244
146629
|
this.scannerPersistenceDisabled = config2.scannerPersistent === false;
|
|
146245
146630
|
this.scanProfiles = config2.scanProfiles;
|
|
146246
|
-
this.codexRoots = config2.codexRoots ?? [(0, import_path29.join)((0,
|
|
146631
|
+
this.codexRoots = config2.codexRoots ?? [(0, import_path29.join)((0, import_os13.homedir)(), ".codex", "sessions")];
|
|
146247
146632
|
this.ptyGracePeriodMs = config2.ptyGracePeriodMs ?? DEFAULT_PTY_GRACE_PERIOD_MS;
|
|
146248
146633
|
this.defaultSystemPrompt = config2.defaultSystemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
146249
146634
|
this.featureFlags = resolveFeatureFlags({ cli: config2.featureFlags, yaml: loadFeatureFlags() });
|
|
@@ -146257,7 +146642,7 @@ var StreamerServer = class {
|
|
|
146257
146642
|
this.claudeFlagsPersistable = config2.claudeFlags === void 0;
|
|
146258
146643
|
this.claudeFlags = config2.claudeFlags ?? loadClaudeFlags();
|
|
146259
146644
|
this.claudeExtraArgs = config2.claudeExtraArgs ?? loadClaudeExtraArgs();
|
|
146260
|
-
this.cacheDir = config2.cacheDir ?? loadCacheDir() ?? (0, import_path29.join)((0,
|
|
146645
|
+
this.cacheDir = config2.cacheDir ?? loadCacheDir() ?? (0, import_path29.join)((0, import_os13.homedir)(), ".threadbase", "cache");
|
|
146261
146646
|
this.tailSize = config2.tailSize ?? loadTailSize() ?? 10;
|
|
146262
146647
|
this.directoryDebounceMs = parseDirScanDebounceEnv(process.env.THREADBASE_DIR_SCAN_DEBOUNCE_MS) ?? config2.directoryScanDebounceMs ?? 1e3;
|
|
146263
146648
|
this.markScannerStaleDebounced = debounce(() => {
|
|
@@ -146308,7 +146693,7 @@ var StreamerServer = class {
|
|
|
146308
146693
|
const seqs = cache.extendMessageIndex(
|
|
146309
146694
|
filePath,
|
|
146310
146695
|
spans,
|
|
146311
|
-
(0,
|
|
146696
|
+
(0, import_fs30.statSync)(filePath),
|
|
146312
146697
|
readFrom,
|
|
146313
146698
|
endOffset
|
|
146314
146699
|
);
|
|
@@ -146771,14 +147156,14 @@ var StreamerServer = class {
|
|
|
146771
147156
|
}
|
|
146772
147157
|
this.apnsClient = new ApnsClient(creds);
|
|
146773
147158
|
const sender = new LiveActivitySender(this.apnsClient, pushRepo);
|
|
146774
|
-
const serverId = process.env.THREADBASE_INSTANCE_ID ?? (0,
|
|
146775
|
-
this.liveActivityNotifier = new LiveActivityNotifier(sender, serverId, (0,
|
|
147159
|
+
const serverId = process.env.THREADBASE_INSTANCE_ID ?? (0, import_os13.hostname)();
|
|
147160
|
+
this.liveActivityNotifier = new LiveActivityNotifier(sender, serverId, (0, import_os13.hostname)());
|
|
146776
147161
|
this.liveActivityRenewal = new LiveActivityRenewalScheduler({
|
|
146777
147162
|
repo: pushRepo,
|
|
146778
147163
|
sender,
|
|
146779
147164
|
sessionStore: this.sessionStore,
|
|
146780
147165
|
serverId,
|
|
146781
|
-
serverLabel: (0,
|
|
147166
|
+
serverLabel: (0, import_os13.hostname)()
|
|
146782
147167
|
});
|
|
146783
147168
|
this.liveActivityRenewal.start();
|
|
146784
147169
|
this.log.info("Live Activity push enabled", {
|
|
@@ -147117,7 +147502,7 @@ var StreamerServer = class {
|
|
|
147117
147502
|
this.fileWatcher.watchDirectory(dir);
|
|
147118
147503
|
}
|
|
147119
147504
|
for (const dir of this.codexRoots) {
|
|
147120
|
-
if (!(0,
|
|
147505
|
+
if (!(0, import_fs30.existsSync)(dir)) continue;
|
|
147121
147506
|
this.fileWatcher.watchDirectory(dir);
|
|
147122
147507
|
}
|
|
147123
147508
|
} catch (err) {
|
|
@@ -147390,7 +147775,7 @@ var StreamerServer = class {
|
|
|
147390
147775
|
}
|
|
147391
147776
|
let body;
|
|
147392
147777
|
try {
|
|
147393
|
-
body = await
|
|
147778
|
+
body = await readBody2(req);
|
|
147394
147779
|
} catch (err) {
|
|
147395
147780
|
const message = err instanceof Error ? err.message : "Invalid body";
|
|
147396
147781
|
json2(res, 400, { error: message });
|
|
@@ -147436,7 +147821,7 @@ var StreamerServer = class {
|
|
|
147436
147821
|
nonce: sealed.nonce,
|
|
147437
147822
|
ephemeralPublicKey: sealed.ephemeralPublicKey,
|
|
147438
147823
|
publicUrl: this.publicUrl,
|
|
147439
|
-
machineName: (0,
|
|
147824
|
+
machineName: (0, import_os13.hostname)(),
|
|
147440
147825
|
...device && {
|
|
147441
147826
|
deviceId: device.deviceId,
|
|
147442
147827
|
deviceToken: device.deviceToken,
|
|
@@ -147564,7 +147949,7 @@ var StreamerServer = class {
|
|
|
147564
147949
|
if (this.scanProfiles && this.scanProfiles.length > 0) {
|
|
147565
147950
|
return this.scanProfiles.filter((p2) => p2.enabled).map((p2) => (0, import_path29.join)(p2.configDir, "projects"));
|
|
147566
147951
|
}
|
|
147567
|
-
return [(0, import_path29.join)((0,
|
|
147952
|
+
return [(0, import_path29.join)((0, import_os13.homedir)(), ".claude", "projects")];
|
|
147568
147953
|
}
|
|
147569
147954
|
/**
|
|
147570
147955
|
* Full-glob scan + cache upsert/delete reconcile. Used by ?refresh=1 and by
|
|
@@ -147966,20 +148351,20 @@ var StreamerServer = class {
|
|
|
147966
148351
|
if (this.scanProfiles && this.scanProfiles.length > 0) {
|
|
147967
148352
|
return this.scanProfiles.filter((p2) => p2.enabled).map((p2) => (0, import_path29.join)(p2.configDir, "projects"));
|
|
147968
148353
|
}
|
|
147969
|
-
return [(0, import_path29.join)((0,
|
|
148354
|
+
return [(0, import_path29.join)((0, import_os13.homedir)(), ".claude", "projects")];
|
|
147970
148355
|
}
|
|
147971
148356
|
findJsonlPath(uuid3) {
|
|
147972
148357
|
const filename = `${uuid3}.jsonl`;
|
|
147973
148358
|
for (const projectsDir of this.projectsDirs()) {
|
|
147974
|
-
if (!(0,
|
|
147975
|
-
for (const dir of (0,
|
|
148359
|
+
if (!(0, import_fs30.existsSync)(projectsDir)) continue;
|
|
148360
|
+
for (const dir of (0, import_fs30.readdirSync)(projectsDir)) {
|
|
147976
148361
|
const fp = (0, import_path29.join)(projectsDir, dir, filename);
|
|
147977
|
-
if ((0,
|
|
148362
|
+
if ((0, import_fs30.existsSync)(fp)) return fp;
|
|
147978
148363
|
const projectDir = (0, import_path29.join)(projectsDir, dir);
|
|
147979
148364
|
try {
|
|
147980
|
-
for (const sub of (0,
|
|
148365
|
+
for (const sub of (0, import_fs30.readdirSync)(projectDir)) {
|
|
147981
148366
|
const subagentPath = (0, import_path29.join)(projectDir, sub, "subagents", filename);
|
|
147982
|
-
if ((0,
|
|
148367
|
+
if ((0, import_fs30.existsSync)(subagentPath)) return subagentPath;
|
|
147983
148368
|
}
|
|
147984
148369
|
} catch {
|
|
147985
148370
|
}
|
|
@@ -147989,7 +148374,7 @@ var StreamerServer = class {
|
|
|
147989
148374
|
}
|
|
147990
148375
|
async readCwdFromJsonl(filePath) {
|
|
147991
148376
|
return new Promise((resolve4) => {
|
|
147992
|
-
const rl = (0, import_readline4.createInterface)({ input: (0,
|
|
148377
|
+
const rl = (0, import_readline4.createInterface)({ input: (0, import_fs30.createReadStream)(filePath), crlfDelay: Infinity });
|
|
147993
148378
|
let found = false;
|
|
147994
148379
|
rl.on("line", (line) => {
|
|
147995
148380
|
if (found) return;
|
|
@@ -148079,7 +148464,7 @@ var StreamerServer = class {
|
|
|
148079
148464
|
if (this.isManagedTailPath(key)) return;
|
|
148080
148465
|
let mtimeMs;
|
|
148081
148466
|
try {
|
|
148082
|
-
mtimeMs = (0,
|
|
148467
|
+
mtimeMs = (0, import_fs30.statSync)(filePath).mtimeMs;
|
|
148083
148468
|
} catch {
|
|
148084
148469
|
return;
|
|
148085
148470
|
}
|
|
@@ -148261,7 +148646,7 @@ var StreamerServer = class {
|
|
|
148261
148646
|
if (!conv.filePath) return false;
|
|
148262
148647
|
let mtimeMs = null;
|
|
148263
148648
|
try {
|
|
148264
|
-
mtimeMs = (0,
|
|
148649
|
+
mtimeMs = (0, import_fs30.statSync)(conv.filePath).mtimeMs;
|
|
148265
148650
|
} catch {
|
|
148266
148651
|
return false;
|
|
148267
148652
|
}
|
|
@@ -148516,7 +148901,7 @@ var StreamerServer = class {
|
|
|
148516
148901
|
}
|
|
148517
148902
|
let body;
|
|
148518
148903
|
try {
|
|
148519
|
-
body = await
|
|
148904
|
+
body = await readBody2(req);
|
|
148520
148905
|
} catch {
|
|
148521
148906
|
res.setHeader("Accept-Query", "application/json");
|
|
148522
148907
|
json2(res, 422, { error: "Malformed JSON body", code: "invalid_query" });
|
|
@@ -148554,17 +148939,27 @@ var StreamerServer = class {
|
|
|
148554
148939
|
});
|
|
148555
148940
|
}
|
|
148556
148941
|
async handleSearch(url2, res) {
|
|
148557
|
-
|
|
148558
|
-
|
|
148559
|
-
|
|
148560
|
-
|
|
148942
|
+
let parsed;
|
|
148943
|
+
try {
|
|
148944
|
+
parsed = parseSearchQuery(url2.searchParams);
|
|
148945
|
+
} catch (err) {
|
|
148946
|
+
if (err instanceof SearchQueryError) {
|
|
148947
|
+
json2(res, 400, { error: err.message, code: err.code });
|
|
148948
|
+
return;
|
|
148949
|
+
}
|
|
148950
|
+
throw err;
|
|
148561
148951
|
}
|
|
148562
|
-
const
|
|
148952
|
+
const { q: q2, limit, offset, filters } = parsed;
|
|
148953
|
+
const startedAt = Date.now();
|
|
148563
148954
|
const scanner = await this.getScanner();
|
|
148564
148955
|
const results = await search(
|
|
148565
148956
|
q2,
|
|
148566
148957
|
{
|
|
148567
|
-
|
|
148958
|
+
// Fetch beyond the requested page: filters below are applied AFTER the
|
|
148959
|
+
// scanner returns, so slicing at `limit` here would drop results that a
|
|
148960
|
+
// later page should contain. Bounded so a broad query cannot pull an
|
|
148961
|
+
// unbounded set into memory.
|
|
148962
|
+
limit: Math.min(offset + limit * SEARCH_OVERFETCH, SEARCH_MAX_SCAN),
|
|
148568
148963
|
include: "conversations",
|
|
148569
148964
|
...this.scanProfiles ? { profiles: this.scanProfiles } : {},
|
|
148570
148965
|
...this.codexScanOpts()
|
|
@@ -148588,13 +148983,24 @@ var StreamerServer = class {
|
|
|
148588
148983
|
lastActivity: r.meta.timestamp,
|
|
148589
148984
|
firstMessage: r.meta.firstMessage ?? void 0,
|
|
148590
148985
|
lastMessage: r.meta.lastMessage ?? void 0,
|
|
148591
|
-
provider: r.meta.provider ?? CLAUDE_CODE_PROVIDER2
|
|
148986
|
+
provider: r.meta.provider ?? CLAUDE_CODE_PROVIDER2,
|
|
148987
|
+
// The scanner already computes relevance and match snippets; the previous
|
|
148988
|
+
// adapter discarded both, so results arrived in an unexplained order with
|
|
148989
|
+
// no indication of WHY anything matched.
|
|
148990
|
+
score: r.score,
|
|
148991
|
+
matches: Array.isArray(r.matches) ? r.matches.map((m2) => ({
|
|
148992
|
+
field: m2.field,
|
|
148993
|
+
snippet: m2.snippet
|
|
148994
|
+
})) : []
|
|
148592
148995
|
}));
|
|
148996
|
+
const page = paginate(applyFilters(adapted, filters), offset, limit);
|
|
148593
148997
|
json2(res, 200, {
|
|
148594
|
-
conversations:
|
|
148595
|
-
hasMore:
|
|
148596
|
-
offset:
|
|
148597
|
-
total:
|
|
148998
|
+
conversations: page.items,
|
|
148999
|
+
hasMore: page.hasMore,
|
|
149000
|
+
offset: page.offset,
|
|
149001
|
+
total: page.total,
|
|
149002
|
+
// Query timing, so a slow search is diagnosable rather than merely felt.
|
|
149003
|
+
tookMs: Date.now() - startedAt
|
|
148598
149004
|
});
|
|
148599
149005
|
}
|
|
148600
149006
|
async handleListSessions(url2, res) {
|
|
@@ -148640,7 +149046,7 @@ var StreamerServer = class {
|
|
|
148640
149046
|
if (this.rejectIfWarmingUp(res)) return;
|
|
148641
149047
|
const session = this.sessionStore.get(sessionId, this.ptyAttachedIds());
|
|
148642
149048
|
if (session) {
|
|
148643
|
-
if (!(0,
|
|
149049
|
+
if (!(0, import_fs30.existsSync)(session.projectPath)) {
|
|
148644
149050
|
session.failureReason = `Project directory not found: ${session.projectPath}`;
|
|
148645
149051
|
}
|
|
148646
149052
|
const reconciled = this.withReconciledLifecycle([session])[0];
|
|
@@ -148667,7 +149073,7 @@ var StreamerServer = class {
|
|
|
148667
149073
|
json2(res, 404, { error: "Session not found" });
|
|
148668
149074
|
}
|
|
148669
149075
|
async handleResume(req, res) {
|
|
148670
|
-
const body = await
|
|
149076
|
+
const body = await readBody2(req);
|
|
148671
149077
|
const sessionId = body.sessionId ?? body.conversationId;
|
|
148672
149078
|
if (!sessionId) {
|
|
148673
149079
|
json2(res, 400, { error: "Missing sessionId" });
|
|
@@ -148799,7 +149205,7 @@ var StreamerServer = class {
|
|
|
148799
149205
|
return;
|
|
148800
149206
|
}
|
|
148801
149207
|
if (this.agentConfig.enabled) {
|
|
148802
|
-
const body2 = await
|
|
149208
|
+
const body2 = await readBody2(req);
|
|
148803
149209
|
const cache = this.cache;
|
|
148804
149210
|
if (!cache) {
|
|
148805
149211
|
json2(res, 503, {
|
|
@@ -148818,7 +149224,7 @@ var StreamerServer = class {
|
|
|
148818
149224
|
json2(res, result.status, result.body);
|
|
148819
149225
|
return;
|
|
148820
149226
|
}
|
|
148821
|
-
const body = await
|
|
149227
|
+
const body = await readBody2(req);
|
|
148822
149228
|
const { input, keys } = body;
|
|
148823
149229
|
let idempotencyKey;
|
|
148824
149230
|
try {
|
|
@@ -148982,7 +149388,7 @@ var StreamerServer = class {
|
|
|
148982
149388
|
});
|
|
148983
149389
|
}
|
|
148984
149390
|
async handleSendAnswer(sessionId, req, res) {
|
|
148985
|
-
const body = await
|
|
149391
|
+
const body = await readBody2(req);
|
|
148986
149392
|
const pending = this.pendingQuestions.get(sessionId);
|
|
148987
149393
|
const resolution = resolveAnswer(pending, body);
|
|
148988
149394
|
if (!resolution.ok) {
|
|
@@ -149011,7 +149417,7 @@ var StreamerServer = class {
|
|
|
149011
149417
|
json2(res, 400, { error: "Session has no project path" });
|
|
149012
149418
|
return;
|
|
149013
149419
|
}
|
|
149014
|
-
const body = await
|
|
149420
|
+
const body = await readBody2(req);
|
|
149015
149421
|
const { filename, mimeType, dataBase64 } = body ?? {};
|
|
149016
149422
|
if (typeof filename !== "string" || typeof mimeType !== "string" || typeof dataBase64 !== "string") {
|
|
149017
149423
|
json2(res, 400, { error: "Missing filename, mimeType, or dataBase64" });
|
|
@@ -149213,7 +149619,7 @@ var StreamerServer = class {
|
|
|
149213
149619
|
return;
|
|
149214
149620
|
}
|
|
149215
149621
|
if (this.agentConfig.enabled) {
|
|
149216
|
-
const body2 = await
|
|
149622
|
+
const body2 = await readBody2(req);
|
|
149217
149623
|
const result = await handleStartAgentSession(body2, {
|
|
149218
149624
|
sessionStore: this.sessionStore,
|
|
149219
149625
|
// biome-ignore lint/style/noNonNullAssertion: agentClient is set when agentConfig.enabled is true
|
|
@@ -149227,7 +149633,7 @@ var StreamerServer = class {
|
|
|
149227
149633
|
}
|
|
149228
149634
|
return;
|
|
149229
149635
|
}
|
|
149230
|
-
const body = await
|
|
149636
|
+
const body = await readBody2(req);
|
|
149231
149637
|
const { path: relativePath, provider: requestedProvider, systemPrompt: clientPrompt } = body;
|
|
149232
149638
|
if (requestedProvider !== void 0 && !isProviderName(requestedProvider)) {
|
|
149233
149639
|
json2(res, 400, { error: "Invalid provider" });
|
|
@@ -149364,7 +149770,7 @@ var StreamerServer = class {
|
|
|
149364
149770
|
// file isn't slurped in full.
|
|
149365
149771
|
readFirstLineSessionId(filePath) {
|
|
149366
149772
|
try {
|
|
149367
|
-
const content = (0,
|
|
149773
|
+
const content = (0, import_fs30.readFileSync)(filePath, "utf8");
|
|
149368
149774
|
const nl = content.indexOf("\n");
|
|
149369
149775
|
const firstLine = nl === -1 ? content : content.slice(0, nl);
|
|
149370
149776
|
if (!firstLine.trim()) return null;
|
|
@@ -149379,7 +149785,7 @@ var StreamerServer = class {
|
|
|
149379
149785
|
// was passed to Claude via --session-id so the filename matches from the start.
|
|
149380
149786
|
watchForJsonl(sessionId, projectPath) {
|
|
149381
149787
|
const encoded = projectPath.replace(/[/\\:.]/g, "-");
|
|
149382
|
-
const projectsDir = (0, import_path29.join)((0,
|
|
149788
|
+
const projectsDir = (0, import_path29.join)((0, import_os13.homedir)(), ".claude", "projects", encoded);
|
|
149383
149789
|
const expectedFile = `${sessionId}.jsonl`;
|
|
149384
149790
|
const filePath = (0, import_path29.join)(projectsDir, expectedFile);
|
|
149385
149791
|
const deadline = Date.now() + 12e4;
|
|
@@ -149399,11 +149805,11 @@ var StreamerServer = class {
|
|
|
149399
149805
|
cleanup();
|
|
149400
149806
|
return;
|
|
149401
149807
|
}
|
|
149402
|
-
let resolvedFilePath = (0,
|
|
149403
|
-
if (!resolvedFilePath && (0,
|
|
149808
|
+
let resolvedFilePath = (0, import_fs30.existsSync)(filePath) ? filePath : null;
|
|
149809
|
+
if (!resolvedFilePath && (0, import_fs30.existsSync)(projectsDir)) {
|
|
149404
149810
|
try {
|
|
149405
149811
|
const now = Date.now();
|
|
149406
|
-
const match2 = (0,
|
|
149812
|
+
const match2 = (0, import_fs30.readdirSync)(projectsDir).filter((f2) => f2.endsWith(".jsonl")).map((f2) => ({ f: f2, mtime: (0, import_fs30.statSync)((0, import_path29.join)(projectsDir, f2)).mtimeMs })).filter(({ mtime }) => now - mtime < 5e3).filter(
|
|
149407
149813
|
({ f: f2 }) => (0, import_path29.basename)(f2, ".jsonl") === sessionId || this.readFirstLineSessionId((0, import_path29.join)(projectsDir, f2)) === sessionId
|
|
149408
149814
|
).sort((a, b2) => b2.mtime - a.mtime)[0];
|
|
149409
149815
|
if (match2) resolvedFilePath = (0, import_path29.join)(projectsDir, match2.f);
|
|
@@ -149414,7 +149820,7 @@ var StreamerServer = class {
|
|
|
149414
149820
|
cleanup();
|
|
149415
149821
|
this.sessionFileMap.set(sessionId, resolvedFilePath);
|
|
149416
149822
|
try {
|
|
149417
|
-
const existing = (0,
|
|
149823
|
+
const existing = (0, import_fs30.readFileSync)(resolvedFilePath, "utf8").split("\n").filter(Boolean);
|
|
149418
149824
|
if (existing.length > 0) {
|
|
149419
149825
|
this.broadcastConversationLines(sessionId, existing);
|
|
149420
149826
|
}
|
|
@@ -149438,7 +149844,7 @@ var StreamerServer = class {
|
|
|
149438
149844
|
if (this.sessionFileMap.has(sessionId)) return;
|
|
149439
149845
|
try {
|
|
149440
149846
|
require("fs").mkdirSync(projectsDir, { recursive: true });
|
|
149441
|
-
watcher = (0,
|
|
149847
|
+
watcher = (0, import_fs30.watch)(projectsDir, tryWire);
|
|
149442
149848
|
watcher.on("error", cleanup);
|
|
149443
149849
|
} catch {
|
|
149444
149850
|
}
|
|
@@ -149467,7 +149873,7 @@ var StreamerServer = class {
|
|
|
149467
149873
|
};
|
|
149468
149874
|
const matchesProjectPath = (candidatePath) => {
|
|
149469
149875
|
try {
|
|
149470
|
-
const firstLine = (0,
|
|
149876
|
+
const firstLine = (0, import_fs30.readFileSync)(candidatePath, "utf8").split("\n", 1)[0];
|
|
149471
149877
|
if (!firstLine) return null;
|
|
149472
149878
|
const parsed = JSON.parse(firstLine);
|
|
149473
149879
|
if (parsed?.type !== "session_meta") return null;
|
|
@@ -149496,15 +149902,15 @@ var StreamerServer = class {
|
|
|
149496
149902
|
);
|
|
149497
149903
|
for (const root of this.codexRoots) {
|
|
149498
149904
|
const sessionsDir = (0, import_path29.join)(root, dateDir);
|
|
149499
|
-
if (!(0,
|
|
149905
|
+
if (!(0, import_fs30.existsSync)(sessionsDir)) continue;
|
|
149500
149906
|
let candidateFiles;
|
|
149501
149907
|
try {
|
|
149502
|
-
candidateFiles = (0,
|
|
149908
|
+
candidateFiles = (0, import_fs30.readdirSync)(sessionsDir).filter((f2) => f2.endsWith(".jsonl"));
|
|
149503
149909
|
} catch {
|
|
149504
149910
|
continue;
|
|
149505
149911
|
}
|
|
149506
149912
|
const nowMs = Date.now();
|
|
149507
|
-
const recentCandidates = candidateFiles.map((f2) => ({ f: f2, mtime: (0,
|
|
149913
|
+
const recentCandidates = candidateFiles.map((f2) => ({ f: f2, mtime: (0, import_fs30.statSync)((0, import_path29.join)(sessionsDir, f2)).mtimeMs })).filter(({ mtime }) => nowMs - mtime < 1e4).sort((a, b2) => b2.mtime - a.mtime);
|
|
149508
149914
|
for (const { f: f2 } of recentCandidates) {
|
|
149509
149915
|
const candidatePath = (0, import_path29.join)(sessionsDir, f2);
|
|
149510
149916
|
const match2 = matchesProjectPath(candidatePath);
|
|
@@ -149516,7 +149922,7 @@ var StreamerServer = class {
|
|
|
149516
149922
|
this.sessionFileMap.set(sessionId, candidatePath);
|
|
149517
149923
|
this.fileWatcher.watch(candidatePath);
|
|
149518
149924
|
try {
|
|
149519
|
-
const existing = (0,
|
|
149925
|
+
const existing = (0, import_fs30.readFileSync)(candidatePath, "utf8").split("\n").filter(Boolean);
|
|
149520
149926
|
if (existing.length > 0) {
|
|
149521
149927
|
this.broadcastConversationLines(sessionId, existing);
|
|
149522
149928
|
}
|
|
@@ -149585,7 +149991,7 @@ var StreamerServer = class {
|
|
|
149585
149991
|
});
|
|
149586
149992
|
return;
|
|
149587
149993
|
}
|
|
149588
|
-
const body = await
|
|
149994
|
+
const body = await readBody2(req);
|
|
149589
149995
|
const { path: relativePath, name } = body;
|
|
149590
149996
|
if (!name || typeof name !== "string") {
|
|
149591
149997
|
json2(res, 400, { error: "Missing name field" });
|
|
@@ -149615,7 +150021,7 @@ var StreamerServer = class {
|
|
|
149615
150021
|
}
|
|
149616
150022
|
let parsed;
|
|
149617
150023
|
try {
|
|
149618
|
-
parsed = await
|
|
150024
|
+
parsed = await readBody2(req);
|
|
149619
150025
|
} catch {
|
|
149620
150026
|
json2(res, 400, { error: "Invalid JSON" });
|
|
149621
150027
|
return;
|
|
@@ -149672,7 +150078,7 @@ var StreamerServer = class {
|
|
|
149672
150078
|
}
|
|
149673
150079
|
let parsed;
|
|
149674
150080
|
try {
|
|
149675
|
-
parsed = await
|
|
150081
|
+
parsed = await readBody2(req);
|
|
149676
150082
|
} catch {
|
|
149677
150083
|
json2(res, 400, { error: "Invalid JSON" });
|
|
149678
150084
|
return;
|
|
@@ -149731,7 +150137,7 @@ async function waitForProcessExit(pid, timeoutMs, pollMs = ADOPT_KILL_POLL_MS) {
|
|
|
149731
150137
|
}
|
|
149732
150138
|
function classifyResumability(cwd) {
|
|
149733
150139
|
if (!cwd) return { resumable: true };
|
|
149734
|
-
if ((0,
|
|
150140
|
+
if ((0, import_fs30.existsSync)(cwd)) return { resumable: true };
|
|
149735
150141
|
const ranInWorktree = /\/\.worktrees\//.test(cwd) || /\/\.claude\/worktrees\//.test(cwd);
|
|
149736
150142
|
return {
|
|
149737
150143
|
resumable: false,
|
|
@@ -149849,7 +150255,7 @@ function parseSessionListQuery(url2) {
|
|
|
149849
150255
|
const cursor = url2.searchParams.get("cursor") ?? void 0;
|
|
149850
150256
|
return { query: { limit, sortBy, order, status, cursor } };
|
|
149851
150257
|
}
|
|
149852
|
-
function
|
|
150258
|
+
function readBody2(req) {
|
|
149853
150259
|
return new Promise((resolve4, reject) => {
|
|
149854
150260
|
const chunks = [];
|
|
149855
150261
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
@@ -150401,7 +150807,7 @@ var import_node_fs18 = require("fs");
|
|
|
150401
150807
|
|
|
150402
150808
|
// node_modules/tar/dist/esm/index.min.js
|
|
150403
150809
|
var import_events3 = __toESM(require("events"), 1);
|
|
150404
|
-
var
|
|
150810
|
+
var import_fs31 = __toESM(require("fs"), 1);
|
|
150405
150811
|
var import_node_events3 = require("events");
|
|
150406
150812
|
var import_node_stream2 = __toESM(require("stream"), 1);
|
|
150407
150813
|
var import_node_string_decoder = require("string_decoder");
|
|
@@ -150415,8 +150821,8 @@ var Ps = __toESM(require("zlib"), 1);
|
|
|
150415
150821
|
var import_zlib = __toESM(require("zlib"), 1);
|
|
150416
150822
|
var import_node_path15 = require("path");
|
|
150417
150823
|
var import_node_path16 = require("path");
|
|
150418
|
-
var import_fs31 = __toESM(require("fs"), 1);
|
|
150419
150824
|
var import_fs32 = __toESM(require("fs"), 1);
|
|
150825
|
+
var import_fs33 = __toESM(require("fs"), 1);
|
|
150420
150826
|
var import_path31 = __toESM(require("path"), 1);
|
|
150421
150827
|
var import_node_path17 = require("path");
|
|
150422
150828
|
var import_path32 = __toESM(require("path"), 1);
|
|
@@ -150425,7 +150831,7 @@ var import_node_assert = __toESM(require("assert"), 1);
|
|
|
150425
150831
|
var import_node_crypto6 = require("crypto");
|
|
150426
150832
|
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
150427
150833
|
var import_node_path18 = __toESM(require("path"), 1);
|
|
150428
|
-
var
|
|
150834
|
+
var import_fs34 = __toESM(require("fs"), 1);
|
|
150429
150835
|
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
150430
150836
|
var import_node_path19 = __toESM(require("path"), 1);
|
|
150431
150837
|
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
@@ -150777,7 +151183,7 @@ var A = class extends import_node_events3.EventEmitter {
|
|
|
150777
151183
|
return Wr;
|
|
150778
151184
|
}
|
|
150779
151185
|
};
|
|
150780
|
-
var Jr =
|
|
151186
|
+
var Jr = import_fs31.default.writev;
|
|
150781
151187
|
var ht = /* @__PURE__ */ Symbol("_autoClose");
|
|
150782
151188
|
var H2 = /* @__PURE__ */ Symbol("_close");
|
|
150783
151189
|
var te = /* @__PURE__ */ Symbol("_ended");
|
|
@@ -150832,7 +151238,7 @@ var _t = class extends A {
|
|
|
150832
151238
|
throw new TypeError("this is a readable stream");
|
|
150833
151239
|
}
|
|
150834
151240
|
[at]() {
|
|
150835
|
-
|
|
151241
|
+
import_fs31.default.open(this[U], "r", (t, e) => this[Ht](t, e));
|
|
150836
151242
|
}
|
|
150837
151243
|
[Ht](t, e) {
|
|
150838
151244
|
t ? this[Ut](t) : (this[u] = e, this.emit("open", e), this[zt]());
|
|
@@ -150845,7 +151251,7 @@ var _t = class extends A {
|
|
|
150845
151251
|
this[j] = true;
|
|
150846
151252
|
let t = this[vi]();
|
|
150847
151253
|
if (t.length === 0) return process.nextTick(() => this[Ii](null, 0, t));
|
|
150848
|
-
|
|
151254
|
+
import_fs31.default.read(this[u], t, 0, t.length, null, (e, i, r) => this[Ii](e, i, r));
|
|
150849
151255
|
}
|
|
150850
151256
|
}
|
|
150851
151257
|
[Ii](t, e, i) {
|
|
@@ -150854,7 +151260,7 @@ var _t = class extends A {
|
|
|
150854
151260
|
[H2]() {
|
|
150855
151261
|
if (this[ht] && typeof this[u] == "number") {
|
|
150856
151262
|
let t = this[u];
|
|
150857
|
-
this[u] = void 0,
|
|
151263
|
+
this[u] = void 0, import_fs31.default.close(t, (e) => e ? this.emit("error", e) : this.emit("close"));
|
|
150858
151264
|
}
|
|
150859
151265
|
}
|
|
150860
151266
|
[Ut](t) {
|
|
@@ -150882,7 +151288,7 @@ var Be = class extends _t {
|
|
|
150882
151288
|
[at]() {
|
|
150883
151289
|
let t = true;
|
|
150884
151290
|
try {
|
|
150885
|
-
this[Ht](null,
|
|
151291
|
+
this[Ht](null, import_fs31.default.openSync(this[U], "r")), t = false;
|
|
150886
151292
|
} finally {
|
|
150887
151293
|
t && this[H2]();
|
|
150888
151294
|
}
|
|
@@ -150893,7 +151299,7 @@ var Be = class extends _t {
|
|
|
150893
151299
|
if (!this[j]) {
|
|
150894
151300
|
this[j] = true;
|
|
150895
151301
|
do {
|
|
150896
|
-
let e = this[vi](), i = e.length === 0 ? 0 :
|
|
151302
|
+
let e = this[vi](), i = e.length === 0 ? 0 : import_fs31.default.readSync(this[u], e, 0, e.length, null);
|
|
150897
151303
|
if (!this[ki](i, e)) break;
|
|
150898
151304
|
} while (true);
|
|
150899
151305
|
this[j] = false;
|
|
@@ -150906,7 +151312,7 @@ var Be = class extends _t {
|
|
|
150906
151312
|
[H2]() {
|
|
150907
151313
|
if (this[ht] && typeof this[u] == "number") {
|
|
150908
151314
|
let t = this[u];
|
|
150909
|
-
this[u] = void 0,
|
|
151315
|
+
this[u] = void 0, import_fs31.default.closeSync(t), this.emit("close");
|
|
150910
151316
|
}
|
|
150911
151317
|
}
|
|
150912
151318
|
};
|
|
@@ -150948,7 +151354,7 @@ var et = class extends import_events3.default {
|
|
|
150948
151354
|
this[H2](), this[gt] = true, this.emit("error", t);
|
|
150949
151355
|
}
|
|
150950
151356
|
[at]() {
|
|
150951
|
-
|
|
151357
|
+
import_fs31.default.open(this[U], this[tt], this[ie], (t, e) => this[Ht](t, e));
|
|
150952
151358
|
}
|
|
150953
151359
|
[Ht](t, e) {
|
|
150954
151360
|
this[Me] && this[tt] === "r+" && t && t.code === "ENOENT" ? (this[tt] = "w", this[at]()) : t ? this[Ut](t) : (this[u] = e, this.emit("open", e), this[gt] || this[Ai]());
|
|
@@ -150960,7 +151366,7 @@ var et = class extends import_events3.default {
|
|
|
150960
151366
|
return typeof t == "string" && (t = Buffer.from(t, e)), this[te] ? (this.emit("error", new Error("write() after end()")), false) : this[u] === void 0 || this[gt] || this[Y2].length ? (this[Y2].push(t), this[ke] = true, false) : (this[gt] = true, this[ve](t), true);
|
|
150961
151367
|
}
|
|
150962
151368
|
[ve](t) {
|
|
150963
|
-
|
|
151369
|
+
import_fs31.default.write(this[u], t, 0, t.length, this[ot], (e, i) => this[Pt](e, i));
|
|
150964
151370
|
}
|
|
150965
151371
|
[Pt](t, e) {
|
|
150966
151372
|
t ? this[Ut](t) : (this[ot] !== void 0 && typeof e == "number" && (this[ot] += e), this[Y2].length ? this[Ai]() : (this[gt] = false, this[te] && !this[Ni] ? (this[Ni] = true, this[H2](), this.emit("finish")) : this[ke] && (this[ke] = false, this.emit("drain"))));
|
|
@@ -150976,7 +151382,7 @@ var et = class extends import_events3.default {
|
|
|
150976
151382
|
[H2]() {
|
|
150977
151383
|
if (this[ht] && typeof this[u] == "number") {
|
|
150978
151384
|
let t = this[u];
|
|
150979
|
-
this[u] = void 0,
|
|
151385
|
+
this[u] = void 0, import_fs31.default.close(t, (e) => e ? this.emit("error", e) : this.emit("close"));
|
|
150980
151386
|
}
|
|
150981
151387
|
}
|
|
150982
151388
|
};
|
|
@@ -150984,24 +151390,24 @@ var Wt = class extends et {
|
|
|
150984
151390
|
[at]() {
|
|
150985
151391
|
let t;
|
|
150986
151392
|
if (this[Me] && this[tt] === "r+") try {
|
|
150987
|
-
t =
|
|
151393
|
+
t = import_fs31.default.openSync(this[U], this[tt], this[ie]);
|
|
150988
151394
|
} catch (e) {
|
|
150989
151395
|
if (e?.code === "ENOENT") return this[tt] = "w", this[at]();
|
|
150990
151396
|
throw e;
|
|
150991
151397
|
}
|
|
150992
|
-
else t =
|
|
151398
|
+
else t = import_fs31.default.openSync(this[U], this[tt], this[ie]);
|
|
150993
151399
|
this[Ht](null, t);
|
|
150994
151400
|
}
|
|
150995
151401
|
[H2]() {
|
|
150996
151402
|
if (this[ht] && typeof this[u] == "number") {
|
|
150997
151403
|
let t = this[u];
|
|
150998
|
-
this[u] = void 0,
|
|
151404
|
+
this[u] = void 0, import_fs31.default.closeSync(t), this.emit("close");
|
|
150999
151405
|
}
|
|
151000
151406
|
}
|
|
151001
151407
|
[ve](t) {
|
|
151002
151408
|
let e = true;
|
|
151003
151409
|
try {
|
|
151004
|
-
this[Pt](null,
|
|
151410
|
+
this[Pt](null, import_fs31.default.writeSync(this[u], t, 0, t.length, this[ot])), e = false;
|
|
151005
151411
|
} finally {
|
|
151006
151412
|
if (e) try {
|
|
151007
151413
|
this[H2]();
|
|
@@ -151919,7 +152325,7 @@ var de = class extends A {
|
|
|
151919
152325
|
return t === "error" && (this.#t = true), super.emit(t, ...e);
|
|
151920
152326
|
}
|
|
151921
152327
|
[ss]() {
|
|
151922
|
-
|
|
152328
|
+
import_fs33.default.lstat(this.absolute, (t, e) => {
|
|
151923
152329
|
if (t) return this.emit("error", t);
|
|
151924
152330
|
this[si](e);
|
|
151925
152331
|
});
|
|
@@ -151957,7 +152363,7 @@ var de = class extends A {
|
|
|
151957
152363
|
this.path.slice(-1) !== "/" && (this.path += "/"), this.stat.size = 0, this[fe](), this.end();
|
|
151958
152364
|
}
|
|
151959
152365
|
[is]() {
|
|
151960
|
-
|
|
152366
|
+
import_fs33.default.readlink(this.absolute, (t, e) => {
|
|
151961
152367
|
if (t) return this.emit("error", t);
|
|
151962
152368
|
this[ns](e);
|
|
151963
152369
|
});
|
|
@@ -151980,7 +152386,7 @@ var de = class extends A {
|
|
|
151980
152386
|
this[os]();
|
|
151981
152387
|
}
|
|
151982
152388
|
[os]() {
|
|
151983
|
-
|
|
152389
|
+
import_fs33.default.open(this.absolute, "r", (t, e) => {
|
|
151984
152390
|
if (t) return this.emit("error", t);
|
|
151985
152391
|
this[hs](e);
|
|
151986
152392
|
});
|
|
@@ -151995,14 +152401,14 @@ var de = class extends A {
|
|
|
151995
152401
|
[ii]() {
|
|
151996
152402
|
let { fd: t, buf: e, offset: i, length: r, pos: n } = this;
|
|
151997
152403
|
if (t === void 0 || e === void 0) throw new Error("cannot read file without first opening");
|
|
151998
|
-
|
|
152404
|
+
import_fs33.default.read(t, e, i, r, n, (o, h) => {
|
|
151999
152405
|
if (o) return this[pt](() => this.emit("error", o));
|
|
152000
152406
|
this[rs](h);
|
|
152001
152407
|
});
|
|
152002
152408
|
}
|
|
152003
152409
|
[pt](t = () => {
|
|
152004
152410
|
}) {
|
|
152005
|
-
this.fd !== void 0 &&
|
|
152411
|
+
this.fd !== void 0 && import_fs33.default.close(this.fd, t);
|
|
152006
152412
|
}
|
|
152007
152413
|
[rs](t) {
|
|
152008
152414
|
if (t <= 0 && this.remain > 0) {
|
|
@@ -152037,20 +152443,20 @@ var de = class extends A {
|
|
|
152037
152443
|
var ni = class extends de {
|
|
152038
152444
|
sync = true;
|
|
152039
152445
|
[ss]() {
|
|
152040
|
-
this[si](
|
|
152446
|
+
this[si](import_fs33.default.lstatSync(this.absolute));
|
|
152041
152447
|
}
|
|
152042
152448
|
[is]() {
|
|
152043
|
-
this[ns](
|
|
152449
|
+
this[ns](import_fs33.default.readlinkSync(this.absolute));
|
|
152044
152450
|
}
|
|
152045
152451
|
[os]() {
|
|
152046
|
-
this[hs](
|
|
152452
|
+
this[hs](import_fs33.default.openSync(this.absolute, "r"));
|
|
152047
152453
|
}
|
|
152048
152454
|
[ii]() {
|
|
152049
152455
|
let t = true;
|
|
152050
152456
|
try {
|
|
152051
152457
|
let { fd: e, buf: i, offset: r, length: n, pos: o } = this;
|
|
152052
152458
|
if (e === void 0 || i === void 0) throw new Error("fd and buf must be set in READ method");
|
|
152053
|
-
let h =
|
|
152459
|
+
let h = import_fs33.default.readSync(e, i, r, n, o);
|
|
152054
152460
|
this[rs](h), t = false;
|
|
152055
152461
|
} finally {
|
|
152056
152462
|
if (t) try {
|
|
@@ -152065,7 +152471,7 @@ var ni = class extends de {
|
|
|
152065
152471
|
}
|
|
152066
152472
|
[pt](t = () => {
|
|
152067
152473
|
}) {
|
|
152068
|
-
this.fd !== void 0 &&
|
|
152474
|
+
this.fd !== void 0 && import_fs33.default.closeSync(this.fd), t();
|
|
152069
152475
|
}
|
|
152070
152476
|
};
|
|
152071
152477
|
var oi = class extends A {
|
|
@@ -152396,7 +152802,7 @@ var wt = class extends A {
|
|
|
152396
152802
|
[ds](t) {
|
|
152397
152803
|
t.pending = true, this[G] += 1;
|
|
152398
152804
|
let e = this.follow ? "stat" : "lstat";
|
|
152399
|
-
|
|
152805
|
+
import_fs32.default[e](t.absolute, (i, r) => {
|
|
152400
152806
|
t.pending = false, this[G] -= 1, i ? this.emit("error", i) : this[li](t, r);
|
|
152401
152807
|
});
|
|
152402
152808
|
}
|
|
@@ -152410,7 +152816,7 @@ var wt = class extends A {
|
|
|
152410
152816
|
this[Ft]();
|
|
152411
152817
|
}
|
|
152412
152818
|
[ms](t) {
|
|
152413
|
-
t.pending = true, this[G] += 1,
|
|
152819
|
+
t.pending = true, this[G] += 1, import_fs32.default.readdir(t.absolute, (e, i) => {
|
|
152414
152820
|
if (t.pending = false, this[G] -= 1, e) return this.emit("error", e);
|
|
152415
152821
|
this[fi](t, i);
|
|
152416
152822
|
});
|
|
@@ -152511,10 +152917,10 @@ var kt = class extends wt {
|
|
|
152511
152917
|
}
|
|
152512
152918
|
[ds](t) {
|
|
152513
152919
|
let e = this.follow ? "statSync" : "lstatSync";
|
|
152514
|
-
this[li](t,
|
|
152920
|
+
this[li](t, import_fs32.default[e](t.absolute));
|
|
152515
152921
|
}
|
|
152516
152922
|
[ms](t) {
|
|
152517
|
-
this[fi](t,
|
|
152923
|
+
this[fi](t, import_fs32.default.readdirSync(t.absolute));
|
|
152518
152924
|
}
|
|
152519
152925
|
[di](t) {
|
|
152520
152926
|
let e = t.entry, i = this.zip;
|
|
@@ -152565,8 +152971,8 @@ var Qn = K(Vn, $n, Xn, qn, (s3, t) => {
|
|
|
152565
152971
|
});
|
|
152566
152972
|
var Jn = process.env.__FAKE_PLATFORM__ || process.platform;
|
|
152567
152973
|
var Er = Jn === "win32";
|
|
152568
|
-
var { O_CREAT: wr, O_NOFOLLOW: mr, O_TRUNC: Sr, O_WRONLY: yr } =
|
|
152569
|
-
var Rr = Number(process.env.__FAKE_FS_O_FILENAME__) ||
|
|
152974
|
+
var { O_CREAT: wr, O_NOFOLLOW: mr, O_TRUNC: Sr, O_WRONLY: yr } = import_fs34.default.constants;
|
|
152975
|
+
var Rr = Number(process.env.__FAKE_FS_O_FILENAME__) || import_fs34.default.constants.UV_FS_O_FILEMAP || 0;
|
|
152570
152976
|
var jn = Er && !!Rr;
|
|
152571
152977
|
var to = 512 * 1024;
|
|
152572
152978
|
var eo = Rr | Sr | wr | yr;
|
|
@@ -153944,12 +154350,12 @@ program2.command("cache").description("Manage the local SQLite conversation cach
|
|
|
153944
154350
|
"Cache directory (default: ~/.threadbase/cache)",
|
|
153945
154351
|
`${process.env.HOME}/.threadbase/cache`
|
|
153946
154352
|
).action((opts) => {
|
|
153947
|
-
const { rmSync: rmSync6, existsSync:
|
|
154353
|
+
const { rmSync: rmSync6, existsSync: existsSync16 } = require("fs");
|
|
153948
154354
|
const { join: join29 } = require("path");
|
|
153949
154355
|
const dbPath = join29(opts.cacheDir, "cache.db");
|
|
153950
154356
|
for (const suffix of ["", "-shm", "-wal"]) {
|
|
153951
154357
|
const f2 = dbPath + suffix;
|
|
153952
|
-
if (
|
|
154358
|
+
if (existsSync16(f2)) {
|
|
153953
154359
|
rmSync6(f2);
|
|
153954
154360
|
log11.info(`Deleted ${f2}`, { path: f2 }, "console");
|
|
153955
154361
|
}
|