sim 2.1.2-preview.47.1 → 2.1.2-preview.49.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 +543 -128
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2315,8 +2315,26 @@ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "n
|
|
|
2315
2315
|
import { dirname } from "node:path";
|
|
2316
2316
|
|
|
2317
2317
|
// src/config/ini.ts
|
|
2318
|
+
class ProfileConfigError extends Error {
|
|
2319
|
+
constructor(message) {
|
|
2320
|
+
super(message);
|
|
2321
|
+
this.name = "ProfileConfigError";
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2318
2324
|
var SECTION_PATTERN = /^\s*\[([^\]]*)\]\s*$/;
|
|
2319
2325
|
var KV_PATTERN = /^\s*([A-Za-z0-9_.-]+)\s*=\s*(.*?)\s*$/;
|
|
2326
|
+
var FORBIDDEN_CLASS = "\\u0000-\\u001f\\u007f-\\u009f\\u2028\\u2029";
|
|
2327
|
+
var FORBIDDEN_IN_VALUE = new RegExp(`[${FORBIDDEN_CLASS}]`);
|
|
2328
|
+
var FORBIDDEN_IN_NAME = new RegExp(`[${FORBIDDEN_CLASS}[\\]]`);
|
|
2329
|
+
var WRITABLE_KEY = /^[A-Za-z0-9_.-]+$/;
|
|
2330
|
+
function assertWritable(text, what, forbidden) {
|
|
2331
|
+
if (forbidden.test(text)) {
|
|
2332
|
+
throw new ProfileConfigError(`Refusing to write ${what}: line breaks and control characters cannot be stored in the ~/.sim files, because the format has no way to escape them.`);
|
|
2333
|
+
}
|
|
2334
|
+
if (text !== text.trim()) {
|
|
2335
|
+
throw new ProfileConfigError(`Refusing to write ${what}: leading or trailing whitespace is not preserved by the ~/.sim files, so it would not read back as written.`);
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2320
2338
|
function parseIni(text) {
|
|
2321
2339
|
const doc = { preamble: [], sections: [] };
|
|
2322
2340
|
let current = null;
|
|
@@ -2379,9 +2397,23 @@ function listSections(doc) {
|
|
|
2379
2397
|
return doc.sections.map((s) => s.name);
|
|
2380
2398
|
}
|
|
2381
2399
|
function setSectionValues(doc, name, values) {
|
|
2400
|
+
assertWritable(name, `a section named "${name}"`, FORBIDDEN_IN_NAME);
|
|
2401
|
+
for (const [key, value] of Object.entries(values)) {
|
|
2402
|
+
if (!WRITABLE_KEY.test(key)) {
|
|
2403
|
+
throw new ProfileConfigError(`Refusing to write an unreadable setting name "${key}".`);
|
|
2404
|
+
}
|
|
2405
|
+
if (value === null)
|
|
2406
|
+
continue;
|
|
2407
|
+
if (value.trim() === "") {
|
|
2408
|
+
throw new ProfileConfigError(`Refusing to write a blank value for "${key}".`);
|
|
2409
|
+
}
|
|
2410
|
+
assertWritable(value, `a value for "${key}"`, FORBIDDEN_IN_VALUE);
|
|
2411
|
+
}
|
|
2382
2412
|
const matching = doc.sections.filter((s) => s.name === name);
|
|
2383
2413
|
let section = matching[0];
|
|
2384
2414
|
if (!section) {
|
|
2415
|
+
if (Object.values(values).every((value) => value === null))
|
|
2416
|
+
return;
|
|
2385
2417
|
section = { name, entries: [] };
|
|
2386
2418
|
doc.sections.push(section);
|
|
2387
2419
|
matching.push(section);
|
|
@@ -2413,11 +2445,11 @@ function removeSection(doc, name) {
|
|
|
2413
2445
|
var DEFAULT_PROFILE = "default";
|
|
2414
2446
|
var DEFAULT_ENDPOINT = "https://www.sim.ai";
|
|
2415
2447
|
var OUTPUT_FORMATS = ["table", "json", "yaml", "text"];
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2448
|
+
var FORBIDDEN_IN_VALUE_GLOBAL = new RegExp(FORBIDDEN_IN_VALUE.source, "g");
|
|
2449
|
+
var PROFILE_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
2450
|
+
function validateProfileName(name) {
|
|
2451
|
+
if (!PROFILE_NAME_PATTERN.test(name)) {
|
|
2452
|
+
throw new ProfileConfigError(`Invalid profile name "${name.replace(FORBIDDEN_IN_VALUE_GLOBAL, " ")}". Use letters, numbers, dots, underscores, or hyphens, starting with a letter or number.`);
|
|
2421
2453
|
}
|
|
2422
2454
|
}
|
|
2423
2455
|
function configSectionName(profile) {
|
|
@@ -2541,18 +2573,31 @@ function deleteProfile(profile) {
|
|
|
2541
2573
|
return { config, credentials };
|
|
2542
2574
|
}
|
|
2543
2575
|
function normalizeEndpoint(endpoint, source) {
|
|
2544
|
-
const trimmed = endpoint.replace(/\/+$/, "");
|
|
2576
|
+
const trimmed = endpoint.trim().replace(/\/+$/, "");
|
|
2577
|
+
if (FORBIDDEN_IN_VALUE.test(trimmed)) {
|
|
2578
|
+
throw new ProfileConfigError(`Invalid endpoint "${endpoint.replace(FORBIDDEN_IN_VALUE_GLOBAL, " ")}" from ${source}. An endpoint cannot contain line breaks or control characters.`);
|
|
2579
|
+
}
|
|
2545
2580
|
let parsed;
|
|
2546
2581
|
try {
|
|
2547
2582
|
parsed = new URL(trimmed);
|
|
2548
2583
|
} catch {
|
|
2549
|
-
throw new ProfileConfigError(`Invalid endpoint "${endpoint}" from ${source}. Use an absolute URL, e.g. ${DEFAULT_ENDPOINT} or http://localhost:3000`);
|
|
2584
|
+
throw new ProfileConfigError(`Invalid endpoint "${endpoint.replace(FORBIDDEN_IN_VALUE_GLOBAL, " ")}" from ${source}. Use an absolute URL, e.g. ${DEFAULT_ENDPOINT} or http://localhost:3000`);
|
|
2550
2585
|
}
|
|
2551
2586
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
2552
2587
|
throw new ProfileConfigError(`Unsupported endpoint scheme "${parsed.protocol.replace(/:$/, "")}" from ${source}. Use http or https, e.g. ${DEFAULT_ENDPOINT}`);
|
|
2553
2588
|
}
|
|
2554
2589
|
return trimmed;
|
|
2555
2590
|
}
|
|
2591
|
+
function normalizeWorkspaceId(workspaceId, source) {
|
|
2592
|
+
const trimmed = workspaceId.trim();
|
|
2593
|
+
if (!trimmed) {
|
|
2594
|
+
throw new ProfileConfigError(`Empty workspace id from ${source}.`);
|
|
2595
|
+
}
|
|
2596
|
+
if (FORBIDDEN_IN_VALUE.test(trimmed)) {
|
|
2597
|
+
throw new ProfileConfigError(`Invalid workspace id "${trimmed.replace(FORBIDDEN_IN_VALUE_GLOBAL, " ")}" from ${source}. A workspace id cannot contain line breaks or control characters.`);
|
|
2598
|
+
}
|
|
2599
|
+
return trimmed;
|
|
2600
|
+
}
|
|
2556
2601
|
function resolve(candidates, fallback, fallbackSource) {
|
|
2557
2602
|
for (const [source, value] of candidates) {
|
|
2558
2603
|
if (value !== null && value !== undefined && value !== "")
|
|
@@ -2565,6 +2610,9 @@ function resolveProfile(overrides = {}) {
|
|
|
2565
2610
|
const name = named || DEFAULT_PROFILE;
|
|
2566
2611
|
if (named && !overrides.allowUnknownProfile)
|
|
2567
2612
|
requireKnownProfile(named);
|
|
2613
|
+
if (named && overrides.allowUnknownProfile && !listProfiles().includes(named)) {
|
|
2614
|
+
validateProfileName(named);
|
|
2615
|
+
}
|
|
2568
2616
|
const config = readConfigProfile(name);
|
|
2569
2617
|
const authProfile = resolveAuthenticationProfileName(name);
|
|
2570
2618
|
const authConfig = authProfile === name ? config : readConfigProfile(authProfile);
|
|
@@ -6518,7 +6566,8 @@ var V2_OPERATIONS = {
|
|
|
6518
6566
|
version: "Numeric deployment version."
|
|
6519
6567
|
},
|
|
6520
6568
|
responseMode: "json",
|
|
6521
|
-
summary: "Activate Workflow Version"
|
|
6569
|
+
summary: "Activate Workflow Version",
|
|
6570
|
+
personalKeyOnly: true
|
|
6522
6571
|
},
|
|
6523
6572
|
addTableColumn: {
|
|
6524
6573
|
method: "POST",
|
|
@@ -6565,6 +6614,7 @@ var V2_OPERATIONS = {
|
|
|
6565
6614
|
pathParamDocs: { knowledgeBaseId: "Unique knowledge base identifier." },
|
|
6566
6615
|
responseMode: "json",
|
|
6567
6616
|
summary: "Index Workspace Files",
|
|
6617
|
+
personalKeyOnly: true,
|
|
6568
6618
|
body: {
|
|
6569
6619
|
workspaceId: {
|
|
6570
6620
|
kind: "string",
|
|
@@ -6585,6 +6635,7 @@ var V2_OPERATIONS = {
|
|
|
6585
6635
|
pathParamDocs: { workflowId: "Unique workflow identifier." },
|
|
6586
6636
|
responseMode: "json",
|
|
6587
6637
|
summary: "Apply Workflow Operations",
|
|
6638
|
+
personalKeyOnly: true,
|
|
6588
6639
|
query: {
|
|
6589
6640
|
dryRun: {
|
|
6590
6641
|
kind: "boolean",
|
|
@@ -6684,6 +6735,7 @@ var V2_OPERATIONS = {
|
|
|
6684
6735
|
pathParamDocs: { knowledgeBaseId: "Unique knowledge base identifier." },
|
|
6685
6736
|
responseMode: "json",
|
|
6686
6737
|
summary: "Bulk Save Tag Definitions",
|
|
6738
|
+
personalKeyOnly: true,
|
|
6687
6739
|
body: {
|
|
6688
6740
|
workspaceId: {
|
|
6689
6741
|
kind: "string",
|
|
@@ -6707,6 +6759,7 @@ var V2_OPERATIONS = {
|
|
|
6707
6759
|
},
|
|
6708
6760
|
responseMode: "json",
|
|
6709
6761
|
summary: "Bulk Update Chunks",
|
|
6762
|
+
personalKeyOnly: true,
|
|
6710
6763
|
body: {
|
|
6711
6764
|
workspaceId: {
|
|
6712
6765
|
kind: "string",
|
|
@@ -6722,7 +6775,7 @@ var V2_OPERATIONS = {
|
|
|
6722
6775
|
chunkIds: {
|
|
6723
6776
|
kind: "array",
|
|
6724
6777
|
required: true,
|
|
6725
|
-
describe: "Chunks to operate on, by identifier.
|
|
6778
|
+
describe: "Chunks to operate on, by identifier. An id naming no chunk in the document is reported in errors and does not fail the request."
|
|
6726
6779
|
}
|
|
6727
6780
|
}
|
|
6728
6781
|
},
|
|
@@ -6733,6 +6786,7 @@ var V2_OPERATIONS = {
|
|
|
6733
6786
|
pathParamDocs: { knowledgeBaseId: "Unique knowledge base identifier." },
|
|
6734
6787
|
responseMode: "json",
|
|
6735
6788
|
summary: "Bulk Enable or Disable Documents",
|
|
6789
|
+
personalKeyOnly: true,
|
|
6736
6790
|
body: {
|
|
6737
6791
|
workspaceId: {
|
|
6738
6792
|
kind: "string",
|
|
@@ -6957,6 +7011,7 @@ var V2_OPERATIONS = {
|
|
|
6957
7011
|
pathParams: [],
|
|
6958
7012
|
responseMode: "json",
|
|
6959
7013
|
summary: "Create Credential Connection",
|
|
7014
|
+
personalKeyOnly: true,
|
|
6960
7015
|
body: {
|
|
6961
7016
|
workspaceId: {
|
|
6962
7017
|
kind: "string",
|
|
@@ -7132,6 +7187,7 @@ var V2_OPERATIONS = {
|
|
|
7132
7187
|
},
|
|
7133
7188
|
responseMode: "json",
|
|
7134
7189
|
summary: "Create Chunk",
|
|
7190
|
+
personalKeyOnly: true,
|
|
7135
7191
|
body: {
|
|
7136
7192
|
workspaceId: {
|
|
7137
7193
|
kind: "string",
|
|
@@ -7157,6 +7213,7 @@ var V2_OPERATIONS = {
|
|
|
7157
7213
|
pathParamDocs: { knowledgeBaseId: "Unique knowledge base identifier." },
|
|
7158
7214
|
responseMode: "json",
|
|
7159
7215
|
summary: "Create Knowledge Connector",
|
|
7216
|
+
personalKeyOnly: true,
|
|
7160
7217
|
body: {
|
|
7161
7218
|
workspaceId: {
|
|
7162
7219
|
kind: "string",
|
|
@@ -7272,6 +7329,7 @@ var V2_OPERATIONS = {
|
|
|
7272
7329
|
pathParamDocs: { knowledgeBaseId: "Unique knowledge base identifier." },
|
|
7273
7330
|
responseMode: "json",
|
|
7274
7331
|
summary: "Create Tag",
|
|
7332
|
+
personalKeyOnly: true,
|
|
7275
7333
|
body: {
|
|
7276
7334
|
workspaceId: {
|
|
7277
7335
|
kind: "string",
|
|
@@ -7379,6 +7437,7 @@ var V2_OPERATIONS = {
|
|
|
7379
7437
|
pathParams: [],
|
|
7380
7438
|
responseMode: "json",
|
|
7381
7439
|
summary: "Create Service-Account Credential",
|
|
7440
|
+
personalKeyOnly: true,
|
|
7382
7441
|
body: {
|
|
7383
7442
|
workspaceId: {
|
|
7384
7443
|
kind: "string",
|
|
@@ -7417,6 +7476,7 @@ var V2_OPERATIONS = {
|
|
|
7417
7476
|
pathParams: [],
|
|
7418
7477
|
responseMode: "json",
|
|
7419
7478
|
summary: "Create Skill",
|
|
7479
|
+
personalKeyOnly: true,
|
|
7420
7480
|
body: {
|
|
7421
7481
|
workspaceId: {
|
|
7422
7482
|
kind: "string",
|
|
@@ -7632,6 +7692,7 @@ var V2_OPERATIONS = {
|
|
|
7632
7692
|
pathParams: [],
|
|
7633
7693
|
responseMode: "json",
|
|
7634
7694
|
summary: "Create Workflow MCP Server",
|
|
7695
|
+
personalKeyOnly: true,
|
|
7635
7696
|
body: {
|
|
7636
7697
|
workspaceId: {
|
|
7637
7698
|
kind: "string",
|
|
@@ -7662,6 +7723,7 @@ var V2_OPERATIONS = {
|
|
|
7662
7723
|
pathParamDocs: { credentialId: "Credential to disconnect." },
|
|
7663
7724
|
responseMode: "json",
|
|
7664
7725
|
summary: "Disconnect Credential",
|
|
7726
|
+
personalKeyOnly: true,
|
|
7665
7727
|
query: {
|
|
7666
7728
|
workspaceId: {
|
|
7667
7729
|
kind: "string",
|
|
@@ -7752,6 +7814,7 @@ var V2_OPERATIONS = {
|
|
|
7752
7814
|
},
|
|
7753
7815
|
responseMode: "json",
|
|
7754
7816
|
summary: "Delete Chunk",
|
|
7817
|
+
personalKeyOnly: true,
|
|
7755
7818
|
query: {
|
|
7756
7819
|
workspaceId: {
|
|
7757
7820
|
kind: "string",
|
|
@@ -7770,6 +7833,7 @@ var V2_OPERATIONS = {
|
|
|
7770
7833
|
},
|
|
7771
7834
|
responseMode: "json",
|
|
7772
7835
|
summary: "Delete Knowledge Connector",
|
|
7836
|
+
personalKeyOnly: true,
|
|
7773
7837
|
query: {
|
|
7774
7838
|
workspaceId: {
|
|
7775
7839
|
kind: "string",
|
|
@@ -7840,6 +7904,7 @@ var V2_OPERATIONS = {
|
|
|
7840
7904
|
},
|
|
7841
7905
|
responseMode: "json",
|
|
7842
7906
|
summary: "Delete Tag",
|
|
7907
|
+
personalKeyOnly: true,
|
|
7843
7908
|
query: {
|
|
7844
7909
|
workspaceId: {
|
|
7845
7910
|
kind: "string",
|
|
@@ -7855,6 +7920,7 @@ var V2_OPERATIONS = {
|
|
|
7855
7920
|
pathParamDocs: { knowledgeBaseId: "Unique knowledge base identifier." },
|
|
7856
7921
|
responseMode: "json",
|
|
7857
7922
|
summary: "Delete Tag Definitions",
|
|
7923
|
+
personalKeyOnly: true,
|
|
7858
7924
|
query: {
|
|
7859
7925
|
workspaceId: {
|
|
7860
7926
|
kind: "string",
|
|
@@ -7886,9 +7952,10 @@ var V2_OPERATIONS = {
|
|
|
7886
7952
|
method: "DELETE",
|
|
7887
7953
|
path: "/api/v2/secrets/[name]",
|
|
7888
7954
|
pathParams: ["name"],
|
|
7889
|
-
pathParamDocs: { name: "Secret to
|
|
7955
|
+
pathParamDocs: { name: "Secret to delete." },
|
|
7890
7956
|
responseMode: "json",
|
|
7891
7957
|
summary: "Delete Secret",
|
|
7958
|
+
personalKeyOnly: true,
|
|
7892
7959
|
query: {
|
|
7893
7960
|
workspaceId: {
|
|
7894
7961
|
kind: "string",
|
|
@@ -7912,6 +7979,7 @@ var V2_OPERATIONS = {
|
|
|
7912
7979
|
},
|
|
7913
7980
|
responseMode: "json",
|
|
7914
7981
|
summary: "Delete Skill",
|
|
7982
|
+
personalKeyOnly: true,
|
|
7915
7983
|
query: {
|
|
7916
7984
|
workspaceId: { kind: "string", required: true, describe: "Workspace that owns the skill." }
|
|
7917
7985
|
}
|
|
@@ -8022,7 +8090,8 @@ var V2_OPERATIONS = {
|
|
|
8022
8090
|
pathParams: ["workflowId"],
|
|
8023
8091
|
pathParamDocs: { workflowId: "Unique workflow identifier." },
|
|
8024
8092
|
responseMode: "json",
|
|
8025
|
-
summary: "Delete Workflow Chat Deployment"
|
|
8093
|
+
summary: "Delete Workflow Chat Deployment",
|
|
8094
|
+
personalKeyOnly: true
|
|
8026
8095
|
},
|
|
8027
8096
|
deleteWorkflowFolder: {
|
|
8028
8097
|
method: "DELETE",
|
|
@@ -8072,7 +8141,8 @@ var V2_OPERATIONS = {
|
|
|
8072
8141
|
pathParams: ["serverId"],
|
|
8073
8142
|
pathParamDocs: { serverId: "Unique workflow-MCP server identifier." },
|
|
8074
8143
|
responseMode: "json",
|
|
8075
|
-
summary: "Delete Workflow MCP Server"
|
|
8144
|
+
summary: "Delete Workflow MCP Server",
|
|
8145
|
+
personalKeyOnly: true
|
|
8076
8146
|
},
|
|
8077
8147
|
deployWorkflow: {
|
|
8078
8148
|
method: "POST",
|
|
@@ -8081,6 +8151,7 @@ var V2_OPERATIONS = {
|
|
|
8081
8151
|
pathParamDocs: { workflowId: "Unique workflow identifier." },
|
|
8082
8152
|
responseMode: "json",
|
|
8083
8153
|
summary: "Deploy Workflow",
|
|
8154
|
+
personalKeyOnly: true,
|
|
8084
8155
|
body: {
|
|
8085
8156
|
name: { kind: "string", describe: "Optional label for the deployment version." },
|
|
8086
8157
|
description: {
|
|
@@ -8096,6 +8167,7 @@ var V2_OPERATIONS = {
|
|
|
8096
8167
|
pathParamDocs: { serverId: "Unique workflow-MCP server identifier." },
|
|
8097
8168
|
responseMode: "json",
|
|
8098
8169
|
summary: "Publish Workflow As MCP Tool",
|
|
8170
|
+
personalKeyOnly: true,
|
|
8099
8171
|
body: {
|
|
8100
8172
|
workflowId: {
|
|
8101
8173
|
kind: "string",
|
|
@@ -8236,6 +8308,7 @@ var V2_OPERATIONS = {
|
|
|
8236
8308
|
pathParamDocs: { auditLogId: "Audit-log entry identifier." },
|
|
8237
8309
|
responseMode: "json",
|
|
8238
8310
|
summary: "Get Audit Log",
|
|
8311
|
+
personalKeyOnly: true,
|
|
8239
8312
|
query: {
|
|
8240
8313
|
organizationId: {
|
|
8241
8314
|
kind: "string",
|
|
@@ -8301,7 +8374,7 @@ var V2_OPERATIONS = {
|
|
|
8301
8374
|
kind: "enum",
|
|
8302
8375
|
values: ["active", "archived"],
|
|
8303
8376
|
default: "active",
|
|
8304
|
-
describe: "Which lifecycle set to read from: `active` (default) resolves live files only and returns `404` for a file a
|
|
8377
|
+
describe: "Which lifecycle set to read from: `active` (default) resolves live files only and returns `404` for a file a delete soft-deleted; `archived` also resolves soft-deleted files, so metadata stays readable before the file is restored. Authorization is identical for both."
|
|
8305
8378
|
}
|
|
8306
8379
|
}
|
|
8307
8380
|
},
|
|
@@ -8364,6 +8437,7 @@ var V2_OPERATIONS = {
|
|
|
8364
8437
|
},
|
|
8365
8438
|
responseMode: "json",
|
|
8366
8439
|
summary: "Get Chunk",
|
|
8440
|
+
personalKeyOnly: true,
|
|
8367
8441
|
query: {
|
|
8368
8442
|
workspaceId: {
|
|
8369
8443
|
kind: "string",
|
|
@@ -8382,6 +8456,7 @@ var V2_OPERATIONS = {
|
|
|
8382
8456
|
},
|
|
8383
8457
|
responseMode: "json",
|
|
8384
8458
|
summary: "Get Knowledge Connector",
|
|
8459
|
+
personalKeyOnly: true,
|
|
8385
8460
|
query: {
|
|
8386
8461
|
workspaceId: {
|
|
8387
8462
|
kind: "string",
|
|
@@ -8489,6 +8564,7 @@ var V2_OPERATIONS = {
|
|
|
8489
8564
|
pathParamDocs: { knowledgeBaseId: "Unique knowledge base identifier." },
|
|
8490
8565
|
responseMode: "json",
|
|
8491
8566
|
summary: "Get Next Tag Slot",
|
|
8567
|
+
personalKeyOnly: true,
|
|
8492
8568
|
query: {
|
|
8493
8569
|
workspaceId: {
|
|
8494
8570
|
kind: "string",
|
|
@@ -8656,7 +8732,8 @@ var V2_OPERATIONS = {
|
|
|
8656
8732
|
pathParams: ["workflowId"],
|
|
8657
8733
|
pathParamDocs: { workflowId: "Unique workflow identifier." },
|
|
8658
8734
|
responseMode: "json",
|
|
8659
|
-
summary: "Get Workflow Chat Deployment"
|
|
8735
|
+
summary: "Get Workflow Chat Deployment",
|
|
8736
|
+
personalKeyOnly: true
|
|
8660
8737
|
},
|
|
8661
8738
|
getWorkflowDeployment: {
|
|
8662
8739
|
method: "GET",
|
|
@@ -8672,7 +8749,8 @@ var V2_OPERATIONS = {
|
|
|
8672
8749
|
pathParams: ["serverId"],
|
|
8673
8750
|
pathParamDocs: { serverId: "Unique workflow-MCP server identifier." },
|
|
8674
8751
|
responseMode: "json",
|
|
8675
|
-
summary: "Get Workflow MCP Server"
|
|
8752
|
+
summary: "Get Workflow MCP Server",
|
|
8753
|
+
personalKeyOnly: true
|
|
8676
8754
|
},
|
|
8677
8755
|
getWorkflowRun: {
|
|
8678
8756
|
method: "GET",
|
|
@@ -8739,6 +8817,7 @@ var V2_OPERATIONS = {
|
|
|
8739
8817
|
},
|
|
8740
8818
|
responseMode: "json",
|
|
8741
8819
|
summary: "Grant Skill Editor",
|
|
8820
|
+
personalKeyOnly: true,
|
|
8742
8821
|
body: {
|
|
8743
8822
|
workspaceId: { kind: "string", required: true, describe: "Workspace that owns the skill." },
|
|
8744
8823
|
email: {
|
|
@@ -8779,6 +8858,7 @@ var V2_OPERATIONS = {
|
|
|
8779
8858
|
pathParams: [],
|
|
8780
8859
|
responseMode: "json",
|
|
8781
8860
|
summary: "List Audit Logs",
|
|
8861
|
+
personalKeyOnly: true,
|
|
8782
8862
|
query: {
|
|
8783
8863
|
action: { kind: "string", describe: "Filter by exact action name." },
|
|
8784
8864
|
resourceType: {
|
|
@@ -9116,7 +9196,7 @@ var V2_OPERATIONS = {
|
|
|
9116
9196
|
kind: "enum",
|
|
9117
9197
|
values: ["active", "archived"],
|
|
9118
9198
|
default: "active",
|
|
9119
|
-
describe: "Which lifecycle set to list: `active` (default) returns live folders only; `archived` returns folders a recursive
|
|
9199
|
+
describe: "Which lifecycle set to list: `active` (default) returns live folders only; `archived` returns folders a recursive delete soft-deleted, which is how a caller finds a path to hand to the folder restore. Authorization is identical for both."
|
|
9120
9200
|
}
|
|
9121
9201
|
}
|
|
9122
9202
|
},
|
|
@@ -9158,7 +9238,7 @@ var V2_OPERATIONS = {
|
|
|
9158
9238
|
kind: "enum",
|
|
9159
9239
|
values: ["active", "archived"],
|
|
9160
9240
|
default: "active",
|
|
9161
|
-
describe: "Which lifecycle set to list: `active` (default) for live files, `archived` for files a
|
|
9241
|
+
describe: "Which lifecycle set to list: `active` (default) for live files, `archived` for files a delete soft-deleted. `folderPath` resolves against active folders only, so pairing it with `scope=archived` returns an empty page when the containing folder was archived too."
|
|
9162
9242
|
},
|
|
9163
9243
|
search: {
|
|
9164
9244
|
kind: "string",
|
|
@@ -9246,6 +9326,7 @@ var V2_OPERATIONS = {
|
|
|
9246
9326
|
},
|
|
9247
9327
|
responseMode: "json",
|
|
9248
9328
|
summary: "List Chunks",
|
|
9329
|
+
personalKeyOnly: true,
|
|
9249
9330
|
query: {
|
|
9250
9331
|
workspaceId: {
|
|
9251
9332
|
kind: "string",
|
|
@@ -9295,6 +9376,7 @@ var V2_OPERATIONS = {
|
|
|
9295
9376
|
},
|
|
9296
9377
|
responseMode: "json",
|
|
9297
9378
|
summary: "List Knowledge Connector Documents",
|
|
9379
|
+
personalKeyOnly: true,
|
|
9298
9380
|
query: {
|
|
9299
9381
|
workspaceId: {
|
|
9300
9382
|
kind: "string",
|
|
@@ -9323,6 +9405,7 @@ var V2_OPERATIONS = {
|
|
|
9323
9405
|
pathParamDocs: { knowledgeBaseId: "Unique knowledge base identifier." },
|
|
9324
9406
|
responseMode: "json",
|
|
9325
9407
|
summary: "List Knowledge Connectors",
|
|
9408
|
+
personalKeyOnly: true,
|
|
9326
9409
|
query: {
|
|
9327
9410
|
workspaceId: {
|
|
9328
9411
|
kind: "string",
|
|
@@ -9466,6 +9549,7 @@ var V2_OPERATIONS = {
|
|
|
9466
9549
|
pathParamDocs: { knowledgeBaseId: "Unique knowledge base identifier." },
|
|
9467
9550
|
responseMode: "json",
|
|
9468
9551
|
summary: "List Tag Usage",
|
|
9552
|
+
personalKeyOnly: true,
|
|
9469
9553
|
query: {
|
|
9470
9554
|
workspaceId: {
|
|
9471
9555
|
kind: "string",
|
|
@@ -9624,6 +9708,7 @@ var V2_OPERATIONS = {
|
|
|
9624
9708
|
pathParamDocs: { mcpServerId: "Unique MCP server identifier." },
|
|
9625
9709
|
responseMode: "json",
|
|
9626
9710
|
summary: "List MCP Server Tools",
|
|
9711
|
+
personalKeyOnly: true,
|
|
9627
9712
|
query: {
|
|
9628
9713
|
workspaceId: {
|
|
9629
9714
|
kind: "string",
|
|
@@ -9642,6 +9727,7 @@ var V2_OPERATIONS = {
|
|
|
9642
9727
|
pathParams: [],
|
|
9643
9728
|
responseMode: "json",
|
|
9644
9729
|
summary: "List Secrets",
|
|
9730
|
+
personalKeyOnly: true,
|
|
9645
9731
|
query: {
|
|
9646
9732
|
workspaceId: {
|
|
9647
9733
|
kind: "string",
|
|
@@ -9834,7 +9920,7 @@ var V2_OPERATIONS = {
|
|
|
9834
9920
|
kind: "enum",
|
|
9835
9921
|
values: ["active", "archived"],
|
|
9836
9922
|
default: "active",
|
|
9837
|
-
describe: "Which lifecycle set to list: `active` (default) for live tables, `archived` for tables a
|
|
9923
|
+
describe: "Which lifecycle set to list: `active` (default) for live tables, `archived` for tables a delete archived and a table 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."
|
|
9838
9924
|
},
|
|
9839
9925
|
folderPath: {
|
|
9840
9926
|
kind: "string",
|
|
@@ -9977,6 +10063,7 @@ var V2_OPERATIONS = {
|
|
|
9977
10063
|
pathParams: [],
|
|
9978
10064
|
responseMode: "json",
|
|
9979
10065
|
summary: "List Workflow MCP Servers",
|
|
10066
|
+
personalKeyOnly: true,
|
|
9980
10067
|
query: {
|
|
9981
10068
|
workspaceId: {
|
|
9982
10069
|
kind: "string",
|
|
@@ -10012,7 +10099,8 @@ var V2_OPERATIONS = {
|
|
|
10012
10099
|
pathParams: ["serverId"],
|
|
10013
10100
|
pathParamDocs: { serverId: "Unique workflow-MCP server identifier." },
|
|
10014
10101
|
responseMode: "json",
|
|
10015
|
-
summary: "List Workflow MCP Tools"
|
|
10102
|
+
summary: "List Workflow MCP Tools",
|
|
10103
|
+
personalKeyOnly: true
|
|
10016
10104
|
},
|
|
10017
10105
|
listWorkflowRuns: {
|
|
10018
10106
|
method: "GET",
|
|
@@ -10372,6 +10460,7 @@ var V2_OPERATIONS = {
|
|
|
10372
10460
|
pathParamDocs: { workflowId: "Unique workflow identifier." },
|
|
10373
10461
|
responseMode: "json",
|
|
10374
10462
|
summary: "Create or Replace Workflow Chat Deployment",
|
|
10463
|
+
personalKeyOnly: true,
|
|
10375
10464
|
body: {
|
|
10376
10465
|
identifier: {
|
|
10377
10466
|
kind: "string",
|
|
@@ -10424,6 +10513,7 @@ var V2_OPERATIONS = {
|
|
|
10424
10513
|
pathParamDocs: { workflowId: "Unique workflow identifier." },
|
|
10425
10514
|
responseMode: "json",
|
|
10426
10515
|
summary: "Replace Workflow State",
|
|
10516
|
+
personalKeyOnly: true,
|
|
10427
10517
|
query: {
|
|
10428
10518
|
dryRun: {
|
|
10429
10519
|
kind: "boolean",
|
|
@@ -10477,7 +10567,7 @@ var V2_OPERATIONS = {
|
|
|
10477
10567
|
path: {
|
|
10478
10568
|
kind: "string",
|
|
10479
10569
|
required: true,
|
|
10480
|
-
describe: "Path of the archived folder to restore, as reported by
|
|
10570
|
+
describe: "Path of the archived folder to restore, as reported by an archived-scope folder list."
|
|
10481
10571
|
}
|
|
10482
10572
|
}
|
|
10483
10573
|
},
|
|
@@ -10522,7 +10612,7 @@ var V2_OPERATIONS = {
|
|
|
10522
10612
|
path: {
|
|
10523
10613
|
kind: "string",
|
|
10524
10614
|
required: true,
|
|
10525
|
-
describe: "Path the folder held when
|
|
10615
|
+
describe: "Path the folder held when a folder delete archived it."
|
|
10526
10616
|
}
|
|
10527
10617
|
}
|
|
10528
10618
|
},
|
|
@@ -10562,7 +10652,8 @@ var V2_OPERATIONS = {
|
|
|
10562
10652
|
version: "Numeric deployment version, or `active` for the currently live version."
|
|
10563
10653
|
},
|
|
10564
10654
|
responseMode: "json",
|
|
10565
|
-
summary: "Revert Workflow To Version"
|
|
10655
|
+
summary: "Revert Workflow To Version",
|
|
10656
|
+
personalKeyOnly: true
|
|
10566
10657
|
},
|
|
10567
10658
|
revokeSkillEditor: {
|
|
10568
10659
|
method: "DELETE",
|
|
@@ -10573,6 +10664,7 @@ var V2_OPERATIONS = {
|
|
|
10573
10664
|
},
|
|
10574
10665
|
responseMode: "json",
|
|
10575
10666
|
summary: "Revoke Skill Editor",
|
|
10667
|
+
personalKeyOnly: true,
|
|
10576
10668
|
query: {
|
|
10577
10669
|
workspaceId: { kind: "string", required: true, describe: "Workspace that owns the skill." },
|
|
10578
10670
|
email: {
|
|
@@ -10589,6 +10681,7 @@ var V2_OPERATIONS = {
|
|
|
10589
10681
|
pathParamDocs: { workflowId: "Unique workflow identifier." },
|
|
10590
10682
|
responseMode: "json",
|
|
10591
10683
|
summary: "Rollback Workflow",
|
|
10684
|
+
personalKeyOnly: true,
|
|
10592
10685
|
body: {
|
|
10593
10686
|
version: {
|
|
10594
10687
|
kind: "integer",
|
|
@@ -10683,9 +10776,10 @@ var V2_OPERATIONS = {
|
|
|
10683
10776
|
method: "PUT",
|
|
10684
10777
|
path: "/api/v2/secrets/[name]",
|
|
10685
10778
|
pathParams: ["name"],
|
|
10686
|
-
pathParamDocs: { name: "Secret to create
|
|
10779
|
+
pathParamDocs: { name: "Secret to create or replace." },
|
|
10687
10780
|
responseMode: "json",
|
|
10688
10781
|
summary: "Set Secret",
|
|
10782
|
+
personalKeyOnly: true,
|
|
10689
10783
|
body: {
|
|
10690
10784
|
workspaceId: {
|
|
10691
10785
|
kind: "string",
|
|
@@ -10700,8 +10794,7 @@ var V2_OPERATIONS = {
|
|
|
10700
10794
|
},
|
|
10701
10795
|
value: {
|
|
10702
10796
|
kind: "string",
|
|
10703
|
-
|
|
10704
|
-
describe: "Write-only secret value. It is never returned."
|
|
10797
|
+
describe: "Write-only secret value. It is never returned. Omit it on a workspace secret to change description or unredacted alone, leaving the stored value untouched; the secret must already exist. Always required for a personal secret, which carries no other writable field."
|
|
10705
10798
|
},
|
|
10706
10799
|
description: {
|
|
10707
10800
|
kind: "string",
|
|
@@ -10723,6 +10816,7 @@ var V2_OPERATIONS = {
|
|
|
10723
10816
|
},
|
|
10724
10817
|
responseMode: "json",
|
|
10725
10818
|
summary: "Sync Knowledge Connector",
|
|
10819
|
+
personalKeyOnly: true,
|
|
10726
10820
|
body: {
|
|
10727
10821
|
workspaceId: {
|
|
10728
10822
|
kind: "string",
|
|
@@ -10760,7 +10854,8 @@ var V2_OPERATIONS = {
|
|
|
10760
10854
|
pathParams: ["workflowId"],
|
|
10761
10855
|
pathParamDocs: { workflowId: "Unique workflow identifier." },
|
|
10762
10856
|
responseMode: "json",
|
|
10763
|
-
summary: "Undeploy Workflow"
|
|
10857
|
+
summary: "Undeploy Workflow",
|
|
10858
|
+
personalKeyOnly: true
|
|
10764
10859
|
},
|
|
10765
10860
|
undeployWorkflowMcpTool: {
|
|
10766
10861
|
method: "DELETE",
|
|
@@ -10771,7 +10866,8 @@ var V2_OPERATIONS = {
|
|
|
10771
10866
|
workflowId: "Workflow published as a tool on this server."
|
|
10772
10867
|
},
|
|
10773
10868
|
responseMode: "json",
|
|
10774
|
-
summary: "Unpublish Workflow MCP Tool"
|
|
10869
|
+
summary: "Unpublish Workflow MCP Tool",
|
|
10870
|
+
personalKeyOnly: true
|
|
10775
10871
|
},
|
|
10776
10872
|
unzipFile: {
|
|
10777
10873
|
method: "POST",
|
|
@@ -10791,6 +10887,7 @@ var V2_OPERATIONS = {
|
|
|
10791
10887
|
pathParamDocs: { credentialId: "Credential to update." },
|
|
10792
10888
|
responseMode: "json",
|
|
10793
10889
|
summary: "Update Credential",
|
|
10890
|
+
personalKeyOnly: true,
|
|
10794
10891
|
query: {
|
|
10795
10892
|
workspaceId: {
|
|
10796
10893
|
kind: "string",
|
|
@@ -10892,6 +10989,7 @@ var V2_OPERATIONS = {
|
|
|
10892
10989
|
},
|
|
10893
10990
|
responseMode: "json",
|
|
10894
10991
|
summary: "Update Chunk",
|
|
10992
|
+
personalKeyOnly: true,
|
|
10895
10993
|
body: {
|
|
10896
10994
|
workspaceId: {
|
|
10897
10995
|
kind: "string",
|
|
@@ -10918,6 +11016,7 @@ var V2_OPERATIONS = {
|
|
|
10918
11016
|
},
|
|
10919
11017
|
responseMode: "json",
|
|
10920
11018
|
summary: "Update Knowledge Connector",
|
|
11019
|
+
personalKeyOnly: true,
|
|
10921
11020
|
body: {
|
|
10922
11021
|
workspaceId: {
|
|
10923
11022
|
kind: "string",
|
|
@@ -10949,6 +11048,7 @@ var V2_OPERATIONS = {
|
|
|
10949
11048
|
},
|
|
10950
11049
|
responseMode: "json",
|
|
10951
11050
|
summary: "Update Knowledge Connector Documents",
|
|
11051
|
+
personalKeyOnly: true,
|
|
10952
11052
|
body: {
|
|
10953
11053
|
workspaceId: {
|
|
10954
11054
|
kind: "string",
|
|
@@ -10978,6 +11078,7 @@ var V2_OPERATIONS = {
|
|
|
10978
11078
|
},
|
|
10979
11079
|
responseMode: "json",
|
|
10980
11080
|
summary: "Update Document",
|
|
11081
|
+
personalKeyOnly: true,
|
|
10981
11082
|
body: {
|
|
10982
11083
|
workspaceId: {
|
|
10983
11084
|
kind: "string",
|
|
@@ -11022,6 +11123,7 @@ var V2_OPERATIONS = {
|
|
|
11022
11123
|
},
|
|
11023
11124
|
responseMode: "json",
|
|
11024
11125
|
summary: "Update Tag",
|
|
11126
|
+
personalKeyOnly: true,
|
|
11025
11127
|
body: {
|
|
11026
11128
|
workspaceId: {
|
|
11027
11129
|
kind: "string",
|
|
@@ -11126,6 +11228,7 @@ var V2_OPERATIONS = {
|
|
|
11126
11228
|
},
|
|
11127
11229
|
responseMode: "json",
|
|
11128
11230
|
summary: "Update Skill",
|
|
11231
|
+
personalKeyOnly: true,
|
|
11129
11232
|
body: {
|
|
11130
11233
|
workspaceId: { kind: "string", required: true, describe: "Workspace that owns the skill." },
|
|
11131
11234
|
name: { kind: "string", describe: "New kebab-case skill name." },
|
|
@@ -11263,6 +11366,7 @@ var V2_OPERATIONS = {
|
|
|
11263
11366
|
pathParamDocs: { serverId: "Unique workflow-MCP server identifier." },
|
|
11264
11367
|
responseMode: "json",
|
|
11265
11368
|
summary: "Update Workflow MCP Server",
|
|
11369
|
+
personalKeyOnly: true,
|
|
11266
11370
|
body: {
|
|
11267
11371
|
name: { kind: "string", describe: "Server display name, shown to connecting MCP clients." },
|
|
11268
11372
|
description: { kind: "string", describe: "New server description, or null to clear it." },
|
|
@@ -11279,6 +11383,7 @@ var V2_OPERATIONS = {
|
|
|
11279
11383
|
pathParamDocs: { workflowId: "Unique workflow identifier." },
|
|
11280
11384
|
responseMode: "json",
|
|
11281
11385
|
summary: "Update Workflow Public API Access",
|
|
11386
|
+
personalKeyOnly: true,
|
|
11282
11387
|
body: {
|
|
11283
11388
|
isPublicApi: {
|
|
11284
11389
|
kind: "boolean",
|
|
@@ -11327,6 +11432,7 @@ var V2_OPERATIONS = {
|
|
|
11327
11432
|
pathParamDocs: { fileId: "File identifier." },
|
|
11328
11433
|
responseMode: "json",
|
|
11329
11434
|
summary: "Enable or Disable File Share",
|
|
11435
|
+
personalKeyOnly: true,
|
|
11330
11436
|
body: {
|
|
11331
11437
|
workspaceId: { kind: "string", required: true, describe: "Workspace that owns the file." },
|
|
11332
11438
|
isActive: {
|
|
@@ -11361,7 +11467,7 @@ var V2_OPERATIONS = {
|
|
|
11361
11467
|
data: {
|
|
11362
11468
|
kind: "object",
|
|
11363
11469
|
required: true,
|
|
11364
|
-
describe: "Complete set of row cells keyed by column name. On the update branch this REPLACES the matched row: any column not present here is cleared, unlike
|
|
11470
|
+
describe: "Complete set of row cells keyed by column name. On the update branch this REPLACES the matched row: any column not present here is cleared, unlike a single-row update, which merges."
|
|
11365
11471
|
},
|
|
11366
11472
|
conflictTarget: { kind: "string", describe: "Unique column used to detect a conflict." }
|
|
11367
11473
|
}
|
|
@@ -11369,7 +11475,6 @@ var V2_OPERATIONS = {
|
|
|
11369
11475
|
};
|
|
11370
11476
|
|
|
11371
11477
|
// src/commands/auth.ts
|
|
11372
|
-
var PROFILE_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
11373
11478
|
var MAX_INTERACTIVE_WORKSPACES = 1000;
|
|
11374
11479
|
function openBrowser(url) {
|
|
11375
11480
|
const [command, args] = process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : [process.platform === "darwin" ? "open" : "xdg-open", [url]];
|
|
@@ -11410,13 +11515,16 @@ function selectedProfileName(command) {
|
|
|
11410
11515
|
return globalsOf(command).profile || process.env.SIM_PROFILE || DEFAULT_PROFILE;
|
|
11411
11516
|
}
|
|
11412
11517
|
function validateNewProfileName(profileName) {
|
|
11413
|
-
|
|
11414
|
-
throw new SimApiError(`Invalid profile name "${profileName}". Use letters, numbers, dots, underscores, or hyphens, starting with a letter or number.`, 0);
|
|
11415
|
-
}
|
|
11518
|
+
validateProfileName(profileName);
|
|
11416
11519
|
if (listProfiles().includes(profileName)) {
|
|
11417
11520
|
throw new SimApiError(`Profile "${profileName}" already exists. Remove it first with: sim logout --all --profile ${profileName}`, 0);
|
|
11418
11521
|
}
|
|
11419
11522
|
}
|
|
11523
|
+
function requireStorableKey(apiKey) {
|
|
11524
|
+
if (typeof apiKey !== "string" || !apiKey || apiKey !== apiKey.trim() || FORBIDDEN_IN_VALUE.test(apiKey)) {
|
|
11525
|
+
throw new SimApiError("The server returned a malformed API key. Nothing was stored; check the endpoint.", 0);
|
|
11526
|
+
}
|
|
11527
|
+
}
|
|
11420
11528
|
function requireStoredAuthentication(profile) {
|
|
11421
11529
|
const authProfile = resolveAuthenticationProfileName(profile.name);
|
|
11422
11530
|
const storedKey = readCredentialsProfile(authProfile).api_key;
|
|
@@ -11476,7 +11584,7 @@ function addProfileCommand() {
|
|
|
11476
11584
|
const workspace = workspaceId ? await getWorkspaceById(client, workspaceId) : await chooseWorkspace(client);
|
|
11477
11585
|
writeConfigProfile(profileName, {
|
|
11478
11586
|
auth_profile: authProfile,
|
|
11479
|
-
workspace: workspace.id
|
|
11587
|
+
workspace: normalizeWorkspaceId(workspace.id, "the workspace response")
|
|
11480
11588
|
});
|
|
11481
11589
|
console.log(source_default.green(`✓ Added profile "${profileName}" in ${configPath()}`));
|
|
11482
11590
|
console.log(` Workspace: ${safeOneLine(workspace.name)} (${workspace.id})`);
|
|
@@ -11518,12 +11626,13 @@ Waiting for approval…`));
|
|
|
11518
11626
|
if (key.scope !== scope) {
|
|
11519
11627
|
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);
|
|
11520
11628
|
}
|
|
11521
|
-
writeCredentialsProfile(profile.name, key.apiKey);
|
|
11522
11629
|
const settings = {
|
|
11523
11630
|
endpoint: profile.endpoint,
|
|
11524
|
-
workspace: key.workspaceId
|
|
11631
|
+
workspace: key.workspaceId == null ? null : normalizeWorkspaceId(key.workspaceId, "the login response")
|
|
11525
11632
|
};
|
|
11633
|
+
requireStorableKey(key.apiKey);
|
|
11526
11634
|
writeConfigProfile(profile.name, settings);
|
|
11635
|
+
writeCredentialsProfile(profile.name, key.apiKey);
|
|
11527
11636
|
console.log(source_default.green(`
|
|
11528
11637
|
✓ Logged in. Key stored in ${credentialsPath()}`));
|
|
11529
11638
|
if (key.workspaceBound && key.workspaceId) {
|
|
@@ -11687,30 +11796,62 @@ function whoamiCommand() {
|
|
|
11687
11796
|
process.exitCode = exitCode;
|
|
11688
11797
|
});
|
|
11689
11798
|
}
|
|
11799
|
+
var PROFILE_COLUMNS = [
|
|
11800
|
+
{ header: "", value: (row) => row.active ? source_default.green("*") : " " },
|
|
11801
|
+
{ header: "profile", value: (row) => text(row.name) },
|
|
11802
|
+
{ header: "key", value: (row) => row.error ? text(null) : row.hasKey ? "yes" : "no" },
|
|
11803
|
+
{ header: "auth", value: (row) => text(row.authProfile) },
|
|
11804
|
+
{ header: "error", value: (row) => row.error ? source_default.red(safeOneLine(row.error)) : text(null) }
|
|
11805
|
+
];
|
|
11806
|
+
function buildProfileRow(name, active) {
|
|
11807
|
+
try {
|
|
11808
|
+
const authProfile = resolveAuthenticationProfileName(name);
|
|
11809
|
+
return {
|
|
11810
|
+
name,
|
|
11811
|
+
active,
|
|
11812
|
+
hasKey: Boolean(readCredentialsProfile(authProfile).api_key),
|
|
11813
|
+
authProfile,
|
|
11814
|
+
error: null
|
|
11815
|
+
};
|
|
11816
|
+
} catch (error) {
|
|
11817
|
+
if (!(error instanceof ProfileConfigError))
|
|
11818
|
+
throw error;
|
|
11819
|
+
return { name, active, hasKey: false, authProfile: null, error: error.message };
|
|
11820
|
+
}
|
|
11821
|
+
}
|
|
11822
|
+
function profileListingContext(command) {
|
|
11823
|
+
try {
|
|
11824
|
+
const profile = profileFrom(command);
|
|
11825
|
+
return { activeName: profile.name, output: profile.output };
|
|
11826
|
+
} catch (error) {
|
|
11827
|
+
if (!(error instanceof ProfileConfigError))
|
|
11828
|
+
throw error;
|
|
11829
|
+
const globals = globalsOf(command);
|
|
11830
|
+
const named = globals.profile || process.env.SIM_PROFILE;
|
|
11831
|
+
if (named && named !== DEFAULT_PROFILE && !listProfiles().includes(named))
|
|
11832
|
+
throw error;
|
|
11833
|
+
const requested = globals.output ?? process.env.SIM_OUTPUT;
|
|
11834
|
+
if (requested && !OUTPUT_FORMATS.includes(requested))
|
|
11835
|
+
throw error;
|
|
11836
|
+
return {
|
|
11837
|
+
activeName: named || DEFAULT_PROFILE,
|
|
11838
|
+
output: requested ? requested : "table"
|
|
11839
|
+
};
|
|
11840
|
+
}
|
|
11841
|
+
}
|
|
11690
11842
|
function profilesCommand() {
|
|
11691
11843
|
const command = new Command("profiles").alias("profile").description("List profiles or add a workspace profile that shares a stored login");
|
|
11692
11844
|
const printProfiles = (_options, actionCommand) => {
|
|
11693
|
-
const
|
|
11694
|
-
|
|
11695
|
-
|
|
11845
|
+
const { activeName, output } = profileListingContext(actionCommand);
|
|
11846
|
+
const rows = listProfiles().map((name) => buildProfileRow(name, name === activeName));
|
|
11847
|
+
if (rows.length === 0) {
|
|
11848
|
+
if (output === "table")
|
|
11849
|
+
console.log(source_default.dim("No profiles yet. Run: sim login"));
|
|
11850
|
+
else
|
|
11851
|
+
printList(output, rows, PROFILE_COLUMNS);
|
|
11696
11852
|
return;
|
|
11697
11853
|
}
|
|
11698
|
-
|
|
11699
|
-
for (const name of profiles) {
|
|
11700
|
-
const marker = name === active ? source_default.green("*") : " ";
|
|
11701
|
-
let authProfile;
|
|
11702
|
-
try {
|
|
11703
|
-
authProfile = resolveAuthenticationProfileName(name);
|
|
11704
|
-
} catch (error) {
|
|
11705
|
-
if (!(error instanceof ProfileConfigError))
|
|
11706
|
-
throw error;
|
|
11707
|
-
console.log(`${marker} ${name}${source_default.red(` (${safeOneLine(error.message)})`)}`);
|
|
11708
|
-
continue;
|
|
11709
|
-
}
|
|
11710
|
-
const hasKey = Boolean(readCredentialsProfile(authProfile).api_key);
|
|
11711
|
-
const authentication = authProfile === name ? "" : source_default.dim(` (auth: ${authProfile})`);
|
|
11712
|
-
console.log(`${marker} ${name}${hasKey ? "" : source_default.dim(" (no key)")}${authentication}`);
|
|
11713
|
-
}
|
|
11854
|
+
printList(output, rows, PROFILE_COLUMNS);
|
|
11714
11855
|
};
|
|
11715
11856
|
command.action(printProfiles);
|
|
11716
11857
|
command.addCommand(new Command("list").description("List configured profiles").action(printProfiles));
|
|
@@ -11719,6 +11860,11 @@ function profilesCommand() {
|
|
|
11719
11860
|
}
|
|
11720
11861
|
|
|
11721
11862
|
// src/commands/configure.ts
|
|
11863
|
+
var GLOBAL_FLAG_TWINS = [
|
|
11864
|
+
{ option: "endpoint", flag: "--endpoint", setFlag: "--set-endpoint" },
|
|
11865
|
+
{ option: "workspace", flag: "-w, --workspace", setFlag: "--set-workspace" },
|
|
11866
|
+
{ option: "output", flag: "--output", setFlag: "--set-output" }
|
|
11867
|
+
];
|
|
11722
11868
|
function requireValue(value, flag, key) {
|
|
11723
11869
|
if (value !== undefined && value.trim() === "") {
|
|
11724
11870
|
throw new SimApiError(`${flag} requires a value. To remove it, run: sim configure --unset ${key}`, 0);
|
|
@@ -11726,6 +11872,13 @@ function requireValue(value, flag, key) {
|
|
|
11726
11872
|
}
|
|
11727
11873
|
function configureCommand() {
|
|
11728
11874
|
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) => {
|
|
11875
|
+
const globals = globalsOf(command);
|
|
11876
|
+
for (const { option, flag, setFlag } of GLOBAL_FLAG_TWINS) {
|
|
11877
|
+
const value = globals[option];
|
|
11878
|
+
if (value === undefined)
|
|
11879
|
+
continue;
|
|
11880
|
+
throw new SimApiError(`${flag} applies to a single command and is not stored. To save it, run: sim configure ${setFlag} ${value}`, 0);
|
|
11881
|
+
}
|
|
11729
11882
|
const profile = profileFrom(command, { allowUnknownProfile: true });
|
|
11730
11883
|
const authProfile = resolveAuthenticationProfileName(profile.name);
|
|
11731
11884
|
const updates = {};
|
|
@@ -11738,8 +11891,9 @@ function configureCommand() {
|
|
|
11738
11891
|
}
|
|
11739
11892
|
updates.endpoint = normalizeEndpoint(options.setEndpoint, "--set-endpoint");
|
|
11740
11893
|
}
|
|
11741
|
-
if (options.setWorkspace)
|
|
11742
|
-
updates.workspace = options.setWorkspace;
|
|
11894
|
+
if (options.setWorkspace) {
|
|
11895
|
+
updates.workspace = normalizeWorkspaceId(options.setWorkspace, "--set-workspace");
|
|
11896
|
+
}
|
|
11743
11897
|
if (options.setOutput) {
|
|
11744
11898
|
if (!OUTPUT_FORMATS.includes(options.setOutput)) {
|
|
11745
11899
|
throw new SimApiError(`Unknown output format "${options.setOutput}". Use one of: ${OUTPUT_FORMATS.join(", ")}`, 0);
|
|
@@ -11766,6 +11920,11 @@ function configureCommand() {
|
|
|
11766
11920
|
}
|
|
11767
11921
|
return;
|
|
11768
11922
|
}
|
|
11923
|
+
const removalOnly = Object.values(updates).every((value) => value === null);
|
|
11924
|
+
if (removalOnly && Object.keys(readConfigProfile(profile.name)).length === 0) {
|
|
11925
|
+
console.log(source_default.dim(`No settings stored for profile "${profile.name}".`));
|
|
11926
|
+
return;
|
|
11927
|
+
}
|
|
11769
11928
|
writeConfigProfile(profile.name, updates);
|
|
11770
11929
|
console.log(source_default.green(`✓ Updated profile "${profile.name}" in ${configPath()}`));
|
|
11771
11930
|
});
|
|
@@ -11858,7 +12017,7 @@ var CLI_CONTRACT = {
|
|
|
11858
12017
|
listBillingLogs: {
|
|
11859
12018
|
command: "billing logs",
|
|
11860
12019
|
allWorkspaces: true,
|
|
11861
|
-
describe: "List credit usage events",
|
|
12020
|
+
describe: "List credit usage events (a personal API key reports only your own events; a workspace API key reports every member's)",
|
|
11862
12021
|
flags: {
|
|
11863
12022
|
source: { describe: "Filter by usage source; sim-chat combines Copilot and workspace chat" },
|
|
11864
12023
|
period: { describe: "Billing period" },
|
|
@@ -12014,14 +12173,14 @@ var CLI_CONTRACT = {
|
|
|
12014
12173
|
}
|
|
12015
12174
|
},
|
|
12016
12175
|
columns: [
|
|
12017
|
-
{ header: "started", path: "startedAt", format: "timestamp" },
|
|
12018
|
-
{ header: "status" },
|
|
12176
|
+
{ header: "started", path: "startedAt", format: "timestamp", minWidth: 19 },
|
|
12177
|
+
{ header: "status", minWidth: 9 },
|
|
12019
12178
|
{ header: "level" },
|
|
12020
|
-
{ header: "trigger" },
|
|
12021
|
-
{ header: "workflow", path: "workflow.name" },
|
|
12179
|
+
{ header: "trigger", minWidth: 12 },
|
|
12180
|
+
{ header: "workflow", path: "workflow.name", minWidth: 24 },
|
|
12022
12181
|
{ header: "duration", path: "totalDurationMs", format: "duration" },
|
|
12023
|
-
{ header: "cost", path: "cost.total", format: "cost" },
|
|
12024
|
-
{ header: "run", path: "runId" }
|
|
12182
|
+
{ header: "cost", path: "cost.total", format: "cost", minWidth: 8 },
|
|
12183
|
+
{ header: "run", path: "runId", minWidth: 36 }
|
|
12025
12184
|
]
|
|
12026
12185
|
},
|
|
12027
12186
|
getLog: {
|
|
@@ -12769,6 +12928,23 @@ var CLI_CONTRACT = {
|
|
|
12769
12928
|
}
|
|
12770
12929
|
}
|
|
12771
12930
|
},
|
|
12931
|
+
listTableDispatches: {
|
|
12932
|
+
columns: [
|
|
12933
|
+
{ header: "id" },
|
|
12934
|
+
{ header: "status" },
|
|
12935
|
+
{ header: "mode" },
|
|
12936
|
+
{ header: "max rows", path: "limit.max" },
|
|
12937
|
+
{ header: "processed", path: "processedCount" },
|
|
12938
|
+
{ header: "manual", path: "isManualRun", format: "bool" },
|
|
12939
|
+
{ header: "requested", path: "requestedAt", format: "timestamp" },
|
|
12940
|
+
{ header: "completed", path: "completedAt", format: "timestamp" },
|
|
12941
|
+
{ header: "canceled", path: "canceledAt", format: "timestamp" },
|
|
12942
|
+
{ header: "groups", path: "scope.groupIds", format: "count" },
|
|
12943
|
+
{ header: "rows", path: "scope.rowIds", format: "count" },
|
|
12944
|
+
{ header: "filtered", path: "scope.filtered", format: "bool" },
|
|
12945
|
+
{ header: "excluded", path: "scope.excludeRowIds", format: "count" }
|
|
12946
|
+
]
|
|
12947
|
+
},
|
|
12772
12948
|
runRowEnrichment: {
|
|
12773
12949
|
command: "tables rows enrich",
|
|
12774
12950
|
describe: "Run one row’s enrichment group"
|
|
@@ -12777,8 +12953,16 @@ var CLI_CONTRACT = {
|
|
|
12777
12953
|
createTableImportPartUrls: { hidden: true },
|
|
12778
12954
|
completeTableImport: { hidden: true },
|
|
12779
12955
|
getTableImport: { flags: TRANSFER_TOKEN_OMITTED },
|
|
12780
|
-
cancelTableImport: {
|
|
12781
|
-
|
|
12956
|
+
cancelTableImport: {
|
|
12957
|
+
command: "tables imports cancel",
|
|
12958
|
+
flags: TRANSFER_TOKEN_OMITTED,
|
|
12959
|
+
describe: "Stop a running import",
|
|
12960
|
+
confirm: "This stops the import between row batches, so whatever it already wrote stays and nothing resumes it. A replace import empties the table before its first batch, so cancelling one leaves only part of the new file; an append adds its rows again if you import the file a second time."
|
|
12961
|
+
},
|
|
12962
|
+
cancelTableExport: {
|
|
12963
|
+
command: "tables exports cancel",
|
|
12964
|
+
describe: "Stop a running export"
|
|
12965
|
+
},
|
|
12782
12966
|
tableExportDownload: {
|
|
12783
12967
|
command: "tables exports download",
|
|
12784
12968
|
describe: "Get the download URL for a finished export"
|
|
@@ -12800,7 +12984,7 @@ var CLI_CONTRACT = {
|
|
|
12800
12984
|
selectedOutputs: {
|
|
12801
12985
|
name: "select-output",
|
|
12802
12986
|
list: true,
|
|
12803
|
-
describe: "Return blockName.field values (e.g. agent_1.content); missing fields are omitted"
|
|
12987
|
+
describe: "Return blockName.field values from the streamed result (e.g. agent_1.content), requires --follow; missing fields are omitted"
|
|
12804
12988
|
},
|
|
12805
12989
|
stream: { omit: true },
|
|
12806
12990
|
includeThinking: { omit: true },
|
|
@@ -12824,7 +13008,7 @@ var CLI_CONTRACT = {
|
|
|
12824
13008
|
selectedOutputs: {
|
|
12825
13009
|
name: "select-output",
|
|
12826
13010
|
list: true,
|
|
12827
|
-
describe: "Include
|
|
13011
|
+
describe: "Include blockId or blockId.path values in JSON or YAML output; block names are not resolved on a finished run"
|
|
12828
13012
|
}
|
|
12829
13013
|
},
|
|
12830
13014
|
fields: [
|
|
@@ -12935,6 +13119,13 @@ var PROFILE_INJECTED_FIELD = "workspaceId";
|
|
|
12935
13119
|
function isProfileWorkspacePath(commandSpec, param) {
|
|
12936
13120
|
return commandSpec.profileWorkspacePath === true && param === PROFILE_INJECTED_FIELD;
|
|
12937
13121
|
}
|
|
13122
|
+
function cursorSlot(operationSpec) {
|
|
13123
|
+
if (operationSpec.query && "cursor" in operationSpec.query)
|
|
13124
|
+
return "query";
|
|
13125
|
+
if (operationSpec.body && "cursor" in operationSpec.body)
|
|
13126
|
+
return "body";
|
|
13127
|
+
return null;
|
|
13128
|
+
}
|
|
12938
13129
|
var JSON_KINDS = new Set(["object", "array", "unknown"]);
|
|
12939
13130
|
function flagSpecFor(operation, field) {
|
|
12940
13131
|
return CLI_CONTRACT[operation]?.flags?.[field] ?? {};
|
|
@@ -13001,6 +13192,9 @@ function readStdin() {
|
|
|
13001
13192
|
}
|
|
13002
13193
|
return Buffer.concat(chunks).toString("utf8");
|
|
13003
13194
|
}
|
|
13195
|
+
function literalAtHint(error, path) {
|
|
13196
|
+
return error?.code === "ENOENT" ? `. To pass the literal value @${path}, write @@${path}` : "";
|
|
13197
|
+
}
|
|
13004
13198
|
function readArgumentSource(raw, flagName) {
|
|
13005
13199
|
if (raw.startsWith("@@"))
|
|
13006
13200
|
return { text: raw.slice(1), from: "" };
|
|
@@ -13020,7 +13214,7 @@ function readArgumentSource(raw, flagName) {
|
|
|
13020
13214
|
try {
|
|
13021
13215
|
return { text: readFileSync3(path, "utf8"), from: ` (read from ${path})` };
|
|
13022
13216
|
} catch (error) {
|
|
13023
|
-
throw new SimApiError(`--${flagName} cannot read ${path}: ${error.message}`, 0);
|
|
13217
|
+
throw new SimApiError(`--${flagName} cannot read ${path}: ${error.message}${literalAtHint(error, path)}`, 0);
|
|
13024
13218
|
}
|
|
13025
13219
|
}
|
|
13026
13220
|
function readListValues(raw, flagName) {
|
|
@@ -13113,6 +13307,7 @@ function coerce(raw, field, flag, flagName) {
|
|
|
13113
13307
|
return encodeFolderPath(raw);
|
|
13114
13308
|
return raw;
|
|
13115
13309
|
}
|
|
13310
|
+
var NO_WORKSPACE_FALLBACK = "No workspace set. Pass --workspace, or run: sim configure --set-workspace <id>";
|
|
13116
13311
|
function asQueryValue(value) {
|
|
13117
13312
|
if (value === null || value === undefined)
|
|
13118
13313
|
return;
|
|
@@ -13133,7 +13328,7 @@ function buildRequest(operation, positional, flags, workspaceId) {
|
|
|
13133
13328
|
const value = profileWorkspacePath ? workspaceId : pathFlag ? flags[camel(flagName)] : positional[positionalIndex++];
|
|
13134
13329
|
if (value === undefined || value === null) {
|
|
13135
13330
|
if (profileWorkspacePath) {
|
|
13136
|
-
throw new SimApiError(
|
|
13331
|
+
throw new SimApiError(NO_WORKSPACE_FALLBACK, 0);
|
|
13137
13332
|
}
|
|
13138
13333
|
throw new SimApiError(pathFlag ? `--${flagName} is required` : `Missing <${argumentName}>`, 0);
|
|
13139
13334
|
}
|
|
@@ -13145,6 +13340,7 @@ function buildRequest(operation, positional, flags, workspaceId) {
|
|
|
13145
13340
|
const query = {};
|
|
13146
13341
|
const body = {};
|
|
13147
13342
|
const headers = {};
|
|
13343
|
+
const paginatedLimit = cursorSlot(spec) !== null;
|
|
13148
13344
|
for (const slot of ["query", "body", "headers"]) {
|
|
13149
13345
|
for (const [field, descriptor] of Object.entries(spec[slot] ?? {})) {
|
|
13150
13346
|
const flag = flagSpecFor(operation, field);
|
|
@@ -13154,10 +13350,13 @@ function buildRequest(operation, positional, flags, workspaceId) {
|
|
|
13154
13350
|
const omitProfileWorkspace = commandSpec.allWorkspaces && flags.allWorkspaces === true;
|
|
13155
13351
|
const provided = field === PROFILE_INJECTED_FIELD ? omitProfileWorkspace ? undefined : workspaceId : flags[camel(flagName)];
|
|
13156
13352
|
const raw = provided ?? flag.requestDefault;
|
|
13353
|
+
if (slot === "query" && typeof raw === "string" && raw.trim() === "" && !(field === "limit" && paginatedLimit)) {
|
|
13354
|
+
throw new SimApiError(`--${flagName} cannot be empty`, 0);
|
|
13355
|
+
}
|
|
13157
13356
|
const value = coerce(raw ?? undefined, descriptor, flag, flagName);
|
|
13158
13357
|
if (value === undefined) {
|
|
13159
13358
|
if (descriptor.required) {
|
|
13160
|
-
throw new SimApiError(field === PROFILE_INJECTED_FIELD ?
|
|
13359
|
+
throw new SimApiError(field === PROFILE_INJECTED_FIELD ? NO_WORKSPACE_FALLBACK : `--${flagName} is required`, 0);
|
|
13161
13360
|
}
|
|
13162
13361
|
continue;
|
|
13163
13362
|
}
|
|
@@ -13333,7 +13532,8 @@ function at(row, path) {
|
|
|
13333
13532
|
function decodeFolderPath(value) {
|
|
13334
13533
|
return value.split("/").map((segment) => {
|
|
13335
13534
|
try {
|
|
13336
|
-
|
|
13535
|
+
const decoded = decodeURIComponent(segment);
|
|
13536
|
+
return decoded.includes("/") ? segment : decoded;
|
|
13337
13537
|
} catch {
|
|
13338
13538
|
return segment;
|
|
13339
13539
|
}
|
|
@@ -13464,8 +13664,10 @@ function unwrapResource(data) {
|
|
|
13464
13664
|
const [, value] = entries[0];
|
|
13465
13665
|
return value && typeof value === "object" && !Array.isArray(value) ? value : data;
|
|
13466
13666
|
}
|
|
13467
|
-
function renderPage(format, rows, spec, envelope) {
|
|
13667
|
+
function renderPage(format, rows, spec, envelope, options = {}) {
|
|
13468
13668
|
writePageNote(spec, envelope);
|
|
13669
|
+
writeEnvelopeTruncation(envelope);
|
|
13670
|
+
writeCursorTruncation(rows.length, options.truncated === true);
|
|
13469
13671
|
printList(format, rows, spec.columns ? columnsFrom(spec.columns) : inferColumns(rows, spec.expand));
|
|
13470
13672
|
}
|
|
13471
13673
|
function writePageNote(spec, envelope) {
|
|
@@ -13477,7 +13679,48 @@ function writePageNote(spec, envelope) {
|
|
|
13477
13679
|
process.stderr.write(source_default.dim(`${spec.pageNote.label}: ${String(value)}
|
|
13478
13680
|
`));
|
|
13479
13681
|
}
|
|
13480
|
-
|
|
13682
|
+
var TRUNCATION_FLAG = /^truncated$|^[A-Za-z0-9]+Truncated$/;
|
|
13683
|
+
var NEGATED_TRUNCATION_FLAG = /^(?:not|un|non|never)Truncated$|(?:Not|Un|Non|Never)Truncated$/;
|
|
13684
|
+
function truncationFlags(container) {
|
|
13685
|
+
if (!container || typeof container !== "object" || Array.isArray(container))
|
|
13686
|
+
return [];
|
|
13687
|
+
return Object.entries(container).filter(([key, value]) => value === true && TRUNCATION_FLAG.test(key) && !NEGATED_TRUNCATION_FLAG.test(key)).map(([key]) => key);
|
|
13688
|
+
}
|
|
13689
|
+
function responseTruncationFlags(envelope) {
|
|
13690
|
+
return [...truncationFlags(envelope), ...truncationFlags(at(envelope, "data"))];
|
|
13691
|
+
}
|
|
13692
|
+
function foldPageEnvelope(current, page) {
|
|
13693
|
+
if (current === undefined)
|
|
13694
|
+
return page;
|
|
13695
|
+
const raised = truncationFlags(page);
|
|
13696
|
+
if (raised.length === 0 || !current || typeof current !== "object")
|
|
13697
|
+
return current;
|
|
13698
|
+
return {
|
|
13699
|
+
...current,
|
|
13700
|
+
...Object.fromEntries(raised.map((flag) => [flag, true]))
|
|
13701
|
+
};
|
|
13702
|
+
}
|
|
13703
|
+
function spellOut(flag) {
|
|
13704
|
+
return flag.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().trim();
|
|
13705
|
+
}
|
|
13706
|
+
function clippedSubject(flag) {
|
|
13707
|
+
const subject = flag.replace(/^truncated$|Truncated$/, "");
|
|
13708
|
+
return subject ? `the ${spellOut(subject)} it returned` : "this result";
|
|
13709
|
+
}
|
|
13710
|
+
function writeEnvelopeTruncation(envelope) {
|
|
13711
|
+
for (const flag of responseTruncationFlags(envelope)) {
|
|
13712
|
+
process.stderr.write(source_default.dim(`${spellOut(flag)}: the server clipped ${clippedSubject(flag)}, so the answer is incomplete
|
|
13713
|
+
`));
|
|
13714
|
+
}
|
|
13715
|
+
}
|
|
13716
|
+
function writeCursorTruncation(count, truncated) {
|
|
13717
|
+
if (!truncated)
|
|
13718
|
+
return;
|
|
13719
|
+
process.stderr.write(source_default.dim(`showing the first ${count}; more results exist — re-run with --limit 0 for all
|
|
13720
|
+
`));
|
|
13721
|
+
}
|
|
13722
|
+
function renderResult(operation, format, raw, spec, options = {}, envelope) {
|
|
13723
|
+
writeEnvelopeTruncation(envelope);
|
|
13481
13724
|
if (spec.document) {
|
|
13482
13725
|
printDocument(format, raw);
|
|
13483
13726
|
return;
|
|
@@ -13620,8 +13863,8 @@ function attachCredentialCommands(program2) {
|
|
|
13620
13863
|
if (!credentials)
|
|
13621
13864
|
throw new Error("The generated credentials command group is missing");
|
|
13622
13865
|
acceptNameOnUpdate(credentials);
|
|
13623
|
-
credentials.command("create").argument("<providerId>", "Service-account provider to create a credential for").description("Create a service-account credential using its discovered provider schema").requiredOption("--name <displayName>", "Name shown for the credential in Sim").requiredOption("--credentials <json|@file>", "Provider credentials as JSON (or @path / @- to read a file or stdin)").option("--description <description>", "Optional credential description").option("--id <credentialId>", "Client-generated credential ID when provider discovery requires it").action((providerId, options, command) => createServiceAccount(command, providerId, options));
|
|
13624
|
-
credentials.command("connect").argument("<providerId>", "OAuth provider to connect").description("Create a short-lived link for connecting an OAuth provider").requiredOption("--name <displayName>", "Name shown for the new credential in Sim").action(async (providerId, options, command) => createConnectionLink(command, { providerId, displayName: options.name }));
|
|
13866
|
+
credentials.command("create").argument("<providerId>", "Service-account provider to create a credential for").description("Create a service-account credential using its discovered provider schema").requiredOption("--name <displayName>", "Name shown for the credential in Sim (required)").requiredOption("--credentials <json|@file>", "Provider credentials as JSON (or @path / @- to read a file or stdin) (required)").option("--description <description>", "Optional credential description").option("--id <credentialId>", "Client-generated credential ID when provider discovery requires it").action((providerId, options, command) => createServiceAccount(command, providerId, options));
|
|
13867
|
+
credentials.command("connect").argument("<providerId>", "OAuth provider to connect").description("Create a short-lived link for connecting an OAuth provider").requiredOption("--name <displayName>", "Name shown for the new credential in Sim (required)").action(async (providerId, options, command) => createConnectionLink(command, { providerId, displayName: options.name }));
|
|
13625
13868
|
credentials.command("reconnect").argument("<credentialId>", "Existing OAuth credential to re-authorize").description("Create a short-lived link for reconnecting an OAuth credential").action((credentialId, _options, command) => createConnectionLink(command, { credentialId }));
|
|
13626
13869
|
}
|
|
13627
13870
|
|
|
@@ -13775,7 +14018,7 @@ Examples:
|
|
|
13775
14018
|
|
|
13776
14019
|
// src/commands/protocol/files-get.ts
|
|
13777
14020
|
import { once as once2 } from "node:events";
|
|
13778
|
-
import { createWriteStream } from "node:fs";
|
|
14021
|
+
import { createWriteStream, rmSync } from "node:fs";
|
|
13779
14022
|
import { link, lstat, mkdtemp, readlink, rename, rm } from "node:fs/promises";
|
|
13780
14023
|
import { dirname as dirname2, join as join2, resolve as resolve2 } from "node:path";
|
|
13781
14024
|
import { Readable } from "node:stream";
|
|
@@ -13831,37 +14074,66 @@ async function streamToFile(body, file, reportedPath = file.path) {
|
|
|
13831
14074
|
throw writeFailure(reportedPath, error);
|
|
13832
14075
|
}
|
|
13833
14076
|
}
|
|
14077
|
+
var STAGE_SIGNALS = ["SIGINT", "SIGTERM"];
|
|
14078
|
+
function reRaise(signal) {
|
|
14079
|
+
process.kill(process.pid, signal);
|
|
14080
|
+
}
|
|
14081
|
+
function removeStagingOnSignal(stagingDirectory, terminate = reRaise) {
|
|
14082
|
+
const installed = STAGE_SIGNALS.map((signal) => {
|
|
14083
|
+
const onSignal = () => {
|
|
14084
|
+
process.off(signal, onSignal);
|
|
14085
|
+
const directory = stagingDirectory();
|
|
14086
|
+
if (directory) {
|
|
14087
|
+
try {
|
|
14088
|
+
rmSync(directory, { recursive: true, force: true });
|
|
14089
|
+
} catch {}
|
|
14090
|
+
}
|
|
14091
|
+
terminate(signal);
|
|
14092
|
+
};
|
|
14093
|
+
process.on(signal, onSignal);
|
|
14094
|
+
return [signal, onSignal];
|
|
14095
|
+
});
|
|
14096
|
+
return () => {
|
|
14097
|
+
for (const [signal, onSignal] of installed)
|
|
14098
|
+
process.off(signal, onSignal);
|
|
14099
|
+
};
|
|
14100
|
+
}
|
|
13834
14101
|
async function saveStagedFile(body, target, force) {
|
|
13835
14102
|
let temporaryDirectory = null;
|
|
13836
14103
|
let failure = null;
|
|
14104
|
+
const disposeSignalCleanup = removeStagingOnSignal(() => temporaryDirectory);
|
|
13837
14105
|
try {
|
|
13838
|
-
|
|
13839
|
-
|
|
13840
|
-
|
|
13841
|
-
|
|
13842
|
-
|
|
13843
|
-
|
|
13844
|
-
|
|
13845
|
-
|
|
13846
|
-
|
|
13847
|
-
|
|
13848
|
-
|
|
14106
|
+
try {
|
|
14107
|
+
const publicationTarget = force ? await forcedPublicationTarget(target) : target;
|
|
14108
|
+
temporaryDirectory = await mkdtemp(join2(dirname2(publicationTarget), ".sim-download-"));
|
|
14109
|
+
const temporaryPath = join2(temporaryDirectory, "payload");
|
|
14110
|
+
await streamToFile(body, createWriteStream(temporaryPath, { flags: "wx" }), target);
|
|
14111
|
+
if (force) {
|
|
14112
|
+
await rename(temporaryPath, publicationTarget);
|
|
14113
|
+
} else {
|
|
14114
|
+
try {
|
|
14115
|
+
await link(temporaryPath, publicationTarget);
|
|
14116
|
+
} catch (error) {
|
|
14117
|
+
throw unsupportedAtomicPublish(target, error) ?? error;
|
|
14118
|
+
}
|
|
13849
14119
|
}
|
|
14120
|
+
} catch (error) {
|
|
14121
|
+
failure = normalizedWriteFailure(target, error);
|
|
13850
14122
|
}
|
|
13851
|
-
|
|
13852
|
-
|
|
13853
|
-
|
|
13854
|
-
|
|
13855
|
-
|
|
13856
|
-
|
|
13857
|
-
|
|
13858
|
-
|
|
13859
|
-
throw combinedCleanupFailure(failure, temporaryDirectory, cleanupError);
|
|
13860
|
-
throw new SimApiError(`Saved ${target}, but could not remove temporary directory ${temporaryDirectory}: ${cleanupError.message}`, 0);
|
|
14123
|
+
if (temporaryDirectory) {
|
|
14124
|
+
try {
|
|
14125
|
+
await rm(temporaryDirectory, { recursive: true, force: true });
|
|
14126
|
+
} catch (cleanupError) {
|
|
14127
|
+
if (failure)
|
|
14128
|
+
throw combinedCleanupFailure(failure, temporaryDirectory, cleanupError);
|
|
14129
|
+
throw new SimApiError(`Saved ${target}, but could not remove temporary directory ${temporaryDirectory}: ${cleanupError.message}`, 0);
|
|
14130
|
+
}
|
|
13861
14131
|
}
|
|
14132
|
+
if (failure)
|
|
14133
|
+
throw failure;
|
|
14134
|
+
} finally {
|
|
14135
|
+
disposeSignalCleanup();
|
|
13862
14136
|
}
|
|
13863
|
-
if (failure)
|
|
13864
|
-
throw failure;
|
|
13865
14137
|
}
|
|
13866
14138
|
async function saveToFile(body, target, force) {
|
|
13867
14139
|
return saveStagedFile(body, target, force);
|
|
@@ -14172,6 +14444,7 @@ function renderCell2(value, format) {
|
|
|
14172
14444
|
}
|
|
14173
14445
|
var COLUMNS = (CLI_CONTRACT.listLogs?.columns ?? []).map((spec) => ({
|
|
14174
14446
|
header: spec.header,
|
|
14447
|
+
floor: Math.min(MAX_CELL_WIDTH2, spec.minWidth ?? 0),
|
|
14175
14448
|
value: (row) => renderCell2(at2(row, spec.path ?? spec.header), spec.format)
|
|
14176
14449
|
}));
|
|
14177
14450
|
function oneLine2(value) {
|
|
@@ -14188,15 +14461,15 @@ function clamp2(value, width) {
|
|
|
14188
14461
|
function createTableWriter() {
|
|
14189
14462
|
let widths = null;
|
|
14190
14463
|
return (rows) => {
|
|
14191
|
-
const lines = rows.map((row) => COLUMNS.map((column) => oneLine2(column.value(row))));
|
|
14464
|
+
const lines = rows.map((row) => COLUMNS.map((column) => clamp2(oneLine2(column.value(row)), MAX_CELL_WIDTH2)));
|
|
14192
14465
|
if (!widths) {
|
|
14193
|
-
widths = COLUMNS.map((column, index) => Math.min(MAX_CELL_WIDTH2, Math.max(visibleWidth(column.header), ...lines.map((line) => visibleWidth(line[index])))));
|
|
14466
|
+
widths = COLUMNS.map((column, index) => Math.min(MAX_CELL_WIDTH2, Math.max(column.floor, visibleWidth(column.header), ...lines.map((line) => visibleWidth(line[index])))));
|
|
14194
14467
|
const header = widths;
|
|
14195
14468
|
console.log(source_default.dim(COLUMNS.map((column, index) => pad2(column.header.toUpperCase(), header[index])).join(" ").trimEnd()));
|
|
14196
14469
|
}
|
|
14197
14470
|
const locked = widths;
|
|
14198
14471
|
for (const line of lines) {
|
|
14199
|
-
console.log(line.map((cell, index) => pad2(
|
|
14472
|
+
console.log(line.map((cell, index) => pad2(cell, locked[index])).join(" ").trimEnd());
|
|
14200
14473
|
}
|
|
14201
14474
|
};
|
|
14202
14475
|
}
|
|
@@ -14421,7 +14694,8 @@ var WIRE_VOCABULARY_SENTENCE = /\s*The listed spellings[^.]*\.\s*/g;
|
|
|
14421
14694
|
function withoutWireVocabulary(documented) {
|
|
14422
14695
|
return documented.replace(WIRE_VOCABULARY_SENTENCE, " ").trim();
|
|
14423
14696
|
}
|
|
14424
|
-
|
|
14697
|
+
var NON_PAGINATED_LIMIT_HINT = " (caps a --filter match only; omit it to act on every match, and note 0 is not accepted)";
|
|
14698
|
+
function addFieldOption(command, operation, field, descriptor, slot, paginates) {
|
|
14425
14699
|
if (field === PROFILE_INJECTED_FIELD || field === "cursor")
|
|
14426
14700
|
return;
|
|
14427
14701
|
const flag = flagSpecFor(operation, field);
|
|
@@ -14429,11 +14703,11 @@ function addFieldOption(command, operation, field, descriptor, slot) {
|
|
|
14429
14703
|
return;
|
|
14430
14704
|
const name = flagNameFor(operation, field);
|
|
14431
14705
|
const short = flag.short ? `-${flag.short}, ` : "";
|
|
14432
|
-
if (field === "limit" && (descriptor.kind === "number" || descriptor.kind === "integer")) {
|
|
14706
|
+
if (paginates && field === "limit" && (descriptor.kind === "number" || descriptor.kind === "integer")) {
|
|
14433
14707
|
command.option("--limit <n>", "Maximum items to return (0 for everything)", String(DEFAULT_LIMIT));
|
|
14434
14708
|
return;
|
|
14435
14709
|
}
|
|
14436
|
-
const documented = describeField(flag, descriptor, name, field)
|
|
14710
|
+
const documented = `${describeField(flag, descriptor, name, field)}${field === "limit" && (descriptor.kind === "number" || descriptor.kind === "integer") ? NON_PAGINATED_LIMIT_HINT : ""}`;
|
|
14437
14711
|
if (descriptor.kind === "boolean" || flag.boolean) {
|
|
14438
14712
|
const booleanDoc = withoutWireVocabulary(documented);
|
|
14439
14713
|
if (descriptor.required) {
|
|
@@ -14451,7 +14725,7 @@ function addFieldOption(command, operation, field, descriptor, slot) {
|
|
|
14451
14725
|
const placeholder = takesList ? "<value...>" : flag.rowCap ? "<n>" : wantsJson ? "<json|@file>" : "<value>";
|
|
14452
14726
|
const choices = flag.choices ?? descriptor.values;
|
|
14453
14727
|
const literalNull = slot === "body" && !takesList && !wantsJson;
|
|
14454
|
-
const describe = `${documented}${takesList ? " (space-separated, or @path / @- with one value per line)" : wantsJson ? " (JSON, or @path / @- to read a file or stdin)" : ""}${descriptor.required ? " (required)" : ""}${literalNull ? literalNullHint(documented, name) : ""}`;
|
|
14728
|
+
const describe = `${documented}${takesList ? " (space-separated, or @path / @- with one value per line; @@value for a literal leading @)" : wantsJson ? " (JSON, or @path / @- to read a file or stdin)" : ""}${descriptor.required ? " (required)" : ""}${literalNull ? literalNullHint(documented, name) : ""}`;
|
|
14455
14729
|
const renamedFrom = flag.renamedFrom ?? [];
|
|
14456
14730
|
const option = new Option(`${short}--${name} ${placeholder}`, describe);
|
|
14457
14731
|
if (flag.hidden)
|
|
@@ -14480,13 +14754,14 @@ function addOperationOptions(command, operation, commandSpec, operationSpec) {
|
|
|
14480
14754
|
const short = flag.short ? `-${flag.short}, ` : "";
|
|
14481
14755
|
command.addOption(new Option(`${short}--${name} <${flag.placeholder ?? "value"}>`, `${flag.describe ?? operationSpec.pathParamDocs?.[param] ?? `Set ${name.replaceAll("-", " ")}`} (required)`).makeOptionMandatory());
|
|
14482
14756
|
}
|
|
14757
|
+
const paginates = cursorSlot(operationSpec) !== null;
|
|
14483
14758
|
for (const slot of ["query", "body", "headers"]) {
|
|
14484
14759
|
for (const [field, descriptor] of Object.entries(operationSpec[slot] ?? {})) {
|
|
14485
14760
|
if (commandSpec.requestFields && !commandSpec.requestFields.includes(field))
|
|
14486
14761
|
continue;
|
|
14487
14762
|
if (commandSpec.positionals?.includes(field))
|
|
14488
14763
|
continue;
|
|
14489
|
-
addFieldOption(command, operation, field, descriptor, slot);
|
|
14764
|
+
addFieldOption(command, operation, field, descriptor, slot, paginates);
|
|
14490
14765
|
}
|
|
14491
14766
|
}
|
|
14492
14767
|
if (commandSpec.allWorkspaces) {
|
|
@@ -14663,13 +14938,16 @@ function validateTargetOptions(options) {
|
|
|
14663
14938
|
return intoExisting;
|
|
14664
14939
|
}
|
|
14665
14940
|
function attachTableImport(tables) {
|
|
14666
|
-
tables.command("import").argument("[path]", "Local CSV file to import; omit when using --file-id").allowExcessArguments(false).description("Import a CSV, into a new table by default").option("--name <name>", "Identifier for the new table: letters, numbers, and underscores; defaults to the sanitized file name").option("--table-id <id>", "Import into this existing table instead of creating one").addOption(new Option("--mode <append|replace>", "How to write into --table-id (default: append)").choices(["append", "replace"])).option("--folder <path>", "Folder path for the new table, as shown in the app").option("--file-id <id>", "Import a file already in the workspace instead of a local path").option("--mapping <json|@file>", "Column mapping (--table-id only)").option("--create-columns <json|@file>", "Columns to create (--table-id only)").option("--timezone <iana>", "Timezone for date parsing, e.g. America/New_York").option("--no-wait", "Return once the import is queued instead of watching it").action(async (path, options, command) => {
|
|
14941
|
+
tables.command("import").argument("[path]", "Local CSV file to import; omit when using --file-id").allowExcessArguments(false).description("Import a CSV, into a new table by default").option("--name <name>", "Identifier for the new table: letters, numbers, and underscores; defaults to the sanitized file name").option("--table-id <id>", "Import into this existing table instead of creating one").addOption(new Option("--mode <append|replace>", "How to write into --table-id (default: append)").choices(["append", "replace"])).option("--folder <path>", "Folder path for the new table, as shown in the app").option("--file-id <id>", "Import a file already in the workspace instead of a local path").option("--mapping <json|@file>", "Column mapping (--table-id only)").option("--create-columns <json|@file>", "Columns to create (--table-id only)").option("--timezone <iana>", "Timezone for date parsing, e.g. America/New_York").option("-y, --yes", "Confirm this destructive operation (required with --mode replace)").option("--no-wait", "Return once the import is queued instead of watching it").action(async (path, options, command) => {
|
|
14667
14942
|
const { client, profile } = clientFrom(command);
|
|
14668
14943
|
const workspaceId = client.requireWorkspace();
|
|
14669
14944
|
if (Boolean(path) === Boolean(options.fileId)) {
|
|
14670
14945
|
throw new SimApiError("Pass exactly one of <path> or --file-id <id>", 0);
|
|
14671
14946
|
}
|
|
14672
14947
|
const intoExisting = validateTargetOptions(options);
|
|
14948
|
+
if (intoExisting && options.mode === "replace" && options.yes !== true) {
|
|
14949
|
+
throw new SimApiError("This deletes every row in the table before loading the CSV and cannot be undone. Re-run with --yes to confirm.", 0);
|
|
14950
|
+
}
|
|
14673
14951
|
const local = path ? await localFile(path) : null;
|
|
14674
14952
|
const source = local ? {
|
|
14675
14953
|
type: "upload",
|
|
@@ -14784,6 +15062,14 @@ var BULK_OUTCOME_CHECKS = {
|
|
|
14784
15062
|
return null;
|
|
14785
15063
|
return `Deleted nothing: none of the ${requested} requested ${requested === 1 ? "file was" : "files were"} deleted.`;
|
|
14786
15064
|
},
|
|
15065
|
+
addWorkspaceFilesToKnowledgeBase: (payload) => {
|
|
15066
|
+
if (lengthOf(payload.added) > 0)
|
|
15067
|
+
return null;
|
|
15068
|
+
const failed = lengthOf(payload.failed);
|
|
15069
|
+
if (failed === 0)
|
|
15070
|
+
return null;
|
|
15071
|
+
return `Indexed nothing: none of the ${failed} requested ${failed === 1 ? "file was" : "files were"} added.`;
|
|
15072
|
+
},
|
|
14787
15073
|
bulkDeleteTables: (payload) => {
|
|
14788
15074
|
const items = payload.deletedItems;
|
|
14789
15075
|
const deleted = countOf(items?.tables) + countOf(items?.folders);
|
|
@@ -14794,6 +15080,15 @@ var BULK_OUTCOME_CHECKS = {
|
|
|
14794
15080
|
return null;
|
|
14795
15081
|
return `Deleted nothing: ${missed} of ${missed} ${missed === 1 ? "item was" : "items were"} not found or could not be deleted.`;
|
|
14796
15082
|
},
|
|
15083
|
+
bulkUpdateKnowledgeChunks: (payload, body) => {
|
|
15084
|
+
if (countOf(payload.processed) > 0)
|
|
15085
|
+
return null;
|
|
15086
|
+
const requested = lengthOf(body?.chunkIds);
|
|
15087
|
+
if (requested === 0)
|
|
15088
|
+
return null;
|
|
15089
|
+
const reported2 = payload.errors?.[0];
|
|
15090
|
+
return typeof reported2 === "string" && reported2 ? safeOneLine(reported2) : `Updated nothing: none of the ${requested} requested ${requested === 1 ? "chunk" : "chunks"} matched.`;
|
|
15091
|
+
},
|
|
14797
15092
|
moveTables: (payload) => {
|
|
14798
15093
|
if (lengthOf(payload.moved) > 0)
|
|
14799
15094
|
return null;
|
|
@@ -14825,12 +15120,18 @@ function bulkFailureMessage(operation, payload, body) {
|
|
|
14825
15120
|
return null;
|
|
14826
15121
|
return check(payload, body);
|
|
14827
15122
|
}
|
|
14828
|
-
|
|
14829
|
-
|
|
14830
|
-
|
|
14831
|
-
|
|
14832
|
-
|
|
14833
|
-
|
|
15123
|
+
var EXCLUSIVE_CAP_FIELDS = {
|
|
15124
|
+
deleteTableRows: { cap: "limit", ids: "rowIds" }
|
|
15125
|
+
};
|
|
15126
|
+
function assertCapIsUsable(operation, flags) {
|
|
15127
|
+
const exclusive = EXCLUSIVE_CAP_FIELDS[operation];
|
|
15128
|
+
if (!exclusive)
|
|
15129
|
+
return;
|
|
15130
|
+
const cap = flagNameFor(operation, exclusive.cap);
|
|
15131
|
+
const ids = flagNameFor(operation, exclusive.ids);
|
|
15132
|
+
if (flags[camel(cap)] === undefined || flags[camel(ids)] === undefined)
|
|
15133
|
+
return;
|
|
15134
|
+
throw new SimApiError(`--${cap} caps a --filter match and does nothing to an explicit --${ids} list; pass one, not both`, 0);
|
|
14834
15135
|
}
|
|
14835
15136
|
function foldRenamedFlags(operation, commandSpec, flags) {
|
|
14836
15137
|
for (const [field, flag] of Object.entries(commandSpec.flags ?? {})) {
|
|
@@ -14864,6 +15165,7 @@ async function executeOperation(operation, commandSpec, operationSpec, invocatio
|
|
|
14864
15165
|
requestFlags[camel(flagNameFor(operation, field))] = invocation[pathPositionalCount + index];
|
|
14865
15166
|
}
|
|
14866
15167
|
foldRenamedFlags(operation, commandSpec, requestFlags);
|
|
15168
|
+
assertCapIsUsable(operation, requestFlags);
|
|
14867
15169
|
if (commandSpec.confirm && !requestFlags.yes && requestFlags.dryRun !== true) {
|
|
14868
15170
|
throw new SimApiError(`${commandSpec.confirm} Re-run with --yes to confirm.`, 0);
|
|
14869
15171
|
}
|
|
@@ -14873,12 +15175,14 @@ async function executeOperation(operation, commandSpec, operationSpec, invocatio
|
|
|
14873
15175
|
const { client, profile } = clientFrom(host);
|
|
14874
15176
|
const hasWorkspaceField = Boolean(operationSpec.query && PROFILE_INJECTED_FIELD in operationSpec.query || operationSpec.body && PROFILE_INJECTED_FIELD in operationSpec.body);
|
|
14875
15177
|
const omitsWorkspace = commandSpec.allWorkspaces && requestFlags.allWorkspaces === true;
|
|
14876
|
-
const
|
|
15178
|
+
const needsWorkspace = (hasWorkspaceField || commandSpec.profileWorkspacePath === true) && !omitsWorkspace;
|
|
15179
|
+
const request = buildRequest(operation, positional, requestFlags, needsWorkspace ? client.requireWorkspace() : profile.workspaceId);
|
|
14877
15180
|
const paging = cursorSlot(operationSpec);
|
|
14878
15181
|
if (paging) {
|
|
14879
|
-
const
|
|
14880
|
-
|
|
14881
|
-
|
|
15182
|
+
const limitText = String(requestFlags.limit ?? DEFAULT_LIMIT).trim();
|
|
15183
|
+
const rawLimit = limitText === "" ? Number.NaN : Number(limitText);
|
|
15184
|
+
if (!Number.isInteger(rawLimit) || rawLimit < 0) {
|
|
15185
|
+
throw new SimApiError("--limit must be a whole number of 0 or more (0 for everything)", 0);
|
|
14882
15186
|
}
|
|
14883
15187
|
const limit = rawLimit === 0 ? Number.POSITIVE_INFINITY : rawLimit;
|
|
14884
15188
|
const pageSize = Math.min(Number.isFinite(limit) ? limit : DEFAULT_LIMIT, DEFAULT_LIMIT);
|
|
@@ -14895,7 +15199,7 @@ async function executeOperation(operation, commandSpec, operationSpec, invocatio
|
|
|
14895
15199
|
query: paging === "query" ? { ...request.query, ...pageLimit, cursor } : request.query,
|
|
14896
15200
|
body: paging === "body" ? { ...request.body ?? {}, ...pageLimit, ...cursor ? { cursor } : {} } : request.body
|
|
14897
15201
|
});
|
|
14898
|
-
envelope
|
|
15202
|
+
envelope = foldPageEnvelope(envelope, page);
|
|
14899
15203
|
rows.push(...page.data);
|
|
14900
15204
|
cursor = page.nextCursor;
|
|
14901
15205
|
if (cursor && rows.length < limit)
|
|
@@ -14904,7 +15208,7 @@ async function executeOperation(operation, commandSpec, operationSpec, invocatio
|
|
|
14904
15208
|
} finally {
|
|
14905
15209
|
progress.finish();
|
|
14906
15210
|
}
|
|
14907
|
-
renderPage(profile.output, Number.isFinite(limit) ? rows.slice(0, limit) : rows, commandSpec, envelope);
|
|
15211
|
+
renderPage(profile.output, Number.isFinite(limit) ? rows.slice(0, limit) : rows, commandSpec, envelope, { truncated: Boolean(cursor) });
|
|
14908
15212
|
return;
|
|
14909
15213
|
}
|
|
14910
15214
|
const result = await client.request(request.path, {
|
|
@@ -14914,9 +15218,7 @@ async function executeOperation(operation, commandSpec, operationSpec, invocatio
|
|
|
14914
15218
|
body: request.body
|
|
14915
15219
|
});
|
|
14916
15220
|
const payload = result?.data ?? result;
|
|
14917
|
-
renderResult(operation, profile.output, payload, commandSpec, {
|
|
14918
|
-
expandedTrace: requestFlags.trace === true
|
|
14919
|
-
});
|
|
15221
|
+
renderResult(operation, profile.output, payload, commandSpec, { expandedTrace: requestFlags.trace === true }, result);
|
|
14920
15222
|
const failure = runFailureMessage(operation, payload) ?? bulkFailureMessage(operation, payload, request.body);
|
|
14921
15223
|
if (failure)
|
|
14922
15224
|
throw new SimApiError(failure, 0);
|
|
@@ -15141,6 +15443,9 @@ function followOrDelegate(previous) {
|
|
|
15141
15443
|
command.setOptionValue("run", selection);
|
|
15142
15444
|
const flags = command.optsWithGlobals();
|
|
15143
15445
|
if (flags.follow !== true) {
|
|
15446
|
+
if (Array.isArray(flags.selectOutput) && flags.selectOutput.length > 0) {
|
|
15447
|
+
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);
|
|
15448
|
+
}
|
|
15144
15449
|
if (flags.includeThinking === true || flags.includeToolCalls === true) {
|
|
15145
15450
|
throw new SimApiError("--include-thinking and --include-tool-calls describe a stream; add --follow", 0);
|
|
15146
15451
|
}
|
|
@@ -15455,6 +15760,8 @@ function validateWorkspaceOnlyFlag(flag, value, scope) {
|
|
|
15455
15760
|
async function readSecretValue(options) {
|
|
15456
15761
|
if (options.value !== undefined)
|
|
15457
15762
|
return validateSecretValue(readValueArgument(options.value));
|
|
15763
|
+
if (options.description !== undefined || options.unredacted !== undefined)
|
|
15764
|
+
return;
|
|
15458
15765
|
try {
|
|
15459
15766
|
return validateSecretValue(await promptSecret());
|
|
15460
15767
|
} catch (error) {
|
|
@@ -15464,7 +15771,10 @@ async function readSecretValue(options) {
|
|
|
15464
15771
|
return process.exit(CANCELLED_EXIT_CODE);
|
|
15465
15772
|
}
|
|
15466
15773
|
}
|
|
15467
|
-
async function setSecret(name, options, command) {
|
|
15774
|
+
async function setSecret(name, options, command, redactionSpellings) {
|
|
15775
|
+
if (redactionSpellings.size > 1) {
|
|
15776
|
+
throw new SimApiError("Pass either --unredacted or --no-unredacted, not both: they are one setting, and commander keeps only whichever came last.", 0);
|
|
15777
|
+
}
|
|
15468
15778
|
const description = validateWorkspaceOnlyFlag("description", options.description, options.scope);
|
|
15469
15779
|
const unredacted = validateWorkspaceOnlyFlag("unredacted", options.unredacted, options.scope);
|
|
15470
15780
|
const value = await readSecretValue(options);
|
|
@@ -15475,7 +15785,7 @@ async function setSecret(name, options, command) {
|
|
|
15475
15785
|
body: {
|
|
15476
15786
|
workspaceId: client.requireWorkspace(),
|
|
15477
15787
|
scope: options.scope,
|
|
15478
|
-
value,
|
|
15788
|
+
...value === undefined ? {} : { value },
|
|
15479
15789
|
description,
|
|
15480
15790
|
...unredacted === undefined ? {} : { unredacted }
|
|
15481
15791
|
}
|
|
@@ -15486,7 +15796,85 @@ function attachSecretCommands(program2) {
|
|
|
15486
15796
|
const secrets = program2.commands.find((command) => command.name() === "secrets");
|
|
15487
15797
|
if (!secrets)
|
|
15488
15798
|
throw new Error("The generated secrets command group is missing");
|
|
15489
|
-
|
|
15799
|
+
const redactionSpellings = new Set;
|
|
15800
|
+
secrets.command("set").argument("<name>", "Secret name, as referenced in workflows").description("Create or replace a named secret").addOption(new Option("--scope <scope>", "Secret ownership scope (required)").choices([...SECRET_SCOPES]).makeOptionMandatory()).option("--value <value|@file>", "Secret value. Passing it inline exposes it to shell history and process listings; @path reads it from a file and @- from stdin, verbatim — a trailing newline is part of the value, so write the file with printf rather than echo. Prefix a literal leading @ with a second one").option("--description <description>", "What the secret is for, shown to teammates; workspace scope only. Omit to leave an existing description unchanged").option("--unredacted", `${V2_OPERATIONS.setSecret.body.unredacted.describe} Pass --no-unredacted to restore redaction`).option("--no-unredacted", "Send --unredacted as false").on("option:unredacted", () => redactionSpellings.add("--unredacted")).on("option:no-unredacted", () => redactionSpellings.add("--no-unredacted")).action((name, options, command) => setSecret(name, options, command, redactionSpellings));
|
|
15801
|
+
}
|
|
15802
|
+
|
|
15803
|
+
// src/runtime/naming.ts
|
|
15804
|
+
var WIRE_IDENTIFIER = /^[a-z]+[A-Z]/;
|
|
15805
|
+
function spellingFor(operation, commandSpec, operationSpec, field) {
|
|
15806
|
+
if (field === PROFILE_INJECTED_FIELD)
|
|
15807
|
+
return "--workspace";
|
|
15808
|
+
if (field === "cursor")
|
|
15809
|
+
return null;
|
|
15810
|
+
if (operationSpec.pathParams.includes(field)) {
|
|
15811
|
+
return commandSpec.pathFlags?.[field] ? `--${pathFlagNameFor(commandSpec, field)}` : `<${commandSpec.pathArgumentNames?.[field] ?? field}>`;
|
|
15812
|
+
}
|
|
15813
|
+
if (commandSpec.positionals?.includes(field))
|
|
15814
|
+
return `<${flagNameFor(operation, field)}>`;
|
|
15815
|
+
if (flagSpecFor(operation, field).omit)
|
|
15816
|
+
return null;
|
|
15817
|
+
if (commandSpec.requestFields && !commandSpec.requestFields.includes(field))
|
|
15818
|
+
return null;
|
|
15819
|
+
const declared = operationSpec.query && field in operationSpec.query || operationSpec.body && field in operationSpec.body || operationSpec.headers && field in operationSpec.headers;
|
|
15820
|
+
if (!declared)
|
|
15821
|
+
return null;
|
|
15822
|
+
return `--${flagNameFor(operation, field)}`;
|
|
15823
|
+
}
|
|
15824
|
+
function typeableFields(operation, commandSpec, operationSpec) {
|
|
15825
|
+
const spellings = new Map;
|
|
15826
|
+
const fields = [
|
|
15827
|
+
...operationSpec.pathParams,
|
|
15828
|
+
...Object.keys(operationSpec.query ?? {}),
|
|
15829
|
+
...Object.keys(operationSpec.body ?? {}),
|
|
15830
|
+
...Object.keys(operationSpec.headers ?? {})
|
|
15831
|
+
];
|
|
15832
|
+
for (const field of fields) {
|
|
15833
|
+
if (spellings.has(field))
|
|
15834
|
+
continue;
|
|
15835
|
+
const spelling = spellingFor(operation, commandSpec, operationSpec, field);
|
|
15836
|
+
if (spelling)
|
|
15837
|
+
spellings.set(field, spelling);
|
|
15838
|
+
}
|
|
15839
|
+
return spellings;
|
|
15840
|
+
}
|
|
15841
|
+
function retypeMessage(message, spellings) {
|
|
15842
|
+
let retyped = message;
|
|
15843
|
+
for (const [field, spelling] of spellings) {
|
|
15844
|
+
if (!WIRE_IDENTIFIER.test(field))
|
|
15845
|
+
continue;
|
|
15846
|
+
retyped = retyped.replaceAll(new RegExp(`\\b${field}\\b`, "g"), spelling);
|
|
15847
|
+
}
|
|
15848
|
+
return retyped;
|
|
15849
|
+
}
|
|
15850
|
+
function retypeDetails(details, spellings) {
|
|
15851
|
+
if (Array.isArray(details))
|
|
15852
|
+
return details.map((issue2) => retypeDetails(issue2, spellings));
|
|
15853
|
+
if (!details || typeof details !== "object")
|
|
15854
|
+
return details;
|
|
15855
|
+
const issue = details;
|
|
15856
|
+
const retyped = { ...issue };
|
|
15857
|
+
if (Array.isArray(issue.path) && issue.path.length > 0) {
|
|
15858
|
+
const [head, ...rest] = issue.path.map(String);
|
|
15859
|
+
const spelling = spellings.get(head);
|
|
15860
|
+
if (spelling)
|
|
15861
|
+
retyped.path = [spelling, ...rest];
|
|
15862
|
+
}
|
|
15863
|
+
if (typeof issue.message === "string") {
|
|
15864
|
+
retyped.message = retypeMessage(issue.message, spellings);
|
|
15865
|
+
}
|
|
15866
|
+
if (Array.isArray(issue.errors)) {
|
|
15867
|
+
retyped.errors = retypeDetails(issue.errors, spellings);
|
|
15868
|
+
}
|
|
15869
|
+
return retyped;
|
|
15870
|
+
}
|
|
15871
|
+
function retypeApiError(error, operation, commandSpec, operationSpec) {
|
|
15872
|
+
if (!(error instanceof SimApiError) || error.status === 0)
|
|
15873
|
+
return error;
|
|
15874
|
+
const spellings = typeableFields(operation, commandSpec, operationSpec);
|
|
15875
|
+
if (spellings.size === 0)
|
|
15876
|
+
return error;
|
|
15877
|
+
return new SimApiError(retypeMessage(error.message, spellings), error.status, error.code, error.details === undefined ? undefined : retypeDetails(error.details, spellings));
|
|
15490
15878
|
}
|
|
15491
15879
|
|
|
15492
15880
|
// src/runtime/build.ts
|
|
@@ -15565,6 +15953,29 @@ function assertNoReservedProgramFlags(program2) {
|
|
|
15565
15953
|
for (const child of program2.commands)
|
|
15566
15954
|
walk(child, []);
|
|
15567
15955
|
}
|
|
15956
|
+
function refuseHelpAfterUnknownCommand(program2) {
|
|
15957
|
+
const walk = (command) => {
|
|
15958
|
+
const internals = command;
|
|
15959
|
+
const dispatchesOnly = command.commands.length > 0 && !internals._actionHandler && command.registeredArguments.length === 0;
|
|
15960
|
+
if (dispatchesOnly) {
|
|
15961
|
+
const known = new Set(["help"]);
|
|
15962
|
+
for (const child of command.commands) {
|
|
15963
|
+
known.add(child.name());
|
|
15964
|
+
for (const alias of child.aliases())
|
|
15965
|
+
known.add(alias);
|
|
15966
|
+
}
|
|
15967
|
+
command.on("beforeHelp", () => {
|
|
15968
|
+
const first = command.args[0];
|
|
15969
|
+
if (first === undefined || first.startsWith("-") || known.has(first))
|
|
15970
|
+
return;
|
|
15971
|
+
internals.unknownCommand();
|
|
15972
|
+
});
|
|
15973
|
+
}
|
|
15974
|
+
for (const child of command.commands)
|
|
15975
|
+
walk(child);
|
|
15976
|
+
};
|
|
15977
|
+
walk(program2);
|
|
15978
|
+
}
|
|
15568
15979
|
function configureOperation(command, operation, spec) {
|
|
15569
15980
|
const operationSpec = V2_OPERATIONS[operation];
|
|
15570
15981
|
command.allowExcessArguments(false);
|
|
@@ -15625,10 +16036,13 @@ function configureOperation(command, operation, spec) {
|
|
|
15625
16036
|
}
|
|
15626
16037
|
}
|
|
15627
16038
|
}
|
|
15628
|
-
|
|
16039
|
+
const described = spec.describe ?? operationSpec.summary ?? `${operationSpec.method} ${operationSpec.path}`;
|
|
16040
|
+
command.description(operationSpec.personalKeyOnly ? `${described} (personal API key required)` : described);
|
|
15629
16041
|
addOperationOptions(command, operation, spec, operationSpec);
|
|
15630
16042
|
assertNoReservedFlags(command, operation);
|
|
15631
|
-
command.action((...invocation) => executeOperation(operation, spec, operationSpec, invocation))
|
|
16043
|
+
command.action((...invocation) => executeOperation(operation, spec, operationSpec, invocation).catch((error) => {
|
|
16044
|
+
throw retypeApiError(error, operation, spec, operationSpec);
|
|
16045
|
+
}));
|
|
15632
16046
|
return command;
|
|
15633
16047
|
}
|
|
15634
16048
|
function buildLeaf(operation, spec, leafName) {
|
|
@@ -15816,6 +16230,7 @@ function buildProgram(options = {}) {
|
|
|
15816
16230
|
attachProtocolCommands(program2);
|
|
15817
16231
|
attachSecretCommands(program2);
|
|
15818
16232
|
program2.addHelpText("after", HELP_EPILOGUE);
|
|
16233
|
+
refuseHelpAfterUnknownCommand(program2);
|
|
15819
16234
|
assertNoReservedProgramFlags(program2);
|
|
15820
16235
|
return program2;
|
|
15821
16236
|
}
|