sim 2.1.5 → 2.1.6-dev.86.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.
Files changed (2) hide show
  1. package/dist/index.js +328 -118
  2. package/package.json +7 -1
package/dist/index.js CHANGED
@@ -2314,6 +2314,30 @@ function credentialsPath() {
2314
2314
  import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2315
2315
  import { dirname } from "node:path";
2316
2316
 
2317
+ // src/embed-context.ts
2318
+ import { AsyncLocalStorage } from "node:async_hooks";
2319
+ function setSoftExitCode(code) {
2320
+ const ctx = embedStore.getStore();
2321
+ if (ctx)
2322
+ ctx.softExitCode = code;
2323
+ else
2324
+ process.exitCode = code;
2325
+ }
2326
+ var embedStore = new AsyncLocalStorage;
2327
+ function embeddedProfile() {
2328
+ const ctx = embedStore.getStore();
2329
+ if (!ctx)
2330
+ return null;
2331
+ return {
2332
+ name: "embedded",
2333
+ endpoint: ctx.identity.endpoint,
2334
+ apiKey: ctx.identity.apiKey,
2335
+ workspaceId: ctx.identity.workspaceId ?? null,
2336
+ output: "json",
2337
+ sources: { endpoint: "flag", apiKey: "flag", workspaceId: "flag", output: "flag" }
2338
+ };
2339
+ }
2340
+
2317
2341
  // src/config/ini.ts
2318
2342
  class ProfileConfigError extends Error {
2319
2343
  constructor(message) {
@@ -2629,6 +2653,9 @@ function refuseBlankOverrides(overrides) {
2629
2653
  }
2630
2654
  }
2631
2655
  function resolveProfile(overrides = {}) {
2656
+ const embedded = embeddedProfile();
2657
+ if (embedded)
2658
+ return embedded;
2632
2659
  refuseBlankOverrides(overrides);
2633
2660
  const named = overrides.profile || process.env.SIM_PROFILE;
2634
2661
  const name = named || DEFAULT_PROFILE;
@@ -2681,14 +2708,22 @@ function resolveProfile(overrides = {}) {
2681
2708
  // src/version.ts
2682
2709
  import { readFileSync as readFileSync2 } from "node:fs";
2683
2710
  function readPackageVersion() {
2684
- const metadata = JSON.parse(readFileSync2(new URL("../package.json", import.meta.url), "utf8"));
2685
- if (typeof metadata !== "object" || metadata === null || !("version" in metadata) || typeof metadata.version !== "string") {
2686
- throw new Error("CLI package metadata is missing a valid version");
2687
- }
2688
- return metadata.version;
2711
+ try {
2712
+ const metadata = JSON.parse(readFileSync2(new URL("../package.json", import.meta.url), "utf8"));
2713
+ if (typeof metadata === "object" && metadata !== null && "version" in metadata && typeof metadata.version === "string") {
2714
+ return metadata.version;
2715
+ }
2716
+ } catch {}
2717
+ return "0.0.0-embedded";
2718
+ }
2719
+ var cachedVersion = null;
2720
+ function cliVersion() {
2721
+ cachedVersion ??= readPackageVersion();
2722
+ return cachedVersion;
2723
+ }
2724
+ function userAgent() {
2725
+ return `sim-cli/${cliVersion()} node/${process.versions.node} (${process.platform}; ${process.arch})`;
2689
2726
  }
2690
- var CLI_VERSION = readPackageVersion();
2691
- var USER_AGENT = `sim-cli/${CLI_VERSION} node/${process.versions.node} (${process.platform}; ${process.arch})`;
2692
2727
 
2693
2728
  // src/http/environment.ts
2694
2729
  var reported = new Set;
@@ -2971,7 +3006,7 @@ class SimClient {
2971
3006
  headers: {
2972
3007
  ...apiKey ? { "x-api-key": apiKey } : {},
2973
3008
  accept: "application/json",
2974
- "user-agent": USER_AGENT,
3009
+ "user-agent": userAgent(),
2975
3010
  ...hasBody ? { "content-type": "application/json" } : {},
2976
3011
  ...options.headers
2977
3012
  },
@@ -6470,7 +6505,7 @@ async function pollForKey(endpoint, auth, signal) {
6470
6505
  headers: {
6471
6506
  "content-type": "application/json",
6472
6507
  accept: "application/json",
6473
- "user-agent": USER_AGENT
6508
+ "user-agent": userAgent()
6474
6509
  },
6475
6510
  body: JSON.stringify({ request: auth.request, verifier: auth.pollSecret }),
6476
6511
  signal,
@@ -6631,8 +6666,8 @@ var V2_OPERATIONS = {
6631
6666
  },
6632
6667
  outputColumns: {
6633
6668
  kind: "array",
6634
- required: true,
6635
- describe: "Columns created for producer outputs."
6669
+ default: [],
6670
+ 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."
6636
6671
  },
6637
6672
  autoRun: {
6638
6673
  kind: "boolean",
@@ -6936,7 +6971,7 @@ var V2_OPERATIONS = {
6936
6971
  rowId: { kind: "string", describe: "Row whose runs should be canceled for row scope." },
6937
6972
  filter: {
6938
6973
  kind: "unknown",
6939
- describe: 'Recursive predicate tree. Each group node is exactly one non-empty `all` or `any` array whose members are further groups or `{ field, op, value }` conditions; the root must be a group, not a bare condition. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
6974
+ describe: 'A single `{ field, op, value }` condition or a recursive `all`/`any` group; either form is normalized to a grouped predicate after validation. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
6940
6975
  },
6941
6976
  excludeRowIds: { kind: "array", describe: "Rows excluded from an all-scope cancellation." }
6942
6977
  }
@@ -6967,6 +7002,11 @@ var V2_OPERATIONS = {
6967
7002
  conversationId: {
6968
7003
  kind: "string",
6969
7004
  describe: "Conversation to continue; a new one starts when omitted."
7005
+ },
7006
+ effort: {
7007
+ kind: "enum",
7008
+ values: ["low", "medium", "high", "xhigh", "max"],
7009
+ describe: "Model effort for this turn; defaults to the deployment default (high)."
6970
7010
  }
6971
7011
  }
6972
7012
  },
@@ -7495,7 +7535,7 @@ var V2_OPERATIONS = {
7495
7535
  description: { kind: "string", describe: "Optional credential description." },
7496
7536
  id: {
7497
7537
  kind: "string",
7498
- describe: "Required only when provider discovery requests a client-generated ID."
7538
+ 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."
7499
7539
  },
7500
7540
  credentials: {
7501
7541
  kind: "string",
@@ -7571,7 +7611,7 @@ var V2_OPERATIONS = {
7571
7611
  rowIds: { kind: "array", describe: "Explicit row subset to run." },
7572
7612
  filter: {
7573
7613
  kind: "unknown",
7574
- describe: 'Recursive predicate tree. Each group node is exactly one non-empty `all` or `any` array whose members are further groups or `{ field, op, value }` conditions; the root must be a group, not a bare condition. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
7614
+ describe: 'A single `{ field, op, value }` condition or a recursive `all`/`any` group; either form is normalized to a grouped predicate after validation. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
7575
7615
  },
7576
7616
  excludeRowIds: { kind: "array", describe: "Rows excluded from a select-all run scope." },
7577
7617
  limit: { kind: "object", describe: "Optional cap on eligible rows to run." }
@@ -8093,7 +8133,7 @@ var V2_OPERATIONS = {
8093
8133
  workspaceId: { kind: "string", required: true, describe: "Unique workspace identifier." },
8094
8134
  filter: {
8095
8135
  kind: "unknown",
8096
- describe: 'Recursive predicate tree. Each group node is exactly one non-empty `all` or `any` array whose members are further groups or `{ field, op, value }` conditions; the root must be a group, not a bare condition. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
8136
+ describe: 'A single `{ field, op, value }` condition or a recursive `all`/`any` group; either form is normalized to a grouped predicate after validation. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
8097
8137
  },
8098
8138
  limit: { kind: "integer", describe: "Maximum matching rows to delete." },
8099
8139
  rowIds: { kind: "array", describe: "Explicit row identifiers to delete." }
@@ -8263,37 +8303,6 @@ var V2_OPERATIONS = {
8263
8303
  }
8264
8304
  }
8265
8305
  },
8266
- executeTool: {
8267
- method: "POST",
8268
- path: "/api/v2/tools/[toolId]/execute",
8269
- pathParams: ["toolId"],
8270
- pathParamDocs: {
8271
- toolId: "Tool identifier. An unversioned name resolves to the newest version, and the response echoes the resolved id."
8272
- },
8273
- responseMode: "json",
8274
- summary: "Run Tool",
8275
- personalKeyOnly: true,
8276
- body: {
8277
- workspaceId: {
8278
- kind: "string",
8279
- required: true,
8280
- describe: "Workspace whose integration allowlist, credentials, and environment variables govern this call."
8281
- },
8282
- input: {
8283
- kind: "object",
8284
- default: {},
8285
- 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."
8286
- },
8287
- credentialId: {
8288
- kind: "string",
8289
- describe: "Credential to authenticate with. Required when the tool declares an OAuth requirement; the workspace credentials list names the candidates."
8290
- },
8291
- timeoutSeconds: {
8292
- kind: "integer",
8293
- describe: "How long to wait for the tool before abandoning the call."
8294
- }
8295
- }
8296
- },
8297
8306
  executeWorkflow: {
8298
8307
  method: "POST",
8299
8308
  path: "/api/v2/workflows/[workflowId]/execute",
@@ -8326,7 +8335,7 @@ var V2_OPERATIONS = {
8326
8335
  },
8327
8336
  selectedOutputs: {
8328
8337
  kind: "array",
8329
- 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."
8338
+ describe: "Block output references to include in the response. Use `<blockName>.<outputPath>` for the executed workflow or `<childWorkflowId>.<blockName>.<outputPath>` for a child workflow; block names are normalized workflow reference names, and selecting a child workflow applies to every invocation of it. On a sync request the named outputs come back in `blockOutputs`, keyed by these selector strings exactly as sent; on a stream they shape the streamed envelope. A selector whose block name or id matches no block in the workflow is rejected with `400` naming the available blocks, before the run starts. A selector whose block did not run or whose path is absent is omitted. Rejected when `async` is true — a queued run has produced nothing to select; narrow the finished run via the run resource instead."
8330
8339
  },
8331
8340
  includeThinking: {
8332
8341
  kind: "boolean",
@@ -8364,7 +8373,13 @@ var V2_OPERATIONS = {
8364
8373
  pathParams: ["workflowId"],
8365
8374
  pathParamDocs: { workflowId: "Unique workflow identifier." },
8366
8375
  responseMode: "json",
8367
- summary: "Export Workflow"
8376
+ summary: "Export Workflow",
8377
+ query: {
8378
+ includeWorkspaceBindings: {
8379
+ kind: "boolean",
8380
+ 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."
8381
+ }
8382
+ }
8368
8383
  },
8369
8384
  getAuditLog: {
8370
8385
  method: "GET",
@@ -8585,6 +8600,10 @@ var V2_OPERATIONS = {
8585
8600
  values: ["info", "error"],
8586
8601
  describe: "Severity level to include."
8587
8602
  },
8603
+ includeHandledErrors: {
8604
+ kind: "boolean",
8605
+ 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."
8606
+ },
8588
8607
  startDate: {
8589
8608
  kind: "string",
8590
8609
  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."
@@ -8596,7 +8615,26 @@ var V2_OPERATIONS = {
8596
8615
  segmentCount: {
8597
8616
  kind: "integer",
8598
8617
  default: 72,
8599
- 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."
8618
+ 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."
8619
+ },
8620
+ includeEmpty: {
8621
+ kind: "enum",
8622
+ values: [
8623
+ "true",
8624
+ "1",
8625
+ "yes",
8626
+ "on",
8627
+ "y",
8628
+ "enabled",
8629
+ "false",
8630
+ "0",
8631
+ "no",
8632
+ "off",
8633
+ "n",
8634
+ "disabled"
8635
+ ],
8636
+ default: false,
8637
+ 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."
8600
8638
  }
8601
8639
  }
8602
8640
  },
@@ -8654,7 +8692,7 @@ var V2_OPERATIONS = {
8654
8692
  groupId: "Workflow or enrichment group to run."
8655
8693
  },
8656
8694
  responseMode: "json",
8657
- summary: "Get Enrichment Run Detail",
8695
+ summary: "Get Row Group Run",
8658
8696
  query: {
8659
8697
  workspaceId: { kind: "string", required: true, describe: "Workspace that owns the table." }
8660
8698
  }
@@ -8978,8 +9016,7 @@ var V2_OPERATIONS = {
8978
9016
  "knowledge-base",
8979
9017
  "voice-input",
8980
9018
  "enrichment",
8981
- "voice-output",
8982
- "api-tool"
9019
+ "voice-output"
8983
9020
  ],
8984
9021
  describe: "Restrict results to one usage source."
8985
9022
  },
@@ -9043,6 +9080,10 @@ var V2_OPERATIONS = {
9043
9080
  values: ["builtin", "custom"],
9044
9081
  describe: "Restrict to shipped blocks or to this workspace’s deployed custom blocks."
9045
9082
  },
9083
+ includeSunset: {
9084
+ kind: "boolean",
9085
+ 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."
9086
+ },
9046
9087
  sortBy: {
9047
9088
  kind: "enum",
9048
9089
  values: ["id", "name", "category"],
@@ -9118,6 +9159,21 @@ var V2_OPERATIONS = {
9118
9159
  search: {
9119
9160
  kind: "string",
9120
9161
  describe: "Case-insensitive substring match against the connector name."
9162
+ },
9163
+ detail: {
9164
+ kind: "enum",
9165
+ values: ["summary", "full"],
9166
+ default: "summary",
9167
+ 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."
9168
+ },
9169
+ limit: {
9170
+ kind: "integer",
9171
+ default: 25,
9172
+ describe: "Maximum connector types to return per page. Must be a whole number from 1 to 100. Defaults to 25."
9173
+ },
9174
+ cursor: {
9175
+ kind: "string",
9176
+ 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."
9121
9177
  }
9122
9178
  }
9123
9179
  },
@@ -9697,6 +9753,10 @@ var V2_OPERATIONS = {
9697
9753
  kind: "string",
9698
9754
  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."
9699
9755
  },
9756
+ includeHandledErrors: {
9757
+ kind: "boolean",
9758
+ 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."
9759
+ },
9700
9760
  status: {
9701
9761
  kind: "string",
9702
9762
  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."
@@ -9907,7 +9967,7 @@ var V2_OPERATIONS = {
9907
9967
  pathParams: ["tableId"],
9908
9968
  pathParamDocs: { tableId: "Unique table identifier." },
9909
9969
  responseMode: "json",
9910
- summary: "List Active Run Dispatches",
9970
+ summary: "List Run Dispatches",
9911
9971
  query: {
9912
9972
  workspaceId: { kind: "string", required: true, describe: "Workspace that owns the table." }
9913
9973
  }
@@ -10319,8 +10379,8 @@ var V2_OPERATIONS = {
10319
10379
  },
10320
10380
  limit: {
10321
10381
  kind: "integer",
10322
- default: 50,
10323
- describe: "Maximum workspaces to return per page. Must be a whole number from 1 to 100. Defaults to 50."
10382
+ default: 25,
10383
+ describe: "Maximum workspaces to return per page. Must be a whole number from 1 to 100. Defaults to 25."
10324
10384
  },
10325
10385
  cursor: {
10326
10386
  kind: "string",
@@ -10432,7 +10492,9 @@ var V2_OPERATIONS = {
10432
10492
  method: "GET",
10433
10493
  path: "/api/v2/files/[fileId]/text",
10434
10494
  pathParams: ["fileId"],
10435
- pathParamDocs: { fileId: "File identifier." },
10495
+ pathParamDocs: {
10496
+ fileId: "File identifier, or the file’s VFS path: `files/<folder>/<name>`, or `uploads/<name>` for a Chat upload."
10497
+ },
10436
10498
  responseMode: "json",
10437
10499
  summary: "Read File Text",
10438
10500
  query: {
@@ -10455,7 +10517,7 @@ var V2_OPERATIONS = {
10455
10517
  destinationPath: {
10456
10518
  kind: "string",
10457
10519
  required: true,
10458
- describe: "New full path for the folder and its descendants."
10520
+ 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)."
10459
10521
  }
10460
10522
  }
10461
10523
  },
@@ -10471,7 +10533,7 @@ var V2_OPERATIONS = {
10471
10533
  destinationPath: {
10472
10534
  kind: "string",
10473
10535
  required: true,
10474
- describe: "New full path for the folder and its descendants."
10536
+ 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)."
10475
10537
  }
10476
10538
  }
10477
10539
  },
@@ -10487,7 +10549,7 @@ var V2_OPERATIONS = {
10487
10549
  destinationPath: {
10488
10550
  kind: "string",
10489
10551
  required: true,
10490
- describe: "New full path for the folder and its descendants."
10552
+ 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)."
10491
10553
  }
10492
10554
  }
10493
10555
  },
@@ -10503,7 +10565,7 @@ var V2_OPERATIONS = {
10503
10565
  destinationPath: {
10504
10566
  kind: "string",
10505
10567
  required: true,
10506
- describe: "New full path for the folder and its descendants."
10568
+ 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)."
10507
10569
  }
10508
10570
  }
10509
10571
  },
@@ -10833,7 +10895,7 @@ var V2_OPERATIONS = {
10833
10895
  q: { kind: "string", required: true, describe: "Case-insensitive cell substring to find." },
10834
10896
  predicate: {
10835
10897
  kind: "unknown",
10836
- describe: 'Recursive predicate tree. Each group node is exactly one non-empty `all` or `any` array whose members are further groups or `{ field, op, value }` conditions; the root must be a group, not a bare condition. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
10898
+ describe: 'A single `{ field, op, value }` condition or a recursive `all`/`any` group; either form is normalized to a grouped predicate after validation. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
10837
10899
  },
10838
10900
  sort: { kind: "array", describe: "Ordered table-row sort specification." }
10839
10901
  }
@@ -11275,7 +11337,7 @@ var V2_OPERATIONS = {
11275
11337
  filter: {
11276
11338
  kind: "unknown",
11277
11339
  required: true,
11278
- describe: 'Recursive predicate tree. Each group node is exactly one non-empty `all` or `any` array whose members are further groups or `{ field, op, value }` conditions; the root must be a group, not a bare condition. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
11340
+ describe: 'A single `{ field, op, value }` condition or a recursive `all`/`any` group; either form is normalized to a grouped predicate after validation. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids.'
11279
11341
  },
11280
11342
  data: {
11281
11343
  kind: "object",
@@ -11859,7 +11921,7 @@ function whoamiCommand() {
11859
11921
  });
11860
11922
  const exitCode = WHOAMI_EXIT_CODES[verification.status];
11861
11923
  if (exitCode !== 0)
11862
- process.exitCode = exitCode;
11924
+ setSoftExitCode(exitCode);
11863
11925
  });
11864
11926
  }
11865
11927
  var PROFILE_COLUMNS = [
@@ -12228,7 +12290,7 @@ var CLI_CONTRACT = {
12228
12290
  },
12229
12291
  deleteTableView: { confirm: "This deletes the saved view and its filters." },
12230
12292
  deleteWorkflowGroup: {
12231
- confirm: "This deletes the group, every column it fed, and the values in them.",
12293
+ confirm: "This deletes the group AND its output columns with all of their row data; the workflow it pointed at is untouched.",
12232
12294
  fields: [
12233
12295
  { header: "id" },
12234
12296
  { header: "deleted", format: "bool" },
@@ -12348,7 +12410,7 @@ var CLI_CONTRACT = {
12348
12410
  },
12349
12411
  applyWorkflowOperations: {
12350
12412
  command: "workflows operations apply",
12351
- confirm: "This edits the draft graph, and a delete operation removes blocks and their edges.",
12413
+ confirm: "This edits the draft graph: the batch adds, edits, or deletes blocks and their edges as written.",
12352
12414
  flags: {
12353
12415
  operations: { json: true, describe: WORKFLOW_OPERATIONS_HELP },
12354
12416
  setBlockEnabled: { json: true, describe: WORKFLOW_SET_BLOCK_ENABLED_HELP }
@@ -13057,24 +13119,6 @@ var CLI_CONTRACT = {
13057
13119
  describe: "Print a workflow as a portable JSON document",
13058
13120
  document: true
13059
13121
  },
13060
- executeTool: {
13061
- command: "tools execute",
13062
- describe: "Run one built-in tool and print what it produced",
13063
- flags: {
13064
- input: {
13065
- json: true,
13066
- describe: "Tool arguments as JSON, keyed by the parameter ids `sim tools get <toolId>` lists"
13067
- },
13068
- credentialId: { describe: "Credential to authenticate with, required for OAuth tools" },
13069
- timeoutSeconds: { name: "timeout", describe: "Seconds to wait before abandoning the call" }
13070
- },
13071
- fields: [
13072
- { path: "toolId", header: "Tool" },
13073
- { path: "status", header: "Status" },
13074
- { path: "output", header: "Output" },
13075
- { path: "error.message", header: "Error" }
13076
- ]
13077
- },
13078
13122
  executeWorkflow: {
13079
13123
  command: "workflows run",
13080
13124
  describe: "Run a deployed workflow or execute saved state manually",
@@ -13088,7 +13132,7 @@ var CLI_CONTRACT = {
13088
13132
  selectedOutputs: {
13089
13133
  name: "select-output",
13090
13134
  list: true,
13091
- describe: "Return streamed outputs as blockName.path or childWorkflowId.blockName.path; selecting a child workflow applies to every invocation, requires --follow"
13135
+ 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"
13092
13136
  },
13093
13137
  stream: { omit: true },
13094
13138
  includeThinking: { omit: true },
@@ -13112,7 +13156,7 @@ var CLI_CONTRACT = {
13112
13156
  selectedOutputs: {
13113
13157
  name: "select-output",
13114
13158
  list: true,
13115
- describe: "Include blockId or blockId.path values in JSON or YAML output; block names are not resolved on a finished run"
13159
+ 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"
13116
13160
  }
13117
13161
  },
13118
13162
  fields: [
@@ -13306,6 +13350,13 @@ function readArgumentSource(raw, flagName) {
13306
13350
  return { text: raw.slice(1), from: "" };
13307
13351
  if (!raw.startsWith("@"))
13308
13352
  return { text: raw, from: "" };
13353
+ const embedded = embedStore.getStore();
13354
+ if (embedded) {
13355
+ const preloaded = embedded.fileArguments?.[raw.slice(1)];
13356
+ if (preloaded !== undefined)
13357
+ return { text: preloaded, from: " (read from your machine)" };
13358
+ throw new SimApiError(`--${flagName}: no file "${raw.slice(1)}" on this machine — write it first (run_code), or pass the value inline`, 0);
13359
+ }
13309
13360
  const path = raw.slice(1);
13310
13361
  if (path === "-") {
13311
13362
  if (process.stdin.isTTY) {
@@ -13961,7 +14012,7 @@ function renderResult(operation, format, raw, spec, options = {}, envelope) {
13961
14012
  printDocument(format, raw);
13962
14013
  return;
13963
14014
  }
13964
- const data = unwrapResource(raw);
14015
+ const data = format === "json" || format === "yaml" ? raw : unwrapResource(raw);
13965
14016
  if (spec.itemsPath) {
13966
14017
  const items = at(data, spec.itemsPath);
13967
14018
  if (!Array.isArray(items)) {
@@ -13989,25 +14040,20 @@ function renderResult(operation, format, raw, spec, options = {}, envelope) {
13989
14040
  }
13990
14041
 
13991
14042
  // src/runtime/execute.ts
13992
- var RUN_OUTCOME_OPERATIONS = {
13993
- executeWorkflow: {
13994
- failed: "The workflow run failed.",
13995
- cancelled: "The workflow run was cancelled."
13996
- },
13997
- executeTool: {
13998
- failed: "The tool call failed."
13999
- }
14043
+ var RUN_OUTCOME_OPERATIONS = new Set(["executeWorkflow"]);
14044
+ var FAILED_RUN_STATUS_MESSAGES = {
14045
+ failed: "The workflow run failed.",
14046
+ cancelled: "The workflow run was cancelled."
14000
14047
  };
14001
14048
  function runFailureMessage(operation, payload) {
14002
- const failureMessages = RUN_OUTCOME_OPERATIONS[operation];
14003
- if (!failureMessages)
14049
+ if (!RUN_OUTCOME_OPERATIONS.has(operation))
14004
14050
  return null;
14005
14051
  if (!payload || typeof payload !== "object" || Array.isArray(payload))
14006
14052
  return null;
14007
14053
  const { status, error } = payload;
14008
14054
  if (typeof status !== "string")
14009
14055
  return null;
14010
- const fallback = failureMessages[status];
14056
+ const fallback = FAILED_RUN_STATUS_MESSAGES[status];
14011
14057
  if (!fallback)
14012
14058
  return null;
14013
14059
  const reported2 = error?.message;
@@ -14080,6 +14126,22 @@ function countOf(value) {
14080
14126
  function lengthOf(value) {
14081
14127
  return Array.isArray(value) ? value.length : 0;
14082
14128
  }
14129
+ var RESULT_NOTES = {
14130
+ replaceWorkflowChatDeployment: (payload, body) => {
14131
+ const authType = payload.authType ?? body?.authType ?? "public";
14132
+ return authType === "public" ? "note: auth type is public — anyone with the link can chat; pass --auth-type password|email to restrict it." : null;
14133
+ }
14134
+ };
14135
+ function writeResultNote(operation, payload, body) {
14136
+ const note = RESULT_NOTES[operation];
14137
+ if (!note)
14138
+ return;
14139
+ const record = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
14140
+ const message = note(record, body);
14141
+ if (message)
14142
+ process.stderr.write(source_default.dim(`${message}
14143
+ `));
14144
+ }
14083
14145
  function bulkFailureMessage(operation, payload, body) {
14084
14146
  const check = BULK_OUTCOME_CHECKS[operation];
14085
14147
  if (!check)
@@ -14205,6 +14267,7 @@ async function executeOperation(operation, commandSpec, operationSpec, invocatio
14205
14267
  });
14206
14268
  const payload = result?.data ?? result;
14207
14269
  renderResult(operation, profile.output, payload, commandSpec, { expandedTrace: requestFlags.trace === true }, result);
14270
+ writeResultNote(operation, payload, request.body);
14208
14271
  const failure = runFailureMessage(operation, payload) ?? bulkFailureMessage(operation, payload, request.body);
14209
14272
  if (failure)
14210
14273
  throw new SimApiError(failure, 0);
@@ -14975,6 +15038,18 @@ async function saveStagedFile(body, target, force) {
14975
15038
  }
14976
15039
  }
14977
15040
  async function saveToFile(body, target, force) {
15041
+ const embedded = embedStore.getStore();
15042
+ if (embedded) {
15043
+ if (!embedded.writeFile) {
15044
+ throw new SimApiError(`--output-file cannot save ${target} here: this surface has no machine to write to. Read the file instead, or pipe a text command with | to-sandbox <name>.`, 0);
15045
+ }
15046
+ const bytes2 = new Uint8Array(await new Response(body).arrayBuffer());
15047
+ const written = await embedded.writeFile(target, bytes2);
15048
+ if (!written) {
15049
+ throw new SimApiError(`Could not write ${target} on your machine — the workbench is not running yet; run any run_code call first, then retry.`, 0);
15050
+ }
15051
+ return;
15052
+ }
14978
15053
  return saveStagedFile(body, target, force);
14979
15054
  }
14980
15055
  async function streamToStdout(body, output = process.stdout) {
@@ -15046,6 +15121,16 @@ function attachFileGet(files) {
15046
15121
  import { constants } from "node:fs";
15047
15122
  import { access, stat } from "node:fs/promises";
15048
15123
  import { basename } from "node:path";
15124
+ function embeddedFileKey(path) {
15125
+ return path.startsWith("@") ? path.slice(1) : path;
15126
+ }
15127
+ function embeddedFileContent(embedded, path) {
15128
+ const key = embeddedFileKey(path);
15129
+ const content = embedded.fileArguments?.[key];
15130
+ if (content !== undefined)
15131
+ return content;
15132
+ throw new SimApiError(`Files on your machine are passed as @path: use @${key}. (If it does not exist yet, write it with run_code or | to-sandbox first.)`, 0);
15133
+ }
15049
15134
  var CONTENT_TYPES = {
15050
15135
  css: "text/css",
15051
15136
  csv: "text/csv",
@@ -15079,6 +15164,14 @@ function contentTypeFor(name) {
15079
15164
  return CONTENT_TYPES[extension] ?? "application/octet-stream";
15080
15165
  }
15081
15166
  async function localFile(path, override) {
15167
+ const embedded = embedStore.getStore();
15168
+ if (embedded) {
15169
+ const content = embeddedFileContent(embedded, path);
15170
+ const size2 = Buffer.byteLength(content);
15171
+ if (size2 === 0)
15172
+ throw new SimApiError(`${path} is empty`, 0);
15173
+ return { name: override ?? basename(embeddedFileKey(path)), size: size2 };
15174
+ }
15082
15175
  let size;
15083
15176
  try {
15084
15177
  const stats = await stat(path);
@@ -15141,7 +15234,8 @@ async function uploadParts(client, workspaceId, session, transfer, blob) {
15141
15234
  }
15142
15235
  async function finishUploadSession(client, workspaceId, session, path) {
15143
15236
  try {
15144
- const blob = await openAsBlob(path);
15237
+ const embedded = embedStore.getStore();
15238
+ const blob = embedded ? new Blob([embeddedFileContent(embedded, path)]) : await openAsBlob(path);
15145
15239
  if (session.transfer.method === "put") {
15146
15240
  await uploadPut(session.transfer, blob);
15147
15241
  } else {
@@ -15247,9 +15341,11 @@ function attachKnowledgeDocumentUpload(documents) {
15247
15341
  printProtocolResult(profile.output, {
15248
15342
  id: completed.document.id,
15249
15343
  knowledgeBaseId: completed.document.knowledgeBaseId,
15250
- name: completed.document.filename,
15251
- size: completed.document.fileSize,
15252
- status: completed.document.processingStatus
15344
+ filename: completed.document.filename,
15345
+ fileSize: completed.document.fileSize,
15346
+ mimeType: completed.document.mimeType,
15347
+ processingStatus: completed.document.processingStatus,
15348
+ chunkCount: completed.document.chunkCount
15253
15349
  });
15254
15350
  });
15255
15351
  }
@@ -15766,14 +15862,11 @@ var AGENT_STREAM_PROTOCOL_HEADER = "x-sim-stream-protocol";
15766
15862
  var AGENT_STREAM_PROTOCOL_V1 = "agent-events-v1";
15767
15863
  var DONE_SENTINEL = "[DONE]";
15768
15864
  function resolveWorkflowRunSelection(flags) {
15769
- const manual = flags.manual === true;
15770
15865
  const trigger = typeof flags.trigger === "string" ? flags.trigger : undefined;
15771
15866
  const useMockPayload = flags.mockPayload === true;
15867
+ const manual = flags.manual === true || trigger !== undefined || useMockPayload;
15772
15868
  const fromBlock = typeof flags.fromBlock === "string" ? flags.fromBlock : undefined;
15773
15869
  const sourceRun = typeof flags.sourceRun === "string" ? flags.sourceRun : undefined;
15774
- if ((trigger || useMockPayload) && !manual) {
15775
- throw new SimApiError("--trigger and --mock-payload require --manual", 0);
15776
- }
15777
15870
  if (fromBlock && (trigger || useMockPayload)) {
15778
15871
  throw new SimApiError("--from-block cannot be combined with --trigger or --mock-payload", 0);
15779
15872
  }
@@ -15980,8 +16073,8 @@ function followOrDelegate(previous) {
15980
16073
  command.setOptionValue("run", selection);
15981
16074
  const flags = command.optsWithGlobals();
15982
16075
  if (flags.follow !== true) {
15983
- if (Array.isArray(flags.selectOutput) && flags.selectOutput.length > 0) {
15984
- throw new SimApiError(flags.async === true ? "--select-output shapes a streamed result, and --async returns as soon as the run is queued, so there is no stream to shape. Drop one of them, or read the finished run with: sim workflows runs get <runId> --workflow <workflowId> --select-output <blockId>[.path] — that resource matches block ids, not the block names --select-output takes here." : "--select-output shapes a streamed result; add --follow. To narrow a run that has already finished: sim workflows runs get <runId> --workflow <workflowId> --select-output <blockId>[.path] — that resource matches block ids, not the block names --select-output takes here.", 0);
16076
+ if (Array.isArray(flags.selectOutput) && flags.selectOutput.length > 0 && flags.async === true) {
16077
+ 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 <blockId>[.path] — that resource matches block ids, not the block names --select-output takes here.", 0);
15985
16078
  }
15986
16079
  if (flags.includeThinking === true || flags.includeToolCalls === true) {
15987
16080
  throw new SimApiError("--include-thinking and --include-tool-calls describe a stream; add --follow", 0);
@@ -16003,7 +16096,119 @@ function attachWorkflowRunFollow(workflows) {
16003
16096
  }
16004
16097
  const held = run._actionHandler;
16005
16098
  const previous = typeof held === "function" ? held : null;
16006
- run.option("--manual", "Run the current saved workflow state instead of the active deployment").option("--trigger <blockId>", "Enter a manual run through this runnable trigger (requires --manual)").option("--mock-payload", "Use the selected trigger's server-derived mock payload (requires --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));
16099
+ 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));
16100
+ }
16101
+
16102
+ // src/commands/protocol/workflow-run-get.ts
16103
+ var BLOCK_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
16104
+ var SELECT_OUTPUT_FLAG = "select-output";
16105
+ function normalizeBlockName(name) {
16106
+ return name.toLowerCase().replace(/\s+/g, "").replace(/\./g, "");
16107
+ }
16108
+ function isRecord2(value) {
16109
+ return typeof value === "object" && value !== null && !Array.isArray(value);
16110
+ }
16111
+ async function loadWorkflowBlocks(client, workflowId) {
16112
+ const operation = V2_OPERATIONS.getWorkflowState;
16113
+ const raw = await client.request(resolvePath(operation.path, { workflowId }), {
16114
+ method: operation.method
16115
+ });
16116
+ const state = isRecord2(raw) && isRecord2(raw.data) ? raw.data : raw;
16117
+ const blocks = isRecord2(state) && isRecord2(state.blocks) ? Object.entries(state.blocks) : [];
16118
+ return blocks.map(([key, block]) => ({
16119
+ id: isRecord2(block) && typeof block.id === "string" ? block.id : key,
16120
+ name: isRecord2(block) && typeof block.name === "string" ? block.name : ""
16121
+ }));
16122
+ }
16123
+ function splitSelector(selector) {
16124
+ const dot = selector.indexOf(".");
16125
+ return dot === -1 ? { head: selector, path: "" } : { head: selector.slice(0, dot), path: selector.slice(dot) };
16126
+ }
16127
+ function isIdHeaded(selector) {
16128
+ return BLOCK_ID.test(splitSelector(selector).head);
16129
+ }
16130
+ function resolveSelection(typed, blocks, workflowId) {
16131
+ const resolved = [];
16132
+ const typedBy = new Map;
16133
+ const unresolved = [];
16134
+ for (const selector of typed) {
16135
+ const { head, path } = splitSelector(selector);
16136
+ let blockId = head;
16137
+ if (!BLOCK_ID.test(head)) {
16138
+ const wanted = normalizeBlockName(head);
16139
+ const matches = blocks.filter((block) => block.id === head || normalizeBlockName(block.name) === wanted);
16140
+ if (matches.length === 0) {
16141
+ unresolved.push(selector);
16142
+ continue;
16143
+ }
16144
+ if (matches.length > 1) {
16145
+ throw new SimApiError(`--${SELECT_OUTPUT_FLAG} ${selector} names ${matches.length} blocks (${matches.map((block) => block.id).join(", ")}); pass the block id instead`, 0);
16146
+ }
16147
+ blockId = matches[0].id;
16148
+ }
16149
+ const rewritten = `${blockId}${path}`;
16150
+ resolved.push(rewritten);
16151
+ if (!typedBy.has(rewritten))
16152
+ typedBy.set(rewritten, selector);
16153
+ }
16154
+ if (unresolved.length > 0) {
16155
+ const names = blocks.map((block) => block.name).filter((name) => name !== "");
16156
+ 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);
16157
+ }
16158
+ return { resolved, typedBy };
16159
+ }
16160
+ function keyByTyped(payload, typedBy) {
16161
+ if (!isRecord2(payload) || !isRecord2(payload.blockOutputs))
16162
+ return payload;
16163
+ const blockOutputs = {};
16164
+ for (const [key, value] of Object.entries(payload.blockOutputs)) {
16165
+ blockOutputs[typedBy.get(key) ?? key] = value;
16166
+ }
16167
+ return { ...payload, blockOutputs };
16168
+ }
16169
+ async function readRunByName(runId, typed, command) {
16170
+ const flags = command.optsWithGlobals();
16171
+ const { client, profile } = clientFrom(command);
16172
+ const operation = V2_OPERATIONS.getWorkflowRun;
16173
+ const spec = CLI_CONTRACT.getWorkflowRun ?? {};
16174
+ buildRequest("getWorkflowRun", [runId], flags, profile.workspaceId);
16175
+ const workflowId = String(flags.workflow);
16176
+ const selection = resolveSelection(typed, await loadWorkflowBlocks(client, workflowId), workflowId);
16177
+ const request = buildRequest("getWorkflowRun", [runId], { ...flags, selectOutput: selection.resolved }, profile.workspaceId);
16178
+ let result;
16179
+ try {
16180
+ result = await client.request(request.path, {
16181
+ method: operation.method,
16182
+ headers: request.headers,
16183
+ query: request.query,
16184
+ body: request.body
16185
+ });
16186
+ } catch (error) {
16187
+ throw retypeApiError(error, "getWorkflowRun", spec, operation);
16188
+ }
16189
+ renderResult("getWorkflowRun", profile.output, keyByTyped(result?.data ?? result, selection.typedBy), spec, {}, result);
16190
+ }
16191
+ function attachWorkflowRunGet(runs) {
16192
+ const get = runs.commands.find((command) => command.name() === "get");
16193
+ const held = get?._actionHandler;
16194
+ if (!get || typeof held !== "function") {
16195
+ throw new Error("workflows runs get must be registered before block names can be attached to it");
16196
+ }
16197
+ const previous = held;
16198
+ get.action(async (runId, _options, command) => {
16199
+ const raw = command.optsWithGlobals().selectOutput;
16200
+ if (raw === undefined) {
16201
+ await previous(command.processedArgs);
16202
+ return;
16203
+ }
16204
+ const typed = readListValues(raw, SELECT_OUTPUT_FLAG);
16205
+ command.setOptionValue("selectOutput", typed);
16206
+ if (typed.every(isIdHeaded)) {
16207
+ await previous(command.processedArgs);
16208
+ return;
16209
+ }
16210
+ await readRunByName(runId, typed, command);
16211
+ });
16007
16212
  }
16008
16213
 
16009
16214
  // src/commands/protocol/workflow-run-wait.ts
@@ -16020,18 +16225,21 @@ var MAX_POLL_DELAY_MS = 15000;
16020
16225
  var POLL_BACKOFF_FACTOR = 2;
16021
16226
  var DEFAULT_WAIT_TIMEOUT_SECONDS = 3600;
16022
16227
  var WAIT_TIMEOUT_FLAG = "--wait-timeout <seconds>";
16023
- function isRecord2(value) {
16228
+ function isRecord3(value) {
16024
16229
  return typeof value === "object" && value !== null && !Array.isArray(value);
16025
16230
  }
16026
16231
  function optionalString(value) {
16027
16232
  return typeof value === "string" && value !== "" ? value : null;
16028
16233
  }
16234
+ function runData(raw) {
16235
+ return isRecord3(raw) && isRecord3(raw.data) ? raw.data : raw;
16236
+ }
16029
16237
  function readRun(raw) {
16030
- const run = isRecord2(raw) && isRecord2(raw.data) ? raw.data : raw;
16031
- if (!isRecord2(run) || typeof run.status !== "string") {
16238
+ const run = isRecord3(raw) && isRecord3(raw.data) ? raw.data : raw;
16239
+ if (!isRecord3(run) || typeof run.status !== "string") {
16032
16240
  throw new SimApiError("Run status response carried no status.", 0);
16033
16241
  }
16034
- const paused = isRecord2(run.paused) ? run.paused : null;
16242
+ const paused = isRecord3(run.paused) ? run.paused : null;
16035
16243
  return {
16036
16244
  status: run.status,
16037
16245
  pauseKind: paused ? optionalString(paused.pauseKind) : null,
@@ -16100,19 +16308,19 @@ function attachWorkflowRunWait(runs) {
16100
16308
  const outcome = classify(snapshot);
16101
16309
  if (outcome) {
16102
16310
  progress.finish();
16103
- renderResult("getWorkflowRun", profile.output, raw, runSpec());
16311
+ renderResult("getWorkflowRun", profile.output, runData(raw), runSpec());
16104
16312
  const message = explain(outcome, runId, options.workflow, snapshot);
16105
16313
  if (message)
16106
16314
  console.error(source_default.red(message));
16107
- process.exitCode = WAIT_EXIT_CODES[outcome];
16315
+ setSoftExitCode(WAIT_EXIT_CODES[outcome]);
16108
16316
  return;
16109
16317
  }
16110
16318
  const remainingMs = deadline - Date.now();
16111
16319
  if (remainingMs <= 0) {
16112
16320
  progress.finish();
16113
- renderResult("getWorkflowRun", profile.output, raw, runSpec());
16321
+ renderResult("getWorkflowRun", profile.output, runData(raw), runSpec());
16114
16322
  console.error(source_default.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.`));
16115
- process.exitCode = WAIT_EXIT_CODES.timeout;
16323
+ setSoftExitCode(WAIT_EXIT_CODES.timeout);
16116
16324
  return;
16117
16325
  }
16118
16326
  progress.advance(snapshot.status, Date.now() - startedAt);
@@ -16168,7 +16376,9 @@ function attachProtocolCommands(program2) {
16168
16376
  createFolder: "createWorkflowFolder"
16169
16377
  });
16170
16378
  attachWorkflowRunFollow(workflows);
16171
- attachWorkflowRunWait(group(workflows, "runs"));
16379
+ const runs = group(workflows, "runs");
16380
+ attachWorkflowRunGet(runs);
16381
+ attachWorkflowRunWait(runs);
16172
16382
  attachLogsFollow(group(program2, "logs"));
16173
16383
  attachChat(program2);
16174
16384
  }
@@ -16396,7 +16606,7 @@ function addVersionOption(program2) {
16396
16606
  }
16397
16607
  program2.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.");
16398
16608
  });
16399
- program2.version(CLI_VERSION, "-V, --version [none]", "output the version number (takes no value)");
16609
+ program2.version(cliVersion(), "-V, --version [none]", "output the version number (takes no value)");
16400
16610
  }
16401
16611
  function buildProgram(options = {}) {
16402
16612
  const program2 = new Command;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sim",
3
- "version": "2.1.5",
3
+ "version": "2.1.6-dev.86.1",
4
4
  "description": "Sim CLI - talk to the Sim API from your terminal",
5
5
  "type": "module",
6
6
  "bin": {
@@ -57,5 +57,11 @@
57
57
  "@types/node": "24.2.1",
58
58
  "typescript": "^7.0.2",
59
59
  "vitest": "^4.1.0"
60
+ },
61
+ "exports": {
62
+ "./embed": {
63
+ "types": "./src/embed.ts",
64
+ "default": "./src/embed.ts"
65
+ }
60
66
  }
61
67
  }