@wayai/cli 0.3.88 → 0.3.90
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 +514 -362
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -82,8 +82,8 @@ import { fileURLToPath } from "url";
|
|
|
82
82
|
import { homedir, platform, arch } from "os";
|
|
83
83
|
function getVersion() {
|
|
84
84
|
try {
|
|
85
|
-
const
|
|
86
|
-
const pkg2 = JSON.parse(readFileSync(join(
|
|
85
|
+
const __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
86
|
+
const pkg2 = JSON.parse(readFileSync(join(__dirname2, "..", "..", "package.json"), "utf-8"));
|
|
87
87
|
return pkg2.version || "0.0.0";
|
|
88
88
|
} catch {
|
|
89
89
|
return "0.0.0";
|
|
@@ -96,16 +96,16 @@ function isInstalledPackage() {
|
|
|
96
96
|
return false;
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
-
function initSentry(command2) {
|
|
99
|
+
function initSentry(command2, version) {
|
|
100
100
|
if (initialized) return;
|
|
101
101
|
if (process.env.WAYAI_TELEMETRY_DISABLED === "1") return;
|
|
102
102
|
const dsn = process.env.SENTRY_DSN || HARDCODED_DSN;
|
|
103
103
|
if (!process.env.SENTRY_DSN && !isInstalledPackage()) return;
|
|
104
|
-
const
|
|
104
|
+
const resolvedVersion = version ?? getVersion();
|
|
105
105
|
Sentry.init({
|
|
106
106
|
dsn,
|
|
107
107
|
tracesSampleRate: 0,
|
|
108
|
-
release: `wayai-cli@${
|
|
108
|
+
release: `wayai-cli@${resolvedVersion}`,
|
|
109
109
|
environment: "production",
|
|
110
110
|
defaultIntegrations: false,
|
|
111
111
|
beforeSend(event) {
|
|
@@ -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, path27) {
|
|
169
169
|
if (!initialized) return;
|
|
170
170
|
Sentry.addBreadcrumb({
|
|
171
171
|
category: "http",
|
|
172
|
-
message: `${method} ${
|
|
172
|
+
message: `${method} ${path27}`,
|
|
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, path27, status, body) {
|
|
235
235
|
const safeBody = redactSecrets(body);
|
|
236
|
-
super(`API request failed: ${method} ${
|
|
236
|
+
super(`API request failed: ${method} ${path27} (${status}): ${safeBody}`);
|
|
237
237
|
this.name = "ApiError";
|
|
238
238
|
this.status = status;
|
|
239
239
|
this.body = safeBody;
|
|
@@ -376,8 +376,8 @@ var init_api_client = __esm({
|
|
|
376
376
|
...organizationId && { organization_id: organizationId }
|
|
377
377
|
});
|
|
378
378
|
}
|
|
379
|
-
async lookup(
|
|
380
|
-
const params = new URLSearchParams({ path:
|
|
379
|
+
async lookup(path27, opts) {
|
|
380
|
+
const params = new URLSearchParams({ path: path27 });
|
|
381
381
|
if (opts?.organizationId) params.set("organization_id", opts.organizationId);
|
|
382
382
|
return this.request("GET", `/api/ci/lookup?${params.toString()}`);
|
|
383
383
|
}
|
|
@@ -765,9 +765,9 @@ var init_api_client = __esm({
|
|
|
765
765
|
* sandbox for this conversation, or the blob was purged).
|
|
766
766
|
*/
|
|
767
767
|
async downloadArchiveSandboxFs(hubId, conversationId) {
|
|
768
|
-
const
|
|
769
|
-
addApiBreadcrumb("GET",
|
|
770
|
-
const url = `${this.apiUrl}${
|
|
768
|
+
const path27 = `/api/archive/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}/sandbox`;
|
|
769
|
+
addApiBreadcrumb("GET", path27);
|
|
770
|
+
const url = `${this.apiUrl}${path27}`;
|
|
771
771
|
let response = await this.send(url, "GET");
|
|
772
772
|
if (response.status === 401 && this.onUnauthorized) {
|
|
773
773
|
let refreshed;
|
|
@@ -781,7 +781,7 @@ var init_api_client = __esm({
|
|
|
781
781
|
}
|
|
782
782
|
}
|
|
783
783
|
if (!response.ok) {
|
|
784
|
-
throw new ApiError("GET",
|
|
784
|
+
throw new ApiError("GET", path27, response.status, await response.text());
|
|
785
785
|
}
|
|
786
786
|
return new Uint8Array(await response.arrayBuffer());
|
|
787
787
|
}
|
|
@@ -821,9 +821,9 @@ var init_api_client = __esm({
|
|
|
821
821
|
`/api/admin/data-explorer/debug/observability/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}${qs}`
|
|
822
822
|
);
|
|
823
823
|
}
|
|
824
|
-
async request(method,
|
|
825
|
-
addApiBreadcrumb(method,
|
|
826
|
-
const url = `${this.apiUrl}${
|
|
824
|
+
async request(method, path27, body) {
|
|
825
|
+
addApiBreadcrumb(method, path27);
|
|
826
|
+
const url = `${this.apiUrl}${path27}`;
|
|
827
827
|
let refreshedOn401 = false;
|
|
828
828
|
for (let retry = 0; ; retry++) {
|
|
829
829
|
let response = await this.send(url, method, body);
|
|
@@ -847,7 +847,7 @@ var init_api_client = __esm({
|
|
|
847
847
|
await delay(RETRYABLE_BACKOFF_MS[retry]);
|
|
848
848
|
continue;
|
|
849
849
|
}
|
|
850
|
-
throw new ApiError(method,
|
|
850
|
+
throw new ApiError(method, path27, response.status, errorBody);
|
|
851
851
|
}
|
|
852
852
|
}
|
|
853
853
|
/** Issue a single authenticated request with the client's current token. */
|
|
@@ -1282,8 +1282,8 @@ var init_parseUtil = __esm({
|
|
|
1282
1282
|
init_errors();
|
|
1283
1283
|
init_en();
|
|
1284
1284
|
makeIssue = (params) => {
|
|
1285
|
-
const { data, path:
|
|
1286
|
-
const fullPath = [...
|
|
1285
|
+
const { data, path: path27, errorMaps, issueData } = params;
|
|
1286
|
+
const fullPath = [...path27, ...issueData.path || []];
|
|
1287
1287
|
const fullIssue = {
|
|
1288
1288
|
...issueData,
|
|
1289
1289
|
path: fullPath
|
|
@@ -1594,11 +1594,11 @@ var init_types = __esm({
|
|
|
1594
1594
|
init_parseUtil();
|
|
1595
1595
|
init_util();
|
|
1596
1596
|
ParseInputLazyPath = class {
|
|
1597
|
-
constructor(parent, value,
|
|
1597
|
+
constructor(parent, value, path27, key) {
|
|
1598
1598
|
this._cachedPath = [];
|
|
1599
1599
|
this.parent = parent;
|
|
1600
1600
|
this.data = value;
|
|
1601
|
-
this._path =
|
|
1601
|
+
this._path = path27;
|
|
1602
1602
|
this._key = key;
|
|
1603
1603
|
}
|
|
1604
1604
|
get path() {
|
|
@@ -5052,12 +5052,12 @@ function typeMatches(typeField, allowed) {
|
|
|
5052
5052
|
if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
|
|
5053
5053
|
return false;
|
|
5054
5054
|
}
|
|
5055
|
-
function validateSchema(schema,
|
|
5055
|
+
function validateSchema(schema, path27, errors, opts = {}) {
|
|
5056
5056
|
if (typeof schema === "boolean") return;
|
|
5057
5057
|
const depth = opts.depth ?? 0;
|
|
5058
5058
|
if (depth > MAX_SCHEMA_DEPTH) {
|
|
5059
5059
|
errors.push({
|
|
5060
|
-
path:
|
|
5060
|
+
path: path27 || "<root>",
|
|
5061
5061
|
message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH} levels`,
|
|
5062
5062
|
suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
|
|
5063
5063
|
});
|
|
@@ -5065,7 +5065,7 @@ function validateSchema(schema, path26, errors, opts = {}) {
|
|
|
5065
5065
|
}
|
|
5066
5066
|
if (!isRecord(schema)) {
|
|
5067
5067
|
errors.push({
|
|
5068
|
-
path:
|
|
5068
|
+
path: path27,
|
|
5069
5069
|
message: `expected object, got ${schema === null ? "null" : typeof schema}`
|
|
5070
5070
|
});
|
|
5071
5071
|
return;
|
|
@@ -5073,14 +5073,14 @@ function validateSchema(schema, path26, errors, opts = {}) {
|
|
|
5073
5073
|
if (opts.isRoot) {
|
|
5074
5074
|
if ("type" in schema && schema.type !== "object") {
|
|
5075
5075
|
errors.push({
|
|
5076
|
-
path:
|
|
5076
|
+
path: path27 ? `${path27}.type` : "type",
|
|
5077
5077
|
message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
|
|
5078
5078
|
suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
|
|
5079
5079
|
});
|
|
5080
5080
|
}
|
|
5081
5081
|
} else if ("type" in schema && !typeMatches(schema.type, ALLOWED_TYPES)) {
|
|
5082
5082
|
errors.push({
|
|
5083
|
-
path: `${
|
|
5083
|
+
path: `${path27}.type`,
|
|
5084
5084
|
message: `type must be one of ${[...ALLOWED_TYPES].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
|
|
5085
5085
|
});
|
|
5086
5086
|
}
|
|
@@ -5089,25 +5089,25 @@ function validateSchema(schema, path26, errors, opts = {}) {
|
|
|
5089
5089
|
if (typeof e === "string") {
|
|
5090
5090
|
const isPlaceholder = PLACEHOLDER_TOKENS.includes(e);
|
|
5091
5091
|
errors.push({
|
|
5092
|
-
path: `${
|
|
5092
|
+
path: `${path27}.enum`,
|
|
5093
5093
|
message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
|
|
5094
5094
|
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"]`.'
|
|
5095
5095
|
});
|
|
5096
5096
|
} else if (!Array.isArray(e)) {
|
|
5097
5097
|
errors.push({
|
|
5098
|
-
path: `${
|
|
5098
|
+
path: `${path27}.enum`,
|
|
5099
5099
|
message: `enum must be a non-empty array of primitives, got ${typeof e}`
|
|
5100
5100
|
});
|
|
5101
5101
|
} else if (e.length === 0) {
|
|
5102
5102
|
errors.push({
|
|
5103
|
-
path: `${
|
|
5103
|
+
path: `${path27}.enum`,
|
|
5104
5104
|
message: "enum must not be empty"
|
|
5105
5105
|
});
|
|
5106
5106
|
} else {
|
|
5107
5107
|
for (let i = 0; i < e.length; i++) {
|
|
5108
5108
|
if (!isPrimitive(e[i])) {
|
|
5109
5109
|
errors.push({
|
|
5110
|
-
path: `${
|
|
5110
|
+
path: `${path27}.enum[${i}]`,
|
|
5111
5111
|
message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
|
|
5112
5112
|
});
|
|
5113
5113
|
}
|
|
@@ -5117,7 +5117,7 @@ function validateSchema(schema, path26, errors, opts = {}) {
|
|
|
5117
5117
|
for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
|
|
5118
5118
|
if (key in schema && typeof schema[key] === "boolean") {
|
|
5119
5119
|
errors.push({
|
|
5120
|
-
path: `${
|
|
5120
|
+
path: `${path27}.${key}`,
|
|
5121
5121
|
message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
|
|
5122
5122
|
suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
|
|
5123
5123
|
});
|
|
@@ -5126,45 +5126,45 @@ function validateSchema(schema, path26, errors, opts = {}) {
|
|
|
5126
5126
|
if ("properties" in schema) {
|
|
5127
5127
|
if (!isRecord(schema.properties)) {
|
|
5128
5128
|
errors.push({
|
|
5129
|
-
path: `${
|
|
5129
|
+
path: `${path27}.properties`,
|
|
5130
5130
|
message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
|
|
5131
5131
|
});
|
|
5132
5132
|
} else {
|
|
5133
5133
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
5134
|
-
validateSchema(propSchema, `${
|
|
5134
|
+
validateSchema(propSchema, `${path27}.properties.${propName}`, errors, { depth: depth + 1 });
|
|
5135
5135
|
}
|
|
5136
5136
|
}
|
|
5137
5137
|
}
|
|
5138
5138
|
if (schemaTypeIncludes(schema, "array") && "items" in schema) {
|
|
5139
5139
|
if (Array.isArray(schema.items)) {
|
|
5140
|
-
schema.items.forEach((sub, i) => validateSchema(sub, `${
|
|
5140
|
+
schema.items.forEach((sub, i) => validateSchema(sub, `${path27}.items[${i}]`, errors, { depth: depth + 1 }));
|
|
5141
5141
|
} else {
|
|
5142
|
-
validateSchema(schema.items, `${
|
|
5142
|
+
validateSchema(schema.items, `${path27}.items`, errors, { depth: depth + 1 });
|
|
5143
5143
|
}
|
|
5144
5144
|
}
|
|
5145
5145
|
for (const key of SUBSCHEMA_OBJECT_KEYWORDS) {
|
|
5146
5146
|
if (key in schema && isRecord(schema[key])) {
|
|
5147
|
-
validateSchema(schema[key], `${
|
|
5147
|
+
validateSchema(schema[key], `${path27}.${key}`, errors, { depth: depth + 1 });
|
|
5148
5148
|
}
|
|
5149
5149
|
}
|
|
5150
5150
|
for (const key of SUBSCHEMA_LIST_KEYWORDS) {
|
|
5151
5151
|
const list = schema[key];
|
|
5152
5152
|
if (Array.isArray(list)) {
|
|
5153
|
-
list.forEach((sub, i) => validateSchema(sub, `${
|
|
5153
|
+
list.forEach((sub, i) => validateSchema(sub, `${path27}.${key}[${i}]`, errors, { depth: depth + 1 }));
|
|
5154
5154
|
}
|
|
5155
5155
|
}
|
|
5156
5156
|
for (const key of SUBSCHEMA_MAP_KEYWORDS) {
|
|
5157
5157
|
const map = schema[key];
|
|
5158
5158
|
if (isRecord(map)) {
|
|
5159
5159
|
for (const [name, sub] of Object.entries(map)) {
|
|
5160
|
-
validateSchema(sub, `${
|
|
5160
|
+
validateSchema(sub, `${path27}.${key}.${name}`, errors, { depth: depth + 1 });
|
|
5161
5161
|
}
|
|
5162
5162
|
}
|
|
5163
5163
|
}
|
|
5164
5164
|
const reportedPaths = new Set(errors.map((e) => e.path));
|
|
5165
5165
|
for (const [k, v] of Object.entries(schema)) {
|
|
5166
5166
|
if (typeof v !== "string") continue;
|
|
5167
|
-
const fieldPath = `${
|
|
5167
|
+
const fieldPath = `${path27}.${k}`;
|
|
5168
5168
|
if (reportedPaths.has(fieldPath)) continue;
|
|
5169
5169
|
for (const token of PLACEHOLDER_TOKENS) {
|
|
5170
5170
|
if (v === token) {
|
|
@@ -5320,10 +5320,10 @@ function refineHubAsCodeLanes(config, ctx) {
|
|
|
5320
5320
|
}
|
|
5321
5321
|
}
|
|
5322
5322
|
}
|
|
5323
|
-
function isSafeTemplatePath(
|
|
5324
|
-
if (
|
|
5325
|
-
if (
|
|
5326
|
-
const segments =
|
|
5323
|
+
function isSafeTemplatePath(path27) {
|
|
5324
|
+
if (path27.length === 0 || path27.length > 300) return false;
|
|
5325
|
+
if (path27.startsWith("/") || path27.includes("\\")) return false;
|
|
5326
|
+
const segments = path27.split("/");
|
|
5327
5327
|
return segments.every(
|
|
5328
5328
|
(seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
|
|
5329
5329
|
);
|
|
@@ -8795,9 +8795,9 @@ function getVersionCachePath(filename = CLI_CACHE_FILE) {
|
|
|
8795
8795
|
}
|
|
8796
8796
|
function readVersionCache(filename = CLI_CACHE_FILE) {
|
|
8797
8797
|
try {
|
|
8798
|
-
const
|
|
8799
|
-
if (!existsSync4(
|
|
8800
|
-
const parsed = JSON.parse(readFileSync5(
|
|
8798
|
+
const path27 = getVersionCachePath(filename);
|
|
8799
|
+
if (!existsSync4(path27)) return null;
|
|
8800
|
+
const parsed = JSON.parse(readFileSync5(path27, "utf-8"));
|
|
8801
8801
|
if (typeof parsed.lastCheck !== "number") return null;
|
|
8802
8802
|
if (parsed.latest !== null && typeof parsed.latest !== "string") return null;
|
|
8803
8803
|
return parsed;
|
|
@@ -8817,10 +8817,10 @@ function isVersionCacheStale(filename = CLI_CACHE_FILE, maxAgeMs = MAX_AGE_24H_M
|
|
|
8817
8817
|
return Date.now() - cache.lastCheck > maxAgeMs;
|
|
8818
8818
|
}
|
|
8819
8819
|
function writeVersionCache(filename, cache) {
|
|
8820
|
-
const
|
|
8821
|
-
const dir = dirname3(
|
|
8820
|
+
const path27 = getVersionCachePath(filename);
|
|
8821
|
+
const dir = dirname3(path27);
|
|
8822
8822
|
if (!existsSync4(dir)) mkdirSync(dir, { recursive: true });
|
|
8823
|
-
writeFileSync2(
|
|
8823
|
+
writeFileSync2(path27, JSON.stringify(cache));
|
|
8824
8824
|
}
|
|
8825
8825
|
function touchVersionCache(filename) {
|
|
8826
8826
|
writeVersionCache(filename, { lastCheck: Date.now(), latest: readVersionCache(filename)?.latest ?? null });
|
|
@@ -8859,14 +8859,14 @@ function parseFrontmatterVersion(content) {
|
|
|
8859
8859
|
function findInstalledSkills(projectRoot, paths = SKILL_INSTALL_PATHS) {
|
|
8860
8860
|
const found = [];
|
|
8861
8861
|
for (const rel of paths) {
|
|
8862
|
-
const
|
|
8863
|
-
if (!existsSync5(
|
|
8862
|
+
const path27 = join7(projectRoot, rel);
|
|
8863
|
+
if (!existsSync5(path27)) continue;
|
|
8864
8864
|
let version = null;
|
|
8865
8865
|
try {
|
|
8866
|
-
version = parseFrontmatterVersion(readFileSync6(
|
|
8866
|
+
version = parseFrontmatterVersion(readFileSync6(path27, "utf-8"));
|
|
8867
8867
|
} catch {
|
|
8868
8868
|
}
|
|
8869
|
-
found.push({ path:
|
|
8869
|
+
found.push({ path: path27, version });
|
|
8870
8870
|
}
|
|
8871
8871
|
return found;
|
|
8872
8872
|
}
|
|
@@ -10099,6 +10099,85 @@ var init_constants = __esm({
|
|
|
10099
10099
|
}
|
|
10100
10100
|
});
|
|
10101
10101
|
|
|
10102
|
+
// src/lib/workspace-files.ts
|
|
10103
|
+
import * as fs8 from "fs";
|
|
10104
|
+
import * as path9 from "path";
|
|
10105
|
+
function perHubAgentsMd(hubFolderName) {
|
|
10106
|
+
return [
|
|
10107
|
+
`# ${hubFolderName}`,
|
|
10108
|
+
"",
|
|
10109
|
+
"Notes about THIS hub that the config files (hub.yaml, agents/) don't capture:",
|
|
10110
|
+
"why it exists, key decisions and the reasons behind them, business rules that",
|
|
10111
|
+
"only apply here, terminology, integration quirks.",
|
|
10112
|
+
"",
|
|
10113
|
+
"Keep it short and about *why / what is different* \u2014 platform mechanics live in",
|
|
10114
|
+
"the WayAI skill. Fill this in as you learn about the hub; delete this",
|
|
10115
|
+
"placeholder once you do.",
|
|
10116
|
+
""
|
|
10117
|
+
].join("\n");
|
|
10118
|
+
}
|
|
10119
|
+
function isWorkspace(gitRoot) {
|
|
10120
|
+
if (fs8.existsSync(path9.join(gitRoot, ".wayai.yaml"))) return true;
|
|
10121
|
+
return isDirectory(resolveLayout(gitRoot).hubsDir);
|
|
10122
|
+
}
|
|
10123
|
+
function writeIfAbsent(filePath, content) {
|
|
10124
|
+
if (fs8.existsSync(filePath)) return null;
|
|
10125
|
+
fs8.writeFileSync(filePath, content, "utf-8");
|
|
10126
|
+
return path9.basename(filePath);
|
|
10127
|
+
}
|
|
10128
|
+
function ensureWorkspaceFiles(gitRoot) {
|
|
10129
|
+
if (!isWorkspace(gitRoot)) return [];
|
|
10130
|
+
const created = [];
|
|
10131
|
+
const agents = writeIfAbsent(path9.join(gitRoot, "AGENTS.md"), ROOT_AGENTS_MD);
|
|
10132
|
+
if (agents) created.push(agents);
|
|
10133
|
+
const claude = writeIfAbsent(path9.join(gitRoot, "CLAUDE.md"), CLAUDE_MD_SHIM);
|
|
10134
|
+
if (claude) created.push(claude);
|
|
10135
|
+
return created;
|
|
10136
|
+
}
|
|
10137
|
+
var REKOR_SKILL_INSTALL_COMMAND, CLAUDE_MD_SHIM, ROOT_AGENTS_MD;
|
|
10138
|
+
var init_workspace_files = __esm({
|
|
10139
|
+
"src/lib/workspace-files.ts"() {
|
|
10140
|
+
"use strict";
|
|
10141
|
+
init_constants();
|
|
10142
|
+
init_layout();
|
|
10143
|
+
REKOR_SKILL_INSTALL_COMMAND = SKILL_INSTALL_COMMAND.replace(
|
|
10144
|
+
"wayai-pro/wayai-skill",
|
|
10145
|
+
"wayai-pro/rekor-skill"
|
|
10146
|
+
);
|
|
10147
|
+
CLAUDE_MD_SHIM = "@AGENTS.md\n";
|
|
10148
|
+
ROOT_AGENTS_MD = [
|
|
10149
|
+
"# Working with WayAI and Rekor",
|
|
10150
|
+
"",
|
|
10151
|
+
"WayAI is the layer that talks to people across channels; Rekor is the data",
|
|
10152
|
+
"layer (system of record) behind it. They are used together.",
|
|
10153
|
+
"",
|
|
10154
|
+
"## At the start of every session",
|
|
10155
|
+
"",
|
|
10156
|
+
"1. Check for updates first. Make sure both skills and both CLIs are current,",
|
|
10157
|
+
" and update whatever is not:",
|
|
10158
|
+
` - WayAI skill: \`wayai status\` \u2192 if newer, \`${SKILL_INSTALL_COMMAND}\``,
|
|
10159
|
+
` - Rekor skill: \`rekor status\` \u2192 if newer, \`${REKOR_SKILL_INSTALL_COMMAND}\``,
|
|
10160
|
+
" - CLIs: `wayai update` and `rekor update`",
|
|
10161
|
+
"2. Load both the WayAI and Rekor skills at the start of every session \u2014 every",
|
|
10162
|
+
" time, even for a quick task. They hold the real instructions for everything",
|
|
10163
|
+
" else.",
|
|
10164
|
+
"",
|
|
10165
|
+
"More detail if you need it:",
|
|
10166
|
+
"- WayAI: https://www.wayai.pro/docs/get-started",
|
|
10167
|
+
"- Rekor: https://rekor.pro/en/docs/get-started",
|
|
10168
|
+
"",
|
|
10169
|
+
"## When helping the person you are working with",
|
|
10170
|
+
"",
|
|
10171
|
+
"- They may be new to WayAI and Rekor \u2014 use plain language, not jargon.",
|
|
10172
|
+
"- Don't explain things they didn't ask about. Only if they seem stuck or ask",
|
|
10173
|
+
" what something means, give a one-line answer, then move on \u2014 don't turn",
|
|
10174
|
+
" replies into tutorials.",
|
|
10175
|
+
"- Keep answers short and to the point.",
|
|
10176
|
+
""
|
|
10177
|
+
].join("\n");
|
|
10178
|
+
}
|
|
10179
|
+
});
|
|
10180
|
+
|
|
10102
10181
|
// src/commands/init.ts
|
|
10103
10182
|
var init_exports = {};
|
|
10104
10183
|
__export(init_exports, {
|
|
@@ -10108,12 +10187,12 @@ __export(init_exports, {
|
|
|
10108
10187
|
parseArgs: () => parseArgs3
|
|
10109
10188
|
});
|
|
10110
10189
|
import { mkdirSync as mkdirSync5 } from "fs";
|
|
10111
|
-
import
|
|
10190
|
+
import path10 from "path";
|
|
10112
10191
|
function ensureHubsDir(gitRoot) {
|
|
10113
10192
|
const hubsDir = resolveLayout(gitRoot).hubsDir;
|
|
10114
10193
|
if (isDirectory(hubsDir)) return null;
|
|
10115
10194
|
mkdirSync5(hubsDir, { recursive: true });
|
|
10116
|
-
return `${
|
|
10195
|
+
return `${path10.relative(gitRoot, hubsDir)}/`;
|
|
10117
10196
|
}
|
|
10118
10197
|
function parseArgs3(args2) {
|
|
10119
10198
|
let orgId;
|
|
@@ -10156,6 +10235,9 @@ async function initCommand(args2) {
|
|
|
10156
10235
|
if (createdDir) {
|
|
10157
10236
|
console.log(`Created ${createdDir}`);
|
|
10158
10237
|
}
|
|
10238
|
+
for (const file of ensureWorkspaceFiles(gitRoot)) {
|
|
10239
|
+
console.log(`Created ${file}`);
|
|
10240
|
+
}
|
|
10159
10241
|
}
|
|
10160
10242
|
console.log(
|
|
10161
10243
|
`Run \`${SKILL_INSTALL_CMD}\` to install the WayAI skill in your AI harness, then \`wayai pull\` to fetch hub configuration.`
|
|
@@ -10236,6 +10318,7 @@ var init_init = __esm({
|
|
|
10236
10318
|
init_repo_config();
|
|
10237
10319
|
init_workspace();
|
|
10238
10320
|
init_layout();
|
|
10321
|
+
init_workspace_files();
|
|
10239
10322
|
init_utils();
|
|
10240
10323
|
init_constants();
|
|
10241
10324
|
SKILL_INSTALL_CMD = SKILL_INSTALL_COMMAND;
|
|
@@ -10243,8 +10326,8 @@ var init_init = __esm({
|
|
|
10243
10326
|
});
|
|
10244
10327
|
|
|
10245
10328
|
// src/lib/resource-files.ts
|
|
10246
|
-
import * as
|
|
10247
|
-
import * as
|
|
10329
|
+
import * as fs9 from "fs";
|
|
10330
|
+
import * as path11 from "path";
|
|
10248
10331
|
import * as crypto3 from "crypto";
|
|
10249
10332
|
function isBinaryFile(filename) {
|
|
10250
10333
|
const ext = filename.split(".").pop()?.toLowerCase() || "";
|
|
@@ -10290,14 +10373,14 @@ function computeHash(data) {
|
|
|
10290
10373
|
}
|
|
10291
10374
|
function scanResourceFiles(dir, prefix = "") {
|
|
10292
10375
|
const files = [];
|
|
10293
|
-
const entries =
|
|
10376
|
+
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
10294
10377
|
for (const entry of entries) {
|
|
10295
10378
|
const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
10296
10379
|
if (entry.isDirectory()) {
|
|
10297
|
-
files.push(...scanResourceFiles(
|
|
10380
|
+
files.push(...scanResourceFiles(path11.join(dir, entry.name), relPath));
|
|
10298
10381
|
} else if (entry.isFile()) {
|
|
10299
|
-
const fullPath =
|
|
10300
|
-
const stat =
|
|
10382
|
+
const fullPath = path11.join(dir, entry.name);
|
|
10383
|
+
const stat = fs9.statSync(fullPath);
|
|
10301
10384
|
if (stat.size > MAX_RESOURCE_FILE_SIZE2) {
|
|
10302
10385
|
console.warn(` Warning: skipping ${relPath} (${(stat.size / 1024 / 1024).toFixed(1)}MB exceeds 10MB limit)`);
|
|
10303
10386
|
continue;
|
|
@@ -10307,7 +10390,7 @@ function scanResourceFiles(dir, prefix = "") {
|
|
|
10307
10390
|
mime_type: guessMimeType(entry.name),
|
|
10308
10391
|
file_size: stat.size
|
|
10309
10392
|
};
|
|
10310
|
-
const data =
|
|
10393
|
+
const data = fs9.readFileSync(fullPath);
|
|
10311
10394
|
fileEntry.hash = computeHash(data);
|
|
10312
10395
|
if (isBinaryFile(entry.name)) {
|
|
10313
10396
|
fileEntry.content_base64 = data.toString("base64");
|
|
@@ -10321,37 +10404,37 @@ function scanResourceFiles(dir, prefix = "") {
|
|
|
10321
10404
|
}
|
|
10322
10405
|
function writeResourceFileTree(resDir, files) {
|
|
10323
10406
|
if (files.length === 0) {
|
|
10324
|
-
if (
|
|
10407
|
+
if (fs9.existsSync(resDir)) cleanOrphanFiles(resDir, "", /* @__PURE__ */ new Set());
|
|
10325
10408
|
return;
|
|
10326
10409
|
}
|
|
10327
10410
|
const writtenPaths = /* @__PURE__ */ new Set();
|
|
10328
10411
|
for (const file of files) {
|
|
10329
|
-
const filePath =
|
|
10330
|
-
if (!filePath.startsWith(resDir +
|
|
10412
|
+
const filePath = path11.join(resDir, file.path);
|
|
10413
|
+
if (!filePath.startsWith(resDir + path11.sep) && filePath !== resDir) {
|
|
10331
10414
|
console.warn(` Warning: skipping ${file.path} (path traversal detected)`);
|
|
10332
10415
|
continue;
|
|
10333
10416
|
}
|
|
10334
|
-
const fileDir =
|
|
10335
|
-
if (!
|
|
10417
|
+
const fileDir = path11.dirname(filePath);
|
|
10418
|
+
if (!fs9.existsSync(fileDir)) fs9.mkdirSync(fileDir, { recursive: true });
|
|
10336
10419
|
writtenPaths.add(file.path);
|
|
10337
10420
|
if (file.content !== void 0) {
|
|
10338
|
-
|
|
10421
|
+
fs9.writeFileSync(filePath, file.content, "utf-8");
|
|
10339
10422
|
} else if (file.content_base64) {
|
|
10340
|
-
|
|
10423
|
+
fs9.writeFileSync(filePath, Buffer.from(file.content_base64, "base64"));
|
|
10341
10424
|
}
|
|
10342
10425
|
}
|
|
10343
|
-
if (
|
|
10426
|
+
if (fs9.existsSync(resDir)) cleanOrphanFiles(resDir, "", writtenPaths);
|
|
10344
10427
|
}
|
|
10345
10428
|
function cleanOrphanFiles(dir, prefix, writtenPaths) {
|
|
10346
|
-
const entries =
|
|
10429
|
+
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
10347
10430
|
for (const entry of entries) {
|
|
10348
10431
|
const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
10349
|
-
const fullPath =
|
|
10432
|
+
const fullPath = path11.join(dir, entry.name);
|
|
10350
10433
|
if (entry.isDirectory()) {
|
|
10351
10434
|
cleanOrphanFiles(fullPath, relPath, writtenPaths);
|
|
10352
|
-
if (
|
|
10435
|
+
if (fs9.readdirSync(fullPath).length === 0) fs9.rmdirSync(fullPath);
|
|
10353
10436
|
} else if (!writtenPaths.has(relPath)) {
|
|
10354
|
-
|
|
10437
|
+
fs9.unlinkSync(fullPath);
|
|
10355
10438
|
}
|
|
10356
10439
|
}
|
|
10357
10440
|
}
|
|
@@ -10360,8 +10443,8 @@ async function downloadBinaryFiles(resDir, files) {
|
|
|
10360
10443
|
for (const file of files) {
|
|
10361
10444
|
if (!file.download_url || file.content !== void 0) continue;
|
|
10362
10445
|
try {
|
|
10363
|
-
const filePath =
|
|
10364
|
-
if (!filePath.startsWith(resDir +
|
|
10446
|
+
const filePath = path11.join(resDir, file.path);
|
|
10447
|
+
if (!filePath.startsWith(resDir + path11.sep) && filePath !== resDir) {
|
|
10365
10448
|
console.warn(` Warning: skipping ${file.path} (path traversal detected)`);
|
|
10366
10449
|
continue;
|
|
10367
10450
|
}
|
|
@@ -10371,9 +10454,9 @@ async function downloadBinaryFiles(resDir, files) {
|
|
|
10371
10454
|
continue;
|
|
10372
10455
|
}
|
|
10373
10456
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
10374
|
-
const fileDir =
|
|
10375
|
-
if (!
|
|
10376
|
-
|
|
10457
|
+
const fileDir = path11.dirname(filePath);
|
|
10458
|
+
if (!fs9.existsSync(fileDir)) fs9.mkdirSync(fileDir, { recursive: true });
|
|
10459
|
+
fs9.writeFileSync(filePath, buffer);
|
|
10377
10460
|
count++;
|
|
10378
10461
|
} catch (err) {
|
|
10379
10462
|
console.warn(` Warning: failed to download ${file.path} (${err instanceof Error ? err.message : String(err)})`);
|
|
@@ -10410,8 +10493,8 @@ var init_resource_files = __esm({
|
|
|
10410
10493
|
});
|
|
10411
10494
|
|
|
10412
10495
|
// src/lib/yaml-writer.ts
|
|
10413
|
-
import * as
|
|
10414
|
-
import * as
|
|
10496
|
+
import * as fs10 from "fs";
|
|
10497
|
+
import * as path12 from "path";
|
|
10415
10498
|
import * as yaml4 from "js-yaml";
|
|
10416
10499
|
function buildEvalYamlObject(evalEntry, slug) {
|
|
10417
10500
|
const out = {};
|
|
@@ -10444,43 +10527,43 @@ function buildEvalYamlObject(evalEntry, slug) {
|
|
|
10444
10527
|
}
|
|
10445
10528
|
return out;
|
|
10446
10529
|
}
|
|
10447
|
-
function writeHubFolder(hubFolder, payload) {
|
|
10448
|
-
const agentsDir =
|
|
10449
|
-
if (!
|
|
10450
|
-
|
|
10530
|
+
function writeHubFolder(hubFolder, payload, options = {}) {
|
|
10531
|
+
const agentsDir = path12.join(hubFolder, "agents");
|
|
10532
|
+
if (!fs10.existsSync(hubFolder)) {
|
|
10533
|
+
fs10.mkdirSync(hubFolder, { recursive: true });
|
|
10451
10534
|
}
|
|
10452
|
-
if (!
|
|
10453
|
-
|
|
10535
|
+
if (!fs10.existsSync(agentsDir)) {
|
|
10536
|
+
fs10.mkdirSync(agentsDir, { recursive: true });
|
|
10454
10537
|
}
|
|
10455
10538
|
const yamlPayload = buildYamlPayload(payload);
|
|
10456
10539
|
const agentFiles = extractAgentFiles(payload);
|
|
10457
10540
|
const yamlContent = yaml4.dump(yamlPayload, YAML_DUMP_OPTIONS);
|
|
10458
|
-
|
|
10459
|
-
|
|
10460
|
-
|
|
10461
|
-
|
|
10541
|
+
fs10.writeFileSync(path12.join(hubFolder, "hub.yaml"), yamlContent, "utf-8");
|
|
10542
|
+
if (options.seedAgentContext ?? true) {
|
|
10543
|
+
writeIfAbsent(path12.join(hubFolder, "AGENTS.md"), perHubAgentsMd(path12.basename(hubFolder)));
|
|
10544
|
+
writeIfAbsent(path12.join(hubFolder, "CLAUDE.md"), CLAUDE_MD_SHIM);
|
|
10462
10545
|
}
|
|
10463
|
-
const oldYamlPath =
|
|
10464
|
-
if (
|
|
10465
|
-
|
|
10546
|
+
const oldYamlPath = path12.join(hubFolder, "wayai.yaml");
|
|
10547
|
+
if (fs10.existsSync(oldYamlPath)) {
|
|
10548
|
+
fs10.unlinkSync(oldYamlPath);
|
|
10466
10549
|
}
|
|
10467
10550
|
const yamlSlugs = writeAgentYamlFiles(agentsDir, payload.agents || []);
|
|
10468
10551
|
const mdSlugs = /* @__PURE__ */ new Set();
|
|
10469
10552
|
for (const { slug, content } of agentFiles) {
|
|
10470
10553
|
mdSlugs.add(slug);
|
|
10471
|
-
|
|
10554
|
+
fs10.writeFileSync(path12.join(agentsDir, `${slug}.md`), content, "utf-8");
|
|
10472
10555
|
}
|
|
10473
|
-
const existingFiles =
|
|
10556
|
+
const existingFiles = fs10.readdirSync(agentsDir);
|
|
10474
10557
|
for (const file of existingFiles) {
|
|
10475
10558
|
if (file.endsWith(".yaml")) {
|
|
10476
10559
|
const slug = file.slice(0, -5);
|
|
10477
10560
|
if (!yamlSlugs.has(slug)) {
|
|
10478
|
-
|
|
10561
|
+
fs10.unlinkSync(path12.join(agentsDir, file));
|
|
10479
10562
|
}
|
|
10480
10563
|
} else if (file.endsWith(".md")) {
|
|
10481
10564
|
const slug = file.slice(0, -3);
|
|
10482
10565
|
if (!mdSlugs.has(slug)) {
|
|
10483
|
-
|
|
10566
|
+
fs10.unlinkSync(path12.join(agentsDir, file));
|
|
10484
10567
|
}
|
|
10485
10568
|
}
|
|
10486
10569
|
}
|
|
@@ -10491,10 +10574,10 @@ function writeHubFolder(hubFolder, payload) {
|
|
|
10491
10574
|
function setPreviewLabelInHubYaml(hubFolder, label) {
|
|
10492
10575
|
const yamlPath = resolveHubYamlPath(hubFolder);
|
|
10493
10576
|
if (!yamlPath) return;
|
|
10494
|
-
const obj = yaml4.load(
|
|
10577
|
+
const obj = yaml4.load(fs10.readFileSync(yamlPath, "utf-8")) ?? {};
|
|
10495
10578
|
if (label) obj.preview_label = label;
|
|
10496
10579
|
else delete obj.preview_label;
|
|
10497
|
-
|
|
10580
|
+
fs10.writeFileSync(yamlPath, yaml4.dump(obj, YAML_DUMP_OPTIONS), "utf-8");
|
|
10498
10581
|
}
|
|
10499
10582
|
function buildYamlPayload(payload) {
|
|
10500
10583
|
const result = {
|
|
@@ -10540,7 +10623,7 @@ function writeAgentYamlFiles(agentsDir, agents) {
|
|
|
10540
10623
|
const entry = { ...agent };
|
|
10541
10624
|
delete entry.instructions;
|
|
10542
10625
|
const yamlContent = yaml4.dump(entry, YAML_DUMP_OPTIONS);
|
|
10543
|
-
|
|
10626
|
+
fs10.writeFileSync(path12.join(agentsDir, `${slug}.yaml`), yamlContent, "utf-8");
|
|
10544
10627
|
}
|
|
10545
10628
|
return slugs;
|
|
10546
10629
|
}
|
|
@@ -10557,65 +10640,65 @@ function extractAgentFiles(payload) {
|
|
|
10557
10640
|
return files;
|
|
10558
10641
|
}
|
|
10559
10642
|
function writeEvalYamlFiles(hubFolder, evals) {
|
|
10560
|
-
const evalsDir =
|
|
10643
|
+
const evalsDir = path12.join(hubFolder, "evals");
|
|
10561
10644
|
if (evals.length === 0) {
|
|
10562
|
-
if (
|
|
10645
|
+
if (fs10.existsSync(evalsDir)) {
|
|
10563
10646
|
cleanEvalOrphans(evalsDir, /* @__PURE__ */ new Set());
|
|
10564
10647
|
try {
|
|
10565
|
-
if (
|
|
10648
|
+
if (fs10.readdirSync(evalsDir).length === 0) fs10.rmdirSync(evalsDir);
|
|
10566
10649
|
} catch {
|
|
10567
10650
|
}
|
|
10568
10651
|
}
|
|
10569
10652
|
return;
|
|
10570
10653
|
}
|
|
10571
|
-
if (!
|
|
10572
|
-
|
|
10654
|
+
if (!fs10.existsSync(evalsDir)) {
|
|
10655
|
+
fs10.mkdirSync(evalsDir, { recursive: true });
|
|
10573
10656
|
}
|
|
10574
10657
|
const writtenRelPaths = /* @__PURE__ */ new Set();
|
|
10575
10658
|
for (const evalEntry of evals) {
|
|
10576
10659
|
const slug = slugify(evalEntry.name);
|
|
10577
10660
|
const setName = evalEntry.path && evalEntry.path.trim().length > 0 ? evalEntry.path : null;
|
|
10578
10661
|
const relPath = setName ? `${setName}/${slug}.yaml` : `${slug}.yaml`;
|
|
10579
|
-
const targetPath =
|
|
10580
|
-
if (!targetPath.startsWith(evalsDir +
|
|
10662
|
+
const targetPath = path12.join(evalsDir, relPath);
|
|
10663
|
+
if (!targetPath.startsWith(evalsDir + path12.sep)) {
|
|
10581
10664
|
console.warn(` Warning: skipping eval "${evalEntry.name}" (scenario set "${setName}" escapes evals/ \u2014 possible bad backend data)`);
|
|
10582
10665
|
continue;
|
|
10583
10666
|
}
|
|
10584
10667
|
if (setName) {
|
|
10585
|
-
const setDir =
|
|
10586
|
-
if (!
|
|
10587
|
-
|
|
10668
|
+
const setDir = path12.join(evalsDir, setName);
|
|
10669
|
+
if (!fs10.existsSync(setDir)) {
|
|
10670
|
+
fs10.mkdirSync(setDir, { recursive: true });
|
|
10588
10671
|
}
|
|
10589
10672
|
}
|
|
10590
10673
|
const yamlContent = yaml4.dump(buildEvalYamlObject(evalEntry, slug), YAML_DUMP_OPTIONS);
|
|
10591
|
-
|
|
10674
|
+
fs10.writeFileSync(targetPath, yamlContent, "utf-8");
|
|
10592
10675
|
writtenRelPaths.add(relPath);
|
|
10593
10676
|
}
|
|
10594
10677
|
cleanEvalOrphans(evalsDir, writtenRelPaths);
|
|
10595
10678
|
}
|
|
10596
10679
|
function cleanEvalOrphans(evalsDir, writtenRelPaths) {
|
|
10597
|
-
const entries =
|
|
10680
|
+
const entries = fs10.readdirSync(evalsDir, { withFileTypes: true });
|
|
10598
10681
|
for (const entry of entries) {
|
|
10599
|
-
const fullPath =
|
|
10682
|
+
const fullPath = path12.join(evalsDir, entry.name);
|
|
10600
10683
|
if (entry.isFile()) {
|
|
10601
10684
|
if (entry.name.endsWith(".yaml") && !writtenRelPaths.has(entry.name)) {
|
|
10602
|
-
|
|
10685
|
+
fs10.unlinkSync(fullPath);
|
|
10603
10686
|
}
|
|
10604
10687
|
continue;
|
|
10605
10688
|
}
|
|
10606
10689
|
if (entry.isDirectory()) {
|
|
10607
10690
|
const setName = entry.name;
|
|
10608
|
-
const subEntries =
|
|
10691
|
+
const subEntries = fs10.readdirSync(fullPath, { withFileTypes: true });
|
|
10609
10692
|
for (const sub of subEntries) {
|
|
10610
10693
|
if (sub.isFile() && sub.name.endsWith(".yaml")) {
|
|
10611
10694
|
const relPath = `${setName}/${sub.name}`;
|
|
10612
10695
|
if (!writtenRelPaths.has(relPath)) {
|
|
10613
|
-
|
|
10696
|
+
fs10.unlinkSync(path12.join(fullPath, sub.name));
|
|
10614
10697
|
}
|
|
10615
10698
|
}
|
|
10616
10699
|
}
|
|
10617
10700
|
try {
|
|
10618
|
-
if (
|
|
10701
|
+
if (fs10.readdirSync(fullPath).length === 0) fs10.rmdirSync(fullPath);
|
|
10619
10702
|
} catch {
|
|
10620
10703
|
}
|
|
10621
10704
|
}
|
|
@@ -10651,19 +10734,19 @@ function buildJourneyYamlObject(journeyEntry, slug) {
|
|
|
10651
10734
|
return out;
|
|
10652
10735
|
}
|
|
10653
10736
|
function writeJourneyYamlFiles(hubFolder, journeys) {
|
|
10654
|
-
const journeysDir =
|
|
10737
|
+
const journeysDir = path12.join(hubFolder, "journeys");
|
|
10655
10738
|
if (journeys.length === 0) {
|
|
10656
|
-
if (
|
|
10739
|
+
if (fs10.existsSync(journeysDir)) {
|
|
10657
10740
|
cleanJourneyOrphans(journeysDir, /* @__PURE__ */ new Set());
|
|
10658
10741
|
try {
|
|
10659
|
-
if (
|
|
10742
|
+
if (fs10.readdirSync(journeysDir).length === 0) fs10.rmdirSync(journeysDir);
|
|
10660
10743
|
} catch {
|
|
10661
10744
|
}
|
|
10662
10745
|
}
|
|
10663
10746
|
return;
|
|
10664
10747
|
}
|
|
10665
|
-
if (!
|
|
10666
|
-
|
|
10748
|
+
if (!fs10.existsSync(journeysDir)) {
|
|
10749
|
+
fs10.mkdirSync(journeysDir, { recursive: true });
|
|
10667
10750
|
}
|
|
10668
10751
|
const writtenFiles = /* @__PURE__ */ new Set();
|
|
10669
10752
|
const usedSlugs = /* @__PURE__ */ new Set();
|
|
@@ -10671,33 +10754,33 @@ function writeJourneyYamlFiles(hubFolder, journeys) {
|
|
|
10671
10754
|
const slug = ensureUniqueSlug(slugify(journeyEntry.name), usedSlugs);
|
|
10672
10755
|
const fileName = `${slug}.yaml`;
|
|
10673
10756
|
const yamlContent = yaml4.dump(buildJourneyYamlObject(journeyEntry, slug), YAML_DUMP_OPTIONS);
|
|
10674
|
-
|
|
10757
|
+
fs10.writeFileSync(path12.join(journeysDir, fileName), yamlContent, "utf-8");
|
|
10675
10758
|
writtenFiles.add(fileName);
|
|
10676
10759
|
}
|
|
10677
10760
|
cleanJourneyOrphans(journeysDir, writtenFiles);
|
|
10678
10761
|
}
|
|
10679
10762
|
function cleanJourneyOrphans(journeysDir, writtenFiles) {
|
|
10680
|
-
const entries =
|
|
10763
|
+
const entries = fs10.readdirSync(journeysDir, { withFileTypes: true });
|
|
10681
10764
|
for (const entry of entries) {
|
|
10682
10765
|
if (entry.isFile() && entry.name.endsWith(".yaml") && !writtenFiles.has(entry.name)) {
|
|
10683
|
-
|
|
10766
|
+
fs10.unlinkSync(path12.join(journeysDir, entry.name));
|
|
10684
10767
|
}
|
|
10685
10768
|
}
|
|
10686
10769
|
}
|
|
10687
10770
|
function writeResourceFiles(hubFolder, resources) {
|
|
10688
|
-
const resourcesDir =
|
|
10771
|
+
const resourcesDir = path12.join(hubFolder, "resources");
|
|
10689
10772
|
const currentSlugs = /* @__PURE__ */ new Set();
|
|
10690
10773
|
for (const resource of resources) {
|
|
10691
10774
|
const resSlug = slugify(resource.name);
|
|
10692
10775
|
currentSlugs.add(resSlug);
|
|
10693
|
-
const resDir =
|
|
10776
|
+
const resDir = path12.join(resourcesDir, resSlug);
|
|
10694
10777
|
writeResourceFileTree(resDir, resource.files || []);
|
|
10695
10778
|
}
|
|
10696
|
-
if (
|
|
10697
|
-
const existingDirs =
|
|
10779
|
+
if (fs10.existsSync(resourcesDir)) {
|
|
10780
|
+
const existingDirs = fs10.readdirSync(resourcesDir, { withFileTypes: true });
|
|
10698
10781
|
for (const entry of existingDirs) {
|
|
10699
10782
|
if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
|
|
10700
|
-
|
|
10783
|
+
fs10.rmSync(path12.join(resourcesDir, entry.name), { recursive: true, force: true });
|
|
10701
10784
|
}
|
|
10702
10785
|
}
|
|
10703
10786
|
}
|
|
@@ -10709,6 +10792,7 @@ var init_yaml_writer = __esm({
|
|
|
10709
10792
|
init_dist();
|
|
10710
10793
|
init_utils();
|
|
10711
10794
|
init_resource_files();
|
|
10795
|
+
init_workspace_files();
|
|
10712
10796
|
YAML_DUMP_OPTIONS = {
|
|
10713
10797
|
lineWidth: -1,
|
|
10714
10798
|
// don't wrap lines
|
|
@@ -10722,8 +10806,8 @@ var init_yaml_writer = __esm({
|
|
|
10722
10806
|
});
|
|
10723
10807
|
|
|
10724
10808
|
// src/lib/parser.ts
|
|
10725
|
-
import * as
|
|
10726
|
-
import * as
|
|
10809
|
+
import * as fs11 from "fs";
|
|
10810
|
+
import * as path13 from "path";
|
|
10727
10811
|
import * as yaml5 from "js-yaml";
|
|
10728
10812
|
function expected(message) {
|
|
10729
10813
|
const err = new Error(message);
|
|
@@ -10737,7 +10821,7 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
10737
10821
|
err.isExpected = true;
|
|
10738
10822
|
throw err;
|
|
10739
10823
|
}
|
|
10740
|
-
const yamlContent =
|
|
10824
|
+
const yamlContent = fs11.readFileSync(yamlPath, "utf-8");
|
|
10741
10825
|
let config;
|
|
10742
10826
|
try {
|
|
10743
10827
|
config = yaml5.load(yamlContent);
|
|
@@ -10772,9 +10856,9 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
10772
10856
|
const resolved = { ...agent };
|
|
10773
10857
|
if (typeof resolved.instructions === "string" && resolved.instructions.endsWith(".md")) {
|
|
10774
10858
|
const instrValue = resolved.instructions;
|
|
10775
|
-
const instructionsPath = instrValue.startsWith("agents/") ?
|
|
10776
|
-
if (
|
|
10777
|
-
resolved.instructions =
|
|
10859
|
+
const instructionsPath = instrValue.startsWith("agents/") ? path13.join(hubFolder, instrValue) : path13.join(hubFolder, "agents", instrValue);
|
|
10860
|
+
if (fs11.existsSync(instructionsPath)) {
|
|
10861
|
+
resolved.instructions = fs11.readFileSync(instructionsPath, "utf-8");
|
|
10778
10862
|
} else {
|
|
10779
10863
|
const err = new Error(
|
|
10780
10864
|
`Agent instructions file not found: ${instructionsPath} (referenced by agent "${agent.name}")`
|
|
@@ -10783,9 +10867,9 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
10783
10867
|
throw err;
|
|
10784
10868
|
}
|
|
10785
10869
|
} else if (resolved.instructions === void 0 && typeof agent.name === "string") {
|
|
10786
|
-
const conventionPath =
|
|
10787
|
-
if (
|
|
10788
|
-
resolved.instructions =
|
|
10870
|
+
const conventionPath = path13.join(hubFolder, "agents", `${slugify(agent.name)}.md`);
|
|
10871
|
+
if (fs11.existsSync(conventionPath)) {
|
|
10872
|
+
resolved.instructions = fs11.readFileSync(conventionPath, "utf-8");
|
|
10789
10873
|
}
|
|
10790
10874
|
}
|
|
10791
10875
|
return resolved;
|
|
@@ -10835,26 +10919,26 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
10835
10919
|
return payload;
|
|
10836
10920
|
}
|
|
10837
10921
|
function scanEvalYamlFiles(hubFolder) {
|
|
10838
|
-
const evalsDir =
|
|
10839
|
-
if (!
|
|
10922
|
+
const evalsDir = path13.join(hubFolder, "evals");
|
|
10923
|
+
if (!fs11.existsSync(evalsDir)) return [];
|
|
10840
10924
|
const evals = [];
|
|
10841
10925
|
const seen = /* @__PURE__ */ new Set();
|
|
10842
|
-
const topEntries =
|
|
10926
|
+
const topEntries = fs11.readdirSync(evalsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
10843
10927
|
for (const entry of topEntries) {
|
|
10844
10928
|
if (entry.isFile() && entry.name.endsWith(".yaml")) {
|
|
10845
|
-
collectEval(evals, seen,
|
|
10929
|
+
collectEval(evals, seen, path13.join(evalsDir, entry.name), `evals/${entry.name}`, null);
|
|
10846
10930
|
} else if (entry.isDirectory()) {
|
|
10847
10931
|
const setName = entry.name;
|
|
10848
|
-
const setDir =
|
|
10849
|
-
const setEntries =
|
|
10932
|
+
const setDir = path13.join(evalsDir, setName);
|
|
10933
|
+
const setEntries = fs11.readdirSync(setDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
10850
10934
|
for (const sub of setEntries) {
|
|
10851
10935
|
if (sub.isDirectory()) {
|
|
10852
10936
|
throw expected(
|
|
10853
|
-
`Nested scenario sets are not supported: ${
|
|
10937
|
+
`Nested scenario sets are not supported: ${path13.relative(hubFolder, path13.join(setDir, sub.name))}. Move scenarios up to evals/${setName}/.`
|
|
10854
10938
|
);
|
|
10855
10939
|
}
|
|
10856
10940
|
if (sub.isFile() && sub.name.endsWith(".yaml")) {
|
|
10857
|
-
collectEval(evals, seen,
|
|
10941
|
+
collectEval(evals, seen, path13.join(setDir, sub.name), `evals/${setName}/${sub.name}`, setName);
|
|
10858
10942
|
}
|
|
10859
10943
|
}
|
|
10860
10944
|
}
|
|
@@ -10868,14 +10952,14 @@ function collectEval(evals, seen, filePath, relPath, setName) {
|
|
|
10868
10952
|
if (seen.has(key)) {
|
|
10869
10953
|
const where = setName ? `scenario set "${setName}"` : "root";
|
|
10870
10954
|
throw expected(
|
|
10871
|
-
`Duplicate eval at ${where}: "${evalEntry.name}" (in ${
|
|
10955
|
+
`Duplicate eval at ${where}: "${evalEntry.name}" (in ${path13.basename(filePath)}). Each (name, scenario set) pair must be unique.`
|
|
10872
10956
|
);
|
|
10873
10957
|
}
|
|
10874
10958
|
seen.add(key);
|
|
10875
10959
|
evals.push(evalEntry);
|
|
10876
10960
|
}
|
|
10877
10961
|
function parseEvalYaml(filePath, relPath, setName) {
|
|
10878
|
-
const content =
|
|
10962
|
+
const content = fs11.readFileSync(filePath, "utf-8");
|
|
10879
10963
|
let raw;
|
|
10880
10964
|
try {
|
|
10881
10965
|
raw = yaml5.load(content);
|
|
@@ -10890,7 +10974,7 @@ function parseEvalYaml(filePath, relPath, setName) {
|
|
|
10890
10974
|
return null;
|
|
10891
10975
|
}
|
|
10892
10976
|
const data = raw;
|
|
10893
|
-
const fileSlug =
|
|
10977
|
+
const fileSlug = path13.basename(filePath, ".yaml");
|
|
10894
10978
|
const evalName = typeof data.name === "string" && data.name.trim().length > 0 ? data.name : fileSlug;
|
|
10895
10979
|
if (typeof data.agent !== "string" || data.agent.trim().length === 0) {
|
|
10896
10980
|
throw expected(`Eval "${evalName}" in ${relPath}: missing required field "agent" (string).`);
|
|
@@ -10944,19 +11028,19 @@ function parseFixtureField(raw, label, key) {
|
|
|
10944
11028
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
10945
11029
|
}
|
|
10946
11030
|
function scanJourneyYamlFiles(hubFolder) {
|
|
10947
|
-
const journeysDir =
|
|
10948
|
-
if (!
|
|
11031
|
+
const journeysDir = path13.join(hubFolder, "journeys");
|
|
11032
|
+
if (!fs11.existsSync(journeysDir)) return [];
|
|
10949
11033
|
const journeys = [];
|
|
10950
11034
|
const seen = /* @__PURE__ */ new Set();
|
|
10951
|
-
const entries =
|
|
11035
|
+
const entries = fs11.readdirSync(journeysDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
10952
11036
|
for (const entry of entries) {
|
|
10953
11037
|
if (entry.isDirectory()) {
|
|
10954
11038
|
throw expected(
|
|
10955
|
-
`Subfolders are not supported under journeys/: ${
|
|
11039
|
+
`Subfolders are not supported under journeys/: ${path13.relative(hubFolder, path13.join(journeysDir, entry.name))}. A journey owns its own managed scenario set \u2014 put each journey in a single journeys/<slug>.yaml file.`
|
|
10956
11040
|
);
|
|
10957
11041
|
}
|
|
10958
11042
|
if (!entry.isFile() || !entry.name.endsWith(".yaml")) continue;
|
|
10959
|
-
const journeyEntry = parseJourneyYaml(
|
|
11043
|
+
const journeyEntry = parseJourneyYaml(path13.join(journeysDir, entry.name), `journeys/${entry.name}`);
|
|
10960
11044
|
if (!journeyEntry) continue;
|
|
10961
11045
|
if (seen.has(journeyEntry.name)) {
|
|
10962
11046
|
throw expected(
|
|
@@ -10969,7 +11053,7 @@ function scanJourneyYamlFiles(hubFolder) {
|
|
|
10969
11053
|
return journeys;
|
|
10970
11054
|
}
|
|
10971
11055
|
function parseJourneyYaml(filePath, relPath) {
|
|
10972
|
-
const content =
|
|
11056
|
+
const content = fs11.readFileSync(filePath, "utf-8");
|
|
10973
11057
|
let raw;
|
|
10974
11058
|
try {
|
|
10975
11059
|
raw = yaml5.load(content);
|
|
@@ -10984,7 +11068,7 @@ function parseJourneyYaml(filePath, relPath) {
|
|
|
10984
11068
|
return null;
|
|
10985
11069
|
}
|
|
10986
11070
|
const data = raw;
|
|
10987
|
-
const fileSlug =
|
|
11071
|
+
const fileSlug = path13.basename(filePath, ".yaml");
|
|
10988
11072
|
const journeyName = typeof data.name === "string" && data.name.trim().length > 0 ? data.name : fileSlug;
|
|
10989
11073
|
if (typeof data.agent !== "string" || data.agent.trim().length === 0) {
|
|
10990
11074
|
throw expected(`Journey "${journeyName}" in ${relPath}: missing required field "agent" (string).`);
|
|
@@ -11020,14 +11104,14 @@ function parseJourneyYaml(filePath, relPath) {
|
|
|
11020
11104
|
return journeyEntry;
|
|
11021
11105
|
}
|
|
11022
11106
|
function scanAgentYamlFiles(hubFolder) {
|
|
11023
|
-
const agentsDir =
|
|
11024
|
-
if (!
|
|
11025
|
-
const yamlFiles =
|
|
11107
|
+
const agentsDir = path13.join(hubFolder, "agents");
|
|
11108
|
+
if (!fs11.existsSync(agentsDir)) return [];
|
|
11109
|
+
const yamlFiles = fs11.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml")).sort();
|
|
11026
11110
|
if (yamlFiles.length === 0) return [];
|
|
11027
11111
|
const agents = [];
|
|
11028
11112
|
for (const file of yamlFiles) {
|
|
11029
|
-
const filePath =
|
|
11030
|
-
const content =
|
|
11113
|
+
const filePath = path13.join(agentsDir, file);
|
|
11114
|
+
const content = fs11.readFileSync(filePath, "utf-8");
|
|
11031
11115
|
let agent;
|
|
11032
11116
|
try {
|
|
11033
11117
|
agent = yaml5.load(content);
|
|
@@ -11049,7 +11133,7 @@ function scanAgentYamlFiles(hubFolder) {
|
|
|
11049
11133
|
return agents;
|
|
11050
11134
|
}
|
|
11051
11135
|
function parseResources(hubFolder, configResources) {
|
|
11052
|
-
const resourcesDir =
|
|
11136
|
+
const resourcesDir = path13.join(hubFolder, "resources");
|
|
11053
11137
|
const results = [];
|
|
11054
11138
|
for (const res of configResources) {
|
|
11055
11139
|
const resource = {
|
|
@@ -11062,8 +11146,8 @@ function parseResources(hubFolder, configResources) {
|
|
|
11062
11146
|
if (res.user_browsable) resource.user_browsable = res.user_browsable;
|
|
11063
11147
|
if (res.skill_name) resource.skill_name = res.skill_name;
|
|
11064
11148
|
const resSlug = slugify(resource.name);
|
|
11065
|
-
const resDir =
|
|
11066
|
-
if (
|
|
11149
|
+
const resDir = path13.join(resourcesDir, resSlug);
|
|
11150
|
+
if (fs11.existsSync(resDir)) {
|
|
11067
11151
|
const files = scanResourceFiles(resDir, "");
|
|
11068
11152
|
if (files.length > 0) {
|
|
11069
11153
|
resource.files = files;
|
|
@@ -11117,8 +11201,8 @@ __export(pull_exports, {
|
|
|
11117
11201
|
resolveHubTarget: () => resolveHubTarget,
|
|
11118
11202
|
writeProductionMirror: () => writeProductionMirror
|
|
11119
11203
|
});
|
|
11120
|
-
import * as
|
|
11121
|
-
import * as
|
|
11204
|
+
import * as fs12 from "fs";
|
|
11205
|
+
import * as path14 from "path";
|
|
11122
11206
|
function parseArgs4(args2) {
|
|
11123
11207
|
let autoConfirm = false;
|
|
11124
11208
|
let hubSelector;
|
|
@@ -11137,7 +11221,7 @@ function resolveHubTarget(workspaceDir, selector) {
|
|
|
11137
11221
|
const allHubs = scanWorkspaceHubs(workspaceDir);
|
|
11138
11222
|
if (selector) {
|
|
11139
11223
|
const match = allHubs.find(
|
|
11140
|
-
(h) => h.hubId === selector ||
|
|
11224
|
+
(h) => h.hubId === selector || path14.basename(h.hubFolder) === selector
|
|
11141
11225
|
);
|
|
11142
11226
|
if (match) return { hubId: match.hubId, hubFolder: match.hubFolder };
|
|
11143
11227
|
if (UUID_RE.test(selector)) return { hubId: selector, hubFolder: null };
|
|
@@ -11154,7 +11238,7 @@ function resolveHubTarget(workspaceDir, selector) {
|
|
|
11154
11238
|
}
|
|
11155
11239
|
console.error(`Multiple hubs found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
|
|
11156
11240
|
for (const h of previewHubs) {
|
|
11157
|
-
console.error(` ${
|
|
11241
|
+
console.error(` ${path14.basename(h.hubFolder)} (${h.hubId})`);
|
|
11158
11242
|
}
|
|
11159
11243
|
process.exit(1);
|
|
11160
11244
|
}
|
|
@@ -11167,6 +11251,11 @@ async function pullCommand(args2) {
|
|
|
11167
11251
|
const workspaceDir = resolveWorkspaceDir();
|
|
11168
11252
|
const gitRoot = findGitRoot();
|
|
11169
11253
|
if (gitRoot) warnLayoutOnce(gitRoot);
|
|
11254
|
+
if (gitRoot) {
|
|
11255
|
+
for (const file of ensureWorkspaceFiles(gitRoot)) {
|
|
11256
|
+
console.error(`Created ${file}`);
|
|
11257
|
+
}
|
|
11258
|
+
}
|
|
11170
11259
|
const { hubId, hubFolder: existingFolder } = resolveHubTarget(workspaceDir, hubSelector);
|
|
11171
11260
|
console.log("Fetching hub configuration...");
|
|
11172
11261
|
const payload = await client.pull(hubId, organizationId);
|
|
@@ -11187,7 +11276,7 @@ async function pullCommand(args2) {
|
|
|
11187
11276
|
payload.preview_label,
|
|
11188
11277
|
payload.branch_name
|
|
11189
11278
|
);
|
|
11190
|
-
|
|
11279
|
+
fs12.mkdirSync(path14.dirname(hubFolder), { recursive: true });
|
|
11191
11280
|
console.log("Writing hub configuration...");
|
|
11192
11281
|
writeHubFolder(hubFolder, payload);
|
|
11193
11282
|
await downloadBinaryResourceFiles(hubFolder, payload);
|
|
@@ -11248,8 +11337,8 @@ async function pullCommand(args2) {
|
|
|
11248
11337
|
}
|
|
11249
11338
|
async function writeProductionMirror(workspaceDir, prodPayload) {
|
|
11250
11339
|
const folder = resolveHubFolder(workspaceDir, prodPayload.hub_id, prodPayload.hub.name, "production", null, null);
|
|
11251
|
-
|
|
11252
|
-
writeHubFolder(folder, prodPayload);
|
|
11340
|
+
fs12.mkdirSync(path14.dirname(folder), { recursive: true });
|
|
11341
|
+
writeHubFolder(folder, prodPayload, { seedAgentContext: false });
|
|
11253
11342
|
await downloadBinaryResourceFiles(folder, prodPayload);
|
|
11254
11343
|
const finalFolder = autoRenameHubFolder(folder, prodPayload.hub.name, "production", prodPayload.hub_id, null, null);
|
|
11255
11344
|
prependMirrorMarker(finalFolder, prodPayload.hub_id);
|
|
@@ -11265,13 +11354,13 @@ async function mirrorLinkedProduction(client, workspaceDir, productionHubId, org
|
|
|
11265
11354
|
}
|
|
11266
11355
|
}
|
|
11267
11356
|
function prependMirrorMarker(hubFolder, productionHubId) {
|
|
11268
|
-
const hubYaml =
|
|
11357
|
+
const hubYaml = path14.join(hubFolder, "hub.yaml");
|
|
11269
11358
|
try {
|
|
11270
|
-
const content =
|
|
11359
|
+
const content = fs12.readFileSync(hubYaml, "utf-8");
|
|
11271
11360
|
if (content.startsWith(MIRROR_MARKER_PREFIX)) return;
|
|
11272
11361
|
const marker = `${MIRROR_MARKER_PREFIX} ${productionHubId}. Edits are ignored; push is blocked. Edit the linked preview hub instead.
|
|
11273
11362
|
`;
|
|
11274
|
-
|
|
11363
|
+
fs12.writeFileSync(hubYaml, marker + content, "utf-8");
|
|
11275
11364
|
} catch {
|
|
11276
11365
|
}
|
|
11277
11366
|
}
|
|
@@ -11280,7 +11369,7 @@ async function downloadBinaryResourceFiles(hubFolder, payload) {
|
|
|
11280
11369
|
let downloadCount = 0;
|
|
11281
11370
|
for (const resource of resources) {
|
|
11282
11371
|
if (!resource.files) continue;
|
|
11283
|
-
const resDir =
|
|
11372
|
+
const resDir = path14.join(hubFolder, "resources", slugify(resource.name));
|
|
11284
11373
|
downloadCount += await downloadBinaryFiles(resDir, resource.files);
|
|
11285
11374
|
}
|
|
11286
11375
|
if (downloadCount > 0) {
|
|
@@ -11313,6 +11402,7 @@ var init_pull = __esm({
|
|
|
11313
11402
|
init_resource_files();
|
|
11314
11403
|
init_workspace();
|
|
11315
11404
|
init_layout();
|
|
11405
|
+
init_workspace_files();
|
|
11316
11406
|
init_repo_config();
|
|
11317
11407
|
init_hub_binding();
|
|
11318
11408
|
MIRROR_MARKER_PREFIX = "# Read-only mirror of production hub";
|
|
@@ -11331,8 +11421,8 @@ __export(push_exports, {
|
|
|
11331
11421
|
selectExistingHub: () => selectExistingHub,
|
|
11332
11422
|
shouldWarnIgnoredPreviewLabel: () => shouldWarnIgnoredPreviewLabel
|
|
11333
11423
|
});
|
|
11334
|
-
import * as
|
|
11335
|
-
import * as
|
|
11424
|
+
import * as fs13 from "fs";
|
|
11425
|
+
import * as path15 from "path";
|
|
11336
11426
|
import * as yaml6 from "js-yaml";
|
|
11337
11427
|
function parseArgs5(args2) {
|
|
11338
11428
|
let autoConfirm = false;
|
|
@@ -11416,13 +11506,13 @@ function printWarnings(warnings) {
|
|
|
11416
11506
|
}
|
|
11417
11507
|
}
|
|
11418
11508
|
async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
|
|
11419
|
-
const agentsDir =
|
|
11509
|
+
const agentsDir = path15.join(hubFolder, "agents");
|
|
11420
11510
|
let agentsWithIds = [];
|
|
11421
|
-
if (
|
|
11422
|
-
const yamlFiles =
|
|
11511
|
+
if (fs13.existsSync(agentsDir)) {
|
|
11512
|
+
const yamlFiles = fs13.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml"));
|
|
11423
11513
|
for (const file of yamlFiles) {
|
|
11424
11514
|
try {
|
|
11425
|
-
const content =
|
|
11515
|
+
const content = fs13.readFileSync(path15.join(agentsDir, file), "utf-8");
|
|
11426
11516
|
const agent = yaml6.load(content);
|
|
11427
11517
|
if (agent?.id && agent.name) {
|
|
11428
11518
|
agentsWithIds.push({ id: agent.id, name: agent.name });
|
|
@@ -11435,7 +11525,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
|
|
|
11435
11525
|
if (agentsWithIds.length === 0) {
|
|
11436
11526
|
const yamlPath = resolveHubYamlPath(hubFolder);
|
|
11437
11527
|
if (!yamlPath) return;
|
|
11438
|
-
const yamlContent =
|
|
11528
|
+
const yamlContent = fs13.readFileSync(yamlPath, "utf-8");
|
|
11439
11529
|
const config = yaml6.load(yamlContent);
|
|
11440
11530
|
agentsWithIds = (config.agents || []).filter((a) => !!a.id && !!a.name);
|
|
11441
11531
|
}
|
|
@@ -11465,18 +11555,18 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
|
|
|
11465
11555
|
}
|
|
11466
11556
|
}
|
|
11467
11557
|
if (renames.length === 0) return;
|
|
11468
|
-
if (!
|
|
11469
|
-
for (const file of
|
|
11558
|
+
if (!fs13.existsSync(agentsDir)) return;
|
|
11559
|
+
for (const file of fs13.readdirSync(agentsDir)) {
|
|
11470
11560
|
if (file.startsWith("__rename_temp_") && (file.endsWith(".md") || file.endsWith(".yaml"))) {
|
|
11471
11561
|
console.warn(` Warning: removing orphaned temp file agents/${file}`);
|
|
11472
|
-
|
|
11562
|
+
fs13.unlinkSync(path15.join(agentsDir, file));
|
|
11473
11563
|
}
|
|
11474
11564
|
}
|
|
11475
11565
|
const renameFileIfExists = (dir, oldName, newName) => {
|
|
11476
|
-
const oldPath =
|
|
11477
|
-
const newPath =
|
|
11478
|
-
if (!
|
|
11479
|
-
|
|
11566
|
+
const oldPath = path15.join(dir, oldName);
|
|
11567
|
+
const newPath = path15.join(dir, newName);
|
|
11568
|
+
if (!fs13.existsSync(oldPath)) return false;
|
|
11569
|
+
fs13.renameSync(oldPath, newPath);
|
|
11480
11570
|
return true;
|
|
11481
11571
|
};
|
|
11482
11572
|
const oldSlugs = new Set(renames.map((r) => r.oldSlug));
|
|
@@ -11509,9 +11599,9 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
|
|
|
11509
11599
|
}
|
|
11510
11600
|
} else {
|
|
11511
11601
|
for (const { oldSlug, newSlug } of renames) {
|
|
11512
|
-
const hasOldFile = extensions.some((ext) =>
|
|
11602
|
+
const hasOldFile = extensions.some((ext) => fs13.existsSync(path15.join(agentsDir, `${oldSlug}${ext}`)));
|
|
11513
11603
|
if (!hasOldFile) continue;
|
|
11514
|
-
const hasNewFile = extensions.some((ext) =>
|
|
11604
|
+
const hasNewFile = extensions.some((ext) => fs13.existsSync(path15.join(agentsDir, `${newSlug}${ext}`)));
|
|
11515
11605
|
if (hasNewFile) {
|
|
11516
11606
|
console.warn(` Warning: skipping rename agents/${oldSlug}.* \u2192 agents/${newSlug}.* (target already exists)`);
|
|
11517
11607
|
continue;
|
|
@@ -11526,7 +11616,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
|
|
|
11526
11616
|
if (completedRenames.length === 0) return;
|
|
11527
11617
|
const mainYamlPath = resolveHubYamlPath(hubFolder);
|
|
11528
11618
|
if (mainYamlPath) {
|
|
11529
|
-
const mainYamlContent =
|
|
11619
|
+
const mainYamlContent = fs13.readFileSync(mainYamlPath, "utf-8");
|
|
11530
11620
|
const substitutionMap = /* @__PURE__ */ new Map();
|
|
11531
11621
|
for (const { oldSlug, newSlug } of completedRenames) {
|
|
11532
11622
|
substitutionMap.set(`agents/${oldSlug}.md`, `agents/${newSlug}.md`);
|
|
@@ -11537,8 +11627,8 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
|
|
|
11537
11627
|
(_match, prefix, pathMatch) => `${prefix}${substitutionMap.get(pathMatch) ?? pathMatch}`
|
|
11538
11628
|
);
|
|
11539
11629
|
if (updatedYaml !== mainYamlContent) {
|
|
11540
|
-
|
|
11541
|
-
console.log(` Updated instructions paths in ${
|
|
11630
|
+
fs13.writeFileSync(mainYamlPath, updatedYaml, "utf-8");
|
|
11631
|
+
console.log(` Updated instructions paths in ${path15.basename(mainYamlPath)}`);
|
|
11542
11632
|
}
|
|
11543
11633
|
}
|
|
11544
11634
|
}
|
|
@@ -11599,7 +11689,7 @@ async function pushSingleHub(client, hubId, hubFolder, autoConfirm, organization
|
|
|
11599
11689
|
function selectExistingHub(workspaceDir, allHubs, selector, wsLabel) {
|
|
11600
11690
|
if (selector) {
|
|
11601
11691
|
const match = allHubs.find(
|
|
11602
|
-
(h) => h.hubId === selector ||
|
|
11692
|
+
(h) => h.hubId === selector || path15.basename(h.hubFolder) === selector
|
|
11603
11693
|
);
|
|
11604
11694
|
if (!match) {
|
|
11605
11695
|
console.error(`No hub matching --hub ${selector} found in ${wsLabel}/.`);
|
|
@@ -11642,7 +11732,7 @@ New hub: "${newHub.hubName}" (${hubType})`);
|
|
|
11642
11732
|
process.exit(1);
|
|
11643
11733
|
}
|
|
11644
11734
|
console.log(`Hub created: ${createdHub.hub_name} (${hubId})`);
|
|
11645
|
-
const content =
|
|
11735
|
+
const content = fs13.readFileSync(hubYamlPath, "utf-8");
|
|
11646
11736
|
const hasVersion = content.match(/^version:\s/m);
|
|
11647
11737
|
let updated;
|
|
11648
11738
|
if (hasVersion) {
|
|
@@ -11658,7 +11748,7 @@ hub_id: "${hubId}"
|
|
|
11658
11748
|
hub_environment: preview
|
|
11659
11749
|
${content}`;
|
|
11660
11750
|
}
|
|
11661
|
-
|
|
11751
|
+
fs13.writeFileSync(hubYamlPath, updated, "utf-8");
|
|
11662
11752
|
autoBindIfUnbound(hubId);
|
|
11663
11753
|
await pushSingleHub(client, hubId, newHub.hubFolder, opts.autoConfirm, opts.organizationId, { skipAgentRename: true });
|
|
11664
11754
|
}
|
|
@@ -11667,7 +11757,7 @@ function reportUnresolvedPushTarget(reason, existingHubs, newHubs, selector, wsL
|
|
|
11667
11757
|
if (existingHubs.length > 0) {
|
|
11668
11758
|
console.error(`No pushable hub found in ${wsLabel}/ \u2014 only read-only production mirror folder(s). Edit the linked preview hub, pull one, or create a new hub with \`wayai create\`:`);
|
|
11669
11759
|
for (const h of existingHubs) {
|
|
11670
|
-
console.error(` ${
|
|
11760
|
+
console.error(` ${path15.basename(h.hubFolder)} (${h.hubId}, production mirror)`);
|
|
11671
11761
|
}
|
|
11672
11762
|
} else {
|
|
11673
11763
|
console.error(`No hub folders found. Create hub files in ${wsLabel}/<hub>/hub.yaml with \`hub: { name: ... }\` and run \`wayai push\` (or \`wayai create\`).`);
|
|
@@ -11680,10 +11770,10 @@ function reportUnresolvedPushTarget(reason, existingHubs, newHubs, selector, wsL
|
|
|
11680
11770
|
console.error(`Multiple hub folders found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
|
|
11681
11771
|
}
|
|
11682
11772
|
for (const h of existingHubs) {
|
|
11683
|
-
console.error(` ${
|
|
11773
|
+
console.error(` ${path15.basename(h.hubFolder)} (${h.hubId})`);
|
|
11684
11774
|
}
|
|
11685
11775
|
for (const h of newHubs) {
|
|
11686
|
-
console.error(` ${
|
|
11776
|
+
console.error(` ${path15.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
|
|
11687
11777
|
}
|
|
11688
11778
|
process.exit(1);
|
|
11689
11779
|
}
|
|
@@ -11697,7 +11787,12 @@ async function pushCommand(args2) {
|
|
|
11697
11787
|
const gitRoot = findGitRoot();
|
|
11698
11788
|
const wsLabel = hubsDirLabel(gitRoot);
|
|
11699
11789
|
if (gitRoot) warnLayoutOnce(gitRoot);
|
|
11700
|
-
if (
|
|
11790
|
+
if (gitRoot) {
|
|
11791
|
+
for (const file of ensureWorkspaceFiles(gitRoot)) {
|
|
11792
|
+
console.error(`Created ${file}`);
|
|
11793
|
+
}
|
|
11794
|
+
}
|
|
11795
|
+
if (!fs13.existsSync(workspaceDir)) {
|
|
11701
11796
|
console.error(`No ${wsLabel}/ directory found. Run \`wayai pull\` first or create hub files in ${wsLabel}/<hub>/hub.yaml.`);
|
|
11702
11797
|
process.exit(1);
|
|
11703
11798
|
}
|
|
@@ -11716,8 +11811,8 @@ async function pushCommand(args2) {
|
|
|
11716
11811
|
if (label) {
|
|
11717
11812
|
console.warn("Note: --label is only used when creating a new hub. To change an existing hub's label, use `wayai relabel`.");
|
|
11718
11813
|
}
|
|
11719
|
-
console.log(`Target hub: ${
|
|
11720
|
-
assertHubMatchesBinding(existing.hubId,
|
|
11814
|
+
console.log(`Target hub: ${path15.basename(existing.hubFolder)} (${existing.hubId})`);
|
|
11815
|
+
assertHubMatchesBinding(existing.hubId, path15.basename(existing.hubFolder));
|
|
11721
11816
|
await pushSingleHub(client, existing.hubId, existing.hubFolder, autoConfirm, organizationId);
|
|
11722
11817
|
return;
|
|
11723
11818
|
}
|
|
@@ -11736,6 +11831,7 @@ var init_push = __esm({
|
|
|
11736
11831
|
init_utils();
|
|
11737
11832
|
init_workspace();
|
|
11738
11833
|
init_layout();
|
|
11834
|
+
init_workspace_files();
|
|
11739
11835
|
init_repo_config();
|
|
11740
11836
|
init_hub_binding();
|
|
11741
11837
|
}
|
|
@@ -11746,8 +11842,8 @@ var create_exports = {};
|
|
|
11746
11842
|
__export(create_exports, {
|
|
11747
11843
|
createCommand: () => createCommand
|
|
11748
11844
|
});
|
|
11749
|
-
import * as
|
|
11750
|
-
import * as
|
|
11845
|
+
import * as path16 from "path";
|
|
11846
|
+
import * as fs14 from "fs";
|
|
11751
11847
|
function parseArgs6(args2) {
|
|
11752
11848
|
let autoConfirm = false;
|
|
11753
11849
|
let folderSelector;
|
|
@@ -11774,7 +11870,7 @@ async function createCommand(args2) {
|
|
|
11774
11870
|
const gitRoot = findGitRoot();
|
|
11775
11871
|
const wsLabel = hubsDirLabel(gitRoot);
|
|
11776
11872
|
if (gitRoot) warnLayoutOnce(gitRoot);
|
|
11777
|
-
if (!
|
|
11873
|
+
if (!fs14.existsSync(workspaceDir)) {
|
|
11778
11874
|
console.error(`No ${wsLabel}/ directory found. Create hub files in ${wsLabel}/<hub>/hub.yaml with \`hub: { name: ... }\` first.`);
|
|
11779
11875
|
process.exit(1);
|
|
11780
11876
|
}
|
|
@@ -11783,7 +11879,7 @@ async function createCommand(args2) {
|
|
|
11783
11879
|
const resolution = resolveNewHubForCreate(workspaceDir, existingHubs, newHubs, folderSelector);
|
|
11784
11880
|
if (!resolution.ok) {
|
|
11785
11881
|
if (resolution.reason === "exists") {
|
|
11786
|
-
const folder =
|
|
11882
|
+
const folder = path16.basename(resolution.existing.hubFolder);
|
|
11787
11883
|
console.error(`Hub "${folder}" already exists (${resolution.existing.hubId}). Use \`wayai push --hub ${folder}\` to update it.`);
|
|
11788
11884
|
process.exit(1);
|
|
11789
11885
|
}
|
|
@@ -11797,7 +11893,7 @@ async function createCommand(args2) {
|
|
|
11797
11893
|
}
|
|
11798
11894
|
console.error(`Multiple new hub folders found in ${wsLabel}/. Pass the folder name (\`wayai create <folder>\`) or run from inside one:`);
|
|
11799
11895
|
for (const h of newHubs) {
|
|
11800
|
-
console.error(` ${
|
|
11896
|
+
console.error(` ${path16.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
|
|
11801
11897
|
}
|
|
11802
11898
|
process.exit(1);
|
|
11803
11899
|
}
|
|
@@ -11967,12 +12063,12 @@ function typeMatches2(typeField, allowed) {
|
|
|
11967
12063
|
if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
|
|
11968
12064
|
return false;
|
|
11969
12065
|
}
|
|
11970
|
-
function validateSchema2(schema,
|
|
12066
|
+
function validateSchema2(schema, path27, errors, opts = {}) {
|
|
11971
12067
|
if (typeof schema === "boolean") return;
|
|
11972
12068
|
const depth = opts.depth ?? 0;
|
|
11973
12069
|
if (depth > MAX_SCHEMA_DEPTH2) {
|
|
11974
12070
|
errors.push({
|
|
11975
|
-
path:
|
|
12071
|
+
path: path27 || "<root>",
|
|
11976
12072
|
message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH2} levels`,
|
|
11977
12073
|
suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
|
|
11978
12074
|
});
|
|
@@ -11980,7 +12076,7 @@ function validateSchema2(schema, path26, errors, opts = {}) {
|
|
|
11980
12076
|
}
|
|
11981
12077
|
if (!isRecord2(schema)) {
|
|
11982
12078
|
errors.push({
|
|
11983
|
-
path:
|
|
12079
|
+
path: path27,
|
|
11984
12080
|
message: `expected object, got ${schema === null ? "null" : typeof schema}`
|
|
11985
12081
|
});
|
|
11986
12082
|
return;
|
|
@@ -11988,14 +12084,14 @@ function validateSchema2(schema, path26, errors, opts = {}) {
|
|
|
11988
12084
|
if (opts.isRoot) {
|
|
11989
12085
|
if ("type" in schema && schema.type !== "object") {
|
|
11990
12086
|
errors.push({
|
|
11991
|
-
path:
|
|
12087
|
+
path: path27 ? `${path27}.type` : "type",
|
|
11992
12088
|
message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
|
|
11993
12089
|
suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
|
|
11994
12090
|
});
|
|
11995
12091
|
}
|
|
11996
12092
|
} else if ("type" in schema && !typeMatches2(schema.type, ALLOWED_TYPES2)) {
|
|
11997
12093
|
errors.push({
|
|
11998
|
-
path: `${
|
|
12094
|
+
path: `${path27}.type`,
|
|
11999
12095
|
message: `type must be one of ${[...ALLOWED_TYPES2].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
|
|
12000
12096
|
});
|
|
12001
12097
|
}
|
|
@@ -12004,25 +12100,25 @@ function validateSchema2(schema, path26, errors, opts = {}) {
|
|
|
12004
12100
|
if (typeof e === "string") {
|
|
12005
12101
|
const isPlaceholder = PLACEHOLDER_TOKENS2.includes(e);
|
|
12006
12102
|
errors.push({
|
|
12007
|
-
path: `${
|
|
12103
|
+
path: `${path27}.enum`,
|
|
12008
12104
|
message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
|
|
12009
12105
|
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"]`.'
|
|
12010
12106
|
});
|
|
12011
12107
|
} else if (!Array.isArray(e)) {
|
|
12012
12108
|
errors.push({
|
|
12013
|
-
path: `${
|
|
12109
|
+
path: `${path27}.enum`,
|
|
12014
12110
|
message: `enum must be a non-empty array of primitives, got ${typeof e}`
|
|
12015
12111
|
});
|
|
12016
12112
|
} else if (e.length === 0) {
|
|
12017
12113
|
errors.push({
|
|
12018
|
-
path: `${
|
|
12114
|
+
path: `${path27}.enum`,
|
|
12019
12115
|
message: "enum must not be empty"
|
|
12020
12116
|
});
|
|
12021
12117
|
} else {
|
|
12022
12118
|
for (let i = 0; i < e.length; i++) {
|
|
12023
12119
|
if (!isPrimitive2(e[i])) {
|
|
12024
12120
|
errors.push({
|
|
12025
|
-
path: `${
|
|
12121
|
+
path: `${path27}.enum[${i}]`,
|
|
12026
12122
|
message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
|
|
12027
12123
|
});
|
|
12028
12124
|
}
|
|
@@ -12032,7 +12128,7 @@ function validateSchema2(schema, path26, errors, opts = {}) {
|
|
|
12032
12128
|
for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
|
|
12033
12129
|
if (key in schema && typeof schema[key] === "boolean") {
|
|
12034
12130
|
errors.push({
|
|
12035
|
-
path: `${
|
|
12131
|
+
path: `${path27}.${key}`,
|
|
12036
12132
|
message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
|
|
12037
12133
|
suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
|
|
12038
12134
|
});
|
|
@@ -12041,45 +12137,45 @@ function validateSchema2(schema, path26, errors, opts = {}) {
|
|
|
12041
12137
|
if ("properties" in schema) {
|
|
12042
12138
|
if (!isRecord2(schema.properties)) {
|
|
12043
12139
|
errors.push({
|
|
12044
|
-
path: `${
|
|
12140
|
+
path: `${path27}.properties`,
|
|
12045
12141
|
message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
|
|
12046
12142
|
});
|
|
12047
12143
|
} else {
|
|
12048
12144
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
12049
|
-
validateSchema2(propSchema, `${
|
|
12145
|
+
validateSchema2(propSchema, `${path27}.properties.${propName}`, errors, { depth: depth + 1 });
|
|
12050
12146
|
}
|
|
12051
12147
|
}
|
|
12052
12148
|
}
|
|
12053
12149
|
if (schemaTypeIncludes2(schema, "array") && "items" in schema) {
|
|
12054
12150
|
if (Array.isArray(schema.items)) {
|
|
12055
|
-
schema.items.forEach((sub, i) => validateSchema2(sub, `${
|
|
12151
|
+
schema.items.forEach((sub, i) => validateSchema2(sub, `${path27}.items[${i}]`, errors, { depth: depth + 1 }));
|
|
12056
12152
|
} else {
|
|
12057
|
-
validateSchema2(schema.items, `${
|
|
12153
|
+
validateSchema2(schema.items, `${path27}.items`, errors, { depth: depth + 1 });
|
|
12058
12154
|
}
|
|
12059
12155
|
}
|
|
12060
12156
|
for (const key of SUBSCHEMA_OBJECT_KEYWORDS2) {
|
|
12061
12157
|
if (key in schema && isRecord2(schema[key])) {
|
|
12062
|
-
validateSchema2(schema[key], `${
|
|
12158
|
+
validateSchema2(schema[key], `${path27}.${key}`, errors, { depth: depth + 1 });
|
|
12063
12159
|
}
|
|
12064
12160
|
}
|
|
12065
12161
|
for (const key of SUBSCHEMA_LIST_KEYWORDS2) {
|
|
12066
12162
|
const list = schema[key];
|
|
12067
12163
|
if (Array.isArray(list)) {
|
|
12068
|
-
list.forEach((sub, i) => validateSchema2(sub, `${
|
|
12164
|
+
list.forEach((sub, i) => validateSchema2(sub, `${path27}.${key}[${i}]`, errors, { depth: depth + 1 }));
|
|
12069
12165
|
}
|
|
12070
12166
|
}
|
|
12071
12167
|
for (const key of SUBSCHEMA_MAP_KEYWORDS2) {
|
|
12072
12168
|
const map = schema[key];
|
|
12073
12169
|
if (isRecord2(map)) {
|
|
12074
12170
|
for (const [name, sub] of Object.entries(map)) {
|
|
12075
|
-
validateSchema2(sub, `${
|
|
12171
|
+
validateSchema2(sub, `${path27}.${key}.${name}`, errors, { depth: depth + 1 });
|
|
12076
12172
|
}
|
|
12077
12173
|
}
|
|
12078
12174
|
}
|
|
12079
12175
|
const reportedPaths = new Set(errors.map((e) => e.path));
|
|
12080
12176
|
for (const [k, v] of Object.entries(schema)) {
|
|
12081
12177
|
if (typeof v !== "string") continue;
|
|
12082
|
-
const fieldPath = `${
|
|
12178
|
+
const fieldPath = `${path27}.${k}`;
|
|
12083
12179
|
if (reportedPaths.has(fieldPath)) continue;
|
|
12084
12180
|
for (const token of PLACEHOLDER_TOKENS2) {
|
|
12085
12181
|
if (v === token) {
|
|
@@ -12235,10 +12331,10 @@ function refineHubAsCodeLanes2(config, ctx) {
|
|
|
12235
12331
|
}
|
|
12236
12332
|
}
|
|
12237
12333
|
}
|
|
12238
|
-
function isSafeTemplatePath2(
|
|
12239
|
-
if (
|
|
12240
|
-
if (
|
|
12241
|
-
const segments =
|
|
12334
|
+
function isSafeTemplatePath2(path27) {
|
|
12335
|
+
if (path27.length === 0 || path27.length > 300) return false;
|
|
12336
|
+
if (path27.startsWith("/") || path27.includes("\\")) return false;
|
|
12337
|
+
const segments = path27.split("/");
|
|
12242
12338
|
return segments.every(
|
|
12243
12339
|
(seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
|
|
12244
12340
|
);
|
|
@@ -12266,9 +12362,9 @@ function isPlainObject(value) {
|
|
|
12266
12362
|
const proto = Object.getPrototypeOf(value);
|
|
12267
12363
|
return proto === Object.prototype || proto === null;
|
|
12268
12364
|
}
|
|
12269
|
-
function isSanitizableSliceFile(
|
|
12270
|
-
if (!/\.ya?ml$/i.test(
|
|
12271
|
-
return
|
|
12365
|
+
function isSanitizableSliceFile(path27) {
|
|
12366
|
+
if (!/\.ya?ml$/i.test(path27)) return false;
|
|
12367
|
+
return path27 !== "resources" && !path27.startsWith("resources/");
|
|
12272
12368
|
}
|
|
12273
12369
|
function distinctUsesBackends(uses) {
|
|
12274
12370
|
return [...new Set((uses ?? []).map((u) => u.backend))];
|
|
@@ -14888,8 +14984,8 @@ var replicate_exports = {};
|
|
|
14888
14984
|
__export(replicate_exports, {
|
|
14889
14985
|
replicateCommand: () => replicateCommand
|
|
14890
14986
|
});
|
|
14891
|
-
import * as
|
|
14892
|
-
import * as
|
|
14987
|
+
import * as fs15 from "fs";
|
|
14988
|
+
import * as path17 from "path";
|
|
14893
14989
|
function parseArgs8(args2) {
|
|
14894
14990
|
let label;
|
|
14895
14991
|
let hubSelector;
|
|
@@ -14935,7 +15031,7 @@ async function replicateCommand(args2) {
|
|
|
14935
15031
|
payload.preview_label,
|
|
14936
15032
|
payload.branch_name
|
|
14937
15033
|
);
|
|
14938
|
-
|
|
15034
|
+
fs15.mkdirSync(path17.dirname(hubFolder), { recursive: true });
|
|
14939
15035
|
writeHubFolder(hubFolder, payload);
|
|
14940
15036
|
await downloadBinaryResourceFiles(hubFolder, payload);
|
|
14941
15037
|
hubFolder = autoRenameHubFolder(
|
|
@@ -14947,8 +15043,8 @@ async function replicateCommand(args2) {
|
|
|
14947
15043
|
payload.branch_name
|
|
14948
15044
|
);
|
|
14949
15045
|
autoBindIfUnbound(previewHubId);
|
|
14950
|
-
console.log(`Preview written to ${
|
|
14951
|
-
console.log(` Switch to it with: wayai use ${
|
|
15046
|
+
console.log(`Preview written to ${path17.basename(hubFolder)}`);
|
|
15047
|
+
console.log(` Switch to it with: wayai use ${path17.basename(hubFolder)}`);
|
|
14952
15048
|
}
|
|
14953
15049
|
var init_replicate = __esm({
|
|
14954
15050
|
"src/commands/replicate.ts"() {
|
|
@@ -14970,7 +15066,7 @@ var relabel_exports = {};
|
|
|
14970
15066
|
__export(relabel_exports, {
|
|
14971
15067
|
relabelCommand: () => relabelCommand
|
|
14972
15068
|
});
|
|
14973
|
-
import * as
|
|
15069
|
+
import * as path18 from "path";
|
|
14974
15070
|
function parseArgs9(args2) {
|
|
14975
15071
|
let label;
|
|
14976
15072
|
let clear = false;
|
|
@@ -15014,7 +15110,7 @@ async function relabelCommand(args2) {
|
|
|
15014
15110
|
} else {
|
|
15015
15111
|
console.error(`Multiple hubs found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
|
|
15016
15112
|
for (const h of previewHubs) {
|
|
15017
|
-
console.error(` ${
|
|
15113
|
+
console.error(` ${path18.basename(h.hubFolder)} (${h.hubId})`);
|
|
15018
15114
|
}
|
|
15019
15115
|
}
|
|
15020
15116
|
process.exit(1);
|
|
@@ -15023,7 +15119,7 @@ async function relabelCommand(args2) {
|
|
|
15023
15119
|
console.log("This is a read-only production mirror \u2014 production hubs have no preview label. Relabel the linked preview hub instead.");
|
|
15024
15120
|
return;
|
|
15025
15121
|
}
|
|
15026
|
-
assertHubMatchesBinding(target.hubId,
|
|
15122
|
+
assertHubMatchesBinding(target.hubId, path18.basename(target.hubFolder));
|
|
15027
15123
|
console.log(normalizedLabel ? `Setting preview label to "${normalizedLabel}"...` : "Clearing preview label...");
|
|
15028
15124
|
const { data } = await client.relabelPreview(target.hubId, normalizedLabel);
|
|
15029
15125
|
const row = data[0];
|
|
@@ -15039,7 +15135,7 @@ async function relabelCommand(args2) {
|
|
|
15039
15135
|
);
|
|
15040
15136
|
console.log(serverLabel ? `Preview label set to "${serverLabel}".` : "Preview label cleared.");
|
|
15041
15137
|
if (finalFolder !== target.hubFolder) {
|
|
15042
|
-
console.log(`Hub folder is now ${
|
|
15138
|
+
console.log(`Hub folder is now ${path18.basename(finalFolder)}`);
|
|
15043
15139
|
}
|
|
15044
15140
|
}
|
|
15045
15141
|
var init_relabel = __esm({
|
|
@@ -15065,7 +15161,7 @@ __export(publish_exports, {
|
|
|
15065
15161
|
renderHubDiff: () => renderHubDiff,
|
|
15066
15162
|
runPublish: () => runPublish
|
|
15067
15163
|
});
|
|
15068
|
-
import * as
|
|
15164
|
+
import * as path19 from "path";
|
|
15069
15165
|
function parseArgs10(args2) {
|
|
15070
15166
|
let autoConfirm = false;
|
|
15071
15167
|
let hubSelector;
|
|
@@ -15171,7 +15267,7 @@ async function publishCommand(args2) {
|
|
|
15171
15267
|
return;
|
|
15172
15268
|
}
|
|
15173
15269
|
}
|
|
15174
|
-
assertHubMatchesBinding(hubId, hubFolder ?
|
|
15270
|
+
assertHubMatchesBinding(hubId, hubFolder ? path19.basename(hubFolder) : void 0);
|
|
15175
15271
|
await runPublish(client, { hubId, localConfig, organizationId, autoConfirm });
|
|
15176
15272
|
}
|
|
15177
15273
|
var STATUS_STYLE;
|
|
@@ -15203,7 +15299,7 @@ var use_exports = {};
|
|
|
15203
15299
|
__export(use_exports, {
|
|
15204
15300
|
useCommand: () => useCommand
|
|
15205
15301
|
});
|
|
15206
|
-
import * as
|
|
15302
|
+
import * as path20 from "path";
|
|
15207
15303
|
async function useCommand(args2) {
|
|
15208
15304
|
const target = args2[0];
|
|
15209
15305
|
if (!target || target.startsWith("-")) {
|
|
@@ -15225,7 +15321,7 @@ async function useCommand(args2) {
|
|
|
15225
15321
|
const match = findHubByFolderName(workspaceDir, target);
|
|
15226
15322
|
if (!match) {
|
|
15227
15323
|
const newHubs = scanNewHubs(workspaceDir);
|
|
15228
|
-
const pending = newHubs.find((h) =>
|
|
15324
|
+
const pending = newHubs.find((h) => path20.basename(h.hubFolder) === target);
|
|
15229
15325
|
if (pending) {
|
|
15230
15326
|
console.error(
|
|
15231
15327
|
`"${target}" is a new hub that hasn't been created on the platform yet, so it has no id to bind to.
|
|
@@ -15236,10 +15332,10 @@ Create it first \u2014 the worktree binds automatically afterward:
|
|
|
15236
15332
|
}
|
|
15237
15333
|
console.error(`No hub matching "${target}" found in ${wsLabel}/. Pass a UUID or a folder name from:`);
|
|
15238
15334
|
for (const h of scanWorkspaceHubs(workspaceDir)) {
|
|
15239
|
-
console.error(` ${
|
|
15335
|
+
console.error(` ${path20.basename(h.hubFolder)} (${h.hubId})`);
|
|
15240
15336
|
}
|
|
15241
15337
|
for (const h of newHubs) {
|
|
15242
|
-
console.error(` ${
|
|
15338
|
+
console.error(` ${path20.basename(h.hubFolder)} (new \u2014 "${h.hubName}", run \`wayai create ${path20.basename(h.hubFolder)}\`)`);
|
|
15243
15339
|
}
|
|
15244
15340
|
process.exit(1);
|
|
15245
15341
|
}
|
|
@@ -15278,11 +15374,11 @@ __export(migrate_exports, {
|
|
|
15278
15374
|
migrateCommand: () => migrateCommand
|
|
15279
15375
|
});
|
|
15280
15376
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
15281
|
-
import * as
|
|
15282
|
-
import * as
|
|
15377
|
+
import * as fs16 from "fs";
|
|
15378
|
+
import * as path21 from "path";
|
|
15283
15379
|
function isTracked(gitRoot, p) {
|
|
15284
15380
|
try {
|
|
15285
|
-
execFileSync3("git", ["ls-files", "--error-unmatch", "--",
|
|
15381
|
+
execFileSync3("git", ["ls-files", "--error-unmatch", "--", path21.relative(gitRoot, p)], {
|
|
15286
15382
|
cwd: gitRoot,
|
|
15287
15383
|
stdio: ["pipe", "pipe", "pipe"]
|
|
15288
15384
|
});
|
|
@@ -15292,10 +15388,10 @@ function isTracked(gitRoot, p) {
|
|
|
15292
15388
|
}
|
|
15293
15389
|
}
|
|
15294
15390
|
function moveDir(gitRoot, from, to) {
|
|
15295
|
-
|
|
15391
|
+
fs16.mkdirSync(path21.dirname(to), { recursive: true });
|
|
15296
15392
|
if (isTracked(gitRoot, from)) {
|
|
15297
15393
|
try {
|
|
15298
|
-
execFileSync3("git", ["mv",
|
|
15394
|
+
execFileSync3("git", ["mv", path21.relative(gitRoot, from), path21.relative(gitRoot, to)], {
|
|
15299
15395
|
cwd: gitRoot,
|
|
15300
15396
|
stdio: ["pipe", "pipe", "pipe"]
|
|
15301
15397
|
});
|
|
@@ -15303,7 +15399,7 @@ function moveDir(gitRoot, from, to) {
|
|
|
15303
15399
|
} catch {
|
|
15304
15400
|
}
|
|
15305
15401
|
}
|
|
15306
|
-
|
|
15402
|
+
fs16.renameSync(from, to);
|
|
15307
15403
|
return "fs";
|
|
15308
15404
|
}
|
|
15309
15405
|
async function migrateCommand(_args) {
|
|
@@ -15312,12 +15408,12 @@ async function migrateCommand(_args) {
|
|
|
15312
15408
|
console.error("Not inside a git repository.");
|
|
15313
15409
|
process.exit(1);
|
|
15314
15410
|
}
|
|
15315
|
-
const rel = (p) =>
|
|
15316
|
-
const newWs =
|
|
15317
|
-
const legacyWs =
|
|
15318
|
-
const legacyOrg =
|
|
15319
|
-
const newHubs =
|
|
15320
|
-
const newOrg =
|
|
15411
|
+
const rel = (p) => path21.relative(gitRoot, p);
|
|
15412
|
+
const newWs = path21.join(gitRoot, WAYAI_LAYOUT.wsDir);
|
|
15413
|
+
const legacyWs = path21.join(gitRoot, WAYAI_LAYOUT.legacy.wsDir);
|
|
15414
|
+
const legacyOrg = path21.join(gitRoot, WAYAI_LAYOUT.legacy.orgAtRoot);
|
|
15415
|
+
const newHubs = path21.join(newWs, WAYAI_LAYOUT.hubsSubdir);
|
|
15416
|
+
const newOrg = path21.join(newWs, WAYAI_LAYOUT.orgSubdir);
|
|
15321
15417
|
const hasLegacyWs = isDirectory(legacyWs);
|
|
15322
15418
|
const hasLegacyOrg = isDirectory(legacyOrg);
|
|
15323
15419
|
if (!hasLegacyWs && !hasLegacyOrg) {
|
|
@@ -16654,8 +16750,8 @@ var eval_capture_exports = {};
|
|
|
16654
16750
|
__export(eval_capture_exports, {
|
|
16655
16751
|
evalCaptureCommand: () => evalCaptureCommand
|
|
16656
16752
|
});
|
|
16657
|
-
import * as
|
|
16658
|
-
import * as
|
|
16753
|
+
import * as fs17 from "fs";
|
|
16754
|
+
import * as path22 from "path";
|
|
16659
16755
|
import * as yaml7 from "js-yaml";
|
|
16660
16756
|
function isValidSetName(name) {
|
|
16661
16757
|
if (name.length === 0 || name === "." || name === "..") return false;
|
|
@@ -16721,15 +16817,15 @@ async function evalCaptureCommand(args2) {
|
|
|
16721
16817
|
const setFolderName = targetSetName;
|
|
16722
16818
|
const scenarioName = parsed.evalName ?? `Capture ${parsed.conversationId.slice(0, 8)}`;
|
|
16723
16819
|
const slug = slugify(scenarioName);
|
|
16724
|
-
const evalsDir =
|
|
16725
|
-
const targetDir =
|
|
16726
|
-
const targetPath =
|
|
16727
|
-
if (!targetPath.startsWith(evalsDir +
|
|
16728
|
-
console.error(`Resolved path "${
|
|
16820
|
+
const evalsDir = path22.join(hubFolder, "evals");
|
|
16821
|
+
const targetDir = path22.join(evalsDir, setFolderName);
|
|
16822
|
+
const targetPath = path22.join(targetDir, `${slug}.yaml`);
|
|
16823
|
+
if (!targetPath.startsWith(evalsDir + path22.sep)) {
|
|
16824
|
+
console.error(`Resolved path "${path22.relative(hubFolder, targetPath)}" escapes evals/. Aborting.`);
|
|
16729
16825
|
process.exit(1);
|
|
16730
16826
|
}
|
|
16731
|
-
if (
|
|
16732
|
-
console.error(`File already exists: ${
|
|
16827
|
+
if (fs17.existsSync(targetPath)) {
|
|
16828
|
+
console.error(`File already exists: ${path22.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
|
|
16733
16829
|
process.exit(1);
|
|
16734
16830
|
}
|
|
16735
16831
|
console.log("Resolving scenario set...");
|
|
@@ -16761,9 +16857,9 @@ async function evalCaptureCommand(args2) {
|
|
|
16761
16857
|
...captured.evaluator_instructions ? { evaluator_instructions: captured.evaluator_instructions } : {}
|
|
16762
16858
|
};
|
|
16763
16859
|
const yamlObj = buildEvalYamlObject(evalEntry, slug);
|
|
16764
|
-
|
|
16765
|
-
|
|
16766
|
-
const relPath =
|
|
16860
|
+
fs17.mkdirSync(targetDir, { recursive: true });
|
|
16861
|
+
fs17.writeFileSync(targetPath, yaml7.dump(yamlObj, YAML_DUMP_OPTIONS), "utf-8");
|
|
16862
|
+
const relPath = path22.relative(process.cwd(), targetPath);
|
|
16767
16863
|
console.log(`
|
|
16768
16864
|
Wrote ${relPath}`);
|
|
16769
16865
|
console.log("Run `wayai pull` to refresh the agent display name, then commit. The scenario is already on the platform.");
|
|
@@ -17990,23 +18086,23 @@ var init_set_connection_credential = __esm({
|
|
|
17990
18086
|
});
|
|
17991
18087
|
|
|
17992
18088
|
// src/lib/org-workspace.ts
|
|
17993
|
-
import * as
|
|
17994
|
-
import * as
|
|
18089
|
+
import * as fs18 from "fs";
|
|
18090
|
+
import * as path23 from "path";
|
|
17995
18091
|
import * as yaml8 from "js-yaml";
|
|
17996
18092
|
function getOrgDir(gitRoot) {
|
|
17997
18093
|
return resolveLayout(gitRoot).orgDir;
|
|
17998
18094
|
}
|
|
17999
18095
|
function orgManifestExists(orgDir) {
|
|
18000
|
-
return
|
|
18096
|
+
return fs18.existsSync(path23.join(orgDir, ORG_MANIFEST_NAME));
|
|
18001
18097
|
}
|
|
18002
18098
|
function parseOrgResources(orgDir) {
|
|
18003
|
-
const manifestPath =
|
|
18099
|
+
const manifestPath = path23.join(orgDir, ORG_MANIFEST_NAME);
|
|
18004
18100
|
let manifest = {};
|
|
18005
|
-
if (
|
|
18006
|
-
manifest = yaml8.load(
|
|
18101
|
+
if (fs18.existsSync(manifestPath)) {
|
|
18102
|
+
manifest = yaml8.load(fs18.readFileSync(manifestPath, "utf-8")) ?? {};
|
|
18007
18103
|
}
|
|
18008
18104
|
const rawResources = Array.isArray(manifest.resources) ? manifest.resources : [];
|
|
18009
|
-
const resourcesDir =
|
|
18105
|
+
const resourcesDir = path23.join(orgDir, "resources");
|
|
18010
18106
|
const resources = rawResources.map((res) => {
|
|
18011
18107
|
const resource = { name: res.name };
|
|
18012
18108
|
if (res.id) resource.id = res.id;
|
|
@@ -18018,8 +18114,8 @@ function parseOrgResources(orgDir) {
|
|
|
18018
18114
|
if (res.environment) resource.environment = res.environment;
|
|
18019
18115
|
if (Array.isArray(res.tags)) resource.tags = res.tags;
|
|
18020
18116
|
if (Array.isArray(res.folders)) resource.folders = res.folders;
|
|
18021
|
-
const resDir =
|
|
18022
|
-
if (
|
|
18117
|
+
const resDir = path23.join(resourcesDir, slugify(resource.name));
|
|
18118
|
+
if (fs18.existsSync(resDir)) {
|
|
18023
18119
|
const files = scanResourceFiles(resDir, "");
|
|
18024
18120
|
if (files.length > 0) resource.files = files;
|
|
18025
18121
|
}
|
|
@@ -18028,28 +18124,28 @@ function parseOrgResources(orgDir) {
|
|
|
18028
18124
|
return { version: 1, resources };
|
|
18029
18125
|
}
|
|
18030
18126
|
function writeOrgResources(orgDir, payload) {
|
|
18031
|
-
|
|
18127
|
+
fs18.mkdirSync(orgDir, { recursive: true });
|
|
18032
18128
|
const resources = payload.resources ?? [];
|
|
18033
18129
|
const manifestResources = resources.map((r) => {
|
|
18034
18130
|
const { files: _files, ...rest } = r;
|
|
18035
18131
|
return rest;
|
|
18036
18132
|
});
|
|
18037
|
-
|
|
18038
|
-
|
|
18133
|
+
fs18.writeFileSync(
|
|
18134
|
+
path23.join(orgDir, ORG_MANIFEST_NAME),
|
|
18039
18135
|
yaml8.dump({ version: 1, resources: manifestResources }, YAML_DUMP_OPTIONS),
|
|
18040
18136
|
"utf-8"
|
|
18041
18137
|
);
|
|
18042
|
-
const resourcesDir =
|
|
18138
|
+
const resourcesDir = path23.join(orgDir, "resources");
|
|
18043
18139
|
const currentSlugs = /* @__PURE__ */ new Set();
|
|
18044
18140
|
for (const resource of resources) {
|
|
18045
18141
|
const resSlug = slugify(resource.name);
|
|
18046
18142
|
currentSlugs.add(resSlug);
|
|
18047
|
-
writeResourceFileTree(
|
|
18143
|
+
writeResourceFileTree(path23.join(resourcesDir, resSlug), resource.files || []);
|
|
18048
18144
|
}
|
|
18049
|
-
if (
|
|
18050
|
-
for (const entry of
|
|
18145
|
+
if (fs18.existsSync(resourcesDir)) {
|
|
18146
|
+
for (const entry of fs18.readdirSync(resourcesDir, { withFileTypes: true })) {
|
|
18051
18147
|
if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
|
|
18052
|
-
|
|
18148
|
+
fs18.rmSync(path23.join(resourcesDir, entry.name), { recursive: true, force: true });
|
|
18053
18149
|
}
|
|
18054
18150
|
}
|
|
18055
18151
|
}
|
|
@@ -18058,7 +18154,7 @@ async function downloadOrgBinaryFiles(orgDir, payload) {
|
|
|
18058
18154
|
let count = 0;
|
|
18059
18155
|
for (const resource of payload.resources ?? []) {
|
|
18060
18156
|
if (!resource.files) continue;
|
|
18061
|
-
const resDir =
|
|
18157
|
+
const resDir = path23.join(orgDir, "resources", slugify(resource.name));
|
|
18062
18158
|
count += await downloadBinaryFiles(resDir, resource.files);
|
|
18063
18159
|
}
|
|
18064
18160
|
if (count > 0) console.log(`Downloaded ${count} binary resource file(s).`);
|
|
@@ -18314,20 +18410,20 @@ var init_list = __esm({
|
|
|
18314
18410
|
});
|
|
18315
18411
|
|
|
18316
18412
|
// src/lib/template-files.ts
|
|
18317
|
-
import * as
|
|
18318
|
-
import * as
|
|
18413
|
+
import * as fs19 from "fs";
|
|
18414
|
+
import * as path24 from "path";
|
|
18319
18415
|
function readDirToFileMap(rootDir) {
|
|
18320
18416
|
const out = {};
|
|
18321
18417
|
function walk(dir, prefix) {
|
|
18322
|
-
const entries =
|
|
18418
|
+
const entries = fs19.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
18323
18419
|
for (const entry of entries) {
|
|
18324
|
-
const abs =
|
|
18420
|
+
const abs = path24.join(dir, entry.name);
|
|
18325
18421
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
18326
18422
|
if (entry.isDirectory()) walk(abs, rel);
|
|
18327
|
-
else if (entry.isFile()) out[rel] =
|
|
18423
|
+
else if (entry.isFile()) out[rel] = fs19.readFileSync(abs, "utf-8");
|
|
18328
18424
|
}
|
|
18329
18425
|
}
|
|
18330
|
-
if (
|
|
18426
|
+
if (fs19.existsSync(rootDir)) walk(rootDir, "");
|
|
18331
18427
|
return out;
|
|
18332
18428
|
}
|
|
18333
18429
|
function detectCollisions(targetDir, files) {
|
|
@@ -18336,7 +18432,7 @@ function detectCollisions(targetDir, files) {
|
|
|
18336
18432
|
if (!isSafeTemplatePath2(rel)) {
|
|
18337
18433
|
throw new Error(`Refusing to inspect unsafe template path: ${rel}`);
|
|
18338
18434
|
}
|
|
18339
|
-
if (
|
|
18435
|
+
if (fs19.existsSync(path24.join(targetDir, rel))) collisions.push(rel);
|
|
18340
18436
|
}
|
|
18341
18437
|
return collisions.sort((a, b) => a.localeCompare(b));
|
|
18342
18438
|
}
|
|
@@ -18346,9 +18442,9 @@ function writeFileMap(targetDir, files) {
|
|
|
18346
18442
|
if (!isSafeTemplatePath2(rel)) {
|
|
18347
18443
|
throw new Error(`Refusing to write unsafe template path: ${rel}`);
|
|
18348
18444
|
}
|
|
18349
|
-
const abs =
|
|
18350
|
-
|
|
18351
|
-
|
|
18445
|
+
const abs = path24.join(targetDir, rel);
|
|
18446
|
+
fs19.mkdirSync(path24.dirname(abs), { recursive: true });
|
|
18447
|
+
fs19.writeFileSync(abs, body, "utf-8");
|
|
18352
18448
|
written.push(rel);
|
|
18353
18449
|
}
|
|
18354
18450
|
return written;
|
|
@@ -18356,20 +18452,20 @@ function writeFileMap(targetDir, files) {
|
|
|
18356
18452
|
function listDirRelFiles(dir) {
|
|
18357
18453
|
const out = [];
|
|
18358
18454
|
function walk(d, prefix) {
|
|
18359
|
-
for (const entry of
|
|
18455
|
+
for (const entry of fs19.readdirSync(d, { withFileTypes: true })) {
|
|
18360
18456
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
18361
|
-
if (entry.isDirectory()) walk(
|
|
18457
|
+
if (entry.isDirectory()) walk(path24.join(d, entry.name), rel);
|
|
18362
18458
|
else if (entry.isFile()) out.push(rel);
|
|
18363
18459
|
}
|
|
18364
18460
|
}
|
|
18365
|
-
if (
|
|
18461
|
+
if (fs19.existsSync(dir)) walk(dir, "");
|
|
18366
18462
|
return out;
|
|
18367
18463
|
}
|
|
18368
18464
|
function writeSliceSnapshot(targetDir, files) {
|
|
18369
18465
|
const keep = new Set(Object.keys(files));
|
|
18370
18466
|
const removed = listDirRelFiles(targetDir).filter((rel) => !keep.has(rel)).sort((a, b) => a.localeCompare(b));
|
|
18371
18467
|
const written = writeFileMap(targetDir, files).sort((a, b) => a.localeCompare(b));
|
|
18372
|
-
if (
|
|
18468
|
+
if (fs19.existsSync(targetDir)) cleanOrphanFiles(targetDir, "", keep);
|
|
18373
18469
|
return { written, removed };
|
|
18374
18470
|
}
|
|
18375
18471
|
var init_template_files = __esm({
|
|
@@ -18385,7 +18481,7 @@ var templates_exports = {};
|
|
|
18385
18481
|
__export(templates_exports, {
|
|
18386
18482
|
templateCommand: () => templateCommand
|
|
18387
18483
|
});
|
|
18388
|
-
import * as
|
|
18484
|
+
import * as path25 from "path";
|
|
18389
18485
|
async function templateCommand(args2) {
|
|
18390
18486
|
const [sub, ...rest] = args2;
|
|
18391
18487
|
switch (sub) {
|
|
@@ -18501,8 +18597,8 @@ async function runTemplatePull(rest) {
|
|
|
18501
18597
|
console.log(`Template "${slug}" has no WayAI slice${hint}`);
|
|
18502
18598
|
return;
|
|
18503
18599
|
}
|
|
18504
|
-
const targetDir =
|
|
18505
|
-
const relTarget =
|
|
18600
|
+
const targetDir = path25.join(resolveLayout(gitRoot).hubsDir, slug);
|
|
18601
|
+
const relTarget = path25.relative(gitRoot, targetDir);
|
|
18506
18602
|
const collisions = detectCollisions(targetDir, detail.files);
|
|
18507
18603
|
if (dryRun) {
|
|
18508
18604
|
const planned = Object.keys(detail.files).sort((a, b) => a.localeCompare(b));
|
|
@@ -18676,8 +18772,8 @@ var admin_exports = {};
|
|
|
18676
18772
|
__export(admin_exports, {
|
|
18677
18773
|
adminCommand: () => adminCommand
|
|
18678
18774
|
});
|
|
18679
|
-
import * as
|
|
18680
|
-
import * as
|
|
18775
|
+
import * as fs20 from "fs";
|
|
18776
|
+
import * as path26 from "path";
|
|
18681
18777
|
import * as yaml10 from "js-yaml";
|
|
18682
18778
|
async function adminCommand(args2) {
|
|
18683
18779
|
const [group, ...afterGroup] = args2;
|
|
@@ -18985,7 +19081,7 @@ async function runArchiveRead(positional, flagArgs) {
|
|
|
18985
19081
|
exitOnApiError(err);
|
|
18986
19082
|
throw err;
|
|
18987
19083
|
}
|
|
18988
|
-
|
|
19084
|
+
fs20.writeFileSync(outPath, zip);
|
|
18989
19085
|
console.log(`Wrote ${zip.byteLength} bytes to ${outPath}`);
|
|
18990
19086
|
return;
|
|
18991
19087
|
}
|
|
@@ -19117,15 +19213,15 @@ function loadTemplateManifest(slug) {
|
|
|
19117
19213
|
console.error("Not in a git repository. Run from the tutorials/ authoring repo.");
|
|
19118
19214
|
process.exit(1);
|
|
19119
19215
|
}
|
|
19120
|
-
const templateDir =
|
|
19121
|
-
const manifestPath =
|
|
19122
|
-
if (!
|
|
19123
|
-
console.error(`template.yaml not found at ${
|
|
19216
|
+
const templateDir = path26.join(resolveTemplatesDir(gitRoot), slug);
|
|
19217
|
+
const manifestPath = path26.join(templateDir, "template.yaml");
|
|
19218
|
+
if (!fs20.existsSync(manifestPath)) {
|
|
19219
|
+
console.error(`template.yaml not found at ${path26.relative(gitRoot, manifestPath)}`);
|
|
19124
19220
|
process.exit(1);
|
|
19125
19221
|
}
|
|
19126
19222
|
let manifest;
|
|
19127
19223
|
try {
|
|
19128
|
-
manifest = templateYamlSchema2.parse(yaml10.load(
|
|
19224
|
+
manifest = templateYamlSchema2.parse(yaml10.load(fs20.readFileSync(manifestPath, "utf-8")));
|
|
19129
19225
|
} catch (err) {
|
|
19130
19226
|
console.error(`Invalid template.yaml: ${err instanceof Error ? err.message : String(err)}`);
|
|
19131
19227
|
process.exit(1);
|
|
@@ -19155,20 +19251,20 @@ async function runTemplatePush(positional) {
|
|
|
19155
19251
|
const wayaiEntry = manifest.wayai.locales[locale];
|
|
19156
19252
|
let wayaiFiles;
|
|
19157
19253
|
if (wayaiEntry) {
|
|
19158
|
-
const sliceDir =
|
|
19159
|
-
if (!
|
|
19254
|
+
const sliceDir = path26.resolve(templateDir, wayaiEntry.source);
|
|
19255
|
+
if (!fs20.existsSync(sliceDir)) {
|
|
19160
19256
|
console.error(`wayai source not found for ${locale}: ${wayaiEntry.source} (resolved ${sliceDir})`);
|
|
19161
19257
|
process.exit(1);
|
|
19162
19258
|
}
|
|
19163
19259
|
if (!isInsideTemplateDir(sliceDir, templateDir)) {
|
|
19164
19260
|
console.warn(
|
|
19165
|
-
`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 ${
|
|
19261
|
+
`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 ${path26.basename(sliceDir)}\` to commit a stable frozen slice.`
|
|
19166
19262
|
);
|
|
19167
19263
|
}
|
|
19168
19264
|
wayaiFiles = readDirToFileMap(sliceDir);
|
|
19169
19265
|
}
|
|
19170
|
-
const readmePath =
|
|
19171
|
-
const readmeMarkdown =
|
|
19266
|
+
const readmePath = path26.join(templateDir, `README.${locale}.md`);
|
|
19267
|
+
const readmeMarkdown = fs20.existsSync(readmePath) ? fs20.readFileSync(readmePath, "utf-8") : "";
|
|
19172
19268
|
locales[locale] = {
|
|
19173
19269
|
readmeMarkdown,
|
|
19174
19270
|
...wayaiFiles && { wayaiFiles },
|
|
@@ -19179,9 +19275,9 @@ async function runTemplatePush(positional) {
|
|
|
19179
19275
|
}
|
|
19180
19276
|
let hero;
|
|
19181
19277
|
if (manifest.hero) {
|
|
19182
|
-
const heroPath =
|
|
19183
|
-
if (
|
|
19184
|
-
hero = { filename:
|
|
19278
|
+
const heroPath = path26.resolve(templateDir, manifest.hero);
|
|
19279
|
+
if (fs20.existsSync(heroPath)) {
|
|
19280
|
+
hero = { filename: path26.basename(heroPath), dataBase64: fs20.readFileSync(heroPath).toString("base64") };
|
|
19185
19281
|
} else {
|
|
19186
19282
|
console.error(`Warning: hero not found at ${manifest.hero}; skipping.`);
|
|
19187
19283
|
}
|
|
@@ -19207,7 +19303,7 @@ async function runTemplatePush(positional) {
|
|
|
19207
19303
|
}
|
|
19208
19304
|
}
|
|
19209
19305
|
function isInsideTemplateDir(dest, templateDir) {
|
|
19210
|
-
return dest === templateDir || dest.startsWith(templateDir +
|
|
19306
|
+
return dest === templateDir || dest.startsWith(templateDir + path26.sep);
|
|
19211
19307
|
}
|
|
19212
19308
|
async function runTemplateFreeze(positional, flagArgs) {
|
|
19213
19309
|
const slug = positional[0];
|
|
@@ -19268,7 +19364,7 @@ async function runTemplateFreeze(positional, flagArgs) {
|
|
|
19268
19364
|
process.exit(1);
|
|
19269
19365
|
}
|
|
19270
19366
|
const entry = manifest.wayai.locales[targetLocale];
|
|
19271
|
-
const dest =
|
|
19367
|
+
const dest = path26.resolve(templateDir, entry.source);
|
|
19272
19368
|
if (!isInsideTemplateDir(dest, templateDir) || dest === templateDir) {
|
|
19273
19369
|
console.error(
|
|
19274
19370
|
`source for "${targetLocale}" must be a committed path inside ${slug}/ (e.g. "./${targetLocale}/slice"), but resolved to:
|
|
@@ -19287,7 +19383,7 @@ Set it to a subdir of the template folder and re-run freeze.`
|
|
|
19287
19383
|
const hubs = scanWorkspaceHubs(hubsDir);
|
|
19288
19384
|
if (hubs.length) {
|
|
19289
19385
|
console.error("Available hubs:");
|
|
19290
|
-
for (const h of hubs) console.error(` ${
|
|
19386
|
+
for (const h of hubs) console.error(` ${path26.basename(h.hubFolder)} (${h.hubId})`);
|
|
19291
19387
|
}
|
|
19292
19388
|
console.error(`
|
|
19293
19389
|
Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`);
|
|
@@ -19295,12 +19391,12 @@ Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`
|
|
|
19295
19391
|
}
|
|
19296
19392
|
const liveFiles = readDirToFileMap(hubFolder);
|
|
19297
19393
|
if (Object.keys(liveFiles).length === 0) {
|
|
19298
|
-
console.error(`Source hub folder has no files to freeze: ${
|
|
19394
|
+
console.error(`Source hub folder has no files to freeze: ${path26.relative(gitRoot, hubFolder)}`);
|
|
19299
19395
|
process.exit(1);
|
|
19300
19396
|
}
|
|
19301
19397
|
const sanitized = sanitizeWayaiSliceFiles(liveFiles);
|
|
19302
|
-
const relDest =
|
|
19303
|
-
const relSrc =
|
|
19398
|
+
const relDest = path26.relative(gitRoot, dest);
|
|
19399
|
+
const relSrc = path26.relative(gitRoot, hubFolder);
|
|
19304
19400
|
if (dryRun) {
|
|
19305
19401
|
const existing = new Set(listDirRelFiles(dest));
|
|
19306
19402
|
const nextKeys = new Set(Object.keys(sanitized));
|
|
@@ -19360,7 +19456,7 @@ async function runTemplatePull2(positional, flagArgs) {
|
|
|
19360
19456
|
console.log(JSON.stringify(detail, null, 2));
|
|
19361
19457
|
return;
|
|
19362
19458
|
}
|
|
19363
|
-
const target = outDir ?
|
|
19459
|
+
const target = outDir ? path26.resolve(outDir) : path26.join(process.cwd(), "template-store-pull", slug);
|
|
19364
19460
|
const written = writeFileMap(target, detail.files);
|
|
19365
19461
|
console.log(`Pulled "${slug}" from the store \u2192 ${target} (${written.length} file${written.length === 1 ? "" : "s"}).`);
|
|
19366
19462
|
const uses = detail.uses ?? [];
|
|
@@ -19383,13 +19479,13 @@ async function runSkillInstall(positional) {
|
|
|
19383
19479
|
throw err;
|
|
19384
19480
|
}
|
|
19385
19481
|
const root = findGitRoot() ?? process.cwd();
|
|
19386
|
-
const present = HARNESS_SKILL_DIRS.filter((dir) =>
|
|
19482
|
+
const present = HARNESS_SKILL_DIRS.filter((dir) => fs20.existsSync(path26.join(root, dir)));
|
|
19387
19483
|
const targets = present.length > 0 ? present : HARNESS_SKILL_DIRS;
|
|
19388
19484
|
const fileCount = Object.keys(res.files).length;
|
|
19389
19485
|
const relDirs = targets.map((harness) => {
|
|
19390
|
-
const targetDir =
|
|
19486
|
+
const targetDir = path26.join(root, harness, "skills", name);
|
|
19391
19487
|
writeFileMap(targetDir, res.files);
|
|
19392
|
-
return `${
|
|
19488
|
+
return `${path26.relative(root, targetDir)}/`;
|
|
19393
19489
|
});
|
|
19394
19490
|
console.log(`Installed skill "${name}" (${fileCount} file${fileCount === 1 ? "" : "s"}) \u2192 ${relDirs.join(", ")}`);
|
|
19395
19491
|
console.log("Reload your agent (e.g. restart Claude Code) to pick up the skill.");
|
|
@@ -20222,19 +20318,58 @@ var init_admin = __esm({
|
|
|
20222
20318
|
}
|
|
20223
20319
|
});
|
|
20224
20320
|
|
|
20225
|
-
// src/
|
|
20226
|
-
|
|
20227
|
-
|
|
20228
|
-
|
|
20229
|
-
function
|
|
20230
|
-
|
|
20231
|
-
|
|
20232
|
-
|
|
20233
|
-
|
|
20234
|
-
|
|
20321
|
+
// src/lib/version-status.ts
|
|
20322
|
+
function componentStatus(current, latest) {
|
|
20323
|
+
return { current, latest, behind: Boolean(current && latest && isNewerVersion(latest, current)) };
|
|
20324
|
+
}
|
|
20325
|
+
function resolveVersionStatus(cliVersion) {
|
|
20326
|
+
const cliLatest = readVersionCache(CLI_CACHE_FILE)?.latest ?? null;
|
|
20327
|
+
const repoRoot = findRepoRootSync() ?? process.cwd();
|
|
20328
|
+
const skillCurrent = lowestInstalledVersion(findInstalledSkills(repoRoot));
|
|
20329
|
+
const skillLatest = skillCurrent ? readVersionCache(SKILL_CACHE_FILE)?.latest ?? null : null;
|
|
20330
|
+
return { cli: componentStatus(cliVersion, cliLatest), skill: componentStatus(skillCurrent, skillLatest) };
|
|
20331
|
+
}
|
|
20332
|
+
function isVersionBehind(status) {
|
|
20333
|
+
return status.cli.behind || status.skill.behind;
|
|
20334
|
+
}
|
|
20335
|
+
function formatClientVersion(status) {
|
|
20336
|
+
const cli = `cli@${status.cli.current ?? "unknown"}`;
|
|
20337
|
+
if (!status.skill.current) return cli.slice(0, 64);
|
|
20338
|
+
const withSkill = `${cli} skill@${status.skill.current}`;
|
|
20339
|
+
return withSkill.length <= 64 ? withSkill : cli.slice(0, 64);
|
|
20340
|
+
}
|
|
20341
|
+
function buildStaleToolingWarning(status) {
|
|
20342
|
+
const lines = [];
|
|
20343
|
+
if (status.cli.behind) {
|
|
20344
|
+
lines.push(` CLI ${status.cli.current} \u2192 ${status.cli.latest} (run: wayai update)`);
|
|
20345
|
+
}
|
|
20346
|
+
if (status.skill.behind) {
|
|
20347
|
+
lines.push(` Skill ${status.skill.current} \u2192 ${status.skill.latest} (run: npx skills add wayai-pro/wayai-skill -y)`);
|
|
20348
|
+
}
|
|
20349
|
+
if (lines.length === 0) return null;
|
|
20350
|
+
return [
|
|
20351
|
+
"Your WayAI tooling is behind the latest release:",
|
|
20352
|
+
...lines,
|
|
20353
|
+
"",
|
|
20354
|
+
"A stale CLI or skill is the most common cause of a false bug report \u2014 the issue may",
|
|
20355
|
+
"already be fixed upstream. Update, then reproduce before reporting."
|
|
20356
|
+
].join("\n");
|
|
20357
|
+
}
|
|
20358
|
+
var init_version_status = __esm({
|
|
20359
|
+
"src/lib/version-status.ts"() {
|
|
20360
|
+
"use strict";
|
|
20361
|
+
init_version_cache();
|
|
20362
|
+
init_skill_version();
|
|
20363
|
+
init_workspace();
|
|
20364
|
+
init_utils();
|
|
20235
20365
|
}
|
|
20366
|
+
});
|
|
20367
|
+
|
|
20368
|
+
// src/commands/report-create.ts
|
|
20369
|
+
function isVersionGateDisabled() {
|
|
20370
|
+
return Boolean(process.env.NO_UPDATE_NOTIFIER || process.env.WAYAI_NO_UPDATE_CHECK);
|
|
20236
20371
|
}
|
|
20237
|
-
async function reportCreateCommand(args2) {
|
|
20372
|
+
async function reportCreateCommand(args2, cliVersion = null) {
|
|
20238
20373
|
let title;
|
|
20239
20374
|
let description;
|
|
20240
20375
|
let source;
|
|
@@ -20245,9 +20380,12 @@ async function reportCreateCommand(args2) {
|
|
|
20245
20380
|
let errorMessage;
|
|
20246
20381
|
let steps;
|
|
20247
20382
|
let context;
|
|
20383
|
+
let skipVersionCheck = false;
|
|
20248
20384
|
for (let i = 0; i < args2.length; i++) {
|
|
20249
20385
|
const arg = args2[i];
|
|
20250
|
-
if (arg === "--
|
|
20386
|
+
if (arg === "--skip-version-check") {
|
|
20387
|
+
skipVersionCheck = true;
|
|
20388
|
+
} else if (arg === "--title" || arg === "-t") {
|
|
20251
20389
|
title = args2[++i];
|
|
20252
20390
|
} else if (arg === "--description" || arg === "-d") {
|
|
20253
20391
|
description = args2[++i];
|
|
@@ -20285,8 +20423,23 @@ async function reportCreateCommand(args2) {
|
|
|
20285
20423
|
console.error(" -e, --error <text> Error message or stack trace");
|
|
20286
20424
|
console.error(" -s, --steps <text> Steps to reproduce");
|
|
20287
20425
|
console.error(" --context <text> Additional context");
|
|
20426
|
+
console.error(" --skip-version-check File even when the CLI/skill is behind the latest release");
|
|
20288
20427
|
process.exit(1);
|
|
20289
20428
|
}
|
|
20429
|
+
const versionStatus = resolveVersionStatus(cliVersion);
|
|
20430
|
+
const clientVersion = formatClientVersion(versionStatus);
|
|
20431
|
+
if (isVersionBehind(versionStatus) && !isVersionGateDisabled()) {
|
|
20432
|
+
const warning = buildStaleToolingWarning(versionStatus);
|
|
20433
|
+
if (!skipVersionCheck) {
|
|
20434
|
+
console.error(warning);
|
|
20435
|
+
console.error("");
|
|
20436
|
+
console.error("To file this report anyway, re-run with --skip-version-check.");
|
|
20437
|
+
process.exit(1);
|
|
20438
|
+
}
|
|
20439
|
+
console.error("Filing on stale tooling (--skip-version-check):");
|
|
20440
|
+
console.error(warning);
|
|
20441
|
+
console.error("");
|
|
20442
|
+
}
|
|
20290
20443
|
const { config, accessToken } = await requireAuth();
|
|
20291
20444
|
const client = new ApiClient({ apiUrl: config.api_url, accessToken });
|
|
20292
20445
|
const repoConfig = readRepoConfig();
|
|
@@ -20304,7 +20457,7 @@ async function reportCreateCommand(args2) {
|
|
|
20304
20457
|
error_message: errorMessage,
|
|
20305
20458
|
steps_to_reproduce: steps,
|
|
20306
20459
|
additional_context: context,
|
|
20307
|
-
client_version:
|
|
20460
|
+
client_version: clientVersion
|
|
20308
20461
|
});
|
|
20309
20462
|
if (result.created) {
|
|
20310
20463
|
console.log(`Report submitted: ${result.report_id}`);
|
|
@@ -20328,14 +20481,13 @@ async function reportCreateCommand(args2) {
|
|
|
20328
20481
|
throw err;
|
|
20329
20482
|
}
|
|
20330
20483
|
}
|
|
20331
|
-
var __dirname;
|
|
20332
20484
|
var init_report_create = __esm({
|
|
20333
20485
|
"src/commands/report-create.ts"() {
|
|
20334
20486
|
"use strict";
|
|
20335
20487
|
init_auth();
|
|
20336
20488
|
init_repo_config();
|
|
20337
20489
|
init_api_client();
|
|
20338
|
-
|
|
20490
|
+
init_version_status();
|
|
20339
20491
|
}
|
|
20340
20492
|
});
|
|
20341
20493
|
|
|
@@ -20344,11 +20496,11 @@ var report_exports = {};
|
|
|
20344
20496
|
__export(report_exports, {
|
|
20345
20497
|
reportCommand: () => reportCommand
|
|
20346
20498
|
});
|
|
20347
|
-
async function reportCommand(args2) {
|
|
20499
|
+
async function reportCommand(args2, cliVersion) {
|
|
20348
20500
|
const sub = args2[0];
|
|
20349
20501
|
switch (sub) {
|
|
20350
20502
|
case "create":
|
|
20351
|
-
await reportCreateCommand(args2.slice(1));
|
|
20503
|
+
await reportCreateCommand(args2.slice(1), cliVersion ?? null);
|
|
20352
20504
|
return;
|
|
20353
20505
|
case "edit":
|
|
20354
20506
|
await reportEditCommand(args2.slice(1));
|
|
@@ -20610,9 +20762,9 @@ var init_update = __esm({
|
|
|
20610
20762
|
|
|
20611
20763
|
// src/index.ts
|
|
20612
20764
|
init_sentry();
|
|
20613
|
-
import { readFileSync as
|
|
20614
|
-
import { fileURLToPath as
|
|
20615
|
-
import { dirname as
|
|
20765
|
+
import { readFileSync as readFileSync18 } from "fs";
|
|
20766
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
20767
|
+
import { dirname as dirname9, join as join25 } from "path";
|
|
20616
20768
|
|
|
20617
20769
|
// src/lib/errors.ts
|
|
20618
20770
|
init_api_client();
|
|
@@ -20791,11 +20943,11 @@ Run \`wayai admin skill install\` to update.`);
|
|
|
20791
20943
|
}
|
|
20792
20944
|
|
|
20793
20945
|
// src/index.ts
|
|
20794
|
-
var
|
|
20795
|
-
var pkg = JSON.parse(
|
|
20946
|
+
var __dirname = dirname9(fileURLToPath2(import.meta.url));
|
|
20947
|
+
var pkg = JSON.parse(readFileSync18(join25(__dirname, "..", "package.json"), "utf-8"));
|
|
20796
20948
|
var [, , command, ...args] = process.argv;
|
|
20797
20949
|
var isBackgroundRefresh = command === REFRESH_COMMAND;
|
|
20798
|
-
if (!isBackgroundRefresh) initSentry(command);
|
|
20950
|
+
if (!isBackgroundRefresh) initSentry(command, pkg.version);
|
|
20799
20951
|
async function main() {
|
|
20800
20952
|
if (shouldInterceptHelp(command, args, OWN_HELP_COMMANDS)) {
|
|
20801
20953
|
printHelp3();
|
|
@@ -20978,7 +21130,7 @@ async function main() {
|
|
|
20978
21130
|
}
|
|
20979
21131
|
case "report": {
|
|
20980
21132
|
const { reportCommand: reportCommand2 } = await Promise.resolve().then(() => (init_report(), report_exports));
|
|
20981
|
-
await reportCommand2(args);
|
|
21133
|
+
await reportCommand2(args, pkg.version);
|
|
20982
21134
|
break;
|
|
20983
21135
|
}
|
|
20984
21136
|
case "update": {
|
|
@@ -21115,7 +21267,7 @@ async function runForeground() {
|
|
|
21115
21267
|
try {
|
|
21116
21268
|
await main();
|
|
21117
21269
|
if (command && !SKIP_UPDATE_CHECK.includes(command) && !wantsHelp(args)) {
|
|
21118
|
-
showUpdateNudges(pkg.version,
|
|
21270
|
+
showUpdateNudges(pkg.version, fileURLToPath2(import.meta.url));
|
|
21119
21271
|
}
|
|
21120
21272
|
await closeSentry();
|
|
21121
21273
|
} catch (err) {
|