sim 2.1.8-preview.103.1 → 2.1.8-preview.97.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 +6 -32
- package/dist/index.js +134 -249
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,27 +33,16 @@ Sign in to the default profile:
|
|
|
33
33
|
sim login
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
|
|
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,
|
|
36
|
+
The CLI opens Sim in your browser, asks you to approve the requested access,
|
|
42
37
|
and receives the one-time authorization code on a loopback callback. It stores
|
|
43
38
|
a short-lived OAuth login that renews automatically and can be revoked under
|
|
44
39
|
**Settings → General → Authorized apps**. Choose a default workspace afterward with
|
|
45
40
|
`sim configure --set-workspace <id>`.
|
|
46
41
|
|
|
47
|
-
Use
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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.
|
|
42
|
+
Use `sim login --no-browser` to print the OAuth URL without opening it. The
|
|
43
|
+
browser must still be able to reach the CLI's loopback callback. Over SSH or in
|
|
44
|
+
a container without port forwarding, use `sim login --browserless`; that
|
|
45
|
+
pairing-code fallback creates a permanent personal API key instead.
|
|
57
46
|
|
|
58
47
|
Check the active profile and verify that its endpoint, credential, and workspace
|
|
59
48
|
work together:
|
|
@@ -220,26 +209,11 @@ will consume the result, and `text` for tab-separated shell output:
|
|
|
220
209
|
|
|
221
210
|
```bash
|
|
222
211
|
sim workflows list --output json
|
|
223
|
-
sim logs list --output json | jq -r '.
|
|
212
|
+
sim logs list --output json | jq -r '.[].runId'
|
|
224
213
|
SIM_OUTPUT=yaml sim tables get <tableId>
|
|
225
214
|
sim configure --set-output json
|
|
226
215
|
```
|
|
227
216
|
|
|
228
|
-
Paginated lists return `{ "data": [...], "nextCursor": "..." }` in JSON and YAML.
|
|
229
|
-
`nextCursor` is `null` when no pages remain. Resource lists and directory `ls`
|
|
230
|
-
fetch every page by default; use `--limit N` to cap them. Table rows (including
|
|
231
|
-
queries), logs, audit/billing events, workflow runs/versions, and knowledge
|
|
232
|
-
documents/chunks keep a default limit of 100. Use `--limit 0` to fetch every page
|
|
233
|
-
of those datasets, or pass the returned `nextCursor` to `--cursor` to continue
|
|
234
|
-
with another bounded result. Keep the same resource, filters, and sort order
|
|
235
|
-
when resuming; stop when `nextCursor` is `null`. Results accumulate in memory
|
|
236
|
-
before printing, so large datasets need an explicit limit or filter.
|
|
237
|
-
|
|
238
|
-
```bash
|
|
239
|
-
sim tables rows list <tableId> --limit 100 --output json
|
|
240
|
-
sim tables rows list <tableId> --limit 100 --cursor "$nextCursor" --output json
|
|
241
|
-
```
|
|
242
|
-
|
|
243
217
|
JSON-valued options accept inline JSON, a file prefixed with `@`, or stdin with
|
|
244
218
|
`@-`:
|
|
245
219
|
|
package/dist/index.js
CHANGED
|
@@ -4460,22 +4460,6 @@ 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
|
-
}
|
|
4479
4463
|
function namesKeyScopeRefusal(error) {
|
|
4480
4464
|
if (typeof error.code === "string" && KEY_SCOPE_REFUSALS.has(error.code))
|
|
4481
4465
|
return true;
|
|
@@ -4699,7 +4683,7 @@ class SimClient {
|
|
|
4699
4683
|
if (timeout?.aborted) {
|
|
4700
4684
|
throw new SimApiError(`${url} did not answer within ${timeoutMs / 1000}s. ${RAISE_TIMEOUT_HINT}`, 0);
|
|
4701
4685
|
}
|
|
4702
|
-
throw new SimApiError(`Could not reach ${this.profile.endpoint}: ${
|
|
4686
|
+
throw new SimApiError(`Could not reach ${this.profile.endpoint}: ${cause.message}`, 0);
|
|
4703
4687
|
}
|
|
4704
4688
|
if (trace)
|
|
4705
4689
|
traceRequest(method, url, response.status, startedAt);
|
|
@@ -4763,21 +4747,15 @@ function pageProgress() {
|
|
|
4763
4747
|
}
|
|
4764
4748
|
};
|
|
4765
4749
|
}
|
|
4766
|
-
function assertCursorAdvances(cursor, seenCursors) {
|
|
4767
|
-
if (cursor === null)
|
|
4768
|
-
return;
|
|
4769
|
-
if (seenCursors.has(cursor)) {
|
|
4770
|
-
throw new SimApiError("The API returned a repeated pagination cursor; cannot continue.", 0);
|
|
4771
|
-
}
|
|
4772
|
-
seenCursors.add(cursor);
|
|
4773
|
-
}
|
|
4774
4750
|
async function requestAllPages(client, path, options) {
|
|
4751
|
+
return (await requestPages(client, path, options)).items;
|
|
4752
|
+
}
|
|
4753
|
+
async function requestPages(client, path, options) {
|
|
4775
4754
|
const { query, pageSize, limit: requestedLimit, ...requestOptions } = options;
|
|
4776
4755
|
const limit = requestedLimit ?? Number.POSITIVE_INFINITY;
|
|
4777
4756
|
if (limit <= 0)
|
|
4778
|
-
return [];
|
|
4757
|
+
return { items: [], truncated: false };
|
|
4779
4758
|
const items = [];
|
|
4780
|
-
const seenCursors = new Set;
|
|
4781
4759
|
const progress = pageProgress();
|
|
4782
4760
|
let cursor = null;
|
|
4783
4761
|
try {
|
|
@@ -4790,7 +4768,6 @@ async function requestAllPages(client, path, options) {
|
|
|
4790
4768
|
cursor
|
|
4791
4769
|
}
|
|
4792
4770
|
});
|
|
4793
|
-
assertCursorAdvances(page.nextCursor, seenCursors);
|
|
4794
4771
|
items.push(...page.data);
|
|
4795
4772
|
cursor = page.nextCursor;
|
|
4796
4773
|
if (cursor && items.length < limit)
|
|
@@ -4799,7 +4776,7 @@ async function requestAllPages(client, path, options) {
|
|
|
4799
4776
|
} finally {
|
|
4800
4777
|
progress.finish();
|
|
4801
4778
|
}
|
|
4802
|
-
return items.slice(0, limit);
|
|
4779
|
+
return { items: items.slice(0, limit), truncated: cursor !== null || items.length > limit };
|
|
4803
4780
|
}
|
|
4804
4781
|
function resolvePath(template, params = {}) {
|
|
4805
4782
|
return template.replace(/\[([^\]]+)\]/g, (_match, key) => {
|
|
@@ -8163,12 +8140,12 @@ function createAuthRequest() {
|
|
|
8163
8140
|
pairing: pairingCode()
|
|
8164
8141
|
};
|
|
8165
8142
|
}
|
|
8166
|
-
function buildApprovalUrl(endpoint, auth, workspaceId) {
|
|
8143
|
+
function buildApprovalUrl(endpoint, auth, scope, workspaceId) {
|
|
8167
8144
|
return buildUrl(endpoint, APPROVAL_PATH, {
|
|
8168
8145
|
request: auth.request,
|
|
8169
8146
|
challenge: auth.challenge,
|
|
8170
8147
|
pairing: auth.pairing,
|
|
8171
|
-
scope
|
|
8148
|
+
scope,
|
|
8172
8149
|
workspace: workspaceId
|
|
8173
8150
|
});
|
|
8174
8151
|
}
|
|
@@ -8474,7 +8451,7 @@ function listenForCallback(server, expectedState, completionUrl, signal, timeout
|
|
|
8474
8451
|
const onAbort = () => finish({ ok: false, error: new SimApiError("Login cancelled.", 0) });
|
|
8475
8452
|
const timer = setTimeout(() => finish({
|
|
8476
8453
|
ok: false,
|
|
8477
|
-
error: new SimApiError(`Timed out after ${Math.round(timeoutMs / 60000)} minutes waiting for the browser. Run sim login again, or use --
|
|
8454
|
+
error: new SimApiError(`Timed out after ${Math.round(timeoutMs / 60000)} minutes waiting for the browser. Run sim login again, or use --browserless if this terminal's browser cannot reach it.`, 0)
|
|
8478
8455
|
}), timeoutMs);
|
|
8479
8456
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
8480
8457
|
server.on("request", (request, response) => {
|
|
@@ -8723,7 +8700,6 @@ var V2_OPERATIONS = {
|
|
|
8723
8700
|
pathParamDocs: { workflowId: "Unique workflow identifier." },
|
|
8724
8701
|
responseMode: "json",
|
|
8725
8702
|
summary: "Apply Workflow Operations",
|
|
8726
|
-
workspaceKeyUnsupported: true,
|
|
8727
8703
|
query: {
|
|
8728
8704
|
dryRun: {
|
|
8729
8705
|
kind: "boolean",
|
|
@@ -8812,7 +8788,7 @@ var V2_OPERATIONS = {
|
|
|
8812
8788
|
},
|
|
8813
8789
|
folderPaths: {
|
|
8814
8790
|
kind: "string",
|
|
8815
|
-
describe: "
|
|
8791
|
+
describe: "Folder paths to include with all their descendants, comma-separated. At most 100 entries, and the files they resolve to count against the same 100-file download ceiling. A path that matches no folder is rejected rather than ignored."
|
|
8816
8792
|
}
|
|
8817
8793
|
}
|
|
8818
8794
|
},
|
|
@@ -9471,7 +9447,7 @@ var V2_OPERATIONS = {
|
|
|
9471
9447
|
kind: "enum",
|
|
9472
9448
|
values: ["streamable-http"],
|
|
9473
9449
|
default: "streamable-http",
|
|
9474
|
-
describe: "Transport
|
|
9450
|
+
describe: "Transport used to communicate with the server. Applied server-side as `streamable-http` when omitted on create."
|
|
9475
9451
|
},
|
|
9476
9452
|
url: {
|
|
9477
9453
|
kind: "string",
|
|
@@ -9490,17 +9466,17 @@ var V2_OPERATIONS = {
|
|
|
9490
9466
|
timeout: {
|
|
9491
9467
|
kind: "integer",
|
|
9492
9468
|
default: 30000,
|
|
9493
|
-
describe: "Per-request timeout in milliseconds.
|
|
9469
|
+
describe: "Per-request timeout in milliseconds. Applied server-side as 30000 when omitted on create."
|
|
9494
9470
|
},
|
|
9495
9471
|
retries: {
|
|
9496
9472
|
kind: "integer",
|
|
9497
9473
|
default: 3,
|
|
9498
|
-
describe: "Number of retries per request.
|
|
9474
|
+
describe: "Number of retries per request. Applied server-side as 3 when omitted on create."
|
|
9499
9475
|
},
|
|
9500
9476
|
enabled: {
|
|
9501
9477
|
kind: "boolean",
|
|
9502
9478
|
default: true,
|
|
9503
|
-
describe: "Whether
|
|
9479
|
+
describe: "Whether the server tools are available to workflows. Applied server-side as true when omitted on create."
|
|
9504
9480
|
},
|
|
9505
9481
|
oauthClientId: {
|
|
9506
9482
|
kind: "string",
|
|
@@ -10398,7 +10374,7 @@ var V2_OPERATIONS = {
|
|
|
10398
10374
|
input: {
|
|
10399
10375
|
kind: "object",
|
|
10400
10376
|
default: {},
|
|
10401
|
-
describe: "
|
|
10377
|
+
describe: "Arguments for the tool, keyed by the parameter ids the tool catalog publishes for it. A parameter whose visibility is `user-only` also accepts an environment-variable reference written as the whole value, `{{VAR_NAME}}`, resolved server-side against the workspace environment; any other value is sent verbatim."
|
|
10402
10378
|
},
|
|
10403
10379
|
credentialId: {
|
|
10404
10380
|
kind: "string",
|
|
@@ -10433,7 +10409,7 @@ var V2_OPERATIONS = {
|
|
|
10433
10409
|
},
|
|
10434
10410
|
executionTimeoutSeconds: {
|
|
10435
10411
|
kind: "integer",
|
|
10436
|
-
describe: "
|
|
10412
|
+
describe: "Requested server-side timeout for an asynchronous run, in seconds. An upper bound, not the effective timeout: the run uses the smaller of this value and the plan's execution timeout, so requesting more than the plan allows silently yields the plan timeout. Rejected with `400` unless `async` is true."
|
|
10437
10413
|
},
|
|
10438
10414
|
stream: {
|
|
10439
10415
|
kind: "boolean",
|
|
@@ -10442,7 +10418,7 @@ var V2_OPERATIONS = {
|
|
|
10442
10418
|
},
|
|
10443
10419
|
selectedOutputs: {
|
|
10444
10420
|
kind: "array",
|
|
10445
|
-
describe: "
|
|
10421
|
+
describe: "Block output references to include in a streamed response. Use `<blockName>.<outputPath>` for the executed workflow or `<childWorkflowId>.<blockName>.<outputPath>` for a child workflow; block names are normalized workflow reference names. Selecting a child workflow applies to every invocation of it. Requires `stream: true` — it shapes the streamed envelope only, so it is rejected on a sync request and when `async` is true. To narrow a finished run, pass `selectedOutputs` to the run resource instead."
|
|
10446
10422
|
},
|
|
10447
10423
|
includeThinking: {
|
|
10448
10424
|
kind: "boolean",
|
|
@@ -10466,7 +10442,7 @@ var V2_OPERATIONS = {
|
|
|
10466
10442
|
headers: {
|
|
10467
10443
|
"x-run-id": {
|
|
10468
10444
|
kind: "string",
|
|
10469
|
-
describe:
|
|
10445
|
+
describe: 'Caller-supplied run identifier, available only to API-key callers. A one-shot uniqueness claim, NOT an idempotency key: reusing a value fails with `409` and `error.details.code: "RUN_ID_CONFLICT"` rather than replaying the original result. To retry safely, send a fresh value per attempt, or omit the header and let the server allocate one.'
|
|
10470
10446
|
},
|
|
10471
10447
|
"x-sim-via": {
|
|
10472
10448
|
kind: "string",
|
|
@@ -10690,7 +10666,7 @@ var V2_OPERATIONS = {
|
|
|
10690
10666
|
},
|
|
10691
10667
|
folderPaths: {
|
|
10692
10668
|
kind: "string",
|
|
10693
|
-
describe: "Comma-separated workflow folder paths
|
|
10669
|
+
describe: "Comma-separated workflow folder paths to include. At most 100 entries. A path covers its whole subtree. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error."
|
|
10694
10670
|
},
|
|
10695
10671
|
triggers: {
|
|
10696
10672
|
kind: "string",
|
|
@@ -10712,7 +10688,7 @@ var V2_OPERATIONS = {
|
|
|
10712
10688
|
segmentCount: {
|
|
10713
10689
|
kind: "integer",
|
|
10714
10690
|
default: 72,
|
|
10715
|
-
describe: "Number of time buckets,
|
|
10691
|
+
describe: "Number of equal time buckets to divide the window into, from 1 to 500. Exactly this many buckets are always returned. 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."
|
|
10716
10692
|
}
|
|
10717
10693
|
}
|
|
10718
10694
|
},
|
|
@@ -11168,7 +11144,7 @@ var V2_OPERATIONS = {
|
|
|
11168
11144
|
source: {
|
|
11169
11145
|
kind: "enum",
|
|
11170
11146
|
values: ["builtin", "custom"],
|
|
11171
|
-
describe: "Restrict to
|
|
11147
|
+
describe: "Restrict to shipped blocks or to this workspace’s deployed custom blocks."
|
|
11172
11148
|
},
|
|
11173
11149
|
sortBy: {
|
|
11174
11150
|
kind: "enum",
|
|
@@ -11367,7 +11343,7 @@ var V2_OPERATIONS = {
|
|
|
11367
11343
|
},
|
|
11368
11344
|
parentPath: {
|
|
11369
11345
|
kind: "string",
|
|
11370
|
-
describe: "Restrict results to direct children of this parent path.
|
|
11346
|
+
describe: "Restrict results to direct children of this parent path. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error."
|
|
11371
11347
|
},
|
|
11372
11348
|
search: {
|
|
11373
11349
|
kind: "string",
|
|
@@ -11429,7 +11405,7 @@ var V2_OPERATIONS = {
|
|
|
11429
11405
|
},
|
|
11430
11406
|
folderPath: {
|
|
11431
11407
|
kind: "string",
|
|
11432
|
-
describe: "Restrict
|
|
11408
|
+
describe: "Restrict results to files inside this folder — its direct children, or its whole subtree when `recursive` is true. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error."
|
|
11433
11409
|
},
|
|
11434
11410
|
recursive: {
|
|
11435
11411
|
kind: "enum",
|
|
@@ -11447,7 +11423,7 @@ var V2_OPERATIONS = {
|
|
|
11447
11423
|
"n",
|
|
11448
11424
|
"disabled"
|
|
11449
11425
|
],
|
|
11450
|
-
describe: "
|
|
11426
|
+
describe: "Whether the folder filter includes files in subfolders. Defaults to true when a search is set, false otherwise, so listing a folder shows that folder while searching one looks through everything in it. Ignored when no folder filter is set, which already spans the workspace. The listed spellings are the whole accepted vocabulary and are case-sensitive; any other value is rejected."
|
|
11451
11427
|
},
|
|
11452
11428
|
scope: {
|
|
11453
11429
|
kind: "enum",
|
|
@@ -11498,11 +11474,11 @@ var V2_OPERATIONS = {
|
|
|
11498
11474
|
kind: "enum",
|
|
11499
11475
|
values: ["active", "archived"],
|
|
11500
11476
|
default: "active",
|
|
11501
|
-
describe: "
|
|
11477
|
+
describe: "Which lifecycle set to list: `active` (default) for live knowledge bases, `archived` for knowledge bases a `DELETE` archived and `POST /knowledge/{knowledgeBaseId}/restore` can bring back. `folderPath` resolves against active folders only, so pairing it with `scope=archived` returns an empty page when the containing folder was archived too."
|
|
11502
11478
|
},
|
|
11503
11479
|
folderPath: {
|
|
11504
11480
|
kind: "string",
|
|
11505
|
-
describe: "Restrict results to knowledge bases in this folder.
|
|
11481
|
+
describe: "Restrict results to knowledge bases in this folder. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error."
|
|
11506
11482
|
},
|
|
11507
11483
|
search: {
|
|
11508
11484
|
kind: "string",
|
|
@@ -11722,7 +11698,7 @@ var V2_OPERATIONS = {
|
|
|
11722
11698
|
},
|
|
11723
11699
|
parentPath: {
|
|
11724
11700
|
kind: "string",
|
|
11725
|
-
describe: "Restrict results to direct children of this parent path.
|
|
11701
|
+
describe: "Restrict results to direct children of this parent path. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error."
|
|
11726
11702
|
},
|
|
11727
11703
|
search: {
|
|
11728
11704
|
kind: "string",
|
|
@@ -11873,7 +11849,7 @@ var V2_OPERATIONS = {
|
|
|
11873
11849
|
},
|
|
11874
11850
|
folderPaths: {
|
|
11875
11851
|
kind: "string",
|
|
11876
|
-
describe: "Comma-separated workflow folder paths
|
|
11852
|
+
describe: "Comma-separated workflow folder paths to include. At most 100 entries. A path covers its whole subtree, so `/prod` also selects runs in `/prod/nested`. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error."
|
|
11877
11853
|
}
|
|
11878
11854
|
}
|
|
11879
11855
|
},
|
|
@@ -11932,7 +11908,7 @@ var V2_OPERATIONS = {
|
|
|
11932
11908
|
},
|
|
11933
11909
|
refresh: {
|
|
11934
11910
|
kind: "boolean",
|
|
11935
|
-
describe: "
|
|
11911
|
+
describe: "Bypass the short-lived per-workspace tool cache and reconnect under your own credentials. A cached result reflects whichever workspace member last ran discovery, so this is the only way to pick up a tool added since then; it costs a live round trip."
|
|
11936
11912
|
}
|
|
11937
11913
|
}
|
|
11938
11914
|
},
|
|
@@ -12110,7 +12086,7 @@ var V2_OPERATIONS = {
|
|
|
12110
12086
|
},
|
|
12111
12087
|
parentPath: {
|
|
12112
12088
|
kind: "string",
|
|
12113
|
-
describe: "Restrict results to direct children of this parent path.
|
|
12089
|
+
describe: "Restrict results to direct children of this parent path. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error."
|
|
12114
12090
|
},
|
|
12115
12091
|
search: {
|
|
12116
12092
|
kind: "string",
|
|
@@ -12174,7 +12150,7 @@ var V2_OPERATIONS = {
|
|
|
12174
12150
|
},
|
|
12175
12151
|
folderPath: {
|
|
12176
12152
|
kind: "string",
|
|
12177
|
-
describe: "Restrict results to tables in this folder.
|
|
12153
|
+
describe: "Restrict results to tables in this folder. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error."
|
|
12178
12154
|
},
|
|
12179
12155
|
search: {
|
|
12180
12156
|
kind: "string",
|
|
@@ -12276,7 +12252,7 @@ var V2_OPERATIONS = {
|
|
|
12276
12252
|
},
|
|
12277
12253
|
parentPath: {
|
|
12278
12254
|
kind: "string",
|
|
12279
|
-
describe: "Restrict results to direct children of this parent path.
|
|
12255
|
+
describe: "Restrict results to direct children of this parent path. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error."
|
|
12280
12256
|
},
|
|
12281
12257
|
search: {
|
|
12282
12258
|
kind: "string",
|
|
@@ -12411,7 +12387,7 @@ var V2_OPERATIONS = {
|
|
|
12411
12387
|
},
|
|
12412
12388
|
folderPath: {
|
|
12413
12389
|
kind: "string",
|
|
12414
|
-
describe: "Restrict results to workflows in this folder path.
|
|
12390
|
+
describe: "Restrict results to workflows in this folder path. A path that names no folder narrows the result to nothing, so the response is an empty page rather than an error."
|
|
12415
12391
|
},
|
|
12416
12392
|
deployedOnly: {
|
|
12417
12393
|
kind: "boolean",
|
|
@@ -12718,7 +12694,6 @@ var V2_OPERATIONS = {
|
|
|
12718
12694
|
pathParamDocs: { workflowId: "Unique workflow identifier." },
|
|
12719
12695
|
responseMode: "json",
|
|
12720
12696
|
summary: "Create or Replace Workflow Chat Deployment",
|
|
12721
|
-
workspaceKeyUnsupported: true,
|
|
12722
12697
|
body: {
|
|
12723
12698
|
identifier: {
|
|
12724
12699
|
kind: "string",
|
|
@@ -12771,7 +12746,6 @@ var V2_OPERATIONS = {
|
|
|
12771
12746
|
pathParamDocs: { workflowId: "Unique workflow identifier." },
|
|
12772
12747
|
responseMode: "json",
|
|
12773
12748
|
summary: "Replace Workflow State",
|
|
12774
|
-
workspaceKeyUnsupported: true,
|
|
12775
12749
|
query: {
|
|
12776
12750
|
dryRun: {
|
|
12777
12751
|
kind: "boolean",
|
|
@@ -13208,11 +13182,6 @@ var V2_OPERATIONS = {
|
|
|
13208
13182
|
},
|
|
13209
13183
|
apiToken: { kind: "string", describe: "Write-only provider API token." },
|
|
13210
13184
|
domain: { kind: "string", describe: "Provider account domain." },
|
|
13211
|
-
atlassianProduct: {
|
|
13212
|
-
kind: "enum",
|
|
13213
|
-
values: ["jira", "confluence"],
|
|
13214
|
-
describe: "Atlassian product to verify; defaults to Jira on create and preserves the saved product on reconnect."
|
|
13215
|
-
},
|
|
13216
13185
|
signingSecret: { kind: "string", describe: "Write-only webhook signing secret." },
|
|
13217
13186
|
botToken: { kind: "string", describe: "Write-only bot token." },
|
|
13218
13187
|
clientId: { kind: "string", describe: "OAuth client identifier." },
|
|
@@ -13463,7 +13432,7 @@ var V2_OPERATIONS = {
|
|
|
13463
13432
|
kind: "enum",
|
|
13464
13433
|
values: ["streamable-http"],
|
|
13465
13434
|
default: "streamable-http",
|
|
13466
|
-
describe: "Transport
|
|
13435
|
+
describe: "Transport used to communicate with the server. Applied server-side as `streamable-http` when omitted on create."
|
|
13467
13436
|
},
|
|
13468
13437
|
url: {
|
|
13469
13438
|
kind: "string",
|
|
@@ -13481,17 +13450,17 @@ var V2_OPERATIONS = {
|
|
|
13481
13450
|
timeout: {
|
|
13482
13451
|
kind: "integer",
|
|
13483
13452
|
default: 30000,
|
|
13484
|
-
describe: "Per-request timeout in milliseconds.
|
|
13453
|
+
describe: "Per-request timeout in milliseconds. Applied server-side as 30000 when omitted on create."
|
|
13485
13454
|
},
|
|
13486
13455
|
retries: {
|
|
13487
13456
|
kind: "integer",
|
|
13488
13457
|
default: 3,
|
|
13489
|
-
describe: "Number of retries per request.
|
|
13458
|
+
describe: "Number of retries per request. Applied server-side as 3 when omitted on create."
|
|
13490
13459
|
},
|
|
13491
13460
|
enabled: {
|
|
13492
13461
|
kind: "boolean",
|
|
13493
13462
|
default: true,
|
|
13494
|
-
describe: "Whether
|
|
13463
|
+
describe: "Whether the server tools are available to workflows. Applied server-side as true when omitted on create."
|
|
13495
13464
|
},
|
|
13496
13465
|
oauthClientId: {
|
|
13497
13466
|
kind: "string",
|
|
@@ -13975,12 +13944,12 @@ function addProfileCommand() {
|
|
|
13975
13944
|
console.log(source_default.dim(` Try: sim --profile ${safeOneLine(profileName)} whoami`));
|
|
13976
13945
|
});
|
|
13977
13946
|
}
|
|
13978
|
-
async function chooseLoginFlow(profile, options) {
|
|
13947
|
+
async function chooseLoginFlow(profile, options, scope) {
|
|
13979
13948
|
requireSecureEndpoint(profile.endpoint);
|
|
13980
|
-
if (options.
|
|
13949
|
+
if (options.browserless || scope === "copilot")
|
|
13981
13950
|
return "handoff";
|
|
13982
|
-
if (
|
|
13983
|
-
console.log(source_default.dim(`This looks like a remote session
|
|
13951
|
+
if (isLikelyRemoteSession() && options.callbackPort === undefined) {
|
|
13952
|
+
console.log(source_default.dim(`This looks like a remote session, so the browser on this machine cannot finish an OAuth login; using the pairing code instead. Forward a port and pass --callback-port <port> to sign in through the browser anyway.
|
|
13984
13953
|
`));
|
|
13985
13954
|
return "handoff";
|
|
13986
13955
|
}
|
|
@@ -13989,10 +13958,7 @@ async function chooseLoginFlow(profile, options) {
|
|
|
13989
13958
|
throw new SimApiError(`Could not reach ${profile.endpoint}. Check the endpoint.`, 0);
|
|
13990
13959
|
}
|
|
13991
13960
|
if (status === "unavailable") {
|
|
13992
|
-
|
|
13993
|
-
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);
|
|
13994
|
-
}
|
|
13995
|
-
console.log(source_default.dim(`${profile.endpoint} does not offer OAuth sign-in; using the pairing code to create a personal API key.
|
|
13961
|
+
console.log(source_default.dim(`${profile.endpoint} does not offer OAuth sign-in; using the pairing code instead.
|
|
13996
13962
|
`));
|
|
13997
13963
|
return "handoff";
|
|
13998
13964
|
}
|
|
@@ -14070,12 +14036,16 @@ Waiting for you to approve in the browser…`));
|
|
|
14070
14036
|
}
|
|
14071
14037
|
}
|
|
14072
14038
|
function loginCommand() {
|
|
14073
|
-
return new Command("login").description("Sign in through the browser and store the login for the profile").
|
|
14039
|
+
return new Command("login").description("Sign in through the browser and store the login for the profile").option("--scope <scope>", 'Key space for the pairing-code handoff; only "copilot" changes anything, and it forces that flow', "platform").option("--no-browser", "Print the URL instead of opening a browser").option("--browserless", "Use the pairing-code handoff for a terminal whose browser cannot reach it (SSH, containers)").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) => {
|
|
14074
14040
|
const profile = profileFrom(command, { allowUnknownProfile: true });
|
|
14075
14041
|
const authProfile = resolveAuthenticationProfileName(profile.name);
|
|
14076
14042
|
if (authProfile !== profile.name) {
|
|
14077
14043
|
throw new SimApiError(`Profile "${redact(profile.name)}" shares authentication with "${redact(authProfile)}". Run: sim login --profile ${redact(authProfile)}`, 0);
|
|
14078
14044
|
}
|
|
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;
|
|
14079
14049
|
const snapshot = readLoginProfileSnapshot(profile.name);
|
|
14080
14050
|
const storedCredential = snapshot.credential;
|
|
14081
14051
|
if (storedCredential?.kind === "oauth") {
|
|
@@ -14089,13 +14059,13 @@ function loginCommand() {
|
|
|
14089
14059
|
}
|
|
14090
14060
|
}
|
|
14091
14061
|
const callbackPort = parseCallbackPort(options.callbackPort);
|
|
14092
|
-
const loginFlow = await chooseLoginFlow(profile, options);
|
|
14062
|
+
const loginFlow = await chooseLoginFlow(profile, options, scope);
|
|
14093
14063
|
if (loginFlow === "handoff") {
|
|
14094
14064
|
if (options.readOnly) {
|
|
14095
|
-
throw new SimApiError("
|
|
14065
|
+
throw new SimApiError("The pairing-code handoff cannot issue a read-only login; it mints a full API key. Drop --read-only, or sign in through the browser.", 0);
|
|
14096
14066
|
}
|
|
14097
14067
|
if (callbackPort !== undefined) {
|
|
14098
|
-
throw new SimApiError("
|
|
14068
|
+
throw new SimApiError("The pairing-code handoff has no local callback, so --callback-port does not apply. Drop it, or sign in through the browser.", 0);
|
|
14099
14069
|
}
|
|
14100
14070
|
}
|
|
14101
14071
|
await withProfileLoginLease(profile.name, async () => {
|
|
@@ -14104,13 +14074,13 @@ function loginCommand() {
|
|
|
14104
14074
|
await loginWithOAuth(profile, options, callbackPort, snapshot);
|
|
14105
14075
|
return;
|
|
14106
14076
|
}
|
|
14107
|
-
await loginWithHandoff(profile, options, snapshot);
|
|
14077
|
+
await loginWithHandoff(profile, options, scope, snapshot);
|
|
14108
14078
|
});
|
|
14109
14079
|
});
|
|
14110
14080
|
}
|
|
14111
|
-
async function loginWithHandoff(profile, options, expected) {
|
|
14081
|
+
async function loginWithHandoff(profile, options, scope, expected) {
|
|
14112
14082
|
const auth = createAuthRequest();
|
|
14113
|
-
const url = buildApprovalUrl(profile.endpoint, auth, profile.workspaceId ?? undefined);
|
|
14083
|
+
const url = buildApprovalUrl(profile.endpoint, auth, scope, profile.workspaceId ?? undefined);
|
|
14114
14084
|
console.log(`Signing in to ${source_default.bold(profile.endpoint)} as profile ${source_default.bold(safeOneLine(profile.name))}`);
|
|
14115
14085
|
console.log(`
|
|
14116
14086
|
Pairing code: ${source_default.bold(auth.pairing)}`);
|
|
@@ -14123,8 +14093,8 @@ Pairing code: ${source_default.bold(auth.pairing)}`);
|
|
|
14123
14093
|
Waiting for approval…`));
|
|
14124
14094
|
const key = await pollForKey(profile.endpoint, auth);
|
|
14125
14095
|
try {
|
|
14126
|
-
if (key.scope !==
|
|
14127
|
-
throw new SimApiError(`Server issued a ${key.scope} key
|
|
14096
|
+
if (key.scope !== scope) {
|
|
14097
|
+
throw new SimApiError(`Server issued a ${key.scope} key but this profile needs a ${scope} key. Update the Sim deployment, or run: sim login --scope ${key.scope}`, 0);
|
|
14128
14098
|
}
|
|
14129
14099
|
const settings = {
|
|
14130
14100
|
endpoint: profile.endpoint,
|
|
@@ -16087,30 +16057,7 @@ function buildRequest(operation, positional, flags, workspaceId) {
|
|
|
16087
16057
|
}
|
|
16088
16058
|
|
|
16089
16059
|
// src/runtime/options.ts
|
|
16090
|
-
var
|
|
16091
|
-
var COMPLETE_LIST_OPERATIONS = new Set([
|
|
16092
|
-
"listBlocks",
|
|
16093
|
-
"listChatDeployments",
|
|
16094
|
-
"listCredentials",
|
|
16095
|
-
"listCustomTools",
|
|
16096
|
-
"listFiles",
|
|
16097
|
-
"listKnowledgeBases",
|
|
16098
|
-
"listKnowledgeConnectors",
|
|
16099
|
-
"listMcpServers",
|
|
16100
|
-
"listSandboxes",
|
|
16101
|
-
"listSecrets",
|
|
16102
|
-
"listSkillEditors",
|
|
16103
|
-
"listSkills",
|
|
16104
|
-
"listTables",
|
|
16105
|
-
"listTools",
|
|
16106
|
-
"listWorkflowMcpServers",
|
|
16107
|
-
"listWorkflows",
|
|
16108
|
-
"listWorkspaceMembers",
|
|
16109
|
-
"listWorkspaces"
|
|
16110
|
-
]);
|
|
16111
|
-
function defaultListLimit(operation) {
|
|
16112
|
-
return COMPLETE_LIST_OPERATIONS.has(operation) ? 0 : 100;
|
|
16113
|
-
}
|
|
16060
|
+
var DEFAULT_LIMIT = 100;
|
|
16114
16061
|
function describeField(flag, descriptor, name, field) {
|
|
16115
16062
|
return flag.describe ?? descriptor.describe ?? `Set ${name.replaceAll("-", " ") || field}`;
|
|
16116
16063
|
}
|
|
@@ -16123,21 +16070,15 @@ function withoutWireVocabulary(documented) {
|
|
|
16123
16070
|
}
|
|
16124
16071
|
var NON_PAGINATED_LIMIT_HINT = " (caps a --filter match only; omit it to act on every match, and note 0 is not accepted)";
|
|
16125
16072
|
function addFieldOption(command, operation, field, descriptor, slot, paginates, capsAFilter) {
|
|
16126
|
-
if (field === PROFILE_INJECTED_FIELD)
|
|
16127
|
-
return;
|
|
16128
|
-
if (field === "cursor") {
|
|
16129
|
-
if (paginates && defaultListLimit(operation) > 0) {
|
|
16130
|
-
command.option("--cursor <value>", "Continue from nextCursor returned by a previous result");
|
|
16131
|
-
}
|
|
16073
|
+
if (field === PROFILE_INJECTED_FIELD || field === "cursor")
|
|
16132
16074
|
return;
|
|
16133
|
-
}
|
|
16134
16075
|
const flag = flagSpecFor(operation, field);
|
|
16135
16076
|
if (flag.omit)
|
|
16136
16077
|
return;
|
|
16137
16078
|
const name = flagNameFor(operation, field);
|
|
16138
16079
|
const short = flag.short ? `-${flag.short}, ` : "";
|
|
16139
16080
|
if (paginates && field === "limit" && (descriptor.kind === "number" || descriptor.kind === "integer")) {
|
|
16140
|
-
command.option("--limit <n>", "Maximum items to return (0 for everything)", String(
|
|
16081
|
+
command.option("--limit <n>", "Maximum items to return (0 for everything)", String(DEFAULT_LIMIT));
|
|
16141
16082
|
return;
|
|
16142
16083
|
}
|
|
16143
16084
|
const documented = `${describeField(flag, descriptor, name, field)}${capsAFilter && field === "limit" && (descriptor.kind === "number" || descriptor.kind === "integer") ? NON_PAGINATED_LIMIT_HINT : ""}`;
|
|
@@ -16497,10 +16438,11 @@ function unwrapResource(data) {
|
|
|
16497
16438
|
const [, value] = entries[0];
|
|
16498
16439
|
return value && typeof value === "object" && !Array.isArray(value) ? value : data;
|
|
16499
16440
|
}
|
|
16500
|
-
function renderPage(format,
|
|
16441
|
+
function renderPage(format, rows, spec, envelope, options = {}) {
|
|
16501
16442
|
writePageNote(spec, envelope);
|
|
16502
16443
|
writeEnvelopeTruncation(envelope);
|
|
16503
|
-
|
|
16444
|
+
writeCursorTruncation(rows.length, options.truncated === true);
|
|
16445
|
+
printList(format, rows, spec.columns ? columnsFrom(spec.columns) : inferColumns(rows, spec.expand));
|
|
16504
16446
|
}
|
|
16505
16447
|
function writePageNote(spec, envelope) {
|
|
16506
16448
|
if (!spec.pageNote)
|
|
@@ -16545,6 +16487,12 @@ function writeEnvelopeTruncation(envelope) {
|
|
|
16545
16487
|
`));
|
|
16546
16488
|
}
|
|
16547
16489
|
}
|
|
16490
|
+
function writeCursorTruncation(count, truncated) {
|
|
16491
|
+
if (!truncated)
|
|
16492
|
+
return;
|
|
16493
|
+
process.stderr.write(source_default.dim(`showing the first ${count}; more results exist — re-run with --limit 0 for all
|
|
16494
|
+
`));
|
|
16495
|
+
}
|
|
16548
16496
|
function renderResult(operation, format, raw, spec, options = {}, envelope) {
|
|
16549
16497
|
writeEnvelopeTruncation(envelope);
|
|
16550
16498
|
if (spec.document) {
|
|
@@ -16681,8 +16629,8 @@ function bulkFailureMessage(operation, payload, body) {
|
|
|
16681
16629
|
var EXCLUSIVE_CAP_FIELDS = {
|
|
16682
16630
|
deleteTableRows: { cap: "limit", ids: "rowIds" }
|
|
16683
16631
|
};
|
|
16684
|
-
function readPagedLimit(raw
|
|
16685
|
-
const text = String(raw ??
|
|
16632
|
+
function readPagedLimit(raw) {
|
|
16633
|
+
const text = String(raw ?? DEFAULT_LIMIT).trim();
|
|
16686
16634
|
const value = text === "" ? Number.NaN : Number(text);
|
|
16687
16635
|
if (!Number.isInteger(value) || value < 0) {
|
|
16688
16636
|
throw new SimApiError("--limit must be a whole number of 0 or more (0 for everything)", 0);
|
|
@@ -16757,33 +16705,24 @@ async function executeOperation(operation, commandSpec, operationSpec, invocatio
|
|
|
16757
16705
|
const omitsWorkspace = commandSpec.allWorkspaces && requestFlags.allWorkspaces === true;
|
|
16758
16706
|
const needsWorkspace = (hasWorkspaceField || commandSpec.profileWorkspacePath === true) && !omitsWorkspace;
|
|
16759
16707
|
const paging = cursorSlot(operationSpec);
|
|
16760
|
-
const pagedLimit = paging ? readPagedLimit(requestFlags.limit
|
|
16708
|
+
const pagedLimit = paging ? readPagedLimit(requestFlags.limit) : 0;
|
|
16761
16709
|
const request = buildRequest(operation, positional, requestFlags, needsWorkspace ? client.requireWorkspace() : profile.workspaceId);
|
|
16762
16710
|
if (paging) {
|
|
16763
|
-
const initialCursor = request[paging]?.cursor;
|
|
16764
|
-
if (initialCursor !== undefined && (typeof initialCursor !== "string" || initialCursor.trim() === "")) {
|
|
16765
|
-
throw new SimApiError("--cursor must be a non-empty string", 0);
|
|
16766
|
-
}
|
|
16767
16711
|
const limit = pagedLimit === 0 ? Number.POSITIVE_INFINITY : pagedLimit;
|
|
16712
|
+
const pageSize = Math.min(Number.isFinite(limit) ? limit : DEFAULT_LIMIT, DEFAULT_LIMIT);
|
|
16713
|
+
const pageLimit = "limit" in (operationSpec[paging] ?? {}) ? { limit: pageSize } : {};
|
|
16768
16714
|
const rows = [];
|
|
16769
|
-
const seenCursors = new Set(initialCursor ? [initialCursor] : []);
|
|
16770
16715
|
const progress = pageProgress();
|
|
16771
|
-
let cursor =
|
|
16716
|
+
let cursor = null;
|
|
16772
16717
|
let envelope;
|
|
16773
16718
|
try {
|
|
16774
16719
|
do {
|
|
16775
|
-
const pageSize = Math.min(DEFAULT_PAGE_SIZE, limit - rows.length);
|
|
16776
|
-
const pageLimit = "limit" in (operationSpec[paging] ?? {}) ? { limit: pageSize } : {};
|
|
16777
16720
|
const page = await client.request(request.path, {
|
|
16778
16721
|
method: operationSpec.method,
|
|
16779
16722
|
headers: request.headers,
|
|
16780
16723
|
query: paging === "query" ? { ...request.query, ...pageLimit, cursor } : request.query,
|
|
16781
16724
|
body: paging === "body" ? { ...request.body ?? {}, ...pageLimit, ...cursor ? { cursor } : {} } : request.body
|
|
16782
16725
|
});
|
|
16783
|
-
if (page.data.length > pageSize) {
|
|
16784
|
-
throw new SimApiError(`The API returned ${page.data.length} items for a page limit of ${pageSize}; nextCursor would skip unreturned items.`, 0);
|
|
16785
|
-
}
|
|
16786
|
-
assertCursorAdvances(page.nextCursor, seenCursors);
|
|
16787
16726
|
envelope = foldPageEnvelope(envelope, page);
|
|
16788
16727
|
rows.push(...page.data);
|
|
16789
16728
|
cursor = page.nextCursor;
|
|
@@ -16793,7 +16732,7 @@ async function executeOperation(operation, commandSpec, operationSpec, invocatio
|
|
|
16793
16732
|
} finally {
|
|
16794
16733
|
progress.finish();
|
|
16795
16734
|
}
|
|
16796
|
-
renderPage(profile.output,
|
|
16735
|
+
renderPage(profile.output, Number.isFinite(limit) ? rows.slice(0, limit) : rows, commandSpec, envelope, { truncated: Boolean(cursor) });
|
|
16797
16736
|
return;
|
|
16798
16737
|
}
|
|
16799
16738
|
const result = await client.request(request.path, {
|
|
@@ -17301,47 +17240,6 @@ function attachCredentialCommands(program) {
|
|
|
17301
17240
|
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 }));
|
|
17302
17241
|
}
|
|
17303
17242
|
|
|
17304
|
-
// src/http/ndjson.ts
|
|
17305
|
-
async function* readNdjson(body, protocol) {
|
|
17306
|
-
if (!body) {
|
|
17307
|
-
throw new SimApiError(`${protocol} ended without a response body`, 0);
|
|
17308
|
-
}
|
|
17309
|
-
const reader = body.getReader();
|
|
17310
|
-
const decoder = new TextDecoder;
|
|
17311
|
-
let buffer = "";
|
|
17312
|
-
const parse = (line) => {
|
|
17313
|
-
const trimmed = line.trim();
|
|
17314
|
-
if (!trimmed)
|
|
17315
|
-
return;
|
|
17316
|
-
try {
|
|
17317
|
-
return JSON.parse(trimmed);
|
|
17318
|
-
} catch {
|
|
17319
|
-
throw new SimApiError(`${protocol} returned malformed data`, 0);
|
|
17320
|
-
}
|
|
17321
|
-
};
|
|
17322
|
-
try {
|
|
17323
|
-
while (true) {
|
|
17324
|
-
const { done, value } = await reader.read();
|
|
17325
|
-
buffer += done ? decoder.decode() : decoder.decode(value, { stream: true });
|
|
17326
|
-
const lines = buffer.split(`
|
|
17327
|
-
`);
|
|
17328
|
-
buffer = done ? "" : lines.pop() ?? "";
|
|
17329
|
-
for (const line of lines) {
|
|
17330
|
-
const event = parse(line);
|
|
17331
|
-
if (event !== undefined)
|
|
17332
|
-
yield event;
|
|
17333
|
-
}
|
|
17334
|
-
if (done)
|
|
17335
|
-
return;
|
|
17336
|
-
}
|
|
17337
|
-
} finally {
|
|
17338
|
-
reader.cancel().catch(() => {
|
|
17339
|
-
return;
|
|
17340
|
-
});
|
|
17341
|
-
reader.releaseLock();
|
|
17342
|
-
}
|
|
17343
|
-
}
|
|
17344
|
-
|
|
17345
17243
|
// src/commands/protocol/result.ts
|
|
17346
17244
|
function printProtocolResult(format, result) {
|
|
17347
17245
|
const fields = Object.entries(result).map(([key, value]) => [key, text(value)]);
|
|
@@ -17349,28 +17247,72 @@ function printProtocolResult(format, result) {
|
|
|
17349
17247
|
}
|
|
17350
17248
|
|
|
17351
17249
|
// 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
|
+
}
|
|
17352
17260
|
async function readChatStream(response, onChunk) {
|
|
17353
|
-
|
|
17354
|
-
|
|
17355
|
-
|
|
17356
|
-
|
|
17357
|
-
|
|
17358
|
-
|
|
17359
|
-
|
|
17261
|
+
if (!response.body) {
|
|
17262
|
+
throw new SimApiError("Chat stream ended without a response body", 0);
|
|
17263
|
+
}
|
|
17264
|
+
const reader = response.body.getReader();
|
|
17265
|
+
const decoder = new TextDecoder;
|
|
17266
|
+
let buffer = "";
|
|
17267
|
+
let finalResult;
|
|
17268
|
+
const processLine = (line) => {
|
|
17269
|
+
const event = parseChatStreamLine(line);
|
|
17270
|
+
if (!event || event.type === "heartbeat")
|
|
17271
|
+
return false;
|
|
17360
17272
|
if (event.type === "chunk") {
|
|
17361
17273
|
if (event.content)
|
|
17362
17274
|
onChunk(sanitize(event.content));
|
|
17363
|
-
|
|
17275
|
+
return false;
|
|
17364
17276
|
}
|
|
17365
17277
|
if (event.type === "error") {
|
|
17366
17278
|
throw new SimApiError(event.error || "Chat request failed", 0);
|
|
17367
17279
|
}
|
|
17368
17280
|
if (event.type === "final") {
|
|
17369
|
-
|
|
17281
|
+
finalResult = event.data;
|
|
17282
|
+
return true;
|
|
17370
17283
|
}
|
|
17371
17284
|
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
|
+
});
|
|
17372
17315
|
}
|
|
17373
|
-
throw new SimApiError("Chat stream ended without a final result", 0);
|
|
17374
17316
|
}
|
|
17375
17317
|
function ignoreBrokenPipe(stream) {
|
|
17376
17318
|
const onError = (error) => {
|
|
@@ -18145,11 +18087,11 @@ async function listResources(client, config, workspaceId, folderPath, search, li
|
|
|
18145
18087
|
const paginated = "cursor" in V2_OPERATIONS[config.resources].query;
|
|
18146
18088
|
if (!paginated) {
|
|
18147
18089
|
const page = await client.request(path, { query });
|
|
18148
|
-
return page.data.slice(0, limit);
|
|
18090
|
+
return { items: page.data.slice(0, limit), truncated: page.data.length > limit };
|
|
18149
18091
|
}
|
|
18150
|
-
return
|
|
18092
|
+
return requestPages(client, path, {
|
|
18151
18093
|
query,
|
|
18152
|
-
pageSize:
|
|
18094
|
+
pageSize: DEFAULT_LIMIT,
|
|
18153
18095
|
limit
|
|
18154
18096
|
});
|
|
18155
18097
|
}
|
|
@@ -18179,7 +18121,7 @@ function entriesFor(config, folders, resources) {
|
|
|
18179
18121
|
].sort((left, right) => left.name.localeCompare(right.name) || left.kind.localeCompare(right.kind));
|
|
18180
18122
|
}
|
|
18181
18123
|
function attachResourceDirectoryCommands(group, config) {
|
|
18182
|
-
group.command("ls").argument("[path]", "Folder path to list; defaults to the root folder").allowExcessArguments(false).description(`List ${config.kind} resources and child folders together`).option("--search <text>", "Filter folders and resources by name").addOption(new Option("--limit <n>", "Maximum combined items to return (0 for everything)").default(
|
|
18124
|
+
group.command("ls").argument("[path]", "Folder path to list; defaults to the root folder").allowExcessArguments(false).description(`List ${config.kind} resources and child folders together`).option("--search <text>", "Filter folders and resources by name").addOption(new Option("--limit <n>", "Maximum combined items to return (0 for everything)").default(String(DEFAULT_LIMIT))).action(async (path, options, command) => {
|
|
18183
18125
|
const rawLimit = Number(options.limit);
|
|
18184
18126
|
if (!Number.isSafeInteger(rawLimit) || rawLimit < 0) {
|
|
18185
18127
|
throw new SimApiError("--limit must be a whole number of 0 or more (0 for everything)", 0);
|
|
@@ -18192,8 +18134,9 @@ function attachResourceDirectoryCommands(group, config) {
|
|
|
18192
18134
|
listFolders(client, config.folders, workspaceId, folderPath, options.search),
|
|
18193
18135
|
listResources(client, config, workspaceId, folderPath, options.search, limit)
|
|
18194
18136
|
]);
|
|
18195
|
-
const entries = entriesFor(config, folders, resources);
|
|
18137
|
+
const entries = entriesFor(config, folders, resources.items);
|
|
18196
18138
|
const shown = entries.slice(0, limit);
|
|
18139
|
+
writeCursorTruncation(shown.length, resources.truncated || entries.length > limit);
|
|
18197
18140
|
printList(profile.output, shown, COLUMNS2);
|
|
18198
18141
|
});
|
|
18199
18142
|
group.command("mkdir").argument("<path>", "Folder path to create; the leading / is optional").allowExcessArguments(false).description(`Create a ${config.kind} directory at a path`).action(async (path, _options, command) => {
|
|
@@ -18360,7 +18303,6 @@ function attachTableImport(tables) {
|
|
|
18360
18303
|
// src/commands/protocol/workflow-run-follow.ts
|
|
18361
18304
|
var AGENT_STREAM_PROTOCOL_HEADER = "x-sim-stream-protocol";
|
|
18362
18305
|
var AGENT_STREAM_PROTOCOL_V1 = "agent-events-v1";
|
|
18363
|
-
var WORKFLOW_RESULT_STREAM_CONTENT_TYPE = "application/x-ndjson";
|
|
18364
18306
|
var DONE_SENTINEL = "[DONE]";
|
|
18365
18307
|
function resolveWorkflowRunSelection(flags) {
|
|
18366
18308
|
const manual = flags.manual === true;
|
|
@@ -18412,59 +18354,6 @@ function stringField(frame, key) {
|
|
|
18412
18354
|
const value = frame[key];
|
|
18413
18355
|
return typeof value === "string" ? value : null;
|
|
18414
18356
|
}
|
|
18415
|
-
async function readWorkflowResult(response) {
|
|
18416
|
-
const contentType = (response.headers.get("content-type") ?? "").toLowerCase();
|
|
18417
|
-
if (!contentType.includes(WORKFLOW_RESULT_STREAM_CONTENT_TYPE)) {
|
|
18418
|
-
let envelope;
|
|
18419
|
-
try {
|
|
18420
|
-
envelope = await response.json();
|
|
18421
|
-
} catch {
|
|
18422
|
-
throw new SimApiError(`Workflow run returned malformed JSON${contentType ? ` as ${contentType}` : ""}`, response.status);
|
|
18423
|
-
}
|
|
18424
|
-
if (!isRecord(envelope)) {
|
|
18425
|
-
throw new SimApiError("Workflow run returned an invalid result envelope", response.status);
|
|
18426
|
-
}
|
|
18427
|
-
return isRecord(envelope.data) ? envelope.data : envelope;
|
|
18428
|
-
}
|
|
18429
|
-
for await (const value of readNdjson(response.body, "Workflow result stream")) {
|
|
18430
|
-
if (!isRecord(value) || typeof value.type !== "string") {
|
|
18431
|
-
throw new SimApiError("Workflow result stream returned an unknown event", response.status);
|
|
18432
|
-
}
|
|
18433
|
-
if (value.type === "heartbeat")
|
|
18434
|
-
continue;
|
|
18435
|
-
if (value.type === "error") {
|
|
18436
|
-
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);
|
|
18437
|
-
}
|
|
18438
|
-
if (value.type === "final" && isRecord(value.data))
|
|
18439
|
-
return value.data;
|
|
18440
|
-
throw new SimApiError("Workflow result stream returned an unknown event", response.status);
|
|
18441
|
-
}
|
|
18442
|
-
throw new SimApiError("Workflow result stream ended without a final result", response.status);
|
|
18443
|
-
}
|
|
18444
|
-
async function runWithResultStream(workflowId, command) {
|
|
18445
|
-
const flags = command.optsWithGlobals();
|
|
18446
|
-
const { client, profile } = clientFrom(command);
|
|
18447
|
-
const operation = V2_OPERATIONS.executeWorkflow;
|
|
18448
|
-
const commandSpec = CLI_CONTRACT.executeWorkflow ?? {};
|
|
18449
|
-
try {
|
|
18450
|
-
const request = buildRequest("executeWorkflow", [workflowId], flags, profile.workspaceId);
|
|
18451
|
-
const response = await client.requestRaw(request.path, {
|
|
18452
|
-
method: operation.method,
|
|
18453
|
-
query: request.query,
|
|
18454
|
-
body: request.body,
|
|
18455
|
-
headers: { ...request.headers, accept: WORKFLOW_RESULT_STREAM_CONTENT_TYPE }
|
|
18456
|
-
});
|
|
18457
|
-
const payload = await readWorkflowResult(response);
|
|
18458
|
-
renderResult("executeWorkflow", profile.output, payload, commandSpec, {
|
|
18459
|
-
expandedTrace: flags.trace === true
|
|
18460
|
-
});
|
|
18461
|
-
const failure = runFailureMessage("executeWorkflow", payload);
|
|
18462
|
-
if (failure)
|
|
18463
|
-
throw new SimApiError(failure, 0);
|
|
18464
|
-
} catch (error) {
|
|
18465
|
-
throw retypeApiError(error, "executeWorkflow", commandSpec, operation);
|
|
18466
|
-
}
|
|
18467
|
-
}
|
|
18468
18357
|
async function* sseData(body) {
|
|
18469
18358
|
const reader = body.getReader();
|
|
18470
18359
|
const decoder = new TextDecoder;
|
|
@@ -18636,10 +18525,6 @@ function followOrDelegate(previous) {
|
|
|
18636
18525
|
if (flags.includeThinking === true || flags.includeToolCalls === true) {
|
|
18637
18526
|
throw new SimApiError("--include-thinking and --include-tool-calls describe a stream; add --follow", 0);
|
|
18638
18527
|
}
|
|
18639
|
-
if (flags.async !== true) {
|
|
18640
|
-
await runWithResultStream(workflowId, command);
|
|
18641
|
-
return;
|
|
18642
|
-
}
|
|
18643
18528
|
if (previous) {
|
|
18644
18529
|
await previous(command.processedArgs);
|
|
18645
18530
|
return;
|