@wayai/cli 0.3.76 → 0.3.77
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 +330 -152
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -165,11 +165,11 @@ function captureException2(error, context) {
|
|
|
165
165
|
Sentry.captureException(error);
|
|
166
166
|
});
|
|
167
167
|
}
|
|
168
|
-
function addApiBreadcrumb(method,
|
|
168
|
+
function addApiBreadcrumb(method, path25) {
|
|
169
169
|
if (!initialized) return;
|
|
170
170
|
Sentry.addBreadcrumb({
|
|
171
171
|
category: "http",
|
|
172
|
-
message: `${method} ${
|
|
172
|
+
message: `${method} ${path25}`,
|
|
173
173
|
level: "info"
|
|
174
174
|
});
|
|
175
175
|
}
|
|
@@ -231,9 +231,9 @@ var init_api_client = __esm({
|
|
|
231
231
|
ApiError = class extends Error {
|
|
232
232
|
status;
|
|
233
233
|
body;
|
|
234
|
-
constructor(method,
|
|
234
|
+
constructor(method, path25, status, body) {
|
|
235
235
|
const safeBody = redactSecrets(body);
|
|
236
|
-
super(`API request failed: ${method} ${
|
|
236
|
+
super(`API request failed: ${method} ${path25} (${status}): ${safeBody}`);
|
|
237
237
|
this.name = "ApiError";
|
|
238
238
|
this.status = status;
|
|
239
239
|
this.body = safeBody;
|
|
@@ -325,8 +325,8 @@ var init_api_client = __esm({
|
|
|
325
325
|
...organizationId && { organization_id: organizationId }
|
|
326
326
|
});
|
|
327
327
|
}
|
|
328
|
-
async lookup(
|
|
329
|
-
const params = new URLSearchParams({ path:
|
|
328
|
+
async lookup(path25, opts) {
|
|
329
|
+
const params = new URLSearchParams({ path: path25 });
|
|
330
330
|
if (opts?.organizationId) params.set("organization_id", opts.organizationId);
|
|
331
331
|
return this.request("GET", `/api/ci/lookup?${params.toString()}`);
|
|
332
332
|
}
|
|
@@ -543,6 +543,30 @@ var init_api_client = __esm({
|
|
|
543
543
|
preview_label: previewLabel ?? null
|
|
544
544
|
});
|
|
545
545
|
}
|
|
546
|
+
/**
|
|
547
|
+
* Preview → production diff — the source of truth for what `wayai publish`
|
|
548
|
+
* will do. `data.is_first_publish` distinguishes a first publish (no linked
|
|
549
|
+
* production hub yet, all entities listed as added) from a subsequent sync.
|
|
550
|
+
* Requires only `hub:read`, so it also drives the pre-confirm preview.
|
|
551
|
+
*/
|
|
552
|
+
async getHubDiff(hubId) {
|
|
553
|
+
return this.request("GET", `/api/setup/hubs/${hubId}/diff`);
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* First publish: clone the preview hub into a NEW production hub. Errors if the
|
|
557
|
+
* preview is already linked to production (use `syncHub` instead). Returns the
|
|
558
|
+
* new production hub id (POST /api/setup/hubs/:id/publish — HTTP 201).
|
|
559
|
+
*/
|
|
560
|
+
async publishHub(hubId) {
|
|
561
|
+
return this.request("POST", `/api/setup/hubs/${hubId}/publish`);
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Sync a preview hub's changes into its linked production hub
|
|
565
|
+
* (POST /api/setup/hubs/:id/sync). No-op-safe when already in sync.
|
|
566
|
+
*/
|
|
567
|
+
async syncHub(hubId) {
|
|
568
|
+
return this.request("POST", `/api/setup/hubs/${hubId}/sync`);
|
|
569
|
+
}
|
|
546
570
|
/**
|
|
547
571
|
* Set or clear a preview hub's label (PATCH /api/setup/hubs/:id). Pass null to
|
|
548
572
|
* clear. The backend trims and normalizes empty → null (max 60 chars).
|
|
@@ -715,9 +739,9 @@ var init_api_client = __esm({
|
|
|
715
739
|
`/api/admin/data-explorer/debug/observability/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}${qs}`
|
|
716
740
|
);
|
|
717
741
|
}
|
|
718
|
-
async request(method,
|
|
719
|
-
addApiBreadcrumb(method,
|
|
720
|
-
const url = `${this.apiUrl}${
|
|
742
|
+
async request(method, path25, body) {
|
|
743
|
+
addApiBreadcrumb(method, path25);
|
|
744
|
+
const url = `${this.apiUrl}${path25}`;
|
|
721
745
|
let refreshedOn401 = false;
|
|
722
746
|
for (let retry = 0; ; retry++) {
|
|
723
747
|
let response = await this.send(url, method, body);
|
|
@@ -741,7 +765,7 @@ var init_api_client = __esm({
|
|
|
741
765
|
await delay(RETRYABLE_BACKOFF_MS[retry]);
|
|
742
766
|
continue;
|
|
743
767
|
}
|
|
744
|
-
throw new ApiError(method,
|
|
768
|
+
throw new ApiError(method, path25, response.status, errorBody);
|
|
745
769
|
}
|
|
746
770
|
}
|
|
747
771
|
/** Issue a single authenticated request with the client's current token. */
|
|
@@ -1176,8 +1200,8 @@ var init_parseUtil = __esm({
|
|
|
1176
1200
|
init_errors();
|
|
1177
1201
|
init_en();
|
|
1178
1202
|
makeIssue = (params) => {
|
|
1179
|
-
const { data, path:
|
|
1180
|
-
const fullPath = [...
|
|
1203
|
+
const { data, path: path25, errorMaps, issueData } = params;
|
|
1204
|
+
const fullPath = [...path25, ...issueData.path || []];
|
|
1181
1205
|
const fullIssue = {
|
|
1182
1206
|
...issueData,
|
|
1183
1207
|
path: fullPath
|
|
@@ -1488,11 +1512,11 @@ var init_types = __esm({
|
|
|
1488
1512
|
init_parseUtil();
|
|
1489
1513
|
init_util();
|
|
1490
1514
|
ParseInputLazyPath = class {
|
|
1491
|
-
constructor(parent, value,
|
|
1515
|
+
constructor(parent, value, path25, key) {
|
|
1492
1516
|
this._cachedPath = [];
|
|
1493
1517
|
this.parent = parent;
|
|
1494
1518
|
this.data = value;
|
|
1495
|
-
this._path =
|
|
1519
|
+
this._path = path25;
|
|
1496
1520
|
this._key = key;
|
|
1497
1521
|
}
|
|
1498
1522
|
get path() {
|
|
@@ -4946,12 +4970,12 @@ function typeMatches(typeField, allowed) {
|
|
|
4946
4970
|
if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
|
|
4947
4971
|
return false;
|
|
4948
4972
|
}
|
|
4949
|
-
function validateSchema(schema,
|
|
4973
|
+
function validateSchema(schema, path25, errors, opts = {}) {
|
|
4950
4974
|
if (typeof schema === "boolean") return;
|
|
4951
4975
|
const depth = opts.depth ?? 0;
|
|
4952
4976
|
if (depth > MAX_SCHEMA_DEPTH) {
|
|
4953
4977
|
errors.push({
|
|
4954
|
-
path:
|
|
4978
|
+
path: path25 || "<root>",
|
|
4955
4979
|
message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH} levels`,
|
|
4956
4980
|
suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
|
|
4957
4981
|
});
|
|
@@ -4959,7 +4983,7 @@ function validateSchema(schema, path24, errors, opts = {}) {
|
|
|
4959
4983
|
}
|
|
4960
4984
|
if (!isRecord(schema)) {
|
|
4961
4985
|
errors.push({
|
|
4962
|
-
path:
|
|
4986
|
+
path: path25,
|
|
4963
4987
|
message: `expected object, got ${schema === null ? "null" : typeof schema}`
|
|
4964
4988
|
});
|
|
4965
4989
|
return;
|
|
@@ -4967,14 +4991,14 @@ function validateSchema(schema, path24, errors, opts = {}) {
|
|
|
4967
4991
|
if (opts.isRoot) {
|
|
4968
4992
|
if ("type" in schema && schema.type !== "object") {
|
|
4969
4993
|
errors.push({
|
|
4970
|
-
path:
|
|
4994
|
+
path: path25 ? `${path25}.type` : "type",
|
|
4971
4995
|
message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
|
|
4972
4996
|
suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
|
|
4973
4997
|
});
|
|
4974
4998
|
}
|
|
4975
4999
|
} else if ("type" in schema && !typeMatches(schema.type, ALLOWED_TYPES)) {
|
|
4976
5000
|
errors.push({
|
|
4977
|
-
path: `${
|
|
5001
|
+
path: `${path25}.type`,
|
|
4978
5002
|
message: `type must be one of ${[...ALLOWED_TYPES].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
|
|
4979
5003
|
});
|
|
4980
5004
|
}
|
|
@@ -4983,25 +5007,25 @@ function validateSchema(schema, path24, errors, opts = {}) {
|
|
|
4983
5007
|
if (typeof e === "string") {
|
|
4984
5008
|
const isPlaceholder = PLACEHOLDER_TOKENS.includes(e);
|
|
4985
5009
|
errors.push({
|
|
4986
|
-
path: `${
|
|
5010
|
+
path: `${path25}.enum`,
|
|
4987
5011
|
message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
|
|
4988
5012
|
suggestion: isPlaceholder ? "Set `operation: 'update_kanban_status'` on the tool and ensure at least one hub.kanban_status has `allowsAgentUpdate: true` so the platform can render the placeholder into a valid array." : 'Wrap the value in an array: `enum: ["value"]`.'
|
|
4989
5013
|
});
|
|
4990
5014
|
} else if (!Array.isArray(e)) {
|
|
4991
5015
|
errors.push({
|
|
4992
|
-
path: `${
|
|
5016
|
+
path: `${path25}.enum`,
|
|
4993
5017
|
message: `enum must be a non-empty array of primitives, got ${typeof e}`
|
|
4994
5018
|
});
|
|
4995
5019
|
} else if (e.length === 0) {
|
|
4996
5020
|
errors.push({
|
|
4997
|
-
path: `${
|
|
5021
|
+
path: `${path25}.enum`,
|
|
4998
5022
|
message: "enum must not be empty"
|
|
4999
5023
|
});
|
|
5000
5024
|
} else {
|
|
5001
5025
|
for (let i = 0; i < e.length; i++) {
|
|
5002
5026
|
if (!isPrimitive(e[i])) {
|
|
5003
5027
|
errors.push({
|
|
5004
|
-
path: `${
|
|
5028
|
+
path: `${path25}.enum[${i}]`,
|
|
5005
5029
|
message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
|
|
5006
5030
|
});
|
|
5007
5031
|
}
|
|
@@ -5011,7 +5035,7 @@ function validateSchema(schema, path24, errors, opts = {}) {
|
|
|
5011
5035
|
for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
|
|
5012
5036
|
if (key in schema && typeof schema[key] === "boolean") {
|
|
5013
5037
|
errors.push({
|
|
5014
|
-
path: `${
|
|
5038
|
+
path: `${path25}.${key}`,
|
|
5015
5039
|
message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
|
|
5016
5040
|
suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
|
|
5017
5041
|
});
|
|
@@ -5020,45 +5044,45 @@ function validateSchema(schema, path24, errors, opts = {}) {
|
|
|
5020
5044
|
if ("properties" in schema) {
|
|
5021
5045
|
if (!isRecord(schema.properties)) {
|
|
5022
5046
|
errors.push({
|
|
5023
|
-
path: `${
|
|
5047
|
+
path: `${path25}.properties`,
|
|
5024
5048
|
message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
|
|
5025
5049
|
});
|
|
5026
5050
|
} else {
|
|
5027
5051
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
5028
|
-
validateSchema(propSchema, `${
|
|
5052
|
+
validateSchema(propSchema, `${path25}.properties.${propName}`, errors, { depth: depth + 1 });
|
|
5029
5053
|
}
|
|
5030
5054
|
}
|
|
5031
5055
|
}
|
|
5032
5056
|
if (schemaTypeIncludes(schema, "array") && "items" in schema) {
|
|
5033
5057
|
if (Array.isArray(schema.items)) {
|
|
5034
|
-
schema.items.forEach((sub, i) => validateSchema(sub, `${
|
|
5058
|
+
schema.items.forEach((sub, i) => validateSchema(sub, `${path25}.items[${i}]`, errors, { depth: depth + 1 }));
|
|
5035
5059
|
} else {
|
|
5036
|
-
validateSchema(schema.items, `${
|
|
5060
|
+
validateSchema(schema.items, `${path25}.items`, errors, { depth: depth + 1 });
|
|
5037
5061
|
}
|
|
5038
5062
|
}
|
|
5039
5063
|
for (const key of SUBSCHEMA_OBJECT_KEYWORDS) {
|
|
5040
5064
|
if (key in schema && isRecord(schema[key])) {
|
|
5041
|
-
validateSchema(schema[key], `${
|
|
5065
|
+
validateSchema(schema[key], `${path25}.${key}`, errors, { depth: depth + 1 });
|
|
5042
5066
|
}
|
|
5043
5067
|
}
|
|
5044
5068
|
for (const key of SUBSCHEMA_LIST_KEYWORDS) {
|
|
5045
5069
|
const list = schema[key];
|
|
5046
5070
|
if (Array.isArray(list)) {
|
|
5047
|
-
list.forEach((sub, i) => validateSchema(sub, `${
|
|
5071
|
+
list.forEach((sub, i) => validateSchema(sub, `${path25}.${key}[${i}]`, errors, { depth: depth + 1 }));
|
|
5048
5072
|
}
|
|
5049
5073
|
}
|
|
5050
5074
|
for (const key of SUBSCHEMA_MAP_KEYWORDS) {
|
|
5051
5075
|
const map = schema[key];
|
|
5052
5076
|
if (isRecord(map)) {
|
|
5053
5077
|
for (const [name, sub] of Object.entries(map)) {
|
|
5054
|
-
validateSchema(sub, `${
|
|
5078
|
+
validateSchema(sub, `${path25}.${key}.${name}`, errors, { depth: depth + 1 });
|
|
5055
5079
|
}
|
|
5056
5080
|
}
|
|
5057
5081
|
}
|
|
5058
5082
|
const reportedPaths = new Set(errors.map((e) => e.path));
|
|
5059
5083
|
for (const [k, v] of Object.entries(schema)) {
|
|
5060
5084
|
if (typeof v !== "string") continue;
|
|
5061
|
-
const fieldPath = `${
|
|
5085
|
+
const fieldPath = `${path25}.${k}`;
|
|
5062
5086
|
if (reportedPaths.has(fieldPath)) continue;
|
|
5063
5087
|
for (const token of PLACEHOLDER_TOKENS) {
|
|
5064
5088
|
if (v === token) {
|
|
@@ -5214,10 +5238,10 @@ function refineHubAsCodeLanes(config, ctx) {
|
|
|
5214
5238
|
}
|
|
5215
5239
|
}
|
|
5216
5240
|
}
|
|
5217
|
-
function isSafeTemplatePath(
|
|
5218
|
-
if (
|
|
5219
|
-
if (
|
|
5220
|
-
const segments =
|
|
5241
|
+
function isSafeTemplatePath(path25) {
|
|
5242
|
+
if (path25.length === 0 || path25.length > 300) return false;
|
|
5243
|
+
if (path25.startsWith("/") || path25.includes("\\")) return false;
|
|
5244
|
+
const segments = path25.split("/");
|
|
5221
5245
|
return segments.every(
|
|
5222
5246
|
(seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
|
|
5223
5247
|
);
|
|
@@ -8536,9 +8560,9 @@ function getVersionCachePath(filename = CLI_CACHE_FILE) {
|
|
|
8536
8560
|
}
|
|
8537
8561
|
function readVersionCache(filename = CLI_CACHE_FILE) {
|
|
8538
8562
|
try {
|
|
8539
|
-
const
|
|
8540
|
-
if (!existsSync4(
|
|
8541
|
-
const parsed = JSON.parse(readFileSync5(
|
|
8563
|
+
const path25 = getVersionCachePath(filename);
|
|
8564
|
+
if (!existsSync4(path25)) return null;
|
|
8565
|
+
const parsed = JSON.parse(readFileSync5(path25, "utf-8"));
|
|
8542
8566
|
if (typeof parsed.lastCheck !== "number") return null;
|
|
8543
8567
|
if (parsed.latest !== null && typeof parsed.latest !== "string") return null;
|
|
8544
8568
|
return parsed;
|
|
@@ -8558,10 +8582,10 @@ function isVersionCacheStale(filename = CLI_CACHE_FILE, maxAgeMs = MAX_AGE_24H_M
|
|
|
8558
8582
|
return Date.now() - cache.lastCheck > maxAgeMs;
|
|
8559
8583
|
}
|
|
8560
8584
|
function writeVersionCache(filename, cache) {
|
|
8561
|
-
const
|
|
8562
|
-
const dir = dirname3(
|
|
8585
|
+
const path25 = getVersionCachePath(filename);
|
|
8586
|
+
const dir = dirname3(path25);
|
|
8563
8587
|
if (!existsSync4(dir)) mkdirSync(dir, { recursive: true });
|
|
8564
|
-
writeFileSync2(
|
|
8588
|
+
writeFileSync2(path25, JSON.stringify(cache));
|
|
8565
8589
|
}
|
|
8566
8590
|
function touchVersionCache(filename) {
|
|
8567
8591
|
writeVersionCache(filename, { lastCheck: Date.now(), latest: readVersionCache(filename)?.latest ?? null });
|
|
@@ -8600,14 +8624,14 @@ function parseFrontmatterVersion(content) {
|
|
|
8600
8624
|
function findInstalledSkills(projectRoot, paths = SKILL_INSTALL_PATHS) {
|
|
8601
8625
|
const found = [];
|
|
8602
8626
|
for (const rel of paths) {
|
|
8603
|
-
const
|
|
8604
|
-
if (!existsSync5(
|
|
8627
|
+
const path25 = join7(projectRoot, rel);
|
|
8628
|
+
if (!existsSync5(path25)) continue;
|
|
8605
8629
|
let version = null;
|
|
8606
8630
|
try {
|
|
8607
|
-
version = parseFrontmatterVersion(readFileSync6(
|
|
8631
|
+
version = parseFrontmatterVersion(readFileSync6(path25, "utf-8"));
|
|
8608
8632
|
} catch {
|
|
8609
8633
|
}
|
|
8610
|
-
found.push({ path:
|
|
8634
|
+
found.push({ path: path25, version });
|
|
8611
8635
|
}
|
|
8612
8636
|
return found;
|
|
8613
8637
|
}
|
|
@@ -11577,12 +11601,12 @@ function typeMatches2(typeField, allowed) {
|
|
|
11577
11601
|
if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
|
|
11578
11602
|
return false;
|
|
11579
11603
|
}
|
|
11580
|
-
function validateSchema2(schema,
|
|
11604
|
+
function validateSchema2(schema, path25, errors, opts = {}) {
|
|
11581
11605
|
if (typeof schema === "boolean") return;
|
|
11582
11606
|
const depth = opts.depth ?? 0;
|
|
11583
11607
|
if (depth > MAX_SCHEMA_DEPTH2) {
|
|
11584
11608
|
errors.push({
|
|
11585
|
-
path:
|
|
11609
|
+
path: path25 || "<root>",
|
|
11586
11610
|
message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH2} levels`,
|
|
11587
11611
|
suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
|
|
11588
11612
|
});
|
|
@@ -11590,7 +11614,7 @@ function validateSchema2(schema, path24, errors, opts = {}) {
|
|
|
11590
11614
|
}
|
|
11591
11615
|
if (!isRecord2(schema)) {
|
|
11592
11616
|
errors.push({
|
|
11593
|
-
path:
|
|
11617
|
+
path: path25,
|
|
11594
11618
|
message: `expected object, got ${schema === null ? "null" : typeof schema}`
|
|
11595
11619
|
});
|
|
11596
11620
|
return;
|
|
@@ -11598,14 +11622,14 @@ function validateSchema2(schema, path24, errors, opts = {}) {
|
|
|
11598
11622
|
if (opts.isRoot) {
|
|
11599
11623
|
if ("type" in schema && schema.type !== "object") {
|
|
11600
11624
|
errors.push({
|
|
11601
|
-
path:
|
|
11625
|
+
path: path25 ? `${path25}.type` : "type",
|
|
11602
11626
|
message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
|
|
11603
11627
|
suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
|
|
11604
11628
|
});
|
|
11605
11629
|
}
|
|
11606
11630
|
} else if ("type" in schema && !typeMatches2(schema.type, ALLOWED_TYPES2)) {
|
|
11607
11631
|
errors.push({
|
|
11608
|
-
path: `${
|
|
11632
|
+
path: `${path25}.type`,
|
|
11609
11633
|
message: `type must be one of ${[...ALLOWED_TYPES2].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
|
|
11610
11634
|
});
|
|
11611
11635
|
}
|
|
@@ -11614,25 +11638,25 @@ function validateSchema2(schema, path24, errors, opts = {}) {
|
|
|
11614
11638
|
if (typeof e === "string") {
|
|
11615
11639
|
const isPlaceholder = PLACEHOLDER_TOKENS2.includes(e);
|
|
11616
11640
|
errors.push({
|
|
11617
|
-
path: `${
|
|
11641
|
+
path: `${path25}.enum`,
|
|
11618
11642
|
message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
|
|
11619
11643
|
suggestion: isPlaceholder ? "Set `operation: 'update_kanban_status'` on the tool and ensure at least one hub.kanban_status has `allowsAgentUpdate: true` so the platform can render the placeholder into a valid array." : 'Wrap the value in an array: `enum: ["value"]`.'
|
|
11620
11644
|
});
|
|
11621
11645
|
} else if (!Array.isArray(e)) {
|
|
11622
11646
|
errors.push({
|
|
11623
|
-
path: `${
|
|
11647
|
+
path: `${path25}.enum`,
|
|
11624
11648
|
message: `enum must be a non-empty array of primitives, got ${typeof e}`
|
|
11625
11649
|
});
|
|
11626
11650
|
} else if (e.length === 0) {
|
|
11627
11651
|
errors.push({
|
|
11628
|
-
path: `${
|
|
11652
|
+
path: `${path25}.enum`,
|
|
11629
11653
|
message: "enum must not be empty"
|
|
11630
11654
|
});
|
|
11631
11655
|
} else {
|
|
11632
11656
|
for (let i = 0; i < e.length; i++) {
|
|
11633
11657
|
if (!isPrimitive2(e[i])) {
|
|
11634
11658
|
errors.push({
|
|
11635
|
-
path: `${
|
|
11659
|
+
path: `${path25}.enum[${i}]`,
|
|
11636
11660
|
message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
|
|
11637
11661
|
});
|
|
11638
11662
|
}
|
|
@@ -11642,7 +11666,7 @@ function validateSchema2(schema, path24, errors, opts = {}) {
|
|
|
11642
11666
|
for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
|
|
11643
11667
|
if (key in schema && typeof schema[key] === "boolean") {
|
|
11644
11668
|
errors.push({
|
|
11645
|
-
path: `${
|
|
11669
|
+
path: `${path25}.${key}`,
|
|
11646
11670
|
message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
|
|
11647
11671
|
suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
|
|
11648
11672
|
});
|
|
@@ -11651,45 +11675,45 @@ function validateSchema2(schema, path24, errors, opts = {}) {
|
|
|
11651
11675
|
if ("properties" in schema) {
|
|
11652
11676
|
if (!isRecord2(schema.properties)) {
|
|
11653
11677
|
errors.push({
|
|
11654
|
-
path: `${
|
|
11678
|
+
path: `${path25}.properties`,
|
|
11655
11679
|
message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
|
|
11656
11680
|
});
|
|
11657
11681
|
} else {
|
|
11658
11682
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
11659
|
-
validateSchema2(propSchema, `${
|
|
11683
|
+
validateSchema2(propSchema, `${path25}.properties.${propName}`, errors, { depth: depth + 1 });
|
|
11660
11684
|
}
|
|
11661
11685
|
}
|
|
11662
11686
|
}
|
|
11663
11687
|
if (schemaTypeIncludes2(schema, "array") && "items" in schema) {
|
|
11664
11688
|
if (Array.isArray(schema.items)) {
|
|
11665
|
-
schema.items.forEach((sub, i) => validateSchema2(sub, `${
|
|
11689
|
+
schema.items.forEach((sub, i) => validateSchema2(sub, `${path25}.items[${i}]`, errors, { depth: depth + 1 }));
|
|
11666
11690
|
} else {
|
|
11667
|
-
validateSchema2(schema.items, `${
|
|
11691
|
+
validateSchema2(schema.items, `${path25}.items`, errors, { depth: depth + 1 });
|
|
11668
11692
|
}
|
|
11669
11693
|
}
|
|
11670
11694
|
for (const key of SUBSCHEMA_OBJECT_KEYWORDS2) {
|
|
11671
11695
|
if (key in schema && isRecord2(schema[key])) {
|
|
11672
|
-
validateSchema2(schema[key], `${
|
|
11696
|
+
validateSchema2(schema[key], `${path25}.${key}`, errors, { depth: depth + 1 });
|
|
11673
11697
|
}
|
|
11674
11698
|
}
|
|
11675
11699
|
for (const key of SUBSCHEMA_LIST_KEYWORDS2) {
|
|
11676
11700
|
const list = schema[key];
|
|
11677
11701
|
if (Array.isArray(list)) {
|
|
11678
|
-
list.forEach((sub, i) => validateSchema2(sub, `${
|
|
11702
|
+
list.forEach((sub, i) => validateSchema2(sub, `${path25}.${key}[${i}]`, errors, { depth: depth + 1 }));
|
|
11679
11703
|
}
|
|
11680
11704
|
}
|
|
11681
11705
|
for (const key of SUBSCHEMA_MAP_KEYWORDS2) {
|
|
11682
11706
|
const map = schema[key];
|
|
11683
11707
|
if (isRecord2(map)) {
|
|
11684
11708
|
for (const [name, sub] of Object.entries(map)) {
|
|
11685
|
-
validateSchema2(sub, `${
|
|
11709
|
+
validateSchema2(sub, `${path25}.${key}.${name}`, errors, { depth: depth + 1 });
|
|
11686
11710
|
}
|
|
11687
11711
|
}
|
|
11688
11712
|
}
|
|
11689
11713
|
const reportedPaths = new Set(errors.map((e) => e.path));
|
|
11690
11714
|
for (const [k, v] of Object.entries(schema)) {
|
|
11691
11715
|
if (typeof v !== "string") continue;
|
|
11692
|
-
const fieldPath = `${
|
|
11716
|
+
const fieldPath = `${path25}.${k}`;
|
|
11693
11717
|
if (reportedPaths.has(fieldPath)) continue;
|
|
11694
11718
|
for (const token of PLACEHOLDER_TOKENS2) {
|
|
11695
11719
|
if (v === token) {
|
|
@@ -11845,10 +11869,10 @@ function refineHubAsCodeLanes2(config, ctx) {
|
|
|
11845
11869
|
}
|
|
11846
11870
|
}
|
|
11847
11871
|
}
|
|
11848
|
-
function isSafeTemplatePath2(
|
|
11849
|
-
if (
|
|
11850
|
-
if (
|
|
11851
|
-
const segments =
|
|
11872
|
+
function isSafeTemplatePath2(path25) {
|
|
11873
|
+
if (path25.length === 0 || path25.length > 300) return false;
|
|
11874
|
+
if (path25.startsWith("/") || path25.includes("\\")) return false;
|
|
11875
|
+
const segments = path25.split("/");
|
|
11852
11876
|
return segments.every(
|
|
11853
11877
|
(seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
|
|
11854
11878
|
);
|
|
@@ -11876,9 +11900,9 @@ function isPlainObject(value) {
|
|
|
11876
11900
|
const proto = Object.getPrototypeOf(value);
|
|
11877
11901
|
return proto === Object.prototype || proto === null;
|
|
11878
11902
|
}
|
|
11879
|
-
function isSanitizableSliceFile(
|
|
11880
|
-
if (!/\.ya?ml$/i.test(
|
|
11881
|
-
return
|
|
11903
|
+
function isSanitizableSliceFile(path25) {
|
|
11904
|
+
if (!/\.ya?ml$/i.test(path25)) return false;
|
|
11905
|
+
return path25 !== "resources" && !path25.startsWith("resources/");
|
|
11882
11906
|
}
|
|
11883
11907
|
function distinctUsesBackends(uses) {
|
|
11884
11908
|
return [...new Set((uses ?? []).map((u) => u.backend))];
|
|
@@ -14567,12 +14591,153 @@ var init_relabel = __esm({
|
|
|
14567
14591
|
}
|
|
14568
14592
|
});
|
|
14569
14593
|
|
|
14594
|
+
// src/commands/publish.ts
|
|
14595
|
+
var publish_exports = {};
|
|
14596
|
+
__export(publish_exports, {
|
|
14597
|
+
parseArgs: () => parseArgs9,
|
|
14598
|
+
publishCommand: () => publishCommand,
|
|
14599
|
+
renderHubDiff: () => renderHubDiff,
|
|
14600
|
+
runPublish: () => runPublish
|
|
14601
|
+
});
|
|
14602
|
+
import * as path17 from "path";
|
|
14603
|
+
function parseArgs9(args2) {
|
|
14604
|
+
let autoConfirm = false;
|
|
14605
|
+
let hubSelector;
|
|
14606
|
+
for (let i = 0; i < args2.length; i++) {
|
|
14607
|
+
const arg = args2[i];
|
|
14608
|
+
if (arg === "--yes" || arg === "-y") {
|
|
14609
|
+
autoConfirm = true;
|
|
14610
|
+
} else if (arg === "--hub" && args2[i + 1]) {
|
|
14611
|
+
hubSelector = args2[++i];
|
|
14612
|
+
}
|
|
14613
|
+
}
|
|
14614
|
+
return { autoConfirm, hubSelector };
|
|
14615
|
+
}
|
|
14616
|
+
function renderSection(title, entries) {
|
|
14617
|
+
if (entries.length === 0) return;
|
|
14618
|
+
console.log(`
|
|
14619
|
+
\x1B[1m${title}\x1B[0m`);
|
|
14620
|
+
for (const e of entries) {
|
|
14621
|
+
const { sym, color } = STATUS_STYLE[e.status];
|
|
14622
|
+
const type = e.type ? ` (${e.type})` : "";
|
|
14623
|
+
console.log(`\x1B[${color}m${sym} ${e.name}${type}\x1B[0m`);
|
|
14624
|
+
}
|
|
14625
|
+
}
|
|
14626
|
+
function renderHubDiff(result) {
|
|
14627
|
+
if (result.hub_changed) {
|
|
14628
|
+
const { sym, color } = STATUS_STYLE[result.is_first_publish ? "added" : "updated"];
|
|
14629
|
+
console.log("\n\x1B[1mHub\x1B[0m");
|
|
14630
|
+
console.log(`\x1B[${color}m${sym} hub settings\x1B[0m`);
|
|
14631
|
+
}
|
|
14632
|
+
renderSection("Agents", result.agents);
|
|
14633
|
+
renderSection("Connections", result.connections);
|
|
14634
|
+
renderSection("Tools", result.tools);
|
|
14635
|
+
renderSection("Channels", result.channels);
|
|
14636
|
+
renderSection("States", result.states);
|
|
14637
|
+
renderSection("Resources", result.resources);
|
|
14638
|
+
console.log();
|
|
14639
|
+
}
|
|
14640
|
+
async function runPublish(client, opts) {
|
|
14641
|
+
const { hubId, localConfig, organizationId, autoConfirm } = opts;
|
|
14642
|
+
const confirmFn = opts.confirmFn ?? confirm;
|
|
14643
|
+
if (localConfig) {
|
|
14644
|
+
const pushDiff = await client.diff(hubId, localConfig, "push", organizationId);
|
|
14645
|
+
if (pushDiff.has_changes) {
|
|
14646
|
+
console.log("\n\x1B[33mYou have local changes not yet pushed to this preview.\x1B[0m");
|
|
14647
|
+
console.log("Publishing promotes the PREVIEW (server) state \u2014 these local edits are NOT included.");
|
|
14648
|
+
console.log("Run `wayai push` first if you want them in production.");
|
|
14649
|
+
if (!autoConfirm) {
|
|
14650
|
+
const ok = await confirmFn("Continue with the current preview state anyway?");
|
|
14651
|
+
if (!ok) {
|
|
14652
|
+
console.log("Cancelled.");
|
|
14653
|
+
return "cancelled";
|
|
14654
|
+
}
|
|
14655
|
+
}
|
|
14656
|
+
}
|
|
14657
|
+
}
|
|
14658
|
+
const { data: diff } = await client.getHubDiff(hubId);
|
|
14659
|
+
if (!diff.has_changes && !diff.is_first_publish) {
|
|
14660
|
+
console.log("Production is already up to date. Nothing to sync.");
|
|
14661
|
+
return "up-to-date";
|
|
14662
|
+
}
|
|
14663
|
+
console.log(
|
|
14664
|
+
diff.is_first_publish ? "\nPublish preview \u2192 new production hub:" : "\nSync preview \u2192 production:"
|
|
14665
|
+
);
|
|
14666
|
+
renderHubDiff(diff);
|
|
14667
|
+
if (!autoConfirm) {
|
|
14668
|
+
const ok = await confirmFn(
|
|
14669
|
+
diff.is_first_publish ? "Publish to production?" : "Sync these changes to production?"
|
|
14670
|
+
);
|
|
14671
|
+
if (!ok) {
|
|
14672
|
+
console.log("Cancelled.");
|
|
14673
|
+
return "cancelled";
|
|
14674
|
+
}
|
|
14675
|
+
}
|
|
14676
|
+
if (diff.is_first_publish) {
|
|
14677
|
+
console.log("Publishing...");
|
|
14678
|
+
const { data } = await client.publishHub(hubId);
|
|
14679
|
+
console.log(`
|
|
14680
|
+
Published. Production hub: ${data.production_hub_id}`);
|
|
14681
|
+
return "published";
|
|
14682
|
+
}
|
|
14683
|
+
console.log("Syncing...");
|
|
14684
|
+
await client.syncHub(hubId);
|
|
14685
|
+
console.log("\nSynced preview changes to production.");
|
|
14686
|
+
return "synced";
|
|
14687
|
+
}
|
|
14688
|
+
async function publishCommand(args2) {
|
|
14689
|
+
const { autoConfirm, hubSelector } = parseArgs9(args2);
|
|
14690
|
+
const repoConfig = requireRepoConfig();
|
|
14691
|
+
const { organization_id: organizationId } = repoConfig;
|
|
14692
|
+
const { config, accessToken } = await requireAuth();
|
|
14693
|
+
const client = new ApiClient({ apiUrl: config.api_url, accessToken });
|
|
14694
|
+
const workspaceDir = resolveWorkspaceDir();
|
|
14695
|
+
const gitRoot = findGitRoot();
|
|
14696
|
+
if (gitRoot) warnLayoutOnce(gitRoot);
|
|
14697
|
+
const { hubId, hubFolder } = resolveHubTarget(workspaceDir, hubSelector);
|
|
14698
|
+
let localConfig = null;
|
|
14699
|
+
if (hubFolder) {
|
|
14700
|
+
localConfig = parseHubFolder(hubFolder);
|
|
14701
|
+
if (localConfig.hub_environment === "production") {
|
|
14702
|
+
console.log(
|
|
14703
|
+
"This is a read-only production mirror \u2014 production hubs cannot be published. Publish the linked preview hub instead."
|
|
14704
|
+
);
|
|
14705
|
+
return;
|
|
14706
|
+
}
|
|
14707
|
+
}
|
|
14708
|
+
assertHubMatchesBinding(hubId, hubFolder ? path17.basename(hubFolder) : void 0);
|
|
14709
|
+
await runPublish(client, { hubId, localConfig, organizationId, autoConfirm });
|
|
14710
|
+
}
|
|
14711
|
+
var STATUS_STYLE;
|
|
14712
|
+
var init_publish = __esm({
|
|
14713
|
+
"src/commands/publish.ts"() {
|
|
14714
|
+
"use strict";
|
|
14715
|
+
init_auth();
|
|
14716
|
+
init_api_client();
|
|
14717
|
+
init_parser();
|
|
14718
|
+
init_pull();
|
|
14719
|
+
init_utils();
|
|
14720
|
+
init_workspace();
|
|
14721
|
+
init_layout();
|
|
14722
|
+
init_repo_config();
|
|
14723
|
+
init_hub_binding();
|
|
14724
|
+
STATUS_STYLE = {
|
|
14725
|
+
added: { sym: "+", color: 32 },
|
|
14726
|
+
// green
|
|
14727
|
+
removed: { sym: "-", color: 31 },
|
|
14728
|
+
// red
|
|
14729
|
+
updated: { sym: "~", color: 33 }
|
|
14730
|
+
// yellow
|
|
14731
|
+
};
|
|
14732
|
+
}
|
|
14733
|
+
});
|
|
14734
|
+
|
|
14570
14735
|
// src/commands/use.ts
|
|
14571
14736
|
var use_exports = {};
|
|
14572
14737
|
__export(use_exports, {
|
|
14573
14738
|
useCommand: () => useCommand
|
|
14574
14739
|
});
|
|
14575
|
-
import * as
|
|
14740
|
+
import * as path18 from "path";
|
|
14576
14741
|
async function useCommand(args2) {
|
|
14577
14742
|
const target = args2[0];
|
|
14578
14743
|
if (!target || target.startsWith("-")) {
|
|
@@ -14595,7 +14760,7 @@ async function useCommand(args2) {
|
|
|
14595
14760
|
if (!match) {
|
|
14596
14761
|
console.error(`No hub matching "${target}" found in ${wsLabel}/. Pass a UUID or a folder name from:`);
|
|
14597
14762
|
for (const h of scanWorkspaceHubs(workspaceDir)) {
|
|
14598
|
-
console.error(` ${
|
|
14763
|
+
console.error(` ${path18.basename(h.hubFolder)} (${h.hubId})`);
|
|
14599
14764
|
}
|
|
14600
14765
|
process.exit(1);
|
|
14601
14766
|
}
|
|
@@ -14635,10 +14800,10 @@ __export(migrate_exports, {
|
|
|
14635
14800
|
});
|
|
14636
14801
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
14637
14802
|
import * as fs14 from "fs";
|
|
14638
|
-
import * as
|
|
14803
|
+
import * as path19 from "path";
|
|
14639
14804
|
function isTracked(gitRoot, p) {
|
|
14640
14805
|
try {
|
|
14641
|
-
execFileSync3("git", ["ls-files", "--error-unmatch", "--",
|
|
14806
|
+
execFileSync3("git", ["ls-files", "--error-unmatch", "--", path19.relative(gitRoot, p)], {
|
|
14642
14807
|
cwd: gitRoot,
|
|
14643
14808
|
stdio: ["pipe", "pipe", "pipe"]
|
|
14644
14809
|
});
|
|
@@ -14648,10 +14813,10 @@ function isTracked(gitRoot, p) {
|
|
|
14648
14813
|
}
|
|
14649
14814
|
}
|
|
14650
14815
|
function moveDir(gitRoot, from, to) {
|
|
14651
|
-
fs14.mkdirSync(
|
|
14816
|
+
fs14.mkdirSync(path19.dirname(to), { recursive: true });
|
|
14652
14817
|
if (isTracked(gitRoot, from)) {
|
|
14653
14818
|
try {
|
|
14654
|
-
execFileSync3("git", ["mv",
|
|
14819
|
+
execFileSync3("git", ["mv", path19.relative(gitRoot, from), path19.relative(gitRoot, to)], {
|
|
14655
14820
|
cwd: gitRoot,
|
|
14656
14821
|
stdio: ["pipe", "pipe", "pipe"]
|
|
14657
14822
|
});
|
|
@@ -14668,12 +14833,12 @@ async function migrateCommand(_args) {
|
|
|
14668
14833
|
console.error("Not inside a git repository.");
|
|
14669
14834
|
process.exit(1);
|
|
14670
14835
|
}
|
|
14671
|
-
const rel = (p) =>
|
|
14672
|
-
const newWs =
|
|
14673
|
-
const legacyWs =
|
|
14674
|
-
const legacyOrg =
|
|
14675
|
-
const newHubs =
|
|
14676
|
-
const newOrg =
|
|
14836
|
+
const rel = (p) => path19.relative(gitRoot, p);
|
|
14837
|
+
const newWs = path19.join(gitRoot, WAYAI_LAYOUT.wsDir);
|
|
14838
|
+
const legacyWs = path19.join(gitRoot, WAYAI_LAYOUT.legacy.wsDir);
|
|
14839
|
+
const legacyOrg = path19.join(gitRoot, WAYAI_LAYOUT.legacy.orgAtRoot);
|
|
14840
|
+
const newHubs = path19.join(newWs, WAYAI_LAYOUT.hubsSubdir);
|
|
14841
|
+
const newOrg = path19.join(newWs, WAYAI_LAYOUT.orgSubdir);
|
|
14677
14842
|
const hasLegacyWs = isDirectory(legacyWs);
|
|
14678
14843
|
const hasLegacyOrg = isDirectory(legacyOrg);
|
|
14679
14844
|
if (!hasLegacyWs && !hasLegacyOrg) {
|
|
@@ -15307,10 +15472,10 @@ var init_delete_history = __esm({
|
|
|
15307
15472
|
// src/commands/sync-skills.ts
|
|
15308
15473
|
var sync_skills_exports = {};
|
|
15309
15474
|
__export(sync_skills_exports, {
|
|
15310
|
-
parseArgs: () =>
|
|
15475
|
+
parseArgs: () => parseArgs10,
|
|
15311
15476
|
syncSkillsCommand: () => syncSkillsCommand
|
|
15312
15477
|
});
|
|
15313
|
-
function
|
|
15478
|
+
function parseArgs10(args2) {
|
|
15314
15479
|
let connectionId;
|
|
15315
15480
|
const idx = args2.indexOf("--connection-id");
|
|
15316
15481
|
if (idx !== -1 && args2[idx + 1]) {
|
|
@@ -15333,7 +15498,7 @@ function printSyncResults(response) {
|
|
|
15333
15498
|
}
|
|
15334
15499
|
async function syncSkillsCommand(args2) {
|
|
15335
15500
|
const hubId = resolveActiveHubId(args2);
|
|
15336
|
-
const { connectionId } =
|
|
15501
|
+
const { connectionId } = parseArgs10(args2);
|
|
15337
15502
|
requireRepoConfig();
|
|
15338
15503
|
const { config, accessToken } = await requireAuth();
|
|
15339
15504
|
const client = new ApiClient({ apiUrl: config.api_url, accessToken });
|
|
@@ -15358,10 +15523,10 @@ var init_sync_skills = __esm({
|
|
|
15358
15523
|
// src/commands/sync-mcp.ts
|
|
15359
15524
|
var sync_mcp_exports = {};
|
|
15360
15525
|
__export(sync_mcp_exports, {
|
|
15361
|
-
parseArgs: () =>
|
|
15526
|
+
parseArgs: () => parseArgs11,
|
|
15362
15527
|
syncMcpCommand: () => syncMcpCommand
|
|
15363
15528
|
});
|
|
15364
|
-
function
|
|
15529
|
+
function parseArgs11(args2) {
|
|
15365
15530
|
let connection;
|
|
15366
15531
|
for (let i = 0; i < args2.length; i++) {
|
|
15367
15532
|
const arg = args2[i];
|
|
@@ -15373,7 +15538,7 @@ function parseArgs10(args2) {
|
|
|
15373
15538
|
}
|
|
15374
15539
|
async function syncMcpCommand(args2) {
|
|
15375
15540
|
const hubId = resolveActiveHubId(args2);
|
|
15376
|
-
const { connection } =
|
|
15541
|
+
const { connection } = parseArgs11(args2);
|
|
15377
15542
|
if (!connection) {
|
|
15378
15543
|
console.error("Usage: wayai sync-mcp --connection <name> [--hub <uuid|folder-name>]");
|
|
15379
15544
|
console.error("");
|
|
@@ -15982,14 +16147,14 @@ __export(eval_capture_exports, {
|
|
|
15982
16147
|
evalCaptureCommand: () => evalCaptureCommand
|
|
15983
16148
|
});
|
|
15984
16149
|
import * as fs15 from "fs";
|
|
15985
|
-
import * as
|
|
16150
|
+
import * as path20 from "path";
|
|
15986
16151
|
import * as yaml7 from "js-yaml";
|
|
15987
16152
|
function isValidSetName(name) {
|
|
15988
16153
|
if (name.length === 0 || name === "." || name === "..") return false;
|
|
15989
16154
|
if (name.startsWith(".")) return false;
|
|
15990
16155
|
return !/[\/\\\0]/.test(name);
|
|
15991
16156
|
}
|
|
15992
|
-
function
|
|
16157
|
+
function parseArgs12(args2) {
|
|
15993
16158
|
if (args2.length === 0 || args2[0].startsWith("-")) {
|
|
15994
16159
|
console.error("Usage: wayai eval capture <conversation_id> [--set <name>] [--name <eval_name>] [--instructions <text>]");
|
|
15995
16160
|
process.exit(1);
|
|
@@ -16035,7 +16200,7 @@ function parseArgs11(args2) {
|
|
|
16035
16200
|
}
|
|
16036
16201
|
async function evalCaptureCommand(args2) {
|
|
16037
16202
|
const hubId = resolveActiveHubId(args2);
|
|
16038
|
-
const parsed =
|
|
16203
|
+
const parsed = parseArgs12(args2);
|
|
16039
16204
|
const { config, accessToken } = await requireAuth();
|
|
16040
16205
|
requireRepoConfig();
|
|
16041
16206
|
const client = new ApiClient({ apiUrl: config.api_url, accessToken });
|
|
@@ -16048,15 +16213,15 @@ async function evalCaptureCommand(args2) {
|
|
|
16048
16213
|
const setFolderName = targetSetName;
|
|
16049
16214
|
const scenarioName = parsed.evalName ?? `Capture ${parsed.conversationId.slice(0, 8)}`;
|
|
16050
16215
|
const slug = slugify(scenarioName);
|
|
16051
|
-
const evalsDir =
|
|
16052
|
-
const targetDir =
|
|
16053
|
-
const targetPath =
|
|
16054
|
-
if (!targetPath.startsWith(evalsDir +
|
|
16055
|
-
console.error(`Resolved path "${
|
|
16216
|
+
const evalsDir = path20.join(hubFolder, "evals");
|
|
16217
|
+
const targetDir = path20.join(evalsDir, setFolderName);
|
|
16218
|
+
const targetPath = path20.join(targetDir, `${slug}.yaml`);
|
|
16219
|
+
if (!targetPath.startsWith(evalsDir + path20.sep)) {
|
|
16220
|
+
console.error(`Resolved path "${path20.relative(hubFolder, targetPath)}" escapes evals/. Aborting.`);
|
|
16056
16221
|
process.exit(1);
|
|
16057
16222
|
}
|
|
16058
16223
|
if (fs15.existsSync(targetPath)) {
|
|
16059
|
-
console.error(`File already exists: ${
|
|
16224
|
+
console.error(`File already exists: ${path20.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
|
|
16060
16225
|
process.exit(1);
|
|
16061
16226
|
}
|
|
16062
16227
|
console.log("Resolving scenario set...");
|
|
@@ -16090,7 +16255,7 @@ async function evalCaptureCommand(args2) {
|
|
|
16090
16255
|
const yamlObj = buildEvalYamlObject(evalEntry, slug);
|
|
16091
16256
|
fs15.mkdirSync(targetDir, { recursive: true });
|
|
16092
16257
|
fs15.writeFileSync(targetPath, yaml7.dump(yamlObj, YAML_DUMP_OPTIONS), "utf-8");
|
|
16093
|
-
const relPath =
|
|
16258
|
+
const relPath = path20.relative(process.cwd(), targetPath);
|
|
16094
16259
|
console.log(`
|
|
16095
16260
|
Wrote ${relPath}`);
|
|
16096
16261
|
console.log("Run `wayai pull` to refresh the agent display name, then commit. The scenario is already on the platform.");
|
|
@@ -16112,7 +16277,7 @@ var journey_capture_exports = {};
|
|
|
16112
16277
|
__export(journey_capture_exports, {
|
|
16113
16278
|
journeyCaptureCommand: () => journeyCaptureCommand
|
|
16114
16279
|
});
|
|
16115
|
-
function
|
|
16280
|
+
function parseArgs13(args2) {
|
|
16116
16281
|
if (args2.length === 0 || args2[0].startsWith("-")) {
|
|
16117
16282
|
console.error("Usage: wayai eval journey capture <conversation_id> [--name <journey_name>] [--instructions <text>]");
|
|
16118
16283
|
process.exit(1);
|
|
@@ -16147,7 +16312,7 @@ function parseArgs12(args2) {
|
|
|
16147
16312
|
}
|
|
16148
16313
|
async function journeyCaptureCommand(args2) {
|
|
16149
16314
|
const hubId = resolveActiveHubId(args2);
|
|
16150
|
-
const parsed =
|
|
16315
|
+
const parsed = parseArgs13(args2);
|
|
16151
16316
|
const { config, accessToken } = await requireAuth();
|
|
16152
16317
|
requireRepoConfig();
|
|
16153
16318
|
const client = new ApiClient({ apiUrl: config.api_url, accessToken });
|
|
@@ -16944,9 +17109,9 @@ var init_credential_utils = __esm({
|
|
|
16944
17109
|
var create_credential_exports = {};
|
|
16945
17110
|
__export(create_credential_exports, {
|
|
16946
17111
|
createCredentialCommand: () => createCredentialCommand,
|
|
16947
|
-
parseArgs: () =>
|
|
17112
|
+
parseArgs: () => parseArgs14
|
|
16948
17113
|
});
|
|
16949
|
-
function
|
|
17114
|
+
function parseArgs14(args2) {
|
|
16950
17115
|
let name;
|
|
16951
17116
|
let type;
|
|
16952
17117
|
let orgId;
|
|
@@ -16974,7 +17139,7 @@ function parseArgs13(args2) {
|
|
|
16974
17139
|
return { name, type, orgId, description, tags: splitTagRefs(tags), environment, stdin };
|
|
16975
17140
|
}
|
|
16976
17141
|
async function createCredentialCommand(args2) {
|
|
16977
|
-
const parsed =
|
|
17142
|
+
const parsed = parseArgs14(args2);
|
|
16978
17143
|
if (!parsed.name) {
|
|
16979
17144
|
console.error("Missing required flag: --name <credential-name>");
|
|
16980
17145
|
console.error('Usage: wayai create-credential --name "openai-key" --type "Bearer Token"');
|
|
@@ -17081,10 +17246,10 @@ var init_create_credential = __esm({
|
|
|
17081
17246
|
// src/commands/update-credential.ts
|
|
17082
17247
|
var update_credential_exports = {};
|
|
17083
17248
|
__export(update_credential_exports, {
|
|
17084
|
-
parseArgs: () =>
|
|
17249
|
+
parseArgs: () => parseArgs15,
|
|
17085
17250
|
updateCredentialCommand: () => updateCredentialCommand
|
|
17086
17251
|
});
|
|
17087
|
-
function
|
|
17252
|
+
function parseArgs15(args2) {
|
|
17088
17253
|
let name;
|
|
17089
17254
|
let rename;
|
|
17090
17255
|
let orgId;
|
|
@@ -17117,7 +17282,7 @@ function parseArgs14(args2) {
|
|
|
17117
17282
|
return { name, rename, orgId, description, tags: splitTagRefs(tags), hasTagFlag, environment, stdin, secretPrompt };
|
|
17118
17283
|
}
|
|
17119
17284
|
async function updateCredentialCommand(args2) {
|
|
17120
|
-
const parsed =
|
|
17285
|
+
const parsed = parseArgs15(args2);
|
|
17121
17286
|
if (!parsed.name) {
|
|
17122
17287
|
console.error("Missing required flag: --name <credential-name>");
|
|
17123
17288
|
console.error('Usage: wayai update-credential --name "my-key" --stdin');
|
|
@@ -17222,10 +17387,10 @@ var init_update_credential = __esm({
|
|
|
17222
17387
|
// src/commands/set-connection-credential.ts
|
|
17223
17388
|
var set_connection_credential_exports = {};
|
|
17224
17389
|
__export(set_connection_credential_exports, {
|
|
17225
|
-
parseArgs: () =>
|
|
17390
|
+
parseArgs: () => parseArgs16,
|
|
17226
17391
|
setConnectionCredentialCommand: () => setConnectionCredentialCommand
|
|
17227
17392
|
});
|
|
17228
|
-
function
|
|
17393
|
+
function parseArgs16(args2) {
|
|
17229
17394
|
let connection;
|
|
17230
17395
|
let orgCredential;
|
|
17231
17396
|
let field;
|
|
@@ -17248,7 +17413,7 @@ function usage(msg) {
|
|
|
17248
17413
|
}
|
|
17249
17414
|
async function setConnectionCredentialCommand(args2) {
|
|
17250
17415
|
const hubId = resolveActiveHubId(args2);
|
|
17251
|
-
const parsed =
|
|
17416
|
+
const parsed = parseArgs16(args2);
|
|
17252
17417
|
if (!parsed.connection) usage("Missing required flag: --connection <name|id>");
|
|
17253
17418
|
const orgMode = !!parsed.orgCredential;
|
|
17254
17419
|
const directMode = !!parsed.field;
|
|
@@ -17318,22 +17483,22 @@ var init_set_connection_credential = __esm({
|
|
|
17318
17483
|
|
|
17319
17484
|
// src/lib/org-workspace.ts
|
|
17320
17485
|
import * as fs16 from "fs";
|
|
17321
|
-
import * as
|
|
17486
|
+
import * as path21 from "path";
|
|
17322
17487
|
import * as yaml8 from "js-yaml";
|
|
17323
17488
|
function getOrgDir(gitRoot) {
|
|
17324
17489
|
return resolveLayout(gitRoot).orgDir;
|
|
17325
17490
|
}
|
|
17326
17491
|
function orgManifestExists(orgDir) {
|
|
17327
|
-
return fs16.existsSync(
|
|
17492
|
+
return fs16.existsSync(path21.join(orgDir, ORG_MANIFEST_NAME));
|
|
17328
17493
|
}
|
|
17329
17494
|
function parseOrgResources(orgDir) {
|
|
17330
|
-
const manifestPath =
|
|
17495
|
+
const manifestPath = path21.join(orgDir, ORG_MANIFEST_NAME);
|
|
17331
17496
|
let manifest = {};
|
|
17332
17497
|
if (fs16.existsSync(manifestPath)) {
|
|
17333
17498
|
manifest = yaml8.load(fs16.readFileSync(manifestPath, "utf-8")) ?? {};
|
|
17334
17499
|
}
|
|
17335
17500
|
const rawResources = Array.isArray(manifest.resources) ? manifest.resources : [];
|
|
17336
|
-
const resourcesDir =
|
|
17501
|
+
const resourcesDir = path21.join(orgDir, "resources");
|
|
17337
17502
|
const resources = rawResources.map((res) => {
|
|
17338
17503
|
const resource = { name: res.name };
|
|
17339
17504
|
if (res.id) resource.id = res.id;
|
|
@@ -17345,7 +17510,7 @@ function parseOrgResources(orgDir) {
|
|
|
17345
17510
|
if (res.environment) resource.environment = res.environment;
|
|
17346
17511
|
if (Array.isArray(res.tags)) resource.tags = res.tags;
|
|
17347
17512
|
if (Array.isArray(res.folders)) resource.folders = res.folders;
|
|
17348
|
-
const resDir =
|
|
17513
|
+
const resDir = path21.join(resourcesDir, slugify(resource.name));
|
|
17349
17514
|
if (fs16.existsSync(resDir)) {
|
|
17350
17515
|
const files = scanResourceFiles(resDir, "");
|
|
17351
17516
|
if (files.length > 0) resource.files = files;
|
|
@@ -17362,21 +17527,21 @@ function writeOrgResources(orgDir, payload) {
|
|
|
17362
17527
|
return rest;
|
|
17363
17528
|
});
|
|
17364
17529
|
fs16.writeFileSync(
|
|
17365
|
-
|
|
17530
|
+
path21.join(orgDir, ORG_MANIFEST_NAME),
|
|
17366
17531
|
yaml8.dump({ version: 1, resources: manifestResources }, YAML_DUMP_OPTIONS),
|
|
17367
17532
|
"utf-8"
|
|
17368
17533
|
);
|
|
17369
|
-
const resourcesDir =
|
|
17534
|
+
const resourcesDir = path21.join(orgDir, "resources");
|
|
17370
17535
|
const currentSlugs = /* @__PURE__ */ new Set();
|
|
17371
17536
|
for (const resource of resources) {
|
|
17372
17537
|
const resSlug = slugify(resource.name);
|
|
17373
17538
|
currentSlugs.add(resSlug);
|
|
17374
|
-
writeResourceFileTree(
|
|
17539
|
+
writeResourceFileTree(path21.join(resourcesDir, resSlug), resource.files || []);
|
|
17375
17540
|
}
|
|
17376
17541
|
if (fs16.existsSync(resourcesDir)) {
|
|
17377
17542
|
for (const entry of fs16.readdirSync(resourcesDir, { withFileTypes: true })) {
|
|
17378
17543
|
if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
|
|
17379
|
-
fs16.rmSync(
|
|
17544
|
+
fs16.rmSync(path21.join(resourcesDir, entry.name), { recursive: true, force: true });
|
|
17380
17545
|
}
|
|
17381
17546
|
}
|
|
17382
17547
|
}
|
|
@@ -17385,7 +17550,7 @@ async function downloadOrgBinaryFiles(orgDir, payload) {
|
|
|
17385
17550
|
let count = 0;
|
|
17386
17551
|
for (const resource of payload.resources ?? []) {
|
|
17387
17552
|
if (!resource.files) continue;
|
|
17388
|
-
const resDir =
|
|
17553
|
+
const resDir = path21.join(orgDir, "resources", slugify(resource.name));
|
|
17389
17554
|
count += await downloadBinaryFiles(resDir, resource.files);
|
|
17390
17555
|
}
|
|
17391
17556
|
if (count > 0) console.log(`Downloaded ${count} binary resource file(s).`);
|
|
@@ -17573,9 +17738,9 @@ var init_org = __esm({
|
|
|
17573
17738
|
var list_exports = {};
|
|
17574
17739
|
__export(list_exports, {
|
|
17575
17740
|
listCommand: () => listCommand,
|
|
17576
|
-
parseArgs: () =>
|
|
17741
|
+
parseArgs: () => parseArgs17
|
|
17577
17742
|
});
|
|
17578
|
-
function
|
|
17743
|
+
function parseArgs17(args2) {
|
|
17579
17744
|
let orgId;
|
|
17580
17745
|
let json = false;
|
|
17581
17746
|
for (let i = 0; i < args2.length; i++) {
|
|
@@ -17588,7 +17753,7 @@ function parseArgs16(args2) {
|
|
|
17588
17753
|
return { orgId, json };
|
|
17589
17754
|
}
|
|
17590
17755
|
async function listCommand(args2) {
|
|
17591
|
-
const { orgId, json } =
|
|
17756
|
+
const { orgId, json } = parseArgs17(args2);
|
|
17592
17757
|
const { config, accessToken } = await requireAuth();
|
|
17593
17758
|
const client = new ApiClient({ apiUrl: config.api_url, accessToken });
|
|
17594
17759
|
const { organizations } = await client.organizations();
|
|
@@ -17642,13 +17807,13 @@ var init_list = __esm({
|
|
|
17642
17807
|
|
|
17643
17808
|
// src/lib/template-files.ts
|
|
17644
17809
|
import * as fs17 from "fs";
|
|
17645
|
-
import * as
|
|
17810
|
+
import * as path22 from "path";
|
|
17646
17811
|
function readDirToFileMap(rootDir) {
|
|
17647
17812
|
const out = {};
|
|
17648
17813
|
function walk(dir, prefix) {
|
|
17649
17814
|
const entries = fs17.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
17650
17815
|
for (const entry of entries) {
|
|
17651
|
-
const abs =
|
|
17816
|
+
const abs = path22.join(dir, entry.name);
|
|
17652
17817
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
17653
17818
|
if (entry.isDirectory()) walk(abs, rel);
|
|
17654
17819
|
else if (entry.isFile()) out[rel] = fs17.readFileSync(abs, "utf-8");
|
|
@@ -17663,7 +17828,7 @@ function detectCollisions(targetDir, files) {
|
|
|
17663
17828
|
if (!isSafeTemplatePath2(rel)) {
|
|
17664
17829
|
throw new Error(`Refusing to inspect unsafe template path: ${rel}`);
|
|
17665
17830
|
}
|
|
17666
|
-
if (fs17.existsSync(
|
|
17831
|
+
if (fs17.existsSync(path22.join(targetDir, rel))) collisions.push(rel);
|
|
17667
17832
|
}
|
|
17668
17833
|
return collisions.sort((a, b) => a.localeCompare(b));
|
|
17669
17834
|
}
|
|
@@ -17673,8 +17838,8 @@ function writeFileMap(targetDir, files) {
|
|
|
17673
17838
|
if (!isSafeTemplatePath2(rel)) {
|
|
17674
17839
|
throw new Error(`Refusing to write unsafe template path: ${rel}`);
|
|
17675
17840
|
}
|
|
17676
|
-
const abs =
|
|
17677
|
-
fs17.mkdirSync(
|
|
17841
|
+
const abs = path22.join(targetDir, rel);
|
|
17842
|
+
fs17.mkdirSync(path22.dirname(abs), { recursive: true });
|
|
17678
17843
|
fs17.writeFileSync(abs, body, "utf-8");
|
|
17679
17844
|
written.push(rel);
|
|
17680
17845
|
}
|
|
@@ -17685,7 +17850,7 @@ function listDirRelFiles(dir) {
|
|
|
17685
17850
|
function walk(d, prefix) {
|
|
17686
17851
|
for (const entry of fs17.readdirSync(d, { withFileTypes: true })) {
|
|
17687
17852
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
17688
|
-
if (entry.isDirectory()) walk(
|
|
17853
|
+
if (entry.isDirectory()) walk(path22.join(d, entry.name), rel);
|
|
17689
17854
|
else if (entry.isFile()) out.push(rel);
|
|
17690
17855
|
}
|
|
17691
17856
|
}
|
|
@@ -17712,7 +17877,7 @@ var templates_exports = {};
|
|
|
17712
17877
|
__export(templates_exports, {
|
|
17713
17878
|
templateCommand: () => templateCommand
|
|
17714
17879
|
});
|
|
17715
|
-
import * as
|
|
17880
|
+
import * as path23 from "path";
|
|
17716
17881
|
async function templateCommand(args2) {
|
|
17717
17882
|
const [sub, ...rest] = args2;
|
|
17718
17883
|
switch (sub) {
|
|
@@ -17828,8 +17993,8 @@ async function runTemplatePull(rest) {
|
|
|
17828
17993
|
console.log(`Template "${slug}" has no WayAI slice${hint}`);
|
|
17829
17994
|
return;
|
|
17830
17995
|
}
|
|
17831
|
-
const targetDir =
|
|
17832
|
-
const relTarget =
|
|
17996
|
+
const targetDir = path23.join(resolveLayout(gitRoot).hubsDir, slug);
|
|
17997
|
+
const relTarget = path23.relative(gitRoot, targetDir);
|
|
17833
17998
|
const collisions = detectCollisions(targetDir, detail.files);
|
|
17834
17999
|
if (dryRun) {
|
|
17835
18000
|
const planned = Object.keys(detail.files).sort((a, b) => a.localeCompare(b));
|
|
@@ -18004,7 +18169,7 @@ __export(admin_exports, {
|
|
|
18004
18169
|
adminCommand: () => adminCommand
|
|
18005
18170
|
});
|
|
18006
18171
|
import * as fs18 from "fs";
|
|
18007
|
-
import * as
|
|
18172
|
+
import * as path24 from "path";
|
|
18008
18173
|
import * as yaml10 from "js-yaml";
|
|
18009
18174
|
async function adminCommand(args2) {
|
|
18010
18175
|
const [group, ...afterGroup] = args2;
|
|
@@ -18383,10 +18548,10 @@ function loadTemplateManifest(slug) {
|
|
|
18383
18548
|
console.error("Not in a git repository. Run from the tutorials/ authoring repo.");
|
|
18384
18549
|
process.exit(1);
|
|
18385
18550
|
}
|
|
18386
|
-
const templateDir =
|
|
18387
|
-
const manifestPath =
|
|
18551
|
+
const templateDir = path24.join(resolveTemplatesDir(gitRoot), slug);
|
|
18552
|
+
const manifestPath = path24.join(templateDir, "template.yaml");
|
|
18388
18553
|
if (!fs18.existsSync(manifestPath)) {
|
|
18389
|
-
console.error(`template.yaml not found at ${
|
|
18554
|
+
console.error(`template.yaml not found at ${path24.relative(gitRoot, manifestPath)}`);
|
|
18390
18555
|
process.exit(1);
|
|
18391
18556
|
}
|
|
18392
18557
|
let manifest;
|
|
@@ -18421,19 +18586,19 @@ async function runTemplatePush(positional) {
|
|
|
18421
18586
|
const wayaiEntry = manifest.wayai.locales[locale];
|
|
18422
18587
|
let wayaiFiles;
|
|
18423
18588
|
if (wayaiEntry) {
|
|
18424
|
-
const sliceDir =
|
|
18589
|
+
const sliceDir = path24.resolve(templateDir, wayaiEntry.source);
|
|
18425
18590
|
if (!fs18.existsSync(sliceDir)) {
|
|
18426
18591
|
console.error(`wayai source not found for ${locale}: ${wayaiEntry.source} (resolved ${sliceDir})`);
|
|
18427
18592
|
process.exit(1);
|
|
18428
18593
|
}
|
|
18429
18594
|
if (!isInsideTemplateDir(sliceDir, templateDir)) {
|
|
18430
18595
|
console.warn(
|
|
18431
|
-
`Note: ${locale} source points at a live hub (${wayaiEntry.source}); it can go stale on a hub recreate. Run \`wayai admin template freeze ${slug} --locale ${locale} --from ${
|
|
18596
|
+
`Note: ${locale} source points at a live hub (${wayaiEntry.source}); it can go stale on a hub recreate. Run \`wayai admin template freeze ${slug} --locale ${locale} --from ${path24.basename(sliceDir)}\` to commit a stable frozen slice.`
|
|
18432
18597
|
);
|
|
18433
18598
|
}
|
|
18434
18599
|
wayaiFiles = readDirToFileMap(sliceDir);
|
|
18435
18600
|
}
|
|
18436
|
-
const readmePath =
|
|
18601
|
+
const readmePath = path24.join(templateDir, `README.${locale}.md`);
|
|
18437
18602
|
const readmeMarkdown = fs18.existsSync(readmePath) ? fs18.readFileSync(readmePath, "utf-8") : "";
|
|
18438
18603
|
locales[locale] = {
|
|
18439
18604
|
readmeMarkdown,
|
|
@@ -18445,9 +18610,9 @@ async function runTemplatePush(positional) {
|
|
|
18445
18610
|
}
|
|
18446
18611
|
let hero;
|
|
18447
18612
|
if (manifest.hero) {
|
|
18448
|
-
const heroPath =
|
|
18613
|
+
const heroPath = path24.resolve(templateDir, manifest.hero);
|
|
18449
18614
|
if (fs18.existsSync(heroPath)) {
|
|
18450
|
-
hero = { filename:
|
|
18615
|
+
hero = { filename: path24.basename(heroPath), dataBase64: fs18.readFileSync(heroPath).toString("base64") };
|
|
18451
18616
|
} else {
|
|
18452
18617
|
console.error(`Warning: hero not found at ${manifest.hero}; skipping.`);
|
|
18453
18618
|
}
|
|
@@ -18473,7 +18638,7 @@ async function runTemplatePush(positional) {
|
|
|
18473
18638
|
}
|
|
18474
18639
|
}
|
|
18475
18640
|
function isInsideTemplateDir(dest, templateDir) {
|
|
18476
|
-
return dest === templateDir || dest.startsWith(templateDir +
|
|
18641
|
+
return dest === templateDir || dest.startsWith(templateDir + path24.sep);
|
|
18477
18642
|
}
|
|
18478
18643
|
async function runTemplateFreeze(positional, flagArgs) {
|
|
18479
18644
|
const slug = positional[0];
|
|
@@ -18534,7 +18699,7 @@ async function runTemplateFreeze(positional, flagArgs) {
|
|
|
18534
18699
|
process.exit(1);
|
|
18535
18700
|
}
|
|
18536
18701
|
const entry = manifest.wayai.locales[targetLocale];
|
|
18537
|
-
const dest =
|
|
18702
|
+
const dest = path24.resolve(templateDir, entry.source);
|
|
18538
18703
|
if (!isInsideTemplateDir(dest, templateDir) || dest === templateDir) {
|
|
18539
18704
|
console.error(
|
|
18540
18705
|
`source for "${targetLocale}" must be a committed path inside ${slug}/ (e.g. "./${targetLocale}/slice"), but resolved to:
|
|
@@ -18553,7 +18718,7 @@ Set it to a subdir of the template folder and re-run freeze.`
|
|
|
18553
18718
|
const hubs = scanWorkspaceHubs(hubsDir);
|
|
18554
18719
|
if (hubs.length) {
|
|
18555
18720
|
console.error("Available hubs:");
|
|
18556
|
-
for (const h of hubs) console.error(` ${
|
|
18721
|
+
for (const h of hubs) console.error(` ${path24.basename(h.hubFolder)} (${h.hubId})`);
|
|
18557
18722
|
}
|
|
18558
18723
|
console.error(`
|
|
18559
18724
|
Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`);
|
|
@@ -18561,12 +18726,12 @@ Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`
|
|
|
18561
18726
|
}
|
|
18562
18727
|
const liveFiles = readDirToFileMap(hubFolder);
|
|
18563
18728
|
if (Object.keys(liveFiles).length === 0) {
|
|
18564
|
-
console.error(`Source hub folder has no files to freeze: ${
|
|
18729
|
+
console.error(`Source hub folder has no files to freeze: ${path24.relative(gitRoot, hubFolder)}`);
|
|
18565
18730
|
process.exit(1);
|
|
18566
18731
|
}
|
|
18567
18732
|
const sanitized = sanitizeWayaiSliceFiles(liveFiles);
|
|
18568
|
-
const relDest =
|
|
18569
|
-
const relSrc =
|
|
18733
|
+
const relDest = path24.relative(gitRoot, dest);
|
|
18734
|
+
const relSrc = path24.relative(gitRoot, hubFolder);
|
|
18570
18735
|
if (dryRun) {
|
|
18571
18736
|
const existing = new Set(listDirRelFiles(dest));
|
|
18572
18737
|
const nextKeys = new Set(Object.keys(sanitized));
|
|
@@ -18626,7 +18791,7 @@ async function runTemplatePull2(positional, flagArgs) {
|
|
|
18626
18791
|
console.log(JSON.stringify(detail, null, 2));
|
|
18627
18792
|
return;
|
|
18628
18793
|
}
|
|
18629
|
-
const target = outDir ?
|
|
18794
|
+
const target = outDir ? path24.resolve(outDir) : path24.join(process.cwd(), "template-store-pull", slug);
|
|
18630
18795
|
const written = writeFileMap(target, detail.files);
|
|
18631
18796
|
console.log(`Pulled "${slug}" from the store \u2192 ${target} (${written.length} file${written.length === 1 ? "" : "s"}).`);
|
|
18632
18797
|
const uses = detail.uses ?? [];
|
|
@@ -18649,13 +18814,13 @@ async function runSkillInstall(positional) {
|
|
|
18649
18814
|
throw err;
|
|
18650
18815
|
}
|
|
18651
18816
|
const root = findGitRoot() ?? process.cwd();
|
|
18652
|
-
const present = HARNESS_SKILL_DIRS.filter((dir) => fs18.existsSync(
|
|
18817
|
+
const present = HARNESS_SKILL_DIRS.filter((dir) => fs18.existsSync(path24.join(root, dir)));
|
|
18653
18818
|
const targets = present.length > 0 ? present : HARNESS_SKILL_DIRS;
|
|
18654
18819
|
const fileCount = Object.keys(res.files).length;
|
|
18655
18820
|
const relDirs = targets.map((harness) => {
|
|
18656
|
-
const targetDir =
|
|
18821
|
+
const targetDir = path24.join(root, harness, "skills", name);
|
|
18657
18822
|
writeFileMap(targetDir, res.files);
|
|
18658
|
-
return `${
|
|
18823
|
+
return `${path24.relative(root, targetDir)}/`;
|
|
18659
18824
|
});
|
|
18660
18825
|
console.log(`Installed skill "${name}" (${fileCount} file${fileCount === 1 ? "" : "s"}) \u2192 ${relDirs.join(", ")}`);
|
|
18661
18826
|
console.log("Reload your agent (e.g. restart Claude Code) to pick up the skill.");
|
|
@@ -19549,6 +19714,9 @@ function friendlyHint(err) {
|
|
|
19549
19714
|
return "Couldn't reach WayAI \u2014 check your network connection and try again.";
|
|
19550
19715
|
}
|
|
19551
19716
|
if (!(err instanceof ApiError)) return null;
|
|
19717
|
+
if (err.body.includes("FREE_PLAN_RESTRICTION")) {
|
|
19718
|
+
return "Publishing to production requires a paid plan. Upgrade your organization to publish or sync.";
|
|
19719
|
+
}
|
|
19552
19720
|
const { status } = err;
|
|
19553
19721
|
if (status === 401) return "Your session may have expired. Run `wayai login` to re-authenticate.";
|
|
19554
19722
|
if (status === 402) return "Quota exceeded for your plan. Review usage or upgrade your plan.";
|
|
@@ -19785,6 +19953,14 @@ async function main() {
|
|
|
19785
19953
|
await relabelCommand2(args);
|
|
19786
19954
|
break;
|
|
19787
19955
|
}
|
|
19956
|
+
// `sync` is a bare alias of `publish` (distinct from `sync-skills` / `sync-mcp`,
|
|
19957
|
+
// which are exact-string cases). Both promote preview → production.
|
|
19958
|
+
case "publish":
|
|
19959
|
+
case "sync": {
|
|
19960
|
+
const { publishCommand: publishCommand2 } = await Promise.resolve().then(() => (init_publish(), publish_exports));
|
|
19961
|
+
await publishCommand2(args);
|
|
19962
|
+
break;
|
|
19963
|
+
}
|
|
19788
19964
|
case "use": {
|
|
19789
19965
|
const { useCommand: useCommand2 } = await Promise.resolve().then(() => (init_use(), use_exports));
|
|
19790
19966
|
await useCommand2(args);
|
|
@@ -19935,6 +20111,8 @@ Commands:
|
|
|
19935
20111
|
diff Dry-run diff of local files vs the platform (--production diffs vs the linked production hub)
|
|
19936
20112
|
replicate Clone a hub into a new sibling preview (--label to name it)
|
|
19937
20113
|
relabel Set a preview hub's label (--clear to remove it)
|
|
20114
|
+
publish Promote the preview to production (first publish clones it; subsequent runs sync changes)
|
|
20115
|
+
sync Alias of \`publish\` (not to be confused with sync-skills / sync-mcp)
|
|
19938
20116
|
org create Create a new organization (you become its owner)
|
|
19939
20117
|
org <pull|push|diff> Sync org-scoped resources as code (wayai-ws/org/)
|
|
19940
20118
|
use <hub> Bind this worktree to a specific hub (UUID or folder name)
|
|
@@ -19960,7 +20138,7 @@ Commands:
|
|
|
19960
20138
|
|
|
19961
20139
|
Flags:
|
|
19962
20140
|
--yes, -y Skip confirmation prompts (useful for CI and scripting)
|
|
19963
|
-
--hub <uuid|name> Target hub when the workspace has more than one (push, pull, diff, replicate, relabel)
|
|
20141
|
+
--hub <uuid|name> Target hub when the workspace has more than one (push, pull, diff, replicate, relabel, publish)
|
|
19964
20142
|
--production Diff local preview files against the linked production hub (diff)
|
|
19965
20143
|
--label <name> Preview label \u2014 for the new sibling (replicate) or a brand-new hub (push on create)
|
|
19966
20144
|
--clear Remove the preview label (relabel)
|