rudel 0.1.15 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +89 -72
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1889,7 +1889,7 @@ async function run(app, inputs, context) {
|
|
|
1889
1889
|
// package.json
|
|
1890
1890
|
var package_default = {
|
|
1891
1891
|
name: "rudel",
|
|
1892
|
-
version: "0.1.
|
|
1892
|
+
version: "0.1.17",
|
|
1893
1893
|
type: "module",
|
|
1894
1894
|
description: "CLI for the Coding Agent Analytics Platform rudel.ai",
|
|
1895
1895
|
license: "MIT",
|
|
@@ -1924,7 +1924,7 @@ var package_default = {
|
|
|
1924
1924
|
build: "bun build src/bin/cli.ts --outdir dist --target node",
|
|
1925
1925
|
prepack: "bun run build",
|
|
1926
1926
|
test: "bun test",
|
|
1927
|
-
"test:integration": "bun test ./src/__tests__/api-upload.integration.ts ./src/__tests__/auth-verify.integration.ts ./src/__tests__/auth.e2e.integration.ts"
|
|
1927
|
+
"test:integration": "bun test ./src/__tests__/api-upload.integration.ts ./src/__tests__/uploader-rate-limit.integration.ts ./src/__tests__/auth-verify.integration.ts ./src/__tests__/auth.e2e.integration.ts"
|
|
1928
1928
|
},
|
|
1929
1929
|
dependencies: {
|
|
1930
1930
|
"@clack/prompts": "^1.0.1",
|
|
@@ -6385,7 +6385,7 @@ class ClaudeCodeAdapter {
|
|
|
6385
6385
|
await ingestRudelClaudeSessions(ingestor, [row]);
|
|
6386
6386
|
}
|
|
6387
6387
|
buildRow(input, context) {
|
|
6388
|
-
const now =
|
|
6388
|
+
const now = context.ingestedAt.toISOString().replace("Z", "");
|
|
6389
6389
|
const subagents = {};
|
|
6390
6390
|
if (input.subagents) {
|
|
6391
6391
|
for (const sub of input.subagents) {
|
|
@@ -7717,7 +7717,7 @@ class CodexAdapter {
|
|
|
7717
7717
|
await ingestRudelCodexSessions(ingestor, [row]);
|
|
7718
7718
|
}
|
|
7719
7719
|
buildRow(input, context) {
|
|
7720
|
-
const now =
|
|
7720
|
+
const now = context.ingestedAt.toISOString().replace("Z", "");
|
|
7721
7721
|
const timestamps = this.extractTimestamps(input.content);
|
|
7722
7722
|
return {
|
|
7723
7723
|
session_date: timestamps ? toClickHouseDateTime(timestamps.sessionDate) : now,
|
|
@@ -13157,9 +13157,18 @@ var SessionTagSchema = exports_external.enum([
|
|
|
13157
13157
|
"tests",
|
|
13158
13158
|
"other"
|
|
13159
13159
|
]);
|
|
13160
|
+
var INGEST_AGGREGATE_CONTENT_MAX_BYTES = 128 * 1024 * 1024;
|
|
13161
|
+
var INGEST_MAX_SUBAGENT_COUNT = 512;
|
|
13162
|
+
var INGEST_LIMIT_REASONS = {
|
|
13163
|
+
requestLimit: "request_limit",
|
|
13164
|
+
byteLimit: "byte_limit",
|
|
13165
|
+
sessionLimit: "session_limit",
|
|
13166
|
+
transcriptTooLarge: "transcript_too_large"
|
|
13167
|
+
};
|
|
13168
|
+
var INGEST_CONTENT_MAX_CODE_UNITS = 160 * 1024 * 1024;
|
|
13160
13169
|
var SubagentFileSchema = exports_external.object({
|
|
13161
|
-
agentId: exports_external.string(),
|
|
13162
|
-
content: exports_external.string()
|
|
13170
|
+
agentId: exports_external.string().max(200),
|
|
13171
|
+
content: exports_external.string().max(INGEST_CONTENT_MAX_CODE_UNITS)
|
|
13163
13172
|
});
|
|
13164
13173
|
var IngestSessionInputSchema = exports_external.object({
|
|
13165
13174
|
source: SourceSchema.default("claude_code"),
|
|
@@ -13171,8 +13180,8 @@ var IngestSessionInputSchema = exports_external.object({
|
|
|
13171
13180
|
gitBranch: exports_external.string().max(200).optional(),
|
|
13172
13181
|
gitSha: exports_external.string().max(200).optional(),
|
|
13173
13182
|
tag: SessionTagSchema.optional(),
|
|
13174
|
-
content: exports_external.string(),
|
|
13175
|
-
subagents: exports_external.array(SubagentFileSchema).optional(),
|
|
13183
|
+
content: exports_external.string().max(INGEST_CONTENT_MAX_CODE_UNITS),
|
|
13184
|
+
subagents: exports_external.array(SubagentFileSchema).max(INGEST_MAX_SUBAGENT_COUNT).refine((subagents) => new Set(subagents.map((subagent) => subagent.agentId)).size === subagents.length, { message: "Subagent agentId values must be unique" }).optional(),
|
|
13176
13185
|
organizationId: exports_external.string().max(200).optional(),
|
|
13177
13186
|
client_surface: ProductAnalyticsClientSurfaceSchema.optional(),
|
|
13178
13187
|
upload_mode: ProductAnalyticsUploadModeSchema.optional(),
|
|
@@ -18214,6 +18223,13 @@ function formatUploadError(error) {
|
|
|
18214
18223
|
}
|
|
18215
18224
|
if (isRateLimited(error)) {
|
|
18216
18225
|
const data = getErrorData(error);
|
|
18226
|
+
const isRequestLimit = data.reason === INGEST_LIMIT_REASONS.requestLimit;
|
|
18227
|
+
if (isRequestLimit || data.reason === INGEST_LIMIT_REASONS.byteLimit) {
|
|
18228
|
+
const limit2 = data.limit === null ? null : isRequestLimit ? `${data.limit} requests` : `${formatMebibytes(data.limit)} MiB`;
|
|
18229
|
+
const detail = limit2 && data.windowSeconds ? ` (${limit2} per ${Math.round(data.windowSeconds / 60)} min)` : "";
|
|
18230
|
+
const kind = isRequestLimit ? "request" : "byte";
|
|
18231
|
+
return `Ingest ${kind} limit reached${detail}. Wait and retry with: rudel upload --retry`;
|
|
18232
|
+
}
|
|
18217
18233
|
const windowMin = data?.windowSeconds ? Math.round(data.windowSeconds / 60) : 60;
|
|
18218
18234
|
const limit = data?.limit ?? "unknown";
|
|
18219
18235
|
return `Rate limit reached (${limit} sessions per ${windowMin} min). Wait and retry with: rudel upload --retry`;
|
|
@@ -18222,6 +18238,10 @@ function formatUploadError(error) {
|
|
|
18222
18238
|
return "This session ID is already owned by another organization member. Upload it from the original member account or use a different session ID.";
|
|
18223
18239
|
}
|
|
18224
18240
|
if (isPayloadTooLarge(error)) {
|
|
18241
|
+
const data = getErrorData(error);
|
|
18242
|
+
if (data.reason === INGEST_LIMIT_REASONS.transcriptTooLarge) {
|
|
18243
|
+
return formatTranscriptTooLargeError(data.actualBytes, data.maxBytes);
|
|
18244
|
+
}
|
|
18225
18245
|
return formatPayloadTooLargeError(error);
|
|
18226
18246
|
}
|
|
18227
18247
|
if (isServerError(error)) {
|
|
@@ -18261,8 +18281,10 @@ function getErrorData(error) {
|
|
|
18261
18281
|
const data = isRecord(error.data) ? error.data : null;
|
|
18262
18282
|
return {
|
|
18263
18283
|
authMessage: getStringField(data, "authMessage"),
|
|
18284
|
+
actualBytes: getNumberField(data, "actualBytes"),
|
|
18264
18285
|
code: getStringField(data, "code"),
|
|
18265
18286
|
limit: getNumberField(data, "limit"),
|
|
18287
|
+
maxBytes: getNumberField(data, "maxBytes"),
|
|
18266
18288
|
reason: getStringField(data, "reason"),
|
|
18267
18289
|
tryAgainIn: getNumberField(data, "tryAgainIn"),
|
|
18268
18290
|
windowSeconds: getNumberField(data, "windowSeconds")
|
|
@@ -18292,6 +18314,15 @@ function formatWait(milliseconds) {
|
|
|
18292
18314
|
return `${hours} hr`;
|
|
18293
18315
|
}
|
|
18294
18316
|
async function uploadSession(request, config) {
|
|
18317
|
+
const maxAggregateBytes = config.maxAggregateBytes ?? INGEST_AGGREGATE_CONTENT_MAX_BYTES;
|
|
18318
|
+
const aggregateBytes = getUploadAggregateBytes(request);
|
|
18319
|
+
if (aggregateBytes > maxAggregateBytes) {
|
|
18320
|
+
return {
|
|
18321
|
+
success: false,
|
|
18322
|
+
error: formatTranscriptTooLargeError(aggregateBytes, maxAggregateBytes),
|
|
18323
|
+
attempts: 0
|
|
18324
|
+
};
|
|
18325
|
+
}
|
|
18295
18326
|
const link = new RPCLink({
|
|
18296
18327
|
url: config.endpoint,
|
|
18297
18328
|
headers: config.authType === "api-key" ? { "x-api-key": config.token } : { Authorization: `Bearer ${config.token}` }
|
|
@@ -18330,6 +18361,20 @@ async function uploadSession(request, config) {
|
|
|
18330
18361
|
attempts: MAX_ATTEMPTS
|
|
18331
18362
|
};
|
|
18332
18363
|
}
|
|
18364
|
+
function getUploadAggregateBytes(request) {
|
|
18365
|
+
return Buffer.byteLength(request.content, "utf8") + (request.subagents ?? []).reduce((total, subagent) => total + Buffer.byteLength(subagent.content, "utf8"), 0);
|
|
18366
|
+
}
|
|
18367
|
+
function formatTranscriptTooLargeError(actualBytes, maxBytes) {
|
|
18368
|
+
if (actualBytes === null || maxBytes === null) {
|
|
18369
|
+
return "Session transcript payload exceeds the per-session limit. Reduce the transcript/subagent payload before retrying.";
|
|
18370
|
+
}
|
|
18371
|
+
const actualText = `${formatMebibytes(actualBytes)} MiB`;
|
|
18372
|
+
const limitText = `the ${formatMebibytes(maxBytes)} MiB per-session limit`;
|
|
18373
|
+
return `Session transcript payload is ${actualText}, above ${limitText}. Reduce the transcript/subagent payload before retrying.`;
|
|
18374
|
+
}
|
|
18375
|
+
function formatMebibytes(bytes) {
|
|
18376
|
+
return (bytes / (1024 * 1024)).toFixed(2);
|
|
18377
|
+
}
|
|
18333
18378
|
|
|
18334
18379
|
// src/commands/enable.ts
|
|
18335
18380
|
async function runEnable() {
|
|
@@ -18356,10 +18401,8 @@ async function runEnable() {
|
|
|
18356
18401
|
failureStage: "auth_verify",
|
|
18357
18402
|
error: auth.reason
|
|
18358
18403
|
});
|
|
18359
|
-
R2.error(auth.message);
|
|
18360
18404
|
Gt("Run `rudel login` to authenticate.");
|
|
18361
|
-
|
|
18362
|
-
return;
|
|
18405
|
+
return new Error(auth.message);
|
|
18363
18406
|
}
|
|
18364
18407
|
const { credentials } = auth;
|
|
18365
18408
|
let orgs;
|
|
@@ -18376,9 +18419,7 @@ async function runEnable() {
|
|
|
18376
18419
|
error,
|
|
18377
18420
|
userId: auth.user.id
|
|
18378
18421
|
});
|
|
18379
|
-
|
|
18380
|
-
process.exitCode = 1;
|
|
18381
|
-
return;
|
|
18422
|
+
return new Error("Failed to fetch organizations. Check your connection.");
|
|
18382
18423
|
}
|
|
18383
18424
|
}
|
|
18384
18425
|
if (orgs.length === 0) {
|
|
@@ -18388,10 +18429,8 @@ async function runEnable() {
|
|
|
18388
18429
|
error: new Error("No organizations found"),
|
|
18389
18430
|
userId: auth.user.id
|
|
18390
18431
|
});
|
|
18391
|
-
R2.error("No organizations found.");
|
|
18392
18432
|
Gt("Create one at app.rudel.ai first.");
|
|
18393
|
-
|
|
18394
|
-
return;
|
|
18433
|
+
return new Error("No organizations found.");
|
|
18395
18434
|
}
|
|
18396
18435
|
const cwd = process.cwd();
|
|
18397
18436
|
const existingOrgId = await getProjectOrgId(cwd);
|
|
@@ -18538,7 +18577,7 @@ async function runEnable() {
|
|
|
18538
18577
|
}
|
|
18539
18578
|
Gt("Done!");
|
|
18540
18579
|
if (totalFailed > 0 || hookInstallFailures > 0) {
|
|
18541
|
-
|
|
18580
|
+
return new Error(`Enable completed with ${hookInstallFailures} hook installation failure(s) and ${totalFailed} upload failure(s).`);
|
|
18542
18581
|
}
|
|
18543
18582
|
}
|
|
18544
18583
|
var enableCommand = buildCommand({
|
|
@@ -20789,9 +20828,7 @@ async function runLogin(flags) {
|
|
|
20789
20828
|
deviceCode = await requestDeviceCode(flags.apiBase);
|
|
20790
20829
|
} catch (error) {
|
|
20791
20830
|
captureLoginFailure("device_code_request", error);
|
|
20792
|
-
|
|
20793
|
-
process.exitCode = 1;
|
|
20794
|
-
return;
|
|
20831
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
20795
20832
|
}
|
|
20796
20833
|
const verifyUrl = deviceCode.verification_uri_complete ?? `${deviceCode.verification_uri}?user_code=${encodeURIComponent(deviceCode.user_code)}`;
|
|
20797
20834
|
captureCliProductAnalyticsEvent({
|
|
@@ -20821,9 +20858,7 @@ ${verifyUrl}`);
|
|
|
20821
20858
|
const failureReason = normalizeFailureReason(error);
|
|
20822
20859
|
captureLoginFailure(failureReason === "timeout" ? "browser_approval_timeout" : "token_exchange", error);
|
|
20823
20860
|
spin.stop("Authentication failed");
|
|
20824
|
-
|
|
20825
|
-
process.exitCode = 1;
|
|
20826
|
-
return;
|
|
20861
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
20827
20862
|
}
|
|
20828
20863
|
spin.message("Creating ingest token...");
|
|
20829
20864
|
let ingestKey;
|
|
@@ -20832,9 +20867,7 @@ ${verifyUrl}`);
|
|
|
20832
20867
|
} catch (error) {
|
|
20833
20868
|
captureLoginFailure("api_key_create", error);
|
|
20834
20869
|
spin.stop("Authentication failed");
|
|
20835
|
-
|
|
20836
|
-
process.exitCode = 1;
|
|
20837
|
-
return;
|
|
20870
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
20838
20871
|
}
|
|
20839
20872
|
const client2 = createApiClient({
|
|
20840
20873
|
apiBaseUrl: flags.apiBase,
|
|
@@ -20857,9 +20890,7 @@ ${verifyUrl}`);
|
|
|
20857
20890
|
} catch (error) {
|
|
20858
20891
|
captureLoginFailure("account_fetch", error);
|
|
20859
20892
|
spin.stop("Authentication failed");
|
|
20860
|
-
|
|
20861
|
-
process.exitCode = 1;
|
|
20862
|
-
return;
|
|
20893
|
+
return new Error("Login failed: unable to fetch account details");
|
|
20863
20894
|
}
|
|
20864
20895
|
try {
|
|
20865
20896
|
saveCredentials({
|
|
@@ -20873,9 +20904,7 @@ ${verifyUrl}`);
|
|
|
20873
20904
|
} catch (error) {
|
|
20874
20905
|
captureLoginFailure("account_fetch", error);
|
|
20875
20906
|
spin.stop("Authentication failed");
|
|
20876
|
-
|
|
20877
|
-
process.exitCode = 1;
|
|
20878
|
-
return;
|
|
20907
|
+
return new Error("Login failed: unable to persist credentials");
|
|
20879
20908
|
}
|
|
20880
20909
|
captureCliProductAnalyticsEvent({
|
|
20881
20910
|
distinctId: user.id,
|
|
@@ -20921,26 +20950,35 @@ var loginCommand = buildCommand({
|
|
|
20921
20950
|
});
|
|
20922
20951
|
|
|
20923
20952
|
// src/commands/logout.ts
|
|
20924
|
-
async function runLogout() {
|
|
20953
|
+
async function runLogout(flags) {
|
|
20925
20954
|
const credentials = loadCredentials();
|
|
20926
20955
|
if (!credentials) {
|
|
20927
20956
|
R2.info("Not logged in.");
|
|
20928
20957
|
return;
|
|
20929
20958
|
}
|
|
20930
|
-
if (credentials.authType === "api-key") {
|
|
20959
|
+
if (credentials.authType === "api-key" && !flags.localOnly) {
|
|
20931
20960
|
try {
|
|
20932
20961
|
const client2 = createApiClient(credentials);
|
|
20933
20962
|
await client2.cli.revokeToken();
|
|
20934
|
-
} catch {
|
|
20935
|
-
|
|
20963
|
+
} catch (error) {
|
|
20964
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
20965
|
+
return new Error(`Failed to revoke token on server: ${message}. Credentials were kept; retry or run \`rudel logout --local-only\`.`);
|
|
20936
20966
|
}
|
|
20937
20967
|
}
|
|
20938
20968
|
clearCredentials();
|
|
20939
|
-
R2.success("Logged out successfully.");
|
|
20969
|
+
R2.success(flags.localOnly ? "Logged out locally. Server token was not revoked." : "Logged out successfully.");
|
|
20940
20970
|
}
|
|
20941
20971
|
var logoutCommand = buildCommand({
|
|
20942
20972
|
loader: async () => ({ default: runLogout }),
|
|
20943
|
-
parameters: {
|
|
20973
|
+
parameters: {
|
|
20974
|
+
flags: {
|
|
20975
|
+
localOnly: {
|
|
20976
|
+
kind: "boolean",
|
|
20977
|
+
brief: "Clear local credentials without revoking the server token",
|
|
20978
|
+
default: false
|
|
20979
|
+
}
|
|
20980
|
+
}
|
|
20981
|
+
},
|
|
20944
20982
|
docs: {
|
|
20945
20983
|
brief: "Log out and remove stored credentials"
|
|
20946
20984
|
}
|
|
@@ -20951,10 +20989,8 @@ async function runSetOrg() {
|
|
|
20951
20989
|
Wt2("rudel set-org");
|
|
20952
20990
|
const credentials = loadCredentials();
|
|
20953
20991
|
if (!credentials) {
|
|
20954
|
-
R2.error("Not authenticated.");
|
|
20955
20992
|
Gt("Run `rudel login` first.");
|
|
20956
|
-
|
|
20957
|
-
return;
|
|
20993
|
+
return new Error("Not authenticated.");
|
|
20958
20994
|
}
|
|
20959
20995
|
let orgs;
|
|
20960
20996
|
if (credentials.authType === "api-key") {
|
|
@@ -20964,16 +21000,12 @@ async function runSetOrg() {
|
|
|
20964
21000
|
try {
|
|
20965
21001
|
orgs = await client2.listMyOrganizations();
|
|
20966
21002
|
} catch {
|
|
20967
|
-
|
|
20968
|
-
process.exitCode = 1;
|
|
20969
|
-
return;
|
|
21003
|
+
return new Error("Failed to fetch organizations. Check your connection.");
|
|
20970
21004
|
}
|
|
20971
21005
|
}
|
|
20972
21006
|
if (orgs.length === 0) {
|
|
20973
|
-
R2.error("No organizations found.");
|
|
20974
21007
|
Gt("Create one at app.rudel.ai first.");
|
|
20975
|
-
|
|
20976
|
-
return;
|
|
21008
|
+
return new Error("No organizations found.");
|
|
20977
21009
|
}
|
|
20978
21010
|
const cwd = process.cwd();
|
|
20979
21011
|
const currentOrgId = await getProjectOrgId(cwd);
|
|
@@ -21147,9 +21179,7 @@ function validateNotSubagent(filename) {
|
|
|
21147
21179
|
async function runInteractiveUpload(flags) {
|
|
21148
21180
|
const credentials = loadCredentials();
|
|
21149
21181
|
if (!credentials && !flags.dryRun) {
|
|
21150
|
-
|
|
21151
|
-
process.exitCode = 1;
|
|
21152
|
-
return;
|
|
21182
|
+
return new Error("Not authenticated. Run `rudel login` first.");
|
|
21153
21183
|
}
|
|
21154
21184
|
Wt2("rudel upload");
|
|
21155
21185
|
const spin = be();
|
|
@@ -21242,7 +21272,7 @@ async function runInteractiveUpload(flags) {
|
|
|
21242
21272
|
Gt("Done!");
|
|
21243
21273
|
}
|
|
21244
21274
|
if (summary.failed > 0) {
|
|
21245
|
-
|
|
21275
|
+
return new Error(`${summary.failed} upload(s) failed.`);
|
|
21246
21276
|
}
|
|
21247
21277
|
}
|
|
21248
21278
|
function getAdapterName(source) {
|
|
@@ -21254,26 +21284,18 @@ function sessionCountHint(count) {
|
|
|
21254
21284
|
async function runSingleUpload(flags, session) {
|
|
21255
21285
|
const write = (msg) => {
|
|
21256
21286
|
process.stdout.write(`${msg}
|
|
21257
|
-
`);
|
|
21258
|
-
};
|
|
21259
|
-
const writeError = (msg) => {
|
|
21260
|
-
process.stderr.write(`${msg}
|
|
21261
21287
|
`);
|
|
21262
21288
|
};
|
|
21263
21289
|
const credentials = loadCredentials();
|
|
21264
21290
|
if (!credentials && !flags.dryRun) {
|
|
21265
|
-
|
|
21266
|
-
process.exitCode = 1;
|
|
21267
|
-
return;
|
|
21291
|
+
return new Error("Not authenticated. Run `rudel login` first.");
|
|
21268
21292
|
}
|
|
21269
21293
|
write(`Resolving session: ${session}`);
|
|
21270
21294
|
let sessionInfo;
|
|
21271
21295
|
try {
|
|
21272
21296
|
sessionInfo = await resolveSession(session);
|
|
21273
21297
|
} catch (error) {
|
|
21274
|
-
|
|
21275
|
-
process.exitCode = 1;
|
|
21276
|
-
return;
|
|
21298
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
21277
21299
|
}
|
|
21278
21300
|
write(`Found session at: ${sessionInfo.transcriptPath}`);
|
|
21279
21301
|
const gitInfo = await getGitInfo(sessionInfo.projectPath);
|
|
@@ -21331,16 +21353,13 @@ async function runSingleUpload(flags, session) {
|
|
|
21331
21353
|
if (result.success) {
|
|
21332
21354
|
write("Upload successful!");
|
|
21333
21355
|
} else {
|
|
21334
|
-
|
|
21335
|
-
process.exitCode = 1;
|
|
21356
|
+
return new Error(`Upload failed: ${result.error}`);
|
|
21336
21357
|
}
|
|
21337
21358
|
}
|
|
21338
21359
|
async function runRetryUpload(flags) {
|
|
21339
21360
|
const credentials = loadCredentials();
|
|
21340
21361
|
if (!credentials) {
|
|
21341
|
-
|
|
21342
|
-
process.exitCode = 1;
|
|
21343
|
-
return;
|
|
21362
|
+
return new Error("Not authenticated. Run `rudel login` first.");
|
|
21344
21363
|
}
|
|
21345
21364
|
Wt2("rudel upload --retry");
|
|
21346
21365
|
const failures = await loadFailedUploads();
|
|
@@ -21403,7 +21422,7 @@ async function runRetryUpload(flags) {
|
|
|
21403
21422
|
renderBatchSummary(summary);
|
|
21404
21423
|
Gt("Done!");
|
|
21405
21424
|
if (summary.failed > 0) {
|
|
21406
|
-
|
|
21425
|
+
return new Error(`${summary.failed} upload(s) failed.`);
|
|
21407
21426
|
}
|
|
21408
21427
|
}
|
|
21409
21428
|
async function runUpload(flags, ...sessions) {
|
|
@@ -21487,11 +21506,9 @@ async function runWhoami() {
|
|
|
21487
21506
|
if (!result.authenticated) {
|
|
21488
21507
|
if (result.reason === "no_credentials") {
|
|
21489
21508
|
R2.info("Not logged in. Run `rudel login` to authenticate.");
|
|
21490
|
-
|
|
21491
|
-
R2.error(result.message);
|
|
21492
|
-
process.exitCode = 1;
|
|
21509
|
+
return;
|
|
21493
21510
|
}
|
|
21494
|
-
return;
|
|
21511
|
+
return new Error(result.message);
|
|
21495
21512
|
}
|
|
21496
21513
|
R2.info(`Logged in as ${result.user.name} (${result.user.email})`);
|
|
21497
21514
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rudel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI for the Coding Agent Analytics Platform rudel.ai",
|
|
6
6
|
"license": "MIT",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"build": "bun build src/bin/cli.ts --outdir dist --target node",
|
|
36
36
|
"prepack": "bun run build",
|
|
37
37
|
"test": "bun test",
|
|
38
|
-
"test:integration": "bun test ./src/__tests__/api-upload.integration.ts ./src/__tests__/auth-verify.integration.ts ./src/__tests__/auth.e2e.integration.ts"
|
|
38
|
+
"test:integration": "bun test ./src/__tests__/api-upload.integration.ts ./src/__tests__/uploader-rate-limit.integration.ts ./src/__tests__/auth-verify.integration.ts ./src/__tests__/auth.e2e.integration.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@clack/prompts": "^1.0.1",
|