@wayai/cli 0.3.89 → 0.3.91
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 +431 -338
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -165,11 +165,11 @@ function captureException2(error, context) {
|
|
|
165
165
|
Sentry.captureException(error);
|
|
166
166
|
});
|
|
167
167
|
}
|
|
168
|
-
function addApiBreadcrumb(method,
|
|
168
|
+
function addApiBreadcrumb(method, 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
|
);
|
|
@@ -7459,7 +7459,6 @@ var init_dist = __esm({
|
|
|
7459
7459
|
});
|
|
7460
7460
|
dataExplorerDebugAnalyticsTable = external_exports.enum([
|
|
7461
7461
|
"conversation",
|
|
7462
|
-
"message",
|
|
7463
7462
|
"schedule_event"
|
|
7464
7463
|
]);
|
|
7465
7464
|
debugUuid = external_exports.string().uuid();
|
|
@@ -8795,9 +8794,9 @@ function getVersionCachePath(filename = CLI_CACHE_FILE) {
|
|
|
8795
8794
|
}
|
|
8796
8795
|
function readVersionCache(filename = CLI_CACHE_FILE) {
|
|
8797
8796
|
try {
|
|
8798
|
-
const
|
|
8799
|
-
if (!existsSync4(
|
|
8800
|
-
const parsed = JSON.parse(readFileSync5(
|
|
8797
|
+
const path27 = getVersionCachePath(filename);
|
|
8798
|
+
if (!existsSync4(path27)) return null;
|
|
8799
|
+
const parsed = JSON.parse(readFileSync5(path27, "utf-8"));
|
|
8801
8800
|
if (typeof parsed.lastCheck !== "number") return null;
|
|
8802
8801
|
if (parsed.latest !== null && typeof parsed.latest !== "string") return null;
|
|
8803
8802
|
return parsed;
|
|
@@ -8817,10 +8816,10 @@ function isVersionCacheStale(filename = CLI_CACHE_FILE, maxAgeMs = MAX_AGE_24H_M
|
|
|
8817
8816
|
return Date.now() - cache.lastCheck > maxAgeMs;
|
|
8818
8817
|
}
|
|
8819
8818
|
function writeVersionCache(filename, cache) {
|
|
8820
|
-
const
|
|
8821
|
-
const dir = dirname3(
|
|
8819
|
+
const path27 = getVersionCachePath(filename);
|
|
8820
|
+
const dir = dirname3(path27);
|
|
8822
8821
|
if (!existsSync4(dir)) mkdirSync(dir, { recursive: true });
|
|
8823
|
-
writeFileSync2(
|
|
8822
|
+
writeFileSync2(path27, JSON.stringify(cache));
|
|
8824
8823
|
}
|
|
8825
8824
|
function touchVersionCache(filename) {
|
|
8826
8825
|
writeVersionCache(filename, { lastCheck: Date.now(), latest: readVersionCache(filename)?.latest ?? null });
|
|
@@ -8859,14 +8858,14 @@ function parseFrontmatterVersion(content) {
|
|
|
8859
8858
|
function findInstalledSkills(projectRoot, paths = SKILL_INSTALL_PATHS) {
|
|
8860
8859
|
const found = [];
|
|
8861
8860
|
for (const rel of paths) {
|
|
8862
|
-
const
|
|
8863
|
-
if (!existsSync5(
|
|
8861
|
+
const path27 = join7(projectRoot, rel);
|
|
8862
|
+
if (!existsSync5(path27)) continue;
|
|
8864
8863
|
let version = null;
|
|
8865
8864
|
try {
|
|
8866
|
-
version = parseFrontmatterVersion(readFileSync6(
|
|
8865
|
+
version = parseFrontmatterVersion(readFileSync6(path27, "utf-8"));
|
|
8867
8866
|
} catch {
|
|
8868
8867
|
}
|
|
8869
|
-
found.push({ path:
|
|
8868
|
+
found.push({ path: path27, version });
|
|
8870
8869
|
}
|
|
8871
8870
|
return found;
|
|
8872
8871
|
}
|
|
@@ -10099,6 +10098,85 @@ var init_constants = __esm({
|
|
|
10099
10098
|
}
|
|
10100
10099
|
});
|
|
10101
10100
|
|
|
10101
|
+
// src/lib/workspace-files.ts
|
|
10102
|
+
import * as fs8 from "fs";
|
|
10103
|
+
import * as path9 from "path";
|
|
10104
|
+
function perHubAgentsMd(hubFolderName) {
|
|
10105
|
+
return [
|
|
10106
|
+
`# ${hubFolderName}`,
|
|
10107
|
+
"",
|
|
10108
|
+
"Notes about THIS hub that the config files (hub.yaml, agents/) don't capture:",
|
|
10109
|
+
"why it exists, key decisions and the reasons behind them, business rules that",
|
|
10110
|
+
"only apply here, terminology, integration quirks.",
|
|
10111
|
+
"",
|
|
10112
|
+
"Keep it short and about *why / what is different* \u2014 platform mechanics live in",
|
|
10113
|
+
"the WayAI skill. Fill this in as you learn about the hub; delete this",
|
|
10114
|
+
"placeholder once you do.",
|
|
10115
|
+
""
|
|
10116
|
+
].join("\n");
|
|
10117
|
+
}
|
|
10118
|
+
function isWorkspace(gitRoot) {
|
|
10119
|
+
if (fs8.existsSync(path9.join(gitRoot, ".wayai.yaml"))) return true;
|
|
10120
|
+
return isDirectory(resolveLayout(gitRoot).hubsDir);
|
|
10121
|
+
}
|
|
10122
|
+
function writeIfAbsent(filePath, content) {
|
|
10123
|
+
if (fs8.existsSync(filePath)) return null;
|
|
10124
|
+
fs8.writeFileSync(filePath, content, "utf-8");
|
|
10125
|
+
return path9.basename(filePath);
|
|
10126
|
+
}
|
|
10127
|
+
function ensureWorkspaceFiles(gitRoot) {
|
|
10128
|
+
if (!isWorkspace(gitRoot)) return [];
|
|
10129
|
+
const created = [];
|
|
10130
|
+
const agents = writeIfAbsent(path9.join(gitRoot, "AGENTS.md"), ROOT_AGENTS_MD);
|
|
10131
|
+
if (agents) created.push(agents);
|
|
10132
|
+
const claude = writeIfAbsent(path9.join(gitRoot, "CLAUDE.md"), CLAUDE_MD_SHIM);
|
|
10133
|
+
if (claude) created.push(claude);
|
|
10134
|
+
return created;
|
|
10135
|
+
}
|
|
10136
|
+
var REKOR_SKILL_INSTALL_COMMAND, CLAUDE_MD_SHIM, ROOT_AGENTS_MD;
|
|
10137
|
+
var init_workspace_files = __esm({
|
|
10138
|
+
"src/lib/workspace-files.ts"() {
|
|
10139
|
+
"use strict";
|
|
10140
|
+
init_constants();
|
|
10141
|
+
init_layout();
|
|
10142
|
+
REKOR_SKILL_INSTALL_COMMAND = SKILL_INSTALL_COMMAND.replace(
|
|
10143
|
+
"wayai-pro/wayai-skill",
|
|
10144
|
+
"wayai-pro/rekor-skill"
|
|
10145
|
+
);
|
|
10146
|
+
CLAUDE_MD_SHIM = "@AGENTS.md\n";
|
|
10147
|
+
ROOT_AGENTS_MD = [
|
|
10148
|
+
"# Working with WayAI and Rekor",
|
|
10149
|
+
"",
|
|
10150
|
+
"WayAI is the layer that talks to people across channels; Rekor is the data",
|
|
10151
|
+
"layer (system of record) behind it. They are used together.",
|
|
10152
|
+
"",
|
|
10153
|
+
"## At the start of every session",
|
|
10154
|
+
"",
|
|
10155
|
+
"1. Check for updates first. Make sure both skills and both CLIs are current,",
|
|
10156
|
+
" and update whatever is not:",
|
|
10157
|
+
` - WayAI skill: \`wayai status\` \u2192 if newer, \`${SKILL_INSTALL_COMMAND}\``,
|
|
10158
|
+
` - Rekor skill: \`rekor status\` \u2192 if newer, \`${REKOR_SKILL_INSTALL_COMMAND}\``,
|
|
10159
|
+
" - CLIs: `wayai update` and `rekor update`",
|
|
10160
|
+
"2. Load both the WayAI and Rekor skills at the start of every session \u2014 every",
|
|
10161
|
+
" time, even for a quick task. They hold the real instructions for everything",
|
|
10162
|
+
" else.",
|
|
10163
|
+
"",
|
|
10164
|
+
"More detail if you need it:",
|
|
10165
|
+
"- WayAI: https://www.wayai.pro/docs/get-started",
|
|
10166
|
+
"- Rekor: https://rekor.pro/en/docs/get-started",
|
|
10167
|
+
"",
|
|
10168
|
+
"## When helping the person you are working with",
|
|
10169
|
+
"",
|
|
10170
|
+
"- They may be new to WayAI and Rekor \u2014 use plain language, not jargon.",
|
|
10171
|
+
"- Don't explain things they didn't ask about. Only if they seem stuck or ask",
|
|
10172
|
+
" what something means, give a one-line answer, then move on \u2014 don't turn",
|
|
10173
|
+
" replies into tutorials.",
|
|
10174
|
+
"- Keep answers short and to the point.",
|
|
10175
|
+
""
|
|
10176
|
+
].join("\n");
|
|
10177
|
+
}
|
|
10178
|
+
});
|
|
10179
|
+
|
|
10102
10180
|
// src/commands/init.ts
|
|
10103
10181
|
var init_exports = {};
|
|
10104
10182
|
__export(init_exports, {
|
|
@@ -10108,12 +10186,12 @@ __export(init_exports, {
|
|
|
10108
10186
|
parseArgs: () => parseArgs3
|
|
10109
10187
|
});
|
|
10110
10188
|
import { mkdirSync as mkdirSync5 } from "fs";
|
|
10111
|
-
import
|
|
10189
|
+
import path10 from "path";
|
|
10112
10190
|
function ensureHubsDir(gitRoot) {
|
|
10113
10191
|
const hubsDir = resolveLayout(gitRoot).hubsDir;
|
|
10114
10192
|
if (isDirectory(hubsDir)) return null;
|
|
10115
10193
|
mkdirSync5(hubsDir, { recursive: true });
|
|
10116
|
-
return `${
|
|
10194
|
+
return `${path10.relative(gitRoot, hubsDir)}/`;
|
|
10117
10195
|
}
|
|
10118
10196
|
function parseArgs3(args2) {
|
|
10119
10197
|
let orgId;
|
|
@@ -10156,6 +10234,9 @@ async function initCommand(args2) {
|
|
|
10156
10234
|
if (createdDir) {
|
|
10157
10235
|
console.log(`Created ${createdDir}`);
|
|
10158
10236
|
}
|
|
10237
|
+
for (const file of ensureWorkspaceFiles(gitRoot)) {
|
|
10238
|
+
console.log(`Created ${file}`);
|
|
10239
|
+
}
|
|
10159
10240
|
}
|
|
10160
10241
|
console.log(
|
|
10161
10242
|
`Run \`${SKILL_INSTALL_CMD}\` to install the WayAI skill in your AI harness, then \`wayai pull\` to fetch hub configuration.`
|
|
@@ -10236,6 +10317,7 @@ var init_init = __esm({
|
|
|
10236
10317
|
init_repo_config();
|
|
10237
10318
|
init_workspace();
|
|
10238
10319
|
init_layout();
|
|
10320
|
+
init_workspace_files();
|
|
10239
10321
|
init_utils();
|
|
10240
10322
|
init_constants();
|
|
10241
10323
|
SKILL_INSTALL_CMD = SKILL_INSTALL_COMMAND;
|
|
@@ -10243,8 +10325,8 @@ var init_init = __esm({
|
|
|
10243
10325
|
});
|
|
10244
10326
|
|
|
10245
10327
|
// src/lib/resource-files.ts
|
|
10246
|
-
import * as
|
|
10247
|
-
import * as
|
|
10328
|
+
import * as fs9 from "fs";
|
|
10329
|
+
import * as path11 from "path";
|
|
10248
10330
|
import * as crypto3 from "crypto";
|
|
10249
10331
|
function isBinaryFile(filename) {
|
|
10250
10332
|
const ext = filename.split(".").pop()?.toLowerCase() || "";
|
|
@@ -10290,14 +10372,14 @@ function computeHash(data) {
|
|
|
10290
10372
|
}
|
|
10291
10373
|
function scanResourceFiles(dir, prefix = "") {
|
|
10292
10374
|
const files = [];
|
|
10293
|
-
const entries =
|
|
10375
|
+
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
10294
10376
|
for (const entry of entries) {
|
|
10295
10377
|
const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
10296
10378
|
if (entry.isDirectory()) {
|
|
10297
|
-
files.push(...scanResourceFiles(
|
|
10379
|
+
files.push(...scanResourceFiles(path11.join(dir, entry.name), relPath));
|
|
10298
10380
|
} else if (entry.isFile()) {
|
|
10299
|
-
const fullPath =
|
|
10300
|
-
const stat =
|
|
10381
|
+
const fullPath = path11.join(dir, entry.name);
|
|
10382
|
+
const stat = fs9.statSync(fullPath);
|
|
10301
10383
|
if (stat.size > MAX_RESOURCE_FILE_SIZE2) {
|
|
10302
10384
|
console.warn(` Warning: skipping ${relPath} (${(stat.size / 1024 / 1024).toFixed(1)}MB exceeds 10MB limit)`);
|
|
10303
10385
|
continue;
|
|
@@ -10307,7 +10389,7 @@ function scanResourceFiles(dir, prefix = "") {
|
|
|
10307
10389
|
mime_type: guessMimeType(entry.name),
|
|
10308
10390
|
file_size: stat.size
|
|
10309
10391
|
};
|
|
10310
|
-
const data =
|
|
10392
|
+
const data = fs9.readFileSync(fullPath);
|
|
10311
10393
|
fileEntry.hash = computeHash(data);
|
|
10312
10394
|
if (isBinaryFile(entry.name)) {
|
|
10313
10395
|
fileEntry.content_base64 = data.toString("base64");
|
|
@@ -10321,37 +10403,37 @@ function scanResourceFiles(dir, prefix = "") {
|
|
|
10321
10403
|
}
|
|
10322
10404
|
function writeResourceFileTree(resDir, files) {
|
|
10323
10405
|
if (files.length === 0) {
|
|
10324
|
-
if (
|
|
10406
|
+
if (fs9.existsSync(resDir)) cleanOrphanFiles(resDir, "", /* @__PURE__ */ new Set());
|
|
10325
10407
|
return;
|
|
10326
10408
|
}
|
|
10327
10409
|
const writtenPaths = /* @__PURE__ */ new Set();
|
|
10328
10410
|
for (const file of files) {
|
|
10329
|
-
const filePath =
|
|
10330
|
-
if (!filePath.startsWith(resDir +
|
|
10411
|
+
const filePath = path11.join(resDir, file.path);
|
|
10412
|
+
if (!filePath.startsWith(resDir + path11.sep) && filePath !== resDir) {
|
|
10331
10413
|
console.warn(` Warning: skipping ${file.path} (path traversal detected)`);
|
|
10332
10414
|
continue;
|
|
10333
10415
|
}
|
|
10334
|
-
const fileDir =
|
|
10335
|
-
if (!
|
|
10416
|
+
const fileDir = path11.dirname(filePath);
|
|
10417
|
+
if (!fs9.existsSync(fileDir)) fs9.mkdirSync(fileDir, { recursive: true });
|
|
10336
10418
|
writtenPaths.add(file.path);
|
|
10337
10419
|
if (file.content !== void 0) {
|
|
10338
|
-
|
|
10420
|
+
fs9.writeFileSync(filePath, file.content, "utf-8");
|
|
10339
10421
|
} else if (file.content_base64) {
|
|
10340
|
-
|
|
10422
|
+
fs9.writeFileSync(filePath, Buffer.from(file.content_base64, "base64"));
|
|
10341
10423
|
}
|
|
10342
10424
|
}
|
|
10343
|
-
if (
|
|
10425
|
+
if (fs9.existsSync(resDir)) cleanOrphanFiles(resDir, "", writtenPaths);
|
|
10344
10426
|
}
|
|
10345
10427
|
function cleanOrphanFiles(dir, prefix, writtenPaths) {
|
|
10346
|
-
const entries =
|
|
10428
|
+
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
10347
10429
|
for (const entry of entries) {
|
|
10348
10430
|
const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
10349
|
-
const fullPath =
|
|
10431
|
+
const fullPath = path11.join(dir, entry.name);
|
|
10350
10432
|
if (entry.isDirectory()) {
|
|
10351
10433
|
cleanOrphanFiles(fullPath, relPath, writtenPaths);
|
|
10352
|
-
if (
|
|
10434
|
+
if (fs9.readdirSync(fullPath).length === 0) fs9.rmdirSync(fullPath);
|
|
10353
10435
|
} else if (!writtenPaths.has(relPath)) {
|
|
10354
|
-
|
|
10436
|
+
fs9.unlinkSync(fullPath);
|
|
10355
10437
|
}
|
|
10356
10438
|
}
|
|
10357
10439
|
}
|
|
@@ -10360,8 +10442,8 @@ async function downloadBinaryFiles(resDir, files) {
|
|
|
10360
10442
|
for (const file of files) {
|
|
10361
10443
|
if (!file.download_url || file.content !== void 0) continue;
|
|
10362
10444
|
try {
|
|
10363
|
-
const filePath =
|
|
10364
|
-
if (!filePath.startsWith(resDir +
|
|
10445
|
+
const filePath = path11.join(resDir, file.path);
|
|
10446
|
+
if (!filePath.startsWith(resDir + path11.sep) && filePath !== resDir) {
|
|
10365
10447
|
console.warn(` Warning: skipping ${file.path} (path traversal detected)`);
|
|
10366
10448
|
continue;
|
|
10367
10449
|
}
|
|
@@ -10371,9 +10453,9 @@ async function downloadBinaryFiles(resDir, files) {
|
|
|
10371
10453
|
continue;
|
|
10372
10454
|
}
|
|
10373
10455
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
10374
|
-
const fileDir =
|
|
10375
|
-
if (!
|
|
10376
|
-
|
|
10456
|
+
const fileDir = path11.dirname(filePath);
|
|
10457
|
+
if (!fs9.existsSync(fileDir)) fs9.mkdirSync(fileDir, { recursive: true });
|
|
10458
|
+
fs9.writeFileSync(filePath, buffer);
|
|
10377
10459
|
count++;
|
|
10378
10460
|
} catch (err) {
|
|
10379
10461
|
console.warn(` Warning: failed to download ${file.path} (${err instanceof Error ? err.message : String(err)})`);
|
|
@@ -10410,8 +10492,8 @@ var init_resource_files = __esm({
|
|
|
10410
10492
|
});
|
|
10411
10493
|
|
|
10412
10494
|
// src/lib/yaml-writer.ts
|
|
10413
|
-
import * as
|
|
10414
|
-
import * as
|
|
10495
|
+
import * as fs10 from "fs";
|
|
10496
|
+
import * as path12 from "path";
|
|
10415
10497
|
import * as yaml4 from "js-yaml";
|
|
10416
10498
|
function buildEvalYamlObject(evalEntry, slug) {
|
|
10417
10499
|
const out = {};
|
|
@@ -10444,43 +10526,43 @@ function buildEvalYamlObject(evalEntry, slug) {
|
|
|
10444
10526
|
}
|
|
10445
10527
|
return out;
|
|
10446
10528
|
}
|
|
10447
|
-
function writeHubFolder(hubFolder, payload) {
|
|
10448
|
-
const agentsDir =
|
|
10449
|
-
if (!
|
|
10450
|
-
|
|
10529
|
+
function writeHubFolder(hubFolder, payload, options = {}) {
|
|
10530
|
+
const agentsDir = path12.join(hubFolder, "agents");
|
|
10531
|
+
if (!fs10.existsSync(hubFolder)) {
|
|
10532
|
+
fs10.mkdirSync(hubFolder, { recursive: true });
|
|
10451
10533
|
}
|
|
10452
|
-
if (!
|
|
10453
|
-
|
|
10534
|
+
if (!fs10.existsSync(agentsDir)) {
|
|
10535
|
+
fs10.mkdirSync(agentsDir, { recursive: true });
|
|
10454
10536
|
}
|
|
10455
10537
|
const yamlPayload = buildYamlPayload(payload);
|
|
10456
10538
|
const agentFiles = extractAgentFiles(payload);
|
|
10457
10539
|
const yamlContent = yaml4.dump(yamlPayload, YAML_DUMP_OPTIONS);
|
|
10458
|
-
|
|
10459
|
-
|
|
10460
|
-
|
|
10461
|
-
|
|
10540
|
+
fs10.writeFileSync(path12.join(hubFolder, "hub.yaml"), yamlContent, "utf-8");
|
|
10541
|
+
if (options.seedAgentContext ?? true) {
|
|
10542
|
+
writeIfAbsent(path12.join(hubFolder, "AGENTS.md"), perHubAgentsMd(path12.basename(hubFolder)));
|
|
10543
|
+
writeIfAbsent(path12.join(hubFolder, "CLAUDE.md"), CLAUDE_MD_SHIM);
|
|
10462
10544
|
}
|
|
10463
|
-
const oldYamlPath =
|
|
10464
|
-
if (
|
|
10465
|
-
|
|
10545
|
+
const oldYamlPath = path12.join(hubFolder, "wayai.yaml");
|
|
10546
|
+
if (fs10.existsSync(oldYamlPath)) {
|
|
10547
|
+
fs10.unlinkSync(oldYamlPath);
|
|
10466
10548
|
}
|
|
10467
10549
|
const yamlSlugs = writeAgentYamlFiles(agentsDir, payload.agents || []);
|
|
10468
10550
|
const mdSlugs = /* @__PURE__ */ new Set();
|
|
10469
10551
|
for (const { slug, content } of agentFiles) {
|
|
10470
10552
|
mdSlugs.add(slug);
|
|
10471
|
-
|
|
10553
|
+
fs10.writeFileSync(path12.join(agentsDir, `${slug}.md`), content, "utf-8");
|
|
10472
10554
|
}
|
|
10473
|
-
const existingFiles =
|
|
10555
|
+
const existingFiles = fs10.readdirSync(agentsDir);
|
|
10474
10556
|
for (const file of existingFiles) {
|
|
10475
10557
|
if (file.endsWith(".yaml")) {
|
|
10476
10558
|
const slug = file.slice(0, -5);
|
|
10477
10559
|
if (!yamlSlugs.has(slug)) {
|
|
10478
|
-
|
|
10560
|
+
fs10.unlinkSync(path12.join(agentsDir, file));
|
|
10479
10561
|
}
|
|
10480
10562
|
} else if (file.endsWith(".md")) {
|
|
10481
10563
|
const slug = file.slice(0, -3);
|
|
10482
10564
|
if (!mdSlugs.has(slug)) {
|
|
10483
|
-
|
|
10565
|
+
fs10.unlinkSync(path12.join(agentsDir, file));
|
|
10484
10566
|
}
|
|
10485
10567
|
}
|
|
10486
10568
|
}
|
|
@@ -10491,10 +10573,10 @@ function writeHubFolder(hubFolder, payload) {
|
|
|
10491
10573
|
function setPreviewLabelInHubYaml(hubFolder, label) {
|
|
10492
10574
|
const yamlPath = resolveHubYamlPath(hubFolder);
|
|
10493
10575
|
if (!yamlPath) return;
|
|
10494
|
-
const obj = yaml4.load(
|
|
10576
|
+
const obj = yaml4.load(fs10.readFileSync(yamlPath, "utf-8")) ?? {};
|
|
10495
10577
|
if (label) obj.preview_label = label;
|
|
10496
10578
|
else delete obj.preview_label;
|
|
10497
|
-
|
|
10579
|
+
fs10.writeFileSync(yamlPath, yaml4.dump(obj, YAML_DUMP_OPTIONS), "utf-8");
|
|
10498
10580
|
}
|
|
10499
10581
|
function buildYamlPayload(payload) {
|
|
10500
10582
|
const result = {
|
|
@@ -10540,7 +10622,7 @@ function writeAgentYamlFiles(agentsDir, agents) {
|
|
|
10540
10622
|
const entry = { ...agent };
|
|
10541
10623
|
delete entry.instructions;
|
|
10542
10624
|
const yamlContent = yaml4.dump(entry, YAML_DUMP_OPTIONS);
|
|
10543
|
-
|
|
10625
|
+
fs10.writeFileSync(path12.join(agentsDir, `${slug}.yaml`), yamlContent, "utf-8");
|
|
10544
10626
|
}
|
|
10545
10627
|
return slugs;
|
|
10546
10628
|
}
|
|
@@ -10557,65 +10639,65 @@ function extractAgentFiles(payload) {
|
|
|
10557
10639
|
return files;
|
|
10558
10640
|
}
|
|
10559
10641
|
function writeEvalYamlFiles(hubFolder, evals) {
|
|
10560
|
-
const evalsDir =
|
|
10642
|
+
const evalsDir = path12.join(hubFolder, "evals");
|
|
10561
10643
|
if (evals.length === 0) {
|
|
10562
|
-
if (
|
|
10644
|
+
if (fs10.existsSync(evalsDir)) {
|
|
10563
10645
|
cleanEvalOrphans(evalsDir, /* @__PURE__ */ new Set());
|
|
10564
10646
|
try {
|
|
10565
|
-
if (
|
|
10647
|
+
if (fs10.readdirSync(evalsDir).length === 0) fs10.rmdirSync(evalsDir);
|
|
10566
10648
|
} catch {
|
|
10567
10649
|
}
|
|
10568
10650
|
}
|
|
10569
10651
|
return;
|
|
10570
10652
|
}
|
|
10571
|
-
if (!
|
|
10572
|
-
|
|
10653
|
+
if (!fs10.existsSync(evalsDir)) {
|
|
10654
|
+
fs10.mkdirSync(evalsDir, { recursive: true });
|
|
10573
10655
|
}
|
|
10574
10656
|
const writtenRelPaths = /* @__PURE__ */ new Set();
|
|
10575
10657
|
for (const evalEntry of evals) {
|
|
10576
10658
|
const slug = slugify(evalEntry.name);
|
|
10577
10659
|
const setName = evalEntry.path && evalEntry.path.trim().length > 0 ? evalEntry.path : null;
|
|
10578
10660
|
const relPath = setName ? `${setName}/${slug}.yaml` : `${slug}.yaml`;
|
|
10579
|
-
const targetPath =
|
|
10580
|
-
if (!targetPath.startsWith(evalsDir +
|
|
10661
|
+
const targetPath = path12.join(evalsDir, relPath);
|
|
10662
|
+
if (!targetPath.startsWith(evalsDir + path12.sep)) {
|
|
10581
10663
|
console.warn(` Warning: skipping eval "${evalEntry.name}" (scenario set "${setName}" escapes evals/ \u2014 possible bad backend data)`);
|
|
10582
10664
|
continue;
|
|
10583
10665
|
}
|
|
10584
10666
|
if (setName) {
|
|
10585
|
-
const setDir =
|
|
10586
|
-
if (!
|
|
10587
|
-
|
|
10667
|
+
const setDir = path12.join(evalsDir, setName);
|
|
10668
|
+
if (!fs10.existsSync(setDir)) {
|
|
10669
|
+
fs10.mkdirSync(setDir, { recursive: true });
|
|
10588
10670
|
}
|
|
10589
10671
|
}
|
|
10590
10672
|
const yamlContent = yaml4.dump(buildEvalYamlObject(evalEntry, slug), YAML_DUMP_OPTIONS);
|
|
10591
|
-
|
|
10673
|
+
fs10.writeFileSync(targetPath, yamlContent, "utf-8");
|
|
10592
10674
|
writtenRelPaths.add(relPath);
|
|
10593
10675
|
}
|
|
10594
10676
|
cleanEvalOrphans(evalsDir, writtenRelPaths);
|
|
10595
10677
|
}
|
|
10596
10678
|
function cleanEvalOrphans(evalsDir, writtenRelPaths) {
|
|
10597
|
-
const entries =
|
|
10679
|
+
const entries = fs10.readdirSync(evalsDir, { withFileTypes: true });
|
|
10598
10680
|
for (const entry of entries) {
|
|
10599
|
-
const fullPath =
|
|
10681
|
+
const fullPath = path12.join(evalsDir, entry.name);
|
|
10600
10682
|
if (entry.isFile()) {
|
|
10601
10683
|
if (entry.name.endsWith(".yaml") && !writtenRelPaths.has(entry.name)) {
|
|
10602
|
-
|
|
10684
|
+
fs10.unlinkSync(fullPath);
|
|
10603
10685
|
}
|
|
10604
10686
|
continue;
|
|
10605
10687
|
}
|
|
10606
10688
|
if (entry.isDirectory()) {
|
|
10607
10689
|
const setName = entry.name;
|
|
10608
|
-
const subEntries =
|
|
10690
|
+
const subEntries = fs10.readdirSync(fullPath, { withFileTypes: true });
|
|
10609
10691
|
for (const sub of subEntries) {
|
|
10610
10692
|
if (sub.isFile() && sub.name.endsWith(".yaml")) {
|
|
10611
10693
|
const relPath = `${setName}/${sub.name}`;
|
|
10612
10694
|
if (!writtenRelPaths.has(relPath)) {
|
|
10613
|
-
|
|
10695
|
+
fs10.unlinkSync(path12.join(fullPath, sub.name));
|
|
10614
10696
|
}
|
|
10615
10697
|
}
|
|
10616
10698
|
}
|
|
10617
10699
|
try {
|
|
10618
|
-
if (
|
|
10700
|
+
if (fs10.readdirSync(fullPath).length === 0) fs10.rmdirSync(fullPath);
|
|
10619
10701
|
} catch {
|
|
10620
10702
|
}
|
|
10621
10703
|
}
|
|
@@ -10651,19 +10733,19 @@ function buildJourneyYamlObject(journeyEntry, slug) {
|
|
|
10651
10733
|
return out;
|
|
10652
10734
|
}
|
|
10653
10735
|
function writeJourneyYamlFiles(hubFolder, journeys) {
|
|
10654
|
-
const journeysDir =
|
|
10736
|
+
const journeysDir = path12.join(hubFolder, "journeys");
|
|
10655
10737
|
if (journeys.length === 0) {
|
|
10656
|
-
if (
|
|
10738
|
+
if (fs10.existsSync(journeysDir)) {
|
|
10657
10739
|
cleanJourneyOrphans(journeysDir, /* @__PURE__ */ new Set());
|
|
10658
10740
|
try {
|
|
10659
|
-
if (
|
|
10741
|
+
if (fs10.readdirSync(journeysDir).length === 0) fs10.rmdirSync(journeysDir);
|
|
10660
10742
|
} catch {
|
|
10661
10743
|
}
|
|
10662
10744
|
}
|
|
10663
10745
|
return;
|
|
10664
10746
|
}
|
|
10665
|
-
if (!
|
|
10666
|
-
|
|
10747
|
+
if (!fs10.existsSync(journeysDir)) {
|
|
10748
|
+
fs10.mkdirSync(journeysDir, { recursive: true });
|
|
10667
10749
|
}
|
|
10668
10750
|
const writtenFiles = /* @__PURE__ */ new Set();
|
|
10669
10751
|
const usedSlugs = /* @__PURE__ */ new Set();
|
|
@@ -10671,33 +10753,33 @@ function writeJourneyYamlFiles(hubFolder, journeys) {
|
|
|
10671
10753
|
const slug = ensureUniqueSlug(slugify(journeyEntry.name), usedSlugs);
|
|
10672
10754
|
const fileName = `${slug}.yaml`;
|
|
10673
10755
|
const yamlContent = yaml4.dump(buildJourneyYamlObject(journeyEntry, slug), YAML_DUMP_OPTIONS);
|
|
10674
|
-
|
|
10756
|
+
fs10.writeFileSync(path12.join(journeysDir, fileName), yamlContent, "utf-8");
|
|
10675
10757
|
writtenFiles.add(fileName);
|
|
10676
10758
|
}
|
|
10677
10759
|
cleanJourneyOrphans(journeysDir, writtenFiles);
|
|
10678
10760
|
}
|
|
10679
10761
|
function cleanJourneyOrphans(journeysDir, writtenFiles) {
|
|
10680
|
-
const entries =
|
|
10762
|
+
const entries = fs10.readdirSync(journeysDir, { withFileTypes: true });
|
|
10681
10763
|
for (const entry of entries) {
|
|
10682
10764
|
if (entry.isFile() && entry.name.endsWith(".yaml") && !writtenFiles.has(entry.name)) {
|
|
10683
|
-
|
|
10765
|
+
fs10.unlinkSync(path12.join(journeysDir, entry.name));
|
|
10684
10766
|
}
|
|
10685
10767
|
}
|
|
10686
10768
|
}
|
|
10687
10769
|
function writeResourceFiles(hubFolder, resources) {
|
|
10688
|
-
const resourcesDir =
|
|
10770
|
+
const resourcesDir = path12.join(hubFolder, "resources");
|
|
10689
10771
|
const currentSlugs = /* @__PURE__ */ new Set();
|
|
10690
10772
|
for (const resource of resources) {
|
|
10691
10773
|
const resSlug = slugify(resource.name);
|
|
10692
10774
|
currentSlugs.add(resSlug);
|
|
10693
|
-
const resDir =
|
|
10775
|
+
const resDir = path12.join(resourcesDir, resSlug);
|
|
10694
10776
|
writeResourceFileTree(resDir, resource.files || []);
|
|
10695
10777
|
}
|
|
10696
|
-
if (
|
|
10697
|
-
const existingDirs =
|
|
10778
|
+
if (fs10.existsSync(resourcesDir)) {
|
|
10779
|
+
const existingDirs = fs10.readdirSync(resourcesDir, { withFileTypes: true });
|
|
10698
10780
|
for (const entry of existingDirs) {
|
|
10699
10781
|
if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
|
|
10700
|
-
|
|
10782
|
+
fs10.rmSync(path12.join(resourcesDir, entry.name), { recursive: true, force: true });
|
|
10701
10783
|
}
|
|
10702
10784
|
}
|
|
10703
10785
|
}
|
|
@@ -10709,6 +10791,7 @@ var init_yaml_writer = __esm({
|
|
|
10709
10791
|
init_dist();
|
|
10710
10792
|
init_utils();
|
|
10711
10793
|
init_resource_files();
|
|
10794
|
+
init_workspace_files();
|
|
10712
10795
|
YAML_DUMP_OPTIONS = {
|
|
10713
10796
|
lineWidth: -1,
|
|
10714
10797
|
// don't wrap lines
|
|
@@ -10722,8 +10805,8 @@ var init_yaml_writer = __esm({
|
|
|
10722
10805
|
});
|
|
10723
10806
|
|
|
10724
10807
|
// src/lib/parser.ts
|
|
10725
|
-
import * as
|
|
10726
|
-
import * as
|
|
10808
|
+
import * as fs11 from "fs";
|
|
10809
|
+
import * as path13 from "path";
|
|
10727
10810
|
import * as yaml5 from "js-yaml";
|
|
10728
10811
|
function expected(message) {
|
|
10729
10812
|
const err = new Error(message);
|
|
@@ -10737,7 +10820,7 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
10737
10820
|
err.isExpected = true;
|
|
10738
10821
|
throw err;
|
|
10739
10822
|
}
|
|
10740
|
-
const yamlContent =
|
|
10823
|
+
const yamlContent = fs11.readFileSync(yamlPath, "utf-8");
|
|
10741
10824
|
let config;
|
|
10742
10825
|
try {
|
|
10743
10826
|
config = yaml5.load(yamlContent);
|
|
@@ -10772,9 +10855,9 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
10772
10855
|
const resolved = { ...agent };
|
|
10773
10856
|
if (typeof resolved.instructions === "string" && resolved.instructions.endsWith(".md")) {
|
|
10774
10857
|
const instrValue = resolved.instructions;
|
|
10775
|
-
const instructionsPath = instrValue.startsWith("agents/") ?
|
|
10776
|
-
if (
|
|
10777
|
-
resolved.instructions =
|
|
10858
|
+
const instructionsPath = instrValue.startsWith("agents/") ? path13.join(hubFolder, instrValue) : path13.join(hubFolder, "agents", instrValue);
|
|
10859
|
+
if (fs11.existsSync(instructionsPath)) {
|
|
10860
|
+
resolved.instructions = fs11.readFileSync(instructionsPath, "utf-8");
|
|
10778
10861
|
} else {
|
|
10779
10862
|
const err = new Error(
|
|
10780
10863
|
`Agent instructions file not found: ${instructionsPath} (referenced by agent "${agent.name}")`
|
|
@@ -10783,9 +10866,9 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
10783
10866
|
throw err;
|
|
10784
10867
|
}
|
|
10785
10868
|
} else if (resolved.instructions === void 0 && typeof agent.name === "string") {
|
|
10786
|
-
const conventionPath =
|
|
10787
|
-
if (
|
|
10788
|
-
resolved.instructions =
|
|
10869
|
+
const conventionPath = path13.join(hubFolder, "agents", `${slugify(agent.name)}.md`);
|
|
10870
|
+
if (fs11.existsSync(conventionPath)) {
|
|
10871
|
+
resolved.instructions = fs11.readFileSync(conventionPath, "utf-8");
|
|
10789
10872
|
}
|
|
10790
10873
|
}
|
|
10791
10874
|
return resolved;
|
|
@@ -10835,26 +10918,26 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
10835
10918
|
return payload;
|
|
10836
10919
|
}
|
|
10837
10920
|
function scanEvalYamlFiles(hubFolder) {
|
|
10838
|
-
const evalsDir =
|
|
10839
|
-
if (!
|
|
10921
|
+
const evalsDir = path13.join(hubFolder, "evals");
|
|
10922
|
+
if (!fs11.existsSync(evalsDir)) return [];
|
|
10840
10923
|
const evals = [];
|
|
10841
10924
|
const seen = /* @__PURE__ */ new Set();
|
|
10842
|
-
const topEntries =
|
|
10925
|
+
const topEntries = fs11.readdirSync(evalsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
10843
10926
|
for (const entry of topEntries) {
|
|
10844
10927
|
if (entry.isFile() && entry.name.endsWith(".yaml")) {
|
|
10845
|
-
collectEval(evals, seen,
|
|
10928
|
+
collectEval(evals, seen, path13.join(evalsDir, entry.name), `evals/${entry.name}`, null);
|
|
10846
10929
|
} else if (entry.isDirectory()) {
|
|
10847
10930
|
const setName = entry.name;
|
|
10848
|
-
const setDir =
|
|
10849
|
-
const setEntries =
|
|
10931
|
+
const setDir = path13.join(evalsDir, setName);
|
|
10932
|
+
const setEntries = fs11.readdirSync(setDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
10850
10933
|
for (const sub of setEntries) {
|
|
10851
10934
|
if (sub.isDirectory()) {
|
|
10852
10935
|
throw expected(
|
|
10853
|
-
`Nested scenario sets are not supported: ${
|
|
10936
|
+
`Nested scenario sets are not supported: ${path13.relative(hubFolder, path13.join(setDir, sub.name))}. Move scenarios up to evals/${setName}/.`
|
|
10854
10937
|
);
|
|
10855
10938
|
}
|
|
10856
10939
|
if (sub.isFile() && sub.name.endsWith(".yaml")) {
|
|
10857
|
-
collectEval(evals, seen,
|
|
10940
|
+
collectEval(evals, seen, path13.join(setDir, sub.name), `evals/${setName}/${sub.name}`, setName);
|
|
10858
10941
|
}
|
|
10859
10942
|
}
|
|
10860
10943
|
}
|
|
@@ -10868,14 +10951,14 @@ function collectEval(evals, seen, filePath, relPath, setName) {
|
|
|
10868
10951
|
if (seen.has(key)) {
|
|
10869
10952
|
const where = setName ? `scenario set "${setName}"` : "root";
|
|
10870
10953
|
throw expected(
|
|
10871
|
-
`Duplicate eval at ${where}: "${evalEntry.name}" (in ${
|
|
10954
|
+
`Duplicate eval at ${where}: "${evalEntry.name}" (in ${path13.basename(filePath)}). Each (name, scenario set) pair must be unique.`
|
|
10872
10955
|
);
|
|
10873
10956
|
}
|
|
10874
10957
|
seen.add(key);
|
|
10875
10958
|
evals.push(evalEntry);
|
|
10876
10959
|
}
|
|
10877
10960
|
function parseEvalYaml(filePath, relPath, setName) {
|
|
10878
|
-
const content =
|
|
10961
|
+
const content = fs11.readFileSync(filePath, "utf-8");
|
|
10879
10962
|
let raw;
|
|
10880
10963
|
try {
|
|
10881
10964
|
raw = yaml5.load(content);
|
|
@@ -10890,7 +10973,7 @@ function parseEvalYaml(filePath, relPath, setName) {
|
|
|
10890
10973
|
return null;
|
|
10891
10974
|
}
|
|
10892
10975
|
const data = raw;
|
|
10893
|
-
const fileSlug =
|
|
10976
|
+
const fileSlug = path13.basename(filePath, ".yaml");
|
|
10894
10977
|
const evalName = typeof data.name === "string" && data.name.trim().length > 0 ? data.name : fileSlug;
|
|
10895
10978
|
if (typeof data.agent !== "string" || data.agent.trim().length === 0) {
|
|
10896
10979
|
throw expected(`Eval "${evalName}" in ${relPath}: missing required field "agent" (string).`);
|
|
@@ -10944,19 +11027,19 @@ function parseFixtureField(raw, label, key) {
|
|
|
10944
11027
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
10945
11028
|
}
|
|
10946
11029
|
function scanJourneyYamlFiles(hubFolder) {
|
|
10947
|
-
const journeysDir =
|
|
10948
|
-
if (!
|
|
11030
|
+
const journeysDir = path13.join(hubFolder, "journeys");
|
|
11031
|
+
if (!fs11.existsSync(journeysDir)) return [];
|
|
10949
11032
|
const journeys = [];
|
|
10950
11033
|
const seen = /* @__PURE__ */ new Set();
|
|
10951
|
-
const entries =
|
|
11034
|
+
const entries = fs11.readdirSync(journeysDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
10952
11035
|
for (const entry of entries) {
|
|
10953
11036
|
if (entry.isDirectory()) {
|
|
10954
11037
|
throw expected(
|
|
10955
|
-
`Subfolders are not supported under journeys/: ${
|
|
11038
|
+
`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
11039
|
);
|
|
10957
11040
|
}
|
|
10958
11041
|
if (!entry.isFile() || !entry.name.endsWith(".yaml")) continue;
|
|
10959
|
-
const journeyEntry = parseJourneyYaml(
|
|
11042
|
+
const journeyEntry = parseJourneyYaml(path13.join(journeysDir, entry.name), `journeys/${entry.name}`);
|
|
10960
11043
|
if (!journeyEntry) continue;
|
|
10961
11044
|
if (seen.has(journeyEntry.name)) {
|
|
10962
11045
|
throw expected(
|
|
@@ -10969,7 +11052,7 @@ function scanJourneyYamlFiles(hubFolder) {
|
|
|
10969
11052
|
return journeys;
|
|
10970
11053
|
}
|
|
10971
11054
|
function parseJourneyYaml(filePath, relPath) {
|
|
10972
|
-
const content =
|
|
11055
|
+
const content = fs11.readFileSync(filePath, "utf-8");
|
|
10973
11056
|
let raw;
|
|
10974
11057
|
try {
|
|
10975
11058
|
raw = yaml5.load(content);
|
|
@@ -10984,7 +11067,7 @@ function parseJourneyYaml(filePath, relPath) {
|
|
|
10984
11067
|
return null;
|
|
10985
11068
|
}
|
|
10986
11069
|
const data = raw;
|
|
10987
|
-
const fileSlug =
|
|
11070
|
+
const fileSlug = path13.basename(filePath, ".yaml");
|
|
10988
11071
|
const journeyName = typeof data.name === "string" && data.name.trim().length > 0 ? data.name : fileSlug;
|
|
10989
11072
|
if (typeof data.agent !== "string" || data.agent.trim().length === 0) {
|
|
10990
11073
|
throw expected(`Journey "${journeyName}" in ${relPath}: missing required field "agent" (string).`);
|
|
@@ -11020,14 +11103,14 @@ function parseJourneyYaml(filePath, relPath) {
|
|
|
11020
11103
|
return journeyEntry;
|
|
11021
11104
|
}
|
|
11022
11105
|
function scanAgentYamlFiles(hubFolder) {
|
|
11023
|
-
const agentsDir =
|
|
11024
|
-
if (!
|
|
11025
|
-
const yamlFiles =
|
|
11106
|
+
const agentsDir = path13.join(hubFolder, "agents");
|
|
11107
|
+
if (!fs11.existsSync(agentsDir)) return [];
|
|
11108
|
+
const yamlFiles = fs11.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml")).sort();
|
|
11026
11109
|
if (yamlFiles.length === 0) return [];
|
|
11027
11110
|
const agents = [];
|
|
11028
11111
|
for (const file of yamlFiles) {
|
|
11029
|
-
const filePath =
|
|
11030
|
-
const content =
|
|
11112
|
+
const filePath = path13.join(agentsDir, file);
|
|
11113
|
+
const content = fs11.readFileSync(filePath, "utf-8");
|
|
11031
11114
|
let agent;
|
|
11032
11115
|
try {
|
|
11033
11116
|
agent = yaml5.load(content);
|
|
@@ -11049,7 +11132,7 @@ function scanAgentYamlFiles(hubFolder) {
|
|
|
11049
11132
|
return agents;
|
|
11050
11133
|
}
|
|
11051
11134
|
function parseResources(hubFolder, configResources) {
|
|
11052
|
-
const resourcesDir =
|
|
11135
|
+
const resourcesDir = path13.join(hubFolder, "resources");
|
|
11053
11136
|
const results = [];
|
|
11054
11137
|
for (const res of configResources) {
|
|
11055
11138
|
const resource = {
|
|
@@ -11062,8 +11145,8 @@ function parseResources(hubFolder, configResources) {
|
|
|
11062
11145
|
if (res.user_browsable) resource.user_browsable = res.user_browsable;
|
|
11063
11146
|
if (res.skill_name) resource.skill_name = res.skill_name;
|
|
11064
11147
|
const resSlug = slugify(resource.name);
|
|
11065
|
-
const resDir =
|
|
11066
|
-
if (
|
|
11148
|
+
const resDir = path13.join(resourcesDir, resSlug);
|
|
11149
|
+
if (fs11.existsSync(resDir)) {
|
|
11067
11150
|
const files = scanResourceFiles(resDir, "");
|
|
11068
11151
|
if (files.length > 0) {
|
|
11069
11152
|
resource.files = files;
|
|
@@ -11117,8 +11200,8 @@ __export(pull_exports, {
|
|
|
11117
11200
|
resolveHubTarget: () => resolveHubTarget,
|
|
11118
11201
|
writeProductionMirror: () => writeProductionMirror
|
|
11119
11202
|
});
|
|
11120
|
-
import * as
|
|
11121
|
-
import * as
|
|
11203
|
+
import * as fs12 from "fs";
|
|
11204
|
+
import * as path14 from "path";
|
|
11122
11205
|
function parseArgs4(args2) {
|
|
11123
11206
|
let autoConfirm = false;
|
|
11124
11207
|
let hubSelector;
|
|
@@ -11137,7 +11220,7 @@ function resolveHubTarget(workspaceDir, selector) {
|
|
|
11137
11220
|
const allHubs = scanWorkspaceHubs(workspaceDir);
|
|
11138
11221
|
if (selector) {
|
|
11139
11222
|
const match = allHubs.find(
|
|
11140
|
-
(h) => h.hubId === selector ||
|
|
11223
|
+
(h) => h.hubId === selector || path14.basename(h.hubFolder) === selector
|
|
11141
11224
|
);
|
|
11142
11225
|
if (match) return { hubId: match.hubId, hubFolder: match.hubFolder };
|
|
11143
11226
|
if (UUID_RE.test(selector)) return { hubId: selector, hubFolder: null };
|
|
@@ -11154,7 +11237,7 @@ function resolveHubTarget(workspaceDir, selector) {
|
|
|
11154
11237
|
}
|
|
11155
11238
|
console.error(`Multiple hubs found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
|
|
11156
11239
|
for (const h of previewHubs) {
|
|
11157
|
-
console.error(` ${
|
|
11240
|
+
console.error(` ${path14.basename(h.hubFolder)} (${h.hubId})`);
|
|
11158
11241
|
}
|
|
11159
11242
|
process.exit(1);
|
|
11160
11243
|
}
|
|
@@ -11167,6 +11250,11 @@ async function pullCommand(args2) {
|
|
|
11167
11250
|
const workspaceDir = resolveWorkspaceDir();
|
|
11168
11251
|
const gitRoot = findGitRoot();
|
|
11169
11252
|
if (gitRoot) warnLayoutOnce(gitRoot);
|
|
11253
|
+
if (gitRoot) {
|
|
11254
|
+
for (const file of ensureWorkspaceFiles(gitRoot)) {
|
|
11255
|
+
console.error(`Created ${file}`);
|
|
11256
|
+
}
|
|
11257
|
+
}
|
|
11170
11258
|
const { hubId, hubFolder: existingFolder } = resolveHubTarget(workspaceDir, hubSelector);
|
|
11171
11259
|
console.log("Fetching hub configuration...");
|
|
11172
11260
|
const payload = await client.pull(hubId, organizationId);
|
|
@@ -11187,7 +11275,7 @@ async function pullCommand(args2) {
|
|
|
11187
11275
|
payload.preview_label,
|
|
11188
11276
|
payload.branch_name
|
|
11189
11277
|
);
|
|
11190
|
-
|
|
11278
|
+
fs12.mkdirSync(path14.dirname(hubFolder), { recursive: true });
|
|
11191
11279
|
console.log("Writing hub configuration...");
|
|
11192
11280
|
writeHubFolder(hubFolder, payload);
|
|
11193
11281
|
await downloadBinaryResourceFiles(hubFolder, payload);
|
|
@@ -11248,8 +11336,8 @@ async function pullCommand(args2) {
|
|
|
11248
11336
|
}
|
|
11249
11337
|
async function writeProductionMirror(workspaceDir, prodPayload) {
|
|
11250
11338
|
const folder = resolveHubFolder(workspaceDir, prodPayload.hub_id, prodPayload.hub.name, "production", null, null);
|
|
11251
|
-
|
|
11252
|
-
writeHubFolder(folder, prodPayload);
|
|
11339
|
+
fs12.mkdirSync(path14.dirname(folder), { recursive: true });
|
|
11340
|
+
writeHubFolder(folder, prodPayload, { seedAgentContext: false });
|
|
11253
11341
|
await downloadBinaryResourceFiles(folder, prodPayload);
|
|
11254
11342
|
const finalFolder = autoRenameHubFolder(folder, prodPayload.hub.name, "production", prodPayload.hub_id, null, null);
|
|
11255
11343
|
prependMirrorMarker(finalFolder, prodPayload.hub_id);
|
|
@@ -11265,13 +11353,13 @@ async function mirrorLinkedProduction(client, workspaceDir, productionHubId, org
|
|
|
11265
11353
|
}
|
|
11266
11354
|
}
|
|
11267
11355
|
function prependMirrorMarker(hubFolder, productionHubId) {
|
|
11268
|
-
const hubYaml =
|
|
11356
|
+
const hubYaml = path14.join(hubFolder, "hub.yaml");
|
|
11269
11357
|
try {
|
|
11270
|
-
const content =
|
|
11358
|
+
const content = fs12.readFileSync(hubYaml, "utf-8");
|
|
11271
11359
|
if (content.startsWith(MIRROR_MARKER_PREFIX)) return;
|
|
11272
11360
|
const marker = `${MIRROR_MARKER_PREFIX} ${productionHubId}. Edits are ignored; push is blocked. Edit the linked preview hub instead.
|
|
11273
11361
|
`;
|
|
11274
|
-
|
|
11362
|
+
fs12.writeFileSync(hubYaml, marker + content, "utf-8");
|
|
11275
11363
|
} catch {
|
|
11276
11364
|
}
|
|
11277
11365
|
}
|
|
@@ -11280,7 +11368,7 @@ async function downloadBinaryResourceFiles(hubFolder, payload) {
|
|
|
11280
11368
|
let downloadCount = 0;
|
|
11281
11369
|
for (const resource of resources) {
|
|
11282
11370
|
if (!resource.files) continue;
|
|
11283
|
-
const resDir =
|
|
11371
|
+
const resDir = path14.join(hubFolder, "resources", slugify(resource.name));
|
|
11284
11372
|
downloadCount += await downloadBinaryFiles(resDir, resource.files);
|
|
11285
11373
|
}
|
|
11286
11374
|
if (downloadCount > 0) {
|
|
@@ -11313,6 +11401,7 @@ var init_pull = __esm({
|
|
|
11313
11401
|
init_resource_files();
|
|
11314
11402
|
init_workspace();
|
|
11315
11403
|
init_layout();
|
|
11404
|
+
init_workspace_files();
|
|
11316
11405
|
init_repo_config();
|
|
11317
11406
|
init_hub_binding();
|
|
11318
11407
|
MIRROR_MARKER_PREFIX = "# Read-only mirror of production hub";
|
|
@@ -11331,8 +11420,8 @@ __export(push_exports, {
|
|
|
11331
11420
|
selectExistingHub: () => selectExistingHub,
|
|
11332
11421
|
shouldWarnIgnoredPreviewLabel: () => shouldWarnIgnoredPreviewLabel
|
|
11333
11422
|
});
|
|
11334
|
-
import * as
|
|
11335
|
-
import * as
|
|
11423
|
+
import * as fs13 from "fs";
|
|
11424
|
+
import * as path15 from "path";
|
|
11336
11425
|
import * as yaml6 from "js-yaml";
|
|
11337
11426
|
function parseArgs5(args2) {
|
|
11338
11427
|
let autoConfirm = false;
|
|
@@ -11416,13 +11505,13 @@ function printWarnings(warnings) {
|
|
|
11416
11505
|
}
|
|
11417
11506
|
}
|
|
11418
11507
|
async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
|
|
11419
|
-
const agentsDir =
|
|
11508
|
+
const agentsDir = path15.join(hubFolder, "agents");
|
|
11420
11509
|
let agentsWithIds = [];
|
|
11421
|
-
if (
|
|
11422
|
-
const yamlFiles =
|
|
11510
|
+
if (fs13.existsSync(agentsDir)) {
|
|
11511
|
+
const yamlFiles = fs13.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml"));
|
|
11423
11512
|
for (const file of yamlFiles) {
|
|
11424
11513
|
try {
|
|
11425
|
-
const content =
|
|
11514
|
+
const content = fs13.readFileSync(path15.join(agentsDir, file), "utf-8");
|
|
11426
11515
|
const agent = yaml6.load(content);
|
|
11427
11516
|
if (agent?.id && agent.name) {
|
|
11428
11517
|
agentsWithIds.push({ id: agent.id, name: agent.name });
|
|
@@ -11435,7 +11524,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
|
|
|
11435
11524
|
if (agentsWithIds.length === 0) {
|
|
11436
11525
|
const yamlPath = resolveHubYamlPath(hubFolder);
|
|
11437
11526
|
if (!yamlPath) return;
|
|
11438
|
-
const yamlContent =
|
|
11527
|
+
const yamlContent = fs13.readFileSync(yamlPath, "utf-8");
|
|
11439
11528
|
const config = yaml6.load(yamlContent);
|
|
11440
11529
|
agentsWithIds = (config.agents || []).filter((a) => !!a.id && !!a.name);
|
|
11441
11530
|
}
|
|
@@ -11465,18 +11554,18 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
|
|
|
11465
11554
|
}
|
|
11466
11555
|
}
|
|
11467
11556
|
if (renames.length === 0) return;
|
|
11468
|
-
if (!
|
|
11469
|
-
for (const file of
|
|
11557
|
+
if (!fs13.existsSync(agentsDir)) return;
|
|
11558
|
+
for (const file of fs13.readdirSync(agentsDir)) {
|
|
11470
11559
|
if (file.startsWith("__rename_temp_") && (file.endsWith(".md") || file.endsWith(".yaml"))) {
|
|
11471
11560
|
console.warn(` Warning: removing orphaned temp file agents/${file}`);
|
|
11472
|
-
|
|
11561
|
+
fs13.unlinkSync(path15.join(agentsDir, file));
|
|
11473
11562
|
}
|
|
11474
11563
|
}
|
|
11475
11564
|
const renameFileIfExists = (dir, oldName, newName) => {
|
|
11476
|
-
const oldPath =
|
|
11477
|
-
const newPath =
|
|
11478
|
-
if (!
|
|
11479
|
-
|
|
11565
|
+
const oldPath = path15.join(dir, oldName);
|
|
11566
|
+
const newPath = path15.join(dir, newName);
|
|
11567
|
+
if (!fs13.existsSync(oldPath)) return false;
|
|
11568
|
+
fs13.renameSync(oldPath, newPath);
|
|
11480
11569
|
return true;
|
|
11481
11570
|
};
|
|
11482
11571
|
const oldSlugs = new Set(renames.map((r) => r.oldSlug));
|
|
@@ -11509,9 +11598,9 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
|
|
|
11509
11598
|
}
|
|
11510
11599
|
} else {
|
|
11511
11600
|
for (const { oldSlug, newSlug } of renames) {
|
|
11512
|
-
const hasOldFile = extensions.some((ext) =>
|
|
11601
|
+
const hasOldFile = extensions.some((ext) => fs13.existsSync(path15.join(agentsDir, `${oldSlug}${ext}`)));
|
|
11513
11602
|
if (!hasOldFile) continue;
|
|
11514
|
-
const hasNewFile = extensions.some((ext) =>
|
|
11603
|
+
const hasNewFile = extensions.some((ext) => fs13.existsSync(path15.join(agentsDir, `${newSlug}${ext}`)));
|
|
11515
11604
|
if (hasNewFile) {
|
|
11516
11605
|
console.warn(` Warning: skipping rename agents/${oldSlug}.* \u2192 agents/${newSlug}.* (target already exists)`);
|
|
11517
11606
|
continue;
|
|
@@ -11526,7 +11615,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
|
|
|
11526
11615
|
if (completedRenames.length === 0) return;
|
|
11527
11616
|
const mainYamlPath = resolveHubYamlPath(hubFolder);
|
|
11528
11617
|
if (mainYamlPath) {
|
|
11529
|
-
const mainYamlContent =
|
|
11618
|
+
const mainYamlContent = fs13.readFileSync(mainYamlPath, "utf-8");
|
|
11530
11619
|
const substitutionMap = /* @__PURE__ */ new Map();
|
|
11531
11620
|
for (const { oldSlug, newSlug } of completedRenames) {
|
|
11532
11621
|
substitutionMap.set(`agents/${oldSlug}.md`, `agents/${newSlug}.md`);
|
|
@@ -11537,8 +11626,8 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
|
|
|
11537
11626
|
(_match, prefix, pathMatch) => `${prefix}${substitutionMap.get(pathMatch) ?? pathMatch}`
|
|
11538
11627
|
);
|
|
11539
11628
|
if (updatedYaml !== mainYamlContent) {
|
|
11540
|
-
|
|
11541
|
-
console.log(` Updated instructions paths in ${
|
|
11629
|
+
fs13.writeFileSync(mainYamlPath, updatedYaml, "utf-8");
|
|
11630
|
+
console.log(` Updated instructions paths in ${path15.basename(mainYamlPath)}`);
|
|
11542
11631
|
}
|
|
11543
11632
|
}
|
|
11544
11633
|
}
|
|
@@ -11599,7 +11688,7 @@ async function pushSingleHub(client, hubId, hubFolder, autoConfirm, organization
|
|
|
11599
11688
|
function selectExistingHub(workspaceDir, allHubs, selector, wsLabel) {
|
|
11600
11689
|
if (selector) {
|
|
11601
11690
|
const match = allHubs.find(
|
|
11602
|
-
(h) => h.hubId === selector ||
|
|
11691
|
+
(h) => h.hubId === selector || path15.basename(h.hubFolder) === selector
|
|
11603
11692
|
);
|
|
11604
11693
|
if (!match) {
|
|
11605
11694
|
console.error(`No hub matching --hub ${selector} found in ${wsLabel}/.`);
|
|
@@ -11642,7 +11731,7 @@ New hub: "${newHub.hubName}" (${hubType})`);
|
|
|
11642
11731
|
process.exit(1);
|
|
11643
11732
|
}
|
|
11644
11733
|
console.log(`Hub created: ${createdHub.hub_name} (${hubId})`);
|
|
11645
|
-
const content =
|
|
11734
|
+
const content = fs13.readFileSync(hubYamlPath, "utf-8");
|
|
11646
11735
|
const hasVersion = content.match(/^version:\s/m);
|
|
11647
11736
|
let updated;
|
|
11648
11737
|
if (hasVersion) {
|
|
@@ -11658,7 +11747,7 @@ hub_id: "${hubId}"
|
|
|
11658
11747
|
hub_environment: preview
|
|
11659
11748
|
${content}`;
|
|
11660
11749
|
}
|
|
11661
|
-
|
|
11750
|
+
fs13.writeFileSync(hubYamlPath, updated, "utf-8");
|
|
11662
11751
|
autoBindIfUnbound(hubId);
|
|
11663
11752
|
await pushSingleHub(client, hubId, newHub.hubFolder, opts.autoConfirm, opts.organizationId, { skipAgentRename: true });
|
|
11664
11753
|
}
|
|
@@ -11667,7 +11756,7 @@ function reportUnresolvedPushTarget(reason, existingHubs, newHubs, selector, wsL
|
|
|
11667
11756
|
if (existingHubs.length > 0) {
|
|
11668
11757
|
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
11758
|
for (const h of existingHubs) {
|
|
11670
|
-
console.error(` ${
|
|
11759
|
+
console.error(` ${path15.basename(h.hubFolder)} (${h.hubId}, production mirror)`);
|
|
11671
11760
|
}
|
|
11672
11761
|
} else {
|
|
11673
11762
|
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 +11769,10 @@ function reportUnresolvedPushTarget(reason, existingHubs, newHubs, selector, wsL
|
|
|
11680
11769
|
console.error(`Multiple hub folders found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
|
|
11681
11770
|
}
|
|
11682
11771
|
for (const h of existingHubs) {
|
|
11683
|
-
console.error(` ${
|
|
11772
|
+
console.error(` ${path15.basename(h.hubFolder)} (${h.hubId})`);
|
|
11684
11773
|
}
|
|
11685
11774
|
for (const h of newHubs) {
|
|
11686
|
-
console.error(` ${
|
|
11775
|
+
console.error(` ${path15.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
|
|
11687
11776
|
}
|
|
11688
11777
|
process.exit(1);
|
|
11689
11778
|
}
|
|
@@ -11697,7 +11786,12 @@ async function pushCommand(args2) {
|
|
|
11697
11786
|
const gitRoot = findGitRoot();
|
|
11698
11787
|
const wsLabel = hubsDirLabel(gitRoot);
|
|
11699
11788
|
if (gitRoot) warnLayoutOnce(gitRoot);
|
|
11700
|
-
if (
|
|
11789
|
+
if (gitRoot) {
|
|
11790
|
+
for (const file of ensureWorkspaceFiles(gitRoot)) {
|
|
11791
|
+
console.error(`Created ${file}`);
|
|
11792
|
+
}
|
|
11793
|
+
}
|
|
11794
|
+
if (!fs13.existsSync(workspaceDir)) {
|
|
11701
11795
|
console.error(`No ${wsLabel}/ directory found. Run \`wayai pull\` first or create hub files in ${wsLabel}/<hub>/hub.yaml.`);
|
|
11702
11796
|
process.exit(1);
|
|
11703
11797
|
}
|
|
@@ -11716,8 +11810,8 @@ async function pushCommand(args2) {
|
|
|
11716
11810
|
if (label) {
|
|
11717
11811
|
console.warn("Note: --label is only used when creating a new hub. To change an existing hub's label, use `wayai relabel`.");
|
|
11718
11812
|
}
|
|
11719
|
-
console.log(`Target hub: ${
|
|
11720
|
-
assertHubMatchesBinding(existing.hubId,
|
|
11813
|
+
console.log(`Target hub: ${path15.basename(existing.hubFolder)} (${existing.hubId})`);
|
|
11814
|
+
assertHubMatchesBinding(existing.hubId, path15.basename(existing.hubFolder));
|
|
11721
11815
|
await pushSingleHub(client, existing.hubId, existing.hubFolder, autoConfirm, organizationId);
|
|
11722
11816
|
return;
|
|
11723
11817
|
}
|
|
@@ -11736,6 +11830,7 @@ var init_push = __esm({
|
|
|
11736
11830
|
init_utils();
|
|
11737
11831
|
init_workspace();
|
|
11738
11832
|
init_layout();
|
|
11833
|
+
init_workspace_files();
|
|
11739
11834
|
init_repo_config();
|
|
11740
11835
|
init_hub_binding();
|
|
11741
11836
|
}
|
|
@@ -11746,8 +11841,8 @@ var create_exports = {};
|
|
|
11746
11841
|
__export(create_exports, {
|
|
11747
11842
|
createCommand: () => createCommand
|
|
11748
11843
|
});
|
|
11749
|
-
import * as
|
|
11750
|
-
import * as
|
|
11844
|
+
import * as path16 from "path";
|
|
11845
|
+
import * as fs14 from "fs";
|
|
11751
11846
|
function parseArgs6(args2) {
|
|
11752
11847
|
let autoConfirm = false;
|
|
11753
11848
|
let folderSelector;
|
|
@@ -11774,7 +11869,7 @@ async function createCommand(args2) {
|
|
|
11774
11869
|
const gitRoot = findGitRoot();
|
|
11775
11870
|
const wsLabel = hubsDirLabel(gitRoot);
|
|
11776
11871
|
if (gitRoot) warnLayoutOnce(gitRoot);
|
|
11777
|
-
if (!
|
|
11872
|
+
if (!fs14.existsSync(workspaceDir)) {
|
|
11778
11873
|
console.error(`No ${wsLabel}/ directory found. Create hub files in ${wsLabel}/<hub>/hub.yaml with \`hub: { name: ... }\` first.`);
|
|
11779
11874
|
process.exit(1);
|
|
11780
11875
|
}
|
|
@@ -11783,7 +11878,7 @@ async function createCommand(args2) {
|
|
|
11783
11878
|
const resolution = resolveNewHubForCreate(workspaceDir, existingHubs, newHubs, folderSelector);
|
|
11784
11879
|
if (!resolution.ok) {
|
|
11785
11880
|
if (resolution.reason === "exists") {
|
|
11786
|
-
const folder =
|
|
11881
|
+
const folder = path16.basename(resolution.existing.hubFolder);
|
|
11787
11882
|
console.error(`Hub "${folder}" already exists (${resolution.existing.hubId}). Use \`wayai push --hub ${folder}\` to update it.`);
|
|
11788
11883
|
process.exit(1);
|
|
11789
11884
|
}
|
|
@@ -11797,7 +11892,7 @@ async function createCommand(args2) {
|
|
|
11797
11892
|
}
|
|
11798
11893
|
console.error(`Multiple new hub folders found in ${wsLabel}/. Pass the folder name (\`wayai create <folder>\`) or run from inside one:`);
|
|
11799
11894
|
for (const h of newHubs) {
|
|
11800
|
-
console.error(` ${
|
|
11895
|
+
console.error(` ${path16.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
|
|
11801
11896
|
}
|
|
11802
11897
|
process.exit(1);
|
|
11803
11898
|
}
|
|
@@ -11967,12 +12062,12 @@ function typeMatches2(typeField, allowed) {
|
|
|
11967
12062
|
if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
|
|
11968
12063
|
return false;
|
|
11969
12064
|
}
|
|
11970
|
-
function validateSchema2(schema,
|
|
12065
|
+
function validateSchema2(schema, path27, errors, opts = {}) {
|
|
11971
12066
|
if (typeof schema === "boolean") return;
|
|
11972
12067
|
const depth = opts.depth ?? 0;
|
|
11973
12068
|
if (depth > MAX_SCHEMA_DEPTH2) {
|
|
11974
12069
|
errors.push({
|
|
11975
|
-
path:
|
|
12070
|
+
path: path27 || "<root>",
|
|
11976
12071
|
message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH2} levels`,
|
|
11977
12072
|
suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
|
|
11978
12073
|
});
|
|
@@ -11980,7 +12075,7 @@ function validateSchema2(schema, path26, errors, opts = {}) {
|
|
|
11980
12075
|
}
|
|
11981
12076
|
if (!isRecord2(schema)) {
|
|
11982
12077
|
errors.push({
|
|
11983
|
-
path:
|
|
12078
|
+
path: path27,
|
|
11984
12079
|
message: `expected object, got ${schema === null ? "null" : typeof schema}`
|
|
11985
12080
|
});
|
|
11986
12081
|
return;
|
|
@@ -11988,14 +12083,14 @@ function validateSchema2(schema, path26, errors, opts = {}) {
|
|
|
11988
12083
|
if (opts.isRoot) {
|
|
11989
12084
|
if ("type" in schema && schema.type !== "object") {
|
|
11990
12085
|
errors.push({
|
|
11991
|
-
path:
|
|
12086
|
+
path: path27 ? `${path27}.type` : "type",
|
|
11992
12087
|
message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
|
|
11993
12088
|
suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
|
|
11994
12089
|
});
|
|
11995
12090
|
}
|
|
11996
12091
|
} else if ("type" in schema && !typeMatches2(schema.type, ALLOWED_TYPES2)) {
|
|
11997
12092
|
errors.push({
|
|
11998
|
-
path: `${
|
|
12093
|
+
path: `${path27}.type`,
|
|
11999
12094
|
message: `type must be one of ${[...ALLOWED_TYPES2].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
|
|
12000
12095
|
});
|
|
12001
12096
|
}
|
|
@@ -12004,25 +12099,25 @@ function validateSchema2(schema, path26, errors, opts = {}) {
|
|
|
12004
12099
|
if (typeof e === "string") {
|
|
12005
12100
|
const isPlaceholder = PLACEHOLDER_TOKENS2.includes(e);
|
|
12006
12101
|
errors.push({
|
|
12007
|
-
path: `${
|
|
12102
|
+
path: `${path27}.enum`,
|
|
12008
12103
|
message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
|
|
12009
12104
|
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
12105
|
});
|
|
12011
12106
|
} else if (!Array.isArray(e)) {
|
|
12012
12107
|
errors.push({
|
|
12013
|
-
path: `${
|
|
12108
|
+
path: `${path27}.enum`,
|
|
12014
12109
|
message: `enum must be a non-empty array of primitives, got ${typeof e}`
|
|
12015
12110
|
});
|
|
12016
12111
|
} else if (e.length === 0) {
|
|
12017
12112
|
errors.push({
|
|
12018
|
-
path: `${
|
|
12113
|
+
path: `${path27}.enum`,
|
|
12019
12114
|
message: "enum must not be empty"
|
|
12020
12115
|
});
|
|
12021
12116
|
} else {
|
|
12022
12117
|
for (let i = 0; i < e.length; i++) {
|
|
12023
12118
|
if (!isPrimitive2(e[i])) {
|
|
12024
12119
|
errors.push({
|
|
12025
|
-
path: `${
|
|
12120
|
+
path: `${path27}.enum[${i}]`,
|
|
12026
12121
|
message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
|
|
12027
12122
|
});
|
|
12028
12123
|
}
|
|
@@ -12032,7 +12127,7 @@ function validateSchema2(schema, path26, errors, opts = {}) {
|
|
|
12032
12127
|
for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
|
|
12033
12128
|
if (key in schema && typeof schema[key] === "boolean") {
|
|
12034
12129
|
errors.push({
|
|
12035
|
-
path: `${
|
|
12130
|
+
path: `${path27}.${key}`,
|
|
12036
12131
|
message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
|
|
12037
12132
|
suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
|
|
12038
12133
|
});
|
|
@@ -12041,45 +12136,45 @@ function validateSchema2(schema, path26, errors, opts = {}) {
|
|
|
12041
12136
|
if ("properties" in schema) {
|
|
12042
12137
|
if (!isRecord2(schema.properties)) {
|
|
12043
12138
|
errors.push({
|
|
12044
|
-
path: `${
|
|
12139
|
+
path: `${path27}.properties`,
|
|
12045
12140
|
message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
|
|
12046
12141
|
});
|
|
12047
12142
|
} else {
|
|
12048
12143
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
12049
|
-
validateSchema2(propSchema, `${
|
|
12144
|
+
validateSchema2(propSchema, `${path27}.properties.${propName}`, errors, { depth: depth + 1 });
|
|
12050
12145
|
}
|
|
12051
12146
|
}
|
|
12052
12147
|
}
|
|
12053
12148
|
if (schemaTypeIncludes2(schema, "array") && "items" in schema) {
|
|
12054
12149
|
if (Array.isArray(schema.items)) {
|
|
12055
|
-
schema.items.forEach((sub, i) => validateSchema2(sub, `${
|
|
12150
|
+
schema.items.forEach((sub, i) => validateSchema2(sub, `${path27}.items[${i}]`, errors, { depth: depth + 1 }));
|
|
12056
12151
|
} else {
|
|
12057
|
-
validateSchema2(schema.items, `${
|
|
12152
|
+
validateSchema2(schema.items, `${path27}.items`, errors, { depth: depth + 1 });
|
|
12058
12153
|
}
|
|
12059
12154
|
}
|
|
12060
12155
|
for (const key of SUBSCHEMA_OBJECT_KEYWORDS2) {
|
|
12061
12156
|
if (key in schema && isRecord2(schema[key])) {
|
|
12062
|
-
validateSchema2(schema[key], `${
|
|
12157
|
+
validateSchema2(schema[key], `${path27}.${key}`, errors, { depth: depth + 1 });
|
|
12063
12158
|
}
|
|
12064
12159
|
}
|
|
12065
12160
|
for (const key of SUBSCHEMA_LIST_KEYWORDS2) {
|
|
12066
12161
|
const list = schema[key];
|
|
12067
12162
|
if (Array.isArray(list)) {
|
|
12068
|
-
list.forEach((sub, i) => validateSchema2(sub, `${
|
|
12163
|
+
list.forEach((sub, i) => validateSchema2(sub, `${path27}.${key}[${i}]`, errors, { depth: depth + 1 }));
|
|
12069
12164
|
}
|
|
12070
12165
|
}
|
|
12071
12166
|
for (const key of SUBSCHEMA_MAP_KEYWORDS2) {
|
|
12072
12167
|
const map = schema[key];
|
|
12073
12168
|
if (isRecord2(map)) {
|
|
12074
12169
|
for (const [name, sub] of Object.entries(map)) {
|
|
12075
|
-
validateSchema2(sub, `${
|
|
12170
|
+
validateSchema2(sub, `${path27}.${key}.${name}`, errors, { depth: depth + 1 });
|
|
12076
12171
|
}
|
|
12077
12172
|
}
|
|
12078
12173
|
}
|
|
12079
12174
|
const reportedPaths = new Set(errors.map((e) => e.path));
|
|
12080
12175
|
for (const [k, v] of Object.entries(schema)) {
|
|
12081
12176
|
if (typeof v !== "string") continue;
|
|
12082
|
-
const fieldPath = `${
|
|
12177
|
+
const fieldPath = `${path27}.${k}`;
|
|
12083
12178
|
if (reportedPaths.has(fieldPath)) continue;
|
|
12084
12179
|
for (const token of PLACEHOLDER_TOKENS2) {
|
|
12085
12180
|
if (v === token) {
|
|
@@ -12235,10 +12330,10 @@ function refineHubAsCodeLanes2(config, ctx) {
|
|
|
12235
12330
|
}
|
|
12236
12331
|
}
|
|
12237
12332
|
}
|
|
12238
|
-
function isSafeTemplatePath2(
|
|
12239
|
-
if (
|
|
12240
|
-
if (
|
|
12241
|
-
const segments =
|
|
12333
|
+
function isSafeTemplatePath2(path27) {
|
|
12334
|
+
if (path27.length === 0 || path27.length > 300) return false;
|
|
12335
|
+
if (path27.startsWith("/") || path27.includes("\\")) return false;
|
|
12336
|
+
const segments = path27.split("/");
|
|
12242
12337
|
return segments.every(
|
|
12243
12338
|
(seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
|
|
12244
12339
|
);
|
|
@@ -12266,9 +12361,9 @@ function isPlainObject(value) {
|
|
|
12266
12361
|
const proto = Object.getPrototypeOf(value);
|
|
12267
12362
|
return proto === Object.prototype || proto === null;
|
|
12268
12363
|
}
|
|
12269
|
-
function isSanitizableSliceFile(
|
|
12270
|
-
if (!/\.ya?ml$/i.test(
|
|
12271
|
-
return
|
|
12364
|
+
function isSanitizableSliceFile(path27) {
|
|
12365
|
+
if (!/\.ya?ml$/i.test(path27)) return false;
|
|
12366
|
+
return path27 !== "resources" && !path27.startsWith("resources/");
|
|
12272
12367
|
}
|
|
12273
12368
|
function distinctUsesBackends(uses) {
|
|
12274
12369
|
return [...new Set((uses ?? []).map((u) => u.backend))];
|
|
@@ -14255,7 +14350,6 @@ var init_contracts = __esm({
|
|
|
14255
14350
|
});
|
|
14256
14351
|
dataExplorerDebugAnalyticsTable2 = external_exports.enum([
|
|
14257
14352
|
"conversation",
|
|
14258
|
-
"message",
|
|
14259
14353
|
"schedule_event"
|
|
14260
14354
|
]);
|
|
14261
14355
|
debugUuid2 = external_exports.string().uuid();
|
|
@@ -14888,8 +14982,8 @@ var replicate_exports = {};
|
|
|
14888
14982
|
__export(replicate_exports, {
|
|
14889
14983
|
replicateCommand: () => replicateCommand
|
|
14890
14984
|
});
|
|
14891
|
-
import * as
|
|
14892
|
-
import * as
|
|
14985
|
+
import * as fs15 from "fs";
|
|
14986
|
+
import * as path17 from "path";
|
|
14893
14987
|
function parseArgs8(args2) {
|
|
14894
14988
|
let label;
|
|
14895
14989
|
let hubSelector;
|
|
@@ -14935,7 +15029,7 @@ async function replicateCommand(args2) {
|
|
|
14935
15029
|
payload.preview_label,
|
|
14936
15030
|
payload.branch_name
|
|
14937
15031
|
);
|
|
14938
|
-
|
|
15032
|
+
fs15.mkdirSync(path17.dirname(hubFolder), { recursive: true });
|
|
14939
15033
|
writeHubFolder(hubFolder, payload);
|
|
14940
15034
|
await downloadBinaryResourceFiles(hubFolder, payload);
|
|
14941
15035
|
hubFolder = autoRenameHubFolder(
|
|
@@ -14947,8 +15041,8 @@ async function replicateCommand(args2) {
|
|
|
14947
15041
|
payload.branch_name
|
|
14948
15042
|
);
|
|
14949
15043
|
autoBindIfUnbound(previewHubId);
|
|
14950
|
-
console.log(`Preview written to ${
|
|
14951
|
-
console.log(` Switch to it with: wayai use ${
|
|
15044
|
+
console.log(`Preview written to ${path17.basename(hubFolder)}`);
|
|
15045
|
+
console.log(` Switch to it with: wayai use ${path17.basename(hubFolder)}`);
|
|
14952
15046
|
}
|
|
14953
15047
|
var init_replicate = __esm({
|
|
14954
15048
|
"src/commands/replicate.ts"() {
|
|
@@ -14970,7 +15064,7 @@ var relabel_exports = {};
|
|
|
14970
15064
|
__export(relabel_exports, {
|
|
14971
15065
|
relabelCommand: () => relabelCommand
|
|
14972
15066
|
});
|
|
14973
|
-
import * as
|
|
15067
|
+
import * as path18 from "path";
|
|
14974
15068
|
function parseArgs9(args2) {
|
|
14975
15069
|
let label;
|
|
14976
15070
|
let clear = false;
|
|
@@ -15014,7 +15108,7 @@ async function relabelCommand(args2) {
|
|
|
15014
15108
|
} else {
|
|
15015
15109
|
console.error(`Multiple hubs found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
|
|
15016
15110
|
for (const h of previewHubs) {
|
|
15017
|
-
console.error(` ${
|
|
15111
|
+
console.error(` ${path18.basename(h.hubFolder)} (${h.hubId})`);
|
|
15018
15112
|
}
|
|
15019
15113
|
}
|
|
15020
15114
|
process.exit(1);
|
|
@@ -15023,7 +15117,7 @@ async function relabelCommand(args2) {
|
|
|
15023
15117
|
console.log("This is a read-only production mirror \u2014 production hubs have no preview label. Relabel the linked preview hub instead.");
|
|
15024
15118
|
return;
|
|
15025
15119
|
}
|
|
15026
|
-
assertHubMatchesBinding(target.hubId,
|
|
15120
|
+
assertHubMatchesBinding(target.hubId, path18.basename(target.hubFolder));
|
|
15027
15121
|
console.log(normalizedLabel ? `Setting preview label to "${normalizedLabel}"...` : "Clearing preview label...");
|
|
15028
15122
|
const { data } = await client.relabelPreview(target.hubId, normalizedLabel);
|
|
15029
15123
|
const row = data[0];
|
|
@@ -15039,7 +15133,7 @@ async function relabelCommand(args2) {
|
|
|
15039
15133
|
);
|
|
15040
15134
|
console.log(serverLabel ? `Preview label set to "${serverLabel}".` : "Preview label cleared.");
|
|
15041
15135
|
if (finalFolder !== target.hubFolder) {
|
|
15042
|
-
console.log(`Hub folder is now ${
|
|
15136
|
+
console.log(`Hub folder is now ${path18.basename(finalFolder)}`);
|
|
15043
15137
|
}
|
|
15044
15138
|
}
|
|
15045
15139
|
var init_relabel = __esm({
|
|
@@ -15065,7 +15159,7 @@ __export(publish_exports, {
|
|
|
15065
15159
|
renderHubDiff: () => renderHubDiff,
|
|
15066
15160
|
runPublish: () => runPublish
|
|
15067
15161
|
});
|
|
15068
|
-
import * as
|
|
15162
|
+
import * as path19 from "path";
|
|
15069
15163
|
function parseArgs10(args2) {
|
|
15070
15164
|
let autoConfirm = false;
|
|
15071
15165
|
let hubSelector;
|
|
@@ -15171,7 +15265,7 @@ async function publishCommand(args2) {
|
|
|
15171
15265
|
return;
|
|
15172
15266
|
}
|
|
15173
15267
|
}
|
|
15174
|
-
assertHubMatchesBinding(hubId, hubFolder ?
|
|
15268
|
+
assertHubMatchesBinding(hubId, hubFolder ? path19.basename(hubFolder) : void 0);
|
|
15175
15269
|
await runPublish(client, { hubId, localConfig, organizationId, autoConfirm });
|
|
15176
15270
|
}
|
|
15177
15271
|
var STATUS_STYLE;
|
|
@@ -15203,7 +15297,7 @@ var use_exports = {};
|
|
|
15203
15297
|
__export(use_exports, {
|
|
15204
15298
|
useCommand: () => useCommand
|
|
15205
15299
|
});
|
|
15206
|
-
import * as
|
|
15300
|
+
import * as path20 from "path";
|
|
15207
15301
|
async function useCommand(args2) {
|
|
15208
15302
|
const target = args2[0];
|
|
15209
15303
|
if (!target || target.startsWith("-")) {
|
|
@@ -15225,7 +15319,7 @@ async function useCommand(args2) {
|
|
|
15225
15319
|
const match = findHubByFolderName(workspaceDir, target);
|
|
15226
15320
|
if (!match) {
|
|
15227
15321
|
const newHubs = scanNewHubs(workspaceDir);
|
|
15228
|
-
const pending = newHubs.find((h) =>
|
|
15322
|
+
const pending = newHubs.find((h) => path20.basename(h.hubFolder) === target);
|
|
15229
15323
|
if (pending) {
|
|
15230
15324
|
console.error(
|
|
15231
15325
|
`"${target}" is a new hub that hasn't been created on the platform yet, so it has no id to bind to.
|
|
@@ -15236,10 +15330,10 @@ Create it first \u2014 the worktree binds automatically afterward:
|
|
|
15236
15330
|
}
|
|
15237
15331
|
console.error(`No hub matching "${target}" found in ${wsLabel}/. Pass a UUID or a folder name from:`);
|
|
15238
15332
|
for (const h of scanWorkspaceHubs(workspaceDir)) {
|
|
15239
|
-
console.error(` ${
|
|
15333
|
+
console.error(` ${path20.basename(h.hubFolder)} (${h.hubId})`);
|
|
15240
15334
|
}
|
|
15241
15335
|
for (const h of newHubs) {
|
|
15242
|
-
console.error(` ${
|
|
15336
|
+
console.error(` ${path20.basename(h.hubFolder)} (new \u2014 "${h.hubName}", run \`wayai create ${path20.basename(h.hubFolder)}\`)`);
|
|
15243
15337
|
}
|
|
15244
15338
|
process.exit(1);
|
|
15245
15339
|
}
|
|
@@ -15278,11 +15372,11 @@ __export(migrate_exports, {
|
|
|
15278
15372
|
migrateCommand: () => migrateCommand
|
|
15279
15373
|
});
|
|
15280
15374
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
15281
|
-
import * as
|
|
15282
|
-
import * as
|
|
15375
|
+
import * as fs16 from "fs";
|
|
15376
|
+
import * as path21 from "path";
|
|
15283
15377
|
function isTracked(gitRoot, p) {
|
|
15284
15378
|
try {
|
|
15285
|
-
execFileSync3("git", ["ls-files", "--error-unmatch", "--",
|
|
15379
|
+
execFileSync3("git", ["ls-files", "--error-unmatch", "--", path21.relative(gitRoot, p)], {
|
|
15286
15380
|
cwd: gitRoot,
|
|
15287
15381
|
stdio: ["pipe", "pipe", "pipe"]
|
|
15288
15382
|
});
|
|
@@ -15292,10 +15386,10 @@ function isTracked(gitRoot, p) {
|
|
|
15292
15386
|
}
|
|
15293
15387
|
}
|
|
15294
15388
|
function moveDir(gitRoot, from, to) {
|
|
15295
|
-
|
|
15389
|
+
fs16.mkdirSync(path21.dirname(to), { recursive: true });
|
|
15296
15390
|
if (isTracked(gitRoot, from)) {
|
|
15297
15391
|
try {
|
|
15298
|
-
execFileSync3("git", ["mv",
|
|
15392
|
+
execFileSync3("git", ["mv", path21.relative(gitRoot, from), path21.relative(gitRoot, to)], {
|
|
15299
15393
|
cwd: gitRoot,
|
|
15300
15394
|
stdio: ["pipe", "pipe", "pipe"]
|
|
15301
15395
|
});
|
|
@@ -15303,7 +15397,7 @@ function moveDir(gitRoot, from, to) {
|
|
|
15303
15397
|
} catch {
|
|
15304
15398
|
}
|
|
15305
15399
|
}
|
|
15306
|
-
|
|
15400
|
+
fs16.renameSync(from, to);
|
|
15307
15401
|
return "fs";
|
|
15308
15402
|
}
|
|
15309
15403
|
async function migrateCommand(_args) {
|
|
@@ -15312,12 +15406,12 @@ async function migrateCommand(_args) {
|
|
|
15312
15406
|
console.error("Not inside a git repository.");
|
|
15313
15407
|
process.exit(1);
|
|
15314
15408
|
}
|
|
15315
|
-
const rel = (p) =>
|
|
15316
|
-
const newWs =
|
|
15317
|
-
const legacyWs =
|
|
15318
|
-
const legacyOrg =
|
|
15319
|
-
const newHubs =
|
|
15320
|
-
const newOrg =
|
|
15409
|
+
const rel = (p) => path21.relative(gitRoot, p);
|
|
15410
|
+
const newWs = path21.join(gitRoot, WAYAI_LAYOUT.wsDir);
|
|
15411
|
+
const legacyWs = path21.join(gitRoot, WAYAI_LAYOUT.legacy.wsDir);
|
|
15412
|
+
const legacyOrg = path21.join(gitRoot, WAYAI_LAYOUT.legacy.orgAtRoot);
|
|
15413
|
+
const newHubs = path21.join(newWs, WAYAI_LAYOUT.hubsSubdir);
|
|
15414
|
+
const newOrg = path21.join(newWs, WAYAI_LAYOUT.orgSubdir);
|
|
15321
15415
|
const hasLegacyWs = isDirectory(legacyWs);
|
|
15322
15416
|
const hasLegacyOrg = isDirectory(legacyOrg);
|
|
15323
15417
|
if (!hasLegacyWs && !hasLegacyOrg) {
|
|
@@ -16654,8 +16748,8 @@ var eval_capture_exports = {};
|
|
|
16654
16748
|
__export(eval_capture_exports, {
|
|
16655
16749
|
evalCaptureCommand: () => evalCaptureCommand
|
|
16656
16750
|
});
|
|
16657
|
-
import * as
|
|
16658
|
-
import * as
|
|
16751
|
+
import * as fs17 from "fs";
|
|
16752
|
+
import * as path22 from "path";
|
|
16659
16753
|
import * as yaml7 from "js-yaml";
|
|
16660
16754
|
function isValidSetName(name) {
|
|
16661
16755
|
if (name.length === 0 || name === "." || name === "..") return false;
|
|
@@ -16721,15 +16815,15 @@ async function evalCaptureCommand(args2) {
|
|
|
16721
16815
|
const setFolderName = targetSetName;
|
|
16722
16816
|
const scenarioName = parsed.evalName ?? `Capture ${parsed.conversationId.slice(0, 8)}`;
|
|
16723
16817
|
const slug = slugify(scenarioName);
|
|
16724
|
-
const evalsDir =
|
|
16725
|
-
const targetDir =
|
|
16726
|
-
const targetPath =
|
|
16727
|
-
if (!targetPath.startsWith(evalsDir +
|
|
16728
|
-
console.error(`Resolved path "${
|
|
16818
|
+
const evalsDir = path22.join(hubFolder, "evals");
|
|
16819
|
+
const targetDir = path22.join(evalsDir, setFolderName);
|
|
16820
|
+
const targetPath = path22.join(targetDir, `${slug}.yaml`);
|
|
16821
|
+
if (!targetPath.startsWith(evalsDir + path22.sep)) {
|
|
16822
|
+
console.error(`Resolved path "${path22.relative(hubFolder, targetPath)}" escapes evals/. Aborting.`);
|
|
16729
16823
|
process.exit(1);
|
|
16730
16824
|
}
|
|
16731
|
-
if (
|
|
16732
|
-
console.error(`File already exists: ${
|
|
16825
|
+
if (fs17.existsSync(targetPath)) {
|
|
16826
|
+
console.error(`File already exists: ${path22.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
|
|
16733
16827
|
process.exit(1);
|
|
16734
16828
|
}
|
|
16735
16829
|
console.log("Resolving scenario set...");
|
|
@@ -16761,9 +16855,9 @@ async function evalCaptureCommand(args2) {
|
|
|
16761
16855
|
...captured.evaluator_instructions ? { evaluator_instructions: captured.evaluator_instructions } : {}
|
|
16762
16856
|
};
|
|
16763
16857
|
const yamlObj = buildEvalYamlObject(evalEntry, slug);
|
|
16764
|
-
|
|
16765
|
-
|
|
16766
|
-
const relPath =
|
|
16858
|
+
fs17.mkdirSync(targetDir, { recursive: true });
|
|
16859
|
+
fs17.writeFileSync(targetPath, yaml7.dump(yamlObj, YAML_DUMP_OPTIONS), "utf-8");
|
|
16860
|
+
const relPath = path22.relative(process.cwd(), targetPath);
|
|
16767
16861
|
console.log(`
|
|
16768
16862
|
Wrote ${relPath}`);
|
|
16769
16863
|
console.log("Run `wayai pull` to refresh the agent display name, then commit. The scenario is already on the platform.");
|
|
@@ -17990,23 +18084,23 @@ var init_set_connection_credential = __esm({
|
|
|
17990
18084
|
});
|
|
17991
18085
|
|
|
17992
18086
|
// src/lib/org-workspace.ts
|
|
17993
|
-
import * as
|
|
17994
|
-
import * as
|
|
18087
|
+
import * as fs18 from "fs";
|
|
18088
|
+
import * as path23 from "path";
|
|
17995
18089
|
import * as yaml8 from "js-yaml";
|
|
17996
18090
|
function getOrgDir(gitRoot) {
|
|
17997
18091
|
return resolveLayout(gitRoot).orgDir;
|
|
17998
18092
|
}
|
|
17999
18093
|
function orgManifestExists(orgDir) {
|
|
18000
|
-
return
|
|
18094
|
+
return fs18.existsSync(path23.join(orgDir, ORG_MANIFEST_NAME));
|
|
18001
18095
|
}
|
|
18002
18096
|
function parseOrgResources(orgDir) {
|
|
18003
|
-
const manifestPath =
|
|
18097
|
+
const manifestPath = path23.join(orgDir, ORG_MANIFEST_NAME);
|
|
18004
18098
|
let manifest = {};
|
|
18005
|
-
if (
|
|
18006
|
-
manifest = yaml8.load(
|
|
18099
|
+
if (fs18.existsSync(manifestPath)) {
|
|
18100
|
+
manifest = yaml8.load(fs18.readFileSync(manifestPath, "utf-8")) ?? {};
|
|
18007
18101
|
}
|
|
18008
18102
|
const rawResources = Array.isArray(manifest.resources) ? manifest.resources : [];
|
|
18009
|
-
const resourcesDir =
|
|
18103
|
+
const resourcesDir = path23.join(orgDir, "resources");
|
|
18010
18104
|
const resources = rawResources.map((res) => {
|
|
18011
18105
|
const resource = { name: res.name };
|
|
18012
18106
|
if (res.id) resource.id = res.id;
|
|
@@ -18018,8 +18112,8 @@ function parseOrgResources(orgDir) {
|
|
|
18018
18112
|
if (res.environment) resource.environment = res.environment;
|
|
18019
18113
|
if (Array.isArray(res.tags)) resource.tags = res.tags;
|
|
18020
18114
|
if (Array.isArray(res.folders)) resource.folders = res.folders;
|
|
18021
|
-
const resDir =
|
|
18022
|
-
if (
|
|
18115
|
+
const resDir = path23.join(resourcesDir, slugify(resource.name));
|
|
18116
|
+
if (fs18.existsSync(resDir)) {
|
|
18023
18117
|
const files = scanResourceFiles(resDir, "");
|
|
18024
18118
|
if (files.length > 0) resource.files = files;
|
|
18025
18119
|
}
|
|
@@ -18028,28 +18122,28 @@ function parseOrgResources(orgDir) {
|
|
|
18028
18122
|
return { version: 1, resources };
|
|
18029
18123
|
}
|
|
18030
18124
|
function writeOrgResources(orgDir, payload) {
|
|
18031
|
-
|
|
18125
|
+
fs18.mkdirSync(orgDir, { recursive: true });
|
|
18032
18126
|
const resources = payload.resources ?? [];
|
|
18033
18127
|
const manifestResources = resources.map((r) => {
|
|
18034
18128
|
const { files: _files, ...rest } = r;
|
|
18035
18129
|
return rest;
|
|
18036
18130
|
});
|
|
18037
|
-
|
|
18038
|
-
|
|
18131
|
+
fs18.writeFileSync(
|
|
18132
|
+
path23.join(orgDir, ORG_MANIFEST_NAME),
|
|
18039
18133
|
yaml8.dump({ version: 1, resources: manifestResources }, YAML_DUMP_OPTIONS),
|
|
18040
18134
|
"utf-8"
|
|
18041
18135
|
);
|
|
18042
|
-
const resourcesDir =
|
|
18136
|
+
const resourcesDir = path23.join(orgDir, "resources");
|
|
18043
18137
|
const currentSlugs = /* @__PURE__ */ new Set();
|
|
18044
18138
|
for (const resource of resources) {
|
|
18045
18139
|
const resSlug = slugify(resource.name);
|
|
18046
18140
|
currentSlugs.add(resSlug);
|
|
18047
|
-
writeResourceFileTree(
|
|
18141
|
+
writeResourceFileTree(path23.join(resourcesDir, resSlug), resource.files || []);
|
|
18048
18142
|
}
|
|
18049
|
-
if (
|
|
18050
|
-
for (const entry of
|
|
18143
|
+
if (fs18.existsSync(resourcesDir)) {
|
|
18144
|
+
for (const entry of fs18.readdirSync(resourcesDir, { withFileTypes: true })) {
|
|
18051
18145
|
if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
|
|
18052
|
-
|
|
18146
|
+
fs18.rmSync(path23.join(resourcesDir, entry.name), { recursive: true, force: true });
|
|
18053
18147
|
}
|
|
18054
18148
|
}
|
|
18055
18149
|
}
|
|
@@ -18058,7 +18152,7 @@ async function downloadOrgBinaryFiles(orgDir, payload) {
|
|
|
18058
18152
|
let count = 0;
|
|
18059
18153
|
for (const resource of payload.resources ?? []) {
|
|
18060
18154
|
if (!resource.files) continue;
|
|
18061
|
-
const resDir =
|
|
18155
|
+
const resDir = path23.join(orgDir, "resources", slugify(resource.name));
|
|
18062
18156
|
count += await downloadBinaryFiles(resDir, resource.files);
|
|
18063
18157
|
}
|
|
18064
18158
|
if (count > 0) console.log(`Downloaded ${count} binary resource file(s).`);
|
|
@@ -18314,20 +18408,20 @@ var init_list = __esm({
|
|
|
18314
18408
|
});
|
|
18315
18409
|
|
|
18316
18410
|
// src/lib/template-files.ts
|
|
18317
|
-
import * as
|
|
18318
|
-
import * as
|
|
18411
|
+
import * as fs19 from "fs";
|
|
18412
|
+
import * as path24 from "path";
|
|
18319
18413
|
function readDirToFileMap(rootDir) {
|
|
18320
18414
|
const out = {};
|
|
18321
18415
|
function walk(dir, prefix) {
|
|
18322
|
-
const entries =
|
|
18416
|
+
const entries = fs19.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
18323
18417
|
for (const entry of entries) {
|
|
18324
|
-
const abs =
|
|
18418
|
+
const abs = path24.join(dir, entry.name);
|
|
18325
18419
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
18326
18420
|
if (entry.isDirectory()) walk(abs, rel);
|
|
18327
|
-
else if (entry.isFile()) out[rel] =
|
|
18421
|
+
else if (entry.isFile()) out[rel] = fs19.readFileSync(abs, "utf-8");
|
|
18328
18422
|
}
|
|
18329
18423
|
}
|
|
18330
|
-
if (
|
|
18424
|
+
if (fs19.existsSync(rootDir)) walk(rootDir, "");
|
|
18331
18425
|
return out;
|
|
18332
18426
|
}
|
|
18333
18427
|
function detectCollisions(targetDir, files) {
|
|
@@ -18336,7 +18430,7 @@ function detectCollisions(targetDir, files) {
|
|
|
18336
18430
|
if (!isSafeTemplatePath2(rel)) {
|
|
18337
18431
|
throw new Error(`Refusing to inspect unsafe template path: ${rel}`);
|
|
18338
18432
|
}
|
|
18339
|
-
if (
|
|
18433
|
+
if (fs19.existsSync(path24.join(targetDir, rel))) collisions.push(rel);
|
|
18340
18434
|
}
|
|
18341
18435
|
return collisions.sort((a, b) => a.localeCompare(b));
|
|
18342
18436
|
}
|
|
@@ -18346,9 +18440,9 @@ function writeFileMap(targetDir, files) {
|
|
|
18346
18440
|
if (!isSafeTemplatePath2(rel)) {
|
|
18347
18441
|
throw new Error(`Refusing to write unsafe template path: ${rel}`);
|
|
18348
18442
|
}
|
|
18349
|
-
const abs =
|
|
18350
|
-
|
|
18351
|
-
|
|
18443
|
+
const abs = path24.join(targetDir, rel);
|
|
18444
|
+
fs19.mkdirSync(path24.dirname(abs), { recursive: true });
|
|
18445
|
+
fs19.writeFileSync(abs, body, "utf-8");
|
|
18352
18446
|
written.push(rel);
|
|
18353
18447
|
}
|
|
18354
18448
|
return written;
|
|
@@ -18356,20 +18450,20 @@ function writeFileMap(targetDir, files) {
|
|
|
18356
18450
|
function listDirRelFiles(dir) {
|
|
18357
18451
|
const out = [];
|
|
18358
18452
|
function walk(d, prefix) {
|
|
18359
|
-
for (const entry of
|
|
18453
|
+
for (const entry of fs19.readdirSync(d, { withFileTypes: true })) {
|
|
18360
18454
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
18361
|
-
if (entry.isDirectory()) walk(
|
|
18455
|
+
if (entry.isDirectory()) walk(path24.join(d, entry.name), rel);
|
|
18362
18456
|
else if (entry.isFile()) out.push(rel);
|
|
18363
18457
|
}
|
|
18364
18458
|
}
|
|
18365
|
-
if (
|
|
18459
|
+
if (fs19.existsSync(dir)) walk(dir, "");
|
|
18366
18460
|
return out;
|
|
18367
18461
|
}
|
|
18368
18462
|
function writeSliceSnapshot(targetDir, files) {
|
|
18369
18463
|
const keep = new Set(Object.keys(files));
|
|
18370
18464
|
const removed = listDirRelFiles(targetDir).filter((rel) => !keep.has(rel)).sort((a, b) => a.localeCompare(b));
|
|
18371
18465
|
const written = writeFileMap(targetDir, files).sort((a, b) => a.localeCompare(b));
|
|
18372
|
-
if (
|
|
18466
|
+
if (fs19.existsSync(targetDir)) cleanOrphanFiles(targetDir, "", keep);
|
|
18373
18467
|
return { written, removed };
|
|
18374
18468
|
}
|
|
18375
18469
|
var init_template_files = __esm({
|
|
@@ -18385,7 +18479,7 @@ var templates_exports = {};
|
|
|
18385
18479
|
__export(templates_exports, {
|
|
18386
18480
|
templateCommand: () => templateCommand
|
|
18387
18481
|
});
|
|
18388
|
-
import * as
|
|
18482
|
+
import * as path25 from "path";
|
|
18389
18483
|
async function templateCommand(args2) {
|
|
18390
18484
|
const [sub, ...rest] = args2;
|
|
18391
18485
|
switch (sub) {
|
|
@@ -18501,8 +18595,8 @@ async function runTemplatePull(rest) {
|
|
|
18501
18595
|
console.log(`Template "${slug}" has no WayAI slice${hint}`);
|
|
18502
18596
|
return;
|
|
18503
18597
|
}
|
|
18504
|
-
const targetDir =
|
|
18505
|
-
const relTarget =
|
|
18598
|
+
const targetDir = path25.join(resolveLayout(gitRoot).hubsDir, slug);
|
|
18599
|
+
const relTarget = path25.relative(gitRoot, targetDir);
|
|
18506
18600
|
const collisions = detectCollisions(targetDir, detail.files);
|
|
18507
18601
|
if (dryRun) {
|
|
18508
18602
|
const planned = Object.keys(detail.files).sort((a, b) => a.localeCompare(b));
|
|
@@ -18676,8 +18770,8 @@ var admin_exports = {};
|
|
|
18676
18770
|
__export(admin_exports, {
|
|
18677
18771
|
adminCommand: () => adminCommand
|
|
18678
18772
|
});
|
|
18679
|
-
import * as
|
|
18680
|
-
import * as
|
|
18773
|
+
import * as fs20 from "fs";
|
|
18774
|
+
import * as path26 from "path";
|
|
18681
18775
|
import * as yaml10 from "js-yaml";
|
|
18682
18776
|
async function adminCommand(args2) {
|
|
18683
18777
|
const [group, ...afterGroup] = args2;
|
|
@@ -18985,7 +19079,7 @@ async function runArchiveRead(positional, flagArgs) {
|
|
|
18985
19079
|
exitOnApiError(err);
|
|
18986
19080
|
throw err;
|
|
18987
19081
|
}
|
|
18988
|
-
|
|
19082
|
+
fs20.writeFileSync(outPath, zip);
|
|
18989
19083
|
console.log(`Wrote ${zip.byteLength} bytes to ${outPath}`);
|
|
18990
19084
|
return;
|
|
18991
19085
|
}
|
|
@@ -19117,15 +19211,15 @@ function loadTemplateManifest(slug) {
|
|
|
19117
19211
|
console.error("Not in a git repository. Run from the tutorials/ authoring repo.");
|
|
19118
19212
|
process.exit(1);
|
|
19119
19213
|
}
|
|
19120
|
-
const templateDir =
|
|
19121
|
-
const manifestPath =
|
|
19122
|
-
if (!
|
|
19123
|
-
console.error(`template.yaml not found at ${
|
|
19214
|
+
const templateDir = path26.join(resolveTemplatesDir(gitRoot), slug);
|
|
19215
|
+
const manifestPath = path26.join(templateDir, "template.yaml");
|
|
19216
|
+
if (!fs20.existsSync(manifestPath)) {
|
|
19217
|
+
console.error(`template.yaml not found at ${path26.relative(gitRoot, manifestPath)}`);
|
|
19124
19218
|
process.exit(1);
|
|
19125
19219
|
}
|
|
19126
19220
|
let manifest;
|
|
19127
19221
|
try {
|
|
19128
|
-
manifest = templateYamlSchema2.parse(yaml10.load(
|
|
19222
|
+
manifest = templateYamlSchema2.parse(yaml10.load(fs20.readFileSync(manifestPath, "utf-8")));
|
|
19129
19223
|
} catch (err) {
|
|
19130
19224
|
console.error(`Invalid template.yaml: ${err instanceof Error ? err.message : String(err)}`);
|
|
19131
19225
|
process.exit(1);
|
|
@@ -19155,20 +19249,20 @@ async function runTemplatePush(positional) {
|
|
|
19155
19249
|
const wayaiEntry = manifest.wayai.locales[locale];
|
|
19156
19250
|
let wayaiFiles;
|
|
19157
19251
|
if (wayaiEntry) {
|
|
19158
|
-
const sliceDir =
|
|
19159
|
-
if (!
|
|
19252
|
+
const sliceDir = path26.resolve(templateDir, wayaiEntry.source);
|
|
19253
|
+
if (!fs20.existsSync(sliceDir)) {
|
|
19160
19254
|
console.error(`wayai source not found for ${locale}: ${wayaiEntry.source} (resolved ${sliceDir})`);
|
|
19161
19255
|
process.exit(1);
|
|
19162
19256
|
}
|
|
19163
19257
|
if (!isInsideTemplateDir(sliceDir, templateDir)) {
|
|
19164
19258
|
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 ${
|
|
19259
|
+
`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
19260
|
);
|
|
19167
19261
|
}
|
|
19168
19262
|
wayaiFiles = readDirToFileMap(sliceDir);
|
|
19169
19263
|
}
|
|
19170
|
-
const readmePath =
|
|
19171
|
-
const readmeMarkdown =
|
|
19264
|
+
const readmePath = path26.join(templateDir, `README.${locale}.md`);
|
|
19265
|
+
const readmeMarkdown = fs20.existsSync(readmePath) ? fs20.readFileSync(readmePath, "utf-8") : "";
|
|
19172
19266
|
locales[locale] = {
|
|
19173
19267
|
readmeMarkdown,
|
|
19174
19268
|
...wayaiFiles && { wayaiFiles },
|
|
@@ -19179,9 +19273,9 @@ async function runTemplatePush(positional) {
|
|
|
19179
19273
|
}
|
|
19180
19274
|
let hero;
|
|
19181
19275
|
if (manifest.hero) {
|
|
19182
|
-
const heroPath =
|
|
19183
|
-
if (
|
|
19184
|
-
hero = { filename:
|
|
19276
|
+
const heroPath = path26.resolve(templateDir, manifest.hero);
|
|
19277
|
+
if (fs20.existsSync(heroPath)) {
|
|
19278
|
+
hero = { filename: path26.basename(heroPath), dataBase64: fs20.readFileSync(heroPath).toString("base64") };
|
|
19185
19279
|
} else {
|
|
19186
19280
|
console.error(`Warning: hero not found at ${manifest.hero}; skipping.`);
|
|
19187
19281
|
}
|
|
@@ -19207,7 +19301,7 @@ async function runTemplatePush(positional) {
|
|
|
19207
19301
|
}
|
|
19208
19302
|
}
|
|
19209
19303
|
function isInsideTemplateDir(dest, templateDir) {
|
|
19210
|
-
return dest === templateDir || dest.startsWith(templateDir +
|
|
19304
|
+
return dest === templateDir || dest.startsWith(templateDir + path26.sep);
|
|
19211
19305
|
}
|
|
19212
19306
|
async function runTemplateFreeze(positional, flagArgs) {
|
|
19213
19307
|
const slug = positional[0];
|
|
@@ -19268,7 +19362,7 @@ async function runTemplateFreeze(positional, flagArgs) {
|
|
|
19268
19362
|
process.exit(1);
|
|
19269
19363
|
}
|
|
19270
19364
|
const entry = manifest.wayai.locales[targetLocale];
|
|
19271
|
-
const dest =
|
|
19365
|
+
const dest = path26.resolve(templateDir, entry.source);
|
|
19272
19366
|
if (!isInsideTemplateDir(dest, templateDir) || dest === templateDir) {
|
|
19273
19367
|
console.error(
|
|
19274
19368
|
`source for "${targetLocale}" must be a committed path inside ${slug}/ (e.g. "./${targetLocale}/slice"), but resolved to:
|
|
@@ -19287,7 +19381,7 @@ Set it to a subdir of the template folder and re-run freeze.`
|
|
|
19287
19381
|
const hubs = scanWorkspaceHubs(hubsDir);
|
|
19288
19382
|
if (hubs.length) {
|
|
19289
19383
|
console.error("Available hubs:");
|
|
19290
|
-
for (const h of hubs) console.error(` ${
|
|
19384
|
+
for (const h of hubs) console.error(` ${path26.basename(h.hubFolder)} (${h.hubId})`);
|
|
19291
19385
|
}
|
|
19292
19386
|
console.error(`
|
|
19293
19387
|
Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`);
|
|
@@ -19295,12 +19389,12 @@ Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`
|
|
|
19295
19389
|
}
|
|
19296
19390
|
const liveFiles = readDirToFileMap(hubFolder);
|
|
19297
19391
|
if (Object.keys(liveFiles).length === 0) {
|
|
19298
|
-
console.error(`Source hub folder has no files to freeze: ${
|
|
19392
|
+
console.error(`Source hub folder has no files to freeze: ${path26.relative(gitRoot, hubFolder)}`);
|
|
19299
19393
|
process.exit(1);
|
|
19300
19394
|
}
|
|
19301
19395
|
const sanitized = sanitizeWayaiSliceFiles(liveFiles);
|
|
19302
|
-
const relDest =
|
|
19303
|
-
const relSrc =
|
|
19396
|
+
const relDest = path26.relative(gitRoot, dest);
|
|
19397
|
+
const relSrc = path26.relative(gitRoot, hubFolder);
|
|
19304
19398
|
if (dryRun) {
|
|
19305
19399
|
const existing = new Set(listDirRelFiles(dest));
|
|
19306
19400
|
const nextKeys = new Set(Object.keys(sanitized));
|
|
@@ -19360,7 +19454,7 @@ async function runTemplatePull2(positional, flagArgs) {
|
|
|
19360
19454
|
console.log(JSON.stringify(detail, null, 2));
|
|
19361
19455
|
return;
|
|
19362
19456
|
}
|
|
19363
|
-
const target = outDir ?
|
|
19457
|
+
const target = outDir ? path26.resolve(outDir) : path26.join(process.cwd(), "template-store-pull", slug);
|
|
19364
19458
|
const written = writeFileMap(target, detail.files);
|
|
19365
19459
|
console.log(`Pulled "${slug}" from the store \u2192 ${target} (${written.length} file${written.length === 1 ? "" : "s"}).`);
|
|
19366
19460
|
const uses = detail.uses ?? [];
|
|
@@ -19383,13 +19477,13 @@ async function runSkillInstall(positional) {
|
|
|
19383
19477
|
throw err;
|
|
19384
19478
|
}
|
|
19385
19479
|
const root = findGitRoot() ?? process.cwd();
|
|
19386
|
-
const present = HARNESS_SKILL_DIRS.filter((dir) =>
|
|
19480
|
+
const present = HARNESS_SKILL_DIRS.filter((dir) => fs20.existsSync(path26.join(root, dir)));
|
|
19387
19481
|
const targets = present.length > 0 ? present : HARNESS_SKILL_DIRS;
|
|
19388
19482
|
const fileCount = Object.keys(res.files).length;
|
|
19389
19483
|
const relDirs = targets.map((harness) => {
|
|
19390
|
-
const targetDir =
|
|
19484
|
+
const targetDir = path26.join(root, harness, "skills", name);
|
|
19391
19485
|
writeFileMap(targetDir, res.files);
|
|
19392
|
-
return `${
|
|
19486
|
+
return `${path26.relative(root, targetDir)}/`;
|
|
19393
19487
|
});
|
|
19394
19488
|
console.log(`Installed skill "${name}" (${fileCount} file${fileCount === 1 ? "" : "s"}) \u2192 ${relDirs.join(", ")}`);
|
|
19395
19489
|
console.log("Reload your agent (e.g. restart Claude Code) to pick up the skill.");
|
|
@@ -20129,7 +20223,7 @@ Usage:
|
|
|
20129
20223
|
|
|
20130
20224
|
Sources:
|
|
20131
20225
|
do Live DO SQLite (existing conversation, hub config, etc.).
|
|
20132
|
-
analytics ClickHouse projections (conversation,
|
|
20226
|
+
analytics ClickHouse projections (conversation, schedule_event).
|
|
20133
20227
|
archive R2 archive blob \u2014 canonical content for ended conversations after DO cleanup.
|
|
20134
20228
|
observability R2 LLM observability \u2014 per-message OTel GenAI records (prompts, completions,
|
|
20135
20229
|
tool calls, tokens, latency). Default lists all records for the conversation;
|
|
@@ -20179,7 +20273,6 @@ Entity id forms (do):
|
|
|
20179
20273
|
Examples:
|
|
20180
20274
|
wayai admin do tables hub 018fab...
|
|
20181
20275
|
wayai admin do read conversation <conv-id> message --limit 5 --json
|
|
20182
|
-
wayai admin analytics read message --conversation-id <conv-id>
|
|
20183
20276
|
wayai admin analytics read conversation --conversation-id <conv-id>
|
|
20184
20277
|
wayai admin archive <hub-id> <conv-id>
|
|
20185
20278
|
wayai admin archive <hub-id> <conv-id> --message-id <msg-id> --json
|
|
@@ -20668,7 +20761,7 @@ var init_update = __esm({
|
|
|
20668
20761
|
init_sentry();
|
|
20669
20762
|
import { readFileSync as readFileSync18 } from "fs";
|
|
20670
20763
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
20671
|
-
import { dirname as dirname9, join as
|
|
20764
|
+
import { dirname as dirname9, join as join25 } from "path";
|
|
20672
20765
|
|
|
20673
20766
|
// src/lib/errors.ts
|
|
20674
20767
|
init_api_client();
|
|
@@ -20848,7 +20941,7 @@ Run \`wayai admin skill install\` to update.`);
|
|
|
20848
20941
|
|
|
20849
20942
|
// src/index.ts
|
|
20850
20943
|
var __dirname = dirname9(fileURLToPath2(import.meta.url));
|
|
20851
|
-
var pkg = JSON.parse(readFileSync18(
|
|
20944
|
+
var pkg = JSON.parse(readFileSync18(join25(__dirname, "..", "package.json"), "utf-8"));
|
|
20852
20945
|
var [, , command, ...args] = process.argv;
|
|
20853
20946
|
var isBackgroundRefresh = command === REFRESH_COMMAND;
|
|
20854
20947
|
if (!isBackgroundRefresh) initSentry(command, pkg.version);
|