@xdsjs/dossierx-daemon 0.1.0 → 0.1.2
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/index.js +147 -7
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { stat as stat4 } from "fs/promises";
|
|
4
|
+
import { mkdir as mkdir6, stat as stat4 } from "fs/promises";
|
|
5
5
|
import os3 from "os";
|
|
6
6
|
import path8 from "path";
|
|
7
7
|
import { Command } from "commander";
|
|
@@ -112,7 +112,7 @@ function resolveCodexModel(options, env = process.env) {
|
|
|
112
112
|
return options.codexModel?.trim() || env.DOSSIERX_CODEX_MODEL?.trim() || void 0;
|
|
113
113
|
}
|
|
114
114
|
function resolveCodexSandbox(options, env = process.env) {
|
|
115
|
-
const value = options.codexSandbox?.trim() || env.DOSSIERX_CODEX_SANDBOX?.trim() || "
|
|
115
|
+
const value = options.codexSandbox?.trim() || env.DOSSIERX_CODEX_SANDBOX?.trim() || "danger-full-access";
|
|
116
116
|
if (CodexSandboxModes.includes(value)) {
|
|
117
117
|
return value;
|
|
118
118
|
}
|
|
@@ -425,7 +425,7 @@ function createCodexRunner(config) {
|
|
|
425
425
|
kind: "codex",
|
|
426
426
|
async runInvestWikiFlow(input, callbacks) {
|
|
427
427
|
const modelArgs = config.model ? ["-m", config.model] : [];
|
|
428
|
-
const sandbox = config.sandbox ?? "
|
|
428
|
+
const sandbox = config.sandbox ?? "danger-full-access";
|
|
429
429
|
let stdout = "";
|
|
430
430
|
let stderr = "";
|
|
431
431
|
const stdoutLineBuffer = { value: "" };
|
|
@@ -784,6 +784,10 @@ function createTaskArchive(options) {
|
|
|
784
784
|
};
|
|
785
785
|
}
|
|
786
786
|
|
|
787
|
+
// src/version.ts
|
|
788
|
+
var DAEMON_PACKAGE_NAME = "@xdsjs/dossierx-daemon";
|
|
789
|
+
var DAEMON_VERSION = "0.1.2";
|
|
790
|
+
|
|
787
791
|
// src/local-api/server.ts
|
|
788
792
|
var DEFAULT_MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
789
793
|
var ALLOWED_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".mdx", ".txt", ".json"]);
|
|
@@ -792,7 +796,7 @@ function json(response, status, body, origin) {
|
|
|
792
796
|
response.writeHead(status, {
|
|
793
797
|
"content-type": "application/json; charset=utf-8",
|
|
794
798
|
...origin ? { "access-control-allow-origin": origin } : {},
|
|
795
|
-
"access-control-allow-methods": "GET, OPTIONS",
|
|
799
|
+
"access-control-allow-methods": "GET, POST, OPTIONS",
|
|
796
800
|
"access-control-allow-headers": "content-type",
|
|
797
801
|
vary: "Origin"
|
|
798
802
|
});
|
|
@@ -948,9 +952,91 @@ async function detectCodexCommands(configuredCommand) {
|
|
|
948
952
|
return true;
|
|
949
953
|
});
|
|
950
954
|
}
|
|
955
|
+
function updateCommand(packageName) {
|
|
956
|
+
return `npm install -g ${packageName}@latest`;
|
|
957
|
+
}
|
|
958
|
+
function versionParts(value) {
|
|
959
|
+
const plain = value.trim().replace(/^v/, "").split(/[+-]/)[0] ?? "";
|
|
960
|
+
return plain.split(".").map((part) => {
|
|
961
|
+
const valuePart = Number.parseInt(part, 10);
|
|
962
|
+
return Number.isFinite(valuePart) ? valuePart : 0;
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
function isNewerVersion(candidate, current) {
|
|
966
|
+
if (!candidate) {
|
|
967
|
+
return false;
|
|
968
|
+
}
|
|
969
|
+
const nextParts = versionParts(candidate);
|
|
970
|
+
const currentParts = versionParts(current);
|
|
971
|
+
const length = Math.max(nextParts.length, currentParts.length);
|
|
972
|
+
for (let index = 0; index < length; index += 1) {
|
|
973
|
+
const next = nextParts[index] ?? 0;
|
|
974
|
+
const existing = currentParts[index] ?? 0;
|
|
975
|
+
if (next > existing) {
|
|
976
|
+
return true;
|
|
977
|
+
}
|
|
978
|
+
if (next < existing) {
|
|
979
|
+
return false;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
return false;
|
|
983
|
+
}
|
|
984
|
+
async function defaultLatestDaemonVersion(packageName) {
|
|
985
|
+
const result = await execa3("npm", ["view", packageName, "version"], {
|
|
986
|
+
stdin: "ignore",
|
|
987
|
+
timeout: 8e3,
|
|
988
|
+
reject: false
|
|
989
|
+
});
|
|
990
|
+
if (result.exitCode !== 0) {
|
|
991
|
+
return null;
|
|
992
|
+
}
|
|
993
|
+
return result.stdout.trim().replace(/^"|"$/g, "") || null;
|
|
994
|
+
}
|
|
995
|
+
async function defaultUpdateDaemonPackage(input) {
|
|
996
|
+
const customCommand = process.env.DOSSIERX_DAEMON_UPDATE_COMMAND?.trim();
|
|
997
|
+
const result = customCommand ? await execa3("/bin/zsh", ["-lc", customCommand], {
|
|
998
|
+
stdin: "ignore",
|
|
999
|
+
timeout: 12e4,
|
|
1000
|
+
reject: false
|
|
1001
|
+
}) : await execa3("npm", ["install", "-g", `${input.packageName}@latest`], {
|
|
1002
|
+
stdin: "ignore",
|
|
1003
|
+
timeout: 12e4,
|
|
1004
|
+
reject: false
|
|
1005
|
+
});
|
|
1006
|
+
if (result.exitCode !== 0) {
|
|
1007
|
+
throw new Error(
|
|
1008
|
+
(result.stderr || result.stdout || "Daemon package update failed").trim()
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
const latestVersion = await input.latestDaemonVersion(input.packageName) ?? input.latestVersion;
|
|
1012
|
+
return {
|
|
1013
|
+
currentVersion: input.currentVersion,
|
|
1014
|
+
latestVersion,
|
|
1015
|
+
updateAvailable: isNewerVersion(latestVersion, input.currentVersion),
|
|
1016
|
+
restartRequired: true,
|
|
1017
|
+
message: "Daemon package updated. Restart the daemon to use the new version."
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
1020
|
+
async function daemonVersionStatus(options) {
|
|
1021
|
+
const latestVersion = await options.latestDaemonVersion(options.packageName);
|
|
1022
|
+
return {
|
|
1023
|
+
packageName: options.packageName,
|
|
1024
|
+
currentVersion: options.currentVersion,
|
|
1025
|
+
latestVersion,
|
|
1026
|
+
updateAvailable: isNewerVersion(latestVersion, options.currentVersion),
|
|
1027
|
+
updateCommand: updateCommand(options.packageName)
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
951
1030
|
async function startWorkspaceReadServer(options) {
|
|
952
1031
|
const host = options.host ?? "127.0.0.1";
|
|
953
1032
|
const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES;
|
|
1033
|
+
const daemonPackageName = options.daemonPackageName ?? DAEMON_PACKAGE_NAME;
|
|
1034
|
+
const daemonVersion = options.daemonVersion ?? DAEMON_VERSION;
|
|
1035
|
+
const latestDaemonVersion = options.latestDaemonVersion ?? defaultLatestDaemonVersion;
|
|
1036
|
+
const updateDaemonPackage = options.updateDaemonPackage ?? ((input) => defaultUpdateDaemonPackage({
|
|
1037
|
+
...input,
|
|
1038
|
+
latestDaemonVersion
|
|
1039
|
+
}));
|
|
954
1040
|
const taskArchive = options.taskArchive ?? createTaskArchive({ workspaceRoot: options.workspaceRoot });
|
|
955
1041
|
const server = createServer((request, response) => {
|
|
956
1042
|
void (async () => {
|
|
@@ -973,6 +1059,52 @@ async function startWorkspaceReadServer(options) {
|
|
|
973
1059
|
);
|
|
974
1060
|
return;
|
|
975
1061
|
}
|
|
1062
|
+
if (request.method === "GET" && url.pathname === "/runtime/daemon") {
|
|
1063
|
+
json(
|
|
1064
|
+
response,
|
|
1065
|
+
200,
|
|
1066
|
+
await daemonVersionStatus({
|
|
1067
|
+
packageName: daemonPackageName,
|
|
1068
|
+
currentVersion: daemonVersion,
|
|
1069
|
+
latestDaemonVersion
|
|
1070
|
+
}),
|
|
1071
|
+
origin
|
|
1072
|
+
);
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
if (request.method === "POST" && url.pathname === "/runtime/daemon/update") {
|
|
1076
|
+
const status = await daemonVersionStatus({
|
|
1077
|
+
packageName: daemonPackageName,
|
|
1078
|
+
currentVersion: daemonVersion,
|
|
1079
|
+
latestDaemonVersion
|
|
1080
|
+
});
|
|
1081
|
+
try {
|
|
1082
|
+
json(
|
|
1083
|
+
response,
|
|
1084
|
+
200,
|
|
1085
|
+
{
|
|
1086
|
+
ok: true,
|
|
1087
|
+
...await updateDaemonPackage({
|
|
1088
|
+
packageName: daemonPackageName,
|
|
1089
|
+
currentVersion: daemonVersion,
|
|
1090
|
+
latestVersion: status.latestVersion
|
|
1091
|
+
})
|
|
1092
|
+
},
|
|
1093
|
+
origin
|
|
1094
|
+
);
|
|
1095
|
+
} catch (error) {
|
|
1096
|
+
json(
|
|
1097
|
+
response,
|
|
1098
|
+
500,
|
|
1099
|
+
{
|
|
1100
|
+
ok: false,
|
|
1101
|
+
error: error instanceof Error ? error.message : "Daemon update failed"
|
|
1102
|
+
},
|
|
1103
|
+
origin
|
|
1104
|
+
);
|
|
1105
|
+
}
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
976
1108
|
if (request.method === "GET" && url.pathname === "/workspace/manifest") {
|
|
977
1109
|
const ticker = url.searchParams.get("ticker");
|
|
978
1110
|
const market = url.searchParams.get("market");
|
|
@@ -2127,7 +2259,14 @@ async function uninstallLaunchAgent(options = {}) {
|
|
|
2127
2259
|
}
|
|
2128
2260
|
|
|
2129
2261
|
// src/cli.ts
|
|
2130
|
-
async function
|
|
2262
|
+
async function ensureWorkspaceDirectory(workspace) {
|
|
2263
|
+
await mkdir6(workspace, { recursive: true }).catch(async (error) => {
|
|
2264
|
+
const stats2 = await stat4(workspace).catch(() => null);
|
|
2265
|
+
if (!stats2?.isDirectory()) {
|
|
2266
|
+
throw new Error("Workspace path is not a directory");
|
|
2267
|
+
}
|
|
2268
|
+
throw error;
|
|
2269
|
+
});
|
|
2131
2270
|
const stats = await stat4(workspace);
|
|
2132
2271
|
if (!stats.isDirectory()) {
|
|
2133
2272
|
throw new Error("Workspace path is not a directory");
|
|
@@ -2216,7 +2355,7 @@ async function runDaemon(options) {
|
|
|
2216
2355
|
);
|
|
2217
2356
|
}
|
|
2218
2357
|
const workspaceRoot = path8.resolve(expandHomePath(workspacePath3));
|
|
2219
|
-
await
|
|
2358
|
+
await ensureWorkspaceDirectory(workspaceRoot);
|
|
2220
2359
|
const capabilities = await detectCapabilities();
|
|
2221
2360
|
const investWiki = createInvestWikiRunnerFromOptions(runtimeOptions);
|
|
2222
2361
|
const codex = createCodexRunnerFromOptions(runtimeOptions);
|
|
@@ -2229,7 +2368,7 @@ async function runDaemon(options) {
|
|
|
2229
2368
|
hostname: os3.hostname(),
|
|
2230
2369
|
os: `${os3.platform()} ${os3.release()}`,
|
|
2231
2370
|
workspacePath: workspaceRoot,
|
|
2232
|
-
daemonVersion:
|
|
2371
|
+
daemonVersion: DAEMON_VERSION,
|
|
2233
2372
|
capabilities
|
|
2234
2373
|
});
|
|
2235
2374
|
await writeDaemonLocalConfig({
|
|
@@ -2274,6 +2413,7 @@ async function runDaemon(options) {
|
|
|
2274
2413
|
port: runtimeOptions.localApiPort,
|
|
2275
2414
|
allowedOrigins: localApiAllowedOrigins(serverUrl),
|
|
2276
2415
|
codexCommand: runtimeOptions.codexCommand,
|
|
2416
|
+
daemonVersion: DAEMON_VERSION,
|
|
2277
2417
|
taskArchive
|
|
2278
2418
|
}).catch((error) => {
|
|
2279
2419
|
logger.warn({ err: error }, "local workspace preview API unavailable");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xdsjs/dossierx-daemon",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"execa": "^9.0.0",
|
|
29
29
|
"pino": "^10.0.0",
|
|
30
30
|
"zod": "^4.0.0",
|
|
31
|
-
"@xdsjs/dossierx-
|
|
32
|
-
"@xdsjs/dossierx-
|
|
31
|
+
"@xdsjs/dossierx-workspace": "^0.1.0",
|
|
32
|
+
"@xdsjs/dossierx-shared": "^0.1.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "^24.0.0",
|