@rudderhq/cli 0.7.15 → 0.7.16
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 +864 -437
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1700,7 +1700,9 @@ var init_rudder_agent_contract_generated = __esm({
|
|
|
1700
1700
|
},
|
|
1701
1701
|
{
|
|
1702
1702
|
"api": {
|
|
1703
|
-
"
|
|
1703
|
+
"method": "GET",
|
|
1704
|
+
"pathTemplate": "/api/issues/{issue}/comments",
|
|
1705
|
+
"transport": "direct"
|
|
1704
1706
|
},
|
|
1705
1707
|
"cli": {
|
|
1706
1708
|
"attachesRunIdWhenAvailable": false,
|
|
@@ -1760,7 +1762,9 @@ var init_rudder_agent_contract_generated = __esm({
|
|
|
1760
1762
|
},
|
|
1761
1763
|
{
|
|
1762
1764
|
"api": {
|
|
1763
|
-
"
|
|
1765
|
+
"method": "GET",
|
|
1766
|
+
"pathTemplate": "/api/issues/{issue}/comments/{comment}",
|
|
1767
|
+
"transport": "direct"
|
|
1764
1768
|
},
|
|
1765
1769
|
"cli": {
|
|
1766
1770
|
"attachesRunIdWhenAvailable": false,
|
|
@@ -8582,6 +8586,65 @@ var init_rudder_agent_contract_generated = __esm({
|
|
|
8582
8586
|
},
|
|
8583
8587
|
"name": "rudder_runs_retry"
|
|
8584
8588
|
}
|
|
8589
|
+
},
|
|
8590
|
+
{
|
|
8591
|
+
"api": {
|
|
8592
|
+
"method": "POST",
|
|
8593
|
+
"pathTemplate": "/api/agent-runs/delegation",
|
|
8594
|
+
"transport": "direct"
|
|
8595
|
+
},
|
|
8596
|
+
"cli": {
|
|
8597
|
+
"attachesRunIdWhenAvailable": true,
|
|
8598
|
+
"category": "runs",
|
|
8599
|
+
"command": "rudder runs create --task <text> --idempotency-key <key> [--target-agent-id <id>]",
|
|
8600
|
+
"contract": "agent-v1",
|
|
8601
|
+
"description": "Create an independently governed Delegation Run for the current or another same-organization Agent.",
|
|
8602
|
+
"id": "runs.create",
|
|
8603
|
+
"mutating": true,
|
|
8604
|
+
"requiresAgentId": true,
|
|
8605
|
+
"requiresOrgId": false,
|
|
8606
|
+
"requiresRunId": true
|
|
8607
|
+
},
|
|
8608
|
+
"id": "runs.create",
|
|
8609
|
+
"mcp": {
|
|
8610
|
+
"annotations": {
|
|
8611
|
+
"destructiveHint": false,
|
|
8612
|
+
"idempotentHint": true,
|
|
8613
|
+
"readOnlyHint": false,
|
|
8614
|
+
"title": "Create an independently governed Delegation Run"
|
|
8615
|
+
},
|
|
8616
|
+
"capabilityId": "runs.create",
|
|
8617
|
+
"description": "Create an independently governed Delegation Run for the current or another same-organization Agent. Mutating: yes. Runtime identity and authorization are injected by the Rudder-managed MCP server and are not accepted as tool input. Org context: not required by this tool. Agent context: required from runtime env. Run attribution: attached from runtime env when available.",
|
|
8618
|
+
"inputSchema": {
|
|
8619
|
+
"additionalProperties": false,
|
|
8620
|
+
"properties": {
|
|
8621
|
+
"idempotencyKey": {
|
|
8622
|
+
"description": "Required stable key for safe replay.",
|
|
8623
|
+
"maxLength": 500,
|
|
8624
|
+
"minLength": 1,
|
|
8625
|
+
"type": "string"
|
|
8626
|
+
},
|
|
8627
|
+
"targetAgentId": {
|
|
8628
|
+
"description": "Optional same-organization target Agent id.",
|
|
8629
|
+
"maxLength": 200,
|
|
8630
|
+
"minLength": 1,
|
|
8631
|
+
"type": "string"
|
|
8632
|
+
},
|
|
8633
|
+
"task": {
|
|
8634
|
+
"description": "Delegation task to run independently.",
|
|
8635
|
+
"maxLength": 2e4,
|
|
8636
|
+
"minLength": 1,
|
|
8637
|
+
"type": "string"
|
|
8638
|
+
}
|
|
8639
|
+
},
|
|
8640
|
+
"required": [
|
|
8641
|
+
"task",
|
|
8642
|
+
"idempotencyKey"
|
|
8643
|
+
],
|
|
8644
|
+
"type": "object"
|
|
8645
|
+
},
|
|
8646
|
+
"name": "rudder_runs_create"
|
|
8647
|
+
}
|
|
8585
8648
|
}
|
|
8586
8649
|
],
|
|
8587
8650
|
"contractVersion": "rudder.agent-contract/v1",
|
|
@@ -16296,6 +16359,50 @@ var init_rudder_mcp_tool_descriptors_generated = __esm({
|
|
|
16296
16359
|
],
|
|
16297
16360
|
"type": "object"
|
|
16298
16361
|
}
|
|
16362
|
+
},
|
|
16363
|
+
{
|
|
16364
|
+
"capabilityId": "runs.create",
|
|
16365
|
+
"name": "rudder_runs_create",
|
|
16366
|
+
"description": "Create an independently governed Delegation Run for the current or another same-organization Agent.",
|
|
16367
|
+
"semanticDescription": "Create an independently governed Delegation Run for the current or another same-organization Agent. Mutating: yes. Runtime identity and authorization are injected by the Rudder-managed MCP server and are not accepted as tool input. Org context: not required by this tool. Agent context: required from runtime env. Run attribution: attached from runtime env when available.",
|
|
16368
|
+
"annotations": {
|
|
16369
|
+
"destructiveHint": false,
|
|
16370
|
+
"idempotentHint": true,
|
|
16371
|
+
"readOnlyHint": false,
|
|
16372
|
+
"title": "Create an independently governed Delegation Run"
|
|
16373
|
+
},
|
|
16374
|
+
"mutating": true,
|
|
16375
|
+
"requiresOrgId": false,
|
|
16376
|
+
"requiresAgentId": true,
|
|
16377
|
+
"attachesRunIdWhenAvailable": true,
|
|
16378
|
+
"inputSchema": {
|
|
16379
|
+
"additionalProperties": false,
|
|
16380
|
+
"properties": {
|
|
16381
|
+
"idempotencyKey": {
|
|
16382
|
+
"description": "Required stable key for safe replay.",
|
|
16383
|
+
"maxLength": 500,
|
|
16384
|
+
"minLength": 1,
|
|
16385
|
+
"type": "string"
|
|
16386
|
+
},
|
|
16387
|
+
"targetAgentId": {
|
|
16388
|
+
"description": "Optional same-organization target Agent id.",
|
|
16389
|
+
"maxLength": 200,
|
|
16390
|
+
"minLength": 1,
|
|
16391
|
+
"type": "string"
|
|
16392
|
+
},
|
|
16393
|
+
"task": {
|
|
16394
|
+
"description": "Delegation task to run independently.",
|
|
16395
|
+
"maxLength": 2e4,
|
|
16396
|
+
"minLength": 1,
|
|
16397
|
+
"type": "string"
|
|
16398
|
+
}
|
|
16399
|
+
},
|
|
16400
|
+
"required": [
|
|
16401
|
+
"task",
|
|
16402
|
+
"idempotencyKey"
|
|
16403
|
+
],
|
|
16404
|
+
"type": "object"
|
|
16405
|
+
}
|
|
16299
16406
|
}
|
|
16300
16407
|
];
|
|
16301
16408
|
}
|
|
@@ -16895,7 +17002,8 @@ var init_constants = __esm({
|
|
|
16895
17002
|
"rudder_runs_transcript",
|
|
16896
17003
|
"rudder_runs_errors",
|
|
16897
17004
|
"rudder_runs_cancel",
|
|
16898
|
-
"rudder_runs_retry"
|
|
17005
|
+
"rudder_runs_retry",
|
|
17006
|
+
"rudder_runs_create"
|
|
16899
17007
|
];
|
|
16900
17008
|
RUDDER_BROWSER_MCP_TOOL_NAMES2 = RUDDER_AGENT_V1_MCP_TOOL_NAMES.filter((name) => name.startsWith("rudder_browser_"));
|
|
16901
17009
|
RUDDER_CORE_MCP_TOOL_NAMES2 = RUDDER_AGENT_V1_MCP_TOOL_NAMES.filter((name) => !name.startsWith("rudder_browser_"));
|
|
@@ -18532,6 +18640,7 @@ var init_chat = __esm({
|
|
|
18532
18640
|
}).strict();
|
|
18533
18641
|
addChatMessageSchema = z5.object({
|
|
18534
18642
|
body: z5.string().trim().max(2e4).default(""),
|
|
18643
|
+
clientMutationId: z5.string().trim().min(1).max(120).optional(),
|
|
18535
18644
|
inlineAnnotations: chatInlineAnnotationsInputSchema.optional(),
|
|
18536
18645
|
editUserMessageId: z5.string().uuid().optional().nullable(),
|
|
18537
18646
|
queuedMessageId: z5.string().uuid().optional().nullable(),
|
|
@@ -19975,7 +20084,7 @@ var init_resource = __esm({
|
|
|
19975
20084
|
|
|
19976
20085
|
// ../packages/shared/dist/validators/agent.js
|
|
19977
20086
|
import { z as z20 } from "zod";
|
|
19978
|
-
var agentPermissionsSchema, agentInstructionsBundleModeSchema, updateAgentInstructionsBundleSchema, upsertAgentInstructionsFileSchema, agentRuntimeConfigSchema, optionalAgentNameSchema, uploadedAgentIconSchema, diceBearNotionistsAgentIconSchema, oreoAgentIconSchema, agentIconSchema, createAgentSchema, createAgentHireSchema, updateAgentSchema, updateAgentInstructionsPathSchema, createAgentKeySchema, wakeAgentSchema, resetAgentSessionSchema, testAgentRuntimeEnvironmentSchema, updateAgentPermissionsSchema;
|
|
20087
|
+
var agentPermissionsSchema, agentInstructionsBundleModeSchema, updateAgentInstructionsBundleSchema, upsertAgentInstructionsFileSchema, agentRuntimeConfigSchema, optionalAgentNameSchema, uploadedAgentIconSchema, diceBearNotionistsAgentIconSchema, oreoAgentIconSchema, agentIconSchema, createAgentSchema, createAgentHireSchema, updateAgentSchema, updateAgentInstructionsPathSchema, createAgentKeySchema, wakeAgentSchema, delegationTaskSchema, createDelegationRunSchema, resetAgentSessionSchema, testAgentRuntimeEnvironmentSchema, updateAgentPermissionsSchema;
|
|
19979
20088
|
var init_agent = __esm({
|
|
19980
20089
|
"../packages/shared/dist/validators/agent.js"() {
|
|
19981
20090
|
"use strict";
|
|
@@ -20072,6 +20181,12 @@ var init_agent = __esm({
|
|
|
20072
20181
|
idempotencyKey: z20.string().optional().nullable(),
|
|
20073
20182
|
forceFreshSession: z20.preprocess((value) => value === null ? void 0 : value, z20.boolean().optional().default(false))
|
|
20074
20183
|
});
|
|
20184
|
+
delegationTaskSchema = z20.string().trim().min(1).refine((value) => Array.from(value).length <= 2e4, "task must be no more than 20,000 Unicode characters");
|
|
20185
|
+
createDelegationRunSchema = z20.object({
|
|
20186
|
+
task: delegationTaskSchema,
|
|
20187
|
+
targetAgentId: z20.string().trim().min(1).max(200).optional(),
|
|
20188
|
+
idempotencyKey: z20.string().trim().min(1).max(500)
|
|
20189
|
+
});
|
|
20075
20190
|
resetAgentSessionSchema = z20.object({
|
|
20076
20191
|
taskKey: z20.string().min(1).optional().nullable()
|
|
20077
20192
|
});
|
|
@@ -20284,7 +20399,7 @@ var init_project = __esm({
|
|
|
20284
20399
|
|
|
20285
20400
|
// ../packages/shared/dist/validators/issue.js
|
|
20286
20401
|
import { z as z23 } from "zod";
|
|
20287
|
-
var runWorkspaceStrategySchema, issueRunWorkspaceSettingsSchema, issueAssigneeAdapterOverridesSchema, createIssueSchema, createIssueLabelSchema, updateIssueLabelSchema, updateIssueSchema, reorderIssueSchema, checkoutIssueSchema, addIssueCommentSchema, updateIssueCommentSchema, reportIssueCommitSchema, linkIssueApprovalSchema, createIssueAttachmentMetadataSchema, createIssueWorkspaceAttachmentSchema, ISSUE_DOCUMENT_FORMATS, issueDocumentFormatSchema, createLibraryDocumentSchema, updateLibraryDocumentSchema, restoreLibraryDocumentRevisionSchema;
|
|
20402
|
+
var runWorkspaceStrategySchema, issueRunWorkspaceSettingsSchema, issueAssigneeAdapterOverridesSchema, createIssueSchema, createRunDebugIssueSchema, createIssueLabelSchema, updateIssueLabelSchema, updateIssueSchema, reorderIssueSchema, checkoutIssueSchema, addIssueCommentSchema, updateIssueCommentSchema, reportIssueCommitSchema, linkIssueApprovalSchema, createIssueAttachmentMetadataSchema, createIssueWorkspaceAttachmentSchema, ISSUE_DOCUMENT_FORMATS, issueDocumentFormatSchema, createLibraryDocumentSchema, updateLibraryDocumentSchema, restoreLibraryDocumentRevisionSchema;
|
|
20288
20403
|
var init_issue = __esm({
|
|
20289
20404
|
"../packages/shared/dist/validators/issue.js"() {
|
|
20290
20405
|
"use strict";
|
|
@@ -20347,6 +20462,9 @@ var init_issue = __esm({
|
|
|
20347
20462
|
executionWorkspaceSettings: issueRunWorkspaceSettingsSchema.optional().nullable(),
|
|
20348
20463
|
labelIds: z23.array(z23.string().uuid()).optional()
|
|
20349
20464
|
});
|
|
20465
|
+
createRunDebugIssueSchema = z23.object({
|
|
20466
|
+
diagnostics: z23.string().trim().min(1).max(32e3)
|
|
20467
|
+
});
|
|
20350
20468
|
createIssueLabelSchema = z23.object({
|
|
20351
20469
|
name: z23.string().trim().min(1).max(48),
|
|
20352
20470
|
color: z23.string().regex(/^#(?:[0-9a-fA-F]{6})$/, "Color must be a 6-digit hex value")
|
|
@@ -21105,7 +21223,8 @@ var init_plugin_v1 = __esm({
|
|
|
21105
21223
|
inspectRudderPluginArchiveSchema = z36.object({
|
|
21106
21224
|
sourceLabel: z36.string().trim().min(1).max(240),
|
|
21107
21225
|
filename: z36.string().trim().min(1).max(240).refine((value) => /\.zip$/i.test(value), "Only ZIP Plugin archives are supported"),
|
|
21108
|
-
|
|
21226
|
+
// 100 MiB binary package ceiling plus base64 expansion.
|
|
21227
|
+
content: z36.string().min(1).max(14e7),
|
|
21109
21228
|
encoding: z36.literal("base64")
|
|
21110
21229
|
}).strict();
|
|
21111
21230
|
configureRudderPluginMarketplaceSchema = z36.object({
|
|
@@ -21530,12 +21649,12 @@ var init_dist2 = __esm({
|
|
|
21530
21649
|
});
|
|
21531
21650
|
|
|
21532
21651
|
// src/config/home.ts
|
|
21533
|
-
import
|
|
21534
|
-
import
|
|
21652
|
+
import os2 from "node:os";
|
|
21653
|
+
import path2 from "node:path";
|
|
21535
21654
|
function resolveRudderHomeDir() {
|
|
21536
21655
|
const envHome = process.env.RUDDER_HOME?.trim();
|
|
21537
|
-
if (envHome) return
|
|
21538
|
-
return
|
|
21656
|
+
if (envHome) return path2.resolve(expandHomePrefix(envHome));
|
|
21657
|
+
return path2.resolve(os2.homedir(), ".rudder");
|
|
21539
21658
|
}
|
|
21540
21659
|
function resolveRudderInstanceId(override) {
|
|
21541
21660
|
const raw = override?.trim() || process.env.RUDDER_INSTANCE_ID?.trim() || DEFAULT_INSTANCE_ID;
|
|
@@ -21548,35 +21667,35 @@ function resolveRudderInstanceId(override) {
|
|
|
21548
21667
|
}
|
|
21549
21668
|
function resolveRudderInstanceRoot(instanceId) {
|
|
21550
21669
|
const id = resolveRudderInstanceId(instanceId);
|
|
21551
|
-
return
|
|
21670
|
+
return path2.resolve(resolveRudderHomeDir(), "instances", id);
|
|
21552
21671
|
}
|
|
21553
21672
|
function resolveDefaultConfigPath(instanceId) {
|
|
21554
|
-
return
|
|
21673
|
+
return path2.resolve(resolveRudderInstanceRoot(instanceId), "config.json");
|
|
21555
21674
|
}
|
|
21556
21675
|
function resolveDefaultContextPath() {
|
|
21557
|
-
return
|
|
21676
|
+
return path2.resolve(resolveRudderHomeDir(), "context.json");
|
|
21558
21677
|
}
|
|
21559
21678
|
function resolveDefaultCliAuthPath() {
|
|
21560
|
-
return
|
|
21679
|
+
return path2.resolve(resolveRudderHomeDir(), "auth.json");
|
|
21561
21680
|
}
|
|
21562
21681
|
function resolveDefaultEmbeddedPostgresDir(instanceId) {
|
|
21563
|
-
return
|
|
21682
|
+
return path2.resolve(resolveRudderInstanceRoot(instanceId), "db");
|
|
21564
21683
|
}
|
|
21565
21684
|
function resolveDefaultLogsDir(instanceId) {
|
|
21566
|
-
return
|
|
21685
|
+
return path2.resolve(resolveRudderInstanceRoot(instanceId), "logs");
|
|
21567
21686
|
}
|
|
21568
21687
|
function resolveDefaultSecretsKeyFilePath(instanceId) {
|
|
21569
|
-
return
|
|
21688
|
+
return path2.resolve(resolveRudderInstanceRoot(instanceId), "secrets", "master.key");
|
|
21570
21689
|
}
|
|
21571
21690
|
function resolveDefaultStorageDir(instanceId) {
|
|
21572
|
-
return
|
|
21691
|
+
return path2.resolve(resolveRudderInstanceRoot(instanceId), "data", "storage");
|
|
21573
21692
|
}
|
|
21574
21693
|
function resolveDefaultBackupDir(instanceId) {
|
|
21575
|
-
return
|
|
21694
|
+
return path2.resolve(resolveRudderInstanceRoot(instanceId), "data", "backups");
|
|
21576
21695
|
}
|
|
21577
21696
|
function expandHomePrefix(value) {
|
|
21578
|
-
if (value === "~") return
|
|
21579
|
-
if (value.startsWith("~/")) return
|
|
21697
|
+
if (value === "~") return os2.homedir();
|
|
21698
|
+
if (value.startsWith("~/")) return path2.resolve(os2.homedir(), value.slice(2));
|
|
21580
21699
|
return value;
|
|
21581
21700
|
}
|
|
21582
21701
|
function describeLocalInstancePaths(instanceId) {
|
|
@@ -21612,30 +21731,30 @@ var init_schema = __esm({
|
|
|
21612
21731
|
});
|
|
21613
21732
|
|
|
21614
21733
|
// src/config/store.ts
|
|
21615
|
-
import
|
|
21616
|
-
import
|
|
21734
|
+
import fs4 from "node:fs";
|
|
21735
|
+
import path5 from "node:path";
|
|
21617
21736
|
function findConfigFileFromAncestors(startDir) {
|
|
21618
|
-
const absoluteStartDir =
|
|
21737
|
+
const absoluteStartDir = path5.resolve(startDir);
|
|
21619
21738
|
let currentDir = absoluteStartDir;
|
|
21620
21739
|
while (true) {
|
|
21621
|
-
const candidate =
|
|
21622
|
-
if (
|
|
21740
|
+
const candidate = path5.resolve(currentDir, ".rudder", DEFAULT_CONFIG_BASENAME);
|
|
21741
|
+
if (fs4.existsSync(candidate)) {
|
|
21623
21742
|
return candidate;
|
|
21624
21743
|
}
|
|
21625
|
-
const nextDir =
|
|
21744
|
+
const nextDir = path5.resolve(currentDir, "..");
|
|
21626
21745
|
if (nextDir === currentDir) break;
|
|
21627
21746
|
currentDir = nextDir;
|
|
21628
21747
|
}
|
|
21629
21748
|
return null;
|
|
21630
21749
|
}
|
|
21631
21750
|
function resolveConfigPath(overridePath) {
|
|
21632
|
-
if (overridePath) return
|
|
21633
|
-
if (process.env.RUDDER_CONFIG) return
|
|
21751
|
+
if (overridePath) return path5.resolve(overridePath);
|
|
21752
|
+
if (process.env.RUDDER_CONFIG) return path5.resolve(process.env.RUDDER_CONFIG);
|
|
21634
21753
|
return findConfigFileFromAncestors(process.cwd()) ?? resolveDefaultConfigPath(resolveRudderInstanceId());
|
|
21635
21754
|
}
|
|
21636
21755
|
function parseJson2(filePath) {
|
|
21637
21756
|
try {
|
|
21638
|
-
return JSON.parse(
|
|
21757
|
+
return JSON.parse(fs4.readFileSync(filePath, "utf-8"));
|
|
21639
21758
|
} catch (err) {
|
|
21640
21759
|
throw new Error(`Failed to parse JSON at ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
21641
21760
|
}
|
|
@@ -21674,7 +21793,7 @@ function formatValidationError(err) {
|
|
|
21674
21793
|
}
|
|
21675
21794
|
function readConfig(configPath) {
|
|
21676
21795
|
const filePath = resolveConfigPath(configPath);
|
|
21677
|
-
if (!
|
|
21796
|
+
if (!fs4.existsSync(filePath)) return null;
|
|
21678
21797
|
const raw = parseJson2(filePath);
|
|
21679
21798
|
const migrated = migrateLegacyConfig(raw);
|
|
21680
21799
|
const parsed = rudderConfigSchema.safeParse(migrated);
|
|
@@ -21685,19 +21804,19 @@ function readConfig(configPath) {
|
|
|
21685
21804
|
}
|
|
21686
21805
|
function writeConfig(config, configPath) {
|
|
21687
21806
|
const filePath = resolveConfigPath(configPath);
|
|
21688
|
-
const dir =
|
|
21689
|
-
|
|
21690
|
-
if (
|
|
21807
|
+
const dir = path5.dirname(filePath);
|
|
21808
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
21809
|
+
if (fs4.existsSync(filePath)) {
|
|
21691
21810
|
const backupPath = filePath + ".backup";
|
|
21692
|
-
|
|
21693
|
-
|
|
21811
|
+
fs4.copyFileSync(filePath, backupPath);
|
|
21812
|
+
fs4.chmodSync(backupPath, 384);
|
|
21694
21813
|
}
|
|
21695
|
-
|
|
21814
|
+
fs4.writeFileSync(filePath, JSON.stringify(config, null, 2) + "\n", {
|
|
21696
21815
|
mode: 384
|
|
21697
21816
|
});
|
|
21698
21817
|
}
|
|
21699
21818
|
function configExists(configPath) {
|
|
21700
|
-
return
|
|
21819
|
+
return fs4.existsSync(resolveConfigPath(configPath));
|
|
21701
21820
|
}
|
|
21702
21821
|
var DEFAULT_CONFIG_BASENAME;
|
|
21703
21822
|
var init_store = __esm({
|
|
@@ -21711,7 +21830,7 @@ var init_store = __esm({
|
|
|
21711
21830
|
|
|
21712
21831
|
// src/version.ts
|
|
21713
21832
|
import { existsSync, readFileSync } from "node:fs";
|
|
21714
|
-
import
|
|
21833
|
+
import path6 from "node:path";
|
|
21715
21834
|
import { fileURLToPath } from "node:url";
|
|
21716
21835
|
function readPackageVersion(packagePath, expectedName) {
|
|
21717
21836
|
if (!existsSync(packagePath)) return null;
|
|
@@ -21727,12 +21846,12 @@ function resolveCliVersion(moduleUrl = import.meta.url, env = process.env) {
|
|
|
21727
21846
|
if (env.npm_package_name === CLI_PACKAGE_NAME && env.npm_package_version) {
|
|
21728
21847
|
return env.npm_package_version;
|
|
21729
21848
|
}
|
|
21730
|
-
const moduleDir =
|
|
21849
|
+
const moduleDir = path6.dirname(fileURLToPath(moduleUrl));
|
|
21731
21850
|
const candidates = [
|
|
21732
|
-
|
|
21733
|
-
|
|
21734
|
-
|
|
21735
|
-
|
|
21851
|
+
path6.resolve(moduleDir, CLI_VERSION_MANIFEST),
|
|
21852
|
+
path6.resolve(moduleDir, "package.json"),
|
|
21853
|
+
path6.resolve(moduleDir, "../package.json"),
|
|
21854
|
+
path6.resolve(moduleDir, "../../package.json")
|
|
21736
21855
|
];
|
|
21737
21856
|
for (const candidate of candidates) {
|
|
21738
21857
|
const version = readPackageVersion(candidate, CLI_PACKAGE_NAME);
|
|
@@ -21782,10 +21901,10 @@ var init_hostnames = __esm({
|
|
|
21782
21901
|
// src/config/env.ts
|
|
21783
21902
|
import { config as loadDotenv, parse as parseEnvFileContents } from "dotenv";
|
|
21784
21903
|
import { randomBytes } from "node:crypto";
|
|
21785
|
-
import
|
|
21786
|
-
import
|
|
21904
|
+
import fs6 from "node:fs";
|
|
21905
|
+
import path8 from "node:path";
|
|
21787
21906
|
function resolveEnvFilePath(configPath) {
|
|
21788
|
-
return
|
|
21907
|
+
return path8.resolve(path8.dirname(resolveConfigPath(configPath)), ".env");
|
|
21789
21908
|
}
|
|
21790
21909
|
function isNonEmpty(value) {
|
|
21791
21910
|
return typeof value === "string" && value.trim().length > 0;
|
|
@@ -21820,7 +21939,7 @@ function loadRudderEnvFile(configPath) {
|
|
|
21820
21939
|
}
|
|
21821
21940
|
function loadAgentJwtEnvFile(filePath = resolveEnvFilePath()) {
|
|
21822
21941
|
if (loadedEnvFiles.has(filePath)) return;
|
|
21823
|
-
if (!
|
|
21942
|
+
if (!fs6.existsSync(filePath)) return;
|
|
21824
21943
|
loadedEnvFiles.add(filePath);
|
|
21825
21944
|
loadDotenv({ path: filePath, override: false, quiet: true });
|
|
21826
21945
|
}
|
|
@@ -21830,8 +21949,8 @@ function readAgentJwtSecretFromEnv(configPath) {
|
|
|
21830
21949
|
return isNonEmpty(raw) ? raw.trim() : null;
|
|
21831
21950
|
}
|
|
21832
21951
|
function readAgentJwtSecretFromEnvFile(filePath = resolveEnvFilePath()) {
|
|
21833
|
-
if (!
|
|
21834
|
-
const raw =
|
|
21952
|
+
if (!fs6.existsSync(filePath)) return null;
|
|
21953
|
+
const raw = fs6.readFileSync(filePath, "utf-8");
|
|
21835
21954
|
const values = parseEnvFile(raw);
|
|
21836
21955
|
const value = values[JWT_SECRET_ENV_KEY];
|
|
21837
21956
|
return isNonEmpty(value) ? value.trim() : null;
|
|
@@ -21854,13 +21973,13 @@ function writeAgentJwtEnv(secret, filePath = resolveEnvFilePath()) {
|
|
|
21854
21973
|
mergePaperclipEnvEntries({ [JWT_SECRET_ENV_KEY]: secret }, filePath);
|
|
21855
21974
|
}
|
|
21856
21975
|
function readPaperclipEnvEntries(filePath = resolveEnvFilePath()) {
|
|
21857
|
-
if (!
|
|
21858
|
-
return parseEnvFile(
|
|
21976
|
+
if (!fs6.existsSync(filePath)) return {};
|
|
21977
|
+
return parseEnvFile(fs6.readFileSync(filePath, "utf-8"));
|
|
21859
21978
|
}
|
|
21860
21979
|
function writePaperclipEnvEntries(entries, filePath = resolveEnvFilePath()) {
|
|
21861
|
-
const dir =
|
|
21862
|
-
|
|
21863
|
-
|
|
21980
|
+
const dir = path8.dirname(filePath);
|
|
21981
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
21982
|
+
fs6.writeFileSync(filePath, renderEnvFile(entries), {
|
|
21864
21983
|
mode: 384
|
|
21865
21984
|
});
|
|
21866
21985
|
}
|
|
@@ -21904,8 +22023,8 @@ var init_npm_command = __esm({
|
|
|
21904
22023
|
// src/runtime/native-payload.ts
|
|
21905
22024
|
import { execFile } from "node:child_process";
|
|
21906
22025
|
import { existsSync as existsSync3 } from "node:fs";
|
|
21907
|
-
import
|
|
21908
|
-
import
|
|
22026
|
+
import fs7 from "node:fs/promises";
|
|
22027
|
+
import path9 from "node:path";
|
|
21909
22028
|
import { performance } from "node:perf_hooks";
|
|
21910
22029
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
21911
22030
|
import { promisify } from "node:util";
|
|
@@ -21914,14 +22033,14 @@ function nativeTarget() {
|
|
|
21914
22033
|
}
|
|
21915
22034
|
function resolveNativePayloadBinary() {
|
|
21916
22035
|
const configured = process.env.RUDDER_NATIVE_PAYLOAD_PATH?.trim() || process.env.RUDDER_NATIVE_PATH?.trim();
|
|
21917
|
-
if (configured) return
|
|
22036
|
+
if (configured) return path9.resolve(configured);
|
|
21918
22037
|
const binaryName = process.platform === "win32" ? "rudder-native.exe" : "rudder-native";
|
|
21919
|
-
const moduleDir =
|
|
22038
|
+
const moduleDir = path9.dirname(fileURLToPath3(import.meta.url));
|
|
21920
22039
|
const target = nativeTarget();
|
|
21921
22040
|
const candidates = [
|
|
21922
|
-
|
|
21923
|
-
|
|
21924
|
-
|
|
22041
|
+
path9.resolve(moduleDir, "../../../native/target/debug", binaryName),
|
|
22042
|
+
path9.resolve(moduleDir, "../../../../native/target/debug", binaryName),
|
|
22043
|
+
path9.resolve(moduleDir, "../../../native", target ?? "unsupported", binaryName)
|
|
21925
22044
|
];
|
|
21926
22045
|
return candidates.find((candidate) => existsSync3(candidate)) ?? candidates[0];
|
|
21927
22046
|
}
|
|
@@ -21994,7 +22113,7 @@ async function verifyNativePayload(archivePath, expectedSha256, maxArchiveBytes,
|
|
|
21994
22113
|
return runNativePayload("payload.verify", [
|
|
21995
22114
|
"payload",
|
|
21996
22115
|
"verify",
|
|
21997
|
-
|
|
22116
|
+
path9.resolve(archivePath),
|
|
21998
22117
|
expectedSha256,
|
|
21999
22118
|
String(maxArchiveBytes)
|
|
22000
22119
|
], false, timeoutMs);
|
|
@@ -22004,9 +22123,9 @@ async function extractNativePayload(archivePath, stagingPath, maxArchiveBytes, t
|
|
|
22004
22123
|
return await runNativePayload("payload.extract", [
|
|
22005
22124
|
"payload",
|
|
22006
22125
|
"extract",
|
|
22007
|
-
|
|
22126
|
+
path9.resolve(archivePath),
|
|
22008
22127
|
"auto",
|
|
22009
|
-
|
|
22128
|
+
path9.resolve(stagingPath),
|
|
22010
22129
|
String(maxArchiveBytes),
|
|
22011
22130
|
String(maxArchiveBytes),
|
|
22012
22131
|
String(maxArchiveBytes * 2),
|
|
@@ -22023,7 +22142,7 @@ async function probeNativePayloadVersion(rootPath, executable, timeoutMs) {
|
|
|
22023
22142
|
return runNativePayload("payload.probeVersion", [
|
|
22024
22143
|
"payload",
|
|
22025
22144
|
"probe-version",
|
|
22026
|
-
|
|
22145
|
+
path9.resolve(rootPath),
|
|
22027
22146
|
executable,
|
|
22028
22147
|
"PostgreSQL 18.4"
|
|
22029
22148
|
], true, timeoutMs);
|
|
@@ -22032,8 +22151,8 @@ async function publishNativePayload(stagingPath, destinationPath, timeoutMs) {
|
|
|
22032
22151
|
return runNativePayload("payload.publish", [
|
|
22033
22152
|
"payload",
|
|
22034
22153
|
"publish",
|
|
22035
|
-
|
|
22036
|
-
|
|
22154
|
+
path9.resolve(stagingPath),
|
|
22155
|
+
path9.resolve(destinationPath)
|
|
22037
22156
|
], true, timeoutMs);
|
|
22038
22157
|
}
|
|
22039
22158
|
async function tryInstallNativePayload(input) {
|
|
@@ -22132,7 +22251,7 @@ async function tryInstallNativePayload(input) {
|
|
|
22132
22251
|
}
|
|
22133
22252
|
};
|
|
22134
22253
|
} finally {
|
|
22135
|
-
const cleanup = input.cleanupPublishStaging ?? ((publishStagingPath) =>
|
|
22254
|
+
const cleanup = input.cleanupPublishStaging ?? ((publishStagingPath) => fs7.rm(publishStagingPath, { recursive: true, force: true }));
|
|
22136
22255
|
void cleanup(input.publishStagingPath).catch(() => {
|
|
22137
22256
|
});
|
|
22138
22257
|
}
|
|
@@ -22173,7 +22292,7 @@ var init_native_payload = __esm({
|
|
|
22173
22292
|
});
|
|
22174
22293
|
|
|
22175
22294
|
// src/runtime/postgres-runtime-download.ts
|
|
22176
|
-
import { createHash as
|
|
22295
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
22177
22296
|
import { createReadStream, createWriteStream } from "node:fs";
|
|
22178
22297
|
import { Readable, Transform } from "node:stream";
|
|
22179
22298
|
import { pipeline } from "node:stream/promises";
|
|
@@ -22192,7 +22311,7 @@ async function downloadRuntimePostgresArchive(url, targetPath, trustedSha256, op
|
|
|
22192
22311
|
const controller = new AbortController();
|
|
22193
22312
|
const timeout = Number.isFinite(parsedTimeout) && parsedTimeout > 0 ? setTimeout(() => controller.abort(), parsedTimeout) : null;
|
|
22194
22313
|
try {
|
|
22195
|
-
const hash =
|
|
22314
|
+
const hash = createHash3("sha256");
|
|
22196
22315
|
let bytes = 0;
|
|
22197
22316
|
const monitor = new Transform({
|
|
22198
22317
|
transform(chunk, _encoding, callback) {
|
|
@@ -22295,7 +22414,7 @@ import { execFileSync, spawnSync as spawnSync2 } from "node:child_process";
|
|
|
22295
22414
|
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2 } from "node:fs";
|
|
22296
22415
|
import { chmod, mkdir, mkdtemp, readFile, readdir, realpath, rename, rm, stat, symlink, writeFile } from "node:fs/promises";
|
|
22297
22416
|
import { createRequire } from "node:module";
|
|
22298
|
-
import
|
|
22417
|
+
import path10 from "node:path";
|
|
22299
22418
|
import { performance as performance2 } from "node:perf_hooks";
|
|
22300
22419
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
22301
22420
|
import { pathToFileURL } from "node:url";
|
|
@@ -22339,7 +22458,7 @@ function resolveRuntimePackageVersion(version) {
|
|
|
22339
22458
|
return normalized.length > 0 ? normalized : "latest";
|
|
22340
22459
|
}
|
|
22341
22460
|
function resolveRuntimeCacheDir(version, homeDir = resolveRudderHomeDir()) {
|
|
22342
|
-
return
|
|
22461
|
+
return path10.join(homeDir, "runtimes", sanitizeRuntimeCacheSegment(resolveRuntimePackageVersion(version)));
|
|
22343
22462
|
}
|
|
22344
22463
|
function resolveRuntimePackageSpec(version, packageName = RUNTIME_NPM_PACKAGE_NAME) {
|
|
22345
22464
|
const packageVersion = resolveRuntimePackageVersion(version);
|
|
@@ -22347,7 +22466,7 @@ function resolveRuntimePackageSpec(version, packageName = RUNTIME_NPM_PACKAGE_NA
|
|
|
22347
22466
|
}
|
|
22348
22467
|
async function readRuntimeInstallMetadata(cacheDir) {
|
|
22349
22468
|
try {
|
|
22350
|
-
const raw = await readFile(
|
|
22469
|
+
const raw = await readFile(path10.join(cacheDir, RUNTIME_METADATA_FILE), "utf8");
|
|
22351
22470
|
const parsed = JSON.parse(raw);
|
|
22352
22471
|
if (parsed.version !== 1) return null;
|
|
22353
22472
|
if (typeof parsed.packageName !== "string" || typeof parsed.packageVersion !== "string") return null;
|
|
@@ -22362,7 +22481,7 @@ async function readRuntimeInstallMetadata(cacheDir) {
|
|
|
22362
22481
|
}
|
|
22363
22482
|
}
|
|
22364
22483
|
async function writeRuntimeInstallMetadata(cacheDir, metadata) {
|
|
22365
|
-
await writeFile(
|
|
22484
|
+
await writeFile(path10.join(cacheDir, RUNTIME_METADATA_FILE), `${JSON.stringify(metadata, null, 2)}
|
|
22366
22485
|
`, "utf8");
|
|
22367
22486
|
}
|
|
22368
22487
|
async function touchRuntimeInstallMetadata(cacheDir, postgresRuntime) {
|
|
@@ -22390,7 +22509,7 @@ function resolveEmbeddedPostgresPlatformPackage(platform = process.platform, arc
|
|
|
22390
22509
|
}
|
|
22391
22510
|
async function canResolveRuntimePackage(cacheDir, packageName) {
|
|
22392
22511
|
try {
|
|
22393
|
-
await readFile(
|
|
22512
|
+
await readFile(path10.join(cacheDir, "node_modules", ...packageName.split("/"), "package.json"), "utf8");
|
|
22394
22513
|
return true;
|
|
22395
22514
|
} catch {
|
|
22396
22515
|
return false;
|
|
@@ -22402,9 +22521,9 @@ async function hasRequiredRuntimePlatformDependencies(cacheDir, metadata, postgr
|
|
|
22402
22521
|
if (!platformPackage) return true;
|
|
22403
22522
|
if (await canResolveRuntimePackage(cacheDir, platformPackage)) return true;
|
|
22404
22523
|
const expectedSharedBinDir = resolveSharedRuntimePostgresPayloadBinDir(
|
|
22405
|
-
|
|
22524
|
+
path10.dirname(path10.dirname(cacheDir))
|
|
22406
22525
|
);
|
|
22407
|
-
return metadata.postgresRuntime?.scope === "shared" && metadata.postgresRuntime.platform === process.platform && metadata.postgresRuntime.arch === process.arch &&
|
|
22526
|
+
return metadata.postgresRuntime?.scope === "shared" && metadata.postgresRuntime.platform === process.platform && metadata.postgresRuntime.arch === process.arch && path10.resolve(metadata.postgresRuntime.binDir) === path10.resolve(expectedSharedBinDir) && await isRuntimePostgresPayloadUsable(
|
|
22408
22527
|
cacheDir,
|
|
22409
22528
|
metadata.postgresRuntime.binDir,
|
|
22410
22529
|
postgresVersionProbe,
|
|
@@ -22419,7 +22538,7 @@ async function isRuntimeCacheHitWithinDeadline(options, deadline) {
|
|
|
22419
22538
|
return false;
|
|
22420
22539
|
}
|
|
22421
22540
|
try {
|
|
22422
|
-
const packageJsonPath =
|
|
22541
|
+
const packageJsonPath = path10.join(options.cacheDir, "node_modules", ...packageName.split("/"), "package.json");
|
|
22423
22542
|
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
|
|
22424
22543
|
const packageVersionMatches = packageVersion === "latest" || packageJson.version === packageVersion;
|
|
22425
22544
|
return packageVersionMatches && await hasRequiredRuntimePlatformDependencies(
|
|
@@ -22439,7 +22558,7 @@ async function ensureRuntimeInstalled(options) {
|
|
|
22439
22558
|
const cacheDir = resolveRuntimeCacheDir(packageVersion, homeDir);
|
|
22440
22559
|
const deadline = createRuntimeInstallDeadline(options);
|
|
22441
22560
|
return withRuntimeFilesystemLock(
|
|
22442
|
-
|
|
22561
|
+
path10.join(homeDir, "runtime-payloads", ".postgres-runtime.lifecycle.lock"),
|
|
22443
22562
|
async () => withRuntimeFilesystemLock(
|
|
22444
22563
|
`${cacheDir}.install.lock`,
|
|
22445
22564
|
async () => {
|
|
@@ -22562,7 +22681,7 @@ async function ensureRuntimeInstalledUnlocked(options, deadline) {
|
|
|
22562
22681
|
}
|
|
22563
22682
|
await rm(cacheDir, { recursive: true, force: true });
|
|
22564
22683
|
await mkdir(cacheDir, { recursive: true });
|
|
22565
|
-
await writeFile(
|
|
22684
|
+
await writeFile(path10.join(cacheDir, "package.json"), `${JSON.stringify(RUNTIME_CACHE_PACKAGE_JSON, null, 2)}
|
|
22566
22685
|
`, "utf8");
|
|
22567
22686
|
const result = runNpmRuntimeInstall(spawnSyncImpl, cacheDir, packageSpec, deadline);
|
|
22568
22687
|
let output = collectSpawnOutput(result);
|
|
@@ -22602,7 +22721,7 @@ async function ensureRuntimeInstalledUnlocked(options, deadline) {
|
|
|
22602
22721
|
}
|
|
22603
22722
|
await rm(fallbackCacheDir, { recursive: true, force: true });
|
|
22604
22723
|
await mkdir(fallbackCacheDir, { recursive: true });
|
|
22605
|
-
await writeFile(
|
|
22724
|
+
await writeFile(path10.join(fallbackCacheDir, "package.json"), `${JSON.stringify(RUNTIME_CACHE_PACKAGE_JSON, null, 2)}
|
|
22606
22725
|
`, "utf8");
|
|
22607
22726
|
const fallbackResult = runNpmRuntimeInstall(spawnSyncImpl, fallbackCacheDir, fallbackSpec, deadline);
|
|
22608
22727
|
let fallbackOutput = collectSpawnOutput(fallbackResult);
|
|
@@ -22684,10 +22803,10 @@ async function ensureRuntimeInstalledUnlocked(options, deadline) {
|
|
|
22684
22803
|
);
|
|
22685
22804
|
}
|
|
22686
22805
|
function resolveRuntimePostgresPayloadBinDir(cacheDir, platform = process.platform, arch = process.arch) {
|
|
22687
|
-
return
|
|
22806
|
+
return path10.join(cacheDir, RUNTIME_POSTGRES_PAYLOAD_DIR, runtimePostgresPlatformSegment(platform, arch), "bin");
|
|
22688
22807
|
}
|
|
22689
22808
|
function resolveSharedRuntimePostgresPayloadBinDir(homeDir = resolveRudderHomeDir(), platform = process.platform, arch = process.arch) {
|
|
22690
|
-
return
|
|
22809
|
+
return path10.join(
|
|
22691
22810
|
homeDir,
|
|
22692
22811
|
"runtime-payloads",
|
|
22693
22812
|
RUNTIME_POSTGRES_PAYLOAD_DIR,
|
|
@@ -22696,7 +22815,7 @@ function resolveSharedRuntimePostgresPayloadBinDir(homeDir = resolveRudderHomeDi
|
|
|
22696
22815
|
);
|
|
22697
22816
|
}
|
|
22698
22817
|
function resolveRuntimeServerEntrypoint(cacheDir, packageName = RUNTIME_NPM_PACKAGE_NAME) {
|
|
22699
|
-
return createRequire(
|
|
22818
|
+
return createRequire(path10.join(cacheDir, "package.json")).resolve(packageName);
|
|
22700
22819
|
}
|
|
22701
22820
|
async function importRuntimeServerModule(cacheDir, packageName = RUNTIME_NPM_PACKAGE_NAME) {
|
|
22702
22821
|
const entrypoint = resolveRuntimeServerEntrypoint(cacheDir, packageName);
|
|
@@ -22720,7 +22839,7 @@ function formatRuntimeInstallCommand(cacheDir, packageSpec) {
|
|
|
22720
22839
|
return `npm install --prefix ${cacheDir} ${RUNTIME_NPM_INSTALL_FLAGS.join(" ")} ${packageSpec}`;
|
|
22721
22840
|
}
|
|
22722
22841
|
function formatRuntimePlatformRepairCommand(cacheDir, packageSpec) {
|
|
22723
|
-
return `npm pack ${packageSpec} --registry=${NPM_PUBLIC_REGISTRY_URL} --silent, then extract it into ${
|
|
22842
|
+
return `npm pack ${packageSpec} --registry=${NPM_PUBLIC_REGISTRY_URL} --silent, then extract it into ${path10.join(cacheDir, "node_modules")}`;
|
|
22724
22843
|
}
|
|
22725
22844
|
function collectSpawnOutput(result) {
|
|
22726
22845
|
return [result.stdout, result.stderr, result.error instanceof Error ? result.error.message : null].filter((value) => typeof value === "string" && value.trim().length > 0).join("\n").trim();
|
|
@@ -22737,7 +22856,7 @@ function withPostgresPayload(result, postgresPayload) {
|
|
|
22737
22856
|
};
|
|
22738
22857
|
}
|
|
22739
22858
|
function runtimePackageJsonPath(cacheDir, packageName) {
|
|
22740
|
-
return
|
|
22859
|
+
return path10.join(cacheDir, "node_modules", ...packageName.split("/"), "package.json");
|
|
22741
22860
|
}
|
|
22742
22861
|
async function readRuntimePackageJson(cacheDir, packageName) {
|
|
22743
22862
|
try {
|
|
@@ -22792,7 +22911,7 @@ async function ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, cach
|
|
|
22792
22911
|
);
|
|
22793
22912
|
}
|
|
22794
22913
|
async function installRuntimePackageInStaging(spawnSyncImpl, cacheDir, packageSpec, packageName, deadline) {
|
|
22795
|
-
const stagingDir =
|
|
22914
|
+
const stagingDir = path10.join(cacheDir, `.platform-repair-${process.pid}-${Date.now()}`);
|
|
22796
22915
|
await mkdir(stagingDir, { recursive: true });
|
|
22797
22916
|
try {
|
|
22798
22917
|
const packResult = runNpmPack(spawnSyncImpl, packageSpec, stagingDir, cacheDir, deadline);
|
|
@@ -22801,9 +22920,9 @@ async function installRuntimePackageInStaging(spawnSyncImpl, cacheDir, packageSp
|
|
|
22801
22920
|
if (!packFilename) {
|
|
22802
22921
|
return createSyntheticSpawnResult(1, "", `Unable to parse npm pack output for ${packageSpec}.`);
|
|
22803
22922
|
}
|
|
22804
|
-
const archivePath =
|
|
22805
|
-
const targetDir =
|
|
22806
|
-
await mkdir(
|
|
22923
|
+
const archivePath = path10.join(stagingDir, packFilename);
|
|
22924
|
+
const targetDir = path10.dirname(runtimePackageJsonPath(cacheDir, packageName));
|
|
22925
|
+
await mkdir(path10.dirname(targetDir), { recursive: true });
|
|
22807
22926
|
await rm(targetDir, { recursive: true, force: true });
|
|
22808
22927
|
await mkdir(targetDir, { recursive: true });
|
|
22809
22928
|
const extractResult = runTarExtract(spawnSyncImpl, archivePath, targetDir, cacheDir, deadline);
|
|
@@ -22859,8 +22978,8 @@ function combineSpawnResults(...results) {
|
|
|
22859
22978
|
}
|
|
22860
22979
|
async function removeRuntimeInstallLocks(cacheDir) {
|
|
22861
22980
|
await Promise.all([
|
|
22862
|
-
rm(
|
|
22863
|
-
rm(
|
|
22981
|
+
rm(path10.join(cacheDir, "package-lock.json"), { force: true }),
|
|
22982
|
+
rm(path10.join(cacheDir, "node_modules", ".package-lock.json"), { force: true })
|
|
22864
22983
|
]);
|
|
22865
22984
|
}
|
|
22866
22985
|
function packageNameFromSpec(packageSpec) {
|
|
@@ -22884,25 +23003,25 @@ function runtimePostgresExecutableName(baseName) {
|
|
|
22884
23003
|
return process.platform === "win32" ? `${baseName}.exe` : baseName;
|
|
22885
23004
|
}
|
|
22886
23005
|
function debianSharedirCandidate(binDir) {
|
|
22887
|
-
const normalized =
|
|
22888
|
-
const parts = normalized.split(
|
|
23006
|
+
const normalized = path10.resolve(binDir);
|
|
23007
|
+
const parts = normalized.split(path10.sep);
|
|
22889
23008
|
const libIndex = parts.lastIndexOf("lib");
|
|
22890
23009
|
if (libIndex < 0) return null;
|
|
22891
23010
|
if (parts[libIndex + 1] !== "postgresql") return null;
|
|
22892
23011
|
const version = parts[libIndex + 2];
|
|
22893
23012
|
if (!version || parts[libIndex + 3] !== "bin") return null;
|
|
22894
|
-
const prefix = parts.slice(0, libIndex).join(
|
|
22895
|
-
return
|
|
23013
|
+
const prefix = parts.slice(0, libIndex).join(path10.sep) || path10.sep;
|
|
23014
|
+
return path10.join(prefix, "share", "postgresql", version);
|
|
22896
23015
|
}
|
|
22897
23016
|
async function resolveRuntimePostgresTemplateDir(binDir, cacheDir = binDir, deadline) {
|
|
22898
23017
|
for (const candidatePath of [
|
|
22899
|
-
|
|
22900
|
-
|
|
23018
|
+
path10.join(binDir, "..", "share", "postgresql", "postgres.bki"),
|
|
23019
|
+
path10.join(binDir, "..", "share", "postgres.bki")
|
|
22901
23020
|
]) {
|
|
22902
23021
|
remainingRuntimeInstallMs(deadline, cacheDir, "discover PostgreSQL runtime templates");
|
|
22903
23022
|
try {
|
|
22904
23023
|
await stat(candidatePath);
|
|
22905
|
-
return
|
|
23024
|
+
return path10.dirname(candidatePath);
|
|
22906
23025
|
} catch {
|
|
22907
23026
|
}
|
|
22908
23027
|
}
|
|
@@ -22910,12 +23029,12 @@ async function resolveRuntimePostgresTemplateDir(binDir, cacheDir = binDir, dead
|
|
|
22910
23029
|
if (debianSharedir) {
|
|
22911
23030
|
remainingRuntimeInstallMs(deadline, cacheDir, "discover PostgreSQL runtime templates");
|
|
22912
23031
|
try {
|
|
22913
|
-
await stat(
|
|
23032
|
+
await stat(path10.join(debianSharedir, "postgres.bki"));
|
|
22914
23033
|
return debianSharedir;
|
|
22915
23034
|
} catch {
|
|
22916
23035
|
}
|
|
22917
23036
|
}
|
|
22918
|
-
const pgConfigPath =
|
|
23037
|
+
const pgConfigPath = path10.join(binDir, process.platform === "win32" ? "pg_config.exe" : "pg_config");
|
|
22919
23038
|
try {
|
|
22920
23039
|
remainingRuntimeInstallMs(deadline, cacheDir, "discover PostgreSQL runtime templates");
|
|
22921
23040
|
await stat(pgConfigPath);
|
|
@@ -22934,7 +23053,7 @@ async function resolveRuntimePostgresTemplateDir(binDir, cacheDir = binDir, dead
|
|
|
22934
23053
|
}
|
|
22935
23054
|
if (!sharedir) return null;
|
|
22936
23055
|
remainingRuntimeInstallMs(deadline, cacheDir, "validate PostgreSQL runtime templates");
|
|
22937
|
-
const candidatePath =
|
|
23056
|
+
const candidatePath = path10.join(sharedir, "postgres.bki");
|
|
22938
23057
|
await stat(candidatePath);
|
|
22939
23058
|
return sharedir;
|
|
22940
23059
|
} catch (error) {
|
|
@@ -22943,7 +23062,7 @@ async function resolveRuntimePostgresTemplateDir(binDir, cacheDir = binDir, dead
|
|
|
22943
23062
|
}
|
|
22944
23063
|
}
|
|
22945
23064
|
function resolveRuntimePostgresShareDir(binDir, templateDir) {
|
|
22946
|
-
const adjacentShareDir =
|
|
23065
|
+
const adjacentShareDir = path10.resolve(binDir, "..", "share");
|
|
22947
23066
|
return pathIsInside(templateDir, adjacentShareDir) ? adjacentShareDir : templateDir;
|
|
22948
23067
|
}
|
|
22949
23068
|
async function assertRuntimePostgresBinDirComplete(cacheDir, binDir, deadline) {
|
|
@@ -22951,7 +23070,7 @@ async function assertRuntimePostgresBinDirComplete(cacheDir, binDir, deadline) {
|
|
|
22951
23070
|
const missing = [];
|
|
22952
23071
|
for (const binary of requiredBinaries) {
|
|
22953
23072
|
remainingRuntimeInstallMs(deadline, cacheDir, "validate PostgreSQL runtime binaries");
|
|
22954
|
-
const binaryPath =
|
|
23073
|
+
const binaryPath = path10.join(binDir, runtimePostgresExecutableName(binary));
|
|
22955
23074
|
try {
|
|
22956
23075
|
await stat(binaryPath);
|
|
22957
23076
|
} catch {
|
|
@@ -22960,19 +23079,19 @@ async function assertRuntimePostgresBinDirComplete(cacheDir, binDir, deadline) {
|
|
|
22960
23079
|
}
|
|
22961
23080
|
const templateDir = await resolveRuntimePostgresTemplateDir(binDir, cacheDir, deadline);
|
|
22962
23081
|
if (!templateDir) {
|
|
22963
|
-
missing.push(
|
|
23082
|
+
missing.push(path10.join(binDir, "..", "share", "postgresql", "postgres.bki"));
|
|
22964
23083
|
} else {
|
|
22965
23084
|
try {
|
|
22966
|
-
await stat(
|
|
23085
|
+
await stat(path10.join(templateDir, "postgresql.conf.sample"));
|
|
22967
23086
|
} catch {
|
|
22968
|
-
missing.push(
|
|
23087
|
+
missing.push(path10.join(templateDir, "postgresql.conf.sample"));
|
|
22969
23088
|
}
|
|
22970
23089
|
const shareDir = resolveRuntimePostgresShareDir(binDir, templateDir);
|
|
22971
23090
|
const hasTimezoneDir = (await Promise.all([
|
|
22972
|
-
|
|
22973
|
-
|
|
23091
|
+
path10.join(templateDir, "timezone"),
|
|
23092
|
+
path10.join(shareDir, "timezone")
|
|
22974
23093
|
].map((candidate) => stat(candidate).catch(() => null)))).some((candidate) => candidate?.isDirectory());
|
|
22975
|
-
if (!hasTimezoneDir) missing.push(
|
|
23094
|
+
if (!hasTimezoneDir) missing.push(path10.join(shareDir, "timezone"));
|
|
22976
23095
|
}
|
|
22977
23096
|
if (missing.length > 0) {
|
|
22978
23097
|
throw new RuntimeInstallError(
|
|
@@ -22997,8 +23116,8 @@ async function isRuntimePostgresPayloadUsable(cacheDir, binDir, postgresVersionP
|
|
|
22997
23116
|
}
|
|
22998
23117
|
}
|
|
22999
23118
|
function pathIsInside(candidatePath, rootPath) {
|
|
23000
|
-
const relative =
|
|
23001
|
-
return relative === "" || relative !== ".." && !relative.startsWith(`..${
|
|
23119
|
+
const relative = path10.relative(path10.resolve(rootPath), path10.resolve(candidatePath));
|
|
23120
|
+
return relative === "" || relative !== ".." && !relative.startsWith(`..${path10.sep}`) && !path10.isAbsolute(relative);
|
|
23002
23121
|
}
|
|
23003
23122
|
async function copyRuntimePayloadEntry(sourcePath, targetPath, cacheDir, deadline, signal, command) {
|
|
23004
23123
|
if (signal.aborted) throw runtimeInstallDeadlineError(cacheDir, command);
|
|
@@ -23011,8 +23130,8 @@ async function copyRuntimePayloadEntry(sourcePath, targetPath, cacheDir, deadlin
|
|
|
23011
23130
|
const entries = await readdir(sourcePath);
|
|
23012
23131
|
for (const entry of entries) {
|
|
23013
23132
|
await copyRuntimePayloadEntry(
|
|
23014
|
-
|
|
23015
|
-
|
|
23133
|
+
path10.join(sourcePath, entry),
|
|
23134
|
+
path10.join(targetPath, entry),
|
|
23016
23135
|
cacheDir,
|
|
23017
23136
|
deadline,
|
|
23018
23137
|
signal,
|
|
@@ -23022,7 +23141,7 @@ async function copyRuntimePayloadEntry(sourcePath, targetPath, cacheDir, deadlin
|
|
|
23022
23141
|
return;
|
|
23023
23142
|
}
|
|
23024
23143
|
if (!sourceStats.isFile()) return;
|
|
23025
|
-
await mkdir(
|
|
23144
|
+
await mkdir(path10.dirname(targetPath), { recursive: true });
|
|
23026
23145
|
try {
|
|
23027
23146
|
await pipeline2(
|
|
23028
23147
|
createReadStream2(sourcePath),
|
|
@@ -23056,11 +23175,11 @@ async function copyRuntimePostgresPayloadWithinDeadline(sourceRuntimeDir, target
|
|
|
23056
23175
|
const copyPromise = (async () => {
|
|
23057
23176
|
await mkdir(targetRuntimeDir, { recursive: true });
|
|
23058
23177
|
for (const directoryName of ["bin", "lib"]) {
|
|
23059
|
-
const sourceDirectory =
|
|
23178
|
+
const sourceDirectory = path10.join(sourceRuntimeDir, directoryName);
|
|
23060
23179
|
if (!await stat(sourceDirectory).catch(() => null)) continue;
|
|
23061
23180
|
await copyRuntimePayloadEntry(
|
|
23062
23181
|
sourceDirectory,
|
|
23063
|
-
|
|
23182
|
+
path10.join(targetRuntimeDir, directoryName),
|
|
23064
23183
|
cacheDir,
|
|
23065
23184
|
deadline,
|
|
23066
23185
|
controller.signal,
|
|
@@ -23069,7 +23188,7 @@ async function copyRuntimePostgresPayloadWithinDeadline(sourceRuntimeDir, target
|
|
|
23069
23188
|
}
|
|
23070
23189
|
await copyRuntimePayloadEntry(
|
|
23071
23190
|
sourceShareDir,
|
|
23072
|
-
|
|
23191
|
+
path10.join(targetRuntimeDir, "share"),
|
|
23073
23192
|
cacheDir,
|
|
23074
23193
|
deadline,
|
|
23075
23194
|
controller.signal,
|
|
@@ -23087,15 +23206,15 @@ async function copyRuntimePostgresPayloadWithinDeadline(sourceRuntimeDir, target
|
|
|
23087
23206
|
async function withRuntimeFilesystemLock(lockPath, task, options = {}) {
|
|
23088
23207
|
const deadlineTimeout = remainingRuntimeInstallMs(
|
|
23089
23208
|
options.deadline,
|
|
23090
|
-
options.cacheDir ??
|
|
23209
|
+
options.cacheDir ?? path10.dirname(lockPath),
|
|
23091
23210
|
options.command ?? `wait for runtime lock ${lockPath}`
|
|
23092
23211
|
);
|
|
23093
23212
|
const timeoutMs = Math.min(options.timeoutMs ?? 3e4, deadlineTimeout ?? Number.POSITIVE_INFINITY);
|
|
23094
23213
|
const pollMs = options.pollMs ?? 50;
|
|
23095
23214
|
const startedAt = Date.now();
|
|
23096
23215
|
const lockId = `${process.pid}-${startedAt}-${Math.random().toString(16).slice(2)}`;
|
|
23097
|
-
const ownerPath =
|
|
23098
|
-
await mkdir(
|
|
23216
|
+
const ownerPath = path10.join(lockPath, "owner.json");
|
|
23217
|
+
await mkdir(path10.dirname(lockPath), { recursive: true });
|
|
23099
23218
|
while (true) {
|
|
23100
23219
|
try {
|
|
23101
23220
|
await mkdir(lockPath);
|
|
@@ -23124,12 +23243,12 @@ async function withRuntimeFilesystemLock(lockPath, task, options = {}) {
|
|
|
23124
23243
|
if (Date.now() - startedAt >= timeoutMs) {
|
|
23125
23244
|
throw new RuntimeInstallError(
|
|
23126
23245
|
`Timed out waiting for PostgreSQL runtime install lock ${lockPath}`,
|
|
23127
|
-
{ cacheDir:
|
|
23246
|
+
{ cacheDir: path10.dirname(lockPath), command: "prepare shared PostgreSQL runtime", output: "" }
|
|
23128
23247
|
);
|
|
23129
23248
|
}
|
|
23130
23249
|
remainingRuntimeInstallMs(
|
|
23131
23250
|
options.deadline,
|
|
23132
|
-
options.cacheDir ??
|
|
23251
|
+
options.cacheDir ?? path10.dirname(lockPath),
|
|
23133
23252
|
options.command ?? `wait for runtime lock ${lockPath}`
|
|
23134
23253
|
);
|
|
23135
23254
|
await new Promise((resolve) => setTimeout(resolve, pollMs));
|
|
@@ -23149,29 +23268,29 @@ async function withRuntimeFilesystemLock(lockPath, task, options = {}) {
|
|
|
23149
23268
|
}
|
|
23150
23269
|
function isManagedRuntimePostgresBinDir(binDir, homeDir) {
|
|
23151
23270
|
const managedBinDir = process.env[RUDDER_DESKTOP_MANAGED_POSTGRES_BIN_DIR_ENV]?.trim();
|
|
23152
|
-
if (managedBinDir &&
|
|
23153
|
-
const runtimesRelative =
|
|
23154
|
-
|
|
23155
|
-
|
|
23271
|
+
if (managedBinDir && path10.resolve(managedBinDir) === path10.resolve(binDir)) return true;
|
|
23272
|
+
const runtimesRelative = path10.relative(
|
|
23273
|
+
path10.join(homeDir, "runtimes"),
|
|
23274
|
+
path10.resolve(binDir)
|
|
23156
23275
|
);
|
|
23157
|
-
const runtimeSegments = runtimesRelative.split(
|
|
23158
|
-
if (runtimesRelative !== "" && runtimesRelative !== ".." && !runtimesRelative.startsWith(`..${
|
|
23276
|
+
const runtimeSegments = runtimesRelative.split(path10.sep);
|
|
23277
|
+
if (runtimesRelative !== "" && runtimesRelative !== ".." && !runtimesRelative.startsWith(`..${path10.sep}`) && !path10.isAbsolute(runtimesRelative) && runtimeSegments.length === 4 && runtimeSegments[0]?.length > 0 && runtimeSegments[1] === RUNTIME_POSTGRES_PAYLOAD_DIR && runtimeSegments[2] === `${process.platform}-${process.arch}` && runtimeSegments[3] === "bin") {
|
|
23159
23278
|
return true;
|
|
23160
23279
|
}
|
|
23161
|
-
const payloadsRelative =
|
|
23162
|
-
|
|
23163
|
-
|
|
23280
|
+
const payloadsRelative = path10.relative(
|
|
23281
|
+
path10.join(homeDir, "runtime-payloads"),
|
|
23282
|
+
path10.resolve(binDir)
|
|
23164
23283
|
);
|
|
23165
|
-
const payloadSegments = payloadsRelative.split(
|
|
23166
|
-
return payloadsRelative !== "" && payloadsRelative !== ".." && !payloadsRelative.startsWith(`..${
|
|
23284
|
+
const payloadSegments = payloadsRelative.split(path10.sep);
|
|
23285
|
+
return payloadsRelative !== "" && payloadsRelative !== ".." && !payloadsRelative.startsWith(`..${path10.sep}`) && !path10.isAbsolute(payloadsRelative) && payloadSegments.length === 3 && payloadSegments[0] === RUNTIME_POSTGRES_PAYLOAD_DIR && payloadSegments[1] === `${process.platform}-${process.arch}` && payloadSegments[2] === "bin";
|
|
23167
23286
|
}
|
|
23168
23287
|
async function findLegacyRuntimePostgresBinDir(cacheDir, homeDir, postgresVersionProbe, deadline) {
|
|
23169
|
-
const runtimesRoot =
|
|
23288
|
+
const runtimesRoot = path10.join(homeDir, "runtimes");
|
|
23170
23289
|
const entries = await readdir(runtimesRoot, { withFileTypes: true }).catch(() => []);
|
|
23171
23290
|
for (const entry of entries) {
|
|
23172
23291
|
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
23173
|
-
const candidateCacheDir =
|
|
23174
|
-
if (
|
|
23292
|
+
const candidateCacheDir = path10.join(runtimesRoot, entry.name);
|
|
23293
|
+
if (path10.resolve(candidateCacheDir) === path10.resolve(cacheDir)) continue;
|
|
23175
23294
|
const candidateBinDir = resolveRuntimePostgresPayloadBinDir(candidateCacheDir);
|
|
23176
23295
|
remainingRuntimeInstallMs(deadline, cacheDir, "find cached PostgreSQL runtime payload");
|
|
23177
23296
|
if (await isRuntimePostgresPayloadUsable(cacheDir, candidateBinDir, postgresVersionProbe, deadline)) {
|
|
@@ -23181,13 +23300,13 @@ async function findLegacyRuntimePostgresBinDir(cacheDir, homeDir, postgresVersio
|
|
|
23181
23300
|
return null;
|
|
23182
23301
|
}
|
|
23183
23302
|
async function readLiveRuntimeDescriptors(homeDir) {
|
|
23184
|
-
const instancesRoot =
|
|
23303
|
+
const instancesRoot = path10.join(homeDir, "instances");
|
|
23185
23304
|
const entries = await readdir(instancesRoot, { withFileTypes: true }).catch(() => []);
|
|
23186
23305
|
const descriptors = [];
|
|
23187
23306
|
for (const entry of entries) {
|
|
23188
23307
|
if (!entry.isDirectory()) continue;
|
|
23189
23308
|
try {
|
|
23190
|
-
const raw = JSON.parse(await readFile(
|
|
23309
|
+
const raw = JSON.parse(await readFile(path10.join(instancesRoot, entry.name, "runtime", "server.json"), "utf8"));
|
|
23191
23310
|
if (typeof raw.pid !== "number" || !Number.isInteger(raw.pid) || !isPidRunning(raw.pid) || typeof raw.version !== "string") {
|
|
23192
23311
|
continue;
|
|
23193
23312
|
}
|
|
@@ -23205,13 +23324,13 @@ async function assertSharedPostgresPayloadNotLive(cacheDir, homeDir, sharedBinDi
|
|
|
23205
23324
|
const sharedPhysicalBinDir = await realpath(sharedBinDir).catch(() => null);
|
|
23206
23325
|
const mayReferenceSharedPayload = await Promise.all(liveDescriptors.map(async (descriptor) => {
|
|
23207
23326
|
if (descriptor.postgresBinDir === void 0) return true;
|
|
23208
|
-
if (
|
|
23327
|
+
if (path10.resolve(descriptor.postgresBinDir) === path10.resolve(sharedBinDir)) return true;
|
|
23209
23328
|
const descriptorPhysicalBinDir = await realpath(descriptor.postgresBinDir).catch(() => null);
|
|
23210
|
-
if (descriptorPhysicalBinDir && sharedPhysicalBinDir &&
|
|
23329
|
+
if (descriptorPhysicalBinDir && sharedPhysicalBinDir && path10.resolve(descriptorPhysicalBinDir) === path10.resolve(sharedPhysicalBinDir)) {
|
|
23211
23330
|
return true;
|
|
23212
23331
|
}
|
|
23213
23332
|
if (!descriptorPhysicalBinDir) {
|
|
23214
|
-
return pathIsInside(descriptor.postgresBinDir,
|
|
23333
|
+
return pathIsInside(descriptor.postgresBinDir, path10.join(homeDir, "runtimes")) || pathIsInside(descriptor.postgresBinDir, path10.join(homeDir, "runtime-payloads"));
|
|
23215
23334
|
}
|
|
23216
23335
|
return false;
|
|
23217
23336
|
}));
|
|
@@ -23226,7 +23345,7 @@ async function validateRuntimePostgresVersion(cacheDir, binDir, postgresVersionP
|
|
|
23226
23345
|
await assertRuntimePostgresBinDirComplete(cacheDir, binDir, deadline);
|
|
23227
23346
|
for (const binary of ["initdb", "pg_ctl", "postgres"]) {
|
|
23228
23347
|
remainingRuntimeInstallMs(deadline, cacheDir, "validate PostgreSQL runtime version");
|
|
23229
|
-
const binaryPath =
|
|
23348
|
+
const binaryPath = path10.join(binDir, runtimePostgresExecutableName(binary));
|
|
23230
23349
|
const result = postgresVersionProbe(binaryPath);
|
|
23231
23350
|
if (!/\bPostgreSQL\)?\s+18\.4\b/i.test(result)) {
|
|
23232
23351
|
throw new RuntimeInstallError(
|
|
@@ -23266,24 +23385,24 @@ async function findRuntimePostgresBinDir(rootDir, cacheDir, postgresVersionProbe
|
|
|
23266
23385
|
if (await isRuntimePostgresPayloadUsable(cacheDir, current, postgresVersionProbe, deadline)) return current;
|
|
23267
23386
|
const entries = await readdir(current, { withFileTypes: true }).catch(() => []);
|
|
23268
23387
|
for (const entry of entries) {
|
|
23269
|
-
if (entry.isDirectory()) queue.push(
|
|
23388
|
+
if (entry.isDirectory()) queue.push(path10.join(current, entry.name));
|
|
23270
23389
|
}
|
|
23271
23390
|
}
|
|
23272
23391
|
return null;
|
|
23273
23392
|
}
|
|
23274
23393
|
async function reconcileSharedPostgresPayloadGenerations(cacheDir, sharedPlatformRoot, postgresVersionProbe, cleanupDownloads = false, deadline) {
|
|
23275
23394
|
remainingRuntimeInstallMs(deadline, cacheDir, "reconcile shared PostgreSQL payload");
|
|
23276
|
-
const parentDir =
|
|
23277
|
-
const baseName =
|
|
23395
|
+
const parentDir = path10.dirname(sharedPlatformRoot);
|
|
23396
|
+
const baseName = path10.basename(sharedPlatformRoot);
|
|
23278
23397
|
const entries = await readdir(parentDir, { withFileTypes: true }).catch(() => []);
|
|
23279
|
-
const temporaryRoots = entries.filter((entry) => entry.name.startsWith(`${baseName}.tmp-`)).map((entry) =>
|
|
23280
|
-
const previousRoots = entries.filter((entry) => entry.name.startsWith(`${baseName}.previous-`)).map((entry) =>
|
|
23281
|
-
const downloadsRoot =
|
|
23282
|
-
|
|
23398
|
+
const temporaryRoots = entries.filter((entry) => entry.name.startsWith(`${baseName}.tmp-`)).map((entry) => path10.join(parentDir, entry.name));
|
|
23399
|
+
const previousRoots = entries.filter((entry) => entry.name.startsWith(`${baseName}.previous-`)).map((entry) => path10.join(parentDir, entry.name)).sort().reverse();
|
|
23400
|
+
const downloadsRoot = path10.join(
|
|
23401
|
+
path10.dirname(path10.dirname(sharedPlatformRoot)),
|
|
23283
23402
|
".downloads"
|
|
23284
23403
|
);
|
|
23285
|
-
const staleDownloadRoots = cleanupDownloads ? (await readdir(downloadsRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.name.startsWith("postgres-18.4-")).map((entry) =>
|
|
23286
|
-
const canonicalBinDir =
|
|
23404
|
+
const staleDownloadRoots = cleanupDownloads ? (await readdir(downloadsRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.name.startsWith("postgres-18.4-")).map((entry) => path10.join(downloadsRoot, entry.name)) : [];
|
|
23405
|
+
const canonicalBinDir = path10.join(sharedPlatformRoot, "bin");
|
|
23287
23406
|
if (!await isRuntimePostgresPayloadUsable(
|
|
23288
23407
|
cacheDir,
|
|
23289
23408
|
canonicalBinDir,
|
|
@@ -23293,7 +23412,7 @@ async function reconcileSharedPostgresPayloadGenerations(cacheDir, sharedPlatfor
|
|
|
23293
23412
|
for (const previousRoot of previousRoots) {
|
|
23294
23413
|
if (!await isRuntimePostgresPayloadUsable(
|
|
23295
23414
|
cacheDir,
|
|
23296
|
-
|
|
23415
|
+
path10.join(previousRoot, "bin"),
|
|
23297
23416
|
postgresVersionProbe,
|
|
23298
23417
|
deadline
|
|
23299
23418
|
)) {
|
|
@@ -23312,9 +23431,9 @@ async function reconcileSharedPostgresPayloadGenerations(cacheDir, sharedPlatfor
|
|
|
23312
23431
|
}
|
|
23313
23432
|
async function installSharedRuntimePostgresPayload(cacheDir, homeDir, sourceBinDir, postgresVersionProbe, deadline) {
|
|
23314
23433
|
const sharedBinDir = resolveSharedRuntimePostgresPayloadBinDir(homeDir);
|
|
23315
|
-
const sharedRuntimeDir =
|
|
23434
|
+
const sharedRuntimeDir = path10.dirname(sharedBinDir);
|
|
23316
23435
|
const sharedPlatformRoot = sharedRuntimeDir;
|
|
23317
|
-
const sourceRuntimeDir =
|
|
23436
|
+
const sourceRuntimeDir = path10.dirname(sourceBinDir);
|
|
23318
23437
|
const sourceTemplateDir = await resolveRuntimePostgresTemplateDir(sourceBinDir, cacheDir, deadline);
|
|
23319
23438
|
if (!sourceTemplateDir) {
|
|
23320
23439
|
throw new RuntimeInstallError(
|
|
@@ -23335,7 +23454,7 @@ async function installSharedRuntimePostgresPayload(cacheDir, homeDir, sourceBinD
|
|
|
23335
23454
|
return sharedBinDir;
|
|
23336
23455
|
}
|
|
23337
23456
|
await assertSharedPostgresPayloadNotLive(cacheDir, homeDir, sharedBinDir);
|
|
23338
|
-
await mkdir(
|
|
23457
|
+
await mkdir(path10.dirname(sharedPlatformRoot), { recursive: true });
|
|
23339
23458
|
const temporaryPlatformRoot = `${sharedPlatformRoot}.tmp-${process.pid}-${Date.now()}`;
|
|
23340
23459
|
const previousPlatformRoot = `${sharedPlatformRoot}.previous-${process.pid}-${Date.now()}`;
|
|
23341
23460
|
let previousMoved = false;
|
|
@@ -23352,7 +23471,7 @@ async function installSharedRuntimePostgresPayload(cacheDir, homeDir, sourceBinD
|
|
|
23352
23471
|
cacheDir,
|
|
23353
23472
|
deadline
|
|
23354
23473
|
);
|
|
23355
|
-
const temporaryBinDir =
|
|
23474
|
+
const temporaryBinDir = path10.join(temporaryRuntimeDir, "bin");
|
|
23356
23475
|
await validateRuntimePostgresVersion(cacheDir, temporaryBinDir, postgresVersionProbe, deadline);
|
|
23357
23476
|
try {
|
|
23358
23477
|
await rename(sharedPlatformRoot, previousPlatformRoot);
|
|
@@ -23388,17 +23507,17 @@ async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresV
|
|
|
23388
23507
|
const archiveUrl = archiveSource?.url ?? null;
|
|
23389
23508
|
if (!archiveUrl) return null;
|
|
23390
23509
|
const sharedBinDir = resolveSharedRuntimePostgresPayloadBinDir(homeDir);
|
|
23391
|
-
const sharedPlatformRoot =
|
|
23510
|
+
const sharedPlatformRoot = path10.dirname(sharedBinDir);
|
|
23392
23511
|
const downloadLockPath = `${sharedPlatformRoot}.download.lock`;
|
|
23393
23512
|
return withRuntimeFilesystemLock(downloadLockPath, async () => {
|
|
23394
23513
|
if (await isRuntimePostgresPayloadUsable(cacheDir, sharedBinDir, postgresVersionProbe, deadline)) {
|
|
23395
23514
|
return sharedBinDir;
|
|
23396
23515
|
}
|
|
23397
|
-
const workRoot =
|
|
23516
|
+
const workRoot = path10.join(homeDir, "runtime-payloads", ".downloads");
|
|
23398
23517
|
await mkdir(workRoot, { recursive: true });
|
|
23399
|
-
const workDir = await mkdtemp(
|
|
23400
|
-
const archivePath =
|
|
23401
|
-
const extractDir =
|
|
23518
|
+
const workDir = await mkdtemp(path10.join(workRoot, "postgres-18.4-"));
|
|
23519
|
+
const archivePath = path10.join(workDir, "postgresql-18.4.zip");
|
|
23520
|
+
const extractDir = path10.join(workDir, "extract");
|
|
23402
23521
|
try {
|
|
23403
23522
|
await downloadRuntimePostgresArchive(
|
|
23404
23523
|
archiveUrl,
|
|
@@ -23409,7 +23528,7 @@ async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresV
|
|
|
23409
23528
|
const configuredMaxBytes = Number.parseInt(process.env[RUDDER_POSTGRES_RUNTIME_ARCHIVE_MAX_BYTES_ENV2] ?? "", 10);
|
|
23410
23529
|
const maxArchiveBytes = Number.isSafeInteger(configuredMaxBytes) && configuredMaxBytes > 0 ? configuredMaxBytes : DEFAULT_RUNTIME_POSTGRES_ARCHIVE_MAX_BYTES2;
|
|
23411
23530
|
const nativePublishStaging = `${sharedPlatformRoot}.tmp-native-${process.pid}-${Date.now()}`;
|
|
23412
|
-
await mkdir(
|
|
23531
|
+
await mkdir(path10.dirname(sharedPlatformRoot), { recursive: true });
|
|
23413
23532
|
const nativeInstall = await tryInstallNativePayload({
|
|
23414
23533
|
archivePath,
|
|
23415
23534
|
extractPath: extractDir,
|
|
@@ -23441,22 +23560,22 @@ async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresV
|
|
|
23441
23560
|
);
|
|
23442
23561
|
}
|
|
23443
23562
|
await copyRuntimePostgresPayloadWithinDeadline(
|
|
23444
|
-
|
|
23563
|
+
path10.dirname(extractedBinDir2),
|
|
23445
23564
|
publishStagingPath,
|
|
23446
23565
|
resolveRuntimePostgresShareDir(extractedBinDir2, templateDir),
|
|
23447
23566
|
cacheDir,
|
|
23448
23567
|
deadline,
|
|
23449
23568
|
context.signal
|
|
23450
23569
|
);
|
|
23451
|
-
return
|
|
23570
|
+
return path10.relative(
|
|
23452
23571
|
publishStagingPath,
|
|
23453
|
-
|
|
23572
|
+
path10.join(publishStagingPath, "bin", runtimePostgresExecutableName("postgres"))
|
|
23454
23573
|
);
|
|
23455
23574
|
},
|
|
23456
23575
|
validatePublished: async (destinationPath) => {
|
|
23457
23576
|
await validateRuntimePostgresVersion(
|
|
23458
23577
|
cacheDir,
|
|
23459
|
-
|
|
23578
|
+
path10.join(destinationPath, "bin"),
|
|
23460
23579
|
postgresVersionProbe,
|
|
23461
23580
|
deadline
|
|
23462
23581
|
);
|
|
@@ -23494,20 +23613,20 @@ async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresV
|
|
|
23494
23613
|
}, { deadline, cacheDir, command: "acquire shared PostgreSQL download lock" });
|
|
23495
23614
|
}
|
|
23496
23615
|
async function ensureRuntimePostgresCompatibilityLink(cacheDir, homeDir, packageVersion) {
|
|
23497
|
-
const compatibilityRoot =
|
|
23498
|
-
const sharedPayloadRoot =
|
|
23616
|
+
const compatibilityRoot = path10.join(cacheDir, RUNTIME_POSTGRES_PAYLOAD_DIR);
|
|
23617
|
+
const sharedPayloadRoot = path10.join(homeDir, "runtime-payloads", RUNTIME_POSTGRES_PAYLOAD_DIR);
|
|
23499
23618
|
const runtimeMetadata = await readRuntimeInstallMetadata(cacheDir);
|
|
23500
23619
|
const liveDescriptors = await readLiveRuntimeDescriptors(homeDir);
|
|
23501
23620
|
const compatibilityBinDir = resolveRuntimePostgresPayloadBinDir(cacheDir);
|
|
23502
23621
|
const isProtected = liveDescriptors.some((descriptor) => descriptor.postgresBinDir && pathIsInside(descriptor.postgresBinDir, compatibilityRoot) || !descriptor.postgresBinDir && descriptor.version === (runtimeMetadata?.packageVersion ?? packageVersion));
|
|
23503
23622
|
if (isProtected) return;
|
|
23504
|
-
await mkdir(
|
|
23623
|
+
await mkdir(path10.dirname(compatibilityRoot), { recursive: true });
|
|
23505
23624
|
const temporaryRoot = `${compatibilityRoot}.next-${process.pid}-${Date.now()}`;
|
|
23506
23625
|
const previousRoot = `${compatibilityRoot}.previous-${process.pid}-${Date.now()}`;
|
|
23507
23626
|
await rm(temporaryRoot, { recursive: true, force: true });
|
|
23508
23627
|
await rm(previousRoot, { recursive: true, force: true });
|
|
23509
23628
|
await symlink(
|
|
23510
|
-
process.platform === "win32" ? sharedPayloadRoot :
|
|
23629
|
+
process.platform === "win32" ? sharedPayloadRoot : path10.relative(path10.dirname(compatibilityRoot), sharedPayloadRoot),
|
|
23511
23630
|
temporaryRoot,
|
|
23512
23631
|
process.platform === "win32" ? "junction" : "dir"
|
|
23513
23632
|
);
|
|
@@ -23540,7 +23659,7 @@ async function ensureRuntimePostgresCompatibilityLink(cacheDir, homeDir, package
|
|
|
23540
23659
|
async function stageRuntimePostgresPayload(cacheDir, homeDir, packageVersion, enabled, postgresVersionProbe, deadline, cleanupDownloadWorkDir) {
|
|
23541
23660
|
if (!enabled) return { output: "" };
|
|
23542
23661
|
const explicitSourceBinDir = process.env[RUDDER_POSTGRES_BIN_DIR_ENV]?.trim();
|
|
23543
|
-
const resolvedExplicitSourceBinDir = explicitSourceBinDir ?
|
|
23662
|
+
const resolvedExplicitSourceBinDir = explicitSourceBinDir ? path10.resolve(explicitSourceBinDir) : null;
|
|
23544
23663
|
if (resolvedExplicitSourceBinDir && !isManagedRuntimePostgresBinDir(resolvedExplicitSourceBinDir, homeDir)) {
|
|
23545
23664
|
await validateRuntimePostgresVersion(
|
|
23546
23665
|
cacheDir,
|
|
@@ -23561,7 +23680,7 @@ async function stageRuntimePostgresPayload(cacheDir, homeDir, packageVersion, en
|
|
|
23561
23680
|
};
|
|
23562
23681
|
}
|
|
23563
23682
|
const sharedBinDir = resolveSharedRuntimePostgresPayloadBinDir(homeDir);
|
|
23564
|
-
const sharedPlatformRoot =
|
|
23683
|
+
const sharedPlatformRoot = path10.dirname(sharedBinDir);
|
|
23565
23684
|
await withRuntimeFilesystemLock(
|
|
23566
23685
|
`${sharedPlatformRoot}.install.lock`,
|
|
23567
23686
|
async () => reconcileSharedPostgresPayloadGenerations(
|
|
@@ -23673,13 +23792,13 @@ async function pruneRuntimeCache(options = {}) {
|
|
|
23673
23792
|
};
|
|
23674
23793
|
}
|
|
23675
23794
|
async function scanRuntimeCacheEntries(homeDir) {
|
|
23676
|
-
const runtimesDir =
|
|
23795
|
+
const runtimesDir = path10.join(homeDir, "runtimes");
|
|
23677
23796
|
const dirents = await readdir(runtimesDir, { withFileTypes: true }).catch(() => null);
|
|
23678
23797
|
if (!dirents) return [];
|
|
23679
23798
|
const entries = [];
|
|
23680
23799
|
for (const dirent of dirents) {
|
|
23681
23800
|
if (!dirent.isDirectory()) continue;
|
|
23682
|
-
const cacheDir =
|
|
23801
|
+
const cacheDir = path10.join(runtimesDir, dirent.name);
|
|
23683
23802
|
const metadata = await readRuntimeInstallMetadata(cacheDir);
|
|
23684
23803
|
if (!metadata) continue;
|
|
23685
23804
|
const fallbackStat = await safeStat(cacheDir);
|
|
@@ -23712,7 +23831,7 @@ async function directorySizeBytes(targetPath) {
|
|
|
23712
23831
|
if (!dirents) return 0;
|
|
23713
23832
|
let total = 0;
|
|
23714
23833
|
for (const dirent of dirents) {
|
|
23715
|
-
const entryPath =
|
|
23834
|
+
const entryPath = path10.join(targetPath, dirent.name);
|
|
23716
23835
|
if (dirent.isSymbolicLink()) continue;
|
|
23717
23836
|
if (dirent.isDirectory()) {
|
|
23718
23837
|
total += await directorySizeBytes(entryPath);
|
|
@@ -23724,14 +23843,14 @@ async function directorySizeBytes(targetPath) {
|
|
|
23724
23843
|
return total;
|
|
23725
23844
|
}
|
|
23726
23845
|
async function readActiveRuntimeVersions(homeDir) {
|
|
23727
|
-
const instancesDir =
|
|
23846
|
+
const instancesDir = path10.join(homeDir, "instances");
|
|
23728
23847
|
const dirents = await readdir(instancesDir, { withFileTypes: true }).catch(() => null);
|
|
23729
23848
|
if (!dirents) return [];
|
|
23730
23849
|
const versions = /* @__PURE__ */ new Set();
|
|
23731
23850
|
for (const dirent of dirents) {
|
|
23732
23851
|
if (!dirent.isDirectory()) continue;
|
|
23733
23852
|
try {
|
|
23734
|
-
const descriptorPath =
|
|
23853
|
+
const descriptorPath = path10.join(instancesDir, dirent.name, "runtime", "server.json");
|
|
23735
23854
|
const parsed = JSON.parse(await readFile(descriptorPath, "utf8"));
|
|
23736
23855
|
if (typeof parsed.version !== "string") continue;
|
|
23737
23856
|
if (typeof parsed.pid === "number" && Number.isInteger(parsed.pid) && parsed.pid > 0 && isPidRunning(parsed.pid)) {
|
|
@@ -23891,8 +24010,8 @@ var init_install = __esm({
|
|
|
23891
24010
|
});
|
|
23892
24011
|
|
|
23893
24012
|
// src/runtime/server-entry.ts
|
|
23894
|
-
import
|
|
23895
|
-
import
|
|
24013
|
+
import fs8 from "node:fs";
|
|
24014
|
+
import path11 from "node:path";
|
|
23896
24015
|
import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
23897
24016
|
function formatError(err) {
|
|
23898
24017
|
if (err instanceof Error) {
|
|
@@ -23914,12 +24033,12 @@ function maybeEnableUiDevMiddleware(entrypoint) {
|
|
|
23914
24033
|
}
|
|
23915
24034
|
}
|
|
23916
24035
|
function resolveDevServerEntry() {
|
|
23917
|
-
const projectRoot =
|
|
23918
|
-
return
|
|
24036
|
+
const projectRoot = path11.resolve(path11.dirname(fileURLToPath5(import.meta.url)), "../../..");
|
|
24037
|
+
return path11.resolve(projectRoot, "server/src/index.ts");
|
|
23919
24038
|
}
|
|
23920
24039
|
async function loadServerRuntimeModule(options) {
|
|
23921
24040
|
const devEntry = resolveDevServerEntry();
|
|
23922
|
-
if (
|
|
24041
|
+
if (fs8.existsSync(devEntry)) {
|
|
23923
24042
|
maybeEnableUiDevMiddleware(devEntry);
|
|
23924
24043
|
return await import(pathToFileURL2(devEntry).href);
|
|
23925
24044
|
}
|
|
@@ -23930,7 +24049,7 @@ async function loadServerRuntimeModule(options) {
|
|
|
23930
24049
|
};
|
|
23931
24050
|
const runtime = await ensureRuntimeInstalled(installOptions);
|
|
23932
24051
|
if (!process.env[RUDDER_POSTGRES_BIN_DIR_ENV2]?.trim()) {
|
|
23933
|
-
if (runtime.postgresPayloadBinDir &&
|
|
24052
|
+
if (runtime.postgresPayloadBinDir && fs8.existsSync(runtime.postgresPayloadBinDir)) {
|
|
23934
24053
|
process.env[RUDDER_POSTGRES_BIN_DIR_ENV2] = runtime.postgresPayloadBinDir;
|
|
23935
24054
|
}
|
|
23936
24055
|
}
|
|
@@ -24054,24 +24173,24 @@ var init_auth_bootstrap_ceo = __esm({
|
|
|
24054
24173
|
});
|
|
24055
24174
|
|
|
24056
24175
|
// src/utils/path-resolver.ts
|
|
24057
|
-
import
|
|
24058
|
-
import
|
|
24176
|
+
import fs11 from "node:fs";
|
|
24177
|
+
import path19 from "node:path";
|
|
24059
24178
|
function unique(items) {
|
|
24060
24179
|
return Array.from(new Set(items));
|
|
24061
24180
|
}
|
|
24062
24181
|
function resolveRuntimeLikePath(value, configPath) {
|
|
24063
24182
|
const expanded = expandHomePrefix(value);
|
|
24064
|
-
if (
|
|
24183
|
+
if (path19.isAbsolute(expanded)) return path19.resolve(expanded);
|
|
24065
24184
|
const cwd = process.cwd();
|
|
24066
|
-
const configDir = configPath ?
|
|
24067
|
-
const workspaceRoot = configDir ?
|
|
24185
|
+
const configDir = configPath ? path19.dirname(configPath) : null;
|
|
24186
|
+
const workspaceRoot = configDir ? path19.resolve(configDir, "..") : cwd;
|
|
24068
24187
|
const candidates = unique([
|
|
24069
|
-
...configDir ? [
|
|
24070
|
-
|
|
24071
|
-
|
|
24072
|
-
|
|
24188
|
+
...configDir ? [path19.resolve(configDir, expanded)] : [],
|
|
24189
|
+
path19.resolve(workspaceRoot, "server", expanded),
|
|
24190
|
+
path19.resolve(workspaceRoot, expanded),
|
|
24191
|
+
path19.resolve(cwd, expanded)
|
|
24073
24192
|
]);
|
|
24074
|
-
return candidates.find((candidate) =>
|
|
24193
|
+
return candidates.find((candidate) => fs11.existsSync(candidate)) ?? candidates[0];
|
|
24075
24194
|
}
|
|
24076
24195
|
var init_path_resolver = __esm({
|
|
24077
24196
|
"src/utils/path-resolver.ts"() {
|
|
@@ -24082,8 +24201,8 @@ var init_path_resolver = __esm({
|
|
|
24082
24201
|
|
|
24083
24202
|
// src/config/secrets-key.ts
|
|
24084
24203
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
24085
|
-
import
|
|
24086
|
-
import
|
|
24204
|
+
import fs12 from "node:fs";
|
|
24205
|
+
import path20 from "node:path";
|
|
24087
24206
|
function ensureLocalSecretsKeyFile(config, configPath) {
|
|
24088
24207
|
if (config.secrets.provider !== "local_encrypted") {
|
|
24089
24208
|
return { status: "skipped_provider", path: null };
|
|
@@ -24095,16 +24214,16 @@ function ensureLocalSecretsKeyFile(config, configPath) {
|
|
|
24095
24214
|
const keyFileOverride = process.env.RUDDER_SECRETS_MASTER_KEY_FILE;
|
|
24096
24215
|
const configuredPath = keyFileOverride && keyFileOverride.trim().length > 0 ? keyFileOverride.trim() : config.secrets.localEncrypted.keyFilePath;
|
|
24097
24216
|
const keyFilePath = resolveRuntimeLikePath(configuredPath, configPath);
|
|
24098
|
-
if (
|
|
24217
|
+
if (fs12.existsSync(keyFilePath)) {
|
|
24099
24218
|
return { status: "existing", path: keyFilePath };
|
|
24100
24219
|
}
|
|
24101
|
-
|
|
24102
|
-
|
|
24220
|
+
fs12.mkdirSync(path20.dirname(keyFilePath), { recursive: true });
|
|
24221
|
+
fs12.writeFileSync(keyFilePath, randomBytes2(32).toString("base64"), {
|
|
24103
24222
|
encoding: "utf8",
|
|
24104
24223
|
mode: 384
|
|
24105
24224
|
});
|
|
24106
24225
|
try {
|
|
24107
|
-
|
|
24226
|
+
fs12.chmodSync(keyFilePath, 384);
|
|
24108
24227
|
} catch {
|
|
24109
24228
|
}
|
|
24110
24229
|
return { status: "created", path: keyFilePath };
|
|
@@ -24871,7 +24990,7 @@ var init_path_resolver2 = __esm({
|
|
|
24871
24990
|
});
|
|
24872
24991
|
|
|
24873
24992
|
// src/checks/database-check.ts
|
|
24874
|
-
import
|
|
24993
|
+
import fs13 from "node:fs";
|
|
24875
24994
|
async function databaseCheck(config, configPath) {
|
|
24876
24995
|
if (config.database.mode === "postgres") {
|
|
24877
24996
|
if (!config.database.connectionString) {
|
|
@@ -24903,8 +25022,8 @@ async function databaseCheck(config, configPath) {
|
|
|
24903
25022
|
if (config.database.mode === "embedded-postgres") {
|
|
24904
25023
|
const dataDir = resolveRuntimeLikePath(config.database.embeddedPostgresDataDir, configPath);
|
|
24905
25024
|
const reportedPath = dataDir;
|
|
24906
|
-
if (!
|
|
24907
|
-
|
|
25025
|
+
if (!fs13.existsSync(dataDir)) {
|
|
25026
|
+
fs13.mkdirSync(reportedPath, { recursive: true });
|
|
24908
25027
|
}
|
|
24909
25028
|
return {
|
|
24910
25029
|
name: "Database",
|
|
@@ -25100,15 +25219,15 @@ var init_llm_check = __esm({
|
|
|
25100
25219
|
});
|
|
25101
25220
|
|
|
25102
25221
|
// src/checks/log-check.ts
|
|
25103
|
-
import
|
|
25222
|
+
import fs14 from "node:fs";
|
|
25104
25223
|
function logCheck(config, configPath) {
|
|
25105
25224
|
const logDir = resolveRuntimeLikePath(config.logging.logDir, configPath);
|
|
25106
25225
|
const reportedDir = logDir;
|
|
25107
|
-
if (!
|
|
25108
|
-
|
|
25226
|
+
if (!fs14.existsSync(logDir)) {
|
|
25227
|
+
fs14.mkdirSync(reportedDir, { recursive: true });
|
|
25109
25228
|
}
|
|
25110
25229
|
try {
|
|
25111
|
-
|
|
25230
|
+
fs14.accessSync(reportedDir, fs14.constants.W_OK);
|
|
25112
25231
|
return {
|
|
25113
25232
|
name: "Log directory",
|
|
25114
25233
|
status: "pass",
|
|
@@ -25183,8 +25302,8 @@ var init_port_check = __esm({
|
|
|
25183
25302
|
|
|
25184
25303
|
// src/checks/secrets-check.ts
|
|
25185
25304
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
25186
|
-
import
|
|
25187
|
-
import
|
|
25305
|
+
import fs15 from "node:fs";
|
|
25306
|
+
import path21 from "node:path";
|
|
25188
25307
|
function decodeMasterKey(raw) {
|
|
25189
25308
|
const trimmed = raw.trim();
|
|
25190
25309
|
if (!trimmed) return null;
|
|
@@ -25246,7 +25365,7 @@ function secretsCheck(config, configPath) {
|
|
|
25246
25365
|
const keyFileOverride = process.env.RUDDER_SECRETS_MASTER_KEY_FILE;
|
|
25247
25366
|
const configuredPath = keyFileOverride && keyFileOverride.trim().length > 0 ? keyFileOverride.trim() : config.secrets.localEncrypted.keyFilePath;
|
|
25248
25367
|
const keyFilePath = resolveRuntimeLikePath(configuredPath, configPath);
|
|
25249
|
-
if (!
|
|
25368
|
+
if (!fs15.existsSync(keyFilePath)) {
|
|
25250
25369
|
return withStrictModeNote(
|
|
25251
25370
|
{
|
|
25252
25371
|
name: "Secrets adapter",
|
|
@@ -25254,13 +25373,13 @@ function secretsCheck(config, configPath) {
|
|
|
25254
25373
|
message: `Secrets key file does not exist yet: ${keyFilePath}`,
|
|
25255
25374
|
canRepair: true,
|
|
25256
25375
|
repair: () => {
|
|
25257
|
-
|
|
25258
|
-
|
|
25376
|
+
fs15.mkdirSync(path21.dirname(keyFilePath), { recursive: true });
|
|
25377
|
+
fs15.writeFileSync(keyFilePath, randomBytes3(32).toString("base64"), {
|
|
25259
25378
|
encoding: "utf8",
|
|
25260
25379
|
mode: 384
|
|
25261
25380
|
});
|
|
25262
25381
|
try {
|
|
25263
|
-
|
|
25382
|
+
fs15.chmodSync(keyFilePath, 384);
|
|
25264
25383
|
} catch {
|
|
25265
25384
|
}
|
|
25266
25385
|
},
|
|
@@ -25271,7 +25390,7 @@ function secretsCheck(config, configPath) {
|
|
|
25271
25390
|
}
|
|
25272
25391
|
let raw;
|
|
25273
25392
|
try {
|
|
25274
|
-
raw =
|
|
25393
|
+
raw = fs15.readFileSync(keyFilePath, "utf8");
|
|
25275
25394
|
} catch (err) {
|
|
25276
25395
|
return {
|
|
25277
25396
|
name: "Secrets adapter",
|
|
@@ -25307,15 +25426,15 @@ var init_secrets_check = __esm({
|
|
|
25307
25426
|
});
|
|
25308
25427
|
|
|
25309
25428
|
// src/checks/storage-check.ts
|
|
25310
|
-
import
|
|
25429
|
+
import fs16 from "node:fs";
|
|
25311
25430
|
function storageCheck(config, configPath) {
|
|
25312
25431
|
if (config.storage.provider === "local_disk") {
|
|
25313
25432
|
const baseDir = resolveRuntimeLikePath(config.storage.localDisk.baseDir, configPath);
|
|
25314
|
-
if (!
|
|
25315
|
-
|
|
25433
|
+
if (!fs16.existsSync(baseDir)) {
|
|
25434
|
+
fs16.mkdirSync(baseDir, { recursive: true });
|
|
25316
25435
|
}
|
|
25317
25436
|
try {
|
|
25318
|
-
|
|
25437
|
+
fs16.accessSync(baseDir, fs16.constants.W_OK);
|
|
25319
25438
|
return {
|
|
25320
25439
|
name: "Storage",
|
|
25321
25440
|
status: "pass",
|
|
@@ -25721,7 +25840,7 @@ __export(run_exports, {
|
|
|
25721
25840
|
runCommand: () => runCommand
|
|
25722
25841
|
});
|
|
25723
25842
|
import * as p13 from "@clack/prompts";
|
|
25724
|
-
import
|
|
25843
|
+
import fs17 from "node:fs";
|
|
25725
25844
|
import pc12 from "picocolors";
|
|
25726
25845
|
async function runCommand(opts) {
|
|
25727
25846
|
let localEnvProfile = resolveActiveLocalEnvProfile();
|
|
@@ -25731,9 +25850,9 @@ async function runCommand(opts) {
|
|
|
25731
25850
|
const instanceId = resolveRudderInstanceId(opts.instance);
|
|
25732
25851
|
process.env.RUDDER_INSTANCE_ID = instanceId;
|
|
25733
25852
|
const homeDir = resolveRudderHomeDir();
|
|
25734
|
-
|
|
25853
|
+
fs17.mkdirSync(homeDir, { recursive: true });
|
|
25735
25854
|
const paths = describeLocalInstancePaths(instanceId);
|
|
25736
|
-
|
|
25855
|
+
fs17.mkdirSync(paths.instanceRoot, { recursive: true });
|
|
25737
25856
|
const configPath = resolveConfigPath(opts.config);
|
|
25738
25857
|
process.env.RUDDER_CONFIG = configPath;
|
|
25739
25858
|
loadRudderEnvFile(configPath);
|
|
@@ -25830,7 +25949,7 @@ var init_run = __esm({
|
|
|
25830
25949
|
|
|
25831
25950
|
// src/commands/onboard.ts
|
|
25832
25951
|
import * as p14 from "@clack/prompts";
|
|
25833
|
-
import
|
|
25952
|
+
import path22 from "node:path";
|
|
25834
25953
|
import pc13 from "picocolors";
|
|
25835
25954
|
function parseBooleanFromEnv(rawValue) {
|
|
25836
25955
|
if (rawValue === void 0) return null;
|
|
@@ -25863,7 +25982,7 @@ function parseEnumFromEnv(rawValue, allowedValues) {
|
|
|
25863
25982
|
}
|
|
25864
25983
|
function resolvePathFromEnv(rawValue) {
|
|
25865
25984
|
if (!rawValue || rawValue.trim().length === 0) return null;
|
|
25866
|
-
return
|
|
25985
|
+
return path22.resolve(expandHomePrefix(rawValue.trim()));
|
|
25867
25986
|
}
|
|
25868
25987
|
function quickstartDefaultsFromEnv() {
|
|
25869
25988
|
const instanceId = resolveRudderInstanceId();
|
|
@@ -26324,9 +26443,9 @@ function fingerprintRudderMcpToolManifest(tools) {
|
|
|
26324
26443
|
init_dist2();
|
|
26325
26444
|
import { spawn as spawn2, spawnSync } from "node:child_process";
|
|
26326
26445
|
import { existsSync as existsSync2 } from "node:fs";
|
|
26327
|
-
import
|
|
26328
|
-
import
|
|
26329
|
-
import
|
|
26446
|
+
import fs5 from "node:fs/promises";
|
|
26447
|
+
import os3 from "node:os";
|
|
26448
|
+
import path7 from "node:path";
|
|
26330
26449
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
26331
26450
|
|
|
26332
26451
|
// src/agent-v1-registry.ts
|
|
@@ -27737,6 +27856,18 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
27737
27856
|
"requiresAgentId": false,
|
|
27738
27857
|
"requiresOrgId": false,
|
|
27739
27858
|
"requiresRunId": false
|
|
27859
|
+
},
|
|
27860
|
+
{
|
|
27861
|
+
"attachesRunIdWhenAvailable": true,
|
|
27862
|
+
"category": "runs",
|
|
27863
|
+
"command": "rudder runs create --task <text> --idempotency-key <key> [--target-agent-id <id>]",
|
|
27864
|
+
"contract": "agent-v1",
|
|
27865
|
+
"description": "Create an independently governed Delegation Run for the current or another same-organization Agent.",
|
|
27866
|
+
"id": "runs.create",
|
|
27867
|
+
"mutating": true,
|
|
27868
|
+
"requiresAgentId": true,
|
|
27869
|
+
"requiresOrgId": false,
|
|
27870
|
+
"requiresRunId": true
|
|
27740
27871
|
}
|
|
27741
27872
|
];
|
|
27742
27873
|
|
|
@@ -27839,6 +27970,8 @@ function formatAgentCliCapabilitiesHumanReadable(capabilities = getAgentCliCapab
|
|
|
27839
27970
|
|
|
27840
27971
|
// src/client/http.ts
|
|
27841
27972
|
import { URL as URL2 } from "node:url";
|
|
27973
|
+
|
|
27974
|
+
// src/client/api-request-error.ts
|
|
27842
27975
|
var ApiRequestError = class extends Error {
|
|
27843
27976
|
status;
|
|
27844
27977
|
code;
|
|
@@ -27852,6 +27985,222 @@ var ApiRequestError = class extends Error {
|
|
|
27852
27985
|
this.body = body;
|
|
27853
27986
|
}
|
|
27854
27987
|
};
|
|
27988
|
+
|
|
27989
|
+
// src/client/issue-transport-budget.ts
|
|
27990
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
27991
|
+
import fs from "node:fs/promises";
|
|
27992
|
+
import os from "node:os";
|
|
27993
|
+
import path from "node:path";
|
|
27994
|
+
var DEFAULT_BACKOFF_MS = 6e4;
|
|
27995
|
+
var LOCK_RETRY_MS = 5;
|
|
27996
|
+
var LOCK_TIMEOUT_MS = 250;
|
|
27997
|
+
var IssueTransportBudget = class {
|
|
27998
|
+
runId;
|
|
27999
|
+
surface;
|
|
28000
|
+
stateDir;
|
|
28001
|
+
backoffMs;
|
|
28002
|
+
now;
|
|
28003
|
+
constructor(options) {
|
|
28004
|
+
this.runId = options.runId?.trim() || void 0;
|
|
28005
|
+
this.surface = options.surface ?? transportSurfaceFromEnv();
|
|
28006
|
+
this.stateDir = options.stateDir ?? process.env.RUDDER_RUNTIME_TMPDIR?.trim() ?? path.join(os.tmpdir(), "rudder-issue-transport");
|
|
28007
|
+
this.backoffMs = options.backoffMs ?? DEFAULT_BACKOFF_MS;
|
|
28008
|
+
this.now = options.now ?? Date.now;
|
|
28009
|
+
}
|
|
28010
|
+
async reserve(method, requestPath) {
|
|
28011
|
+
if (!this.runId) return null;
|
|
28012
|
+
const scope = issueTransportScope(method, requestPath);
|
|
28013
|
+
if (!scope) return null;
|
|
28014
|
+
const filePath = this.stateFilePath(scope);
|
|
28015
|
+
try {
|
|
28016
|
+
return await this.withLock(filePath, async () => {
|
|
28017
|
+
const now = this.now();
|
|
28018
|
+
let state = await readState(filePath);
|
|
28019
|
+
if (state && state.expiresAt <= now) {
|
|
28020
|
+
await fs.rm(filePath, { force: true });
|
|
28021
|
+
state = null;
|
|
28022
|
+
}
|
|
28023
|
+
if (!state) {
|
|
28024
|
+
return { filePath, scope, surface: this.surface, attempt: "initial" };
|
|
28025
|
+
}
|
|
28026
|
+
if (state.phase === "fallback_available" && state.initialSurface !== this.surface) {
|
|
28027
|
+
await writeState(filePath, {
|
|
28028
|
+
...state,
|
|
28029
|
+
phase: "fallback_in_flight",
|
|
28030
|
+
fallbackSurface: this.surface
|
|
28031
|
+
});
|
|
28032
|
+
return { filePath, scope, surface: this.surface, attempt: "fallback" };
|
|
28033
|
+
}
|
|
28034
|
+
throw issueTransportUnavailable(state, now);
|
|
28035
|
+
});
|
|
28036
|
+
} catch (error) {
|
|
28037
|
+
if (error instanceof ApiRequestError) throw error;
|
|
28038
|
+
return null;
|
|
28039
|
+
}
|
|
28040
|
+
}
|
|
28041
|
+
async succeed(reservation) {
|
|
28042
|
+
if (!reservation) return;
|
|
28043
|
+
await this.tryWithLock(reservation.filePath, async () => {
|
|
28044
|
+
await fs.rm(reservation.filePath, { force: true });
|
|
28045
|
+
});
|
|
28046
|
+
}
|
|
28047
|
+
async fail(reservation, error) {
|
|
28048
|
+
if (!reservation) return;
|
|
28049
|
+
if (error.status < 500 || error.status > 599) {
|
|
28050
|
+
await this.succeed(reservation);
|
|
28051
|
+
return;
|
|
28052
|
+
}
|
|
28053
|
+
const failure = buildFingerprint(reservation.scope, error);
|
|
28054
|
+
const now = this.now();
|
|
28055
|
+
await this.tryWithLock(reservation.filePath, async () => {
|
|
28056
|
+
const current = await readState(reservation.filePath);
|
|
28057
|
+
const concurrentMatchingFailure = reservation.attempt === "initial" && current?.failure?.fingerprint === failure.fingerprint;
|
|
28058
|
+
const budgetExhausted = reservation.attempt === "fallback" || concurrentMatchingFailure;
|
|
28059
|
+
const state = {
|
|
28060
|
+
...reservation.scope,
|
|
28061
|
+
phase: budgetExhausted ? "blocked" : "fallback_available",
|
|
28062
|
+
initialSurface: current?.initialSurface ?? reservation.surface,
|
|
28063
|
+
fallbackSurface: reservation.attempt === "fallback" ? reservation.surface : void 0,
|
|
28064
|
+
fallbackMatchedFingerprint: budgetExhausted ? current?.failure?.fingerprint === failure.fingerprint : void 0,
|
|
28065
|
+
failure,
|
|
28066
|
+
observedAt: now,
|
|
28067
|
+
expiresAt: now + this.backoffMs
|
|
28068
|
+
};
|
|
28069
|
+
await writeState(reservation.filePath, state);
|
|
28070
|
+
attachTransportDiagnostic(error, state, now);
|
|
28071
|
+
if (budgetExhausted) {
|
|
28072
|
+
error.code = "issue_transport_unavailable";
|
|
28073
|
+
error.message = "Issue transport unavailable";
|
|
28074
|
+
}
|
|
28075
|
+
});
|
|
28076
|
+
}
|
|
28077
|
+
stateFilePath(scope) {
|
|
28078
|
+
const key = [this.runId, scope.operation, scope.issueId].join("\n");
|
|
28079
|
+
const digest = createHash2("sha256").update(key).digest("hex");
|
|
28080
|
+
return path.join(this.stateDir, "issue-transport-budget", `${digest}.json`);
|
|
28081
|
+
}
|
|
28082
|
+
async tryWithLock(filePath, action) {
|
|
28083
|
+
try {
|
|
28084
|
+
return await this.withLock(filePath, action);
|
|
28085
|
+
} catch {
|
|
28086
|
+
return void 0;
|
|
28087
|
+
}
|
|
28088
|
+
}
|
|
28089
|
+
async withLock(filePath, action) {
|
|
28090
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true, mode: 448 });
|
|
28091
|
+
const lockPath = `${filePath}.lock`;
|
|
28092
|
+
const deadline = Date.now() + LOCK_TIMEOUT_MS;
|
|
28093
|
+
let lock = null;
|
|
28094
|
+
while (!lock) {
|
|
28095
|
+
try {
|
|
28096
|
+
lock = await fs.open(lockPath, "wx", 384);
|
|
28097
|
+
} catch (error) {
|
|
28098
|
+
if (!isAlreadyExists(error) || Date.now() >= deadline) throw error;
|
|
28099
|
+
await new Promise((resolve) => setTimeout(resolve, LOCK_RETRY_MS));
|
|
28100
|
+
}
|
|
28101
|
+
}
|
|
28102
|
+
try {
|
|
28103
|
+
return await action();
|
|
28104
|
+
} finally {
|
|
28105
|
+
await lock.close();
|
|
28106
|
+
await fs.rm(lockPath, { force: true });
|
|
28107
|
+
}
|
|
28108
|
+
}
|
|
28109
|
+
};
|
|
28110
|
+
function issueTransportScope(method, requestPath) {
|
|
28111
|
+
const normalizedMethod = String(method ?? "GET").toUpperCase();
|
|
28112
|
+
const pathname = requestPath.split("?", 1)[0] ?? "";
|
|
28113
|
+
const match = /^\/api\/issues\/([^/]+)(?:\/(heartbeat-context|comments)(?:\/([^/]+))?)?$/.exec(pathname);
|
|
28114
|
+
if (!match) return null;
|
|
28115
|
+
const issueId = decodeURIComponent(match[1] ?? "");
|
|
28116
|
+
const resource = match[2];
|
|
28117
|
+
const commentId = match[3];
|
|
28118
|
+
let operation = null;
|
|
28119
|
+
if (normalizedMethod === "GET" && !resource) operation = "issue.get";
|
|
28120
|
+
if (normalizedMethod === "GET" && resource === "heartbeat-context") operation = "issue.context";
|
|
28121
|
+
if (normalizedMethod === "GET" && resource === "comments" && !commentId) operation = "issue.comments.list";
|
|
28122
|
+
if (normalizedMethod === "GET" && resource === "comments" && commentId) operation = "issue.comments.get";
|
|
28123
|
+
if (normalizedMethod === "POST" && resource === "comments" && !commentId) operation = "issue.comment";
|
|
28124
|
+
return operation ? { operation, issueId } : null;
|
|
28125
|
+
}
|
|
28126
|
+
function buildFingerprint(scope, error) {
|
|
28127
|
+
const normalizedMessage = error.message.trim().replace(/\s+/g, " ").toLowerCase().slice(0, 256);
|
|
28128
|
+
const code = error.code?.trim() || "api_request_error";
|
|
28129
|
+
const value = [scope.operation, scope.issueId, error.status, code, normalizedMessage].join("\n");
|
|
28130
|
+
return {
|
|
28131
|
+
fingerprint: createHash2("sha256").update(value).digest("hex"),
|
|
28132
|
+
status: error.status,
|
|
28133
|
+
code,
|
|
28134
|
+
normalizedMessage
|
|
28135
|
+
};
|
|
28136
|
+
}
|
|
28137
|
+
function issueTransportUnavailable(state, now) {
|
|
28138
|
+
const details = { issueTransport: transportDiagnostic(state, now) };
|
|
28139
|
+
return new ApiRequestError(
|
|
28140
|
+
503,
|
|
28141
|
+
state.phase === "fallback_in_flight" ? "Issue transport probe already in flight" : "Issue transport unavailable",
|
|
28142
|
+
details,
|
|
28143
|
+
{ error: "Issue transport unavailable", code: "issue_transport_unavailable", details },
|
|
28144
|
+
"issue_transport_unavailable"
|
|
28145
|
+
);
|
|
28146
|
+
}
|
|
28147
|
+
function attachTransportDiagnostic(error, state, now) {
|
|
28148
|
+
const upstreamDetails = error.details;
|
|
28149
|
+
error.details = {
|
|
28150
|
+
...isRecord2(upstreamDetails) ? upstreamDetails : upstreamDetails === void 0 ? {} : { upstreamDetails },
|
|
28151
|
+
issueTransport: transportDiagnostic(state, now)
|
|
28152
|
+
};
|
|
28153
|
+
}
|
|
28154
|
+
function transportDiagnostic(state, now) {
|
|
28155
|
+
return {
|
|
28156
|
+
state: state.phase,
|
|
28157
|
+
fingerprint: state.failure?.fingerprint ?? null,
|
|
28158
|
+
operation: state.operation,
|
|
28159
|
+
issueId: state.issueId,
|
|
28160
|
+
upstreamStatus: state.failure?.status ?? null,
|
|
28161
|
+
upstreamCode: state.failure?.code ?? null,
|
|
28162
|
+
normalizedServerMessage: state.failure?.normalizedMessage ?? null,
|
|
28163
|
+
initialSurface: state.initialSurface,
|
|
28164
|
+
fallbackSurface: state.fallbackSurface ?? null,
|
|
28165
|
+
fallbackMatchedFingerprint: state.fallbackMatchedFingerprint ?? null,
|
|
28166
|
+
fallbackBudgetRemaining: state.phase === "fallback_available" ? 1 : 0,
|
|
28167
|
+
retryAfterMs: Math.max(0, state.expiresAt - now),
|
|
28168
|
+
checkpoint: "Issue transport unavailable"
|
|
28169
|
+
};
|
|
28170
|
+
}
|
|
28171
|
+
async function readState(filePath) {
|
|
28172
|
+
try {
|
|
28173
|
+
const parsed = JSON.parse(await fs.readFile(filePath, "utf8"));
|
|
28174
|
+
return isIssueTransportState(parsed) ? parsed : null;
|
|
28175
|
+
} catch (error) {
|
|
28176
|
+
if (isNotFound(error) || error instanceof SyntaxError) return null;
|
|
28177
|
+
throw error;
|
|
28178
|
+
}
|
|
28179
|
+
}
|
|
28180
|
+
async function writeState(filePath, state) {
|
|
28181
|
+
const tempPath = `${filePath}.${process.pid}.${Math.random().toString(16).slice(2)}.tmp`;
|
|
28182
|
+
await fs.writeFile(tempPath, `${JSON.stringify(state)}
|
|
28183
|
+
`, { encoding: "utf8", mode: 384 });
|
|
28184
|
+
await fs.rename(tempPath, filePath);
|
|
28185
|
+
}
|
|
28186
|
+
function isIssueTransportState(value) {
|
|
28187
|
+
if (!isRecord2(value)) return false;
|
|
28188
|
+
return typeof value.operation === "string" && typeof value.issueId === "string" && ["fallback_available", "fallback_in_flight", "blocked"].includes(String(value.phase)) && (value.initialSurface === "cli" || value.initialSurface === "mcp") && typeof value.observedAt === "number" && typeof value.expiresAt === "number";
|
|
28189
|
+
}
|
|
28190
|
+
function transportSurfaceFromEnv() {
|
|
28191
|
+
return process.env.RUDDER_TOOL_TRANSPORT_SURFACE === "mcp" ? "mcp" : "cli";
|
|
28192
|
+
}
|
|
28193
|
+
function isRecord2(value) {
|
|
28194
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28195
|
+
}
|
|
28196
|
+
function isAlreadyExists(error) {
|
|
28197
|
+
return isRecord2(error) && error.code === "EEXIST";
|
|
28198
|
+
}
|
|
28199
|
+
function isNotFound(error) {
|
|
28200
|
+
return isRecord2(error) && error.code === "ENOENT";
|
|
28201
|
+
}
|
|
28202
|
+
|
|
28203
|
+
// src/client/http.ts
|
|
27855
28204
|
var RudderApiClient = class {
|
|
27856
28205
|
apiBase;
|
|
27857
28206
|
apiKey;
|
|
@@ -27859,6 +28208,7 @@ var RudderApiClient = class {
|
|
|
27859
28208
|
runId;
|
|
27860
28209
|
signal;
|
|
27861
28210
|
recoverAuth;
|
|
28211
|
+
issueTransportBudget;
|
|
27862
28212
|
constructor(opts) {
|
|
27863
28213
|
this.apiBase = opts.apiBase.replace(/\/+$/, "");
|
|
27864
28214
|
this.apiKey = opts.apiKey?.trim() || void 0;
|
|
@@ -27866,42 +28216,50 @@ var RudderApiClient = class {
|
|
|
27866
28216
|
this.runId = opts.runId?.trim() || void 0;
|
|
27867
28217
|
this.signal = opts.signal;
|
|
27868
28218
|
this.recoverAuth = opts.recoverAuth;
|
|
28219
|
+
this.issueTransportBudget = new IssueTransportBudget({
|
|
28220
|
+
runId: this.runId,
|
|
28221
|
+
surface: opts.transportSurface,
|
|
28222
|
+
stateDir: opts.transportStateDir,
|
|
28223
|
+
backoffMs: opts.transportBackoffMs,
|
|
28224
|
+
now: opts.now
|
|
28225
|
+
});
|
|
27869
28226
|
}
|
|
27870
|
-
get(
|
|
27871
|
-
return this.request(
|
|
28227
|
+
get(path26, opts) {
|
|
28228
|
+
return this.request(path26, { method: "GET" }, opts);
|
|
27872
28229
|
}
|
|
27873
|
-
post(
|
|
27874
|
-
return this.request(
|
|
28230
|
+
post(path26, body, opts) {
|
|
28231
|
+
return this.request(path26, {
|
|
27875
28232
|
method: "POST",
|
|
27876
28233
|
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
27877
28234
|
}, opts);
|
|
27878
28235
|
}
|
|
27879
|
-
postForm(
|
|
27880
|
-
return this.request(
|
|
28236
|
+
postForm(path26, form, opts) {
|
|
28237
|
+
return this.request(path26, {
|
|
27881
28238
|
method: "POST",
|
|
27882
28239
|
body: form
|
|
27883
28240
|
}, opts);
|
|
27884
28241
|
}
|
|
27885
|
-
patch(
|
|
27886
|
-
return this.request(
|
|
28242
|
+
patch(path26, body, opts) {
|
|
28243
|
+
return this.request(path26, {
|
|
27887
28244
|
method: "PATCH",
|
|
27888
28245
|
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
27889
28246
|
}, opts);
|
|
27890
28247
|
}
|
|
27891
|
-
put(
|
|
27892
|
-
return this.request(
|
|
28248
|
+
put(path26, body, opts) {
|
|
28249
|
+
return this.request(path26, {
|
|
27893
28250
|
method: "PUT",
|
|
27894
28251
|
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
27895
28252
|
}, opts);
|
|
27896
28253
|
}
|
|
27897
|
-
delete(
|
|
27898
|
-
return this.request(
|
|
28254
|
+
delete(path26, opts) {
|
|
28255
|
+
return this.request(path26, { method: "DELETE" }, opts);
|
|
27899
28256
|
}
|
|
27900
28257
|
setApiKey(apiKey) {
|
|
27901
28258
|
this.apiKey = apiKey?.trim() || void 0;
|
|
27902
28259
|
}
|
|
27903
|
-
async request(
|
|
27904
|
-
const url = buildUrl(this.apiBase,
|
|
28260
|
+
async request(path26, init, opts, hasRetriedAuth = false) {
|
|
28261
|
+
const url = buildUrl(this.apiBase, path26);
|
|
28262
|
+
const reservation = await this.issueTransportBudget.reserve(init.method, path26);
|
|
27905
28263
|
const headers = {
|
|
27906
28264
|
accept: "application/json",
|
|
27907
28265
|
...toStringRecord(init.headers)
|
|
@@ -27920,29 +28278,39 @@ var RudderApiClient = class {
|
|
|
27920
28278
|
headers["x-rudder-run-id"] = this.runId;
|
|
27921
28279
|
}
|
|
27922
28280
|
}
|
|
27923
|
-
|
|
27924
|
-
|
|
27925
|
-
|
|
27926
|
-
|
|
27927
|
-
|
|
28281
|
+
let response;
|
|
28282
|
+
try {
|
|
28283
|
+
response = await fetch(url, {
|
|
28284
|
+
...init,
|
|
28285
|
+
headers,
|
|
28286
|
+
signal: init.signal ?? this.signal
|
|
28287
|
+
});
|
|
28288
|
+
} catch (error) {
|
|
28289
|
+
await this.issueTransportBudget.succeed(reservation);
|
|
28290
|
+
throw error;
|
|
28291
|
+
}
|
|
27928
28292
|
if (opts?.ignoreNotFound && response.status === 404) {
|
|
28293
|
+
await this.issueTransportBudget.succeed(reservation);
|
|
27929
28294
|
return null;
|
|
27930
28295
|
}
|
|
27931
28296
|
if (!response.ok) {
|
|
27932
28297
|
const apiError = await toApiError(response);
|
|
27933
28298
|
if (!hasRetriedAuth && this.recoverAuth) {
|
|
27934
28299
|
const recoveredToken = await this.recoverAuth({
|
|
27935
|
-
path:
|
|
28300
|
+
path: path26,
|
|
27936
28301
|
method: String(init.method ?? "GET").toUpperCase(),
|
|
27937
28302
|
error: apiError
|
|
27938
28303
|
});
|
|
27939
28304
|
if (recoveredToken) {
|
|
28305
|
+
await this.issueTransportBudget.succeed(reservation);
|
|
27940
28306
|
this.setApiKey(recoveredToken);
|
|
27941
|
-
return this.request(
|
|
28307
|
+
return this.request(path26, init, opts, true);
|
|
27942
28308
|
}
|
|
27943
28309
|
}
|
|
28310
|
+
await this.issueTransportBudget.fail(reservation, apiError);
|
|
27944
28311
|
throw apiError;
|
|
27945
28312
|
}
|
|
28313
|
+
await this.issueTransportBudget.succeed(reservation);
|
|
27946
28314
|
if (response.status === 204) {
|
|
27947
28315
|
return null;
|
|
27948
28316
|
}
|
|
@@ -27957,8 +28325,8 @@ function shouldAttachAgentContext(method) {
|
|
|
27957
28325
|
const normalized = String(method ?? "GET").toUpperCase();
|
|
27958
28326
|
return normalized !== "GET" && normalized !== "HEAD";
|
|
27959
28327
|
}
|
|
27960
|
-
function buildUrl(apiBase,
|
|
27961
|
-
const normalizedPath =
|
|
28328
|
+
function buildUrl(apiBase, path26) {
|
|
28329
|
+
const normalizedPath = path26.startsWith("/") ? path26 : `/${path26}`;
|
|
27962
28330
|
const [pathname, query] = normalizedPath.split("?");
|
|
27963
28331
|
const url = new URL2(apiBase);
|
|
27964
28332
|
url.pathname = `${url.pathname.replace(/\/+$/, "")}${pathname}`;
|
|
@@ -28009,8 +28377,8 @@ import pc2 from "picocolors";
|
|
|
28009
28377
|
// src/client/board-auth.ts
|
|
28010
28378
|
init_home();
|
|
28011
28379
|
import { spawn } from "node:child_process";
|
|
28012
|
-
import
|
|
28013
|
-
import
|
|
28380
|
+
import fs2 from "node:fs";
|
|
28381
|
+
import path3 from "node:path";
|
|
28014
28382
|
import pc from "picocolors";
|
|
28015
28383
|
|
|
28016
28384
|
// src/client/command-label.ts
|
|
@@ -28033,14 +28401,14 @@ function normalizeApiBase(apiBase) {
|
|
|
28033
28401
|
return apiBase.trim().replace(/\/+$/, "");
|
|
28034
28402
|
}
|
|
28035
28403
|
function resolveBoardAuthStorePath(overridePath) {
|
|
28036
|
-
if (overridePath?.trim()) return
|
|
28037
|
-
if (process.env.RUDDER_AUTH_STORE?.trim()) return
|
|
28404
|
+
if (overridePath?.trim()) return path3.resolve(overridePath.trim());
|
|
28405
|
+
if (process.env.RUDDER_AUTH_STORE?.trim()) return path3.resolve(process.env.RUDDER_AUTH_STORE.trim());
|
|
28038
28406
|
return resolveDefaultCliAuthPath();
|
|
28039
28407
|
}
|
|
28040
28408
|
function readBoardAuthStore(storePath) {
|
|
28041
28409
|
const filePath = resolveBoardAuthStorePath(storePath);
|
|
28042
|
-
if (!
|
|
28043
|
-
const raw = JSON.parse(
|
|
28410
|
+
if (!fs2.existsSync(filePath)) return defaultBoardAuthStore();
|
|
28411
|
+
const raw = JSON.parse(fs2.readFileSync(filePath, "utf8"));
|
|
28044
28412
|
const credentials = raw?.credentials && typeof raw.credentials === "object" ? raw.credentials : {};
|
|
28045
28413
|
const normalized = {};
|
|
28046
28414
|
for (const [key, value] of Object.entries(credentials)) {
|
|
@@ -28066,8 +28434,8 @@ function readBoardAuthStore(storePath) {
|
|
|
28066
28434
|
}
|
|
28067
28435
|
function writeBoardAuthStore(store, storePath) {
|
|
28068
28436
|
const filePath = resolveBoardAuthStorePath(storePath);
|
|
28069
|
-
|
|
28070
|
-
|
|
28437
|
+
fs2.mkdirSync(path3.dirname(filePath), { recursive: true });
|
|
28438
|
+
fs2.writeFileSync(filePath, `${JSON.stringify(store, null, 2)}
|
|
28071
28439
|
`, { mode: 384 });
|
|
28072
28440
|
}
|
|
28073
28441
|
function getStoredBoardCredential(apiBase, storePath) {
|
|
@@ -28213,27 +28581,27 @@ async function revokeStoredBoardCredential(params) {
|
|
|
28213
28581
|
|
|
28214
28582
|
// src/client/context.ts
|
|
28215
28583
|
init_home();
|
|
28216
|
-
import
|
|
28217
|
-
import
|
|
28584
|
+
import fs3 from "node:fs";
|
|
28585
|
+
import path4 from "node:path";
|
|
28218
28586
|
var DEFAULT_CONTEXT_BASENAME = "context.json";
|
|
28219
28587
|
var DEFAULT_PROFILE = "default";
|
|
28220
28588
|
function findContextFileFromAncestors(startDir) {
|
|
28221
|
-
const absoluteStartDir =
|
|
28589
|
+
const absoluteStartDir = path4.resolve(startDir);
|
|
28222
28590
|
let currentDir = absoluteStartDir;
|
|
28223
28591
|
while (true) {
|
|
28224
|
-
const candidate =
|
|
28225
|
-
if (
|
|
28592
|
+
const candidate = path4.resolve(currentDir, ".rudder", DEFAULT_CONTEXT_BASENAME);
|
|
28593
|
+
if (fs3.existsSync(candidate)) {
|
|
28226
28594
|
return candidate;
|
|
28227
28595
|
}
|
|
28228
|
-
const nextDir =
|
|
28596
|
+
const nextDir = path4.resolve(currentDir, "..");
|
|
28229
28597
|
if (nextDir === currentDir) break;
|
|
28230
28598
|
currentDir = nextDir;
|
|
28231
28599
|
}
|
|
28232
28600
|
return null;
|
|
28233
28601
|
}
|
|
28234
28602
|
function resolveContextPath(overridePath) {
|
|
28235
|
-
if (overridePath) return
|
|
28236
|
-
if (process.env.RUDDER_CONTEXT) return
|
|
28603
|
+
if (overridePath) return path4.resolve(overridePath);
|
|
28604
|
+
if (process.env.RUDDER_CONTEXT) return path4.resolve(process.env.RUDDER_CONTEXT);
|
|
28237
28605
|
return findContextFileFromAncestors(process.cwd()) ?? resolveDefaultContextPath();
|
|
28238
28606
|
}
|
|
28239
28607
|
function defaultClientContext() {
|
|
@@ -28247,7 +28615,7 @@ function defaultClientContext() {
|
|
|
28247
28615
|
}
|
|
28248
28616
|
function parseJson(filePath) {
|
|
28249
28617
|
try {
|
|
28250
|
-
return JSON.parse(
|
|
28618
|
+
return JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
28251
28619
|
} catch (err) {
|
|
28252
28620
|
throw new Error(`Failed to parse JSON at ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
28253
28621
|
}
|
|
@@ -28293,7 +28661,7 @@ function normalizeContext(raw) {
|
|
|
28293
28661
|
}
|
|
28294
28662
|
function readContext(contextPath) {
|
|
28295
28663
|
const filePath = resolveContextPath(contextPath);
|
|
28296
|
-
if (!
|
|
28664
|
+
if (!fs3.existsSync(filePath)) {
|
|
28297
28665
|
return defaultClientContext();
|
|
28298
28666
|
}
|
|
28299
28667
|
const raw = parseJson(filePath);
|
|
@@ -28301,10 +28669,10 @@ function readContext(contextPath) {
|
|
|
28301
28669
|
}
|
|
28302
28670
|
function writeContext(context, contextPath) {
|
|
28303
28671
|
const filePath = resolveContextPath(contextPath);
|
|
28304
|
-
const dir =
|
|
28305
|
-
|
|
28672
|
+
const dir = path4.dirname(filePath);
|
|
28673
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
28306
28674
|
const normalized = normalizeContext(context);
|
|
28307
|
-
|
|
28675
|
+
fs3.writeFileSync(filePath, `${JSON.stringify(normalized, null, 2)}
|
|
28308
28676
|
`, { mode: 384 });
|
|
28309
28677
|
}
|
|
28310
28678
|
function upsertProfile(profileName, patch, contextPath) {
|
|
@@ -28750,7 +29118,8 @@ function buildMcpServerEnv(env = process.env) {
|
|
|
28750
29118
|
RUDDER_BROWSER_ENABLED: env.RUDDER_BROWSER_ENABLED,
|
|
28751
29119
|
RUDDER_COMPUTER_ENABLED: env.RUDDER_COMPUTER_ENABLED,
|
|
28752
29120
|
RUDDER_PROJECT_LIBRARY_PATH: env.RUDDER_PROJECT_LIBRARY_PATH,
|
|
28753
|
-
RUDDER_MCP_RUDDER_BIN: env.RUDDER_MCP_RUDDER_BIN
|
|
29121
|
+
RUDDER_MCP_RUDDER_BIN: env.RUDDER_MCP_RUDDER_BIN,
|
|
29122
|
+
RUDDER_TOOL_TRANSPORT_SURFACE: env.RUDDER_TOOL_TRANSPORT_SURFACE
|
|
28754
29123
|
};
|
|
28755
29124
|
}
|
|
28756
29125
|
function buildAgentV1ToolCallPlan(toolName, rawArgs, env = buildMcpServerEnv()) {
|
|
@@ -28758,10 +29127,10 @@ function buildAgentV1ToolCallPlan(toolName, rawArgs, env = buildMcpServerEnv())
|
|
|
28758
29127
|
if (!capabilityId) {
|
|
28759
29128
|
throw new Error(`Unknown Rudder MCP tool: ${toolName}`);
|
|
28760
29129
|
}
|
|
28761
|
-
if (rawArgs !== void 0 && rawArgs !== null && !
|
|
29130
|
+
if (rawArgs !== void 0 && rawArgs !== null && !isRecord3(rawArgs)) {
|
|
28762
29131
|
throwInvalidMcpArgument(toolName, "arguments", "must be object");
|
|
28763
29132
|
}
|
|
28764
|
-
const input = normalizeLegacyToolArguments(capabilityId,
|
|
29133
|
+
const input = normalizeLegacyToolArguments(capabilityId, isRecord3(rawArgs) ? rawArgs : {});
|
|
28765
29134
|
const capability = getAgentCliCapabilityById(capabilityId);
|
|
28766
29135
|
rejectModelProvidedRuntimeIdentity(input);
|
|
28767
29136
|
rejectUnsupportedToolArguments(toolName, input);
|
|
@@ -28784,7 +29153,8 @@ function buildAgentV1ToolCallPlan(toolName, rawArgs, env = buildMcpServerEnv())
|
|
|
28784
29153
|
RUDDER_RUN_ID: env.RUDDER_RUN_ID,
|
|
28785
29154
|
RUDDER_BROWSER_ENABLED: env.RUDDER_BROWSER_ENABLED,
|
|
28786
29155
|
RUDDER_COMPUTER_ENABLED: env.RUDDER_COMPUTER_ENABLED,
|
|
28787
|
-
RUDDER_PROJECT_LIBRARY_PATH: env.RUDDER_PROJECT_LIBRARY_PATH
|
|
29156
|
+
RUDDER_PROJECT_LIBRARY_PATH: env.RUDDER_PROJECT_LIBRARY_PATH,
|
|
29157
|
+
RUDDER_TOOL_TRANSPORT_SURFACE: "mcp"
|
|
28788
29158
|
},
|
|
28789
29159
|
tempFiles
|
|
28790
29160
|
};
|
|
@@ -28870,7 +29240,7 @@ async function runAgentV1McpJsonRpcMessage(message, env = buildMcpServerEnv(), s
|
|
|
28870
29240
|
case "tools/list": {
|
|
28871
29241
|
const tools = surface === "computer" ? computerCapabilityEnabled(env) ? COMPUTER_USE_MCP_TOOLS : [] : surface === "browser" && !browserCapabilityEnabled(env) ? [] : buildAgentV1McpToolsManifest("agent-v1", { surface }).tools.map(toMcpToolListEntry);
|
|
28872
29242
|
if (isModernMcpRequest(message.params)) {
|
|
28873
|
-
const cursor =
|
|
29243
|
+
const cursor = isRecord3(message.params) ? message.params.cursor : void 0;
|
|
28874
29244
|
if (typeof cursor === "string" && parseMcpToolCursor(cursor) === null) {
|
|
28875
29245
|
return rpcError(id, -32602, "Invalid tools/list cursor");
|
|
28876
29246
|
}
|
|
@@ -29024,7 +29394,7 @@ async function callToolSafely(params, env, surface, signal) {
|
|
|
29024
29394
|
const details = errorDetails(err);
|
|
29025
29395
|
const payload = {
|
|
29026
29396
|
status: "error",
|
|
29027
|
-
code:
|
|
29397
|
+
code: isRecord3(details) && typeof details.code === "string" ? details.code : "rudder_mcp_tool_error",
|
|
29028
29398
|
message: errorMessage(err),
|
|
29029
29399
|
details: details ?? null
|
|
29030
29400
|
};
|
|
@@ -29039,7 +29409,7 @@ async function callToolSafely(params, env, surface, signal) {
|
|
|
29039
29409
|
}
|
|
29040
29410
|
}
|
|
29041
29411
|
async function callTool(params, env, surface, signal) {
|
|
29042
|
-
const record =
|
|
29412
|
+
const record = isRecord3(params) ? params : {};
|
|
29043
29413
|
const toolName = typeof record.name === "string" ? record.name : "";
|
|
29044
29414
|
if (surface === "computer") {
|
|
29045
29415
|
if (!computerCapabilityEnabled(env)) {
|
|
@@ -29054,7 +29424,7 @@ async function callTool(params, env, surface, signal) {
|
|
|
29054
29424
|
error.code = "rudder_mcp_tool_not_available";
|
|
29055
29425
|
throw error;
|
|
29056
29426
|
}
|
|
29057
|
-
const rawArgs2 =
|
|
29427
|
+
const rawArgs2 = isRecord3(record.arguments) ? record.arguments : {};
|
|
29058
29428
|
rejectModelProvidedRuntimeIdentity(rawArgs2);
|
|
29059
29429
|
const parsed = computerUseActionSchemas[action].safeParse(rawArgs2);
|
|
29060
29430
|
if (!parsed.success) {
|
|
@@ -29073,17 +29443,17 @@ async function callTool(params, env, surface, signal) {
|
|
|
29073
29443
|
throw err;
|
|
29074
29444
|
}
|
|
29075
29445
|
const rawArgs = record.arguments;
|
|
29076
|
-
const args =
|
|
29446
|
+
const args = isRecord3(rawArgs) ? normalizeLegacyToolArguments(toolNameToCapabilityId(toolName) ?? "", rawArgs) : rawArgs;
|
|
29077
29447
|
const plan = buildAgentV1ToolCallPlan(toolName, args, env);
|
|
29078
29448
|
const directResult = await callToolDirectlyIfSupported(toolName, args, env, signal);
|
|
29079
29449
|
if (directResult) return directResult;
|
|
29080
|
-
const tempDir = plan.tempFiles.length > 0 ? await
|
|
29450
|
+
const tempDir = plan.tempFiles.length > 0 ? await fs5.mkdtemp(path7.join(os3.tmpdir(), "rudder-mcp-")) : null;
|
|
29081
29451
|
const materializedArgs = [...plan.args];
|
|
29082
29452
|
try {
|
|
29083
29453
|
if (tempDir) {
|
|
29084
29454
|
for (const tempFile of plan.tempFiles) {
|
|
29085
|
-
const tempPath =
|
|
29086
|
-
await
|
|
29455
|
+
const tempPath = path7.join(tempDir, `${tempFile.flag.replace(/^-+/, "")}.md`);
|
|
29456
|
+
await fs5.writeFile(tempPath, tempFile.contents, "utf8");
|
|
29087
29457
|
const index = materializedArgs.indexOf(tempFile.flag);
|
|
29088
29458
|
if (index >= 0) materializedArgs[index + 1] = tempPath;
|
|
29089
29459
|
}
|
|
@@ -29111,13 +29481,13 @@ async function callTool(params, env, surface, signal) {
|
|
|
29111
29481
|
isError: true
|
|
29112
29482
|
};
|
|
29113
29483
|
} finally {
|
|
29114
|
-
if (tempDir) await
|
|
29484
|
+
if (tempDir) await fs5.rm(tempDir, { recursive: true, force: true });
|
|
29115
29485
|
}
|
|
29116
29486
|
}
|
|
29117
29487
|
async function callToolDirectlyIfSupported(toolName, rawArgs, env, signal) {
|
|
29118
29488
|
const capabilityId = toolNameToCapabilityId(toolName);
|
|
29119
29489
|
if (!capabilityId) return null;
|
|
29120
|
-
const input =
|
|
29490
|
+
const input = isRecord3(rawArgs) ? rawArgs : {};
|
|
29121
29491
|
if (hasLocalImageInputs(input.images)) return null;
|
|
29122
29492
|
const api = mcpApiClient(env, signal);
|
|
29123
29493
|
const success = (data) => mcpSuccess(
|
|
@@ -29242,6 +29612,18 @@ async function callToolDirectlyIfSupported(toolName, rawArgs, env, signal) {
|
|
|
29242
29612
|
`/api/issues/${encodeURIComponent(requiredAnyString(input, ["issue", "issueId"]))}/heartbeat-context${query ? `?${query}` : ""}`
|
|
29243
29613
|
));
|
|
29244
29614
|
}
|
|
29615
|
+
case "issue.comments.list": {
|
|
29616
|
+
const params = new URLSearchParams();
|
|
29617
|
+
appendOptionalQuery(params, "after", input.after);
|
|
29618
|
+
appendOptionalQuery(params, "order", input.order ?? "desc");
|
|
29619
|
+
return success(await api.get(
|
|
29620
|
+
`/api/issues/${encodeURIComponent(requiredAnyString(input, ["issue", "issueId"]))}/comments?${params}`
|
|
29621
|
+
));
|
|
29622
|
+
}
|
|
29623
|
+
case "issue.comments.get":
|
|
29624
|
+
return success(await api.get(
|
|
29625
|
+
`/api/issues/${encodeURIComponent(requiredAnyString(input, ["issue", "issueId"]))}/comments/${encodeURIComponent(requiredAnyString(input, ["comment", "commentId"]))}`
|
|
29626
|
+
));
|
|
29245
29627
|
case "issue.checkout": {
|
|
29246
29628
|
const expectedStatuses = parseCsvInput(input.expectedStatuses, "todo,backlog,blocked");
|
|
29247
29629
|
const payload = checkoutIssueSchema.parse({
|
|
@@ -29270,6 +29652,12 @@ async function callToolDirectlyIfSupported(toolName, rawArgs, env, signal) {
|
|
|
29270
29652
|
{ status: "done", comment }
|
|
29271
29653
|
));
|
|
29272
29654
|
}
|
|
29655
|
+
case "runs.create":
|
|
29656
|
+
return success(await api.post("/api/agent-runs/delegation", {
|
|
29657
|
+
task: requiredString(input, "task"),
|
|
29658
|
+
...optionalString(input.targetAgentId) ? { targetAgentId: optionalString(input.targetAgentId) } : {},
|
|
29659
|
+
idempotencyKey: requiredString(input, "idempotencyKey")
|
|
29660
|
+
}));
|
|
29273
29661
|
case "runs.list":
|
|
29274
29662
|
return success(await api.get(
|
|
29275
29663
|
`/api/run-intelligence/orgs/${encodeURIComponent(requiredRuntimeString(env, "RUDDER_ORG_ID"))}/runs?${buildDirectRunsListQuery(input)}`
|
|
@@ -29452,11 +29840,12 @@ function mcpApiClient(env, signal) {
|
|
|
29452
29840
|
apiKey: optionalString(env.RUDDER_API_KEY) ?? void 0,
|
|
29453
29841
|
agentId: optionalString(env.RUDDER_AGENT_ID) ?? void 0,
|
|
29454
29842
|
runId: optionalString(env.RUDDER_RUN_ID) ?? void 0,
|
|
29843
|
+
transportSurface: "mcp",
|
|
29455
29844
|
signal
|
|
29456
29845
|
});
|
|
29457
29846
|
}
|
|
29458
29847
|
function mcpSuccess(data, maxResultBytes = RUDDER_MCP_MAX_TOOL_RESULT_BYTES) {
|
|
29459
|
-
if (
|
|
29848
|
+
if (isRecord3(data) && (data.mimeType === "image/png" || data.mimeType === "image/jpeg") && typeof data.base64 === "string" && data.base64.length > 0) {
|
|
29460
29849
|
const { base64, ...metadata } = data;
|
|
29461
29850
|
return {
|
|
29462
29851
|
content: [{ type: "image", data: base64, mimeType: data.mimeType }],
|
|
@@ -29467,9 +29856,9 @@ function mcpSuccess(data, maxResultBytes = RUDDER_MCP_MAX_TOOL_RESULT_BYTES) {
|
|
|
29467
29856
|
return mcpSuccessFromJsonText(JSON.stringify(data ?? {}), maxResultBytes);
|
|
29468
29857
|
}
|
|
29469
29858
|
function mcpSuccessWithImages(data, maxResultBytes) {
|
|
29470
|
-
if (!
|
|
29859
|
+
if (!isRecord3(data) || !Array.isArray(data.images)) return mcpSuccess(data, maxResultBytes);
|
|
29471
29860
|
const images = data.images.filter(
|
|
29472
|
-
(entry) =>
|
|
29861
|
+
(entry) => isRecord3(entry) && (entry.mimeType === "image/png" || entry.mimeType === "image/jpeg") && typeof entry.base64 === "string" && entry.base64.length > 0
|
|
29473
29862
|
);
|
|
29474
29863
|
if (images.length === 0) return mcpSuccess(data, maxResultBytes);
|
|
29475
29864
|
const metadata = { ...data };
|
|
@@ -30073,6 +30462,11 @@ function cliArgsForCapability(capabilityId, input, tempFiles, env) {
|
|
|
30073
30462
|
}
|
|
30074
30463
|
case "chat.archive":
|
|
30075
30464
|
return ["chat", "archive", requiredAnyString(input, ["chat", "chatId"])];
|
|
30465
|
+
case "runs.create": {
|
|
30466
|
+
const args = ["runs", "create", "--task", requiredString(input, "task"), "--idempotency-key", requiredString(input, "idempotencyKey")];
|
|
30467
|
+
pushOptional(args, "--target-agent-id", input.targetAgentId);
|
|
30468
|
+
return args;
|
|
30469
|
+
}
|
|
30076
30470
|
case "runs.list": {
|
|
30077
30471
|
const args = ["runs", "list"];
|
|
30078
30472
|
pushOptional(args, "--updated-after", input.updatedAfter);
|
|
@@ -30162,7 +30556,7 @@ function modernOrLegacyResult(params, result, options) {
|
|
|
30162
30556
|
}
|
|
30163
30557
|
function paginateMcpTools(tools, params) {
|
|
30164
30558
|
if (!isModernMcpRequest(params)) return { tools };
|
|
30165
|
-
const record =
|
|
30559
|
+
const record = isRecord3(params) ? params : {};
|
|
30166
30560
|
const cursor = typeof record.cursor === "string" ? record.cursor : null;
|
|
30167
30561
|
const offset = cursor === null ? 0 : parseMcpToolCursor(cursor) ?? 0;
|
|
30168
30562
|
const page = tools.slice(offset, offset + RUDDER_MCP_TOOL_PAGE_SIZE);
|
|
@@ -30185,7 +30579,7 @@ function parseMcpToolCursor(cursor) {
|
|
|
30185
30579
|
return null;
|
|
30186
30580
|
}
|
|
30187
30581
|
function requestedProtocolVersion(params) {
|
|
30188
|
-
if (!
|
|
30582
|
+
if (!isRecord3(params)) return null;
|
|
30189
30583
|
return typeof params.protocolVersion === "string" && params.protocolVersion.trim().length > 0 ? params.protocolVersion.trim() : null;
|
|
30190
30584
|
}
|
|
30191
30585
|
function toolNameToCapabilityId(toolName) {
|
|
@@ -30230,7 +30624,7 @@ function pushJson(args, flag, value) {
|
|
|
30230
30624
|
args.push(flag, value.trim());
|
|
30231
30625
|
return;
|
|
30232
30626
|
}
|
|
30233
|
-
if (
|
|
30627
|
+
if (isRecord3(value) || Array.isArray(value)) {
|
|
30234
30628
|
args.push(flag, JSON.stringify(value));
|
|
30235
30629
|
}
|
|
30236
30630
|
}
|
|
@@ -30299,20 +30693,20 @@ function validateMcpToolArguments(toolName, input) {
|
|
|
30299
30693
|
}
|
|
30300
30694
|
if (Array.isArray(schema.anyOf)) {
|
|
30301
30695
|
const matches = schema.anyOf.some((candidate) => {
|
|
30302
|
-
if (!
|
|
30696
|
+
if (!isRecord3(candidate) || !Array.isArray(candidate.required)) return false;
|
|
30303
30697
|
return candidate.required.every((key) => {
|
|
30304
30698
|
const value = input[String(key)];
|
|
30305
30699
|
return value !== void 0 && value !== null && !(typeof value === "string" && value.trim().length === 0) && !(Array.isArray(value) && value.length === 0);
|
|
30306
30700
|
});
|
|
30307
30701
|
});
|
|
30308
30702
|
if (!matches) {
|
|
30309
|
-
const alternatives = schema.anyOf.flatMap((candidate) =>
|
|
30703
|
+
const alternatives = schema.anyOf.flatMap((candidate) => isRecord3(candidate) && Array.isArray(candidate.required) ? candidate.required : []).map(String);
|
|
30310
30704
|
throwInvalidMcpArgument(toolName, alternatives.join(" or "), "is required");
|
|
30311
30705
|
}
|
|
30312
30706
|
}
|
|
30313
30707
|
for (const [key, value] of Object.entries(input)) {
|
|
30314
30708
|
const property = schema.properties[key];
|
|
30315
|
-
if (!
|
|
30709
|
+
if (!isRecord3(property) || value === void 0) continue;
|
|
30316
30710
|
const violation = jsonSchemaViolation(value, property);
|
|
30317
30711
|
if (violation) throwInvalidMcpArgument(toolName, key, violation);
|
|
30318
30712
|
}
|
|
@@ -30320,20 +30714,21 @@ function validateMcpToolArguments(toolName, input) {
|
|
|
30320
30714
|
function jsonSchemaViolation(value, schema) {
|
|
30321
30715
|
if (Array.isArray(schema.oneOf)) {
|
|
30322
30716
|
const matches = schema.oneOf.some(
|
|
30323
|
-
(candidate) =>
|
|
30717
|
+
(candidate) => isRecord3(candidate) && jsonSchemaViolation(value, candidate) === null
|
|
30324
30718
|
);
|
|
30325
30719
|
if (!matches) return "does not match any allowed shape";
|
|
30326
30720
|
}
|
|
30327
30721
|
const types = Array.isArray(schema.type) ? schema.type : schema.type === void 0 ? [] : [schema.type];
|
|
30328
30722
|
if (types.length > 0) {
|
|
30329
|
-
const validType = types.some((type) => type === "string" ? typeof value === "string" : type === "number" ? typeof value === "number" && Number.isFinite(value) : type === "boolean" ? typeof value === "boolean" : type === "array" ? Array.isArray(value) : type === "object" ?
|
|
30723
|
+
const validType = types.some((type) => type === "string" ? typeof value === "string" : type === "number" ? typeof value === "number" && Number.isFinite(value) : type === "boolean" ? typeof value === "boolean" : type === "array" ? Array.isArray(value) : type === "object" ? isRecord3(value) : type === "null" ? value === null : false);
|
|
30330
30724
|
if (!validType) return `must be ${types.join(" or ")}`;
|
|
30331
30725
|
}
|
|
30332
30726
|
if (typeof value === "string") {
|
|
30333
|
-
|
|
30727
|
+
const characterLength = Array.from(value).length;
|
|
30728
|
+
if (typeof schema.minLength === "number" && characterLength < schema.minLength) {
|
|
30334
30729
|
return `must contain at least ${schema.minLength} character(s)`;
|
|
30335
30730
|
}
|
|
30336
|
-
if (typeof schema.maxLength === "number" &&
|
|
30731
|
+
if (typeof schema.maxLength === "number" && characterLength > schema.maxLength) {
|
|
30337
30732
|
return `must contain at most ${schema.maxLength} characters`;
|
|
30338
30733
|
}
|
|
30339
30734
|
if (Array.isArray(schema.enum) && !schema.enum.includes(value)) {
|
|
@@ -30355,15 +30750,18 @@ function jsonSchemaViolation(value, schema) {
|
|
|
30355
30750
|
if (typeof schema.maxItems === "number" && value.length > schema.maxItems) {
|
|
30356
30751
|
return `must contain at most ${schema.maxItems} items`;
|
|
30357
30752
|
}
|
|
30358
|
-
if (
|
|
30753
|
+
if (isRecord3(schema.items)) {
|
|
30359
30754
|
for (const [index, item] of value.entries()) {
|
|
30360
30755
|
const violation = jsonSchemaViolation(item, schema.items);
|
|
30361
30756
|
if (violation) return `item ${index} ${violation}`;
|
|
30362
30757
|
}
|
|
30363
30758
|
}
|
|
30364
30759
|
}
|
|
30365
|
-
if (
|
|
30366
|
-
|
|
30760
|
+
if (isRecord3(value) && schema.type === "object") {
|
|
30761
|
+
if (typeof schema.minProperties === "number" && Object.keys(value).length < schema.minProperties) {
|
|
30762
|
+
return `must contain at least ${schema.minProperties} properties`;
|
|
30763
|
+
}
|
|
30764
|
+
const properties = isRecord3(schema.properties) ? schema.properties : {};
|
|
30367
30765
|
const required = Array.isArray(schema.required) ? schema.required.map(String) : [];
|
|
30368
30766
|
for (const key of required) {
|
|
30369
30767
|
if (!(key in value)) return `field ${key} is required`;
|
|
@@ -30374,7 +30772,7 @@ function jsonSchemaViolation(value, schema) {
|
|
|
30374
30772
|
}
|
|
30375
30773
|
for (const [key, child] of Object.entries(value)) {
|
|
30376
30774
|
const childSchema = properties[key];
|
|
30377
|
-
if (!
|
|
30775
|
+
if (!isRecord3(childSchema)) continue;
|
|
30378
30776
|
const violation = jsonSchemaViolation(child, childSchema);
|
|
30379
30777
|
if (violation) return `field ${key} ${violation}`;
|
|
30380
30778
|
}
|
|
@@ -30436,7 +30834,7 @@ function assertBrowserCapabilityEnabled(capabilityId, env) {
|
|
|
30436
30834
|
function structuredContentFromJsonText(text6) {
|
|
30437
30835
|
try {
|
|
30438
30836
|
const parsed = JSON.parse(text6);
|
|
30439
|
-
if (
|
|
30837
|
+
if (isRecord3(parsed)) return { structuredContent: parsed };
|
|
30440
30838
|
return { structuredContent: { result: parsed } };
|
|
30441
30839
|
} catch {
|
|
30442
30840
|
return {};
|
|
@@ -30497,10 +30895,18 @@ function errorMessage(err) {
|
|
|
30497
30895
|
}
|
|
30498
30896
|
function errorDetails(err) {
|
|
30499
30897
|
if (!(err instanceof Error)) return void 0;
|
|
30898
|
+
if (err instanceof ApiRequestError) {
|
|
30899
|
+
const details = isRecord3(err.details) ? err.details : err.details === void 0 ? {} : { upstreamDetails: err.details };
|
|
30900
|
+
return {
|
|
30901
|
+
code: err.code ?? "api_request_error",
|
|
30902
|
+
status: err.status,
|
|
30903
|
+
...details
|
|
30904
|
+
};
|
|
30905
|
+
}
|
|
30500
30906
|
const code = err.code;
|
|
30501
30907
|
return code ? { code } : void 0;
|
|
30502
30908
|
}
|
|
30503
|
-
function
|
|
30909
|
+
function isRecord3(value) {
|
|
30504
30910
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30505
30911
|
}
|
|
30506
30912
|
|
|
@@ -30554,8 +30960,8 @@ function registerActivityCommands(program) {
|
|
|
30554
30960
|
if (opts.entityType) params.set("entityType", opts.entityType);
|
|
30555
30961
|
if (opts.entityId) params.set("entityId", opts.entityId);
|
|
30556
30962
|
const query = params.toString();
|
|
30557
|
-
const
|
|
30558
|
-
const rows = await ctx.api.get(
|
|
30963
|
+
const path26 = `/api/orgs/${ctx.orgId}/activity${query ? `?${query}` : ""}`;
|
|
30964
|
+
const rows = await ctx.api.get(path26) ?? [];
|
|
30559
30965
|
if (ctx.json) {
|
|
30560
30966
|
printOutput(rows, { json: true });
|
|
30561
30967
|
return;
|
|
@@ -30586,8 +30992,8 @@ function registerActivityCommands(program) {
|
|
|
30586
30992
|
}
|
|
30587
30993
|
|
|
30588
30994
|
// ../packages/agent-runtime-utils/dist/server-utils.cli.js
|
|
30589
|
-
import { promises as
|
|
30590
|
-
import
|
|
30995
|
+
import { promises as fs9 } from "node:fs";
|
|
30996
|
+
import path12 from "node:path";
|
|
30591
30997
|
|
|
30592
30998
|
// ../packages/agent-runtime-utils/dist/native-process-runner.js
|
|
30593
30999
|
init_dist2();
|
|
@@ -31055,6 +31461,12 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
|
|
|
31055
31461
|
"",
|
|
31056
31462
|
"When an issue comment, done comment, or blocker comment cites visual evidence from a local screenshot/image path, attach the image with the Rudder CLI `--image <path>` option instead of leaving only the filesystem path in the text.",
|
|
31057
31463
|
"",
|
|
31464
|
+
"## Rudder Issue Transport Failures",
|
|
31465
|
+
"",
|
|
31466
|
+
"For Issue read/comment operations, treat typed Rudder MCP and the `rudder issue` CLI as one backend failure domain. Build the failure fingerprint from operation, Issue id, HTTP status/code, and normalized server message.",
|
|
31467
|
+
"After the typed MCP surface returns a 5xx failure, make at most one recorded fallback through the CLI. If that fallback returns the same fingerprint or reports `issue_transport_unavailable`, stop all Issue transport probes for the reported backoff: do not switch profiles, repeat either surface, or call the API directly.",
|
|
31468
|
+
"When the Issue transport budget is exhausted but local task work can continue, record the checkpoint `Issue transport unavailable` in the run outcome and keep Issue ownership, reviewer, and lifecycle state unchanged. Retry only after the diagnostic backoff expires or an explicit prerequisite changes.",
|
|
31469
|
+
"",
|
|
31058
31470
|
"## Memory and Shared Work Notes",
|
|
31059
31471
|
"",
|
|
31060
31472
|
"You MUST use the `para-memory-files` skill for all memory operations: storing facts, writing daily notes, creating entities, running weekly synthesis, recalling past context, and managing shared work notes. The skill defines your three-layer memory system (knowledge graph, daily notes, tacit knowledge), the PARA folder structure, atomic fact schemas, memory decay rules, and recall conventions.",
|
|
@@ -31093,15 +31505,15 @@ var RUDDER_AGENT_HEARTBEAT_INSTRUCTION = [
|
|
|
31093
31505
|
// ../packages/agent-runtime-utils/dist/server-utils.cli.js
|
|
31094
31506
|
async function resolveRudderSkillsDir(moduleDir, additionalCandidates = []) {
|
|
31095
31507
|
const candidates = [
|
|
31096
|
-
...RUDDER_SKILL_ROOT_RELATIVE_CANDIDATES.map((relativePath) =>
|
|
31097
|
-
...additionalCandidates.map((candidate) =>
|
|
31508
|
+
...RUDDER_SKILL_ROOT_RELATIVE_CANDIDATES.map((relativePath) => path12.resolve(moduleDir, relativePath)),
|
|
31509
|
+
...additionalCandidates.map((candidate) => path12.resolve(candidate))
|
|
31098
31510
|
];
|
|
31099
31511
|
const seenRoots = /* @__PURE__ */ new Set();
|
|
31100
31512
|
for (const root of candidates) {
|
|
31101
31513
|
if (seenRoots.has(root))
|
|
31102
31514
|
continue;
|
|
31103
31515
|
seenRoots.add(root);
|
|
31104
|
-
const isDirectory = await
|
|
31516
|
+
const isDirectory = await fs9.stat(root).then((stats) => stats.isDirectory()).catch(() => false);
|
|
31105
31517
|
if (isDirectory)
|
|
31106
31518
|
return root;
|
|
31107
31519
|
}
|
|
@@ -31111,36 +31523,36 @@ async function removeMaintainerOnlySkillSymlinks(skillsHome, allowedSkillNames)
|
|
|
31111
31523
|
return removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames);
|
|
31112
31524
|
}
|
|
31113
31525
|
async function readRudderMaterializedSkillSource(target) {
|
|
31114
|
-
const manifestPath =
|
|
31115
|
-
const raw = await
|
|
31526
|
+
const manifestPath = path12.join(target, ".rudder", "materialized-skill.json");
|
|
31527
|
+
const raw = await fs9.readFile(manifestPath, "utf8").catch(() => null);
|
|
31116
31528
|
if (!raw)
|
|
31117
31529
|
return null;
|
|
31118
31530
|
try {
|
|
31119
31531
|
const parsed = parseObject(JSON.parse(raw));
|
|
31120
31532
|
const sourcePath = asString(parsed.sourcePath, "").trim();
|
|
31121
|
-
return sourcePath.length > 0 ?
|
|
31533
|
+
return sourcePath.length > 0 ? path12.resolve(sourcePath) : null;
|
|
31122
31534
|
} catch {
|
|
31123
31535
|
return null;
|
|
31124
31536
|
}
|
|
31125
31537
|
}
|
|
31126
31538
|
async function removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames, knownSkillSources = []) {
|
|
31127
31539
|
const allowed = new Set(Array.from(allowedSkillNames));
|
|
31128
|
-
const knownSources = new Set(Array.from(knownSkillSources).map((value) => value.trim()).filter(Boolean).map((value) =>
|
|
31540
|
+
const knownSources = new Set(Array.from(knownSkillSources).map((value) => value.trim()).filter(Boolean).map((value) => path12.resolve(value)));
|
|
31129
31541
|
try {
|
|
31130
|
-
const entries = await
|
|
31542
|
+
const entries = await fs9.readdir(skillsHome, { withFileTypes: true });
|
|
31131
31543
|
const removed = [];
|
|
31132
31544
|
for (const entry of entries) {
|
|
31133
|
-
const target =
|
|
31134
|
-
const existing = await
|
|
31545
|
+
const target = path12.join(skillsHome, entry.name);
|
|
31546
|
+
const existing = await fs9.lstat(target).catch(() => null);
|
|
31135
31547
|
if (!existing)
|
|
31136
31548
|
continue;
|
|
31137
31549
|
let isRudderManagedSkill = false;
|
|
31138
31550
|
if (existing.isSymbolicLink()) {
|
|
31139
|
-
const linkedPath = await
|
|
31551
|
+
const linkedPath = await fs9.readlink(target).catch(() => null);
|
|
31140
31552
|
if (!linkedPath)
|
|
31141
31553
|
continue;
|
|
31142
|
-
const resolvedLinkedPath =
|
|
31143
|
-
isRudderManagedSkill = knownSources.has(
|
|
31554
|
+
const resolvedLinkedPath = path12.isAbsolute(linkedPath) ? linkedPath : path12.resolve(path12.dirname(target), linkedPath);
|
|
31555
|
+
isRudderManagedSkill = knownSources.has(path12.resolve(resolvedLinkedPath)) || isMaintainerOnlySkillTarget(linkedPath) || isMaintainerOnlySkillTarget(resolvedLinkedPath);
|
|
31144
31556
|
} else if (existing.isDirectory()) {
|
|
31145
31557
|
const materializedSource = await readRudderMaterializedSkillSource(target);
|
|
31146
31558
|
isRudderManagedSkill = materializedSource !== null && knownSources.has(materializedSource);
|
|
@@ -31149,7 +31561,7 @@ async function removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames
|
|
|
31149
31561
|
continue;
|
|
31150
31562
|
if (allowed.has(entry.name))
|
|
31151
31563
|
continue;
|
|
31152
|
-
await
|
|
31564
|
+
await fs9.rm(target, { recursive: true, force: true });
|
|
31153
31565
|
removed.push(entry.name);
|
|
31154
31566
|
}
|
|
31155
31567
|
return removed;
|
|
@@ -31160,9 +31572,9 @@ async function removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames
|
|
|
31160
31572
|
|
|
31161
31573
|
// src/commands/client/agent.ts
|
|
31162
31574
|
init_dist2();
|
|
31163
|
-
import
|
|
31164
|
-
import
|
|
31165
|
-
import
|
|
31575
|
+
import fs10 from "node:fs/promises";
|
|
31576
|
+
import os4 from "node:os";
|
|
31577
|
+
import path13 from "node:path";
|
|
31166
31578
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
31167
31579
|
|
|
31168
31580
|
// src/commands/client/help.ts
|
|
@@ -31186,16 +31598,16 @@ function formatHelpExample(example) {
|
|
|
31186
31598
|
}
|
|
31187
31599
|
|
|
31188
31600
|
// src/commands/client/agent.ts
|
|
31189
|
-
var __moduleDir =
|
|
31601
|
+
var __moduleDir = path13.dirname(fileURLToPath6(import.meta.url));
|
|
31190
31602
|
function codexSkillsHome() {
|
|
31191
31603
|
const fromEnv = process.env.CODEX_HOME?.trim();
|
|
31192
|
-
const base = fromEnv && fromEnv.length > 0 ? fromEnv :
|
|
31193
|
-
return
|
|
31604
|
+
const base = fromEnv && fromEnv.length > 0 ? fromEnv : path13.join(os4.homedir(), ".codex");
|
|
31605
|
+
return path13.join(base, "skills");
|
|
31194
31606
|
}
|
|
31195
31607
|
function claudeSkillsHome() {
|
|
31196
31608
|
const fromEnv = process.env.CLAUDE_HOME?.trim();
|
|
31197
|
-
const base = fromEnv && fromEnv.length > 0 ? fromEnv :
|
|
31198
|
-
return
|
|
31609
|
+
const base = fromEnv && fromEnv.length > 0 ? fromEnv : path13.join(os4.homedir(), ".claude");
|
|
31610
|
+
return path13.join(base, "skills");
|
|
31199
31611
|
}
|
|
31200
31612
|
async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool2) {
|
|
31201
31613
|
const summary = {
|
|
@@ -31206,26 +31618,26 @@ async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool2) {
|
|
|
31206
31618
|
skipped: [],
|
|
31207
31619
|
failed: []
|
|
31208
31620
|
};
|
|
31209
|
-
await
|
|
31210
|
-
const entries = await
|
|
31621
|
+
await fs10.mkdir(targetSkillsDir, { recursive: true });
|
|
31622
|
+
const entries = await fs10.readdir(sourceSkillsDir, { withFileTypes: true });
|
|
31211
31623
|
summary.removed = await removeMaintainerOnlySkillSymlinks(
|
|
31212
31624
|
targetSkillsDir,
|
|
31213
31625
|
entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name)
|
|
31214
31626
|
);
|
|
31215
31627
|
for (const entry of entries) {
|
|
31216
31628
|
if (!entry.isDirectory()) continue;
|
|
31217
|
-
const source =
|
|
31218
|
-
const target =
|
|
31219
|
-
const existing = await
|
|
31629
|
+
const source = path13.join(sourceSkillsDir, entry.name);
|
|
31630
|
+
const target = path13.join(targetSkillsDir, entry.name);
|
|
31631
|
+
const existing = await fs10.lstat(target).catch(() => null);
|
|
31220
31632
|
if (existing) {
|
|
31221
31633
|
if (existing.isSymbolicLink()) {
|
|
31222
31634
|
let linkedPath = null;
|
|
31223
31635
|
try {
|
|
31224
|
-
linkedPath = await
|
|
31636
|
+
linkedPath = await fs10.readlink(target);
|
|
31225
31637
|
} catch (err) {
|
|
31226
|
-
await
|
|
31638
|
+
await fs10.unlink(target);
|
|
31227
31639
|
try {
|
|
31228
|
-
await
|
|
31640
|
+
await fs10.symlink(source, target);
|
|
31229
31641
|
summary.linked.push(entry.name);
|
|
31230
31642
|
continue;
|
|
31231
31643
|
} catch (linkErr) {
|
|
@@ -31236,10 +31648,10 @@ async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool2) {
|
|
|
31236
31648
|
continue;
|
|
31237
31649
|
}
|
|
31238
31650
|
}
|
|
31239
|
-
const resolvedLinkedPath =
|
|
31240
|
-
const linkedTargetExists = await
|
|
31651
|
+
const resolvedLinkedPath = path13.isAbsolute(linkedPath) ? linkedPath : path13.resolve(path13.dirname(target), linkedPath);
|
|
31652
|
+
const linkedTargetExists = await fs10.stat(resolvedLinkedPath).then(() => true).catch(() => false);
|
|
31241
31653
|
if (!linkedTargetExists) {
|
|
31242
|
-
await
|
|
31654
|
+
await fs10.unlink(target);
|
|
31243
31655
|
} else {
|
|
31244
31656
|
summary.skipped.push(entry.name);
|
|
31245
31657
|
continue;
|
|
@@ -31250,7 +31662,7 @@ async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool2) {
|
|
|
31250
31662
|
}
|
|
31251
31663
|
}
|
|
31252
31664
|
try {
|
|
31253
|
-
await
|
|
31665
|
+
await fs10.symlink(source, target);
|
|
31254
31666
|
summary.linked.push(entry.name);
|
|
31255
31667
|
} catch (err) {
|
|
31256
31668
|
summary.failed.push({
|
|
@@ -31461,7 +31873,7 @@ function registerAgentCommands(program) {
|
|
|
31461
31873
|
if (opts.markdown && opts.markdownFile) {
|
|
31462
31874
|
throw new Error("Pass only one of --markdown or --markdown-file.");
|
|
31463
31875
|
}
|
|
31464
|
-
const markdown = opts.markdownFile ? await
|
|
31876
|
+
const markdown = opts.markdownFile ? await fs10.readFile(path13.resolve(opts.markdownFile), "utf8") : opts.markdown;
|
|
31465
31877
|
const payload = organizationSkillCreateSchema.parse({
|
|
31466
31878
|
name: opts.name,
|
|
31467
31879
|
slug: opts.slug?.trim() || null,
|
|
@@ -31640,7 +32052,7 @@ function registerAgentCommands(program) {
|
|
|
31640
32052
|
}
|
|
31641
32053
|
const installSummaries = [];
|
|
31642
32054
|
if (opts.installSkills !== false) {
|
|
31643
|
-
const skillsDir = await resolveRudderSkillsDir(__moduleDir, [
|
|
32055
|
+
const skillsDir = await resolveRudderSkillsDir(__moduleDir, [path13.resolve(process.cwd(), "skills")]);
|
|
31644
32056
|
if (!skillsDir) {
|
|
31645
32057
|
throw new Error(
|
|
31646
32058
|
"Could not locate local Rudder skills directory. Expected ./skills in the repo checkout."
|
|
@@ -31728,10 +32140,10 @@ async function buildAgentUpdatePatch(opts) {
|
|
|
31728
32140
|
if (opts.capabilities !== void 0) rawPatch.capabilities = opts.capabilities;
|
|
31729
32141
|
if (opts.description !== void 0) rawPatch.capabilities = opts.description;
|
|
31730
32142
|
if (opts.capabilitiesFile !== void 0) {
|
|
31731
|
-
rawPatch.capabilities = await
|
|
32143
|
+
rawPatch.capabilities = await fs10.readFile(path13.resolve(opts.capabilitiesFile), "utf8");
|
|
31732
32144
|
}
|
|
31733
32145
|
if (opts.descriptionFile !== void 0) {
|
|
31734
|
-
rawPatch.capabilities = await
|
|
32146
|
+
rawPatch.capabilities = await fs10.readFile(path13.resolve(opts.descriptionFile), "utf8");
|
|
31735
32147
|
}
|
|
31736
32148
|
if (clearCapabilities) rawPatch.capabilities = null;
|
|
31737
32149
|
return updateAgentSchema.parse(rawPatch);
|
|
@@ -31755,7 +32167,7 @@ function parseJsonObject(value, name) {
|
|
|
31755
32167
|
// src/commands/client/approval.ts
|
|
31756
32168
|
init_dist2();
|
|
31757
32169
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
31758
|
-
import
|
|
32170
|
+
import path14 from "node:path";
|
|
31759
32171
|
function registerApprovalCommands(program) {
|
|
31760
32172
|
const approval = program.command("approval").description("Approval operations");
|
|
31761
32173
|
addCommonClientOptions(
|
|
@@ -31946,7 +32358,7 @@ async function readTextInputFile(inputPath, optionName) {
|
|
|
31946
32358
|
if (inputPath === "-") {
|
|
31947
32359
|
return readStdinText();
|
|
31948
32360
|
}
|
|
31949
|
-
const resolvedPath =
|
|
32361
|
+
const resolvedPath = path14.resolve(process.cwd(), inputPath);
|
|
31950
32362
|
return readFile2(resolvedPath, "utf8").catch((err) => {
|
|
31951
32363
|
throw new Error(`Unable to read ${optionName} ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
31952
32364
|
});
|
|
@@ -32784,11 +33196,11 @@ async function readStdin() {
|
|
|
32784
33196
|
// src/commands/client/company.ts
|
|
32785
33197
|
import * as p3 from "@clack/prompts";
|
|
32786
33198
|
import { mkdir as mkdir2, readdir as readdir2, readFile as readFile3, stat as stat2, writeFile as writeFile2 } from "node:fs/promises";
|
|
32787
|
-
import
|
|
33199
|
+
import path16 from "node:path";
|
|
32788
33200
|
import pc5 from "picocolors";
|
|
32789
33201
|
|
|
32790
33202
|
// src/commands/client/zip.ts
|
|
32791
|
-
import
|
|
33203
|
+
import path15 from "node:path";
|
|
32792
33204
|
import { inflateRawSync } from "node:zlib";
|
|
32793
33205
|
var textDecoder = new TextDecoder();
|
|
32794
33206
|
var binaryContentTypeByExtension = {
|
|
@@ -32816,7 +33228,7 @@ function sharedArchiveRoot(paths) {
|
|
|
32816
33228
|
return firstSegments.every((parts) => parts.length > 1 && parts[0] === candidate) ? candidate : null;
|
|
32817
33229
|
}
|
|
32818
33230
|
function bytesToPortableFileEntry(pathValue, bytes) {
|
|
32819
|
-
const contentType = binaryContentTypeByExtension[
|
|
33231
|
+
const contentType = binaryContentTypeByExtension[path15.extname(pathValue).toLowerCase()];
|
|
32820
33232
|
if (!contentType) return textDecoder.decode(bytes);
|
|
32821
33233
|
return {
|
|
32822
33234
|
encoding: "base64",
|
|
@@ -32904,7 +33316,7 @@ var IMPORT_INCLUDE_OPTIONS = [
|
|
|
32904
33316
|
];
|
|
32905
33317
|
var IMPORT_PREVIEW_SAMPLE_LIMIT = 6;
|
|
32906
33318
|
function readPortableFileEntry(filePath, contents) {
|
|
32907
|
-
const contentType = binaryContentTypeByExtension[
|
|
33319
|
+
const contentType = binaryContentTypeByExtension[path16.extname(filePath).toLowerCase()];
|
|
32908
33320
|
if (!contentType) return contents.toString("utf8");
|
|
32909
33321
|
return {
|
|
32910
33322
|
encoding: "base64",
|
|
@@ -32959,10 +33371,10 @@ function normalizePortablePath(filePath) {
|
|
|
32959
33371
|
return filePath.replace(/\\/g, "/");
|
|
32960
33372
|
}
|
|
32961
33373
|
function shouldIncludePortableFile(filePath) {
|
|
32962
|
-
const baseName =
|
|
33374
|
+
const baseName = path16.basename(filePath);
|
|
32963
33375
|
const isMarkdown = baseName.endsWith(".md");
|
|
32964
33376
|
const isPaperclipYaml = baseName === ".rudder.yaml" || baseName === ".rudder.yml";
|
|
32965
|
-
const contentType = binaryContentTypeByExtension[
|
|
33377
|
+
const contentType = binaryContentTypeByExtension[path16.extname(baseName).toLowerCase()];
|
|
32966
33378
|
return isMarkdown || isPaperclipYaml || Boolean(contentType);
|
|
32967
33379
|
}
|
|
32968
33380
|
function findPortableExtensionPath(files) {
|
|
@@ -33517,7 +33929,7 @@ function normalizeGithubImportSource(input, refOverride) {
|
|
|
33517
33929
|
}
|
|
33518
33930
|
async function pathExists(inputPath) {
|
|
33519
33931
|
try {
|
|
33520
|
-
await stat2(
|
|
33932
|
+
await stat2(path16.resolve(inputPath));
|
|
33521
33933
|
return true;
|
|
33522
33934
|
} catch {
|
|
33523
33935
|
return false;
|
|
@@ -33527,45 +33939,45 @@ async function collectPackageFiles(root, current, files) {
|
|
|
33527
33939
|
const entries = await readdir2(current, { withFileTypes: true });
|
|
33528
33940
|
for (const entry of entries) {
|
|
33529
33941
|
if (entry.name.startsWith(".git")) continue;
|
|
33530
|
-
const absolutePath =
|
|
33942
|
+
const absolutePath = path16.join(current, entry.name);
|
|
33531
33943
|
if (entry.isDirectory()) {
|
|
33532
33944
|
await collectPackageFiles(root, absolutePath, files);
|
|
33533
33945
|
continue;
|
|
33534
33946
|
}
|
|
33535
33947
|
if (!entry.isFile()) continue;
|
|
33536
|
-
const relativePath =
|
|
33948
|
+
const relativePath = path16.relative(root, absolutePath).replace(/\\/g, "/");
|
|
33537
33949
|
if (!shouldIncludePortableFile(relativePath)) continue;
|
|
33538
33950
|
files[relativePath] = readPortableFileEntry(relativePath, await readFile3(absolutePath));
|
|
33539
33951
|
}
|
|
33540
33952
|
}
|
|
33541
33953
|
async function resolveInlineSourceFromPath(inputPath) {
|
|
33542
|
-
const resolved =
|
|
33954
|
+
const resolved = path16.resolve(inputPath);
|
|
33543
33955
|
const resolvedStat = await stat2(resolved);
|
|
33544
|
-
if (resolvedStat.isFile() &&
|
|
33956
|
+
if (resolvedStat.isFile() && path16.extname(resolved).toLowerCase() === ".zip") {
|
|
33545
33957
|
const archive = await readZipArchive(await readFile3(resolved));
|
|
33546
33958
|
const filteredFiles = Object.fromEntries(
|
|
33547
33959
|
Object.entries(archive.files).filter(([relativePath]) => shouldIncludePortableFile(relativePath))
|
|
33548
33960
|
);
|
|
33549
33961
|
return {
|
|
33550
|
-
rootPath: archive.rootPath ??
|
|
33962
|
+
rootPath: archive.rootPath ?? path16.basename(resolved, ".zip"),
|
|
33551
33963
|
files: filteredFiles
|
|
33552
33964
|
};
|
|
33553
33965
|
}
|
|
33554
|
-
const rootDir = resolvedStat.isDirectory() ? resolved :
|
|
33966
|
+
const rootDir = resolvedStat.isDirectory() ? resolved : path16.dirname(resolved);
|
|
33555
33967
|
const files = {};
|
|
33556
33968
|
await collectPackageFiles(rootDir, rootDir, files);
|
|
33557
33969
|
return {
|
|
33558
|
-
rootPath:
|
|
33970
|
+
rootPath: path16.basename(rootDir),
|
|
33559
33971
|
files
|
|
33560
33972
|
};
|
|
33561
33973
|
}
|
|
33562
33974
|
async function writeExportToFolder(outDir, exported) {
|
|
33563
|
-
const root =
|
|
33975
|
+
const root = path16.resolve(outDir);
|
|
33564
33976
|
await mkdir2(root, { recursive: true });
|
|
33565
33977
|
for (const [relativePath, content] of Object.entries(exported.files)) {
|
|
33566
33978
|
const normalized = relativePath.replace(/\\/g, "/");
|
|
33567
|
-
const filePath =
|
|
33568
|
-
await mkdir2(
|
|
33979
|
+
const filePath = path16.join(root, normalized);
|
|
33980
|
+
await mkdir2(path16.dirname(filePath), { recursive: true });
|
|
33569
33981
|
const writeValue = portableFileEntryToWriteValue(content);
|
|
33570
33982
|
if (typeof writeValue === "string") {
|
|
33571
33983
|
await writeFile2(filePath, writeValue, "utf8");
|
|
@@ -33575,7 +33987,7 @@ async function writeExportToFolder(outDir, exported) {
|
|
|
33575
33987
|
}
|
|
33576
33988
|
}
|
|
33577
33989
|
async function confirmOverwriteExportDirectory(outDir) {
|
|
33578
|
-
const root =
|
|
33990
|
+
const root = path16.resolve(outDir);
|
|
33579
33991
|
const stats = await stat2(root).catch(() => null);
|
|
33580
33992
|
if (!stats) return;
|
|
33581
33993
|
if (!stats.isDirectory()) {
|
|
@@ -33757,7 +34169,7 @@ function registerCompanyCommands(program) {
|
|
|
33757
34169
|
printOutput(
|
|
33758
34170
|
{
|
|
33759
34171
|
ok: true,
|
|
33760
|
-
out:
|
|
34172
|
+
out: path16.resolve(opts.out),
|
|
33761
34173
|
rootPath: exported.rootPath,
|
|
33762
34174
|
filesWritten: Object.keys(exported.files).length,
|
|
33763
34175
|
rudderExtensionPath: exported.rudderExtensionPath,
|
|
@@ -34256,7 +34668,7 @@ function parseResultValue(value) {
|
|
|
34256
34668
|
// src/commands/client/issue.ts
|
|
34257
34669
|
init_dist2();
|
|
34258
34670
|
import { readFile as readFile4, stat as stat3 } from "node:fs/promises";
|
|
34259
|
-
import
|
|
34671
|
+
import path17 from "node:path";
|
|
34260
34672
|
function registerIssueCommands(program) {
|
|
34261
34673
|
const issue = program.command("issue").description("Issue operations");
|
|
34262
34674
|
addCommonClientOptions(
|
|
@@ -34620,7 +35032,7 @@ async function readTextInputFile2(inputPath, optionName) {
|
|
|
34620
35032
|
if (inputPath === "-") {
|
|
34621
35033
|
return readStdinText2();
|
|
34622
35034
|
}
|
|
34623
|
-
const resolvedPath =
|
|
35035
|
+
const resolvedPath = path17.resolve(process.cwd(), inputPath);
|
|
34624
35036
|
return readFile4(resolvedPath, "utf8").catch((err) => {
|
|
34625
35037
|
throw new Error(`Unable to read ${optionName} ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
34626
35038
|
});
|
|
@@ -34677,14 +35089,14 @@ async function appendUploadedIssueImages(ctx, issueId, body, imagePaths) {
|
|
|
34677
35089
|
${imageBlock}` : imageBlock;
|
|
34678
35090
|
}
|
|
34679
35091
|
async function uploadIssueCommentImage(ctx, issue, imagePath) {
|
|
34680
|
-
const resolvedPath =
|
|
35092
|
+
const resolvedPath = path17.resolve(process.cwd(), imagePath);
|
|
34681
35093
|
const stats = await stat3(resolvedPath).catch((err) => {
|
|
34682
35094
|
throw new Error(`Unable to read image ${imagePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
34683
35095
|
});
|
|
34684
35096
|
if (!stats.isFile()) {
|
|
34685
35097
|
throw new Error(`Image path must be a file: ${imagePath}`);
|
|
34686
35098
|
}
|
|
34687
|
-
const filename =
|
|
35099
|
+
const filename = path17.basename(resolvedPath);
|
|
34688
35100
|
const contentType = inferCommentImageContentType(filename);
|
|
34689
35101
|
const buffer = await readFile4(resolvedPath);
|
|
34690
35102
|
if (buffer.length <= 0) {
|
|
@@ -34703,7 +35115,7 @@ async function uploadIssueCommentImage(ctx, issue, imagePath) {
|
|
|
34703
35115
|
return attachment;
|
|
34704
35116
|
}
|
|
34705
35117
|
function inferCommentImageContentType(filename) {
|
|
34706
|
-
const ext =
|
|
35118
|
+
const ext = path17.extname(filename).toLowerCase();
|
|
34707
35119
|
switch (ext) {
|
|
34708
35120
|
case ".png":
|
|
34709
35121
|
return "image/png";
|
|
@@ -34807,7 +35219,7 @@ function formatIssueSearchMatch(match) {
|
|
|
34807
35219
|
|
|
34808
35220
|
// src/commands/client/library.ts
|
|
34809
35221
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
34810
|
-
import
|
|
35222
|
+
import path18 from "node:path";
|
|
34811
35223
|
function toLibraryFileLinkResult(detail) {
|
|
34812
35224
|
return {
|
|
34813
35225
|
filePath: detail.filePath,
|
|
@@ -34952,7 +35364,7 @@ async function resolveBodyFileInput(inputPath) {
|
|
|
34952
35364
|
if (inputPath === "-") {
|
|
34953
35365
|
return readStdinText3();
|
|
34954
35366
|
}
|
|
34955
|
-
const resolvedPath =
|
|
35367
|
+
const resolvedPath = path18.resolve(process.cwd(), inputPath);
|
|
34956
35368
|
return readFile5(resolvedPath, "utf8").catch((err) => {
|
|
34957
35369
|
throw new Error(`Unable to read --body-file ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
34958
35370
|
});
|
|
@@ -35154,6 +35566,21 @@ function projectPath(projectRef, orgId) {
|
|
|
35154
35566
|
// src/commands/client/runs.ts
|
|
35155
35567
|
function registerRunsCommands(program) {
|
|
35156
35568
|
const runs = program.command("runs").description("Run debugging operations");
|
|
35569
|
+
addCommonClientOptions(
|
|
35570
|
+
runs.command("create").description(getAgentCliCapabilityById("runs.create").description).requiredOption("--task <text>", "Delegation task text").option("--target-agent-id <id>", "Same-organization target Agent; defaults to the current Agent").requiredOption("--idempotency-key <key>", "Stable key for safe replay").action(async (opts) => {
|
|
35571
|
+
try {
|
|
35572
|
+
const ctx = resolveCommandContext(opts);
|
|
35573
|
+
const row = await ctx.api.post("/api/agent-runs/delegation", {
|
|
35574
|
+
task: opts.task,
|
|
35575
|
+
...opts.targetAgentId ? { targetAgentId: opts.targetAgentId } : {},
|
|
35576
|
+
idempotencyKey: opts.idempotencyKey
|
|
35577
|
+
});
|
|
35578
|
+
printOutput(row, { json: ctx.json });
|
|
35579
|
+
} catch (err) {
|
|
35580
|
+
handleCommandError(err);
|
|
35581
|
+
}
|
|
35582
|
+
})
|
|
35583
|
+
);
|
|
35157
35584
|
addCommonClientOptions(
|
|
35158
35585
|
runs.command("list").description(getAgentCliCapabilityById("runs.list").description).option("-O, --org-id <id>", "Organization ID").option("--updated-after <iso>", "Only runs updated after this timestamp").option("--run-id-prefix <prefix>", "Filter by run ID prefix").option("--agent-id <id>", "Filter by agent ID").option("--status <status>", "Filter by run status").option("--runtime <type>", "Filter by runtime type").option("--issue-id <id>", "Filter by linked issue ID").option("--used-skill <key-or-name>", "Filter by skill actually used during the run").option("--loaded-skill <key-or-name>", "Filter by skill loaded for the run").option("--created-before <iso>", "Only runs created before this timestamp").option("--cursor <cursor>", "Stable summary cursor returned in page.nextCursor").option("--limit <n>", "Maximum rows; defaults to 50 summaries or 200 full rows").option("--full", "Use the legacy full-row list response for compatibility").addHelpText("after", formatExamplesAndCautions({
|
|
35159
35586
|
examples: [
|
|
@@ -35806,8 +36233,8 @@ function registerUserCommands(program) {
|
|
|
35806
36233
|
appendParam(params, "limit", opts.limit);
|
|
35807
36234
|
appendParam(params, "cursor", opts.cursor);
|
|
35808
36235
|
const query = params.toString();
|
|
35809
|
-
const
|
|
35810
|
-
const result = await ctx.api.get(
|
|
36236
|
+
const path26 = `/api/orgs/${ctx.orgId}/users/${encodeURIComponent(userId)}/activity-ledger${query ? `?${query}` : ""}`;
|
|
36237
|
+
const result = await ctx.api.get(path26);
|
|
35811
36238
|
if (ctx.json) {
|
|
35812
36239
|
printOutput(result, { json: true });
|
|
35813
36240
|
return;
|
|
@@ -36622,11 +37049,11 @@ init_run();
|
|
|
36622
37049
|
// src/commands/start.ts
|
|
36623
37050
|
import * as p15 from "@clack/prompts";
|
|
36624
37051
|
import { spawn as spawn3, spawnSync as spawnSync4 } from "node:child_process";
|
|
36625
|
-
import { createHash as
|
|
37052
|
+
import { createHash as createHash5, randomUUID } from "node:crypto";
|
|
36626
37053
|
import { constants as fsConstants, mkdirSync as mkdirSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
36627
37054
|
import { access, chmod as chmod2, copyFile, cp, lstat, mkdir as mkdir3, mkdtemp as mkdtemp2, readdir as readdir3, readFile as readFile6, rm as rm3, stat as stat4, utimes, writeFile as writeFile3 } from "node:fs/promises";
|
|
36628
37055
|
import { homedir, tmpdir } from "node:os";
|
|
36629
|
-
import
|
|
37056
|
+
import path24 from "node:path";
|
|
36630
37057
|
import { clearTimeout as clearTimeout3, setTimeout as setTimeout3 } from "node:timers";
|
|
36631
37058
|
import { setTimeout as delay2 } from "node:timers/promises";
|
|
36632
37059
|
import pc14 from "picocolors";
|
|
@@ -36654,10 +37081,10 @@ function parseChecksumFile(contents) {
|
|
|
36654
37081
|
init_home();
|
|
36655
37082
|
|
|
36656
37083
|
// src/desktop-download.ts
|
|
36657
|
-
import { createHash as
|
|
37084
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
36658
37085
|
import { createWriteStream as createWriteStream3, mkdirSync } from "node:fs";
|
|
36659
37086
|
import { rm as rm2 } from "node:fs/promises";
|
|
36660
|
-
import
|
|
37087
|
+
import path23 from "node:path";
|
|
36661
37088
|
import { Readable as Readable2, Transform as Transform2 } from "node:stream";
|
|
36662
37089
|
import { pipeline as pipeline3 } from "node:stream/promises";
|
|
36663
37090
|
import { clearTimeout as clearTimeout2, setTimeout as setTimeout2 } from "node:timers";
|
|
@@ -36897,7 +37324,7 @@ async function resolveDesktopDownloadOrigins(options) {
|
|
|
36897
37324
|
}
|
|
36898
37325
|
async function downloadAsset(asset, outputDir, progressFactory = createByteProgress, expectedChecksum, timeouts = {}) {
|
|
36899
37326
|
mkdirSync(outputDir, { recursive: true });
|
|
36900
|
-
const outputPath =
|
|
37327
|
+
const outputPath = path23.join(outputDir, path23.basename(asset.name));
|
|
36901
37328
|
const idleTimeoutMs = timeouts.idleMs ?? DESKTOP_ASSET_IDLE_TIMEOUT_MS;
|
|
36902
37329
|
const responseTimeoutMs = timeouts.responseMs ?? DESKTOP_ASSET_RESPONSE_TIMEOUT_MS;
|
|
36903
37330
|
const failures = [];
|
|
@@ -36917,7 +37344,7 @@ async function downloadAsset(asset, outputDir, progressFactory = createByteProgr
|
|
|
36917
37344
|
const totalBytes = contentLengthFromHeaders(response.headers);
|
|
36918
37345
|
progress = progressFactory(`Downloading ${asset.name}`);
|
|
36919
37346
|
let receivedBytes = 0;
|
|
36920
|
-
const hash =
|
|
37347
|
+
const hash = createHash4("sha256");
|
|
36921
37348
|
let monitor;
|
|
36922
37349
|
const armIdleTimeout = () => {
|
|
36923
37350
|
if (idleTimeout) clearTimeout2(idleTimeout);
|
|
@@ -37233,38 +37660,38 @@ function resolveDesktopAssetTarget(platform = process.platform, arch = process.a
|
|
|
37233
37660
|
throw new Error(`Rudder Desktop does not publish portable assets for ${platform}.`);
|
|
37234
37661
|
}
|
|
37235
37662
|
function resolveDefaultDesktopInstallRoot(target, env = process.env, homeDir = homedir()) {
|
|
37236
|
-
if (target.platform === "macos") return
|
|
37663
|
+
if (target.platform === "macos") return path24.join(homeDir, "Applications");
|
|
37237
37664
|
if (target.platform === "windows") {
|
|
37238
|
-
const localAppData = env.LOCALAPPDATA?.trim() ||
|
|
37239
|
-
return
|
|
37665
|
+
const localAppData = env.LOCALAPPDATA?.trim() || path24.join(homeDir, "AppData", "Local");
|
|
37666
|
+
return path24.join(localAppData, "Programs", DESKTOP_APP_NAME);
|
|
37240
37667
|
}
|
|
37241
|
-
return
|
|
37668
|
+
return path24.join(homeDir, ".local", "share", "rudder");
|
|
37242
37669
|
}
|
|
37243
37670
|
function resolveDesktopInstallPaths(target, installRoot) {
|
|
37244
|
-
const root =
|
|
37671
|
+
const root = path24.resolve(installRoot);
|
|
37245
37672
|
if (target.platform === "macos") {
|
|
37246
|
-
const appPath2 =
|
|
37673
|
+
const appPath2 = path24.join(root, `${DESKTOP_APP_NAME}.app`);
|
|
37247
37674
|
return {
|
|
37248
37675
|
installRoot: root,
|
|
37249
37676
|
appPath: appPath2,
|
|
37250
|
-
executablePath:
|
|
37251
|
-
metadataPath:
|
|
37677
|
+
executablePath: path24.join(appPath2, "Contents", "MacOS", DESKTOP_APP_NAME),
|
|
37678
|
+
metadataPath: path24.join(root, DESKTOP_METADATA_FILE)
|
|
37252
37679
|
};
|
|
37253
37680
|
}
|
|
37254
37681
|
if (target.platform === "windows") {
|
|
37255
37682
|
return {
|
|
37256
37683
|
installRoot: root,
|
|
37257
37684
|
appPath: root,
|
|
37258
|
-
executablePath:
|
|
37259
|
-
metadataPath:
|
|
37685
|
+
executablePath: path24.join(root, `${DESKTOP_APP_NAME}.exe`),
|
|
37686
|
+
metadataPath: path24.join(root, DESKTOP_METADATA_FILE)
|
|
37260
37687
|
};
|
|
37261
37688
|
}
|
|
37262
|
-
const appPath =
|
|
37689
|
+
const appPath = path24.join(root, `${DESKTOP_APP_NAME}.AppImage`);
|
|
37263
37690
|
return {
|
|
37264
37691
|
installRoot: root,
|
|
37265
37692
|
appPath,
|
|
37266
37693
|
executablePath: appPath,
|
|
37267
|
-
metadataPath:
|
|
37694
|
+
metadataPath: path24.join(root, DESKTOP_METADATA_FILE)
|
|
37268
37695
|
};
|
|
37269
37696
|
}
|
|
37270
37697
|
function normalizeAssetName(name) {
|
|
@@ -37447,21 +37874,21 @@ function buildGithubReleaseAsset(repo, tag, assetName, downloadBaseUrl) {
|
|
|
37447
37874
|
};
|
|
37448
37875
|
}
|
|
37449
37876
|
function checksumForFile(filePath) {
|
|
37450
|
-
const hash =
|
|
37877
|
+
const hash = createHash5("sha256");
|
|
37451
37878
|
hash.update(readFileSync2(filePath));
|
|
37452
37879
|
return hash.digest("hex");
|
|
37453
37880
|
}
|
|
37454
37881
|
function resolveAssetChecksum(checksums, assetName) {
|
|
37455
|
-
const expected = checksums.get(
|
|
37882
|
+
const expected = checksums.get(path24.basename(assetName));
|
|
37456
37883
|
if (!expected) {
|
|
37457
|
-
throw new Error(`Desktop release checksums do not include ${
|
|
37884
|
+
throw new Error(`Desktop release checksums do not include ${path24.basename(assetName)}.`);
|
|
37458
37885
|
}
|
|
37459
37886
|
return expected;
|
|
37460
37887
|
}
|
|
37461
37888
|
function assertChecksumMatch(filePath, expected) {
|
|
37462
37889
|
const actual = checksumForFile(filePath);
|
|
37463
37890
|
if (actual !== expected.toLowerCase()) {
|
|
37464
|
-
throw new Error(`Checksum mismatch for ${
|
|
37891
|
+
throw new Error(`Checksum mismatch for ${path24.basename(filePath)}.`);
|
|
37465
37892
|
}
|
|
37466
37893
|
return actual;
|
|
37467
37894
|
}
|
|
@@ -37480,10 +37907,10 @@ function normalizeDesktopAssetChecksum(checksum) {
|
|
|
37480
37907
|
return normalized;
|
|
37481
37908
|
}
|
|
37482
37909
|
function resolveDesktopAssetCacheDir(assetChecksum, homeDir = resolveRudderHomeDir()) {
|
|
37483
|
-
return
|
|
37910
|
+
return path24.join(homeDir, DESKTOP_ASSET_CACHE_DIR, normalizeDesktopAssetChecksum(assetChecksum));
|
|
37484
37911
|
}
|
|
37485
37912
|
function resolveDesktopCachedAssetPath(assetName, assetChecksum, homeDir = resolveRudderHomeDir()) {
|
|
37486
|
-
return
|
|
37913
|
+
return path24.join(resolveDesktopAssetCacheDir(assetChecksum, homeDir), path24.basename(assetName));
|
|
37487
37914
|
}
|
|
37488
37915
|
async function pruneDesktopAssetCache(options = {}) {
|
|
37489
37916
|
const homeDir = options.homeDir ?? resolveRudderHomeDir();
|
|
@@ -37529,7 +37956,7 @@ async function maybePruneDesktopAssetCache(options) {
|
|
|
37529
37956
|
return result.deleted.length > 0 || result.warnings.length > 0 ? result : null;
|
|
37530
37957
|
}
|
|
37531
37958
|
async function scanDesktopAssetCacheEntries(homeDir) {
|
|
37532
|
-
const cacheRoot =
|
|
37959
|
+
const cacheRoot = path24.join(homeDir, DESKTOP_ASSET_CACHE_DIR);
|
|
37533
37960
|
const dirents = await readdir3(cacheRoot, { withFileTypes: true }).catch(() => null);
|
|
37534
37961
|
if (!dirents) return [];
|
|
37535
37962
|
const entries = [];
|
|
@@ -37541,7 +37968,7 @@ async function scanDesktopAssetCacheEntries(homeDir) {
|
|
|
37541
37968
|
} catch {
|
|
37542
37969
|
continue;
|
|
37543
37970
|
}
|
|
37544
|
-
const cacheDir =
|
|
37971
|
+
const cacheDir = path24.join(cacheRoot, dirent.name);
|
|
37545
37972
|
const stats = await desktopCacheDirectoryStats(cacheDir);
|
|
37546
37973
|
entries.push({
|
|
37547
37974
|
cacheDir,
|
|
@@ -37565,7 +37992,7 @@ async function desktopCacheDirectoryStats(targetPath) {
|
|
|
37565
37992
|
let lastUsedAtMs = Number(fallbackStat?.mtimeMs ?? 0);
|
|
37566
37993
|
for (const dirent of dirents) {
|
|
37567
37994
|
if (dirent.isSymbolicLink()) continue;
|
|
37568
|
-
const entryPath =
|
|
37995
|
+
const entryPath = path24.join(targetPath, dirent.name);
|
|
37569
37996
|
const entryStat = await stat4(entryPath).catch(() => null);
|
|
37570
37997
|
if (!entryStat) continue;
|
|
37571
37998
|
lastUsedAtMs = Math.max(lastUsedAtMs, Number(entryStat.mtimeMs ?? 0));
|
|
@@ -37642,13 +38069,13 @@ async function downloadDesktopAssetWithCache(asset, expectedChecksum, options =
|
|
|
37642
38069
|
await rm3(cachePath, { force: true });
|
|
37643
38070
|
}
|
|
37644
38071
|
}
|
|
37645
|
-
const outputDir = options.outputDir ?? await mkdtemp2(
|
|
38072
|
+
const outputDir = options.outputDir ?? await mkdtemp2(path24.join(tmpdir(), "rudder-desktop-installer."));
|
|
37646
38073
|
const removeOutputDir = options.outputDir ? false : true;
|
|
37647
38074
|
try {
|
|
37648
38075
|
const downloadedPath = await downloadAsset(asset, outputDir, options.progressFactory, normalizedChecksum);
|
|
37649
38076
|
const checksum = assertChecksumMatch(downloadedPath, normalizedChecksum);
|
|
37650
|
-
await mkdir3(
|
|
37651
|
-
if (
|
|
38077
|
+
await mkdir3(path24.dirname(cachePath), { recursive: true });
|
|
38078
|
+
if (path24.resolve(downloadedPath) !== path24.resolve(cachePath)) {
|
|
37652
38079
|
await copyFile(downloadedPath, cachePath);
|
|
37653
38080
|
}
|
|
37654
38081
|
return { path: cachePath, checksum, cacheStatus: "miss" };
|
|
@@ -37665,8 +38092,8 @@ async function pathExists2(targetPath) {
|
|
|
37665
38092
|
}
|
|
37666
38093
|
}
|
|
37667
38094
|
function resolveDesktopInstallLockPath(paths) {
|
|
37668
|
-
const installRootHash =
|
|
37669
|
-
return
|
|
38095
|
+
const installRootHash = createHash5("sha256").update(path24.resolve(paths.installRoot)).digest("hex").slice(0, 16);
|
|
38096
|
+
return path24.join(path24.dirname(paths.appPath), `.rudder-desktop-install-${installRootHash}.lock`);
|
|
37670
38097
|
}
|
|
37671
38098
|
async function readDesktopInstallLock(lockPath) {
|
|
37672
38099
|
try {
|
|
@@ -37686,14 +38113,14 @@ async function readDesktopInstallLock(lockPath) {
|
|
|
37686
38113
|
}
|
|
37687
38114
|
async function withDesktopInstallLock(paths, fn, options = {}) {
|
|
37688
38115
|
const lockPath = resolveDesktopInstallLockPath(paths);
|
|
37689
|
-
const lockDir =
|
|
38116
|
+
const lockDir = path24.dirname(lockPath);
|
|
37690
38117
|
const timeoutMs = options.timeoutMs ?? DESKTOP_INSTALL_LOCK_TIMEOUT_MS;
|
|
37691
38118
|
const pollMs = options.pollMs ?? DESKTOP_INSTALL_LOCK_POLL_MS;
|
|
37692
38119
|
const startedAt = Date.now();
|
|
37693
38120
|
const payload = {
|
|
37694
38121
|
lockId: randomUUID(),
|
|
37695
38122
|
pid: process.pid,
|
|
37696
|
-
installRoot:
|
|
38123
|
+
installRoot: path24.resolve(paths.installRoot),
|
|
37697
38124
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
37698
38125
|
};
|
|
37699
38126
|
await mkdir3(lockDir, { recursive: true });
|
|
@@ -37769,7 +38196,7 @@ async function findPath(root, predicate, maxDepth = 5) {
|
|
|
37769
38196
|
async function visit(dir, depth) {
|
|
37770
38197
|
const entries = await readdir3(dir, { withFileTypes: true });
|
|
37771
38198
|
for (const entry of entries) {
|
|
37772
|
-
const fullPath =
|
|
38199
|
+
const fullPath = path24.join(dir, entry.name);
|
|
37773
38200
|
if (predicate(fullPath, entry.isDirectory())) return fullPath;
|
|
37774
38201
|
if (entry.isDirectory() && depth < maxDepth) {
|
|
37775
38202
|
const nested = await visit(fullPath, depth + 1);
|
|
@@ -37781,18 +38208,18 @@ async function findPath(root, predicate, maxDepth = 5) {
|
|
|
37781
38208
|
return await visit(root, 0);
|
|
37782
38209
|
}
|
|
37783
38210
|
async function findMacApp(extractDir) {
|
|
37784
|
-
const direct =
|
|
38211
|
+
const direct = path24.join(extractDir, `${DESKTOP_APP_NAME}.app`);
|
|
37785
38212
|
if (await pathExists2(direct)) return direct;
|
|
37786
|
-
const found = await findPath(extractDir, (filePath, isDirectory) => isDirectory &&
|
|
38213
|
+
const found = await findPath(extractDir, (filePath, isDirectory) => isDirectory && path24.basename(filePath) === `${DESKTOP_APP_NAME}.app`);
|
|
37787
38214
|
if (!found) throw new Error(`Portable macOS archive did not contain ${DESKTOP_APP_NAME}.app.`);
|
|
37788
38215
|
return found;
|
|
37789
38216
|
}
|
|
37790
38217
|
async function findWindowsAppDir(extractDir) {
|
|
37791
|
-
const direct =
|
|
38218
|
+
const direct = path24.join(extractDir, `${DESKTOP_APP_NAME}.exe`);
|
|
37792
38219
|
if (await pathExists2(direct)) return extractDir;
|
|
37793
|
-
const executable = await findPath(extractDir, (filePath, isDirectory) => !isDirectory &&
|
|
38220
|
+
const executable = await findPath(extractDir, (filePath, isDirectory) => !isDirectory && path24.basename(filePath).toLowerCase() === `${DESKTOP_APP_NAME.toLowerCase()}.exe`);
|
|
37794
38221
|
if (!executable) throw new Error(`Portable Windows archive did not contain ${DESKTOP_APP_NAME}.exe.`);
|
|
37795
|
-
return
|
|
38222
|
+
return path24.dirname(executable);
|
|
37796
38223
|
}
|
|
37797
38224
|
async function readInstallMetadata(metadataPath) {
|
|
37798
38225
|
try {
|
|
@@ -37860,7 +38287,7 @@ async function waitForUpdateQuitResponse(responsePath, timeoutMs = 8e3) {
|
|
|
37860
38287
|
}
|
|
37861
38288
|
async function requestDesktopQuit(executablePath, target, options = {}) {
|
|
37862
38289
|
if (!await pathExists2(executablePath)) return { ok: true, status: "not_running" };
|
|
37863
|
-
const responsePath =
|
|
38290
|
+
const responsePath = path24.join(tmpdir(), `rudder-update-quit-${process.pid}-${Date.now()}.json`);
|
|
37864
38291
|
const result = spawnSync4(executablePath, [
|
|
37865
38292
|
`${DESKTOP_UPDATE_QUIT_ARG}=${responsePath}`,
|
|
37866
38293
|
...options.forceUpdate ? [DESKTOP_UPDATE_FORCE_ARG] : []
|
|
@@ -38024,7 +38451,7 @@ async function installPortableDesktop(installerPath, paths, target) {
|
|
|
38024
38451
|
await chmod2(paths.appPath, 493);
|
|
38025
38452
|
return;
|
|
38026
38453
|
}
|
|
38027
|
-
const extractDir = await mkdtemp2(
|
|
38454
|
+
const extractDir = await mkdtemp2(path24.join(tmpdir(), "rudder-desktop-extract."));
|
|
38028
38455
|
try {
|
|
38029
38456
|
await extractZip(installerPath, extractDir, target);
|
|
38030
38457
|
if (target.platform === "macos") {
|
|
@@ -38033,7 +38460,7 @@ async function installPortableDesktop(installerPath, paths, target) {
|
|
|
38033
38460
|
return;
|
|
38034
38461
|
}
|
|
38035
38462
|
const appSource = await findWindowsAppDir(extractDir);
|
|
38036
|
-
await mkdir3(
|
|
38463
|
+
await mkdir3(path24.dirname(paths.installRoot), { recursive: true });
|
|
38037
38464
|
await copyPortableAppBundle(appSource, paths.installRoot);
|
|
38038
38465
|
} finally {
|
|
38039
38466
|
await rm3(extractDir, { recursive: true, force: true });
|
|
@@ -38074,12 +38501,12 @@ function buildLinuxDesktopEntry(executablePath) {
|
|
|
38074
38501
|
].join("\n");
|
|
38075
38502
|
}
|
|
38076
38503
|
async function writeLinuxLaunchers(paths) {
|
|
38077
|
-
const desktopDir =
|
|
38504
|
+
const desktopDir = path24.join(homedir(), ".local", "share", "applications");
|
|
38078
38505
|
await mkdir3(desktopDir, { recursive: true });
|
|
38079
|
-
await writeFile3(
|
|
38080
|
-
const binDir =
|
|
38506
|
+
await writeFile3(path24.join(desktopDir, "rudder.desktop"), buildLinuxDesktopEntry(paths.executablePath), "utf8");
|
|
38507
|
+
const binDir = path24.join(homedir(), ".local", "bin");
|
|
38081
38508
|
await mkdir3(binDir, { recursive: true });
|
|
38082
|
-
const wrapperPath =
|
|
38509
|
+
const wrapperPath = path24.join(binDir, "rudder-desktop");
|
|
38083
38510
|
const escaped = paths.executablePath.replaceAll("'", `'"'"'`);
|
|
38084
38511
|
await writeFile3(wrapperPath, `#!/bin/sh
|
|
38085
38512
|
exec '${escaped}' "$@"
|
|
@@ -38087,13 +38514,13 @@ exec '${escaped}' "$@"
|
|
|
38087
38514
|
await chmod2(wrapperPath, 493);
|
|
38088
38515
|
}
|
|
38089
38516
|
function buildWindowsShortcutScript(executablePath) {
|
|
38090
|
-
const appData = process.env.APPDATA?.trim() ||
|
|
38091
|
-
const shortcutPath =
|
|
38517
|
+
const appData = process.env.APPDATA?.trim() || path24.join(homedir(), "AppData", "Roaming");
|
|
38518
|
+
const shortcutPath = path24.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Rudder.lnk");
|
|
38092
38519
|
return [
|
|
38093
38520
|
"$shell = New-Object -ComObject WScript.Shell",
|
|
38094
38521
|
`$shortcut = $shell.CreateShortcut(${powershellQuote(shortcutPath)})`,
|
|
38095
38522
|
`$shortcut.TargetPath = ${powershellQuote(executablePath)}`,
|
|
38096
|
-
`$shortcut.WorkingDirectory = ${powershellQuote(
|
|
38523
|
+
`$shortcut.WorkingDirectory = ${powershellQuote(path24.dirname(executablePath))}`,
|
|
38097
38524
|
"$shortcut.Save()"
|
|
38098
38525
|
].join("; ");
|
|
38099
38526
|
}
|
|
@@ -38125,7 +38552,7 @@ function launchDesktop(paths, target) {
|
|
|
38125
38552
|
spawn3(paths.executablePath, [], { detached: true, stdio: "ignore" }).unref();
|
|
38126
38553
|
}
|
|
38127
38554
|
async function writeInstallMetadata(paths, releaseTag, assetName, assetChecksum, assetKind = "full") {
|
|
38128
|
-
mkdirSync2(
|
|
38555
|
+
mkdirSync2(path24.dirname(paths.metadataPath), { recursive: true });
|
|
38129
38556
|
const metadata = {
|
|
38130
38557
|
version: 1,
|
|
38131
38558
|
releaseTag,
|
|
@@ -38181,7 +38608,7 @@ async function startCommand(opts) {
|
|
|
38181
38608
|
if (!exactDesktopAssetPath || !exactDesktopAssetChecksum || !exactDesktopAssetName || !exactDesktopReleaseDigest) {
|
|
38182
38609
|
throw new Error("Exact Desktop asset mode requires path, checksum, asset name, and release digest.");
|
|
38183
38610
|
}
|
|
38184
|
-
if (!
|
|
38611
|
+
if (!path24.isAbsolute(exactDesktopAssetPath) || exactDesktopAssetName.includes("/") || !/^[a-f0-9]{64}$/iu.test(exactDesktopAssetChecksum) || !/^[a-f0-9]{64}$/iu.test(exactDesktopReleaseDigest)) {
|
|
38185
38612
|
throw new Error("Exact Desktop asset mode received invalid candidate identity.");
|
|
38186
38613
|
}
|
|
38187
38614
|
if (opts.desktopAssetKind && opts.desktopAssetKind !== "full" && opts.desktopAssetKind !== "shell") {
|
|
@@ -38295,9 +38722,9 @@ async function startCommand(opts) {
|
|
|
38295
38722
|
const smokeReleaseBaseUrls = resolveDesktopSmokeReleaseBaseUrls();
|
|
38296
38723
|
const target = resolveDesktopAssetTarget();
|
|
38297
38724
|
const tag = resolveDesktopReleaseTag(version);
|
|
38298
|
-
const installRoot = opts.desktopInstallDir ?
|
|
38725
|
+
const installRoot = opts.desktopInstallDir ? path24.resolve(opts.desktopInstallDir) : resolveDefaultDesktopInstallRoot(target);
|
|
38299
38726
|
const installPaths = resolveDesktopInstallPaths(target, installRoot);
|
|
38300
|
-
const outputDir = opts.outputDir ?
|
|
38727
|
+
const outputDir = opts.outputDir ? path24.resolve(opts.outputDir) : await mkdtemp2(path24.join(tmpdir(), "rudder-desktop-installer."));
|
|
38301
38728
|
p15.log.step("Installing desktop app");
|
|
38302
38729
|
p15.log.message(`Release: ${pc14.cyan(`${repo}@${tag}`)}`);
|
|
38303
38730
|
p15.log.message(`Target: ${pc14.cyan(`${target.platform}/${target.arch}`)}`);
|
|
@@ -38326,7 +38753,7 @@ async function startCommand(opts) {
|
|
|
38326
38753
|
};
|
|
38327
38754
|
selectedAssetKind = opts.desktopAssetKind ?? "full";
|
|
38328
38755
|
expectedChecksum = normalizeDesktopAssetChecksum(exactDesktopAssetChecksum);
|
|
38329
|
-
const computedReleaseDigest =
|
|
38756
|
+
const computedReleaseDigest = createHash5("sha256").update(JSON.stringify({
|
|
38330
38757
|
releaseTag,
|
|
38331
38758
|
assetName: selectedAsset.name,
|
|
38332
38759
|
assetChecksum: expectedChecksum,
|
|
@@ -38343,7 +38770,7 @@ async function startCommand(opts) {
|
|
|
38343
38770
|
if (linkDescriptor.isSymbolicLink()) throw new Error("Exact Desktop asset must not be a symbolic link.");
|
|
38344
38771
|
const checksum = await runStartPhase(
|
|
38345
38772
|
"Verifying staged Desktop checksum...",
|
|
38346
|
-
`Verified ${pc14.cyan(
|
|
38773
|
+
`Verified ${pc14.cyan(path24.basename(exactDesktopAssetPath))}.`,
|
|
38347
38774
|
() => assertChecksumMatch(exactDesktopAssetPath, expectedChecksum),
|
|
38348
38775
|
desktopProgressJson ? "verifying_checksum" : null
|
|
38349
38776
|
);
|
|
@@ -38462,7 +38889,7 @@ async function startCommand(opts) {
|
|
|
38462
38889
|
}
|
|
38463
38890
|
const checksum = await runStartPhase(
|
|
38464
38891
|
"Verifying Desktop checksum...",
|
|
38465
|
-
`Verified ${pc14.cyan(
|
|
38892
|
+
`Verified ${pc14.cyan(path24.basename(verifiedAsset.path))}.`,
|
|
38466
38893
|
() => assertChecksumMatch(verifiedAsset.path, expectedChecksum),
|
|
38467
38894
|
desktopProgressJson ? "verifying_checksum" : null
|
|
38468
38895
|
);
|
|
@@ -38474,9 +38901,9 @@ async function startCommand(opts) {
|
|
|
38474
38901
|
assetName: selectedAsset.name,
|
|
38475
38902
|
assetChecksum: checksum,
|
|
38476
38903
|
assetKind: selectedAssetKind,
|
|
38477
|
-
stagedArtifactPath:
|
|
38904
|
+
stagedArtifactPath: path24.resolve(verifiedAsset.path),
|
|
38478
38905
|
stagedArtifactDigest: checksum,
|
|
38479
|
-
releaseDigest:
|
|
38906
|
+
releaseDigest: createHash5("sha256").update(JSON.stringify({
|
|
38480
38907
|
releaseTag,
|
|
38481
38908
|
assetName: selectedAsset.name,
|
|
38482
38909
|
assetChecksum: checksum,
|
|
@@ -38567,11 +38994,11 @@ async function startCommand(opts) {
|
|
|
38567
38994
|
|
|
38568
38995
|
// src/config/data-dir.ts
|
|
38569
38996
|
init_home();
|
|
38570
|
-
import
|
|
38997
|
+
import path25 from "node:path";
|
|
38571
38998
|
function applyDataDirOverride(options, support = {}) {
|
|
38572
38999
|
const rawDataDir = options.dataDir?.trim();
|
|
38573
39000
|
if (!rawDataDir) return null;
|
|
38574
|
-
const resolvedDataDir =
|
|
39001
|
+
const resolvedDataDir = path25.resolve(expandHomePrefix(rawDataDir));
|
|
38575
39002
|
process.env.RUDDER_HOME = resolvedDataDir;
|
|
38576
39003
|
if (support.hasConfigOption) {
|
|
38577
39004
|
const hasConfigOverride = Boolean(options.config?.trim()) || Boolean(process.env.RUDDER_CONFIG?.trim());
|