sim 2.1.3-preview.50.1 → 2.1.3-preview.52.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +133 -35
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2866,6 +2866,10 @@ function traceRequest(method, url, status, startedAt) {
|
|
|
2866
2866
|
process.stderr.write(`${source_default.dim(`[sim] ${method} ${url} → ${status} ${Math.round(performance.now() - startedAt)}ms`)}
|
|
2867
2867
|
`);
|
|
2868
2868
|
}
|
|
2869
|
+
function withoutLeadingLabel(message, label) {
|
|
2870
|
+
const prefix = `${label}: `;
|
|
2871
|
+
return message.startsWith(prefix) ? message.slice(prefix.length) : message;
|
|
2872
|
+
}
|
|
2869
2873
|
function formatApiErrorDetails(details) {
|
|
2870
2874
|
const issues = [];
|
|
2871
2875
|
const seen = new Set;
|
|
@@ -2903,7 +2907,10 @@ function formatApiErrorDetails(details) {
|
|
|
2903
2907
|
const visible = kept.slice(0, 8);
|
|
2904
2908
|
const lines = [
|
|
2905
2909
|
" details:",
|
|
2906
|
-
...visible.map((issue) =>
|
|
2910
|
+
...visible.map((issue) => {
|
|
2911
|
+
const label = issue.path.length > 0 ? issue.path.join(".") : "request";
|
|
2912
|
+
return ` ${label}: ${withoutLeadingLabel(issue.message, label)}`;
|
|
2913
|
+
})
|
|
2907
2914
|
];
|
|
2908
2915
|
if (kept.length > visible.length)
|
|
2909
2916
|
lines.push(` … ${kept.length - visible.length} more issues`);
|
|
@@ -3041,10 +3048,13 @@ function pageProgress() {
|
|
|
3041
3048
|
};
|
|
3042
3049
|
}
|
|
3043
3050
|
async function requestAllPages(client, path, options) {
|
|
3051
|
+
return (await requestPages(client, path, options)).items;
|
|
3052
|
+
}
|
|
3053
|
+
async function requestPages(client, path, options) {
|
|
3044
3054
|
const { query, pageSize, limit: requestedLimit, ...requestOptions } = options;
|
|
3045
3055
|
const limit = requestedLimit ?? Number.POSITIVE_INFINITY;
|
|
3046
3056
|
if (limit <= 0)
|
|
3047
|
-
return [];
|
|
3057
|
+
return { items: [], truncated: false };
|
|
3048
3058
|
const items = [];
|
|
3049
3059
|
const progress = pageProgress();
|
|
3050
3060
|
let cursor = null;
|
|
@@ -3066,7 +3076,7 @@ async function requestAllPages(client, path, options) {
|
|
|
3066
3076
|
} finally {
|
|
3067
3077
|
progress.finish();
|
|
3068
3078
|
}
|
|
3069
|
-
return items.slice(0, limit);
|
|
3079
|
+
return { items: items.slice(0, limit), truncated: cursor !== null || items.length > limit };
|
|
3070
3080
|
}
|
|
3071
3081
|
function resolvePath(template, params = {}) {
|
|
3072
3082
|
return template.replace(/\[([^\]]+)\]/g, (_match, key) => {
|
|
@@ -9198,7 +9208,7 @@ var V2_OPERATIONS = {
|
|
|
9198
9208
|
},
|
|
9199
9209
|
parentPath: {
|
|
9200
9210
|
kind: "string",
|
|
9201
|
-
describe: "Restrict results to direct children of this parent path."
|
|
9211
|
+
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."
|
|
9202
9212
|
},
|
|
9203
9213
|
search: {
|
|
9204
9214
|
kind: "string",
|
|
@@ -9531,7 +9541,7 @@ var V2_OPERATIONS = {
|
|
|
9531
9541
|
},
|
|
9532
9542
|
parentPath: {
|
|
9533
9543
|
kind: "string",
|
|
9534
|
-
describe: "Restrict results to direct children of this parent path."
|
|
9544
|
+
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."
|
|
9535
9545
|
},
|
|
9536
9546
|
search: {
|
|
9537
9547
|
kind: "string",
|
|
@@ -9884,7 +9894,7 @@ var V2_OPERATIONS = {
|
|
|
9884
9894
|
},
|
|
9885
9895
|
parentPath: {
|
|
9886
9896
|
kind: "string",
|
|
9887
|
-
describe: "Restrict results to direct children of this parent path."
|
|
9897
|
+
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."
|
|
9888
9898
|
},
|
|
9889
9899
|
search: {
|
|
9890
9900
|
kind: "string",
|
|
@@ -10050,7 +10060,7 @@ var V2_OPERATIONS = {
|
|
|
10050
10060
|
},
|
|
10051
10061
|
parentPath: {
|
|
10052
10062
|
kind: "string",
|
|
10053
|
-
describe: "Restrict results to direct children of this parent path."
|
|
10063
|
+
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."
|
|
10054
10064
|
},
|
|
10055
10065
|
search: {
|
|
10056
10066
|
kind: "string",
|
|
@@ -11902,14 +11912,22 @@ function requireValue(value, flag, key) {
|
|
|
11902
11912
|
throw new SimApiError(`${flag} requires a value. To remove it, run: sim configure --unset ${key}`, 0);
|
|
11903
11913
|
}
|
|
11904
11914
|
}
|
|
11915
|
+
function quoteProfileArgument(name) {
|
|
11916
|
+
const redacted = redact(name);
|
|
11917
|
+
if (PROFILE_NAME_PATTERN.test(redacted))
|
|
11918
|
+
return redacted;
|
|
11919
|
+
return `'${redacted.replaceAll("'", "'\\''")}'`;
|
|
11920
|
+
}
|
|
11905
11921
|
function configureCommand() {
|
|
11906
11922
|
return new Command("configure").description("Set a profile's endpoint, default workspace, or output format").option("--set-endpoint <url>", "Sim deployment to talk to").option("--set-workspace <id>", "Default workspace for workspace-scoped commands").option("--set-output <format>", `Default output format (${OUTPUT_FORMATS.join(" | ")})`).option("--unset <key...>", "Remove settings (endpoint, workspace, output)").action((options, command) => {
|
|
11907
11923
|
const globals = globalsOf(command);
|
|
11924
|
+
const selectedProfile = globals.profile || process.env.SIM_PROFILE;
|
|
11925
|
+
const profileArg = selectedProfile ? ` --profile ${quoteProfileArgument(selectedProfile)}` : "";
|
|
11908
11926
|
for (const { option, flag, setFlag } of GLOBAL_FLAG_TWINS) {
|
|
11909
11927
|
const value = globals[option];
|
|
11910
11928
|
if (value === undefined)
|
|
11911
11929
|
continue;
|
|
11912
|
-
throw new SimApiError(`${flag} applies to a single command and is not stored. To save it, run: sim configure ${setFlag} ${value}`, 0);
|
|
11930
|
+
throw new SimApiError(`${flag} applies to a single command and is not stored. To save it, run: sim configure${profileArg} ${setFlag} ${redact(value)}`, 0);
|
|
11913
11931
|
}
|
|
11914
11932
|
const profile = profileFrom(command, { allowUnknownProfile: true });
|
|
11915
11933
|
const authProfile = resolveAuthenticationProfileName(profile.name);
|
|
@@ -11970,7 +11988,7 @@ var TABLE_SORT_HELP = 'Ordered sort keys: [{"field":"createdAt","direction":"des
|
|
|
11970
11988
|
var KNOWLEDGE_TAG_DEFINITIONS_HELP = 'Tag definitions: [{"tagSlot":"tag1","displayName":"category","fieldType":"text"}]';
|
|
11971
11989
|
var CUSTOM_TOOL_SCHEMA_HELP = 'OpenAI function schema: {"type":"function","function":{"name":"...","parameters":{"type":"object","properties":{}}}}';
|
|
11972
11990
|
var DISPATCH_ROW_LIMIT_HELP = "Stop after this many eligible rows have run (1-1,000,000). Omit for an unbounded run";
|
|
11973
|
-
var WORKFLOW_OPERATIONS_HELP = 'Edits to apply, in a single batch, keyed by operation_type: [{"operation_type":"add","block_id":"my-fn","params":{"type":"function","name":"My Fn","inputs":{"code":"return {ok:true}"}}},{"operation_type":"edit","block_id":"<uuid>","params":{"name":"Renamed","connections":{"success":"my-fn"}}},{"operation_type":"delete","block_id":"<uuid>"}]. Also
|
|
11991
|
+
var WORKFLOW_OPERATIONS_HELP = 'Edits to apply, in a single batch, keyed by operation_type: [{"operation_type":"add","block_id":"my-fn","params":{"type":"function","name":"My Fn","inputs":{"code":"return {ok:true}"}}},{"operation_type":"edit","block_id":"<uuid>","params":{"name":"Renamed","connections":{"success":"my-fn"}}},{"operation_type":"delete","block_id":"<uuid>"}]. Also extract_from_subflow, whose params carry {"subflowId":"<loop-id>"}, and insert_into_subflow, which creates a block and so takes an add’s params plus that subflowId';
|
|
11974
11992
|
var WORKFLOW_SET_BLOCK_ENABLED_HELP = 'Blocks to enable or disable, applied after --operations: [{"block_id":"<uuid>","enabled":false}]. Disabling a loop or parallel cascades to its unlocked descendants; enabling a block whose container is disabled is declined';
|
|
11975
11993
|
var WORKFLOW_VARIABLE_OPERATIONS_HELP = 'Variable changes to apply in order, keyed by operation: [{"operation":"add","name":"my_var","type":"string","value":"hello"},{"operation":"edit","name":"my_var","value":"updated"},{"operation":"delete","name":"my_var"}]';
|
|
11976
11994
|
var MCP_PARAMETER_DESCRIPTIONS_HELP = 'Per-field description overrides applied to the schema generated from the deployed workflow inputs, as [{"name":"email","description":"Customer email address"}]. A name matching no input field is ignored';
|
|
@@ -12046,7 +12064,7 @@ var CLI_CONTRACT = {
|
|
|
12046
12064
|
listBillingLogs: {
|
|
12047
12065
|
command: "billing logs",
|
|
12048
12066
|
allWorkspaces: true,
|
|
12049
|
-
describe: "List credit usage events (a personal API key reports only your own events; a workspace API key reports every member's)",
|
|
12067
|
+
describe: "List credit usage events (a personal API key reports only your own events; a workspace API key reports every member's in aggregate, unattributed)",
|
|
12050
12068
|
flags: {
|
|
12051
12069
|
source: { describe: "Filter by usage source; sim-chat combines Copilot and workspace chat" },
|
|
12052
12070
|
period: { describe: "Billing period" },
|
|
@@ -12239,7 +12257,7 @@ var CLI_CONTRACT = {
|
|
|
12239
12257
|
},
|
|
12240
12258
|
getLogStats: {
|
|
12241
12259
|
command: "logs stats",
|
|
12242
|
-
describe: "Summarize run counts, failures
|
|
12260
|
+
describe: "Summarize run counts, failures and latency over a window",
|
|
12243
12261
|
flags: LOG_LIST_FILTER_FLAGS,
|
|
12244
12262
|
fields: [
|
|
12245
12263
|
{ header: "runs", path: "totalRuns" },
|
|
@@ -12316,6 +12334,9 @@ var CLI_CONTRACT = {
|
|
|
12316
12334
|
rollbackWorkflow: {
|
|
12317
12335
|
confirm: "This changes which deployed version runs in production for every API and chat consumer."
|
|
12318
12336
|
},
|
|
12337
|
+
activateWorkflowVersion: {
|
|
12338
|
+
confirm: "This changes which deployed version runs in production for every API and chat consumer."
|
|
12339
|
+
},
|
|
12319
12340
|
moveWorkflows: {
|
|
12320
12341
|
command: "workflows move",
|
|
12321
12342
|
flags: {
|
|
@@ -12567,7 +12588,7 @@ var CLI_CONTRACT = {
|
|
|
12567
12588
|
listCustomTools: {
|
|
12568
12589
|
columns: [
|
|
12569
12590
|
{ header: "id" },
|
|
12570
|
-
{ header: "
|
|
12591
|
+
{ header: "title", path: "title" },
|
|
12571
12592
|
{ header: "description", path: "schema.function.description" },
|
|
12572
12593
|
{ header: "updated", path: "updatedAt", format: "timestamp" }
|
|
12573
12594
|
]
|
|
@@ -12799,6 +12820,7 @@ var CLI_CONTRACT = {
|
|
|
12799
12820
|
]
|
|
12800
12821
|
},
|
|
12801
12822
|
listFileFolders: {
|
|
12823
|
+
describe: "List folders",
|
|
12802
12824
|
aliases: ["ls"],
|
|
12803
12825
|
flags: {
|
|
12804
12826
|
parentPath: { ...FOLDER_PATH_INPUT, name: "parent", describe: "Direct parent folder path" }
|
|
@@ -12806,6 +12828,7 @@ var CLI_CONTRACT = {
|
|
|
12806
12828
|
columns: FOLDER_LIST_COLUMNS
|
|
12807
12829
|
},
|
|
12808
12830
|
listKnowledgeFolders: {
|
|
12831
|
+
describe: "List knowledge folders",
|
|
12809
12832
|
aliases: ["ls"],
|
|
12810
12833
|
flags: {
|
|
12811
12834
|
parentPath: { ...FOLDER_PATH_INPUT, name: "parent", describe: "Direct parent folder path" }
|
|
@@ -12813,6 +12836,7 @@ var CLI_CONTRACT = {
|
|
|
12813
12836
|
columns: FOLDER_LIST_COLUMNS
|
|
12814
12837
|
},
|
|
12815
12838
|
listTableFolders: {
|
|
12839
|
+
describe: "List table folders",
|
|
12816
12840
|
aliases: ["ls"],
|
|
12817
12841
|
flags: {
|
|
12818
12842
|
parentPath: { ...FOLDER_PATH_INPUT, name: "parent", describe: "Direct parent folder path" }
|
|
@@ -12820,6 +12844,7 @@ var CLI_CONTRACT = {
|
|
|
12820
12844
|
columns: FOLDER_LIST_COLUMNS
|
|
12821
12845
|
},
|
|
12822
12846
|
listWorkflowFolders: {
|
|
12847
|
+
describe: "List workflow folders",
|
|
12823
12848
|
aliases: ["ls"],
|
|
12824
12849
|
flags: {
|
|
12825
12850
|
parentPath: { ...FOLDER_PATH_INPUT, name: "parent", describe: "Direct parent folder path" }
|
|
@@ -13298,6 +13323,7 @@ function encodeFolderPath(value) {
|
|
|
13298
13323
|
}
|
|
13299
13324
|
}).join("/");
|
|
13300
13325
|
}
|
|
13326
|
+
var FRACTIONAL_DIGITS = /\.\d*[1-9]/;
|
|
13301
13327
|
function pathHint(raw) {
|
|
13302
13328
|
if (raw.startsWith("@") || /^\s*[[{"\-\d]|^\s*(true|false|null)/.test(raw))
|
|
13303
13329
|
return "";
|
|
@@ -13326,6 +13352,12 @@ function coerce(raw, field, flag, flagName) {
|
|
|
13326
13352
|
const value = Number(raw);
|
|
13327
13353
|
if (Number.isNaN(value))
|
|
13328
13354
|
throw new SimApiError(`--${flagName} must be a number`, 0);
|
|
13355
|
+
if (field.kind === "integer" && (!Number.isInteger(value) || FRACTIONAL_DIGITS.test(String(raw)))) {
|
|
13356
|
+
throw new SimApiError(`--${flagName} must be a whole number`, 0);
|
|
13357
|
+
}
|
|
13358
|
+
if (field.kind === "integer" && !Number.isSafeInteger(value)) {
|
|
13359
|
+
throw new SimApiError(`--${flagName} is outside the whole-number range the API accepts (±${Number.MAX_SAFE_INTEGER})`, 0);
|
|
13360
|
+
}
|
|
13329
13361
|
return value;
|
|
13330
13362
|
}
|
|
13331
13363
|
if (field.kind === "boolean" || flag.boolean)
|
|
@@ -13385,6 +13417,9 @@ function buildRequest(operation, positional, flags, workspaceId) {
|
|
|
13385
13417
|
throw new SimApiError(`--${flagName} cannot be empty`, 0);
|
|
13386
13418
|
}
|
|
13387
13419
|
const value = coerce(raw ?? undefined, descriptor, flag, flagName);
|
|
13420
|
+
if (field === "limit" && !paginatedLimit && NUMERIC_KINDS.has(descriptor.kind) && typeof value === "number" && value < 1) {
|
|
13421
|
+
throw new SimApiError(`--${flagName} must be 1 or more`, 0);
|
|
13422
|
+
}
|
|
13388
13423
|
if (value === undefined) {
|
|
13389
13424
|
if (descriptor.required) {
|
|
13390
13425
|
throw new SimApiError(field === PROFILE_INJECTED_FIELD ? NO_WORKSPACE_FALLBACK : `--${flagName} is required`, 0);
|
|
@@ -13533,7 +13568,7 @@ function addOperationOptions(command, operation, commandSpec, operationSpec) {
|
|
|
13533
13568
|
}
|
|
13534
13569
|
if (commandSpec.confirm) {
|
|
13535
13570
|
const exemptedByDryRun = operationSpec.query?.dryRun !== undefined || operationSpec.body?.dryRun !== undefined;
|
|
13536
|
-
command.option("-y, --yes", exemptedByDryRun ? "Confirm this
|
|
13571
|
+
command.option("-y, --yes", exemptedByDryRun ? "Confirm this operation (required unless --dry-run)" : "Confirm this operation (required)");
|
|
13537
13572
|
}
|
|
13538
13573
|
}
|
|
13539
13574
|
|
|
@@ -13959,6 +13994,14 @@ var BULK_OUTCOME_CHECKS = {
|
|
|
13959
13994
|
const reported2 = payload.errors?.[0];
|
|
13960
13995
|
return typeof reported2 === "string" && reported2 ? safeOneLine(reported2) : `Updated nothing: none of the ${requested} requested ${requested === 1 ? "chunk" : "chunks"} matched.`;
|
|
13961
13996
|
},
|
|
13997
|
+
deleteTableRows: (payload) => {
|
|
13998
|
+
if (countOf(payload.deletedCount) > 0)
|
|
13999
|
+
return null;
|
|
14000
|
+
const requested = countOf(payload.requestedCount);
|
|
14001
|
+
if (requested === 0)
|
|
14002
|
+
return null;
|
|
14003
|
+
return `Deleted nothing: none of the ${requested} requested ${requested === 1 ? "row was" : "rows were"} deleted.`;
|
|
14004
|
+
},
|
|
13962
14005
|
moveTables: (payload) => {
|
|
13963
14006
|
if (lengthOf(payload.moved) > 0)
|
|
13964
14007
|
return null;
|
|
@@ -13993,6 +14036,14 @@ function bulkFailureMessage(operation, payload, body) {
|
|
|
13993
14036
|
var EXCLUSIVE_CAP_FIELDS = {
|
|
13994
14037
|
deleteTableRows: { cap: "limit", ids: "rowIds" }
|
|
13995
14038
|
};
|
|
14039
|
+
function readPagedLimit(raw) {
|
|
14040
|
+
const text2 = String(raw ?? DEFAULT_LIMIT).trim();
|
|
14041
|
+
const value = text2 === "" ? Number.NaN : Number(text2);
|
|
14042
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
14043
|
+
throw new SimApiError("--limit must be a whole number of 0 or more (0 for everything)", 0);
|
|
14044
|
+
}
|
|
14045
|
+
return value;
|
|
14046
|
+
}
|
|
13996
14047
|
function assertCapIsUsable(operation, flags) {
|
|
13997
14048
|
const exclusive = EXCLUSIVE_CAP_FIELDS[operation];
|
|
13998
14049
|
if (!exclusive)
|
|
@@ -14003,6 +14054,19 @@ function assertCapIsUsable(operation, flags) {
|
|
|
14003
14054
|
return;
|
|
14004
14055
|
throw new SimApiError(`--${cap} caps a --filter match and does nothing to an explicit --${ids} list; pass one, not both`, 0);
|
|
14005
14056
|
}
|
|
14057
|
+
var REQUIRED_SELECTORS = {
|
|
14058
|
+
deleteTableRows: { fields: ["filter", "rowIds"], noun: "rows to delete" }
|
|
14059
|
+
};
|
|
14060
|
+
function assertSelectorIsUsable(operation, flags) {
|
|
14061
|
+
const selector = REQUIRED_SELECTORS[operation];
|
|
14062
|
+
if (!selector)
|
|
14063
|
+
return;
|
|
14064
|
+
const [first, second] = selector.fields.map((field) => flagNameFor(operation, field));
|
|
14065
|
+
const given = [first, second].filter((name) => flags[camel(name)] !== undefined);
|
|
14066
|
+
if (given.length === 1)
|
|
14067
|
+
return;
|
|
14068
|
+
throw new SimApiError(given.length === 0 ? `--${first} or --${second} is required to choose the ${selector.noun}` : `--${first} and --${second} choose the ${selector.noun} two different ways; pass one, not both`, 0);
|
|
14069
|
+
}
|
|
14006
14070
|
function foldRenamedFlags(operation, commandSpec, flags) {
|
|
14007
14071
|
for (const [field, flag] of Object.entries(commandSpec.flags ?? {})) {
|
|
14008
14072
|
if (!flag.renamedFrom?.length)
|
|
@@ -14036,6 +14100,7 @@ async function executeOperation(operation, commandSpec, operationSpec, invocatio
|
|
|
14036
14100
|
}
|
|
14037
14101
|
foldRenamedFlags(operation, commandSpec, requestFlags);
|
|
14038
14102
|
assertCapIsUsable(operation, requestFlags);
|
|
14103
|
+
assertSelectorIsUsable(operation, requestFlags);
|
|
14039
14104
|
if (commandSpec.confirm && !requestFlags.yes && requestFlags.dryRun !== true) {
|
|
14040
14105
|
throw new SimApiError(`${commandSpec.confirm} Re-run with --yes to confirm.`, 0);
|
|
14041
14106
|
}
|
|
@@ -14046,15 +14111,11 @@ async function executeOperation(operation, commandSpec, operationSpec, invocatio
|
|
|
14046
14111
|
const hasWorkspaceField = Boolean(operationSpec.query && PROFILE_INJECTED_FIELD in operationSpec.query || operationSpec.body && PROFILE_INJECTED_FIELD in operationSpec.body);
|
|
14047
14112
|
const omitsWorkspace = commandSpec.allWorkspaces && requestFlags.allWorkspaces === true;
|
|
14048
14113
|
const needsWorkspace = (hasWorkspaceField || commandSpec.profileWorkspacePath === true) && !omitsWorkspace;
|
|
14049
|
-
const request = buildRequest(operation, positional, requestFlags, needsWorkspace ? client.requireWorkspace() : profile.workspaceId);
|
|
14050
14114
|
const paging = cursorSlot(operationSpec);
|
|
14115
|
+
const pagedLimit = paging ? readPagedLimit(requestFlags.limit) : 0;
|
|
14116
|
+
const request = buildRequest(operation, positional, requestFlags, needsWorkspace ? client.requireWorkspace() : profile.workspaceId);
|
|
14051
14117
|
if (paging) {
|
|
14052
|
-
const
|
|
14053
|
-
const rawLimit = limitText === "" ? Number.NaN : Number(limitText);
|
|
14054
|
-
if (!Number.isInteger(rawLimit) || rawLimit < 0) {
|
|
14055
|
-
throw new SimApiError("--limit must be a whole number of 0 or more (0 for everything)", 0);
|
|
14056
|
-
}
|
|
14057
|
-
const limit = rawLimit === 0 ? Number.POSITIVE_INFINITY : rawLimit;
|
|
14118
|
+
const limit = pagedLimit === 0 ? Number.POSITIVE_INFINITY : pagedLimit;
|
|
14058
14119
|
const pageSize = Math.min(Number.isFinite(limit) ? limit : DEFAULT_LIMIT, DEFAULT_LIMIT);
|
|
14059
14120
|
const pageLimit = "limit" in (operationSpec[paging] ?? {}) ? { limit: pageSize } : {};
|
|
14060
14121
|
const rows = [];
|
|
@@ -14139,6 +14200,14 @@ function retypeMessage(message, spellings) {
|
|
|
14139
14200
|
continue;
|
|
14140
14201
|
retyped = retyped.replaceAll(new RegExp(`\\b${field}\\b`, "g"), spelling);
|
|
14141
14202
|
}
|
|
14203
|
+
if (retyped === message)
|
|
14204
|
+
return message;
|
|
14205
|
+
for (const field of spellings.keys()) {
|
|
14206
|
+
if (WIRE_IDENTIFIER.test(field))
|
|
14207
|
+
continue;
|
|
14208
|
+
if (new RegExp(`\\b${field}\\b`).test(message))
|
|
14209
|
+
return message;
|
|
14210
|
+
}
|
|
14142
14211
|
return retyped;
|
|
14143
14212
|
}
|
|
14144
14213
|
function retypeDetails(details, spellings) {
|
|
@@ -14204,18 +14273,30 @@ function commandPath(command) {
|
|
|
14204
14273
|
}
|
|
14205
14274
|
return names.join(" ");
|
|
14206
14275
|
}
|
|
14207
|
-
|
|
14276
|
+
var UNKNOWN_OPTION_TOKEN = /^error: unknown option '(.+?)'/;
|
|
14277
|
+
function looksLikeAnId(token2) {
|
|
14278
|
+
return token2.length > 2 && !token2.startsWith("--") && /^-[A-Za-z0-9_-]*[A-Z0-9][A-Za-z0-9_-]*$/.test(token2);
|
|
14279
|
+
}
|
|
14280
|
+
function addArgumentExamples(command) {
|
|
14208
14281
|
const outputError = command.configureOutput().outputError;
|
|
14209
14282
|
if (!outputError)
|
|
14210
14283
|
throw new Error("Commander output formatter is not configured");
|
|
14211
14284
|
command.configureOutput({
|
|
14212
14285
|
outputError: (message, write) => {
|
|
14213
14286
|
outputError(message, write);
|
|
14214
|
-
if (
|
|
14287
|
+
if (message.startsWith("error: missing required argument ")) {
|
|
14288
|
+
const syntax = argumentSyntax(command);
|
|
14289
|
+
const example = syntax ? `${commandPath(command)} ${syntax}` : commandPath(command);
|
|
14290
|
+
write(`Example: ${example}
|
|
14291
|
+
`);
|
|
14292
|
+
return;
|
|
14293
|
+
}
|
|
14294
|
+
if (command.registeredArguments.length === 0)
|
|
14295
|
+
return;
|
|
14296
|
+
const token2 = UNKNOWN_OPTION_TOKEN.exec(message)?.[1];
|
|
14297
|
+
if (!token2 || !looksLikeAnId(token2))
|
|
14215
14298
|
return;
|
|
14216
|
-
|
|
14217
|
-
const example = syntax ? `${commandPath(command)} ${syntax}` : commandPath(command);
|
|
14218
|
-
write(`Example: ${example}
|
|
14299
|
+
write(`Example: ${commandPath(command)} -- ${token2}
|
|
14219
14300
|
`);
|
|
14220
14301
|
}
|
|
14221
14302
|
});
|
|
@@ -14342,7 +14423,7 @@ function configureOperation(command, operation, spec) {
|
|
|
14342
14423
|
return command;
|
|
14343
14424
|
}
|
|
14344
14425
|
function buildLeaf(operation, spec, leafName) {
|
|
14345
|
-
return
|
|
14426
|
+
return addArgumentExamples(configureOperation(new Command(leafName), operation, spec));
|
|
14346
14427
|
}
|
|
14347
14428
|
function addRenamedCommand(groups, operation, spec, from, to) {
|
|
14348
14429
|
const segments = from.split(" ");
|
|
@@ -14662,6 +14743,12 @@ Examples:
|
|
|
14662
14743
|
$ sim chat -c 3f2a… "Which of those run on a schedule?"
|
|
14663
14744
|
$ sim --output json chat "Summarize yesterday's failed runs" | jq -r '.content'
|
|
14664
14745
|
`).action(async (message, options, command) => {
|
|
14746
|
+
if (message.trim() === "") {
|
|
14747
|
+
throw new SimApiError("<message> cannot be empty", 0);
|
|
14748
|
+
}
|
|
14749
|
+
if (options.conversation !== undefined && options.conversation.trim() === "") {
|
|
14750
|
+
throw new SimApiError("-c/--conversation cannot be empty — pass the conversation id printed on stderr after each turn", 0);
|
|
14751
|
+
}
|
|
14665
14752
|
const { client, profile } = clientFrom(command);
|
|
14666
14753
|
const workspaceId = client.requireWorkspace();
|
|
14667
14754
|
const response = await client.requestRaw(V2_OPERATIONS.chat.path, {
|
|
@@ -15070,8 +15157,15 @@ function uploadMetadata(options) {
|
|
|
15070
15157
|
}
|
|
15071
15158
|
return metadata;
|
|
15072
15159
|
}
|
|
15160
|
+
var UPLOAD_RECIPES = [
|
|
15161
|
+
"default",
|
|
15162
|
+
"plain",
|
|
15163
|
+
"markdown",
|
|
15164
|
+
"code"
|
|
15165
|
+
];
|
|
15166
|
+
var LANGUAGE_TAG_HELP = "Document language tag: hyphen-separated letter and digit subtags, for example en or en-US";
|
|
15073
15167
|
function attachKnowledgeDocumentUpload(documents) {
|
|
15074
|
-
documents.command("upload").argument("<knowledgeBaseId>", "Knowledge base to upload into").argument("<path>", "Local file to upload").allowExcessArguments(false).description("Upload a document to a knowledge base").option("--name <name>", "Store it under a different name").option("--tag <value...>", "Document tags, in tag1 through tag7 order").
|
|
15168
|
+
documents.command("upload").argument("<knowledgeBaseId>", "Knowledge base to upload into").argument("<path>", "Local file to upload").allowExcessArguments(false).description("Upload a document to a knowledge base").option("--name <name>", "Store it under a different name").option("--tag <value...>", "Document tags, in tag1 through tag7 order").addOption(new Option("--recipe <name>", "Document processing recipe").choices(UPLOAD_RECIPES)).option("--lang <code>", LANGUAGE_TAG_HELP).action(async (knowledgeBaseId, path, options, command) => {
|
|
15075
15169
|
const { client, profile } = clientFrom(command);
|
|
15076
15170
|
const workspaceId = client.requireWorkspace();
|
|
15077
15171
|
const { name, size } = await localFile(path, options.name);
|
|
@@ -15290,7 +15384,7 @@ function isTransient(error) {
|
|
|
15290
15384
|
function nonNegativeInteger(raw, flag) {
|
|
15291
15385
|
const value = Number(raw);
|
|
15292
15386
|
if (!Number.isSafeInteger(value) || value < 0) {
|
|
15293
|
-
throw new SimApiError(`${flag} must be a
|
|
15387
|
+
throw new SimApiError(`${flag} must be a whole number of 0 or more`, 0);
|
|
15294
15388
|
}
|
|
15295
15389
|
return value;
|
|
15296
15390
|
}
|
|
@@ -15317,7 +15411,7 @@ follow.
|
|
|
15317
15411
|
|
|
15318
15412
|
Examples:
|
|
15319
15413
|
$ sim logs follow --level error
|
|
15320
|
-
$ sim logs follow --workflow
|
|
15414
|
+
$ sim logs follow --workflow 00000000-0000-4000-8000-000000000000 -n 0
|
|
15321
15415
|
$ sim --output json logs follow | jq -r '.runId'
|
|
15322
15416
|
`).action(async (options, command) => {
|
|
15323
15417
|
const lines = nonNegativeInteger(options.lines, "--lines");
|
|
@@ -15399,9 +15493,9 @@ async function listResources(client, config, workspaceId, folderPath, search, li
|
|
|
15399
15493
|
const paginated = "cursor" in V2_OPERATIONS[config.resources].query;
|
|
15400
15494
|
if (!paginated) {
|
|
15401
15495
|
const page = await client.request(path, { query });
|
|
15402
|
-
return page.data.slice(0, limit);
|
|
15496
|
+
return { items: page.data.slice(0, limit), truncated: page.data.length > limit };
|
|
15403
15497
|
}
|
|
15404
|
-
return
|
|
15498
|
+
return requestPages(client, path, {
|
|
15405
15499
|
query,
|
|
15406
15500
|
pageSize: DEFAULT_LIMIT,
|
|
15407
15501
|
limit
|
|
@@ -15436,7 +15530,7 @@ function attachResourceDirectoryCommands(group, config) {
|
|
|
15436
15530
|
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) => {
|
|
15437
15531
|
const rawLimit = Number(options.limit);
|
|
15438
15532
|
if (!Number.isSafeInteger(rawLimit) || rawLimit < 0) {
|
|
15439
|
-
throw new SimApiError("--limit must be a
|
|
15533
|
+
throw new SimApiError("--limit must be a whole number of 0 or more (0 for everything)", 0);
|
|
15440
15534
|
}
|
|
15441
15535
|
const limit = rawLimit === 0 ? Number.POSITIVE_INFINITY : rawLimit;
|
|
15442
15536
|
const folderPath = encodeFolderPath(path ?? "/");
|
|
@@ -15446,8 +15540,10 @@ function attachResourceDirectoryCommands(group, config) {
|
|
|
15446
15540
|
listFolders(client, config.folders, workspaceId, folderPath, options.search),
|
|
15447
15541
|
listResources(client, config, workspaceId, folderPath, options.search, limit)
|
|
15448
15542
|
]);
|
|
15449
|
-
const entries = entriesFor(config, folders, resources);
|
|
15450
|
-
|
|
15543
|
+
const entries = entriesFor(config, folders, resources.items);
|
|
15544
|
+
const shown = entries.slice(0, limit);
|
|
15545
|
+
writeCursorTruncation(shown.length, resources.truncated || entries.length > limit);
|
|
15546
|
+
printList(profile.output, shown, COLUMNS2);
|
|
15451
15547
|
});
|
|
15452
15548
|
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) => {
|
|
15453
15549
|
const { client, profile } = clientFrom(command);
|
|
@@ -16194,7 +16290,9 @@ Profiles work like the AWS CLI: settings live in ~/.sim/config, keys in
|
|
|
16194
16290
|
with -P, --profile, or SIM_PROFILE.
|
|
16195
16291
|
|
|
16196
16292
|
Workflow, knowledge-base and workspace IDs are bare UUIDs. Table IDs carry a
|
|
16197
|
-
tbl_ prefix and file IDs a wf_ one, so wf_ never names a workflow.
|
|
16293
|
+
tbl_ prefix and file IDs a wf_ one, so wf_ never names a workflow. An audit-log
|
|
16294
|
+
or custom-tool ID can open with a dash, which reads as a flag; put -- in front
|
|
16295
|
+
of it, as in sim audit-logs get -- -HlDcD1z76nK6R4crsUp0.
|
|
16198
16296
|
|
|
16199
16297
|
Examples:
|
|
16200
16298
|
$ sim login Authorize the default profile
|