@ganakailabs/cloudeval-cli 0.19.3 → 0.20.1
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 +31 -4
- package/dist/{App-PS547LKZ.js → App-FJ7ANARO.js} +1570 -512
- package/dist/{Banner-XZFAVVR2.js → Banner-NJ6WDPDB.js} +3 -3
- package/dist/Onboarding-3NZCPBCO.js +8 -0
- package/dist/{ReportDashboard-6JFJJVRW.js → ReportDashboard-T63UGA7M.js} +1 -1
- package/dist/{chunk-4QIKW5TJ.js → chunk-2D4BE3OS.js} +68 -7
- package/dist/{chunk-3DVPEIVB.js → chunk-2GTSKMHA.js} +2 -2
- package/dist/{chunk-SCKO2ZTZ.js → chunk-AWSLWW4V.js} +1 -1
- package/dist/{chunk-UOCT7M4J.js → chunk-QKZCKI55.js} +8 -6
- package/dist/chunk-RCRNSEQS.js +1014 -0
- package/dist/{chunk-EPKCZBPH.js → chunk-RGFWN4RL.js} +2 -2
- package/dist/cli.js +929 -1034
- package/dist/{dist-I4IPYCRC.js → dist-TBAQ5KOK.js} +7 -1
- package/package.json +2 -2
- package/sbom.spdx.json +1 -1
- package/dist/Onboarding-HVCYIPTL.js +0 -8
- package/dist/chunk-TA4WC462.js +0 -174
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
buildFrontendUrl,
|
|
4
|
+
deleteSession,
|
|
5
|
+
exportSessions,
|
|
6
|
+
getActiveConfigProfile,
|
|
7
|
+
getCliConfigPath,
|
|
8
|
+
getCloudevalConfigDir,
|
|
4
9
|
getFirstNameForDisplay,
|
|
10
|
+
getSession,
|
|
11
|
+
listCliConfigProfiles,
|
|
12
|
+
listSessions,
|
|
13
|
+
loadCliConfig,
|
|
14
|
+
normalizeCliMode,
|
|
15
|
+
normalizeConfigProfile,
|
|
5
16
|
openExternalUrl,
|
|
6
|
-
|
|
7
|
-
|
|
17
|
+
pruneSessions,
|
|
18
|
+
readCliConfigValue,
|
|
19
|
+
recordSessionTurn,
|
|
20
|
+
renameSession,
|
|
21
|
+
resolveFrontendBaseUrl,
|
|
22
|
+
resolveSessionReference,
|
|
23
|
+
saveCliConfig,
|
|
24
|
+
searchSessions,
|
|
25
|
+
unsetCliConfigValue,
|
|
26
|
+
writeCliConfigValue
|
|
27
|
+
} from "./chunk-RCRNSEQS.js";
|
|
8
28
|
import {
|
|
9
29
|
getBundledAgentProfile,
|
|
10
30
|
getBundledAgentProfiles,
|
|
@@ -13,10 +33,10 @@ import {
|
|
|
13
33
|
normalizeApiBase,
|
|
14
34
|
redactSensitiveSecrets,
|
|
15
35
|
redactSensitiveText
|
|
16
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-2D4BE3OS.js";
|
|
17
37
|
import {
|
|
18
38
|
CLI_VERSION
|
|
19
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-AWSLWW4V.js";
|
|
20
40
|
|
|
21
41
|
// src/runtime/prepareInk.ts
|
|
22
42
|
import fs from "fs";
|
|
@@ -116,8 +136,8 @@ ensureInkRuntimeEnvironment();
|
|
|
116
136
|
import React from "react";
|
|
117
137
|
import { Command } from "commander";
|
|
118
138
|
import { promises as fs12 } from "fs";
|
|
119
|
-
import
|
|
120
|
-
import
|
|
139
|
+
import os4 from "os";
|
|
140
|
+
import path9 from "path";
|
|
121
141
|
|
|
122
142
|
// src/shellCompletion.ts
|
|
123
143
|
var normalizeCompletionShell = (shell) => {
|
|
@@ -452,6 +472,22 @@ var cliCommands = [
|
|
|
452
472
|
],
|
|
453
473
|
workflows: ["recipes list", "recipes show", "recipes run"]
|
|
454
474
|
},
|
|
475
|
+
{
|
|
476
|
+
name: "skills",
|
|
477
|
+
description: "List, inspect, and validate CloudEval agent skills",
|
|
478
|
+
domain: "skills",
|
|
479
|
+
options: [
|
|
480
|
+
"list",
|
|
481
|
+
"show",
|
|
482
|
+
"doctor",
|
|
483
|
+
"path",
|
|
484
|
+
"--format",
|
|
485
|
+
"--output",
|
|
486
|
+
"--profile",
|
|
487
|
+
"--help"
|
|
488
|
+
],
|
|
489
|
+
workflows: ["skills list", "skills show", "skills doctor", "skills path"]
|
|
490
|
+
},
|
|
455
491
|
{
|
|
456
492
|
name: "projects",
|
|
457
493
|
description: "Project utilities",
|
|
@@ -1568,7 +1604,7 @@ var resolveReportProjectId = async ({
|
|
|
1568
1604
|
if (!token) {
|
|
1569
1605
|
throw new Error("No project specified. Use --project <id> for report access.");
|
|
1570
1606
|
}
|
|
1571
|
-
const resolvedWorkspace = workspace ?? await import("./dist-
|
|
1607
|
+
const resolvedWorkspace = workspace ?? await import("./dist-TBAQ5KOK.js").then((core) => ({
|
|
1572
1608
|
checkUserStatus: core.checkUserStatus,
|
|
1573
1609
|
getProjects: core.getProjects
|
|
1574
1610
|
}));
|
|
@@ -1597,7 +1633,7 @@ var warnIfAccessKeyFromCliOption = (options, command) => {
|
|
|
1597
1633
|
};
|
|
1598
1634
|
var resolveAuthContext = async (options, command, deps) => {
|
|
1599
1635
|
const baseUrl = await deps.resolveBaseUrl(options, command);
|
|
1600
|
-
const core = await import("./dist-
|
|
1636
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
1601
1637
|
core.assertSecureBaseUrl(baseUrl);
|
|
1602
1638
|
warnIfAccessKeyFromCliOption(options, command);
|
|
1603
1639
|
let accessKey = options.accessKey;
|
|
@@ -1683,7 +1719,7 @@ var resolveToken = async (options, baseUrl, deps, command) => {
|
|
|
1683
1719
|
if (options.accessKey) {
|
|
1684
1720
|
return options.accessKey;
|
|
1685
1721
|
}
|
|
1686
|
-
const { getAuthToken } = await import("./dist-
|
|
1722
|
+
const { getAuthToken } = await import("./dist-TBAQ5KOK.js");
|
|
1687
1723
|
try {
|
|
1688
1724
|
return await getAuthToken({
|
|
1689
1725
|
accessKey: options.accessKey,
|
|
@@ -1694,7 +1730,7 @@ var resolveToken = async (options, baseUrl, deps, command) => {
|
|
|
1694
1730
|
if (!canLogin) {
|
|
1695
1731
|
throw error;
|
|
1696
1732
|
}
|
|
1697
|
-
const { login } = await import("./dist-
|
|
1733
|
+
const { login } = await import("./dist-TBAQ5KOK.js");
|
|
1698
1734
|
process.stderr.write("Authentication required. Starting login flow...\n");
|
|
1699
1735
|
const token = await login(baseUrl, {
|
|
1700
1736
|
headless: Boolean(process.env.SSH_TTY || process.env.CLOUDEVAL_HEADLESS_LOGIN)
|
|
@@ -1730,7 +1766,7 @@ var writeReport = async (report, options, tuiDefault) => {
|
|
|
1730
1766
|
const [{ default: React2 }, { render }, { ReportDashboard }] = await Promise.all([
|
|
1731
1767
|
import("react"),
|
|
1732
1768
|
import("ink"),
|
|
1733
|
-
import("./ReportDashboard-
|
|
1769
|
+
import("./ReportDashboard-T63UGA7M.js")
|
|
1734
1770
|
]);
|
|
1735
1771
|
render(React2.createElement(ReportDashboard, {
|
|
1736
1772
|
report,
|
|
@@ -1778,8 +1814,8 @@ var writeDownloadPayload = async (input) => {
|
|
|
1778
1814
|
return [];
|
|
1779
1815
|
}
|
|
1780
1816
|
const fs13 = await import("fs/promises");
|
|
1781
|
-
const
|
|
1782
|
-
await fs13.mkdir(
|
|
1817
|
+
const path10 = await import("path");
|
|
1818
|
+
await fs13.mkdir(path10.dirname(input.output), { recursive: true });
|
|
1783
1819
|
const text = formatOutput({
|
|
1784
1820
|
command: input.command,
|
|
1785
1821
|
data: input.payload,
|
|
@@ -1860,7 +1896,7 @@ var registerReportsCommand = (program2, deps) => {
|
|
|
1860
1896
|
token,
|
|
1861
1897
|
requestedProjectId: options.project
|
|
1862
1898
|
});
|
|
1863
|
-
const core = await import("./dist-
|
|
1899
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
1864
1900
|
const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
|
|
1865
1901
|
const reports2 = await core.listReports({
|
|
1866
1902
|
baseUrl,
|
|
@@ -1882,7 +1918,7 @@ var registerReportsCommand = (program2, deps) => {
|
|
|
1882
1918
|
try {
|
|
1883
1919
|
const baseUrl = await deps.resolveBaseUrl(options, command);
|
|
1884
1920
|
const token = await resolveToken(options, baseUrl, deps, command);
|
|
1885
|
-
const core = await import("./dist-
|
|
1921
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
1886
1922
|
const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
|
|
1887
1923
|
const projectId = await resolveReportProjectId({
|
|
1888
1924
|
baseUrl,
|
|
@@ -1936,13 +1972,13 @@ var registerReportsCommand = (program2, deps) => {
|
|
|
1936
1972
|
const data = reportTypes.length === 1 ? payload[reportTypes[0] === "architecture" ? "waf" : reportTypes[0]] : payload;
|
|
1937
1973
|
if (options.output && reportTypes.length > 1) {
|
|
1938
1974
|
const fs13 = await import("fs/promises");
|
|
1939
|
-
const
|
|
1975
|
+
const path10 = await import("path");
|
|
1940
1976
|
const stat = await fs13.stat(options.output).catch(() => void 0);
|
|
1941
|
-
if (stat?.isDirectory() || !
|
|
1977
|
+
if (stat?.isDirectory() || !path10.extname(options.output)) {
|
|
1942
1978
|
await fs13.mkdir(options.output, { recursive: true });
|
|
1943
1979
|
const files = [];
|
|
1944
1980
|
for (const [key, value] of Object.entries(payload)) {
|
|
1945
|
-
const file =
|
|
1981
|
+
const file = path10.join(options.output, `${projectId}-${key}-report.json`);
|
|
1946
1982
|
files.push(
|
|
1947
1983
|
...await writeDownloadPayload({
|
|
1948
1984
|
command: "reports download",
|
|
@@ -1985,7 +2021,7 @@ var registerReportsCommand = (program2, deps) => {
|
|
|
1985
2021
|
try {
|
|
1986
2022
|
const baseUrl = await deps.resolveBaseUrl(options, command);
|
|
1987
2023
|
const token = await resolveToken(options, baseUrl, deps, command);
|
|
1988
|
-
const core = await import("./dist-
|
|
2024
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
1989
2025
|
const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
|
|
1990
2026
|
const projectId = await resolveReportProjectId({
|
|
1991
2027
|
baseUrl,
|
|
@@ -2055,7 +2091,7 @@ var registerReportsCommand = (program2, deps) => {
|
|
|
2055
2091
|
token,
|
|
2056
2092
|
requestedProjectId: options.project
|
|
2057
2093
|
});
|
|
2058
|
-
const core = await import("./dist-
|
|
2094
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
2059
2095
|
const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
|
|
2060
2096
|
const report = await core.getWafReport({
|
|
2061
2097
|
baseUrl,
|
|
@@ -2094,7 +2130,7 @@ var registerReportsCommand = (program2, deps) => {
|
|
|
2094
2130
|
token,
|
|
2095
2131
|
requestedProjectId: options.project
|
|
2096
2132
|
});
|
|
2097
|
-
const core = await import("./dist-
|
|
2133
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
2098
2134
|
const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
|
|
2099
2135
|
const report = await core.getReport({
|
|
2100
2136
|
baseUrl,
|
|
@@ -2122,7 +2158,7 @@ var registerReportsCommand = (program2, deps) => {
|
|
|
2122
2158
|
token,
|
|
2123
2159
|
requestedProjectId: options.project
|
|
2124
2160
|
});
|
|
2125
|
-
const core = await import("./dist-
|
|
2161
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
2126
2162
|
const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
|
|
2127
2163
|
const report = await core.getCostReport({
|
|
2128
2164
|
baseUrl,
|
|
@@ -2151,7 +2187,7 @@ var registerReportsCommand = (program2, deps) => {
|
|
|
2151
2187
|
token,
|
|
2152
2188
|
requestedProjectId: options.project
|
|
2153
2189
|
});
|
|
2154
|
-
const core = await import("./dist-
|
|
2190
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
2155
2191
|
const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
|
|
2156
2192
|
const report = await core.getWafReport({
|
|
2157
2193
|
baseUrl,
|
|
@@ -2173,7 +2209,7 @@ var registerReportsCommand = (program2, deps) => {
|
|
|
2173
2209
|
|
|
2174
2210
|
// src/recipesCommand.ts
|
|
2175
2211
|
import { randomUUID } from "crypto";
|
|
2176
|
-
import
|
|
2212
|
+
import fs2 from "fs/promises";
|
|
2177
2213
|
|
|
2178
2214
|
// src/askProgress.ts
|
|
2179
2215
|
var ASK_PROGRESS_MODES = /* @__PURE__ */ new Set(["auto", "stderr", "ndjson", "none"]);
|
|
@@ -3346,725 +3382,6 @@ var renderRecipeMarkdown = (recipe) => {
|
|
|
3346
3382
|
].join("\n");
|
|
3347
3383
|
};
|
|
3348
3384
|
|
|
3349
|
-
// src/cliConfig.ts
|
|
3350
|
-
import fs2 from "fs/promises";
|
|
3351
|
-
import os from "os";
|
|
3352
|
-
import path2 from "path";
|
|
3353
|
-
var CONFIG_PROFILE_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/;
|
|
3354
|
-
var SETTINGS_FILE = "settings.json";
|
|
3355
|
-
var normalizeConfigProfile = (profile) => {
|
|
3356
|
-
const normalized = (profile || process.env.CLOUDEVAL_PROFILE || "default").trim() || "default";
|
|
3357
|
-
if (!CONFIG_PROFILE_PATTERN.test(normalized)) {
|
|
3358
|
-
throw new Error(
|
|
3359
|
-
`Invalid profile '${normalized}'. Use letters, numbers, dashes, or underscores.`
|
|
3360
|
-
);
|
|
3361
|
-
}
|
|
3362
|
-
return normalized;
|
|
3363
|
-
};
|
|
3364
|
-
var getActiveConfigProfile = (command) => {
|
|
3365
|
-
const opts = typeof command?.optsWithGlobals === "function" ? command.optsWithGlobals() : command?.opts();
|
|
3366
|
-
return normalizeConfigProfile(opts?.profile);
|
|
3367
|
-
};
|
|
3368
|
-
var getCloudevalConfigDir = () => path2.join(os.homedir(), ".config", "cloudeval");
|
|
3369
|
-
var getCliConfigPath = (profile) => {
|
|
3370
|
-
const normalized = normalizeConfigProfile(profile);
|
|
3371
|
-
if (normalized === "default") {
|
|
3372
|
-
return path2.join(getCloudevalConfigDir(), SETTINGS_FILE);
|
|
3373
|
-
}
|
|
3374
|
-
return path2.join(getCloudevalConfigDir(), "profiles", normalized, SETTINGS_FILE);
|
|
3375
|
-
};
|
|
3376
|
-
var ensureConfigParent = async (filePath) => {
|
|
3377
|
-
await fs2.mkdir(path2.dirname(filePath), { recursive: true, mode: 448 });
|
|
3378
|
-
};
|
|
3379
|
-
var loadCliConfig = async (profile) => {
|
|
3380
|
-
const filePath = getCliConfigPath(profile);
|
|
3381
|
-
try {
|
|
3382
|
-
const raw = await fs2.readFile(filePath, "utf8");
|
|
3383
|
-
const parsed = JSON.parse(raw);
|
|
3384
|
-
return parsed && typeof parsed === "object" ? parsed : {};
|
|
3385
|
-
} catch (error) {
|
|
3386
|
-
if (error?.code === "ENOENT") {
|
|
3387
|
-
return {};
|
|
3388
|
-
}
|
|
3389
|
-
throw error;
|
|
3390
|
-
}
|
|
3391
|
-
};
|
|
3392
|
-
var saveCliConfig = async (config, profile) => {
|
|
3393
|
-
const filePath = getCliConfigPath(profile);
|
|
3394
|
-
await ensureConfigParent(filePath);
|
|
3395
|
-
const tempPath = `${filePath}.${process.pid}.tmp`;
|
|
3396
|
-
await fs2.writeFile(tempPath, `${JSON.stringify(config, null, 2)}
|
|
3397
|
-
`, {
|
|
3398
|
-
encoding: "utf8",
|
|
3399
|
-
mode: 384
|
|
3400
|
-
});
|
|
3401
|
-
await fs2.rename(tempPath, filePath);
|
|
3402
|
-
return filePath;
|
|
3403
|
-
};
|
|
3404
|
-
var listCliConfigProfiles = async () => {
|
|
3405
|
-
const profiles = /* @__PURE__ */ new Set(["default"]);
|
|
3406
|
-
const profilesDir = path2.join(getCloudevalConfigDir(), "profiles");
|
|
3407
|
-
try {
|
|
3408
|
-
const entries = await fs2.readdir(profilesDir, { withFileTypes: true });
|
|
3409
|
-
for (const entry of entries) {
|
|
3410
|
-
if (entry.isDirectory() && CONFIG_PROFILE_PATTERN.test(entry.name)) {
|
|
3411
|
-
profiles.add(entry.name);
|
|
3412
|
-
}
|
|
3413
|
-
}
|
|
3414
|
-
} catch (error) {
|
|
3415
|
-
if (error?.code !== "ENOENT") {
|
|
3416
|
-
throw error;
|
|
3417
|
-
}
|
|
3418
|
-
}
|
|
3419
|
-
return [...profiles].sort();
|
|
3420
|
-
};
|
|
3421
|
-
var keyAliases = {
|
|
3422
|
-
project: "defaultProjectId",
|
|
3423
|
-
projectId: "defaultProjectId",
|
|
3424
|
-
defaultProject: "defaultProjectId",
|
|
3425
|
-
defaultProjectId: "defaultProjectId",
|
|
3426
|
-
model: "model",
|
|
3427
|
-
mode: "mode",
|
|
3428
|
-
chatMode: "mode",
|
|
3429
|
-
defaultMode: "mode",
|
|
3430
|
-
baseUrl: "baseUrl",
|
|
3431
|
-
frontendUrl: "frontendUrl",
|
|
3432
|
-
outputFormat: "outputFormat",
|
|
3433
|
-
format: "outputFormat"
|
|
3434
|
-
};
|
|
3435
|
-
var normalizeCliMode = (value) => {
|
|
3436
|
-
const normalized = value?.trim().toLowerCase();
|
|
3437
|
-
if (!normalized) {
|
|
3438
|
-
return void 0;
|
|
3439
|
-
}
|
|
3440
|
-
if (normalized === "ask" || normalized === "agent") {
|
|
3441
|
-
return normalized;
|
|
3442
|
-
}
|
|
3443
|
-
throw new Error("mode must be one of: ask, agent");
|
|
3444
|
-
};
|
|
3445
|
-
var normalizeConfigKey = (key) => {
|
|
3446
|
-
const normalized = key.trim();
|
|
3447
|
-
const mapped = keyAliases[normalized];
|
|
3448
|
-
if (!mapped) {
|
|
3449
|
-
throw new Error(
|
|
3450
|
-
`Unsupported config key '${key}'. Supported keys: baseUrl, frontendUrl, defaultProjectId, model, mode, outputFormat.`
|
|
3451
|
-
);
|
|
3452
|
-
}
|
|
3453
|
-
return mapped;
|
|
3454
|
-
};
|
|
3455
|
-
var readCliConfigValue = (config, key) => {
|
|
3456
|
-
const normalized = normalizeConfigKey(key);
|
|
3457
|
-
const value = config[normalized];
|
|
3458
|
-
return typeof value === "string" ? value : void 0;
|
|
3459
|
-
};
|
|
3460
|
-
var writeCliConfigValue = (config, key, value) => {
|
|
3461
|
-
const normalized = normalizeConfigKey(key);
|
|
3462
|
-
const normalizedValue = normalized === "mode" ? normalizeCliMode(value) : value;
|
|
3463
|
-
return {
|
|
3464
|
-
...config,
|
|
3465
|
-
[normalized]: normalizedValue
|
|
3466
|
-
};
|
|
3467
|
-
};
|
|
3468
|
-
var unsetCliConfigValue = (config, key) => {
|
|
3469
|
-
const normalized = normalizeConfigKey(key);
|
|
3470
|
-
const next = { ...config };
|
|
3471
|
-
delete next[normalized];
|
|
3472
|
-
return next;
|
|
3473
|
-
};
|
|
3474
|
-
|
|
3475
|
-
// src/sessionsStore.ts
|
|
3476
|
-
import fsSync from "fs";
|
|
3477
|
-
import fs3 from "fs/promises";
|
|
3478
|
-
import path3 from "path";
|
|
3479
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3480
|
-
var SQLJS_WASM_ENV_VAR = "CLOUDEVAL_SQLJS_WASM";
|
|
3481
|
-
var legacySessionsDir = (profile) => {
|
|
3482
|
-
const normalized = normalizeConfigProfile(profile);
|
|
3483
|
-
if (normalized === "default") {
|
|
3484
|
-
return path3.join(getCloudevalConfigDir(), "sessions");
|
|
3485
|
-
}
|
|
3486
|
-
return path3.join(getCloudevalConfigDir(), "profiles", normalized, "sessions");
|
|
3487
|
-
};
|
|
3488
|
-
var sessionsDatabasePath = (profile) => {
|
|
3489
|
-
const normalized = normalizeConfigProfile(profile);
|
|
3490
|
-
if (normalized === "default") {
|
|
3491
|
-
return path3.join(getCloudevalConfigDir(), "sessions.sqlite");
|
|
3492
|
-
}
|
|
3493
|
-
return path3.join(getCloudevalConfigDir(), "profiles", normalized, "sessions.sqlite");
|
|
3494
|
-
};
|
|
3495
|
-
var legacySessionPath = (threadId, profile) => path3.join(legacySessionsDir(profile), `${sanitizeThreadId(threadId)}.json`);
|
|
3496
|
-
var sanitizeThreadId = (threadId) => threadId.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
3497
|
-
var nowIso = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
3498
|
-
var titleFromQuestion = (question) => {
|
|
3499
|
-
const singleLine = question.replace(/[^\p{L}\p{N}\s'-]/gu, " ").replace(/\s+/g, " ").trim().replace(/^(can you|could you|please|help me|show me|tell me|what is|what are|how do i)\s+/i, "").replace(/^(review|investigate|triage|summarize|explain|analyze)\s+the\s+/i, "$1 ");
|
|
3500
|
-
if (!singleLine) {
|
|
3501
|
-
return "Untitled CloudEval session";
|
|
3502
|
-
}
|
|
3503
|
-
const words = singleLine.split(/\s+/).slice(0, 7);
|
|
3504
|
-
const joined = words.join(" ");
|
|
3505
|
-
const title = joined.charAt(0).toUpperCase() + joined.slice(1);
|
|
3506
|
-
return title.length > 80 ? `${title.slice(0, 77)}...` : title;
|
|
3507
|
-
};
|
|
3508
|
-
var sanitizeTitle = (title) => {
|
|
3509
|
-
const cleaned = title.replace(/[\u0000-\u001f\u007f]/g, " ").replace(/[\u200b-\u200f\u202a-\u202e]/g, "").replace(/\s+/g, " ").trim();
|
|
3510
|
-
if (!cleaned) {
|
|
3511
|
-
throw new Error("Session title cannot be empty.");
|
|
3512
|
-
}
|
|
3513
|
-
return cleaned.length > 100 ? cleaned.slice(0, 100) : cleaned;
|
|
3514
|
-
};
|
|
3515
|
-
var hasFile2 = (candidate) => {
|
|
3516
|
-
try {
|
|
3517
|
-
return fsSync.statSync(candidate).isFile();
|
|
3518
|
-
} catch {
|
|
3519
|
-
return false;
|
|
3520
|
-
}
|
|
3521
|
-
};
|
|
3522
|
-
var findSqlJsWasmInNodeModules = (dir) => {
|
|
3523
|
-
const nodeModulesDir = path3.join(dir, "node_modules");
|
|
3524
|
-
const direct = path3.join(nodeModulesDir, "sql.js", "dist", "sql-wasm.wasm");
|
|
3525
|
-
if (hasFile2(direct)) {
|
|
3526
|
-
return direct;
|
|
3527
|
-
}
|
|
3528
|
-
const pnpmRoot = path3.join(nodeModulesDir, ".pnpm");
|
|
3529
|
-
if (!fsSync.existsSync(pnpmRoot)) {
|
|
3530
|
-
return void 0;
|
|
3531
|
-
}
|
|
3532
|
-
for (const entry of fsSync.readdirSync(pnpmRoot)) {
|
|
3533
|
-
if (!entry.startsWith("sql.js@")) {
|
|
3534
|
-
continue;
|
|
3535
|
-
}
|
|
3536
|
-
const candidate = path3.join(
|
|
3537
|
-
pnpmRoot,
|
|
3538
|
-
entry,
|
|
3539
|
-
"node_modules",
|
|
3540
|
-
"sql.js",
|
|
3541
|
-
"dist",
|
|
3542
|
-
"sql-wasm.wasm"
|
|
3543
|
-
);
|
|
3544
|
-
if (hasFile2(candidate)) {
|
|
3545
|
-
return candidate;
|
|
3546
|
-
}
|
|
3547
|
-
}
|
|
3548
|
-
return void 0;
|
|
3549
|
-
};
|
|
3550
|
-
var searchSqlJsWasmFrom = (start) => {
|
|
3551
|
-
let current = path3.resolve(start);
|
|
3552
|
-
while (true) {
|
|
3553
|
-
const localCandidates = [
|
|
3554
|
-
path3.join(current, "sql-wasm.wasm"),
|
|
3555
|
-
path3.join(current, "dist", "sql-wasm.wasm")
|
|
3556
|
-
];
|
|
3557
|
-
for (const candidate of localCandidates) {
|
|
3558
|
-
if (hasFile2(candidate)) {
|
|
3559
|
-
return candidate;
|
|
3560
|
-
}
|
|
3561
|
-
}
|
|
3562
|
-
const nodeModulesMatch = findSqlJsWasmInNodeModules(current);
|
|
3563
|
-
if (nodeModulesMatch) {
|
|
3564
|
-
return nodeModulesMatch;
|
|
3565
|
-
}
|
|
3566
|
-
const parent = path3.dirname(current);
|
|
3567
|
-
if (parent === current) {
|
|
3568
|
-
return void 0;
|
|
3569
|
-
}
|
|
3570
|
-
current = parent;
|
|
3571
|
-
}
|
|
3572
|
-
};
|
|
3573
|
-
var resolveSqlJsWasmPath = () => {
|
|
3574
|
-
if (process.env[SQLJS_WASM_ENV_VAR]) {
|
|
3575
|
-
return process.env[SQLJS_WASM_ENV_VAR];
|
|
3576
|
-
}
|
|
3577
|
-
const moduleDir = path3.dirname(fileURLToPath2(import.meta.url));
|
|
3578
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3579
|
-
const roots = [process.cwd(), moduleDir, path3.dirname(process.execPath)];
|
|
3580
|
-
for (const root of roots) {
|
|
3581
|
-
const resolvedRoot = path3.resolve(root);
|
|
3582
|
-
if (seen.has(resolvedRoot)) {
|
|
3583
|
-
continue;
|
|
3584
|
-
}
|
|
3585
|
-
seen.add(resolvedRoot);
|
|
3586
|
-
const match = searchSqlJsWasmFrom(resolvedRoot);
|
|
3587
|
-
if (match) {
|
|
3588
|
-
return match;
|
|
3589
|
-
}
|
|
3590
|
-
}
|
|
3591
|
-
return void 0;
|
|
3592
|
-
};
|
|
3593
|
-
var isBunRuntime = () => typeof process.versions.bun === "string";
|
|
3594
|
-
var dynamicImport = new Function("specifier", "return import(specifier)");
|
|
3595
|
-
var openBunDatabase = async (dbPath) => {
|
|
3596
|
-
if (!isBunRuntime()) {
|
|
3597
|
-
return null;
|
|
3598
|
-
}
|
|
3599
|
-
try {
|
|
3600
|
-
const { Database } = await dynamicImport("bun:sqlite");
|
|
3601
|
-
await fs3.mkdir(path3.dirname(dbPath), { recursive: true, mode: 448 });
|
|
3602
|
-
const db = new Database(dbPath, { create: true });
|
|
3603
|
-
db.exec("PRAGMA foreign_keys = ON");
|
|
3604
|
-
return {
|
|
3605
|
-
rows(sql, params = []) {
|
|
3606
|
-
const statement = db.query(sql);
|
|
3607
|
-
return statement.all(...params);
|
|
3608
|
-
},
|
|
3609
|
-
run(sql, params = []) {
|
|
3610
|
-
const statement = db.query(sql);
|
|
3611
|
-
statement.run(...params);
|
|
3612
|
-
},
|
|
3613
|
-
async persist() {
|
|
3614
|
-
},
|
|
3615
|
-
close() {
|
|
3616
|
-
db.close();
|
|
3617
|
-
}
|
|
3618
|
-
};
|
|
3619
|
-
} catch {
|
|
3620
|
-
return null;
|
|
3621
|
-
}
|
|
3622
|
-
};
|
|
3623
|
-
var sqlJsFactoryPromise = null;
|
|
3624
|
-
var loadSqlJsFactory = async () => {
|
|
3625
|
-
if (!sqlJsFactoryPromise) {
|
|
3626
|
-
sqlJsFactoryPromise = (async () => {
|
|
3627
|
-
const initSqlJs = (await import("sql.js")).default;
|
|
3628
|
-
const wasmPath = resolveSqlJsWasmPath();
|
|
3629
|
-
return initSqlJs({
|
|
3630
|
-
locateFile: (file) => {
|
|
3631
|
-
if (file === "sql-wasm.wasm" && wasmPath) {
|
|
3632
|
-
return wasmPath;
|
|
3633
|
-
}
|
|
3634
|
-
return file;
|
|
3635
|
-
}
|
|
3636
|
-
});
|
|
3637
|
-
})();
|
|
3638
|
-
}
|
|
3639
|
-
return sqlJsFactoryPromise;
|
|
3640
|
-
};
|
|
3641
|
-
var openSqlJsDatabase = async (dbPath) => {
|
|
3642
|
-
await fs3.mkdir(path3.dirname(dbPath), { recursive: true, mode: 448 });
|
|
3643
|
-
const SQL = await loadSqlJsFactory();
|
|
3644
|
-
let bytes;
|
|
3645
|
-
try {
|
|
3646
|
-
bytes = await fs3.readFile(dbPath);
|
|
3647
|
-
} catch (error) {
|
|
3648
|
-
if (error?.code !== "ENOENT") {
|
|
3649
|
-
throw error;
|
|
3650
|
-
}
|
|
3651
|
-
}
|
|
3652
|
-
const db = bytes ? new SQL.Database(bytes) : new SQL.Database();
|
|
3653
|
-
db.run("PRAGMA foreign_keys = ON");
|
|
3654
|
-
let dirty = false;
|
|
3655
|
-
return {
|
|
3656
|
-
rows(sql, params = []) {
|
|
3657
|
-
const statement = db.prepare(sql, params);
|
|
3658
|
-
const rows = [];
|
|
3659
|
-
try {
|
|
3660
|
-
while (statement.step()) {
|
|
3661
|
-
rows.push(statement.getAsObject());
|
|
3662
|
-
}
|
|
3663
|
-
} finally {
|
|
3664
|
-
statement.free();
|
|
3665
|
-
}
|
|
3666
|
-
return rows;
|
|
3667
|
-
},
|
|
3668
|
-
run(sql, params = []) {
|
|
3669
|
-
db.run(sql, params);
|
|
3670
|
-
dirty = true;
|
|
3671
|
-
},
|
|
3672
|
-
async persist() {
|
|
3673
|
-
if (!dirty) {
|
|
3674
|
-
return;
|
|
3675
|
-
}
|
|
3676
|
-
const tempPath = `${dbPath}.${process.pid}.tmp`;
|
|
3677
|
-
await fs3.writeFile(tempPath, Buffer.from(db.export()), { mode: 384 });
|
|
3678
|
-
await fs3.rename(tempPath, dbPath);
|
|
3679
|
-
dirty = false;
|
|
3680
|
-
},
|
|
3681
|
-
close() {
|
|
3682
|
-
db.close();
|
|
3683
|
-
}
|
|
3684
|
-
};
|
|
3685
|
-
};
|
|
3686
|
-
var openSessionDatabase = async (profile) => {
|
|
3687
|
-
const dbPath = sessionsDatabasePath(profile);
|
|
3688
|
-
return await openBunDatabase(dbPath) ?? openSqlJsDatabase(dbPath);
|
|
3689
|
-
};
|
|
3690
|
-
var ensureSchema = (db) => {
|
|
3691
|
-
db.run(`
|
|
3692
|
-
CREATE TABLE IF NOT EXISTS sessions (
|
|
3693
|
-
thread_id TEXT PRIMARY KEY,
|
|
3694
|
-
title TEXT NOT NULL,
|
|
3695
|
-
project_id TEXT,
|
|
3696
|
-
project_name TEXT,
|
|
3697
|
-
model TEXT,
|
|
3698
|
-
profile TEXT NOT NULL,
|
|
3699
|
-
created_at TEXT NOT NULL,
|
|
3700
|
-
updated_at TEXT NOT NULL,
|
|
3701
|
-
message_count INTEGER NOT NULL DEFAULT 0
|
|
3702
|
-
)
|
|
3703
|
-
`);
|
|
3704
|
-
db.run(`
|
|
3705
|
-
CREATE TABLE IF NOT EXISTS session_messages (
|
|
3706
|
-
session_thread_id TEXT NOT NULL,
|
|
3707
|
-
message_index INTEGER NOT NULL,
|
|
3708
|
-
role TEXT NOT NULL CHECK (role IN ('user', 'assistant')),
|
|
3709
|
-
content TEXT NOT NULL,
|
|
3710
|
-
created_at TEXT NOT NULL,
|
|
3711
|
-
PRIMARY KEY (session_thread_id, message_index),
|
|
3712
|
-
FOREIGN KEY (session_thread_id) REFERENCES sessions(thread_id) ON DELETE CASCADE
|
|
3713
|
-
)
|
|
3714
|
-
`);
|
|
3715
|
-
db.run("CREATE INDEX IF NOT EXISTS idx_sessions_updated_at ON sessions(updated_at DESC)");
|
|
3716
|
-
db.run(
|
|
3717
|
-
"CREATE INDEX IF NOT EXISTS idx_session_messages_thread ON session_messages(session_thread_id, message_index)"
|
|
3718
|
-
);
|
|
3719
|
-
};
|
|
3720
|
-
var optionalString = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
|
|
3721
|
-
var messageFromRow = (row) => {
|
|
3722
|
-
const role = row.role;
|
|
3723
|
-
const content = row.content;
|
|
3724
|
-
const createdAt = row.created_at;
|
|
3725
|
-
if (role !== "user" && role !== "assistant" || typeof content !== "string") {
|
|
3726
|
-
return null;
|
|
3727
|
-
}
|
|
3728
|
-
return {
|
|
3729
|
-
role,
|
|
3730
|
-
content,
|
|
3731
|
-
createdAt: typeof createdAt === "string" ? createdAt : nowIso()
|
|
3732
|
-
};
|
|
3733
|
-
};
|
|
3734
|
-
var sessionFromRow = (db, row) => {
|
|
3735
|
-
const threadId = row.thread_id;
|
|
3736
|
-
const title = row.title;
|
|
3737
|
-
const createdAt = row.created_at;
|
|
3738
|
-
const updatedAt = row.updated_at;
|
|
3739
|
-
if (typeof threadId !== "string" || typeof title !== "string" || typeof createdAt !== "string" || typeof updatedAt !== "string") {
|
|
3740
|
-
return null;
|
|
3741
|
-
}
|
|
3742
|
-
const messages = db.rows(
|
|
3743
|
-
`SELECT role, content, created_at
|
|
3744
|
-
FROM session_messages
|
|
3745
|
-
WHERE session_thread_id = ?
|
|
3746
|
-
ORDER BY message_index ASC`,
|
|
3747
|
-
[threadId]
|
|
3748
|
-
).map(messageFromRow).filter((message) => Boolean(message));
|
|
3749
|
-
return {
|
|
3750
|
-
threadId,
|
|
3751
|
-
title,
|
|
3752
|
-
projectId: optionalString(row.project_id),
|
|
3753
|
-
projectName: optionalString(row.project_name),
|
|
3754
|
-
model: optionalString(row.model),
|
|
3755
|
-
profile: optionalString(row.profile),
|
|
3756
|
-
createdAt,
|
|
3757
|
-
updatedAt,
|
|
3758
|
-
messageCount: Number(row.message_count) || messages.length,
|
|
3759
|
-
messages
|
|
3760
|
-
};
|
|
3761
|
-
};
|
|
3762
|
-
var getSessionFromDb = (db, threadId) => {
|
|
3763
|
-
const row = db.rows("SELECT * FROM sessions WHERE thread_id = ?", [threadId])[0];
|
|
3764
|
-
return row ? sessionFromRow(db, row) : null;
|
|
3765
|
-
};
|
|
3766
|
-
var runTransaction = (db, fn) => {
|
|
3767
|
-
db.run("BEGIN IMMEDIATE");
|
|
3768
|
-
try {
|
|
3769
|
-
const result = fn();
|
|
3770
|
-
db.run("COMMIT");
|
|
3771
|
-
return result;
|
|
3772
|
-
} catch (error) {
|
|
3773
|
-
try {
|
|
3774
|
-
db.run("ROLLBACK");
|
|
3775
|
-
} catch {
|
|
3776
|
-
}
|
|
3777
|
-
throw error;
|
|
3778
|
-
}
|
|
3779
|
-
};
|
|
3780
|
-
var upsertSession = (db, session) => {
|
|
3781
|
-
runTransaction(db, () => {
|
|
3782
|
-
db.run(
|
|
3783
|
-
`INSERT INTO sessions (
|
|
3784
|
-
thread_id,
|
|
3785
|
-
title,
|
|
3786
|
-
project_id,
|
|
3787
|
-
project_name,
|
|
3788
|
-
model,
|
|
3789
|
-
profile,
|
|
3790
|
-
created_at,
|
|
3791
|
-
updated_at,
|
|
3792
|
-
message_count
|
|
3793
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3794
|
-
ON CONFLICT(thread_id) DO UPDATE SET
|
|
3795
|
-
title = excluded.title,
|
|
3796
|
-
project_id = excluded.project_id,
|
|
3797
|
-
project_name = excluded.project_name,
|
|
3798
|
-
model = excluded.model,
|
|
3799
|
-
profile = excluded.profile,
|
|
3800
|
-
created_at = excluded.created_at,
|
|
3801
|
-
updated_at = excluded.updated_at,
|
|
3802
|
-
message_count = excluded.message_count`,
|
|
3803
|
-
[
|
|
3804
|
-
session.threadId,
|
|
3805
|
-
session.title,
|
|
3806
|
-
session.projectId ?? null,
|
|
3807
|
-
session.projectName ?? null,
|
|
3808
|
-
session.model ?? null,
|
|
3809
|
-
session.profile ?? "default",
|
|
3810
|
-
session.createdAt,
|
|
3811
|
-
session.updatedAt,
|
|
3812
|
-
session.messages.length
|
|
3813
|
-
]
|
|
3814
|
-
);
|
|
3815
|
-
db.run("DELETE FROM session_messages WHERE session_thread_id = ?", [session.threadId]);
|
|
3816
|
-
session.messages.forEach((message, index) => {
|
|
3817
|
-
db.run(
|
|
3818
|
-
`INSERT INTO session_messages (
|
|
3819
|
-
session_thread_id,
|
|
3820
|
-
message_index,
|
|
3821
|
-
role,
|
|
3822
|
-
content,
|
|
3823
|
-
created_at
|
|
3824
|
-
) VALUES (?, ?, ?, ?, ?)`,
|
|
3825
|
-
[session.threadId, index, message.role, message.content, message.createdAt]
|
|
3826
|
-
);
|
|
3827
|
-
});
|
|
3828
|
-
});
|
|
3829
|
-
};
|
|
3830
|
-
var readLegacySessionFile = async (filePath) => {
|
|
3831
|
-
try {
|
|
3832
|
-
const raw = await fs3.readFile(filePath, "utf8");
|
|
3833
|
-
const parsed = JSON.parse(raw);
|
|
3834
|
-
return parsed && typeof parsed === "object" ? normalizeLegacySession(parsed) : null;
|
|
3835
|
-
} catch (error) {
|
|
3836
|
-
if (error?.code === "ENOENT") {
|
|
3837
|
-
return null;
|
|
3838
|
-
}
|
|
3839
|
-
throw error;
|
|
3840
|
-
}
|
|
3841
|
-
};
|
|
3842
|
-
var normalizeLegacySession = (value) => {
|
|
3843
|
-
if (!value || typeof value !== "object" || typeof value.threadId !== "string") {
|
|
3844
|
-
return null;
|
|
3845
|
-
}
|
|
3846
|
-
const timestamp = nowIso();
|
|
3847
|
-
const messages = Array.isArray(value.messages) ? value.messages.map((message) => {
|
|
3848
|
-
if (!message || message.role !== "user" && message.role !== "assistant" || typeof message.content !== "string") {
|
|
3849
|
-
return null;
|
|
3850
|
-
}
|
|
3851
|
-
return {
|
|
3852
|
-
role: message.role,
|
|
3853
|
-
content: message.content,
|
|
3854
|
-
createdAt: typeof message.createdAt === "string" ? message.createdAt : timestamp
|
|
3855
|
-
};
|
|
3856
|
-
}).filter(
|
|
3857
|
-
(message) => Boolean(message)
|
|
3858
|
-
) : [];
|
|
3859
|
-
return {
|
|
3860
|
-
threadId: value.threadId,
|
|
3861
|
-
title: typeof value.title === "string" && value.title.trim() ? sanitizeTitle(value.title) : "Untitled CloudEval session",
|
|
3862
|
-
projectId: optionalString(value.projectId),
|
|
3863
|
-
projectName: optionalString(value.projectName),
|
|
3864
|
-
model: optionalString(value.model),
|
|
3865
|
-
profile: optionalString(value.profile),
|
|
3866
|
-
createdAt: typeof value.createdAt === "string" ? value.createdAt : timestamp,
|
|
3867
|
-
updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : timestamp,
|
|
3868
|
-
messageCount: messages.length,
|
|
3869
|
-
messages
|
|
3870
|
-
};
|
|
3871
|
-
};
|
|
3872
|
-
var readLegacySessions = async (profile) => {
|
|
3873
|
-
try {
|
|
3874
|
-
const dir = legacySessionsDir(profile);
|
|
3875
|
-
const entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
3876
|
-
const sessions = await Promise.all(
|
|
3877
|
-
entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => readLegacySessionFile(path3.join(dir, entry.name)))
|
|
3878
|
-
);
|
|
3879
|
-
return sessions.filter((session) => Boolean(session));
|
|
3880
|
-
} catch (error) {
|
|
3881
|
-
if (error?.code === "ENOENT") {
|
|
3882
|
-
return [];
|
|
3883
|
-
}
|
|
3884
|
-
throw error;
|
|
3885
|
-
}
|
|
3886
|
-
};
|
|
3887
|
-
var migrateLegacyJsonSessions = async (db, profile) => {
|
|
3888
|
-
const normalizedProfile = normalizeConfigProfile(profile);
|
|
3889
|
-
const legacySessions = await readLegacySessions(normalizedProfile);
|
|
3890
|
-
for (const session of legacySessions) {
|
|
3891
|
-
if (getSessionFromDb(db, session.threadId)) {
|
|
3892
|
-
continue;
|
|
3893
|
-
}
|
|
3894
|
-
upsertSession(db, {
|
|
3895
|
-
...session,
|
|
3896
|
-
profile: session.profile ?? normalizedProfile,
|
|
3897
|
-
messageCount: session.messages.length
|
|
3898
|
-
});
|
|
3899
|
-
}
|
|
3900
|
-
};
|
|
3901
|
-
var withSessionDatabase = async (profile, fn) => {
|
|
3902
|
-
const normalizedProfile = normalizeConfigProfile(profile);
|
|
3903
|
-
const db = await openSessionDatabase(normalizedProfile);
|
|
3904
|
-
try {
|
|
3905
|
-
ensureSchema(db);
|
|
3906
|
-
await migrateLegacyJsonSessions(db, normalizedProfile);
|
|
3907
|
-
const result = await fn(db, normalizedProfile);
|
|
3908
|
-
await db.persist();
|
|
3909
|
-
return result;
|
|
3910
|
-
} finally {
|
|
3911
|
-
db.close();
|
|
3912
|
-
}
|
|
3913
|
-
};
|
|
3914
|
-
var recordSessionTurn = async ({
|
|
3915
|
-
threadId,
|
|
3916
|
-
question,
|
|
3917
|
-
response,
|
|
3918
|
-
project,
|
|
3919
|
-
model,
|
|
3920
|
-
profile
|
|
3921
|
-
}) => {
|
|
3922
|
-
if (!threadId || !question.trim() && !response.trim()) {
|
|
3923
|
-
return;
|
|
3924
|
-
}
|
|
3925
|
-
await withSessionDatabase(profile, (db, normalizedProfile) => {
|
|
3926
|
-
const existing = getSessionFromDb(db, threadId);
|
|
3927
|
-
const timestamp = nowIso();
|
|
3928
|
-
const messages = [
|
|
3929
|
-
...existing?.messages ?? [],
|
|
3930
|
-
...question.trim() ? [{ role: "user", content: question.trim(), createdAt: timestamp }] : [],
|
|
3931
|
-
...response.trim() ? [{ role: "assistant", content: response.trim(), createdAt: timestamp }] : []
|
|
3932
|
-
];
|
|
3933
|
-
upsertSession(db, {
|
|
3934
|
-
threadId,
|
|
3935
|
-
title: existing?.title ?? titleFromQuestion(question),
|
|
3936
|
-
projectId: project?.id ?? existing?.projectId,
|
|
3937
|
-
projectName: project?.name ?? existing?.projectName,
|
|
3938
|
-
model: model ?? existing?.model,
|
|
3939
|
-
profile: normalizedProfile,
|
|
3940
|
-
createdAt: existing?.createdAt ?? timestamp,
|
|
3941
|
-
updatedAt: timestamp,
|
|
3942
|
-
messageCount: messages.length,
|
|
3943
|
-
messages
|
|
3944
|
-
});
|
|
3945
|
-
});
|
|
3946
|
-
};
|
|
3947
|
-
var listSessions = async (limit = 20, profile) => withSessionDatabase(profile, (db) => {
|
|
3948
|
-
const rows = db.rows(
|
|
3949
|
-
`SELECT *
|
|
3950
|
-
FROM sessions
|
|
3951
|
-
ORDER BY updated_at DESC
|
|
3952
|
-
LIMIT ?`,
|
|
3953
|
-
[Math.max(1, limit)]
|
|
3954
|
-
);
|
|
3955
|
-
return rows.map((row) => sessionFromRow(db, row)).filter((session) => Boolean(session));
|
|
3956
|
-
});
|
|
3957
|
-
var getSession = async (threadId, profile) => withSessionDatabase(profile, (db) => getSessionFromDb(db, threadId));
|
|
3958
|
-
var renameSession = async (threadId, title, profile) => {
|
|
3959
|
-
return withSessionDatabase(profile, (db) => {
|
|
3960
|
-
const session = getSessionFromDb(db, threadId);
|
|
3961
|
-
if (!session) {
|
|
3962
|
-
return null;
|
|
3963
|
-
}
|
|
3964
|
-
const updated = {
|
|
3965
|
-
...session,
|
|
3966
|
-
title: sanitizeTitle(title),
|
|
3967
|
-
updatedAt: nowIso()
|
|
3968
|
-
};
|
|
3969
|
-
upsertSession(db, updated);
|
|
3970
|
-
return updated;
|
|
3971
|
-
});
|
|
3972
|
-
};
|
|
3973
|
-
var searchTerms = (query) => query.toLowerCase().split(/[^a-z0-9]+/i).map((term) => term.trim()).filter((term) => term.length > 1);
|
|
3974
|
-
var countTerm = (text, term) => {
|
|
3975
|
-
if (!text || !term) return 0;
|
|
3976
|
-
const escaped = term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3977
|
-
return text.match(new RegExp(escaped, "gi"))?.length ?? 0;
|
|
3978
|
-
};
|
|
3979
|
-
var previewFor = (session, terms) => {
|
|
3980
|
-
const matched = session.messages.map((message) => ({
|
|
3981
|
-
message,
|
|
3982
|
-
score: terms.reduce((total, term) => total + countTerm(message.content, term), 0)
|
|
3983
|
-
})).filter((entry) => entry.score > 0).sort((a, b) => b.score - a.score)[0]?.message;
|
|
3984
|
-
const value = matched?.content ?? session.messages.at(-1)?.content ?? session.title;
|
|
3985
|
-
const singleLine = value.replace(/\s+/g, " ").trim();
|
|
3986
|
-
return singleLine.length > 180 ? `${singleLine.slice(0, 177)}...` : singleLine;
|
|
3987
|
-
};
|
|
3988
|
-
var scoreSession = (session, terms) => {
|
|
3989
|
-
const title = session.title.toLowerCase();
|
|
3990
|
-
const project = `${session.projectId ?? ""} ${session.projectName ?? ""}`.toLowerCase();
|
|
3991
|
-
const messages = session.messages.map((message) => message.content).join("\n").toLowerCase();
|
|
3992
|
-
return terms.reduce(
|
|
3993
|
-
(score, term) => score + countTerm(title, term) * 8 + countTerm(project, term) * 4 + countTerm(messages, term),
|
|
3994
|
-
0
|
|
3995
|
-
);
|
|
3996
|
-
};
|
|
3997
|
-
var toSearchResult = (session, score, terms) => ({
|
|
3998
|
-
threadId: session.threadId,
|
|
3999
|
-
title: session.title,
|
|
4000
|
-
projectId: session.projectId,
|
|
4001
|
-
projectName: session.projectName,
|
|
4002
|
-
model: session.model,
|
|
4003
|
-
profile: session.profile,
|
|
4004
|
-
createdAt: session.createdAt,
|
|
4005
|
-
updatedAt: session.updatedAt,
|
|
4006
|
-
messageCount: session.messageCount,
|
|
4007
|
-
score,
|
|
4008
|
-
preview: previewFor(session, terms)
|
|
4009
|
-
});
|
|
4010
|
-
var searchSessions = async (query, options = {}) => {
|
|
4011
|
-
const terms = searchTerms(query);
|
|
4012
|
-
const sessions = await exportSessions(options.profile);
|
|
4013
|
-
if (!terms.length) {
|
|
4014
|
-
return sessions.slice(0, Math.max(1, options.limit ?? 20)).map((session) => toSearchResult(session, 0, []));
|
|
4015
|
-
}
|
|
4016
|
-
return sessions.map((session) => ({
|
|
4017
|
-
session,
|
|
4018
|
-
score: scoreSession(session, terms)
|
|
4019
|
-
})).filter((entry) => entry.score > 0).sort((a, b) => b.score - a.score || b.session.updatedAt.localeCompare(a.session.updatedAt)).slice(0, Math.max(1, options.limit ?? 20)).map((entry) => toSearchResult(entry.session, entry.score, terms));
|
|
4020
|
-
};
|
|
4021
|
-
var resolveSessionReference = async (reference, profile) => {
|
|
4022
|
-
const trimmed = reference.trim();
|
|
4023
|
-
if (!trimmed) {
|
|
4024
|
-
return null;
|
|
4025
|
-
}
|
|
4026
|
-
const exact = await getSession(trimmed, profile);
|
|
4027
|
-
if (exact) {
|
|
4028
|
-
return exact;
|
|
4029
|
-
}
|
|
4030
|
-
const sessions = await exportSessions(profile);
|
|
4031
|
-
const lower = trimmed.toLowerCase();
|
|
4032
|
-
return sessions.find((session) => session.title.toLowerCase() === lower) ?? sessions.find((session) => session.threadId.startsWith(trimmed)) ?? sessions.find((session) => session.title.toLowerCase().includes(lower)) ?? null;
|
|
4033
|
-
};
|
|
4034
|
-
var deleteSession = async (threadId, profile) => {
|
|
4035
|
-
const deleted = await withSessionDatabase(profile, (db) => {
|
|
4036
|
-
const existing = getSessionFromDb(db, threadId);
|
|
4037
|
-
if (!existing) {
|
|
4038
|
-
return false;
|
|
4039
|
-
}
|
|
4040
|
-
db.run("DELETE FROM sessions WHERE thread_id = ?", [threadId]);
|
|
4041
|
-
return true;
|
|
4042
|
-
});
|
|
4043
|
-
try {
|
|
4044
|
-
await fs3.unlink(legacySessionPath(threadId, profile));
|
|
4045
|
-
} catch (error) {
|
|
4046
|
-
if (error?.code !== "ENOENT") {
|
|
4047
|
-
throw error;
|
|
4048
|
-
}
|
|
4049
|
-
}
|
|
4050
|
-
return deleted;
|
|
4051
|
-
};
|
|
4052
|
-
var exportSessions = async (profile) => listSessions(Number.MAX_SAFE_INTEGER, profile);
|
|
4053
|
-
var pruneSessions = async (olderThanDays, profile) => {
|
|
4054
|
-
const cutoff = Date.now() - Math.max(1, olderThanDays) * 24 * 60 * 60 * 1e3;
|
|
4055
|
-
const sessions = await exportSessions(profile);
|
|
4056
|
-
let deleted = 0;
|
|
4057
|
-
for (const session of sessions) {
|
|
4058
|
-
const updatedAt = Date.parse(session.updatedAt);
|
|
4059
|
-
if (Number.isFinite(updatedAt) && updatedAt < cutoff) {
|
|
4060
|
-
if (await deleteSession(session.threadId, profile)) {
|
|
4061
|
-
deleted++;
|
|
4062
|
-
}
|
|
4063
|
-
}
|
|
4064
|
-
}
|
|
4065
|
-
return deleted;
|
|
4066
|
-
};
|
|
4067
|
-
|
|
4068
3385
|
// src/recipesCommand.ts
|
|
4069
3386
|
var STREAM_OUTPUT_NODES = /* @__PURE__ */ new Set([
|
|
4070
3387
|
"generate_response",
|
|
@@ -4128,7 +3445,7 @@ var writeRecipeList = async (options) => {
|
|
|
4128
3445
|
if (format === "table" || format === "text") {
|
|
4129
3446
|
const text = renderRecipesTable();
|
|
4130
3447
|
if (options.output) {
|
|
4131
|
-
await
|
|
3448
|
+
await fs2.writeFile(options.output, text, "utf8");
|
|
4132
3449
|
return;
|
|
4133
3450
|
}
|
|
4134
3451
|
process.stdout.write(text);
|
|
@@ -4137,7 +3454,7 @@ var writeRecipeList = async (options) => {
|
|
|
4137
3454
|
if (format === "markdown") {
|
|
4138
3455
|
const text = renderRecipesMarkdown();
|
|
4139
3456
|
if (options.output) {
|
|
4140
|
-
await
|
|
3457
|
+
await fs2.writeFile(options.output, text, "utf8");
|
|
4141
3458
|
return;
|
|
4142
3459
|
}
|
|
4143
3460
|
process.stdout.write(text);
|
|
@@ -4155,7 +3472,7 @@ var writeRecipeShow = async (recipe, options) => {
|
|
|
4155
3472
|
if (format === "markdown" || format === "text") {
|
|
4156
3473
|
const text = renderRecipeMarkdown(recipe);
|
|
4157
3474
|
if (options.output) {
|
|
4158
|
-
await
|
|
3475
|
+
await fs2.writeFile(options.output, text, "utf8");
|
|
4159
3476
|
return;
|
|
4160
3477
|
}
|
|
4161
3478
|
process.stdout.write(text);
|
|
@@ -4212,7 +3529,7 @@ var runChatRecipe = async (recipe, prompt2, options, command, deps) => {
|
|
|
4212
3529
|
});
|
|
4213
3530
|
progressWriter.write({ type: "auth", step: "auth", message: "Resolving authentication" });
|
|
4214
3531
|
const context = await resolveAuthContext(options, command, deps);
|
|
4215
|
-
const core = await import("./dist-
|
|
3532
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
4216
3533
|
progressWriter.write({
|
|
4217
3534
|
type: "request",
|
|
4218
3535
|
step: "project",
|
|
@@ -4264,88 +3581,528 @@ var runChatRecipe = async (recipe, prompt2, options, command, deps) => {
|
|
|
4264
3581
|
throw new Error(chunk.message || chunk.description || "CloudEval recipe failed.");
|
|
4265
3582
|
}
|
|
4266
3583
|
}
|
|
4267
|
-
const finalMessage = [...chatState.messages].reverse().find((message) => message.role === "assistant");
|
|
4268
|
-
const finalResponse = collapseRepeatedAssistantText(finalMessage?.content || responseText || "");
|
|
4269
|
-
if (!finalResponse.trim()) {
|
|
4270
|
-
throw new Error("No final response returned by CloudEval for this recipe.");
|
|
3584
|
+
const finalMessage = [...chatState.messages].reverse().find((message) => message.role === "assistant");
|
|
3585
|
+
const finalResponse = collapseRepeatedAssistantText(finalMessage?.content || responseText || "");
|
|
3586
|
+
if (!finalResponse.trim()) {
|
|
3587
|
+
throw new Error("No final response returned by CloudEval for this recipe.");
|
|
3588
|
+
}
|
|
3589
|
+
const frontendUrl = buildFrontendUrl({
|
|
3590
|
+
baseUrl: resolveFrontendBaseUrl({
|
|
3591
|
+
frontendUrl: selectedFrontendUrl,
|
|
3592
|
+
apiBaseUrl: context.baseUrl
|
|
3593
|
+
}),
|
|
3594
|
+
target: "chat",
|
|
3595
|
+
threadId: chatState.threadId
|
|
3596
|
+
});
|
|
3597
|
+
await recordSessionTurn({
|
|
3598
|
+
threadId: chatState.threadId,
|
|
3599
|
+
question: prompt2,
|
|
3600
|
+
response: finalResponse,
|
|
3601
|
+
project: { id: project.id, name: project.name },
|
|
3602
|
+
model: selectedModel,
|
|
3603
|
+
profile: selectedProfile
|
|
3604
|
+
}).catch(() => void 0);
|
|
3605
|
+
progressWriter.clear();
|
|
3606
|
+
return {
|
|
3607
|
+
recipeId: recipe.id,
|
|
3608
|
+
title: recipe.title,
|
|
3609
|
+
mode: recipe.mode,
|
|
3610
|
+
prompt: prompt2,
|
|
3611
|
+
response: finalResponse,
|
|
3612
|
+
threadId: chatState.threadId,
|
|
3613
|
+
project: { id: project.id, name: project.name },
|
|
3614
|
+
commands: renderRecipeCommands(recipe, recipeContext(options)),
|
|
3615
|
+
safety: recipe.safety,
|
|
3616
|
+
frontendUrl
|
|
3617
|
+
};
|
|
3618
|
+
};
|
|
3619
|
+
var buildGuideResult = (recipe, context) => ({
|
|
3620
|
+
recipeId: recipe.id,
|
|
3621
|
+
title: recipe.title,
|
|
3622
|
+
mode: recipe.mode,
|
|
3623
|
+
prompt: renderRecipePrompt(recipe, context),
|
|
3624
|
+
commands: renderRecipeCommands(recipe, context),
|
|
3625
|
+
inputs: context,
|
|
3626
|
+
safety: recipe.safety,
|
|
3627
|
+
expectedOutput: recipe.expectedOutput,
|
|
3628
|
+
note: "This recipe requires explicit user-run commands for side effects; no project, file, billing, or MCP config mutation was performed."
|
|
3629
|
+
});
|
|
3630
|
+
var registerRecipesCommand = (program2, deps) => {
|
|
3631
|
+
const command = program2.command("recipes").description("CloudEval reusable recipes and agent skills");
|
|
3632
|
+
command.command("list").description("List CloudEval recipes").option("--format <format>", "Output format: table, text, json, ndjson, markdown", "table").option("--output <file>", "Output file").action((options) => writeRecipeList(options));
|
|
3633
|
+
command.command("show").description("Show a CloudEval recipe").argument("<id>", "Recipe id").option("--format <format>", "Output format: text, json, ndjson, markdown", "markdown").option("--output <file>", "Output file").action(async (id, options) => {
|
|
3634
|
+
const recipe = getRecipe(id);
|
|
3635
|
+
if (!recipe) {
|
|
3636
|
+
console.error(`Unknown recipe '${id}'. Run 'cloudeval recipes list' to see available recipes.`);
|
|
3637
|
+
process.exit(1);
|
|
3638
|
+
}
|
|
3639
|
+
await writeRecipeShow(recipe, options);
|
|
3640
|
+
});
|
|
3641
|
+
addAuthOptions(
|
|
3642
|
+
command.command("run").description("Run a CloudEval recipe or print explicit commands for side-effecting recipes").argument("<id>", "Recipe id"),
|
|
3643
|
+
deps.defaultBaseUrl
|
|
3644
|
+
).option("--project <id>", "Project ID to use").option("--connection-id <id>", "Connection id for connection recipes").option("--credential-id <id>", "Credential id for credential recipes").option("--range <range>", "Usage/report range such as 7d, 30d, 90d, all", "30d").option("--template-file <path>", "Local JSON template file").option("--template-url <url>", "Template URL").option("--parameters-file <path>", "Local parameters file").option("--parameters-url <url>", "Parameters URL").option("--provider <provider>", "Cloud provider accepted by projects create").option("--name <name>", "Project or recipe display name").option("--output-path <path>", "Side-effect output path for guide recipes").option("--output-dir <path>", "Side-effect output directory for guide recipes").option("--client <name>", "MCP client name for setup recipes").option("--layout <layout>", "Visualization layout such as architecture or dependency").option("--model <name>", "Model name").option("--thread <id>", "Thread id to reuse").option("--format <format>", "Output format: text, json, ndjson, markdown", "text").option("--output <file>", "Output file").option("--progress <mode>", "Progress events: auto, stderr, ndjson, none", "auto").option("--quiet", "Suppress progress and warning messages", false).option("--frontend-url <url>", "Frontend base URL").action(async (id, options, actionCommand) => {
|
|
3645
|
+
const recipe = getRecipe(id);
|
|
3646
|
+
if (!recipe) {
|
|
3647
|
+
console.error(`Unknown recipe '${id}'. Run 'cloudeval recipes list' to see available recipes.`);
|
|
3648
|
+
process.exit(1);
|
|
3649
|
+
}
|
|
3650
|
+
try {
|
|
3651
|
+
const context = recipeContext(options);
|
|
3652
|
+
const prompt2 = renderRecipePrompt(recipe, context);
|
|
3653
|
+
const result = recipe.mode === "guide" ? buildGuideResult(recipe, context) : await runChatRecipe(recipe, prompt2, options, actionCommand, deps);
|
|
3654
|
+
const frontendUrl = "frontendUrl" in result ? result.frontendUrl : void 0;
|
|
3655
|
+
await writeFormattedOutput({
|
|
3656
|
+
command: "recipes run",
|
|
3657
|
+
data: result,
|
|
3658
|
+
format: options.format === "table" ? "text" : options.format,
|
|
3659
|
+
output: options.output,
|
|
3660
|
+
frontendUrl
|
|
3661
|
+
});
|
|
3662
|
+
} catch (error) {
|
|
3663
|
+
console.error(`Failed to run recipe: ${error?.message ?? "Unknown error"}`);
|
|
3664
|
+
process.exit(1);
|
|
3665
|
+
}
|
|
3666
|
+
});
|
|
3667
|
+
};
|
|
3668
|
+
|
|
3669
|
+
// src/skillsCommand.ts
|
|
3670
|
+
import fs4 from "fs/promises";
|
|
3671
|
+
|
|
3672
|
+
// src/skills/catalog.ts
|
|
3673
|
+
import fs3 from "fs/promises";
|
|
3674
|
+
import fsSync from "fs";
|
|
3675
|
+
import path2 from "path";
|
|
3676
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3677
|
+
var repoRoot = path2.resolve(fileURLToPath2(new URL("../../../../", import.meta.url)));
|
|
3678
|
+
var defaultSkillsPath = path2.join(repoRoot, "skills");
|
|
3679
|
+
var requiredSkillSections = [
|
|
3680
|
+
"## WHEN",
|
|
3681
|
+
"## DO NOT USE FOR",
|
|
3682
|
+
"## Required CloudEval Context",
|
|
3683
|
+
"## CLI Commands",
|
|
3684
|
+
"## MCP Tools",
|
|
3685
|
+
"## Safety Requirements",
|
|
3686
|
+
"## Expected Output / Proof",
|
|
3687
|
+
"## Failure Handling"
|
|
3688
|
+
];
|
|
3689
|
+
var bundledSkillMetadata = [
|
|
3690
|
+
{
|
|
3691
|
+
id: "cloudeval",
|
|
3692
|
+
title: "CloudEval Skill Router",
|
|
3693
|
+
description: "Routes CloudEval CLI and MCP work across projects, reports, billing, credentials, connections, diagnostics, recipes, and agent workflows."
|
|
3694
|
+
},
|
|
3695
|
+
{
|
|
3696
|
+
id: "cloudeval-agent-ops",
|
|
3697
|
+
title: "CloudEval Agent Ops",
|
|
3698
|
+
description: "Runs CloudEval ask, agent, chat/TUI, model selection, recipes, and local session recovery."
|
|
3699
|
+
},
|
|
3700
|
+
{
|
|
3701
|
+
id: "cloudeval-billing",
|
|
3702
|
+
title: "CloudEval Billing",
|
|
3703
|
+
description: "Inspects CloudEval credits, plans, usage, ledger, invoices, notifications, top-ups, and checkout links."
|
|
3704
|
+
},
|
|
3705
|
+
{
|
|
3706
|
+
id: "cloudeval-connections",
|
|
3707
|
+
title: "CloudEval Connections",
|
|
3708
|
+
description: "Inspects CloudEval cloud/template connections, connection health, and connection frontend links."
|
|
3709
|
+
},
|
|
3710
|
+
{
|
|
3711
|
+
id: "cloudeval-cost",
|
|
3712
|
+
title: "CloudEval Cost",
|
|
3713
|
+
description: "Triages CloudEval cost reports, billing usage, savings opportunities, anomalies, and credit impact."
|
|
3714
|
+
},
|
|
3715
|
+
{
|
|
3716
|
+
id: "cloudeval-credentials",
|
|
3717
|
+
title: "CloudEval Credentials",
|
|
3718
|
+
description: "Manages CloudEval scoped access-key templates, creation, inspection, rotation, and revocation."
|
|
3719
|
+
},
|
|
3720
|
+
{
|
|
3721
|
+
id: "cloudeval-graph-intelligence",
|
|
3722
|
+
title: "CloudEval Graph Intelligence",
|
|
3723
|
+
description: "Inspects project graphs, graph drift, sync history, dependency impact, critical paths, and graph-derived risk signals."
|
|
3724
|
+
},
|
|
3725
|
+
{
|
|
3726
|
+
id: "cloudeval-mcp-diagnostics",
|
|
3727
|
+
title: "CloudEval MCP Diagnostics",
|
|
3728
|
+
description: "Sets up and diagnoses CloudEval MCP, config, auth, doctor, status, update, completion, banner, and deeplinks."
|
|
3729
|
+
},
|
|
3730
|
+
{
|
|
3731
|
+
id: "cloudeval-projects",
|
|
3732
|
+
title: "CloudEval Projects",
|
|
3733
|
+
description: "Lists, inspects, creates, opens, and health-checks CloudEval projects and template project workflows."
|
|
3734
|
+
},
|
|
3735
|
+
{
|
|
3736
|
+
id: "cloudeval-reports",
|
|
3737
|
+
title: "CloudEval Reports",
|
|
3738
|
+
description: "Lists, shows, generates, downloads, and summarizes CloudEval cost and Well-Architected reports."
|
|
3739
|
+
},
|
|
3740
|
+
{
|
|
3741
|
+
id: "cloudeval-template-validation",
|
|
3742
|
+
title: "CloudEval Template Validation",
|
|
3743
|
+
description: "Validates, parses, tests, and release-gates CloudEval-supported cloud template files."
|
|
3744
|
+
},
|
|
3745
|
+
{
|
|
3746
|
+
id: "cloudeval-visualizations",
|
|
3747
|
+
title: "CloudEval Visualizations",
|
|
3748
|
+
description: "Exports CloudEval architecture or dependency diagrams and prepares visual evidence for reviews."
|
|
3749
|
+
},
|
|
3750
|
+
{
|
|
3751
|
+
id: "cloudeval-waf",
|
|
3752
|
+
title: "CloudEval WAF",
|
|
3753
|
+
description: "Triages CloudEval Well-Architected findings, failed rules, pillar risk, and remediation plans."
|
|
3754
|
+
}
|
|
3755
|
+
];
|
|
3756
|
+
var metadataById = new Map(bundledSkillMetadata.map((skill) => [skill.id, skill]));
|
|
3757
|
+
var normalizeSkillId = (id) => {
|
|
3758
|
+
const normalized = id.trim().toLowerCase();
|
|
3759
|
+
if (metadataById.has(normalized)) {
|
|
3760
|
+
return normalized;
|
|
3761
|
+
}
|
|
3762
|
+
const prefixed = `cloudeval-${normalized}`;
|
|
3763
|
+
return metadataById.has(prefixed) ? prefixed : normalized;
|
|
3764
|
+
};
|
|
3765
|
+
var getSkillsPath = () => process.env.CLOUDEVAL_SKILLS_PATH ?? defaultSkillsPath;
|
|
3766
|
+
var skillFilePath = (id) => path2.join(getSkillsPath(), id, "SKILL.md");
|
|
3767
|
+
var fileExists = (filePath) => {
|
|
3768
|
+
try {
|
|
3769
|
+
return fsSync.statSync(filePath).isFile();
|
|
3770
|
+
} catch {
|
|
3771
|
+
return false;
|
|
3772
|
+
}
|
|
3773
|
+
};
|
|
3774
|
+
var readSkillFile = async (id) => {
|
|
3775
|
+
const filePath = skillFilePath(id);
|
|
3776
|
+
if (fileExists(filePath)) {
|
|
3777
|
+
return {
|
|
3778
|
+
content: await fs3.readFile(filePath, "utf8"),
|
|
3779
|
+
path: filePath,
|
|
3780
|
+
source: "filesystem"
|
|
3781
|
+
};
|
|
3782
|
+
}
|
|
3783
|
+
return {
|
|
3784
|
+
content: synthesizeSkillContent(metadataById.get(id) ?? {
|
|
3785
|
+
id,
|
|
3786
|
+
title: id,
|
|
3787
|
+
description: "CloudEval skill metadata."
|
|
3788
|
+
}),
|
|
3789
|
+
source: "embedded"
|
|
3790
|
+
};
|
|
3791
|
+
};
|
|
3792
|
+
var recipesForSkill = (id) => recipes.filter((recipe) => recipe.skill === id);
|
|
3793
|
+
var unique = (values) => [...new Set(values)].filter(Boolean).sort();
|
|
3794
|
+
var summarizeSkill = async (metadata) => {
|
|
3795
|
+
const file = await readSkillFile(metadata.id);
|
|
3796
|
+
const skillRecipes = recipesForSkill(metadata.id);
|
|
3797
|
+
return {
|
|
3798
|
+
...metadata,
|
|
3799
|
+
path: file.path,
|
|
3800
|
+
source: file.source,
|
|
3801
|
+
recipes: skillRecipes.map((recipe) => recipe.id),
|
|
3802
|
+
mcpTools: unique(skillRecipes.flatMap((recipe) => recipe.mcpTools))
|
|
3803
|
+
};
|
|
3804
|
+
};
|
|
3805
|
+
var listSkills = async () => Promise.all(bundledSkillMetadata.map(summarizeSkill));
|
|
3806
|
+
var getSkill = async (id) => {
|
|
3807
|
+
const normalized = normalizeSkillId(id);
|
|
3808
|
+
const metadata = metadataById.get(normalized);
|
|
3809
|
+
if (!metadata) {
|
|
3810
|
+
return void 0;
|
|
3811
|
+
}
|
|
3812
|
+
const [summary, file] = await Promise.all([
|
|
3813
|
+
summarizeSkill(metadata),
|
|
3814
|
+
readSkillFile(metadata.id)
|
|
3815
|
+
]);
|
|
3816
|
+
return {
|
|
3817
|
+
...summary,
|
|
3818
|
+
content: file.content
|
|
3819
|
+
};
|
|
3820
|
+
};
|
|
3821
|
+
var synthesizeSkillContent = (metadata) => `---
|
|
3822
|
+
name: ${metadata.id}
|
|
3823
|
+
description: ${metadata.description}
|
|
3824
|
+
---
|
|
3825
|
+
|
|
3826
|
+
# ${metadata.title}
|
|
3827
|
+
|
|
3828
|
+
## WHEN
|
|
3829
|
+
- Use this bundled CloudEval skill when source SKILL.md files are unavailable at runtime.
|
|
3830
|
+
|
|
3831
|
+
## DO NOT USE FOR
|
|
3832
|
+
- Unsupported CloudEval capabilities or private backend internals.
|
|
3833
|
+
|
|
3834
|
+
## Required CloudEval Context
|
|
3835
|
+
- Run \`cloudeval capabilities --format json\` and \`cloudeval recipes list\` to discover available commands.
|
|
3836
|
+
|
|
3837
|
+
## CLI Commands
|
|
3838
|
+
- \`cloudeval skills show ${metadata.id}\`
|
|
3839
|
+
- \`cloudeval recipes list\`
|
|
3840
|
+
|
|
3841
|
+
## MCP Tools
|
|
3842
|
+
- \`capabilities_get\`
|
|
3843
|
+
- \`recipes_list\`
|
|
3844
|
+
|
|
3845
|
+
## Safety Requirements
|
|
3846
|
+
- Redact secrets, account identifiers, session identifiers, tenant identifiers, billing data, and raw report payloads by default.
|
|
3847
|
+
|
|
3848
|
+
## Expected Output / Proof
|
|
3849
|
+
- State the command or MCP tool used and separate confirmed evidence from missing data.
|
|
3850
|
+
|
|
3851
|
+
## Failure Handling
|
|
3852
|
+
- If the source skill file is needed, run from a CloudEval CLI checkout or inspect the public repository.
|
|
3853
|
+
`;
|
|
3854
|
+
var frontMatterNamePattern = (id) => new RegExp(`^---[\\s\\S]*?^name:\\s*${id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*$[\\s\\S]*?^---`, "m");
|
|
3855
|
+
var sensitivePatterns = [
|
|
3856
|
+
/sk-or-v1-[a-z0-9]{16,}/i,
|
|
3857
|
+
/sk-[a-z0-9]{20,}/i,
|
|
3858
|
+
/ghp_[a-z0-9]{20,}/i,
|
|
3859
|
+
/xox[baprs]-[a-z0-9-]{20,}/i,
|
|
3860
|
+
/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/
|
|
3861
|
+
];
|
|
3862
|
+
var unsupportedClaims = [
|
|
3863
|
+
/\bterraform\b/i,
|
|
3864
|
+
/\bpull request\b/i,
|
|
3865
|
+
/\bgithub pr\b/i,
|
|
3866
|
+
/\bpr integration\b/i
|
|
3867
|
+
];
|
|
3868
|
+
var validateSkillText = (id, text, file) => {
|
|
3869
|
+
const checks = [];
|
|
3870
|
+
checks.push({
|
|
3871
|
+
id: `${id}:frontmatter-name`,
|
|
3872
|
+
status: frontMatterNamePattern(id).test(text) ? "pass" : "fail",
|
|
3873
|
+
message: `Skill ${id} declares matching frontmatter name.`,
|
|
3874
|
+
file
|
|
3875
|
+
});
|
|
3876
|
+
for (const section of requiredSkillSections) {
|
|
3877
|
+
checks.push({
|
|
3878
|
+
id: `${id}:section:${section.replace(/^##\s+/, "").toLowerCase().replace(/[^a-z0-9]+/g, "-")}`,
|
|
3879
|
+
status: text.includes(section) ? "pass" : "fail",
|
|
3880
|
+
message: `Skill ${id} includes ${section}.`,
|
|
3881
|
+
file
|
|
3882
|
+
});
|
|
3883
|
+
}
|
|
3884
|
+
for (const pattern of sensitivePatterns) {
|
|
3885
|
+
checks.push({
|
|
3886
|
+
id: `${id}:no-sensitive-pattern:${pattern.source.slice(0, 24)}`,
|
|
3887
|
+
status: pattern.test(text) ? "fail" : "pass",
|
|
3888
|
+
message: `Skill ${id} does not contain obvious secret patterns.`,
|
|
3889
|
+
file
|
|
3890
|
+
});
|
|
3891
|
+
}
|
|
3892
|
+
for (const pattern of unsupportedClaims) {
|
|
3893
|
+
checks.push({
|
|
3894
|
+
id: `${id}:no-unsupported-claim:${pattern.source}`,
|
|
3895
|
+
status: pattern.test(text) ? "fail" : "pass",
|
|
3896
|
+
message: `Skill ${id} does not claim unsupported workflows.`,
|
|
3897
|
+
file
|
|
3898
|
+
});
|
|
3899
|
+
}
|
|
3900
|
+
return checks;
|
|
3901
|
+
};
|
|
3902
|
+
var validateSkills = async () => {
|
|
3903
|
+
const skills = await listSkills();
|
|
3904
|
+
const knownIds = new Set(skills.map((skill) => skill.id));
|
|
3905
|
+
const checks = [];
|
|
3906
|
+
for (const recipe of recipes) {
|
|
3907
|
+
checks.push({
|
|
3908
|
+
id: `recipe:${recipe.id}:skill-exists`,
|
|
3909
|
+
status: knownIds.has(recipe.skill) ? "pass" : "fail",
|
|
3910
|
+
message: `Recipe ${recipe.id} references implemented skill ${recipe.skill}.`
|
|
3911
|
+
});
|
|
3912
|
+
}
|
|
3913
|
+
for (const skill of skills) {
|
|
3914
|
+
const file = await readSkillFile(skill.id);
|
|
3915
|
+
checks.push({
|
|
3916
|
+
id: `${skill.id}:source`,
|
|
3917
|
+
status: file.source === "filesystem" ? "pass" : "fail",
|
|
3918
|
+
message: `Skill ${skill.id} has a public SKILL.md file.`,
|
|
3919
|
+
file: file.path
|
|
3920
|
+
});
|
|
3921
|
+
checks.push(...validateSkillText(skill.id, file.content, file.path));
|
|
3922
|
+
}
|
|
3923
|
+
return {
|
|
3924
|
+
ok: checks.every((check) => check.status === "pass"),
|
|
3925
|
+
skillsPath: getSkillsPath(),
|
|
3926
|
+
skills,
|
|
3927
|
+
checks
|
|
3928
|
+
};
|
|
3929
|
+
};
|
|
3930
|
+
var skillsResourceData = async () => ({
|
|
3931
|
+
skillsPath: getSkillsPath(),
|
|
3932
|
+
skills: await listSkills(),
|
|
3933
|
+
requiredSections: [...requiredSkillSections]
|
|
3934
|
+
});
|
|
3935
|
+
|
|
3936
|
+
// src/skillsCommand.ts
|
|
3937
|
+
var renderSkillsTable = (skills) => formatTextTable(
|
|
3938
|
+
skills.map((skill) => ({
|
|
3939
|
+
id: skill.id,
|
|
3940
|
+
title: skill.title,
|
|
3941
|
+
recipes: skill.recipes.length,
|
|
3942
|
+
tools: skill.mcpTools.length,
|
|
3943
|
+
source: skill.source
|
|
3944
|
+
})),
|
|
3945
|
+
[
|
|
3946
|
+
{ key: "id", header: "ID", width: 36 },
|
|
3947
|
+
{ key: "title", header: "Title", maxWidth: 40 },
|
|
3948
|
+
{ key: "recipes", header: "Recipes", align: "right" },
|
|
3949
|
+
{ key: "tools", header: "MCP Tools", align: "right" },
|
|
3950
|
+
{ key: "source", header: "Source", maxWidth: 12 }
|
|
3951
|
+
],
|
|
3952
|
+
{ emptyMessage: "No CloudEval skills found." }
|
|
3953
|
+
);
|
|
3954
|
+
var renderSkillsMarkdown = (skills) => [
|
|
3955
|
+
"# CloudEval Skills",
|
|
3956
|
+
"",
|
|
3957
|
+
...skills.map((skill) => [
|
|
3958
|
+
`## ${skill.title}`,
|
|
3959
|
+
"",
|
|
3960
|
+
`- ID: ${skill.id}`,
|
|
3961
|
+
`- Source: ${skill.source}`,
|
|
3962
|
+
`- Recipes: ${skill.recipes.length ? skill.recipes.join(", ") : "none"}`,
|
|
3963
|
+
`- MCP tools: ${skill.mcpTools.length ? skill.mcpTools.join(", ") : "none"}`,
|
|
3964
|
+
"",
|
|
3965
|
+
skill.description,
|
|
3966
|
+
""
|
|
3967
|
+
].join("\n"))
|
|
3968
|
+
].join("\n");
|
|
3969
|
+
var writeSkillList = async (options) => {
|
|
3970
|
+
const skills = await listSkills();
|
|
3971
|
+
const format = options.format ?? "table";
|
|
3972
|
+
if (format === "table" || format === "text") {
|
|
3973
|
+
const text = renderSkillsTable(skills);
|
|
3974
|
+
if (options.output) {
|
|
3975
|
+
await fs4.writeFile(options.output, text, "utf8");
|
|
3976
|
+
return;
|
|
3977
|
+
}
|
|
3978
|
+
process.stdout.write(text);
|
|
3979
|
+
return;
|
|
3980
|
+
}
|
|
3981
|
+
if (format === "markdown") {
|
|
3982
|
+
const text = renderSkillsMarkdown(skills);
|
|
3983
|
+
if (options.output) {
|
|
3984
|
+
await fs4.writeFile(options.output, text, "utf8");
|
|
3985
|
+
return;
|
|
3986
|
+
}
|
|
3987
|
+
process.stdout.write(text);
|
|
3988
|
+
return;
|
|
4271
3989
|
}
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
target: "chat",
|
|
4278
|
-
threadId: chatState.threadId
|
|
3990
|
+
await writeFormattedOutput({
|
|
3991
|
+
command: "skills list",
|
|
3992
|
+
data: { skills },
|
|
3993
|
+
format,
|
|
3994
|
+
output: options.output
|
|
4279
3995
|
});
|
|
4280
|
-
await recordSessionTurn({
|
|
4281
|
-
threadId: chatState.threadId,
|
|
4282
|
-
question: prompt2,
|
|
4283
|
-
response: finalResponse,
|
|
4284
|
-
project: { id: project.id, name: project.name },
|
|
4285
|
-
model: selectedModel,
|
|
4286
|
-
profile: selectedProfile
|
|
4287
|
-
}).catch(() => void 0);
|
|
4288
|
-
progressWriter.clear();
|
|
4289
|
-
return {
|
|
4290
|
-
recipeId: recipe.id,
|
|
4291
|
-
title: recipe.title,
|
|
4292
|
-
mode: recipe.mode,
|
|
4293
|
-
prompt: prompt2,
|
|
4294
|
-
response: finalResponse,
|
|
4295
|
-
threadId: chatState.threadId,
|
|
4296
|
-
project: { id: project.id, name: project.name },
|
|
4297
|
-
commands: renderRecipeCommands(recipe, recipeContext(options)),
|
|
4298
|
-
safety: recipe.safety,
|
|
4299
|
-
frontendUrl
|
|
4300
|
-
};
|
|
4301
3996
|
};
|
|
4302
|
-
var
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
const command = program2.command("recipes").description("CloudEval reusable recipes and agent skills");
|
|
4315
|
-
command.command("list").description("List CloudEval recipes").option("--format <format>", "Output format: table, text, json, ndjson, markdown", "table").option("--output <file>", "Output file").action((options) => writeRecipeList(options));
|
|
4316
|
-
command.command("show").description("Show a CloudEval recipe").argument("<id>", "Recipe id").option("--format <format>", "Output format: text, json, ndjson, markdown", "markdown").option("--output <file>", "Output file").action(async (id, options) => {
|
|
4317
|
-
const recipe = getRecipe(id);
|
|
4318
|
-
if (!recipe) {
|
|
4319
|
-
console.error(`Unknown recipe '${id}'. Run 'cloudeval recipes list' to see available recipes.`);
|
|
4320
|
-
process.exit(1);
|
|
3997
|
+
var writeSkillShow = async (id, options) => {
|
|
3998
|
+
const skill = await getSkill(id);
|
|
3999
|
+
if (!skill) {
|
|
4000
|
+
process.stderr.write(`Unknown skill '${id}'. Run 'cloudeval skills list' to see available skills.
|
|
4001
|
+
`);
|
|
4002
|
+
process.exit(1);
|
|
4003
|
+
}
|
|
4004
|
+
const format = options.format ?? "markdown";
|
|
4005
|
+
if (format === "markdown" || format === "text") {
|
|
4006
|
+
if (options.output) {
|
|
4007
|
+
await fs4.writeFile(options.output, skill.content, "utf8");
|
|
4008
|
+
return;
|
|
4321
4009
|
}
|
|
4322
|
-
|
|
4010
|
+
process.stdout.write(skill.content);
|
|
4011
|
+
if (!skill.content.endsWith("\n")) {
|
|
4012
|
+
process.stdout.write("\n");
|
|
4013
|
+
}
|
|
4014
|
+
return;
|
|
4015
|
+
}
|
|
4016
|
+
await writeFormattedOutput({
|
|
4017
|
+
command: "skills show",
|
|
4018
|
+
data: skill,
|
|
4019
|
+
format: format === "table" ? "text" : format,
|
|
4020
|
+
output: options.output
|
|
4323
4021
|
});
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4022
|
+
};
|
|
4023
|
+
var writeSkillDoctor = async (options) => {
|
|
4024
|
+
const result = await validateSkills();
|
|
4025
|
+
const format = options.format ?? "table";
|
|
4026
|
+
if (format === "table" || format === "text") {
|
|
4027
|
+
const failed = result.checks.filter((check) => check.status === "fail");
|
|
4028
|
+
const text = [
|
|
4029
|
+
formatTextTable(
|
|
4030
|
+
[
|
|
4031
|
+
{
|
|
4032
|
+
ok: result.ok ? "yes" : "no",
|
|
4033
|
+
skills: result.skills.length,
|
|
4034
|
+
checks: result.checks.length,
|
|
4035
|
+
failures: failed.length,
|
|
4036
|
+
path: result.skillsPath
|
|
4037
|
+
}
|
|
4038
|
+
],
|
|
4039
|
+
[
|
|
4040
|
+
{ key: "ok", header: "OK", width: 4 },
|
|
4041
|
+
{ key: "skills", header: "Skills", align: "right" },
|
|
4042
|
+
{ key: "checks", header: "Checks", align: "right" },
|
|
4043
|
+
{ key: "failures", header: "Failures", align: "right" },
|
|
4044
|
+
{ key: "path", header: "Path", maxWidth: 72 }
|
|
4045
|
+
]
|
|
4046
|
+
).trimEnd(),
|
|
4047
|
+
failed.length ? "\nFailures\n" + formatTextTable(
|
|
4048
|
+
failed.map((check) => ({
|
|
4049
|
+
check: check.id,
|
|
4050
|
+
message: check.message,
|
|
4051
|
+
file: check.file ?? ""
|
|
4052
|
+
})),
|
|
4053
|
+
[
|
|
4054
|
+
{ key: "check", header: "Check", maxWidth: 44 },
|
|
4055
|
+
{ key: "message", header: "Message", maxWidth: 72 },
|
|
4056
|
+
{ key: "file", header: "File", maxWidth: 64 }
|
|
4057
|
+
]
|
|
4058
|
+
).trimEnd() : "",
|
|
4059
|
+
""
|
|
4060
|
+
].filter(Boolean).join("\n");
|
|
4061
|
+
if (options.output) {
|
|
4062
|
+
await fs4.writeFile(options.output, `${text}
|
|
4063
|
+
`, "utf8");
|
|
4064
|
+
return;
|
|
4332
4065
|
}
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4066
|
+
process.stdout.write(`${text}
|
|
4067
|
+
`);
|
|
4068
|
+
if (!result.ok) {
|
|
4069
|
+
process.exitCode = 1;
|
|
4070
|
+
}
|
|
4071
|
+
return;
|
|
4072
|
+
}
|
|
4073
|
+
await writeFormattedOutput({
|
|
4074
|
+
command: "skills doctor",
|
|
4075
|
+
data: result,
|
|
4076
|
+
format,
|
|
4077
|
+
output: options.output
|
|
4078
|
+
});
|
|
4079
|
+
if (!result.ok) {
|
|
4080
|
+
process.exitCode = 1;
|
|
4081
|
+
}
|
|
4082
|
+
};
|
|
4083
|
+
var registerSkillsCommand = (program2) => {
|
|
4084
|
+
const command = program2.command("skills").description("List, inspect, and validate CloudEval agent skills");
|
|
4085
|
+
command.command("list").description("List CloudEval skills").option("--format <format>", "Output format: table, text, json, ndjson, markdown", "table").option("--output <file>", "Output file").action((options) => writeSkillList(options));
|
|
4086
|
+
command.command("show").description("Show a CloudEval skill").argument("<id>", "Skill id").option("--format <format>", "Output format: text, json, ndjson, markdown", "markdown").option("--output <file>", "Output file").action((id, options) => writeSkillShow(id, options));
|
|
4087
|
+
command.command("doctor").description("Validate CloudEval skill files and recipe references").option("--format <format>", "Output format: table, text, json, ndjson, markdown", "table").option("--output <file>", "Output file").action((options) => writeSkillDoctor(options));
|
|
4088
|
+
command.command("path").description("Print the CloudEval skills directory").option("--format <format>", "Output format: text, json, ndjson, markdown", "text").option("--output <file>", "Output file").action(async (options) => {
|
|
4089
|
+
const skillsPath = getSkillsPath();
|
|
4090
|
+
if (!options.format || options.format === "text" || options.format === "table") {
|
|
4091
|
+
const text = `${skillsPath}
|
|
4092
|
+
`;
|
|
4093
|
+
if (options.output) {
|
|
4094
|
+
await fs4.writeFile(options.output, text, "utf8");
|
|
4095
|
+
return;
|
|
4096
|
+
}
|
|
4097
|
+
process.stdout.write(text);
|
|
4098
|
+
return;
|
|
4348
4099
|
}
|
|
4100
|
+
await writeFormattedOutput({
|
|
4101
|
+
command: "skills path",
|
|
4102
|
+
data: { skillsPath },
|
|
4103
|
+
format: options.format,
|
|
4104
|
+
output: options.output
|
|
4105
|
+
});
|
|
4349
4106
|
});
|
|
4350
4107
|
};
|
|
4351
4108
|
|
|
@@ -4507,7 +4264,7 @@ var registerOpenCommand = (program2, deps) => {
|
|
|
4507
4264
|
};
|
|
4508
4265
|
|
|
4509
4266
|
// src/projectsCommand.ts
|
|
4510
|
-
import
|
|
4267
|
+
import path3 from "path";
|
|
4511
4268
|
import fs5 from "fs/promises";
|
|
4512
4269
|
|
|
4513
4270
|
// src/projectDiagramImage.ts
|
|
@@ -4687,12 +4444,12 @@ var responseErrorMessage = async (response) => {
|
|
|
4687
4444
|
var fetchCloudEvalJson = async ({
|
|
4688
4445
|
baseUrl,
|
|
4689
4446
|
authToken,
|
|
4690
|
-
path:
|
|
4447
|
+
path: path10,
|
|
4691
4448
|
method = "GET",
|
|
4692
4449
|
query = {},
|
|
4693
4450
|
body
|
|
4694
4451
|
}) => {
|
|
4695
|
-
const url = new URL(`${normalizeApiBase(baseUrl)}${
|
|
4452
|
+
const url = new URL(`${normalizeApiBase(baseUrl)}${path10}`);
|
|
4696
4453
|
for (const [key, value] of Object.entries(query)) {
|
|
4697
4454
|
if (value !== void 0 && value !== null && value !== "") {
|
|
4698
4455
|
url.searchParams.set(key, String(value));
|
|
@@ -4880,11 +4637,11 @@ var fileBlob = async (filePath) => {
|
|
|
4880
4637
|
const bytes = await fs5.readFile(filePath);
|
|
4881
4638
|
return {
|
|
4882
4639
|
blob: new Blob([bytes], { type: "application/json" }),
|
|
4883
|
-
name:
|
|
4640
|
+
name: path3.basename(filePath)
|
|
4884
4641
|
};
|
|
4885
4642
|
};
|
|
4886
4643
|
var writeDiagramImageHeaders = async (outputPath, headers) => {
|
|
4887
|
-
await fs5.mkdir(
|
|
4644
|
+
await fs5.mkdir(path3.dirname(outputPath), { recursive: true });
|
|
4888
4645
|
const text = Object.entries(headers).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `${key}: ${value}`).join("\n");
|
|
4889
4646
|
await fs5.writeFile(outputPath, `${text}
|
|
4890
4647
|
`, "utf8");
|
|
@@ -5021,7 +4778,7 @@ var configureDiagramExportCommand = (command, deps) => addAuthOptions(command, d
|
|
|
5021
4778
|
const context = requireAuthUser(
|
|
5022
4779
|
await resolveAuthContext(options, actionCommand, deps)
|
|
5023
4780
|
);
|
|
5024
|
-
const core = await import("./dist-
|
|
4781
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5025
4782
|
const projects = await core.getProjects(
|
|
5026
4783
|
context.baseUrl,
|
|
5027
4784
|
context.token,
|
|
@@ -5049,9 +4806,9 @@ var configureDiagramExportCommand = (command, deps) => addAuthOptions(command, d
|
|
|
5049
4806
|
publicGraph,
|
|
5050
4807
|
syncVersion: options.syncVersion
|
|
5051
4808
|
});
|
|
5052
|
-
const outputPath =
|
|
5053
|
-
const headersOutputPath = options.headersOutput ?
|
|
5054
|
-
await fs5.mkdir(
|
|
4809
|
+
const outputPath = path3.resolve(options.output);
|
|
4810
|
+
const headersOutputPath = options.headersOutput ? path3.resolve(options.headersOutput) : void 0;
|
|
4811
|
+
await fs5.mkdir(path3.dirname(outputPath), { recursive: true });
|
|
5055
4812
|
await fs5.writeFile(outputPath, result.bytes);
|
|
5056
4813
|
const filesWritten = [outputPath];
|
|
5057
4814
|
if (headersOutputPath) {
|
|
@@ -5098,7 +4855,7 @@ var registerProjectsCommand = (program2, deps) => {
|
|
|
5098
4855
|
addCommon(addAuthOptions(projects.command("list").description("List projects"), deps.defaultBaseUrl)).action(async (options, command) => {
|
|
5099
4856
|
try {
|
|
5100
4857
|
const context = await resolveAuthContext(options, command, deps);
|
|
5101
|
-
const core = await import("./dist-
|
|
4858
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5102
4859
|
const data = await listProjectsForContext(core, context);
|
|
5103
4860
|
const url = buildFrontendUrl({ baseUrl: frontendBase(context, options), target: "projects" });
|
|
5104
4861
|
await writeProjectListOutput({ data, options, frontendUrl: url });
|
|
@@ -5116,7 +4873,7 @@ var registerProjectsCommand = (program2, deps) => {
|
|
|
5116
4873
|
).action(async (id, options, command) => {
|
|
5117
4874
|
try {
|
|
5118
4875
|
const context = await resolveAuthContext(options, command, deps);
|
|
5119
|
-
const core = await import("./dist-
|
|
4876
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5120
4877
|
const list = await listProjectsForContext(core, context);
|
|
5121
4878
|
const data = list.find((project) => project.id === id);
|
|
5122
4879
|
if (!data) {
|
|
@@ -5180,10 +4937,10 @@ var registerProjectsCommand = (program2, deps) => {
|
|
|
5180
4937
|
addCommon(addAuthOptions(projects.command("create").description("Create a quick template project"), deps.defaultBaseUrl)).option("--template-url <url>", "Template URL").option("--template-file <path>", "Local JSON template file").option("--parameters-file <path>", "Local JSON parameters file").option("--parameters-url <url>", "Parameters file URL").option("--name <name>", "Project name").option("--description <text>", "Project description").option("--provider <provider>", "Cloud provider: azure, aws, gcp").action(async (options, command) => {
|
|
5181
4938
|
try {
|
|
5182
4939
|
const context = requireAuthUser(await resolveAuthContext(options, command, deps));
|
|
5183
|
-
const core = await import("./dist-
|
|
4940
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5184
4941
|
const template = await fileBlob(options.templateFile);
|
|
5185
4942
|
const parameters = await fileBlob(options.parametersFile);
|
|
5186
|
-
const inferredName = options.name || (options.templateFile ?
|
|
4943
|
+
const inferredName = options.name || (options.templateFile ? path3.basename(options.templateFile, path3.extname(options.templateFile)) : void 0);
|
|
5187
4944
|
const result = await core.createQuickProject({
|
|
5188
4945
|
baseUrl: context.baseUrl,
|
|
5189
4946
|
authToken: context.token,
|
|
@@ -5303,7 +5060,7 @@ var registerConnectionsCommand = (program2, deps) => {
|
|
|
5303
5060
|
addCommon2(addAuthOptions(connections.command("list").description("List connections"), deps.defaultBaseUrl)).action(async (options, command) => {
|
|
5304
5061
|
try {
|
|
5305
5062
|
const context = requireAuthUser(await resolveAuthContext(options, command, deps));
|
|
5306
|
-
const core = await import("./dist-
|
|
5063
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5307
5064
|
const data = await core.listConnections({
|
|
5308
5065
|
baseUrl: context.baseUrl,
|
|
5309
5066
|
authToken: context.token,
|
|
@@ -5328,7 +5085,7 @@ var registerConnectionsCommand = (program2, deps) => {
|
|
|
5328
5085
|
).action(async (id, options, command) => {
|
|
5329
5086
|
try {
|
|
5330
5087
|
const context = requireAuthUser(await resolveAuthContext(options, command, deps));
|
|
5331
|
-
const core = await import("./dist-
|
|
5088
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5332
5089
|
const data = await core.getConnection({
|
|
5333
5090
|
baseUrl: context.baseUrl,
|
|
5334
5091
|
authToken: context.token,
|
|
@@ -5666,7 +5423,7 @@ var checkoutReturnUrl = (context, options) => options.returnTo || billingUrl(con
|
|
|
5666
5423
|
var runTopUpCheckout = async (commandName, packId, options, command, deps) => {
|
|
5667
5424
|
try {
|
|
5668
5425
|
const context = requireAuthUser(await resolveAuthContext(options, command, deps));
|
|
5669
|
-
const core = await import("./dist-
|
|
5426
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5670
5427
|
const returnTo = checkoutReturnUrl(context, options);
|
|
5671
5428
|
const session = await core.createTopUpCheckoutSession({
|
|
5672
5429
|
baseUrl: context.baseUrl,
|
|
@@ -5706,14 +5463,27 @@ var registerBillingCommands = (program2, deps) => {
|
|
|
5706
5463
|
).action(async (options, command) => {
|
|
5707
5464
|
try {
|
|
5708
5465
|
const context = requireAuthUser(await resolveAuthContext(options, command, deps));
|
|
5709
|
-
const core = await import("./dist-
|
|
5710
|
-
const
|
|
5711
|
-
|
|
5712
|
-
|
|
5466
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5467
|
+
const range = rangeToDates("30d");
|
|
5468
|
+
const [entitlement, usageSummary] = await Promise.all([
|
|
5469
|
+
core.getBillingEntitlement({
|
|
5470
|
+
baseUrl: context.baseUrl,
|
|
5471
|
+
authToken: context.token
|
|
5472
|
+
}),
|
|
5473
|
+
core.getBillingUsageSummary({
|
|
5474
|
+
baseUrl: context.baseUrl,
|
|
5475
|
+
authToken: context.token,
|
|
5476
|
+
startAt: range.startAt,
|
|
5477
|
+
endAt: range.endAt,
|
|
5478
|
+
granularity: "day"
|
|
5479
|
+
}).catch(() => null)
|
|
5480
|
+
]);
|
|
5481
|
+
const usageCreditsUsed = core.getBillingUsageCreditsUsed(usageSummary);
|
|
5482
|
+
const status = core.getCreditStatus(entitlement, {
|
|
5483
|
+
reportedUsedCredits: usageCreditsUsed
|
|
5713
5484
|
});
|
|
5714
|
-
const status = core.getCreditStatus(entitlement);
|
|
5715
5485
|
const url = billingUrl(context, { ...options, tab: "usage" });
|
|
5716
|
-
await write("credits", { status, entitlement }, options, url);
|
|
5486
|
+
await write("credits", { status, entitlement, usageCreditsUsed }, options, url);
|
|
5717
5487
|
await maybeOpen3(url, options);
|
|
5718
5488
|
} catch (error) {
|
|
5719
5489
|
failBillingCommand("credits", "Failed to show credits", error, options);
|
|
@@ -5723,15 +5493,31 @@ var registerBillingCommands = (program2, deps) => {
|
|
|
5723
5493
|
addCommon3(addAuthOptions(billing.command("summary").description("Show billing summary"), deps.defaultBaseUrl)).action(async (options, command) => {
|
|
5724
5494
|
try {
|
|
5725
5495
|
const context = requireAuthUser(await resolveAuthContext(options, command, deps));
|
|
5726
|
-
const core = await import("./dist-
|
|
5727
|
-
const
|
|
5496
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5497
|
+
const range = rangeToDates("30d");
|
|
5498
|
+
const [entitlement, subscriptionStatus, usageSummary] = await Promise.all([
|
|
5728
5499
|
core.getBillingEntitlement({ baseUrl: context.baseUrl, authToken: context.token }),
|
|
5729
|
-
core.getSubscriptionStatus({ baseUrl: context.baseUrl, authToken: context.token })
|
|
5500
|
+
core.getSubscriptionStatus({ baseUrl: context.baseUrl, authToken: context.token }),
|
|
5501
|
+
core.getBillingUsageSummary({
|
|
5502
|
+
baseUrl: context.baseUrl,
|
|
5503
|
+
authToken: context.token,
|
|
5504
|
+
startAt: range.startAt,
|
|
5505
|
+
endAt: range.endAt,
|
|
5506
|
+
granularity: "day"
|
|
5507
|
+
}).catch(() => null)
|
|
5730
5508
|
]);
|
|
5509
|
+
const usageCreditsUsed = core.getBillingUsageCreditsUsed(usageSummary);
|
|
5731
5510
|
const url = billingUrl(context, { ...options, tab: "plans" });
|
|
5732
5511
|
await write(
|
|
5733
5512
|
"billing summary",
|
|
5734
|
-
{
|
|
5513
|
+
{
|
|
5514
|
+
creditStatus: core.getCreditStatus(entitlement, {
|
|
5515
|
+
reportedUsedCredits: usageCreditsUsed
|
|
5516
|
+
}),
|
|
5517
|
+
entitlement,
|
|
5518
|
+
subscriptionStatus,
|
|
5519
|
+
usageCreditsUsed
|
|
5520
|
+
},
|
|
5735
5521
|
options,
|
|
5736
5522
|
url
|
|
5737
5523
|
);
|
|
@@ -5743,7 +5529,7 @@ var registerBillingCommands = (program2, deps) => {
|
|
|
5743
5529
|
addCommon3(addAuthOptions(billing.command("plans").description("Show billing plans"), deps.defaultBaseUrl)).action(async (options, command) => {
|
|
5744
5530
|
try {
|
|
5745
5531
|
const context = await resolveAuthContext(options, command, deps);
|
|
5746
|
-
const core = await import("./dist-
|
|
5532
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5747
5533
|
const data = await core.getBillingConfig({ baseUrl: context.baseUrl, authToken: context.token });
|
|
5748
5534
|
const url = billingUrl(context, { ...options, tab: "plans" });
|
|
5749
5535
|
await write("billing plans", data, options, url);
|
|
@@ -5755,7 +5541,7 @@ var registerBillingCommands = (program2, deps) => {
|
|
|
5755
5541
|
addCommon3(addAuthOptions(billing.command("usage").description("Show billing usage summary"), deps.defaultBaseUrl)).option("--range <range>", "Usage range: 7d, 30d, 90d, all", "30d").option("--start-at <iso>", "Start timestamp").option("--end-at <iso>", "End timestamp").option("--granularity <value>", "Granularity: hour, day, month", "day").option("--action-type <type>", "Action type filter").option("--model <name>", "Model filter").option("--outcome <outcome>", "Outcome filter").option("--charge-status <status>", "Charge status filter").action(async (options, command) => {
|
|
5756
5542
|
try {
|
|
5757
5543
|
const context = requireAuthUser(await resolveAuthContext(options, command, deps));
|
|
5758
|
-
const core = await import("./dist-
|
|
5544
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5759
5545
|
const range = rangeToDates(options.range);
|
|
5760
5546
|
const data = await core.getBillingUsageSummary({
|
|
5761
5547
|
baseUrl: context.baseUrl,
|
|
@@ -5778,7 +5564,7 @@ var registerBillingCommands = (program2, deps) => {
|
|
|
5778
5564
|
addCommon3(addAuthOptions(billing.command("ledger").description("Show billing ledger"), deps.defaultBaseUrl)).option("--range <range>", "Usage range: 7d, 30d, 90d, all", "30d").option("--start-at <iso>", "Start timestamp").option("--end-at <iso>", "End timestamp").option("--action-type <type>", "Action type filter").option("--model <name>", "Model filter").option("--outcome <outcome>", "Outcome filter").option("--charge-status <status>", "Charge status filter").option("--limit <n>", "Page size", "25").option("--cursor <cursor>", "Pagination cursor").action(async (options, command) => {
|
|
5779
5565
|
try {
|
|
5780
5566
|
const context = requireAuthUser(await resolveAuthContext(options, command, deps));
|
|
5781
|
-
const core = await import("./dist-
|
|
5567
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5782
5568
|
const range = rangeToDates(options.range);
|
|
5783
5569
|
const data = await core.getBillingUsageLedger({
|
|
5784
5570
|
baseUrl: context.baseUrl,
|
|
@@ -5806,7 +5592,7 @@ var registerBillingCommands = (program2, deps) => {
|
|
|
5806
5592
|
addCommon3(addAuthOptions(billing.command(name).description(`Show billing ${name}`), deps.defaultBaseUrl)).option("--limit <n>", "Result limit", "25").action(async (options, command) => {
|
|
5807
5593
|
try {
|
|
5808
5594
|
const context = requireAuthUser(await resolveAuthContext(options, command, deps));
|
|
5809
|
-
const core = await import("./dist-
|
|
5595
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5810
5596
|
const data = await core[getter]({
|
|
5811
5597
|
baseUrl: context.baseUrl,
|
|
5812
5598
|
authToken: context.token,
|
|
@@ -5824,7 +5610,7 @@ var registerBillingCommands = (program2, deps) => {
|
|
|
5824
5610
|
addCommon3(addAuthOptions(topups, deps.defaultBaseUrl)).option("--limit <n>", "Result limit", "25").action(async (options, command) => {
|
|
5825
5611
|
try {
|
|
5826
5612
|
const context = requireAuthUser(await resolveAuthContext(options, command, deps));
|
|
5827
|
-
const core = await import("./dist-
|
|
5613
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
5828
5614
|
const data = await core.getTopUpPacks({
|
|
5829
5615
|
baseUrl: context.baseUrl,
|
|
5830
5616
|
authToken: context.token
|
|
@@ -5860,13 +5646,13 @@ var registerBillingCommands = (program2, deps) => {
|
|
|
5860
5646
|
|
|
5861
5647
|
// src/mcpCommand.ts
|
|
5862
5648
|
import fs8 from "fs/promises";
|
|
5863
|
-
import
|
|
5649
|
+
import path5 from "path";
|
|
5864
5650
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
5865
5651
|
|
|
5866
5652
|
// src/mcpSetupCommand.ts
|
|
5867
5653
|
import fs6 from "fs/promises";
|
|
5868
|
-
import
|
|
5869
|
-
import
|
|
5654
|
+
import os from "os";
|
|
5655
|
+
import path4 from "path";
|
|
5870
5656
|
var MCP_SETUP_CLIENTS = ["codex", "claude", "cursor", "vscode", "generic"];
|
|
5871
5657
|
var CLIENTS = new Set(MCP_SETUP_CLIENTS);
|
|
5872
5658
|
var TOOLSETS = /* @__PURE__ */ new Set([
|
|
@@ -5892,8 +5678,8 @@ var normalizeMcpSetupToolset = (value) => {
|
|
|
5892
5678
|
};
|
|
5893
5679
|
var defaultConfigPath = (client) => {
|
|
5894
5680
|
if (client === "claude") {
|
|
5895
|
-
return
|
|
5896
|
-
|
|
5681
|
+
return path4.join(
|
|
5682
|
+
os.homedir(),
|
|
5897
5683
|
"Library",
|
|
5898
5684
|
"Application Support",
|
|
5899
5685
|
"Claude",
|
|
@@ -5901,10 +5687,10 @@ var defaultConfigPath = (client) => {
|
|
|
5901
5687
|
);
|
|
5902
5688
|
}
|
|
5903
5689
|
if (client === "cursor") {
|
|
5904
|
-
return
|
|
5690
|
+
return path4.join(os.homedir(), ".cursor", "mcp.json");
|
|
5905
5691
|
}
|
|
5906
5692
|
if (client === "vscode") {
|
|
5907
|
-
return
|
|
5693
|
+
return path4.join(process.cwd(), ".vscode", "mcp.json");
|
|
5908
5694
|
}
|
|
5909
5695
|
return void 0;
|
|
5910
5696
|
};
|
|
@@ -6039,7 +5825,7 @@ var writeMcpClientConfig = async (setup) => {
|
|
|
6039
5825
|
cloudeval: nextServer
|
|
6040
5826
|
}
|
|
6041
5827
|
};
|
|
6042
|
-
await fs6.mkdir(
|
|
5828
|
+
await fs6.mkdir(path4.dirname(setup.configPath), { recursive: true });
|
|
6043
5829
|
await fs6.writeFile(setup.configPath, `${JSON.stringify(next, null, 2)}
|
|
6044
5830
|
`, {
|
|
6045
5831
|
encoding: "utf8",
|
|
@@ -8005,6 +7791,13 @@ var mcpResourceDefinitions = [
|
|
|
8005
7791
|
title: "CloudEval Recipes",
|
|
8006
7792
|
description: "CloudEval reusable recipes and agent skill metadata.",
|
|
8007
7793
|
mimeType: "application/json"
|
|
7794
|
+
},
|
|
7795
|
+
{
|
|
7796
|
+
uri: "cloudeval://skills",
|
|
7797
|
+
name: "skills",
|
|
7798
|
+
title: "CloudEval Skills",
|
|
7799
|
+
description: "Public CloudEval SKILL.md catalog for agent reasoning.",
|
|
7800
|
+
mimeType: "application/json"
|
|
8008
7801
|
}
|
|
8009
7802
|
];
|
|
8010
7803
|
var mcpPromptDefinitions = recipes.map((recipe) => ({
|
|
@@ -8022,7 +7815,8 @@ var MCP_RESOURCE_TOOL_REQUIREMENTS = {
|
|
|
8022
7815
|
"cloudeval://projects": ["projects_list"],
|
|
8023
7816
|
"cloudeval://billing/summary": ["billing_summary"],
|
|
8024
7817
|
"cloudeval://reports/latest": ["reports_list"],
|
|
8025
|
-
"cloudeval://recipes": ["recipes_list"]
|
|
7818
|
+
"cloudeval://recipes": ["recipes_list"],
|
|
7819
|
+
"cloudeval://skills": ["capabilities_get"]
|
|
8026
7820
|
};
|
|
8027
7821
|
var promptRequirementTools = (tools) => tools.filter((tool) => tool !== "ask" && tool !== "recipes_run");
|
|
8028
7822
|
var MCP_PROMPT_TOOL_REQUIREMENTS = Object.fromEntries(
|
|
@@ -8180,7 +7974,7 @@ var isTerminalJobStatus3 = (value) => {
|
|
|
8180
7974
|
};
|
|
8181
7975
|
var sleep3 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
8182
7976
|
var writeHeaderFile = async (outputPath, headers) => {
|
|
8183
|
-
await fs8.mkdir(
|
|
7977
|
+
await fs8.mkdir(path5.dirname(outputPath), { recursive: true });
|
|
8184
7978
|
const text = Object.entries(headers).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `${key}: ${value}`).join("\n");
|
|
8185
7979
|
await fs8.writeFile(outputPath, `${text}
|
|
8186
7980
|
`, "utf8");
|
|
@@ -8214,7 +8008,7 @@ var reportsFrontendUrl = (config, input) => buildFrontendUrl({
|
|
|
8214
8008
|
reportVerbosity: input.reportVerbosity
|
|
8215
8009
|
});
|
|
8216
8010
|
var resolveAuth = async (config, options = {}) => {
|
|
8217
|
-
const core = await import("./dist-
|
|
8011
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
8218
8012
|
core.assertSecureBaseUrl(config.baseUrl);
|
|
8219
8013
|
let token;
|
|
8220
8014
|
try {
|
|
@@ -8314,7 +8108,7 @@ var assertModelAvailable = async (config, token) => {
|
|
|
8314
8108
|
if (!config.model) {
|
|
8315
8109
|
return;
|
|
8316
8110
|
}
|
|
8317
|
-
const core = await import("./dist-
|
|
8111
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
8318
8112
|
try {
|
|
8319
8113
|
const response = await fetch(
|
|
8320
8114
|
`${core.normalizeApiBase(config.baseUrl)}/models`,
|
|
@@ -8429,11 +8223,11 @@ var downloadReports = async (config, args, auth) => {
|
|
|
8429
8223
|
if (outputPath) {
|
|
8430
8224
|
if (reportTypes.length > 1) {
|
|
8431
8225
|
const stat = await fs8.stat(outputPath).catch(() => void 0);
|
|
8432
|
-
const outputIsDirectory = stat?.isDirectory() || !
|
|
8226
|
+
const outputIsDirectory = stat?.isDirectory() || !path5.extname(outputPath);
|
|
8433
8227
|
if (outputIsDirectory) {
|
|
8434
8228
|
await fs8.mkdir(outputPath, { recursive: true });
|
|
8435
8229
|
for (const [key, value] of Object.entries(payload)) {
|
|
8436
|
-
const file =
|
|
8230
|
+
const file = path5.join(outputPath, `${projectId}-${key}-report.json`);
|
|
8437
8231
|
await fs8.writeFile(
|
|
8438
8232
|
file,
|
|
8439
8233
|
`${JSON.stringify(value, null, 2)}
|
|
@@ -8443,7 +8237,7 @@ var downloadReports = async (config, args, auth) => {
|
|
|
8443
8237
|
filesWritten.push(file);
|
|
8444
8238
|
}
|
|
8445
8239
|
} else {
|
|
8446
|
-
await fs8.mkdir(
|
|
8240
|
+
await fs8.mkdir(path5.dirname(outputPath), { recursive: true });
|
|
8447
8241
|
await fs8.writeFile(
|
|
8448
8242
|
outputPath,
|
|
8449
8243
|
`${JSON.stringify(data, null, 2)}
|
|
@@ -8453,7 +8247,7 @@ var downloadReports = async (config, args, auth) => {
|
|
|
8453
8247
|
filesWritten.push(outputPath);
|
|
8454
8248
|
}
|
|
8455
8249
|
} else {
|
|
8456
|
-
await fs8.mkdir(
|
|
8250
|
+
await fs8.mkdir(path5.dirname(outputPath), { recursive: true });
|
|
8457
8251
|
await fs8.writeFile(
|
|
8458
8252
|
outputPath,
|
|
8459
8253
|
`${JSON.stringify(data, null, 2)}
|
|
@@ -8571,7 +8365,7 @@ var buildToolHandlers = (serverOptions) => {
|
|
|
8571
8365
|
});
|
|
8572
8366
|
handlers.set("agent_profiles_list", async (args) => {
|
|
8573
8367
|
const config = await resolveInvocationConfig(serverOptions, args);
|
|
8574
|
-
const core = await import("./dist-
|
|
8368
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
8575
8369
|
const data = await listProfilesForDiscovery(core, config.baseUrl);
|
|
8576
8370
|
return withEnvelope({
|
|
8577
8371
|
command: "agents list",
|
|
@@ -8584,7 +8378,7 @@ var buildToolHandlers = (serverOptions) => {
|
|
|
8584
8378
|
throw new Error("profileId is required.");
|
|
8585
8379
|
}
|
|
8586
8380
|
const config = await resolveInvocationConfig(serverOptions, args);
|
|
8587
|
-
const core = await import("./dist-
|
|
8381
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
8588
8382
|
const data = await getProfileForDiscovery(core, config.baseUrl, profileId);
|
|
8589
8383
|
return withEnvelope({
|
|
8590
8384
|
command: "agents show",
|
|
@@ -8764,7 +8558,7 @@ var buildToolHandlers = (serverOptions) => {
|
|
|
8764
8558
|
if (!rawOutputPath) {
|
|
8765
8559
|
throw new Error("outputPath is required.");
|
|
8766
8560
|
}
|
|
8767
|
-
const outputPath =
|
|
8561
|
+
const outputPath = path5.resolve(rawOutputPath);
|
|
8768
8562
|
const publicGraph = booleanValue(args.public) ?? false;
|
|
8769
8563
|
const auth = publicGraph ? void 0 : await resolveAuth(config, { requireUser: true });
|
|
8770
8564
|
const layout = normalizeProjectDiagramImageLayout(stringValue(args.layout));
|
|
@@ -8785,11 +8579,11 @@ var buildToolHandlers = (serverOptions) => {
|
|
|
8785
8579
|
publicGraph,
|
|
8786
8580
|
syncVersion: stringValue(args.syncVersion)
|
|
8787
8581
|
});
|
|
8788
|
-
await fs8.mkdir(
|
|
8582
|
+
await fs8.mkdir(path5.dirname(outputPath), { recursive: true });
|
|
8789
8583
|
await fs8.writeFile(outputPath, result.bytes);
|
|
8790
8584
|
const filesWritten = [outputPath];
|
|
8791
8585
|
const rawHeadersOutputPath = stringValue(args.headersOutputPath);
|
|
8792
|
-
const headersOutputPath = rawHeadersOutputPath ?
|
|
8586
|
+
const headersOutputPath = rawHeadersOutputPath ? path5.resolve(rawHeadersOutputPath) : void 0;
|
|
8793
8587
|
if (headersOutputPath) {
|
|
8794
8588
|
await writeHeaderFile(headersOutputPath, result.headers);
|
|
8795
8589
|
filesWritten.push(headersOutputPath);
|
|
@@ -9221,7 +9015,7 @@ var buildToolHandlers = (serverOptions) => {
|
|
|
9221
9015
|
});
|
|
9222
9016
|
handlers.set("auth_status", async (args) => {
|
|
9223
9017
|
const config = await resolveInvocationConfig(serverOptions, args);
|
|
9224
|
-
const core = await import("./dist-
|
|
9018
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
9225
9019
|
const data = await core.getAuthStatus(config.baseUrl, { validate: true });
|
|
9226
9020
|
return withEnvelope({
|
|
9227
9021
|
command: "auth status",
|
|
@@ -9230,7 +9024,7 @@ var buildToolHandlers = (serverOptions) => {
|
|
|
9230
9024
|
});
|
|
9231
9025
|
handlers.set("status", async (args) => {
|
|
9232
9026
|
const config = await resolveInvocationConfig(serverOptions, args);
|
|
9233
|
-
const core = await import("./dist-
|
|
9027
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
9234
9028
|
const auth = await core.getAuthStatus(config.baseUrl, { validate: true });
|
|
9235
9029
|
return withEnvelope({
|
|
9236
9030
|
command: "status",
|
|
@@ -9261,7 +9055,7 @@ var buildToolHandlers = (serverOptions) => {
|
|
|
9261
9055
|
}
|
|
9262
9056
|
];
|
|
9263
9057
|
try {
|
|
9264
|
-
const core = await import("./dist-
|
|
9058
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
9265
9059
|
core.assertSecureBaseUrl(config.baseUrl);
|
|
9266
9060
|
checks.push({
|
|
9267
9061
|
id: "base-url-secure",
|
|
@@ -9675,7 +9469,8 @@ var buildToolHandlers = (serverOptions) => {
|
|
|
9675
9469
|
handlers.set("billing_summary", async (args) => {
|
|
9676
9470
|
const config = await resolveInvocationConfig(serverOptions, args);
|
|
9677
9471
|
const auth = await resolveAuth(config, { requireUser: true });
|
|
9678
|
-
const
|
|
9472
|
+
const range = rangeToDates2("30d");
|
|
9473
|
+
const [entitlement, subscriptionStatus, usageSummary] = await Promise.all([
|
|
9679
9474
|
auth.core.getBillingEntitlement({
|
|
9680
9475
|
baseUrl: config.baseUrl,
|
|
9681
9476
|
authToken: auth.token
|
|
@@ -9683,19 +9478,30 @@ var buildToolHandlers = (serverOptions) => {
|
|
|
9683
9478
|
auth.core.getSubscriptionStatus({
|
|
9684
9479
|
baseUrl: config.baseUrl,
|
|
9685
9480
|
authToken: auth.token
|
|
9686
|
-
})
|
|
9481
|
+
}),
|
|
9482
|
+
auth.core.getBillingUsageSummary({
|
|
9483
|
+
baseUrl: config.baseUrl,
|
|
9484
|
+
authToken: auth.token,
|
|
9485
|
+
startAt: range.startAt,
|
|
9486
|
+
endAt: range.endAt,
|
|
9487
|
+
granularity: "day"
|
|
9488
|
+
}).catch(() => null)
|
|
9687
9489
|
]);
|
|
9688
9490
|
const frontendUrl = buildFrontendUrl({
|
|
9689
9491
|
baseUrl: frontendBase3(config),
|
|
9690
9492
|
target: "billing",
|
|
9691
9493
|
tab: "plans"
|
|
9692
9494
|
});
|
|
9495
|
+
const usageCreditsUsed = auth.core.getBillingUsageCreditsUsed(usageSummary);
|
|
9693
9496
|
return withEnvelope({
|
|
9694
9497
|
command: "billing summary",
|
|
9695
9498
|
data: {
|
|
9696
|
-
creditStatus: auth.core.getCreditStatus(entitlement
|
|
9499
|
+
creditStatus: auth.core.getCreditStatus(entitlement, {
|
|
9500
|
+
reportedUsedCredits: usageCreditsUsed
|
|
9501
|
+
}),
|
|
9697
9502
|
entitlement,
|
|
9698
|
-
subscriptionStatus
|
|
9503
|
+
subscriptionStatus,
|
|
9504
|
+
usageCreditsUsed
|
|
9699
9505
|
},
|
|
9700
9506
|
frontendUrl
|
|
9701
9507
|
});
|
|
@@ -9769,7 +9575,7 @@ var buildToolHandlers = (serverOptions) => {
|
|
|
9769
9575
|
} catch {
|
|
9770
9576
|
token = config.accessKey;
|
|
9771
9577
|
}
|
|
9772
|
-
const core = await import("./dist-
|
|
9578
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
9773
9579
|
const data = await core.getBillingConfig({
|
|
9774
9580
|
baseUrl: config.baseUrl,
|
|
9775
9581
|
authToken: token
|
|
@@ -9943,6 +9749,19 @@ var readMcpResource = async (uri, handlers, availableToolNames, toolset) => {
|
|
|
9943
9749
|
const envelope = await handlers.get("capabilities_get")?.({});
|
|
9944
9750
|
return { contents: [resourceText(uri, envelope?.data ?? {})] };
|
|
9945
9751
|
}
|
|
9752
|
+
if (uri === "cloudeval://skills") {
|
|
9753
|
+
return {
|
|
9754
|
+
contents: [
|
|
9755
|
+
resourceText(
|
|
9756
|
+
uri,
|
|
9757
|
+
formatSuccessEnvelope({
|
|
9758
|
+
command: "skills list",
|
|
9759
|
+
data: await skillsResourceData()
|
|
9760
|
+
})
|
|
9761
|
+
)
|
|
9762
|
+
]
|
|
9763
|
+
};
|
|
9764
|
+
}
|
|
9946
9765
|
const toolName = uri === "cloudeval://projects" ? "projects_list" : uri === "cloudeval://billing/summary" ? "billing_summary" : uri === "cloudeval://recipes" ? "recipes_list" : "reports_list";
|
|
9947
9766
|
const handler = handlers.get(toolName);
|
|
9948
9767
|
if (!handler) {
|
|
@@ -10590,7 +10409,7 @@ var registerCapabilitiesCommand = (program2, deps) => {
|
|
|
10590
10409
|
warnIfAccessKeyFromCliOption(options, command);
|
|
10591
10410
|
let data = capabilities;
|
|
10592
10411
|
if (options.live) {
|
|
10593
|
-
const core = await import("./dist-
|
|
10412
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
10594
10413
|
const baseUrl = await deps.resolveBaseUrl(options, command);
|
|
10595
10414
|
const accessKey = options.accessKeyStdin ? await deps.readStdinValue() : options.accessKey;
|
|
10596
10415
|
const token = await core.getAuthToken({ accessKey, baseUrl });
|
|
@@ -10622,6 +10441,8 @@ Mode-specific commands:
|
|
|
10622
10441
|
cloudeval recipes list Discover reusable CloudEval workflows
|
|
10623
10442
|
cloudeval recipes show <id> Show skill-style commands, safety, and outputs
|
|
10624
10443
|
cloudeval recipes run <id> Run ask/agent recipes or print explicit commands for side-effecting recipes
|
|
10444
|
+
cloudeval skills list Discover portable CloudEval SKILL.md instructions
|
|
10445
|
+
cloudeval skills doctor Validate skill files and recipe references
|
|
10625
10446
|
|
|
10626
10447
|
Progress:
|
|
10627
10448
|
ask/agent show a live stderr loader and reasoning progress bar in interactive terminals, then write the final answer to stdout. In non-TTY logs this falls back to append-only stderr events. Use --progress none or --quiet to suppress progress, or --format ndjson --progress ndjson to stream progress on stdout.
|
|
@@ -10647,6 +10468,7 @@ Stable JSON envelope:
|
|
|
10647
10468
|
Discovery:
|
|
10648
10469
|
cloudeval capabilities --format json
|
|
10649
10470
|
cloudeval recipes list
|
|
10471
|
+
cloudeval skills list
|
|
10650
10472
|
cloudeval mcp serve
|
|
10651
10473
|
cloudeval doctor --format json
|
|
10652
10474
|
cloudeval config show --format json
|
|
@@ -10725,7 +10547,7 @@ var writeCredentialOutput = async (input) => {
|
|
|
10725
10547
|
};
|
|
10726
10548
|
var resolveCoreAuth = async (options, command, deps) => {
|
|
10727
10549
|
const context = await resolveAuthContext(options, command, deps);
|
|
10728
|
-
const core = await import("./dist-
|
|
10550
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
10729
10551
|
return { ...context, core };
|
|
10730
10552
|
};
|
|
10731
10553
|
var parseCapabilities = (value) => value?.split(",").map((item) => item.trim()).filter(Boolean);
|
|
@@ -10833,8 +10655,8 @@ import { randomUUID as randomUUID4 } from "crypto";
|
|
|
10833
10655
|
import { exec } from "child_process";
|
|
10834
10656
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
10835
10657
|
import fs9 from "fs/promises";
|
|
10836
|
-
import
|
|
10837
|
-
import
|
|
10658
|
+
import os2 from "os";
|
|
10659
|
+
import path6 from "path";
|
|
10838
10660
|
var normalizeHooks = (config, event) => {
|
|
10839
10661
|
if (config.hooks?.enabled !== true) {
|
|
10840
10662
|
return [];
|
|
@@ -10845,8 +10667,8 @@ var normalizeHooks = (config, event) => {
|
|
|
10845
10667
|
) : [];
|
|
10846
10668
|
};
|
|
10847
10669
|
var writeHookPayload = async (input, hook) => {
|
|
10848
|
-
const filePath =
|
|
10849
|
-
|
|
10670
|
+
const filePath = path6.join(
|
|
10671
|
+
os2.tmpdir(),
|
|
10850
10672
|
`cloudeval-hook-${process.pid}-${randomUUID3()}.json`
|
|
10851
10673
|
);
|
|
10852
10674
|
await fs9.writeFile(
|
|
@@ -11042,7 +10864,7 @@ var registerAgentsCommand = (program2, deps) => {
|
|
|
11042
10864
|
const agents = program2.command("agents").description("CloudEval Agent Profile utilities");
|
|
11043
10865
|
addAgentOutputOptions(agents.command("list").description("List Agent Profiles"), deps).action(async (options, command) => {
|
|
11044
10866
|
const baseUrl = await deps.resolveBaseUrl(options, command);
|
|
11045
|
-
const core = await import("./dist-
|
|
10867
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
11046
10868
|
core.assertSecureBaseUrl(baseUrl);
|
|
11047
10869
|
const data = await listProfilesForDiscovery2(core, baseUrl);
|
|
11048
10870
|
await writeProfiles({
|
|
@@ -11058,7 +10880,7 @@ var registerAgentsCommand = (program2, deps) => {
|
|
|
11058
10880
|
deps
|
|
11059
10881
|
).action(async (profileId, options, command) => {
|
|
11060
10882
|
const baseUrl = await deps.resolveBaseUrl(options, command);
|
|
11061
|
-
const core = await import("./dist-
|
|
10883
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
11062
10884
|
core.assertSecureBaseUrl(baseUrl);
|
|
11063
10885
|
const data = await getProfileForDiscovery2(core, baseUrl, profileId);
|
|
11064
10886
|
await writeProfiles({
|
|
@@ -11077,7 +10899,7 @@ var registerAgentsCommand = (program2, deps) => {
|
|
|
11077
10899
|
const cliProfile = getActiveConfigProfile(command);
|
|
11078
10900
|
const cliConfig = await loadCliConfig(cliProfile);
|
|
11079
10901
|
const auth = await resolveAuthContext(options, command, deps);
|
|
11080
|
-
const core = await import("./dist-
|
|
10902
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
11081
10903
|
const profileResponse = await core.getAgentProfile({
|
|
11082
10904
|
baseUrl: auth.baseUrl,
|
|
11083
10905
|
authToken: auth.token,
|
|
@@ -11469,10 +11291,10 @@ var registerConfigCommand = (program2) => {
|
|
|
11469
11291
|
const profile = resolveProfile(options, command);
|
|
11470
11292
|
const current = await loadCliConfig(profile);
|
|
11471
11293
|
const next = writeCliConfigValue(current, key, value);
|
|
11472
|
-
const
|
|
11294
|
+
const path10 = await saveCliConfig(next, profile);
|
|
11473
11295
|
await writeFormattedOutput({
|
|
11474
11296
|
command: "config set",
|
|
11475
|
-
data: { profile, path:
|
|
11297
|
+
data: { profile, path: path10, config: next },
|
|
11476
11298
|
format: options.format,
|
|
11477
11299
|
output: options.output
|
|
11478
11300
|
});
|
|
@@ -11483,10 +11305,10 @@ var registerConfigCommand = (program2) => {
|
|
|
11483
11305
|
const profile = resolveProfile(options, command);
|
|
11484
11306
|
const current = await loadCliConfig(profile);
|
|
11485
11307
|
const next = unsetCliConfigValue(current, key);
|
|
11486
|
-
const
|
|
11308
|
+
const path10 = await saveCliConfig(next, profile);
|
|
11487
11309
|
await writeFormattedOutput({
|
|
11488
11310
|
command: "config unset",
|
|
11489
|
-
data: { profile, path:
|
|
11311
|
+
data: { profile, path: path10, config: next },
|
|
11490
11312
|
format: options.format,
|
|
11491
11313
|
output: options.output
|
|
11492
11314
|
});
|
|
@@ -11575,7 +11397,7 @@ var registerDiagnosticsCommands = (program2, deps) => {
|
|
|
11575
11397
|
const baseUrl = await deps.resolveBaseUrl(options, command);
|
|
11576
11398
|
const profile = getActiveConfigProfile(command);
|
|
11577
11399
|
const config = await loadCliConfig(profile);
|
|
11578
|
-
const core = await import("./dist-
|
|
11400
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
11579
11401
|
const auth = await core.getAuthStatus(baseUrl, { validate: true });
|
|
11580
11402
|
if (options.format === "text" || !options.format) {
|
|
11581
11403
|
process.stdout.write(
|
|
@@ -11625,7 +11447,7 @@ var registerDiagnosticsCommands = (program2, deps) => {
|
|
|
11625
11447
|
detail: getCliConfigPath(profile)
|
|
11626
11448
|
});
|
|
11627
11449
|
try {
|
|
11628
|
-
const core = await import("./dist-
|
|
11450
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
11629
11451
|
core.assertSecureBaseUrl(baseUrl);
|
|
11630
11452
|
checks.push({
|
|
11631
11453
|
id: "base-url-secure",
|
|
@@ -11725,7 +11547,7 @@ var resolveToken2 = async (options, deps, baseUrl, command) => {
|
|
|
11725
11547
|
return options.accessKey;
|
|
11726
11548
|
}
|
|
11727
11549
|
try {
|
|
11728
|
-
const core = await import("./dist-
|
|
11550
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
11729
11551
|
return await core.getAuthToken({
|
|
11730
11552
|
baseUrl
|
|
11731
11553
|
});
|
|
@@ -11809,7 +11631,7 @@ var registerModelsCommand = (program2, deps) => {
|
|
|
11809
11631
|
let source = "fallback";
|
|
11810
11632
|
let modelList = fallbackModels;
|
|
11811
11633
|
try {
|
|
11812
|
-
const core = await import("./dist-
|
|
11634
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
11813
11635
|
const response = await fetch(`${core.normalizeApiBase(baseUrl)}/models`, {
|
|
11814
11636
|
headers: {
|
|
11815
11637
|
Accept: "application/json",
|
|
@@ -11850,10 +11672,10 @@ var registerModelsCommand = (program2, deps) => {
|
|
|
11850
11672
|
const profile = options.profile || getActiveConfigProfile(command);
|
|
11851
11673
|
const config = await loadCliConfig(profile);
|
|
11852
11674
|
const next = { ...config, model };
|
|
11853
|
-
const
|
|
11675
|
+
const path10 = await saveCliConfig(next, profile);
|
|
11854
11676
|
await writeFormattedOutput({
|
|
11855
11677
|
command: "models default set",
|
|
11856
|
-
data: { profile, path:
|
|
11678
|
+
data: { profile, path: path10, model },
|
|
11857
11679
|
format: options.format,
|
|
11858
11680
|
output: options.output
|
|
11859
11681
|
});
|
|
@@ -12069,12 +11891,12 @@ var registerSetupCommand = (program2, defaultBaseUrl = CLOUD_BASE_URL) => {
|
|
|
12069
11891
|
rl.close();
|
|
12070
11892
|
}
|
|
12071
11893
|
}
|
|
12072
|
-
const
|
|
11894
|
+
const path10 = await saveCliConfig(next, profile);
|
|
12073
11895
|
await writeFormattedOutput({
|
|
12074
11896
|
command: "setup",
|
|
12075
11897
|
data: {
|
|
12076
11898
|
profile,
|
|
12077
|
-
path:
|
|
11899
|
+
path: path10,
|
|
12078
11900
|
config: next,
|
|
12079
11901
|
nextSteps: [
|
|
12080
11902
|
"Run `cloudeval auth status` to inspect authentication.",
|
|
@@ -12091,10 +11913,11 @@ var registerSetupCommand = (program2, defaultBaseUrl = CLOUD_BASE_URL) => {
|
|
|
12091
11913
|
// src/updateCommand.ts
|
|
12092
11914
|
import { spawn } from "child_process";
|
|
12093
11915
|
import fs10 from "fs/promises";
|
|
12094
|
-
import
|
|
11916
|
+
import path7 from "path";
|
|
12095
11917
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
12096
11918
|
var DEFAULT_LATEST_RELEASE_URL = "https://api.github.com/repos/ganakailabs/cloudeval-cli/releases/latest";
|
|
12097
11919
|
var DEFAULT_INSTALLER_URL = "https://cli.cloudeval.ai/install.sh";
|
|
11920
|
+
var DEFAULT_POWERSHELL_INSTALLER_URL = "https://cli.cloudeval.ai/install.ps1";
|
|
12098
11921
|
var DEFAULT_UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
12099
11922
|
var UPDATE_CACHE_FILE = "update-check.json";
|
|
12100
11923
|
var normalizeVersion = (value) => value.trim().replace(/^v/i, "").split("+")[0] || "0.0.0";
|
|
@@ -12204,7 +12027,7 @@ var getUpdateStatus = async ({
|
|
|
12204
12027
|
);
|
|
12205
12028
|
};
|
|
12206
12029
|
var runInstaller = async ({
|
|
12207
|
-
installerUrl
|
|
12030
|
+
installerUrl,
|
|
12208
12031
|
targetTag,
|
|
12209
12032
|
fetchImpl = fetch,
|
|
12210
12033
|
spawnImpl = spawn,
|
|
@@ -12213,14 +12036,11 @@ var runInstaller = async ({
|
|
|
12213
12036
|
env = process.env,
|
|
12214
12037
|
promptAgentSetup = false
|
|
12215
12038
|
}) => {
|
|
12216
|
-
|
|
12217
|
-
|
|
12218
|
-
|
|
12219
|
-
);
|
|
12220
|
-
}
|
|
12221
|
-
const response = await fetchImpl(installerUrl, {
|
|
12039
|
+
const resolvedInstallerUrl = installerUrl ?? process.env.CLOUDEVAL_UPDATE_INSTALLER_URL ?? (platform === "win32" ? DEFAULT_POWERSHELL_INSTALLER_URL : DEFAULT_INSTALLER_URL);
|
|
12040
|
+
const usePowerShellInstaller = platform === "win32" || resolvedInstallerUrl.endsWith(".ps1");
|
|
12041
|
+
const response = await fetchImpl(resolvedInstallerUrl, {
|
|
12222
12042
|
headers: {
|
|
12223
|
-
Accept: "text/x-shellscript,text/plain,*/*",
|
|
12043
|
+
Accept: usePowerShellInstaller ? "text/plain,*/*" : "text/x-shellscript,text/plain,*/*",
|
|
12224
12044
|
"User-Agent": `cloudeval-cli/${CLI_VERSION}`
|
|
12225
12045
|
}
|
|
12226
12046
|
});
|
|
@@ -12230,6 +12050,55 @@ var runInstaller = async ({
|
|
|
12230
12050
|
);
|
|
12231
12051
|
}
|
|
12232
12052
|
const installerScript = await response.text();
|
|
12053
|
+
if (usePowerShellInstaller) {
|
|
12054
|
+
const configDir = getCloudevalConfigDir();
|
|
12055
|
+
await fs10.mkdir(configDir, { recursive: true, mode: 448 });
|
|
12056
|
+
const scriptPath = path7.join(
|
|
12057
|
+
await fs10.mkdtemp(path7.join(configDir, "installer-")),
|
|
12058
|
+
"install.ps1"
|
|
12059
|
+
);
|
|
12060
|
+
await fs10.writeFile(scriptPath, installerScript, "utf8");
|
|
12061
|
+
const child2 = spawnImpl(
|
|
12062
|
+
"pwsh",
|
|
12063
|
+
[
|
|
12064
|
+
"-NoProfile",
|
|
12065
|
+
"-ExecutionPolicy",
|
|
12066
|
+
"Bypass",
|
|
12067
|
+
"-File",
|
|
12068
|
+
scriptPath,
|
|
12069
|
+
targetTag
|
|
12070
|
+
],
|
|
12071
|
+
{
|
|
12072
|
+
env: {
|
|
12073
|
+
...env,
|
|
12074
|
+
CLOUDEVAL_ASSUME_YES: "1"
|
|
12075
|
+
},
|
|
12076
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
12077
|
+
}
|
|
12078
|
+
);
|
|
12079
|
+
await new Promise((resolve, reject) => {
|
|
12080
|
+
child2.once("error", (error) => {
|
|
12081
|
+
reject(
|
|
12082
|
+
error instanceof Error && error.message.includes("ENOENT") ? new Error(
|
|
12083
|
+
"Automatic update requires PowerShell 7 (pwsh). Install the latest CLI from https://cli.cloudeval.ai/install.ps1."
|
|
12084
|
+
) : error
|
|
12085
|
+
);
|
|
12086
|
+
});
|
|
12087
|
+
child2.once("close", (code) => {
|
|
12088
|
+
void fs10.rm(path7.dirname(scriptPath), { recursive: true, force: true });
|
|
12089
|
+
if (code === 0) {
|
|
12090
|
+
resolve();
|
|
12091
|
+
return;
|
|
12092
|
+
}
|
|
12093
|
+
reject(
|
|
12094
|
+
new Error(`CloudEval CLI installer exited with code ${code ?? "unknown"}.`)
|
|
12095
|
+
);
|
|
12096
|
+
});
|
|
12097
|
+
child2.stdout?.on("data", (chunk) => output.write(chunk));
|
|
12098
|
+
child2.stderr?.on("data", (chunk) => output.write(chunk));
|
|
12099
|
+
});
|
|
12100
|
+
return;
|
|
12101
|
+
}
|
|
12233
12102
|
const child = spawnImpl("bash", ["-s", "--", targetTag], {
|
|
12234
12103
|
env: {
|
|
12235
12104
|
...env,
|
|
@@ -12256,7 +12125,7 @@ var runInstaller = async ({
|
|
|
12256
12125
|
child.stdin.end(installerScript);
|
|
12257
12126
|
});
|
|
12258
12127
|
};
|
|
12259
|
-
var getUpdateCachePath = () =>
|
|
12128
|
+
var getUpdateCachePath = () => path7.join(getCloudevalConfigDir(), UPDATE_CACHE_FILE);
|
|
12260
12129
|
var readCache = async (cachePath) => {
|
|
12261
12130
|
try {
|
|
12262
12131
|
const parsed = JSON.parse(await fs10.readFile(cachePath, "utf8"));
|
|
@@ -12271,7 +12140,7 @@ var readCache = async (cachePath) => {
|
|
|
12271
12140
|
return void 0;
|
|
12272
12141
|
};
|
|
12273
12142
|
var writeCache = async (cachePath, status) => {
|
|
12274
|
-
await fs10.mkdir(
|
|
12143
|
+
await fs10.mkdir(path7.dirname(cachePath), { recursive: true, mode: 448 });
|
|
12275
12144
|
await fs10.writeFile(
|
|
12276
12145
|
cachePath,
|
|
12277
12146
|
`${JSON.stringify(
|
|
@@ -12495,8 +12364,8 @@ var registerUpdateCommand = (program2) => {
|
|
|
12495
12364
|
|
|
12496
12365
|
// src/uninstallCommand.ts
|
|
12497
12366
|
import fs11 from "fs/promises";
|
|
12498
|
-
import
|
|
12499
|
-
import
|
|
12367
|
+
import os3 from "os";
|
|
12368
|
+
import path8 from "path";
|
|
12500
12369
|
import { createInterface as createInterface3 } from "readline/promises";
|
|
12501
12370
|
var pathExists = async (candidate) => {
|
|
12502
12371
|
try {
|
|
@@ -12509,12 +12378,12 @@ var pathExists = async (candidate) => {
|
|
|
12509
12378
|
throw error;
|
|
12510
12379
|
}
|
|
12511
12380
|
};
|
|
12512
|
-
var installerBinDir = (home) =>
|
|
12381
|
+
var installerBinDir = (home) => path8.join(home, ".local", "bin");
|
|
12513
12382
|
var completionPaths = (home) => [
|
|
12514
|
-
|
|
12515
|
-
|
|
12516
|
-
|
|
12517
|
-
|
|
12383
|
+
path8.join(home, ".local", "share", "bash-completion", "completions", "cloudeval"),
|
|
12384
|
+
path8.join(home, ".zsh", "completions", "_cloudeval"),
|
|
12385
|
+
path8.join(home, ".config", "fish", "completions", "cloudeval.fish"),
|
|
12386
|
+
path8.join(home, ".config", "powershell", "cloudeval-completion.ps1")
|
|
12518
12387
|
];
|
|
12519
12388
|
var installerArtifactTargets = (home, platform) => {
|
|
12520
12389
|
const binDir = installerBinDir(home);
|
|
@@ -12522,37 +12391,37 @@ var installerArtifactTargets = (home, platform) => {
|
|
|
12522
12391
|
const targets = [
|
|
12523
12392
|
{
|
|
12524
12393
|
label: "cloudeval binary",
|
|
12525
|
-
path:
|
|
12394
|
+
path: path8.join(binDir, executableName),
|
|
12526
12395
|
kind: "file",
|
|
12527
12396
|
status: "missing"
|
|
12528
12397
|
},
|
|
12529
12398
|
{
|
|
12530
12399
|
label: "cloudeval binary",
|
|
12531
|
-
path:
|
|
12400
|
+
path: path8.join(binDir, "cloudeval"),
|
|
12532
12401
|
kind: "file",
|
|
12533
12402
|
status: "missing"
|
|
12534
12403
|
},
|
|
12535
12404
|
{
|
|
12536
12405
|
label: "eva alias",
|
|
12537
|
-
path:
|
|
12406
|
+
path: path8.join(binDir, "eva"),
|
|
12538
12407
|
kind: "file",
|
|
12539
12408
|
status: "missing"
|
|
12540
12409
|
},
|
|
12541
12410
|
{
|
|
12542
12411
|
label: "cloud alias",
|
|
12543
|
-
path:
|
|
12412
|
+
path: path8.join(binDir, "cloud"),
|
|
12544
12413
|
kind: "file",
|
|
12545
12414
|
status: "missing"
|
|
12546
12415
|
},
|
|
12547
12416
|
{
|
|
12548
12417
|
label: "Ink runtime asset",
|
|
12549
|
-
path:
|
|
12418
|
+
path: path8.join(binDir, "yoga.wasm"),
|
|
12550
12419
|
kind: "file",
|
|
12551
12420
|
status: "missing"
|
|
12552
12421
|
},
|
|
12553
12422
|
{
|
|
12554
12423
|
label: "license notices",
|
|
12555
|
-
path:
|
|
12424
|
+
path: path8.join(home, ".local", "share", "cloudeval", "licenses"),
|
|
12556
12425
|
kind: "directory",
|
|
12557
12426
|
status: "missing"
|
|
12558
12427
|
},
|
|
@@ -12568,11 +12437,11 @@ var installerArtifactTargets = (home, platform) => {
|
|
|
12568
12437
|
);
|
|
12569
12438
|
};
|
|
12570
12439
|
var shellProfilePaths = (home) => [
|
|
12571
|
-
|
|
12572
|
-
|
|
12573
|
-
|
|
12574
|
-
|
|
12575
|
-
|
|
12440
|
+
path8.join(home, ".bashrc"),
|
|
12441
|
+
path8.join(home, ".bash_profile"),
|
|
12442
|
+
path8.join(home, ".zshrc"),
|
|
12443
|
+
path8.join(home, ".profile"),
|
|
12444
|
+
path8.join(home, ".config", "fish", "config.fish")
|
|
12576
12445
|
];
|
|
12577
12446
|
var removeInstallerPathSnippet = (content, binDir) => {
|
|
12578
12447
|
const exportLine = `export PATH="${binDir}:$PATH"`;
|
|
@@ -12652,7 +12521,7 @@ var confirmUninstall = async ({
|
|
|
12652
12521
|
}
|
|
12653
12522
|
};
|
|
12654
12523
|
var handleUninstallCommand = async (options, deps = {}) => {
|
|
12655
|
-
const home = deps.home ??
|
|
12524
|
+
const home = deps.home ?? os3.homedir();
|
|
12656
12525
|
const platform = deps.platform ?? process.platform;
|
|
12657
12526
|
const dryRun = Boolean(options.dryRun);
|
|
12658
12527
|
const removeConfig = Boolean(options.removeConfig);
|
|
@@ -12682,7 +12551,7 @@ var handleUninstallCommand = async (options, deps = {}) => {
|
|
|
12682
12551
|
}
|
|
12683
12552
|
const configTarget = {
|
|
12684
12553
|
label: "config",
|
|
12685
|
-
path:
|
|
12554
|
+
path: path8.join(home, ".config", "cloudeval"),
|
|
12686
12555
|
kind: "directory",
|
|
12687
12556
|
status: "kept"
|
|
12688
12557
|
};
|
|
@@ -12887,21 +12756,21 @@ var assertNoLegacyApiKeyUsage = () => {
|
|
|
12887
12756
|
};
|
|
12888
12757
|
assertNoLegacyApiKeyUsage();
|
|
12889
12758
|
var completionScriptPath = (shell) => {
|
|
12890
|
-
const home =
|
|
12759
|
+
const home = os4.homedir();
|
|
12891
12760
|
switch (shell) {
|
|
12892
12761
|
case "bash":
|
|
12893
|
-
return
|
|
12762
|
+
return path9.join(home, ".local", "share", "bash-completion", "completions", "cloudeval");
|
|
12894
12763
|
case "zsh":
|
|
12895
|
-
return
|
|
12764
|
+
return path9.join(home, ".zsh", "completions", "_cloudeval");
|
|
12896
12765
|
case "fish":
|
|
12897
|
-
return
|
|
12766
|
+
return path9.join(home, ".config", "fish", "completions", "cloudeval.fish");
|
|
12898
12767
|
case "powershell":
|
|
12899
|
-
return
|
|
12768
|
+
return path9.join(home, ".config", "powershell", "cloudeval-completion.ps1");
|
|
12900
12769
|
}
|
|
12901
12770
|
};
|
|
12902
12771
|
var ZSH_FPATH_MARKER = "CloudEval CLI completions";
|
|
12903
12772
|
var ensureZshCompletionFpath = async () => {
|
|
12904
|
-
const zshrc =
|
|
12773
|
+
const zshrc = path9.join(os4.homedir(), ".zshrc");
|
|
12905
12774
|
let existing = "";
|
|
12906
12775
|
try {
|
|
12907
12776
|
existing = await fs12.readFile(zshrc, "utf8");
|
|
@@ -12919,7 +12788,7 @@ fpath=("$HOME/.zsh/completions" $fpath)
|
|
|
12919
12788
|
};
|
|
12920
12789
|
var installCompletionScript = async (shell, binaryName) => {
|
|
12921
12790
|
const scriptPath = completionScriptPath(shell);
|
|
12922
|
-
await fs12.mkdir(
|
|
12791
|
+
await fs12.mkdir(path9.dirname(scriptPath), { recursive: true });
|
|
12923
12792
|
await fs12.writeFile(scriptPath, buildCompletionScript(shell, binaryName), "utf8");
|
|
12924
12793
|
if (shell === "zsh") {
|
|
12925
12794
|
await ensureZshCompletionFpath();
|
|
@@ -12934,7 +12803,7 @@ var uninstallCompletionScript = async (shell) => {
|
|
|
12934
12803
|
var runInteractiveLoginOnboarding = async (baseUrl, token) => {
|
|
12935
12804
|
const [{ render }, { Onboarding }] = await Promise.all([
|
|
12936
12805
|
import("ink"),
|
|
12937
|
-
import("./Onboarding-
|
|
12806
|
+
import("./Onboarding-3NZCPBCO.js")
|
|
12938
12807
|
]);
|
|
12939
12808
|
await new Promise((resolve) => {
|
|
12940
12809
|
let app;
|
|
@@ -13168,7 +13037,7 @@ var resolveBaseUrl = async (options, command) => {
|
|
|
13168
13037
|
});
|
|
13169
13038
|
}
|
|
13170
13039
|
try {
|
|
13171
|
-
const { getAuthStatus } = await import("./dist-
|
|
13040
|
+
const { getAuthStatus } = await import("./dist-TBAQ5KOK.js");
|
|
13172
13041
|
const status = await getAuthStatus();
|
|
13173
13042
|
const storedBaseUrl = status.baseUrl;
|
|
13174
13043
|
if (storedBaseUrl && shouldUseStoredBaseUrl(storedBaseUrl)) {
|
|
@@ -13239,7 +13108,7 @@ program.command("login").description("Authenticate with Cloudeval").option(
|
|
|
13239
13108
|
checkUserStatus,
|
|
13240
13109
|
ensurePlaygroundProject,
|
|
13241
13110
|
login
|
|
13242
|
-
} = await import("./dist-
|
|
13111
|
+
} = await import("./dist-TBAQ5KOK.js");
|
|
13243
13112
|
assertSecureBaseUrl(options.baseUrl);
|
|
13244
13113
|
const headlessEnvironment = isHeadlessEnvironment();
|
|
13245
13114
|
const headlessLogin = options.headless || headlessEnvironment;
|
|
@@ -13303,7 +13172,7 @@ program.command("logout").description("Log out and clear stored authentication s
|
|
|
13303
13172
|
DEFAULT_BASE_URL
|
|
13304
13173
|
).option("--all-devices", "Revoke sessions on all devices", false).action(async (options) => {
|
|
13305
13174
|
try {
|
|
13306
|
-
const { assertSecureBaseUrl, logout } = await import("./dist-
|
|
13175
|
+
const { assertSecureBaseUrl, logout } = await import("./dist-TBAQ5KOK.js");
|
|
13307
13176
|
assertSecureBaseUrl(options.baseUrl);
|
|
13308
13177
|
const result = await logout({
|
|
13309
13178
|
baseUrl: options.baseUrl,
|
|
@@ -13327,7 +13196,7 @@ authCommand.command("status").description("Show current authentication status").
|
|
|
13327
13196
|
DEFAULT_BASE_URL
|
|
13328
13197
|
).option("--format <format>", "Output format: text, json, ndjson, markdown", "text").option("--show-sensitive-ids", "Show full account/session identifiers in command output", false).option("-v, --verbose", "Enable verbose logging and show full non-token identifiers", false).action(async (options, command) => {
|
|
13329
13198
|
try {
|
|
13330
|
-
const { assertSecureBaseUrl, getAuthStatus } = await import("./dist-
|
|
13199
|
+
const { assertSecureBaseUrl, getAuthStatus } = await import("./dist-TBAQ5KOK.js");
|
|
13331
13200
|
const effectiveBaseUrl = await resolveBaseUrl(options, command);
|
|
13332
13201
|
assertSecureBaseUrl(effectiveBaseUrl);
|
|
13333
13202
|
const status = await getAuthStatus(effectiveBaseUrl, { validate: true });
|
|
@@ -13379,6 +13248,7 @@ registerRecipesCommand(program, {
|
|
|
13379
13248
|
readStdinValue,
|
|
13380
13249
|
isHeadlessEnvironment
|
|
13381
13250
|
});
|
|
13251
|
+
registerSkillsCommand(program);
|
|
13382
13252
|
registerOpenCommand(program, {
|
|
13383
13253
|
defaultBaseUrl: DEFAULT_BASE_URL,
|
|
13384
13254
|
resolveBaseUrl
|
|
@@ -13508,14 +13378,15 @@ program.command("tui").description("Open the CloudEval Terminal UI").option(
|
|
|
13508
13378
|
"--access-key <key>",
|
|
13509
13379
|
"Access key for automation",
|
|
13510
13380
|
process.env.CLOUDEVAL_ACCESS_KEY
|
|
13511
|
-
).option("--access-key-stdin", "Read access key from stdin (recommended for automation)", false).option("--model <name>", "Model name").option("--debug", "Log raw chunks", false).option("--health-check", "Enable health check (disabled by default)").option("--no-banner", "Disable ASCII banner").option("--animate", "Enable TUI animations").option("--no-anim", "Disable TUI animations").option("-v, --verbose", "Enable verbose logging", false).action(async (options, command) => {
|
|
13512
|
-
const { assertSecureBaseUrl } = await import("./dist-
|
|
13381
|
+
).option("--access-key-stdin", "Read access key from stdin (recommended for automation)", false).option("--model <name>", "Model name").option("--debug", "Log raw chunks", false).option("--health-check", "Enable health check (disabled by default)").option("--no-banner", "Disable ASCII banner").option("--animate", "Enable TUI animations (default)").option("--no-anim", "Disable TUI animations").option("-v, --verbose", "Enable verbose logging", false).action(async (options, command) => {
|
|
13382
|
+
const { assertSecureBaseUrl } = await import("./dist-TBAQ5KOK.js");
|
|
13513
13383
|
const [{ render }, { App }] = await Promise.all([
|
|
13514
13384
|
import("ink"),
|
|
13515
|
-
import("./App-
|
|
13385
|
+
import("./App-FJ7ANARO.js")
|
|
13516
13386
|
]);
|
|
13517
13387
|
const baseUrl = await resolveBaseUrl(options, command);
|
|
13518
13388
|
assertSecureBaseUrl(baseUrl);
|
|
13389
|
+
const selectedProfile = getActiveConfigProfile(command);
|
|
13519
13390
|
const cliConfig = await resolveCliConfig(command);
|
|
13520
13391
|
const initialMode = normalizeCliMode(options.mode ?? cliConfig.mode) ?? "ask";
|
|
13521
13392
|
let accessKey = options.accessKey;
|
|
@@ -13540,6 +13411,7 @@ program.command("tui").description("Open the CloudEval Terminal UI").option(
|
|
|
13540
13411
|
initialMode,
|
|
13541
13412
|
initialTab: options.tab,
|
|
13542
13413
|
initialProjectId: options.project ?? cliConfig.defaultProjectId,
|
|
13414
|
+
configProfile: selectedProfile,
|
|
13543
13415
|
frontendUrl: options.frontendUrl ?? cliConfig.frontendUrl,
|
|
13544
13416
|
debug: options.debug,
|
|
13545
13417
|
disableBanner: options.banner === false,
|
|
@@ -13558,11 +13430,11 @@ program.command("chat").description("Start an interactive chat session").option(
|
|
|
13558
13430
|
"--access-key <key>",
|
|
13559
13431
|
"Access key for automation",
|
|
13560
13432
|
process.env.CLOUDEVAL_ACCESS_KEY
|
|
13561
|
-
).option("--access-key-stdin", "Read access key from stdin (recommended for automation)", false).option("--conversation <id>", "Conversation/thread id to resume").option("--continue", "Resume the most recent local chat session", false).option("--resume <id-or-title>", "Resume a local chat session by thread id or title").option("--model <name>", "Model name").option("--mode <mode>", "Initial chat mode: ask, agent").option("--debug", "Log raw chunks", false).option("--health-check", "Enable health check (disabled by default)").option("--no-banner", "Disable ASCII banner").option("--animate", "Enable TUI animations").option("--no-anim", "Disable TUI animations").option("-v, --verbose", "Enable verbose logging", false).action(async (options, command) => {
|
|
13562
|
-
const { assertSecureBaseUrl } = await import("./dist-
|
|
13433
|
+
).option("--access-key-stdin", "Read access key from stdin (recommended for automation)", false).option("--conversation <id>", "Conversation/thread id to resume").option("--continue", "Resume the most recent local chat session", false).option("--resume <id-or-title>", "Resume a local chat session by thread id or title").option("--model <name>", "Model name").option("--mode <mode>", "Initial chat mode: ask, agent").option("--debug", "Log raw chunks", false).option("--health-check", "Enable health check (disabled by default)").option("--no-banner", "Disable ASCII banner").option("--animate", "Enable TUI animations (default)").option("--no-anim", "Disable TUI animations").option("-v, --verbose", "Enable verbose logging", false).action(async (options, command) => {
|
|
13434
|
+
const { assertSecureBaseUrl } = await import("./dist-TBAQ5KOK.js");
|
|
13563
13435
|
const [{ render }, { App }] = await Promise.all([
|
|
13564
13436
|
import("ink"),
|
|
13565
|
-
import("./App-
|
|
13437
|
+
import("./App-FJ7ANARO.js")
|
|
13566
13438
|
]);
|
|
13567
13439
|
const baseUrl = await resolveBaseUrl(options, command);
|
|
13568
13440
|
assertSecureBaseUrl(baseUrl);
|
|
@@ -13608,6 +13480,7 @@ program.command("chat").description("Start an interactive chat session").option(
|
|
|
13608
13480
|
model: options.model ?? cliConfig.model,
|
|
13609
13481
|
initialMode,
|
|
13610
13482
|
initialProjectId: cliConfig.defaultProjectId,
|
|
13483
|
+
configProfile: selectedProfile,
|
|
13611
13484
|
frontendUrl: cliConfig.frontendUrl,
|
|
13612
13485
|
debug: options.debug,
|
|
13613
13486
|
disableBanner: options.banner === false,
|
|
@@ -13630,7 +13503,7 @@ program.command("ask").alias("agent").description("Ask a single question or run
|
|
|
13630
13503
|
const question = Array.isArray(questionParts) ? questionParts.join(" ") : String(questionParts);
|
|
13631
13504
|
const commandName = command.parent?.args?.[0] === "agent" ? "agent" : "ask";
|
|
13632
13505
|
const selectedMode = commandName === "agent" ? "agent" : "ask";
|
|
13633
|
-
const { assertSecureBaseUrl } = await import("./dist-
|
|
13506
|
+
const { assertSecureBaseUrl } = await import("./dist-TBAQ5KOK.js");
|
|
13634
13507
|
const baseUrl = await resolveBaseUrl(options, command);
|
|
13635
13508
|
assertSecureBaseUrl(baseUrl);
|
|
13636
13509
|
const selectedProfile = getActiveConfigProfile(command);
|
|
@@ -13671,7 +13544,7 @@ program.command("ask").alias("agent").description("Ask a single question or run
|
|
|
13671
13544
|
const fs13 = await import("fs");
|
|
13672
13545
|
const fsPromises = await import("fs/promises");
|
|
13673
13546
|
const { randomUUID: randomUUID5 } = await import("crypto");
|
|
13674
|
-
const core = await import("./dist-
|
|
13547
|
+
const core = await import("./dist-TBAQ5KOK.js");
|
|
13675
13548
|
const {
|
|
13676
13549
|
streamChat,
|
|
13677
13550
|
reduceChunk,
|
|
@@ -13681,7 +13554,8 @@ program.command("ask").alias("agent").description("Ask a single question or run
|
|
|
13681
13554
|
checkUserStatus,
|
|
13682
13555
|
extractEmailFromToken,
|
|
13683
13556
|
initialChatState,
|
|
13684
|
-
normalizeApiBase: normalizeApiBase2
|
|
13557
|
+
normalizeApiBase: normalizeApiBase2,
|
|
13558
|
+
isExpiredDeviceTokenStreamError
|
|
13685
13559
|
} = core;
|
|
13686
13560
|
const progressWriter = createAskProgressWriter({
|
|
13687
13561
|
mode: progressMode,
|
|
@@ -13728,7 +13602,7 @@ program.command("ask").alias("agent").description("Ask a single question or run
|
|
|
13728
13602
|
console.error("Authentication required. Starting login process...\n");
|
|
13729
13603
|
}
|
|
13730
13604
|
try {
|
|
13731
|
-
const { login } = await import("./dist-
|
|
13605
|
+
const { login } = await import("./dist-TBAQ5KOK.js");
|
|
13732
13606
|
verboseLog("Calling interactive login", { baseUrl });
|
|
13733
13607
|
token = await login(baseUrl, {
|
|
13734
13608
|
headless: isHeadlessEnvironment()
|
|
@@ -13941,6 +13815,7 @@ program.command("ask").alias("agent").description("Ask a single question or run
|
|
|
13941
13815
|
try {
|
|
13942
13816
|
let totalChunkCount = 0;
|
|
13943
13817
|
let hitlResume;
|
|
13818
|
+
let retriedAfterAuthRefresh = false;
|
|
13944
13819
|
while (true) {
|
|
13945
13820
|
let pendingHitlRequest;
|
|
13946
13821
|
progressWriter.write({
|
|
@@ -13950,89 +13825,109 @@ program.command("ask").alias("agent").description("Ask a single question or run
|
|
|
13950
13825
|
threadId,
|
|
13951
13826
|
projectId: project.id
|
|
13952
13827
|
});
|
|
13953
|
-
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
|
|
13974
|
-
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
|
|
13989
|
-
|
|
13990
|
-
|
|
13991
|
-
|
|
13992
|
-
|
|
13993
|
-
|
|
13994
|
-
}
|
|
13995
|
-
const latestMessage = [...chatState.messages].reverse().find((m) => m.role === "assistant");
|
|
13996
|
-
if (ndjsonOutput && chunk.type === "responding" && chunk.content && (!chunk.node || STREAM_OUTPUT_NODES3.has(chunk.node))) {
|
|
13997
|
-
writeAskDataEvent({
|
|
13998
|
-
type: "chunk",
|
|
13999
|
-
content: chunk.content,
|
|
14000
|
-
node: chunk.node,
|
|
14001
|
-
threadId
|
|
14002
|
-
});
|
|
14003
|
-
}
|
|
14004
|
-
if (streamTextOutput && chunk.type === "responding" && chunk.content && (!chunk.node || STREAM_OUTPUT_NODES3.has(chunk.node))) {
|
|
14005
|
-
if (latestMessage?.content) {
|
|
14006
|
-
responseText = latestMessage.content;
|
|
14007
|
-
const delta = responseText.slice(emittedTextLength);
|
|
14008
|
-
if (delta) {
|
|
14009
|
-
progressWriter.clear();
|
|
14010
|
-
if (!responseText.slice(0, emittedTextLength).endsWith(delta)) {
|
|
14011
|
-
outputStream.write(delta);
|
|
13828
|
+
while (true) {
|
|
13829
|
+
try {
|
|
13830
|
+
for await (const chunk of streamChat({
|
|
13831
|
+
baseUrl,
|
|
13832
|
+
authToken: token,
|
|
13833
|
+
message: hitlResume ? "" : question,
|
|
13834
|
+
threadId,
|
|
13835
|
+
user: { id: project.user_id ?? authenticatedUserId ?? "cli-user", name: userName },
|
|
13836
|
+
project,
|
|
13837
|
+
settings: streamSettings,
|
|
13838
|
+
debug: options.debug,
|
|
13839
|
+
completeAfterResponse: true,
|
|
13840
|
+
responseCompletionGraceMs: 5e3,
|
|
13841
|
+
streamIdleTimeoutMs: ASK_STREAM_IDLE_TIMEOUT_MS2,
|
|
13842
|
+
hitlResume
|
|
13843
|
+
})) {
|
|
13844
|
+
totalChunkCount++;
|
|
13845
|
+
if (options.verbose && totalChunkCount % 10 === 0) {
|
|
13846
|
+
verboseLog(`Received ${totalChunkCount} chunks`);
|
|
13847
|
+
}
|
|
13848
|
+
if (options.debug || options.verbose) {
|
|
13849
|
+
verboseLog("Chunk received:", {
|
|
13850
|
+
type: chunk.type,
|
|
13851
|
+
node: chunk.node,
|
|
13852
|
+
hasContent: !!chunk.content,
|
|
13853
|
+
contentLength: chunk.content?.length || 0
|
|
13854
|
+
});
|
|
13855
|
+
}
|
|
13856
|
+
chatState = reduceChunk(chatState, chunk);
|
|
13857
|
+
writeChunkProgressEvent(progressEventFromChunk(chunk, { verbose: options.verbose }));
|
|
13858
|
+
if (chunk.type === "hitl_request") {
|
|
13859
|
+
pendingHitlRequest = chunk;
|
|
13860
|
+
if (ndjsonOutput) {
|
|
13861
|
+
writeAskDataEvent({
|
|
13862
|
+
type: "hitl_request",
|
|
13863
|
+
threadId,
|
|
13864
|
+
checkpointId: chunk.checkpoint_id,
|
|
13865
|
+
pendingIntentId: chunk.pending_intent_id,
|
|
13866
|
+
questions: chunk.questions ?? [],
|
|
13867
|
+
frontendUrl
|
|
13868
|
+
});
|
|
14012
13869
|
}
|
|
14013
|
-
|
|
13870
|
+
break;
|
|
14014
13871
|
}
|
|
14015
|
-
|
|
14016
|
-
|
|
14017
|
-
|
|
14018
|
-
|
|
14019
|
-
|
|
14020
|
-
|
|
14021
|
-
|
|
14022
|
-
|
|
14023
|
-
|
|
14024
|
-
|
|
14025
|
-
|
|
14026
|
-
|
|
14027
|
-
|
|
14028
|
-
|
|
14029
|
-
|
|
14030
|
-
|
|
14031
|
-
|
|
13872
|
+
const latestMessage = [...chatState.messages].reverse().find((m) => m.role === "assistant");
|
|
13873
|
+
if (ndjsonOutput && chunk.type === "responding" && chunk.content && (!chunk.node || STREAM_OUTPUT_NODES3.has(chunk.node))) {
|
|
13874
|
+
writeAskDataEvent({
|
|
13875
|
+
type: "chunk",
|
|
13876
|
+
content: chunk.content,
|
|
13877
|
+
node: chunk.node,
|
|
13878
|
+
threadId
|
|
13879
|
+
});
|
|
13880
|
+
}
|
|
13881
|
+
if (streamTextOutput && chunk.type === "responding" && chunk.content && (!chunk.node || STREAM_OUTPUT_NODES3.has(chunk.node))) {
|
|
13882
|
+
if (latestMessage?.content) {
|
|
13883
|
+
responseText = latestMessage.content;
|
|
13884
|
+
const delta = responseText.slice(emittedTextLength);
|
|
13885
|
+
if (delta) {
|
|
13886
|
+
progressWriter.clear();
|
|
13887
|
+
if (!responseText.slice(0, emittedTextLength).endsWith(delta)) {
|
|
13888
|
+
outputStream.write(delta);
|
|
13889
|
+
}
|
|
13890
|
+
emittedTextLength = responseText.length;
|
|
13891
|
+
}
|
|
13892
|
+
}
|
|
13893
|
+
}
|
|
13894
|
+
if (chunk.type === "error") {
|
|
13895
|
+
const errorMsg = chunk.message || chunk.description || "Unknown error";
|
|
13896
|
+
verboseLog("Error chunk received:", {
|
|
13897
|
+
message: errorMsg,
|
|
13898
|
+
node: chunk.node,
|
|
13899
|
+
status: chunk.status,
|
|
13900
|
+
stack: chunk.stacktrace
|
|
13901
|
+
});
|
|
13902
|
+
progressWriter.clear();
|
|
13903
|
+
if (jsonOutput) {
|
|
13904
|
+
responseText = `Error: ${errorMsg}`;
|
|
13905
|
+
} else if (ndjsonOutput) {
|
|
13906
|
+
writeAskDataEvent({ type: "error", error: { message: errorMsg }, threadId });
|
|
13907
|
+
} else {
|
|
13908
|
+
outputStream.write(`
|
|
14032
13909
|
Error: ${errorMsg}
|
|
14033
13910
|
`);
|
|
13911
|
+
}
|
|
13912
|
+
break;
|
|
13913
|
+
}
|
|
14034
13914
|
}
|
|
14035
13915
|
break;
|
|
13916
|
+
} catch (error) {
|
|
13917
|
+
if (!providedAccessKey && !retriedAfterAuthRefresh && isExpiredDeviceTokenStreamError(error)) {
|
|
13918
|
+
retriedAfterAuthRefresh = true;
|
|
13919
|
+
verboseLog("Stored device token expired during stream; refreshing and retrying once");
|
|
13920
|
+
progressWriter.write({
|
|
13921
|
+
type: "auth",
|
|
13922
|
+
step: "auth",
|
|
13923
|
+
message: "Refreshing expired session",
|
|
13924
|
+
threadId,
|
|
13925
|
+
projectId: project.id
|
|
13926
|
+
});
|
|
13927
|
+
token = await getAuthToken({ baseUrl, forceRefresh: true });
|
|
13928
|
+
continue;
|
|
13929
|
+
}
|
|
13930
|
+
throw error;
|
|
14036
13931
|
}
|
|
14037
13932
|
}
|
|
14038
13933
|
if (!pendingHitlRequest) {
|
|
@@ -14296,7 +14191,7 @@ Error: ${errorMsg}
|
|
|
14296
14191
|
program.command("banner").description("Preview the startup banner and terminal capabilities").action(async () => {
|
|
14297
14192
|
const { render } = await import("ink");
|
|
14298
14193
|
const BannerPreview = React.lazy(async () => ({
|
|
14299
|
-
default: (await import("./Banner-
|
|
14194
|
+
default: (await import("./Banner-NJ6WDPDB.js")).Banner
|
|
14300
14195
|
}));
|
|
14301
14196
|
render(
|
|
14302
14197
|
/* @__PURE__ */ jsx(React.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(BannerPreview, { disable: false }) })
|