@xdsjs/dossierx-daemon 0.1.15 → 0.1.17
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 +115 -12
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2290,7 +2290,7 @@ function createTaskArchive(options) {
|
|
|
2290
2290
|
|
|
2291
2291
|
// src/version.ts
|
|
2292
2292
|
var DAEMON_PACKAGE_NAME = "@xdsjs/dossierx-daemon";
|
|
2293
|
-
var DAEMON_VERSION = "0.1.
|
|
2293
|
+
var DAEMON_VERSION = "0.1.17";
|
|
2294
2294
|
|
|
2295
2295
|
// src/local-api/server.ts
|
|
2296
2296
|
var DEFAULT_MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
@@ -2300,18 +2300,58 @@ function json(response, status, body, origin) {
|
|
|
2300
2300
|
response.writeHead(status, {
|
|
2301
2301
|
"content-type": "application/json; charset=utf-8",
|
|
2302
2302
|
...origin ? { "access-control-allow-origin": origin } : {},
|
|
2303
|
+
...origin ? { "access-control-allow-private-network": "true" } : {},
|
|
2303
2304
|
"access-control-allow-methods": "GET, POST, OPTIONS",
|
|
2304
2305
|
"access-control-allow-headers": "content-type",
|
|
2305
2306
|
vary: "Origin"
|
|
2306
2307
|
});
|
|
2307
2308
|
response.end(JSON.stringify(body));
|
|
2308
2309
|
}
|
|
2310
|
+
function vercelProjectNameFromAllowedOrigin(origin) {
|
|
2311
|
+
try {
|
|
2312
|
+
const url = new URL(origin);
|
|
2313
|
+
if (url.protocol !== "https:" || !url.hostname.endsWith(".vercel.app")) {
|
|
2314
|
+
return null;
|
|
2315
|
+
}
|
|
2316
|
+
const label = url.hostname.slice(0, -".vercel.app".length);
|
|
2317
|
+
for (const suffix of ["-beta", "-production", "-prod", "-preview", "-staging"]) {
|
|
2318
|
+
if (label.endsWith(suffix) && label.length > suffix.length) {
|
|
2319
|
+
return label.slice(0, -suffix.length);
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
return label;
|
|
2323
|
+
} catch {
|
|
2324
|
+
return null;
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
function isVercelDeploymentOriginAllowed(origin, allowedOrigins) {
|
|
2328
|
+
let requested;
|
|
2329
|
+
try {
|
|
2330
|
+
requested = new URL(origin);
|
|
2331
|
+
} catch {
|
|
2332
|
+
return false;
|
|
2333
|
+
}
|
|
2334
|
+
if (requested.protocol !== "https:" || !requested.hostname.endsWith(".vercel.app")) {
|
|
2335
|
+
return false;
|
|
2336
|
+
}
|
|
2337
|
+
const requestedLabel = requested.hostname.slice(0, -".vercel.app".length);
|
|
2338
|
+
return allowedOrigins.some((allowedOriginValue) => {
|
|
2339
|
+
const projectName = vercelProjectNameFromAllowedOrigin(allowedOriginValue);
|
|
2340
|
+
if (!projectName) {
|
|
2341
|
+
return false;
|
|
2342
|
+
}
|
|
2343
|
+
const deploymentPattern = new RegExp(
|
|
2344
|
+
`^${projectName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}-[a-z0-9]+-[a-z0-9-]+$`
|
|
2345
|
+
);
|
|
2346
|
+
return requestedLabel === projectName || deploymentPattern.test(requestedLabel);
|
|
2347
|
+
});
|
|
2348
|
+
}
|
|
2309
2349
|
function allowedOrigin(request, allowedOrigins) {
|
|
2310
2350
|
const origin = request.headers.origin;
|
|
2311
2351
|
if (!origin) {
|
|
2312
2352
|
return "";
|
|
2313
2353
|
}
|
|
2314
|
-
return allowedOrigins.includes(origin) ? origin : null;
|
|
2354
|
+
return allowedOrigins.includes(origin) || isVercelDeploymentOriginAllowed(origin, allowedOrigins) ? origin : null;
|
|
2315
2355
|
}
|
|
2316
2356
|
function requestUrl(request) {
|
|
2317
2357
|
return new URL(request.url ?? "/", "http://127.0.0.1");
|
|
@@ -2544,16 +2584,40 @@ async function startWorkspaceReadServer(options) {
|
|
|
2544
2584
|
const taskArchive = options.taskArchive ?? createTaskArchive({ workspaceRoot: options.workspaceRoot });
|
|
2545
2585
|
const server = createServer((request, response) => {
|
|
2546
2586
|
void (async () => {
|
|
2587
|
+
const url = requestUrl(request);
|
|
2547
2588
|
const origin = allowedOrigin(request, options.allowedOrigins);
|
|
2548
2589
|
if (origin === null) {
|
|
2590
|
+
if (url.pathname === "/workspace/manifest") {
|
|
2591
|
+
console.warn(
|
|
2592
|
+
JSON.stringify({
|
|
2593
|
+
msg: "workspace manifest cors rejected",
|
|
2594
|
+
origin: request.headers.origin ?? null,
|
|
2595
|
+
requestedMethod: request.headers["access-control-request-method"] ?? null,
|
|
2596
|
+
requestedPrivateNetwork: request.headers["access-control-request-private-network"] ?? null,
|
|
2597
|
+
status: 403,
|
|
2598
|
+
error: "Origin not allowed"
|
|
2599
|
+
})
|
|
2600
|
+
);
|
|
2601
|
+
}
|
|
2549
2602
|
json(response, 403, { error: "Origin not allowed" });
|
|
2550
2603
|
return;
|
|
2551
2604
|
}
|
|
2552
2605
|
if (request.method === "OPTIONS") {
|
|
2606
|
+
if (url.pathname === "/workspace/manifest") {
|
|
2607
|
+
console.info(
|
|
2608
|
+
JSON.stringify({
|
|
2609
|
+
msg: "workspace manifest preflight served",
|
|
2610
|
+
origin,
|
|
2611
|
+
requestedMethod: request.headers["access-control-request-method"] ?? null,
|
|
2612
|
+
requestedPrivateNetwork: request.headers["access-control-request-private-network"] ?? null,
|
|
2613
|
+
status: 204,
|
|
2614
|
+
allowPrivateNetwork: true
|
|
2615
|
+
})
|
|
2616
|
+
);
|
|
2617
|
+
}
|
|
2553
2618
|
json(response, 204, {}, origin);
|
|
2554
2619
|
return;
|
|
2555
2620
|
}
|
|
2556
|
-
const url = requestUrl(request);
|
|
2557
2621
|
if (request.method === "GET" && url.pathname === "/runtime/codex") {
|
|
2558
2622
|
json(
|
|
2559
2623
|
response,
|
|
@@ -2613,26 +2677,65 @@ async function startWorkspaceReadServer(options) {
|
|
|
2613
2677
|
const ticker = url.searchParams.get("ticker");
|
|
2614
2678
|
const market = url.searchParams.get("market");
|
|
2615
2679
|
if (!ticker || !market) {
|
|
2680
|
+
console.warn(
|
|
2681
|
+
JSON.stringify({
|
|
2682
|
+
msg: "workspace manifest request rejected",
|
|
2683
|
+
origin,
|
|
2684
|
+
ticker,
|
|
2685
|
+
market,
|
|
2686
|
+
status: 400,
|
|
2687
|
+
error: "Missing ticker or market"
|
|
2688
|
+
})
|
|
2689
|
+
);
|
|
2616
2690
|
json(response, 400, { error: "Missing ticker or market" }, origin);
|
|
2617
2691
|
return;
|
|
2618
2692
|
}
|
|
2619
2693
|
try {
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2694
|
+
const body = await readCompanyManifest({
|
|
2695
|
+
workspaceRoot: options.workspaceRoot,
|
|
2696
|
+
ticker,
|
|
2697
|
+
market
|
|
2698
|
+
});
|
|
2699
|
+
const paths = body.manifest.pages.map((page) => page.path);
|
|
2700
|
+
console.info(
|
|
2701
|
+
JSON.stringify({
|
|
2702
|
+
msg: "workspace manifest served",
|
|
2703
|
+
origin,
|
|
2625
2704
|
ticker,
|
|
2626
|
-
market
|
|
2627
|
-
|
|
2628
|
-
|
|
2705
|
+
market,
|
|
2706
|
+
status: 200,
|
|
2707
|
+
pageCount: paths.length,
|
|
2708
|
+
hasNotebook: paths.some(
|
|
2709
|
+
(item) => item.endsWith("/financial-reports/notebooklm/notebook.json")
|
|
2710
|
+
),
|
|
2711
|
+
hasFactsBundle: paths.some(
|
|
2712
|
+
(item) => item.endsWith("/financial-reports/ingest/facts-bundle.json")
|
|
2713
|
+
),
|
|
2714
|
+
hasFinancialWiki: paths.some(
|
|
2715
|
+
(item) => item.endsWith(
|
|
2716
|
+
"/financial-reports/wiki/financial-report-analysis.md"
|
|
2717
|
+
)
|
|
2718
|
+
)
|
|
2719
|
+
})
|
|
2629
2720
|
);
|
|
2721
|
+
json(response, 200, body, origin);
|
|
2630
2722
|
} catch (error) {
|
|
2723
|
+
const message = error instanceof Error ? error.message : "Workspace manifest failed";
|
|
2724
|
+
console.warn(
|
|
2725
|
+
JSON.stringify({
|
|
2726
|
+
msg: "workspace manifest request failed",
|
|
2727
|
+
origin,
|
|
2728
|
+
ticker,
|
|
2729
|
+
market,
|
|
2730
|
+
status: 400,
|
|
2731
|
+
error: message
|
|
2732
|
+
})
|
|
2733
|
+
);
|
|
2631
2734
|
json(
|
|
2632
2735
|
response,
|
|
2633
2736
|
400,
|
|
2634
2737
|
{
|
|
2635
|
-
error:
|
|
2738
|
+
error: message
|
|
2636
2739
|
},
|
|
2637
2740
|
origin
|
|
2638
2741
|
);
|