@rudderhq/cli 0.2.0-canary.13 → 0.2.0-canary.15
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 +228 -142
- package/dist/index.js.map +3 -3
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -122,7 +122,7 @@ var init_constants = __esm({
|
|
|
122
122
|
"routing_suggestion",
|
|
123
123
|
"system_event"
|
|
124
124
|
];
|
|
125
|
-
CHAT_MESSAGE_STATUSES = ["completed", "stopped", "failed"];
|
|
125
|
+
CHAT_MESSAGE_STATUSES = ["streaming", "completed", "stopped", "failed", "interrupted"];
|
|
126
126
|
CHAT_CONTEXT_ENTITY_TYPES = ["issue", "project", "agent"];
|
|
127
127
|
GOAL_LEVELS = ["organization", "team", "agent", "task"];
|
|
128
128
|
GOAL_STATUSES = ["planned", "active", "achieved", "cancelled"];
|
|
@@ -7696,8 +7696,8 @@ function pruneOldBackups(backupDir, retentionDays, filenamePrefix) {
|
|
|
7696
7696
|
for (const name of readdirSync(backupDir)) {
|
|
7697
7697
|
if (!name.startsWith(`${filenamePrefix}-`) || !name.endsWith(".sql")) continue;
|
|
7698
7698
|
const fullPath = resolve2(backupDir, name);
|
|
7699
|
-
const
|
|
7700
|
-
if (
|
|
7699
|
+
const stat3 = statSync(fullPath);
|
|
7700
|
+
if (stat3.mtimeMs < cutoff) {
|
|
7701
7701
|
unlinkSync(fullPath);
|
|
7702
7702
|
pruned++;
|
|
7703
7703
|
}
|
|
@@ -11391,8 +11391,8 @@ function printItemCompleted(item) {
|
|
|
11391
11391
|
const changes = Array.isArray(item.changes) ? item.changes : [];
|
|
11392
11392
|
const entries = changes.map((changeRaw) => asRecord(changeRaw)).filter((change) => Boolean(change)).map((change) => {
|
|
11393
11393
|
const kind = asString(change.kind, "update");
|
|
11394
|
-
const
|
|
11395
|
-
return `${kind} ${
|
|
11394
|
+
const path24 = asString(change.path, "unknown");
|
|
11395
|
+
return `${kind} ${path24}`;
|
|
11396
11396
|
});
|
|
11397
11397
|
const preview = entries.length > 0 ? entries.slice(0, 6).join(", ") : "none";
|
|
11398
11398
|
const more = entries.length > 6 ? ` (+${entries.length - 6} more)` : "";
|
|
@@ -12573,40 +12573,46 @@ var RudderApiClient = class {
|
|
|
12573
12573
|
this.runId = opts.runId?.trim() || void 0;
|
|
12574
12574
|
this.recoverAuth = opts.recoverAuth;
|
|
12575
12575
|
}
|
|
12576
|
-
get(
|
|
12577
|
-
return this.request(
|
|
12576
|
+
get(path24, opts) {
|
|
12577
|
+
return this.request(path24, { method: "GET" }, opts);
|
|
12578
12578
|
}
|
|
12579
|
-
post(
|
|
12580
|
-
return this.request(
|
|
12579
|
+
post(path24, body, opts) {
|
|
12580
|
+
return this.request(path24, {
|
|
12581
12581
|
method: "POST",
|
|
12582
12582
|
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
12583
12583
|
}, opts);
|
|
12584
12584
|
}
|
|
12585
|
-
|
|
12586
|
-
return this.request(
|
|
12585
|
+
postForm(path24, form, opts) {
|
|
12586
|
+
return this.request(path24, {
|
|
12587
|
+
method: "POST",
|
|
12588
|
+
body: form
|
|
12589
|
+
}, opts);
|
|
12590
|
+
}
|
|
12591
|
+
patch(path24, body, opts) {
|
|
12592
|
+
return this.request(path24, {
|
|
12587
12593
|
method: "PATCH",
|
|
12588
12594
|
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
12589
12595
|
}, opts);
|
|
12590
12596
|
}
|
|
12591
|
-
put(
|
|
12592
|
-
return this.request(
|
|
12597
|
+
put(path24, body, opts) {
|
|
12598
|
+
return this.request(path24, {
|
|
12593
12599
|
method: "PUT",
|
|
12594
12600
|
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
12595
12601
|
}, opts);
|
|
12596
12602
|
}
|
|
12597
|
-
delete(
|
|
12598
|
-
return this.request(
|
|
12603
|
+
delete(path24, opts) {
|
|
12604
|
+
return this.request(path24, { method: "DELETE" }, opts);
|
|
12599
12605
|
}
|
|
12600
12606
|
setApiKey(apiKey) {
|
|
12601
12607
|
this.apiKey = apiKey?.trim() || void 0;
|
|
12602
12608
|
}
|
|
12603
|
-
async request(
|
|
12604
|
-
const url = buildUrl(this.apiBase,
|
|
12609
|
+
async request(path24, init, opts, hasRetriedAuth = false) {
|
|
12610
|
+
const url = buildUrl(this.apiBase, path24);
|
|
12605
12611
|
const headers = {
|
|
12606
12612
|
accept: "application/json",
|
|
12607
12613
|
...toStringRecord(init.headers)
|
|
12608
12614
|
};
|
|
12609
|
-
if (init.body
|
|
12615
|
+
if (typeof init.body === "string") {
|
|
12610
12616
|
headers["content-type"] = headers["content-type"] ?? "application/json";
|
|
12611
12617
|
}
|
|
12612
12618
|
if (this.apiKey) {
|
|
@@ -12626,13 +12632,13 @@ var RudderApiClient = class {
|
|
|
12626
12632
|
const apiError = await toApiError(response);
|
|
12627
12633
|
if (!hasRetriedAuth && this.recoverAuth) {
|
|
12628
12634
|
const recoveredToken = await this.recoverAuth({
|
|
12629
|
-
path:
|
|
12635
|
+
path: path24,
|
|
12630
12636
|
method: String(init.method ?? "GET").toUpperCase(),
|
|
12631
12637
|
error: apiError
|
|
12632
12638
|
});
|
|
12633
12639
|
if (recoveredToken) {
|
|
12634
12640
|
this.setApiKey(recoveredToken);
|
|
12635
|
-
return this.request(
|
|
12641
|
+
return this.request(path24, init, opts, true);
|
|
12636
12642
|
}
|
|
12637
12643
|
}
|
|
12638
12644
|
throw apiError;
|
|
@@ -12651,8 +12657,8 @@ function shouldAttachRunId(method) {
|
|
|
12651
12657
|
const normalized = String(method ?? "GET").toUpperCase();
|
|
12652
12658
|
return normalized !== "GET" && normalized !== "HEAD";
|
|
12653
12659
|
}
|
|
12654
|
-
function buildUrl(apiBase,
|
|
12655
|
-
const normalizedPath =
|
|
12660
|
+
function buildUrl(apiBase, path24) {
|
|
12661
|
+
const normalizedPath = path24.startsWith("/") ? path24 : `/${path24}`;
|
|
12656
12662
|
const [pathname, query] = normalizedPath.split("?");
|
|
12657
12663
|
const url = new URL2(apiBase);
|
|
12658
12664
|
url.pathname = `${url.pathname.replace(/\/+$/, "")}${pathname}`;
|
|
@@ -14499,6 +14505,8 @@ ${organizationUrl}`);
|
|
|
14499
14505
|
|
|
14500
14506
|
// src/commands/client/issue.ts
|
|
14501
14507
|
init_src();
|
|
14508
|
+
import { readFile as readFile5, stat as stat2 } from "node:fs/promises";
|
|
14509
|
+
import path16 from "node:path";
|
|
14502
14510
|
|
|
14503
14511
|
// src/agent-v1-registry.ts
|
|
14504
14512
|
var AGENT_CLI_CAPABILITIES = [
|
|
@@ -14684,9 +14692,9 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
14684
14692
|
},
|
|
14685
14693
|
{
|
|
14686
14694
|
id: "issue.comment",
|
|
14687
|
-
command: "rudder issue comment <issue> --body <text>",
|
|
14695
|
+
command: "rudder issue comment <issue> --body <text> [--image <path>]",
|
|
14688
14696
|
category: "issue",
|
|
14689
|
-
description: "Add a comment to an issue.",
|
|
14697
|
+
description: "Add a comment to an issue, optionally uploading images and appending Markdown image links.",
|
|
14690
14698
|
mutating: true,
|
|
14691
14699
|
contract: "agent-v1",
|
|
14692
14700
|
requiresOrgId: false,
|
|
@@ -14720,9 +14728,9 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
14720
14728
|
},
|
|
14721
14729
|
{
|
|
14722
14730
|
id: "issue.update",
|
|
14723
|
-
command: "rudder issue update <issue> ...",
|
|
14731
|
+
command: "rudder issue update <issue> ... [--image <path>]",
|
|
14724
14732
|
category: "issue",
|
|
14725
|
-
description: "Apply generic issue updates when workflow commands are not enough.",
|
|
14733
|
+
description: "Apply generic issue updates when workflow commands are not enough, optionally uploading images for the update comment.",
|
|
14726
14734
|
mutating: true,
|
|
14727
14735
|
contract: "agent-v1",
|
|
14728
14736
|
requiresOrgId: false,
|
|
@@ -14744,9 +14752,9 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
14744
14752
|
},
|
|
14745
14753
|
{
|
|
14746
14754
|
id: "issue.done",
|
|
14747
|
-
command: "rudder issue done <issue> --comment <text>",
|
|
14755
|
+
command: "rudder issue done <issue> --comment <text> [--image <path>]",
|
|
14748
14756
|
category: "issue",
|
|
14749
|
-
description: "Mark an issue done with a required completion comment.",
|
|
14757
|
+
description: "Mark an issue done with a required completion comment, optionally uploading images.",
|
|
14750
14758
|
mutating: true,
|
|
14751
14759
|
contract: "agent-v1",
|
|
14752
14760
|
requiresOrgId: false,
|
|
@@ -14756,9 +14764,9 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
14756
14764
|
},
|
|
14757
14765
|
{
|
|
14758
14766
|
id: "issue.block",
|
|
14759
|
-
command: "rudder issue block <issue> --comment <text>",
|
|
14767
|
+
command: "rudder issue block <issue> --comment <text> [--image <path>]",
|
|
14760
14768
|
category: "issue",
|
|
14761
|
-
description: "Mark an issue blocked with a required blocker comment.",
|
|
14769
|
+
description: "Mark an issue blocked with a required blocker comment, optionally uploading images.",
|
|
14762
14770
|
mutating: true,
|
|
14763
14771
|
contract: "agent-v1",
|
|
14764
14772
|
requiresOrgId: false,
|
|
@@ -15037,8 +15045,8 @@ function registerIssueCommands(program) {
|
|
|
15037
15045
|
if (opts.assigneeAgentId) params.set("assigneeAgentId", opts.assigneeAgentId);
|
|
15038
15046
|
if (opts.projectId) params.set("projectId", opts.projectId);
|
|
15039
15047
|
const query = params.toString();
|
|
15040
|
-
const
|
|
15041
|
-
const rows = await ctx.api.get(
|
|
15048
|
+
const path24 = `/api/orgs/${ctx.orgId}/issues${query ? `?${query}` : ""}`;
|
|
15049
|
+
const rows = await ctx.api.get(path24) ?? [];
|
|
15042
15050
|
const filtered = filterIssueRows(rows, opts.match);
|
|
15043
15051
|
if (ctx.json) {
|
|
15044
15052
|
printOutput(filtered, { json: true });
|
|
@@ -15119,9 +15127,10 @@ function registerIssueCommands(program) {
|
|
|
15119
15127
|
{ includeCompany: false }
|
|
15120
15128
|
);
|
|
15121
15129
|
addCommonClientOptions(
|
|
15122
|
-
issue.command("update").description(getAgentCliCapabilityById("issue.update").description).argument("<issueId>", "Issue ID").option("--title <title>", "Issue title").option("--description <text>", "Issue description").option("--status <status>", "Issue status").option("--priority <priority>", "Issue priority").option("--assignee-agent-id <id>", "Assignee agent ID").option("--project-id <id>", "Project ID").option("--goal-id <id>", "Goal ID").option("--parent-id <id>", "Parent issue ID").option("--request-depth <n>", "Request depth integer").option("--billing-code <code>", "Billing code").option("--comment <text>", "Optional comment to add with update").option("--hidden-at <iso8601|null>", "Set hiddenAt timestamp or literal 'null'").action(async (issueId, opts) => {
|
|
15130
|
+
issue.command("update").description(getAgentCliCapabilityById("issue.update").description).argument("<issueId>", "Issue ID").option("--title <title>", "Issue title").option("--description <text>", "Issue description").option("--status <status>", "Issue status").option("--priority <priority>", "Issue priority").option("--assignee-agent-id <id>", "Assignee agent ID").option("--project-id <id>", "Project ID").option("--goal-id <id>", "Goal ID").option("--parent-id <id>", "Parent issue ID").option("--request-depth <n>", "Request depth integer").option("--billing-code <code>", "Billing code").option("--comment <text>", "Optional comment to add with update").option("--image <path>", "Image file to upload and append to the update comment; may be repeated", collectImagePath, []).option("--hidden-at <iso8601|null>", "Set hiddenAt timestamp or literal 'null'").action(async (issueId, opts) => {
|
|
15123
15131
|
try {
|
|
15124
15132
|
const ctx = resolveCommandContext(opts);
|
|
15133
|
+
const comment = await appendUploadedIssueImages(ctx, issueId, opts.comment, opts.image);
|
|
15125
15134
|
const payload = updateIssueSchema.parse({
|
|
15126
15135
|
title: opts.title,
|
|
15127
15136
|
description: opts.description,
|
|
@@ -15133,7 +15142,7 @@ function registerIssueCommands(program) {
|
|
|
15133
15142
|
parentId: opts.parentId,
|
|
15134
15143
|
requestDepth: parseOptionalInt(opts.requestDepth),
|
|
15135
15144
|
billingCode: opts.billingCode,
|
|
15136
|
-
comment
|
|
15145
|
+
comment,
|
|
15137
15146
|
hiddenAt: parseHiddenAt(opts.hiddenAt)
|
|
15138
15147
|
});
|
|
15139
15148
|
const updated = await ctx.api.patch(`/api/issues/${issueId}`, payload);
|
|
@@ -15144,11 +15153,12 @@ function registerIssueCommands(program) {
|
|
|
15144
15153
|
})
|
|
15145
15154
|
);
|
|
15146
15155
|
addCommonClientOptions(
|
|
15147
|
-
issue.command("comment").description(getAgentCliCapabilityById("issue.comment").description).argument("<issueId>", "Issue ID").requiredOption("--body <text>", "Comment body").option("--reopen", "Reopen if issue is done/cancelled").action(async (issueId, opts) => {
|
|
15156
|
+
issue.command("comment").description(getAgentCliCapabilityById("issue.comment").description).argument("<issueId>", "Issue ID").requiredOption("--body <text>", "Comment body").option("--image <path>", "Image file to upload and append to the comment; may be repeated", collectImagePath, []).option("--reopen", "Reopen if issue is done/cancelled").action(async (issueId, opts) => {
|
|
15148
15157
|
try {
|
|
15149
15158
|
const ctx = resolveCommandContext(opts);
|
|
15159
|
+
const body = await appendUploadedIssueImages(ctx, issueId, opts.body, opts.image);
|
|
15150
15160
|
const payload = addIssueCommentSchema.parse({
|
|
15151
|
-
body
|
|
15161
|
+
body,
|
|
15152
15162
|
reopen: opts.reopen
|
|
15153
15163
|
});
|
|
15154
15164
|
const comment = await ctx.api.post(`/api/issues/${issueId}/comments`, payload);
|
|
@@ -15177,12 +15187,13 @@ function registerIssueCommands(program) {
|
|
|
15177
15187
|
})
|
|
15178
15188
|
);
|
|
15179
15189
|
addCommonClientOptions(
|
|
15180
|
-
issue.command("done").description(getAgentCliCapabilityById("issue.done").description).argument("<issueId>", "Issue ID").requiredOption("--comment <text>", "Required completion comment").action(async (issueId, opts) => {
|
|
15190
|
+
issue.command("done").description(getAgentCliCapabilityById("issue.done").description).argument("<issueId>", "Issue ID").requiredOption("--comment <text>", "Required completion comment").option("--image <path>", "Image file to upload and append to the completion comment; may be repeated", collectImagePath, []).action(async (issueId, opts) => {
|
|
15181
15191
|
try {
|
|
15182
15192
|
const ctx = resolveCommandContext(opts);
|
|
15193
|
+
const comment = await appendUploadedIssueImages(ctx, issueId, opts.comment, opts.image);
|
|
15183
15194
|
const updated = await ctx.api.patch(`/api/issues/${issueId}`, {
|
|
15184
15195
|
status: "done",
|
|
15185
|
-
comment
|
|
15196
|
+
comment
|
|
15186
15197
|
});
|
|
15187
15198
|
printOutput(updated, { json: ctx.json });
|
|
15188
15199
|
} catch (err) {
|
|
@@ -15191,12 +15202,13 @@ function registerIssueCommands(program) {
|
|
|
15191
15202
|
})
|
|
15192
15203
|
);
|
|
15193
15204
|
addCommonClientOptions(
|
|
15194
|
-
issue.command("block").description(getAgentCliCapabilityById("issue.block").description).argument("<issueId>", "Issue ID").requiredOption("--comment <text>", "Required blocker comment").action(async (issueId, opts) => {
|
|
15205
|
+
issue.command("block").description(getAgentCliCapabilityById("issue.block").description).argument("<issueId>", "Issue ID").requiredOption("--comment <text>", "Required blocker comment").option("--image <path>", "Image file to upload and append to the blocker comment; may be repeated", collectImagePath, []).action(async (issueId, opts) => {
|
|
15195
15206
|
try {
|
|
15196
15207
|
const ctx = resolveCommandContext(opts);
|
|
15208
|
+
const comment = await appendUploadedIssueImages(ctx, issueId, opts.comment, opts.image);
|
|
15197
15209
|
const updated = await ctx.api.patch(`/api/issues/${issueId}`, {
|
|
15198
15210
|
status: "blocked",
|
|
15199
|
-
comment
|
|
15211
|
+
comment
|
|
15200
15212
|
});
|
|
15201
15213
|
printOutput(updated, { json: ctx.json });
|
|
15202
15214
|
} catch (err) {
|
|
@@ -15320,6 +15332,80 @@ function registerIssueCommands(program) {
|
|
|
15320
15332
|
})
|
|
15321
15333
|
);
|
|
15322
15334
|
}
|
|
15335
|
+
function collectImagePath(value, previous) {
|
|
15336
|
+
const trimmed = value.trim();
|
|
15337
|
+
if (!trimmed) {
|
|
15338
|
+
throw new Error("--image path cannot be empty");
|
|
15339
|
+
}
|
|
15340
|
+
return [...previous, trimmed];
|
|
15341
|
+
}
|
|
15342
|
+
async function appendUploadedIssueImages(ctx, issueId, body, imagePaths) {
|
|
15343
|
+
const paths = imagePaths ?? [];
|
|
15344
|
+
if (paths.length === 0) return body;
|
|
15345
|
+
const issue = await ctx.api.get(`/api/issues/${issueId}`);
|
|
15346
|
+
if (!issue) {
|
|
15347
|
+
throw new Error("Issue not found");
|
|
15348
|
+
}
|
|
15349
|
+
const links = [];
|
|
15350
|
+
for (const imagePath of paths) {
|
|
15351
|
+
const attachment = await uploadIssueCommentImage(ctx, issue, imagePath);
|
|
15352
|
+
links.push(formatAttachmentMarkdown(attachment));
|
|
15353
|
+
}
|
|
15354
|
+
const base = body?.trimEnd() ?? "";
|
|
15355
|
+
const imageBlock = links.join("\n");
|
|
15356
|
+
return base ? `${base}
|
|
15357
|
+
|
|
15358
|
+
${imageBlock}` : imageBlock;
|
|
15359
|
+
}
|
|
15360
|
+
async function uploadIssueCommentImage(ctx, issue, imagePath) {
|
|
15361
|
+
const resolvedPath = path16.resolve(process.cwd(), imagePath);
|
|
15362
|
+
const stats = await stat2(resolvedPath).catch((err) => {
|
|
15363
|
+
throw new Error(`Unable to read image ${imagePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
15364
|
+
});
|
|
15365
|
+
if (!stats.isFile()) {
|
|
15366
|
+
throw new Error(`Image path must be a file: ${imagePath}`);
|
|
15367
|
+
}
|
|
15368
|
+
const filename = path16.basename(resolvedPath);
|
|
15369
|
+
const contentType = inferCommentImageContentType(filename);
|
|
15370
|
+
const buffer = await readFile5(resolvedPath);
|
|
15371
|
+
if (buffer.length <= 0) {
|
|
15372
|
+
throw new Error(`Image is empty: ${imagePath}`);
|
|
15373
|
+
}
|
|
15374
|
+
const form = new FormData();
|
|
15375
|
+
form.set("usage", "comment_inline");
|
|
15376
|
+
form.set("file", new Blob([buffer], { type: contentType }), filename);
|
|
15377
|
+
const attachment = await ctx.api.postForm(
|
|
15378
|
+
`/api/orgs/${issue.orgId}/issues/${issue.id}/attachments`,
|
|
15379
|
+
form
|
|
15380
|
+
);
|
|
15381
|
+
if (!attachment) {
|
|
15382
|
+
throw new Error(`Image upload returned no attachment: ${imagePath}`);
|
|
15383
|
+
}
|
|
15384
|
+
return attachment;
|
|
15385
|
+
}
|
|
15386
|
+
function inferCommentImageContentType(filename) {
|
|
15387
|
+
const ext = path16.extname(filename).toLowerCase();
|
|
15388
|
+
switch (ext) {
|
|
15389
|
+
case ".png":
|
|
15390
|
+
return "image/png";
|
|
15391
|
+
case ".jpg":
|
|
15392
|
+
case ".jpeg":
|
|
15393
|
+
return "image/jpeg";
|
|
15394
|
+
case ".webp":
|
|
15395
|
+
return "image/webp";
|
|
15396
|
+
case ".gif":
|
|
15397
|
+
return "image/gif";
|
|
15398
|
+
default:
|
|
15399
|
+
throw new Error(`Unsupported comment image type: ${filename}. Use PNG, JPEG, WebP, or GIF.`);
|
|
15400
|
+
}
|
|
15401
|
+
}
|
|
15402
|
+
function formatAttachmentMarkdown(attachment) {
|
|
15403
|
+
const alt = escapeMarkdownAltText(attachment.originalFilename ?? "image");
|
|
15404
|
+
return ``;
|
|
15405
|
+
}
|
|
15406
|
+
function escapeMarkdownAltText(value) {
|
|
15407
|
+
return value.replaceAll("\\", "\\\\").replaceAll("]", "\\]");
|
|
15408
|
+
}
|
|
15323
15409
|
function parseCsv(value) {
|
|
15324
15410
|
if (!value) return [];
|
|
15325
15411
|
return value.split(",").map((v) => v.trim()).filter(Boolean);
|
|
@@ -15358,7 +15444,7 @@ init_src();
|
|
|
15358
15444
|
|
|
15359
15445
|
// ../packages/agent-runtime-utils/src/server-utils.ts
|
|
15360
15446
|
import { constants as fsConstants2, promises as fs12 } from "node:fs";
|
|
15361
|
-
import
|
|
15447
|
+
import path17 from "node:path";
|
|
15362
15448
|
var MAX_CAPTURE_BYTES = 4 * 1024 * 1024;
|
|
15363
15449
|
var MAX_EXCERPT_BYTES = 32 * 1024;
|
|
15364
15450
|
var RUDDER_SKILL_ROOT_RELATIVE_CANDIDATES = [
|
|
@@ -15406,8 +15492,8 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
|
|
|
15406
15492
|
].join("\n");
|
|
15407
15493
|
async function resolveRudderSkillsDir(moduleDir, additionalCandidates = []) {
|
|
15408
15494
|
const candidates = [
|
|
15409
|
-
...RUDDER_SKILL_ROOT_RELATIVE_CANDIDATES.map((relativePath) =>
|
|
15410
|
-
...additionalCandidates.map((candidate) =>
|
|
15495
|
+
...RUDDER_SKILL_ROOT_RELATIVE_CANDIDATES.map((relativePath) => path17.resolve(moduleDir, relativePath)),
|
|
15496
|
+
...additionalCandidates.map((candidate) => path17.resolve(candidate))
|
|
15411
15497
|
];
|
|
15412
15498
|
const seenRoots = /* @__PURE__ */ new Set();
|
|
15413
15499
|
for (const root of candidates) {
|
|
@@ -15425,12 +15511,12 @@ async function removeMaintainerOnlySkillSymlinks(skillsHome, allowedSkillNames)
|
|
|
15425
15511
|
const removed = [];
|
|
15426
15512
|
for (const entry of entries) {
|
|
15427
15513
|
if (allowed.has(entry.name)) continue;
|
|
15428
|
-
const target =
|
|
15514
|
+
const target = path17.join(skillsHome, entry.name);
|
|
15429
15515
|
const existing = await fs12.lstat(target).catch(() => null);
|
|
15430
15516
|
if (!existing?.isSymbolicLink()) continue;
|
|
15431
15517
|
const linkedPath = await fs12.readlink(target).catch(() => null);
|
|
15432
15518
|
if (!linkedPath) continue;
|
|
15433
|
-
const resolvedLinkedPath =
|
|
15519
|
+
const resolvedLinkedPath = path17.isAbsolute(linkedPath) ? linkedPath : path17.resolve(path17.dirname(target), linkedPath);
|
|
15434
15520
|
if (!isMaintainerOnlySkillTarget(linkedPath) && !isMaintainerOnlySkillTarget(resolvedLinkedPath)) {
|
|
15435
15521
|
continue;
|
|
15436
15522
|
}
|
|
@@ -15446,18 +15532,18 @@ async function removeMaintainerOnlySkillSymlinks(skillsHome, allowedSkillNames)
|
|
|
15446
15532
|
// src/commands/client/agent.ts
|
|
15447
15533
|
import fs13 from "node:fs/promises";
|
|
15448
15534
|
import os2 from "node:os";
|
|
15449
|
-
import
|
|
15535
|
+
import path18 from "node:path";
|
|
15450
15536
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
15451
|
-
var __moduleDir =
|
|
15537
|
+
var __moduleDir = path18.dirname(fileURLToPath4(import.meta.url));
|
|
15452
15538
|
function codexSkillsHome() {
|
|
15453
15539
|
const fromEnv = process.env.CODEX_HOME?.trim();
|
|
15454
|
-
const base = fromEnv && fromEnv.length > 0 ? fromEnv :
|
|
15455
|
-
return
|
|
15540
|
+
const base = fromEnv && fromEnv.length > 0 ? fromEnv : path18.join(os2.homedir(), ".codex");
|
|
15541
|
+
return path18.join(base, "skills");
|
|
15456
15542
|
}
|
|
15457
15543
|
function claudeSkillsHome() {
|
|
15458
15544
|
const fromEnv = process.env.CLAUDE_HOME?.trim();
|
|
15459
|
-
const base = fromEnv && fromEnv.length > 0 ? fromEnv :
|
|
15460
|
-
return
|
|
15545
|
+
const base = fromEnv && fromEnv.length > 0 ? fromEnv : path18.join(os2.homedir(), ".claude");
|
|
15546
|
+
return path18.join(base, "skills");
|
|
15461
15547
|
}
|
|
15462
15548
|
async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool) {
|
|
15463
15549
|
const summary = {
|
|
@@ -15476,8 +15562,8 @@ async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool) {
|
|
|
15476
15562
|
);
|
|
15477
15563
|
for (const entry of entries) {
|
|
15478
15564
|
if (!entry.isDirectory()) continue;
|
|
15479
|
-
const source =
|
|
15480
|
-
const target =
|
|
15565
|
+
const source = path18.join(sourceSkillsDir, entry.name);
|
|
15566
|
+
const target = path18.join(targetSkillsDir, entry.name);
|
|
15481
15567
|
const existing = await fs13.lstat(target).catch(() => null);
|
|
15482
15568
|
if (existing) {
|
|
15483
15569
|
if (existing.isSymbolicLink()) {
|
|
@@ -15498,7 +15584,7 @@ async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool) {
|
|
|
15498
15584
|
continue;
|
|
15499
15585
|
}
|
|
15500
15586
|
}
|
|
15501
|
-
const resolvedLinkedPath =
|
|
15587
|
+
const resolvedLinkedPath = path18.isAbsolute(linkedPath) ? linkedPath : path18.resolve(path18.dirname(target), linkedPath);
|
|
15502
15588
|
const linkedTargetExists = await fs13.stat(resolvedLinkedPath).then(() => true).catch(() => false);
|
|
15503
15589
|
if (!linkedTargetExists) {
|
|
15504
15590
|
await fs13.unlink(target);
|
|
@@ -15779,7 +15865,7 @@ function registerAgentCommands(program) {
|
|
|
15779
15865
|
}
|
|
15780
15866
|
const installSummaries = [];
|
|
15781
15867
|
if (opts.installSkills !== false) {
|
|
15782
|
-
const skillsDir = await resolveRudderSkillsDir(__moduleDir, [
|
|
15868
|
+
const skillsDir = await resolveRudderSkillsDir(__moduleDir, [path18.resolve(process.cwd(), "skills")]);
|
|
15783
15869
|
if (!skillsDir) {
|
|
15784
15870
|
throw new Error(
|
|
15785
15871
|
"Could not locate local Rudder skills directory. Expected ./skills in the repo checkout."
|
|
@@ -16036,8 +16122,8 @@ function registerActivityCommands(program) {
|
|
|
16036
16122
|
if (opts.entityType) params.set("entityType", opts.entityType);
|
|
16037
16123
|
if (opts.entityId) params.set("entityId", opts.entityId);
|
|
16038
16124
|
const query = params.toString();
|
|
16039
|
-
const
|
|
16040
|
-
const rows = await ctx.api.get(
|
|
16125
|
+
const path24 = `/api/orgs/${ctx.orgId}/activity${query ? `?${query}` : ""}`;
|
|
16126
|
+
const rows = await ctx.api.get(path24) ?? [];
|
|
16041
16127
|
if (ctx.json) {
|
|
16042
16128
|
printOutput(rows, { json: true });
|
|
16043
16129
|
return;
|
|
@@ -16206,11 +16292,11 @@ function parseCsv4(value) {
|
|
|
16206
16292
|
|
|
16207
16293
|
// src/config/data-dir.ts
|
|
16208
16294
|
init_home();
|
|
16209
|
-
import
|
|
16295
|
+
import path19 from "node:path";
|
|
16210
16296
|
function applyDataDirOverride(options, support = {}) {
|
|
16211
16297
|
const rawDataDir = options.dataDir?.trim();
|
|
16212
16298
|
if (!rawDataDir) return null;
|
|
16213
|
-
const resolvedDataDir =
|
|
16299
|
+
const resolvedDataDir = path19.resolve(expandHomePrefix(rawDataDir));
|
|
16214
16300
|
process.env.RUDDER_HOME = resolvedDataDir;
|
|
16215
16301
|
if (support.hasConfigOption) {
|
|
16216
16302
|
const hasConfigOverride = Boolean(options.config?.trim()) || Boolean(process.env.RUDDER_CONFIG?.trim());
|
|
@@ -16255,7 +16341,7 @@ import {
|
|
|
16255
16341
|
writeFileSync
|
|
16256
16342
|
} from "node:fs";
|
|
16257
16343
|
import os3 from "node:os";
|
|
16258
|
-
import
|
|
16344
|
+
import path21 from "node:path";
|
|
16259
16345
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
16260
16346
|
import { createServer } from "node:net";
|
|
16261
16347
|
import { Readable as Readable2 } from "node:stream";
|
|
@@ -16266,7 +16352,7 @@ import { and as and2, eq as eq2, inArray, sql as sql3 } from "drizzle-orm";
|
|
|
16266
16352
|
// src/commands/worktree-lib.ts
|
|
16267
16353
|
init_home();
|
|
16268
16354
|
import { randomInt } from "node:crypto";
|
|
16269
|
-
import
|
|
16355
|
+
import path20 from "node:path";
|
|
16270
16356
|
var DEFAULT_WORKTREE_HOME = "~/.rudder-worktrees";
|
|
16271
16357
|
var WORKTREE_SEED_MODES = ["minimal", "full"];
|
|
16272
16358
|
var MINIMAL_WORKTREE_EXCLUDED_TABLES = [
|
|
@@ -16314,7 +16400,7 @@ function sanitizeWorktreeInstanceId(rawValue) {
|
|
|
16314
16400
|
return normalized || "worktree";
|
|
16315
16401
|
}
|
|
16316
16402
|
function resolveSuggestedWorktreeName(cwd, explicitName) {
|
|
16317
|
-
return nonEmpty(explicitName) ??
|
|
16403
|
+
return nonEmpty(explicitName) ?? path20.basename(path20.resolve(cwd));
|
|
16318
16404
|
}
|
|
16319
16405
|
function hslComponentToHex(n) {
|
|
16320
16406
|
return Math.round(Math.max(0, Math.min(255, n))).toString(16).padStart(2, "0");
|
|
@@ -16354,24 +16440,24 @@ function generateWorktreeColor() {
|
|
|
16354
16440
|
return hslToHex(randomInt(0, 360), 68, 56);
|
|
16355
16441
|
}
|
|
16356
16442
|
function resolveWorktreeLocalPaths(opts) {
|
|
16357
|
-
const cwd =
|
|
16358
|
-
const homeDir =
|
|
16359
|
-
const instanceRoot =
|
|
16360
|
-
const repoConfigDir =
|
|
16443
|
+
const cwd = path20.resolve(opts.cwd);
|
|
16444
|
+
const homeDir = path20.resolve(expandHomePrefix(opts.homeDir ?? DEFAULT_WORKTREE_HOME));
|
|
16445
|
+
const instanceRoot = path20.resolve(homeDir, "instances", opts.instanceId);
|
|
16446
|
+
const repoConfigDir = path20.resolve(cwd, ".rudder");
|
|
16361
16447
|
return {
|
|
16362
16448
|
cwd,
|
|
16363
16449
|
repoConfigDir,
|
|
16364
|
-
configPath:
|
|
16365
|
-
envPath:
|
|
16450
|
+
configPath: path20.resolve(repoConfigDir, "config.json"),
|
|
16451
|
+
envPath: path20.resolve(repoConfigDir, ".env"),
|
|
16366
16452
|
homeDir,
|
|
16367
16453
|
instanceId: opts.instanceId,
|
|
16368
16454
|
instanceRoot,
|
|
16369
|
-
contextPath:
|
|
16370
|
-
embeddedPostgresDataDir:
|
|
16371
|
-
backupDir:
|
|
16372
|
-
logDir:
|
|
16373
|
-
secretsKeyFilePath:
|
|
16374
|
-
storageDir:
|
|
16455
|
+
contextPath: path20.resolve(homeDir, "context.json"),
|
|
16456
|
+
embeddedPostgresDataDir: path20.resolve(instanceRoot, "db"),
|
|
16457
|
+
backupDir: path20.resolve(instanceRoot, "data", "backups"),
|
|
16458
|
+
logDir: path20.resolve(instanceRoot, "logs"),
|
|
16459
|
+
secretsKeyFilePath: path20.resolve(instanceRoot, "secrets", "master.key"),
|
|
16460
|
+
storageDir: path20.resolve(instanceRoot, "data", "storage")
|
|
16375
16461
|
};
|
|
16376
16462
|
}
|
|
16377
16463
|
function rewriteLocalUrlPort(rawUrl, port) {
|
|
@@ -16895,7 +16981,7 @@ function isCurrentSourceConfigPath(sourceConfigPath) {
|
|
|
16895
16981
|
if (!currentConfigPath || currentConfigPath.trim().length === 0) {
|
|
16896
16982
|
return false;
|
|
16897
16983
|
}
|
|
16898
|
-
return
|
|
16984
|
+
return path21.resolve(currentConfigPath) === path21.resolve(sourceConfigPath);
|
|
16899
16985
|
}
|
|
16900
16986
|
var WORKTREE_NAME_PREFIX = "rudder-";
|
|
16901
16987
|
function resolveWorktreeMakeName(name) {
|
|
@@ -16933,9 +17019,9 @@ function normalizeStorageObjectKey(objectKey) {
|
|
|
16933
17019
|
return parts.join("/");
|
|
16934
17020
|
}
|
|
16935
17021
|
function resolveLocalStoragePath(baseDir, objectKey) {
|
|
16936
|
-
const resolved =
|
|
16937
|
-
const root =
|
|
16938
|
-
if (resolved !== root && !resolved.startsWith(`${root}${
|
|
17022
|
+
const resolved = path21.resolve(baseDir, normalizeStorageObjectKey(objectKey));
|
|
17023
|
+
const root = path21.resolve(baseDir);
|
|
17024
|
+
if (resolved !== root && !resolved.startsWith(`${root}${path21.sep}`)) {
|
|
16939
17025
|
throw new Error("Invalid object key path.");
|
|
16940
17026
|
}
|
|
16941
17027
|
return resolved;
|
|
@@ -16986,7 +17072,7 @@ function createConfiguredStorageFromRudderConfig(config) {
|
|
|
16986
17072
|
async putObject(orgId, objectKey, body) {
|
|
16987
17073
|
assertStorageCompanyPrefix(orgId, objectKey);
|
|
16988
17074
|
const filePath = resolveLocalStoragePath(baseDir, objectKey);
|
|
16989
|
-
await fsPromises.mkdir(
|
|
17075
|
+
await fsPromises.mkdir(path21.dirname(filePath), { recursive: true });
|
|
16990
17076
|
await fsPromises.writeFile(filePath, body);
|
|
16991
17077
|
}
|
|
16992
17078
|
};
|
|
@@ -17070,7 +17156,7 @@ async function readSourceAttachmentBody(sourceStorages, orgId, objectKey) {
|
|
|
17070
17156
|
return null;
|
|
17071
17157
|
}
|
|
17072
17158
|
function resolveWorktreeMakeTargetPath(name) {
|
|
17073
|
-
return
|
|
17159
|
+
return path21.resolve(os3.homedir(), resolveWorktreeMakeName(name));
|
|
17074
17160
|
}
|
|
17075
17161
|
function extractExecSyncErrorMessage(error) {
|
|
17076
17162
|
if (!error || typeof error !== "object") {
|
|
@@ -17176,10 +17262,10 @@ function detectGitWorkspaceInfo(cwd) {
|
|
|
17176
17262
|
stdio: ["ignore", "pipe", "ignore"]
|
|
17177
17263
|
}).trim();
|
|
17178
17264
|
return {
|
|
17179
|
-
root:
|
|
17180
|
-
commonDir:
|
|
17181
|
-
gitDir:
|
|
17182
|
-
hooksPath:
|
|
17265
|
+
root: path21.resolve(root),
|
|
17266
|
+
commonDir: path21.resolve(root, commonDirRaw),
|
|
17267
|
+
gitDir: path21.resolve(root, gitDirRaw),
|
|
17268
|
+
hooksPath: path21.resolve(root, hooksPathRaw)
|
|
17183
17269
|
};
|
|
17184
17270
|
} catch {
|
|
17185
17271
|
return null;
|
|
@@ -17192,8 +17278,8 @@ function copyDirectoryContents(sourceDir, targetDir) {
|
|
|
17192
17278
|
mkdirSync3(targetDir, { recursive: true });
|
|
17193
17279
|
let copied = false;
|
|
17194
17280
|
for (const entry of entries) {
|
|
17195
|
-
const sourcePath =
|
|
17196
|
-
const targetPath =
|
|
17281
|
+
const sourcePath = path21.resolve(sourceDir, entry.name);
|
|
17282
|
+
const targetPath = path21.resolve(targetDir, entry.name);
|
|
17197
17283
|
if (entry.isDirectory()) {
|
|
17198
17284
|
mkdirSync3(targetPath, { recursive: true });
|
|
17199
17285
|
copyDirectoryContents(sourcePath, targetPath);
|
|
@@ -17219,7 +17305,7 @@ function copyGitHooksToWorktreeGitDir(cwd) {
|
|
|
17219
17305
|
const workspace = detectGitWorkspaceInfo(cwd);
|
|
17220
17306
|
if (!workspace) return null;
|
|
17221
17307
|
const sourceHooksPath = workspace.hooksPath;
|
|
17222
|
-
const targetHooksPath =
|
|
17308
|
+
const targetHooksPath = path21.resolve(workspace.gitDir, "hooks");
|
|
17223
17309
|
if (sourceHooksPath === targetHooksPath) {
|
|
17224
17310
|
return {
|
|
17225
17311
|
sourceHooksPath,
|
|
@@ -17234,17 +17320,17 @@ function copyGitHooksToWorktreeGitDir(cwd) {
|
|
|
17234
17320
|
};
|
|
17235
17321
|
}
|
|
17236
17322
|
function rebindWorkspaceCwd(input) {
|
|
17237
|
-
const sourceRepoRoot =
|
|
17238
|
-
const targetRepoRoot =
|
|
17239
|
-
const workspaceCwd =
|
|
17240
|
-
const relative =
|
|
17323
|
+
const sourceRepoRoot = path21.resolve(input.sourceRepoRoot);
|
|
17324
|
+
const targetRepoRoot = path21.resolve(input.targetRepoRoot);
|
|
17325
|
+
const workspaceCwd = path21.resolve(input.workspaceCwd);
|
|
17326
|
+
const relative = path21.relative(sourceRepoRoot, workspaceCwd);
|
|
17241
17327
|
if (!relative || relative === "") {
|
|
17242
17328
|
return targetRepoRoot;
|
|
17243
17329
|
}
|
|
17244
|
-
if (relative.startsWith("..") ||
|
|
17330
|
+
if (relative.startsWith("..") || path21.isAbsolute(relative)) {
|
|
17245
17331
|
return null;
|
|
17246
17332
|
}
|
|
17247
|
-
return
|
|
17333
|
+
return path21.resolve(targetRepoRoot, relative);
|
|
17248
17334
|
}
|
|
17249
17335
|
async function rebindSeededProjectWorkspaces(input) {
|
|
17250
17336
|
const targetRepo = detectGitWorkspaceInfo(input.currentCwd);
|
|
@@ -17270,7 +17356,7 @@ async function rebindSeededProjectWorkspaces(input) {
|
|
|
17270
17356
|
workspaceCwd
|
|
17271
17357
|
});
|
|
17272
17358
|
if (!reboundCwd) continue;
|
|
17273
|
-
const normalizedCurrent =
|
|
17359
|
+
const normalizedCurrent = path21.resolve(workspaceCwd);
|
|
17274
17360
|
if (reboundCwd === normalizedCurrent) continue;
|
|
17275
17361
|
if (!existsSync3(reboundCwd)) continue;
|
|
17276
17362
|
await db.update(projectWorkspaces).set({
|
|
@@ -17289,14 +17375,14 @@ async function rebindSeededProjectWorkspaces(input) {
|
|
|
17289
17375
|
}
|
|
17290
17376
|
}
|
|
17291
17377
|
function resolveSourceConfigPath(opts) {
|
|
17292
|
-
if (opts.sourceConfigPathOverride) return
|
|
17293
|
-
if (opts.fromConfig) return
|
|
17378
|
+
if (opts.sourceConfigPathOverride) return path21.resolve(opts.sourceConfigPathOverride);
|
|
17379
|
+
if (opts.fromConfig) return path21.resolve(opts.fromConfig);
|
|
17294
17380
|
if (!opts.fromDataDir && !opts.fromInstance) {
|
|
17295
17381
|
return resolveConfigPath();
|
|
17296
17382
|
}
|
|
17297
|
-
const sourceHome =
|
|
17383
|
+
const sourceHome = path21.resolve(expandHomePrefix(opts.fromDataDir ?? "~/.rudder"));
|
|
17298
17384
|
const sourceInstanceId = sanitizeWorktreeInstanceId(opts.fromInstance ?? "default");
|
|
17299
|
-
return
|
|
17385
|
+
return path21.resolve(sourceHome, "instances", sourceInstanceId, "config.json");
|
|
17300
17386
|
}
|
|
17301
17387
|
function resolveSourceConnectionString(config, envEntries, portOverride) {
|
|
17302
17388
|
if (config.database.mode === "postgres") {
|
|
@@ -17315,7 +17401,7 @@ function copySeededSecretsKey(input) {
|
|
|
17315
17401
|
if (input.sourceConfig.secrets.provider !== "local_encrypted") {
|
|
17316
17402
|
return;
|
|
17317
17403
|
}
|
|
17318
|
-
mkdirSync3(
|
|
17404
|
+
mkdirSync3(path21.dirname(input.targetKeyFilePath), { recursive: true });
|
|
17319
17405
|
const allowProcessEnvFallback = isCurrentSourceConfigPath(input.sourceConfigPath);
|
|
17320
17406
|
const sourceInlineMasterKey = nonEmpty2(input.sourceEnvEntries.RUDDER_SECRETS_MASTER_KEY) ?? (allowProcessEnvFallback ? nonEmpty2(process.env.RUDDER_SECRETS_MASTER_KEY) : null);
|
|
17321
17407
|
if (sourceInlineMasterKey) {
|
|
@@ -17354,7 +17440,7 @@ async function ensureEmbeddedPostgres(dataDir, preferredPort) {
|
|
|
17354
17440
|
"Embedded PostgreSQL support requires dependency `embedded-postgres`. Reinstall dependencies and try again."
|
|
17355
17441
|
);
|
|
17356
17442
|
}
|
|
17357
|
-
const postmasterPidFile =
|
|
17443
|
+
const postmasterPidFile = path21.resolve(dataDir, "postmaster.pid");
|
|
17358
17444
|
const runningPid = readRunningPostmasterPid(postmasterPidFile);
|
|
17359
17445
|
if (runningPid) {
|
|
17360
17446
|
return {
|
|
@@ -17377,7 +17463,7 @@ async function ensureEmbeddedPostgres(dataDir, preferredPort) {
|
|
|
17377
17463
|
onError: () => {
|
|
17378
17464
|
}
|
|
17379
17465
|
});
|
|
17380
|
-
if (!existsSync3(
|
|
17466
|
+
if (!existsSync3(path21.resolve(dataDir, "PG_VERSION"))) {
|
|
17381
17467
|
await instance.initialise();
|
|
17382
17468
|
}
|
|
17383
17469
|
if (existsSync3(postmasterPidFile)) {
|
|
@@ -17418,7 +17504,7 @@ async function seedWorktreeDatabase(input) {
|
|
|
17418
17504
|
);
|
|
17419
17505
|
const backup = await runDatabaseBackup({
|
|
17420
17506
|
connectionString: sourceConnectionString,
|
|
17421
|
-
backupDir:
|
|
17507
|
+
backupDir: path21.resolve(input.targetPaths.backupDir, "seed"),
|
|
17422
17508
|
retentionDays: 7,
|
|
17423
17509
|
filenamePrefix: `${input.instanceId}-seed`,
|
|
17424
17510
|
includeMigrationJournal: true,
|
|
@@ -17577,7 +17663,7 @@ async function worktreeMakeCommand(nameArg, opts) {
|
|
|
17577
17663
|
if (existsSync3(targetPath)) {
|
|
17578
17664
|
throw new Error(`Target path already exists: ${targetPath}`);
|
|
17579
17665
|
}
|
|
17580
|
-
mkdirSync3(
|
|
17666
|
+
mkdirSync3(path21.dirname(targetPath), { recursive: true });
|
|
17581
17667
|
if (startPoint) {
|
|
17582
17668
|
const [remote] = startPoint.split("/", 1);
|
|
17583
17669
|
try {
|
|
@@ -17673,15 +17759,15 @@ function parseGitWorktreeList(cwd) {
|
|
|
17673
17759
|
return entries;
|
|
17674
17760
|
}
|
|
17675
17761
|
function toMergeSourceChoices(cwd) {
|
|
17676
|
-
const currentCwd =
|
|
17762
|
+
const currentCwd = path21.resolve(cwd);
|
|
17677
17763
|
return parseGitWorktreeList(cwd).map((entry) => {
|
|
17678
17764
|
const branchLabel = entry.branch?.replace(/^refs\/heads\//, "") ?? "(detached)";
|
|
17679
|
-
const worktreePath =
|
|
17765
|
+
const worktreePath = path21.resolve(entry.worktree);
|
|
17680
17766
|
return {
|
|
17681
17767
|
worktree: worktreePath,
|
|
17682
17768
|
branch: entry.branch,
|
|
17683
17769
|
branchLabel,
|
|
17684
|
-
hasRudderConfig: existsSync3(
|
|
17770
|
+
hasRudderConfig: existsSync3(path21.resolve(worktreePath, ".rudder", "config.json")),
|
|
17685
17771
|
isCurrent: worktreePath === currentCwd
|
|
17686
17772
|
};
|
|
17687
17773
|
});
|
|
@@ -17729,14 +17815,14 @@ async function worktreeCleanupCommand(nameArg, opts) {
|
|
|
17729
17815
|
const sourceCwd = process.cwd();
|
|
17730
17816
|
const targetPath = resolveWorktreeMakeTargetPath(name);
|
|
17731
17817
|
const instanceId = sanitizeWorktreeInstanceId(opts.instance ?? name);
|
|
17732
|
-
const homeDir =
|
|
17733
|
-
const instanceRoot =
|
|
17818
|
+
const homeDir = path21.resolve(expandHomePrefix(resolveWorktreeHome(opts.home)));
|
|
17819
|
+
const instanceRoot = path21.resolve(homeDir, "instances", instanceId);
|
|
17734
17820
|
const hasBranch = localBranchExists(sourceCwd, name);
|
|
17735
17821
|
const hasTargetDir = existsSync3(targetPath);
|
|
17736
17822
|
const hasInstanceData = existsSync3(instanceRoot);
|
|
17737
17823
|
const worktrees = parseGitWorktreeList(sourceCwd);
|
|
17738
17824
|
const linkedWorktree = worktrees.find(
|
|
17739
|
-
(wt) => wt.branch === `refs/heads/${name}` ||
|
|
17825
|
+
(wt) => wt.branch === `refs/heads/${name}` || path21.resolve(wt.worktree) === path21.resolve(targetPath)
|
|
17740
17826
|
);
|
|
17741
17827
|
if (!hasBranch && !hasTargetDir && !hasInstanceData && !linkedWorktree) {
|
|
17742
17828
|
p17.log.info("Nothing to clean up \u2014 no branch, worktree directory, or instance data found.");
|
|
@@ -17854,7 +17940,7 @@ async function closeDb(db) {
|
|
|
17854
17940
|
}
|
|
17855
17941
|
function resolveCurrentEndpoint() {
|
|
17856
17942
|
return {
|
|
17857
|
-
rootPath:
|
|
17943
|
+
rootPath: path21.resolve(process.cwd()),
|
|
17858
17944
|
configPath: resolveConfigPath(),
|
|
17859
17945
|
label: "current",
|
|
17860
17946
|
isCurrent: true
|
|
@@ -17865,12 +17951,12 @@ function resolveAttachmentLookupStorages(input) {
|
|
|
17865
17951
|
input.sourceEndpoint.configPath,
|
|
17866
17952
|
resolveCurrentEndpoint().configPath,
|
|
17867
17953
|
input.targetEndpoint.configPath,
|
|
17868
|
-
...toMergeSourceChoices(process.cwd()).filter((choice) => choice.hasRudderConfig).map((choice) =>
|
|
17954
|
+
...toMergeSourceChoices(process.cwd()).filter((choice) => choice.hasRudderConfig).map((choice) => path21.resolve(choice.worktree, ".rudder", "config.json"))
|
|
17869
17955
|
];
|
|
17870
17956
|
const seen = /* @__PURE__ */ new Set();
|
|
17871
17957
|
const storages = [];
|
|
17872
17958
|
for (const configPath of orderedConfigPaths) {
|
|
17873
|
-
const resolved =
|
|
17959
|
+
const resolved = path21.resolve(configPath);
|
|
17874
17960
|
if (seen.has(resolved) || !existsSync3(resolved)) continue;
|
|
17875
17961
|
seen.add(resolved);
|
|
17876
17962
|
storages.push(openConfiguredStorage(resolved));
|
|
@@ -18289,7 +18375,7 @@ function resolveEndpointFromChoice(choice) {
|
|
|
18289
18375
|
}
|
|
18290
18376
|
return {
|
|
18291
18377
|
rootPath: choice.worktree,
|
|
18292
|
-
configPath:
|
|
18378
|
+
configPath: path21.resolve(choice.worktree, ".rudder", "config.json"),
|
|
18293
18379
|
label: choice.branchLabel,
|
|
18294
18380
|
isCurrent: false
|
|
18295
18381
|
};
|
|
@@ -18305,24 +18391,24 @@ function resolveWorktreeEndpointFromSelector(selector, opts) {
|
|
|
18305
18391
|
return currentEndpoint;
|
|
18306
18392
|
}
|
|
18307
18393
|
const choices = toMergeSourceChoices(process.cwd());
|
|
18308
|
-
const directPath =
|
|
18394
|
+
const directPath = path21.resolve(trimmed);
|
|
18309
18395
|
if (existsSync3(directPath)) {
|
|
18310
18396
|
if (allowCurrent && directPath === currentEndpoint.rootPath) {
|
|
18311
18397
|
return currentEndpoint;
|
|
18312
18398
|
}
|
|
18313
|
-
const configPath =
|
|
18399
|
+
const configPath = path21.resolve(directPath, ".rudder", "config.json");
|
|
18314
18400
|
if (!existsSync3(configPath)) {
|
|
18315
18401
|
throw new Error(`Resolved worktree path ${directPath} does not contain .rudder/config.json.`);
|
|
18316
18402
|
}
|
|
18317
18403
|
return {
|
|
18318
18404
|
rootPath: directPath,
|
|
18319
18405
|
configPath,
|
|
18320
|
-
label:
|
|
18406
|
+
label: path21.basename(directPath),
|
|
18321
18407
|
isCurrent: false
|
|
18322
18408
|
};
|
|
18323
18409
|
}
|
|
18324
18410
|
const matched = choices.find(
|
|
18325
|
-
(choice) => (allowCurrent || !choice.isCurrent) && (choice.worktree === directPath ||
|
|
18411
|
+
(choice) => (allowCurrent || !choice.isCurrent) && (choice.worktree === directPath || path21.basename(choice.worktree) === trimmed || choice.branchLabel === trimmed)
|
|
18326
18412
|
);
|
|
18327
18413
|
if (!matched) {
|
|
18328
18414
|
throw new Error(
|
|
@@ -18335,9 +18421,9 @@ function resolveWorktreeEndpointFromSelector(selector, opts) {
|
|
|
18335
18421
|
return resolveEndpointFromChoice(matched);
|
|
18336
18422
|
}
|
|
18337
18423
|
async function promptForSourceEndpoint(excludeWorktreePath) {
|
|
18338
|
-
const excluded = excludeWorktreePath ?
|
|
18424
|
+
const excluded = excludeWorktreePath ? path21.resolve(excludeWorktreePath) : null;
|
|
18339
18425
|
const currentEndpoint = resolveCurrentEndpoint();
|
|
18340
|
-
const choices = toMergeSourceChoices(process.cwd()).filter((choice) => choice.hasRudderConfig || choice.isCurrent).filter((choice) =>
|
|
18426
|
+
const choices = toMergeSourceChoices(process.cwd()).filter((choice) => choice.hasRudderConfig || choice.isCurrent).filter((choice) => path21.resolve(choice.worktree) !== excluded).map((choice) => ({
|
|
18341
18427
|
value: choice.isCurrent ? "__current__" : choice.worktree,
|
|
18342
18428
|
label: choice.branchLabel,
|
|
18343
18429
|
hint: `${choice.worktree}${choice.isCurrent ? " (current)" : ""}`
|
|
@@ -18661,7 +18747,7 @@ async function worktreeMergeHistoryCommand(sourceArg, opts) {
|
|
|
18661
18747
|
}
|
|
18662
18748
|
const targetEndpoint = opts.to ? resolveWorktreeEndpointFromSelector(opts.to, { allowCurrent: true }) : resolveCurrentEndpoint();
|
|
18663
18749
|
const sourceEndpoint = opts.from ? resolveWorktreeEndpointFromSelector(opts.from, { allowCurrent: true }) : sourceArg ? resolveWorktreeEndpointFromSelector(sourceArg, { allowCurrent: true }) : await promptForSourceEndpoint(targetEndpoint.rootPath);
|
|
18664
|
-
if (
|
|
18750
|
+
if (path21.resolve(sourceEndpoint.configPath) === path21.resolve(targetEndpoint.configPath)) {
|
|
18665
18751
|
throw new Error("Source and target Rudder configs are the same. Choose different --from/--to worktrees.");
|
|
18666
18752
|
}
|
|
18667
18753
|
const scopes = parseWorktreeMergeScopes(opts.scope);
|
|
@@ -18750,16 +18836,16 @@ function registerWorktreeCommands(program) {
|
|
|
18750
18836
|
}
|
|
18751
18837
|
|
|
18752
18838
|
// src/commands/client/plugin.ts
|
|
18753
|
-
import
|
|
18839
|
+
import path22 from "node:path";
|
|
18754
18840
|
import pc24 from "picocolors";
|
|
18755
18841
|
function resolvePackageArg(packageArg, isLocal) {
|
|
18756
18842
|
if (!isLocal) return packageArg;
|
|
18757
|
-
if (
|
|
18843
|
+
if (path22.isAbsolute(packageArg)) return packageArg;
|
|
18758
18844
|
if (packageArg.startsWith("~")) {
|
|
18759
18845
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
18760
|
-
return
|
|
18846
|
+
return path22.resolve(home, packageArg.slice(1).replace(/^[\\/]/, ""));
|
|
18761
18847
|
}
|
|
18762
|
-
return
|
|
18848
|
+
return path22.resolve(process.cwd(), packageArg);
|
|
18763
18849
|
}
|
|
18764
18850
|
function formatPlugin(p18) {
|
|
18765
18851
|
const statusColor = p18.status === "ready" ? pc24.green(p18.status) : p18.status === "error" ? pc24.red(p18.status) : p18.status === "disabled" ? pc24.dim(p18.status) : pc24.yellow(p18.status);
|
|
@@ -19031,7 +19117,7 @@ function registerClientAuthCommands(auth) {
|
|
|
19031
19117
|
|
|
19032
19118
|
// src/commands/benchmark-create-agent.ts
|
|
19033
19119
|
import fs14 from "node:fs/promises";
|
|
19034
|
-
import
|
|
19120
|
+
import path23 from "node:path";
|
|
19035
19121
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
19036
19122
|
import { LangfuseClient } from "@langfuse/client";
|
|
19037
19123
|
|
|
@@ -19591,11 +19677,11 @@ function createAgentEvalCheckToScoreValue(check) {
|
|
|
19591
19677
|
}
|
|
19592
19678
|
|
|
19593
19679
|
// src/commands/benchmark-create-agent.ts
|
|
19594
|
-
var __moduleDir2 =
|
|
19595
|
-
var repoRoot =
|
|
19596
|
-
var defaultCasesDir =
|
|
19597
|
-
var defaultSetsDir =
|
|
19598
|
-
var defaultArtifactsDir =
|
|
19680
|
+
var __moduleDir2 = path23.dirname(fileURLToPath5(import.meta.url));
|
|
19681
|
+
var repoRoot = path23.resolve(__moduleDir2, "../../..");
|
|
19682
|
+
var defaultCasesDir = path23.join(repoRoot, "benchmark", "create-agent", "cases");
|
|
19683
|
+
var defaultSetsDir = path23.join(repoRoot, "benchmark", "create-agent", "sets");
|
|
19684
|
+
var defaultArtifactsDir = path23.join(repoRoot, ".artifacts", "create-agent-benchmark");
|
|
19599
19685
|
var TERMINAL_RUN_STATUSES2 = /* @__PURE__ */ new Set(["succeeded", "failed", "cancelled", "timed_out"]);
|
|
19600
19686
|
var DEFAULT_JUDGE_PROMPT_NAME = "judge-create-agent";
|
|
19601
19687
|
var DEFAULT_JUDGE_MODEL = "gpt-5-mini";
|
|
@@ -19645,16 +19731,16 @@ async function readJsonFile(filePath) {
|
|
|
19645
19731
|
return JSON.parse(content);
|
|
19646
19732
|
}
|
|
19647
19733
|
async function writeJsonFile(filePath, value) {
|
|
19648
|
-
await fs14.mkdir(
|
|
19734
|
+
await fs14.mkdir(path23.dirname(filePath), { recursive: true });
|
|
19649
19735
|
await fs14.writeFile(filePath, `${JSON.stringify(value, null, 2)}
|
|
19650
19736
|
`, "utf8");
|
|
19651
19737
|
}
|
|
19652
19738
|
async function loadCaseById(caseId, casesDir) {
|
|
19653
|
-
const filePath =
|
|
19739
|
+
const filePath = path23.join(casesDir, `${caseId}.json`);
|
|
19654
19740
|
return parseCreateAgentCase(await readJsonFile(filePath));
|
|
19655
19741
|
}
|
|
19656
19742
|
async function loadSet(setName, setsDir) {
|
|
19657
|
-
const filePath =
|
|
19743
|
+
const filePath = path23.join(setsDir, `${setName}.json`);
|
|
19658
19744
|
const raw = await readJsonFile(filePath);
|
|
19659
19745
|
if (!Array.isArray(raw) || raw.some((item) => typeof item !== "string")) {
|
|
19660
19746
|
throw new Error(`Benchmark set ${setName} must be a JSON array of case IDs.`);
|
|
@@ -19742,13 +19828,13 @@ async function captureCreatedApprovals(api, approvals2) {
|
|
|
19742
19828
|
);
|
|
19743
19829
|
}
|
|
19744
19830
|
function resultRunDir(artifactsDir, testCase, runId) {
|
|
19745
|
-
return
|
|
19831
|
+
return path23.join(artifactsDir, "runs", `${testCase.id}-${runId}`);
|
|
19746
19832
|
}
|
|
19747
19833
|
function resultJsonPath(artifactsDir, testCase, runId) {
|
|
19748
|
-
return
|
|
19834
|
+
return path23.join(resultRunDir(artifactsDir, testCase, runId), "result.json");
|
|
19749
19835
|
}
|
|
19750
19836
|
function reportMarkdownPath(artifactsDir, testCase, runId) {
|
|
19751
|
-
return
|
|
19837
|
+
return path23.join(resultRunDir(artifactsDir, testCase, runId), "report.md");
|
|
19752
19838
|
}
|
|
19753
19839
|
function averageJudgeScore(judge) {
|
|
19754
19840
|
if (!judge || judge.status !== "completed") return null;
|
|
@@ -20157,7 +20243,7 @@ async function executeBenchmarkCase(caseId, opts) {
|
|
|
20157
20243
|
const jsonPath = resultJsonPath(artifactsDir, testCase, runDetail.run.id);
|
|
20158
20244
|
const markdownPath = reportMarkdownPath(artifactsDir, testCase, runDetail.run.id);
|
|
20159
20245
|
await writeJsonFile(jsonPath, provisionalResult);
|
|
20160
|
-
await fs14.mkdir(
|
|
20246
|
+
await fs14.mkdir(path23.dirname(markdownPath), { recursive: true });
|
|
20161
20247
|
await fs14.writeFile(markdownPath, buildMarkdownReport(provisionalResult), "utf8");
|
|
20162
20248
|
return provisionalResult;
|
|
20163
20249
|
}
|
|
@@ -20180,7 +20266,7 @@ async function rescoreStoredResult(resultPath, opts) {
|
|
|
20180
20266
|
result.langfuse.scoreSyncError = sync.scoreSyncError;
|
|
20181
20267
|
}
|
|
20182
20268
|
await writeJsonFile(resultPath, result);
|
|
20183
|
-
await fs14.writeFile(
|
|
20269
|
+
await fs14.writeFile(path23.join(path23.dirname(resultPath), "report.md"), buildMarkdownReport(result), "utf8");
|
|
20184
20270
|
return result;
|
|
20185
20271
|
}
|
|
20186
20272
|
function printBenchmarkSummary(result, json = false) {
|
|
@@ -20249,7 +20335,7 @@ function registerCreateAgentBenchmarkCommands(program) {
|
|
|
20249
20335
|
addCommonClientOptions(
|
|
20250
20336
|
createAgent.command("rescore").description("Re-run deterministic scoring and optional judge for an existing result.json").argument("<resultPath>", "Path to a stored create-agent benchmark result.json").option("--queue-id <id>", "Langfuse annotation queue id for low-quality runs").option("--judge-model <model>", "Override the judge model").option("--no-sync-langfuse", "Skip Langfuse score sync").option("--no-judge", "Skip optional quality judge").action(async (resultPath, opts) => {
|
|
20251
20337
|
try {
|
|
20252
|
-
const result = await rescoreStoredResult(
|
|
20338
|
+
const result = await rescoreStoredResult(path23.resolve(resultPath), opts);
|
|
20253
20339
|
printBenchmarkSummary(result, Boolean(opts.json));
|
|
20254
20340
|
} catch (error) {
|
|
20255
20341
|
handleCommandError(error);
|
|
@@ -20259,11 +20345,11 @@ function registerCreateAgentBenchmarkCommands(program) {
|
|
|
20259
20345
|
addCommonClientOptions(
|
|
20260
20346
|
createAgent.command("sync-langfuse").description("Sync one stored create-agent benchmark result to Langfuse").argument("<resultPath>", "Path to a stored create-agent benchmark result.json").option("--queue-id <id>", "Langfuse annotation queue id for low-quality runs").action(async (resultPath, opts) => {
|
|
20261
20347
|
try {
|
|
20262
|
-
const result = await readJsonFile(
|
|
20348
|
+
const result = await readJsonFile(path23.resolve(resultPath));
|
|
20263
20349
|
const sync = await syncResultToLangfuse(result, { queueId: asString6(opts.queueId) });
|
|
20264
20350
|
result.langfuse.scoreSync = sync.scoreSync;
|
|
20265
20351
|
result.langfuse.scoreSyncError = sync.scoreSyncError;
|
|
20266
|
-
await writeJsonFile(
|
|
20352
|
+
await writeJsonFile(path23.resolve(resultPath), result);
|
|
20267
20353
|
printOutput({
|
|
20268
20354
|
caseId: result.case.id,
|
|
20269
20355
|
runId: result.runDetail.run.id,
|
|
@@ -20279,7 +20365,7 @@ function registerCreateAgentBenchmarkCommands(program) {
|
|
|
20279
20365
|
addCommonClientOptions(
|
|
20280
20366
|
createAgent.command("report").description("Render the markdown summary for an existing result.json").argument("<resultPath>", "Path to a stored create-agent benchmark result.json").option("--markdown", "Print report markdown instead of the parsed result summary", false).action(async (resultPath, opts) => {
|
|
20281
20367
|
try {
|
|
20282
|
-
const result = await readJsonFile(
|
|
20368
|
+
const result = await readJsonFile(path23.resolve(resultPath));
|
|
20283
20369
|
if (opts.markdown) {
|
|
20284
20370
|
process.stdout.write(buildMarkdownReport(result));
|
|
20285
20371
|
return;
|