rush-ai 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/index.js +146 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,6 +57,7 @@ npx rush-ai <command> # Or use npx directly
|
|
|
57
57
|
| `task status <id>` | - | Check task status |
|
|
58
58
|
| `task result <id>` | - | Get task result and file summary |
|
|
59
59
|
| `task files <id>` | - | List and download task artifacts |
|
|
60
|
+
| `task messages <id>` | - | View conversation messages for a task |
|
|
60
61
|
| `task list` | `task ls` | List tasks |
|
|
61
62
|
| `task watch <id>` | - | Stream task execution in real-time (SSE) |
|
|
62
63
|
| `task cancel <id>` | - | Cancel a running task |
|
|
@@ -124,6 +125,13 @@ rush-ai task send <task-id> -p "Change the button color to blue"
|
|
|
124
125
|
# Pipe prompt from stdin
|
|
125
126
|
echo "Refactor the auth module" | rush-ai task create -a rush
|
|
126
127
|
|
|
128
|
+
# View conversation messages
|
|
129
|
+
rush-ai task messages <task-id>
|
|
130
|
+
rush-ai task messages <task-id> -c <conversation-id>
|
|
131
|
+
rush-ai task messages <task-id> --last 5 --role user
|
|
132
|
+
rush-ai task messages <task-id> --compact
|
|
133
|
+
rush-ai task messages <task-id> --json
|
|
134
|
+
|
|
127
135
|
# List recent tasks
|
|
128
136
|
rush-ai task list -l 10 -s completed
|
|
129
137
|
```
|
package/dist/index.js
CHANGED
|
@@ -3508,6 +3508,54 @@ function registerDeploySubcommand(task, program) {
|
|
|
3508
3508
|
}
|
|
3509
3509
|
|
|
3510
3510
|
// src/commands/task/index.ts
|
|
3511
|
+
var MAX_TEXT_LENGTH = 500;
|
|
3512
|
+
function truncateText(text) {
|
|
3513
|
+
if (text.length <= MAX_TEXT_LENGTH) return text;
|
|
3514
|
+
return text.slice(0, MAX_TEXT_LENGTH) + "...";
|
|
3515
|
+
}
|
|
3516
|
+
function summarizeTools(parts) {
|
|
3517
|
+
const toolParts = parts.filter(
|
|
3518
|
+
(p) => p.type === "tool-invocation" || p.type.startsWith("tool-")
|
|
3519
|
+
);
|
|
3520
|
+
if (toolParts.length === 0) return "";
|
|
3521
|
+
return toolParts.map((p) => {
|
|
3522
|
+
if (p.toolName) return p.toolName;
|
|
3523
|
+
if (p.type.startsWith("tool-")) return p.type.slice(5);
|
|
3524
|
+
return "unknown";
|
|
3525
|
+
}).join(", ");
|
|
3526
|
+
}
|
|
3527
|
+
function formatTimestamp(ts) {
|
|
3528
|
+
if (!ts) return "";
|
|
3529
|
+
const d = new Date(ts);
|
|
3530
|
+
return d.toLocaleString();
|
|
3531
|
+
}
|
|
3532
|
+
function renderMessages(messages, conversationId, compact) {
|
|
3533
|
+
output.log(
|
|
3534
|
+
output.bold(`Conversation ${conversationId} \u2014 ${messages.length} messages`)
|
|
3535
|
+
);
|
|
3536
|
+
output.newline();
|
|
3537
|
+
for (const msg of messages) {
|
|
3538
|
+
const ts = formatTimestamp(msg.createdAt);
|
|
3539
|
+
output.log(`[${msg.role}] ${ts}`);
|
|
3540
|
+
const textParts = (msg.parts ?? []).filter(
|
|
3541
|
+
(p) => p.type === "text" && p.text
|
|
3542
|
+
);
|
|
3543
|
+
if (textParts.length > 0) {
|
|
3544
|
+
for (const tp of textParts) {
|
|
3545
|
+
output.log(` ${truncateText(tp.text)}`);
|
|
3546
|
+
}
|
|
3547
|
+
} else if (msg.content) {
|
|
3548
|
+
output.log(` ${truncateText(msg.content)}`);
|
|
3549
|
+
}
|
|
3550
|
+
if (!compact && msg.role === "assistant" && msg.parts) {
|
|
3551
|
+
const toolSummary = summarizeTools(msg.parts);
|
|
3552
|
+
if (toolSummary) {
|
|
3553
|
+
output.dim(` Tools: ${toolSummary}`);
|
|
3554
|
+
}
|
|
3555
|
+
}
|
|
3556
|
+
output.newline();
|
|
3557
|
+
}
|
|
3558
|
+
}
|
|
3511
3559
|
var VALID_CATEGORIES = ["code", "image", "document", "other"];
|
|
3512
3560
|
function sanitizeFilePath(filePath, outputDir) {
|
|
3513
3561
|
let stripped = filePath.replace(/^[/\\]+/, "").replace(/^[a-zA-Z]:/, "");
|
|
@@ -3521,8 +3569,25 @@ function sanitizeFilePath(filePath, outputDir) {
|
|
|
3521
3569
|
}
|
|
3522
3570
|
return target;
|
|
3523
3571
|
}
|
|
3524
|
-
async function downloadFile(
|
|
3525
|
-
|
|
3572
|
+
async function downloadFile(file, destPath, client) {
|
|
3573
|
+
let response = null;
|
|
3574
|
+
if (file.ossPath) {
|
|
3575
|
+
try {
|
|
3576
|
+
const proxyResponse = await client.fetchRaw(
|
|
3577
|
+
`/api/files/oss-preview?action=file&path=${encodeURIComponent(file.ossPath)}`
|
|
3578
|
+
);
|
|
3579
|
+
if (proxyResponse.ok) {
|
|
3580
|
+
response = proxyResponse;
|
|
3581
|
+
}
|
|
3582
|
+
} catch {
|
|
3583
|
+
}
|
|
3584
|
+
}
|
|
3585
|
+
if (!response && file.ossUrl) {
|
|
3586
|
+
response = await fetch(file.ossUrl);
|
|
3587
|
+
}
|
|
3588
|
+
if (!response) {
|
|
3589
|
+
throw new Error("No download path available");
|
|
3590
|
+
}
|
|
3526
3591
|
if (!response.ok) {
|
|
3527
3592
|
throw new Error(
|
|
3528
3593
|
`Download failed: ${response.status} ${response.statusText}`
|
|
@@ -3619,8 +3684,23 @@ function registerTaskCommand(program) {
|
|
|
3619
3684
|
output.log(output.bold(`Task ${data.id}`));
|
|
3620
3685
|
output.log(` Agent: ${data.agent}`);
|
|
3621
3686
|
output.log(` Status: ${data.status}`);
|
|
3687
|
+
if (data.template) {
|
|
3688
|
+
output.log(` Template: ${data.template}`);
|
|
3689
|
+
}
|
|
3690
|
+
if (data.podImageName) {
|
|
3691
|
+
output.log(` Image: ${data.podImageName}`);
|
|
3692
|
+
}
|
|
3622
3693
|
output.log(` Created: ${new Date(data.createdAt).toLocaleString()}`);
|
|
3623
3694
|
output.log(` Updated: ${new Date(data.updatedAt).toLocaleString()}`);
|
|
3695
|
+
if (data.previewUrl) {
|
|
3696
|
+
output.log(` Preview: ${data.previewUrl}`);
|
|
3697
|
+
}
|
|
3698
|
+
if (data.gitRepoUrl) {
|
|
3699
|
+
output.log(` Git: ${data.gitRepoUrl}`);
|
|
3700
|
+
}
|
|
3701
|
+
if (data.deployedProductionUrl) {
|
|
3702
|
+
output.log(` Production: ${data.deployedProductionUrl}`);
|
|
3703
|
+
}
|
|
3624
3704
|
if (data.error) {
|
|
3625
3705
|
output.error(` Error: ${data.error}`);
|
|
3626
3706
|
}
|
|
@@ -3704,8 +3784,8 @@ function registerTaskCommand(program) {
|
|
|
3704
3784
|
output.error(`File not found: ${options.download}`);
|
|
3705
3785
|
process.exit(1);
|
|
3706
3786
|
}
|
|
3707
|
-
if (!file.ossUrl) {
|
|
3708
|
-
output.error(`File "${file.fileName}" has no download
|
|
3787
|
+
if (!file.ossPath && !file.ossUrl) {
|
|
3788
|
+
output.error(`File "${file.fileName}" has no download path.`);
|
|
3709
3789
|
process.exit(1);
|
|
3710
3790
|
}
|
|
3711
3791
|
const outputDir = options.output || ".";
|
|
@@ -3714,7 +3794,7 @@ function registerTaskCommand(program) {
|
|
|
3714
3794
|
output.error(`Unsafe file path: ${file.filePath}`);
|
|
3715
3795
|
process.exit(1);
|
|
3716
3796
|
}
|
|
3717
|
-
await downloadFile(file
|
|
3797
|
+
await downloadFile(file, destPath, client);
|
|
3718
3798
|
if (format === "json") {
|
|
3719
3799
|
output.log(
|
|
3720
3800
|
JSON.stringify(
|
|
@@ -3734,10 +3814,10 @@ function registerTaskCommand(program) {
|
|
|
3734
3814
|
let skipped = 0;
|
|
3735
3815
|
let failed = 0;
|
|
3736
3816
|
for (const file of files) {
|
|
3737
|
-
if (!file.ossUrl) {
|
|
3817
|
+
if (!file.ossPath && !file.ossUrl) {
|
|
3738
3818
|
skipped++;
|
|
3739
3819
|
if (format !== "json") {
|
|
3740
|
-
output.dim(` Skipped (no
|
|
3820
|
+
output.dim(` Skipped (no download path): ${file.filePath}`);
|
|
3741
3821
|
}
|
|
3742
3822
|
continue;
|
|
3743
3823
|
}
|
|
@@ -3750,7 +3830,7 @@ function registerTaskCommand(program) {
|
|
|
3750
3830
|
continue;
|
|
3751
3831
|
}
|
|
3752
3832
|
try {
|
|
3753
|
-
await downloadFile(file
|
|
3833
|
+
await downloadFile(file, destPath, client);
|
|
3754
3834
|
downloaded++;
|
|
3755
3835
|
if (format !== "json") {
|
|
3756
3836
|
output.dim(` Downloaded: ${file.filePath}`);
|
|
@@ -3807,6 +3887,64 @@ function registerTaskCommand(program) {
|
|
|
3807
3887
|
output.log(formatOutput(rows, format));
|
|
3808
3888
|
}
|
|
3809
3889
|
);
|
|
3890
|
+
task.command("messages").description("View conversation messages for a task").argument("<id>", "Task ID (project ID)").option("-c, --conversation <id>", "Specific conversation ID").option("--last <n>", "Show only last N messages").option("--role <role>", "Filter by role (user, assistant, system)").option("--compact", "Text-only output, no tool details or reasoning").action(
|
|
3891
|
+
async (id, options) => {
|
|
3892
|
+
requireAuth();
|
|
3893
|
+
const format = resolveFormat(program.opts());
|
|
3894
|
+
const client = createClient();
|
|
3895
|
+
let conversationId = options.conversation;
|
|
3896
|
+
if (!conversationId) {
|
|
3897
|
+
const { data: convData } = await client.get(
|
|
3898
|
+
`/api/chat/${encodeURIComponent(id)}/conversations`
|
|
3899
|
+
);
|
|
3900
|
+
if (!convData.conversations || convData.conversations.length === 0) {
|
|
3901
|
+
if (format === "json") {
|
|
3902
|
+
output.log(
|
|
3903
|
+
JSON.stringify({ messages: [], conversationId: null }, null, 2)
|
|
3904
|
+
);
|
|
3905
|
+
} else {
|
|
3906
|
+
output.info("No conversations found for this task.");
|
|
3907
|
+
}
|
|
3908
|
+
return;
|
|
3909
|
+
}
|
|
3910
|
+
conversationId = convData.conversations[0].id;
|
|
3911
|
+
}
|
|
3912
|
+
const { data } = await client.get(
|
|
3913
|
+
`/api/chat/${encodeURIComponent(id)}/conversations/${encodeURIComponent(conversationId)}`
|
|
3914
|
+
);
|
|
3915
|
+
let messages = data.messages ?? [];
|
|
3916
|
+
if (messages.length === 0) {
|
|
3917
|
+
if (format === "json") {
|
|
3918
|
+
output.log(
|
|
3919
|
+
JSON.stringify({ messages: [], conversationId }, null, 2)
|
|
3920
|
+
);
|
|
3921
|
+
} else {
|
|
3922
|
+
output.info("No messages in this conversation.");
|
|
3923
|
+
}
|
|
3924
|
+
return;
|
|
3925
|
+
}
|
|
3926
|
+
if (options.role) {
|
|
3927
|
+
messages = messages.filter((m) => m.role === options.role);
|
|
3928
|
+
}
|
|
3929
|
+
if (options.last) {
|
|
3930
|
+
const n = parseInt(options.last, 10);
|
|
3931
|
+
if (!isNaN(n) && n > 0) {
|
|
3932
|
+
messages = messages.slice(-n);
|
|
3933
|
+
}
|
|
3934
|
+
}
|
|
3935
|
+
if (format === "json") {
|
|
3936
|
+
output.log(
|
|
3937
|
+
JSON.stringify(
|
|
3938
|
+
{ messages, conversationId, metadata: data.metadata },
|
|
3939
|
+
null,
|
|
3940
|
+
2
|
|
3941
|
+
)
|
|
3942
|
+
);
|
|
3943
|
+
} else {
|
|
3944
|
+
renderMessages(messages, conversationId, !!options.compact);
|
|
3945
|
+
}
|
|
3946
|
+
}
|
|
3947
|
+
);
|
|
3810
3948
|
task.command("list").alias("ls").description("List tasks").option("-l, --limit <limit>", "Maximum number of tasks", "20").option("-s, --status <status>", "Filter by status").action(async (options) => {
|
|
3811
3949
|
requireAuth();
|
|
3812
3950
|
const format = resolveFormat(program.opts());
|