sim 2.1.17 → 2.1.18-dev.130.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/dist/auth/device-flow.d.ts +39 -0
- package/dist/auth/oauth-flow.d.ts +119 -0
- package/dist/auth/refresh.d.ts +16 -0
- package/dist/commands/auth.d.ts +5 -0
- package/dist/commands/configure.d.ts +2 -0
- package/dist/commands/credentials.d.ts +3 -0
- package/dist/commands/protocol/chat.d.ts +11 -0
- package/dist/commands/protocol/files-get.d.ts +25 -0
- package/dist/commands/protocol/files-upload.d.ts +2 -0
- package/dist/commands/protocol/index.d.ts +3 -0
- package/dist/commands/protocol/knowledge-document-upload.d.ts +2 -0
- package/dist/commands/protocol/knowledge-export.d.ts +14 -0
- package/dist/commands/protocol/logs-follow.d.ts +39 -0
- package/dist/commands/protocol/resource-directory.d.ts +24 -0
- package/dist/commands/protocol/result.d.ts +2 -0
- package/dist/commands/protocol/tables-import.d.ts +2 -0
- package/dist/commands/protocol/workflow-run-follow.d.ts +56 -0
- package/dist/commands/protocol/workflow-run-get.d.ts +15 -0
- package/dist/commands/protocol/workflow-run-wait.d.ts +3 -0
- package/dist/commands/protocol/workspace-operation-wait.d.ts +14 -0
- package/dist/commands/secrets.d.ts +3 -0
- package/dist/commands/telemetry.d.ts +2 -0
- package/dist/commands/update.d.ts +2 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/ini.d.ts +111 -0
- package/dist/config/json-file.d.ts +18 -0
- package/dist/config/paths.d.ts +29 -0
- package/dist/config/profile.d.ts +210 -0
- package/dist/context.d.ts +21 -0
- package/dist/contract/commands.d.ts +14 -0
- package/dist/contract/types.d.ts +306 -0
- package/dist/embed-context.d.ts +77 -0
- package/dist/embed-output.d.ts +15 -0
- package/dist/embed.d.ts +39 -0
- package/dist/environment.d.ts +22 -0
- package/dist/generated/v2-api.d.ts +15057 -0
- package/dist/helpers.d.ts +9 -0
- package/dist/http/client.d.ts +173 -0
- package/dist/http/environment.d.ts +24 -0
- package/dist/http/ndjson.d.ts +5 -0
- package/dist/index.js +809 -327
- package/dist/output/io.d.ts +5 -0
- package/dist/output/presentation.d.ts +4 -0
- package/dist/output/render.d.ts +60 -0
- package/dist/output/terminal-text.d.ts +17 -0
- package/dist/output/trace.d.ts +3 -0
- package/dist/output/truncation.d.ts +3 -0
- package/dist/program.d.ts +21 -0
- package/dist/runtime/build.d.ts +38 -0
- package/dist/runtime/derive.d.ts +20 -0
- package/dist/runtime/execute.d.ts +32 -0
- package/dist/runtime/naming.d.ts +25 -0
- package/dist/runtime/options.d.ts +9 -0
- package/dist/runtime/renamed.d.ts +6 -0
- package/dist/runtime/request.d.ts +110 -0
- package/dist/runtime/result.d.ts +41 -0
- package/dist/runtime/types.d.ts +23 -0
- package/dist/runtime.d.ts +5 -0
- package/dist/runtime.js +21854 -0
- package/dist/telemetry/client-info.d.ts +20 -0
- package/dist/telemetry/coding-agent.d.ts +31 -0
- package/dist/telemetry/index.d.ts +4 -0
- package/dist/telemetry/invocation.d.ts +98 -0
- package/dist/telemetry/policy.d.ts +38 -0
- package/dist/telemetry/state.d.ts +47 -0
- package/dist/telemetry/transport.d.ts +47 -0
- package/dist/terminal/secret-input.d.ts +15 -0
- package/dist/terminal.d.ts +7 -0
- package/dist/transfer/local-file.d.ts +16 -0
- package/dist/transfer/streaming-upload.d.ts +16 -0
- package/dist/transfer/upload-session.d.ts +18 -0
- package/dist/update/check.d.ts +53 -0
- package/dist/update/install.d.ts +20 -0
- package/dist/version.d.ts +10 -0
- package/package.json +12 -2
package/dist/index.js
CHANGED
|
@@ -3692,6 +3692,12 @@ var applyOptions = (object, options = {}) => {
|
|
|
3692
3692
|
const colorLevel = stdoutColor ? stdoutColor.level : 0;
|
|
3693
3693
|
object.level = options.level === undefined ? colorLevel : options.level;
|
|
3694
3694
|
};
|
|
3695
|
+
|
|
3696
|
+
class Chalk {
|
|
3697
|
+
constructor(options) {
|
|
3698
|
+
return chalkFactory(options);
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3695
3701
|
var chalkFactory = (options) => {
|
|
3696
3702
|
const chalk = (...strings) => strings.join(" ");
|
|
3697
3703
|
applyOptions(chalk, options);
|
|
@@ -3820,6 +3826,56 @@ var chalk = createChalk();
|
|
|
3820
3826
|
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
3821
3827
|
var source_default = chalk;
|
|
3822
3828
|
|
|
3829
|
+
// src/embed-context.ts
|
|
3830
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3831
|
+
function setSoftExitCode(code) {
|
|
3832
|
+
const ctx = embedStore.getStore();
|
|
3833
|
+
if (ctx)
|
|
3834
|
+
ctx.softExitCode = code;
|
|
3835
|
+
else
|
|
3836
|
+
process.exitCode = code;
|
|
3837
|
+
}
|
|
3838
|
+
var embedStore = new AsyncLocalStorage;
|
|
3839
|
+
|
|
3840
|
+
class EmbeddedExit extends Error {
|
|
3841
|
+
code;
|
|
3842
|
+
constructor(code) {
|
|
3843
|
+
super(`CLI exited with code ${code}`);
|
|
3844
|
+
this.code = code;
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3847
|
+
function embeddedProfile() {
|
|
3848
|
+
const ctx = embedStore.getStore();
|
|
3849
|
+
if (!ctx)
|
|
3850
|
+
return null;
|
|
3851
|
+
return {
|
|
3852
|
+
name: "embedded",
|
|
3853
|
+
authProfile: "embedded",
|
|
3854
|
+
oauth: null,
|
|
3855
|
+
endpoint: ctx.identity.endpoint,
|
|
3856
|
+
apiKey: ctx.identity.apiKey,
|
|
3857
|
+
workspaceId: ctx.identity.workspaceId ?? null,
|
|
3858
|
+
output: "json",
|
|
3859
|
+
...ctx.identity.transport ? { transport: ctx.identity.transport } : {},
|
|
3860
|
+
...ctx.identity.signal ? { signal: ctx.identity.signal } : {},
|
|
3861
|
+
sources: { endpoint: "flag", credential: "flag", workspaceId: "flag", output: "flag" }
|
|
3862
|
+
};
|
|
3863
|
+
}
|
|
3864
|
+
function exitCli(code) {
|
|
3865
|
+
if (embedStore.getStore())
|
|
3866
|
+
throw new EmbeddedExit(code);
|
|
3867
|
+
return process.exit(code);
|
|
3868
|
+
}
|
|
3869
|
+
|
|
3870
|
+
// src/output/presentation.ts
|
|
3871
|
+
var plain = new Chalk({ level: 0 });
|
|
3872
|
+
function styles3() {
|
|
3873
|
+
return embedStore.getStore() ? plain : source_default;
|
|
3874
|
+
}
|
|
3875
|
+
function hasProgressTerminal() {
|
|
3876
|
+
return !embedStore.getStore() && Boolean(process.stderr.isTTY);
|
|
3877
|
+
}
|
|
3878
|
+
|
|
3823
3879
|
// node_modules/js-yaml/dist/js-yaml.mjs
|
|
3824
3880
|
function getDefaultExportFromCjs(x) {
|
|
3825
3881
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
@@ -6962,15 +7018,6 @@ function getErrorMessage(value, fallback) {
|
|
|
6962
7018
|
return fallback ?? String(value);
|
|
6963
7019
|
}
|
|
6964
7020
|
|
|
6965
|
-
// ../utils/src/object.ts
|
|
6966
|
-
function omit(obj, keys) {
|
|
6967
|
-
const result = { ...obj };
|
|
6968
|
-
for (const key of keys) {
|
|
6969
|
-
delete result[key];
|
|
6970
|
-
}
|
|
6971
|
-
return result;
|
|
6972
|
-
}
|
|
6973
|
-
|
|
6974
7021
|
// src/update/install.ts
|
|
6975
7022
|
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
6976
7023
|
|
|
@@ -7103,14 +7150,22 @@ function childProcessEnv(strip, extra = {}) {
|
|
|
7103
7150
|
// src/version.ts
|
|
7104
7151
|
import { readFileSync } from "node:fs";
|
|
7105
7152
|
function readPackageVersion() {
|
|
7106
|
-
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7153
|
+
try {
|
|
7154
|
+
const metadata = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
7155
|
+
if (typeof metadata === "object" && metadata !== null && "version" in metadata && typeof metadata.version === "string") {
|
|
7156
|
+
return metadata.version;
|
|
7157
|
+
}
|
|
7158
|
+
} catch {}
|
|
7159
|
+
return "0.0.0-embedded";
|
|
7160
|
+
}
|
|
7161
|
+
var cachedVersion = null;
|
|
7162
|
+
function cliVersion() {
|
|
7163
|
+
cachedVersion ??= readPackageVersion();
|
|
7164
|
+
return cachedVersion;
|
|
7165
|
+
}
|
|
7166
|
+
function userAgent() {
|
|
7167
|
+
return `sim-cli/${cliVersion()} node/${process.versions.node} (${process.platform}; ${process.arch})`;
|
|
7111
7168
|
}
|
|
7112
|
-
var CLI_VERSION = readPackageVersion();
|
|
7113
|
-
var USER_AGENT = `sim-cli/${CLI_VERSION} node/${process.versions.node} (${process.platform}; ${process.arch})`;
|
|
7114
7169
|
|
|
7115
7170
|
// src/update/check.ts
|
|
7116
7171
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
@@ -7243,7 +7298,7 @@ async function fetchDistTags(env, request) {
|
|
|
7243
7298
|
if (!url)
|
|
7244
7299
|
return null;
|
|
7245
7300
|
const text = await request(url, {
|
|
7246
|
-
headers: { accept: "application/json", "user-agent": `${PACKAGE_NAME}-cli/${
|
|
7301
|
+
headers: { accept: "application/json", "user-agent": `${PACKAGE_NAME}-cli/${cliVersion()}` },
|
|
7247
7302
|
maxResponseBytes: MAX_RESPONSE_BYTES,
|
|
7248
7303
|
timeoutMs: REGISTRY_TIMEOUT_MS
|
|
7249
7304
|
});
|
|
@@ -7315,7 +7370,7 @@ async function announceUpdateIfAvailable(options = {}) {
|
|
|
7315
7370
|
return;
|
|
7316
7371
|
if (isUnadvisableInstall(modulePath, env, cwd))
|
|
7317
7372
|
return;
|
|
7318
|
-
const currentVersion = options.currentVersion ??
|
|
7373
|
+
const currentVersion = options.currentVersion ?? cliVersion();
|
|
7319
7374
|
const current = parseStableVersion(currentVersion);
|
|
7320
7375
|
if (!current)
|
|
7321
7376
|
return;
|
|
@@ -7438,7 +7493,7 @@ function parseRegistryVersion(output, manager) {
|
|
|
7438
7493
|
}
|
|
7439
7494
|
async function installUpdate(options = {}) {
|
|
7440
7495
|
const modulePath = resolveInstallationPath(options.modulePath ?? fileURLToPath2(import.meta.url));
|
|
7441
|
-
const env =
|
|
7496
|
+
const env = { ...options.env ?? process.env, SIM_API_KEY: undefined };
|
|
7442
7497
|
const normalized = modulePath.replaceAll("\\", "/").toLowerCase();
|
|
7443
7498
|
if (env.npm_command === "exec" || normalized.includes("/_npx/") || normalized.includes("/bunx-") || !normalized.endsWith("/node_modules/sim/dist/index.js")) {
|
|
7444
7499
|
throw new CliUpdateError("sim update requires a global installation. Update project dependencies with their package manager, or use sim@latest with your package runner.");
|
|
@@ -7449,7 +7504,7 @@ async function installUpdate(options = {}) {
|
|
|
7449
7504
|
}
|
|
7450
7505
|
const packageManager = manager;
|
|
7451
7506
|
const run = options.run ?? runPackageManager;
|
|
7452
|
-
const currentVersion = options.currentVersion ??
|
|
7507
|
+
const currentVersion = options.currentVersion ?? cliVersion();
|
|
7453
7508
|
const current = parseReleaseVersion(currentVersion);
|
|
7454
7509
|
const target = current.channel;
|
|
7455
7510
|
const write = options.write ?? ((message) => void process.stderr.write(message));
|
|
@@ -7516,7 +7571,7 @@ async function installUpdate(options = {}) {
|
|
|
7516
7571
|
}
|
|
7517
7572
|
// src/config/profile.ts
|
|
7518
7573
|
var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
|
|
7519
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7574
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
7520
7575
|
import { createHash } from "node:crypto";
|
|
7521
7576
|
import {
|
|
7522
7577
|
chmodSync,
|
|
@@ -7850,7 +7905,7 @@ function readStoredCredential(profile) {
|
|
|
7850
7905
|
var CREDENTIALS_LOCK_STALE_MS = 30000;
|
|
7851
7906
|
var CREDENTIALS_LOCK_WAIT_MS = 20000;
|
|
7852
7907
|
var CREDENTIALS_LOCK_POLL_MS = 50;
|
|
7853
|
-
var heldLock = new
|
|
7908
|
+
var heldLock = new AsyncLocalStorage2;
|
|
7854
7909
|
async function withProfileLoginLease(profile, work) {
|
|
7855
7910
|
const digest = createHash("sha256").update(profile, "utf8").digest("hex");
|
|
7856
7911
|
const path = `${credentialsPath()}.login-${digest}`;
|
|
@@ -7964,6 +8019,9 @@ function refuseBlankOverrides(overrides) {
|
|
|
7964
8019
|
}
|
|
7965
8020
|
}
|
|
7966
8021
|
function resolveProfile(overrides = {}) {
|
|
8022
|
+
const embedded = embeddedProfile();
|
|
8023
|
+
if (embedded)
|
|
8024
|
+
return embedded;
|
|
7967
8025
|
refuseBlankOverrides(overrides);
|
|
7968
8026
|
const named = overrides.profile || process.env.SIM_PROFILE;
|
|
7969
8027
|
const name = named || DEFAULT_PROFILE;
|
|
@@ -8021,6 +8079,39 @@ function resolveProfile(overrides = {}) {
|
|
|
8021
8079
|
}
|
|
8022
8080
|
};
|
|
8023
8081
|
}
|
|
8082
|
+
// src/output/io.ts
|
|
8083
|
+
import { format } from "node:util";
|
|
8084
|
+
function printLine(...args) {
|
|
8085
|
+
const context = embedStore.getStore();
|
|
8086
|
+
if (context)
|
|
8087
|
+
context.stdout.write(`${format(...args)}
|
|
8088
|
+
`);
|
|
8089
|
+
else
|
|
8090
|
+
console.log(...args);
|
|
8091
|
+
}
|
|
8092
|
+
function printError(...args) {
|
|
8093
|
+
const context = embedStore.getStore();
|
|
8094
|
+
if (context)
|
|
8095
|
+
context.stderr.write(`${format(...args)}
|
|
8096
|
+
`);
|
|
8097
|
+
else
|
|
8098
|
+
console.error(...args);
|
|
8099
|
+
}
|
|
8100
|
+
function writeStdout(chunk) {
|
|
8101
|
+
const context = embedStore.getStore();
|
|
8102
|
+
if (!context)
|
|
8103
|
+
return process.stdout.write(chunk);
|
|
8104
|
+
context.stdout.write(chunk);
|
|
8105
|
+
return true;
|
|
8106
|
+
}
|
|
8107
|
+
function writeStderr(chunk) {
|
|
8108
|
+
const context = embedStore.getStore();
|
|
8109
|
+
if (!context)
|
|
8110
|
+
return process.stderr.write(chunk);
|
|
8111
|
+
context.stderr.write(chunk);
|
|
8112
|
+
return true;
|
|
8113
|
+
}
|
|
8114
|
+
|
|
8024
8115
|
// ../utils/src/client-info.ts
|
|
8025
8116
|
var CLIENT_INFO_HEADER = "x-sim-client-info";
|
|
8026
8117
|
var SIM_SURFACES = ["web", "desktop", "cli", "sdk-js", "sdk-python"];
|
|
@@ -8192,12 +8283,12 @@ function clientInfoHeader(env = process.env) {
|
|
|
8192
8283
|
return cached;
|
|
8193
8284
|
}
|
|
8194
8285
|
function identityHeaders() {
|
|
8195
|
-
return { "user-agent":
|
|
8286
|
+
return { "user-agent": userAgent(), [CLIENT_INFO_HEADER]: clientInfoHeader() };
|
|
8196
8287
|
}
|
|
8197
8288
|
function buildClientInfoHeader(env) {
|
|
8198
8289
|
return formatClientInfo({
|
|
8199
8290
|
surface: "cli",
|
|
8200
|
-
version:
|
|
8291
|
+
version: cliVersion(),
|
|
8201
8292
|
runtime: { name: "node", version: process.versions.node },
|
|
8202
8293
|
os: process.platform,
|
|
8203
8294
|
arch: process.arch,
|
|
@@ -8214,7 +8305,7 @@ function once(key, message) {
|
|
|
8214
8305
|
if (reported.has(key))
|
|
8215
8306
|
return;
|
|
8216
8307
|
reported.add(key);
|
|
8217
|
-
|
|
8308
|
+
writeStderr(`warning: ${message}
|
|
8218
8309
|
`);
|
|
8219
8310
|
}
|
|
8220
8311
|
var PROXY_VARIABLES = ["HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy"];
|
|
@@ -8406,7 +8497,7 @@ function debugEnabled(env = process.env) {
|
|
|
8406
8497
|
return raw !== undefined && raw !== "" && raw !== "0" && raw.toLowerCase() !== "false";
|
|
8407
8498
|
}
|
|
8408
8499
|
function traceRequest(method, url, status, startedAt) {
|
|
8409
|
-
|
|
8500
|
+
writeStderr(`${styles3().dim(`[sim] ${method} ${url} → ${status} ${Math.round(performance.now() - startedAt)}ms`)}
|
|
8410
8501
|
`);
|
|
8411
8502
|
}
|
|
8412
8503
|
function withoutLeadingLabel(message, label) {
|
|
@@ -8534,12 +8625,15 @@ class SimClient {
|
|
|
8534
8625
|
warnIfCredentialOverCleartext(this.profile.endpoint, Boolean(credential));
|
|
8535
8626
|
const timeoutMs = resolveTimeoutMs();
|
|
8536
8627
|
const timeout = timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : undefined;
|
|
8537
|
-
const
|
|
8628
|
+
const caller = combineSignals(options.signal, this.profile.signal);
|
|
8629
|
+
if (caller?.aborted)
|
|
8630
|
+
throw new SimApiError("Request cancelled.", 0);
|
|
8631
|
+
const signal = combineSignals(caller, timeout);
|
|
8538
8632
|
const trace = debugEnabled();
|
|
8539
8633
|
const startedAt = performance.now();
|
|
8540
8634
|
let response;
|
|
8541
8635
|
try {
|
|
8542
|
-
response = await fetch(url, {
|
|
8636
|
+
response = await (this.profile.transport ?? fetch)(url, {
|
|
8543
8637
|
method,
|
|
8544
8638
|
headers: {
|
|
8545
8639
|
...credential?.kind === "api_key" ? { "x-api-key": credential.apiKey } : {},
|
|
@@ -8556,7 +8650,7 @@ class SimClient {
|
|
|
8556
8650
|
} catch (cause) {
|
|
8557
8651
|
if (trace)
|
|
8558
8652
|
traceRequest(method, url, "failed", startedAt);
|
|
8559
|
-
if (
|
|
8653
|
+
if (caller?.aborted) {
|
|
8560
8654
|
throw new SimApiError("Request cancelled.", 0);
|
|
8561
8655
|
}
|
|
8562
8656
|
if (timeout?.aborted) {
|
|
@@ -8615,14 +8709,14 @@ function pageProgress() {
|
|
|
8615
8709
|
let reported = false;
|
|
8616
8710
|
return {
|
|
8617
8711
|
advance: (fetched) => {
|
|
8618
|
-
if (!
|
|
8712
|
+
if (!hasProgressTerminal())
|
|
8619
8713
|
return;
|
|
8620
8714
|
reported = true;
|
|
8621
|
-
|
|
8715
|
+
writeStderr(`\r${styles3().dim(`fetched ${fetched}…`)}\x1B[K`);
|
|
8622
8716
|
},
|
|
8623
8717
|
finish: () => {
|
|
8624
8718
|
if (reported)
|
|
8625
|
-
|
|
8719
|
+
writeStderr("\r\x1B[K");
|
|
8626
8720
|
}
|
|
8627
8721
|
};
|
|
8628
8722
|
}
|
|
@@ -9046,7 +9140,6 @@ function isWideCodePoint(codePoint) {
|
|
|
9046
9140
|
|
|
9047
9141
|
// src/output/render.ts
|
|
9048
9142
|
var EMPTY_GLYPH = "—";
|
|
9049
|
-
var EMPTY = source_default.dim(EMPTY_GLYPH);
|
|
9050
9143
|
var ESC = String.fromCharCode(27);
|
|
9051
9144
|
var CONTROL_PATTERN = new RegExp([
|
|
9052
9145
|
`${ESC}\\][^\\u0007${ESC}]*(?:\\u0007|${ESC}\\\\)?`,
|
|
@@ -9065,12 +9158,12 @@ function safeOneLine(value) {
|
|
|
9065
9158
|
}
|
|
9066
9159
|
function text(value) {
|
|
9067
9160
|
if (value === null || value === undefined || value === "")
|
|
9068
|
-
return
|
|
9161
|
+
return styles3().dim(EMPTY_GLYPH);
|
|
9069
9162
|
return sanitize(String(value));
|
|
9070
9163
|
}
|
|
9071
9164
|
function timestamp2(value) {
|
|
9072
9165
|
if (!value)
|
|
9073
|
-
return
|
|
9166
|
+
return styles3().dim(EMPTY_GLYPH);
|
|
9074
9167
|
const date = new Date(value);
|
|
9075
9168
|
if (Number.isNaN(date.getTime()))
|
|
9076
9169
|
return sanitize(String(value));
|
|
@@ -9078,12 +9171,12 @@ function timestamp2(value) {
|
|
|
9078
9171
|
}
|
|
9079
9172
|
function bool2(value) {
|
|
9080
9173
|
if (value === null || value === undefined)
|
|
9081
|
-
return
|
|
9082
|
-
return value ?
|
|
9174
|
+
return styles3().dim(EMPTY_GLYPH);
|
|
9175
|
+
return value ? styles3().green("yes") : styles3().dim("no");
|
|
9083
9176
|
}
|
|
9084
9177
|
function bytes(value) {
|
|
9085
9178
|
if (value === null || value === undefined)
|
|
9086
|
-
return
|
|
9179
|
+
return styles3().dim(EMPTY_GLYPH);
|
|
9087
9180
|
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
9088
9181
|
let size = value;
|
|
9089
9182
|
let unit = 0;
|
|
@@ -9095,7 +9188,7 @@ function bytes(value) {
|
|
|
9095
9188
|
}
|
|
9096
9189
|
function duration(ms) {
|
|
9097
9190
|
if (ms === null || ms === undefined)
|
|
9098
|
-
return
|
|
9191
|
+
return styles3().dim(EMPTY_GLYPH);
|
|
9099
9192
|
if (ms < 1000)
|
|
9100
9193
|
return `${Math.round(ms)}ms`;
|
|
9101
9194
|
if (ms < 60000)
|
|
@@ -9126,11 +9219,11 @@ function clamp(value, width) {
|
|
|
9126
9219
|
}
|
|
9127
9220
|
function renderTable(rows, columns) {
|
|
9128
9221
|
if (rows.length === 0)
|
|
9129
|
-
return
|
|
9222
|
+
return styles3().dim("No results.");
|
|
9130
9223
|
const headers = columns.map((column) => sanitize(column.header));
|
|
9131
9224
|
const cells = rows.map((row) => columns.map((column) => clamp(oneLine(column.value(row)), MAX_CELL_WIDTH)));
|
|
9132
9225
|
const widths = columns.map((_column, index) => Math.max(visibleWidth(headers[index]), ...cells.map((line) => visibleWidth(line[index]))));
|
|
9133
|
-
const header = headers.map((label, index) =>
|
|
9226
|
+
const header = headers.map((label, index) => styles3().dim(pad(label.toUpperCase(), widths[index]))).join(" ").trimEnd();
|
|
9134
9227
|
const body = cells.map((line) => line.map((cell, index) => pad(cell, widths[index])).join(" ").trimEnd());
|
|
9135
9228
|
return [header, ...body].join(`
|
|
9136
9229
|
`);
|
|
@@ -9145,36 +9238,36 @@ function renderMachine(format, raw) {
|
|
|
9145
9238
|
function printList(format, rows, columns, raw = rows) {
|
|
9146
9239
|
const machine = renderMachine(format, raw);
|
|
9147
9240
|
if (machine !== null) {
|
|
9148
|
-
|
|
9241
|
+
printLine(machine);
|
|
9149
9242
|
return;
|
|
9150
9243
|
}
|
|
9151
9244
|
if (format === "text") {
|
|
9152
9245
|
for (const row of rows) {
|
|
9153
|
-
|
|
9246
|
+
printLine(columns.map((column) => oneLine(stripAnsi(column.value(row)))).join("\t"));
|
|
9154
9247
|
}
|
|
9155
9248
|
return;
|
|
9156
9249
|
}
|
|
9157
|
-
|
|
9250
|
+
printLine(renderTable(rows, columns));
|
|
9158
9251
|
}
|
|
9159
9252
|
function printDocument(format, raw) {
|
|
9160
|
-
|
|
9253
|
+
printLine(format === "yaml" ? renderMachine("yaml", raw) : JSON.stringify(raw, null, 2));
|
|
9161
9254
|
}
|
|
9162
9255
|
function printRecord(format, fields, raw) {
|
|
9163
9256
|
const machine = renderMachine(format, raw);
|
|
9164
9257
|
if (machine !== null) {
|
|
9165
|
-
|
|
9258
|
+
printLine(machine);
|
|
9166
9259
|
return;
|
|
9167
9260
|
}
|
|
9168
9261
|
const safeFields = fields.map(([label, value]) => [safeOneLine(label), value]);
|
|
9169
9262
|
if (format === "text") {
|
|
9170
9263
|
for (const [label, value] of safeFields) {
|
|
9171
|
-
|
|
9264
|
+
printLine(`${label} ${oneLine(stripAnsi(value))}`);
|
|
9172
9265
|
}
|
|
9173
9266
|
return;
|
|
9174
9267
|
}
|
|
9175
9268
|
const width = Math.max(...safeFields.map(([label]) => visibleWidth(label)));
|
|
9176
9269
|
for (const [label, value] of safeFields) {
|
|
9177
|
-
|
|
9270
|
+
printLine(`${styles3().dim(pad(`${label}:`, width + 1))} ${clamp(oneLine(value), MAX_RECORD_WIDTH)}`);
|
|
9178
9271
|
}
|
|
9179
9272
|
}
|
|
9180
9273
|
|
|
@@ -9289,7 +9382,7 @@ async function pollForKey(endpoint, auth, signal) {
|
|
|
9289
9382
|
consecutiveTransportFailures++;
|
|
9290
9383
|
if (!warnedAboutTransport && consecutiveTransportFailures >= TRANSPORT_FAILURES_BEFORE_WARNING) {
|
|
9291
9384
|
warnedAboutTransport = true;
|
|
9292
|
-
|
|
9385
|
+
writeStderr(`Still waiting: ${endpoint} is not answering the login poll (${cause.message}). Check the endpoint; retrying until you approve or the login times out.
|
|
9293
9386
|
`);
|
|
9294
9387
|
}
|
|
9295
9388
|
}
|
|
@@ -9420,8 +9513,8 @@ var V2_OPERATIONS = {
|
|
|
9420
9513
|
},
|
|
9421
9514
|
outputColumns: {
|
|
9422
9515
|
kind: "array",
|
|
9423
|
-
|
|
9424
|
-
describe: "Columns
|
|
9516
|
+
default: [],
|
|
9517
|
+
describe: "Columns to create for producer outputs. An entry naming a column the table already has attaches that column to the group instead of creating it (its `type` must match), and an output whose column already exists may omit its entry entirely — so `[]` attaches existing columns only."
|
|
9425
9518
|
},
|
|
9426
9519
|
autoRun: {
|
|
9427
9520
|
kind: "boolean",
|
|
@@ -9462,7 +9555,7 @@ var V2_OPERATIONS = {
|
|
|
9462
9555
|
query: {
|
|
9463
9556
|
dryRun: {
|
|
9464
9557
|
kind: "boolean",
|
|
9465
|
-
describe: "Validate and lint without
|
|
9558
|
+
describe: "Validate and lint without writing, auditing, or notifying collaborators. Returns the same validation, preparation warnings, lint findings, and ID-ownership conflicts (`409`) as a committed write. `needsRedeployment` describes the pre-write state. For semantic operations, `mintedBlockIds` is empty; `previewBlockIds` contains provisional IDs with a warning, since committing mints new IDs."
|
|
9466
9559
|
}
|
|
9467
9560
|
},
|
|
9468
9561
|
body: {
|
|
@@ -9507,7 +9600,7 @@ var V2_OPERATIONS = {
|
|
|
9507
9600
|
summary: "Delete Files",
|
|
9508
9601
|
body: {
|
|
9509
9602
|
workspaceId: { kind: "string", required: true, describe: "Workspace containing the files." },
|
|
9510
|
-
fileIds: { kind: "array", required: true, describe: "File identifiers to
|
|
9603
|
+
fileIds: { kind: "array", required: true, describe: "File identifiers to delete." }
|
|
9511
9604
|
}
|
|
9512
9605
|
},
|
|
9513
9606
|
bulkDeleteTables: {
|
|
@@ -9725,7 +9818,7 @@ var V2_OPERATIONS = {
|
|
|
9725
9818
|
rowId: { kind: "string", describe: "Row whose runs should be canceled for row scope." },
|
|
9726
9819
|
filter: {
|
|
9727
9820
|
kind: "unknown",
|
|
9728
|
-
describe: "
|
|
9821
|
+
describe: "One condition or a recursive `all`/`any` group, normalized to a grouped predicate. Limits: 100 members per group, 10 levels, and 500 nodes. The negating operators include nulls and absent cells, multi-select included; combine with `isNotNull` or `isNotEmpty` to exclude them. Pattern operators use `*` as the only wildcard; `%`, `_`, and backslash are literal. Select operators: single-select uses `eq`/`ne`/`in`/`nin`; multi-select uses `contains`/`ncontains`; option names resolve to IDs. Full operand rules are documented on `op`."
|
|
9729
9822
|
},
|
|
9730
9823
|
excludeRowIds: { kind: "array", describe: "Rows excluded from an all-scope cancellation." }
|
|
9731
9824
|
}
|
|
@@ -9756,6 +9849,11 @@ var V2_OPERATIONS = {
|
|
|
9756
9849
|
conversationId: {
|
|
9757
9850
|
kind: "string",
|
|
9758
9851
|
describe: "Conversation to continue; a new one starts when omitted."
|
|
9852
|
+
},
|
|
9853
|
+
effort: {
|
|
9854
|
+
kind: "enum",
|
|
9855
|
+
values: ["low", "medium", "high", "xhigh", "max"],
|
|
9856
|
+
describe: "Model effort for this turn; defaults to the deployment default (high)."
|
|
9759
9857
|
}
|
|
9760
9858
|
}
|
|
9761
9859
|
},
|
|
@@ -10318,7 +10416,7 @@ var V2_OPERATIONS = {
|
|
|
10318
10416
|
description: { kind: "string", describe: "Optional credential description." },
|
|
10319
10417
|
id: {
|
|
10320
10418
|
kind: "string",
|
|
10321
|
-
describe: "
|
|
10419
|
+
describe: "Optional client-generated credential ID. The server mints one when it is omitted, so no provider requires it. A `slack-custom-bot` credential may supply one so its Slack Request URL, which embeds the ID, can be configured before the credential exists; every other provider ignores it."
|
|
10322
10420
|
},
|
|
10323
10421
|
credentials: {
|
|
10324
10422
|
kind: "string",
|
|
@@ -10394,7 +10492,7 @@ var V2_OPERATIONS = {
|
|
|
10394
10492
|
rowIds: { kind: "array", describe: "Explicit row subset to run." },
|
|
10395
10493
|
filter: {
|
|
10396
10494
|
kind: "unknown",
|
|
10397
|
-
describe: "
|
|
10495
|
+
describe: "One condition or a recursive `all`/`any` group, normalized to a grouped predicate. Limits: 100 members per group, 10 levels, and 500 nodes. The negating operators include nulls and absent cells, multi-select included; combine with `isNotNull` or `isNotEmpty` to exclude them. Pattern operators use `*` as the only wildcard; `%`, `_`, and backslash are literal. Select operators: single-select uses `eq`/`ne`/`in`/`nin`; multi-select uses `contains`/`ncontains`; option names resolve to IDs. Full operand rules are documented on `op`."
|
|
10398
10496
|
},
|
|
10399
10497
|
excludeRowIds: { kind: "array", describe: "Rows excluded from a select-all run scope." },
|
|
10400
10498
|
limit: { kind: "object", describe: "Optional cap on eligible rows to run." }
|
|
@@ -10928,7 +11026,7 @@ var V2_OPERATIONS = {
|
|
|
10928
11026
|
workspaceId: { kind: "string", required: true, describe: "Unique workspace identifier." },
|
|
10929
11027
|
filter: {
|
|
10930
11028
|
kind: "unknown",
|
|
10931
|
-
describe: "
|
|
11029
|
+
describe: "One condition or a recursive `all`/`any` group, normalized to a grouped predicate. Limits: 100 members per group, 10 levels, and 500 nodes. The negating operators include nulls and absent cells, multi-select included; combine with `isNotNull` or `isNotEmpty` to exclude them. Pattern operators use `*` as the only wildcard; `%`, `_`, and backslash are literal. Select operators: single-select uses `eq`/`ne`/`in`/`nin`; multi-select uses `contains`/`ncontains`; option names resolve to IDs. Full operand rules are documented on `op`."
|
|
10932
11030
|
},
|
|
10933
11031
|
limit: { kind: "integer", describe: "Maximum matching rows to delete." },
|
|
10934
11032
|
rowIds: { kind: "array", describe: "Explicit row identifiers to delete." }
|
|
@@ -11177,7 +11275,7 @@ var V2_OPERATIONS = {
|
|
|
11177
11275
|
},
|
|
11178
11276
|
selectedOutputs: {
|
|
11179
11277
|
kind: "array",
|
|
11180
|
-
describe: "
|
|
11278
|
+
describe: "Select `<blockName>.<outputPath>` or `<childWorkflowId>.<blockName>.<outputPath>` using normalized block reference names. Child selectors cover every invocation. Synchronous results use selector strings verbatim as `blockOutputs` keys; streaming selections shape the envelope. Unknown block names or IDs return `400` with available blocks before execution. Unexecuted blocks and absent paths are omitted. Incompatible with `async`; select outputs from the finished run resource instead."
|
|
11181
11279
|
},
|
|
11182
11280
|
includeThinking: {
|
|
11183
11281
|
kind: "boolean",
|
|
@@ -11239,6 +11337,10 @@ var V2_OPERATIONS = {
|
|
|
11239
11337
|
includeReferences: {
|
|
11240
11338
|
kind: "boolean",
|
|
11241
11339
|
describe: "Include non-secret resource identifiers and source field occurrences for mapped imports."
|
|
11340
|
+
},
|
|
11341
|
+
includeWorkspaceBindings: {
|
|
11342
|
+
kind: "boolean",
|
|
11343
|
+
describe: "Whether to keep workspace-scoped bindings — table, knowledge base, document, folder, channel, and other resource selectors — in the exported state. Defaults to false, the sharing-safe export in which those ids are cleared because they resolve nowhere else. Send true for a same-workspace round trip so the re-imported workflow can run without re-selecting them. Credentials, passwords, and table sub-block values are cleared either way."
|
|
11242
11344
|
}
|
|
11243
11345
|
}
|
|
11244
11346
|
},
|
|
@@ -11487,6 +11589,10 @@ var V2_OPERATIONS = {
|
|
|
11487
11589
|
values: ["info", "error"],
|
|
11488
11590
|
describe: "Severity level to include."
|
|
11489
11591
|
},
|
|
11592
|
+
includeHandledErrors: {
|
|
11593
|
+
kind: "boolean",
|
|
11594
|
+
describe: "Whether runs with a handled block error are counted as `handledErrorRuns`, and whether `level=error` also selects them. Off by default: counting them scans each run’s stored trace."
|
|
11595
|
+
},
|
|
11490
11596
|
startDate: {
|
|
11491
11597
|
kind: "string",
|
|
11492
11598
|
describe: "Only include runs started at or after this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant."
|
|
@@ -11498,7 +11604,26 @@ var V2_OPERATIONS = {
|
|
|
11498
11604
|
segmentCount: {
|
|
11499
11605
|
kind: "integer",
|
|
11500
11606
|
default: 72,
|
|
11501
|
-
describe: "Number of time buckets,
|
|
11607
|
+
describe: "Number of equal time buckets to divide the window into, from 1 to 500. It is the ceiling on how many buckets a series carries: with `includeEmpty=true` exactly this many are returned, otherwise only the buckets holding at least one run. Buckets are never narrower than one minute, so on a short window the series extends past the end of the window rather than being compressed, and the trailing buckets are empty."
|
|
11608
|
+
},
|
|
11609
|
+
includeEmpty: {
|
|
11610
|
+
kind: "enum",
|
|
11611
|
+
values: [
|
|
11612
|
+
"true",
|
|
11613
|
+
"1",
|
|
11614
|
+
"yes",
|
|
11615
|
+
"on",
|
|
11616
|
+
"y",
|
|
11617
|
+
"enabled",
|
|
11618
|
+
"false",
|
|
11619
|
+
"0",
|
|
11620
|
+
"no",
|
|
11621
|
+
"off",
|
|
11622
|
+
"n",
|
|
11623
|
+
"disabled"
|
|
11624
|
+
],
|
|
11625
|
+
default: false,
|
|
11626
|
+
describe: "Whether buckets with no runs are included in every series. Off by default, so each series carries only the buckets that hold at least one run; set it to publish exactly `segmentCount` buckets per series, empty ones included. The listed spellings are the whole accepted vocabulary and are case-sensitive; any other value is rejected."
|
|
11502
11627
|
}
|
|
11503
11628
|
}
|
|
11504
11629
|
},
|
|
@@ -11556,7 +11681,7 @@ var V2_OPERATIONS = {
|
|
|
11556
11681
|
groupId: "Workflow or enrichment group to run."
|
|
11557
11682
|
},
|
|
11558
11683
|
responseMode: "json",
|
|
11559
|
-
summary: "Get
|
|
11684
|
+
summary: "Get Row Group Run",
|
|
11560
11685
|
query: {
|
|
11561
11686
|
workspaceId: { kind: "string", required: true, describe: "Workspace that owns the table." }
|
|
11562
11687
|
}
|
|
@@ -12166,7 +12291,11 @@ var V2_OPERATIONS = {
|
|
|
12166
12291
|
source: {
|
|
12167
12292
|
kind: "enum",
|
|
12168
12293
|
values: ["builtin", "custom"],
|
|
12169
|
-
describe: "Restrict to
|
|
12294
|
+
describe: "Restrict to shipped blocks or to this workspace’s deployed custom blocks."
|
|
12295
|
+
},
|
|
12296
|
+
includeSunset: {
|
|
12297
|
+
kind: "boolean",
|
|
12298
|
+
describe: "Include `legacy` and `deprecated` blocks. Off by default: a sunset block keeps executing where it is already placed, but it is not offered for new authoring. Each returned entry carries `sunset.replacedBy`, the block to build with instead."
|
|
12170
12299
|
},
|
|
12171
12300
|
sortBy: {
|
|
12172
12301
|
kind: "enum",
|
|
@@ -12243,6 +12372,21 @@ var V2_OPERATIONS = {
|
|
|
12243
12372
|
search: {
|
|
12244
12373
|
kind: "string",
|
|
12245
12374
|
describe: "Case-insensitive substring match against the connector name."
|
|
12375
|
+
},
|
|
12376
|
+
detail: {
|
|
12377
|
+
kind: "enum",
|
|
12378
|
+
values: ["summary", "full"],
|
|
12379
|
+
default: "summary",
|
|
12380
|
+
describe: "Projection of each item. `summary` (the default) carries the identifier, name, description, and auth mode; `full` adds the version, the complete auth settings, the `sourceConfig` field schema, incremental-sync support, and tag definitions."
|
|
12381
|
+
},
|
|
12382
|
+
limit: {
|
|
12383
|
+
kind: "integer",
|
|
12384
|
+
default: 25,
|
|
12385
|
+
describe: "Maximum connector types to return per page. Must be a whole number from 1 to 100. Defaults to 25."
|
|
12386
|
+
},
|
|
12387
|
+
cursor: {
|
|
12388
|
+
kind: "string",
|
|
12389
|
+
describe: "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor."
|
|
12246
12390
|
}
|
|
12247
12391
|
}
|
|
12248
12392
|
},
|
|
@@ -12844,6 +12988,10 @@ var V2_OPERATIONS = {
|
|
|
12844
12988
|
kind: "string",
|
|
12845
12989
|
describe: "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor."
|
|
12846
12990
|
},
|
|
12991
|
+
includeHandledErrors: {
|
|
12992
|
+
kind: "boolean",
|
|
12993
|
+
describe: "Whether `level=error` also selects runs that finished at `info` after a block error was recovered by an error path. Off by default: such a run succeeded, so it is an error only to a caller auditing error handling. Every row reports `hasHandledErrors` whether or not this is set. Job runs carry no block trace, so the flag never widens that branch."
|
|
12994
|
+
},
|
|
12847
12995
|
status: {
|
|
12848
12996
|
kind: "string",
|
|
12849
12997
|
describe: "Comma-separated execution statuses to include, from `pending` | `running` | `paused` | `redacting` | `completed` | `failed` | `cancelled`. An empty entry is rejected. ANDed with `level`, which reports severity rather than lifecycle."
|
|
@@ -13218,7 +13366,7 @@ var V2_OPERATIONS = {
|
|
|
13218
13366
|
pathParams: ["tableId"],
|
|
13219
13367
|
pathParamDocs: { tableId: "Unique table identifier." },
|
|
13220
13368
|
responseMode: "json",
|
|
13221
|
-
summary: "List
|
|
13369
|
+
summary: "List Run Dispatches",
|
|
13222
13370
|
query: {
|
|
13223
13371
|
workspaceId: { kind: "string", required: true, describe: "Workspace that owns the table." }
|
|
13224
13372
|
}
|
|
@@ -13731,8 +13879,8 @@ var V2_OPERATIONS = {
|
|
|
13731
13879
|
},
|
|
13732
13880
|
limit: {
|
|
13733
13881
|
kind: "integer",
|
|
13734
|
-
default:
|
|
13735
|
-
describe: "Maximum workspaces to return per page. Must be a whole number from 1 to 100. Defaults to
|
|
13882
|
+
default: 25,
|
|
13883
|
+
describe: "Maximum workspaces to return per page. Must be a whole number from 1 to 100. Defaults to 25."
|
|
13736
13884
|
},
|
|
13737
13885
|
cursor: {
|
|
13738
13886
|
kind: "string",
|
|
@@ -14071,7 +14219,9 @@ var V2_OPERATIONS = {
|
|
|
14071
14219
|
method: "GET",
|
|
14072
14220
|
path: "/api/v2/files/[fileId]/text",
|
|
14073
14221
|
pathParams: ["fileId"],
|
|
14074
|
-
pathParamDocs: {
|
|
14222
|
+
pathParamDocs: {
|
|
14223
|
+
fileId: "File identifier, or the file’s VFS path: `files/<folder>/<name>`, or `uploads/<name>` for a Chat upload."
|
|
14224
|
+
},
|
|
14075
14225
|
responseMode: "json",
|
|
14076
14226
|
summary: "Read File Text",
|
|
14077
14227
|
query: {
|
|
@@ -14102,7 +14252,7 @@ var V2_OPERATIONS = {
|
|
|
14102
14252
|
destinationPath: {
|
|
14103
14253
|
kind: "string",
|
|
14104
14254
|
required: true,
|
|
14105
|
-
describe: "
|
|
14255
|
+
describe: "Where the folder lands, with `mv` semantics. A path naming an existing folder receives the source as a child under its current name; `/` moves it to the workspace root under its current name; any other path becomes the folder’s new full path (a rename, a relocation, or both)."
|
|
14106
14256
|
}
|
|
14107
14257
|
}
|
|
14108
14258
|
},
|
|
@@ -14118,7 +14268,7 @@ var V2_OPERATIONS = {
|
|
|
14118
14268
|
destinationPath: {
|
|
14119
14269
|
kind: "string",
|
|
14120
14270
|
required: true,
|
|
14121
|
-
describe: "
|
|
14271
|
+
describe: "Where the folder lands, with `mv` semantics. A path naming an existing folder receives the source as a child under its current name; `/` moves it to the workspace root under its current name; any other path becomes the folder’s new full path (a rename, a relocation, or both)."
|
|
14122
14272
|
}
|
|
14123
14273
|
}
|
|
14124
14274
|
},
|
|
@@ -14134,7 +14284,7 @@ var V2_OPERATIONS = {
|
|
|
14134
14284
|
destinationPath: {
|
|
14135
14285
|
kind: "string",
|
|
14136
14286
|
required: true,
|
|
14137
|
-
describe: "
|
|
14287
|
+
describe: "Where the folder lands, with `mv` semantics. A path naming an existing folder receives the source as a child under its current name; `/` moves it to the workspace root under its current name; any other path becomes the folder’s new full path (a rename, a relocation, or both)."
|
|
14138
14288
|
}
|
|
14139
14289
|
}
|
|
14140
14290
|
},
|
|
@@ -14150,7 +14300,7 @@ var V2_OPERATIONS = {
|
|
|
14150
14300
|
destinationPath: {
|
|
14151
14301
|
kind: "string",
|
|
14152
14302
|
required: true,
|
|
14153
|
-
describe: "
|
|
14303
|
+
describe: "Where the folder lands, with `mv` semantics. A path naming an existing folder receives the source as a child under its current name; `/` moves it to the workspace root under its current name; any other path becomes the folder’s new full path (a rename, a relocation, or both)."
|
|
14154
14304
|
}
|
|
14155
14305
|
}
|
|
14156
14306
|
},
|
|
@@ -14230,7 +14380,7 @@ var V2_OPERATIONS = {
|
|
|
14230
14380
|
query: {
|
|
14231
14381
|
dryRun: {
|
|
14232
14382
|
kind: "boolean",
|
|
14233
|
-
describe: "Validate and lint without
|
|
14383
|
+
describe: "Validate and lint without writing, auditing, or notifying collaborators. Returns the same validation, preparation warnings, lint findings, and ID-ownership conflicts (`409`) as a committed write. `needsRedeployment` describes the pre-write state. For semantic operations, `mintedBlockIds` is empty; `previewBlockIds` contains provisional IDs with a warning, since committing mints new IDs."
|
|
14234
14384
|
}
|
|
14235
14385
|
},
|
|
14236
14386
|
body: {
|
|
@@ -14539,7 +14689,7 @@ var V2_OPERATIONS = {
|
|
|
14539
14689
|
q: { kind: "string", required: true, describe: "Case-insensitive cell substring to find." },
|
|
14540
14690
|
predicate: {
|
|
14541
14691
|
kind: "unknown",
|
|
14542
|
-
describe: "
|
|
14692
|
+
describe: "One condition or a recursive `all`/`any` group, normalized to a grouped predicate. Limits: 100 members per group, 10 levels, and 500 nodes. The negating operators include nulls and absent cells, multi-select included; combine with `isNotNull` or `isNotEmpty` to exclude them. Pattern operators use `*` as the only wildcard; `%`, `_`, and backslash are literal. Select operators: single-select uses `eq`/`ne`/`in`/`nin`; multi-select uses `contains`/`ncontains`; option names resolve to IDs. Full operand rules are documented on `op`."
|
|
14543
14693
|
},
|
|
14544
14694
|
sort: { kind: "array", describe: "Ordered table-row sort specification." }
|
|
14545
14695
|
}
|
|
@@ -15002,7 +15152,7 @@ var V2_OPERATIONS = {
|
|
|
15002
15152
|
filter: {
|
|
15003
15153
|
kind: "unknown",
|
|
15004
15154
|
required: true,
|
|
15005
|
-
describe: "
|
|
15155
|
+
describe: "One condition or a recursive `all`/`any` group, normalized to a grouped predicate. Limits: 100 members per group, 10 levels, and 500 nodes. The negating operators include nulls and absent cells, multi-select included; combine with `isNotNull` or `isNotEmpty` to exclude them. Pattern operators use `*` as the only wildcard; `%`, `_`, and backslash are literal. Select operators: single-select uses `eq`/`ne`/`in`/`nin`; multi-select uses `contains`/`ncontains`; option names resolve to IDs. Full operand rules are documented on `op`."
|
|
15006
15156
|
},
|
|
15007
15157
|
data: {
|
|
15008
15158
|
kind: "object",
|
|
@@ -15466,10 +15616,10 @@ async function chooseWorkspace(client) {
|
|
|
15466
15616
|
if (workspaces.length > MAX_INTERACTIVE_WORKSPACES) {
|
|
15467
15617
|
throw new SimApiError(`The active credential can access more than ${MAX_INTERACTIVE_WORKSPACES} workspaces, which is too many to show interactively. Pass --workspace <id> instead.`, 0);
|
|
15468
15618
|
}
|
|
15469
|
-
|
|
15619
|
+
printLine(`
|
|
15470
15620
|
Available workspaces:`);
|
|
15471
15621
|
for (const [index, workspace] of workspaces.entries()) {
|
|
15472
|
-
|
|
15622
|
+
printLine(` ${index + 1}) ${safeOneLine(workspace.name)} (${workspace.id})`);
|
|
15473
15623
|
}
|
|
15474
15624
|
const prompt = createInterface({ input: process.stdin, output: process.stderr });
|
|
15475
15625
|
try {
|
|
@@ -15504,10 +15654,10 @@ function addProfileCommand() {
|
|
|
15504
15654
|
workspace: normalizedWorkspaceId
|
|
15505
15655
|
});
|
|
15506
15656
|
});
|
|
15507
|
-
|
|
15508
|
-
|
|
15509
|
-
|
|
15510
|
-
|
|
15657
|
+
printLine(styles3().green(`✓ Added profile "${safeOneLine(profileName)}" in ${configPath()}`));
|
|
15658
|
+
printLine(` Workspace: ${safeOneLine(workspace.name)} (${workspace.id})`);
|
|
15659
|
+
printLine(` Authentication: ${safeOneLine(authProfile)}`);
|
|
15660
|
+
printLine(styles3().dim(` Try: sim --profile ${safeOneLine(profileName)} whoami`));
|
|
15511
15661
|
});
|
|
15512
15662
|
}
|
|
15513
15663
|
async function chooseLoginFlow(profile, options) {
|
|
@@ -15515,7 +15665,7 @@ async function chooseLoginFlow(profile, options) {
|
|
|
15515
15665
|
if (options.method === "api-key")
|
|
15516
15666
|
return "handoff";
|
|
15517
15667
|
if (options.method === undefined && isLikelyRemoteSession() && options.callbackPort === undefined) {
|
|
15518
|
-
|
|
15668
|
+
printLine(styles3().dim(`This looks like a remote session; using the pairing code to create a personal API key. To use OAuth, forward a port and pass --method oauth --callback-port <port>.
|
|
15519
15669
|
`));
|
|
15520
15670
|
return "handoff";
|
|
15521
15671
|
}
|
|
@@ -15527,7 +15677,7 @@ async function chooseLoginFlow(profile, options) {
|
|
|
15527
15677
|
if (options.method === "oauth") {
|
|
15528
15678
|
throw new SimApiError(`${profile.endpoint} does not offer OAuth sign-in. Enable OAuth on the server or explicitly choose sim login --method api-key.`, 0);
|
|
15529
15679
|
}
|
|
15530
|
-
|
|
15680
|
+
printLine(styles3().dim(`${profile.endpoint} does not offer OAuth sign-in; using the pairing code to create a personal API key.
|
|
15531
15681
|
`));
|
|
15532
15682
|
return "handoff";
|
|
15533
15683
|
}
|
|
@@ -15543,16 +15693,16 @@ function parseCallbackPort(value) {
|
|
|
15543
15693
|
return port;
|
|
15544
15694
|
}
|
|
15545
15695
|
async function loginWithOAuth(profile, options, callbackPort, expected) {
|
|
15546
|
-
|
|
15696
|
+
printLine(`Signing in to ${styles3().bold(profile.endpoint)} as profile ${styles3().bold(safeOneLine(profile.name))}`);
|
|
15547
15697
|
const tokens = await loginWithBrowser(profile.endpoint, {
|
|
15548
15698
|
scopes: options.readOnly ? OAUTH_SCOPES_READ_ONLY : OAUTH_SCOPES_FULL,
|
|
15549
15699
|
callbackPort,
|
|
15550
15700
|
onAuthorizeUrl: (url) => {
|
|
15551
|
-
|
|
15701
|
+
printLine(`
|
|
15552
15702
|
${url}`);
|
|
15553
15703
|
if (options.browser)
|
|
15554
15704
|
openBrowser(url);
|
|
15555
|
-
|
|
15705
|
+
printLine(styles3().dim(`
|
|
15556
15706
|
Waiting for you to approve in the browser…`));
|
|
15557
15707
|
}
|
|
15558
15708
|
});
|
|
@@ -15584,7 +15734,7 @@ Waiting for you to approve in the browser…`));
|
|
|
15584
15734
|
try {
|
|
15585
15735
|
writeCredentialsProfile(profile.name, null);
|
|
15586
15736
|
} catch {}
|
|
15587
|
-
|
|
15737
|
+
printLine(styles3().yellow(`Could not restore the previous profile safely (${safeOneLine(getErrorMessage(rollbackError))}). Its local login was cleared to avoid using it against the wrong endpoint. The new server login will still be revoked.`));
|
|
15588
15738
|
}
|
|
15589
15739
|
throw error;
|
|
15590
15740
|
}
|
|
@@ -15593,15 +15743,15 @@ Waiting for you to approve in the browser…`));
|
|
|
15593
15743
|
try {
|
|
15594
15744
|
await revokeToken(profile.endpoint, tokens.refreshToken);
|
|
15595
15745
|
} catch (revocationError) {
|
|
15596
|
-
|
|
15746
|
+
printLine(styles3().yellow(`Could not revoke the uncommitted login (${safeOneLine(getErrorMessage(revocationError))}). Revoke Sim CLI in Settings → General → Authorized apps.`));
|
|
15597
15747
|
}
|
|
15598
15748
|
throw error;
|
|
15599
15749
|
}
|
|
15600
|
-
|
|
15750
|
+
printLine(styles3().green(`
|
|
15601
15751
|
✓ Logged in. Login stored in ${credentialsPath()}`));
|
|
15602
|
-
|
|
15752
|
+
printLine(styles3().dim(grantsWriteAccess(tokens.scope) ? " Renews itself; revoke it any time in Settings → General → Authorized apps, or with: sim logout" : " Read-only login — commands that change anything will be refused."));
|
|
15603
15753
|
if (!profile.workspaceId) {
|
|
15604
|
-
|
|
15754
|
+
printLine(styles3().dim(" No default workspace. Set one with: sim configure --set-workspace <id>"));
|
|
15605
15755
|
}
|
|
15606
15756
|
}
|
|
15607
15757
|
function loginCommand() {
|
|
@@ -15619,7 +15769,7 @@ function loginCommand() {
|
|
|
15619
15769
|
if (storedCredential && !options.yes) {
|
|
15620
15770
|
const confirmed = await confirmProfileOverwrite(profile.name);
|
|
15621
15771
|
if (!confirmed) {
|
|
15622
|
-
|
|
15772
|
+
printLine(styles3().dim("Login cancelled; the existing profile was not changed."));
|
|
15623
15773
|
return;
|
|
15624
15774
|
}
|
|
15625
15775
|
}
|
|
@@ -15646,15 +15796,15 @@ function loginCommand() {
|
|
|
15646
15796
|
async function loginWithHandoff(profile, options, expected) {
|
|
15647
15797
|
const auth = createAuthRequest();
|
|
15648
15798
|
const url = buildApprovalUrl(profile.endpoint, auth, profile.workspaceId ?? undefined);
|
|
15649
|
-
|
|
15650
|
-
|
|
15651
|
-
Pairing code: ${
|
|
15652
|
-
|
|
15799
|
+
printLine(`Signing in to ${styles3().bold(profile.endpoint)} as profile ${styles3().bold(safeOneLine(profile.name))}`);
|
|
15800
|
+
printLine(`
|
|
15801
|
+
Pairing code: ${styles3().bold(auth.pairing)}`);
|
|
15802
|
+
printLine(styles3().dim(`Confirm this code matches what the browser shows before approving.
|
|
15653
15803
|
`));
|
|
15654
|
-
|
|
15804
|
+
printLine(url);
|
|
15655
15805
|
if (options.browser)
|
|
15656
15806
|
openBrowser(url);
|
|
15657
|
-
|
|
15807
|
+
printLine(styles3().dim(`
|
|
15658
15808
|
Waiting for approval…`));
|
|
15659
15809
|
const key = await pollForKey(profile.endpoint, auth);
|
|
15660
15810
|
try {
|
|
@@ -15683,24 +15833,24 @@ Waiting for approval…`));
|
|
|
15683
15833
|
try {
|
|
15684
15834
|
writeCredentialsProfile(profile.name, null);
|
|
15685
15835
|
} catch {}
|
|
15686
|
-
|
|
15836
|
+
printLine(styles3().yellow(`Could not restore the previous profile safely (${safeOneLine(getErrorMessage(rollbackError))}). Its local login was cleared to avoid using it against the wrong endpoint.`));
|
|
15687
15837
|
}
|
|
15688
15838
|
throw error;
|
|
15689
15839
|
}
|
|
15690
15840
|
});
|
|
15691
15841
|
} catch (error) {
|
|
15692
15842
|
const keyId = typeof key.id === "string" && key.id ? safeOneLine(key.id) : "unknown";
|
|
15693
|
-
|
|
15843
|
+
printLine(styles3().yellow(`API key ${keyId} was created but could not be stored safely. Revoke it in Settings → API keys.`));
|
|
15694
15844
|
throw error;
|
|
15695
15845
|
}
|
|
15696
|
-
|
|
15846
|
+
printLine(styles3().green(`
|
|
15697
15847
|
✓ Logged in. Key stored in ${credentialsPath()}`));
|
|
15698
15848
|
if (key.workspaceBound && key.workspaceId) {
|
|
15699
|
-
|
|
15849
|
+
printLine(styles3().dim(` Workspace-scoped key — it can only reach ${key.workspaceId}.`));
|
|
15700
15850
|
} else if (key.workspaceId) {
|
|
15701
|
-
|
|
15851
|
+
printLine(styles3().dim(` Personal key, defaulting to ${key.workspaceId}. Override per command with --workspace.`));
|
|
15702
15852
|
} else {
|
|
15703
|
-
|
|
15853
|
+
printLine(styles3().dim(" Personal key with no default workspace. Set one with: sim configure --set-workspace <id>"));
|
|
15704
15854
|
}
|
|
15705
15855
|
}
|
|
15706
15856
|
async function revokeStoredOAuth(credential) {
|
|
@@ -15718,9 +15868,9 @@ async function revokeStoredOAuth(credential) {
|
|
|
15718
15868
|
const endpoint = issuer.toString().replace(/\/$/, "");
|
|
15719
15869
|
displayEndpoint = safeOneLine(endpoint);
|
|
15720
15870
|
await revokeToken(endpoint, credential.refreshToken);
|
|
15721
|
-
|
|
15871
|
+
printLine(styles3().dim(" Signed out of Sim; every token from this login was revoked."));
|
|
15722
15872
|
} catch (error) {
|
|
15723
|
-
|
|
15873
|
+
printLine(styles3().yellow(` Could not revoke the login on ${displayEndpoint} (${safeOneLine(getErrorMessage(error))}). Revoke it in Settings → General → Authorized apps.`));
|
|
15724
15874
|
}
|
|
15725
15875
|
}
|
|
15726
15876
|
function logoutCommand() {
|
|
@@ -15739,12 +15889,12 @@ function logoutCommand() {
|
|
|
15739
15889
|
return { removed: deleteProfile(profileName), credential };
|
|
15740
15890
|
});
|
|
15741
15891
|
if (!removed.config && !removed.credentials) {
|
|
15742
|
-
|
|
15892
|
+
printLine(styles3().dim(`Nothing stored for profile "${safeOneLine(profileName)}".`));
|
|
15743
15893
|
return;
|
|
15744
15894
|
}
|
|
15745
|
-
|
|
15895
|
+
printLine(styles3().green(`✓ Removed profile "${safeOneLine(profileName)}".`));
|
|
15746
15896
|
if (credential?.kind === "api_key") {
|
|
15747
|
-
|
|
15897
|
+
printLine(styles3().dim(" The key itself is still active — revoke it in Settings → API keys."));
|
|
15748
15898
|
}
|
|
15749
15899
|
return;
|
|
15750
15900
|
}
|
|
@@ -15764,12 +15914,12 @@ function logoutCommand() {
|
|
|
15764
15914
|
return credential;
|
|
15765
15915
|
});
|
|
15766
15916
|
if (!credential) {
|
|
15767
|
-
|
|
15917
|
+
printLine(styles3().dim(`No stored login for profile "${safeOneLine(profileName)}".`));
|
|
15768
15918
|
return;
|
|
15769
15919
|
}
|
|
15770
|
-
|
|
15920
|
+
printLine(styles3().green(`✓ Removed the stored login for profile "${safeOneLine(profileName)}".`));
|
|
15771
15921
|
if (credential.kind === "api_key") {
|
|
15772
|
-
|
|
15922
|
+
printLine(styles3().dim(" The key itself is still active — revoke it in Settings → API keys."));
|
|
15773
15923
|
}
|
|
15774
15924
|
});
|
|
15775
15925
|
}
|
|
@@ -15831,18 +15981,18 @@ function presentVerification(verification) {
|
|
|
15831
15981
|
if (verification.status === "verified") {
|
|
15832
15982
|
const { name, memberCount } = verification.workspace;
|
|
15833
15983
|
const members = `${memberCount} ${memberCount === 1 ? "member" : "members"}`;
|
|
15834
|
-
return `${
|
|
15984
|
+
return `${styles3().green("✓")} ${safeOneLine(name)} · ${members}`;
|
|
15835
15985
|
}
|
|
15836
15986
|
const detail = safeOneLine(verification.detail);
|
|
15837
15987
|
switch (verification.status) {
|
|
15838
15988
|
case "rejected":
|
|
15839
|
-
return `${
|
|
15989
|
+
return `${styles3().red("✗")} ${detail}`;
|
|
15840
15990
|
case "unauthenticated":
|
|
15841
|
-
return
|
|
15991
|
+
return styles3().yellow(`not logged in — ${detail}`);
|
|
15842
15992
|
case "disabled":
|
|
15843
|
-
return
|
|
15993
|
+
return styles3().dim(detail);
|
|
15844
15994
|
default:
|
|
15845
|
-
return
|
|
15995
|
+
return styles3().yellow(`could not check — ${detail}`);
|
|
15846
15996
|
}
|
|
15847
15997
|
}
|
|
15848
15998
|
function whoamiCommand() {
|
|
@@ -15856,17 +16006,17 @@ function whoamiCommand() {
|
|
|
15856
16006
|
keyType: null,
|
|
15857
16007
|
detail: "not checked (--no-verify)"
|
|
15858
16008
|
};
|
|
15859
|
-
const annotate = (value, source) => source === "unset" ?
|
|
16009
|
+
const annotate = (value, source) => source === "unset" ? styles3().dim("not set") : `${value} ${styles3().dim(`(${source})`)}`;
|
|
15860
16010
|
printRecord(profile.output, [
|
|
15861
16011
|
["Profile", profile.name],
|
|
15862
16012
|
["Endpoint", annotate(profile.endpoint, sources.endpoint)],
|
|
15863
16013
|
[
|
|
15864
16014
|
"Login",
|
|
15865
|
-
authentication.authenticated ? annotate(profile.oauth ? "OAuth" : "API key", authentication.source) :
|
|
16015
|
+
authentication.authenticated ? annotate(profile.oauth ? "OAuth" : "API key", authentication.source) : styles3().yellow("not logged in")
|
|
15866
16016
|
],
|
|
15867
16017
|
[
|
|
15868
16018
|
"Key type",
|
|
15869
|
-
verification.keyType ??
|
|
16019
|
+
verification.keyType ?? styles3().dim(options.verify ? "unknown" : "not checked (--no-verify)")
|
|
15870
16020
|
],
|
|
15871
16021
|
["Workspace", annotate(profile.workspaceId ?? "", sources.workspaceId)],
|
|
15872
16022
|
["Output", annotate(profile.output, sources.output)],
|
|
@@ -15892,15 +16042,15 @@ function whoamiCommand() {
|
|
|
15892
16042
|
});
|
|
15893
16043
|
const exitCode = WHOAMI_EXIT_CODES[verification.status];
|
|
15894
16044
|
if (exitCode !== 0)
|
|
15895
|
-
|
|
16045
|
+
setSoftExitCode(exitCode);
|
|
15896
16046
|
});
|
|
15897
16047
|
}
|
|
15898
16048
|
var PROFILE_COLUMNS = [
|
|
15899
|
-
{ header: "", value: (row) => row.active ?
|
|
16049
|
+
{ header: "", value: (row) => row.active ? styles3().green("*") : " " },
|
|
15900
16050
|
{ header: "profile", value: (row) => safeOneLine(row.name) },
|
|
15901
16051
|
{ header: "key", value: (row) => row.error ? text(null) : row.hasKey ? "yes" : "no" },
|
|
15902
16052
|
{ header: "auth", value: (row) => row.authProfile ? safeOneLine(row.authProfile) : text(null) },
|
|
15903
|
-
{ header: "error", value: (row) => row.error ?
|
|
16053
|
+
{ header: "error", value: (row) => row.error ? styles3().red(safeOneLine(row.error)) : text(null) }
|
|
15904
16054
|
];
|
|
15905
16055
|
function buildProfileRow(name, active) {
|
|
15906
16056
|
try {
|
|
@@ -15947,7 +16097,7 @@ function profilesCommand() {
|
|
|
15947
16097
|
const rows = listProfiles().map((name) => buildProfileRow(name, name === activeName));
|
|
15948
16098
|
if (rows.length === 0) {
|
|
15949
16099
|
if (output === "table")
|
|
15950
|
-
|
|
16100
|
+
printLine(styles3().dim("No profiles yet. Run: sim login"));
|
|
15951
16101
|
else
|
|
15952
16102
|
printList(output, rows, PROFILE_COLUMNS);
|
|
15953
16103
|
return;
|
|
@@ -16020,11 +16170,11 @@ function configureCommand() {
|
|
|
16020
16170
|
if (Object.keys(updates).length === 0) {
|
|
16021
16171
|
const current = readConfigProfile(profile.name);
|
|
16022
16172
|
if (Object.keys(current).length === 0) {
|
|
16023
|
-
|
|
16173
|
+
printLine(styles3().dim(`No settings stored for profile "${profile.name}".`));
|
|
16024
16174
|
return;
|
|
16025
16175
|
}
|
|
16026
16176
|
for (const [key, value] of Object.entries(current)) {
|
|
16027
|
-
|
|
16177
|
+
printLine(`${styles3().dim(`${key}:`)} ${value}`);
|
|
16028
16178
|
}
|
|
16029
16179
|
return;
|
|
16030
16180
|
}
|
|
@@ -16049,10 +16199,10 @@ function configureCommand() {
|
|
|
16049
16199
|
return true;
|
|
16050
16200
|
});
|
|
16051
16201
|
if (!changed) {
|
|
16052
|
-
|
|
16202
|
+
printLine(styles3().dim(`No settings stored for profile "${profile.name}".`));
|
|
16053
16203
|
return;
|
|
16054
16204
|
}
|
|
16055
|
-
|
|
16205
|
+
printLine(styles3().green(`✓ Updated profile "${profile.name}" in ${configPath()}`));
|
|
16056
16206
|
});
|
|
16057
16207
|
}
|
|
16058
16208
|
|
|
@@ -16276,7 +16426,7 @@ var CLI_CONTRACT = {
|
|
|
16276
16426
|
},
|
|
16277
16427
|
deleteTableView: { confirm: "This deletes the saved view and its filters." },
|
|
16278
16428
|
deleteWorkflowGroup: {
|
|
16279
|
-
confirm: "This deletes the group
|
|
16429
|
+
confirm: "This deletes the group AND its output columns with all of their row data; the workflow it pointed at is untouched.",
|
|
16280
16430
|
fields: [
|
|
16281
16431
|
{ header: "id" },
|
|
16282
16432
|
{ header: "deleted", format: "bool" },
|
|
@@ -16396,7 +16546,7 @@ var CLI_CONTRACT = {
|
|
|
16396
16546
|
},
|
|
16397
16547
|
applyWorkflowOperations: {
|
|
16398
16548
|
command: "workflows operations apply",
|
|
16399
|
-
confirm: "This edits the draft graph
|
|
16549
|
+
confirm: "This edits the draft graph: the batch adds, edits, or deletes blocks and their edges as written.",
|
|
16400
16550
|
flags: {
|
|
16401
16551
|
operations: { json: true, describe: WORKFLOW_OPERATIONS_HELP },
|
|
16402
16552
|
setBlockEnabled: { json: true, describe: WORKFLOW_SET_BLOCK_ENABLED_HELP }
|
|
@@ -17248,7 +17398,7 @@ var CLI_CONTRACT = {
|
|
|
17248
17398
|
selectedOutputs: {
|
|
17249
17399
|
name: "select-output",
|
|
17250
17400
|
list: true,
|
|
17251
|
-
describe: "Return
|
|
17401
|
+
describe: "Return blockName.path values (e.g. agent_1.content), or childWorkflowId.blockName.path for a child workflow (applies to every invocation) — in blockOutputs on a sync run, or from the streamed result with --follow; missing paths are omitted. Not available with --async"
|
|
17252
17402
|
},
|
|
17253
17403
|
stream: { omit: true },
|
|
17254
17404
|
includeThinking: { omit: true },
|
|
@@ -17272,7 +17422,7 @@ var CLI_CONTRACT = {
|
|
|
17272
17422
|
selectedOutputs: {
|
|
17273
17423
|
name: "select-output",
|
|
17274
17424
|
list: true,
|
|
17275
|
-
describe: "Include
|
|
17425
|
+
describe: "Include blockName.path or blockId.path values (e.g. agent_1.content) in JSON or YAML output; names resolve against the workflow’s current blocks, and missing paths are omitted"
|
|
17276
17426
|
}
|
|
17277
17427
|
},
|
|
17278
17428
|
fields: [
|
|
@@ -17378,6 +17528,22 @@ function camel(flag) {
|
|
|
17378
17528
|
return flag.replace(/-([a-z])/g, (_match, character) => character.toUpperCase());
|
|
17379
17529
|
}
|
|
17380
17530
|
|
|
17531
|
+
// src/output/truncation.ts
|
|
17532
|
+
var TRUNCATION_FLAG = /^truncated$|^[A-Za-z0-9]+Truncated$/;
|
|
17533
|
+
var NEGATED_TRUNCATION_FLAG = /^(?:not|un|non|never)Truncated$|(?:Not|Un|Non|Never)Truncated$/;
|
|
17534
|
+
function isTruncationField(key) {
|
|
17535
|
+
return TRUNCATION_FLAG.test(key) && !NEGATED_TRUNCATION_FLAG.test(key);
|
|
17536
|
+
}
|
|
17537
|
+
function truncationMetadata(container) {
|
|
17538
|
+
if (!container || typeof container !== "object" || Array.isArray(container))
|
|
17539
|
+
return {};
|
|
17540
|
+
const metadata = {};
|
|
17541
|
+
for (const [key, value] of Object.entries(container))
|
|
17542
|
+
if (typeof value === "boolean" && isTruncationField(key))
|
|
17543
|
+
metadata[key] = value;
|
|
17544
|
+
return metadata;
|
|
17545
|
+
}
|
|
17546
|
+
|
|
17381
17547
|
// src/output/trace.ts
|
|
17382
17548
|
function traceSpan(value) {
|
|
17383
17549
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -17480,13 +17646,13 @@ function renderSpan(value, depth) {
|
|
|
17480
17646
|
function printTraceSpans(format, traceSpans) {
|
|
17481
17647
|
if (format === "json" || format === "yaml")
|
|
17482
17648
|
return;
|
|
17483
|
-
|
|
17484
|
-
|
|
17649
|
+
printLine("");
|
|
17650
|
+
printLine(format === "table" ? styles3().dim("trace:") : "trace:");
|
|
17485
17651
|
if (traceSpans.length === 0) {
|
|
17486
|
-
|
|
17652
|
+
printLine(styles3().dim(" No trace spans."));
|
|
17487
17653
|
return;
|
|
17488
17654
|
}
|
|
17489
|
-
|
|
17655
|
+
printLine(traceSpans.flatMap((span) => renderSpan(span, 0)).join(`
|
|
17490
17656
|
`));
|
|
17491
17657
|
}
|
|
17492
17658
|
|
|
@@ -17650,20 +17816,9 @@ function writePageNote(spec, envelope) {
|
|
|
17650
17816
|
const value = at(envelope, spec.pageNote.path);
|
|
17651
17817
|
if (value === undefined || value === null)
|
|
17652
17818
|
return;
|
|
17653
|
-
|
|
17819
|
+
writeStderr(styles3().dim(`${spec.pageNote.label}: ${String(value)}
|
|
17654
17820
|
`));
|
|
17655
17821
|
}
|
|
17656
|
-
var TRUNCATION_FLAG = /^truncated$|^[A-Za-z0-9]+Truncated$/;
|
|
17657
|
-
var NEGATED_TRUNCATION_FLAG = /^(?:not|un|non|never)Truncated$|(?:Not|Un|Non|Never)Truncated$/;
|
|
17658
|
-
function truncationMetadata(container) {
|
|
17659
|
-
if (!container || typeof container !== "object" || Array.isArray(container))
|
|
17660
|
-
return {};
|
|
17661
|
-
const metadata = {};
|
|
17662
|
-
for (const [key, value] of Object.entries(container))
|
|
17663
|
-
if (typeof value === "boolean" && TRUNCATION_FLAG.test(key) && !NEGATED_TRUNCATION_FLAG.test(key))
|
|
17664
|
-
metadata[key] = value;
|
|
17665
|
-
return metadata;
|
|
17666
|
-
}
|
|
17667
17822
|
function truncationFlags(container) {
|
|
17668
17823
|
return Object.entries(truncationMetadata(container)).filter(([, value]) => value).map(([key]) => key);
|
|
17669
17824
|
}
|
|
@@ -17689,7 +17844,7 @@ function clippedSubject(flag) {
|
|
|
17689
17844
|
}
|
|
17690
17845
|
function writeEnvelopeTruncation(envelope) {
|
|
17691
17846
|
for (const flag of responseTruncationFlags(envelope)) {
|
|
17692
|
-
|
|
17847
|
+
writeStderr(styles3().dim(`${spellOut(flag)}: the server clipped ${clippedSubject(flag)}, so the answer is incomplete
|
|
17693
17848
|
`));
|
|
17694
17849
|
}
|
|
17695
17850
|
}
|
|
@@ -17699,7 +17854,7 @@ function renderResult(operation, format, raw, spec, options = {}, envelope) {
|
|
|
17699
17854
|
printDocument(format, raw);
|
|
17700
17855
|
return;
|
|
17701
17856
|
}
|
|
17702
|
-
const data = unwrapResource(raw);
|
|
17857
|
+
const data = format === "json" || format === "yaml" ? raw : unwrapResource(raw);
|
|
17703
17858
|
if (spec.itemsPath) {
|
|
17704
17859
|
const items = at(data, spec.itemsPath);
|
|
17705
17860
|
if (!Array.isArray(items)) {
|
|
@@ -17821,6 +17976,87 @@ function attachWorkspaceOperationWait(operations) {
|
|
|
17821
17976
|
|
|
17822
17977
|
// src/runtime/request.ts
|
|
17823
17978
|
import { closeSync as closeSync2, existsSync as existsSync2, fstatSync as fstatSync2, openSync as openSync2, readSync as readSync2 } from "node:fs";
|
|
17979
|
+
|
|
17980
|
+
// src/transfer/local-file.ts
|
|
17981
|
+
import { constants as constants2 } from "node:fs";
|
|
17982
|
+
import { access, stat } from "node:fs/promises";
|
|
17983
|
+
import { basename } from "node:path";
|
|
17984
|
+
function embeddedFileKey(path) {
|
|
17985
|
+
return path.startsWith("@") ? path.slice(1) : path;
|
|
17986
|
+
}
|
|
17987
|
+
async function embeddedFileContent(embedded, path) {
|
|
17988
|
+
const key = embeddedFileKey(path);
|
|
17989
|
+
embedded.identity.signal?.throwIfAborted();
|
|
17990
|
+
if (!embedded.readFile)
|
|
17991
|
+
throw new SimApiError("This invocation has no machine to read from", 0);
|
|
17992
|
+
const content = await embedded.readFile(key);
|
|
17993
|
+
embedded.identity.signal?.throwIfAborted();
|
|
17994
|
+
return typeof content === "string" ? content : new Uint8Array(content);
|
|
17995
|
+
}
|
|
17996
|
+
var CONTENT_TYPES = {
|
|
17997
|
+
css: "text/css",
|
|
17998
|
+
csv: "text/csv",
|
|
17999
|
+
doc: "application/msword",
|
|
18000
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
18001
|
+
gif: "image/gif",
|
|
18002
|
+
html: "text/html",
|
|
18003
|
+
htm: "text/html",
|
|
18004
|
+
jpeg: "image/jpeg",
|
|
18005
|
+
jpg: "image/jpeg",
|
|
18006
|
+
js: "text/javascript",
|
|
18007
|
+
json: "application/json",
|
|
18008
|
+
jsonl: "application/jsonl",
|
|
18009
|
+
md: "text/markdown",
|
|
18010
|
+
pdf: "application/pdf",
|
|
18011
|
+
ppt: "application/vnd.ms-powerpoint",
|
|
18012
|
+
pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
18013
|
+
png: "image/png",
|
|
18014
|
+
svg: "image/svg+xml",
|
|
18015
|
+
txt: "text/plain",
|
|
18016
|
+
webp: "image/webp",
|
|
18017
|
+
yaml: "application/yaml",
|
|
18018
|
+
yml: "application/yaml",
|
|
18019
|
+
xls: "application/vnd.ms-excel",
|
|
18020
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
18021
|
+
zip: "application/zip"
|
|
18022
|
+
};
|
|
18023
|
+
function contentTypeFor(name) {
|
|
18024
|
+
const dot = name.lastIndexOf(".");
|
|
18025
|
+
const extension = dot === -1 ? "" : name.slice(dot + 1).toLowerCase();
|
|
18026
|
+
return CONTENT_TYPES[extension] ?? "application/octet-stream";
|
|
18027
|
+
}
|
|
18028
|
+
async function localFile(path, override) {
|
|
18029
|
+
const embedded = embedStore.getStore();
|
|
18030
|
+
if (embedded) {
|
|
18031
|
+
embedded.identity.signal?.throwIfAborted();
|
|
18032
|
+
if (!embedded.openFile)
|
|
18033
|
+
throw new SimApiError("This invocation has no machine to read from", 0);
|
|
18034
|
+
const { size } = await embedded.openFile(embeddedFileKey(path));
|
|
18035
|
+
embedded.identity.signal?.throwIfAborted();
|
|
18036
|
+
if (!Number.isSafeInteger(size) || size < 0)
|
|
18037
|
+
throw new SimApiError("Invalid file size", 0);
|
|
18038
|
+
if (size === 0)
|
|
18039
|
+
throw new SimApiError(`${path} is empty`, 0);
|
|
18040
|
+
return { name: override ?? basename(embeddedFileKey(path)), size };
|
|
18041
|
+
}
|
|
18042
|
+
let size;
|
|
18043
|
+
try {
|
|
18044
|
+
const stats = await stat(path);
|
|
18045
|
+
if (!stats.isFile())
|
|
18046
|
+
throw new SimApiError(`${path} is not a regular file`, 0);
|
|
18047
|
+
await access(path, constants2.R_OK);
|
|
18048
|
+
size = stats.size;
|
|
18049
|
+
} catch (error) {
|
|
18050
|
+
if (error instanceof SimApiError)
|
|
18051
|
+
throw error;
|
|
18052
|
+
throw new SimApiError(`Cannot read ${path}: ${error.message}`, 0);
|
|
18053
|
+
}
|
|
18054
|
+
if (size === 0)
|
|
18055
|
+
throw new SimApiError(`${path} is empty`, 0);
|
|
18056
|
+
return { name: override ?? basename(path), size };
|
|
18057
|
+
}
|
|
18058
|
+
|
|
18059
|
+
// src/runtime/request.ts
|
|
17824
18060
|
var PROFILE_INJECTED_FIELD = "workspaceId";
|
|
17825
18061
|
function isProfileWorkspacePath(commandSpec, param) {
|
|
17826
18062
|
return commandSpec.profileWorkspacePath === true && param === PROFILE_INJECTED_FIELD;
|
|
@@ -17907,13 +18143,25 @@ function readArgumentDescriptor(descriptor) {
|
|
|
17907
18143
|
function literalAtHint(error, path) {
|
|
17908
18144
|
return error?.code === "ENOENT" ? `. To pass the literal value @${path}, write @@${path}` : "";
|
|
17909
18145
|
}
|
|
17910
|
-
function readArgumentSource(raw, flagName) {
|
|
18146
|
+
async function readArgumentSource(raw, flagName) {
|
|
17911
18147
|
if (Buffer.byteLength(raw, "utf8") > MAX_JSON_ARGUMENT_BYTES)
|
|
17912
18148
|
throw new SimApiError(`--${flagName} exceeds the 10 MiB JSON input limit`, 0);
|
|
17913
18149
|
if (raw.startsWith("@@"))
|
|
17914
18150
|
return { text: raw.slice(1), from: "" };
|
|
17915
18151
|
if (!raw.startsWith("@"))
|
|
17916
18152
|
return { text: raw, from: "" };
|
|
18153
|
+
const embedded = embedStore.getStore();
|
|
18154
|
+
if (embedded) {
|
|
18155
|
+
if (raw === "@-")
|
|
18156
|
+
throw new SimApiError(`--${flagName}: this invocation has no stdin; use @path or an inline value`, 0);
|
|
18157
|
+
const content = await embeddedFileContent(embedded, raw);
|
|
18158
|
+
if (Buffer.byteLength(content) > MAX_JSON_ARGUMENT_BYTES)
|
|
18159
|
+
throw new SimApiError(`--${flagName} exceeds the 10 MiB JSON input limit`, 0);
|
|
18160
|
+
return {
|
|
18161
|
+
text: typeof content === "string" ? content : new TextDecoder("utf-8", { fatal: true }).decode(content),
|
|
18162
|
+
from: " (read from your machine)"
|
|
18163
|
+
};
|
|
18164
|
+
}
|
|
17917
18165
|
const path = raw.slice(1);
|
|
17918
18166
|
if (path === "-") {
|
|
17919
18167
|
if (process.stdin.isTTY) {
|
|
@@ -17942,15 +18190,18 @@ function isManifestNoise(line) {
|
|
|
17942
18190
|
const trimmed = line.trim();
|
|
17943
18191
|
return trimmed === "" || trimmed.startsWith("#");
|
|
17944
18192
|
}
|
|
17945
|
-
function readListValues(raw, flagName, manifest = false) {
|
|
18193
|
+
async function readListValues(raw, flagName, manifest = false) {
|
|
17946
18194
|
const arguments_ = Array.isArray(raw) ? raw : [raw];
|
|
17947
|
-
const values =
|
|
18195
|
+
const values = [];
|
|
18196
|
+
for (const argument of arguments_) {
|
|
17948
18197
|
if (typeof argument !== "string") {
|
|
17949
18198
|
throw new SimApiError(`--${flagName} values must be strings`, 0);
|
|
17950
18199
|
}
|
|
17951
|
-
if (!argument.startsWith("@"))
|
|
17952
|
-
|
|
17953
|
-
|
|
18200
|
+
if (!argument.startsWith("@")) {
|
|
18201
|
+
values.push(argument);
|
|
18202
|
+
continue;
|
|
18203
|
+
}
|
|
18204
|
+
const source = await readArgumentSource(argument, flagName);
|
|
17954
18205
|
const lines = source.text.split(/\r?\n/);
|
|
17955
18206
|
if (lines.at(-1) === "")
|
|
17956
18207
|
lines.pop();
|
|
@@ -17958,14 +18209,14 @@ function readListValues(raw, flagName, manifest = false) {
|
|
|
17958
18209
|
if (kept.length === 0) {
|
|
17959
18210
|
throw new SimApiError(`--${flagName}${source.from} contains no values`, 0);
|
|
17960
18211
|
}
|
|
17961
|
-
|
|
18212
|
+
values.push(...kept.map((line, index) => {
|
|
17962
18213
|
const value = line.trim();
|
|
17963
18214
|
if (!value) {
|
|
17964
18215
|
throw new SimApiError(`--${flagName}${source.from} has an empty value on line ${index + 1}`, 0);
|
|
17965
18216
|
}
|
|
17966
18217
|
return value;
|
|
17967
|
-
});
|
|
17968
|
-
}
|
|
18218
|
+
}));
|
|
18219
|
+
}
|
|
17969
18220
|
return values.map((value) => {
|
|
17970
18221
|
const trimmed = value.trim();
|
|
17971
18222
|
if (!trimmed)
|
|
@@ -17997,13 +18248,13 @@ var FRACTIONAL_DIGITS = /\.\d*[1-9]/;
|
|
|
17997
18248
|
function pathHint(raw) {
|
|
17998
18249
|
if (raw.startsWith("@") || /^\s*[[{"\-\d]|^\s*(true|false|null)/.test(raw))
|
|
17999
18250
|
return "";
|
|
18000
|
-
return existsSync2(raw) ? `. ${raw} is a file — pass it as @${raw}` : ". To read a file, pass @path (or @- for stdin)";
|
|
18251
|
+
return !embedStore.getStore() && existsSync2(raw) ? `. ${raw} is a file — pass it as @${raw}` : ". To read a file, pass @path (or @- for stdin)";
|
|
18001
18252
|
}
|
|
18002
|
-
function coerce(raw, field, flag, flagName) {
|
|
18253
|
+
async function coerce(raw, field, flag, flagName) {
|
|
18003
18254
|
if (raw === undefined)
|
|
18004
18255
|
return;
|
|
18005
18256
|
if (flag.list) {
|
|
18006
|
-
const values = readListValues(raw, flagName, flag.manifest === true).map((value) => flag.folderPath ? encodeFolderPath(value) : value);
|
|
18257
|
+
const values = (await readListValues(raw, flagName, flag.manifest === true)).map((value) => flag.folderPath ? encodeFolderPath(value) : value);
|
|
18007
18258
|
return field.kind === "string" ? values.join(",") : values;
|
|
18008
18259
|
}
|
|
18009
18260
|
if (flag.rowCap)
|
|
@@ -18011,7 +18262,7 @@ function coerce(raw, field, flag, flagName) {
|
|
|
18011
18262
|
if (takesJson(field, flag)) {
|
|
18012
18263
|
if (typeof raw !== "string")
|
|
18013
18264
|
return raw;
|
|
18014
|
-
const source = readArgumentSource(raw, flagName);
|
|
18265
|
+
const source = await readArgumentSource(raw, flagName);
|
|
18015
18266
|
try {
|
|
18016
18267
|
return JSON.parse(source.text);
|
|
18017
18268
|
} catch (error) {
|
|
@@ -18053,7 +18304,7 @@ function boundedRequest(request) {
|
|
|
18053
18304
|
throw new SimApiError("Aggregate JSON request body exceeds 10 MiB", 0);
|
|
18054
18305
|
return request;
|
|
18055
18306
|
}
|
|
18056
|
-
function buildRequest(operation, positional, flags, workspaceId) {
|
|
18307
|
+
async function buildRequest(operation, positional, flags, workspaceId) {
|
|
18057
18308
|
const commandSpec = CLI_CONTRACT[operation] ?? {};
|
|
18058
18309
|
const spec = V2_OPERATIONS[operation];
|
|
18059
18310
|
let path = spec.path;
|
|
@@ -18091,7 +18342,7 @@ function buildRequest(operation, positional, flags, workspaceId) {
|
|
|
18091
18342
|
if ((slot === "query" || NUMERIC_KINDS.has(descriptor.kind)) && typeof raw === "string" && raw.trim() === "" && !(field === "limit" && paginatedLimit)) {
|
|
18092
18343
|
throw new SimApiError(`--${flagName} cannot be empty`, 0);
|
|
18093
18344
|
}
|
|
18094
|
-
const value = coerce(raw ?? undefined, descriptor, flag, flagName);
|
|
18345
|
+
const value = await coerce(raw ?? undefined, descriptor, flag, flagName);
|
|
18095
18346
|
if (field === "limit" && !paginatedLimit && NUMERIC_KINDS.has(descriptor.kind) && typeof value === "number" && value < 1) {
|
|
18096
18347
|
throw new SimApiError(`--${flagName} must be 1 or more`, 0);
|
|
18097
18348
|
}
|
|
@@ -18121,7 +18372,7 @@ function buildRequest(operation, positional, flags, workspaceId) {
|
|
|
18121
18372
|
const raw = flags[camel(variant.name)];
|
|
18122
18373
|
if (typeof raw !== "string")
|
|
18123
18374
|
throw new SimApiError(`--${variant.name} is required`, 0);
|
|
18124
|
-
const parsed = coerce(raw, { kind: variant.kind }, { json: true }, variant.name);
|
|
18375
|
+
const parsed = await coerce(raw, { kind: variant.kind }, { json: true }, variant.name);
|
|
18125
18376
|
if (variant.kind === "object" && (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) || variant.kind === "array" && !Array.isArray(parsed)) {
|
|
18126
18377
|
throw new SimApiError(`--${variant.name} must be a JSON ${variant.kind}`, 0);
|
|
18127
18378
|
}
|
|
@@ -18135,7 +18386,7 @@ function buildRequest(operation, positional, flags, workspaceId) {
|
|
|
18135
18386
|
const raw = flags.body;
|
|
18136
18387
|
if (typeof raw !== "string")
|
|
18137
18388
|
throw new SimApiError("--body is required", 0);
|
|
18138
|
-
const parsed = coerce(raw, { kind: "object" }, { json: true }, "body");
|
|
18389
|
+
const parsed = await coerce(raw, { kind: "object" }, { json: true }, "body");
|
|
18139
18390
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
18140
18391
|
throw new SimApiError("--body must be a JSON object", 0);
|
|
18141
18392
|
}
|
|
@@ -18298,7 +18549,7 @@ function warn(kind, from, to) {
|
|
|
18298
18549
|
if (warned.has(key))
|
|
18299
18550
|
return;
|
|
18300
18551
|
warned.add(key);
|
|
18301
|
-
|
|
18552
|
+
writeStderr(`warning: ${kind} "${from}" has been renamed to "${to}". The old name still works.
|
|
18302
18553
|
`);
|
|
18303
18554
|
}
|
|
18304
18555
|
function warnRenamedCommand(from, to) {
|
|
@@ -18406,6 +18657,22 @@ function countOf(value) {
|
|
|
18406
18657
|
function lengthOf(value) {
|
|
18407
18658
|
return Array.isArray(value) ? value.length : 0;
|
|
18408
18659
|
}
|
|
18660
|
+
var RESULT_NOTES = {
|
|
18661
|
+
replaceWorkflowChatDeployment: (payload, body) => {
|
|
18662
|
+
const authType = payload.authType ?? body?.authType ?? "public";
|
|
18663
|
+
return authType === "public" ? "note: auth type is public — anyone with the link can chat; pass --auth-type password|email to restrict it." : null;
|
|
18664
|
+
}
|
|
18665
|
+
};
|
|
18666
|
+
function writeResultNote(operation, payload, body) {
|
|
18667
|
+
const note = RESULT_NOTES[operation];
|
|
18668
|
+
if (!note)
|
|
18669
|
+
return;
|
|
18670
|
+
const record = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
18671
|
+
const message = note(record, body);
|
|
18672
|
+
if (message)
|
|
18673
|
+
writeStderr(styles3().dim(`${message}
|
|
18674
|
+
`));
|
|
18675
|
+
}
|
|
18409
18676
|
function bulkFailureMessage(operation, payload, body) {
|
|
18410
18677
|
const check = BULK_OUTCOME_CHECKS[operation];
|
|
18411
18678
|
if (!check)
|
|
@@ -18495,7 +18762,7 @@ async function executeOperation(operation, commandSpec, operationSpec, invocatio
|
|
|
18495
18762
|
const paging = cursorSlot(operationSpec);
|
|
18496
18763
|
const pagedLimit = paging ? readPagedLimit(requestFlags.limit, operation) : 0;
|
|
18497
18764
|
const requestWorkspaceId = needsWorkspace ? client.requireWorkspace() : profile.workspaceId;
|
|
18498
|
-
const request = buildRequest(operation, positional, requestFlags, requestWorkspaceId);
|
|
18765
|
+
const request = await buildRequest(operation, positional, requestFlags, requestWorkspaceId);
|
|
18499
18766
|
if (commandSpec.workspaceOperation) {
|
|
18500
18767
|
if (!WORKSPACE_OPERATION_KINDS[operation])
|
|
18501
18768
|
throw new SimApiError("This command has no workspace operation identity configured", 0);
|
|
@@ -18585,6 +18852,7 @@ async function executeOperation(operation, commandSpec, operationSpec, invocatio
|
|
|
18585
18852
|
return;
|
|
18586
18853
|
}
|
|
18587
18854
|
renderResult(operation, profile.output, payload, commandSpec, { expandedTrace: requestFlags.trace === true }, result);
|
|
18855
|
+
writeResultNote(operation, payload, request.body);
|
|
18588
18856
|
const failure = runFailureMessage(operation, payload) ?? bulkFailureMessage(operation, payload, request.body);
|
|
18589
18857
|
if (failure)
|
|
18590
18858
|
throw new SimApiError(failure, 0);
|
|
@@ -18992,8 +19260,8 @@ function serviceAccountProvider(providers, providerId) {
|
|
|
18992
19260
|
}
|
|
18993
19261
|
return provider;
|
|
18994
19262
|
}
|
|
18995
|
-
function credentialValues(provider, raw) {
|
|
18996
|
-
const parsed = coerce(raw, { kind: "object" }, { json: true }, "credentials");
|
|
19263
|
+
async function credentialValues(provider, raw) {
|
|
19264
|
+
const parsed = await coerce(raw, { kind: "object" }, { json: true }, "credentials");
|
|
18997
19265
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
18998
19266
|
throw new SimApiError("--credentials must be a JSON object", 0);
|
|
18999
19267
|
}
|
|
@@ -19030,7 +19298,7 @@ async function createServiceAccount(command, providerId, options) {
|
|
|
19030
19298
|
if (provider.requiresClientGeneratedCredentialId && !options.id) {
|
|
19031
19299
|
throw new SimApiError(`--id is required for ${providerId}.`, 0);
|
|
19032
19300
|
}
|
|
19033
|
-
const credentialFields = credentialValues(provider, options.credentials);
|
|
19301
|
+
const credentialFields = await credentialValues(provider, options.credentials);
|
|
19034
19302
|
const operation = V2_OPERATIONS.createServiceAccountCredential;
|
|
19035
19303
|
const response = await client.request(operation.path, {
|
|
19036
19304
|
method: operation.method,
|
|
@@ -19198,19 +19466,19 @@ Examples:
|
|
|
19198
19466
|
const endStreamedLine = () => {
|
|
19199
19467
|
if (streamed.length > 0 && !streamed.endsWith(`
|
|
19200
19468
|
`)) {
|
|
19201
|
-
|
|
19469
|
+
writeStdout(`
|
|
19202
19470
|
`);
|
|
19203
19471
|
streamed += `
|
|
19204
19472
|
`;
|
|
19205
19473
|
}
|
|
19206
19474
|
};
|
|
19207
|
-
const restorePipeHandling = streaming ? ignoreBrokenPipe(process.stdout) : undefined;
|
|
19475
|
+
const restorePipeHandling = streaming && !embedStore.getStore() ? ignoreBrokenPipe(process.stdout) : undefined;
|
|
19208
19476
|
try {
|
|
19209
19477
|
const result = await readChatStream(response, (content) => {
|
|
19210
19478
|
if (!streaming)
|
|
19211
19479
|
return;
|
|
19212
19480
|
streamed += content;
|
|
19213
|
-
|
|
19481
|
+
writeStdout(content);
|
|
19214
19482
|
});
|
|
19215
19483
|
if (!streaming) {
|
|
19216
19484
|
printProtocolResult(profile.output, result);
|
|
@@ -19218,11 +19486,11 @@ Examples:
|
|
|
19218
19486
|
}
|
|
19219
19487
|
const content = sanitize(result.content ?? "");
|
|
19220
19488
|
if (content.startsWith(streamed) && content.length > streamed.length) {
|
|
19221
|
-
|
|
19489
|
+
writeStdout(content.slice(streamed.length));
|
|
19222
19490
|
streamed = content;
|
|
19223
19491
|
}
|
|
19224
19492
|
endStreamedLine();
|
|
19225
|
-
|
|
19493
|
+
writeStderr(`${styles3().dim(`conversation: ${result.conversationId}`)}
|
|
19226
19494
|
`);
|
|
19227
19495
|
} catch (error) {
|
|
19228
19496
|
endStreamedLine();
|
|
@@ -19353,19 +19621,38 @@ async function saveStagedFile(body, target, force) {
|
|
|
19353
19621
|
}
|
|
19354
19622
|
}
|
|
19355
19623
|
async function saveToFile(body, target, force) {
|
|
19624
|
+
const embedded = embedStore.getStore();
|
|
19625
|
+
if (embedded) {
|
|
19626
|
+
try {
|
|
19627
|
+
embedded.identity.signal?.throwIfAborted();
|
|
19628
|
+
if (!embedded.writeFile) {
|
|
19629
|
+
throw new SimApiError(`--output-file cannot save ${target} here: this surface has no machine to write to. Read the file instead, or use a client with filesystem access to download it.`, 0);
|
|
19630
|
+
}
|
|
19631
|
+
await embedded.writeFile(target, body, { overwrite: force });
|
|
19632
|
+
embedded.identity.signal?.throwIfAborted();
|
|
19633
|
+
} finally {
|
|
19634
|
+
await body.cancel().catch(() => {});
|
|
19635
|
+
}
|
|
19636
|
+
return;
|
|
19637
|
+
}
|
|
19356
19638
|
return saveStagedFile(body, target, force);
|
|
19357
19639
|
}
|
|
19358
|
-
async function streamToStdout(body, output
|
|
19640
|
+
async function streamToStdout(body, output) {
|
|
19359
19641
|
const reader = body.getReader();
|
|
19360
19642
|
try {
|
|
19361
19643
|
while (true) {
|
|
19362
19644
|
const { done, value } = await reader.read();
|
|
19363
19645
|
if (done)
|
|
19364
19646
|
return;
|
|
19365
|
-
if (
|
|
19366
|
-
|
|
19647
|
+
if (output) {
|
|
19648
|
+
if (!output.write(value))
|
|
19649
|
+
await once2(output, "drain");
|
|
19650
|
+
} else if (!writeStdout(value)) {
|
|
19651
|
+
await once2(process.stdout, "drain");
|
|
19652
|
+
}
|
|
19367
19653
|
}
|
|
19368
19654
|
} finally {
|
|
19655
|
+
await reader.cancel().catch(() => {});
|
|
19369
19656
|
reader.releaseLock();
|
|
19370
19657
|
}
|
|
19371
19658
|
}
|
|
@@ -19403,9 +19690,10 @@ function attachFileGet(files) {
|
|
|
19403
19690
|
}
|
|
19404
19691
|
if (options.outputFile === undefined || options.outputFile === "-") {
|
|
19405
19692
|
const contentType = response.headers.get("content-type");
|
|
19406
|
-
|
|
19693
|
+
const embedded = embedStore.getStore();
|
|
19694
|
+
if ((embedded || process.stdout.isTTY) && !isTerminalSafeContentType(contentType)) {
|
|
19407
19695
|
await response.body.cancel();
|
|
19408
|
-
throw new SimApiError(`Refusing to write ${contentType ?? "unknown content"} to an interactive terminal. Use --output-file <path> or pipe stdout.`, 0);
|
|
19696
|
+
throw new SimApiError(embedded ? `Refusing to put ${contentType ?? "unknown content"} in a text result. Use --output-file <path>.` : `Refusing to write ${contentType ?? "unknown content"} to an interactive terminal. Use --output-file <path> or pipe stdout.`, 0);
|
|
19409
19697
|
}
|
|
19410
19698
|
await streamToStdout(response.body);
|
|
19411
19699
|
return;
|
|
@@ -19420,74 +19708,120 @@ function attachFileGet(files) {
|
|
|
19420
19708
|
});
|
|
19421
19709
|
}
|
|
19422
19710
|
|
|
19423
|
-
// src/transfer/
|
|
19424
|
-
import {
|
|
19425
|
-
|
|
19426
|
-
|
|
19427
|
-
|
|
19428
|
-
|
|
19429
|
-
|
|
19430
|
-
|
|
19431
|
-
|
|
19432
|
-
|
|
19433
|
-
|
|
19434
|
-
|
|
19435
|
-
|
|
19436
|
-
|
|
19437
|
-
|
|
19438
|
-
|
|
19439
|
-
|
|
19440
|
-
|
|
19441
|
-
|
|
19442
|
-
|
|
19443
|
-
|
|
19444
|
-
|
|
19445
|
-
|
|
19446
|
-
|
|
19447
|
-
|
|
19448
|
-
|
|
19449
|
-
|
|
19450
|
-
|
|
19451
|
-
|
|
19452
|
-
|
|
19453
|
-
|
|
19454
|
-
|
|
19455
|
-
|
|
19456
|
-
|
|
19457
|
-
|
|
19458
|
-
|
|
19459
|
-
|
|
19460
|
-
|
|
19461
|
-
|
|
19462
|
-
|
|
19463
|
-
|
|
19464
|
-
|
|
19465
|
-
|
|
19466
|
-
|
|
19467
|
-
|
|
19468
|
-
|
|
19469
|
-
|
|
19470
|
-
|
|
19711
|
+
// src/transfer/upload-session.ts
|
|
19712
|
+
import { openAsBlob } from "node:fs";
|
|
19713
|
+
|
|
19714
|
+
// src/transfer/streaming-upload.ts
|
|
19715
|
+
class StreamingUpload {
|
|
19716
|
+
size;
|
|
19717
|
+
position = 0;
|
|
19718
|
+
pending = new Uint8Array(0);
|
|
19719
|
+
closed = false;
|
|
19720
|
+
reader;
|
|
19721
|
+
onAbort;
|
|
19722
|
+
stopped = new AbortController;
|
|
19723
|
+
signal;
|
|
19724
|
+
constructor(stream, size, signal) {
|
|
19725
|
+
this.size = size;
|
|
19726
|
+
this.signal = signal ? AbortSignal.any([signal, this.stopped.signal]) : this.stopped.signal;
|
|
19727
|
+
this.reader = stream.getReader();
|
|
19728
|
+
this.onAbort = () => {
|
|
19729
|
+
this.reader.cancel(this.signal.reason).catch(() => {});
|
|
19730
|
+
};
|
|
19731
|
+
this.signal.addEventListener("abort", this.onAbort, { once: true });
|
|
19732
|
+
if (this.signal.aborted)
|
|
19733
|
+
this.onAbort();
|
|
19734
|
+
}
|
|
19735
|
+
slice(start, end) {
|
|
19736
|
+
this.signal.throwIfAborted();
|
|
19737
|
+
if (this.closed || start !== this.position || end <= start || end > this.size) {
|
|
19738
|
+
throw new SimApiError("Upload parts must consume the snapshot in order", 0);
|
|
19739
|
+
}
|
|
19740
|
+
return new ReadableStream({
|
|
19741
|
+
pull: async (controller) => {
|
|
19742
|
+
try {
|
|
19743
|
+
this.signal.throwIfAborted();
|
|
19744
|
+
while (this.pending.byteLength === 0) {
|
|
19745
|
+
const next = await this.reader.read();
|
|
19746
|
+
this.signal.throwIfAborted();
|
|
19747
|
+
if (next.done)
|
|
19748
|
+
throw new SimApiError("Upload file ended before its declared size", 0);
|
|
19749
|
+
this.pending = next.value;
|
|
19750
|
+
}
|
|
19751
|
+
const length = Math.min(this.pending.byteLength, end - this.position);
|
|
19752
|
+
controller.enqueue(this.pending.subarray(0, length));
|
|
19753
|
+
this.pending = this.pending.subarray(length);
|
|
19754
|
+
this.position += length;
|
|
19755
|
+
if (this.position === end)
|
|
19756
|
+
controller.close();
|
|
19757
|
+
} catch (error) {
|
|
19758
|
+
controller.error(error);
|
|
19759
|
+
}
|
|
19760
|
+
},
|
|
19761
|
+
cancel: (reason) => this.reader.cancel(reason)
|
|
19762
|
+
}, { highWaterMark: 0 });
|
|
19763
|
+
}
|
|
19764
|
+
assertConsumed(end) {
|
|
19765
|
+
this.signal.throwIfAborted();
|
|
19766
|
+
if (this.position !== end) {
|
|
19767
|
+
throw new SimApiError("Upload was acknowledged before its complete body was consumed", 0);
|
|
19768
|
+
}
|
|
19769
|
+
}
|
|
19770
|
+
async verifyComplete() {
|
|
19771
|
+
this.assertConsumed(this.size);
|
|
19772
|
+
if (this.pending.byteLength > 0) {
|
|
19773
|
+
throw new SimApiError("Upload file exceeds its declared size", 0);
|
|
19774
|
+
}
|
|
19775
|
+
while (true) {
|
|
19776
|
+
const next = await this.reader.read();
|
|
19777
|
+
this.signal.throwIfAborted();
|
|
19778
|
+
if (next.done)
|
|
19779
|
+
return;
|
|
19780
|
+
if (next.value.byteLength > 0)
|
|
19781
|
+
throw new SimApiError("Upload file exceeds its declared size", 0);
|
|
19782
|
+
}
|
|
19783
|
+
}
|
|
19784
|
+
async close() {
|
|
19785
|
+
if (this.closed)
|
|
19786
|
+
return;
|
|
19787
|
+
this.closed = true;
|
|
19788
|
+
this.stopped.abort();
|
|
19789
|
+
this.signal.removeEventListener("abort", this.onAbort);
|
|
19790
|
+
try {
|
|
19791
|
+
await this.reader.cancel().catch(() => {});
|
|
19792
|
+
} finally {
|
|
19793
|
+
this.reader.releaseLock();
|
|
19794
|
+
}
|
|
19471
19795
|
}
|
|
19472
|
-
if (size === 0)
|
|
19473
|
-
throw new SimApiError(`${path} is empty`, 0);
|
|
19474
|
-
return { name: override ?? basename(path), size };
|
|
19475
19796
|
}
|
|
19476
19797
|
|
|
19477
19798
|
// src/transfer/upload-session.ts
|
|
19478
|
-
import { openAsBlob } from "node:fs";
|
|
19479
19799
|
var PART_URL_BATCH = 100;
|
|
19480
|
-
async function
|
|
19481
|
-
const
|
|
19800
|
+
async function uploadBytes(url, headers, file, start, end, label) {
|
|
19801
|
+
const body = file.slice(start, end);
|
|
19802
|
+
const options = {
|
|
19482
19803
|
method: "PUT",
|
|
19483
|
-
headers
|
|
19484
|
-
body
|
|
19485
|
-
|
|
19804
|
+
headers,
|
|
19805
|
+
body,
|
|
19806
|
+
signal: file instanceof StreamingUpload ? file.signal : embedStore.getStore()?.identity.signal
|
|
19807
|
+
};
|
|
19808
|
+
if (file instanceof StreamingUpload) {
|
|
19809
|
+
const streamedHeaders = new Headers(headers);
|
|
19810
|
+
streamedHeaders.set("content-length", String(end - start));
|
|
19811
|
+
options.headers = streamedHeaders;
|
|
19812
|
+
options.duplex = "half";
|
|
19813
|
+
}
|
|
19814
|
+
const response = await fetch(url, options);
|
|
19486
19815
|
if (!response.ok) {
|
|
19487
|
-
throw new SimApiError(
|
|
19816
|
+
throw new SimApiError(`${label} failed with status ${response.status}`, response.status);
|
|
19488
19817
|
}
|
|
19818
|
+
if (file instanceof StreamingUpload)
|
|
19819
|
+
file.assertConsumed(end);
|
|
19489
19820
|
}
|
|
19490
|
-
async function uploadParts(client, workspaceId, session, transfer,
|
|
19821
|
+
async function uploadParts(client, workspaceId, session, transfer, file) {
|
|
19822
|
+
if (file instanceof StreamingUpload && (!Number.isSafeInteger(transfer.partSize) || transfer.partSize <= 0)) {
|
|
19823
|
+
throw new SimApiError("Invalid upload part size", 0);
|
|
19824
|
+
}
|
|
19491
19825
|
const expectedPartCount = Math.ceil(session.size / transfer.partSize);
|
|
19492
19826
|
if (expectedPartCount !== transfer.partCount) {
|
|
19493
19827
|
throw new Error(`Upload session expected ${transfer.partCount} parts, but file requires ${expectedPartCount}`);
|
|
@@ -19503,28 +19837,49 @@ async function uploadParts(client, workspaceId, session, transfer, blob) {
|
|
|
19503
19837
|
headers: { "upload-token": session.uploadToken },
|
|
19504
19838
|
body: { partNumbers }
|
|
19505
19839
|
});
|
|
19506
|
-
|
|
19507
|
-
|
|
19508
|
-
const
|
|
19509
|
-
|
|
19510
|
-
|
|
19511
|
-
headers: part.headers,
|
|
19512
|
-
body: chunk
|
|
19513
|
-
});
|
|
19514
|
-
if (!response.ok) {
|
|
19515
|
-
throw new SimApiError(`Part ${part.partNumber} failed with status ${response.status}`, response.status);
|
|
19840
|
+
let parts = signed.data.parts;
|
|
19841
|
+
if (file instanceof StreamingUpload) {
|
|
19842
|
+
const numbers = new Set(parts.map((part) => part.partNumber));
|
|
19843
|
+
if (parts.length !== partNumbers.length || partNumbers.some((n) => !numbers.has(n))) {
|
|
19844
|
+
throw new SimApiError("Upload part URLs do not match the requested parts", 0);
|
|
19516
19845
|
}
|
|
19846
|
+
parts = [...parts].sort((a, b) => a.partNumber - b.partNumber);
|
|
19847
|
+
}
|
|
19848
|
+
for (const part of parts) {
|
|
19849
|
+
const start = (part.partNumber - 1) * transfer.partSize;
|
|
19850
|
+
await uploadBytes(part.url, part.headers, file, start, Math.min(start + transfer.partSize, session.size), `Part ${part.partNumber}`);
|
|
19517
19851
|
}
|
|
19518
19852
|
}
|
|
19519
19853
|
}
|
|
19520
19854
|
async function finishUploadSession(client, workspaceId, session, path) {
|
|
19855
|
+
let snapshot;
|
|
19856
|
+
let streamed;
|
|
19521
19857
|
try {
|
|
19522
|
-
const
|
|
19858
|
+
const embedded = embedStore.getStore();
|
|
19859
|
+
let file;
|
|
19860
|
+
if (embedded) {
|
|
19861
|
+
embedded.identity.signal?.throwIfAborted();
|
|
19862
|
+
if (!embedded.openFile)
|
|
19863
|
+
throw new SimApiError("This invocation has no machine to read from", 0);
|
|
19864
|
+
snapshot = await embedded.openFile(embeddedFileKey(path));
|
|
19865
|
+
if (snapshot.size !== session.size)
|
|
19866
|
+
throw new SimApiError("Upload snapshot size changed", 0);
|
|
19867
|
+
streamed = new StreamingUpload(await snapshot.stream(), snapshot.size, AbortSignal.any([
|
|
19868
|
+
...embedded.identity.signal ? [embedded.identity.signal] : [],
|
|
19869
|
+
...snapshot.signal ? [snapshot.signal] : []
|
|
19870
|
+
]));
|
|
19871
|
+
file = streamed;
|
|
19872
|
+
} else {
|
|
19873
|
+
file = await openAsBlob(path);
|
|
19874
|
+
}
|
|
19523
19875
|
if (session.transfer.method === "put") {
|
|
19524
|
-
await
|
|
19876
|
+
await uploadBytes(session.transfer.url, session.transfer.headers, file, 0, file instanceof Blob ? file.size : session.size, "Upload");
|
|
19525
19877
|
} else {
|
|
19526
|
-
await uploadParts(client, workspaceId, session, session.transfer,
|
|
19878
|
+
await uploadParts(client, workspaceId, session, session.transfer, file);
|
|
19527
19879
|
}
|
|
19880
|
+
await streamed?.verifyComplete();
|
|
19881
|
+
await streamed?.close();
|
|
19882
|
+
await snapshot?.dispose().catch(() => {});
|
|
19528
19883
|
const completed = await client.request(`${session.basePath}/complete`, {
|
|
19529
19884
|
method: "POST",
|
|
19530
19885
|
query: { workspaceId },
|
|
@@ -19532,7 +19887,10 @@ async function finishUploadSession(client, workspaceId, session, path) {
|
|
|
19532
19887
|
});
|
|
19533
19888
|
return completed.data;
|
|
19534
19889
|
} catch (error) {
|
|
19535
|
-
await
|
|
19890
|
+
await streamed?.close();
|
|
19891
|
+
const profile = embeddedProfile();
|
|
19892
|
+
const cleanupClient = profile ? new SimClient({ ...profile, signal: AbortSignal.timeout(5000) }) : client;
|
|
19893
|
+
await cleanupClient.request(session.basePath, {
|
|
19536
19894
|
method: "DELETE",
|
|
19537
19895
|
query: { workspaceId },
|
|
19538
19896
|
headers: { "upload-token": session.uploadToken }
|
|
@@ -19540,6 +19898,9 @@ async function finishUploadSession(client, workspaceId, session, path) {
|
|
|
19540
19898
|
return;
|
|
19541
19899
|
});
|
|
19542
19900
|
throw error;
|
|
19901
|
+
} finally {
|
|
19902
|
+
await streamed?.close();
|
|
19903
|
+
await snapshot?.dispose().catch(() => {});
|
|
19543
19904
|
}
|
|
19544
19905
|
}
|
|
19545
19906
|
|
|
@@ -19625,9 +19986,11 @@ function attachKnowledgeDocumentUpload(documents) {
|
|
|
19625
19986
|
printProtocolResult(profile.output, {
|
|
19626
19987
|
id: completed.document.id,
|
|
19627
19988
|
knowledgeBaseId: completed.document.knowledgeBaseId,
|
|
19628
|
-
|
|
19629
|
-
|
|
19630
|
-
|
|
19989
|
+
filename: completed.document.filename,
|
|
19990
|
+
fileSize: completed.document.fileSize,
|
|
19991
|
+
mimeType: completed.document.mimeType,
|
|
19992
|
+
processingStatus: completed.document.processingStatus,
|
|
19993
|
+
chunkCount: completed.document.chunkCount
|
|
19631
19994
|
});
|
|
19632
19995
|
});
|
|
19633
19996
|
}
|
|
@@ -19743,11 +20106,11 @@ function createTableWriter() {
|
|
|
19743
20106
|
if (!widths) {
|
|
19744
20107
|
widths = COLUMNS.map((column, index) => Math.min(MAX_CELL_WIDTH2, Math.max(column.floor, visibleWidth(column.header), ...lines.map((line) => visibleWidth(line[index])))));
|
|
19745
20108
|
const header = widths;
|
|
19746
|
-
|
|
20109
|
+
printLine(styles3().dim(COLUMNS.map((column, index) => pad2(column.header.toUpperCase(), header[index])).join(" ").trimEnd()));
|
|
19747
20110
|
}
|
|
19748
20111
|
const locked = widths;
|
|
19749
20112
|
for (const line of lines) {
|
|
19750
|
-
|
|
20113
|
+
printLine(line.map((cell, index) => pad2(cell, locked[index])).join(" ").trimEnd());
|
|
19751
20114
|
}
|
|
19752
20115
|
};
|
|
19753
20116
|
}
|
|
@@ -19755,13 +20118,13 @@ function createWriter(format) {
|
|
|
19755
20118
|
if (format === "json") {
|
|
19756
20119
|
return (rows) => {
|
|
19757
20120
|
for (const row of rows)
|
|
19758
|
-
|
|
20121
|
+
printLine(JSON.stringify(row));
|
|
19759
20122
|
};
|
|
19760
20123
|
}
|
|
19761
20124
|
if (format === "yaml") {
|
|
19762
20125
|
return (rows) => {
|
|
19763
20126
|
for (const row of rows) {
|
|
19764
|
-
|
|
20127
|
+
printLine(`---
|
|
19765
20128
|
${dump(row, { lineWidth: 0, noRefs: true }).trimEnd()}`);
|
|
19766
20129
|
}
|
|
19767
20130
|
};
|
|
@@ -19778,24 +20141,24 @@ function followStatus() {
|
|
|
19778
20141
|
let reported = false;
|
|
19779
20142
|
return {
|
|
19780
20143
|
note: (message) => {
|
|
19781
|
-
if (!
|
|
20144
|
+
if (!hasProgressTerminal())
|
|
19782
20145
|
return;
|
|
19783
20146
|
reported = true;
|
|
19784
|
-
|
|
20147
|
+
writeStderr(`\r${styles3().dim(message)}${ERASE_LINE}`);
|
|
19785
20148
|
},
|
|
19786
20149
|
warn: (message) => {
|
|
19787
20150
|
if (reported) {
|
|
19788
20151
|
reported = false;
|
|
19789
|
-
|
|
20152
|
+
writeStderr(`\r${ERASE_LINE}`);
|
|
19790
20153
|
}
|
|
19791
|
-
|
|
20154
|
+
writeStderr(`warning: ${message}
|
|
19792
20155
|
`);
|
|
19793
20156
|
},
|
|
19794
20157
|
clear: () => {
|
|
19795
20158
|
if (!reported)
|
|
19796
20159
|
return;
|
|
19797
20160
|
reported = false;
|
|
19798
|
-
|
|
20161
|
+
writeStderr(`\r${ERASE_LINE}`);
|
|
19799
20162
|
}
|
|
19800
20163
|
};
|
|
19801
20164
|
}
|
|
@@ -20087,13 +20450,13 @@ async function watchImport(client, workspaceId, job) {
|
|
|
20087
20450
|
const next = await client.request(`/api/v2/tables/imports/${encodeURIComponent(current.id)}`, { query: { workspaceId } });
|
|
20088
20451
|
current = next.data;
|
|
20089
20452
|
const line = progressLine(current);
|
|
20090
|
-
if (
|
|
20453
|
+
if (hasProgressTerminal() && line !== reported) {
|
|
20091
20454
|
reported = line;
|
|
20092
|
-
|
|
20455
|
+
writeStderr(`\r${styles3().dim(line)}\x1B[K`);
|
|
20093
20456
|
}
|
|
20094
20457
|
}
|
|
20095
|
-
if (
|
|
20096
|
-
|
|
20458
|
+
if (hasProgressTerminal() && reported !== null)
|
|
20459
|
+
writeStderr("\r\x1B[K");
|
|
20097
20460
|
return current;
|
|
20098
20461
|
}
|
|
20099
20462
|
function validateTargetOptions(options) {
|
|
@@ -20151,8 +20514,8 @@ function attachTableImport(tables) {
|
|
|
20151
20514
|
workspaceId,
|
|
20152
20515
|
source,
|
|
20153
20516
|
target,
|
|
20154
|
-
...options.mapping ? { mapping: jsonFlag(options.mapping, "mapping", "object") } : {},
|
|
20155
|
-
...options.createColumns ? { createColumns: jsonFlag(options.createColumns, "create-columns", "array") } : {},
|
|
20517
|
+
...options.mapping ? { mapping: await jsonFlag(options.mapping, "mapping", "object") } : {},
|
|
20518
|
+
...options.createColumns ? { createColumns: await jsonFlag(options.createColumns, "create-columns", "array") } : {},
|
|
20156
20519
|
...options.timezone ? { timezone: options.timezone } : {}
|
|
20157
20520
|
}
|
|
20158
20521
|
});
|
|
@@ -20198,14 +20561,11 @@ var AGENT_STREAM_PROTOCOL_V1 = "agent-events-v1";
|
|
|
20198
20561
|
var WORKFLOW_RESULT_STREAM_CONTENT_TYPE = "application/x-ndjson";
|
|
20199
20562
|
var DONE_SENTINEL = "[DONE]";
|
|
20200
20563
|
function resolveWorkflowRunSelection(flags) {
|
|
20201
|
-
const manual = flags.manual === true;
|
|
20202
20564
|
const trigger = typeof flags.trigger === "string" ? flags.trigger : undefined;
|
|
20203
20565
|
const useMockPayload = flags.mockPayload === true;
|
|
20566
|
+
const manual = flags.manual === true || trigger !== undefined || useMockPayload;
|
|
20204
20567
|
const fromBlock = typeof flags.fromBlock === "string" ? flags.fromBlock : undefined;
|
|
20205
20568
|
const sourceRun = typeof flags.sourceRun === "string" ? flags.sourceRun : undefined;
|
|
20206
|
-
if ((trigger || useMockPayload) && !manual) {
|
|
20207
|
-
throw new SimApiError("--trigger and --mock-payload require --manual", 0);
|
|
20208
|
-
}
|
|
20209
20569
|
if (fromBlock && (trigger || useMockPayload)) {
|
|
20210
20570
|
throw new SimApiError("--from-block cannot be combined with --trigger or --mock-payload", 0);
|
|
20211
20571
|
}
|
|
@@ -20282,7 +20642,7 @@ async function runWithResultStream(workflowId, command) {
|
|
|
20282
20642
|
const operation = V2_OPERATIONS.executeWorkflow;
|
|
20283
20643
|
const commandSpec = CLI_CONTRACT.executeWorkflow ?? {};
|
|
20284
20644
|
try {
|
|
20285
|
-
const request = buildRequest("executeWorkflow", [workflowId], flags, profile.workspaceId);
|
|
20645
|
+
const request = await buildRequest("executeWorkflow", [workflowId], flags, profile.workspaceId);
|
|
20286
20646
|
const response = await client.requestRaw(request.path, {
|
|
20287
20647
|
method: operation.method,
|
|
20288
20648
|
query: request.query,
|
|
@@ -20357,11 +20717,11 @@ class Commentary {
|
|
|
20357
20717
|
function toolNotice(frame) {
|
|
20358
20718
|
const name = safeOneLine(stringField(frame, "name") ?? "tool");
|
|
20359
20719
|
if (frame.phase === "start")
|
|
20360
|
-
return
|
|
20720
|
+
return styles3().dim(`→ ${name}`);
|
|
20361
20721
|
const status = stringField(frame, "status");
|
|
20362
20722
|
if (status && status !== "success")
|
|
20363
|
-
return
|
|
20364
|
-
return
|
|
20723
|
+
return styles3().yellow(`✗ ${name} (${safeOneLine(status)})`);
|
|
20724
|
+
return styles3().dim(`✓ ${name}`);
|
|
20365
20725
|
}
|
|
20366
20726
|
async function renderRunStream(body, options) {
|
|
20367
20727
|
const commentary = new Commentary(options.stderr);
|
|
@@ -20383,11 +20743,11 @@ async function renderRunStream(body, options) {
|
|
|
20383
20743
|
}
|
|
20384
20744
|
switch (frame.event) {
|
|
20385
20745
|
case "chunk_reset":
|
|
20386
|
-
commentary.line(
|
|
20746
|
+
commentary.line(styles3().dim("… retracted; that turn resolved to tool calls"));
|
|
20387
20747
|
break;
|
|
20388
20748
|
case "thinking":
|
|
20389
20749
|
if (options.includeThinking && typeof frame.data === "string") {
|
|
20390
|
-
commentary.inline(
|
|
20750
|
+
commentary.inline(styles3().dim(sanitize(frame.data)));
|
|
20391
20751
|
}
|
|
20392
20752
|
break;
|
|
20393
20753
|
case "tool":
|
|
@@ -20395,7 +20755,7 @@ async function renderRunStream(body, options) {
|
|
|
20395
20755
|
commentary.line(toolNotice(frame));
|
|
20396
20756
|
break;
|
|
20397
20757
|
case "stream_error":
|
|
20398
|
-
commentary.line(
|
|
20758
|
+
commentary.line(styles3().yellow(`warning: ${safeOneLine(stringField(frame, "error") ?? "stream read failed")}`));
|
|
20399
20759
|
break;
|
|
20400
20760
|
case "error":
|
|
20401
20761
|
commentary.endLine();
|
|
@@ -20424,7 +20784,7 @@ async function followRun(workflowId, command) {
|
|
|
20424
20784
|
const negotiates = includeThinking || includeToolCalls;
|
|
20425
20785
|
const { client, profile } = clientFrom(command);
|
|
20426
20786
|
const operation = V2_OPERATIONS.executeWorkflow;
|
|
20427
|
-
const request = buildRequest("executeWorkflow", [workflowId], flags, profile.workspaceId);
|
|
20787
|
+
const request = await buildRequest("executeWorkflow", [workflowId], flags, profile.workspaceId);
|
|
20428
20788
|
const response = await client.requestRaw(request.path, {
|
|
20429
20789
|
method: "POST",
|
|
20430
20790
|
query: request.query,
|
|
@@ -20450,7 +20810,7 @@ async function followRun(workflowId, command) {
|
|
|
20450
20810
|
const final = await renderRunStream(response.body, {
|
|
20451
20811
|
includeThinking,
|
|
20452
20812
|
includeToolCalls,
|
|
20453
|
-
stderr:
|
|
20813
|
+
stderr: { write: writeStderr }
|
|
20454
20814
|
});
|
|
20455
20815
|
renderResult("executeWorkflow", profile.output, final, CLI_CONTRACT.executeWorkflow ?? {});
|
|
20456
20816
|
if (final.success === false) {
|
|
@@ -20465,8 +20825,8 @@ function followOrDelegate(previous) {
|
|
|
20465
20825
|
command.setOptionValue("run", selection);
|
|
20466
20826
|
const flags = command.optsWithGlobals();
|
|
20467
20827
|
if (flags.follow !== true) {
|
|
20468
|
-
if (Array.isArray(flags.selectOutput) && flags.selectOutput.length > 0) {
|
|
20469
|
-
throw new SimApiError(
|
|
20828
|
+
if (Array.isArray(flags.selectOutput) && flags.selectOutput.length > 0 && flags.async === true) {
|
|
20829
|
+
throw new SimApiError("--select-output names outputs of a completed run, and --async returns as soon as the run is queued. Drop one of them, or read the finished run with: sim workflows runs get <runId> --workflow <workflowId> --select-output <blockName|blockId>[.path] — that resource takes the same selectors --select-output takes here.", 0);
|
|
20470
20830
|
}
|
|
20471
20831
|
if (flags.includeThinking === true || flags.includeToolCalls === true) {
|
|
20472
20832
|
throw new SimApiError("--include-thinking and --include-tool-calls describe a stream; add --follow", 0);
|
|
@@ -20492,7 +20852,119 @@ function attachWorkflowRunFollow(workflows) {
|
|
|
20492
20852
|
}
|
|
20493
20853
|
const held = run._actionHandler;
|
|
20494
20854
|
const previous = typeof held === "function" ? held : null;
|
|
20495
|
-
run.option("--manual", "Run the current saved workflow state instead of the active deployment").option("--trigger <blockId>", "Enter
|
|
20855
|
+
run.option("--manual", "Run the current saved workflow state instead of the active deployment").option("--trigger <blockId>", "Enter the run through this runnable trigger; runs the current saved workflow state (implies --manual)").option("--mock-payload", "Use the selected trigger's server-derived mock payload; runs the current saved workflow state (implies --manual)").option("--from-block <blockId>", "Run manually from this saved workflow block").option("--source-run <runId>", "Prior run whose persisted state supplies upstream outputs (requires --from-block)").option("--follow", "Stream the run as it happens; progress on stderr, result on stdout. The stream reports only success and output, so the result omits the run id and timings a non-streaming run returns").option("--include-thinking", "Show model reasoning while following (requires --follow)").option("--include-tool-calls", "Show tool calls while following (requires --follow)").action(followOrDelegate(previous));
|
|
20856
|
+
}
|
|
20857
|
+
|
|
20858
|
+
// src/commands/protocol/workflow-run-get.ts
|
|
20859
|
+
var BLOCK_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
20860
|
+
var SELECT_OUTPUT_FLAG = "select-output";
|
|
20861
|
+
function normalizeBlockName(name) {
|
|
20862
|
+
return name.toLowerCase().replace(/\s+/g, "").replace(/\./g, "");
|
|
20863
|
+
}
|
|
20864
|
+
function isRecord2(value) {
|
|
20865
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20866
|
+
}
|
|
20867
|
+
async function loadWorkflowBlocks(client, workflowId) {
|
|
20868
|
+
const operation = V2_OPERATIONS.getWorkflowState;
|
|
20869
|
+
const raw = await client.request(resolvePath(operation.path, { workflowId }), {
|
|
20870
|
+
method: operation.method
|
|
20871
|
+
});
|
|
20872
|
+
const state = isRecord2(raw) && isRecord2(raw.data) ? raw.data : raw;
|
|
20873
|
+
const blocks = isRecord2(state) && isRecord2(state.blocks) ? Object.entries(state.blocks) : [];
|
|
20874
|
+
return blocks.map(([key, block]) => ({
|
|
20875
|
+
id: isRecord2(block) && typeof block.id === "string" ? block.id : key,
|
|
20876
|
+
name: isRecord2(block) && typeof block.name === "string" ? block.name : ""
|
|
20877
|
+
}));
|
|
20878
|
+
}
|
|
20879
|
+
function splitSelector(selector) {
|
|
20880
|
+
const dot = selector.indexOf(".");
|
|
20881
|
+
return dot === -1 ? { head: selector, path: "" } : { head: selector.slice(0, dot), path: selector.slice(dot) };
|
|
20882
|
+
}
|
|
20883
|
+
function isIdHeaded(selector) {
|
|
20884
|
+
return BLOCK_ID.test(splitSelector(selector).head);
|
|
20885
|
+
}
|
|
20886
|
+
function resolveSelection(typed, blocks, workflowId) {
|
|
20887
|
+
const resolved = [];
|
|
20888
|
+
const typedBy = new Map;
|
|
20889
|
+
const unresolved = [];
|
|
20890
|
+
for (const selector of typed) {
|
|
20891
|
+
const { head, path } = splitSelector(selector);
|
|
20892
|
+
let blockId = head;
|
|
20893
|
+
if (!BLOCK_ID.test(head)) {
|
|
20894
|
+
const wanted = normalizeBlockName(head);
|
|
20895
|
+
const matches = blocks.filter((block) => block.id === head || normalizeBlockName(block.name) === wanted);
|
|
20896
|
+
if (matches.length === 0) {
|
|
20897
|
+
unresolved.push(selector);
|
|
20898
|
+
continue;
|
|
20899
|
+
}
|
|
20900
|
+
if (matches.length > 1) {
|
|
20901
|
+
throw new SimApiError(`--${SELECT_OUTPUT_FLAG} ${selector} names ${matches.length} blocks (${matches.map((block) => block.id).join(", ")}); pass the block id instead`, 0);
|
|
20902
|
+
}
|
|
20903
|
+
blockId = matches[0].id;
|
|
20904
|
+
}
|
|
20905
|
+
const rewritten = `${blockId}${path}`;
|
|
20906
|
+
resolved.push(rewritten);
|
|
20907
|
+
if (!typedBy.has(rewritten))
|
|
20908
|
+
typedBy.set(rewritten, selector);
|
|
20909
|
+
}
|
|
20910
|
+
if (unresolved.length > 0) {
|
|
20911
|
+
const names = blocks.map((block) => block.name).filter((name) => name !== "");
|
|
20912
|
+
throw new SimApiError(`--${SELECT_OUTPUT_FLAG} did not resolve to any block on this run: ${unresolved.join(", ")}. Pass a block id or its name — "blockId", "blockId.path", "blockName" or "blockName.path"; names match ignoring case, spaces and dots. Blocks on workflow ${workflowId}: ${names.length > 0 ? names.join(", ") : "none"}.`, 0);
|
|
20913
|
+
}
|
|
20914
|
+
return { resolved, typedBy };
|
|
20915
|
+
}
|
|
20916
|
+
function keyByTyped(payload, typedBy) {
|
|
20917
|
+
if (!isRecord2(payload) || !isRecord2(payload.blockOutputs))
|
|
20918
|
+
return payload;
|
|
20919
|
+
const blockOutputs = {};
|
|
20920
|
+
for (const [key, value] of Object.entries(payload.blockOutputs)) {
|
|
20921
|
+
blockOutputs[typedBy.get(key) ?? key] = value;
|
|
20922
|
+
}
|
|
20923
|
+
return { ...payload, blockOutputs };
|
|
20924
|
+
}
|
|
20925
|
+
async function readRunByName(runId, typed, command) {
|
|
20926
|
+
const flags = command.optsWithGlobals();
|
|
20927
|
+
const { client, profile } = clientFrom(command);
|
|
20928
|
+
const operation = V2_OPERATIONS.getWorkflowRun;
|
|
20929
|
+
const spec = CLI_CONTRACT.getWorkflowRun ?? {};
|
|
20930
|
+
await buildRequest("getWorkflowRun", [runId], flags, profile.workspaceId);
|
|
20931
|
+
const workflowId = String(flags.workflow);
|
|
20932
|
+
const selection = resolveSelection(typed, await loadWorkflowBlocks(client, workflowId), workflowId);
|
|
20933
|
+
const request = await buildRequest("getWorkflowRun", [runId], { ...flags, selectOutput: selection.resolved }, profile.workspaceId);
|
|
20934
|
+
let result;
|
|
20935
|
+
try {
|
|
20936
|
+
result = await client.request(request.path, {
|
|
20937
|
+
method: operation.method,
|
|
20938
|
+
headers: request.headers,
|
|
20939
|
+
query: request.query,
|
|
20940
|
+
body: request.body
|
|
20941
|
+
});
|
|
20942
|
+
} catch (error) {
|
|
20943
|
+
throw retypeApiError(error, "getWorkflowRun", spec, operation);
|
|
20944
|
+
}
|
|
20945
|
+
renderResult("getWorkflowRun", profile.output, keyByTyped(result?.data ?? result, selection.typedBy), spec, {}, result);
|
|
20946
|
+
}
|
|
20947
|
+
function attachWorkflowRunGet(runs) {
|
|
20948
|
+
const get = runs.commands.find((command) => command.name() === "get");
|
|
20949
|
+
const held = get?._actionHandler;
|
|
20950
|
+
if (!get || typeof held !== "function") {
|
|
20951
|
+
throw new Error("workflows runs get must be registered before block names can be attached to it");
|
|
20952
|
+
}
|
|
20953
|
+
const previous = held;
|
|
20954
|
+
get.action(async (runId, _options, command) => {
|
|
20955
|
+
const raw = command.optsWithGlobals().selectOutput;
|
|
20956
|
+
if (raw === undefined) {
|
|
20957
|
+
await previous(command.processedArgs);
|
|
20958
|
+
return;
|
|
20959
|
+
}
|
|
20960
|
+
const typed = await readListValues(raw, SELECT_OUTPUT_FLAG);
|
|
20961
|
+
command.setOptionValue("selectOutput", typed);
|
|
20962
|
+
if (typed.every(isIdHeaded)) {
|
|
20963
|
+
await previous(command.processedArgs);
|
|
20964
|
+
return;
|
|
20965
|
+
}
|
|
20966
|
+
await readRunByName(runId, typed, command);
|
|
20967
|
+
});
|
|
20496
20968
|
}
|
|
20497
20969
|
|
|
20498
20970
|
// src/commands/protocol/workflow-run-wait.ts
|
|
@@ -20509,18 +20981,21 @@ var MAX_POLL_DELAY_MS = 15000;
|
|
|
20509
20981
|
var POLL_BACKOFF_FACTOR = 2;
|
|
20510
20982
|
var DEFAULT_WAIT_TIMEOUT_SECONDS = 3600;
|
|
20511
20983
|
var WAIT_TIMEOUT_FLAG = "--wait-timeout <seconds>";
|
|
20512
|
-
function
|
|
20984
|
+
function isRecord3(value) {
|
|
20513
20985
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20514
20986
|
}
|
|
20515
20987
|
function optionalString(value) {
|
|
20516
20988
|
return typeof value === "string" && value !== "" ? value : null;
|
|
20517
20989
|
}
|
|
20990
|
+
function runData(raw) {
|
|
20991
|
+
return isRecord3(raw) && isRecord3(raw.data) ? raw.data : raw;
|
|
20992
|
+
}
|
|
20518
20993
|
function readRun(raw) {
|
|
20519
|
-
const run =
|
|
20520
|
-
if (!
|
|
20994
|
+
const run = isRecord3(raw) && isRecord3(raw.data) ? raw.data : raw;
|
|
20995
|
+
if (!isRecord3(run) || typeof run.status !== "string") {
|
|
20521
20996
|
throw new SimApiError("Run status response carried no status.", 0);
|
|
20522
20997
|
}
|
|
20523
|
-
const paused =
|
|
20998
|
+
const paused = isRecord3(run.paused) ? run.paused : null;
|
|
20524
20999
|
return {
|
|
20525
21000
|
status: run.status,
|
|
20526
21001
|
pauseKind: paused ? optionalString(paused.pauseKind) : null,
|
|
@@ -20539,16 +21014,16 @@ function waitProgress() {
|
|
|
20539
21014
|
let reported = false;
|
|
20540
21015
|
return {
|
|
20541
21016
|
advance: (status, elapsedMs) => {
|
|
20542
|
-
if (!
|
|
21017
|
+
if (!hasProgressTerminal())
|
|
20543
21018
|
return;
|
|
20544
21019
|
reported = true;
|
|
20545
|
-
|
|
21020
|
+
writeStderr(`\r${styles3().dim(`${status} — waiting ${Math.round(elapsedMs / 1000)}s…`)}\x1B[K`);
|
|
20546
21021
|
},
|
|
20547
21022
|
finish: () => {
|
|
20548
21023
|
if (!reported)
|
|
20549
21024
|
return;
|
|
20550
21025
|
reported = false;
|
|
20551
|
-
|
|
21026
|
+
writeStderr("\r\x1B[K");
|
|
20552
21027
|
}
|
|
20553
21028
|
};
|
|
20554
21029
|
}
|
|
@@ -20589,19 +21064,19 @@ function attachWorkflowRunWait(runs) {
|
|
|
20589
21064
|
const outcome = classify(snapshot);
|
|
20590
21065
|
if (outcome) {
|
|
20591
21066
|
progress.finish();
|
|
20592
|
-
renderResult("getWorkflowRun", profile.output, raw, runSpec());
|
|
21067
|
+
renderResult("getWorkflowRun", profile.output, runData(raw), runSpec());
|
|
20593
21068
|
const message = explain(outcome, runId, options.workflow, snapshot);
|
|
20594
21069
|
if (message)
|
|
20595
|
-
|
|
20596
|
-
|
|
21070
|
+
printError(styles3().red(message));
|
|
21071
|
+
setSoftExitCode(WAIT_EXIT_CODES[outcome]);
|
|
20597
21072
|
return;
|
|
20598
21073
|
}
|
|
20599
21074
|
const remainingMs = deadline - Date.now();
|
|
20600
21075
|
if (remainingMs <= 0) {
|
|
20601
21076
|
progress.finish();
|
|
20602
|
-
renderResult("getWorkflowRun", profile.output, raw, runSpec());
|
|
20603
|
-
|
|
20604
|
-
|
|
21077
|
+
renderResult("getWorkflowRun", profile.output, runData(raw), runSpec());
|
|
21078
|
+
printError(styles3().red(`Timed out after ${timeoutSeconds}s waiting for run ${runId} (status: ${snapshot.status}${snapshot.resumeAt ? `, resuming at ${snapshot.resumeAt}` : ""}). Raise ${WAIT_TIMEOUT_FLAG}, or set it to 0 to wait indefinitely.`));
|
|
21079
|
+
setSoftExitCode(WAIT_EXIT_CODES.timeout);
|
|
20605
21080
|
return;
|
|
20606
21081
|
}
|
|
20607
21082
|
progress.advance(snapshot.status, Date.now() - startedAt);
|
|
@@ -20658,7 +21133,9 @@ function attachProtocolCommands(program) {
|
|
|
20658
21133
|
createFolder: "createWorkflowFolder"
|
|
20659
21134
|
});
|
|
20660
21135
|
attachWorkflowRunFollow(workflows);
|
|
20661
|
-
|
|
21136
|
+
const runs = group(workflows, "runs");
|
|
21137
|
+
attachWorkflowRunGet(runs);
|
|
21138
|
+
attachWorkflowRunWait(runs);
|
|
20662
21139
|
attachWorkspaceOperationWait(group(group(program, "workspaces"), "operations"));
|
|
20663
21140
|
attachLogsFollow(group(program, "logs"));
|
|
20664
21141
|
attachChat(program);
|
|
@@ -20762,12 +21239,12 @@ var SECRET_RESULT = {
|
|
|
20762
21239
|
{ header: "description" }
|
|
20763
21240
|
]
|
|
20764
21241
|
};
|
|
20765
|
-
function readValueArgument(raw) {
|
|
21242
|
+
async function readValueArgument(raw) {
|
|
20766
21243
|
if (raw.startsWith("@@"))
|
|
20767
21244
|
return raw.slice(1);
|
|
20768
21245
|
if (!raw.startsWith("@"))
|
|
20769
21246
|
return raw;
|
|
20770
|
-
return readArgumentSource(raw, "value").text;
|
|
21247
|
+
return (await readArgumentSource(raw, "value")).text;
|
|
20771
21248
|
}
|
|
20772
21249
|
function validateSecretValue(value) {
|
|
20773
21250
|
if (value.length === 0)
|
|
@@ -20787,7 +21264,7 @@ function validateWorkspaceOnlyFlag(flag, value, scope) {
|
|
|
20787
21264
|
}
|
|
20788
21265
|
async function readSecretValue(options) {
|
|
20789
21266
|
if (options.value !== undefined)
|
|
20790
|
-
return validateSecretValue(readValueArgument(options.value));
|
|
21267
|
+
return validateSecretValue(await readValueArgument(options.value));
|
|
20791
21268
|
if (options.description !== undefined || options.unredacted !== undefined)
|
|
20792
21269
|
return;
|
|
20793
21270
|
try {
|
|
@@ -20795,8 +21272,8 @@ async function readSecretValue(options) {
|
|
|
20795
21272
|
} catch (error) {
|
|
20796
21273
|
if (!(error instanceof SecretInputCancelledError))
|
|
20797
21274
|
throw error;
|
|
20798
|
-
|
|
20799
|
-
return
|
|
21275
|
+
printError(styles3().red(`Error: ${error.message}`));
|
|
21276
|
+
return exitCli(CANCELLED_EXIT_CODE);
|
|
20800
21277
|
}
|
|
20801
21278
|
}
|
|
20802
21279
|
async function setSecret(name, options, command, redactionSpellings) {
|
|
@@ -20968,7 +21445,7 @@ function createCommandTelemetry(options = {}) {
|
|
|
20968
21445
|
writeTelemetryState({ ...state, session });
|
|
20969
21446
|
const properties = {
|
|
20970
21447
|
$lib: LIBRARY_NAME,
|
|
20971
|
-
$lib_version:
|
|
21448
|
+
$lib_version: cliVersion(),
|
|
20972
21449
|
$process_person_profile: false,
|
|
20973
21450
|
$session_id: session.id,
|
|
20974
21451
|
session_sequence: session.sequence,
|
|
@@ -20979,7 +21456,7 @@ function createCommandTelemetry(options = {}) {
|
|
|
20979
21456
|
exit_code: outcome.exitCode,
|
|
20980
21457
|
duration_ms: Math.round(elapsed()),
|
|
20981
21458
|
...failureProperties(outcome.error),
|
|
20982
|
-
cli_version:
|
|
21459
|
+
cli_version: cliVersion(),
|
|
20983
21460
|
node_version: process.versions.node,
|
|
20984
21461
|
os: process.platform,
|
|
20985
21462
|
arch: process.arch,
|
|
@@ -21118,19 +21595,22 @@ function addVersionOption(program) {
|
|
|
21118
21595
|
}
|
|
21119
21596
|
program.error("error: --version reports the Sim CLI version and takes no value. A command that acts on a deployment version reads it from --to-version.");
|
|
21120
21597
|
});
|
|
21121
|
-
program.version(
|
|
21598
|
+
program.version(cliVersion(), "-V, --version [none]", "output the version number (takes no value)");
|
|
21122
21599
|
}
|
|
21123
21600
|
function buildProgram(options = {}) {
|
|
21124
|
-
const program = new Command;
|
|
21601
|
+
const program = options.program ?? new Command;
|
|
21125
21602
|
program.name("sim").description(PROGRAM_DESCRIPTION);
|
|
21126
21603
|
if (options.version !== false)
|
|
21127
21604
|
addVersionOption(program);
|
|
21128
21605
|
program.option("-P, --profile <name>", "Profile to use (env: SIM_PROFILE)").option("--endpoint <url>", "Sim deployment to talk to (env: SIM_ENDPOINT)").option("-w, --workspace <id>", "Workspace to target (env: SIM_WORKSPACE)").addOption(new Option("--output <format>", "Output format for this command").choices([...OUTPUT_FORMATS]));
|
|
21129
|
-
|
|
21130
|
-
|
|
21131
|
-
|
|
21132
|
-
|
|
21133
|
-
|
|
21606
|
+
for (const command of [
|
|
21607
|
+
loginCommand,
|
|
21608
|
+
logoutCommand,
|
|
21609
|
+
whoamiCommand,
|
|
21610
|
+
profilesCommand,
|
|
21611
|
+
configureCommand
|
|
21612
|
+
])
|
|
21613
|
+
program.addCommand(command());
|
|
21134
21614
|
const update = updateCommand();
|
|
21135
21615
|
program.addCommand(update);
|
|
21136
21616
|
program.addCommand(telemetryCommand());
|
|
@@ -21140,7 +21620,7 @@ function buildProgram(options = {}) {
|
|
|
21140
21620
|
attachCredentialCommands(program);
|
|
21141
21621
|
attachProtocolCommands(program);
|
|
21142
21622
|
attachSecretCommands(program);
|
|
21143
|
-
program.addHelpText("after", HELP_EPILOGUE);
|
|
21623
|
+
program.addHelpText("after", options.helpText ?? HELP_EPILOGUE);
|
|
21144
21624
|
program.hook("preAction", async (_program, command) => {
|
|
21145
21625
|
if (command === update)
|
|
21146
21626
|
return;
|
|
@@ -21151,14 +21631,14 @@ function buildProgram(options = {}) {
|
|
|
21151
21631
|
return program;
|
|
21152
21632
|
}
|
|
21153
21633
|
|
|
21154
|
-
// src/
|
|
21634
|
+
// src/terminal.ts
|
|
21155
21635
|
function explainFailure(error, program) {
|
|
21156
21636
|
if (error instanceof ProfileConfigError || error instanceof CliUpdateError) {
|
|
21157
|
-
console.error(
|
|
21637
|
+
console.error(styles3().red(`Error: ${sanitize(error.message)}`));
|
|
21158
21638
|
return 1;
|
|
21159
21639
|
}
|
|
21160
21640
|
if (isRequestTimeout(error)) {
|
|
21161
|
-
console.error(
|
|
21641
|
+
console.error(styles3().red(`Error: the request timed out. ${RAISE_TIMEOUT_HINT}`));
|
|
21162
21642
|
return 1;
|
|
21163
21643
|
}
|
|
21164
21644
|
if (error instanceof SimApiError) {
|
|
@@ -21178,30 +21658,32 @@ function explainFailure(error, program) {
|
|
|
21178
21658
|
` : dump(payload));
|
|
21179
21659
|
return error.exitCode;
|
|
21180
21660
|
}
|
|
21181
|
-
console.error(
|
|
21661
|
+
console.error(styles3().red(`Error: ${sanitize(error.message)}`));
|
|
21182
21662
|
if (error.code)
|
|
21183
|
-
console.error(
|
|
21663
|
+
console.error(styles3().dim(` code: ${sanitize(error.code)}`));
|
|
21184
21664
|
if (error.details !== undefined) {
|
|
21185
21665
|
for (const line of formatApiErrorDetails(error.details)) {
|
|
21186
|
-
console.error(
|
|
21666
|
+
console.error(styles3().dim(sanitize(line)));
|
|
21187
21667
|
}
|
|
21188
21668
|
}
|
|
21189
21669
|
return error.exitCode;
|
|
21190
21670
|
}
|
|
21191
21671
|
return null;
|
|
21192
21672
|
}
|
|
21193
|
-
async function
|
|
21194
|
-
const telemetry = createCommandTelemetry();
|
|
21195
|
-
const program = buildProgram();
|
|
21196
|
-
telemetry
|
|
21673
|
+
async function runTerminalCli(suppliedProgram) {
|
|
21674
|
+
const telemetry = suppliedProgram ? undefined : createCommandTelemetry();
|
|
21675
|
+
const program = suppliedProgram ?? buildProgram();
|
|
21676
|
+
telemetry?.observe(program);
|
|
21197
21677
|
try {
|
|
21198
21678
|
await program.parseAsync(process.argv);
|
|
21199
21679
|
} catch (error) {
|
|
21200
21680
|
const exitCode = explainFailure(error, program);
|
|
21201
|
-
telemetry
|
|
21681
|
+
telemetry?.complete({ exitCode: exitCode ?? 1, error });
|
|
21202
21682
|
if (exitCode === null)
|
|
21203
21683
|
throw error;
|
|
21204
21684
|
process.exit(exitCode);
|
|
21205
21685
|
}
|
|
21206
21686
|
}
|
|
21207
|
-
|
|
21687
|
+
|
|
21688
|
+
// src/index.ts
|
|
21689
|
+
runTerminalCli();
|