@wayai/cli 0.3.222 → 0.3.223
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 +1245 -454
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4604,6 +4604,105 @@ var init_zod = __esm({
|
|
|
4604
4604
|
}
|
|
4605
4605
|
});
|
|
4606
4606
|
|
|
4607
|
+
// ../../packages/core/dist/chunk-FK6HBXM7.js
|
|
4608
|
+
var orgResourceIdParam, orgResourceFileIdParam, orgResourceFolderIdParam, hubOrgResourceParam, listOrgResourcesQuery, orgIdQuery, createOrgResourceBody, updateOrgResourceBody, createOrgResourceFolderBody, updateOrgResourceFolderBody, uploadOrgResourceFileBody, updateOrgResourceFileBody, uploadOrgSkillZipBody, linkOrgResourceBody;
|
|
4609
|
+
var init_chunk_FK6HBXM7 = __esm({
|
|
4610
|
+
"../../packages/core/dist/chunk-FK6HBXM7.js"() {
|
|
4611
|
+
"use strict";
|
|
4612
|
+
init_zod();
|
|
4613
|
+
orgResourceIdParam = external_exports.object({
|
|
4614
|
+
id: external_exports.string().uuid()
|
|
4615
|
+
});
|
|
4616
|
+
orgResourceFileIdParam = external_exports.object({
|
|
4617
|
+
file_id: external_exports.string().uuid()
|
|
4618
|
+
});
|
|
4619
|
+
orgResourceFolderIdParam = external_exports.object({
|
|
4620
|
+
folder_id: external_exports.string().uuid()
|
|
4621
|
+
});
|
|
4622
|
+
hubOrgResourceParam = external_exports.object({
|
|
4623
|
+
id: external_exports.string().uuid(),
|
|
4624
|
+
org_resource_id: external_exports.string().uuid()
|
|
4625
|
+
});
|
|
4626
|
+
listOrgResourcesQuery = external_exports.object({
|
|
4627
|
+
organization_id: external_exports.string().uuid(),
|
|
4628
|
+
hub_id: external_exports.string().uuid().optional()
|
|
4629
|
+
});
|
|
4630
|
+
orgIdQuery = external_exports.object({
|
|
4631
|
+
organization_id: external_exports.string().uuid()
|
|
4632
|
+
});
|
|
4633
|
+
createOrgResourceBody = external_exports.object({
|
|
4634
|
+
organization_id: external_exports.string().uuid(),
|
|
4635
|
+
resource_name: external_exports.string().min(1).max(255),
|
|
4636
|
+
resource_description: external_exports.string().max(1e3).nullish(),
|
|
4637
|
+
resource_type: external_exports.enum(["knowledge", "skill"]).default("knowledge"),
|
|
4638
|
+
// Skill-only fields. Required for `resource_type = 'skill'` (validated in
|
|
4639
|
+
// the route layer since cross-field refinement complicates the inferred
|
|
4640
|
+
// input type for callers). Ignored for `knowledge`.
|
|
4641
|
+
skill_name: external_exports.string().min(1).max(255).nullish(),
|
|
4642
|
+
skill_version: external_exports.string().max(50).nullish(),
|
|
4643
|
+
folder_metadata_schema: external_exports.record(external_exports.unknown()).optional(),
|
|
4644
|
+
file_metadata_schema: external_exports.record(external_exports.unknown()).optional(),
|
|
4645
|
+
enabled: external_exports.boolean().optional(),
|
|
4646
|
+
tags: external_exports.array(external_exports.string().uuid()).optional(),
|
|
4647
|
+
environment: external_exports.enum(["preview", "production", "all"]).optional()
|
|
4648
|
+
});
|
|
4649
|
+
updateOrgResourceBody = external_exports.object({
|
|
4650
|
+
resource_name: external_exports.string().min(1).max(255).optional(),
|
|
4651
|
+
resource_description: external_exports.string().max(1e3).nullish(),
|
|
4652
|
+
skill_name: external_exports.string().min(1).max(255).nullish(),
|
|
4653
|
+
skill_version: external_exports.string().max(50).nullish(),
|
|
4654
|
+
folder_metadata_schema: external_exports.record(external_exports.unknown()).optional(),
|
|
4655
|
+
file_metadata_schema: external_exports.record(external_exports.unknown()).optional(),
|
|
4656
|
+
enabled: external_exports.boolean().optional(),
|
|
4657
|
+
tags: external_exports.array(external_exports.string().uuid()).optional(),
|
|
4658
|
+
environment: external_exports.enum(["preview", "production", "all"]).optional()
|
|
4659
|
+
});
|
|
4660
|
+
createOrgResourceFolderBody = external_exports.object({
|
|
4661
|
+
org_resource_id: external_exports.string().uuid(),
|
|
4662
|
+
folder_name: external_exports.string().min(1).max(255),
|
|
4663
|
+
folder_description: external_exports.string().max(1e3).nullish(),
|
|
4664
|
+
parent_folder_id: external_exports.string().uuid().nullish(),
|
|
4665
|
+
order_index: external_exports.number().int().nonnegative().optional(),
|
|
4666
|
+
enabled: external_exports.boolean().optional(),
|
|
4667
|
+
metadata: external_exports.record(external_exports.unknown()).optional()
|
|
4668
|
+
});
|
|
4669
|
+
updateOrgResourceFolderBody = external_exports.object({
|
|
4670
|
+
folder_name: external_exports.string().min(1).max(255).optional(),
|
|
4671
|
+
folder_description: external_exports.string().max(1e3).nullish(),
|
|
4672
|
+
parent_folder_id: external_exports.string().uuid().nullish(),
|
|
4673
|
+
order_index: external_exports.number().int().nonnegative().optional(),
|
|
4674
|
+
enabled: external_exports.boolean().optional(),
|
|
4675
|
+
metadata: external_exports.record(external_exports.unknown()).optional()
|
|
4676
|
+
});
|
|
4677
|
+
uploadOrgResourceFileBody = external_exports.object({
|
|
4678
|
+
org_resource_id: external_exports.string().uuid(),
|
|
4679
|
+
folder_id: external_exports.string().uuid().nullish(),
|
|
4680
|
+
file_name: external_exports.string().min(1).max(255),
|
|
4681
|
+
file_data: external_exports.string(),
|
|
4682
|
+
// base64
|
|
4683
|
+
mime_type: external_exports.string().optional(),
|
|
4684
|
+
file_size: external_exports.number().int().nonnegative().optional(),
|
|
4685
|
+
resource_file_tags: external_exports.array(external_exports.string()).optional(),
|
|
4686
|
+
metadata: external_exports.record(external_exports.unknown()).optional()
|
|
4687
|
+
});
|
|
4688
|
+
updateOrgResourceFileBody = external_exports.object({
|
|
4689
|
+
resource_file_title: external_exports.string().min(1).max(255).optional(),
|
|
4690
|
+
folder_id: external_exports.string().uuid().nullish(),
|
|
4691
|
+
order_index: external_exports.number().int().nonnegative().optional(),
|
|
4692
|
+
enabled: external_exports.boolean().optional(),
|
|
4693
|
+
resource_file_tags: external_exports.array(external_exports.string()).optional(),
|
|
4694
|
+
metadata: external_exports.record(external_exports.unknown()).optional()
|
|
4695
|
+
});
|
|
4696
|
+
uploadOrgSkillZipBody = external_exports.object({
|
|
4697
|
+
zip_data: external_exports.string().min(1),
|
|
4698
|
+
replace_existing: external_exports.boolean().optional()
|
|
4699
|
+
});
|
|
4700
|
+
linkOrgResourceBody = external_exports.object({
|
|
4701
|
+
org_resource_id: external_exports.string().uuid()
|
|
4702
|
+
});
|
|
4703
|
+
}
|
|
4704
|
+
});
|
|
4705
|
+
|
|
4607
4706
|
// ../../packages/core/dist/chunk-VXEAR36B.js
|
|
4608
4707
|
var orgTagIdParam, listOrgTagsQuery, ORG_TAG_NAME_REGEX, ORG_TAG_NAME_MAX_LENGTH, createOrgTagBody, updateOrgTagBody;
|
|
4609
4708
|
var init_chunk_VXEAR36B = __esm({
|
|
@@ -5184,105 +5283,6 @@ var init_chunk_SXDX4GHS = __esm({
|
|
|
5184
5283
|
}
|
|
5185
5284
|
});
|
|
5186
5285
|
|
|
5187
|
-
// ../../packages/core/dist/chunk-FK6HBXM7.js
|
|
5188
|
-
var orgResourceIdParam, orgResourceFileIdParam, orgResourceFolderIdParam, hubOrgResourceParam, listOrgResourcesQuery, orgIdQuery, createOrgResourceBody, updateOrgResourceBody, createOrgResourceFolderBody, updateOrgResourceFolderBody, uploadOrgResourceFileBody, updateOrgResourceFileBody, uploadOrgSkillZipBody, linkOrgResourceBody;
|
|
5189
|
-
var init_chunk_FK6HBXM7 = __esm({
|
|
5190
|
-
"../../packages/core/dist/chunk-FK6HBXM7.js"() {
|
|
5191
|
-
"use strict";
|
|
5192
|
-
init_zod();
|
|
5193
|
-
orgResourceIdParam = external_exports.object({
|
|
5194
|
-
id: external_exports.string().uuid()
|
|
5195
|
-
});
|
|
5196
|
-
orgResourceFileIdParam = external_exports.object({
|
|
5197
|
-
file_id: external_exports.string().uuid()
|
|
5198
|
-
});
|
|
5199
|
-
orgResourceFolderIdParam = external_exports.object({
|
|
5200
|
-
folder_id: external_exports.string().uuid()
|
|
5201
|
-
});
|
|
5202
|
-
hubOrgResourceParam = external_exports.object({
|
|
5203
|
-
id: external_exports.string().uuid(),
|
|
5204
|
-
org_resource_id: external_exports.string().uuid()
|
|
5205
|
-
});
|
|
5206
|
-
listOrgResourcesQuery = external_exports.object({
|
|
5207
|
-
organization_id: external_exports.string().uuid(),
|
|
5208
|
-
hub_id: external_exports.string().uuid().optional()
|
|
5209
|
-
});
|
|
5210
|
-
orgIdQuery = external_exports.object({
|
|
5211
|
-
organization_id: external_exports.string().uuid()
|
|
5212
|
-
});
|
|
5213
|
-
createOrgResourceBody = external_exports.object({
|
|
5214
|
-
organization_id: external_exports.string().uuid(),
|
|
5215
|
-
resource_name: external_exports.string().min(1).max(255),
|
|
5216
|
-
resource_description: external_exports.string().max(1e3).nullish(),
|
|
5217
|
-
resource_type: external_exports.enum(["knowledge", "skill"]).default("knowledge"),
|
|
5218
|
-
// Skill-only fields. Required for `resource_type = 'skill'` (validated in
|
|
5219
|
-
// the route layer since cross-field refinement complicates the inferred
|
|
5220
|
-
// input type for callers). Ignored for `knowledge`.
|
|
5221
|
-
skill_name: external_exports.string().min(1).max(255).nullish(),
|
|
5222
|
-
skill_version: external_exports.string().max(50).nullish(),
|
|
5223
|
-
folder_metadata_schema: external_exports.record(external_exports.unknown()).optional(),
|
|
5224
|
-
file_metadata_schema: external_exports.record(external_exports.unknown()).optional(),
|
|
5225
|
-
enabled: external_exports.boolean().optional(),
|
|
5226
|
-
tags: external_exports.array(external_exports.string().uuid()).optional(),
|
|
5227
|
-
environment: external_exports.enum(["preview", "production", "all"]).optional()
|
|
5228
|
-
});
|
|
5229
|
-
updateOrgResourceBody = external_exports.object({
|
|
5230
|
-
resource_name: external_exports.string().min(1).max(255).optional(),
|
|
5231
|
-
resource_description: external_exports.string().max(1e3).nullish(),
|
|
5232
|
-
skill_name: external_exports.string().min(1).max(255).nullish(),
|
|
5233
|
-
skill_version: external_exports.string().max(50).nullish(),
|
|
5234
|
-
folder_metadata_schema: external_exports.record(external_exports.unknown()).optional(),
|
|
5235
|
-
file_metadata_schema: external_exports.record(external_exports.unknown()).optional(),
|
|
5236
|
-
enabled: external_exports.boolean().optional(),
|
|
5237
|
-
tags: external_exports.array(external_exports.string().uuid()).optional(),
|
|
5238
|
-
environment: external_exports.enum(["preview", "production", "all"]).optional()
|
|
5239
|
-
});
|
|
5240
|
-
createOrgResourceFolderBody = external_exports.object({
|
|
5241
|
-
org_resource_id: external_exports.string().uuid(),
|
|
5242
|
-
folder_name: external_exports.string().min(1).max(255),
|
|
5243
|
-
folder_description: external_exports.string().max(1e3).nullish(),
|
|
5244
|
-
parent_folder_id: external_exports.string().uuid().nullish(),
|
|
5245
|
-
order_index: external_exports.number().int().nonnegative().optional(),
|
|
5246
|
-
enabled: external_exports.boolean().optional(),
|
|
5247
|
-
metadata: external_exports.record(external_exports.unknown()).optional()
|
|
5248
|
-
});
|
|
5249
|
-
updateOrgResourceFolderBody = external_exports.object({
|
|
5250
|
-
folder_name: external_exports.string().min(1).max(255).optional(),
|
|
5251
|
-
folder_description: external_exports.string().max(1e3).nullish(),
|
|
5252
|
-
parent_folder_id: external_exports.string().uuid().nullish(),
|
|
5253
|
-
order_index: external_exports.number().int().nonnegative().optional(),
|
|
5254
|
-
enabled: external_exports.boolean().optional(),
|
|
5255
|
-
metadata: external_exports.record(external_exports.unknown()).optional()
|
|
5256
|
-
});
|
|
5257
|
-
uploadOrgResourceFileBody = external_exports.object({
|
|
5258
|
-
org_resource_id: external_exports.string().uuid(),
|
|
5259
|
-
folder_id: external_exports.string().uuid().nullish(),
|
|
5260
|
-
file_name: external_exports.string().min(1).max(255),
|
|
5261
|
-
file_data: external_exports.string(),
|
|
5262
|
-
// base64
|
|
5263
|
-
mime_type: external_exports.string().optional(),
|
|
5264
|
-
file_size: external_exports.number().int().nonnegative().optional(),
|
|
5265
|
-
resource_file_tags: external_exports.array(external_exports.string()).optional(),
|
|
5266
|
-
metadata: external_exports.record(external_exports.unknown()).optional()
|
|
5267
|
-
});
|
|
5268
|
-
updateOrgResourceFileBody = external_exports.object({
|
|
5269
|
-
resource_file_title: external_exports.string().min(1).max(255).optional(),
|
|
5270
|
-
folder_id: external_exports.string().uuid().nullish(),
|
|
5271
|
-
order_index: external_exports.number().int().nonnegative().optional(),
|
|
5272
|
-
enabled: external_exports.boolean().optional(),
|
|
5273
|
-
resource_file_tags: external_exports.array(external_exports.string()).optional(),
|
|
5274
|
-
metadata: external_exports.record(external_exports.unknown()).optional()
|
|
5275
|
-
});
|
|
5276
|
-
uploadOrgSkillZipBody = external_exports.object({
|
|
5277
|
-
zip_data: external_exports.string().min(1),
|
|
5278
|
-
replace_existing: external_exports.boolean().optional()
|
|
5279
|
-
});
|
|
5280
|
-
linkOrgResourceBody = external_exports.object({
|
|
5281
|
-
org_resource_id: external_exports.string().uuid()
|
|
5282
|
-
});
|
|
5283
|
-
}
|
|
5284
|
-
});
|
|
5285
|
-
|
|
5286
5286
|
// ../../packages/core/dist/chunk-GPM7PE44.js
|
|
5287
5287
|
var bootstrapQuery;
|
|
5288
5288
|
var init_chunk_GPM7PE44 = __esm({
|
|
@@ -6193,13 +6193,19 @@ var init_chunk_BEOHBREG = __esm({
|
|
|
6193
6193
|
});
|
|
6194
6194
|
|
|
6195
6195
|
// ../../packages/core/dist/chunk-4MRBBR5L.js
|
|
6196
|
-
|
|
6196
|
+
function toolsetFileToolName(entry, op) {
|
|
6197
|
+
const names = entry.names;
|
|
6198
|
+
const stated = names?.[op];
|
|
6199
|
+
return stated !== void 0 && stated !== null ? String(stated) : `${op}_${entry.name ?? entry.file_type}`;
|
|
6200
|
+
}
|
|
6201
|
+
var TOOLSET_SLUG_SETTING, TOOLSET_SLUG_PATTERN, REKOR_STRUCTURAL_ID_PATTERN, baseEnvironmentSchema, TOOLSET_FILE_OPERATIONS, toolsetFileToolSchema, toolsetSurfaceSchema, toolsetConnectionBindingSchema, rekorToolsetToolsSchema, rekorBoundAttestation, rekorResolvedToolsetSchema, resolvedFileToolSchema, rekorToolsetFileSchema, rekorToolsetFileListSchema, rekorToolsetFileGetSchema, rekorToolsetFilePutSchema, TOOLSET_CUSTOMER_FACING_REFUSAL_MARK, TOOLSET_CUSTOMER_FACING_REFUSAL;
|
|
6197
6202
|
var init_chunk_4MRBBR5L = __esm({
|
|
6198
6203
|
"../../packages/core/dist/chunk-4MRBBR5L.js"() {
|
|
6199
6204
|
"use strict";
|
|
6200
6205
|
init_chunk_BEOHBREG();
|
|
6201
6206
|
init_chunk_DHPUPI4Y();
|
|
6202
6207
|
init_zod();
|
|
6208
|
+
TOOLSET_SLUG_SETTING = "toolset";
|
|
6203
6209
|
TOOLSET_SLUG_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
|
|
6204
6210
|
REKOR_STRUCTURAL_ID_PATTERN = TOOLSET_SLUG_PATTERN;
|
|
6205
6211
|
baseEnvironmentSchema = external_exports.enum(["preview", "production"]);
|
|
@@ -6783,7 +6789,7 @@ var init_chunk_E4DIIOOE = __esm({
|
|
|
6783
6789
|
}
|
|
6784
6790
|
});
|
|
6785
6791
|
|
|
6786
|
-
// ../../packages/core/dist/chunk-
|
|
6792
|
+
// ../../packages/core/dist/chunk-4MXPUC6I.js
|
|
6787
6793
|
function spokenLineField(label, description2) {
|
|
6788
6794
|
return { type: "text", label, maxLength: SPOKEN_LINE_MAX_CHARS, default: "", description: description2 };
|
|
6789
6795
|
}
|
|
@@ -6793,8 +6799,8 @@ function byLowercaseName(a, b) {
|
|
|
6793
6799
|
return x < y ? -1 : x > y ? 1 : 0;
|
|
6794
6800
|
}
|
|
6795
6801
|
var CALLER_LANGUAGE, TTS_VOICE_REPLY_ENABLED_FIELD, COPILOT_TRIGGER_FIELD, SANDBOX_AGENT_FIELDS, AUDIO_LANGUAGE_OPTIONS, whatsapp, instagram, resend, telegram, API_CHANNEL_DELIVERY_EVENTS, apiChannel, OPENAI_REASONING_MODELS, openai, anthropic, googleAiStudio, openRouter, xai, groqStt, openaiStt, elevenLabsStt, openaiTts, groqTts, elevenLabsTts, GEMINI_TTS_VOICES, googleTts, wayai, externalResources, restApiTool, mcpServer, REKOR_TOOLSET_SERVICE_NAME, rekorToolset, CLAUDE_HARNESS_MODELS, CLAUDE_HARNESS_MODEL_OPTIONS, HARNESS_MCP_SERVERS_FIELD, HARNESS_EGRESS_FIELDS, claudeManagedAgents, SPOKEN_LINE_MAX_CHARS, gptLive, CONNECTORS;
|
|
6796
|
-
var
|
|
6797
|
-
"../../packages/core/dist/chunk-
|
|
6802
|
+
var init_chunk_4MXPUC6I = __esm({
|
|
6803
|
+
"../../packages/core/dist/chunk-4MXPUC6I.js"() {
|
|
6798
6804
|
"use strict";
|
|
6799
6805
|
CALLER_LANGUAGE = "caller";
|
|
6800
6806
|
TTS_VOICE_REPLY_ENABLED_FIELD = {
|
|
@@ -6822,7 +6828,17 @@ var init_chunk_FMXFEZN4 = __esm({
|
|
|
6822
6828
|
type: "toggle",
|
|
6823
6829
|
label: "Code Execution Sandbox",
|
|
6824
6830
|
default: false,
|
|
6825
|
-
description: "Let this agent run code in a WayAI sandbox with the sandbox tools, bash, copy_to_sandbox and copy_from_sandbox (add them under Tools):
|
|
6831
|
+
description: "Let this agent run code in a WayAI sandbox with the sandbox tools, bash, copy_to_sandbox and copy_from_sandbox (add them under Tools): a disposable Linux container, shared with the conversation's other agents or private to this agent (Sandbox Scope), started on first use and ended after 10 minutes without use, 60 minutes in all, or when the conversation closes."
|
|
6832
|
+
},
|
|
6833
|
+
sandbox_scope: {
|
|
6834
|
+
type: "select",
|
|
6835
|
+
label: "Sandbox Scope",
|
|
6836
|
+
options: [
|
|
6837
|
+
{ value: "conversation", label: "Conversation (shared with the conversation's other agents)" },
|
|
6838
|
+
{ value: "agent", label: "Agent (private to this agent)" }
|
|
6839
|
+
],
|
|
6840
|
+
default: "conversation",
|
|
6841
|
+
description: "Whose sandbox this agent uses. Conversation: shared with the conversation's other agents; every agent sharing it sees its files, and agents sharing it need the same Sandbox Network setting, or a command from one ends the sandbox and starts an empty one. Agent: private to this agent; no other agent sees its files. Set Agent for an agent that handles files others must not see, such as a copilot with internal documents. Each agent sandbox is its own container, counts toward the organization's limit on running sandboxes, and ends with the conversation."
|
|
6826
6842
|
},
|
|
6827
6843
|
sandbox_network: {
|
|
6828
6844
|
type: "select",
|
|
@@ -7748,13 +7764,13 @@ var init_chunk_FMXFEZN4 = __esm({
|
|
|
7748
7764
|
}
|
|
7749
7765
|
});
|
|
7750
7766
|
|
|
7751
|
-
// ../../packages/core/dist/chunk-
|
|
7767
|
+
// ../../packages/core/dist/chunk-NTJMGSSO.js
|
|
7752
7768
|
var evalCallInstant, EVAL_CALL_MIN_SECONDS, EVAL_CALL_MAX_SECONDS, EVAL_CALL_SPOKEN_LINE_MAX_CHARS, hubScoped2, createEvalCallBody, createEvalCallResponse, evalCallConversationQuery, evalCallRecordQuery, evalCallSpeaker, evalCallUtterance, evalCallTurn, evalCallRecording, evalCallRecordResponse, evalCallFinishResponse;
|
|
7753
|
-
var
|
|
7754
|
-
"../../packages/core/dist/chunk-
|
|
7769
|
+
var init_chunk_NTJMGSSO = __esm({
|
|
7770
|
+
"../../packages/core/dist/chunk-NTJMGSSO.js"() {
|
|
7755
7771
|
"use strict";
|
|
7756
7772
|
init_chunk_E4DIIOOE();
|
|
7757
|
-
|
|
7773
|
+
init_chunk_4MXPUC6I();
|
|
7758
7774
|
init_chunk_HZ6CADSY();
|
|
7759
7775
|
init_chunk_MIWZOSPI();
|
|
7760
7776
|
init_zod();
|
|
@@ -8121,15 +8137,15 @@ var init_chunk_MH4O3YEX = __esm({
|
|
|
8121
8137
|
}
|
|
8122
8138
|
});
|
|
8123
8139
|
|
|
8124
|
-
// ../../packages/core/dist/chunk-
|
|
8140
|
+
// ../../packages/core/dist/chunk-CWUV6NL3.js
|
|
8125
8141
|
function catalogToolSideEffects(toolName) {
|
|
8126
8142
|
const sideEffects = CATALOG_SIDE_EFFECTS.get(toolName);
|
|
8127
8143
|
if (sideEffects === void 0) return "unknown";
|
|
8128
8144
|
return sideEffects ? "side_effects" : "none";
|
|
8129
8145
|
}
|
|
8130
8146
|
var NATIVE_TOOL_SCHEMAS, WAYAI_CONNECTOR, SANDBOX_AGENT_ROLES, BASE_NATIVE_TOOLS, NATIVE_TOOLS, CATALOG_SIDE_EFFECTS;
|
|
8131
|
-
var
|
|
8132
|
-
"../../packages/core/dist/chunk-
|
|
8147
|
+
var init_chunk_CWUV6NL3 = __esm({
|
|
8148
|
+
"../../packages/core/dist/chunk-CWUV6NL3.js"() {
|
|
8133
8149
|
"use strict";
|
|
8134
8150
|
init_chunk_DHPUPI4Y();
|
|
8135
8151
|
NATIVE_TOOL_SCHEMAS = {
|
|
@@ -9110,9 +9126,10 @@ var init_chunk_HX2LNKHX = __esm({
|
|
|
9110
9126
|
// code it runs can send data out of the conversation.
|
|
9111
9127
|
{ tool_native_id: "nt-030", tool_name: "bash", tool_display_name: "Run Code (Bash)", tool_description: "Run a Bash command in the conversation's code sandbox", connector_id: WAYAI_CONNECTOR, operation: "bash", tool_method: "internal", tool_group: "Native Tools", is_delegation: false, is_auto_set: false, execution_config: null, side_effects: true, replay: "reconcile", assignable_roles: SANDBOX_AGENT_ROLES },
|
|
9112
9128
|
// Copies a conversation file, or a toolset document (`data/`, read through the toolset's `get`),
|
|
9113
|
-
// INTO the sandbox: the sandbox is conversation state, so nothing leaves the conversation.
|
|
9114
|
-
//
|
|
9115
|
-
// them, as anything else an agent leaves in it
|
|
9129
|
+
// INTO the sandbox: the sandbox is conversation state, so nothing leaves the conversation. The
|
|
9130
|
+
// conversation's sandbox is shared by its agents whose `sandbox_scope` is `conversation`, so a
|
|
9131
|
+
// document copied in is there for each of them, as anything else an agent leaves in it; an agent
|
|
9132
|
+
// set to `agent` copies into its own, which no other agent reaches (decision 147).
|
|
9116
9133
|
{ tool_native_id: "nt-031", tool_name: "copy_to_sandbox", tool_display_name: "Copy File to Sandbox", tool_description: "Copy one of the conversation's files into its code sandbox", connector_id: WAYAI_CONNECTOR, operation: "copy_to_sandbox", tool_method: "internal", tool_group: "Native Tools", is_delegation: false, is_auto_set: false, execution_config: null, side_effects: false, replay: "rerun", assignable_roles: SANDBOX_AGENT_ROLES },
|
|
9117
9134
|
// Copies a sandbox file OUT into the conversation, as an internal note for the team: nothing
|
|
9118
9135
|
// reaches the customer until `send_files` sends it. With `path`, it writes a toolset document
|
|
@@ -9160,11 +9177,104 @@ var init_chunk_IBL7FANV = __esm({
|
|
|
9160
9177
|
});
|
|
9161
9178
|
|
|
9162
9179
|
// ../../packages/core/dist/chunk-PFDZEKDE.js
|
|
9163
|
-
|
|
9180
|
+
function parseExpr(expr) {
|
|
9181
|
+
const fnMatch = expr.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*\((.*?)\)\s*(?:\.(.*))?$/);
|
|
9182
|
+
if (!fnMatch) return null;
|
|
9183
|
+
const [, fn, rawArgs, rawPath] = fnMatch;
|
|
9184
|
+
const args2 = splitArgs(rawArgs);
|
|
9185
|
+
const path42 = rawPath ? rawPath.split(".").flatMap((seg) => {
|
|
9186
|
+
const indexed = [];
|
|
9187
|
+
seg.replace(/([^\[\]]+)|\[(\d+)\]/g, (_, prop, idx) => {
|
|
9188
|
+
if (prop) indexed.push(prop);
|
|
9189
|
+
else if (idx !== void 0) indexed.push(idx);
|
|
9190
|
+
return "";
|
|
9191
|
+
});
|
|
9192
|
+
return indexed;
|
|
9193
|
+
}) : [];
|
|
9194
|
+
return { fn, args: args2, path: path42 };
|
|
9195
|
+
}
|
|
9196
|
+
function splitArgs(rawArgs) {
|
|
9197
|
+
const trimmed = rawArgs.trim();
|
|
9198
|
+
return trimmed ? trimmed.split(",").map((s) => stripQuotes(s.trim())) : [];
|
|
9199
|
+
}
|
|
9200
|
+
function stripQuotes(s) {
|
|
9201
|
+
if (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'")) {
|
|
9202
|
+
return s.slice(1, -1);
|
|
9203
|
+
}
|
|
9204
|
+
return s;
|
|
9205
|
+
}
|
|
9206
|
+
function parseCatalogArgs(args2) {
|
|
9207
|
+
let kind = null;
|
|
9208
|
+
let tree = false;
|
|
9209
|
+
for (const token of args2) {
|
|
9210
|
+
if (token === "tree") tree = true;
|
|
9211
|
+
else if ((token === "kb" || token === "skill") && kind === null) kind = token;
|
|
9212
|
+
}
|
|
9213
|
+
return { kind, tree };
|
|
9214
|
+
}
|
|
9215
|
+
function widenKinds(kinds) {
|
|
9216
|
+
if (kinds.has("all") || kinds.size > 1) return "all";
|
|
9217
|
+
return [...kinds][0] ?? null;
|
|
9218
|
+
}
|
|
9219
|
+
function* parseCalls(template) {
|
|
9220
|
+
for (const match of template.matchAll(PLACEHOLDER_RE)) {
|
|
9221
|
+
const parsed = parseExpr(match[1].trim());
|
|
9222
|
+
if (parsed) yield parsed;
|
|
9223
|
+
}
|
|
9224
|
+
}
|
|
9225
|
+
function scanTemplateResources(template) {
|
|
9226
|
+
if (!template || !template.includes("{{")) return EMPTY_SCAN;
|
|
9227
|
+
const scan = { ...EMPTY_SCAN };
|
|
9228
|
+
const names = /* @__PURE__ */ new Set();
|
|
9229
|
+
const paths = /* @__PURE__ */ new Set();
|
|
9230
|
+
const treeKinds = /* @__PURE__ */ new Set();
|
|
9231
|
+
const legacyKinds = /* @__PURE__ */ new Set();
|
|
9232
|
+
for (const { fn, args: args2 } of parseCalls(template)) {
|
|
9233
|
+
switch (fn) {
|
|
9234
|
+
case CATALOG_FN:
|
|
9235
|
+
case LEGACY_CATALOG_FN: {
|
|
9236
|
+
scan.needs_catalog = true;
|
|
9237
|
+
scan.has_catalog_call = true;
|
|
9238
|
+
const { kind, tree } = parseCatalogArgs(args2);
|
|
9239
|
+
if (fn === LEGACY_CATALOG_FN) legacyKinds.add(kind ?? "all");
|
|
9240
|
+
if (tree) treeKinds.add(kind ?? "all");
|
|
9241
|
+
break;
|
|
9242
|
+
}
|
|
9243
|
+
case "agent_skills":
|
|
9244
|
+
scan.needs_catalog = true;
|
|
9245
|
+
break;
|
|
9246
|
+
case "resource_content":
|
|
9247
|
+
if (args2[0]) names.add(args2[0]);
|
|
9248
|
+
break;
|
|
9249
|
+
case "file_content":
|
|
9250
|
+
if (args2[0]) paths.add(args2[0]);
|
|
9251
|
+
break;
|
|
9252
|
+
default:
|
|
9253
|
+
break;
|
|
9254
|
+
}
|
|
9255
|
+
}
|
|
9256
|
+
scan.tree_kinds = widenKinds(treeKinds);
|
|
9257
|
+
scan.legacy_kinds = widenKinds(legacyKinds);
|
|
9258
|
+
scan.resource_content_names = [...names];
|
|
9259
|
+
scan.file_content_paths = [...paths];
|
|
9260
|
+
return scan;
|
|
9261
|
+
}
|
|
9262
|
+
var PREVIOUS_CONVERSATIONS_MAX, PLACEHOLDER_RE, CATALOG_FN, LEGACY_CATALOG_FN, EMPTY_SCAN;
|
|
9164
9263
|
var init_chunk_PFDZEKDE = __esm({
|
|
9165
9264
|
"../../packages/core/dist/chunk-PFDZEKDE.js"() {
|
|
9166
9265
|
"use strict";
|
|
9167
9266
|
PREVIOUS_CONVERSATIONS_MAX = 20;
|
|
9267
|
+
PLACEHOLDER_RE = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
9268
|
+
CATALOG_FN = "files";
|
|
9269
|
+
LEGACY_CATALOG_FN = "resources";
|
|
9270
|
+
EMPTY_SCAN = {
|
|
9271
|
+
needs_catalog: false,
|
|
9272
|
+
has_catalog_call: false,
|
|
9273
|
+
legacy_kinds: null,
|
|
9274
|
+
tree_kinds: null,
|
|
9275
|
+
resource_content_names: [],
|
|
9276
|
+
file_content_paths: []
|
|
9277
|
+
};
|
|
9168
9278
|
}
|
|
9169
9279
|
});
|
|
9170
9280
|
|
|
@@ -9355,7 +9465,7 @@ var init_chunk_T7KQKDET = __esm({
|
|
|
9355
9465
|
}
|
|
9356
9466
|
});
|
|
9357
9467
|
|
|
9358
|
-
// ../../packages/core/dist/chunk-
|
|
9468
|
+
// ../../packages/core/dist/chunk-7PJOBY4O.js
|
|
9359
9469
|
function resolveMonitorTrigger(monitorConfig) {
|
|
9360
9470
|
if (!monitorConfig || typeof monitorConfig !== "object") return "idle";
|
|
9361
9471
|
const raw = monitorConfig.trigger;
|
|
@@ -9661,10 +9771,10 @@ function refineMonitorRulesStructuredOutput(body, ctx) {
|
|
|
9661
9771
|
if (refusal2) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["response_format"], message: refusal2 });
|
|
9662
9772
|
}
|
|
9663
9773
|
var NATIVE_TOOL_NAMES, previousConversationsCountField, summarizationThresholdField, flagConditionSchema, MONITOR_TRIGGERS, monitorTriggerSchema, AUTOMATION_GATE_TRIGGERS, NON_FIRING_TRIGGERS, MONITOR_FIRING_TRIGGERS, MONITOR_DELAY_SECONDS_MIN, MONITOR_IDLE_DELAY_REQUIRED_MESSAGE, MONITOR_HISTORY_MESSAGES_MAX, monitorHistoryMessagesSchema, monitorIncludeToolResultsSchema, MONITOR_INPUT_SHAPING_KEYS, MONITOR_INPUT_SHAPING_SCHEMAS, MONITOR_INPUT_SHAPING_IDLE_MESSAGE, monitorArgumentSourceSchema, MONITOR_NOTE_TEMPLATE_MAX, MONITOR_STEER_NOTE_MAX, MONITOR_GATE_AGENT_NAME_MAX, monitorActionSchema, monitorRuleSchema, MONITOR_RULE_KEYS, MONITOR_RULE_SCHEMAS, MONITOR_RULE_TRIGGERS, MONITOR_RULE_TRIGGER_MESSAGE, CALL_UTTERANCE_SPEAKERS, callUtteranceSpeakerSchema, MONITOR_CALL_KEYS, MONITOR_CALL_SCHEMAS, MONITOR_CALL_KEY_MESSAGE, CALL_STEERING_MIN_CONFIDENCE, CALL_UTTERANCE_RULE_NOT_CONFIDENT_MESSAGE, CALL_UTTERANCE_FALLBACK_MESSAGE, CALL_UTTERANCE_FLAG_CONDITIONS_MESSAGE, CALL_STEER_NOTE_BLANK_MESSAGE, MONITOR_USER_MESSAGE_ACTION_KINDS, MONITOR_ASSISTANT_REPLY_ACTION_KINDS, MONITOR_CALL_UTTERANCE_ACTION_KINDS, MONITOR_AUTOMATION_FIRE_ACTION_KINDS, MONITOR_AUTOMATION_ITEM_ACTION_KINDS, INSERT_NOTE_TOOL_NAME, RUN_MONITOR_TOOL_NAME, MONITOR_RULE_ALLOWED_NATIVE_TOOLS, MONITOR_RULE_REENTRY_TOOLS, MONITOR_RULE_REENTRY_TRACKS, AUTOMATION_FIRE_FLAG_CONDITIONS_MESSAGE, AUTOMATION_FIRE_INPUT_SHAPING_MESSAGE, AUTOMATION_ITEM_FLAG_CONDITIONS_MESSAGE, AUTOMATION_ITEM_INPUT_SHAPING_MESSAGE, AUTOMATION_GATE_KEY_MESSAGES, monitorConfigField, flagConditionsField, agentIdParam, listAgentsQuery, agentConnectionsQuery, createAgentBody, updateAgentBody, AGENT_PARAMETER_TYPES, AGENT_PARAMETER_NAME_REGEX, agentParameterCreateSchema, MAX_AGENT_PARAMETERS_PER_REQUEST, createAgentParametersBody;
|
|
9664
|
-
var
|
|
9665
|
-
"../../packages/core/dist/chunk-
|
|
9774
|
+
var init_chunk_7PJOBY4O = __esm({
|
|
9775
|
+
"../../packages/core/dist/chunk-7PJOBY4O.js"() {
|
|
9666
9776
|
"use strict";
|
|
9667
|
-
|
|
9777
|
+
init_chunk_CWUV6NL3();
|
|
9668
9778
|
init_chunk_IBL7FANV();
|
|
9669
9779
|
init_chunk_PFDZEKDE();
|
|
9670
9780
|
init_chunk_HZ6CADSY();
|
|
@@ -9887,12 +9997,12 @@ var init_chunk_BUXNYLB7 = __esm({
|
|
|
9887
9997
|
}
|
|
9888
9998
|
});
|
|
9889
9999
|
|
|
9890
|
-
// ../../packages/core/dist/chunk-
|
|
10000
|
+
// ../../packages/core/dist/chunk-CYBQP65X.js
|
|
9891
10001
|
var conversationIdParam, conversationHubQuery, claimBody, releaseBody, transferBody, closeBody, additionalContextPayloadSchema, kanbanUpdateBody, annotateConversationBody, observabilityParams, observabilityListParams, deleteUserConversationsBody, deleteUserConversationsResponse, sendMessageBody, listConversationsQuery, flagSourceSchema, getConversationsResponse, getConversationDetailParams, getConversationDetailQuery, getConversationDetailResponse, listWhatsAppTemplatesQuery, sendWhatsAppTemplateBody;
|
|
9892
|
-
var
|
|
9893
|
-
"../../packages/core/dist/chunk-
|
|
10002
|
+
var init_chunk_CYBQP65X = __esm({
|
|
10003
|
+
"../../packages/core/dist/chunk-CYBQP65X.js"() {
|
|
9894
10004
|
"use strict";
|
|
9895
|
-
|
|
10005
|
+
init_chunk_7PJOBY4O();
|
|
9896
10006
|
init_chunk_HZ6CADSY();
|
|
9897
10007
|
init_chunk_DHPUPI4Y();
|
|
9898
10008
|
init_zod();
|
|
@@ -10348,7 +10458,7 @@ var init_chunk_BPCNB5RT = __esm({
|
|
|
10348
10458
|
}
|
|
10349
10459
|
});
|
|
10350
10460
|
|
|
10351
|
-
// ../../packages/core/dist/chunk-
|
|
10461
|
+
// ../../packages/core/dist/chunk-NRJINQVD.js
|
|
10352
10462
|
function idempotencyHeaderRefusal(value) {
|
|
10353
10463
|
if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9-]{0,63}$/.test(value)) {
|
|
10354
10464
|
return "idempotency_header must be a header name: letters, digits and dashes, at most 64";
|
|
@@ -10359,10 +10469,10 @@ function idempotencyHeaderRefusal(value) {
|
|
|
10359
10469
|
return null;
|
|
10360
10470
|
}
|
|
10361
10471
|
var CATALOG_REPLAY, REPLAY_OVERRIDES, RESERVED_HEADERS;
|
|
10362
|
-
var
|
|
10363
|
-
"../../packages/core/dist/chunk-
|
|
10472
|
+
var init_chunk_NRJINQVD = __esm({
|
|
10473
|
+
"../../packages/core/dist/chunk-NRJINQVD.js"() {
|
|
10364
10474
|
"use strict";
|
|
10365
|
-
|
|
10475
|
+
init_chunk_CWUV6NL3();
|
|
10366
10476
|
CATALOG_REPLAY = new Map(
|
|
10367
10477
|
NATIVE_TOOLS.map((tool) => [tool.tool_name, tool.replay])
|
|
10368
10478
|
);
|
|
@@ -10595,7 +10705,7 @@ var init_chunk_WEXVYJ5H = __esm({
|
|
|
10595
10705
|
}
|
|
10596
10706
|
});
|
|
10597
10707
|
|
|
10598
|
-
// ../../packages/core/dist/chunk-
|
|
10708
|
+
// ../../packages/core/dist/chunk-QXHWCZ74.js
|
|
10599
10709
|
function refineToolConfig(value, ctx) {
|
|
10600
10710
|
const raw = value.tool_config;
|
|
10601
10711
|
if (raw == null) return;
|
|
@@ -10631,10 +10741,10 @@ function refineToolConfig(value, ctx) {
|
|
|
10631
10741
|
}
|
|
10632
10742
|
}
|
|
10633
10743
|
var toolIdParam, listToolsQuery, toolAgentQuery, deleteToolQuery, toolConnectionsQuery, nativeToolIdSchema, CONTEXT_BOUNDARIES, contextBoundarySchema, addNativeToolBody, addMcpToolBody, toolReplaySettingsFields, toolReplaySettingsSchema, createCustomToolBody, updateCustomToolBody, updateToolExecutionConfigBody;
|
|
10634
|
-
var
|
|
10635
|
-
"../../packages/core/dist/chunk-
|
|
10744
|
+
var init_chunk_QXHWCZ74 = __esm({
|
|
10745
|
+
"../../packages/core/dist/chunk-QXHWCZ74.js"() {
|
|
10636
10746
|
"use strict";
|
|
10637
|
-
|
|
10747
|
+
init_chunk_NRJINQVD();
|
|
10638
10748
|
init_chunk_WEXVYJ5H();
|
|
10639
10749
|
init_chunk_HZ6CADSY();
|
|
10640
10750
|
init_zod();
|
|
@@ -12006,7 +12116,7 @@ var init_chunk_6NI5RAM4 = __esm({
|
|
|
12006
12116
|
}
|
|
12007
12117
|
});
|
|
12008
12118
|
|
|
12009
|
-
// ../../packages/core/dist/chunk-
|
|
12119
|
+
// ../../packages/core/dist/chunk-QJTHNMWD.js
|
|
12010
12120
|
function refineHubAsCodeCustomTools(config, ctx) {
|
|
12011
12121
|
const agents = config.agents;
|
|
12012
12122
|
if (!Array.isArray(agents)) return;
|
|
@@ -12542,12 +12652,12 @@ function refineHubAsCodeMonitorRulesOutput(config, ctx) {
|
|
|
12542
12652
|
});
|
|
12543
12653
|
}
|
|
12544
12654
|
var MAX_10MB_BASE64_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_CARRIERS, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES, MAX_RESOURCE_ENCODED_BYTES, MAX_HUB_AS_CODE_RESOURCES, MAX_HUB_AS_CODE_RESOURCE_FILES, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES, MAX_CI_CONFIG_BODY_BYTES, MAX_CALL_OPENING_CARRIERS, MAX_CALL_OPENING_AGGREGATE_ENCODED_BYTES, hubAsCodeStateSchema, hubAsCodeResourceFileSchema, hubAsCodeResourceSchema, uuidPattern, ciUuidSchema, boundedHubAsCodeResourcesSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, CI_APPLY_ENTITY_KINDS, CI_APPLY_OPERATIONS, ciApplyErrorBaseSchema, ciApplyErrorSchema, ciSyncCountSchema, ciSyncChangesSchema, ciSyncWarningSchema, ciSyncResponseSchema;
|
|
12545
|
-
var
|
|
12546
|
-
"../../packages/core/dist/chunk-
|
|
12655
|
+
var init_chunk_QJTHNMWD = __esm({
|
|
12656
|
+
"../../packages/core/dist/chunk-QJTHNMWD.js"() {
|
|
12547
12657
|
"use strict";
|
|
12548
|
-
|
|
12658
|
+
init_chunk_QXHWCZ74();
|
|
12549
12659
|
init_chunk_623SRYWZ();
|
|
12550
|
-
|
|
12660
|
+
init_chunk_7PJOBY4O();
|
|
12551
12661
|
init_chunk_LBDH7LCG();
|
|
12552
12662
|
init_chunk_4LXDRTO4();
|
|
12553
12663
|
init_chunk_T4Q5COKJ();
|
|
@@ -13556,13 +13666,13 @@ var init_chunk_LQY2OCQL = __esm({
|
|
|
13556
13666
|
}
|
|
13557
13667
|
});
|
|
13558
13668
|
|
|
13559
|
-
// ../../packages/core/dist/chunk-
|
|
13669
|
+
// ../../packages/core/dist/chunk-UWFYCJCK.js
|
|
13560
13670
|
var AUTOMATION_TRIGGER_TYPES, AUTOMATION_EVENT_TYPES, AUTOMATION_TARGET_TYPES, AUTOMATION_ACTION_TYPES, AUTOMATION_CHANNEL_TYPES, AUTOMATION_PURPOSES, AUTOMATION_NAME_MAX, AUTOMATION_DESCRIPTION_MAX, AUTOMATION_INSTRUCTIONS_MAX, AUTOMATION_TEXT_MAX, AUTOMATION_CRON_MAX, AUTOMATION_WEBHOOK_AUTHS, AUTOMATION_WEBHOOK_HEADERS, AUTOMATION_WEBHOOK_BODY_MAX_BYTES, AUTOMATION_WEBHOOK_HEADER_NAME_MAX, WEBHOOK_RESERVED_HEADERS, automationTriggerSchema, automationTargetSchema, automationActionSchema, automationGateSchema, automationName, automationDescription, automationIdParam, automationHubQuery, automationWebhookParams, AUTOMATION_RUNS_PAGE_MAX, listAutomationRunsQuery, createAutomationBody, updateAutomationBody, AUTOMATION_ALERT_CATEGORIES, AUTOMATION_BLOCKED_ALERT_CATEGORY, automationEventSubscriberParam;
|
|
13561
|
-
var
|
|
13562
|
-
"../../packages/core/dist/chunk-
|
|
13671
|
+
var init_chunk_UWFYCJCK = __esm({
|
|
13672
|
+
"../../packages/core/dist/chunk-UWFYCJCK.js"() {
|
|
13563
13673
|
"use strict";
|
|
13564
13674
|
init_chunk_LQY2OCQL();
|
|
13565
|
-
|
|
13675
|
+
init_chunk_7PJOBY4O();
|
|
13566
13676
|
init_chunk_3HSB6J4J();
|
|
13567
13677
|
init_chunk_F3JHI4Y4();
|
|
13568
13678
|
init_chunk_DHPUPI4Y();
|
|
@@ -14807,6 +14917,7 @@ var init_chunk_TS4EYU3W = __esm({
|
|
|
14807
14917
|
var init_contracts = __esm({
|
|
14808
14918
|
"../../packages/core/dist/contracts/index.js"() {
|
|
14809
14919
|
"use strict";
|
|
14920
|
+
init_chunk_FK6HBXM7();
|
|
14810
14921
|
init_chunk_VXEAR36B();
|
|
14811
14922
|
init_chunk_TIZ57ZBA();
|
|
14812
14923
|
init_chunk_Q7KIQHAZ();
|
|
@@ -14814,7 +14925,6 @@ var init_contracts = __esm({
|
|
|
14814
14925
|
init_chunk_IPXBFWUU();
|
|
14815
14926
|
init_chunk_GK27ENTT();
|
|
14816
14927
|
init_chunk_SXDX4GHS();
|
|
14817
|
-
init_chunk_FK6HBXM7();
|
|
14818
14928
|
init_chunk_GPM7PE44();
|
|
14819
14929
|
init_chunk_DGKMMFIR();
|
|
14820
14930
|
init_chunk_ZC6YGHNX();
|
|
@@ -14829,7 +14939,7 @@ var init_contracts = __esm({
|
|
|
14829
14939
|
init_chunk_34LE6P7E();
|
|
14830
14940
|
init_chunk_FPSDNS2E();
|
|
14831
14941
|
init_chunk_ZXK6N2HN();
|
|
14832
|
-
|
|
14942
|
+
init_chunk_NTJMGSSO();
|
|
14833
14943
|
init_chunk_C4HEZ7ZI();
|
|
14834
14944
|
init_chunk_IR2NOSI3();
|
|
14835
14945
|
init_chunk_EA23LSDS();
|
|
@@ -14837,12 +14947,12 @@ var init_contracts = __esm({
|
|
|
14837
14947
|
init_chunk_LWMLR2WI();
|
|
14838
14948
|
init_chunk_ACGAI25T();
|
|
14839
14949
|
init_chunk_MH4O3YEX();
|
|
14840
|
-
|
|
14950
|
+
init_chunk_CYBQP65X();
|
|
14841
14951
|
init_chunk_KSTYTQ7I();
|
|
14842
14952
|
init_chunk_LKBSHANA();
|
|
14843
14953
|
init_chunk_BPCNB5RT();
|
|
14844
|
-
|
|
14845
|
-
|
|
14954
|
+
init_chunk_QJTHNMWD();
|
|
14955
|
+
init_chunk_QXHWCZ74();
|
|
14846
14956
|
init_chunk_623SRYWZ();
|
|
14847
14957
|
init_chunk_JDJ4EUOL();
|
|
14848
14958
|
init_chunk_3KYTITOR();
|
|
@@ -14852,9 +14962,9 @@ var init_contracts = __esm({
|
|
|
14852
14962
|
init_chunk_YULHXJ5M();
|
|
14853
14963
|
init_chunk_V4FRPRH5();
|
|
14854
14964
|
init_chunk_ZHJEQBXJ();
|
|
14855
|
-
|
|
14965
|
+
init_chunk_UWFYCJCK();
|
|
14856
14966
|
init_chunk_LQY2OCQL();
|
|
14857
|
-
|
|
14967
|
+
init_chunk_7PJOBY4O();
|
|
14858
14968
|
init_chunk_3HSB6J4J();
|
|
14859
14969
|
init_chunk_IG6QBZMA();
|
|
14860
14970
|
init_chunk_ZJJ5ODOD();
|
|
@@ -14863,9 +14973,9 @@ var init_contracts = __esm({
|
|
|
14863
14973
|
init_chunk_4LXDRTO4();
|
|
14864
14974
|
init_chunk_E4DIIOOE();
|
|
14865
14975
|
init_chunk_7CYHPF35();
|
|
14866
|
-
|
|
14867
|
-
|
|
14868
|
-
|
|
14976
|
+
init_chunk_4MXPUC6I();
|
|
14977
|
+
init_chunk_NRJINQVD();
|
|
14978
|
+
init_chunk_CWUV6NL3();
|
|
14869
14979
|
init_chunk_NVKU5PPQ();
|
|
14870
14980
|
init_chunk_2FCLSQSQ();
|
|
14871
14981
|
init_chunk_FECLIZTY();
|
|
@@ -15286,6 +15396,61 @@ var init_api_client = __esm({
|
|
|
15286
15396
|
}
|
|
15287
15397
|
return new Uint8Array(await response.arrayBuffer());
|
|
15288
15398
|
}
|
|
15399
|
+
// ---- A preview hub's knowledge cut-over (`wayai knowledge cut-over`) ----
|
|
15400
|
+
//
|
|
15401
|
+
// The setup routes the web console writes through, so each write takes the same checks: the
|
|
15402
|
+
// as-code push never sees a hub's copies of organization resources or their agent links.
|
|
15403
|
+
async listAgents(hubId) {
|
|
15404
|
+
const params = new URLSearchParams({ hub_id: hubId });
|
|
15405
|
+
return this.request("GET", `/api/setup/agents?${params}`);
|
|
15406
|
+
}
|
|
15407
|
+
/** Patch an agent of a preview hub: the text it reads (`updateAgentBody` takes more). */
|
|
15408
|
+
async updateAgent(hubId, agentId, patch) {
|
|
15409
|
+
const params = new URLSearchParams({ hub_id: hubId });
|
|
15410
|
+
await this.request("PATCH", `/api/setup/agents/${encodeURIComponent(agentId)}?${params}`, patch);
|
|
15411
|
+
}
|
|
15412
|
+
async listAgentResources(hubId, agentId) {
|
|
15413
|
+
const params = new URLSearchParams({ hub_id: hubId, agent_id: agentId });
|
|
15414
|
+
return this.request("GET", `/api/setup/resources/agent-resources?${params}`);
|
|
15415
|
+
}
|
|
15416
|
+
async updateAgentResource(body) {
|
|
15417
|
+
return this.request("PATCH", "/api/setup/resources/agent-resources", body);
|
|
15418
|
+
}
|
|
15419
|
+
/** An agent's tools, and the native and connection tools it could add (`available_action: 'Add'`). */
|
|
15420
|
+
async listAgentTools(hubId, agentId) {
|
|
15421
|
+
const params = new URLSearchParams({ hub_id: hubId, agent_id: agentId });
|
|
15422
|
+
return this.request("GET", `/api/setup/tools?${params}`);
|
|
15423
|
+
}
|
|
15424
|
+
async addNativeTool(hubId, agentId, toolNativeId) {
|
|
15425
|
+
return this.request("POST", "/api/setup/tools/native", {
|
|
15426
|
+
hub_id: hubId,
|
|
15427
|
+
agent_id: agentId,
|
|
15428
|
+
tool_native_id: toolNativeId
|
|
15429
|
+
});
|
|
15430
|
+
}
|
|
15431
|
+
async addMcpTool(hubId, agentId, mcpToolId) {
|
|
15432
|
+
return this.request("POST", "/api/setup/tools/mcp", { hub_id: hubId, agent_id: agentId, mcp_tool_id: mcpToolId });
|
|
15433
|
+
}
|
|
15434
|
+
async enableTool(hubId, agentId, toolId) {
|
|
15435
|
+
const params = new URLSearchParams({ hub_id: hubId, agent_id: agentId });
|
|
15436
|
+
await this.request("POST", `/api/setup/tools/${encodeURIComponent(toolId)}/enable?${params}`);
|
|
15437
|
+
}
|
|
15438
|
+
/** Add a token-holding connection (a Base Toolset's) to a preview hub; the answer lists the hub's connections. */
|
|
15439
|
+
async addConnection(body) {
|
|
15440
|
+
return this.request("POST", "/api/setup/connections", body);
|
|
15441
|
+
}
|
|
15442
|
+
async listAutomations(hubId) {
|
|
15443
|
+
const params = new URLSearchParams({ hub_id: hubId });
|
|
15444
|
+
return this.request("GET", `/api/automations?${params}`);
|
|
15445
|
+
}
|
|
15446
|
+
async updateAutomation(hubId, automationId, body) {
|
|
15447
|
+
const params = new URLSearchParams({ hub_id: hubId });
|
|
15448
|
+
await this.request("PATCH", `/api/automations/${encodeURIComponent(automationId)}?${params}`, body);
|
|
15449
|
+
}
|
|
15450
|
+
/** Record one knowledge resource's move into the org's knowledge base (#5142 step 4). */
|
|
15451
|
+
async recordKnowledgeMove(body) {
|
|
15452
|
+
return this.request("POST", "/api/setup/knowledge/moves", body);
|
|
15453
|
+
}
|
|
15289
15454
|
async me() {
|
|
15290
15455
|
return this.request("GET", "/api/auth/me");
|
|
15291
15456
|
}
|
|
@@ -33543,6 +33708,12 @@ var init_resource_paths = __esm({
|
|
|
33543
33708
|
});
|
|
33544
33709
|
|
|
33545
33710
|
// src/knowledge/source.ts
|
|
33711
|
+
function orgSourceKey(orgResourceId) {
|
|
33712
|
+
return `organization resource ${orgResourceId}`;
|
|
33713
|
+
}
|
|
33714
|
+
function hubSourceKey(productionHubId, resourceId) {
|
|
33715
|
+
return `hub ${productionHubId} resource ${resourceId}`;
|
|
33716
|
+
}
|
|
33546
33717
|
function movesFromOrg(resource) {
|
|
33547
33718
|
return resource.resource_type === "knowledge";
|
|
33548
33719
|
}
|
|
@@ -33592,7 +33763,7 @@ function orgSources(resources, rows) {
|
|
|
33592
33763
|
skill_name: r.skill_name,
|
|
33593
33764
|
resource_type: r.resource_type,
|
|
33594
33765
|
created_at: r.created_at,
|
|
33595
|
-
sourceKey:
|
|
33766
|
+
sourceKey: orgSourceKey(r.org_resource_id),
|
|
33596
33767
|
description: r.resource_description ?? "",
|
|
33597
33768
|
folderSchema: r.folder_metadata_schema,
|
|
33598
33769
|
fileSchema: r.file_metadata_schema,
|
|
@@ -33641,7 +33812,7 @@ function hubSources(hubId, resources, rows) {
|
|
|
33641
33812
|
skill_name: r.skill_name,
|
|
33642
33813
|
resource_type: r.resource_type,
|
|
33643
33814
|
created_at: r.created_at,
|
|
33644
|
-
sourceKey:
|
|
33815
|
+
sourceKey: hubSourceKey(hubId, r.resource_id),
|
|
33645
33816
|
description: r.resource_description ?? "",
|
|
33646
33817
|
folderSchema: r.folder_metadata_schema,
|
|
33647
33818
|
fileSchema: r.file_metadata_schema,
|
|
@@ -33712,7 +33883,10 @@ function orgFileTypeId(resource) {
|
|
|
33712
33883
|
return resource.slug;
|
|
33713
33884
|
}
|
|
33714
33885
|
function hubFileTypeId(hubSlug, resource) {
|
|
33715
|
-
return `${hubSlug}
|
|
33886
|
+
return `${hubSlug}${HUB_PART_SEPARATOR}${resource.slug}`;
|
|
33887
|
+
}
|
|
33888
|
+
function hubPartOf(fileTypeId) {
|
|
33889
|
+
return fileTypeId.split(HUB_PART_SEPARATOR)[0];
|
|
33716
33890
|
}
|
|
33717
33891
|
function toolAlias(id) {
|
|
33718
33892
|
const hash = createHash5("sha256").update(id).digest("hex").slice(0, 6);
|
|
@@ -34251,7 +34425,7 @@ function describeSkip(skip) {
|
|
|
34251
34425
|
return `${skip.fileType}: folder "${skip.folder}" has a description but no path, so it gets no ${INDEX_FILE}.`;
|
|
34252
34426
|
}
|
|
34253
34427
|
}
|
|
34254
|
-
var MAX_TOOL_BASE_LENGTH, INDEX_FILE, PROVENANCE_PREFIX, MAX_NAME_LENGTH3, MAX_PATH_LENGTH, TITLE_SCHEMA, TAGS_SCHEMA, MAX_NOTE_VALUES, DEFINITION_KEYS, DRAFT, MAX_PATTERNED_VALUE_LENGTH, SUBSCHEMA_KEYS, SUBSCHEMA_MAP_KEYS;
|
|
34428
|
+
var MAX_TOOL_BASE_LENGTH, INDEX_FILE, PROVENANCE_PREFIX, MAX_NAME_LENGTH3, MAX_PATH_LENGTH, TITLE_SCHEMA, TAGS_SCHEMA, MAX_NOTE_VALUES, HUB_PART_SEPARATOR, DEFINITION_KEYS, DRAFT, MAX_PATTERNED_VALUE_LENGTH, SUBSCHEMA_KEYS, SUBSCHEMA_MAP_KEYS;
|
|
34255
34429
|
var init_plan = __esm({
|
|
34256
34430
|
"src/knowledge/plan.ts"() {
|
|
34257
34431
|
"use strict";
|
|
@@ -34266,6 +34440,7 @@ var init_plan = __esm({
|
|
|
34266
34440
|
TITLE_SCHEMA = { type: "string" };
|
|
34267
34441
|
TAGS_SCHEMA = { type: "array", items: { type: "string" } };
|
|
34268
34442
|
MAX_NOTE_VALUES = 3;
|
|
34443
|
+
HUB_PART_SEPARATOR = "--";
|
|
34269
34444
|
DEFINITION_KEYS = ["$defs", "definitions"];
|
|
34270
34445
|
DRAFT = "2020-12";
|
|
34271
34446
|
MAX_PATTERNED_VALUE_LENGTH = 1024;
|
|
@@ -34373,17 +34548,17 @@ function sameFileType(remote, spec) {
|
|
|
34373
34548
|
function isObject(value) {
|
|
34374
34549
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34375
34550
|
}
|
|
34376
|
-
function promotionProblems(result, ids) {
|
|
34551
|
+
function promotionProblems(result, ids, section = "file_types") {
|
|
34377
34552
|
const answer = isObject(result) ? result : {};
|
|
34378
34553
|
const problems2 = [];
|
|
34379
|
-
for (const [
|
|
34554
|
+
for (const [kind, bucket2] of Object.entries(isObject(answer.diff) ? answer.diff : {})) {
|
|
34380
34555
|
if (!isObject(bucket2)) continue;
|
|
34381
34556
|
for (const change of ["added", "modified", "removed"]) {
|
|
34382
34557
|
for (const entry of Array.isArray(bucket2[change]) ? bucket2[change] : []) {
|
|
34383
34558
|
const row = isObject(entry) ? isObject(entry.after) ? entry.after : entry : {};
|
|
34384
34559
|
const id = typeof row.id === "string" ? row.id : JSON.stringify(row).slice(0, 80);
|
|
34385
|
-
if (
|
|
34386
|
-
problems2.push(`it would also apply ${
|
|
34560
|
+
if (kind === section && change !== "removed" && ids.has(id)) continue;
|
|
34561
|
+
problems2.push(`it would also apply ${kind} ${change}: "${id}"`);
|
|
34387
34562
|
}
|
|
34388
34563
|
}
|
|
34389
34564
|
}
|
|
@@ -34652,6 +34827,253 @@ var init_headers = __esm({
|
|
|
34652
34827
|
}
|
|
34653
34828
|
});
|
|
34654
34829
|
|
|
34830
|
+
// src/data/commands/tokens.ts
|
|
34831
|
+
import { Command } from "commander";
|
|
34832
|
+
function rawTokenFrom(data) {
|
|
34833
|
+
const token = typeof data === "object" && data !== null && "token" in data ? data.token : void 0;
|
|
34834
|
+
if (typeof token !== "string" || !RAW_TOKEN_PATTERN.test(token)) {
|
|
34835
|
+
throw new Error("Token creation response did not contain a valid rec_ token");
|
|
34836
|
+
}
|
|
34837
|
+
return token;
|
|
34838
|
+
}
|
|
34839
|
+
function addTokenLifecycleOptions(cmd) {
|
|
34840
|
+
return cmd.option("--expires-at <date>", "Expiration date (ISO 8601, e.g. 2026-06-01T00:00:00Z)").option(
|
|
34841
|
+
"--ttl <duration>",
|
|
34842
|
+
"Relative expiry, e.g. 10m, 2h, 7d (use for disposable probe/test tokens)"
|
|
34843
|
+
).option(
|
|
34844
|
+
"--description <text>",
|
|
34845
|
+
'What holds this token (e.g. "behind credential X"); shown in list and revoke warnings'
|
|
34846
|
+
).addHelpText("after", TOKEN_OUTPUT_HELP);
|
|
34847
|
+
}
|
|
34848
|
+
function tokenCreationOutput(cmd, opts) {
|
|
34849
|
+
return opts.tokenOnly ? "token" : outputFormat(cmd);
|
|
34850
|
+
}
|
|
34851
|
+
function printCreatedToken(data, output) {
|
|
34852
|
+
if (output !== "token") {
|
|
34853
|
+
printOutput(data, output);
|
|
34854
|
+
return;
|
|
34855
|
+
}
|
|
34856
|
+
console.log(rawTokenFrom(data));
|
|
34857
|
+
}
|
|
34858
|
+
function resolveExpiresAt(opts) {
|
|
34859
|
+
if (opts.ttl && opts.expiresAt) {
|
|
34860
|
+
throw expected("--ttl and --expires-at are mutually exclusive \u2014 pass one.");
|
|
34861
|
+
}
|
|
34862
|
+
if (opts.ttl) return new Date(Date.now() + parseDuration(opts.ttl, "--ttl")).toISOString();
|
|
34863
|
+
return opts.expiresAt;
|
|
34864
|
+
}
|
|
34865
|
+
function applyTokenLifecycleOpts(body, opts) {
|
|
34866
|
+
const expiresAt = resolveExpiresAt(opts);
|
|
34867
|
+
if (expiresAt) body.expires_at = expiresAt;
|
|
34868
|
+
if (opts.description) body.description = opts.description;
|
|
34869
|
+
}
|
|
34870
|
+
function listAllTokens(client) {
|
|
34871
|
+
return client.collectPages(
|
|
34872
|
+
(cursor) => `/v1/tokens?limit=${TOKEN_LIST_PAGE_LIMIT}${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""}`
|
|
34873
|
+
);
|
|
34874
|
+
}
|
|
34875
|
+
function pruneRow(t, reason) {
|
|
34876
|
+
return {
|
|
34877
|
+
token_id: t.token_id,
|
|
34878
|
+
name: t.name,
|
|
34879
|
+
reason,
|
|
34880
|
+
last_used: t.last_used_at ?? "never"
|
|
34881
|
+
};
|
|
34882
|
+
}
|
|
34883
|
+
function buildBasesTokensCommand() {
|
|
34884
|
+
const tokens2 = new Command("tokens").description("Manage API tokens");
|
|
34885
|
+
addTokenLifecycleOptions(
|
|
34886
|
+
tokens2.command("create").description("Create a scoped API token").requiredOption("--name <name>", "Token name").requiredOption("--grants <json>", "Grant definitions as JSON array").option(
|
|
34887
|
+
"--token-only",
|
|
34888
|
+
"Print only the raw rec_ token for secure command substitution (shown once)"
|
|
34889
|
+
)
|
|
34890
|
+
).action(async function(opts) {
|
|
34891
|
+
const grants = parseData(opts.grants, "--grants");
|
|
34892
|
+
const body = { name: opts.name, grants };
|
|
34893
|
+
applyTokenLifecycleOpts(body, opts);
|
|
34894
|
+
const client = await createDataClient();
|
|
34895
|
+
const data = await client.request("POST", "/v1/tokens", body);
|
|
34896
|
+
printCreatedToken(data, tokenCreationOutput(this, opts));
|
|
34897
|
+
});
|
|
34898
|
+
addTokenLifecycleOptions(
|
|
34899
|
+
// The only token verb that addresses a base, so it alone declares `--base`.
|
|
34900
|
+
// Putting it on the `tokens` group would advertise a flag that does nothing
|
|
34901
|
+
// on `list`, `revoke` and `prune` — the defect `withBaseOption` exists to
|
|
34902
|
+
// avoid.
|
|
34903
|
+
withBaseOption(tokens2.command("create-for-toolset <slug>")).description(
|
|
34904
|
+
"Create a toolset-bound (consumer) token whose authorization IS the toolset tool surface \u2014 it can call exactly the tools that toolset exposes (those record types + operations, relationships, batch, and sql only if enabled) and nothing else. Binds to the configured --base."
|
|
34905
|
+
).option("--name <name>", 'Token name (default: "<slug> consumer")').option(
|
|
34906
|
+
"--token-only",
|
|
34907
|
+
"Print only the raw rec_ token for secure command substitution (shown once)"
|
|
34908
|
+
)
|
|
34909
|
+
).action(async function(slug, opts) {
|
|
34910
|
+
const base = requireBase(this);
|
|
34911
|
+
const body = {
|
|
34912
|
+
name: opts.name ?? `${slug} consumer`,
|
|
34913
|
+
toolset_binding: { base_id: base, toolset_id: slug }
|
|
34914
|
+
};
|
|
34915
|
+
applyTokenLifecycleOpts(body, opts);
|
|
34916
|
+
const client = await createDataClient();
|
|
34917
|
+
const data = await client.request("POST", "/v1/tokens", body);
|
|
34918
|
+
const output = tokenCreationOutput(this, opts);
|
|
34919
|
+
printCreatedToken(data, output);
|
|
34920
|
+
if (output === "table") {
|
|
34921
|
+
console.log(`
|
|
34922
|
+
MCP URL: ${toolsetMcpUrl(slug)}`);
|
|
34923
|
+
}
|
|
34924
|
+
});
|
|
34925
|
+
tokens2.command("list").description("List API tokens (status, last_used_at, expires_at, description)").action(async function() {
|
|
34926
|
+
const client = await createDataClient();
|
|
34927
|
+
printOutput(await listAllTokens(client), outputFormat(this));
|
|
34928
|
+
});
|
|
34929
|
+
tokens2.command("revoke <token_id>").description(
|
|
34930
|
+
"Revoke an API token (permanent). A recently-used or toolset-bound token requires --force."
|
|
34931
|
+
).option("--force", "Revoke even if the token appears to be in live use").action(async function(tokenId, opts) {
|
|
34932
|
+
const client = await createDataClient();
|
|
34933
|
+
const id = pathSegment(tokenId, "token id");
|
|
34934
|
+
const path42 = (force) => `/v1/tokens/${id}${force ? "?force=true" : ""}`;
|
|
34935
|
+
const format = outputFormat(this);
|
|
34936
|
+
const revoked = (forced) => printOutput({ token_id: tokenId, revoked: true, forced }, format);
|
|
34937
|
+
if (opts.force) {
|
|
34938
|
+
await client.request("DELETE", path42(true));
|
|
34939
|
+
revoked(true);
|
|
34940
|
+
return;
|
|
34941
|
+
}
|
|
34942
|
+
try {
|
|
34943
|
+
await client.request("DELETE", path42(false));
|
|
34944
|
+
revoked(false);
|
|
34945
|
+
} catch (err) {
|
|
34946
|
+
if (!(err instanceof ApiError) || err.status !== 409 || dataErrorDetails(err)?.requires_force !== true) {
|
|
34947
|
+
throw err;
|
|
34948
|
+
}
|
|
34949
|
+
console.error(err.message);
|
|
34950
|
+
if (!isInteractive()) {
|
|
34951
|
+
console.error("\nRe-run with --force to revoke anyway.");
|
|
34952
|
+
return process.exit(1);
|
|
34953
|
+
}
|
|
34954
|
+
if (!await confirm("Revoke anyway?")) {
|
|
34955
|
+
console.error("Aborted.");
|
|
34956
|
+
return process.exit(1);
|
|
34957
|
+
}
|
|
34958
|
+
await client.request("DELETE", path42(true));
|
|
34959
|
+
revoked(true);
|
|
34960
|
+
}
|
|
34961
|
+
});
|
|
34962
|
+
tokens2.command("prune").description(
|
|
34963
|
+
"Revoke stale tokens, selected by staleness only (expired, or unused past --unused-since) \u2014 never by name. Previews by default; revoking requires --yes or an interactive confirmation."
|
|
34964
|
+
).option(
|
|
34965
|
+
"--unused-since <duration>",
|
|
34966
|
+
"Also prune tokens with no activity for this long (e.g. 30d). Skips toolset-bound and legacy usage-untracked tokens."
|
|
34967
|
+
).option("--include-bound", "Allow pruning stale toolset-bound (consumer) tokens").option("-y, --yes", "Revoke without prompting (required when non-interactive)").action(async function(opts) {
|
|
34968
|
+
const staleMs = opts.unusedSince ? parseDuration(opts.unusedSince, "--unused-since") : void 0;
|
|
34969
|
+
const client = await createDataClient();
|
|
34970
|
+
const allTokens = await listAllTokens(client);
|
|
34971
|
+
const now = Date.now();
|
|
34972
|
+
const targets = [];
|
|
34973
|
+
const skipped = [];
|
|
34974
|
+
for (const t of allTokens) {
|
|
34975
|
+
const expired = t.status ? t.status === "expired" : !!t.expires_at && Date.parse(t.expires_at) <= now;
|
|
34976
|
+
if (expired) {
|
|
34977
|
+
targets.push(pruneRow(t, "expired"));
|
|
34978
|
+
continue;
|
|
34979
|
+
}
|
|
34980
|
+
if (staleMs === void 0) continue;
|
|
34981
|
+
const lastActivity = Date.parse(t.last_used_at ?? t.created_at);
|
|
34982
|
+
if (!(now - lastActivity > staleMs)) continue;
|
|
34983
|
+
if (t.usage_tracked !== true) {
|
|
34984
|
+
skipped.push(
|
|
34985
|
+
pruneRow(
|
|
34986
|
+
t,
|
|
34987
|
+
"usage untracked (legacy token) \u2014 revoke individually if truly unused"
|
|
34988
|
+
)
|
|
34989
|
+
);
|
|
34990
|
+
} else if (t.toolset_binding && !opts.includeBound) {
|
|
34991
|
+
skipped.push(
|
|
34992
|
+
pruneRow(
|
|
34993
|
+
t,
|
|
34994
|
+
`toolset-bound ('${t.toolset_binding.toolset_id}') \u2014 pass --include-bound to prune`
|
|
34995
|
+
)
|
|
34996
|
+
);
|
|
34997
|
+
} else {
|
|
34998
|
+
targets.push(pruneRow(t, `unused for over ${opts.unusedSince}`));
|
|
34999
|
+
}
|
|
35000
|
+
}
|
|
35001
|
+
const format = outputFormat(this);
|
|
35002
|
+
const json = format === "json";
|
|
35003
|
+
const note = (line) => json ? console.error(line) : console.log(line);
|
|
35004
|
+
const printPreview = () => {
|
|
35005
|
+
if (targets.length === 0) {
|
|
35006
|
+
note("Nothing to prune.");
|
|
35007
|
+
} else {
|
|
35008
|
+
note(`Would revoke ${targets.length} token(s):`);
|
|
35009
|
+
if (!json) printOutput(targets, format);
|
|
35010
|
+
}
|
|
35011
|
+
if (skipped.length === 0) return;
|
|
35012
|
+
note(`
|
|
35013
|
+
Skipped ${skipped.length} stale token(s):`);
|
|
35014
|
+
if (!json) printOutput(skipped, format);
|
|
35015
|
+
};
|
|
35016
|
+
printPreview();
|
|
35017
|
+
if (targets.length === 0) {
|
|
35018
|
+
if (json) printOutput({ revoked: 0, failed: 0, targets, skipped }, format);
|
|
35019
|
+
return;
|
|
35020
|
+
}
|
|
35021
|
+
if (!opts.yes) {
|
|
35022
|
+
if (!isInteractive()) {
|
|
35023
|
+
console.error("\nPreview only \u2014 re-run with --yes to revoke these tokens.");
|
|
35024
|
+
if (json) printOutput({ preview: true, revoked: 0, failed: 0, targets, skipped }, format);
|
|
35025
|
+
return process.exit(1);
|
|
35026
|
+
}
|
|
35027
|
+
if (!await confirm(`
|
|
35028
|
+
Revoke ${targets.length} token(s)?`)) {
|
|
35029
|
+
console.error("Aborted.");
|
|
35030
|
+
return process.exit(1);
|
|
35031
|
+
}
|
|
35032
|
+
}
|
|
35033
|
+
let revoked = 0;
|
|
35034
|
+
let failed = 0;
|
|
35035
|
+
for (const t of targets) {
|
|
35036
|
+
try {
|
|
35037
|
+
await client.request(
|
|
35038
|
+
"DELETE",
|
|
35039
|
+
`/v1/tokens/${pathSegment(t.token_id, "token id")}?force=true`
|
|
35040
|
+
);
|
|
35041
|
+
revoked++;
|
|
35042
|
+
} catch (err) {
|
|
35043
|
+
failed++;
|
|
35044
|
+
console.error(
|
|
35045
|
+
`Failed to revoke ${t.token_id} ('${sanitizeTerminalText(t.name)}'): ${err instanceof Error ? err.message : String(err)}`
|
|
35046
|
+
);
|
|
35047
|
+
}
|
|
35048
|
+
}
|
|
35049
|
+
if (json) printOutput({ revoked, failed, targets, skipped }, format);
|
|
35050
|
+
else console.log(`Revoked ${revoked} token(s)${failed > 0 ? `, ${failed} failed` : ""}.`);
|
|
35051
|
+
if (failed > 0) return process.exit(1);
|
|
35052
|
+
});
|
|
35053
|
+
return tokens2;
|
|
35054
|
+
}
|
|
35055
|
+
var RAW_TOKEN_PATTERN, TOKEN_OUTPUT_HELP, TOKEN_LIST_PAGE_LIMIT;
|
|
35056
|
+
var init_tokens = __esm({
|
|
35057
|
+
"src/data/commands/tokens.ts"() {
|
|
35058
|
+
"use strict";
|
|
35059
|
+
init_client();
|
|
35060
|
+
init_output();
|
|
35061
|
+
init_helpers();
|
|
35062
|
+
init_api_client();
|
|
35063
|
+
init_terminal_output();
|
|
35064
|
+
init_utils();
|
|
35065
|
+
init_expected();
|
|
35066
|
+
RAW_TOKEN_PATTERN = /^rec_[A-Za-z0-9_-]{43}$/;
|
|
35067
|
+
TOKEN_OUTPUT_HELP = `
|
|
35068
|
+
Output:
|
|
35069
|
+
--json prints the unwrapped response object; the secret is at top-level .token, never .data.token.
|
|
35070
|
+
--token-only prints only a validated rec_ token and overrides table/JSON formatting.
|
|
35071
|
+
The raw token is shown once. Capture it securely and do not log it.
|
|
35072
|
+
`;
|
|
35073
|
+
TOKEN_LIST_PAGE_LIMIT = 250;
|
|
35074
|
+
}
|
|
35075
|
+
});
|
|
35076
|
+
|
|
34655
35077
|
// src/knowledge/remote.ts
|
|
34656
35078
|
function pacedRequestsPerMinute(path42, fallback) {
|
|
34657
35079
|
const budget = getEndpointConfig(path42)?.userLimit;
|
|
@@ -34702,6 +35124,14 @@ function knowledgeBase(client) {
|
|
|
34702
35124
|
const request = (method, path42, body) => pacer.run(() => client.request(method, path42, body));
|
|
34703
35125
|
const baseSeg = (id) => pathSegment(id, "--base");
|
|
34704
35126
|
const typeSeg = (id) => pathSegment(id, "file type");
|
|
35127
|
+
const toolsetSeg = (id) => pathSegment(id, "toolset slug");
|
|
35128
|
+
const promoteOnly = (production, preview, section, ids, dryRun) => request("POST", `/v1/${baseSeg(production)}/promote`, {
|
|
35129
|
+
source_base_id: preview,
|
|
35130
|
+
dry_run: dryRun,
|
|
35131
|
+
...Object.fromEntries(ENTITY_KINDS.map((kind) => [kind, []])),
|
|
35132
|
+
file_types: [],
|
|
35133
|
+
[section]: ids
|
|
35134
|
+
});
|
|
34705
35135
|
return {
|
|
34706
35136
|
getBase: (id) => unlessMissing(() => pacer.run(() => getBaseRecord(client, id))),
|
|
34707
35137
|
listPreviews: (id) => pacer.run(
|
|
@@ -34713,14 +35143,7 @@ function knowledgeBase(client) {
|
|
|
34713
35143
|
const { id, ...body } = spec;
|
|
34714
35144
|
await request("PUT", `/v1/${baseSeg(base)}/file-types/${typeSeg(id)}`, body);
|
|
34715
35145
|
},
|
|
34716
|
-
|
|
34717
|
-
return request("POST", `/v1/${baseSeg(production)}/promote`, {
|
|
34718
|
-
source_base_id: preview,
|
|
34719
|
-
dry_run: dryRun,
|
|
34720
|
-
...Object.fromEntries(ENTITY_KINDS.map((kind) => [kind, []])),
|
|
34721
|
-
file_types: ids
|
|
34722
|
-
});
|
|
34723
|
-
},
|
|
35146
|
+
promoteFileTypes: (production, preview, ids, dryRun) => promoteOnly(production, preview, "file_types", ids, dryRun),
|
|
34724
35147
|
async listFiles(base, fileType) {
|
|
34725
35148
|
const rows = [];
|
|
34726
35149
|
for (let page = 0; page < MAX_LIST_PAGES; page++) {
|
|
@@ -34731,6 +35154,13 @@ function knowledgeBase(client) {
|
|
|
34731
35154
|
}
|
|
34732
35155
|
throw expected(`The listing of file type "${fileType}" on base "${base}" did not end after ${MAX_LIST_PAGES} pages.`);
|
|
34733
35156
|
},
|
|
35157
|
+
getToolset: (base, slug) => unlessMissing(() => request("GET", `/v1/${baseSeg(base)}/toolsets/${toolsetSeg(slug)}`)),
|
|
35158
|
+
async putToolset(base, spec) {
|
|
35159
|
+
const { id, ...body } = spec;
|
|
35160
|
+
await request("PUT", `/v1/${baseSeg(base)}/toolsets/${toolsetSeg(id)}`, { ...body, actions: [] });
|
|
35161
|
+
},
|
|
35162
|
+
promoteToolsets: (production, preview, slugs, dryRun) => promoteOnly(production, preview, "toolsets", slugs, dryRun),
|
|
35163
|
+
mintToolsetToken: async (base, slug, name) => rawTokenFrom(await request("POST", "/v1/tokens", { name, toolset_binding: { base_id: base, toolset_id: slug } })),
|
|
34734
35164
|
// `requestRaw`: the page is read whole, `{ data: … }`, as WayAI's copy of its answer declares it
|
|
34735
35165
|
// (`@wayai/core/contracts` `rekorFileSnapshotAnswerSchema`).
|
|
34736
35166
|
snapshotPage: (preview, cursor) => pacer.run(() => client.requestRaw("POST", `/v1/${baseSeg(preview)}/files/snapshot`, cursor === void 0 ? {} : { cursor })),
|
|
@@ -34746,7 +35176,70 @@ function knowledgeBase(client) {
|
|
|
34746
35176
|
}
|
|
34747
35177
|
};
|
|
34748
35178
|
}
|
|
34749
|
-
|
|
35179
|
+
function connectionsOf(rows) {
|
|
35180
|
+
return (rows ?? []).flatMap(
|
|
35181
|
+
(c) => c.connection_id ? [{ connection_id: c.connection_id, connection_display_name: c.connection_display_name, connector_id: c.connector_id, settings: c.settings }] : []
|
|
35182
|
+
);
|
|
35183
|
+
}
|
|
35184
|
+
function hubSetup(api, orgId, pacers = {
|
|
35185
|
+
setup: pacerFor(CUT_OVER_BUDGETS.setup, "setup"),
|
|
35186
|
+
automations: pacerFor(CUT_OVER_BUDGETS.automations, "automations")
|
|
35187
|
+
}) {
|
|
35188
|
+
const run = (send) => pacers.setup.run(send);
|
|
35189
|
+
const auto = (send) => pacers.automations.run(send);
|
|
35190
|
+
return {
|
|
35191
|
+
listHubs: async () => hubsOf(await run(() => api.getUserSchema()), orgId),
|
|
35192
|
+
hubDiff: async (hubId) => (await run(() => api.getHubDiff(hubId))).data,
|
|
35193
|
+
// The rows are the hub's `resource` rows whole, the move's mark (`moved_file_type`) among them.
|
|
35194
|
+
listResources: async (hubId) => (await run(() => api.listHubResources(hubId))).data ?? [],
|
|
35195
|
+
listAgents: async (hubId) => (await run(() => api.listAgents(hubId))).data ?? [],
|
|
35196
|
+
listAgentLinks: async (hubId, agentId) => (await run(() => api.listAgentResources(hubId, agentId))).resources ?? [],
|
|
35197
|
+
listAgentTools: async (hubId, agentId) => {
|
|
35198
|
+
const tools = await run(() => api.listAgentTools(hubId, agentId));
|
|
35199
|
+
return { native: tools.tools ?? [], connection: (tools.mcp_tools ?? []).map((t) => ({ ...t, tool_id: t.tool_id ?? null })) };
|
|
35200
|
+
},
|
|
35201
|
+
listConnections: async (hubId) => connectionsOf((await run(() => api.listConnections(hubId))).connections),
|
|
35202
|
+
listAutomations: async (hubId) => (await auto(() => api.listAutomations(hubId))).automations ?? [],
|
|
35203
|
+
// The answer lists the hub's connections, the new one among them.
|
|
35204
|
+
addToolsetConnection: async (hubId, input) => connectionsOf(
|
|
35205
|
+
(await run(
|
|
35206
|
+
() => api.addConnection({
|
|
35207
|
+
hub_id: hubId,
|
|
35208
|
+
connector_id: input.connectorId,
|
|
35209
|
+
connection_display_name: input.name,
|
|
35210
|
+
settings: { [TOOLSET_SLUG_SETTING]: input.toolset },
|
|
35211
|
+
access_token: input.token
|
|
35212
|
+
})
|
|
35213
|
+
)).connections
|
|
35214
|
+
),
|
|
35215
|
+
async syncConnection(hubId, connectionId) {
|
|
35216
|
+
const answer = await run(() => api.syncMcp(hubId, connectionId));
|
|
35217
|
+
if (!answer.success) {
|
|
35218
|
+
throw expected(`Syncing connection ${connectionId}'s tools failed: ${sanitizeTerminalText(answer.message ?? "no reason given")}`);
|
|
35219
|
+
}
|
|
35220
|
+
},
|
|
35221
|
+
async addNativeTool(hubId, agentId, toolNativeId) {
|
|
35222
|
+
await run(() => api.addNativeTool(hubId, agentId, toolNativeId));
|
|
35223
|
+
},
|
|
35224
|
+
async addConnectionTool(hubId, agentId, mcpToolId) {
|
|
35225
|
+
await run(() => api.addMcpTool(hubId, agentId, mcpToolId));
|
|
35226
|
+
},
|
|
35227
|
+
async enableTool(hubId, agentId, toolId) {
|
|
35228
|
+
await run(() => api.enableTool(hubId, agentId, toolId));
|
|
35229
|
+
},
|
|
35230
|
+
async updateAgentText(hubId, agentId, patch) {
|
|
35231
|
+
await run(() => api.updateAgent(hubId, agentId, patch));
|
|
35232
|
+
},
|
|
35233
|
+
async updateAutomationAction(hubId, automationId, action) {
|
|
35234
|
+
await auto(() => api.updateAutomation(hubId, automationId, { action }));
|
|
35235
|
+
},
|
|
35236
|
+
async disableLink(hubId, agentId, resourceId) {
|
|
35237
|
+
await run(() => api.updateAgentResource({ hub_id: hubId, agent_id: agentId, resource_id: resourceId, enabled: false }));
|
|
35238
|
+
},
|
|
35239
|
+
recordMove: async (body) => (await run(() => api.recordKnowledgeMove(body))).data.recorded
|
|
35240
|
+
};
|
|
35241
|
+
}
|
|
35242
|
+
var LIST_PAGE, MAX_LIST_PAGES, MIGRATION_LABEL, READER_BUDGETS, CUT_OVER_BUDGETS;
|
|
34750
35243
|
var init_remote = __esm({
|
|
34751
35244
|
"src/knowledge/remote.ts"() {
|
|
34752
35245
|
"use strict";
|
|
@@ -34759,10 +35252,14 @@ var init_remote = __esm({
|
|
|
34759
35252
|
init_types2();
|
|
34760
35253
|
init_headers();
|
|
34761
35254
|
init_helpers();
|
|
35255
|
+
init_terminal_output();
|
|
35256
|
+
init_tokens();
|
|
35257
|
+
init_rekor_toolset();
|
|
34762
35258
|
LIST_PAGE = 1e3;
|
|
34763
35259
|
MAX_LIST_PAGES = 1e3;
|
|
34764
35260
|
MIGRATION_LABEL = "wayai knowledge migrate";
|
|
34765
35261
|
READER_BUDGETS = { setup: "/api/setup/organization-resources", sign: "/api/files/sign" };
|
|
35262
|
+
CUT_OVER_BUDGETS = { setup: "/api/setup/agents", automations: "/api/automations" };
|
|
34766
35263
|
}
|
|
34767
35264
|
});
|
|
34768
35265
|
|
|
@@ -34797,6 +35294,520 @@ var init_refresh_preview = __esm({
|
|
|
34797
35294
|
}
|
|
34798
35295
|
});
|
|
34799
35296
|
|
|
35297
|
+
// ../../packages/core/dist/catalog/index.js
|
|
35298
|
+
function getConnectors(filter) {
|
|
35299
|
+
if (!filter?.connector_type && !filter?.service_name) return CONNECTORS;
|
|
35300
|
+
return CONNECTORS.filter(
|
|
35301
|
+
(c) => (!filter.connector_type || c.connector_type === filter.connector_type) && (!filter.service_name || c.service_name === filter.service_name)
|
|
35302
|
+
);
|
|
35303
|
+
}
|
|
35304
|
+
function getConnectorById(id) {
|
|
35305
|
+
return connectorById.get(id) ?? null;
|
|
35306
|
+
}
|
|
35307
|
+
function isRekorToolsetConnector(connector) {
|
|
35308
|
+
return connector?.service_name === REKOR_TOOLSET_SERVICE_NAME;
|
|
35309
|
+
}
|
|
35310
|
+
function isRekorToolsetConnectorId(connectorId) {
|
|
35311
|
+
return typeof connectorId === "string" && isRekorToolsetConnector(connectorById.get(connectorId));
|
|
35312
|
+
}
|
|
35313
|
+
var COUNTER_KEYS, STT_PRICING, CONTAINER_PRICING, connectorById, nativeToolById;
|
|
35314
|
+
var init_catalog = __esm({
|
|
35315
|
+
"../../packages/core/dist/catalog/index.js"() {
|
|
35316
|
+
"use strict";
|
|
35317
|
+
init_chunk_4MXPUC6I();
|
|
35318
|
+
init_chunk_NRJINQVD();
|
|
35319
|
+
init_chunk_CWUV6NL3();
|
|
35320
|
+
init_chunk_MIWZOSPI();
|
|
35321
|
+
init_chunk_DHPUPI4Y();
|
|
35322
|
+
COUNTER_KEYS = Object.keys({
|
|
35323
|
+
input_tokens: true,
|
|
35324
|
+
output_tokens: true,
|
|
35325
|
+
cache_read_input_tokens: true,
|
|
35326
|
+
cache_creation_input_tokens: true,
|
|
35327
|
+
cache_creation_1h_input_tokens: true
|
|
35328
|
+
});
|
|
35329
|
+
STT_PRICING = {
|
|
35330
|
+
"Openai/whisper-1": { per_second: 6e-3 / 60 },
|
|
35331
|
+
"Openai/gpt-4o-mini-transcribe": { per_second: 3e-3 / 60 },
|
|
35332
|
+
"Groq/whisper-large-v3-turbo": { per_second: 0.04 / 3600 },
|
|
35333
|
+
"ElevenLabs/scribe_v2": { per_second: 0.22 / 3600 }
|
|
35334
|
+
};
|
|
35335
|
+
CONTAINER_PRICING = {
|
|
35336
|
+
anthropic_per_request_usd: 0.05 * 10 / 3600,
|
|
35337
|
+
// $0.05/hr × ~10s/request ≈ $0.000139
|
|
35338
|
+
openai_per_session_usd: 0.03
|
|
35339
|
+
// 1GB tier, 20-min session
|
|
35340
|
+
};
|
|
35341
|
+
connectorById = new Map(CONNECTORS.map((c) => [c.connector_id, c]));
|
|
35342
|
+
nativeToolById = new Map(NATIVE_TOOLS.map((t) => [t.tool_native_id, t]));
|
|
35343
|
+
}
|
|
35344
|
+
});
|
|
35345
|
+
|
|
35346
|
+
// src/knowledge/cut-over.ts
|
|
35347
|
+
import { createHash as createHash6 } from "crypto";
|
|
35348
|
+
import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
|
|
35349
|
+
function toolsetSlug(productionHubId, fileTypes) {
|
|
35350
|
+
const hash = createHash6("sha256").update([productionHubId, ...fileTypes].join("\n")).digest("hex").slice(0, 12);
|
|
35351
|
+
return `${CUT_OVER_TOOLSET_PREFIX}${hash}`;
|
|
35352
|
+
}
|
|
35353
|
+
function toolsetEntry(fileType) {
|
|
35354
|
+
const base = toolBase(fileType);
|
|
35355
|
+
return { file_type: fileType, operations: [...FILE_OPERATIONS], ...base === fileType ? {} : { name: base } };
|
|
35356
|
+
}
|
|
35357
|
+
function toolsetToolName(op, fileType) {
|
|
35358
|
+
return toolsetFileToolName(toolsetEntry(fileType), op);
|
|
35359
|
+
}
|
|
35360
|
+
function rewriteCitations(text, fileTypeBySlug) {
|
|
35361
|
+
return text.replace(CITATION_RE, (whole, slash, slug) => {
|
|
35362
|
+
const fileType = fileTypeBySlug.get(slug.toLowerCase());
|
|
35363
|
+
return fileType ? `${slash}${DATA_NAMESPACE}/${fileType}` : whole;
|
|
35364
|
+
});
|
|
35365
|
+
}
|
|
35366
|
+
function knowledgePlaceholders(template, losing) {
|
|
35367
|
+
if (losing.length === 0 || !template.includes("{{")) return [];
|
|
35368
|
+
const scan = scanTemplateResources(template);
|
|
35369
|
+
const kinds = scanTemplateResources(template.replace(/\{\{(\s*)files(\s*\()/g, "{{$1resources$2")).legacy_kinds;
|
|
35370
|
+
const uses = [];
|
|
35371
|
+
if (kinds === "all" || kinds === "kb") uses.push("a {{files()}} catalog that lists knowledge");
|
|
35372
|
+
const names = new Set(losing.map((r) => r.name));
|
|
35373
|
+
for (const name of scan.resource_content_names) if (names.has(name)) uses.push(`{{resource_content(${name})}}`);
|
|
35374
|
+
const slugs = new Set(losing.map((r) => r.slug));
|
|
35375
|
+
for (const path42 of scan.file_content_paths) {
|
|
35376
|
+
const [namespace, slug] = cleanRelativePath(path42).split("/");
|
|
35377
|
+
if (namespace?.toLowerCase() === RESOURCE_NAMESPACE && slug && slugs.has(slug.toLowerCase())) {
|
|
35378
|
+
uses.push(`{{file_content(${path42})}}`);
|
|
35379
|
+
}
|
|
35380
|
+
}
|
|
35381
|
+
return uses;
|
|
35382
|
+
}
|
|
35383
|
+
function sameToolset(remote, spec) {
|
|
35384
|
+
if (!remote) return false;
|
|
35385
|
+
const files = (entries) => [...entries ?? []].map((e) => ({ file_type: e.file_type, operations: [...e.operations].sort(), name: e.name ?? null, path_prefix: e.path_prefix || null })).sort((a, b) => a.file_type.localeCompare(b.file_type));
|
|
35386
|
+
return remote.name === spec.name && (remote.description ?? "") === spec.description && (remote.actions ?? []).length === 0 && (remote.relationships ?? []).length === 0 && !remote.batch && !remote.sql_query && isDeepStrictEqual4(files(remote.files), files(spec.files));
|
|
35387
|
+
}
|
|
35388
|
+
function toolsetConnectorId() {
|
|
35389
|
+
const connector = getConnectors().find((c) => isRekorToolsetConnector(c));
|
|
35390
|
+
if (!connector) throw new Error("The Base Toolset connector is missing from the catalog");
|
|
35391
|
+
return connector.connector_id;
|
|
35392
|
+
}
|
|
35393
|
+
function cutOverToolsetOf(connection) {
|
|
35394
|
+
const toolset = connection.settings?.[TOOLSET_SLUG_SETTING];
|
|
35395
|
+
return isRekorToolsetConnectorId(connection.connector_id) && typeof toolset === "string" && CUT_OVER_TOOLSET_RE.test(toolset) ? toolset : null;
|
|
35396
|
+
}
|
|
35397
|
+
function wantedConnectionTools(fileTypes) {
|
|
35398
|
+
return fileTypes.flatMap((ft) => FILE_OPERATIONS.map((op) => toolsetToolName(op, ft)));
|
|
35399
|
+
}
|
|
35400
|
+
function toolWork(tools, wanted, connectionId) {
|
|
35401
|
+
const native = [];
|
|
35402
|
+
const unavailable = [];
|
|
35403
|
+
for (const name of MOUNT_TOOLS) {
|
|
35404
|
+
const row = tools.native.find((t) => t.tool_name === name);
|
|
35405
|
+
if (!row) unavailable.push(name);
|
|
35406
|
+
else if (row.available_action !== "Disable") native.push(row);
|
|
35407
|
+
}
|
|
35408
|
+
const connection = [];
|
|
35409
|
+
const uncatalogued = [];
|
|
35410
|
+
for (const name of wanted) {
|
|
35411
|
+
const row = connectionId ? tools.connection.find((t) => t.connection_id === connectionId && t.tool_name === name) : void 0;
|
|
35412
|
+
if (!row) uncatalogued.push(name);
|
|
35413
|
+
else if (row.available_action !== "Disable") connection.push(row);
|
|
35414
|
+
}
|
|
35415
|
+
return { native, connection, uncatalogued, unavailable };
|
|
35416
|
+
}
|
|
35417
|
+
function describeToolWork(work) {
|
|
35418
|
+
return [
|
|
35419
|
+
...work.native.map((t) => `${t.available_action === "Enable" ? "enable" : "add"} ${t.tool_name}`),
|
|
35420
|
+
...work.connection.map((t) => `${t.available_action === "Enable" ? "enable" : "add"} ${t.tool_name}`),
|
|
35421
|
+
...work.uncatalogued.map((name) => `add ${name}`)
|
|
35422
|
+
];
|
|
35423
|
+
}
|
|
35424
|
+
async function cutOverHub(hub, kb, opts, io) {
|
|
35425
|
+
const { production, preview } = await resolveBases(kb, opts.base, opts.orgId);
|
|
35426
|
+
const stops = [];
|
|
35427
|
+
const hubs = await hub.listHubs();
|
|
35428
|
+
const previewHub = hubs.find((h) => h.hub_id === opts.hubId);
|
|
35429
|
+
if (!previewHub) throw expected(`Hub ${safe2(opts.hubId)} not found in this organization, or you cannot read it.`);
|
|
35430
|
+
if (previewHub.hub_environment !== "preview") {
|
|
35431
|
+
throw expected(`Hub ${safe2(opts.hubId)} is a production hub. A hub is cut over on its preview; publishing carries it to production.`);
|
|
35432
|
+
}
|
|
35433
|
+
const productionHub2 = previewHub.production_hub_id ? hubs.find((h) => h.hub_id === previewHub.production_hub_id) : void 0;
|
|
35434
|
+
if (!productionHub2) {
|
|
35435
|
+
throw expected(`Hub ${safe2(opts.hubId)} has not been published, and its knowledge moved from its production hub. Publish it, then migrate its knowledge first.`);
|
|
35436
|
+
}
|
|
35437
|
+
const productionHubId = productionHub2.hub_id;
|
|
35438
|
+
const fileTypes = await kb.listFileTypes(production);
|
|
35439
|
+
const fileTypeBySource = /* @__PURE__ */ new Map();
|
|
35440
|
+
for (const ft of fileTypes) {
|
|
35441
|
+
const source = provenanceOf(ft.metadata_schema);
|
|
35442
|
+
if (source) fileTypeBySource.set(source, ft.id);
|
|
35443
|
+
}
|
|
35444
|
+
const resources = await hub.listResources(opts.hubId);
|
|
35445
|
+
const ownKnowledge = (rows) => rows.filter((r) => r.resource_type === "knowledge" && !r.org_resource_id);
|
|
35446
|
+
const productionOwn = ownKnowledge(await hub.listResources(productionHubId));
|
|
35447
|
+
const previewOwn = ownKnowledge(resources);
|
|
35448
|
+
const diff = await hub.hubDiff(opts.hubId);
|
|
35449
|
+
const marked = new Set(previewOwn.filter((r) => r.moved_file_type).map((r) => r.resource_name));
|
|
35450
|
+
const knowledgeNames = new Set([...previewOwn, ...productionOwn].map((r) => r.resource_name).filter((name) => !marked.has(name)));
|
|
35451
|
+
const changed = [
|
|
35452
|
+
...diff.resources.filter((e) => knowledgeNames.has(e.name)).map((e) => `resource "${e.name}" (${e.status})`),
|
|
35453
|
+
...(diff.resource_folders ?? []).filter((e) => e.type && knowledgeNames.has(e.type)).map((e) => `a folder of "${e.type}"`),
|
|
35454
|
+
...(diff.resource_files ?? []).filter((e) => e.type && knowledgeNames.has(e.type)).map((e) => `a file of "${e.type}"`)
|
|
35455
|
+
];
|
|
35456
|
+
if (changed.length > 0) {
|
|
35457
|
+
stops.push(
|
|
35458
|
+
`The preview's knowledge resources differ from production's, which moved (${[...new Set(changed)].join(", ")}): sync or discard those changes first, so its agents are cut over to what they read.`
|
|
35459
|
+
);
|
|
35460
|
+
}
|
|
35461
|
+
const fileTypeOf = /* @__PURE__ */ new Map();
|
|
35462
|
+
for (const resource of resources) {
|
|
35463
|
+
if (resource.resource_type !== "knowledge") continue;
|
|
35464
|
+
if (resource.org_resource_id) {
|
|
35465
|
+
const ft2 = fileTypeBySource.get(orgSourceKey(resource.org_resource_id));
|
|
35466
|
+
if (ft2) fileTypeOf.set(resource.resource_id, ft2);
|
|
35467
|
+
continue;
|
|
35468
|
+
}
|
|
35469
|
+
if (resource.moved_file_type) {
|
|
35470
|
+
fileTypeOf.set(resource.resource_id, resource.moved_file_type);
|
|
35471
|
+
continue;
|
|
35472
|
+
}
|
|
35473
|
+
const twins = productionOwn.filter((r) => r.resource_name === resource.resource_name);
|
|
35474
|
+
const previewTwins = previewOwn.filter((r) => r.resource_name === resource.resource_name);
|
|
35475
|
+
if (twins.length > 1 || previewTwins.length > 1) {
|
|
35476
|
+
stops.push(`Two knowledge resources are named "${resource.resource_name}": rename one (in the preview, then sync), so each pairs with its production copy.`);
|
|
35477
|
+
continue;
|
|
35478
|
+
}
|
|
35479
|
+
const ft = twins[0] ? fileTypeBySource.get(hubSourceKey(productionHubId, twins[0].resource_id)) : void 0;
|
|
35480
|
+
if (ft) fileTypeOf.set(resource.resource_id, ft);
|
|
35481
|
+
}
|
|
35482
|
+
const productionHubs = hubs.filter((h) => h.hub_environment === "production");
|
|
35483
|
+
for (const resource of previewOwn) {
|
|
35484
|
+
const ft = fileTypeOf.get(resource.resource_id);
|
|
35485
|
+
if (!ft || resource.moved_file_type) continue;
|
|
35486
|
+
const hubPart = hubPartOf(ft);
|
|
35487
|
+
const holders = productionHubs.filter((h) => slugifySkillName(h.hub_name) === hubPart);
|
|
35488
|
+
if (holders.length > 1) {
|
|
35489
|
+
stops.push(
|
|
35490
|
+
`File type "${ft}" names the hub slug "${hubPart}", which ${holders.length} production hubs share (${holders.map((h) => `"${h.hub_name}"`).join(", ")}): its move can't be recorded until all but one are renamed.`
|
|
35491
|
+
);
|
|
35492
|
+
}
|
|
35493
|
+
}
|
|
35494
|
+
const slugById = buildResourceSlugMap(resources);
|
|
35495
|
+
const fileTypeBySlug = /* @__PURE__ */ new Map();
|
|
35496
|
+
for (const [resourceId, ft] of fileTypeOf) {
|
|
35497
|
+
const slug = slugById.get(resourceId);
|
|
35498
|
+
if (slug) fileTypeBySlug.set(slug, ft);
|
|
35499
|
+
}
|
|
35500
|
+
const byId = new Map(resources.map((r) => [r.resource_id, r]));
|
|
35501
|
+
const connections = await hub.listConnections(opts.hubId);
|
|
35502
|
+
const previewToolsets = /* @__PURE__ */ new Map();
|
|
35503
|
+
const connectionBySlug = /* @__PURE__ */ new Map();
|
|
35504
|
+
for (const connection of connections) {
|
|
35505
|
+
const slug = cutOverToolsetOf(connection);
|
|
35506
|
+
if (!slug) continue;
|
|
35507
|
+
connectionBySlug.set(slug, connection);
|
|
35508
|
+
if (!previewToolsets.has(slug)) previewToolsets.set(slug, await kb.getToolset(preview, slug));
|
|
35509
|
+
}
|
|
35510
|
+
const toolsetTypes = (slug) => (previewToolsets.get(slug)?.files ?? []).map((e) => e.file_type);
|
|
35511
|
+
const slugByConnection = new Map([...connectionBySlug].map(([slug, c]) => [c.connection_id, slug]));
|
|
35512
|
+
const agents = await hub.listAgents(opts.hubId);
|
|
35513
|
+
const plans = [];
|
|
35514
|
+
for (const agent of agents) {
|
|
35515
|
+
const links2 = (await hub.listAgentLinks(opts.hubId, agent.agent_id)).filter((l) => l.resource_type === "knowledge");
|
|
35516
|
+
const enabled = links2.filter((l) => l.enabled);
|
|
35517
|
+
const tools = await hub.listAgentTools(opts.hubId, agent.agent_id);
|
|
35518
|
+
const set = /* @__PURE__ */ new Set();
|
|
35519
|
+
for (const link of enabled) {
|
|
35520
|
+
const ft = fileTypeOf.get(link.resource_id);
|
|
35521
|
+
const resource = byId.get(link.resource_id);
|
|
35522
|
+
if (!ft) {
|
|
35523
|
+
stops.push(
|
|
35524
|
+
`Agent "${agent.agent_name}" reads knowledge resource "${resource?.resource_name ?? link.resource_id}", which has not moved: move it first (\`wayai knowledge migrate --org ${opts.orgId} --base ${opts.base}${resource?.org_resource_id ? "" : ` --hub ${productionHubId}`}\`).`
|
|
35525
|
+
);
|
|
35526
|
+
continue;
|
|
35527
|
+
}
|
|
35528
|
+
set.add(ft);
|
|
35529
|
+
}
|
|
35530
|
+
for (const tool of tools.connection) {
|
|
35531
|
+
const slug = tool.connection_id ? slugByConnection.get(tool.connection_id) : void 0;
|
|
35532
|
+
if (slug && tool.available_action === "Disable") for (const ft of toolsetTypes(slug)) set.add(ft);
|
|
35533
|
+
}
|
|
35534
|
+
const runner = connections.find((c) => c.connection_id === agent.connection_id);
|
|
35535
|
+
if (enabled.length > 0 && runner && getConnectorById(runner.connector_id)?.is_harness === true) {
|
|
35536
|
+
stops.push(
|
|
35537
|
+
`Agent "${agent.agent_name}" runs on a hosted harness, which takes no Base Toolset's tools yet, so it would lose its knowledge: connect it to a toolset through an MCP Server connection, or detach its knowledge links, then run again.`
|
|
35538
|
+
);
|
|
35539
|
+
}
|
|
35540
|
+
const losing = enabled.flatMap((link) => {
|
|
35541
|
+
const resource = byId.get(link.resource_id);
|
|
35542
|
+
const slug = slugById.get(link.resource_id);
|
|
35543
|
+
return resource && slug ? [{ slug, name: resourceDisplayName(resource) }] : [];
|
|
35544
|
+
});
|
|
35545
|
+
for (const [field, template] of [
|
|
35546
|
+
["instructions", agent.instructions],
|
|
35547
|
+
["additional context", agent.additional_context_template]
|
|
35548
|
+
]) {
|
|
35549
|
+
for (const use of knowledgePlaceholders(template ?? "", losing)) {
|
|
35550
|
+
stops.push(
|
|
35551
|
+
`Agent "${agent.agent_name}" uses ${use} in its ${field}, which reads nothing once its knowledge moves (K19): move that text into its instructions or a skill, then run again.`
|
|
35552
|
+
);
|
|
35553
|
+
}
|
|
35554
|
+
}
|
|
35555
|
+
if (set.size > 0 || enabled.length > 0) plans.push({ agent, fileTypes: [...set].sort(), linksToDisable: enabled, tools });
|
|
35556
|
+
}
|
|
35557
|
+
const groups = /* @__PURE__ */ new Map();
|
|
35558
|
+
for (const plan of plans) {
|
|
35559
|
+
if (plan.fileTypes.length === 0) continue;
|
|
35560
|
+
const slug = toolsetSlug(productionHubId, plan.fileTypes);
|
|
35561
|
+
const group = groups.get(slug);
|
|
35562
|
+
if (group) {
|
|
35563
|
+
group.agents.push(plan.agent);
|
|
35564
|
+
plan.group = group;
|
|
35565
|
+
continue;
|
|
35566
|
+
}
|
|
35567
|
+
plan.group = {
|
|
35568
|
+
slug,
|
|
35569
|
+
fileTypes: plan.fileTypes,
|
|
35570
|
+
agents: [plan.agent],
|
|
35571
|
+
connection: connectionBySlug.get(slug),
|
|
35572
|
+
created: !connectionBySlug.has(slug),
|
|
35573
|
+
spec: {
|
|
35574
|
+
id: slug,
|
|
35575
|
+
name: `Knowledge of ${previewHub.hub_name}`.slice(0, 200),
|
|
35576
|
+
description: `Read-only knowledge for agents of hub ${productionHubId}, written by wayai knowledge cut-over: list and get on ${plan.fileTypes.join(", ")}.`,
|
|
35577
|
+
files: plan.fileTypes.map(toolsetEntry)
|
|
35578
|
+
}
|
|
35579
|
+
};
|
|
35580
|
+
groups.set(slug, plan.group);
|
|
35581
|
+
}
|
|
35582
|
+
const plannedTypes = [...new Set([...groups.values()].flatMap((g) => g.fileTypes))].sort();
|
|
35583
|
+
const missing = [];
|
|
35584
|
+
for (const ft of plannedTypes) {
|
|
35585
|
+
const [inProduction, inPreview] = await Promise.all([kb.listFiles(production, ft), filesOrNone(kb, preview, ft)]);
|
|
35586
|
+
const there = new Set(inPreview.map((f) => f.path));
|
|
35587
|
+
for (const file of inProduction) if (!there.has(file.path)) missing.push(`${ft}/${file.path}`);
|
|
35588
|
+
}
|
|
35589
|
+
if (missing.length > 0) {
|
|
35590
|
+
stops.push(
|
|
35591
|
+
`The preview base "${preview}" lacks ${missing.length} file(s) production holds (${missing.slice(0, 5).join(", ")}${missing.length > 5 ? ", \u2026" : ""}), so the preview's agents would read none of them: copy them in with \`${refreshPreviewCommand(opts.orgId, opts.base)}\`, then run again.`
|
|
35592
|
+
);
|
|
35593
|
+
}
|
|
35594
|
+
const toolsetsToWrite = [];
|
|
35595
|
+
const toolsetsToPromote = [];
|
|
35596
|
+
for (const group of groups.values()) {
|
|
35597
|
+
const [inPreview, inProduction] = await Promise.all([
|
|
35598
|
+
previewToolsets.has(group.slug) ? previewToolsets.get(group.slug) : kb.getToolset(preview, group.slug),
|
|
35599
|
+
kb.getToolset(production, group.slug)
|
|
35600
|
+
]);
|
|
35601
|
+
if (!sameToolset(inPreview, group.spec)) toolsetsToWrite.push(group.spec);
|
|
35602
|
+
if (!sameToolset(inProduction, group.spec)) toolsetsToPromote.push(group.spec);
|
|
35603
|
+
}
|
|
35604
|
+
const connectionsToCreate = [...groups.values()].filter((g) => g.created);
|
|
35605
|
+
const toolLines = [];
|
|
35606
|
+
let toolWrites = 0;
|
|
35607
|
+
for (const plan of plans) {
|
|
35608
|
+
const group = plan.group;
|
|
35609
|
+
if (!group) continue;
|
|
35610
|
+
const work = toolWork(plan.tools, wantedConnectionTools(group.fileTypes), group.connection?.connection_id);
|
|
35611
|
+
for (const name of work.unavailable) stops.push(`Agent "${plan.agent.agent_name}" can't be given ${name}: the hub offers it no such tool.`);
|
|
35612
|
+
const lines = describeToolWork(work);
|
|
35613
|
+
toolWrites += lines.length;
|
|
35614
|
+
if (lines.length > 0) toolLines.push(` ${safe2(plan.agent.agent_name)}: ${lines.map(safe2).join(", ")} (${group.slug})`);
|
|
35615
|
+
}
|
|
35616
|
+
const agentRewrites = [];
|
|
35617
|
+
for (const agent of agents) {
|
|
35618
|
+
const patch = {};
|
|
35619
|
+
const instructions = rewriteCitations(agent.instructions ?? "", fileTypeBySlug);
|
|
35620
|
+
if (instructions !== (agent.instructions ?? "")) patch.instructions = instructions;
|
|
35621
|
+
const context = rewriteCitations(agent.additional_context_template ?? "", fileTypeBySlug);
|
|
35622
|
+
if (context !== (agent.additional_context_template ?? "")) patch.additional_context_template = context;
|
|
35623
|
+
if (Object.keys(patch).length > 0) agentRewrites.push({ agent, patch });
|
|
35624
|
+
}
|
|
35625
|
+
const automationRewrites = [];
|
|
35626
|
+
for (const automation of await hub.listAutomations(opts.hubId)) {
|
|
35627
|
+
const text = automation.action.type === "run_agent" ? automation.action.instructions : null;
|
|
35628
|
+
if (!text) continue;
|
|
35629
|
+
const rewritten = rewriteCitations(text, fileTypeBySlug);
|
|
35630
|
+
if (rewritten !== text) automationRewrites.push({ automation, action: { ...automation.action, instructions: rewritten } });
|
|
35631
|
+
}
|
|
35632
|
+
const moves = [];
|
|
35633
|
+
for (const resource of previewOwn) {
|
|
35634
|
+
const ft = fileTypeOf.get(resource.resource_id);
|
|
35635
|
+
if (!ft || resource.moved_file_type) continue;
|
|
35636
|
+
moves.push({
|
|
35637
|
+
body: { scope: "hub", hub_id: opts.hubId, resource_id: resource.resource_id, file_type: ft, base_id: production },
|
|
35638
|
+
label: `hub resource "${resource.resource_name}" \u2192 ${ft}`
|
|
35639
|
+
});
|
|
35640
|
+
}
|
|
35641
|
+
const orgRecorded = /* @__PURE__ */ new Set();
|
|
35642
|
+
for (const plan of plans) {
|
|
35643
|
+
for (const link of plan.linksToDisable) {
|
|
35644
|
+
const resource = byId.get(link.resource_id);
|
|
35645
|
+
const ft = fileTypeOf.get(link.resource_id);
|
|
35646
|
+
if (!resource?.org_resource_id || !ft || orgRecorded.has(resource.org_resource_id)) continue;
|
|
35647
|
+
orgRecorded.add(resource.org_resource_id);
|
|
35648
|
+
moves.push({
|
|
35649
|
+
body: { scope: "organization", organization_id: opts.orgId, org_resource_id: resource.org_resource_id, file_type: ft, base_id: production },
|
|
35650
|
+
label: `organization resource "${resource.resource_name}" \u2192 ${ft}`
|
|
35651
|
+
});
|
|
35652
|
+
}
|
|
35653
|
+
}
|
|
35654
|
+
const links = plans.flatMap((plan) => plan.linksToDisable.map((link) => ({ plan, link })));
|
|
35655
|
+
const result = {
|
|
35656
|
+
toolsets: [...groups.values()].map((g) => ({ slug: g.slug, fileTypes: g.fileTypes, agents: g.agents.map((a) => a.agent_name) })),
|
|
35657
|
+
toolsetsWritten: toolsetsToWrite.map((s) => s.id),
|
|
35658
|
+
toolsetsPromoted: toolsetsToPromote.map((s) => s.id),
|
|
35659
|
+
connectionsCreated: connectionsToCreate.map((g) => g.slug),
|
|
35660
|
+
toolsAssigned: toolLines,
|
|
35661
|
+
agentsRewritten: agentRewrites.map((r) => r.agent.agent_name),
|
|
35662
|
+
automationsRewritten: automationRewrites.map((r) => r.automation.name),
|
|
35663
|
+
movesRecorded: moves.map((m) => m.label),
|
|
35664
|
+
linksDisabled: links.map(({ plan, link }) => `${plan.agent.agent_name}: ${byId.get(link.resource_id)?.resource_name ?? link.resource_id}`),
|
|
35665
|
+
written: false
|
|
35666
|
+
};
|
|
35667
|
+
io.log(`Cut-over of hub "${safe2(previewHub.hub_name)}" (${opts.hubId}) to base "${safe2(production)}" (toolsets written in "${safe2(preview)}")`);
|
|
35668
|
+
io.log("\nToolsets (read-only: list and get):");
|
|
35669
|
+
if (groups.size === 0) io.log(" (none: no agent reads moved knowledge)");
|
|
35670
|
+
for (const group of groups.values()) {
|
|
35671
|
+
const mark = toolsetsToPromote.includes(group.spec) || toolsetsToWrite.includes(group.spec) ? "+" : "=";
|
|
35672
|
+
io.log(` ${mark} ${group.slug}: ${group.fileTypes.map(safe2).join(", ")} \u2014 ${group.agents.map((a) => safe2(a.agent_name)).join(", ")}`);
|
|
35673
|
+
}
|
|
35674
|
+
io.log("\nConnections:");
|
|
35675
|
+
for (const group of groups.values()) {
|
|
35676
|
+
io.log(` ${group.connection ? "=" : "+"} Base Toolset "${group.slug}"${group.connection ? "" : ", with a new token bound to it on the preview base"}`);
|
|
35677
|
+
}
|
|
35678
|
+
io.log("\nAgent tools:");
|
|
35679
|
+
if (toolLines.length === 0) io.log(" (nothing to assign)");
|
|
35680
|
+
for (const line of toolLines) io.log(line);
|
|
35681
|
+
io.log("\nPaths rewritten to data/ (K13):");
|
|
35682
|
+
if (agentRewrites.length + automationRewrites.length === 0) io.log(" (none)");
|
|
35683
|
+
for (const { agent, patch } of agentRewrites) io.log(` agent "${safe2(agent.agent_name)}": ${Object.keys(patch).join(", ")}`);
|
|
35684
|
+
for (const { automation } of automationRewrites) io.log(` automation "${safe2(automation.name)}": instructions`);
|
|
35685
|
+
io.log("\nMoves recorded:");
|
|
35686
|
+
if (moves.length === 0) io.log(" (none)");
|
|
35687
|
+
for (const move of moves) io.log(` + ${safe2(move.label)}`);
|
|
35688
|
+
io.log("\nKnowledge links disabled:");
|
|
35689
|
+
if (links.length === 0) io.log(" (none)");
|
|
35690
|
+
for (const line of result.linksDisabled) io.log(` - ${safe2(line)}`);
|
|
35691
|
+
if (stops.length > 0) {
|
|
35692
|
+
io.log("\nStopped:");
|
|
35693
|
+
for (const stop of stops) io.log(` ${safe2(stop)}`);
|
|
35694
|
+
throw expected(`The cut-over stops on ${stops.length} reason(s) above; nothing was written.`);
|
|
35695
|
+
}
|
|
35696
|
+
const writes = toolsetsToWrite.length + toolsetsToPromote.length + connectionsToCreate.length + toolWrites + agentRewrites.length + automationRewrites.length + moves.length + links.length;
|
|
35697
|
+
const printProduction = () => printProductionSteps(io, opts, production, productionHubId, [...groups.values()]);
|
|
35698
|
+
if (opts.dryRun) {
|
|
35699
|
+
io.log(`
|
|
35700
|
+
Dry run: nothing written (${writes === 0 ? "nothing to write" : `${writes} write(s) planned`}).`);
|
|
35701
|
+
printProduction();
|
|
35702
|
+
return result;
|
|
35703
|
+
}
|
|
35704
|
+
if (writes === 0) {
|
|
35705
|
+
io.log("\nNothing to write: this hub is cut over.");
|
|
35706
|
+
printProduction();
|
|
35707
|
+
return result;
|
|
35708
|
+
}
|
|
35709
|
+
if (!opts.yes && !await io.confirm(`Make these ${writes} change(s) to the preview hub and its knowledge base?`)) {
|
|
35710
|
+
io.log("Cancelled.");
|
|
35711
|
+
return result;
|
|
35712
|
+
}
|
|
35713
|
+
for (const move of moves) await hub.recordMove(move.body);
|
|
35714
|
+
for (const spec of toolsetsToWrite) await kb.putToolset(preview, spec);
|
|
35715
|
+
if (toolsetsToPromote.length > 0) {
|
|
35716
|
+
const slugs = toolsetsToPromote.map((s) => s.id);
|
|
35717
|
+
const problems2 = promotionProblems(await kb.promoteToolsets(production, preview, slugs, true), new Set(slugs), "toolsets");
|
|
35718
|
+
if (problems2.length > 0) {
|
|
35719
|
+
throw expected(
|
|
35720
|
+
`The promotion into "${safe2(production)}" would not apply as planned (${problems2.map(safe2).join("; ")}). The toolsets are written in "${safe2(preview)}"; nothing reached production, and the hub's agents are unchanged.`
|
|
35721
|
+
);
|
|
35722
|
+
}
|
|
35723
|
+
await kb.promoteToolsets(production, preview, slugs, false);
|
|
35724
|
+
}
|
|
35725
|
+
if (connectionsToCreate.length > 0) {
|
|
35726
|
+
const connectorId = toolsetConnectorId();
|
|
35727
|
+
for (const group of connectionsToCreate) {
|
|
35728
|
+
const token = await kb.mintToolsetToken(preview, group.slug, `${group.slug} (hub ${opts.hubId})`);
|
|
35729
|
+
const after = await hub.addToolsetConnection(opts.hubId, { connectorId, name: group.slug, toolset: group.slug, token });
|
|
35730
|
+
group.connection = after.find((c) => cutOverToolsetOf(c) === group.slug);
|
|
35731
|
+
if (!group.connection) throw new Error(`The Base Toolset connection "${group.slug}" was not found after it was created.`);
|
|
35732
|
+
}
|
|
35733
|
+
}
|
|
35734
|
+
const synced2 = /* @__PURE__ */ new Set();
|
|
35735
|
+
for (const plan of plans) {
|
|
35736
|
+
const group = plan.group;
|
|
35737
|
+
if (!group?.connection) continue;
|
|
35738
|
+
const connectionId = group.connection.connection_id;
|
|
35739
|
+
const wanted = wantedConnectionTools(group.fileTypes);
|
|
35740
|
+
const stale = group.created || synced2.has(connectionId);
|
|
35741
|
+
let tools = stale ? await hub.listAgentTools(opts.hubId, plan.agent.agent_id) : plan.tools;
|
|
35742
|
+
let work = toolWork(tools, wanted, connectionId);
|
|
35743
|
+
if (work.uncatalogued.length > 0 && !synced2.has(connectionId)) {
|
|
35744
|
+
await hub.syncConnection(opts.hubId, connectionId);
|
|
35745
|
+
synced2.add(connectionId);
|
|
35746
|
+
tools = await hub.listAgentTools(opts.hubId, plan.agent.agent_id);
|
|
35747
|
+
work = toolWork(tools, wanted, connectionId);
|
|
35748
|
+
}
|
|
35749
|
+
if (work.uncatalogued.length > 0) {
|
|
35750
|
+
throw new Error(
|
|
35751
|
+
`Connection "${group.slug}" catalogs no ${safe2(work.uncatalogued.join(", "))} after a sync, so agent "${safe2(plan.agent.agent_name)}" can't be given them.`
|
|
35752
|
+
);
|
|
35753
|
+
}
|
|
35754
|
+
for (const tool of [...work.native, ...work.connection]) {
|
|
35755
|
+
if (tool.available_action === "Enable" && tool.tool_id) await hub.enableTool(opts.hubId, plan.agent.agent_id, tool.tool_id);
|
|
35756
|
+
else if (tool.tool_native_id) await hub.addNativeTool(opts.hubId, plan.agent.agent_id, tool.tool_native_id);
|
|
35757
|
+
else if (tool.mcp_tool_id) await hub.addConnectionTool(opts.hubId, plan.agent.agent_id, tool.mcp_tool_id);
|
|
35758
|
+
}
|
|
35759
|
+
}
|
|
35760
|
+
for (const { agent, patch } of agentRewrites) await hub.updateAgentText(opts.hubId, agent.agent_id, patch);
|
|
35761
|
+
for (const { automation, action } of automationRewrites) await hub.updateAutomationAction(opts.hubId, automation.automation_id, action);
|
|
35762
|
+
for (const { plan, link } of links) await hub.disableLink(opts.hubId, plan.agent.agent_id, link.resource_id);
|
|
35763
|
+
io.log(`
|
|
35764
|
+
Done: the preview hub's agents read their knowledge from "${safe2(preview)}" through ${groups.size} toolset(s).`);
|
|
35765
|
+
printProduction();
|
|
35766
|
+
return { ...result, written: true };
|
|
35767
|
+
}
|
|
35768
|
+
async function filesOrNone(kb, base, fileType) {
|
|
35769
|
+
try {
|
|
35770
|
+
return await kb.listFiles(base, fileType);
|
|
35771
|
+
} catch (err) {
|
|
35772
|
+
if (err instanceof ApiError && err.status === 404) return [];
|
|
35773
|
+
throw err;
|
|
35774
|
+
}
|
|
35775
|
+
}
|
|
35776
|
+
function printProductionSteps(io, opts, production, productionHubId, groups) {
|
|
35777
|
+
if (groups.length === 0) return;
|
|
35778
|
+
io.log("\nProduction (not run by this command), once the preview passes its evals:");
|
|
35779
|
+
io.log(` 1. Publish the preview: wayai publish --hub ${opts.hubId}`);
|
|
35780
|
+
io.log(" 2. For each toolset, mint a token bound to it on the production base, and save it on production's connection:");
|
|
35781
|
+
for (const group of groups) {
|
|
35782
|
+
io.log(
|
|
35783
|
+
` wayai bases tokens create-for-toolset ${group.slug} --base ${safe2(production)} --token-only | wayai set-connection-credential --hub ${productionHubId} --connection "${group.slug}" --field access_token --stdin`
|
|
35784
|
+
);
|
|
35785
|
+
}
|
|
35786
|
+
}
|
|
35787
|
+
var CUT_OVER_TOOLSET_PREFIX, CUT_OVER_TOOLSET_RE, FILE_OPERATIONS, MOUNT_TOOLS, DATA_NAMESPACE, safe2, CITATION_RE;
|
|
35788
|
+
var init_cut_over = __esm({
|
|
35789
|
+
"src/knowledge/cut-over.ts"() {
|
|
35790
|
+
"use strict";
|
|
35791
|
+
init_dist();
|
|
35792
|
+
init_catalog();
|
|
35793
|
+
init_rekor_toolset();
|
|
35794
|
+
init_resource_paths();
|
|
35795
|
+
init_expected();
|
|
35796
|
+
init_terminal_output();
|
|
35797
|
+
init_api_client();
|
|
35798
|
+
init_migrate2();
|
|
35799
|
+
init_plan();
|
|
35800
|
+
init_source();
|
|
35801
|
+
CUT_OVER_TOOLSET_PREFIX = "knowledge-";
|
|
35802
|
+
CUT_OVER_TOOLSET_RE = /^knowledge-[0-9a-f]{12}$/;
|
|
35803
|
+
FILE_OPERATIONS = ["list", "get"];
|
|
35804
|
+
MOUNT_TOOLS = ["list_files", "read_file"];
|
|
35805
|
+
DATA_NAMESPACE = "data";
|
|
35806
|
+
safe2 = (text) => sanitizeTerminalText(text);
|
|
35807
|
+
CITATION_RE = /(?<![\w./-])(\/?)resources\/([a-z0-9]+(?:-[a-z0-9]+)*)(?![a-z0-9_]|-[a-z0-9]|\.\w)/gi;
|
|
35808
|
+
}
|
|
35809
|
+
});
|
|
35810
|
+
|
|
34800
35811
|
// src/commands/knowledge.ts
|
|
34801
35812
|
var knowledge_exports = {};
|
|
34802
35813
|
__export(knowledge_exports, {
|
|
@@ -34818,7 +35829,7 @@ function readArgs(args2) {
|
|
|
34818
35829
|
function parseKnowledgeArgs(args2) {
|
|
34819
35830
|
const { values, positionals } = readArgs(args2);
|
|
34820
35831
|
const [verb, ...extra] = positionals;
|
|
34821
|
-
if (verb !== "migrate" && verb !== "refresh-preview") {
|
|
35832
|
+
if (verb !== "migrate" && verb !== "refresh-preview" && verb !== "cut-over") {
|
|
34822
35833
|
throw usageError3(verb === void 0 ? "No subcommand given." : `Unknown subcommand ${JSON.stringify(verb)}.`);
|
|
34823
35834
|
}
|
|
34824
35835
|
if (extra.length > 0) throw usageError3(`Unexpected argument ${JSON.stringify(extra[0])}.`);
|
|
@@ -34826,13 +35837,17 @@ function parseKnowledgeArgs(args2) {
|
|
|
34826
35837
|
if (!UUID_RE3.test(values.org)) throw usageError3(`Invalid --org ${JSON.stringify(values.org)}: expected an organization id (a UUID).`);
|
|
34827
35838
|
if (!values.base) throw usageError3("--base <knowledge base> is required.");
|
|
34828
35839
|
if (verb === "refresh-preview") {
|
|
34829
|
-
if (values.hub !== void 0) throw usageError3("--hub is migrate's: a refresh copies the whole knowledge base.");
|
|
34830
|
-
if (values["dry-run"] !== void 0) throw usageError3("--dry-run is migrate's: a refresh has none.");
|
|
35840
|
+
if (values.hub !== void 0) throw usageError3("--hub is migrate's and cut-over's: a refresh copies the whole knowledge base.");
|
|
35841
|
+
if (values["dry-run"] !== void 0) throw usageError3("--dry-run is migrate's and cut-over's: a refresh has none.");
|
|
34831
35842
|
return { verb, orgId: values.org, base: values.base, yes: values.yes === true };
|
|
34832
35843
|
}
|
|
34833
35844
|
if (values.hub !== void 0 && !UUID_RE3.test(values.hub)) {
|
|
34834
35845
|
throw usageError3(`Invalid --hub ${JSON.stringify(values.hub)}: expected a hub id (a UUID).`);
|
|
34835
35846
|
}
|
|
35847
|
+
if (verb === "cut-over") {
|
|
35848
|
+
if (values.hub === void 0) throw usageError3("--hub <preview hub_id> is required: a cut-over is one preview hub's.");
|
|
35849
|
+
return { verb, orgId: values.org, base: values.base, hubId: values.hub, dryRun: values["dry-run"] === true, yes: values.yes === true };
|
|
35850
|
+
}
|
|
34836
35851
|
return {
|
|
34837
35852
|
verb,
|
|
34838
35853
|
orgId: values.org,
|
|
@@ -34860,10 +35875,12 @@ async function knowledgeCommand(args2) {
|
|
|
34860
35875
|
const { config, accessToken } = await requireAuth();
|
|
34861
35876
|
const api = new ApiClient({ apiUrl: config.api_url, accessToken, onUnauthorized: () => getAccessToken(config) });
|
|
34862
35877
|
const data = await createDataClient(options.orgId, { refreshLogin: true });
|
|
34863
|
-
|
|
34864
|
-
|
|
34865
|
-
|
|
34866
|
-
|
|
35878
|
+
const io = { log: (line) => console.log(line), confirm };
|
|
35879
|
+
if (options.verb === "cut-over") {
|
|
35880
|
+
await cutOverHub(hubSetup(api, options.orgId), knowledgeBase(data), options, io);
|
|
35881
|
+
return;
|
|
35882
|
+
}
|
|
35883
|
+
await migrateKnowledge(knowledgeReader(api, options.orgId), knowledgeBase(data), options, io);
|
|
34867
35884
|
}
|
|
34868
35885
|
var USAGE4, OPTIONS;
|
|
34869
35886
|
var init_knowledge = __esm({
|
|
@@ -34878,12 +35895,14 @@ var init_knowledge = __esm({
|
|
|
34878
35895
|
init_migrate2();
|
|
34879
35896
|
init_remote();
|
|
34880
35897
|
init_refresh_preview();
|
|
35898
|
+
init_cut_over();
|
|
34881
35899
|
USAGE4 = `
|
|
34882
35900
|
wayai knowledge \u2014 the organization's knowledge base
|
|
34883
35901
|
|
|
34884
35902
|
Usage:
|
|
34885
35903
|
wayai knowledge migrate --org <org_id> --base <knowledge base> [--hub <hub_id>] [--dry-run] [-y]
|
|
34886
35904
|
wayai knowledge refresh-preview --org <org_id> --base <knowledge base> [-y]
|
|
35905
|
+
wayai knowledge cut-over --org <org_id> --base <knowledge base> --hub <preview hub_id> [--dry-run] [-y]
|
|
34887
35906
|
|
|
34888
35907
|
migrate: move knowledge resources into the organization's knowledge base.
|
|
34889
35908
|
|
|
@@ -34905,6 +35924,21 @@ refresh-preview: make the knowledge base's preview hold its production base's fi
|
|
|
34905
35924
|
|
|
34906
35925
|
--base The production knowledge base, or its preview.
|
|
34907
35926
|
-y, --yes Skip the question before copying.
|
|
35927
|
+
|
|
35928
|
+
cut-over: switch a preview hub's agents from their knowledge resources to the knowledge base, once
|
|
35929
|
+
its knowledge has moved. Each distinct set of knowledge its agents read gets one read-only
|
|
35930
|
+
toolset on the knowledge base, reached through a Base Toolset connection; each agent is given
|
|
35931
|
+
list_files, read_file and its toolset's list_ and get_ tools, its resources/<slug>/ paths become
|
|
35932
|
+
data/<file type>/, its knowledge links are disabled, and each move is recorded. It changes the
|
|
35933
|
+
preview only, and prints the production steps. The preview base must hold production's files
|
|
35934
|
+
first (refresh-preview): the preview's agents read them there. It stops before writing on a resource placeholder
|
|
35935
|
+
({{files()}}, {{resource_content()}}, {{file_content()}}) that reads knowledge an agent is about
|
|
35936
|
+
to lose: move that text into its instructions or a skill first.
|
|
35937
|
+
|
|
35938
|
+
--hub The preview hub.
|
|
35939
|
+
--base The production knowledge base, or its preview.
|
|
35940
|
+
--dry-run List every change, and every reason it would stop, without writing.
|
|
35941
|
+
-y, --yes Skip the question before writing.
|
|
34908
35942
|
`;
|
|
34909
35943
|
OPTIONS = {
|
|
34910
35944
|
org: { type: "string" },
|
|
@@ -34960,17 +35994,17 @@ async function adminCommand(args2) {
|
|
|
34960
35994
|
process.exit(1);
|
|
34961
35995
|
}
|
|
34962
35996
|
if (group === "archive") {
|
|
34963
|
-
const { positional: positional2, flagArgs: flagArgs2 } =
|
|
35997
|
+
const { positional: positional2, flagArgs: flagArgs2 } = splitArgs2(afterGroup);
|
|
34964
35998
|
await runArchiveRead(positional2, flagArgs2);
|
|
34965
35999
|
return;
|
|
34966
36000
|
}
|
|
34967
36001
|
if (group === "observability") {
|
|
34968
|
-
const { positional: positional2, flagArgs: flagArgs2 } =
|
|
36002
|
+
const { positional: positional2, flagArgs: flagArgs2 } = splitArgs2(afterGroup);
|
|
34969
36003
|
await runObservabilityRead(positional2, flagArgs2);
|
|
34970
36004
|
return;
|
|
34971
36005
|
}
|
|
34972
36006
|
const [sub, ...rest] = afterGroup;
|
|
34973
|
-
const { positional, flagArgs } =
|
|
36007
|
+
const { positional, flagArgs } = splitArgs2(rest);
|
|
34974
36008
|
if (group === "do") {
|
|
34975
36009
|
if (!sub) {
|
|
34976
36010
|
printHelp2();
|
|
@@ -35258,7 +36292,7 @@ async function adminCommand(args2) {
|
|
|
35258
36292
|
printHelp2();
|
|
35259
36293
|
process.exit(1);
|
|
35260
36294
|
}
|
|
35261
|
-
function
|
|
36295
|
+
function splitArgs2(args2) {
|
|
35262
36296
|
const positional = [];
|
|
35263
36297
|
const flagArgs = [];
|
|
35264
36298
|
for (const a of args2) {
|
|
@@ -37383,9 +38417,9 @@ var init_update = __esm({
|
|
|
37383
38417
|
});
|
|
37384
38418
|
|
|
37385
38419
|
// src/data/commands/actions.ts
|
|
37386
|
-
import { Command } from "commander";
|
|
38420
|
+
import { Command as Command2 } from "commander";
|
|
37387
38421
|
function buildActionsCommand() {
|
|
37388
|
-
const actions = new
|
|
38422
|
+
const actions = new Command2("actions").description(
|
|
37389
38423
|
"Manage Actions \u2014 reusable, named definitions: one record_type + one operation, or a composite of atomic write steps (--config with `steps`)"
|
|
37390
38424
|
);
|
|
37391
38425
|
actions.command("upsert <id>").description(
|
|
@@ -37454,7 +38488,7 @@ var init_actions = __esm({
|
|
|
37454
38488
|
});
|
|
37455
38489
|
|
|
37456
38490
|
// src/data/commands/attachments.ts
|
|
37457
|
-
import { Command as
|
|
38491
|
+
import { Command as Command3 } from "commander";
|
|
37458
38492
|
import { readFileSync as readFileSync19 } from "fs";
|
|
37459
38493
|
function findAttachmentByFilename(attachments, filename) {
|
|
37460
38494
|
return attachments.find((a) => a.key.endsWith(`/${filename}`)) ?? null;
|
|
@@ -37481,7 +38515,7 @@ function uploadPathFrom(uploadUrl) {
|
|
|
37481
38515
|
return uploadUrl;
|
|
37482
38516
|
}
|
|
37483
38517
|
function buildAttachmentsCommand() {
|
|
37484
|
-
const attachments = new
|
|
38518
|
+
const attachments = new Command3("attachments").description("Manage record attachments");
|
|
37485
38519
|
attachments.command("upload <record_type> <id>").description(
|
|
37486
38520
|
"Get a presigned upload URL for a record attachment. With --file, uploads the file content in one step."
|
|
37487
38521
|
).requiredOption("--filename <name>", "File name or path (e.g. docs/guide.md)").option("--content-type <type>", "MIME type", "application/octet-stream").option("--file <path>", "Local file to upload (skips presigned URL output, uploads directly)").action(async function(recordType2, id, opts) {
|
|
@@ -37561,9 +38595,9 @@ var init_attachments = __esm({
|
|
|
37561
38595
|
});
|
|
37562
38596
|
|
|
37563
38597
|
// src/data/commands/batch.ts
|
|
37564
|
-
import { Command as
|
|
38598
|
+
import { Command as Command4 } from "commander";
|
|
37565
38599
|
function buildBasesBatchCommand() {
|
|
37566
|
-
return withBaseOption(new
|
|
38600
|
+
return withBaseOption(new Command4("batch")).description("Execute atomic batch operations (up to 1,000 operations)").requiredOption("--operations <json>", "Operations array (inline JSON or @filename)").action(async function(opts) {
|
|
37567
38601
|
const base = pathSegment(requireBase(this), "--base");
|
|
37568
38602
|
const operations = parseData(opts.operations, "--operations");
|
|
37569
38603
|
const client = await createDataClient();
|
|
@@ -37592,7 +38626,7 @@ import { createReadStream } from "fs";
|
|
|
37592
38626
|
import { access, constants, stat } from "fs/promises";
|
|
37593
38627
|
import { createInterface as createInterface3 } from "readline";
|
|
37594
38628
|
import { randomUUID } from "crypto";
|
|
37595
|
-
import { Command as
|
|
38629
|
+
import { Command as Command5 } from "commander";
|
|
37596
38630
|
function isRetryable(err) {
|
|
37597
38631
|
if (isNetworkError(err)) return true;
|
|
37598
38632
|
if (!(err instanceof ApiError)) return false;
|
|
@@ -37668,7 +38702,7 @@ async function beginSession(state, client, base, recordType2, requestKey) {
|
|
|
37668
38702
|
return res.session;
|
|
37669
38703
|
}
|
|
37670
38704
|
function buildBasesImportCommand() {
|
|
37671
|
-
const importCmd = withBaseOption(new
|
|
38705
|
+
const importCmd = withBaseOption(new Command5("import")).description(
|
|
37672
38706
|
"Bulk historical import: load an NDJSON backfill, list sessions, or undo one"
|
|
37673
38707
|
);
|
|
37674
38708
|
importCmd.command("run <record_type>").description(
|
|
@@ -37895,7 +38929,7 @@ var init_import = __esm({
|
|
|
37895
38929
|
});
|
|
37896
38930
|
|
|
37897
38931
|
// src/data/commands/providers.ts
|
|
37898
|
-
import { Command as
|
|
38932
|
+
import { Command as Command6 } from "commander";
|
|
37899
38933
|
import { writeFileSync as writeFileSync10 } from "fs";
|
|
37900
38934
|
function providerSegment(provider) {
|
|
37901
38935
|
if (!VALID_PROVIDERS.includes(provider)) {
|
|
@@ -37904,7 +38938,7 @@ function providerSegment(provider) {
|
|
|
37904
38938
|
return pathSegment(provider, "provider");
|
|
37905
38939
|
}
|
|
37906
38940
|
function buildBasesProvidersCommand() {
|
|
37907
|
-
const providers = withBaseOption(new
|
|
38941
|
+
const providers = withBaseOption(new Command6("providers")).description(
|
|
37908
38942
|
"Import/export tool definitions between LLM providers and record types"
|
|
37909
38943
|
);
|
|
37910
38944
|
providers.command("import <provider>").description(`Import tool definitions as record types. Providers: ${VALID_PROVIDERS_HELP}`).requiredOption("--tools <json>", "Tool definitions (inline JSON or @filename)").action(async function(provider, opts) {
|
|
@@ -37975,7 +39009,7 @@ var init_providers = __esm({
|
|
|
37975
39009
|
});
|
|
37976
39010
|
|
|
37977
39011
|
// src/data/commands/report.ts
|
|
37978
|
-
import { Command as
|
|
39012
|
+
import { Command as Command7 } from "commander";
|
|
37979
39013
|
import { readFileSync as readFileSync20 } from "fs";
|
|
37980
39014
|
import { dirname as dirname15, join as join36 } from "path";
|
|
37981
39015
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
@@ -38019,7 +39053,7 @@ function reportActionError2(err) {
|
|
|
38019
39053
|
throw err;
|
|
38020
39054
|
}
|
|
38021
39055
|
function buildBasesReportCommand() {
|
|
38022
|
-
const report2 = new
|
|
39056
|
+
const report2 = new Command7("report").description(
|
|
38023
39057
|
"File a report to the Data triage queue and verify the outcome"
|
|
38024
39058
|
);
|
|
38025
39059
|
report2.command("create").description("Submit a report to the Data triage queue (deduplicated)").requiredOption("--title <title>", "Short summary").requiredOption("--description <text>", "What happened").option("--source <source>", "Origin: cli_report (default) | review | security_audit").option("--classification <c>", "Nature: bug (default) | flaky_test | security | enhancement").option(
|
|
@@ -38186,7 +39220,7 @@ var init_report3 = __esm({
|
|
|
38186
39220
|
});
|
|
38187
39221
|
|
|
38188
39222
|
// src/data/commands/credentials.ts
|
|
38189
|
-
import { Command as
|
|
39223
|
+
import { Command as Command8 } from "commander";
|
|
38190
39224
|
import { readFileSync as readFileSync21 } from "fs";
|
|
38191
39225
|
function withValueSourceOptions(cmd, what) {
|
|
38192
39226
|
return cmd.option(
|
|
@@ -38221,7 +39255,7 @@ function credentialPath(base, id) {
|
|
|
38221
39255
|
}
|
|
38222
39256
|
function buildBasesCredentialsCommand() {
|
|
38223
39257
|
const credentials = withBaseOption(
|
|
38224
|
-
new
|
|
39258
|
+
new Command8("credentials").description("Manage a base's integration credentials")
|
|
38225
39259
|
);
|
|
38226
39260
|
withValueSourceOptions(
|
|
38227
39261
|
credentials.command("create").description("Store a credential on this base (value read from stdin, a masked prompt, or --file)").requiredOption("--name <name>", "Credential name \u2014 what a credential:<name> reference resolves").option("--content-type <mime>", "MIME type of the value (e.g. application/x-pkcs12)").option(
|
|
@@ -38348,10 +39382,10 @@ var init_credentials = __esm({
|
|
|
38348
39382
|
});
|
|
38349
39383
|
|
|
38350
39384
|
// src/data/commands/sql.ts
|
|
38351
|
-
import { Command as
|
|
39385
|
+
import { Command as Command9 } from "commander";
|
|
38352
39386
|
import { readFileSync as readFileSync22 } from "fs";
|
|
38353
39387
|
function buildBasesSqlCommand() {
|
|
38354
|
-
return withBaseOption(new
|
|
39388
|
+
return withBaseOption(new Command9("sql")).description("Execute a read-only SQL query against base data").argument("[query]", "SQL query (SELECT only)").option("--file <path>", "Read SQL from a file instead of the argument").option(
|
|
38355
39389
|
"--param <kv...>",
|
|
38356
39390
|
"Named parameters as key=value pairs (e.g. --param status=issued)"
|
|
38357
39391
|
).action(async function(queryArg, opts) {
|
|
@@ -38393,250 +39427,6 @@ var init_sql = __esm({
|
|
|
38393
39427
|
}
|
|
38394
39428
|
});
|
|
38395
39429
|
|
|
38396
|
-
// src/data/commands/tokens.ts
|
|
38397
|
-
import { Command as Command9 } from "commander";
|
|
38398
|
-
function addTokenLifecycleOptions(cmd) {
|
|
38399
|
-
return cmd.option("--expires-at <date>", "Expiration date (ISO 8601, e.g. 2026-06-01T00:00:00Z)").option(
|
|
38400
|
-
"--ttl <duration>",
|
|
38401
|
-
"Relative expiry, e.g. 10m, 2h, 7d (use for disposable probe/test tokens)"
|
|
38402
|
-
).option(
|
|
38403
|
-
"--description <text>",
|
|
38404
|
-
'What holds this token (e.g. "behind credential X"); shown in list and revoke warnings'
|
|
38405
|
-
).addHelpText("after", TOKEN_OUTPUT_HELP);
|
|
38406
|
-
}
|
|
38407
|
-
function tokenCreationOutput(cmd, opts) {
|
|
38408
|
-
return opts.tokenOnly ? "token" : outputFormat(cmd);
|
|
38409
|
-
}
|
|
38410
|
-
function printCreatedToken(data, output) {
|
|
38411
|
-
if (output !== "token") {
|
|
38412
|
-
printOutput(data, output);
|
|
38413
|
-
return;
|
|
38414
|
-
}
|
|
38415
|
-
const token = typeof data === "object" && data !== null && "token" in data ? data.token : void 0;
|
|
38416
|
-
if (typeof token !== "string" || !RAW_TOKEN_PATTERN.test(token)) {
|
|
38417
|
-
throw new Error("Token creation response did not contain a valid rec_ token");
|
|
38418
|
-
}
|
|
38419
|
-
console.log(token);
|
|
38420
|
-
}
|
|
38421
|
-
function resolveExpiresAt(opts) {
|
|
38422
|
-
if (opts.ttl && opts.expiresAt) {
|
|
38423
|
-
throw expected("--ttl and --expires-at are mutually exclusive \u2014 pass one.");
|
|
38424
|
-
}
|
|
38425
|
-
if (opts.ttl) return new Date(Date.now() + parseDuration(opts.ttl, "--ttl")).toISOString();
|
|
38426
|
-
return opts.expiresAt;
|
|
38427
|
-
}
|
|
38428
|
-
function applyTokenLifecycleOpts(body, opts) {
|
|
38429
|
-
const expiresAt = resolveExpiresAt(opts);
|
|
38430
|
-
if (expiresAt) body.expires_at = expiresAt;
|
|
38431
|
-
if (opts.description) body.description = opts.description;
|
|
38432
|
-
}
|
|
38433
|
-
function listAllTokens(client) {
|
|
38434
|
-
return client.collectPages(
|
|
38435
|
-
(cursor) => `/v1/tokens?limit=${TOKEN_LIST_PAGE_LIMIT}${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""}`
|
|
38436
|
-
);
|
|
38437
|
-
}
|
|
38438
|
-
function pruneRow(t, reason) {
|
|
38439
|
-
return {
|
|
38440
|
-
token_id: t.token_id,
|
|
38441
|
-
name: t.name,
|
|
38442
|
-
reason,
|
|
38443
|
-
last_used: t.last_used_at ?? "never"
|
|
38444
|
-
};
|
|
38445
|
-
}
|
|
38446
|
-
function buildBasesTokensCommand() {
|
|
38447
|
-
const tokens2 = new Command9("tokens").description("Manage API tokens");
|
|
38448
|
-
addTokenLifecycleOptions(
|
|
38449
|
-
tokens2.command("create").description("Create a scoped API token").requiredOption("--name <name>", "Token name").requiredOption("--grants <json>", "Grant definitions as JSON array").option(
|
|
38450
|
-
"--token-only",
|
|
38451
|
-
"Print only the raw rec_ token for secure command substitution (shown once)"
|
|
38452
|
-
)
|
|
38453
|
-
).action(async function(opts) {
|
|
38454
|
-
const grants = parseData(opts.grants, "--grants");
|
|
38455
|
-
const body = { name: opts.name, grants };
|
|
38456
|
-
applyTokenLifecycleOpts(body, opts);
|
|
38457
|
-
const client = await createDataClient();
|
|
38458
|
-
const data = await client.request("POST", "/v1/tokens", body);
|
|
38459
|
-
printCreatedToken(data, tokenCreationOutput(this, opts));
|
|
38460
|
-
});
|
|
38461
|
-
addTokenLifecycleOptions(
|
|
38462
|
-
// The only token verb that addresses a base, so it alone declares `--base`.
|
|
38463
|
-
// Putting it on the `tokens` group would advertise a flag that does nothing
|
|
38464
|
-
// on `list`, `revoke` and `prune` — the defect `withBaseOption` exists to
|
|
38465
|
-
// avoid.
|
|
38466
|
-
withBaseOption(tokens2.command("create-for-toolset <slug>")).description(
|
|
38467
|
-
"Create a toolset-bound (consumer) token whose authorization IS the toolset tool surface \u2014 it can call exactly the tools that toolset exposes (those record types + operations, relationships, batch, and sql only if enabled) and nothing else. Binds to the configured --base."
|
|
38468
|
-
).option("--name <name>", 'Token name (default: "<slug> consumer")').option(
|
|
38469
|
-
"--token-only",
|
|
38470
|
-
"Print only the raw rec_ token for secure command substitution (shown once)"
|
|
38471
|
-
)
|
|
38472
|
-
).action(async function(slug, opts) {
|
|
38473
|
-
const base = requireBase(this);
|
|
38474
|
-
const body = {
|
|
38475
|
-
name: opts.name ?? `${slug} consumer`,
|
|
38476
|
-
toolset_binding: { base_id: base, toolset_id: slug }
|
|
38477
|
-
};
|
|
38478
|
-
applyTokenLifecycleOpts(body, opts);
|
|
38479
|
-
const client = await createDataClient();
|
|
38480
|
-
const data = await client.request("POST", "/v1/tokens", body);
|
|
38481
|
-
const output = tokenCreationOutput(this, opts);
|
|
38482
|
-
printCreatedToken(data, output);
|
|
38483
|
-
if (output === "table") {
|
|
38484
|
-
console.log(`
|
|
38485
|
-
MCP URL: ${toolsetMcpUrl(slug)}`);
|
|
38486
|
-
}
|
|
38487
|
-
});
|
|
38488
|
-
tokens2.command("list").description("List API tokens (status, last_used_at, expires_at, description)").action(async function() {
|
|
38489
|
-
const client = await createDataClient();
|
|
38490
|
-
printOutput(await listAllTokens(client), outputFormat(this));
|
|
38491
|
-
});
|
|
38492
|
-
tokens2.command("revoke <token_id>").description(
|
|
38493
|
-
"Revoke an API token (permanent). A recently-used or toolset-bound token requires --force."
|
|
38494
|
-
).option("--force", "Revoke even if the token appears to be in live use").action(async function(tokenId, opts) {
|
|
38495
|
-
const client = await createDataClient();
|
|
38496
|
-
const id = pathSegment(tokenId, "token id");
|
|
38497
|
-
const path42 = (force) => `/v1/tokens/${id}${force ? "?force=true" : ""}`;
|
|
38498
|
-
const format = outputFormat(this);
|
|
38499
|
-
const revoked = (forced) => printOutput({ token_id: tokenId, revoked: true, forced }, format);
|
|
38500
|
-
if (opts.force) {
|
|
38501
|
-
await client.request("DELETE", path42(true));
|
|
38502
|
-
revoked(true);
|
|
38503
|
-
return;
|
|
38504
|
-
}
|
|
38505
|
-
try {
|
|
38506
|
-
await client.request("DELETE", path42(false));
|
|
38507
|
-
revoked(false);
|
|
38508
|
-
} catch (err) {
|
|
38509
|
-
if (!(err instanceof ApiError) || err.status !== 409 || dataErrorDetails(err)?.requires_force !== true) {
|
|
38510
|
-
throw err;
|
|
38511
|
-
}
|
|
38512
|
-
console.error(err.message);
|
|
38513
|
-
if (!isInteractive()) {
|
|
38514
|
-
console.error("\nRe-run with --force to revoke anyway.");
|
|
38515
|
-
return process.exit(1);
|
|
38516
|
-
}
|
|
38517
|
-
if (!await confirm("Revoke anyway?")) {
|
|
38518
|
-
console.error("Aborted.");
|
|
38519
|
-
return process.exit(1);
|
|
38520
|
-
}
|
|
38521
|
-
await client.request("DELETE", path42(true));
|
|
38522
|
-
revoked(true);
|
|
38523
|
-
}
|
|
38524
|
-
});
|
|
38525
|
-
tokens2.command("prune").description(
|
|
38526
|
-
"Revoke stale tokens, selected by staleness only (expired, or unused past --unused-since) \u2014 never by name. Previews by default; revoking requires --yes or an interactive confirmation."
|
|
38527
|
-
).option(
|
|
38528
|
-
"--unused-since <duration>",
|
|
38529
|
-
"Also prune tokens with no activity for this long (e.g. 30d). Skips toolset-bound and legacy usage-untracked tokens."
|
|
38530
|
-
).option("--include-bound", "Allow pruning stale toolset-bound (consumer) tokens").option("-y, --yes", "Revoke without prompting (required when non-interactive)").action(async function(opts) {
|
|
38531
|
-
const staleMs = opts.unusedSince ? parseDuration(opts.unusedSince, "--unused-since") : void 0;
|
|
38532
|
-
const client = await createDataClient();
|
|
38533
|
-
const allTokens = await listAllTokens(client);
|
|
38534
|
-
const now = Date.now();
|
|
38535
|
-
const targets = [];
|
|
38536
|
-
const skipped = [];
|
|
38537
|
-
for (const t of allTokens) {
|
|
38538
|
-
const expired = t.status ? t.status === "expired" : !!t.expires_at && Date.parse(t.expires_at) <= now;
|
|
38539
|
-
if (expired) {
|
|
38540
|
-
targets.push(pruneRow(t, "expired"));
|
|
38541
|
-
continue;
|
|
38542
|
-
}
|
|
38543
|
-
if (staleMs === void 0) continue;
|
|
38544
|
-
const lastActivity = Date.parse(t.last_used_at ?? t.created_at);
|
|
38545
|
-
if (!(now - lastActivity > staleMs)) continue;
|
|
38546
|
-
if (t.usage_tracked !== true) {
|
|
38547
|
-
skipped.push(
|
|
38548
|
-
pruneRow(
|
|
38549
|
-
t,
|
|
38550
|
-
"usage untracked (legacy token) \u2014 revoke individually if truly unused"
|
|
38551
|
-
)
|
|
38552
|
-
);
|
|
38553
|
-
} else if (t.toolset_binding && !opts.includeBound) {
|
|
38554
|
-
skipped.push(
|
|
38555
|
-
pruneRow(
|
|
38556
|
-
t,
|
|
38557
|
-
`toolset-bound ('${t.toolset_binding.toolset_id}') \u2014 pass --include-bound to prune`
|
|
38558
|
-
)
|
|
38559
|
-
);
|
|
38560
|
-
} else {
|
|
38561
|
-
targets.push(pruneRow(t, `unused for over ${opts.unusedSince}`));
|
|
38562
|
-
}
|
|
38563
|
-
}
|
|
38564
|
-
const format = outputFormat(this);
|
|
38565
|
-
const json = format === "json";
|
|
38566
|
-
const note = (line) => json ? console.error(line) : console.log(line);
|
|
38567
|
-
const printPreview = () => {
|
|
38568
|
-
if (targets.length === 0) {
|
|
38569
|
-
note("Nothing to prune.");
|
|
38570
|
-
} else {
|
|
38571
|
-
note(`Would revoke ${targets.length} token(s):`);
|
|
38572
|
-
if (!json) printOutput(targets, format);
|
|
38573
|
-
}
|
|
38574
|
-
if (skipped.length === 0) return;
|
|
38575
|
-
note(`
|
|
38576
|
-
Skipped ${skipped.length} stale token(s):`);
|
|
38577
|
-
if (!json) printOutput(skipped, format);
|
|
38578
|
-
};
|
|
38579
|
-
printPreview();
|
|
38580
|
-
if (targets.length === 0) {
|
|
38581
|
-
if (json) printOutput({ revoked: 0, failed: 0, targets, skipped }, format);
|
|
38582
|
-
return;
|
|
38583
|
-
}
|
|
38584
|
-
if (!opts.yes) {
|
|
38585
|
-
if (!isInteractive()) {
|
|
38586
|
-
console.error("\nPreview only \u2014 re-run with --yes to revoke these tokens.");
|
|
38587
|
-
if (json) printOutput({ preview: true, revoked: 0, failed: 0, targets, skipped }, format);
|
|
38588
|
-
return process.exit(1);
|
|
38589
|
-
}
|
|
38590
|
-
if (!await confirm(`
|
|
38591
|
-
Revoke ${targets.length} token(s)?`)) {
|
|
38592
|
-
console.error("Aborted.");
|
|
38593
|
-
return process.exit(1);
|
|
38594
|
-
}
|
|
38595
|
-
}
|
|
38596
|
-
let revoked = 0;
|
|
38597
|
-
let failed = 0;
|
|
38598
|
-
for (const t of targets) {
|
|
38599
|
-
try {
|
|
38600
|
-
await client.request(
|
|
38601
|
-
"DELETE",
|
|
38602
|
-
`/v1/tokens/${pathSegment(t.token_id, "token id")}?force=true`
|
|
38603
|
-
);
|
|
38604
|
-
revoked++;
|
|
38605
|
-
} catch (err) {
|
|
38606
|
-
failed++;
|
|
38607
|
-
console.error(
|
|
38608
|
-
`Failed to revoke ${t.token_id} ('${sanitizeTerminalText(t.name)}'): ${err instanceof Error ? err.message : String(err)}`
|
|
38609
|
-
);
|
|
38610
|
-
}
|
|
38611
|
-
}
|
|
38612
|
-
if (json) printOutput({ revoked, failed, targets, skipped }, format);
|
|
38613
|
-
else console.log(`Revoked ${revoked} token(s)${failed > 0 ? `, ${failed} failed` : ""}.`);
|
|
38614
|
-
if (failed > 0) return process.exit(1);
|
|
38615
|
-
});
|
|
38616
|
-
return tokens2;
|
|
38617
|
-
}
|
|
38618
|
-
var RAW_TOKEN_PATTERN, TOKEN_OUTPUT_HELP, TOKEN_LIST_PAGE_LIMIT;
|
|
38619
|
-
var init_tokens = __esm({
|
|
38620
|
-
"src/data/commands/tokens.ts"() {
|
|
38621
|
-
"use strict";
|
|
38622
|
-
init_client();
|
|
38623
|
-
init_output();
|
|
38624
|
-
init_helpers();
|
|
38625
|
-
init_api_client();
|
|
38626
|
-
init_terminal_output();
|
|
38627
|
-
init_utils();
|
|
38628
|
-
init_expected();
|
|
38629
|
-
RAW_TOKEN_PATTERN = /^rec_[A-Za-z0-9_-]{43}$/;
|
|
38630
|
-
TOKEN_OUTPUT_HELP = `
|
|
38631
|
-
Output:
|
|
38632
|
-
--json prints the unwrapped response object; the secret is at top-level .token, never .data.token.
|
|
38633
|
-
--token-only prints only a validated rec_ token and overrides table/JSON formatting.
|
|
38634
|
-
The raw token is shown once. Capture it securely and do not log it.
|
|
38635
|
-
`;
|
|
38636
|
-
TOKEN_LIST_PAGE_LIMIT = 250;
|
|
38637
|
-
}
|
|
38638
|
-
});
|
|
38639
|
-
|
|
38640
39430
|
// src/data/base-tags.ts
|
|
38641
39431
|
async function resolveBaseTags(rawTags, client) {
|
|
38642
39432
|
const refs = splitList(rawTags);
|
|
@@ -39550,7 +40340,7 @@ function isConflict(err) {
|
|
|
39550
40340
|
return err instanceof ApiError && (err.status === 409 || err.status === 412);
|
|
39551
40341
|
}
|
|
39552
40342
|
function conflictLine(c, texts) {
|
|
39553
|
-
return `${
|
|
40343
|
+
return `${safe3(c.rel)}: ${texts[c.reason]}${c.other === void 0 ? "" : ` "${safe3(c.other)}"`}`;
|
|
39554
40344
|
}
|
|
39555
40345
|
function remedy(conflicts, overwriteCommand) {
|
|
39556
40346
|
const isClash = (c) => c.reason === "case_twin" || c.reason === "file_folder";
|
|
@@ -39571,7 +40361,7 @@ async function pullFiles(opts) {
|
|
|
39571
40361
|
const plan = planPull({ synced: existing?.files ?? {}, local, remote, overwrite: opts.overwrite });
|
|
39572
40362
|
if (plan.replacedLocal.length > 0) {
|
|
39573
40363
|
console.log("These local changes would be replaced with the base's copies:");
|
|
39574
|
-
for (const rel of plan.replacedLocal) console.log(` ${
|
|
40364
|
+
for (const rel of plan.replacedLocal) console.log(` ${safe3(rel)}`);
|
|
39575
40365
|
if (!await agree(`Replace ${plan.replacedLocal.length} locally changed file(s)?`, opts.yes)) {
|
|
39576
40366
|
console.log("Cancelled.");
|
|
39577
40367
|
return;
|
|
@@ -39592,7 +40382,7 @@ async function pullFiles(opts) {
|
|
|
39592
40382
|
}
|
|
39593
40383
|
removeLocal(dir, rel);
|
|
39594
40384
|
delete record.files[rel];
|
|
39595
|
-
changes.push(`${MARK.delete} ${
|
|
40385
|
+
changes.push(`${MARK.delete} ${safe3(rel)}`);
|
|
39596
40386
|
}
|
|
39597
40387
|
for (const w of plan.writes) {
|
|
39598
40388
|
const clash = diskClash(dir, w.rel);
|
|
@@ -39625,7 +40415,7 @@ async function pullFiles(opts) {
|
|
|
39625
40415
|
const hash = computeHash(bytes);
|
|
39626
40416
|
writeLocal(dir, w.rel, bytes);
|
|
39627
40417
|
record.files[w.rel] = { version, content_sha256: hash };
|
|
39628
|
-
changes.push(`${local.has(w.rel) ? MARK.update : MARK.create} ${
|
|
40418
|
+
changes.push(`${local.has(w.rel) ? MARK.update : MARK.create} ${safe3(w.rel)}`);
|
|
39629
40419
|
}
|
|
39630
40420
|
} finally {
|
|
39631
40421
|
writeRecord(dir, record);
|
|
@@ -39633,13 +40423,13 @@ async function pullFiles(opts) {
|
|
|
39633
40423
|
const count = Object.keys(record.files).length;
|
|
39634
40424
|
console.log(sanitizeTerminalText(`Pulled ${describeSync(target)} \u2192 ${dir} (${count} file${count === 1 ? "" : "s"}).`));
|
|
39635
40425
|
printSection("Changes:", changes);
|
|
39636
|
-
printSection("Kept \u2014 your local changes:", plan.kept.map((k) => `${
|
|
40426
|
+
printSection("Kept \u2014 your local changes:", plan.kept.map((k) => `${safe3(k.rel)}: ${PULL_KEPT[k.reason]}`));
|
|
39637
40427
|
printSection(
|
|
39638
40428
|
`Conflicts \u2014 your copy is kept; to settle them, ${remedy(conflicts, pullCommand2(target, opts.dir, true))}:`,
|
|
39639
40429
|
conflicts.map((c) => conflictLine(c, PULL_CONFLICT))
|
|
39640
40430
|
);
|
|
39641
|
-
printSection("Changed or deleted on the base while pulling \u2014 left as is; pull again to take it:", changedWhilePulling.map(
|
|
39642
|
-
printSection(`Not synced \u2014 names a synced folder leaves out (${OUTSIDE_SYNC.join(", ")}):`, excluded.map(
|
|
40431
|
+
printSection("Changed or deleted on the base while pulling \u2014 left as is; pull again to take it:", changedWhilePulling.map(safe3));
|
|
40432
|
+
printSection(`Not synced \u2014 names a synced folder leaves out (${OUTSIDE_SYNC.join(", ")}):`, excluded.map(safe3));
|
|
39643
40433
|
}
|
|
39644
40434
|
function isTextType(contentType) {
|
|
39645
40435
|
const ct = contentType.split(";")[0].trim().toLowerCase();
|
|
@@ -39657,7 +40447,7 @@ function changedLines(before, after) {
|
|
|
39657
40447
|
async function describeSteps(client, t, dir, steps) {
|
|
39658
40448
|
const lines = [];
|
|
39659
40449
|
for (const step of steps) {
|
|
39660
|
-
const rel =
|
|
40450
|
+
const rel = safe3(step.rel);
|
|
39661
40451
|
if (step.op === "create") {
|
|
39662
40452
|
lines.push(`${MARK.create} ${rel} (new, ${step.local.size} bytes)`);
|
|
39663
40453
|
} else if (step.op === "delete") {
|
|
@@ -39684,10 +40474,10 @@ async function describeSteps(client, t, dir, steps) {
|
|
|
39684
40474
|
return lines;
|
|
39685
40475
|
}
|
|
39686
40476
|
function printPushNotes(plan) {
|
|
39687
|
-
printSection("Changed on the base since your last pull \u2014 left as is; pull to take it:", plan.changedOnBase.map(
|
|
39688
|
-
printSection("Deleted on the base since your last pull \u2014 left as is; pull to remove your copy:", plan.deletedOnBase.map(
|
|
39689
|
-
printSection("On the base, not in your files \u2014 left as is; pull to fetch it:", plan.onlyOnBase.map(
|
|
39690
|
-
printSection("Deleted in your files \u2014 kept on the base; push with --prune to delete it:", plan.keptOnBase.map(
|
|
40477
|
+
printSection("Changed on the base since your last pull \u2014 left as is; pull to take it:", plan.changedOnBase.map(safe3));
|
|
40478
|
+
printSection("Deleted on the base since your last pull \u2014 left as is; pull to remove your copy:", plan.deletedOnBase.map(safe3));
|
|
40479
|
+
printSection("On the base, not in your files \u2014 left as is; pull to fetch it:", plan.onlyOnBase.map(safe3));
|
|
40480
|
+
printSection("Deleted in your files \u2014 kept on the base; push with --prune to delete it:", plan.keptOnBase.map(safe3));
|
|
39691
40481
|
}
|
|
39692
40482
|
async function pushFiles(opts) {
|
|
39693
40483
|
const label = opts.label === void 0 ? void 0 : labelValue(opts.label);
|
|
@@ -39750,7 +40540,7 @@ Push ${n} change${n === 1 ? "" : "s"} to ${describeSync(target)}?`, opts.yes)) {
|
|
|
39750
40540
|
} else {
|
|
39751
40541
|
const bytes = readLocal(dir, step.rel);
|
|
39752
40542
|
if (computeHash(bytes) !== step.local.content_sha256) {
|
|
39753
|
-
throw expected(`${
|
|
40543
|
+
throw expected(`${safe3(step.rel)} changed while the push ran. Nothing more was pushed; run the push again.`);
|
|
39754
40544
|
}
|
|
39755
40545
|
const contentType = step.op === "update" ? step.remote.content_type : guessMimeType(step.rel) ?? "application/octet-stream";
|
|
39756
40546
|
const row = await client.upload(
|
|
@@ -39765,7 +40555,7 @@ Push ${n} change${n === 1 ? "" : "s"} to ${describeSync(target)}?`, opts.yes)) {
|
|
|
39765
40555
|
};
|
|
39766
40556
|
}
|
|
39767
40557
|
pushed++;
|
|
39768
|
-
console.log(` ${MARK[step.op]} ${
|
|
40558
|
+
console.log(` ${MARK[step.op]} ${safe3(step.rel)}`);
|
|
39769
40559
|
} catch (err) {
|
|
39770
40560
|
if (step.op === "delete" && err instanceof ApiError && err.status === 404) {
|
|
39771
40561
|
delete record.files[step.rel];
|
|
@@ -39792,7 +40582,7 @@ function finishWithConflicts(t, dir, conflicts) {
|
|
|
39792
40582
|
`${count} conflict${count === 1 ? "" : "s"} not pushed \u2014 the base's copies of those files were left as they are. To settle them, ${remedy(conflicts, pullCommand2(t, dir, true))}, then push again.`
|
|
39793
40583
|
);
|
|
39794
40584
|
}
|
|
39795
|
-
var LIST_PAGE2, MAX_LIST_PAGES2, MAX_DIFF_BYTES, MARK,
|
|
40585
|
+
var LIST_PAGE2, MAX_LIST_PAGES2, MAX_DIFF_BYTES, MARK, safe3, PULL_KEPT, PULL_CONFLICT, PUSH_CONFLICT;
|
|
39796
40586
|
var init_sync3 = __esm({
|
|
39797
40587
|
"src/data/files-sync/sync.ts"() {
|
|
39798
40588
|
"use strict";
|
|
@@ -39814,7 +40604,7 @@ var init_sync3 = __esm({
|
|
|
39814
40604
|
MAX_LIST_PAGES2 = 1e3;
|
|
39815
40605
|
MAX_DIFF_BYTES = 256 * 1024;
|
|
39816
40606
|
MARK = { create: "+", update: "~", delete: "-" };
|
|
39817
|
-
|
|
40607
|
+
safe3 = (rel) => sanitizeTerminalText(rel);
|
|
39818
40608
|
PULL_KEPT = {
|
|
39819
40609
|
edited: "edited in your files, not pushed yet",
|
|
39820
40610
|
deleted: "deleted in your files, not pushed yet (push --prune deletes it from the base)"
|
|
@@ -41436,6 +42226,7 @@ Commands:
|
|
|
41436
42226
|
contacts Link a contact to its customer record in a base, or unlink it (browser sign-in only) \u2014 \`wayai contacts --help\`
|
|
41437
42227
|
knowledge migrate Move an organization's knowledge resources, then a hub's (--hub), into its knowledge base as file types and files \u2014 \`wayai knowledge --help\`
|
|
41438
42228
|
knowledge refresh-preview Make the knowledge base's preview hold its production base's files \u2014 \`wayai knowledge --help\`
|
|
42229
|
+
knowledge cut-over Switch a preview hub's agents from their knowledge resources to the knowledge base \u2014 \`wayai knowledge --help\`
|
|
41439
42230
|
report create Report a platform bug (submits to the triage queue)
|
|
41440
42231
|
report edit Amend your own pending report (title/description/error/steps/context)
|
|
41441
42232
|
update Update CLI to the latest version
|