@threadbase-sh/streamer 1.19.1 → 1.21.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 +452 -618
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +164 -318
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +169 -323
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/cli.cjs
CHANGED
|
@@ -26078,7 +26078,7 @@ var require_thread_stream = __commonJS({
|
|
|
26078
26078
|
var { version: version2 } = require_package();
|
|
26079
26079
|
var { EventEmitter: EventEmitter6 } = require("events");
|
|
26080
26080
|
var { Worker: Worker2 } = require("worker_threads");
|
|
26081
|
-
var { join:
|
|
26081
|
+
var { join: join25 } = require("path");
|
|
26082
26082
|
var { pathToFileURL } = require("url");
|
|
26083
26083
|
var { wait } = require_wait();
|
|
26084
26084
|
var {
|
|
@@ -26129,7 +26129,7 @@ var require_thread_stream = __commonJS({
|
|
|
26129
26129
|
function createWorker(stream, opts) {
|
|
26130
26130
|
const { filename, workerData } = opts;
|
|
26131
26131
|
const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
|
|
26132
|
-
const toExecute = bundlerOverrides["thread-stream-worker"] ||
|
|
26132
|
+
const toExecute = bundlerOverrides["thread-stream-worker"] || join25(__dirname, "lib", "worker.js");
|
|
26133
26133
|
const worker = new Worker2(toExecute, {
|
|
26134
26134
|
...opts.workerOpts,
|
|
26135
26135
|
name: opts.workerOpts?.name || "thread-stream",
|
|
@@ -26597,7 +26597,7 @@ var require_transport = __commonJS({
|
|
|
26597
26597
|
var { createRequire } = require("module");
|
|
26598
26598
|
var { existsSync: existsSync11 } = require("fs");
|
|
26599
26599
|
var getCallers = require_caller();
|
|
26600
|
-
var { join:
|
|
26600
|
+
var { join: join25, isAbsolute: isAbsolute3, sep: sep2 } = require("path");
|
|
26601
26601
|
var { fileURLToPath: fileURLToPath3 } = require("url");
|
|
26602
26602
|
var sleep = require_atomic_sleep();
|
|
26603
26603
|
var onExit = require_on_exit_leak_free();
|
|
@@ -26750,7 +26750,7 @@ var require_transport = __commonJS({
|
|
|
26750
26750
|
throw new Error("only one of target or targets can be specified");
|
|
26751
26751
|
}
|
|
26752
26752
|
if (targets) {
|
|
26753
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
26753
|
+
target = bundlerOverrides["pino-worker"] || join25(__dirname, "worker.js");
|
|
26754
26754
|
options.targets = targets.filter((dest) => dest.target).map((dest) => {
|
|
26755
26755
|
return {
|
|
26756
26756
|
...dest,
|
|
@@ -26768,7 +26768,7 @@ var require_transport = __commonJS({
|
|
|
26768
26768
|
});
|
|
26769
26769
|
});
|
|
26770
26770
|
} else if (pipeline2) {
|
|
26771
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
26771
|
+
target = bundlerOverrides["pino-worker"] || join25(__dirname, "worker.js");
|
|
26772
26772
|
options.pipelines = [pipeline2.map((dest) => {
|
|
26773
26773
|
return {
|
|
26774
26774
|
...dest,
|
|
@@ -26791,7 +26791,7 @@ var require_transport = __commonJS({
|
|
|
26791
26791
|
return origin;
|
|
26792
26792
|
}
|
|
26793
26793
|
if (origin === "pino/file") {
|
|
26794
|
-
return
|
|
26794
|
+
return join25(__dirname, "..", "file.js");
|
|
26795
26795
|
}
|
|
26796
26796
|
let fixTarget2;
|
|
26797
26797
|
for (const filePath of callers) {
|
|
@@ -27772,7 +27772,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
27772
27772
|
return circularValue;
|
|
27773
27773
|
}
|
|
27774
27774
|
let res = "";
|
|
27775
|
-
let
|
|
27775
|
+
let join25 = ",";
|
|
27776
27776
|
const originalIndentation = indentation;
|
|
27777
27777
|
if (Array.isArray(value)) {
|
|
27778
27778
|
if (value.length === 0) {
|
|
@@ -27786,7 +27786,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
27786
27786
|
indentation += spacer;
|
|
27787
27787
|
res += `
|
|
27788
27788
|
${indentation}`;
|
|
27789
|
-
|
|
27789
|
+
join25 = `,
|
|
27790
27790
|
${indentation}`;
|
|
27791
27791
|
}
|
|
27792
27792
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -27794,13 +27794,13 @@ ${indentation}`;
|
|
|
27794
27794
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
27795
27795
|
const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
27796
27796
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
27797
|
-
res +=
|
|
27797
|
+
res += join25;
|
|
27798
27798
|
}
|
|
27799
27799
|
const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
27800
27800
|
res += tmp !== void 0 ? tmp : "null";
|
|
27801
27801
|
if (value.length - 1 > maximumBreadth) {
|
|
27802
27802
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
27803
|
-
res += `${
|
|
27803
|
+
res += `${join25}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
27804
27804
|
}
|
|
27805
27805
|
if (spacer !== "") {
|
|
27806
27806
|
res += `
|
|
@@ -27821,7 +27821,7 @@ ${originalIndentation}`;
|
|
|
27821
27821
|
let separator = "";
|
|
27822
27822
|
if (spacer !== "") {
|
|
27823
27823
|
indentation += spacer;
|
|
27824
|
-
|
|
27824
|
+
join25 = `,
|
|
27825
27825
|
${indentation}`;
|
|
27826
27826
|
whitespace = " ";
|
|
27827
27827
|
}
|
|
@@ -27835,13 +27835,13 @@ ${indentation}`;
|
|
|
27835
27835
|
const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
|
|
27836
27836
|
if (tmp !== void 0) {
|
|
27837
27837
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
27838
|
-
separator =
|
|
27838
|
+
separator = join25;
|
|
27839
27839
|
}
|
|
27840
27840
|
}
|
|
27841
27841
|
if (keyLength > maximumBreadth) {
|
|
27842
27842
|
const removedKeys = keyLength - maximumBreadth;
|
|
27843
27843
|
res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
|
|
27844
|
-
separator =
|
|
27844
|
+
separator = join25;
|
|
27845
27845
|
}
|
|
27846
27846
|
if (spacer !== "" && separator.length > 1) {
|
|
27847
27847
|
res = `
|
|
@@ -27882,7 +27882,7 @@ ${originalIndentation}`;
|
|
|
27882
27882
|
}
|
|
27883
27883
|
const originalIndentation = indentation;
|
|
27884
27884
|
let res = "";
|
|
27885
|
-
let
|
|
27885
|
+
let join25 = ",";
|
|
27886
27886
|
if (Array.isArray(value)) {
|
|
27887
27887
|
if (value.length === 0) {
|
|
27888
27888
|
return "[]";
|
|
@@ -27895,7 +27895,7 @@ ${originalIndentation}`;
|
|
|
27895
27895
|
indentation += spacer;
|
|
27896
27896
|
res += `
|
|
27897
27897
|
${indentation}`;
|
|
27898
|
-
|
|
27898
|
+
join25 = `,
|
|
27899
27899
|
${indentation}`;
|
|
27900
27900
|
}
|
|
27901
27901
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -27903,13 +27903,13 @@ ${indentation}`;
|
|
|
27903
27903
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
27904
27904
|
const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
27905
27905
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
27906
|
-
res +=
|
|
27906
|
+
res += join25;
|
|
27907
27907
|
}
|
|
27908
27908
|
const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
27909
27909
|
res += tmp !== void 0 ? tmp : "null";
|
|
27910
27910
|
if (value.length - 1 > maximumBreadth) {
|
|
27911
27911
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
27912
|
-
res += `${
|
|
27912
|
+
res += `${join25}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
27913
27913
|
}
|
|
27914
27914
|
if (spacer !== "") {
|
|
27915
27915
|
res += `
|
|
@@ -27922,7 +27922,7 @@ ${originalIndentation}`;
|
|
|
27922
27922
|
let whitespace = "";
|
|
27923
27923
|
if (spacer !== "") {
|
|
27924
27924
|
indentation += spacer;
|
|
27925
|
-
|
|
27925
|
+
join25 = `,
|
|
27926
27926
|
${indentation}`;
|
|
27927
27927
|
whitespace = " ";
|
|
27928
27928
|
}
|
|
@@ -27931,7 +27931,7 @@ ${indentation}`;
|
|
|
27931
27931
|
const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
|
|
27932
27932
|
if (tmp !== void 0) {
|
|
27933
27933
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
27934
|
-
separator =
|
|
27934
|
+
separator = join25;
|
|
27935
27935
|
}
|
|
27936
27936
|
}
|
|
27937
27937
|
if (spacer !== "" && separator.length > 1) {
|
|
@@ -27989,20 +27989,20 @@ ${originalIndentation}`;
|
|
|
27989
27989
|
indentation += spacer;
|
|
27990
27990
|
let res2 = `
|
|
27991
27991
|
${indentation}`;
|
|
27992
|
-
const
|
|
27992
|
+
const join26 = `,
|
|
27993
27993
|
${indentation}`;
|
|
27994
27994
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
27995
27995
|
let i = 0;
|
|
27996
27996
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
27997
27997
|
const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
27998
27998
|
res2 += tmp2 !== void 0 ? tmp2 : "null";
|
|
27999
|
-
res2 +=
|
|
27999
|
+
res2 += join26;
|
|
28000
28000
|
}
|
|
28001
28001
|
const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
28002
28002
|
res2 += tmp !== void 0 ? tmp : "null";
|
|
28003
28003
|
if (value.length - 1 > maximumBreadth) {
|
|
28004
28004
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
28005
|
-
res2 += `${
|
|
28005
|
+
res2 += `${join26}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
28006
28006
|
}
|
|
28007
28007
|
res2 += `
|
|
28008
28008
|
${originalIndentation}`;
|
|
@@ -28018,16 +28018,16 @@ ${originalIndentation}`;
|
|
|
28018
28018
|
return '"[Object]"';
|
|
28019
28019
|
}
|
|
28020
28020
|
indentation += spacer;
|
|
28021
|
-
const
|
|
28021
|
+
const join25 = `,
|
|
28022
28022
|
${indentation}`;
|
|
28023
28023
|
let res = "";
|
|
28024
28024
|
let separator = "";
|
|
28025
28025
|
let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
28026
28026
|
if (isTypedArrayWithEntries(value)) {
|
|
28027
|
-
res += stringifyTypedArray(value,
|
|
28027
|
+
res += stringifyTypedArray(value, join25, maximumBreadth);
|
|
28028
28028
|
keys = keys.slice(value.length);
|
|
28029
28029
|
maximumPropertiesToStringify -= value.length;
|
|
28030
|
-
separator =
|
|
28030
|
+
separator = join25;
|
|
28031
28031
|
}
|
|
28032
28032
|
if (deterministic) {
|
|
28033
28033
|
keys = sort(keys, comparator);
|
|
@@ -28038,13 +28038,13 @@ ${indentation}`;
|
|
|
28038
28038
|
const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
|
|
28039
28039
|
if (tmp !== void 0) {
|
|
28040
28040
|
res += `${separator}${strEscape(key2)}: ${tmp}`;
|
|
28041
|
-
separator =
|
|
28041
|
+
separator = join25;
|
|
28042
28042
|
}
|
|
28043
28043
|
}
|
|
28044
28044
|
if (keyLength > maximumBreadth) {
|
|
28045
28045
|
const removedKeys = keyLength - maximumBreadth;
|
|
28046
28046
|
res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
|
|
28047
|
-
separator =
|
|
28047
|
+
separator = join25;
|
|
28048
28048
|
}
|
|
28049
28049
|
if (separator !== "") {
|
|
28050
28050
|
res = `
|
|
@@ -124399,20 +124399,20 @@ var require_semver2 = __commonJS({
|
|
|
124399
124399
|
|
|
124400
124400
|
// src/lifecycle/constants.ts
|
|
124401
124401
|
function installDir() {
|
|
124402
|
-
return process.env.THREADBASE_INSTALL_DIR ?? (0,
|
|
124402
|
+
return process.env.THREADBASE_INSTALL_DIR ?? (0, import_node_path22.join)((0, import_node_os4.homedir)(), ".threadbase");
|
|
124403
124403
|
}
|
|
124404
124404
|
function markerPath() {
|
|
124405
|
-
return (0,
|
|
124405
|
+
return (0, import_node_path22.join)(installDir(), "prod-suspended.json");
|
|
124406
124406
|
}
|
|
124407
124407
|
function prefsPath() {
|
|
124408
|
-
return (0,
|
|
124408
|
+
return (0, import_node_path22.join)(installDir(), "dev-prefs.json");
|
|
124409
124409
|
}
|
|
124410
|
-
var import_node_os4,
|
|
124410
|
+
var import_node_os4, import_node_path22, LAUNCHD_LABEL, TASK_NAME;
|
|
124411
124411
|
var init_constants = __esm({
|
|
124412
124412
|
"src/lifecycle/constants.ts"() {
|
|
124413
124413
|
"use strict";
|
|
124414
124414
|
import_node_os4 = require("os");
|
|
124415
|
-
|
|
124415
|
+
import_node_path22 = require("path");
|
|
124416
124416
|
LAUNCHD_LABEL = "com.ronen.threadbase";
|
|
124417
124417
|
TASK_NAME = process.env.THREADBASE_TASK_NAME ?? "Threadbase";
|
|
124418
124418
|
}
|
|
@@ -124487,8 +124487,8 @@ function darwinPlistPath() {
|
|
|
124487
124487
|
return `${process.env.HOME}/Library/LaunchAgents/${resolveLoadedLabel()}.plist`;
|
|
124488
124488
|
}
|
|
124489
124489
|
function getLogPaths() {
|
|
124490
|
-
const dir = (0,
|
|
124491
|
-
return { stdout: (0,
|
|
124490
|
+
const dir = (0, import_node_path23.join)(installDir(), "logs");
|
|
124491
|
+
return { stdout: (0, import_node_path23.join)(dir, "stdout.log"), stderr: (0, import_node_path23.join)(dir, "stderr.log") };
|
|
124492
124492
|
}
|
|
124493
124493
|
function getAgentPid() {
|
|
124494
124494
|
try {
|
|
@@ -124508,12 +124508,12 @@ function getAgentPid() {
|
|
|
124508
124508
|
return null;
|
|
124509
124509
|
}
|
|
124510
124510
|
}
|
|
124511
|
-
var import_node_child_process4,
|
|
124511
|
+
var import_node_child_process4, import_node_path23, BREW_LAUNCHD_LABEL2;
|
|
124512
124512
|
var init_launchd = __esm({
|
|
124513
124513
|
"src/lifecycle/launchd.ts"() {
|
|
124514
124514
|
"use strict";
|
|
124515
124515
|
import_node_child_process4 = require("child_process");
|
|
124516
|
-
|
|
124516
|
+
import_node_path23 = require("path");
|
|
124517
124517
|
init_constants();
|
|
124518
124518
|
BREW_LAUNCHD_LABEL2 = "homebrew.mxcl.tb-streamer";
|
|
124519
124519
|
}
|
|
@@ -124538,9 +124538,9 @@ var init_marker_schema = __esm({
|
|
|
124538
124538
|
|
|
124539
124539
|
// src/lifecycle/marker.ts
|
|
124540
124540
|
function readMarker() {
|
|
124541
|
-
if (!(0,
|
|
124541
|
+
if (!(0, import_node_fs19.existsSync)(markerPath())) return null;
|
|
124542
124542
|
try {
|
|
124543
|
-
const raw2 = (0,
|
|
124543
|
+
const raw2 = (0, import_node_fs19.readFileSync)(markerPath(), "utf8");
|
|
124544
124544
|
const parsed = JSON.parse(raw2);
|
|
124545
124545
|
return MarkerSchema.parse(parsed);
|
|
124546
124546
|
} catch (err) {
|
|
@@ -124552,21 +124552,21 @@ function readMarker() {
|
|
|
124552
124552
|
}
|
|
124553
124553
|
function writeMarker(marker) {
|
|
124554
124554
|
MarkerSchema.parse(marker);
|
|
124555
|
-
(0,
|
|
124555
|
+
(0, import_node_fs19.mkdirSync)((0, import_node_path24.dirname)(markerPath()), { recursive: true });
|
|
124556
124556
|
const tmp = `${markerPath()}.tmp`;
|
|
124557
|
-
(0,
|
|
124557
|
+
(0, import_node_fs19.writeFileSync)(tmp, `${JSON.stringify(marker, null, 2)}
|
|
124558
124558
|
`, { mode: 384 });
|
|
124559
|
-
(0,
|
|
124559
|
+
(0, import_node_fs19.renameSync)(tmp, markerPath());
|
|
124560
124560
|
}
|
|
124561
124561
|
function clearMarker() {
|
|
124562
|
-
if ((0,
|
|
124562
|
+
if ((0, import_node_fs19.existsSync)(markerPath())) (0, import_node_fs19.rmSync)(markerPath());
|
|
124563
124563
|
}
|
|
124564
|
-
var
|
|
124564
|
+
var import_node_fs19, import_node_path24, log3;
|
|
124565
124565
|
var init_marker = __esm({
|
|
124566
124566
|
"src/lifecycle/marker.ts"() {
|
|
124567
124567
|
"use strict";
|
|
124568
|
-
|
|
124569
|
-
|
|
124568
|
+
import_node_fs19 = require("fs");
|
|
124569
|
+
import_node_path24 = require("path");
|
|
124570
124570
|
init_logger();
|
|
124571
124571
|
init_constants();
|
|
124572
124572
|
init_marker_schema();
|
|
@@ -124661,9 +124661,9 @@ var init_platform = __esm({
|
|
|
124661
124661
|
// src/lifecycle/prefs.ts
|
|
124662
124662
|
function readPrefs() {
|
|
124663
124663
|
const path2 = prefsPath();
|
|
124664
|
-
if (!(0,
|
|
124664
|
+
if (!(0, import_node_fs21.existsSync)(path2)) return { repos: {} };
|
|
124665
124665
|
try {
|
|
124666
|
-
return PrefsSchema.parse(JSON.parse((0,
|
|
124666
|
+
return PrefsSchema.parse(JSON.parse((0, import_node_fs21.readFileSync)(path2, "utf8")));
|
|
124667
124667
|
} catch (err) {
|
|
124668
124668
|
log5.warn(`prefs at ${path2} are malformed; treating as empty`, {
|
|
124669
124669
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -124673,11 +124673,11 @@ function readPrefs() {
|
|
|
124673
124673
|
}
|
|
124674
124674
|
function savePrefs(p2) {
|
|
124675
124675
|
const path2 = prefsPath();
|
|
124676
|
-
(0,
|
|
124676
|
+
(0, import_node_fs21.mkdirSync)((0, import_node_path25.dirname)(path2), { recursive: true });
|
|
124677
124677
|
const tmp = `${path2}.tmp`;
|
|
124678
|
-
(0,
|
|
124678
|
+
(0, import_node_fs21.writeFileSync)(tmp, `${JSON.stringify(p2, null, 2)}
|
|
124679
124679
|
`, { mode: 384 });
|
|
124680
|
-
(0,
|
|
124680
|
+
(0, import_node_fs21.renameSync)(tmp, path2);
|
|
124681
124681
|
}
|
|
124682
124682
|
function writePrefForRepo(repoToplevel, choice) {
|
|
124683
124683
|
const p2 = readPrefs();
|
|
@@ -124698,14 +124698,14 @@ function forgetRepo(repoToplevel) {
|
|
|
124698
124698
|
}
|
|
124699
124699
|
function forgetAll() {
|
|
124700
124700
|
const path2 = prefsPath();
|
|
124701
|
-
if ((0,
|
|
124701
|
+
if ((0, import_node_fs21.existsSync)(path2)) (0, import_node_fs21.rmSync)(path2);
|
|
124702
124702
|
}
|
|
124703
|
-
var
|
|
124703
|
+
var import_node_fs21, import_node_path25, log5, PrefsSchema;
|
|
124704
124704
|
var init_prefs = __esm({
|
|
124705
124705
|
"src/lifecycle/prefs.ts"() {
|
|
124706
124706
|
"use strict";
|
|
124707
|
-
|
|
124708
|
-
|
|
124707
|
+
import_node_fs21 = require("fs");
|
|
124708
|
+
import_node_path25 = require("path");
|
|
124709
124709
|
init_zod();
|
|
124710
124710
|
init_logger();
|
|
124711
124711
|
init_constants();
|
|
@@ -124927,7 +124927,7 @@ __export(setKey_exports, {
|
|
|
124927
124927
|
async function defaultReadStdin() {
|
|
124928
124928
|
return new Promise((resolve6, reject) => {
|
|
124929
124929
|
const chunks = [];
|
|
124930
|
-
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
124930
|
+
process.stdin.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
124931
124931
|
process.stdin.on("end", () => resolve6(Buffer.concat(chunks).toString("utf-8")));
|
|
124932
124932
|
process.stdin.on("error", reject);
|
|
124933
124933
|
});
|
|
@@ -136445,13 +136445,23 @@ var authMiddleware = (deps) => async (c, next) => {
|
|
|
136445
136445
|
};
|
|
136446
136446
|
|
|
136447
136447
|
// src/api/middleware/cors.middleware.ts
|
|
136448
|
+
var ALLOWED_ORIGINS = /* @__PURE__ */ new Set([
|
|
136449
|
+
"http://localhost:8081",
|
|
136450
|
+
"http://localhost:19006",
|
|
136451
|
+
"http://localhost:3000"
|
|
136452
|
+
]);
|
|
136448
136453
|
var corsMiddleware = () => async (c, next) => {
|
|
136449
|
-
c.
|
|
136450
|
-
|
|
136451
|
-
|
|
136452
|
-
|
|
136454
|
+
const origin = c.req.header("origin");
|
|
136455
|
+
const allowedOrigin = origin && ALLOWED_ORIGINS.has(origin) ? origin : null;
|
|
136456
|
+
if (allowedOrigin) {
|
|
136457
|
+
c.res.headers.set("Access-Control-Allow-Origin", allowedOrigin);
|
|
136458
|
+
c.res.headers.set("Vary", "Origin");
|
|
136459
|
+
c.res.headers.set("Access-Control-Allow-Methods", "GET, POST, PATCH, OPTIONS");
|
|
136460
|
+
c.res.headers.set("Access-Control-Allow-Headers", "Authorization, Content-Type, If-None-Match");
|
|
136461
|
+
c.res.headers.set("Access-Control-Expose-Headers", "ETag");
|
|
136462
|
+
}
|
|
136453
136463
|
if (c.req.method === "OPTIONS") {
|
|
136454
|
-
return c.newResponse(null, 204);
|
|
136464
|
+
return c.newResponse(null, allowedOrigin ? 204 : 403);
|
|
136455
136465
|
}
|
|
136456
136466
|
await next();
|
|
136457
136467
|
};
|
|
@@ -136595,6 +136605,19 @@ var createMiscRoutes = (deps) => {
|
|
|
136595
136605
|
});
|
|
136596
136606
|
});
|
|
136597
136607
|
app.get("/api/profiles", (c) => c.json([]));
|
|
136608
|
+
app.post("/api/auth/rotate", (c) => {
|
|
136609
|
+
if (deps.localNoAuth) {
|
|
136610
|
+
return c.json({ error: "key rotation is disabled while localNoAuth is active" }, 403);
|
|
136611
|
+
}
|
|
136612
|
+
const { newKey, persisted } = deps.rotateApiKey();
|
|
136613
|
+
return c.json({
|
|
136614
|
+
apiKey: newKey,
|
|
136615
|
+
persisted,
|
|
136616
|
+
...persisted ? {} : {
|
|
136617
|
+
warning: "Key rotated in memory only. The server was started with --api-key, so the old key will be restored on restart. Remove --api-key and let the server manage the key via ~/.threadbase/server.yaml for rotation to survive restarts."
|
|
136618
|
+
}
|
|
136619
|
+
});
|
|
136620
|
+
});
|
|
136598
136621
|
app.post("/api/push/register", (c) => c.json({ ok: true }));
|
|
136599
136622
|
app.post("/api/__update", async (c) => {
|
|
136600
136623
|
const cfg = loadUpdateConfig();
|
|
@@ -136796,6 +136819,11 @@ var ALREADY_HANDLED4 = 597;
|
|
|
136796
136819
|
var alreadyHandled4 = () => new Response(null, { status: ALREADY_HANDLED4 });
|
|
136797
136820
|
var createProjectRoutes = (deps) => {
|
|
136798
136821
|
const app = new Hono2();
|
|
136822
|
+
app.get("/", (c) => {
|
|
136823
|
+
const url2 = new URL(c.req.url);
|
|
136824
|
+
deps.handleListProjects(url2, c.env.outgoing);
|
|
136825
|
+
return alreadyHandled4();
|
|
136826
|
+
});
|
|
136799
136827
|
app.get("/popular", (c) => {
|
|
136800
136828
|
const url2 = new URL(c.req.url);
|
|
136801
136829
|
deps.handleGetPopularProjects(url2, c.env.outgoing);
|
|
@@ -136814,11 +136842,6 @@ var createScannerRoutes = (deps) => {
|
|
|
136814
136842
|
await deps.handleSearch(url2, c.env.outgoing);
|
|
136815
136843
|
return alreadyHandled5();
|
|
136816
136844
|
});
|
|
136817
|
-
app.get("/project-chats", async (c) => {
|
|
136818
|
-
const url2 = new URL(c.req.url);
|
|
136819
|
-
await deps.handleListProjectChats(url2, c.env.outgoing);
|
|
136820
|
-
return alreadyHandled5();
|
|
136821
|
-
});
|
|
136822
136845
|
return app;
|
|
136823
136846
|
};
|
|
136824
136847
|
|
|
@@ -138082,517 +138105,39 @@ async function recordUpload(pool2, instanceId, row) {
|
|
|
138082
138105
|
);
|
|
138083
138106
|
}
|
|
138084
138107
|
|
|
138085
|
-
// src/
|
|
138086
|
-
init_zod();
|
|
138087
|
-
var ListProjectChatsQuerySchema = external_exports.object({
|
|
138088
|
-
refresh: external_exports.enum(["1"]).optional(),
|
|
138089
|
-
refreshConversations: external_exports.enum(["1"]).optional()
|
|
138090
|
-
});
|
|
138091
|
-
|
|
138092
|
-
// src/services/cache/cacheMetadata.ts
|
|
138093
|
-
function getCacheMetadata(repo, key) {
|
|
138094
|
-
return repo.getCacheMetadata(key);
|
|
138095
|
-
}
|
|
138096
|
-
function setCacheMetadata(repo, key, value) {
|
|
138097
|
-
repo.setCacheMetadata(key, value);
|
|
138098
|
-
}
|
|
138099
|
-
|
|
138100
|
-
// node_modules/date-fns/constants.js
|
|
138101
|
-
var daysInYear = 365.2425;
|
|
138102
|
-
var maxTime = Math.pow(10, 8) * 24 * 60 * 60 * 1e3;
|
|
138103
|
-
var minTime = -maxTime;
|
|
138104
|
-
var millisecondsInMinute = 6e4;
|
|
138105
|
-
var millisecondsInHour = 36e5;
|
|
138106
|
-
var secondsInHour = 3600;
|
|
138107
|
-
var secondsInDay = secondsInHour * 24;
|
|
138108
|
-
var secondsInWeek = secondsInDay * 7;
|
|
138109
|
-
var secondsInYear = secondsInDay * daysInYear;
|
|
138110
|
-
var secondsInMonth = secondsInYear / 12;
|
|
138111
|
-
var secondsInQuarter = secondsInMonth * 3;
|
|
138112
|
-
var constructFromSymbol = /* @__PURE__ */ Symbol.for("constructDateFrom");
|
|
138113
|
-
|
|
138114
|
-
// node_modules/date-fns/constructFrom.js
|
|
138115
|
-
function constructFrom(date5, value) {
|
|
138116
|
-
if (typeof date5 === "function") return date5(value);
|
|
138117
|
-
if (date5 && typeof date5 === "object" && constructFromSymbol in date5)
|
|
138118
|
-
return date5[constructFromSymbol](value);
|
|
138119
|
-
if (date5 instanceof Date) return new date5.constructor(value);
|
|
138120
|
-
return new Date(value);
|
|
138121
|
-
}
|
|
138122
|
-
|
|
138123
|
-
// node_modules/date-fns/toDate.js
|
|
138124
|
-
function toDate(argument, context) {
|
|
138125
|
-
return constructFrom(context || argument, argument);
|
|
138126
|
-
}
|
|
138127
|
-
|
|
138128
|
-
// node_modules/date-fns/compareDesc.js
|
|
138129
|
-
function compareDesc(dateLeft, dateRight) {
|
|
138130
|
-
const diff = +toDate(dateLeft) - +toDate(dateRight);
|
|
138131
|
-
if (diff > 0) return -1;
|
|
138132
|
-
else if (diff < 0) return 1;
|
|
138133
|
-
return diff;
|
|
138134
|
-
}
|
|
138135
|
-
|
|
138136
|
-
// node_modules/date-fns/isDate.js
|
|
138137
|
-
function isDate(value) {
|
|
138138
|
-
return value instanceof Date || typeof value === "object" && Object.prototype.toString.call(value) === "[object Date]";
|
|
138139
|
-
}
|
|
138140
|
-
|
|
138141
|
-
// node_modules/date-fns/isValid.js
|
|
138142
|
-
function isValid(date5) {
|
|
138143
|
-
return !(!isDate(date5) && typeof date5 !== "number" || isNaN(+toDate(date5)));
|
|
138144
|
-
}
|
|
138145
|
-
|
|
138146
|
-
// node_modules/date-fns/parseISO.js
|
|
138147
|
-
function parseISO(argument, options) {
|
|
138148
|
-
const invalidDate = () => constructFrom(options?.in, NaN);
|
|
138149
|
-
const additionalDigits = options?.additionalDigits ?? 2;
|
|
138150
|
-
const dateStrings = splitDateString(argument);
|
|
138151
|
-
let date5;
|
|
138152
|
-
if (dateStrings.date) {
|
|
138153
|
-
const parseYearResult = parseYear(dateStrings.date, additionalDigits);
|
|
138154
|
-
date5 = parseDate(parseYearResult.restDateString, parseYearResult.year);
|
|
138155
|
-
}
|
|
138156
|
-
if (!date5 || isNaN(+date5)) return invalidDate();
|
|
138157
|
-
const timestamp = +date5;
|
|
138158
|
-
let time3 = 0;
|
|
138159
|
-
let offset;
|
|
138160
|
-
if (dateStrings.time) {
|
|
138161
|
-
time3 = parseTime(dateStrings.time);
|
|
138162
|
-
if (isNaN(time3)) return invalidDate();
|
|
138163
|
-
}
|
|
138164
|
-
if (dateStrings.timezone) {
|
|
138165
|
-
offset = parseTimezone(dateStrings.timezone);
|
|
138166
|
-
if (isNaN(offset)) return invalidDate();
|
|
138167
|
-
} else {
|
|
138168
|
-
const tmpDate = new Date(timestamp + time3);
|
|
138169
|
-
const result = toDate(0, options?.in);
|
|
138170
|
-
result.setFullYear(
|
|
138171
|
-
tmpDate.getUTCFullYear(),
|
|
138172
|
-
tmpDate.getUTCMonth(),
|
|
138173
|
-
tmpDate.getUTCDate()
|
|
138174
|
-
);
|
|
138175
|
-
result.setHours(
|
|
138176
|
-
tmpDate.getUTCHours(),
|
|
138177
|
-
tmpDate.getUTCMinutes(),
|
|
138178
|
-
tmpDate.getUTCSeconds(),
|
|
138179
|
-
tmpDate.getUTCMilliseconds()
|
|
138180
|
-
);
|
|
138181
|
-
return result;
|
|
138182
|
-
}
|
|
138183
|
-
return toDate(timestamp + time3 + offset, options?.in);
|
|
138184
|
-
}
|
|
138185
|
-
var patterns = {
|
|
138186
|
-
dateTimeDelimiter: /[T ]/,
|
|
138187
|
-
timeZoneDelimiter: /[Z ]/i,
|
|
138188
|
-
timezone: /([Z+-].*)$/
|
|
138189
|
-
};
|
|
138190
|
-
var dateRegex = /^-?(?:(\d{3})|(\d{2})(?:-?(\d{2}))?|W(\d{2})(?:-?(\d{1}))?|)$/;
|
|
138191
|
-
var timeRegex = /^(\d{2}(?:[.,]\d*)?)(?::?(\d{2}(?:[.,]\d*)?))?(?::?(\d{2}(?:[.,]\d*)?))?$/;
|
|
138192
|
-
var timezoneRegex = /^([+-])(\d{2})(?::?(\d{2}))?$/;
|
|
138193
|
-
function splitDateString(dateString) {
|
|
138194
|
-
const dateStrings = {};
|
|
138195
|
-
const array2 = dateString.split(patterns.dateTimeDelimiter);
|
|
138196
|
-
let timeString;
|
|
138197
|
-
if (array2.length > 2) {
|
|
138198
|
-
return dateStrings;
|
|
138199
|
-
}
|
|
138200
|
-
if (/:/.test(array2[0])) {
|
|
138201
|
-
timeString = array2[0];
|
|
138202
|
-
} else {
|
|
138203
|
-
dateStrings.date = array2[0];
|
|
138204
|
-
timeString = array2[1];
|
|
138205
|
-
if (patterns.timeZoneDelimiter.test(dateStrings.date)) {
|
|
138206
|
-
dateStrings.date = dateString.split(patterns.timeZoneDelimiter)[0];
|
|
138207
|
-
timeString = dateString.substr(
|
|
138208
|
-
dateStrings.date.length,
|
|
138209
|
-
dateString.length
|
|
138210
|
-
);
|
|
138211
|
-
}
|
|
138212
|
-
}
|
|
138213
|
-
if (timeString) {
|
|
138214
|
-
const token = patterns.timezone.exec(timeString);
|
|
138215
|
-
if (token) {
|
|
138216
|
-
dateStrings.time = timeString.replace(token[1], "");
|
|
138217
|
-
dateStrings.timezone = token[1];
|
|
138218
|
-
} else {
|
|
138219
|
-
dateStrings.time = timeString;
|
|
138220
|
-
}
|
|
138221
|
-
}
|
|
138222
|
-
return dateStrings;
|
|
138223
|
-
}
|
|
138224
|
-
function parseYear(dateString, additionalDigits) {
|
|
138225
|
-
const regex = new RegExp(
|
|
138226
|
-
"^(?:(\\d{4}|[+-]\\d{" + (4 + additionalDigits) + "})|(\\d{2}|[+-]\\d{" + (2 + additionalDigits) + "})$)"
|
|
138227
|
-
);
|
|
138228
|
-
const captures = dateString.match(regex);
|
|
138229
|
-
if (!captures) return { year: NaN, restDateString: "" };
|
|
138230
|
-
const year = captures[1] ? parseInt(captures[1]) : null;
|
|
138231
|
-
const century = captures[2] ? parseInt(captures[2]) : null;
|
|
138232
|
-
return {
|
|
138233
|
-
year: century === null ? year : century * 100,
|
|
138234
|
-
restDateString: dateString.slice((captures[1] || captures[2]).length)
|
|
138235
|
-
};
|
|
138236
|
-
}
|
|
138237
|
-
function parseDate(dateString, year) {
|
|
138238
|
-
if (year === null) return /* @__PURE__ */ new Date(NaN);
|
|
138239
|
-
const captures = dateString.match(dateRegex);
|
|
138240
|
-
if (!captures) return /* @__PURE__ */ new Date(NaN);
|
|
138241
|
-
const isWeekDate = !!captures[4];
|
|
138242
|
-
const dayOfYear = parseDateUnit(captures[1]);
|
|
138243
|
-
const month = parseDateUnit(captures[2]) - 1;
|
|
138244
|
-
const day = parseDateUnit(captures[3]);
|
|
138245
|
-
const week = parseDateUnit(captures[4]);
|
|
138246
|
-
const dayOfWeek = parseDateUnit(captures[5]) - 1;
|
|
138247
|
-
if (isWeekDate) {
|
|
138248
|
-
if (!validateWeekDate(year, week, dayOfWeek)) {
|
|
138249
|
-
return /* @__PURE__ */ new Date(NaN);
|
|
138250
|
-
}
|
|
138251
|
-
return dayOfISOWeekYear(year, week, dayOfWeek);
|
|
138252
|
-
} else {
|
|
138253
|
-
const date5 = /* @__PURE__ */ new Date(0);
|
|
138254
|
-
if (!validateDate(year, month, day) || !validateDayOfYearDate(year, dayOfYear)) {
|
|
138255
|
-
return /* @__PURE__ */ new Date(NaN);
|
|
138256
|
-
}
|
|
138257
|
-
date5.setUTCFullYear(year, month, Math.max(dayOfYear, day));
|
|
138258
|
-
return date5;
|
|
138259
|
-
}
|
|
138260
|
-
}
|
|
138261
|
-
function parseDateUnit(value) {
|
|
138262
|
-
return value ? parseInt(value) : 1;
|
|
138263
|
-
}
|
|
138264
|
-
function parseTime(timeString) {
|
|
138265
|
-
const captures = timeString.match(timeRegex);
|
|
138266
|
-
if (!captures) return NaN;
|
|
138267
|
-
const hours = parseTimeUnit(captures[1]);
|
|
138268
|
-
const minutes = parseTimeUnit(captures[2]);
|
|
138269
|
-
const seconds = parseTimeUnit(captures[3]);
|
|
138270
|
-
if (!validateTime(hours, minutes, seconds)) {
|
|
138271
|
-
return NaN;
|
|
138272
|
-
}
|
|
138273
|
-
return hours * millisecondsInHour + minutes * millisecondsInMinute + seconds * 1e3;
|
|
138274
|
-
}
|
|
138275
|
-
function parseTimeUnit(value) {
|
|
138276
|
-
return value && parseFloat(value.replace(",", ".")) || 0;
|
|
138277
|
-
}
|
|
138278
|
-
function parseTimezone(timezoneString) {
|
|
138279
|
-
if (timezoneString === "Z") return 0;
|
|
138280
|
-
const captures = timezoneString.match(timezoneRegex);
|
|
138281
|
-
if (!captures) return 0;
|
|
138282
|
-
const sign = captures[1] === "+" ? -1 : 1;
|
|
138283
|
-
const hours = parseInt(captures[2]);
|
|
138284
|
-
const minutes = captures[3] && parseInt(captures[3]) || 0;
|
|
138285
|
-
if (!validateTimezone(hours, minutes)) {
|
|
138286
|
-
return NaN;
|
|
138287
|
-
}
|
|
138288
|
-
return sign * (hours * millisecondsInHour + minutes * millisecondsInMinute);
|
|
138289
|
-
}
|
|
138290
|
-
function dayOfISOWeekYear(isoWeekYear, week, day) {
|
|
138291
|
-
const date5 = /* @__PURE__ */ new Date(0);
|
|
138292
|
-
date5.setUTCFullYear(isoWeekYear, 0, 4);
|
|
138293
|
-
const fourthOfJanuaryDay = date5.getUTCDay() || 7;
|
|
138294
|
-
const diff = (week - 1) * 7 + day + 1 - fourthOfJanuaryDay;
|
|
138295
|
-
date5.setUTCDate(date5.getUTCDate() + diff);
|
|
138296
|
-
return date5;
|
|
138297
|
-
}
|
|
138298
|
-
var daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
138299
|
-
function isLeapYearIndex(year) {
|
|
138300
|
-
return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;
|
|
138301
|
-
}
|
|
138302
|
-
function validateDate(year, month, date5) {
|
|
138303
|
-
return month >= 0 && month <= 11 && date5 >= 1 && date5 <= (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28));
|
|
138304
|
-
}
|
|
138305
|
-
function validateDayOfYearDate(year, dayOfYear) {
|
|
138306
|
-
return dayOfYear >= 1 && dayOfYear <= (isLeapYearIndex(year) ? 366 : 365);
|
|
138307
|
-
}
|
|
138308
|
-
function validateWeekDate(_year, week, day) {
|
|
138309
|
-
return week >= 1 && week <= 53 && day >= 0 && day <= 6;
|
|
138310
|
-
}
|
|
138311
|
-
function validateTime(hours, minutes, seconds) {
|
|
138312
|
-
if (hours === 24) {
|
|
138313
|
-
return minutes === 0 && seconds === 0;
|
|
138314
|
-
}
|
|
138315
|
-
return seconds >= 0 && seconds < 60 && minutes >= 0 && minutes < 60 && hours >= 0 && hours < 25;
|
|
138316
|
-
}
|
|
138317
|
-
function validateTimezone(_hours, minutes) {
|
|
138318
|
-
return minutes >= 0 && minutes <= 59;
|
|
138319
|
-
}
|
|
138320
|
-
|
|
138321
|
-
// src/utils/dates.ts
|
|
138322
|
-
function parseIsoDateOrNull(value) {
|
|
138323
|
-
if (!value) return null;
|
|
138324
|
-
const parsed = parseISO(value);
|
|
138325
|
-
return isValid(parsed) ? parsed : null;
|
|
138326
|
-
}
|
|
138327
|
-
function compareIsoDesc(a, b2) {
|
|
138328
|
-
const dateA = parseIsoDateOrNull(a);
|
|
138329
|
-
const dateB = parseIsoDateOrNull(b2);
|
|
138330
|
-
if (!dateA && !dateB) return 0;
|
|
138331
|
-
if (!dateA) return 1;
|
|
138332
|
-
if (!dateB) return -1;
|
|
138333
|
-
return compareDesc(dateA, dateB);
|
|
138334
|
-
}
|
|
138335
|
-
|
|
138336
|
-
// src/services/projects/ensureProjectsForConversations.ts
|
|
138337
|
-
function ensureProjectsForConversations(repo, conversations) {
|
|
138338
|
-
const conversationsByPath = /* @__PURE__ */ new Map();
|
|
138339
|
-
for (const conversation of conversations) {
|
|
138340
|
-
if (!conversation.projectPath) continue;
|
|
138341
|
-
const canonical = canonicalizeProjectPath(conversation.projectPath);
|
|
138342
|
-
if (!canonical) continue;
|
|
138343
|
-
const existing = conversationsByPath.get(canonical) ?? [];
|
|
138344
|
-
existing.push(conversation);
|
|
138345
|
-
conversationsByPath.set(canonical, existing);
|
|
138346
|
-
}
|
|
138347
|
-
const pathToProjectId = /* @__PURE__ */ new Map();
|
|
138348
|
-
for (const [path2, projectConversations] of conversationsByPath) {
|
|
138349
|
-
const latest = pickLatestConversation(projectConversations);
|
|
138350
|
-
const project = repo.upsertProjectByPath(path2, {
|
|
138351
|
-
lastConversationId: latest?.id ?? null,
|
|
138352
|
-
lastConversationCreatedAt: latest?.createdAt ?? null,
|
|
138353
|
-
latestMessageAt: latest?.latestMessageAt ?? null
|
|
138354
|
-
});
|
|
138355
|
-
pathToProjectId.set(path2, project.id);
|
|
138356
|
-
}
|
|
138357
|
-
return pathToProjectId;
|
|
138358
|
-
}
|
|
138359
|
-
function pickLatestConversation(conversations) {
|
|
138360
|
-
if (conversations.length === 0) return void 0;
|
|
138361
|
-
return [...conversations].sort((a, b2) => {
|
|
138362
|
-
const cmp = compareIsoDesc(a.latestMessageAt ?? null, b2.latestMessageAt ?? null);
|
|
138363
|
-
if (cmp !== 0) return cmp;
|
|
138364
|
-
return compareIsoDesc(a.createdAt ?? null, b2.createdAt ?? null);
|
|
138365
|
-
})[0];
|
|
138366
|
-
}
|
|
138367
|
-
|
|
138368
|
-
// src/services/conversations/refreshConversationCache.ts
|
|
138369
|
-
function refreshConversationCache(deps) {
|
|
138370
|
-
const { projectsRepo, conversationsRepo, cacheMetadataRepo } = deps;
|
|
138371
|
-
const conversations = conversationsRepo.listConversationsForProjectBackfill();
|
|
138372
|
-
const pathToProjectId = ensureProjectsForConversations(
|
|
138373
|
-
projectsRepo,
|
|
138374
|
-
conversations.map((c) => ({
|
|
138375
|
-
id: c.id,
|
|
138376
|
-
projectPath: c.projectPath,
|
|
138377
|
-
latestMessageAt: c.lastActivity ?? null,
|
|
138378
|
-
createdAt: c.lastActivity ?? null
|
|
138379
|
-
}))
|
|
138380
|
-
);
|
|
138381
|
-
let conversationsBackfilled = 0;
|
|
138382
|
-
for (const conversation of conversations) {
|
|
138383
|
-
if (!conversation.projectPath) continue;
|
|
138384
|
-
if (conversation.projectId) continue;
|
|
138385
|
-
const projectId = pathToProjectId.get(canonicalizeProjectPath(conversation.projectPath));
|
|
138386
|
-
if (!projectId) continue;
|
|
138387
|
-
conversationsRepo.updateConversationProjectId({
|
|
138388
|
-
conversationId: conversation.id,
|
|
138389
|
-
projectId
|
|
138390
|
-
});
|
|
138391
|
-
conversationsBackfilled += 1;
|
|
138392
|
-
}
|
|
138393
|
-
const latest = conversationsRepo.getLatestConversation();
|
|
138394
|
-
if (latest) {
|
|
138395
|
-
setCacheMetadata(cacheMetadataRepo, "last_conversation_id", latest.id);
|
|
138396
|
-
if (latest.lastActivity) {
|
|
138397
|
-
setCacheMetadata(cacheMetadataRepo, "last_conversation_created_at", latest.lastActivity);
|
|
138398
|
-
}
|
|
138399
|
-
}
|
|
138400
|
-
setCacheMetadata(cacheMetadataRepo, "conversations_last_indexed_at", (/* @__PURE__ */ new Date()).toISOString());
|
|
138401
|
-
return {
|
|
138402
|
-
projectsTouched: pathToProjectId.size,
|
|
138403
|
-
conversationsBackfilled,
|
|
138404
|
-
latestConversationId: latest?.id ?? null
|
|
138405
|
-
};
|
|
138406
|
-
}
|
|
138407
|
-
|
|
138408
|
-
// src/services/conversations/shouldRefreshProjectsFromHdd.ts
|
|
138108
|
+
// src/handlers/handleListProjects.ts
|
|
138409
138109
|
var import_fs18 = require("fs");
|
|
138410
138110
|
var import_os7 = require("os");
|
|
138411
138111
|
var import_path14 = require("path");
|
|
138412
|
-
|
|
138413
|
-
|
|
138414
|
-
|
|
138415
|
-
|
|
138416
|
-
|
|
138112
|
+
function decodeProjectPath(dirName) {
|
|
138113
|
+
return dirName.replace(/-/g, "/");
|
|
138114
|
+
}
|
|
138115
|
+
function handleListProjects(url2, res) {
|
|
138116
|
+
const limit = Math.max(1, parseInt(url2.searchParams.get("limit") ?? "50", 10) || 50);
|
|
138117
|
+
const offset = Math.max(0, parseInt(url2.searchParams.get("offset") ?? "0", 10) || 0);
|
|
138118
|
+
const projectsDir = (0, import_path14.join)((0, import_os7.homedir)(), ".claude", "projects");
|
|
138119
|
+
let entries;
|
|
138417
138120
|
try {
|
|
138418
|
-
|
|
138121
|
+
entries = (0, import_fs18.readdirSync)(projectsDir).map((dirName) => {
|
|
138122
|
+
const fullPath = (0, import_path14.join)(projectsDir, dirName);
|
|
138123
|
+
let mtime = 0;
|
|
138124
|
+
try {
|
|
138125
|
+
mtime = (0, import_fs18.statSync)(fullPath).mtimeMs;
|
|
138126
|
+
} catch {
|
|
138127
|
+
}
|
|
138128
|
+
const path2 = decodeProjectPath(dirName);
|
|
138129
|
+
const name = path2.split("/").filter(Boolean).pop() ?? dirName;
|
|
138130
|
+
return { name, path: path2, dirName, mtime };
|
|
138131
|
+
}).sort((a, b2) => b2.mtime - a.mtime);
|
|
138419
138132
|
} catch {
|
|
138420
|
-
|
|
138421
|
-
|
|
138422
|
-
const lastIndexedIso = getCacheMetadata(cacheMetadataRepo, "conversations_last_indexed_at");
|
|
138423
|
-
if (!lastIndexedIso) return true;
|
|
138424
|
-
const lastIndexedMs = Date.parse(lastIndexedIso);
|
|
138425
|
-
if (Number.isNaN(lastIndexedMs)) return true;
|
|
138426
|
-
return dirMtimeMs > lastIndexedMs;
|
|
138427
|
-
}
|
|
138428
|
-
|
|
138429
|
-
// src/services/sessions/ensureSessionProjectIdsFromExistingProjects.ts
|
|
138430
|
-
function ensureSessionProjectIdsFromExistingProjects(projectsRepo, sessionsRepo) {
|
|
138431
|
-
let linked = 0;
|
|
138432
|
-
let missing = 0;
|
|
138433
|
-
for (const session of sessionsRepo.listManagedSessions()) {
|
|
138434
|
-
if (session.projectId) continue;
|
|
138435
|
-
const canonical = canonicalizeProjectPath(session.projectPath);
|
|
138436
|
-
if (!canonical) continue;
|
|
138437
|
-
const project = projectsRepo.getProjectByPath(canonical);
|
|
138438
|
-
if (!project) {
|
|
138439
|
-
missing += 1;
|
|
138440
|
-
continue;
|
|
138441
|
-
}
|
|
138442
|
-
sessionsRepo.updateSessionProjectId({ sessionId: session.id, projectId: project.id });
|
|
138443
|
-
linked += 1;
|
|
138444
|
-
}
|
|
138445
|
-
return { linked, missing };
|
|
138446
|
-
}
|
|
138447
|
-
|
|
138448
|
-
// src/services/projectChats/sortProjectChats.ts
|
|
138449
|
-
function sortProjectChats(a, b2) {
|
|
138450
|
-
const byLatest = compareIsoDesc(a.latestMessageAt, b2.latestMessageAt);
|
|
138451
|
-
if (byLatest !== 0) return byLatest;
|
|
138452
|
-
const byUpdated = compareIsoDesc(a.updatedAt ?? null, b2.updatedAt ?? null);
|
|
138453
|
-
if (byUpdated !== 0) return byUpdated;
|
|
138454
|
-
const byCreated = compareIsoDesc(a.createdAt ?? null, b2.createdAt ?? null);
|
|
138455
|
-
if (byCreated !== 0) return byCreated;
|
|
138456
|
-
return a.title.localeCompare(b2.title);
|
|
138457
|
-
}
|
|
138458
|
-
|
|
138459
|
-
// src/services/projectChats/mergeProjectChats.ts
|
|
138460
|
-
function mergeProjectChats(args) {
|
|
138461
|
-
const { sessions, conversations } = args;
|
|
138462
|
-
const resumedConversationIds = new Set(
|
|
138463
|
-
sessions.filter((c) => c.type === "session").map((c) => c.resumedFromConversationId).filter((id) => Boolean(id))
|
|
138464
|
-
);
|
|
138465
|
-
const visibleConversations = conversations.filter((c) => {
|
|
138466
|
-
if (c.type !== "conversation") return true;
|
|
138467
|
-
return !resumedConversationIds.has(c.id);
|
|
138468
|
-
});
|
|
138469
|
-
return [...sessions, ...visibleConversations].sort(sortProjectChats);
|
|
138470
|
-
}
|
|
138471
|
-
|
|
138472
|
-
// src/services/projectChats/deriveProjectChatTitle.ts
|
|
138473
|
-
function deriveProjectChatTitle(input) {
|
|
138474
|
-
const trimmed = input.title?.trim();
|
|
138475
|
-
if (trimmed) return trimmed;
|
|
138476
|
-
const name = input.projectName?.trim();
|
|
138477
|
-
if (name) return name;
|
|
138478
|
-
const pathSuffix = input.projectPath ? input.projectPath.split(/[/\\]/).filter(Boolean).slice(-2).join("/") : "";
|
|
138479
|
-
if (pathSuffix) return pathSuffix;
|
|
138480
|
-
return `Untitled \xB7 ${input.id.slice(0, 8)}`;
|
|
138481
|
-
}
|
|
138482
|
-
|
|
138483
|
-
// src/services/projectChats/normalizeConversationToProjectChat.ts
|
|
138484
|
-
function normalizeConversationToProjectChat(conversation) {
|
|
138485
|
-
if (!conversation.projectId) {
|
|
138486
|
-
throw new Error(
|
|
138487
|
-
`normalizeConversationToProjectChat: conversation ${conversation.id} has no projectId \u2014 resolve it before normalizing`
|
|
138488
|
-
);
|
|
138489
|
-
}
|
|
138490
|
-
return {
|
|
138491
|
-
type: "conversation",
|
|
138492
|
-
id: conversation.id,
|
|
138493
|
-
projectId: conversation.projectId,
|
|
138494
|
-
projectPath: conversation.projectPath ?? null,
|
|
138495
|
-
title: deriveProjectChatTitle({
|
|
138496
|
-
title: conversation.title,
|
|
138497
|
-
projectName: conversation.projectName,
|
|
138498
|
-
projectPath: conversation.projectPath,
|
|
138499
|
-
id: conversation.id
|
|
138500
|
-
}),
|
|
138501
|
-
latestMessageAt: conversation.lastActivity ?? null,
|
|
138502
|
-
updatedAt: conversation.lastActivity ?? null,
|
|
138503
|
-
createdAt: null,
|
|
138504
|
-
status: "resumable",
|
|
138505
|
-
source: "hdd-cache",
|
|
138506
|
-
provider: conversation.provider ?? CLAUDE_CODE_PROVIDER2,
|
|
138507
|
-
indexedAt: null,
|
|
138508
|
-
fileMtime: null,
|
|
138509
|
-
filePath: conversation.filePath ?? null,
|
|
138510
|
-
sourceHash: null
|
|
138511
|
-
};
|
|
138512
|
-
}
|
|
138513
|
-
|
|
138514
|
-
// src/services/projectChats/normalizeSessionToProjectChat.ts
|
|
138515
|
-
function normalizeSessionToProjectChat(session) {
|
|
138516
|
-
if (!session.projectId) {
|
|
138517
|
-
throw new Error(
|
|
138518
|
-
`normalizeSessionToProjectChat: session ${session.id} has no projectId \u2014 resolve it before normalizing`
|
|
138519
|
-
);
|
|
138520
|
-
}
|
|
138521
|
-
return {
|
|
138522
|
-
type: "session",
|
|
138523
|
-
id: session.id,
|
|
138524
|
-
projectId: session.projectId,
|
|
138525
|
-
projectPath: session.projectPath ?? null,
|
|
138526
|
-
title: deriveProjectChatTitle({
|
|
138527
|
-
title: session.sessionName,
|
|
138528
|
-
projectName: session.projectName,
|
|
138529
|
-
projectPath: session.projectPath,
|
|
138530
|
-
id: session.id
|
|
138531
|
-
}),
|
|
138532
|
-
latestMessageAt: session.lastMessageAt ?? session.lastActivityAt ?? null,
|
|
138533
|
-
updatedAt: session.lastActivityAt ?? null,
|
|
138534
|
-
createdAt: session.startedAt ?? null,
|
|
138535
|
-
status: "active",
|
|
138536
|
-
source: "session-store",
|
|
138537
|
-
resumedFromConversationId: session.resumedFromConversationId ?? null
|
|
138538
|
-
};
|
|
138539
|
-
}
|
|
138540
|
-
|
|
138541
|
-
// src/services/projectChats/listProjectChats.ts
|
|
138542
|
-
async function listProjectChats(deps, args) {
|
|
138543
|
-
const {
|
|
138544
|
-
cache,
|
|
138545
|
-
projectsRepo,
|
|
138546
|
-
conversationsRepo,
|
|
138547
|
-
sessionsRepo,
|
|
138548
|
-
cacheMetadataRepo,
|
|
138549
|
-
getSessionResponses,
|
|
138550
|
-
getFreshScanner,
|
|
138551
|
-
projectsDir
|
|
138552
|
-
} = deps;
|
|
138553
|
-
const needsRefresh = args.refreshConversations || shouldRefreshProjectsFromHdd(conversationsRepo, cacheMetadataRepo, { projectsDir });
|
|
138554
|
-
if (needsRefresh) {
|
|
138555
|
-
const scanner = await getFreshScanner();
|
|
138556
|
-
const metas = [...scanner.getMetadataCache().values()];
|
|
138557
|
-
if (metas.length > 0) {
|
|
138558
|
-
cache.upsertFromScannerMeta(metas);
|
|
138559
|
-
}
|
|
138560
|
-
refreshConversationCache({ cache, projectsRepo, conversationsRepo, cacheMetadataRepo });
|
|
138561
|
-
}
|
|
138562
|
-
ensureSessionProjectIdsFromExistingProjects(projectsRepo, sessionsRepo);
|
|
138563
|
-
const sessionResponses = getSessionResponses();
|
|
138564
|
-
const sessionChats = [];
|
|
138565
|
-
for (const s3 of sessionResponses) {
|
|
138566
|
-
if (!s3.projectId) continue;
|
|
138567
|
-
sessionChats.push(normalizeSessionToProjectChat(s3));
|
|
138568
|
-
}
|
|
138569
|
-
const conversationChats = [];
|
|
138570
|
-
const { conversations } = cache.listConversations({ limit: 1e3, offset: 0 });
|
|
138571
|
-
for (const c of conversations) {
|
|
138572
|
-
if (!c.projectId) continue;
|
|
138573
|
-
conversationChats.push(normalizeConversationToProjectChat(c));
|
|
138574
|
-
}
|
|
138575
|
-
return mergeProjectChats({ sessions: sessionChats, conversations: conversationChats });
|
|
138576
|
-
}
|
|
138577
|
-
|
|
138578
|
-
// src/handlers/handleListProjectChats.ts
|
|
138579
|
-
async function handleListProjectChats(url2, res, deps) {
|
|
138580
|
-
const queryObj = Object.fromEntries(url2.searchParams.entries());
|
|
138581
|
-
const parsed = ListProjectChatsQuerySchema.safeParse(queryObj);
|
|
138582
|
-
if (!parsed.success) {
|
|
138583
|
-
res.writeHead(400, { "Content-Type": "application/json" });
|
|
138584
|
-
res.end(
|
|
138585
|
-
JSON.stringify({
|
|
138586
|
-
error: "Invalid query parameters",
|
|
138587
|
-
details: parsed.error.flatten()
|
|
138588
|
-
})
|
|
138589
|
-
);
|
|
138133
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
138134
|
+
res.end(JSON.stringify({ projects: [], total: 0 }));
|
|
138590
138135
|
return;
|
|
138591
138136
|
}
|
|
138592
|
-
const
|
|
138593
|
-
const
|
|
138137
|
+
const total = entries.length;
|
|
138138
|
+
const page = entries.slice(offset, offset + limit).map(({ name, path: path2, dirName }) => ({ name, path: path2, dirName }));
|
|
138594
138139
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
138595
|
-
res.end(JSON.stringify({
|
|
138140
|
+
res.end(JSON.stringify({ projects: page, total }));
|
|
138596
138141
|
}
|
|
138597
138142
|
|
|
138598
138143
|
// src/server.ts
|
|
@@ -141512,6 +141057,17 @@ function pruneAgentConversations(cache) {
|
|
|
141512
141057
|
return { scanned: rows.length, pruned, missing };
|
|
141513
141058
|
}
|
|
141514
141059
|
|
|
141060
|
+
// src/services/projectChats/deriveProjectChatTitle.ts
|
|
141061
|
+
function deriveProjectChatTitle(input) {
|
|
141062
|
+
const trimmed = input.title?.trim();
|
|
141063
|
+
if (trimmed) return trimmed;
|
|
141064
|
+
const name = input.projectName?.trim();
|
|
141065
|
+
if (name) return name;
|
|
141066
|
+
const pathSuffix = input.projectPath ? input.projectPath.split(/[/\\]/).filter(Boolean).slice(-2).join("/") : "";
|
|
141067
|
+
if (pathSuffix) return pathSuffix;
|
|
141068
|
+
return `Untitled \xB7 ${input.id.slice(0, 8)}`;
|
|
141069
|
+
}
|
|
141070
|
+
|
|
141515
141071
|
// src/services/questions/detectAskUserQuestion.ts
|
|
141516
141072
|
function normalizeContent2(raw2) {
|
|
141517
141073
|
if (Array.isArray(raw2)) return raw2;
|
|
@@ -141941,6 +141497,226 @@ function debounce(fn, waitMs) {
|
|
|
141941
141497
|
return debounced;
|
|
141942
141498
|
}
|
|
141943
141499
|
|
|
141500
|
+
// node_modules/date-fns/constants.js
|
|
141501
|
+
var daysInYear = 365.2425;
|
|
141502
|
+
var maxTime = Math.pow(10, 8) * 24 * 60 * 60 * 1e3;
|
|
141503
|
+
var minTime = -maxTime;
|
|
141504
|
+
var millisecondsInMinute = 6e4;
|
|
141505
|
+
var millisecondsInHour = 36e5;
|
|
141506
|
+
var secondsInHour = 3600;
|
|
141507
|
+
var secondsInDay = secondsInHour * 24;
|
|
141508
|
+
var secondsInWeek = secondsInDay * 7;
|
|
141509
|
+
var secondsInYear = secondsInDay * daysInYear;
|
|
141510
|
+
var secondsInMonth = secondsInYear / 12;
|
|
141511
|
+
var secondsInQuarter = secondsInMonth * 3;
|
|
141512
|
+
var constructFromSymbol = /* @__PURE__ */ Symbol.for("constructDateFrom");
|
|
141513
|
+
|
|
141514
|
+
// node_modules/date-fns/constructFrom.js
|
|
141515
|
+
function constructFrom(date5, value) {
|
|
141516
|
+
if (typeof date5 === "function") return date5(value);
|
|
141517
|
+
if (date5 && typeof date5 === "object" && constructFromSymbol in date5)
|
|
141518
|
+
return date5[constructFromSymbol](value);
|
|
141519
|
+
if (date5 instanceof Date) return new date5.constructor(value);
|
|
141520
|
+
return new Date(value);
|
|
141521
|
+
}
|
|
141522
|
+
|
|
141523
|
+
// node_modules/date-fns/toDate.js
|
|
141524
|
+
function toDate(argument, context) {
|
|
141525
|
+
return constructFrom(context || argument, argument);
|
|
141526
|
+
}
|
|
141527
|
+
|
|
141528
|
+
// node_modules/date-fns/isDate.js
|
|
141529
|
+
function isDate(value) {
|
|
141530
|
+
return value instanceof Date || typeof value === "object" && Object.prototype.toString.call(value) === "[object Date]";
|
|
141531
|
+
}
|
|
141532
|
+
|
|
141533
|
+
// node_modules/date-fns/isValid.js
|
|
141534
|
+
function isValid(date5) {
|
|
141535
|
+
return !(!isDate(date5) && typeof date5 !== "number" || isNaN(+toDate(date5)));
|
|
141536
|
+
}
|
|
141537
|
+
|
|
141538
|
+
// node_modules/date-fns/parseISO.js
|
|
141539
|
+
function parseISO(argument, options) {
|
|
141540
|
+
const invalidDate = () => constructFrom(options?.in, NaN);
|
|
141541
|
+
const additionalDigits = options?.additionalDigits ?? 2;
|
|
141542
|
+
const dateStrings = splitDateString(argument);
|
|
141543
|
+
let date5;
|
|
141544
|
+
if (dateStrings.date) {
|
|
141545
|
+
const parseYearResult = parseYear(dateStrings.date, additionalDigits);
|
|
141546
|
+
date5 = parseDate(parseYearResult.restDateString, parseYearResult.year);
|
|
141547
|
+
}
|
|
141548
|
+
if (!date5 || isNaN(+date5)) return invalidDate();
|
|
141549
|
+
const timestamp = +date5;
|
|
141550
|
+
let time3 = 0;
|
|
141551
|
+
let offset;
|
|
141552
|
+
if (dateStrings.time) {
|
|
141553
|
+
time3 = parseTime(dateStrings.time);
|
|
141554
|
+
if (isNaN(time3)) return invalidDate();
|
|
141555
|
+
}
|
|
141556
|
+
if (dateStrings.timezone) {
|
|
141557
|
+
offset = parseTimezone(dateStrings.timezone);
|
|
141558
|
+
if (isNaN(offset)) return invalidDate();
|
|
141559
|
+
} else {
|
|
141560
|
+
const tmpDate = new Date(timestamp + time3);
|
|
141561
|
+
const result = toDate(0, options?.in);
|
|
141562
|
+
result.setFullYear(
|
|
141563
|
+
tmpDate.getUTCFullYear(),
|
|
141564
|
+
tmpDate.getUTCMonth(),
|
|
141565
|
+
tmpDate.getUTCDate()
|
|
141566
|
+
);
|
|
141567
|
+
result.setHours(
|
|
141568
|
+
tmpDate.getUTCHours(),
|
|
141569
|
+
tmpDate.getUTCMinutes(),
|
|
141570
|
+
tmpDate.getUTCSeconds(),
|
|
141571
|
+
tmpDate.getUTCMilliseconds()
|
|
141572
|
+
);
|
|
141573
|
+
return result;
|
|
141574
|
+
}
|
|
141575
|
+
return toDate(timestamp + time3 + offset, options?.in);
|
|
141576
|
+
}
|
|
141577
|
+
var patterns = {
|
|
141578
|
+
dateTimeDelimiter: /[T ]/,
|
|
141579
|
+
timeZoneDelimiter: /[Z ]/i,
|
|
141580
|
+
timezone: /([Z+-].*)$/
|
|
141581
|
+
};
|
|
141582
|
+
var dateRegex = /^-?(?:(\d{3})|(\d{2})(?:-?(\d{2}))?|W(\d{2})(?:-?(\d{1}))?|)$/;
|
|
141583
|
+
var timeRegex = /^(\d{2}(?:[.,]\d*)?)(?::?(\d{2}(?:[.,]\d*)?))?(?::?(\d{2}(?:[.,]\d*)?))?$/;
|
|
141584
|
+
var timezoneRegex = /^([+-])(\d{2})(?::?(\d{2}))?$/;
|
|
141585
|
+
function splitDateString(dateString) {
|
|
141586
|
+
const dateStrings = {};
|
|
141587
|
+
const array2 = dateString.split(patterns.dateTimeDelimiter);
|
|
141588
|
+
let timeString;
|
|
141589
|
+
if (array2.length > 2) {
|
|
141590
|
+
return dateStrings;
|
|
141591
|
+
}
|
|
141592
|
+
if (/:/.test(array2[0])) {
|
|
141593
|
+
timeString = array2[0];
|
|
141594
|
+
} else {
|
|
141595
|
+
dateStrings.date = array2[0];
|
|
141596
|
+
timeString = array2[1];
|
|
141597
|
+
if (patterns.timeZoneDelimiter.test(dateStrings.date)) {
|
|
141598
|
+
dateStrings.date = dateString.split(patterns.timeZoneDelimiter)[0];
|
|
141599
|
+
timeString = dateString.substr(
|
|
141600
|
+
dateStrings.date.length,
|
|
141601
|
+
dateString.length
|
|
141602
|
+
);
|
|
141603
|
+
}
|
|
141604
|
+
}
|
|
141605
|
+
if (timeString) {
|
|
141606
|
+
const token = patterns.timezone.exec(timeString);
|
|
141607
|
+
if (token) {
|
|
141608
|
+
dateStrings.time = timeString.replace(token[1], "");
|
|
141609
|
+
dateStrings.timezone = token[1];
|
|
141610
|
+
} else {
|
|
141611
|
+
dateStrings.time = timeString;
|
|
141612
|
+
}
|
|
141613
|
+
}
|
|
141614
|
+
return dateStrings;
|
|
141615
|
+
}
|
|
141616
|
+
function parseYear(dateString, additionalDigits) {
|
|
141617
|
+
const regex = new RegExp(
|
|
141618
|
+
"^(?:(\\d{4}|[+-]\\d{" + (4 + additionalDigits) + "})|(\\d{2}|[+-]\\d{" + (2 + additionalDigits) + "})$)"
|
|
141619
|
+
);
|
|
141620
|
+
const captures = dateString.match(regex);
|
|
141621
|
+
if (!captures) return { year: NaN, restDateString: "" };
|
|
141622
|
+
const year = captures[1] ? parseInt(captures[1]) : null;
|
|
141623
|
+
const century = captures[2] ? parseInt(captures[2]) : null;
|
|
141624
|
+
return {
|
|
141625
|
+
year: century === null ? year : century * 100,
|
|
141626
|
+
restDateString: dateString.slice((captures[1] || captures[2]).length)
|
|
141627
|
+
};
|
|
141628
|
+
}
|
|
141629
|
+
function parseDate(dateString, year) {
|
|
141630
|
+
if (year === null) return /* @__PURE__ */ new Date(NaN);
|
|
141631
|
+
const captures = dateString.match(dateRegex);
|
|
141632
|
+
if (!captures) return /* @__PURE__ */ new Date(NaN);
|
|
141633
|
+
const isWeekDate = !!captures[4];
|
|
141634
|
+
const dayOfYear = parseDateUnit(captures[1]);
|
|
141635
|
+
const month = parseDateUnit(captures[2]) - 1;
|
|
141636
|
+
const day = parseDateUnit(captures[3]);
|
|
141637
|
+
const week = parseDateUnit(captures[4]);
|
|
141638
|
+
const dayOfWeek = parseDateUnit(captures[5]) - 1;
|
|
141639
|
+
if (isWeekDate) {
|
|
141640
|
+
if (!validateWeekDate(year, week, dayOfWeek)) {
|
|
141641
|
+
return /* @__PURE__ */ new Date(NaN);
|
|
141642
|
+
}
|
|
141643
|
+
return dayOfISOWeekYear(year, week, dayOfWeek);
|
|
141644
|
+
} else {
|
|
141645
|
+
const date5 = /* @__PURE__ */ new Date(0);
|
|
141646
|
+
if (!validateDate(year, month, day) || !validateDayOfYearDate(year, dayOfYear)) {
|
|
141647
|
+
return /* @__PURE__ */ new Date(NaN);
|
|
141648
|
+
}
|
|
141649
|
+
date5.setUTCFullYear(year, month, Math.max(dayOfYear, day));
|
|
141650
|
+
return date5;
|
|
141651
|
+
}
|
|
141652
|
+
}
|
|
141653
|
+
function parseDateUnit(value) {
|
|
141654
|
+
return value ? parseInt(value) : 1;
|
|
141655
|
+
}
|
|
141656
|
+
function parseTime(timeString) {
|
|
141657
|
+
const captures = timeString.match(timeRegex);
|
|
141658
|
+
if (!captures) return NaN;
|
|
141659
|
+
const hours = parseTimeUnit(captures[1]);
|
|
141660
|
+
const minutes = parseTimeUnit(captures[2]);
|
|
141661
|
+
const seconds = parseTimeUnit(captures[3]);
|
|
141662
|
+
if (!validateTime(hours, minutes, seconds)) {
|
|
141663
|
+
return NaN;
|
|
141664
|
+
}
|
|
141665
|
+
return hours * millisecondsInHour + minutes * millisecondsInMinute + seconds * 1e3;
|
|
141666
|
+
}
|
|
141667
|
+
function parseTimeUnit(value) {
|
|
141668
|
+
return value && parseFloat(value.replace(",", ".")) || 0;
|
|
141669
|
+
}
|
|
141670
|
+
function parseTimezone(timezoneString) {
|
|
141671
|
+
if (timezoneString === "Z") return 0;
|
|
141672
|
+
const captures = timezoneString.match(timezoneRegex);
|
|
141673
|
+
if (!captures) return 0;
|
|
141674
|
+
const sign = captures[1] === "+" ? -1 : 1;
|
|
141675
|
+
const hours = parseInt(captures[2]);
|
|
141676
|
+
const minutes = captures[3] && parseInt(captures[3]) || 0;
|
|
141677
|
+
if (!validateTimezone(hours, minutes)) {
|
|
141678
|
+
return NaN;
|
|
141679
|
+
}
|
|
141680
|
+
return sign * (hours * millisecondsInHour + minutes * millisecondsInMinute);
|
|
141681
|
+
}
|
|
141682
|
+
function dayOfISOWeekYear(isoWeekYear, week, day) {
|
|
141683
|
+
const date5 = /* @__PURE__ */ new Date(0);
|
|
141684
|
+
date5.setUTCFullYear(isoWeekYear, 0, 4);
|
|
141685
|
+
const fourthOfJanuaryDay = date5.getUTCDay() || 7;
|
|
141686
|
+
const diff = (week - 1) * 7 + day + 1 - fourthOfJanuaryDay;
|
|
141687
|
+
date5.setUTCDate(date5.getUTCDate() + diff);
|
|
141688
|
+
return date5;
|
|
141689
|
+
}
|
|
141690
|
+
var daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
141691
|
+
function isLeapYearIndex(year) {
|
|
141692
|
+
return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;
|
|
141693
|
+
}
|
|
141694
|
+
function validateDate(year, month, date5) {
|
|
141695
|
+
return month >= 0 && month <= 11 && date5 >= 1 && date5 <= (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28));
|
|
141696
|
+
}
|
|
141697
|
+
function validateDayOfYearDate(year, dayOfYear) {
|
|
141698
|
+
return dayOfYear >= 1 && dayOfYear <= (isLeapYearIndex(year) ? 366 : 365);
|
|
141699
|
+
}
|
|
141700
|
+
function validateWeekDate(_year, week, day) {
|
|
141701
|
+
return week >= 1 && week <= 53 && day >= 0 && day <= 6;
|
|
141702
|
+
}
|
|
141703
|
+
function validateTime(hours, minutes, seconds) {
|
|
141704
|
+
if (hours === 24) {
|
|
141705
|
+
return minutes === 0 && seconds === 0;
|
|
141706
|
+
}
|
|
141707
|
+
return seconds >= 0 && seconds < 60 && minutes >= 0 && minutes < 60 && hours >= 0 && hours < 25;
|
|
141708
|
+
}
|
|
141709
|
+
function validateTimezone(_hours, minutes) {
|
|
141710
|
+
return minutes >= 0 && minutes <= 59;
|
|
141711
|
+
}
|
|
141712
|
+
|
|
141713
|
+
// src/utils/dates.ts
|
|
141714
|
+
function parseIsoDateOrNull(value) {
|
|
141715
|
+
if (!value) return null;
|
|
141716
|
+
const parsed = parseISO(value);
|
|
141717
|
+
return isValid(parsed) ? parsed : null;
|
|
141718
|
+
}
|
|
141719
|
+
|
|
141944
141720
|
// src/utils/isScannedSnapshotStale.ts
|
|
141945
141721
|
var STALENESS_TOLERANCE_MS = 1e3;
|
|
141946
141722
|
function isScannedSnapshotStale(snapshotTimestamp, fileMtimeMs) {
|
|
@@ -142077,6 +141853,7 @@ var WSHub = class {
|
|
|
142077
141853
|
|
|
142078
141854
|
// src/server.ts
|
|
142079
141855
|
var BROWSE_SYSTEM_PROMPT = (browseRoot) => `You are working within the project boundary: ${browseRoot}. Do not read, write, or execute commands that access files or directories outside this boundary.`;
|
|
141856
|
+
var DEFAULT_SYSTEM_PROMPT = "When presenting options or choices to the user, limit the options to at most 3.";
|
|
142080
141857
|
var DEFAULT_PTY_GRACE_PERIOD_MS = 27e4;
|
|
142081
141858
|
function parseIncludeAgentsEnv(raw2) {
|
|
142082
141859
|
if (raw2 === void 0) return false;
|
|
@@ -142115,6 +141892,7 @@ var StreamerServer = class {
|
|
|
142115
141892
|
binding = false;
|
|
142116
141893
|
cacheReady = false;
|
|
142117
141894
|
apiKey;
|
|
141895
|
+
apiKeySource;
|
|
142118
141896
|
localNoAuth;
|
|
142119
141897
|
logMenubarRequests;
|
|
142120
141898
|
verbose;
|
|
@@ -142126,7 +141904,10 @@ var StreamerServer = class {
|
|
|
142126
141904
|
publicUrl = null;
|
|
142127
141905
|
pairTokens = new PairTokenStore();
|
|
142128
141906
|
exchangeAttempts = /* @__PURE__ */ new Map();
|
|
141907
|
+
sessionStartAttempts = /* @__PURE__ */ new Map();
|
|
141908
|
+
sessionInputAttempts = /* @__PURE__ */ new Map();
|
|
142129
141909
|
ptyGracePeriodMs;
|
|
141910
|
+
defaultSystemPrompt;
|
|
142130
141911
|
// Map of sessionId → grace timer; fires to kill PTY after WS disconnect
|
|
142131
141912
|
ptyGraceTimers = /* @__PURE__ */ new Map();
|
|
142132
141913
|
// Map of sessionId → set of subscribed WS clients
|
|
@@ -142160,13 +141941,20 @@ var StreamerServer = class {
|
|
|
142160
141941
|
constructor(config2) {
|
|
142161
141942
|
this.sessionStatusBus.setMaxListeners(0);
|
|
142162
141943
|
this.apiKey = config2.apiKey;
|
|
141944
|
+
this.apiKeySource = config2.apiKeySource ?? "config";
|
|
142163
141945
|
this.localNoAuth = config2.localNoAuth ?? false;
|
|
142164
141946
|
this.logMenubarRequests = config2.logMenubarRequests ?? false;
|
|
141947
|
+
if (this.localNoAuth) {
|
|
141948
|
+
console.warn(
|
|
141949
|
+
"[WARN] localNoAuth is ENABLED \u2014 all requests from localhost bypass authentication. Do not run with --local-no-auth in shared or production environments."
|
|
141950
|
+
);
|
|
141951
|
+
}
|
|
142165
141952
|
this.verbose = config2.verbose ?? false;
|
|
142166
141953
|
this.disableDb = config2.disableDb ?? false;
|
|
142167
141954
|
this.scanProfiles = config2.scanProfiles;
|
|
142168
141955
|
this.codexRoots = config2.codexRoots ?? [(0, import_path19.join)((0, import_os10.homedir)(), ".codex", "sessions")];
|
|
142169
141956
|
this.ptyGracePeriodMs = config2.ptyGracePeriodMs ?? DEFAULT_PTY_GRACE_PERIOD_MS;
|
|
141957
|
+
this.defaultSystemPrompt = config2.defaultSystemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
142170
141958
|
this.cacheDir = config2.cacheDir ?? loadCacheDir() ?? (0, import_path19.join)((0, import_os10.homedir)(), ".threadbase", "cache");
|
|
142171
141959
|
this.tailSize = config2.tailSize ?? loadTailSize() ?? 10;
|
|
142172
141960
|
this.directoryDebounceMs = parseDirScanDebounceEnv(process.env.THREADBASE_DIR_SCAN_DEBOUNCE_MS) ?? config2.directoryScanDebounceMs ?? 1e3;
|
|
@@ -142338,10 +142126,15 @@ var StreamerServer = class {
|
|
|
142338
142126
|
});
|
|
142339
142127
|
}
|
|
142340
142128
|
const agentClient = this.agentClient;
|
|
142129
|
+
const self2 = this;
|
|
142341
142130
|
const apiDeps = {
|
|
142342
|
-
|
|
142131
|
+
// ponytail: getter so rotateApiKey() takes effect without restarting the server
|
|
142132
|
+
get apiKey() {
|
|
142133
|
+
return self2.apiKey;
|
|
142134
|
+
},
|
|
142343
142135
|
localNoAuth: this.localNoAuth,
|
|
142344
142136
|
logMenubarRequests: this.logMenubarRequests,
|
|
142137
|
+
rotateApiKey: () => this.rotateApiKey(),
|
|
142345
142138
|
publicUrl: this.publicUrl,
|
|
142346
142139
|
browseRoot: this.browseRoot,
|
|
142347
142140
|
ptyManager: this.ptyManager,
|
|
@@ -142372,8 +142165,8 @@ var StreamerServer = class {
|
|
|
142372
142165
|
handleConversationsCount: (url2, res) => this.handleConversationsCount(url2, res),
|
|
142373
142166
|
handleGetConversation: (id, url2, res, ifNoneMatch) => this.handleGetConversation(id, url2, res, ifNoneMatch),
|
|
142374
142167
|
handleSearch: (url2, res) => this.handleSearch(url2, res),
|
|
142168
|
+
handleListProjects: (url2, res) => handleListProjects(url2, res),
|
|
142375
142169
|
handleGetPopularProjects: (url2, res) => this.handleGetPopularProjects(url2, res),
|
|
142376
|
-
handleListProjectChats: (url2, res) => this.handleListProjectChats(url2, res),
|
|
142377
142170
|
handlePairStart: (res) => this.handlePairStart(res),
|
|
142378
142171
|
handlePairExchange: (req, res) => this.handlePairExchange(req, res),
|
|
142379
142172
|
handleBrowse: (url2, res) => this.handleBrowse(url2, res),
|
|
@@ -142808,19 +142601,38 @@ var StreamerServer = class {
|
|
|
142808
142601
|
machineName: hostname4()
|
|
142809
142602
|
});
|
|
142810
142603
|
}
|
|
142811
|
-
|
|
142604
|
+
rotateApiKey() {
|
|
142605
|
+
const newKey = generateApiKey();
|
|
142606
|
+
const persisted = this.apiKeySource === "config";
|
|
142607
|
+
if (persisted) setApiKey(newKey);
|
|
142608
|
+
this.apiKey = newKey;
|
|
142609
|
+
return { newKey, persisted };
|
|
142610
|
+
}
|
|
142611
|
+
checkRateLimit(map2, key, limit, windowMs) {
|
|
142812
142612
|
const now = Date.now();
|
|
142813
|
-
const
|
|
142814
|
-
const limit = 5;
|
|
142815
|
-
const arr = (this.exchangeAttempts.get(ip) ?? []).filter((t2) => now - t2 < windowMs);
|
|
142613
|
+
const arr = (map2.get(key) ?? []).filter((t2) => now - t2 < windowMs);
|
|
142816
142614
|
if (arr.length >= limit) {
|
|
142817
|
-
|
|
142615
|
+
map2.set(key, arr);
|
|
142818
142616
|
return false;
|
|
142819
142617
|
}
|
|
142820
142618
|
arr.push(now);
|
|
142821
|
-
|
|
142619
|
+
map2.set(key, arr);
|
|
142620
|
+
setTimeout(() => {
|
|
142621
|
+
const remaining = (map2.get(key) ?? []).filter((t2) => Date.now() - t2 < windowMs);
|
|
142622
|
+
if (remaining.length === 0) map2.delete(key);
|
|
142623
|
+
else map2.set(key, remaining);
|
|
142624
|
+
}, windowMs);
|
|
142822
142625
|
return true;
|
|
142823
142626
|
}
|
|
142627
|
+
checkExchangeRateLimit(ip) {
|
|
142628
|
+
return this.checkRateLimit(this.exchangeAttempts, ip, 5, 6e4);
|
|
142629
|
+
}
|
|
142630
|
+
checkSessionStartRateLimit(ip) {
|
|
142631
|
+
return this.checkRateLimit(this.sessionStartAttempts, ip, 10, 6e4);
|
|
142632
|
+
}
|
|
142633
|
+
checkSessionInputRateLimit(sessionId) {
|
|
142634
|
+
return this.checkRateLimit(this.sessionInputAttempts, sessionId, 500, 6e4);
|
|
142635
|
+
}
|
|
142824
142636
|
async handleListConversations(url2, res) {
|
|
142825
142637
|
const limit = intParam(url2, "limit", 50);
|
|
142826
142638
|
const offset = intParam(url2, "offset", 0);
|
|
@@ -142982,21 +142794,6 @@ var StreamerServer = class {
|
|
|
142982
142794
|
const projects = this.cache.getPopularProjects(limit);
|
|
142983
142795
|
json2(res, 200, { projects, total: projects.length });
|
|
142984
142796
|
}
|
|
142985
|
-
async handleListProjectChats(url2, res) {
|
|
142986
|
-
if (!this.cache || !this.projectsRepo || !this.conversationsRepo || !this.sessionsRepo || !this.cacheMetadataRepo) {
|
|
142987
|
-
json2(res, 503, { error: "Cache not available" });
|
|
142988
|
-
return;
|
|
142989
|
-
}
|
|
142990
|
-
await handleListProjectChats(url2, res, {
|
|
142991
|
-
cache: this.cache,
|
|
142992
|
-
projectsRepo: this.projectsRepo,
|
|
142993
|
-
conversationsRepo: this.conversationsRepo,
|
|
142994
|
-
sessionsRepo: this.sessionsRepo,
|
|
142995
|
-
cacheMetadataRepo: this.cacheMetadataRepo,
|
|
142996
|
-
getSessionResponses: () => this.sessionStore.list(this.ptyAttachedIds()),
|
|
142997
|
-
getFreshScanner: () => this.getFreshScanner()
|
|
142998
|
-
});
|
|
142999
|
-
}
|
|
143000
142797
|
buildStatCache(previousScanner) {
|
|
143001
142798
|
if (!this.cache) return void 0;
|
|
143002
142799
|
const dbStats = this.cache.getFileStats();
|
|
@@ -143473,6 +143270,10 @@ var StreamerServer = class {
|
|
|
143473
143270
|
}
|
|
143474
143271
|
}
|
|
143475
143272
|
async handleSendInput(sessionId, req, res) {
|
|
143273
|
+
if (!this.checkSessionInputRateLimit(sessionId)) {
|
|
143274
|
+
json2(res, 429, { error: "Too many input requests for this session. Please slow down." });
|
|
143275
|
+
return;
|
|
143276
|
+
}
|
|
143476
143277
|
if (this.agentConfig.enabled) {
|
|
143477
143278
|
const body2 = await readBody(req);
|
|
143478
143279
|
const cache = this.cache;
|
|
@@ -143754,6 +143555,13 @@ var StreamerServer = class {
|
|
|
143754
143555
|
json2(res, 201, { sessionId: session.id });
|
|
143755
143556
|
}
|
|
143756
143557
|
async handleStartSession(req, res) {
|
|
143558
|
+
const ip = req.socket?.remoteAddress ?? "unknown";
|
|
143559
|
+
if (!this.checkSessionStartRateLimit(ip)) {
|
|
143560
|
+
json2(res, 429, {
|
|
143561
|
+
error: "Too many session start requests. Please wait before trying again."
|
|
143562
|
+
});
|
|
143563
|
+
return;
|
|
143564
|
+
}
|
|
143757
143565
|
if (this.agentConfig.enabled) {
|
|
143758
143566
|
const body2 = await readBody(req);
|
|
143759
143567
|
const result = await handleStartAgentSession(body2, {
|
|
@@ -143777,7 +143585,7 @@ var StreamerServer = class {
|
|
|
143777
143585
|
return;
|
|
143778
143586
|
}
|
|
143779
143587
|
const body = await readBody(req);
|
|
143780
|
-
const { path: relativePath } = body;
|
|
143588
|
+
const { path: relativePath, systemPrompt: clientPrompt } = body;
|
|
143781
143589
|
if (typeof relativePath !== "string") {
|
|
143782
143590
|
json2(res, 400, { error: "Missing path field" });
|
|
143783
143591
|
return;
|
|
@@ -143791,11 +143599,16 @@ var StreamerServer = class {
|
|
|
143791
143599
|
return;
|
|
143792
143600
|
}
|
|
143793
143601
|
this.discoveryCache = null;
|
|
143602
|
+
const systemPromptParts = [
|
|
143603
|
+
this.defaultSystemPrompt,
|
|
143604
|
+
BROWSE_SYSTEM_PROMPT(this.browseRoot),
|
|
143605
|
+
typeof clientPrompt === "string" ? clientPrompt : null
|
|
143606
|
+
].filter(Boolean);
|
|
143794
143607
|
try {
|
|
143795
143608
|
const session = await this.ptyManager.startFresh({
|
|
143796
143609
|
projectPath: resolvedPath,
|
|
143797
143610
|
projectName: body.projectName,
|
|
143798
|
-
systemPrompt:
|
|
143611
|
+
systemPrompt: systemPromptParts.join("\n")
|
|
143799
143612
|
});
|
|
143800
143613
|
this.sessionStore.addManaged(session);
|
|
143801
143614
|
json2(res, 202, { id: session.id, status: "pending" });
|
|
@@ -144272,7 +144085,7 @@ async function checkForUpdate(opts) {
|
|
|
144272
144085
|
}
|
|
144273
144086
|
|
|
144274
144087
|
// src/updater/install.ts
|
|
144275
|
-
var
|
|
144088
|
+
var import_node_fs18 = require("fs");
|
|
144276
144089
|
|
|
144277
144090
|
// src/updater/active-sessions.ts
|
|
144278
144091
|
async function countActiveSessions(opts) {
|
|
@@ -147556,14 +147369,29 @@ async function unpackTarball(opts) {
|
|
|
147556
147369
|
await So({ file: tarballPath, cwd: destDir });
|
|
147557
147370
|
}
|
|
147558
147371
|
|
|
147372
|
+
// src/updater/update-log.ts
|
|
147373
|
+
var import_node_fs17 = require("fs");
|
|
147374
|
+
var import_node_path21 = require("path");
|
|
147375
|
+
var LOG_PATH = (0, import_node_path21.join)(THREADBASE_ROOT, "update.log");
|
|
147376
|
+
function appendUpdateLog(line) {
|
|
147377
|
+
try {
|
|
147378
|
+
(0, import_node_fs17.mkdirSync)(THREADBASE_ROOT, { recursive: true });
|
|
147379
|
+
(0, import_node_fs17.appendFileSync)(LOG_PATH, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
147380
|
+
`, "utf8");
|
|
147381
|
+
} catch {
|
|
147382
|
+
}
|
|
147383
|
+
}
|
|
147384
|
+
|
|
147559
147385
|
// src/updater/install.ts
|
|
147560
147386
|
async function runInstall(opts) {
|
|
147561
147387
|
if (isBrewInstall()) {
|
|
147562
|
-
|
|
147388
|
+
const result = {
|
|
147563
147389
|
kind: "unsupported-install",
|
|
147564
147390
|
reason: "Installed via Homebrew \u2014 run `brew upgrade tb-streamer` to update.",
|
|
147565
147391
|
current: opts.currentVersion
|
|
147566
147392
|
};
|
|
147393
|
+
appendUpdateLog(`[no-op] ${result.reason}`);
|
|
147394
|
+
return result;
|
|
147567
147395
|
}
|
|
147568
147396
|
const check2 = await checkForUpdate({
|
|
147569
147397
|
currentVersion: opts.currentVersion,
|
|
@@ -147571,6 +147399,9 @@ async function runInstall(opts) {
|
|
|
147571
147399
|
pinnedVersion: opts.pinnedVersion,
|
|
147572
147400
|
allowMajor: opts.allowMajor
|
|
147573
147401
|
});
|
|
147402
|
+
appendUpdateLog(
|
|
147403
|
+
`[check] current=${check2.current} latest=${check2.latest ?? "none"} status=${check2.reason}`
|
|
147404
|
+
);
|
|
147574
147405
|
if (!check2.wouldInstall) {
|
|
147575
147406
|
return { kind: "no-op", reason: check2.reason, current: check2.current, latest: check2.latest };
|
|
147576
147407
|
}
|
|
@@ -147596,33 +147427,27 @@ async function runInstall(opts) {
|
|
|
147596
147427
|
const artifact = pickArtifact(manifest);
|
|
147597
147428
|
if (opts.dryRun) {
|
|
147598
147429
|
const asset = target.assets.find((a) => a.name === artifact.filename);
|
|
147599
|
-
|
|
147600
|
-
|
|
147601
|
-
|
|
147602
|
-
|
|
147603
|
-
};
|
|
147430
|
+
const tarballUrl = asset?.browserDownloadUrl ?? "(missing)";
|
|
147431
|
+
appendUpdateLog(
|
|
147432
|
+
`[dry-run] would install ${check2.current} \u2192 ${targetVersion} from ${tarballUrl}`
|
|
147433
|
+
);
|
|
147434
|
+
return { kind: "dry-run", latest: targetVersion, tarballUrl };
|
|
147604
147435
|
}
|
|
147605
147436
|
if (opts.config.defer_if_active_sessions && !opts.force && opts.runningServer) {
|
|
147606
147437
|
const active = await countActiveSessions(opts.runningServer);
|
|
147607
147438
|
if (active.kind === "count" && active.count > 0) {
|
|
147608
|
-
|
|
147609
|
-
|
|
147610
|
-
|
|
147611
|
-
activeSessions: active.count,
|
|
147612
|
-
latest: targetVersion
|
|
147613
|
-
};
|
|
147439
|
+
const reason = `${active.count} active session(s); use --force to interrupt`;
|
|
147440
|
+
appendUpdateLog(`[deferred] ${check2.current} \u2192 ${targetVersion}: ${reason}`);
|
|
147441
|
+
return { kind: "deferred", reason, activeSessions: active.count, latest: targetVersion };
|
|
147614
147442
|
}
|
|
147615
147443
|
if (active.kind === "error") {
|
|
147616
|
-
|
|
147617
|
-
|
|
147618
|
-
|
|
147619
|
-
activeSessions: -1,
|
|
147620
|
-
latest: targetVersion
|
|
147621
|
-
};
|
|
147444
|
+
const reason = `cannot determine active sessions (${active.reason}); use --force to override`;
|
|
147445
|
+
appendUpdateLog(`[deferred] ${check2.current} \u2192 ${targetVersion}: ${reason}`);
|
|
147446
|
+
return { kind: "deferred", reason, activeSessions: -1, latest: targetVersion };
|
|
147622
147447
|
}
|
|
147623
147448
|
}
|
|
147624
147449
|
ensureReleasesDir();
|
|
147625
|
-
(0,
|
|
147450
|
+
(0, import_node_fs18.mkdirSync)(DOWNLOAD_DIR, { recursive: true });
|
|
147626
147451
|
const tarballPath = downloadPath(targetVersion, artifact.filename);
|
|
147627
147452
|
await downloadAndVerify({ manifest, assets: target.assets, targetPath: tarballPath });
|
|
147628
147453
|
const destDir = releaseDir(targetVersion);
|
|
@@ -147641,18 +147466,22 @@ async function runInstall(opts) {
|
|
|
147641
147466
|
} catch (err) {
|
|
147642
147467
|
restartMethod = `failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
147643
147468
|
}
|
|
147644
|
-
|
|
147469
|
+
const installed = {
|
|
147645
147470
|
kind: "installed",
|
|
147646
147471
|
previous: check2.current,
|
|
147647
147472
|
installed: targetVersion,
|
|
147648
147473
|
pruned,
|
|
147649
147474
|
restart: { method: restartMethod }
|
|
147650
147475
|
};
|
|
147476
|
+
appendUpdateLog(
|
|
147477
|
+
`[installed] ${installed.previous} \u2192 ${installed.installed} restart=${installed.restart.method}${pruned.length > 0 ? ` pruned=${pruned.length}` : ""}`
|
|
147478
|
+
);
|
|
147479
|
+
return installed;
|
|
147651
147480
|
}
|
|
147652
147481
|
|
|
147653
147482
|
// cli/prod.ts
|
|
147654
147483
|
var import_node_child_process6 = require("child_process");
|
|
147655
|
-
var
|
|
147484
|
+
var import_node_fs20 = require("fs");
|
|
147656
147485
|
init_constants();
|
|
147657
147486
|
init_launchd();
|
|
147658
147487
|
init_marker();
|
|
@@ -147738,7 +147567,7 @@ async function runProdDoctor(opts) {
|
|
|
147738
147567
|
return { findings, repairs };
|
|
147739
147568
|
}
|
|
147740
147569
|
var defaultSpawnTail = ({ files, lines, follow }) => {
|
|
147741
|
-
const existing = files.filter((f2) => (0,
|
|
147570
|
+
const existing = files.filter((f2) => (0, import_node_fs20.existsSync)(f2));
|
|
147742
147571
|
if (existing.length === 0) {
|
|
147743
147572
|
return Promise.resolve({
|
|
147744
147573
|
ok: false,
|
|
@@ -147894,6 +147723,7 @@ program2.command("serve").description("Start the streamer server").option("-p, -
|
|
|
147894
147723
|
const server = new StreamerServer({
|
|
147895
147724
|
port: resolvedPort,
|
|
147896
147725
|
apiKey,
|
|
147726
|
+
apiKeySource: opts.apiKey ? "cli" : "config",
|
|
147897
147727
|
localNoAuth: opts.localNoAuth,
|
|
147898
147728
|
verbose: opts.verbose,
|
|
147899
147729
|
logMenubarRequests: opts.logMenubarRequests,
|
|
@@ -147957,8 +147787,8 @@ program2.command("cache").description("Manage the local SQLite conversation cach
|
|
|
147957
147787
|
`${process.env.HOME}/.threadbase/cache`
|
|
147958
147788
|
).action((opts) => {
|
|
147959
147789
|
const { rmSync: rmSync6, existsSync: existsSync11 } = require("fs");
|
|
147960
|
-
const { join:
|
|
147961
|
-
const dbPath =
|
|
147790
|
+
const { join: join25 } = require("path");
|
|
147791
|
+
const dbPath = join25(opts.cacheDir, "cache.db");
|
|
147962
147792
|
for (const suffix of ["", "-shm", "-wal"]) {
|
|
147963
147793
|
const f2 = dbPath + suffix;
|
|
147964
147794
|
if (existsSync11(f2)) {
|
|
@@ -148007,6 +147837,9 @@ program2.command("update").description("Check for streamer updates from GitHub R
|
|
|
148007
147837
|
pinnedVersion: opts.version,
|
|
148008
147838
|
allowMajor: opts.allowMajor
|
|
148009
147839
|
});
|
|
147840
|
+
appendUpdateLog(
|
|
147841
|
+
`[check] current=${result2.current} latest=${result2.latest ?? "none"} status=${result2.reason}`
|
|
147842
|
+
);
|
|
148010
147843
|
log7.info(`Current : ${result2.current}`, void 0, "console");
|
|
148011
147844
|
log7.info(`Latest : ${result2.latest ?? "(none)"}`, void 0, "console");
|
|
148012
147845
|
log7.info(`Channel : ${cfg.channel}`, void 0, "console");
|
|
@@ -148059,6 +147892,7 @@ program2.command("update").description("Check for streamer updates from GitHub R
|
|
|
148059
147892
|
}
|
|
148060
147893
|
} catch (err) {
|
|
148061
147894
|
const message = err instanceof Error ? err.message : String(err);
|
|
147895
|
+
appendUpdateLog(`[error] ${message}`);
|
|
148062
147896
|
log7.error(`Update failed: ${message}`, { error: message }, "console");
|
|
148063
147897
|
process.exitCode = 1;
|
|
148064
147898
|
}
|