sim 2.1.8-preview.97.1 → 2.1.8-preview.99.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -5
- package/dist/index.js +146 -76
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,16 +33,27 @@ Sign in to the default profile:
|
|
|
33
33
|
sim login
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
With no `--method`, the CLI prefers OAuth when the server offers it and a local
|
|
37
|
+
browser callback is possible. It selects API-key pairing for remote terminals
|
|
38
|
+
or servers without OAuth. Use `sim login --method oauth` to require OAuth;
|
|
39
|
+
if the server does not offer it, login fails without creating an API key.
|
|
40
|
+
|
|
41
|
+
OAuth login opens Sim in your browser, asks you to approve the requested access,
|
|
37
42
|
and receives the one-time authorization code on a loopback callback. It stores
|
|
38
43
|
a short-lived OAuth login that renews automatically and can be revoked under
|
|
39
44
|
**Settings → General → Authorized apps**. Choose a default workspace afterward with
|
|
40
45
|
`sim configure --set-workspace <id>`.
|
|
41
46
|
|
|
42
|
-
Use
|
|
43
|
-
|
|
44
|
-
a container without port forwarding, use
|
|
45
|
-
|
|
47
|
+
Use `--no-browser` with either method to print the approval URL without opening
|
|
48
|
+
it. OAuth still needs the browser to reach the CLI's loopback callback. Over SSH
|
|
49
|
+
or in a container without port forwarding, use
|
|
50
|
+
`sim login --method api-key --no-browser` to approve from another device and
|
|
51
|
+
create a permanent personal API key. `--method api-key` creates a new key;
|
|
52
|
+
set `SIM_API_KEY` to supply an existing one.
|
|
53
|
+
|
|
54
|
+
Pairing requires a server that supports `platform` API keys. Upgrade older
|
|
55
|
+
deployments that only issue `copilot` keys before login; they are not compatible
|
|
56
|
+
with the platform CLI. OAuth discovery does not check pairing compatibility.
|
|
46
57
|
|
|
47
58
|
Check the active profile and verify that its endpoint, credential, and workspace
|
|
48
59
|
work together:
|
package/dist/index.js
CHANGED
|
@@ -4460,6 +4460,22 @@ function toApiError(url, status, contentType, raw) {
|
|
|
4460
4460
|
function truncate(value, max) {
|
|
4461
4461
|
return value.length <= max ? value : `${value.slice(0, max)}…`;
|
|
4462
4462
|
}
|
|
4463
|
+
function transportErrorMessage(error) {
|
|
4464
|
+
const messages = [];
|
|
4465
|
+
const seen = new Set;
|
|
4466
|
+
let current = error;
|
|
4467
|
+
while (current && typeof current === "object" && messages.length < 4 && !seen.has(current)) {
|
|
4468
|
+
seen.add(current);
|
|
4469
|
+
const candidate = current;
|
|
4470
|
+
const message = typeof candidate.message === "string" ? truncate(candidate.message.replace(/\s+/g, " ").trim(), 300) : "";
|
|
4471
|
+
const code = typeof candidate.code === "string" ? candidate.code : "";
|
|
4472
|
+
const detail = `${message}${code && !message.includes(code) ? ` (${code})` : ""}`;
|
|
4473
|
+
if (detail && messages.at(-1) !== detail)
|
|
4474
|
+
messages.push(detail);
|
|
4475
|
+
current = candidate.cause;
|
|
4476
|
+
}
|
|
4477
|
+
return messages.join(": ") || "Unknown network error";
|
|
4478
|
+
}
|
|
4463
4479
|
function namesKeyScopeRefusal(error) {
|
|
4464
4480
|
if (typeof error.code === "string" && KEY_SCOPE_REFUSALS.has(error.code))
|
|
4465
4481
|
return true;
|
|
@@ -4683,7 +4699,7 @@ class SimClient {
|
|
|
4683
4699
|
if (timeout?.aborted) {
|
|
4684
4700
|
throw new SimApiError(`${url} did not answer within ${timeoutMs / 1000}s. ${RAISE_TIMEOUT_HINT}`, 0);
|
|
4685
4701
|
}
|
|
4686
|
-
throw new SimApiError(`Could not reach ${this.profile.endpoint}: ${cause
|
|
4702
|
+
throw new SimApiError(`Could not reach ${this.profile.endpoint}: ${transportErrorMessage(cause)}`, 0);
|
|
4687
4703
|
}
|
|
4688
4704
|
if (trace)
|
|
4689
4705
|
traceRequest(method, url, response.status, startedAt);
|
|
@@ -8140,12 +8156,12 @@ function createAuthRequest() {
|
|
|
8140
8156
|
pairing: pairingCode()
|
|
8141
8157
|
};
|
|
8142
8158
|
}
|
|
8143
|
-
function buildApprovalUrl(endpoint, auth,
|
|
8159
|
+
function buildApprovalUrl(endpoint, auth, workspaceId) {
|
|
8144
8160
|
return buildUrl(endpoint, APPROVAL_PATH, {
|
|
8145
8161
|
request: auth.request,
|
|
8146
8162
|
challenge: auth.challenge,
|
|
8147
8163
|
pairing: auth.pairing,
|
|
8148
|
-
scope,
|
|
8164
|
+
scope: "platform",
|
|
8149
8165
|
workspace: workspaceId
|
|
8150
8166
|
});
|
|
8151
8167
|
}
|
|
@@ -8451,7 +8467,7 @@ function listenForCallback(server, expectedState, completionUrl, signal, timeout
|
|
|
8451
8467
|
const onAbort = () => finish({ ok: false, error: new SimApiError("Login cancelled.", 0) });
|
|
8452
8468
|
const timer = setTimeout(() => finish({
|
|
8453
8469
|
ok: false,
|
|
8454
|
-
error: new SimApiError(`Timed out after ${Math.round(timeoutMs / 60000)} minutes waiting for the browser. Run sim login again, or use --
|
|
8470
|
+
error: new SimApiError(`Timed out after ${Math.round(timeoutMs / 60000)} minutes waiting for the browser. Run sim login again, or use --method api-key if this terminal's browser cannot reach it.`, 0)
|
|
8455
8471
|
}), timeoutMs);
|
|
8456
8472
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
8457
8473
|
server.on("request", (request, response) => {
|
|
@@ -13944,12 +13960,12 @@ function addProfileCommand() {
|
|
|
13944
13960
|
console.log(source_default.dim(` Try: sim --profile ${safeOneLine(profileName)} whoami`));
|
|
13945
13961
|
});
|
|
13946
13962
|
}
|
|
13947
|
-
async function chooseLoginFlow(profile, options
|
|
13963
|
+
async function chooseLoginFlow(profile, options) {
|
|
13948
13964
|
requireSecureEndpoint(profile.endpoint);
|
|
13949
|
-
if (options.
|
|
13965
|
+
if (options.method === "api-key")
|
|
13950
13966
|
return "handoff";
|
|
13951
|
-
if (isLikelyRemoteSession() && options.callbackPort === undefined) {
|
|
13952
|
-
console.log(source_default.dim(`This looks like a remote session
|
|
13967
|
+
if (options.method === undefined && isLikelyRemoteSession() && options.callbackPort === undefined) {
|
|
13968
|
+
console.log(source_default.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>.
|
|
13953
13969
|
`));
|
|
13954
13970
|
return "handoff";
|
|
13955
13971
|
}
|
|
@@ -13958,7 +13974,10 @@ async function chooseLoginFlow(profile, options, scope) {
|
|
|
13958
13974
|
throw new SimApiError(`Could not reach ${profile.endpoint}. Check the endpoint.`, 0);
|
|
13959
13975
|
}
|
|
13960
13976
|
if (status === "unavailable") {
|
|
13961
|
-
|
|
13977
|
+
if (options.method === "oauth") {
|
|
13978
|
+
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);
|
|
13979
|
+
}
|
|
13980
|
+
console.log(source_default.dim(`${profile.endpoint} does not offer OAuth sign-in; using the pairing code to create a personal API key.
|
|
13962
13981
|
`));
|
|
13963
13982
|
return "handoff";
|
|
13964
13983
|
}
|
|
@@ -14036,16 +14055,12 @@ Waiting for you to approve in the browser…`));
|
|
|
14036
14055
|
}
|
|
14037
14056
|
}
|
|
14038
14057
|
function loginCommand() {
|
|
14039
|
-
return new Command("login").description("Sign in through the browser and store the login for the profile").
|
|
14058
|
+
return new Command("login").description("Sign in through the browser and store the login for the profile").addOption(new Option("--method <method>", "Credential to obtain: oauth requires OAuth support; api-key creates a permanent key through pairing (auto-selects when omitted)").choices(["oauth", "api-key"])).option("--no-browser", "Print the approval URL without opening it (either login method)").option("--read-only", "Ask only for permission to read, never to change anything").option("--callback-port <port>", "Pin the local port the browser returns to").option("-y, --yes", "Overwrite an existing API-key profile without prompting").action(async (options, command) => {
|
|
14040
14059
|
const profile = profileFrom(command, { allowUnknownProfile: true });
|
|
14041
14060
|
const authProfile = resolveAuthenticationProfileName(profile.name);
|
|
14042
14061
|
if (authProfile !== profile.name) {
|
|
14043
14062
|
throw new SimApiError(`Profile "${redact(profile.name)}" shares authentication with "${redact(authProfile)}". Run: sim login --profile ${redact(authProfile)}`, 0);
|
|
14044
14063
|
}
|
|
14045
|
-
if (options.scope !== "platform" && options.scope !== "copilot") {
|
|
14046
|
-
throw new SimApiError(`Unknown scope "${options.scope}". Use platform or copilot.`, 0);
|
|
14047
|
-
}
|
|
14048
|
-
const scope = options.scope;
|
|
14049
14064
|
const snapshot = readLoginProfileSnapshot(profile.name);
|
|
14050
14065
|
const storedCredential = snapshot.credential;
|
|
14051
14066
|
if (storedCredential?.kind === "oauth") {
|
|
@@ -14059,13 +14074,13 @@ function loginCommand() {
|
|
|
14059
14074
|
}
|
|
14060
14075
|
}
|
|
14061
14076
|
const callbackPort = parseCallbackPort(options.callbackPort);
|
|
14062
|
-
const loginFlow = await chooseLoginFlow(profile, options
|
|
14077
|
+
const loginFlow = await chooseLoginFlow(profile, options);
|
|
14063
14078
|
if (loginFlow === "handoff") {
|
|
14064
14079
|
if (options.readOnly) {
|
|
14065
|
-
throw new SimApiError("
|
|
14080
|
+
throw new SimApiError("API-key login cannot issue a read-only login. Use --method oauth, or drop --read-only.", 0);
|
|
14066
14081
|
}
|
|
14067
14082
|
if (callbackPort !== undefined) {
|
|
14068
|
-
throw new SimApiError("
|
|
14083
|
+
throw new SimApiError("API-key login has no local callback, so --callback-port does not apply. Use --method oauth, or drop --callback-port.", 0);
|
|
14069
14084
|
}
|
|
14070
14085
|
}
|
|
14071
14086
|
await withProfileLoginLease(profile.name, async () => {
|
|
@@ -14074,13 +14089,13 @@ function loginCommand() {
|
|
|
14074
14089
|
await loginWithOAuth(profile, options, callbackPort, snapshot);
|
|
14075
14090
|
return;
|
|
14076
14091
|
}
|
|
14077
|
-
await loginWithHandoff(profile, options,
|
|
14092
|
+
await loginWithHandoff(profile, options, snapshot);
|
|
14078
14093
|
});
|
|
14079
14094
|
});
|
|
14080
14095
|
}
|
|
14081
|
-
async function loginWithHandoff(profile, options,
|
|
14096
|
+
async function loginWithHandoff(profile, options, expected) {
|
|
14082
14097
|
const auth = createAuthRequest();
|
|
14083
|
-
const url = buildApprovalUrl(profile.endpoint, auth,
|
|
14098
|
+
const url = buildApprovalUrl(profile.endpoint, auth, profile.workspaceId ?? undefined);
|
|
14084
14099
|
console.log(`Signing in to ${source_default.bold(profile.endpoint)} as profile ${source_default.bold(safeOneLine(profile.name))}`);
|
|
14085
14100
|
console.log(`
|
|
14086
14101
|
Pairing code: ${source_default.bold(auth.pairing)}`);
|
|
@@ -14093,8 +14108,8 @@ Pairing code: ${source_default.bold(auth.pairing)}`);
|
|
|
14093
14108
|
Waiting for approval…`));
|
|
14094
14109
|
const key = await pollForKey(profile.endpoint, auth);
|
|
14095
14110
|
try {
|
|
14096
|
-
if (key.scope !==
|
|
14097
|
-
throw new SimApiError(`Server issued a ${key.scope} key but
|
|
14111
|
+
if (key.scope !== "platform") {
|
|
14112
|
+
throw new SimApiError(`Server issued a ${key.scope} key, but the CLI requires a platform API key. Update the Sim deployment and try again.`, 0);
|
|
14098
14113
|
}
|
|
14099
14114
|
const settings = {
|
|
14100
14115
|
endpoint: profile.endpoint,
|
|
@@ -17240,6 +17255,47 @@ function attachCredentialCommands(program) {
|
|
|
17240
17255
|
credentials.command("reconnect").argument("<credentialId>", "Existing OAuth credential to re-authorize").description(describeOperation(V2_OPERATIONS.createCredentialConnection, "Create a short-lived link for reconnecting an OAuth credential")).action((credentialId, _options, command) => createConnectionLink(command, { credentialId }));
|
|
17241
17256
|
}
|
|
17242
17257
|
|
|
17258
|
+
// src/http/ndjson.ts
|
|
17259
|
+
async function* readNdjson(body, protocol) {
|
|
17260
|
+
if (!body) {
|
|
17261
|
+
throw new SimApiError(`${protocol} ended without a response body`, 0);
|
|
17262
|
+
}
|
|
17263
|
+
const reader = body.getReader();
|
|
17264
|
+
const decoder = new TextDecoder;
|
|
17265
|
+
let buffer = "";
|
|
17266
|
+
const parse = (line) => {
|
|
17267
|
+
const trimmed = line.trim();
|
|
17268
|
+
if (!trimmed)
|
|
17269
|
+
return;
|
|
17270
|
+
try {
|
|
17271
|
+
return JSON.parse(trimmed);
|
|
17272
|
+
} catch {
|
|
17273
|
+
throw new SimApiError(`${protocol} returned malformed data`, 0);
|
|
17274
|
+
}
|
|
17275
|
+
};
|
|
17276
|
+
try {
|
|
17277
|
+
while (true) {
|
|
17278
|
+
const { done, value } = await reader.read();
|
|
17279
|
+
buffer += done ? decoder.decode() : decoder.decode(value, { stream: true });
|
|
17280
|
+
const lines = buffer.split(`
|
|
17281
|
+
`);
|
|
17282
|
+
buffer = done ? "" : lines.pop() ?? "";
|
|
17283
|
+
for (const line of lines) {
|
|
17284
|
+
const event = parse(line);
|
|
17285
|
+
if (event !== undefined)
|
|
17286
|
+
yield event;
|
|
17287
|
+
}
|
|
17288
|
+
if (done)
|
|
17289
|
+
return;
|
|
17290
|
+
}
|
|
17291
|
+
} finally {
|
|
17292
|
+
reader.cancel().catch(() => {
|
|
17293
|
+
return;
|
|
17294
|
+
});
|
|
17295
|
+
reader.releaseLock();
|
|
17296
|
+
}
|
|
17297
|
+
}
|
|
17298
|
+
|
|
17243
17299
|
// src/commands/protocol/result.ts
|
|
17244
17300
|
function printProtocolResult(format, result) {
|
|
17245
17301
|
const fields = Object.entries(result).map(([key, value]) => [key, text(value)]);
|
|
@@ -17247,72 +17303,28 @@ function printProtocolResult(format, result) {
|
|
|
17247
17303
|
}
|
|
17248
17304
|
|
|
17249
17305
|
// src/commands/protocol/chat.ts
|
|
17250
|
-
function parseChatStreamLine(line) {
|
|
17251
|
-
const trimmed = line.trim();
|
|
17252
|
-
if (!trimmed)
|
|
17253
|
-
return;
|
|
17254
|
-
try {
|
|
17255
|
-
return JSON.parse(trimmed);
|
|
17256
|
-
} catch {
|
|
17257
|
-
throw new SimApiError("Chat stream returned malformed data", 0);
|
|
17258
|
-
}
|
|
17259
|
-
}
|
|
17260
17306
|
async function readChatStream(response, onChunk) {
|
|
17261
|
-
|
|
17262
|
-
|
|
17263
|
-
|
|
17264
|
-
|
|
17265
|
-
|
|
17266
|
-
|
|
17267
|
-
|
|
17268
|
-
const processLine = (line) => {
|
|
17269
|
-
const event = parseChatStreamLine(line);
|
|
17270
|
-
if (!event || event.type === "heartbeat")
|
|
17271
|
-
return false;
|
|
17307
|
+
for await (const value of readNdjson(response.body, "Chat stream")) {
|
|
17308
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
17309
|
+
throw new SimApiError("Chat stream returned an unknown event", 0);
|
|
17310
|
+
}
|
|
17311
|
+
const event = value;
|
|
17312
|
+
if (event.type === "heartbeat")
|
|
17313
|
+
continue;
|
|
17272
17314
|
if (event.type === "chunk") {
|
|
17273
17315
|
if (event.content)
|
|
17274
17316
|
onChunk(sanitize(event.content));
|
|
17275
|
-
|
|
17317
|
+
continue;
|
|
17276
17318
|
}
|
|
17277
17319
|
if (event.type === "error") {
|
|
17278
17320
|
throw new SimApiError(event.error || "Chat request failed", 0);
|
|
17279
17321
|
}
|
|
17280
17322
|
if (event.type === "final") {
|
|
17281
|
-
|
|
17282
|
-
return true;
|
|
17323
|
+
return event.data;
|
|
17283
17324
|
}
|
|
17284
17325
|
throw new SimApiError("Chat stream returned an unknown event", 0);
|
|
17285
|
-
};
|
|
17286
|
-
try {
|
|
17287
|
-
let ended = false;
|
|
17288
|
-
while (!ended) {
|
|
17289
|
-
const { done, value } = await reader.read();
|
|
17290
|
-
if (done)
|
|
17291
|
-
break;
|
|
17292
|
-
buffer += decoder.decode(value, { stream: true });
|
|
17293
|
-
const lines = buffer.split(`
|
|
17294
|
-
`);
|
|
17295
|
-
buffer = lines.pop() ?? "";
|
|
17296
|
-
for (const line of lines) {
|
|
17297
|
-
if (processLine(line)) {
|
|
17298
|
-
ended = true;
|
|
17299
|
-
break;
|
|
17300
|
-
}
|
|
17301
|
-
}
|
|
17302
|
-
}
|
|
17303
|
-
if (!ended) {
|
|
17304
|
-
buffer += decoder.decode();
|
|
17305
|
-
processLine(buffer);
|
|
17306
|
-
}
|
|
17307
|
-
if (!finalResult) {
|
|
17308
|
-
throw new SimApiError("Chat stream ended without a final result", 0);
|
|
17309
|
-
}
|
|
17310
|
-
return finalResult;
|
|
17311
|
-
} finally {
|
|
17312
|
-
reader.cancel().catch(() => {
|
|
17313
|
-
return;
|
|
17314
|
-
});
|
|
17315
17326
|
}
|
|
17327
|
+
throw new SimApiError("Chat stream ended without a final result", 0);
|
|
17316
17328
|
}
|
|
17317
17329
|
function ignoreBrokenPipe(stream) {
|
|
17318
17330
|
const onError = (error) => {
|
|
@@ -18303,6 +18315,7 @@ function attachTableImport(tables) {
|
|
|
18303
18315
|
// src/commands/protocol/workflow-run-follow.ts
|
|
18304
18316
|
var AGENT_STREAM_PROTOCOL_HEADER = "x-sim-stream-protocol";
|
|
18305
18317
|
var AGENT_STREAM_PROTOCOL_V1 = "agent-events-v1";
|
|
18318
|
+
var WORKFLOW_RESULT_STREAM_CONTENT_TYPE = "application/x-ndjson";
|
|
18306
18319
|
var DONE_SENTINEL = "[DONE]";
|
|
18307
18320
|
function resolveWorkflowRunSelection(flags) {
|
|
18308
18321
|
const manual = flags.manual === true;
|
|
@@ -18354,6 +18367,59 @@ function stringField(frame, key) {
|
|
|
18354
18367
|
const value = frame[key];
|
|
18355
18368
|
return typeof value === "string" ? value : null;
|
|
18356
18369
|
}
|
|
18370
|
+
async function readWorkflowResult(response) {
|
|
18371
|
+
const contentType = (response.headers.get("content-type") ?? "").toLowerCase();
|
|
18372
|
+
if (!contentType.includes(WORKFLOW_RESULT_STREAM_CONTENT_TYPE)) {
|
|
18373
|
+
let envelope;
|
|
18374
|
+
try {
|
|
18375
|
+
envelope = await response.json();
|
|
18376
|
+
} catch {
|
|
18377
|
+
throw new SimApiError(`Workflow run returned malformed JSON${contentType ? ` as ${contentType}` : ""}`, response.status);
|
|
18378
|
+
}
|
|
18379
|
+
if (!isRecord(envelope)) {
|
|
18380
|
+
throw new SimApiError("Workflow run returned an invalid result envelope", response.status);
|
|
18381
|
+
}
|
|
18382
|
+
return isRecord(envelope.data) ? envelope.data : envelope;
|
|
18383
|
+
}
|
|
18384
|
+
for await (const value of readNdjson(response.body, "Workflow result stream")) {
|
|
18385
|
+
if (!isRecord(value) || typeof value.type !== "string") {
|
|
18386
|
+
throw new SimApiError("Workflow result stream returned an unknown event", response.status);
|
|
18387
|
+
}
|
|
18388
|
+
if (value.type === "heartbeat")
|
|
18389
|
+
continue;
|
|
18390
|
+
if (value.type === "error") {
|
|
18391
|
+
throw new SimApiError(safeOneLine(typeof value.error === "string" ? value.error : "Workflow run failed"), typeof value.status === "number" ? value.status : 0, typeof value.code === "string" ? value.code : null);
|
|
18392
|
+
}
|
|
18393
|
+
if (value.type === "final" && isRecord(value.data))
|
|
18394
|
+
return value.data;
|
|
18395
|
+
throw new SimApiError("Workflow result stream returned an unknown event", response.status);
|
|
18396
|
+
}
|
|
18397
|
+
throw new SimApiError("Workflow result stream ended without a final result", response.status);
|
|
18398
|
+
}
|
|
18399
|
+
async function runWithResultStream(workflowId, command) {
|
|
18400
|
+
const flags = command.optsWithGlobals();
|
|
18401
|
+
const { client, profile } = clientFrom(command);
|
|
18402
|
+
const operation = V2_OPERATIONS.executeWorkflow;
|
|
18403
|
+
const commandSpec = CLI_CONTRACT.executeWorkflow ?? {};
|
|
18404
|
+
try {
|
|
18405
|
+
const request = buildRequest("executeWorkflow", [workflowId], flags, profile.workspaceId);
|
|
18406
|
+
const response = await client.requestRaw(request.path, {
|
|
18407
|
+
method: operation.method,
|
|
18408
|
+
query: request.query,
|
|
18409
|
+
body: request.body,
|
|
18410
|
+
headers: { ...request.headers, accept: WORKFLOW_RESULT_STREAM_CONTENT_TYPE }
|
|
18411
|
+
});
|
|
18412
|
+
const payload = await readWorkflowResult(response);
|
|
18413
|
+
renderResult("executeWorkflow", profile.output, payload, commandSpec, {
|
|
18414
|
+
expandedTrace: flags.trace === true
|
|
18415
|
+
});
|
|
18416
|
+
const failure = runFailureMessage("executeWorkflow", payload);
|
|
18417
|
+
if (failure)
|
|
18418
|
+
throw new SimApiError(failure, 0);
|
|
18419
|
+
} catch (error) {
|
|
18420
|
+
throw retypeApiError(error, "executeWorkflow", commandSpec, operation);
|
|
18421
|
+
}
|
|
18422
|
+
}
|
|
18357
18423
|
async function* sseData(body) {
|
|
18358
18424
|
const reader = body.getReader();
|
|
18359
18425
|
const decoder = new TextDecoder;
|
|
@@ -18525,6 +18591,10 @@ function followOrDelegate(previous) {
|
|
|
18525
18591
|
if (flags.includeThinking === true || flags.includeToolCalls === true) {
|
|
18526
18592
|
throw new SimApiError("--include-thinking and --include-tool-calls describe a stream; add --follow", 0);
|
|
18527
18593
|
}
|
|
18594
|
+
if (flags.async !== true) {
|
|
18595
|
+
await runWithResultStream(workflowId, command);
|
|
18596
|
+
return;
|
|
18597
|
+
}
|
|
18528
18598
|
if (previous) {
|
|
18529
18599
|
await previous(command.processedArgs);
|
|
18530
18600
|
return;
|