@wayai/cli 0.3.150 → 0.3.152
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 +1216 -796
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -447,11 +447,11 @@ function captureException2(error, context) {
|
|
|
447
447
|
Sentry.captureException(error);
|
|
448
448
|
});
|
|
449
449
|
}
|
|
450
|
-
function addApiBreadcrumb(method,
|
|
450
|
+
function addApiBreadcrumb(method, path35) {
|
|
451
451
|
if (!initialized) return;
|
|
452
452
|
Sentry.addBreadcrumb({
|
|
453
453
|
category: "http",
|
|
454
|
-
message: `${method} ${
|
|
454
|
+
message: `${method} ${path35}`,
|
|
455
455
|
level: "info"
|
|
456
456
|
});
|
|
457
457
|
}
|
|
@@ -905,8 +905,8 @@ var init_parseUtil = __esm({
|
|
|
905
905
|
init_errors();
|
|
906
906
|
init_en();
|
|
907
907
|
makeIssue = (params) => {
|
|
908
|
-
const { data, path:
|
|
909
|
-
const fullPath = [...
|
|
908
|
+
const { data, path: path35, errorMaps, issueData } = params;
|
|
909
|
+
const fullPath = [...path35, ...issueData.path || []];
|
|
910
910
|
const fullIssue = {
|
|
911
911
|
...issueData,
|
|
912
912
|
path: fullPath
|
|
@@ -1217,11 +1217,11 @@ var init_types = __esm({
|
|
|
1217
1217
|
init_parseUtil();
|
|
1218
1218
|
init_util();
|
|
1219
1219
|
ParseInputLazyPath = class {
|
|
1220
|
-
constructor(parent, value,
|
|
1220
|
+
constructor(parent, value, path35, key) {
|
|
1221
1221
|
this._cachedPath = [];
|
|
1222
1222
|
this.parent = parent;
|
|
1223
1223
|
this.data = value;
|
|
1224
|
-
this._path =
|
|
1224
|
+
this._path = path35;
|
|
1225
1225
|
this._key = key;
|
|
1226
1226
|
}
|
|
1227
1227
|
get path() {
|
|
@@ -4634,12 +4634,12 @@ function validateFollowupLinks(followups, label, ctx) {
|
|
|
4634
4634
|
const linkTargets = /* @__PURE__ */ new Set();
|
|
4635
4635
|
followups.forEach((followup, i) => {
|
|
4636
4636
|
const ref = followup?.after_followup_id;
|
|
4637
|
-
const
|
|
4637
|
+
const path35 = ["followups", i, "after_followup_id"];
|
|
4638
4638
|
if (followup?.type !== "inactivity_after_before_event") {
|
|
4639
4639
|
if (ref !== void 0) {
|
|
4640
4640
|
ctx.addIssue({
|
|
4641
4641
|
code: external_exports.ZodIssueCode.custom,
|
|
4642
|
-
path:
|
|
4642
|
+
path: path35,
|
|
4643
4643
|
message: `kanban status ${label}: after_followup_id is only valid on inactivity_after_before_event followups (this one is ${followup?.type})`
|
|
4644
4644
|
});
|
|
4645
4645
|
}
|
|
@@ -4648,7 +4648,7 @@ function validateFollowupLinks(followups, label, ctx) {
|
|
|
4648
4648
|
if (ref === void 0) {
|
|
4649
4649
|
ctx.addIssue({
|
|
4650
4650
|
code: external_exports.ZodIssueCode.custom,
|
|
4651
|
-
path:
|
|
4651
|
+
path: path35,
|
|
4652
4652
|
message: `kanban status ${label}: inactivity_after_before_event requires after_followup_id naming the id of a before_event followup in the same status`
|
|
4653
4653
|
});
|
|
4654
4654
|
return;
|
|
@@ -4658,7 +4658,7 @@ function validateFollowupLinks(followups, label, ctx) {
|
|
|
4658
4658
|
if (matches.length > 1) {
|
|
4659
4659
|
ctx.addIssue({
|
|
4660
4660
|
code: external_exports.ZodIssueCode.custom,
|
|
4661
|
-
path:
|
|
4661
|
+
path: path35,
|
|
4662
4662
|
message: `kanban status ${label}: after_followup_id "${ref}" matches ${matches.length} followups \u2014 a link must name exactly one`
|
|
4663
4663
|
});
|
|
4664
4664
|
return;
|
|
@@ -4670,7 +4670,7 @@ function validateFollowupLinks(followups, label, ctx) {
|
|
|
4670
4670
|
);
|
|
4671
4671
|
ctx.addIssue({
|
|
4672
4672
|
code: external_exports.ZodIssueCode.custom,
|
|
4673
|
-
path:
|
|
4673
|
+
path: path35,
|
|
4674
4674
|
message: hasIdlessBeforeEvent ? `kanban status ${label}: after_followup_id "${ref}" matches no followup \u2014 a link target must declare an explicit id, and this status has before_event followups without one` : `kanban status ${label}: after_followup_id "${ref}" matches no followup in this status`
|
|
4675
4675
|
});
|
|
4676
4676
|
return;
|
|
@@ -4678,7 +4678,7 @@ function validateFollowupLinks(followups, label, ctx) {
|
|
|
4678
4678
|
if (target.type !== "before_event") {
|
|
4679
4679
|
ctx.addIssue({
|
|
4680
4680
|
code: external_exports.ZodIssueCode.custom,
|
|
4681
|
-
path:
|
|
4681
|
+
path: path35,
|
|
4682
4682
|
message: `kanban status ${label}: after_followup_id "${ref}" points at a ${target.type} followup \u2014 only before_event followups can anchor a chain`
|
|
4683
4683
|
});
|
|
4684
4684
|
}
|
|
@@ -4754,12 +4754,12 @@ function typeMatches(typeField, allowed) {
|
|
|
4754
4754
|
if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
|
|
4755
4755
|
return false;
|
|
4756
4756
|
}
|
|
4757
|
-
function validateSchema(schema,
|
|
4757
|
+
function validateSchema(schema, path35, errors, opts = {}) {
|
|
4758
4758
|
if (typeof schema === "boolean") return;
|
|
4759
4759
|
const depth = opts.depth ?? 0;
|
|
4760
4760
|
if (depth > MAX_SCHEMA_DEPTH) {
|
|
4761
4761
|
errors.push({
|
|
4762
|
-
path:
|
|
4762
|
+
path: path35 || "<root>",
|
|
4763
4763
|
message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH} levels`,
|
|
4764
4764
|
suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
|
|
4765
4765
|
});
|
|
@@ -4767,7 +4767,7 @@ function validateSchema(schema, path36, errors, opts = {}) {
|
|
|
4767
4767
|
}
|
|
4768
4768
|
if (!isRecord(schema)) {
|
|
4769
4769
|
errors.push({
|
|
4770
|
-
path:
|
|
4770
|
+
path: path35,
|
|
4771
4771
|
message: `expected object, got ${schema === null ? "null" : typeof schema}`
|
|
4772
4772
|
});
|
|
4773
4773
|
return;
|
|
@@ -4775,14 +4775,14 @@ function validateSchema(schema, path36, errors, opts = {}) {
|
|
|
4775
4775
|
if (opts.isRoot) {
|
|
4776
4776
|
if ("type" in schema && schema.type !== "object") {
|
|
4777
4777
|
errors.push({
|
|
4778
|
-
path:
|
|
4778
|
+
path: path35 ? `${path35}.type` : "type",
|
|
4779
4779
|
message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
|
|
4780
4780
|
suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
|
|
4781
4781
|
});
|
|
4782
4782
|
}
|
|
4783
4783
|
} else if ("type" in schema && !typeMatches(schema.type, ALLOWED_TYPES)) {
|
|
4784
4784
|
errors.push({
|
|
4785
|
-
path: `${
|
|
4785
|
+
path: `${path35}.type`,
|
|
4786
4786
|
message: `type must be one of ${[...ALLOWED_TYPES].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
|
|
4787
4787
|
});
|
|
4788
4788
|
}
|
|
@@ -4792,25 +4792,25 @@ function validateSchema(schema, path36, errors, opts = {}) {
|
|
|
4792
4792
|
const isPlaceholder = PLACEHOLDER_TOKENS.includes(e);
|
|
4793
4793
|
const isOutcomePlaceholder = e === "[KANBAN_OUTCOME_VALUES]";
|
|
4794
4794
|
errors.push({
|
|
4795
|
-
path: `${
|
|
4795
|
+
path: `${path35}.enum`,
|
|
4796
4796
|
message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
|
|
4797
4797
|
suggestion: isOutcomePlaceholder ? "Declare `outcomes` on the hub's terminal kanban status so the platform can render the placeholder into a valid array; with none configured the platform drops the parameter instead." : 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"]`.'
|
|
4798
4798
|
});
|
|
4799
4799
|
} else if (!Array.isArray(e)) {
|
|
4800
4800
|
errors.push({
|
|
4801
|
-
path: `${
|
|
4801
|
+
path: `${path35}.enum`,
|
|
4802
4802
|
message: `enum must be a non-empty array of primitives, got ${typeof e}`
|
|
4803
4803
|
});
|
|
4804
4804
|
} else if (e.length === 0) {
|
|
4805
4805
|
errors.push({
|
|
4806
|
-
path: `${
|
|
4806
|
+
path: `${path35}.enum`,
|
|
4807
4807
|
message: "enum must not be empty"
|
|
4808
4808
|
});
|
|
4809
4809
|
} else {
|
|
4810
4810
|
for (let i = 0; i < e.length; i++) {
|
|
4811
4811
|
if (!isPrimitive(e[i])) {
|
|
4812
4812
|
errors.push({
|
|
4813
|
-
path: `${
|
|
4813
|
+
path: `${path35}.enum[${i}]`,
|
|
4814
4814
|
message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
|
|
4815
4815
|
});
|
|
4816
4816
|
}
|
|
@@ -4820,7 +4820,7 @@ function validateSchema(schema, path36, errors, opts = {}) {
|
|
|
4820
4820
|
for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
|
|
4821
4821
|
if (key in schema && typeof schema[key] === "boolean") {
|
|
4822
4822
|
errors.push({
|
|
4823
|
-
path: `${
|
|
4823
|
+
path: `${path35}.${key}`,
|
|
4824
4824
|
message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
|
|
4825
4825
|
suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
|
|
4826
4826
|
});
|
|
@@ -4829,45 +4829,45 @@ function validateSchema(schema, path36, errors, opts = {}) {
|
|
|
4829
4829
|
if ("properties" in schema) {
|
|
4830
4830
|
if (!isRecord(schema.properties)) {
|
|
4831
4831
|
errors.push({
|
|
4832
|
-
path: `${
|
|
4832
|
+
path: `${path35}.properties`,
|
|
4833
4833
|
message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
|
|
4834
4834
|
});
|
|
4835
4835
|
} else {
|
|
4836
4836
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
4837
|
-
validateSchema(propSchema, `${
|
|
4837
|
+
validateSchema(propSchema, `${path35}.properties.${propName}`, errors, { depth: depth + 1 });
|
|
4838
4838
|
}
|
|
4839
4839
|
}
|
|
4840
4840
|
}
|
|
4841
4841
|
if (schemaTypeIncludes(schema, "array") && "items" in schema) {
|
|
4842
4842
|
if (Array.isArray(schema.items)) {
|
|
4843
|
-
schema.items.forEach((sub, i) => validateSchema(sub, `${
|
|
4843
|
+
schema.items.forEach((sub, i) => validateSchema(sub, `${path35}.items[${i}]`, errors, { depth: depth + 1 }));
|
|
4844
4844
|
} else {
|
|
4845
|
-
validateSchema(schema.items, `${
|
|
4845
|
+
validateSchema(schema.items, `${path35}.items`, errors, { depth: depth + 1 });
|
|
4846
4846
|
}
|
|
4847
4847
|
}
|
|
4848
4848
|
for (const key of SUBSCHEMA_OBJECT_KEYWORDS) {
|
|
4849
4849
|
if (key in schema && isRecord(schema[key])) {
|
|
4850
|
-
validateSchema(schema[key], `${
|
|
4850
|
+
validateSchema(schema[key], `${path35}.${key}`, errors, { depth: depth + 1 });
|
|
4851
4851
|
}
|
|
4852
4852
|
}
|
|
4853
4853
|
for (const key of SUBSCHEMA_LIST_KEYWORDS) {
|
|
4854
4854
|
const list = schema[key];
|
|
4855
4855
|
if (Array.isArray(list)) {
|
|
4856
|
-
list.forEach((sub, i) => validateSchema(sub, `${
|
|
4856
|
+
list.forEach((sub, i) => validateSchema(sub, `${path35}.${key}[${i}]`, errors, { depth: depth + 1 }));
|
|
4857
4857
|
}
|
|
4858
4858
|
}
|
|
4859
4859
|
for (const key of SUBSCHEMA_MAP_KEYWORDS) {
|
|
4860
4860
|
const map = schema[key];
|
|
4861
4861
|
if (isRecord(map)) {
|
|
4862
4862
|
for (const [name, sub] of Object.entries(map)) {
|
|
4863
|
-
validateSchema(sub, `${
|
|
4863
|
+
validateSchema(sub, `${path35}.${key}.${name}`, errors, { depth: depth + 1 });
|
|
4864
4864
|
}
|
|
4865
4865
|
}
|
|
4866
4866
|
}
|
|
4867
4867
|
const reportedPaths = new Set(errors.map((e) => e.path));
|
|
4868
4868
|
for (const [k, v] of Object.entries(schema)) {
|
|
4869
4869
|
if (typeof v !== "string") continue;
|
|
4870
|
-
const fieldPath = `${
|
|
4870
|
+
const fieldPath = `${path35}.${k}`;
|
|
4871
4871
|
if (reportedPaths.has(fieldPath)) continue;
|
|
4872
4872
|
for (const token of PLACEHOLDER_TOKENS) {
|
|
4873
4873
|
if (v === token) {
|
|
@@ -5012,8 +5012,8 @@ function evalInitialStateError(input) {
|
|
|
5012
5012
|
const parsed = evalInitialStateEntry.safeParse(entries[i]);
|
|
5013
5013
|
if (!parsed.success) {
|
|
5014
5014
|
const issue = parsed.error.issues[0];
|
|
5015
|
-
const
|
|
5016
|
-
return `initial_state[${i}].${
|
|
5015
|
+
const path35 = issue?.path.join(".") || "?";
|
|
5016
|
+
return `initial_state[${i}].${path35} is invalid: ${issue?.message ?? "malformed"}`;
|
|
5017
5017
|
}
|
|
5018
5018
|
if (seenSlugs.has(parsed.data.slug)) {
|
|
5019
5019
|
return `initial_state[${i}].slug "${parsed.data.slug}" is declared more than once`;
|
|
@@ -5201,10 +5201,10 @@ function refineHubAsCodeEvals(config, ctx) {
|
|
|
5201
5201
|
function refineHubAsCodeEvalAttachments(config, ctx) {
|
|
5202
5202
|
const cfg = config;
|
|
5203
5203
|
const referencedHashes = /* @__PURE__ */ new Set();
|
|
5204
|
-
const addTurnIssue = (
|
|
5204
|
+
const addTurnIssue = (path35, turn, name) => {
|
|
5205
5205
|
const error = evalTurnAttachmentsError(turn);
|
|
5206
5206
|
if (error) {
|
|
5207
|
-
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path:
|
|
5207
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: path35, message: `${name}: ${error}` });
|
|
5208
5208
|
return;
|
|
5209
5209
|
}
|
|
5210
5210
|
for (const hash of collectTurnAttachmentHashes(turn)) referencedHashes.add(hash);
|
|
@@ -5350,11 +5350,11 @@ function refineHubAsCodeDelegation(config, ctx) {
|
|
|
5350
5350
|
}
|
|
5351
5351
|
}
|
|
5352
5352
|
if (del.context_boundary === void 0) return;
|
|
5353
|
-
const
|
|
5353
|
+
const path35 = ["agents", agentIndex, "tools", "delegation", delIndex, "context_boundary"];
|
|
5354
5354
|
if (del.type !== "hub") {
|
|
5355
5355
|
ctx.addIssue({
|
|
5356
5356
|
code: external_exports.ZodIssueCode.custom,
|
|
5357
|
-
path:
|
|
5357
|
+
path: path35,
|
|
5358
5358
|
message: `context_boundary applies only to \`type: hub\` delegations (got type "${String(del.type)}")`
|
|
5359
5359
|
});
|
|
5360
5360
|
return;
|
|
@@ -5362,7 +5362,7 @@ function refineHubAsCodeDelegation(config, ctx) {
|
|
|
5362
5362
|
if (!CONTEXT_BOUNDARIES.includes(del.context_boundary)) {
|
|
5363
5363
|
ctx.addIssue({
|
|
5364
5364
|
code: external_exports.ZodIssueCode.custom,
|
|
5365
|
-
path:
|
|
5365
|
+
path: path35,
|
|
5366
5366
|
message: `context_boundary must be one of: ${CONTEXT_BOUNDARIES.join(", ")}`
|
|
5367
5367
|
});
|
|
5368
5368
|
}
|
|
@@ -8915,10 +8915,10 @@ function toDataProxyPath(v1Path) {
|
|
|
8915
8915
|
}
|
|
8916
8916
|
return `${DATA_PROXY_PREFIX}${v1Path.slice(REKOR_V1_PREFIX.length)}`;
|
|
8917
8917
|
}
|
|
8918
|
-
function withOrgSelector(
|
|
8919
|
-
if (!orgId) return
|
|
8920
|
-
const separator =
|
|
8921
|
-
return `${
|
|
8918
|
+
function withOrgSelector(path35, orgId) {
|
|
8919
|
+
if (!orgId) return path35;
|
|
8920
|
+
const separator = path35.includes("?") ? "&" : "?";
|
|
8921
|
+
return `${path35}${separator}${DATA_PROXY_ORG_QUERY_PARAM}=${encodeURIComponent(orgId)}`;
|
|
8922
8922
|
}
|
|
8923
8923
|
function dataErrorMessage(err) {
|
|
8924
8924
|
if (!(err instanceof ApiError)) return null;
|
|
@@ -8942,7 +8942,7 @@ var init_api_client = __esm({
|
|
|
8942
8942
|
init_sentry();
|
|
8943
8943
|
init_mask_secrets();
|
|
8944
8944
|
RETRYABLE_BACKOFF_MS = [500, 1e3, 2e3];
|
|
8945
|
-
delay = (ms) => new Promise((
|
|
8945
|
+
delay = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
8946
8946
|
ApiError = class extends Error {
|
|
8947
8947
|
status;
|
|
8948
8948
|
body;
|
|
@@ -8952,13 +8952,13 @@ var init_api_client = __esm({
|
|
|
8952
8952
|
* telling them apart by body shape misreads one for the other.
|
|
8953
8953
|
*/
|
|
8954
8954
|
path;
|
|
8955
|
-
constructor(method,
|
|
8955
|
+
constructor(method, path35, status, body) {
|
|
8956
8956
|
const safeBody = maskSecretsInMessage(body);
|
|
8957
|
-
super(`API request failed: ${method} ${
|
|
8957
|
+
super(`API request failed: ${method} ${path35} (${status}): ${safeBody}`);
|
|
8958
8958
|
this.name = "ApiError";
|
|
8959
8959
|
this.status = status;
|
|
8960
8960
|
this.body = safeBody;
|
|
8961
|
-
this.path =
|
|
8961
|
+
this.path = path35;
|
|
8962
8962
|
}
|
|
8963
8963
|
/** True when the status code is a 4xx client error (expected user-facing condition, not a bug). */
|
|
8964
8964
|
get isExpected() {
|
|
@@ -9060,8 +9060,8 @@ var init_api_client = __esm({
|
|
|
9060
9060
|
...opts?.check && { check: true }
|
|
9061
9061
|
});
|
|
9062
9062
|
}
|
|
9063
|
-
async lookup(
|
|
9064
|
-
const params = new URLSearchParams({ path:
|
|
9063
|
+
async lookup(path35, opts) {
|
|
9064
|
+
const params = new URLSearchParams({ path: path35 });
|
|
9065
9065
|
if (opts?.organizationId) params.set("organization_id", opts.organizationId);
|
|
9066
9066
|
return this.request("GET", `/api/ci/lookup?${params.toString()}`);
|
|
9067
9067
|
}
|
|
@@ -9504,9 +9504,9 @@ var init_api_client = __esm({
|
|
|
9504
9504
|
* sandbox for this conversation, or the blob was purged).
|
|
9505
9505
|
*/
|
|
9506
9506
|
async downloadArchiveSandboxFs(hubId, conversationId) {
|
|
9507
|
-
const
|
|
9508
|
-
addApiBreadcrumb("GET",
|
|
9509
|
-
const url = `${this.apiUrl}${
|
|
9507
|
+
const path35 = `/api/archive/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}/sandbox`;
|
|
9508
|
+
addApiBreadcrumb("GET", path35);
|
|
9509
|
+
const url = `${this.apiUrl}${path35}`;
|
|
9510
9510
|
let response = await this.send(url, "GET");
|
|
9511
9511
|
if (response.status === 401 && this.onUnauthorized) {
|
|
9512
9512
|
let refreshed;
|
|
@@ -9520,7 +9520,7 @@ var init_api_client = __esm({
|
|
|
9520
9520
|
}
|
|
9521
9521
|
}
|
|
9522
9522
|
if (!response.ok) {
|
|
9523
|
-
throw new ApiError("GET",
|
|
9523
|
+
throw new ApiError("GET", path35, response.status, await response.text());
|
|
9524
9524
|
}
|
|
9525
9525
|
return new Uint8Array(await response.arrayBuffer());
|
|
9526
9526
|
}
|
|
@@ -9560,9 +9560,9 @@ var init_api_client = __esm({
|
|
|
9560
9560
|
`/api/admin/data-explorer/debug/observability/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}${qs}`
|
|
9561
9561
|
);
|
|
9562
9562
|
}
|
|
9563
|
-
async request(method,
|
|
9564
|
-
addApiBreadcrumb(method,
|
|
9565
|
-
const url = `${this.apiUrl}${
|
|
9563
|
+
async request(method, path35, body, extraHeaders, contentType) {
|
|
9564
|
+
addApiBreadcrumb(method, path35);
|
|
9565
|
+
const url = `${this.apiUrl}${path35}`;
|
|
9566
9566
|
let refreshedOn401 = false;
|
|
9567
9567
|
for (let retry = 0; ; retry++) {
|
|
9568
9568
|
let response = await this.send(url, method, body, extraHeaders, contentType);
|
|
@@ -9587,7 +9587,7 @@ var init_api_client = __esm({
|
|
|
9587
9587
|
await delay(RETRYABLE_BACKOFF_MS[retry]);
|
|
9588
9588
|
continue;
|
|
9589
9589
|
}
|
|
9590
|
-
throw new ApiError(method,
|
|
9590
|
+
throw new ApiError(method, path35, response.status, errorBody);
|
|
9591
9591
|
}
|
|
9592
9592
|
}
|
|
9593
9593
|
/**
|
|
@@ -9607,7 +9607,7 @@ var init_api_client = __esm({
|
|
|
9607
9607
|
* `dataErrorMessage` recovers the envelope's own message for display.
|
|
9608
9608
|
*
|
|
9609
9609
|
* `orgId` is the caller's org SELECTOR (the `--org` flag, else the repo's
|
|
9610
|
-
*
|
|
9610
|
+
* `wayai-ws/wayai.yaml`), not an authorization claim: the backend validates it against
|
|
9611
9611
|
* the caller's grants and attests only the validated result. A multi-org user
|
|
9612
9612
|
* needs it to pick; a single-org user can omit it.
|
|
9613
9613
|
*
|
|
@@ -9649,9 +9649,9 @@ var init_api_client = __esm({
|
|
|
9649
9649
|
* transient-retry loop — re-streaming a blob is not worth a cold-start probe.
|
|
9650
9650
|
*/
|
|
9651
9651
|
async dataDownload(v1Path, orgId) {
|
|
9652
|
-
const
|
|
9653
|
-
addApiBreadcrumb("GET",
|
|
9654
|
-
const url = `${this.apiUrl}${
|
|
9652
|
+
const path35 = withOrgSelector(toDataProxyPath(v1Path), orgId);
|
|
9653
|
+
addApiBreadcrumb("GET", path35);
|
|
9654
|
+
const url = `${this.apiUrl}${path35}`;
|
|
9655
9655
|
let response = await this.send(url, "GET");
|
|
9656
9656
|
if (response.status === 401 && this.onUnauthorized) {
|
|
9657
9657
|
let refreshed;
|
|
@@ -9665,7 +9665,7 @@ var init_api_client = __esm({
|
|
|
9665
9665
|
}
|
|
9666
9666
|
}
|
|
9667
9667
|
if (!response.ok) {
|
|
9668
|
-
throw new ApiError("GET",
|
|
9668
|
+
throw new ApiError("GET", path35, response.status, await response.text());
|
|
9669
9669
|
}
|
|
9670
9670
|
return {
|
|
9671
9671
|
bytes: new Uint8Array(await response.arrayBuffer()),
|
|
@@ -9817,12 +9817,12 @@ function validateFollowupLinks2(followups, label, ctx) {
|
|
|
9817
9817
|
const linkTargets = /* @__PURE__ */ new Set();
|
|
9818
9818
|
followups.forEach((followup, i) => {
|
|
9819
9819
|
const ref = followup?.after_followup_id;
|
|
9820
|
-
const
|
|
9820
|
+
const path35 = ["followups", i, "after_followup_id"];
|
|
9821
9821
|
if (followup?.type !== "inactivity_after_before_event") {
|
|
9822
9822
|
if (ref !== void 0) {
|
|
9823
9823
|
ctx.addIssue({
|
|
9824
9824
|
code: external_exports.ZodIssueCode.custom,
|
|
9825
|
-
path:
|
|
9825
|
+
path: path35,
|
|
9826
9826
|
message: `kanban status ${label}: after_followup_id is only valid on inactivity_after_before_event followups (this one is ${followup?.type})`
|
|
9827
9827
|
});
|
|
9828
9828
|
}
|
|
@@ -9831,7 +9831,7 @@ function validateFollowupLinks2(followups, label, ctx) {
|
|
|
9831
9831
|
if (ref === void 0) {
|
|
9832
9832
|
ctx.addIssue({
|
|
9833
9833
|
code: external_exports.ZodIssueCode.custom,
|
|
9834
|
-
path:
|
|
9834
|
+
path: path35,
|
|
9835
9835
|
message: `kanban status ${label}: inactivity_after_before_event requires after_followup_id naming the id of a before_event followup in the same status`
|
|
9836
9836
|
});
|
|
9837
9837
|
return;
|
|
@@ -9841,7 +9841,7 @@ function validateFollowupLinks2(followups, label, ctx) {
|
|
|
9841
9841
|
if (matches.length > 1) {
|
|
9842
9842
|
ctx.addIssue({
|
|
9843
9843
|
code: external_exports.ZodIssueCode.custom,
|
|
9844
|
-
path:
|
|
9844
|
+
path: path35,
|
|
9845
9845
|
message: `kanban status ${label}: after_followup_id "${ref}" matches ${matches.length} followups \u2014 a link must name exactly one`
|
|
9846
9846
|
});
|
|
9847
9847
|
return;
|
|
@@ -9853,7 +9853,7 @@ function validateFollowupLinks2(followups, label, ctx) {
|
|
|
9853
9853
|
);
|
|
9854
9854
|
ctx.addIssue({
|
|
9855
9855
|
code: external_exports.ZodIssueCode.custom,
|
|
9856
|
-
path:
|
|
9856
|
+
path: path35,
|
|
9857
9857
|
message: hasIdlessBeforeEvent ? `kanban status ${label}: after_followup_id "${ref}" matches no followup \u2014 a link target must declare an explicit id, and this status has before_event followups without one` : `kanban status ${label}: after_followup_id "${ref}" matches no followup in this status`
|
|
9858
9858
|
});
|
|
9859
9859
|
return;
|
|
@@ -9861,7 +9861,7 @@ function validateFollowupLinks2(followups, label, ctx) {
|
|
|
9861
9861
|
if (target.type !== "before_event") {
|
|
9862
9862
|
ctx.addIssue({
|
|
9863
9863
|
code: external_exports.ZodIssueCode.custom,
|
|
9864
|
-
path:
|
|
9864
|
+
path: path35,
|
|
9865
9865
|
message: `kanban status ${label}: after_followup_id "${ref}" points at a ${target.type} followup \u2014 only before_event followups can anchor a chain`
|
|
9866
9866
|
});
|
|
9867
9867
|
}
|
|
@@ -9937,12 +9937,12 @@ function typeMatches2(typeField, allowed) {
|
|
|
9937
9937
|
if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
|
|
9938
9938
|
return false;
|
|
9939
9939
|
}
|
|
9940
|
-
function validateSchema2(schema,
|
|
9940
|
+
function validateSchema2(schema, path35, errors, opts = {}) {
|
|
9941
9941
|
if (typeof schema === "boolean") return;
|
|
9942
9942
|
const depth = opts.depth ?? 0;
|
|
9943
9943
|
if (depth > MAX_SCHEMA_DEPTH2) {
|
|
9944
9944
|
errors.push({
|
|
9945
|
-
path:
|
|
9945
|
+
path: path35 || "<root>",
|
|
9946
9946
|
message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH2} levels`,
|
|
9947
9947
|
suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
|
|
9948
9948
|
});
|
|
@@ -9950,7 +9950,7 @@ function validateSchema2(schema, path36, errors, opts = {}) {
|
|
|
9950
9950
|
}
|
|
9951
9951
|
if (!isRecord2(schema)) {
|
|
9952
9952
|
errors.push({
|
|
9953
|
-
path:
|
|
9953
|
+
path: path35,
|
|
9954
9954
|
message: `expected object, got ${schema === null ? "null" : typeof schema}`
|
|
9955
9955
|
});
|
|
9956
9956
|
return;
|
|
@@ -9958,14 +9958,14 @@ function validateSchema2(schema, path36, errors, opts = {}) {
|
|
|
9958
9958
|
if (opts.isRoot) {
|
|
9959
9959
|
if ("type" in schema && schema.type !== "object") {
|
|
9960
9960
|
errors.push({
|
|
9961
|
-
path:
|
|
9961
|
+
path: path35 ? `${path35}.type` : "type",
|
|
9962
9962
|
message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
|
|
9963
9963
|
suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
|
|
9964
9964
|
});
|
|
9965
9965
|
}
|
|
9966
9966
|
} else if ("type" in schema && !typeMatches2(schema.type, ALLOWED_TYPES2)) {
|
|
9967
9967
|
errors.push({
|
|
9968
|
-
path: `${
|
|
9968
|
+
path: `${path35}.type`,
|
|
9969
9969
|
message: `type must be one of ${[...ALLOWED_TYPES2].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
|
|
9970
9970
|
});
|
|
9971
9971
|
}
|
|
@@ -9975,25 +9975,25 @@ function validateSchema2(schema, path36, errors, opts = {}) {
|
|
|
9975
9975
|
const isPlaceholder = PLACEHOLDER_TOKENS2.includes(e);
|
|
9976
9976
|
const isOutcomePlaceholder = e === "[KANBAN_OUTCOME_VALUES]";
|
|
9977
9977
|
errors.push({
|
|
9978
|
-
path: `${
|
|
9978
|
+
path: `${path35}.enum`,
|
|
9979
9979
|
message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
|
|
9980
9980
|
suggestion: isOutcomePlaceholder ? "Declare `outcomes` on the hub's terminal kanban status so the platform can render the placeholder into a valid array; with none configured the platform drops the parameter instead." : 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"]`.'
|
|
9981
9981
|
});
|
|
9982
9982
|
} else if (!Array.isArray(e)) {
|
|
9983
9983
|
errors.push({
|
|
9984
|
-
path: `${
|
|
9984
|
+
path: `${path35}.enum`,
|
|
9985
9985
|
message: `enum must be a non-empty array of primitives, got ${typeof e}`
|
|
9986
9986
|
});
|
|
9987
9987
|
} else if (e.length === 0) {
|
|
9988
9988
|
errors.push({
|
|
9989
|
-
path: `${
|
|
9989
|
+
path: `${path35}.enum`,
|
|
9990
9990
|
message: "enum must not be empty"
|
|
9991
9991
|
});
|
|
9992
9992
|
} else {
|
|
9993
9993
|
for (let i = 0; i < e.length; i++) {
|
|
9994
9994
|
if (!isPrimitive2(e[i])) {
|
|
9995
9995
|
errors.push({
|
|
9996
|
-
path: `${
|
|
9996
|
+
path: `${path35}.enum[${i}]`,
|
|
9997
9997
|
message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
|
|
9998
9998
|
});
|
|
9999
9999
|
}
|
|
@@ -10003,7 +10003,7 @@ function validateSchema2(schema, path36, errors, opts = {}) {
|
|
|
10003
10003
|
for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
|
|
10004
10004
|
if (key in schema && typeof schema[key] === "boolean") {
|
|
10005
10005
|
errors.push({
|
|
10006
|
-
path: `${
|
|
10006
|
+
path: `${path35}.${key}`,
|
|
10007
10007
|
message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
|
|
10008
10008
|
suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
|
|
10009
10009
|
});
|
|
@@ -10012,45 +10012,45 @@ function validateSchema2(schema, path36, errors, opts = {}) {
|
|
|
10012
10012
|
if ("properties" in schema) {
|
|
10013
10013
|
if (!isRecord2(schema.properties)) {
|
|
10014
10014
|
errors.push({
|
|
10015
|
-
path: `${
|
|
10015
|
+
path: `${path35}.properties`,
|
|
10016
10016
|
message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
|
|
10017
10017
|
});
|
|
10018
10018
|
} else {
|
|
10019
10019
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
10020
|
-
validateSchema2(propSchema, `${
|
|
10020
|
+
validateSchema2(propSchema, `${path35}.properties.${propName}`, errors, { depth: depth + 1 });
|
|
10021
10021
|
}
|
|
10022
10022
|
}
|
|
10023
10023
|
}
|
|
10024
10024
|
if (schemaTypeIncludes2(schema, "array") && "items" in schema) {
|
|
10025
10025
|
if (Array.isArray(schema.items)) {
|
|
10026
|
-
schema.items.forEach((sub, i) => validateSchema2(sub, `${
|
|
10026
|
+
schema.items.forEach((sub, i) => validateSchema2(sub, `${path35}.items[${i}]`, errors, { depth: depth + 1 }));
|
|
10027
10027
|
} else {
|
|
10028
|
-
validateSchema2(schema.items, `${
|
|
10028
|
+
validateSchema2(schema.items, `${path35}.items`, errors, { depth: depth + 1 });
|
|
10029
10029
|
}
|
|
10030
10030
|
}
|
|
10031
10031
|
for (const key of SUBSCHEMA_OBJECT_KEYWORDS2) {
|
|
10032
10032
|
if (key in schema && isRecord2(schema[key])) {
|
|
10033
|
-
validateSchema2(schema[key], `${
|
|
10033
|
+
validateSchema2(schema[key], `${path35}.${key}`, errors, { depth: depth + 1 });
|
|
10034
10034
|
}
|
|
10035
10035
|
}
|
|
10036
10036
|
for (const key of SUBSCHEMA_LIST_KEYWORDS2) {
|
|
10037
10037
|
const list = schema[key];
|
|
10038
10038
|
if (Array.isArray(list)) {
|
|
10039
|
-
list.forEach((sub, i) => validateSchema2(sub, `${
|
|
10039
|
+
list.forEach((sub, i) => validateSchema2(sub, `${path35}.${key}[${i}]`, errors, { depth: depth + 1 }));
|
|
10040
10040
|
}
|
|
10041
10041
|
}
|
|
10042
10042
|
for (const key of SUBSCHEMA_MAP_KEYWORDS2) {
|
|
10043
10043
|
const map = schema[key];
|
|
10044
10044
|
if (isRecord2(map)) {
|
|
10045
10045
|
for (const [name, sub] of Object.entries(map)) {
|
|
10046
|
-
validateSchema2(sub, `${
|
|
10046
|
+
validateSchema2(sub, `${path35}.${key}.${name}`, errors, { depth: depth + 1 });
|
|
10047
10047
|
}
|
|
10048
10048
|
}
|
|
10049
10049
|
}
|
|
10050
10050
|
const reportedPaths = new Set(errors.map((e) => e.path));
|
|
10051
10051
|
for (const [k, v] of Object.entries(schema)) {
|
|
10052
10052
|
if (typeof v !== "string") continue;
|
|
10053
|
-
const fieldPath = `${
|
|
10053
|
+
const fieldPath = `${path35}.${k}`;
|
|
10054
10054
|
if (reportedPaths.has(fieldPath)) continue;
|
|
10055
10055
|
for (const token of PLACEHOLDER_TOKENS2) {
|
|
10056
10056
|
if (v === token) {
|
|
@@ -10195,8 +10195,8 @@ function evalInitialStateError2(input) {
|
|
|
10195
10195
|
const parsed = evalInitialStateEntry2.safeParse(entries[i]);
|
|
10196
10196
|
if (!parsed.success) {
|
|
10197
10197
|
const issue = parsed.error.issues[0];
|
|
10198
|
-
const
|
|
10199
|
-
return `initial_state[${i}].${
|
|
10198
|
+
const path35 = issue?.path.join(".") || "?";
|
|
10199
|
+
return `initial_state[${i}].${path35} is invalid: ${issue?.message ?? "malformed"}`;
|
|
10200
10200
|
}
|
|
10201
10201
|
if (seenSlugs.has(parsed.data.slug)) {
|
|
10202
10202
|
return `initial_state[${i}].slug "${parsed.data.slug}" is declared more than once`;
|
|
@@ -10401,10 +10401,10 @@ function refineHubAsCodeEvals2(config, ctx) {
|
|
|
10401
10401
|
function refineHubAsCodeEvalAttachments2(config, ctx) {
|
|
10402
10402
|
const cfg = config;
|
|
10403
10403
|
const referencedHashes = /* @__PURE__ */ new Set();
|
|
10404
|
-
const addTurnIssue = (
|
|
10404
|
+
const addTurnIssue = (path35, turn, name) => {
|
|
10405
10405
|
const error = evalTurnAttachmentsError2(turn);
|
|
10406
10406
|
if (error) {
|
|
10407
|
-
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path:
|
|
10407
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: path35, message: `${name}: ${error}` });
|
|
10408
10408
|
return;
|
|
10409
10409
|
}
|
|
10410
10410
|
for (const hash of collectTurnAttachmentHashes2(turn)) referencedHashes.add(hash);
|
|
@@ -10550,11 +10550,11 @@ function refineHubAsCodeDelegation2(config, ctx) {
|
|
|
10550
10550
|
}
|
|
10551
10551
|
}
|
|
10552
10552
|
if (del.context_boundary === void 0) return;
|
|
10553
|
-
const
|
|
10553
|
+
const path35 = ["agents", agentIndex, "tools", "delegation", delIndex, "context_boundary"];
|
|
10554
10554
|
if (del.type !== "hub") {
|
|
10555
10555
|
ctx.addIssue({
|
|
10556
10556
|
code: external_exports.ZodIssueCode.custom,
|
|
10557
|
-
path:
|
|
10557
|
+
path: path35,
|
|
10558
10558
|
message: `context_boundary applies only to \`type: hub\` delegations (got type "${String(del.type)}")`
|
|
10559
10559
|
});
|
|
10560
10560
|
return;
|
|
@@ -10562,7 +10562,7 @@ function refineHubAsCodeDelegation2(config, ctx) {
|
|
|
10562
10562
|
if (!CONTEXT_BOUNDARIES2.includes(del.context_boundary)) {
|
|
10563
10563
|
ctx.addIssue({
|
|
10564
10564
|
code: external_exports.ZodIssueCode.custom,
|
|
10565
|
-
path:
|
|
10565
|
+
path: path35,
|
|
10566
10566
|
message: `context_boundary must be one of: ${CONTEXT_BOUNDARIES2.join(", ")}`
|
|
10567
10567
|
});
|
|
10568
10568
|
}
|
|
@@ -14516,34 +14516,15 @@ function resolveLayout(gitRoot, layout = WAYAI_LAYOUT) {
|
|
|
14516
14516
|
const newWs = path.join(gitRoot, layout.wsDir);
|
|
14517
14517
|
const legacyWs = path.join(gitRoot, layout.legacy.wsDir);
|
|
14518
14518
|
const legacyOrg = path.join(gitRoot, layout.legacy.orgAtRoot);
|
|
14519
|
-
const newExists = isDirectory(newWs);
|
|
14520
14519
|
const legacyExists = isDirectory(legacyWs) || isDirectory(legacyOrg);
|
|
14521
14520
|
const basesDir = path.join(newWs, layout.basesSubdir);
|
|
14522
|
-
|
|
14523
|
-
|
|
14524
|
-
|
|
14525
|
-
|
|
14526
|
-
|
|
14527
|
-
isLegacy: false,
|
|
14528
|
-
legacyAlsoPresent: legacyExists
|
|
14529
|
-
};
|
|
14521
|
+
const hubsDir = path.join(newWs, layout.hubsSubdir);
|
|
14522
|
+
const orgDir = path.join(newWs, layout.orgSubdir);
|
|
14523
|
+
const newDisplacesLegacy = () => isDirectory(hubsDir) || isDirectory(orgDir) || isDirectory(basesDir);
|
|
14524
|
+
if (legacyExists && !newDisplacesLegacy()) {
|
|
14525
|
+
return { hubsDir: legacyWs, orgDir: legacyOrg, basesDir, isLegacy: true, legacyAlsoPresent: false };
|
|
14530
14526
|
}
|
|
14531
|
-
|
|
14532
|
-
return {
|
|
14533
|
-
hubsDir: legacyWs,
|
|
14534
|
-
orgDir: legacyOrg,
|
|
14535
|
-
basesDir,
|
|
14536
|
-
isLegacy: true,
|
|
14537
|
-
legacyAlsoPresent: false
|
|
14538
|
-
};
|
|
14539
|
-
}
|
|
14540
|
-
return {
|
|
14541
|
-
hubsDir: path.join(newWs, layout.hubsSubdir),
|
|
14542
|
-
orgDir: path.join(newWs, layout.orgSubdir),
|
|
14543
|
-
basesDir,
|
|
14544
|
-
isLegacy: false,
|
|
14545
|
-
legacyAlsoPresent: false
|
|
14546
|
-
};
|
|
14527
|
+
return { hubsDir, orgDir, basesDir, isLegacy: false, legacyAlsoPresent: legacyExists };
|
|
14547
14528
|
}
|
|
14548
14529
|
function resolveBasesDir(gitRoot) {
|
|
14549
14530
|
return resolveLayout(gitRoot).basesDir;
|
|
@@ -14960,111 +14941,344 @@ var init_workspace = __esm({
|
|
|
14960
14941
|
}
|
|
14961
14942
|
});
|
|
14962
14943
|
|
|
14944
|
+
// src/lib/workspace-manifest.ts
|
|
14945
|
+
import * as fs3 from "fs";
|
|
14946
|
+
import * as path3 from "path";
|
|
14947
|
+
import * as yaml2 from "js-yaml";
|
|
14948
|
+
function workspaceManifestPath(gitRoot) {
|
|
14949
|
+
return path3.join(gitRoot, WAYAI_LAYOUT.wsDir, WORKSPACE_MANIFEST_FILE);
|
|
14950
|
+
}
|
|
14951
|
+
function rootConfigPath(gitRoot) {
|
|
14952
|
+
return path3.join(gitRoot, ROOT_CONFIG_FILE);
|
|
14953
|
+
}
|
|
14954
|
+
function loadYamlMapping(file) {
|
|
14955
|
+
let raw;
|
|
14956
|
+
try {
|
|
14957
|
+
raw = fs3.readFileSync(file, "utf-8");
|
|
14958
|
+
} catch (err) {
|
|
14959
|
+
if (err.code === "ENOENT") return { kind: "absent" };
|
|
14960
|
+
return { kind: "malformed", reason: err instanceof Error ? err.message : String(err) };
|
|
14961
|
+
}
|
|
14962
|
+
let doc;
|
|
14963
|
+
try {
|
|
14964
|
+
doc = yaml2.load(raw);
|
|
14965
|
+
} catch (err) {
|
|
14966
|
+
return { kind: "malformed", reason: err instanceof Error ? err.message : String(err) };
|
|
14967
|
+
}
|
|
14968
|
+
if (doc === void 0 || doc === null) return { kind: "ok", doc: {} };
|
|
14969
|
+
if (typeof doc !== "object" || Array.isArray(doc)) {
|
|
14970
|
+
return { kind: "malformed", reason: "expected a YAML mapping of settings" };
|
|
14971
|
+
}
|
|
14972
|
+
return { kind: "ok", doc };
|
|
14973
|
+
}
|
|
14974
|
+
function loadWorkspaceManifest(gitRoot) {
|
|
14975
|
+
return loadYamlMapping(workspaceManifestPath(gitRoot));
|
|
14976
|
+
}
|
|
14977
|
+
var WORKSPACE_MANIFEST_FILE, WORKSPACE_MANIFEST_LABEL, ROOT_CONFIG_FILE;
|
|
14978
|
+
var init_workspace_manifest = __esm({
|
|
14979
|
+
"src/lib/workspace-manifest.ts"() {
|
|
14980
|
+
"use strict";
|
|
14981
|
+
init_layout();
|
|
14982
|
+
WORKSPACE_MANIFEST_FILE = "wayai.yaml";
|
|
14983
|
+
WORKSPACE_MANIFEST_LABEL = `${WAYAI_LAYOUT.wsDir}/${WORKSPACE_MANIFEST_FILE}`;
|
|
14984
|
+
ROOT_CONFIG_FILE = ".wayai.yaml";
|
|
14985
|
+
}
|
|
14986
|
+
});
|
|
14987
|
+
|
|
14963
14988
|
// src/lib/repo-config.ts
|
|
14964
14989
|
var repo_config_exports = {};
|
|
14965
14990
|
__export(repo_config_exports, {
|
|
14991
|
+
_resetRepoConfigNotices: () => _resetRepoConfigNotices,
|
|
14992
|
+
planOrgMigration: () => planOrgMigration,
|
|
14966
14993
|
readRepoConfig: () => readRepoConfig,
|
|
14994
|
+
readRepoConfigUnlessBlocked: () => readRepoConfigUnlessBlocked,
|
|
14995
|
+
readRepoScopeBlocker: () => readRepoScopeBlocker,
|
|
14967
14996
|
requireRepoConfig: () => requireRepoConfig,
|
|
14997
|
+
resolveRepoConfig: () => resolveRepoConfig,
|
|
14968
14998
|
writeRepoConfig: () => writeRepoConfig
|
|
14969
14999
|
});
|
|
14970
|
-
import * as
|
|
14971
|
-
import * as
|
|
14972
|
-
import * as
|
|
14973
|
-
function
|
|
14974
|
-
if (
|
|
14975
|
-
|
|
14976
|
-
|
|
14977
|
-
|
|
14978
|
-
|
|
15000
|
+
import * as fs4 from "fs";
|
|
15001
|
+
import * as path4 from "path";
|
|
15002
|
+
import * as yaml3 from "js-yaml";
|
|
15003
|
+
function noticeOnce(key, emit) {
|
|
15004
|
+
if (noticed.has(key)) return;
|
|
15005
|
+
noticed.add(key);
|
|
15006
|
+
emit();
|
|
15007
|
+
}
|
|
15008
|
+
function _resetRepoConfigNotices() {
|
|
15009
|
+
noticed.clear();
|
|
15010
|
+
}
|
|
15011
|
+
function readOrgFields(doc) {
|
|
15012
|
+
const raw = doc.organization_id;
|
|
15013
|
+
if (raw === void 0 || raw === null) {
|
|
15014
|
+
if (typeof doc.organization === "string") {
|
|
15015
|
+
return {
|
|
15016
|
+
kind: "invalid",
|
|
15017
|
+
detail: "it uses the old format (organization: <name>) \u2014 replace it with organization_id: <uuid>"
|
|
15018
|
+
};
|
|
15019
|
+
}
|
|
15020
|
+
return { kind: "none" };
|
|
15021
|
+
}
|
|
15022
|
+
if (typeof raw !== "string" || !UUID_RE2.test(raw.trim())) {
|
|
15023
|
+
return { kind: "invalid", detail: "organization_id must be a UUID" };
|
|
15024
|
+
}
|
|
15025
|
+
const name = typeof doc.organization_name === "string" && doc.organization_name.trim() ? doc.organization_name.trim() : void 0;
|
|
15026
|
+
const config = { organization_id: raw.trim() };
|
|
15027
|
+
if (name) config.organization_name = name;
|
|
15028
|
+
return { kind: "declared", config };
|
|
15029
|
+
}
|
|
15030
|
+
function declarationFrom(load11) {
|
|
15031
|
+
if (load11.kind === "absent") return { kind: "none" };
|
|
15032
|
+
if (load11.kind === "malformed") return { kind: "invalid", detail: `it does not parse (${load11.reason})` };
|
|
15033
|
+
return readOrgFields(load11.doc);
|
|
15034
|
+
}
|
|
15035
|
+
function legacyFieldsIn(load11) {
|
|
15036
|
+
if (load11.kind !== "ok") return [];
|
|
15037
|
+
return LEGACY_FIELDS.filter((f) => load11.doc[f] !== void 0);
|
|
15038
|
+
}
|
|
15039
|
+
function resolve2(gitRoot) {
|
|
15040
|
+
const manifestFile = workspaceManifestPath(gitRoot);
|
|
15041
|
+
const manifest = declarationFrom(loadWorkspaceManifest(gitRoot));
|
|
15042
|
+
if (manifest.kind === "invalid") {
|
|
15043
|
+
return { kind: "invalid", source: "manifest", file: manifestFile, detail: manifest.detail };
|
|
15044
|
+
}
|
|
15045
|
+
const rootFile = rootConfigPath(gitRoot);
|
|
15046
|
+
const rootLoad = loadYamlMapping(rootFile);
|
|
15047
|
+
const root = declarationFrom(rootLoad);
|
|
15048
|
+
if (manifest.kind === "declared") {
|
|
15049
|
+
if (root.kind === "declared" && root.config.organization_id !== manifest.config.organization_id) {
|
|
15050
|
+
return {
|
|
15051
|
+
kind: "conflict",
|
|
15052
|
+
manifestOrg: manifest.config.organization_id,
|
|
15053
|
+
rootOrg: root.config.organization_id
|
|
15054
|
+
};
|
|
15055
|
+
}
|
|
15056
|
+
return {
|
|
15057
|
+
kind: "ok",
|
|
15058
|
+
resolved: { config: manifest.config, source: "manifest", path: manifestFile },
|
|
15059
|
+
legacyRootFields: []
|
|
15060
|
+
};
|
|
15061
|
+
}
|
|
15062
|
+
if (root.kind === "declared") {
|
|
15063
|
+
return {
|
|
15064
|
+
kind: "ok",
|
|
15065
|
+
resolved: { config: root.config, source: "root", path: rootFile },
|
|
15066
|
+
legacyRootFields: legacyFieldsIn(rootLoad)
|
|
15067
|
+
};
|
|
15068
|
+
}
|
|
15069
|
+
if (root.kind === "invalid") {
|
|
15070
|
+
return { kind: "invalid", source: "root", file: rootFile, detail: root.detail };
|
|
15071
|
+
}
|
|
15072
|
+
return { kind: "none" };
|
|
15073
|
+
}
|
|
15074
|
+
function conflictMessage(manifestOrg, rootOrg, remedy = RECONCILE_REMEDY) {
|
|
15075
|
+
return [
|
|
15076
|
+
"Refusing to guess the organization: two files in this repo name different ones.",
|
|
15077
|
+
` ${WORKSPACE_MANIFEST_LABEL} -> ${manifestOrg} (the workspace manifest)`,
|
|
15078
|
+
` ${ROOT_CONFIG_FILE} -> ${rootOrg} (deprecated fallback)`,
|
|
15079
|
+
"",
|
|
15080
|
+
...remedy
|
|
15081
|
+
].join("\n");
|
|
15082
|
+
}
|
|
15083
|
+
function rebindRefusal(requestedOrg, rootOrg) {
|
|
15084
|
+
return [
|
|
15085
|
+
`Refusing to re-bind the organization: ${ROOT_CONFIG_FILE} still names a different one, and it is read as a fallback.`,
|
|
15086
|
+
` requested -> ${requestedOrg}`,
|
|
15087
|
+
` ${ROOT_CONFIG_FILE} -> ${rootOrg} (deprecated fallback)`,
|
|
15088
|
+
"",
|
|
15089
|
+
`Delete ${ROOT_CONFIG_FILE} (or set its organization_id to ${requestedOrg}), then re-run.`,
|
|
15090
|
+
"Nothing was written \u2014 this repo still resolves to the organization it had."
|
|
15091
|
+
].join("\n");
|
|
15092
|
+
}
|
|
15093
|
+
function invalidMessage(file, detail) {
|
|
15094
|
+
return [
|
|
15095
|
+
`Invalid organization binding in ${file}: ${detail}.`,
|
|
15096
|
+
"",
|
|
15097
|
+
" organization_id: <your-org-uuid>",
|
|
15098
|
+
"",
|
|
15099
|
+
"Run `wayai init` to set up the workspace."
|
|
15100
|
+
].join("\n");
|
|
15101
|
+
}
|
|
15102
|
+
function missingMessage() {
|
|
15103
|
+
return [
|
|
15104
|
+
"This repository is not scoped to an organization.",
|
|
15105
|
+
`Declare it in ${WORKSPACE_MANIFEST_LABEL}:`,
|
|
15106
|
+
"",
|
|
15107
|
+
" organization_id: <your-org-uuid>",
|
|
15108
|
+
"",
|
|
15109
|
+
"Run `wayai init` to set up the workspace."
|
|
15110
|
+
].join("\n");
|
|
15111
|
+
}
|
|
15112
|
+
function report(r, posture) {
|
|
15113
|
+
switch (r.kind) {
|
|
15114
|
+
case "ok":
|
|
15115
|
+
if (r.resolved.source !== "root") return;
|
|
15116
|
+
noticeOnce(
|
|
15117
|
+
"root-fallback",
|
|
15118
|
+
() => console.warn(
|
|
15119
|
+
`Note: this repo's organization binding is still in ${ROOT_CONFIG_FILE} at the repository root. It belongs in the workspace manifest ${WORKSPACE_MANIFEST_LABEL} \u2014 run \`wayai migrate\` to copy it there.`
|
|
15120
|
+
)
|
|
15121
|
+
);
|
|
15122
|
+
if (r.legacyRootFields.length > 0) {
|
|
15123
|
+
noticeOnce(
|
|
15124
|
+
"legacy-fields",
|
|
15125
|
+
() => console.warn(
|
|
15126
|
+
`Note: ${ROOT_CONFIG_FILE} contains deprecated field(s) ${r.legacyRootFields.join(", ")}. These are ignored \u2014 only organization_id is used now. You can remove them.`
|
|
15127
|
+
)
|
|
15128
|
+
);
|
|
15129
|
+
}
|
|
15130
|
+
return;
|
|
15131
|
+
case "invalid": {
|
|
15132
|
+
const emit = () => console.error(invalidMessage(r.file, r.detail));
|
|
15133
|
+
if (posture === "hard") emit();
|
|
15134
|
+
else noticeOnce(`invalid:${r.source}`, emit);
|
|
15135
|
+
return;
|
|
15136
|
+
}
|
|
15137
|
+
case "conflict":
|
|
15138
|
+
console.error(conflictMessage(r.manifestOrg, r.rootOrg));
|
|
15139
|
+
return;
|
|
15140
|
+
case "none":
|
|
15141
|
+
if (posture === "hard") console.error(missingMessage());
|
|
15142
|
+
return;
|
|
15143
|
+
}
|
|
15144
|
+
}
|
|
15145
|
+
function resolveRepoConfig(root) {
|
|
15146
|
+
const gitRoot = root ?? findGitRoot();
|
|
15147
|
+
if (!gitRoot) return null;
|
|
15148
|
+
const r = resolve2(gitRoot);
|
|
15149
|
+
report(r, "soft");
|
|
15150
|
+
return r.kind === "ok" ? r.resolved : null;
|
|
14979
15151
|
}
|
|
14980
15152
|
function readRepoConfig(root) {
|
|
15153
|
+
return resolveRepoConfig(root)?.config ?? null;
|
|
15154
|
+
}
|
|
15155
|
+
function readRepoConfigUnlessBlocked(root) {
|
|
14981
15156
|
const gitRoot = root ?? findGitRoot();
|
|
14982
15157
|
if (!gitRoot) return null;
|
|
14983
|
-
const
|
|
14984
|
-
|
|
14985
|
-
|
|
14986
|
-
|
|
14987
|
-
|
|
14988
|
-
|
|
14989
|
-
if (config?.organization && typeof config.organization === "string") {
|
|
14990
|
-
console.error(
|
|
14991
|
-
".wayai.yaml uses the old format (organization: name). Replace it with organization_id: <uuid>."
|
|
14992
|
-
);
|
|
14993
|
-
}
|
|
15158
|
+
const r = resolve2(gitRoot);
|
|
15159
|
+
switch (r.kind) {
|
|
15160
|
+
case "ok":
|
|
15161
|
+
report(r, "soft");
|
|
15162
|
+
return r.resolved.config;
|
|
15163
|
+
case "none":
|
|
14994
15164
|
return null;
|
|
14995
|
-
|
|
14996
|
-
|
|
14997
|
-
|
|
14998
|
-
|
|
14999
|
-
|
|
15165
|
+
case "conflict":
|
|
15166
|
+
throw expected(conflictMessage(r.manifestOrg, r.rootOrg));
|
|
15167
|
+
case "invalid":
|
|
15168
|
+
throw expected(invalidMessage(r.file, r.detail));
|
|
15169
|
+
}
|
|
15170
|
+
}
|
|
15171
|
+
function requireRepoConfig(root) {
|
|
15172
|
+
const gitRoot = root ?? findGitRoot();
|
|
15173
|
+
const r = gitRoot ? resolve2(gitRoot) : { kind: "none" };
|
|
15174
|
+
report(r, "hard");
|
|
15175
|
+
if (r.kind === "ok") return r.resolved.config;
|
|
15176
|
+
return process.exit(1);
|
|
15177
|
+
}
|
|
15178
|
+
function readRepoScopeBlocker(root) {
|
|
15179
|
+
const gitRoot = root ?? findGitRoot();
|
|
15180
|
+
if (!gitRoot) return null;
|
|
15181
|
+
const r = resolve2(gitRoot);
|
|
15182
|
+
if (r.kind === "conflict") {
|
|
15000
15183
|
return {
|
|
15001
|
-
|
|
15002
|
-
|
|
15184
|
+
kind: "conflict",
|
|
15185
|
+
manifest_organization_id: r.manifestOrg,
|
|
15186
|
+
root_organization_id: r.rootOrg
|
|
15003
15187
|
};
|
|
15004
|
-
} catch {
|
|
15005
|
-
return null;
|
|
15006
15188
|
}
|
|
15189
|
+
if (r.kind === "invalid") return { kind: "invalid", path: r.file, detail: r.detail };
|
|
15190
|
+
return null;
|
|
15007
15191
|
}
|
|
15008
|
-
function
|
|
15009
|
-
const
|
|
15010
|
-
|
|
15011
|
-
|
|
15012
|
-
|
|
15013
|
-
|
|
15014
|
-
|
|
15015
|
-
|
|
15016
|
-
|
|
15017
|
-
|
|
15192
|
+
function planOrgMigration(gitRoot) {
|
|
15193
|
+
const manifest = declarationFrom(loadWorkspaceManifest(gitRoot));
|
|
15194
|
+
const root = declarationFrom(loadYamlMapping(rootConfigPath(gitRoot)));
|
|
15195
|
+
if (root.kind !== "declared") return { kind: "nothing" };
|
|
15196
|
+
if (manifest.kind === "declared") {
|
|
15197
|
+
if (manifest.config.organization_id === root.config.organization_id) return { kind: "nothing" };
|
|
15198
|
+
return {
|
|
15199
|
+
kind: "refuse",
|
|
15200
|
+
message: conflictMessage(manifest.config.organization_id, root.config.organization_id, [
|
|
15201
|
+
"Reconcile them by hand \u2014 migrate cannot know which one you meant."
|
|
15202
|
+
])
|
|
15203
|
+
};
|
|
15018
15204
|
}
|
|
15019
|
-
|
|
15205
|
+
if (manifest.kind === "invalid") {
|
|
15206
|
+
return {
|
|
15207
|
+
kind: "refuse",
|
|
15208
|
+
message: `Cannot copy the organization binding: ${WORKSPACE_MANIFEST_LABEL} is unusable \u2014 ${manifest.detail}. Fix or delete it, then re-run \`wayai migrate\`.`
|
|
15209
|
+
};
|
|
15210
|
+
}
|
|
15211
|
+
return { kind: "copy", config: root.config };
|
|
15020
15212
|
}
|
|
15021
15213
|
function writeRepoConfig(config, root) {
|
|
15022
15214
|
const gitRoot = root ?? findGitRoot();
|
|
15023
15215
|
if (!gitRoot) {
|
|
15024
15216
|
throw new Error("Not inside a git repository. Run `git init` first.");
|
|
15025
15217
|
}
|
|
15026
|
-
const
|
|
15218
|
+
const stale = declarationFrom(loadYamlMapping(rootConfigPath(gitRoot)));
|
|
15219
|
+
if (stale.kind === "declared" && stale.config.organization_id !== config.organization_id) {
|
|
15220
|
+
throw expected(rebindRefusal(config.organization_id, stale.config.organization_id));
|
|
15221
|
+
}
|
|
15222
|
+
const load11 = loadWorkspaceManifest(gitRoot);
|
|
15223
|
+
if (load11.kind === "malformed") {
|
|
15224
|
+
throw expected(
|
|
15225
|
+
`Cannot write the organization binding: ${WORKSPACE_MANIFEST_LABEL} does not parse (${load11.reason}). Fix or delete it, then re-run.`
|
|
15226
|
+
);
|
|
15227
|
+
}
|
|
15228
|
+
const { organization_id: _id, organization_name: _name, ...rest } = load11.kind === "ok" ? load11.doc : {};
|
|
15027
15229
|
const doc = { organization_id: config.organization_id };
|
|
15028
15230
|
if (config.organization_name?.trim()) doc.organization_name = config.organization_name.trim();
|
|
15029
|
-
|
|
15030
|
-
|
|
15031
|
-
|
|
15231
|
+
Object.assign(doc, rest);
|
|
15232
|
+
const file = workspaceManifestPath(gitRoot);
|
|
15233
|
+
fs4.mkdirSync(path4.dirname(file), { recursive: true });
|
|
15234
|
+
fs4.writeFileSync(
|
|
15235
|
+
file,
|
|
15236
|
+
yaml3.dump(doc, { lineWidth: -1, quotingType: '"', forceQuotes: false }),
|
|
15237
|
+
"utf-8"
|
|
15238
|
+
);
|
|
15239
|
+
return file;
|
|
15032
15240
|
}
|
|
15033
|
-
var LEGACY_FIELDS,
|
|
15241
|
+
var LEGACY_FIELDS, noticed, RECONCILE_REMEDY;
|
|
15034
15242
|
var init_repo_config = __esm({
|
|
15035
15243
|
"src/lib/repo-config.ts"() {
|
|
15036
15244
|
"use strict";
|
|
15245
|
+
init_expected();
|
|
15037
15246
|
init_workspace();
|
|
15038
15247
|
init_utils();
|
|
15248
|
+
init_workspace_manifest();
|
|
15039
15249
|
LEGACY_FIELDS = ["project_id", "project_name", "hub_id", "hub_name"];
|
|
15040
|
-
|
|
15250
|
+
noticed = /* @__PURE__ */ new Set();
|
|
15251
|
+
RECONCILE_REMEDY = [
|
|
15252
|
+
"Keep the organization_id you actually work in and delete the other declaration.",
|
|
15253
|
+
`\`wayai init\` rewrites ${WORKSPACE_MANIFEST_LABEL}; the root file is yours to remove.`
|
|
15254
|
+
];
|
|
15041
15255
|
}
|
|
15042
15256
|
});
|
|
15043
15257
|
|
|
15044
15258
|
// src/lib/utils.ts
|
|
15045
|
-
import * as
|
|
15046
|
-
import * as
|
|
15259
|
+
import * as fs5 from "fs";
|
|
15260
|
+
import * as path5 from "path";
|
|
15047
15261
|
import * as readline from "readline";
|
|
15048
15262
|
function prompt(question) {
|
|
15049
15263
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
15050
|
-
return new Promise((
|
|
15264
|
+
return new Promise((resolve8) => {
|
|
15051
15265
|
rl.question(question, (answer) => {
|
|
15052
15266
|
rl.close();
|
|
15053
|
-
|
|
15267
|
+
resolve8(answer.trim());
|
|
15054
15268
|
});
|
|
15055
15269
|
});
|
|
15056
15270
|
}
|
|
15057
15271
|
function confirm(question) {
|
|
15058
15272
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
15059
|
-
return new Promise((
|
|
15273
|
+
return new Promise((resolve8) => {
|
|
15060
15274
|
rl.question(`${question} [y/N]: `, (answer) => {
|
|
15061
15275
|
rl.close();
|
|
15062
|
-
|
|
15276
|
+
resolve8(answer.trim().toLowerCase() === "y");
|
|
15063
15277
|
});
|
|
15064
15278
|
});
|
|
15065
15279
|
}
|
|
15066
15280
|
function promptSecret(question) {
|
|
15067
|
-
return new Promise((
|
|
15281
|
+
return new Promise((resolve8) => {
|
|
15068
15282
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
15069
15283
|
const originalWrite = rl._writeToOutput;
|
|
15070
15284
|
let firstWrite = true;
|
|
@@ -15080,25 +15294,25 @@ function promptSecret(question) {
|
|
|
15080
15294
|
rl._writeToOutput = originalWrite;
|
|
15081
15295
|
process.stdout.write("\n");
|
|
15082
15296
|
rl.close();
|
|
15083
|
-
|
|
15297
|
+
resolve8(answer);
|
|
15084
15298
|
});
|
|
15085
15299
|
});
|
|
15086
15300
|
}
|
|
15087
15301
|
function readStdin() {
|
|
15088
|
-
return new Promise((
|
|
15302
|
+
return new Promise((resolve8, reject) => {
|
|
15089
15303
|
let data = "";
|
|
15090
15304
|
process.stdin.setEncoding("utf-8");
|
|
15091
15305
|
process.stdin.on("data", (chunk) => {
|
|
15092
15306
|
data += chunk;
|
|
15093
15307
|
});
|
|
15094
|
-
process.stdin.on("end", () =>
|
|
15308
|
+
process.stdin.on("end", () => resolve8(data.trim()));
|
|
15095
15309
|
process.stdin.on("error", reject);
|
|
15096
15310
|
});
|
|
15097
15311
|
}
|
|
15098
15312
|
function resolveHubYamlPath(hubFolder) {
|
|
15099
15313
|
for (const filename of ["hub.yaml", "wayai.yaml"]) {
|
|
15100
|
-
const yamlPath =
|
|
15101
|
-
if (
|
|
15314
|
+
const yamlPath = path5.join(hubFolder, filename);
|
|
15315
|
+
if (fs5.existsSync(yamlPath)) return yamlPath;
|
|
15102
15316
|
}
|
|
15103
15317
|
return null;
|
|
15104
15318
|
}
|
|
@@ -15175,8 +15389,8 @@ async function resolveOrganizationId(client, orgIdFlag) {
|
|
|
15175
15389
|
}
|
|
15176
15390
|
return { organizationId: orgIdFlag };
|
|
15177
15391
|
}
|
|
15178
|
-
const {
|
|
15179
|
-
const repoConfig =
|
|
15392
|
+
const { readRepoConfigUnlessBlocked: readRepoConfigUnlessBlocked2 } = await Promise.resolve().then(() => (init_repo_config(), repo_config_exports));
|
|
15393
|
+
const repoConfig = readRepoConfigUnlessBlocked2();
|
|
15180
15394
|
if (repoConfig) {
|
|
15181
15395
|
return { organizationId: repoConfig.organization_id, organizationName: repoConfig.organization_name };
|
|
15182
15396
|
}
|
|
@@ -15312,7 +15526,7 @@ var init_registry = __esm({
|
|
|
15312
15526
|
surviving: null,
|
|
15313
15527
|
clause: 1,
|
|
15314
15528
|
shipped: true,
|
|
15315
|
-
reason: "One
|
|
15529
|
+
reason: "One org binding per repo (`wayai-ws/wayai.yaml`), so one `init`."
|
|
15316
15530
|
},
|
|
15317
15531
|
{
|
|
15318
15532
|
original: "update",
|
|
@@ -15442,7 +15656,7 @@ var init_registry = __esm({
|
|
|
15442
15656
|
surviving: "bases use",
|
|
15443
15657
|
clause: 3,
|
|
15444
15658
|
shipped: true,
|
|
15445
|
-
reason: "
|
|
15659
|
+
reason: "Deprecated since the worktree scope merged into one set-valued file: `wayai use bases/<id>` covers this. Kept as an alias for its JSON output shape."
|
|
15446
15660
|
},
|
|
15447
15661
|
{
|
|
15448
15662
|
original: "unbind",
|
|
@@ -15450,7 +15664,7 @@ var init_registry = __esm({
|
|
|
15450
15664
|
surviving: "bases unbind",
|
|
15451
15665
|
clause: 3,
|
|
15452
15666
|
shipped: true,
|
|
15453
|
-
reason: "
|
|
15667
|
+
reason: "Deprecated alongside `bases use`: `wayai unbind bases/<id>` covers this. It still clears only the bases axis of the worktree scope, never the hubs one."
|
|
15454
15668
|
},
|
|
15455
15669
|
{
|
|
15456
15670
|
original: "bases promote",
|
|
@@ -15563,17 +15777,17 @@ var init_registry = __esm({
|
|
|
15563
15777
|
});
|
|
15564
15778
|
|
|
15565
15779
|
// src/lib/version-cache.ts
|
|
15566
|
-
import { existsSync as
|
|
15567
|
-
import { dirname as
|
|
15780
|
+
import { existsSync as existsSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
15781
|
+
import { dirname as dirname4, join as join6 } from "path";
|
|
15568
15782
|
import { homedir as homedir2 } from "os";
|
|
15569
15783
|
function getVersionCachePath(filename = CLI_CACHE_FILE) {
|
|
15570
15784
|
return join6(homedir2(), ".wayai", filename);
|
|
15571
15785
|
}
|
|
15572
15786
|
function readVersionCache(filename = CLI_CACHE_FILE) {
|
|
15573
15787
|
try {
|
|
15574
|
-
const
|
|
15575
|
-
if (!
|
|
15576
|
-
const parsed = JSON.parse(readFileSync5(
|
|
15788
|
+
const path35 = getVersionCachePath(filename);
|
|
15789
|
+
if (!existsSync3(path35)) return null;
|
|
15790
|
+
const parsed = JSON.parse(readFileSync5(path35, "utf-8"));
|
|
15577
15791
|
if (typeof parsed.lastCheck !== "number") return null;
|
|
15578
15792
|
if (parsed.latest !== null && typeof parsed.latest !== "string") return null;
|
|
15579
15793
|
return parsed;
|
|
@@ -15593,10 +15807,10 @@ function isVersionCacheStale(filename = CLI_CACHE_FILE, maxAgeMs = MAX_AGE_24H_M
|
|
|
15593
15807
|
return Date.now() - cache.lastCheck > maxAgeMs;
|
|
15594
15808
|
}
|
|
15595
15809
|
function writeVersionCache(filename, cache) {
|
|
15596
|
-
const
|
|
15597
|
-
const dir =
|
|
15598
|
-
if (!
|
|
15599
|
-
writeFileSync2(
|
|
15810
|
+
const path35 = getVersionCachePath(filename);
|
|
15811
|
+
const dir = dirname4(path35);
|
|
15812
|
+
if (!existsSync3(dir)) mkdirSync2(dir, { recursive: true });
|
|
15813
|
+
writeFileSync2(path35, JSON.stringify(cache));
|
|
15600
15814
|
}
|
|
15601
15815
|
function touchVersionCache(filename) {
|
|
15602
15816
|
writeVersionCache(filename, { lastCheck: Date.now(), latest: readVersionCache(filename)?.latest ?? null });
|
|
@@ -15613,9 +15827,9 @@ var init_version_cache = __esm({
|
|
|
15613
15827
|
});
|
|
15614
15828
|
|
|
15615
15829
|
// src/lib/skill-version.ts
|
|
15616
|
-
import { existsSync as
|
|
15830
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6 } from "fs";
|
|
15617
15831
|
import { join as join7 } from "path";
|
|
15618
|
-
import * as
|
|
15832
|
+
import * as yaml4 from "js-yaml";
|
|
15619
15833
|
function skillInstallPaths(skillName) {
|
|
15620
15834
|
return HARNESS_SKILL_DIRS.map((dir) => `${dir}/skills/${skillName}/${SKILL_FILENAME}`);
|
|
15621
15835
|
}
|
|
@@ -15624,7 +15838,7 @@ function parseFrontmatterVersion(content) {
|
|
|
15624
15838
|
if (!match) return null;
|
|
15625
15839
|
let parsed;
|
|
15626
15840
|
try {
|
|
15627
|
-
parsed =
|
|
15841
|
+
parsed = yaml4.load(match[1]);
|
|
15628
15842
|
} catch {
|
|
15629
15843
|
return null;
|
|
15630
15844
|
}
|
|
@@ -15635,14 +15849,14 @@ function parseFrontmatterVersion(content) {
|
|
|
15635
15849
|
function findInstalledSkills(projectRoot, paths = SKILL_INSTALL_PATHS) {
|
|
15636
15850
|
const found = [];
|
|
15637
15851
|
for (const rel of paths) {
|
|
15638
|
-
const
|
|
15639
|
-
if (!
|
|
15852
|
+
const path35 = join7(projectRoot, rel);
|
|
15853
|
+
if (!existsSync4(path35)) continue;
|
|
15640
15854
|
let version = null;
|
|
15641
15855
|
try {
|
|
15642
|
-
version = parseFrontmatterVersion(readFileSync6(
|
|
15856
|
+
version = parseFrontmatterVersion(readFileSync6(path35, "utf-8"));
|
|
15643
15857
|
} catch {
|
|
15644
15858
|
}
|
|
15645
|
-
found.push({ path:
|
|
15859
|
+
found.push({ path: path35, version });
|
|
15646
15860
|
}
|
|
15647
15861
|
return found;
|
|
15648
15862
|
}
|
|
@@ -15673,22 +15887,22 @@ __export(config_exports, {
|
|
|
15673
15887
|
readConfig: () => readConfig,
|
|
15674
15888
|
writeConfig: () => writeConfig
|
|
15675
15889
|
});
|
|
15676
|
-
import * as
|
|
15677
|
-
import * as
|
|
15890
|
+
import * as fs6 from "fs";
|
|
15891
|
+
import * as path6 from "path";
|
|
15678
15892
|
import * as os from "os";
|
|
15679
15893
|
function configDir() {
|
|
15680
|
-
return
|
|
15894
|
+
return path6.join(os.homedir(), ".wayai");
|
|
15681
15895
|
}
|
|
15682
15896
|
function configPath() {
|
|
15683
|
-
return
|
|
15897
|
+
return path6.join(configDir(), "config.json");
|
|
15684
15898
|
}
|
|
15685
15899
|
function getConfigPath() {
|
|
15686
15900
|
return configPath();
|
|
15687
15901
|
}
|
|
15688
15902
|
function readConfig() {
|
|
15689
|
-
if (!
|
|
15903
|
+
if (!fs6.existsSync(configPath())) return null;
|
|
15690
15904
|
try {
|
|
15691
|
-
const content =
|
|
15905
|
+
const content = fs6.readFileSync(configPath(), "utf-8");
|
|
15692
15906
|
const parsed = JSON.parse(content);
|
|
15693
15907
|
if (!parsed.api_url) return null;
|
|
15694
15908
|
return {
|
|
@@ -15701,13 +15915,13 @@ function readConfig() {
|
|
|
15701
15915
|
}
|
|
15702
15916
|
}
|
|
15703
15917
|
function writeConfig(config) {
|
|
15704
|
-
if (!
|
|
15705
|
-
|
|
15918
|
+
if (!fs6.existsSync(configDir())) {
|
|
15919
|
+
fs6.mkdirSync(configDir(), { recursive: true });
|
|
15706
15920
|
}
|
|
15707
15921
|
let existing = {};
|
|
15708
|
-
if (
|
|
15922
|
+
if (fs6.existsSync(configPath())) {
|
|
15709
15923
|
try {
|
|
15710
|
-
existing = JSON.parse(
|
|
15924
|
+
existing = JSON.parse(fs6.readFileSync(configPath(), "utf-8"));
|
|
15711
15925
|
} catch {
|
|
15712
15926
|
}
|
|
15713
15927
|
}
|
|
@@ -15715,14 +15929,14 @@ function writeConfig(config) {
|
|
|
15715
15929
|
delete existing.access_token;
|
|
15716
15930
|
delete existing.refresh_token;
|
|
15717
15931
|
Object.assign(existing, config);
|
|
15718
|
-
|
|
15932
|
+
fs6.writeFileSync(configPath(), JSON.stringify(existing, null, 2) + "\n", {
|
|
15719
15933
|
mode: 384
|
|
15720
15934
|
// owner-only read/write
|
|
15721
15935
|
});
|
|
15722
15936
|
}
|
|
15723
15937
|
function deleteConfig() {
|
|
15724
|
-
if (
|
|
15725
|
-
|
|
15938
|
+
if (fs6.existsSync(configPath())) {
|
|
15939
|
+
fs6.unlinkSync(configPath());
|
|
15726
15940
|
}
|
|
15727
15941
|
}
|
|
15728
15942
|
var init_config = __esm({
|
|
@@ -15732,14 +15946,14 @@ var init_config = __esm({
|
|
|
15732
15946
|
});
|
|
15733
15947
|
|
|
15734
15948
|
// src/lib/token-store.ts
|
|
15735
|
-
import * as
|
|
15736
|
-
import * as
|
|
15949
|
+
import * as fs7 from "fs";
|
|
15950
|
+
import * as path7 from "path";
|
|
15737
15951
|
import * as os2 from "os";
|
|
15738
15952
|
function configDir2() {
|
|
15739
|
-
return
|
|
15953
|
+
return path7.join(os2.homedir(), ".wayai");
|
|
15740
15954
|
}
|
|
15741
15955
|
function configPath2() {
|
|
15742
|
-
return
|
|
15956
|
+
return path7.join(configDir2(), "config.json");
|
|
15743
15957
|
}
|
|
15744
15958
|
function manualCleanupCommand(account) {
|
|
15745
15959
|
if (process.platform === "darwin") {
|
|
@@ -15791,9 +16005,9 @@ async function getKeyring() {
|
|
|
15791
16005
|
return keyringCache;
|
|
15792
16006
|
}
|
|
15793
16007
|
function readLegacyConfigFile() {
|
|
15794
|
-
if (!
|
|
16008
|
+
if (!fs7.existsSync(configPath2())) return null;
|
|
15795
16009
|
try {
|
|
15796
|
-
return JSON.parse(
|
|
16010
|
+
return JSON.parse(fs7.readFileSync(configPath2(), "utf-8"));
|
|
15797
16011
|
} catch {
|
|
15798
16012
|
return null;
|
|
15799
16013
|
}
|
|
@@ -15806,7 +16020,7 @@ function stripTokensFromFile() {
|
|
|
15806
16020
|
if (k === "token" || k === "access_token" || k === "refresh_token") continue;
|
|
15807
16021
|
cleaned[k] = v;
|
|
15808
16022
|
}
|
|
15809
|
-
|
|
16023
|
+
fs7.writeFileSync(configPath2(), JSON.stringify(cleaned, null, 2) + "\n", { mode: 384 });
|
|
15810
16024
|
}
|
|
15811
16025
|
async function migrateLegacyTokens() {
|
|
15812
16026
|
const legacy = readLegacyConfigFile();
|
|
@@ -15957,8 +16171,8 @@ async function clearTokens() {
|
|
|
15957
16171
|
}
|
|
15958
16172
|
}
|
|
15959
16173
|
}
|
|
15960
|
-
if (
|
|
15961
|
-
|
|
16174
|
+
if (fs7.existsSync(configPath2())) {
|
|
16175
|
+
fs7.unlinkSync(configPath2());
|
|
15962
16176
|
}
|
|
15963
16177
|
}
|
|
15964
16178
|
function readMetadataExpiresAt() {
|
|
@@ -15972,7 +16186,7 @@ function writeMetadataExpiresAt(expires_at) {
|
|
|
15972
16186
|
delete existing.refresh_token;
|
|
15973
16187
|
existing.token_expires_at = expires_at;
|
|
15974
16188
|
ensureConfigDir();
|
|
15975
|
-
|
|
16189
|
+
fs7.writeFileSync(configPath2(), JSON.stringify(existing, null, 2) + "\n", { mode: 384 });
|
|
15976
16190
|
}
|
|
15977
16191
|
function clearMetadataExpiresAt() {
|
|
15978
16192
|
const existing = readLegacyConfigFile();
|
|
@@ -15982,11 +16196,11 @@ function clearMetadataExpiresAt() {
|
|
|
15982
16196
|
delete existing.refresh_token;
|
|
15983
16197
|
delete existing.token_expires_at;
|
|
15984
16198
|
ensureConfigDir();
|
|
15985
|
-
|
|
16199
|
+
fs7.writeFileSync(configPath2(), JSON.stringify(existing, null, 2) + "\n", { mode: 384 });
|
|
15986
16200
|
}
|
|
15987
16201
|
function ensureConfigDir() {
|
|
15988
|
-
if (!
|
|
15989
|
-
|
|
16202
|
+
if (!fs7.existsSync(configDir2())) {
|
|
16203
|
+
fs7.mkdirSync(configDir2(), { recursive: true });
|
|
15990
16204
|
}
|
|
15991
16205
|
}
|
|
15992
16206
|
function writeFileFallback(tokens) {
|
|
@@ -15997,7 +16211,7 @@ function writeFileFallback(tokens) {
|
|
|
15997
16211
|
delete existing.token_expires_at;
|
|
15998
16212
|
Object.assign(existing, tokens);
|
|
15999
16213
|
ensureConfigDir();
|
|
16000
|
-
|
|
16214
|
+
fs7.writeFileSync(configPath2(), JSON.stringify(existing, null, 2) + "\n", { mode: 384 });
|
|
16001
16215
|
}
|
|
16002
16216
|
var KEYRING_SERVICE, KEY_WAY_TOKEN, KEY_OAUTH_ACCESS, KEY_OAUTH_REFRESH, keyringCache, StaleKeyringSlotError;
|
|
16003
16217
|
var init_token_store = __esm({
|
|
@@ -16106,7 +16320,7 @@ async function validateToken(apiUrl, token) {
|
|
|
16106
16320
|
}
|
|
16107
16321
|
}
|
|
16108
16322
|
function startCallbackServer(port, expectedState, timeoutMs = 12e4) {
|
|
16109
|
-
return new Promise((
|
|
16323
|
+
return new Promise((resolve8, reject) => {
|
|
16110
16324
|
const server = http.createServer((req, res) => {
|
|
16111
16325
|
const url = new URL(req.url || "/", `http://127.0.0.1:${port}`);
|
|
16112
16326
|
if (url.pathname === "/callback") {
|
|
@@ -16132,7 +16346,7 @@ function startCallbackServer(port, expectedState, timeoutMs = 12e4) {
|
|
|
16132
16346
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
16133
16347
|
res.end("<html><body><h2>Login successful!</h2><p>You can close this tab and return to your terminal.</p></body></html>");
|
|
16134
16348
|
server.close();
|
|
16135
|
-
|
|
16349
|
+
resolve8({ code, port });
|
|
16136
16350
|
} else {
|
|
16137
16351
|
res.writeHead(400, { "Content-Type": "text/html" });
|
|
16138
16352
|
res.end("<html><body><h2>Login failed</h2><p>No authorization code received</p></body></html>");
|
|
@@ -16239,14 +16453,14 @@ __export(skill_symlink_exports, {
|
|
|
16239
16453
|
healClaudeSkillLink: () => healClaudeSkillLink,
|
|
16240
16454
|
healSkillLinkForCommand: () => healSkillLinkForCommand
|
|
16241
16455
|
});
|
|
16242
|
-
import { existsSync as
|
|
16456
|
+
import { existsSync as existsSync7, lstatSync, mkdirSync as mkdirSync5, rmSync, symlinkSync } from "fs";
|
|
16243
16457
|
import { join as join10 } from "path";
|
|
16244
16458
|
function healClaudeSkillLink(root) {
|
|
16245
16459
|
try {
|
|
16246
16460
|
const source = join10(root, ".agents", "skills", SKILL_NAME);
|
|
16247
|
-
if (!
|
|
16461
|
+
if (!existsSync7(join10(source, SKILL_FILENAME))) return false;
|
|
16248
16462
|
const link = join10(root, ".claude", "skills", SKILL_NAME);
|
|
16249
|
-
if (
|
|
16463
|
+
if (existsSync7(join10(link, SKILL_FILENAME))) return false;
|
|
16250
16464
|
let entry = null;
|
|
16251
16465
|
try {
|
|
16252
16466
|
entry = lstatSync(link);
|
|
@@ -16257,7 +16471,7 @@ function healClaudeSkillLink(root) {
|
|
|
16257
16471
|
if (!entry.isSymbolicLink()) return false;
|
|
16258
16472
|
rmSync(link, { force: true });
|
|
16259
16473
|
}
|
|
16260
|
-
|
|
16474
|
+
mkdirSync5(join10(root, ".claude", "skills"), { recursive: true });
|
|
16261
16475
|
symlinkSync(join10("..", "..", ".agents", "skills", SKILL_NAME), link, "dir");
|
|
16262
16476
|
return true;
|
|
16263
16477
|
} catch {
|
|
@@ -16344,10 +16558,10 @@ import * as readline2 from "readline";
|
|
|
16344
16558
|
function prompt2(question, defaultValue) {
|
|
16345
16559
|
const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
|
|
16346
16560
|
const display = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
|
|
16347
|
-
return new Promise((
|
|
16561
|
+
return new Promise((resolve8) => {
|
|
16348
16562
|
rl.question(display, (answer) => {
|
|
16349
16563
|
rl.close();
|
|
16350
|
-
|
|
16564
|
+
resolve8(answer.trim() || defaultValue || "");
|
|
16351
16565
|
});
|
|
16352
16566
|
});
|
|
16353
16567
|
}
|
|
@@ -16475,8 +16689,8 @@ async function tryOpenBrowser(url) {
|
|
|
16475
16689
|
cmd = "xdg-open";
|
|
16476
16690
|
args2 = [url];
|
|
16477
16691
|
}
|
|
16478
|
-
return new Promise((
|
|
16479
|
-
execFile(cmd, args2, (err) =>
|
|
16692
|
+
return new Promise((resolve8) => {
|
|
16693
|
+
execFile(cmd, args2, (err) => resolve8(!err));
|
|
16480
16694
|
});
|
|
16481
16695
|
} catch {
|
|
16482
16696
|
return false;
|
|
@@ -16520,10 +16734,33 @@ var init_logout = __esm({
|
|
|
16520
16734
|
}
|
|
16521
16735
|
});
|
|
16522
16736
|
|
|
16523
|
-
// src/lib/
|
|
16737
|
+
// src/lib/base-id.ts
|
|
16738
|
+
function isValidBaseId(id) {
|
|
16739
|
+
return id.length > 0 && id.length <= BASE_ID_MAX_LENGTH && BASE_ID_RE.test(id);
|
|
16740
|
+
}
|
|
16741
|
+
function isPathSafeId(id) {
|
|
16742
|
+
return PATH_SAFE_ID_RE.test(id);
|
|
16743
|
+
}
|
|
16744
|
+
var BASE_ID_MAX_LENGTH, BASE_ID_RE, BASE_ID_RULE, PATH_SAFE_ID_RE, PATH_SAFE_ID_RULE;
|
|
16745
|
+
var init_base_id = __esm({
|
|
16746
|
+
"src/lib/base-id.ts"() {
|
|
16747
|
+
"use strict";
|
|
16748
|
+
BASE_ID_MAX_LENGTH = 128;
|
|
16749
|
+
BASE_ID_RE = /^[A-Za-z0-9_][A-Za-z0-9_-]*$/;
|
|
16750
|
+
BASE_ID_RULE = `letters, digits, \`-\` and \`_\`, starting with a letter, digit or \`_\`, ${BASE_ID_MAX_LENGTH} characters or fewer`;
|
|
16751
|
+
PATH_SAFE_ID_RE = /^(?!\.\.?$)[A-Za-z0-9._-]{1,256}$/;
|
|
16752
|
+
PATH_SAFE_ID_RULE = "letters, digits, dot, dash and underscore, with no path separators, not `.` or `..` alone, 256 characters or fewer";
|
|
16753
|
+
}
|
|
16754
|
+
});
|
|
16755
|
+
|
|
16756
|
+
// src/lib/worktree-scope.ts
|
|
16524
16757
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
16525
|
-
import * as
|
|
16526
|
-
import * as
|
|
16758
|
+
import * as fs8 from "fs";
|
|
16759
|
+
import * as path8 from "path";
|
|
16760
|
+
import * as yaml5 from "js-yaml";
|
|
16761
|
+
function axisNoun(axis) {
|
|
16762
|
+
return AXES[axis].noun;
|
|
16763
|
+
}
|
|
16527
16764
|
function resolveGitDir() {
|
|
16528
16765
|
const cwd = process.cwd();
|
|
16529
16766
|
if (_gitDirCache && _gitDirCache.cwd === cwd) return _gitDirCache.gitDir;
|
|
@@ -16534,165 +16771,234 @@ function resolveGitDir() {
|
|
|
16534
16771
|
encoding: "utf-8",
|
|
16535
16772
|
stdio: ["pipe", "pipe", "pipe"]
|
|
16536
16773
|
}).trim();
|
|
16537
|
-
gitDir = raw ?
|
|
16774
|
+
gitDir = raw ? path8.resolve(cwd, raw) : null;
|
|
16538
16775
|
} catch {
|
|
16539
16776
|
gitDir = null;
|
|
16540
16777
|
}
|
|
16541
16778
|
_gitDirCache = { cwd, gitDir };
|
|
16542
16779
|
return gitDir;
|
|
16543
16780
|
}
|
|
16544
|
-
function
|
|
16545
|
-
const
|
|
16546
|
-
|
|
16547
|
-
|
|
16548
|
-
|
|
16549
|
-
|
|
16550
|
-
|
|
16551
|
-
|
|
16552
|
-
|
|
16553
|
-
|
|
16554
|
-
|
|
16555
|
-
|
|
16556
|
-
|
|
16557
|
-
|
|
16558
|
-
|
|
16559
|
-
|
|
16560
|
-
|
|
16561
|
-
|
|
16562
|
-
|
|
16563
|
-
|
|
16564
|
-
|
|
16565
|
-
if (!bindingPath) continue;
|
|
16566
|
-
let raw;
|
|
16567
|
-
try {
|
|
16568
|
-
raw = fs7.readFileSync(bindingPath, "utf-8");
|
|
16569
|
-
} catch (err) {
|
|
16570
|
-
if (err.code === "ENOENT") continue;
|
|
16571
|
-
throw err;
|
|
16572
|
-
}
|
|
16573
|
-
const trimmed = raw.trim();
|
|
16574
|
-
return isValidId(trimmed) ? trimmed : null;
|
|
16575
|
-
}
|
|
16576
|
-
return null;
|
|
16781
|
+
function getScopePath() {
|
|
16782
|
+
const gitDir = resolveGitDir();
|
|
16783
|
+
return gitDir ? path8.join(gitDir, SCOPE_FILE) : null;
|
|
16784
|
+
}
|
|
16785
|
+
function legacyPaths() {
|
|
16786
|
+
const gitDir = resolveGitDir();
|
|
16787
|
+
if (!gitDir) return [];
|
|
16788
|
+
return AXIS_ORDER.flatMap((axis) => AXES[axis].legacyFiles).map((f) => path8.join(gitDir, f));
|
|
16789
|
+
}
|
|
16790
|
+
function emptyScope() {
|
|
16791
|
+
return { hubs: [], bases: [] };
|
|
16792
|
+
}
|
|
16793
|
+
function parseAxis(raw, axis) {
|
|
16794
|
+
if (!Array.isArray(raw)) return [];
|
|
16795
|
+
const { isValidId } = AXES[axis];
|
|
16796
|
+
const out = [];
|
|
16797
|
+
for (const entry of raw) {
|
|
16798
|
+
if (typeof entry !== "string") continue;
|
|
16799
|
+
const id = entry.trim();
|
|
16800
|
+
if (!isValidId(id) || out.includes(id)) continue;
|
|
16801
|
+
out.push(id);
|
|
16577
16802
|
}
|
|
16578
|
-
|
|
16579
|
-
|
|
16580
|
-
|
|
16803
|
+
return out;
|
|
16804
|
+
}
|
|
16805
|
+
function readLegacyAxis(axis) {
|
|
16806
|
+
const gitDir = resolveGitDir();
|
|
16807
|
+
if (!gitDir) return [];
|
|
16808
|
+
const { isValidId, legacyFiles } = AXES[axis];
|
|
16809
|
+
for (const filename of legacyFiles) {
|
|
16810
|
+
let raw;
|
|
16581
16811
|
try {
|
|
16582
|
-
|
|
16583
|
-
} catch {
|
|
16812
|
+
raw = fs8.readFileSync(path8.join(gitDir, filename), "utf-8");
|
|
16813
|
+
} catch (err) {
|
|
16814
|
+
if (err.code === "ENOENT") continue;
|
|
16815
|
+
throw err;
|
|
16584
16816
|
}
|
|
16817
|
+
const trimmed = raw.trim();
|
|
16818
|
+
return isValidId(trimmed) ? [trimmed] : [];
|
|
16585
16819
|
}
|
|
16586
|
-
|
|
16587
|
-
|
|
16588
|
-
|
|
16820
|
+
return [];
|
|
16821
|
+
}
|
|
16822
|
+
function readScope() {
|
|
16823
|
+
const scopePath = getScopePath();
|
|
16824
|
+
if (!scopePath) return emptyScope();
|
|
16825
|
+
let raw;
|
|
16826
|
+
try {
|
|
16827
|
+
raw = fs8.readFileSync(scopePath, "utf-8");
|
|
16828
|
+
} catch (err) {
|
|
16829
|
+
if (err.code === "ENOENT") {
|
|
16830
|
+
return { hubs: readLegacyAxis("hubs"), bases: readLegacyAxis("bases") };
|
|
16589
16831
|
}
|
|
16590
|
-
|
|
16591
|
-
|
|
16592
|
-
|
|
16832
|
+
throw err;
|
|
16833
|
+
}
|
|
16834
|
+
let doc;
|
|
16835
|
+
try {
|
|
16836
|
+
doc = yaml5.load(raw);
|
|
16837
|
+
} catch {
|
|
16838
|
+
return emptyScope();
|
|
16839
|
+
}
|
|
16840
|
+
if (!doc || typeof doc !== "object" || Array.isArray(doc)) return emptyScope();
|
|
16841
|
+
const map = doc;
|
|
16842
|
+
return { hubs: parseAxis(map.hubs, "hubs"), bases: parseAxis(map.bases, "bases") };
|
|
16843
|
+
}
|
|
16844
|
+
function sweepLegacyFiles() {
|
|
16845
|
+
for (const legacyPath of legacyPaths()) {
|
|
16846
|
+
try {
|
|
16847
|
+
fs8.unlinkSync(legacyPath);
|
|
16848
|
+
} catch {
|
|
16593
16849
|
}
|
|
16594
|
-
fs7.writeFileSync(bindingPath, `${id}
|
|
16595
|
-
`, "utf-8");
|
|
16596
|
-
removeLegacyBinding();
|
|
16597
16850
|
}
|
|
16598
|
-
|
|
16599
|
-
|
|
16600
|
-
|
|
16601
|
-
|
|
16602
|
-
|
|
16603
|
-
|
|
16604
|
-
removed = true;
|
|
16605
|
-
} catch (err) {
|
|
16606
|
-
if (err.code !== "ENOENT") throw err;
|
|
16607
|
-
}
|
|
16851
|
+
}
|
|
16852
|
+
function writeScope(scope) {
|
|
16853
|
+
for (const axis of AXIS_ORDER) {
|
|
16854
|
+
const { isValidId, idLabel } = AXES[axis];
|
|
16855
|
+
for (const id of scope[axis]) {
|
|
16856
|
+
if (!isValidId(id)) throw expected(`Invalid ${idLabel}: ${id}`);
|
|
16608
16857
|
}
|
|
16609
|
-
return removed;
|
|
16610
16858
|
}
|
|
16611
|
-
|
|
16612
|
-
|
|
16613
|
-
|
|
16614
|
-
if (bound === resolvedId) return;
|
|
16615
|
-
const target = label ? `${label} (${resolvedId})` : resolvedId;
|
|
16616
|
-
console.error(
|
|
16617
|
-
[
|
|
16618
|
-
`This worktree is bound to ${noun} ${bound}, but the command resolved to ${target}.`,
|
|
16619
|
-
"",
|
|
16620
|
-
"This usually means a prompt was routed to the wrong worktree.",
|
|
16621
|
-
"Confirm with the user before unbinding. To override:",
|
|
16622
|
-
` ${unbindCommand2} # clear the binding for this worktree`,
|
|
16623
|
-
` ${useCommand2} ${resolvedId} # rebind this worktree to the new ${noun}`
|
|
16624
|
-
].join("\n")
|
|
16625
|
-
);
|
|
16626
|
-
process.exit(1);
|
|
16859
|
+
const scopePath = getScopePath();
|
|
16860
|
+
if (!scopePath) {
|
|
16861
|
+
throw expected("Not inside a git repository \u2014 cannot write the worktree scope.");
|
|
16627
16862
|
}
|
|
16628
|
-
|
|
16629
|
-
|
|
16630
|
-
|
|
16631
|
-
|
|
16632
|
-
|
|
16633
|
-
|
|
16634
|
-
|
|
16635
|
-
|
|
16636
|
-
|
|
16637
|
-
|
|
16638
|
-
|
|
16639
|
-
|
|
16640
|
-
|
|
16863
|
+
const body = yaml5.dump({ hubs: scope.hubs, bases: scope.bases }, { flowLevel: 1 });
|
|
16864
|
+
const tmpPath = `${scopePath}.tmp-${process.pid}`;
|
|
16865
|
+
try {
|
|
16866
|
+
fs8.writeFileSync(tmpPath, body, "utf-8");
|
|
16867
|
+
fs8.renameSync(tmpPath, scopePath);
|
|
16868
|
+
} catch (err) {
|
|
16869
|
+
try {
|
|
16870
|
+
fs8.unlinkSync(tmpPath);
|
|
16871
|
+
} catch {
|
|
16872
|
+
}
|
|
16873
|
+
throw asExpectedEnvironmentError(err);
|
|
16874
|
+
}
|
|
16875
|
+
sweepLegacyFiles();
|
|
16876
|
+
}
|
|
16877
|
+
function asExpectedEnvironmentError(err) {
|
|
16878
|
+
if (err instanceof Error && typeof err.code === "string") {
|
|
16879
|
+
return expected(err.message);
|
|
16641
16880
|
}
|
|
16642
|
-
|
|
16881
|
+
return err;
|
|
16882
|
+
}
|
|
16883
|
+
function setScopeAxis(axis, ids) {
|
|
16884
|
+
writeScope({ ...readScope(), [axis]: ids });
|
|
16885
|
+
return ids;
|
|
16886
|
+
}
|
|
16887
|
+
function addToScope(axis, id) {
|
|
16888
|
+
const scope = readScope();
|
|
16889
|
+
if (scope[axis].includes(id)) return null;
|
|
16890
|
+
const next = [...scope[axis], id];
|
|
16891
|
+
writeScope({ ...scope, [axis]: next });
|
|
16892
|
+
return next;
|
|
16893
|
+
}
|
|
16894
|
+
function removeFromScope(axis, id) {
|
|
16895
|
+
const scope = readScope();
|
|
16896
|
+
if (!scope[axis].includes(id)) return null;
|
|
16897
|
+
const next = scope[axis].filter((entry) => entry !== id);
|
|
16898
|
+
writeScope({ ...scope, [axis]: next });
|
|
16899
|
+
return next;
|
|
16900
|
+
}
|
|
16901
|
+
function clearScope() {
|
|
16902
|
+
const scopePath = getScopePath();
|
|
16903
|
+
let removed = false;
|
|
16904
|
+
for (const target of [...scopePath ? [scopePath] : [], ...legacyPaths()]) {
|
|
16643
16905
|
try {
|
|
16644
|
-
|
|
16645
|
-
|
|
16646
|
-
console.log(`Worktree bound to ${noun} ${id} (run \`${unbindCommand2}\` to clear).`);
|
|
16647
|
-
return true;
|
|
16906
|
+
fs8.unlinkSync(target);
|
|
16907
|
+
removed = true;
|
|
16648
16908
|
} catch (err) {
|
|
16649
|
-
|
|
16650
|
-
` Warning: could not auto-bind worktree (${err instanceof Error ? err.message : String(err)})`
|
|
16651
|
-
);
|
|
16652
|
-
return false;
|
|
16909
|
+
if (err.code !== "ENOENT") throw err;
|
|
16653
16910
|
}
|
|
16654
16911
|
}
|
|
16655
|
-
return
|
|
16656
|
-
getBindingPath: getBindingPath2,
|
|
16657
|
-
readBinding: readBinding2,
|
|
16658
|
-
writeBinding: writeBinding2,
|
|
16659
|
-
clearBinding: clearBinding2,
|
|
16660
|
-
assertMatchesBinding,
|
|
16661
|
-
assertNoBindingBlocksCreation,
|
|
16662
|
-
autoBindIfUnbound: autoBindIfUnbound2
|
|
16663
|
-
};
|
|
16912
|
+
return removed;
|
|
16664
16913
|
}
|
|
16665
|
-
|
|
16666
|
-
|
|
16667
|
-
|
|
16668
|
-
|
|
16914
|
+
function describeAxis(axis, ids) {
|
|
16915
|
+
const { noun } = AXES[axis];
|
|
16916
|
+
return ids.length === 1 ? `${noun} ${ids[0]}` : `${noun}s ${ids.join(", ")}`;
|
|
16917
|
+
}
|
|
16918
|
+
function describeScope(scope) {
|
|
16919
|
+
return AXIS_ORDER.filter((axis) => scope[axis].length > 0).map((axis) => describeAxis(axis, scope[axis])).join("; ");
|
|
16920
|
+
}
|
|
16921
|
+
function assertInScope(axis, resolvedId, label) {
|
|
16922
|
+
const scoped = readScope()[axis];
|
|
16923
|
+
if (scoped.length === 0) return;
|
|
16924
|
+
if (scoped.includes(resolvedId)) return;
|
|
16925
|
+
const { noun, selectorFor } = AXES[axis];
|
|
16926
|
+
const selector = selectorFor(resolvedId);
|
|
16927
|
+
const target = label ? `${label} (${resolvedId})` : resolvedId;
|
|
16928
|
+
console.error(
|
|
16929
|
+
[
|
|
16930
|
+
`This worktree is scoped to ${describeAxis(axis, scoped)}, but the command resolved to ${target}.`,
|
|
16931
|
+
"",
|
|
16932
|
+
"This usually means a prompt was routed to the wrong worktree.",
|
|
16933
|
+
"Confirm with the user before changing this scope. To override:",
|
|
16934
|
+
` ${REPLACE_COMMAND} ${selector} # scope this worktree to that ${noun} INSTEAD`,
|
|
16935
|
+
` ${ADD_COMMAND} ${selector} # scope it to that ${noun} AS WELL`,
|
|
16936
|
+
` ${CLEAR_COMMAND} # clear the whole worktree scope (both hubs and bases)`
|
|
16937
|
+
].join("\n")
|
|
16938
|
+
);
|
|
16939
|
+
process.exit(1);
|
|
16940
|
+
}
|
|
16941
|
+
function assertScopeAllowsCreation(axis, newName) {
|
|
16942
|
+
const scoped = readScope()[axis];
|
|
16943
|
+
if (scoped.length === 0) return;
|
|
16944
|
+
const { noun } = AXES[axis];
|
|
16945
|
+
console.error(
|
|
16946
|
+
[
|
|
16947
|
+
`This worktree is scoped to ${describeAxis(axis, scoped)}, but you're about to create a new ${noun} "${newName}" here.`,
|
|
16948
|
+
"",
|
|
16949
|
+
"This usually means a prompt was routed to the wrong worktree.",
|
|
16950
|
+
"Confirm with the user before clearing this scope. To override:",
|
|
16951
|
+
` ${CLEAR_COMMAND} # clear the whole worktree scope (both hubs and bases)`
|
|
16952
|
+
].join("\n")
|
|
16953
|
+
);
|
|
16954
|
+
process.exit(1);
|
|
16955
|
+
}
|
|
16956
|
+
function seedScopeIfEmpty(axis, id) {
|
|
16957
|
+
try {
|
|
16958
|
+
if (readScope()[axis].length > 0) return false;
|
|
16959
|
+
setScopeAxis(axis, [id]);
|
|
16960
|
+
console.log(
|
|
16961
|
+
`Worktree bound to ${AXES[axis].noun} ${id} (run \`${CLEAR_COMMAND}\` to clear).`
|
|
16962
|
+
);
|
|
16963
|
+
return true;
|
|
16964
|
+
} catch (err) {
|
|
16965
|
+
console.warn(
|
|
16966
|
+
` Warning: could not bind worktree (${err instanceof Error ? err.message : String(err)})`
|
|
16967
|
+
);
|
|
16968
|
+
return false;
|
|
16669
16969
|
}
|
|
16670
|
-
}
|
|
16671
|
-
|
|
16672
|
-
|
|
16673
|
-
|
|
16674
|
-
var init_hub_binding = __esm({
|
|
16675
|
-
"src/lib/hub-binding.ts"() {
|
|
16970
|
+
}
|
|
16971
|
+
var SCOPE_FILE, LEGACY_HUB_SCOPE_FILE, LEGACY_HUB_SCOPE_FILE_PRE_RENAME, LEGACY_BASE_SCOPE_FILE, AXES, AXIS_ORDER, ADD_COMMAND, REPLACE_COMMAND, CLEAR_COMMAND, _gitDirCache;
|
|
16972
|
+
var init_worktree_scope = __esm({
|
|
16973
|
+
"src/lib/worktree-scope.ts"() {
|
|
16676
16974
|
"use strict";
|
|
16975
|
+
init_base_id();
|
|
16976
|
+
init_expected();
|
|
16677
16977
|
init_utils();
|
|
16678
|
-
|
|
16679
|
-
|
|
16680
|
-
|
|
16681
|
-
|
|
16682
|
-
|
|
16683
|
-
|
|
16684
|
-
|
|
16685
|
-
|
|
16686
|
-
|
|
16687
|
-
|
|
16688
|
-
|
|
16689
|
-
|
|
16690
|
-
|
|
16691
|
-
|
|
16692
|
-
|
|
16693
|
-
|
|
16694
|
-
|
|
16695
|
-
|
|
16978
|
+
SCOPE_FILE = "wayai-scope";
|
|
16979
|
+
LEGACY_HUB_SCOPE_FILE = "wayai-binding";
|
|
16980
|
+
LEGACY_HUB_SCOPE_FILE_PRE_RENAME = "wayai-lock";
|
|
16981
|
+
LEGACY_BASE_SCOPE_FILE = "wayai-base-binding";
|
|
16982
|
+
AXES = {
|
|
16983
|
+
hubs: {
|
|
16984
|
+
noun: "hub",
|
|
16985
|
+
idLabel: "hub_id (must be a UUID)",
|
|
16986
|
+
isValidId: (id) => UUID_RE2.test(id),
|
|
16987
|
+
selectorFor: (id) => id,
|
|
16988
|
+
legacyFiles: [LEGACY_HUB_SCOPE_FILE, LEGACY_HUB_SCOPE_FILE_PRE_RENAME]
|
|
16989
|
+
},
|
|
16990
|
+
bases: {
|
|
16991
|
+
noun: "base",
|
|
16992
|
+
idLabel: `base id (${PATH_SAFE_ID_RULE})`,
|
|
16993
|
+
isValidId: isPathSafeId,
|
|
16994
|
+
selectorFor: (id) => `bases/${id}`,
|
|
16995
|
+
legacyFiles: [LEGACY_BASE_SCOPE_FILE]
|
|
16996
|
+
}
|
|
16997
|
+
};
|
|
16998
|
+
AXIS_ORDER = ["hubs", "bases"];
|
|
16999
|
+
ADD_COMMAND = "wayai use --add";
|
|
17000
|
+
REPLACE_COMMAND = "wayai use";
|
|
17001
|
+
CLEAR_COMMAND = "wayai unbind";
|
|
16696
17002
|
}
|
|
16697
17003
|
});
|
|
16698
17004
|
|
|
@@ -16702,7 +17008,6 @@ __export(status_exports, {
|
|
|
16702
17008
|
parseArgs: () => parseArgs,
|
|
16703
17009
|
statusCommand: () => statusCommand
|
|
16704
17010
|
});
|
|
16705
|
-
import * as path8 from "path";
|
|
16706
17011
|
function parseArgs(args2) {
|
|
16707
17012
|
return { json: args2.includes("--json") };
|
|
16708
17013
|
}
|
|
@@ -16722,28 +17027,29 @@ function buildSkillState() {
|
|
|
16722
17027
|
paths: installs.map((i) => i.path)
|
|
16723
17028
|
};
|
|
16724
17029
|
}
|
|
16725
|
-
function buildWorkspaceState(
|
|
16726
|
-
if (!
|
|
17030
|
+
function buildWorkspaceState(resolved) {
|
|
17031
|
+
if (!resolved) return { scoped: false, path: null, hub_count: 0 };
|
|
16727
17032
|
const ws = detectWorkspace();
|
|
16728
|
-
const gitRoot = ws?.gitRoot ?? findGitRoot();
|
|
16729
17033
|
const hubCount = ws ? scanWorkspaceHubs(ws.workspaceDir).length : 0;
|
|
16730
|
-
|
|
16731
|
-
return { scoped: true, path: yamlPath, hub_count: hubCount };
|
|
17034
|
+
return { scoped: true, path: resolved.path, hub_count: hubCount };
|
|
16732
17035
|
}
|
|
16733
17036
|
async function statusCommand(args2, pkg2) {
|
|
16734
17037
|
const { json } = parseArgs(args2);
|
|
16735
17038
|
const config = readConfig();
|
|
16736
|
-
const
|
|
16737
|
-
const
|
|
17039
|
+
const resolvedRepo = resolveRepoConfig();
|
|
17040
|
+
const repoConfig = resolvedRepo?.config ?? null;
|
|
17041
|
+
const workspace = buildWorkspaceState(resolvedRepo);
|
|
17042
|
+
const repoScopeBlocker = resolvedRepo ? null : readRepoScopeBlocker();
|
|
16738
17043
|
const cachedCliLatest = readCachedLatest(CLI_CACHE_FILE);
|
|
16739
17044
|
const cliLatest = cachedCliLatest && isNewerVersion(cachedCliLatest, pkg2.version) ? cachedCliLatest : null;
|
|
16740
17045
|
const skill = buildSkillState();
|
|
16741
|
-
let
|
|
17046
|
+
let scope;
|
|
16742
17047
|
try {
|
|
16743
|
-
|
|
17048
|
+
scope = readScope();
|
|
16744
17049
|
} catch {
|
|
16745
|
-
|
|
17050
|
+
scope = emptyScope();
|
|
16746
17051
|
}
|
|
17052
|
+
const boundHubId = scope.hubs[0] ?? null;
|
|
16747
17053
|
if (!config) {
|
|
16748
17054
|
const snapshot2 = {
|
|
16749
17055
|
logged_in: false,
|
|
@@ -16756,6 +17062,8 @@ async function statusCommand(args2, pkg2) {
|
|
|
16756
17062
|
orgs: [],
|
|
16757
17063
|
active_org: null,
|
|
16758
17064
|
workspace,
|
|
17065
|
+
repo_scope_blocker: repoScopeBlocker,
|
|
17066
|
+
worktree_scope: scope,
|
|
16759
17067
|
worktree_binding: { hub_id: boundHubId },
|
|
16760
17068
|
worktree_lock: { hub_id: boundHubId }
|
|
16761
17069
|
};
|
|
@@ -16811,6 +17119,8 @@ async function statusCommand(args2, pkg2) {
|
|
|
16811
17119
|
orgs,
|
|
16812
17120
|
active_org: activeOrg,
|
|
16813
17121
|
workspace,
|
|
17122
|
+
repo_scope_blocker: repoScopeBlocker,
|
|
17123
|
+
worktree_scope: scope,
|
|
16814
17124
|
worktree_binding: { hub_id: boundHubId },
|
|
16815
17125
|
worktree_lock: { hub_id: boundHubId }
|
|
16816
17126
|
};
|
|
@@ -16839,11 +17149,22 @@ async function statusCommand(args2, pkg2) {
|
|
|
16839
17149
|
console.log(`Repository scope:`);
|
|
16840
17150
|
console.log(` Organization: ${orgLine}`);
|
|
16841
17151
|
console.log(` Hubs: ${workspace.hub_count}`);
|
|
17152
|
+
} else if (repoScopeBlocker?.kind === "conflict") {
|
|
17153
|
+
console.log("Repository scope: UNRESOLVED \u2014 two files name different organizations:");
|
|
17154
|
+
console.log(` ${WORKSPACE_MANIFEST_LABEL} -> ${repoScopeBlocker.manifest_organization_id}`);
|
|
17155
|
+
console.log(` ${ROOT_CONFIG_FILE} -> ${repoScopeBlocker.root_organization_id}`);
|
|
17156
|
+
console.log(` Delete or correct ${ROOT_CONFIG_FILE}; until then every command refuses.`);
|
|
17157
|
+
} else if (repoScopeBlocker?.kind === "invalid") {
|
|
17158
|
+
console.log(`Repository scope: UNRESOLVED \u2014 ${repoScopeBlocker.path} is unusable (${repoScopeBlocker.detail}).`);
|
|
16842
17159
|
} else {
|
|
16843
|
-
console.log(
|
|
17160
|
+
console.log(
|
|
17161
|
+
`No organization binding found in ${WORKSPACE_MANIFEST_LABEL} \u2014 run \`wayai init\` to scope this repo to an organization.`
|
|
17162
|
+
);
|
|
16844
17163
|
}
|
|
16845
|
-
if (
|
|
16846
|
-
console.log(
|
|
17164
|
+
if (scope.hubs.length > 0 || scope.bases.length > 0) {
|
|
17165
|
+
console.log("Worktree scope: (run `wayai unbind` to clear)");
|
|
17166
|
+
if (scope.hubs.length > 0) console.log(` Hubs: ${scope.hubs.join(", ")}`);
|
|
17167
|
+
if (scope.bases.length > 0) console.log(` Bases: ${scope.bases.join(", ")}`);
|
|
16847
17168
|
}
|
|
16848
17169
|
if (tokenValid === true && accessToken) {
|
|
16849
17170
|
await nudgeReportActions(config.api_url, accessToken);
|
|
@@ -16855,8 +17176,9 @@ var init_status = __esm({
|
|
|
16855
17176
|
init_config();
|
|
16856
17177
|
init_auth();
|
|
16857
17178
|
init_repo_config();
|
|
17179
|
+
init_workspace_manifest();
|
|
16858
17180
|
init_workspace();
|
|
16859
|
-
|
|
17181
|
+
init_worktree_scope();
|
|
16860
17182
|
init_api_client();
|
|
16861
17183
|
init_version_cache();
|
|
16862
17184
|
init_skill_version();
|
|
@@ -16938,7 +17260,7 @@ var init_constants = __esm({
|
|
|
16938
17260
|
});
|
|
16939
17261
|
|
|
16940
17262
|
// src/lib/workspace-files.ts
|
|
16941
|
-
import * as
|
|
17263
|
+
import * as fs9 from "fs";
|
|
16942
17264
|
import * as path9 from "path";
|
|
16943
17265
|
function perHubAgentsMd(hubFolderName) {
|
|
16944
17266
|
return [
|
|
@@ -16955,12 +17277,13 @@ function perHubAgentsMd(hubFolderName) {
|
|
|
16955
17277
|
].join("\n");
|
|
16956
17278
|
}
|
|
16957
17279
|
function isWorkspace(gitRoot) {
|
|
16958
|
-
if (
|
|
17280
|
+
if (fs9.existsSync(workspaceManifestPath(gitRoot))) return true;
|
|
17281
|
+
if (fs9.existsSync(rootConfigPath(gitRoot))) return true;
|
|
16959
17282
|
return isDirectory(resolveLayout(gitRoot).hubsDir);
|
|
16960
17283
|
}
|
|
16961
17284
|
function writeIfAbsent(filePath, content) {
|
|
16962
|
-
if (
|
|
16963
|
-
|
|
17285
|
+
if (fs9.existsSync(filePath)) return null;
|
|
17286
|
+
fs9.writeFileSync(filePath, content, "utf-8");
|
|
16964
17287
|
return path9.basename(filePath);
|
|
16965
17288
|
}
|
|
16966
17289
|
function ensureWorkspaceFiles(gitRoot) {
|
|
@@ -16978,6 +17301,7 @@ var init_workspace_files = __esm({
|
|
|
16978
17301
|
"use strict";
|
|
16979
17302
|
init_constants();
|
|
16980
17303
|
init_layout();
|
|
17304
|
+
init_workspace_manifest();
|
|
16981
17305
|
CLAUDE_MD_SHIM = "@AGENTS.md\n";
|
|
16982
17306
|
ROOT_AGENTS_MD = [
|
|
16983
17307
|
"# Working with WayAI",
|
|
@@ -17015,12 +17339,12 @@ __export(init_exports, {
|
|
|
17015
17339
|
initCommand: () => initCommand,
|
|
17016
17340
|
parseArgs: () => parseArgs3
|
|
17017
17341
|
});
|
|
17018
|
-
import { mkdirSync as
|
|
17342
|
+
import { mkdirSync as mkdirSync6 } from "fs";
|
|
17019
17343
|
import path10 from "path";
|
|
17020
17344
|
function ensureHubsDir(gitRoot) {
|
|
17021
17345
|
const hubsDir = resolveLayout(gitRoot).hubsDir;
|
|
17022
17346
|
if (isDirectory(hubsDir)) return null;
|
|
17023
|
-
|
|
17347
|
+
mkdirSync6(hubsDir, { recursive: true });
|
|
17024
17348
|
return `${path10.relative(gitRoot, hubsDir)}/`;
|
|
17025
17349
|
}
|
|
17026
17350
|
function parseArgs3(args2) {
|
|
@@ -17155,18 +17479,18 @@ var init_init = __esm({
|
|
|
17155
17479
|
});
|
|
17156
17480
|
|
|
17157
17481
|
// src/lib/fs-safety.ts
|
|
17158
|
-
import * as
|
|
17482
|
+
import * as fs10 from "fs";
|
|
17159
17483
|
import * as path11 from "path";
|
|
17160
17484
|
function fileHasBytes(abs, data) {
|
|
17161
17485
|
let st;
|
|
17162
17486
|
try {
|
|
17163
|
-
st =
|
|
17487
|
+
st = fs10.lstatSync(abs);
|
|
17164
17488
|
} catch {
|
|
17165
17489
|
return false;
|
|
17166
17490
|
}
|
|
17167
17491
|
if (!st.isFile() || st.isSymbolicLink()) return false;
|
|
17168
17492
|
try {
|
|
17169
|
-
return
|
|
17493
|
+
return fs10.readFileSync(abs).equals(data);
|
|
17170
17494
|
} catch {
|
|
17171
17495
|
return false;
|
|
17172
17496
|
}
|
|
@@ -17175,8 +17499,8 @@ function realpathContained(root, abs) {
|
|
|
17175
17499
|
let realRoot;
|
|
17176
17500
|
let realAbs;
|
|
17177
17501
|
try {
|
|
17178
|
-
realRoot =
|
|
17179
|
-
realAbs =
|
|
17502
|
+
realRoot = fs10.realpathSync(root);
|
|
17503
|
+
realAbs = fs10.realpathSync(abs);
|
|
17180
17504
|
} catch {
|
|
17181
17505
|
return false;
|
|
17182
17506
|
}
|
|
@@ -17184,13 +17508,13 @@ function realpathContained(root, abs) {
|
|
|
17184
17508
|
}
|
|
17185
17509
|
function mkdirTolerateRace(dir) {
|
|
17186
17510
|
try {
|
|
17187
|
-
|
|
17511
|
+
fs10.mkdirSync(dir);
|
|
17188
17512
|
return true;
|
|
17189
17513
|
} catch (err) {
|
|
17190
17514
|
if (err.code !== "EEXIST") throw err;
|
|
17191
17515
|
let st;
|
|
17192
17516
|
try {
|
|
17193
|
-
st =
|
|
17517
|
+
st = fs10.lstatSync(dir);
|
|
17194
17518
|
} catch {
|
|
17195
17519
|
st = void 0;
|
|
17196
17520
|
}
|
|
@@ -17202,7 +17526,7 @@ function ensureRealSubdirNoSymlink(root, target, create) {
|
|
|
17202
17526
|
const targetResolved = path11.resolve(target);
|
|
17203
17527
|
if (targetResolved !== rootResolved && !targetResolved.startsWith(rootResolved + path11.sep)) return false;
|
|
17204
17528
|
try {
|
|
17205
|
-
if (!
|
|
17529
|
+
if (!fs10.lstatSync(rootResolved).isDirectory()) return false;
|
|
17206
17530
|
} catch {
|
|
17207
17531
|
return false;
|
|
17208
17532
|
}
|
|
@@ -17213,7 +17537,7 @@ function ensureRealSubdirNoSymlink(root, target, create) {
|
|
|
17213
17537
|
cur = path11.join(cur, segment);
|
|
17214
17538
|
let st;
|
|
17215
17539
|
try {
|
|
17216
|
-
st =
|
|
17540
|
+
st = fs10.lstatSync(cur);
|
|
17217
17541
|
} catch {
|
|
17218
17542
|
st = void 0;
|
|
17219
17543
|
}
|
|
@@ -17230,8 +17554,8 @@ function ensureRealSubdirNoSymlink(root, target, create) {
|
|
|
17230
17554
|
function readFileNoFollow(root, abs) {
|
|
17231
17555
|
if (!ensureRealSubdirNoSymlink(root, path11.dirname(abs), false)) return null;
|
|
17232
17556
|
try {
|
|
17233
|
-
if (!
|
|
17234
|
-
return
|
|
17557
|
+
if (!fs10.lstatSync(abs).isFile()) return null;
|
|
17558
|
+
return fs10.readFileSync(abs);
|
|
17235
17559
|
} catch {
|
|
17236
17560
|
return null;
|
|
17237
17561
|
}
|
|
@@ -17241,11 +17565,11 @@ function writeFileNoFollow(root, abs, data) {
|
|
|
17241
17565
|
if (!ensureRealSubdirNoSymlink(root, parent, true)) return false;
|
|
17242
17566
|
let st;
|
|
17243
17567
|
try {
|
|
17244
|
-
st =
|
|
17568
|
+
st = fs10.lstatSync(abs);
|
|
17245
17569
|
} catch {
|
|
17246
17570
|
}
|
|
17247
|
-
if (st?.isSymbolicLink())
|
|
17248
|
-
|
|
17571
|
+
if (st?.isSymbolicLink()) fs10.rmSync(abs);
|
|
17572
|
+
fs10.writeFileSync(abs, data);
|
|
17249
17573
|
return true;
|
|
17250
17574
|
}
|
|
17251
17575
|
var init_fs_safety = __esm({
|
|
@@ -17255,7 +17579,7 @@ var init_fs_safety = __esm({
|
|
|
17255
17579
|
});
|
|
17256
17580
|
|
|
17257
17581
|
// src/lib/resource-files.ts
|
|
17258
|
-
import * as
|
|
17582
|
+
import * as fs11 from "fs";
|
|
17259
17583
|
import * as path12 from "path";
|
|
17260
17584
|
import * as crypto3 from "crypto";
|
|
17261
17585
|
function isBinaryFile(filename) {
|
|
@@ -17302,14 +17626,14 @@ function computeHash(data) {
|
|
|
17302
17626
|
}
|
|
17303
17627
|
function scanResourceFiles(dir, prefix = "") {
|
|
17304
17628
|
const files = [];
|
|
17305
|
-
const entries =
|
|
17629
|
+
const entries = fs11.readdirSync(dir, { withFileTypes: true });
|
|
17306
17630
|
for (const entry of entries) {
|
|
17307
17631
|
const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
17308
17632
|
if (entry.isDirectory()) {
|
|
17309
17633
|
files.push(...scanResourceFiles(path12.join(dir, entry.name), relPath));
|
|
17310
17634
|
} else if (entry.isFile()) {
|
|
17311
17635
|
const fullPath = path12.join(dir, entry.name);
|
|
17312
|
-
const stat2 =
|
|
17636
|
+
const stat2 = fs11.statSync(fullPath);
|
|
17313
17637
|
if (stat2.size > MAX_RESOURCE_FILE_SIZE3) {
|
|
17314
17638
|
console.warn(` Warning: skipping ${relPath} (${(stat2.size / 1024 / 1024).toFixed(1)}MB exceeds 10MB limit)`);
|
|
17315
17639
|
continue;
|
|
@@ -17319,7 +17643,7 @@ function scanResourceFiles(dir, prefix = "") {
|
|
|
17319
17643
|
mime_type: guessMimeType(entry.name),
|
|
17320
17644
|
file_size: stat2.size
|
|
17321
17645
|
};
|
|
17322
|
-
const data =
|
|
17646
|
+
const data = fs11.readFileSync(fullPath);
|
|
17323
17647
|
fileEntry.hash = computeHash(data);
|
|
17324
17648
|
if (isBinaryFile(entry.name)) {
|
|
17325
17649
|
fileEntry.content_base64 = data.toString("base64");
|
|
@@ -17379,7 +17703,7 @@ function writeResourceFileTree(resDir, files, root, log) {
|
|
|
17379
17703
|
return;
|
|
17380
17704
|
}
|
|
17381
17705
|
if (files.length === 0) {
|
|
17382
|
-
if (
|
|
17706
|
+
if (fs11.existsSync(resDir)) cleanOrphanFiles(resDir, "", /* @__PURE__ */ new Set(), root, log);
|
|
17383
17707
|
return;
|
|
17384
17708
|
}
|
|
17385
17709
|
const writtenPaths = /* @__PURE__ */ new Set();
|
|
@@ -17400,18 +17724,18 @@ function writeResourceFileTree(resDir, files, root, log) {
|
|
|
17400
17724
|
writtenPaths.delete(file.path);
|
|
17401
17725
|
}
|
|
17402
17726
|
}
|
|
17403
|
-
if (
|
|
17727
|
+
if (fs11.existsSync(resDir)) cleanOrphanFiles(resDir, "", writtenPaths, root, log);
|
|
17404
17728
|
}
|
|
17405
17729
|
function cleanOrphanFiles(dir, prefix, writtenPaths, root, log) {
|
|
17406
|
-
const entries =
|
|
17730
|
+
const entries = fs11.readdirSync(dir, { withFileTypes: true });
|
|
17407
17731
|
for (const entry of entries) {
|
|
17408
17732
|
const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
17409
17733
|
const fullPath = path12.join(dir, entry.name);
|
|
17410
17734
|
if (entry.isDirectory()) {
|
|
17411
17735
|
cleanOrphanFiles(fullPath, relPath, writtenPaths, root, log);
|
|
17412
|
-
if (
|
|
17736
|
+
if (fs11.readdirSync(fullPath).length === 0) fs11.rmdirSync(fullPath);
|
|
17413
17737
|
} else if (!writtenPaths.has(relPath)) {
|
|
17414
|
-
|
|
17738
|
+
fs11.unlinkSync(fullPath);
|
|
17415
17739
|
if (log && root) log.removed.push(path12.relative(root, fullPath));
|
|
17416
17740
|
}
|
|
17417
17741
|
}
|
|
@@ -17432,8 +17756,8 @@ async function downloadBinaryFiles(resDir, files, root, log) {
|
|
|
17432
17756
|
}
|
|
17433
17757
|
if (file.hash) {
|
|
17434
17758
|
try {
|
|
17435
|
-
const st =
|
|
17436
|
-
if (st.isFile() && !st.isSymbolicLink() && computeHash(
|
|
17759
|
+
const st = fs11.lstatSync(filePath);
|
|
17760
|
+
if (st.isFile() && !st.isSymbolicLink() && computeHash(fs11.readFileSync(filePath)) === file.hash) continue;
|
|
17437
17761
|
} catch {
|
|
17438
17762
|
}
|
|
17439
17763
|
}
|
|
@@ -17487,7 +17811,7 @@ var init_resource_files = __esm({
|
|
|
17487
17811
|
});
|
|
17488
17812
|
|
|
17489
17813
|
// src/lib/eval-attachments.ts
|
|
17490
|
-
import * as
|
|
17814
|
+
import * as fs12 from "fs";
|
|
17491
17815
|
import * as path13 from "path";
|
|
17492
17816
|
function resolveTurnAttachments(hubFolder, turn, label, bytesByHash) {
|
|
17493
17817
|
const raw = turn.attachments;
|
|
@@ -17511,7 +17835,7 @@ function resolveTurnAttachments(hubFolder, turn, label, bytesByHash) {
|
|
|
17511
17835
|
}
|
|
17512
17836
|
let stat2;
|
|
17513
17837
|
try {
|
|
17514
|
-
stat2 =
|
|
17838
|
+
stat2 = fs12.statSync(abs);
|
|
17515
17839
|
} catch {
|
|
17516
17840
|
}
|
|
17517
17841
|
if (!stat2?.isFile()) {
|
|
@@ -17525,7 +17849,7 @@ function resolveTurnAttachments(hubFolder, turn, label, bytesByHash) {
|
|
|
17525
17849
|
`${label}: attachment "${entry}" is ${(stat2.size / 1024 / 1024).toFixed(1)}MB, over the 10MB limit.`
|
|
17526
17850
|
);
|
|
17527
17851
|
}
|
|
17528
|
-
const data =
|
|
17852
|
+
const data = fs12.readFileSync(abs);
|
|
17529
17853
|
const hash = computeHash(data);
|
|
17530
17854
|
const fileName = path13.basename(abs);
|
|
17531
17855
|
const mimeType = guessMimeType(fileName) ?? "application/octet-stream";
|
|
@@ -17633,16 +17957,16 @@ async function downloadEvalAttachments(hubFolder, downloads) {
|
|
|
17633
17957
|
console.warn(` Warning: ${ATTACHMENTS_DIR}/ is not reachable inside the hub folder without a symlink; skipping attachment sync.`);
|
|
17634
17958
|
return result;
|
|
17635
17959
|
}
|
|
17636
|
-
if (!
|
|
17960
|
+
if (!fs12.existsSync(attachDir)) return result;
|
|
17637
17961
|
for (const dl of downloads) {
|
|
17638
17962
|
const abs = path13.resolve(hubFolder, dl.relPath);
|
|
17639
17963
|
if (abs !== attachDir && !abs.startsWith(attachDir + path13.sep)) continue;
|
|
17640
17964
|
let existing;
|
|
17641
17965
|
try {
|
|
17642
|
-
existing =
|
|
17966
|
+
existing = fs12.lstatSync(abs);
|
|
17643
17967
|
} catch {
|
|
17644
17968
|
}
|
|
17645
|
-
if (existing?.isFile() && !existing.isSymbolicLink() && computeHash(
|
|
17969
|
+
if (existing?.isFile() && !existing.isSymbolicLink() && computeHash(fs12.readFileSync(abs)) === dl.hash) {
|
|
17646
17970
|
continue;
|
|
17647
17971
|
}
|
|
17648
17972
|
try {
|
|
@@ -17660,11 +17984,11 @@ async function downloadEvalAttachments(hubFolder, downloads) {
|
|
|
17660
17984
|
}
|
|
17661
17985
|
}
|
|
17662
17986
|
const keep = new Set(downloads.map((d) => path13.resolve(hubFolder, d.relPath)));
|
|
17663
|
-
for (const name of
|
|
17987
|
+
for (const name of fs12.readdirSync(attachDir)) {
|
|
17664
17988
|
const abs = path13.join(attachDir, name);
|
|
17665
|
-
const st =
|
|
17989
|
+
const st = fs12.lstatSync(abs);
|
|
17666
17990
|
if ((st.isFile() || st.isSymbolicLink()) && !keep.has(abs)) {
|
|
17667
|
-
|
|
17991
|
+
fs12.rmSync(abs);
|
|
17668
17992
|
result.removed.push(path13.relative(hubFolder, abs));
|
|
17669
17993
|
}
|
|
17670
17994
|
}
|
|
@@ -17682,20 +18006,20 @@ var init_eval_attachments = __esm({
|
|
|
17682
18006
|
});
|
|
17683
18007
|
|
|
17684
18008
|
// src/lib/parser.ts
|
|
17685
|
-
import * as
|
|
18009
|
+
import * as fs13 from "fs";
|
|
17686
18010
|
import * as path14 from "path";
|
|
17687
|
-
import * as
|
|
18011
|
+
import * as yaml6 from "js-yaml";
|
|
17688
18012
|
function parseHubFolder(hubFolder, opts) {
|
|
17689
18013
|
const yamlPath = resolveHubYamlPath(hubFolder);
|
|
17690
18014
|
if (!yamlPath) {
|
|
17691
18015
|
throw expected(`hub.yaml not found in ${hubFolder}`);
|
|
17692
18016
|
}
|
|
17693
|
-
const yamlContent =
|
|
18017
|
+
const yamlContent = fs13.readFileSync(yamlPath, "utf-8");
|
|
17694
18018
|
let config;
|
|
17695
18019
|
try {
|
|
17696
|
-
config =
|
|
18020
|
+
config = yaml6.load(yamlContent);
|
|
17697
18021
|
} catch (err) {
|
|
17698
|
-
if (err instanceof
|
|
18022
|
+
if (err instanceof yaml6.YAMLException) {
|
|
17699
18023
|
throw expected(`Invalid YAML in ${yamlPath}: ${err.message}`);
|
|
17700
18024
|
}
|
|
17701
18025
|
throw err;
|
|
@@ -17718,8 +18042,8 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
17718
18042
|
if (typeof resolved.instructions === "string" && resolved.instructions.endsWith(".md")) {
|
|
17719
18043
|
const instrValue = resolved.instructions;
|
|
17720
18044
|
const instructionsPath = instrValue.startsWith("agents/") ? path14.join(hubFolder, instrValue) : path14.join(hubFolder, "agents", instrValue);
|
|
17721
|
-
if (
|
|
17722
|
-
resolved.instructions =
|
|
18045
|
+
if (fs13.existsSync(instructionsPath)) {
|
|
18046
|
+
resolved.instructions = fs13.readFileSync(instructionsPath, "utf-8");
|
|
17723
18047
|
} else {
|
|
17724
18048
|
throw expected(
|
|
17725
18049
|
`Agent instructions file not found: ${instructionsPath} (referenced by agent "${agent.name}")`
|
|
@@ -17727,8 +18051,8 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
17727
18051
|
}
|
|
17728
18052
|
} else if (resolved.instructions === void 0 && typeof agent.name === "string") {
|
|
17729
18053
|
const conventionPath = path14.join(hubFolder, "agents", `${slugify(agent.name)}.md`);
|
|
17730
|
-
if (
|
|
17731
|
-
resolved.instructions =
|
|
18054
|
+
if (fs13.existsSync(conventionPath)) {
|
|
18055
|
+
resolved.instructions = fs13.readFileSync(conventionPath, "utf-8");
|
|
17732
18056
|
}
|
|
17733
18057
|
}
|
|
17734
18058
|
return resolved;
|
|
@@ -17783,17 +18107,17 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
17783
18107
|
}
|
|
17784
18108
|
function scanEvalYamlFiles(hubFolder, bytesByHash) {
|
|
17785
18109
|
const evalsDir = path14.join(hubFolder, "evals");
|
|
17786
|
-
if (!
|
|
18110
|
+
if (!fs13.existsSync(evalsDir)) return [];
|
|
17787
18111
|
const evals = [];
|
|
17788
18112
|
const seen = /* @__PURE__ */ new Set();
|
|
17789
|
-
const topEntries =
|
|
18113
|
+
const topEntries = fs13.readdirSync(evalsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
17790
18114
|
for (const entry of topEntries) {
|
|
17791
18115
|
if (entry.isFile() && entry.name.endsWith(".yaml")) {
|
|
17792
18116
|
collectEval(evals, seen, path14.join(evalsDir, entry.name), `evals/${entry.name}`, null, hubFolder, bytesByHash);
|
|
17793
18117
|
} else if (entry.isDirectory()) {
|
|
17794
18118
|
const setName = entry.name;
|
|
17795
18119
|
const setDir = path14.join(evalsDir, setName);
|
|
17796
|
-
const setEntries =
|
|
18120
|
+
const setEntries = fs13.readdirSync(setDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
17797
18121
|
for (const sub of setEntries) {
|
|
17798
18122
|
if (sub.isDirectory()) {
|
|
17799
18123
|
throw expected(
|
|
@@ -17822,12 +18146,12 @@ function collectEval(evals, seen, filePath, relPath, setName, hubFolder, bytesBy
|
|
|
17822
18146
|
evals.push(evalEntry);
|
|
17823
18147
|
}
|
|
17824
18148
|
function parseEvalYaml(filePath, relPath, setName, hubFolder, bytesByHash) {
|
|
17825
|
-
const content =
|
|
18149
|
+
const content = fs13.readFileSync(filePath, "utf-8");
|
|
17826
18150
|
let raw;
|
|
17827
18151
|
try {
|
|
17828
|
-
raw =
|
|
18152
|
+
raw = yaml6.load(content);
|
|
17829
18153
|
} catch (err) {
|
|
17830
|
-
if (err instanceof
|
|
18154
|
+
if (err instanceof yaml6.YAMLException) {
|
|
17831
18155
|
throw expected(`Invalid YAML in ${relPath}: ${err.message}`);
|
|
17832
18156
|
}
|
|
17833
18157
|
throw err;
|
|
@@ -17925,10 +18249,10 @@ function parseFixtureField(raw, label, key) {
|
|
|
17925
18249
|
}
|
|
17926
18250
|
function scanJourneyYamlFiles(hubFolder, bytesByHash) {
|
|
17927
18251
|
const journeysDir = path14.join(hubFolder, "journeys");
|
|
17928
|
-
if (!
|
|
18252
|
+
if (!fs13.existsSync(journeysDir)) return [];
|
|
17929
18253
|
const journeys = [];
|
|
17930
18254
|
const seen = /* @__PURE__ */ new Set();
|
|
17931
|
-
const entries =
|
|
18255
|
+
const entries = fs13.readdirSync(journeysDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
17932
18256
|
for (const entry of entries) {
|
|
17933
18257
|
if (entry.isDirectory()) {
|
|
17934
18258
|
throw expected(
|
|
@@ -17949,12 +18273,12 @@ function scanJourneyYamlFiles(hubFolder, bytesByHash) {
|
|
|
17949
18273
|
return journeys;
|
|
17950
18274
|
}
|
|
17951
18275
|
function parseJourneyYaml(filePath, relPath, hubFolder, bytesByHash) {
|
|
17952
|
-
const content =
|
|
18276
|
+
const content = fs13.readFileSync(filePath, "utf-8");
|
|
17953
18277
|
let raw;
|
|
17954
18278
|
try {
|
|
17955
|
-
raw =
|
|
18279
|
+
raw = yaml6.load(content);
|
|
17956
18280
|
} catch (err) {
|
|
17957
|
-
if (err instanceof
|
|
18281
|
+
if (err instanceof yaml6.YAMLException) {
|
|
17958
18282
|
throw expected(`Invalid YAML in ${relPath}: ${err.message}`);
|
|
17959
18283
|
}
|
|
17960
18284
|
throw err;
|
|
@@ -18005,18 +18329,18 @@ function parseJourneyYaml(filePath, relPath, hubFolder, bytesByHash) {
|
|
|
18005
18329
|
}
|
|
18006
18330
|
function scanAgentYamlFiles(hubFolder) {
|
|
18007
18331
|
const agentsDir = path14.join(hubFolder, "agents");
|
|
18008
|
-
if (!
|
|
18009
|
-
const yamlFiles =
|
|
18332
|
+
if (!fs13.existsSync(agentsDir)) return [];
|
|
18333
|
+
const yamlFiles = fs13.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml")).sort();
|
|
18010
18334
|
if (yamlFiles.length === 0) return [];
|
|
18011
18335
|
const agents = [];
|
|
18012
18336
|
for (const file of yamlFiles) {
|
|
18013
18337
|
const filePath = path14.join(agentsDir, file);
|
|
18014
|
-
const content =
|
|
18338
|
+
const content = fs13.readFileSync(filePath, "utf-8");
|
|
18015
18339
|
let agent;
|
|
18016
18340
|
try {
|
|
18017
|
-
agent =
|
|
18341
|
+
agent = yaml6.load(content);
|
|
18018
18342
|
} catch (err) {
|
|
18019
|
-
if (err instanceof
|
|
18343
|
+
if (err instanceof yaml6.YAMLException) {
|
|
18020
18344
|
throw expected(`Invalid YAML in agents/${file}: ${err.message}`);
|
|
18021
18345
|
}
|
|
18022
18346
|
throw err;
|
|
@@ -18046,7 +18370,7 @@ function parseResources(hubFolder, configResources) {
|
|
|
18046
18370
|
if (res.skill_name) resource.skill_name = res.skill_name;
|
|
18047
18371
|
const resSlug = slugify(resource.name);
|
|
18048
18372
|
const resDir = path14.join(resourcesDir, resSlug);
|
|
18049
|
-
if (
|
|
18373
|
+
if (fs13.existsSync(resDir)) {
|
|
18050
18374
|
const files = scanResourceFiles(resDir, "");
|
|
18051
18375
|
if (files.length > 0) {
|
|
18052
18376
|
resource.files = files;
|
|
@@ -18094,9 +18418,9 @@ var init_diff_display = __esm({
|
|
|
18094
18418
|
});
|
|
18095
18419
|
|
|
18096
18420
|
// src/lib/yaml-writer.ts
|
|
18097
|
-
import * as
|
|
18421
|
+
import * as fs14 from "fs";
|
|
18098
18422
|
import * as path15 from "path";
|
|
18099
|
-
import * as
|
|
18423
|
+
import * as yaml7 from "js-yaml";
|
|
18100
18424
|
function writeFileIfChanged(hubFolder, absPath, content, log) {
|
|
18101
18425
|
const buf = Buffer.from(content, "utf-8");
|
|
18102
18426
|
if (fileHasBytes(absPath, buf)) return;
|
|
@@ -18145,15 +18469,15 @@ function buildEvalYamlObject(evalEntry, slug) {
|
|
|
18145
18469
|
function writeHubFolder(hubFolder, payload, options = {}) {
|
|
18146
18470
|
const log = { changed: [], removed: [] };
|
|
18147
18471
|
const agentsDir = path15.join(hubFolder, "agents");
|
|
18148
|
-
if (!
|
|
18149
|
-
|
|
18472
|
+
if (!fs14.existsSync(hubFolder)) {
|
|
18473
|
+
fs14.mkdirSync(hubFolder, { recursive: true });
|
|
18150
18474
|
}
|
|
18151
|
-
if (!
|
|
18152
|
-
|
|
18475
|
+
if (!fs14.existsSync(agentsDir)) {
|
|
18476
|
+
fs14.mkdirSync(agentsDir, { recursive: true });
|
|
18153
18477
|
}
|
|
18154
18478
|
const yamlPayload = buildYamlPayload(payload);
|
|
18155
18479
|
const agentFiles = extractAgentFiles(payload);
|
|
18156
|
-
const yamlContent =
|
|
18480
|
+
const yamlContent = yaml7.dump(yamlPayload, YAML_DUMP_OPTIONS);
|
|
18157
18481
|
writeFileIfChanged(hubFolder, path15.join(hubFolder, "hub.yaml"), yamlContent, log);
|
|
18158
18482
|
if (options.seedAgentContext ?? true) {
|
|
18159
18483
|
for (const seeded of [
|
|
@@ -18164,8 +18488,8 @@ function writeHubFolder(hubFolder, payload, options = {}) {
|
|
|
18164
18488
|
}
|
|
18165
18489
|
}
|
|
18166
18490
|
const oldYamlPath = path15.join(hubFolder, "wayai.yaml");
|
|
18167
|
-
if (
|
|
18168
|
-
|
|
18491
|
+
if (fs14.existsSync(oldYamlPath)) {
|
|
18492
|
+
fs14.unlinkSync(oldYamlPath);
|
|
18169
18493
|
log.removed.push(path15.relative(hubFolder, oldYamlPath));
|
|
18170
18494
|
}
|
|
18171
18495
|
const yamlSlugs = writeAgentYamlFiles(hubFolder, agentsDir, payload.agents || [], log);
|
|
@@ -18174,20 +18498,20 @@ function writeHubFolder(hubFolder, payload, options = {}) {
|
|
|
18174
18498
|
mdSlugs.add(slug);
|
|
18175
18499
|
writeFileIfChanged(hubFolder, path15.join(agentsDir, `${slug}.md`), content, log);
|
|
18176
18500
|
}
|
|
18177
|
-
const existingFiles =
|
|
18501
|
+
const existingFiles = fs14.readdirSync(agentsDir);
|
|
18178
18502
|
for (const file of existingFiles) {
|
|
18179
18503
|
if (file.endsWith(".yaml")) {
|
|
18180
18504
|
const slug = file.slice(0, -5);
|
|
18181
18505
|
if (!yamlSlugs.has(slug)) {
|
|
18182
18506
|
const orphan = path15.join(agentsDir, file);
|
|
18183
|
-
|
|
18507
|
+
fs14.unlinkSync(orphan);
|
|
18184
18508
|
log.removed.push(path15.relative(hubFolder, orphan));
|
|
18185
18509
|
}
|
|
18186
18510
|
} else if (file.endsWith(".md")) {
|
|
18187
18511
|
const slug = file.slice(0, -3);
|
|
18188
18512
|
if (!mdSlugs.has(slug)) {
|
|
18189
18513
|
const orphan = path15.join(agentsDir, file);
|
|
18190
|
-
|
|
18514
|
+
fs14.unlinkSync(orphan);
|
|
18191
18515
|
log.removed.push(path15.relative(hubFolder, orphan));
|
|
18192
18516
|
}
|
|
18193
18517
|
}
|
|
@@ -18200,10 +18524,10 @@ function writeHubFolder(hubFolder, payload, options = {}) {
|
|
|
18200
18524
|
function setPreviewLabelInHubYaml(hubFolder, label) {
|
|
18201
18525
|
const yamlPath = resolveHubYamlPath(hubFolder);
|
|
18202
18526
|
if (!yamlPath) return;
|
|
18203
|
-
const obj =
|
|
18527
|
+
const obj = yaml7.load(fs14.readFileSync(yamlPath, "utf-8")) ?? {};
|
|
18204
18528
|
if (label) obj.preview_label = label;
|
|
18205
18529
|
else delete obj.preview_label;
|
|
18206
|
-
|
|
18530
|
+
fs14.writeFileSync(yamlPath, yaml7.dump(obj, YAML_DUMP_OPTIONS), "utf-8");
|
|
18207
18531
|
}
|
|
18208
18532
|
function buildYamlPayload(payload) {
|
|
18209
18533
|
const result = {
|
|
@@ -18248,7 +18572,7 @@ function writeAgentYamlFiles(hubFolder, agentsDir, agents, log) {
|
|
|
18248
18572
|
slugs.add(slug);
|
|
18249
18573
|
const entry = { ...agent };
|
|
18250
18574
|
delete entry.instructions;
|
|
18251
|
-
const yamlContent =
|
|
18575
|
+
const yamlContent = yaml7.dump(entry, YAML_DUMP_OPTIONS);
|
|
18252
18576
|
writeFileIfChanged(hubFolder, path15.join(agentsDir, `${slug}.yaml`), yamlContent, log);
|
|
18253
18577
|
}
|
|
18254
18578
|
return slugs;
|
|
@@ -18268,17 +18592,17 @@ function extractAgentFiles(payload) {
|
|
|
18268
18592
|
function writeEvalYamlFiles(hubFolder, evals, log) {
|
|
18269
18593
|
const evalsDir = path15.join(hubFolder, "evals");
|
|
18270
18594
|
if (evals.length === 0) {
|
|
18271
|
-
if (
|
|
18595
|
+
if (fs14.existsSync(evalsDir)) {
|
|
18272
18596
|
cleanEvalOrphans(hubFolder, evalsDir, /* @__PURE__ */ new Set(), log);
|
|
18273
18597
|
try {
|
|
18274
|
-
if (
|
|
18598
|
+
if (fs14.readdirSync(evalsDir).length === 0) fs14.rmdirSync(evalsDir);
|
|
18275
18599
|
} catch {
|
|
18276
18600
|
}
|
|
18277
18601
|
}
|
|
18278
18602
|
return;
|
|
18279
18603
|
}
|
|
18280
|
-
if (!
|
|
18281
|
-
|
|
18604
|
+
if (!fs14.existsSync(evalsDir)) {
|
|
18605
|
+
fs14.mkdirSync(evalsDir, { recursive: true });
|
|
18282
18606
|
}
|
|
18283
18607
|
const writtenRelPaths = /* @__PURE__ */ new Set();
|
|
18284
18608
|
for (const evalEntry of evals) {
|
|
@@ -18292,42 +18616,42 @@ function writeEvalYamlFiles(hubFolder, evals, log) {
|
|
|
18292
18616
|
}
|
|
18293
18617
|
if (setName) {
|
|
18294
18618
|
const setDir = path15.join(evalsDir, setName);
|
|
18295
|
-
if (!
|
|
18296
|
-
|
|
18619
|
+
if (!fs14.existsSync(setDir)) {
|
|
18620
|
+
fs14.mkdirSync(setDir, { recursive: true });
|
|
18297
18621
|
}
|
|
18298
18622
|
}
|
|
18299
|
-
const yamlContent =
|
|
18623
|
+
const yamlContent = yaml7.dump(buildEvalYamlObject(evalEntry, slug), YAML_DUMP_OPTIONS);
|
|
18300
18624
|
writeFileIfChanged(hubFolder, targetPath, yamlContent, log);
|
|
18301
18625
|
writtenRelPaths.add(relPath);
|
|
18302
18626
|
}
|
|
18303
18627
|
cleanEvalOrphans(hubFolder, evalsDir, writtenRelPaths, log);
|
|
18304
18628
|
}
|
|
18305
18629
|
function cleanEvalOrphans(hubFolder, evalsDir, writtenRelPaths, log) {
|
|
18306
|
-
const entries =
|
|
18630
|
+
const entries = fs14.readdirSync(evalsDir, { withFileTypes: true });
|
|
18307
18631
|
for (const entry of entries) {
|
|
18308
18632
|
const fullPath = path15.join(evalsDir, entry.name);
|
|
18309
18633
|
if (entry.isFile()) {
|
|
18310
18634
|
if (entry.name.endsWith(".yaml") && !writtenRelPaths.has(entry.name)) {
|
|
18311
|
-
|
|
18635
|
+
fs14.unlinkSync(fullPath);
|
|
18312
18636
|
log.removed.push(path15.relative(hubFolder, fullPath));
|
|
18313
18637
|
}
|
|
18314
18638
|
continue;
|
|
18315
18639
|
}
|
|
18316
18640
|
if (entry.isDirectory()) {
|
|
18317
18641
|
const setName = entry.name;
|
|
18318
|
-
const subEntries =
|
|
18642
|
+
const subEntries = fs14.readdirSync(fullPath, { withFileTypes: true });
|
|
18319
18643
|
for (const sub of subEntries) {
|
|
18320
18644
|
if (sub.isFile() && sub.name.endsWith(".yaml")) {
|
|
18321
18645
|
const relPath = `${setName}/${sub.name}`;
|
|
18322
18646
|
if (!writtenRelPaths.has(relPath)) {
|
|
18323
18647
|
const orphan = path15.join(fullPath, sub.name);
|
|
18324
|
-
|
|
18648
|
+
fs14.unlinkSync(orphan);
|
|
18325
18649
|
log.removed.push(path15.relative(hubFolder, orphan));
|
|
18326
18650
|
}
|
|
18327
18651
|
}
|
|
18328
18652
|
}
|
|
18329
18653
|
try {
|
|
18330
|
-
if (
|
|
18654
|
+
if (fs14.readdirSync(fullPath).length === 0) fs14.rmdirSync(fullPath);
|
|
18331
18655
|
} catch {
|
|
18332
18656
|
}
|
|
18333
18657
|
}
|
|
@@ -18366,35 +18690,35 @@ function buildJourneyYamlObject(journeyEntry, slug) {
|
|
|
18366
18690
|
function writeJourneyYamlFiles(hubFolder, journeys, log) {
|
|
18367
18691
|
const journeysDir = path15.join(hubFolder, "journeys");
|
|
18368
18692
|
if (journeys.length === 0) {
|
|
18369
|
-
if (
|
|
18693
|
+
if (fs14.existsSync(journeysDir)) {
|
|
18370
18694
|
cleanJourneyOrphans(hubFolder, journeysDir, /* @__PURE__ */ new Set(), log);
|
|
18371
18695
|
try {
|
|
18372
|
-
if (
|
|
18696
|
+
if (fs14.readdirSync(journeysDir).length === 0) fs14.rmdirSync(journeysDir);
|
|
18373
18697
|
} catch {
|
|
18374
18698
|
}
|
|
18375
18699
|
}
|
|
18376
18700
|
return;
|
|
18377
18701
|
}
|
|
18378
|
-
if (!
|
|
18379
|
-
|
|
18702
|
+
if (!fs14.existsSync(journeysDir)) {
|
|
18703
|
+
fs14.mkdirSync(journeysDir, { recursive: true });
|
|
18380
18704
|
}
|
|
18381
18705
|
const writtenFiles = /* @__PURE__ */ new Set();
|
|
18382
18706
|
const usedSlugs = /* @__PURE__ */ new Set();
|
|
18383
18707
|
for (const journeyEntry of journeys) {
|
|
18384
18708
|
const slug = ensureUniqueSlug(slugify(journeyEntry.name), usedSlugs);
|
|
18385
18709
|
const fileName = `${slug}.yaml`;
|
|
18386
|
-
const yamlContent =
|
|
18710
|
+
const yamlContent = yaml7.dump(buildJourneyYamlObject(journeyEntry, slug), YAML_DUMP_OPTIONS);
|
|
18387
18711
|
writeFileIfChanged(hubFolder, path15.join(journeysDir, fileName), yamlContent, log);
|
|
18388
18712
|
writtenFiles.add(fileName);
|
|
18389
18713
|
}
|
|
18390
18714
|
cleanJourneyOrphans(hubFolder, journeysDir, writtenFiles, log);
|
|
18391
18715
|
}
|
|
18392
18716
|
function cleanJourneyOrphans(hubFolder, journeysDir, writtenFiles, log) {
|
|
18393
|
-
const entries =
|
|
18717
|
+
const entries = fs14.readdirSync(journeysDir, { withFileTypes: true });
|
|
18394
18718
|
for (const entry of entries) {
|
|
18395
18719
|
if (entry.isFile() && entry.name.endsWith(".yaml") && !writtenFiles.has(entry.name)) {
|
|
18396
18720
|
const orphan = path15.join(journeysDir, entry.name);
|
|
18397
|
-
|
|
18721
|
+
fs14.unlinkSync(orphan);
|
|
18398
18722
|
log.removed.push(path15.relative(hubFolder, orphan));
|
|
18399
18723
|
}
|
|
18400
18724
|
}
|
|
@@ -18408,12 +18732,12 @@ function writeResourceFiles(hubFolder, resources, log) {
|
|
|
18408
18732
|
const resDir = path15.join(resourcesDir, resSlug);
|
|
18409
18733
|
writeResourceFileTree(resDir, resource.files || [], hubFolder, log);
|
|
18410
18734
|
}
|
|
18411
|
-
if (
|
|
18412
|
-
const existingDirs =
|
|
18735
|
+
if (fs14.existsSync(resourcesDir)) {
|
|
18736
|
+
const existingDirs = fs14.readdirSync(resourcesDir, { withFileTypes: true });
|
|
18413
18737
|
for (const entry of existingDirs) {
|
|
18414
18738
|
if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
|
|
18415
18739
|
const orphanDir = path15.join(resourcesDir, entry.name);
|
|
18416
|
-
|
|
18740
|
+
fs14.rmSync(orphanDir, { recursive: true, force: true });
|
|
18417
18741
|
log.removed.push(`${path15.relative(hubFolder, orphanDir)}/`);
|
|
18418
18742
|
}
|
|
18419
18743
|
}
|
|
@@ -18501,35 +18825,16 @@ var init_terminal_output = __esm({
|
|
|
18501
18825
|
}
|
|
18502
18826
|
});
|
|
18503
18827
|
|
|
18504
|
-
// src/lib/base-id.ts
|
|
18505
|
-
function isValidBaseId(id) {
|
|
18506
|
-
return id.length > 0 && id.length <= BASE_ID_MAX_LENGTH && BASE_ID_RE.test(id);
|
|
18507
|
-
}
|
|
18508
|
-
function isPathSafeId(id) {
|
|
18509
|
-
return PATH_SAFE_ID_RE.test(id);
|
|
18510
|
-
}
|
|
18511
|
-
var BASE_ID_MAX_LENGTH, BASE_ID_RE, BASE_ID_RULE, PATH_SAFE_ID_RE, PATH_SAFE_ID_RULE;
|
|
18512
|
-
var init_base_id = __esm({
|
|
18513
|
-
"src/lib/base-id.ts"() {
|
|
18514
|
-
"use strict";
|
|
18515
|
-
BASE_ID_MAX_LENGTH = 128;
|
|
18516
|
-
BASE_ID_RE = /^[A-Za-z0-9_][A-Za-z0-9_-]*$/;
|
|
18517
|
-
BASE_ID_RULE = `letters, digits, \`-\` and \`_\`, starting with a letter, digit or \`_\`, ${BASE_ID_MAX_LENGTH} characters or fewer`;
|
|
18518
|
-
PATH_SAFE_ID_RE = /^(?!\.\.?$)[A-Za-z0-9._-]{1,256}$/;
|
|
18519
|
-
PATH_SAFE_ID_RULE = "letters, digits, dot, dash and underscore, with no path separators, not `.` or `..` alone, 256 characters or fewer";
|
|
18520
|
-
}
|
|
18521
|
-
});
|
|
18522
|
-
|
|
18523
18828
|
// src/lib/base-workspace.ts
|
|
18524
|
-
import * as
|
|
18829
|
+
import * as fs15 from "fs";
|
|
18525
18830
|
import * as path17 from "path";
|
|
18526
|
-
import * as
|
|
18831
|
+
import * as yaml8 from "js-yaml";
|
|
18527
18832
|
function readBaseMeta(folder) {
|
|
18528
18833
|
const bytes = readFileNoFollow(folder, path17.join(folder, BASE_META_FILE));
|
|
18529
18834
|
if (bytes === null) return null;
|
|
18530
18835
|
let doc;
|
|
18531
18836
|
try {
|
|
18532
|
-
doc =
|
|
18837
|
+
doc = yaml8.load(bytes.toString("utf-8"));
|
|
18533
18838
|
} catch {
|
|
18534
18839
|
return null;
|
|
18535
18840
|
}
|
|
@@ -18539,7 +18844,7 @@ function readBaseMeta(folder) {
|
|
|
18539
18844
|
function listBaseFolders(basesDir) {
|
|
18540
18845
|
let entries;
|
|
18541
18846
|
try {
|
|
18542
|
-
entries =
|
|
18847
|
+
entries = fs15.readdirSync(basesDir).filter((entry) => !entry.startsWith("."));
|
|
18543
18848
|
} catch {
|
|
18544
18849
|
return [];
|
|
18545
18850
|
}
|
|
@@ -18618,9 +18923,15 @@ function targetBaseId(target, selector) {
|
|
|
18618
18923
|
if (selector && !selector.includes("/") && !selector.includes(path17.sep)) return selector;
|
|
18619
18924
|
return target.exists ? null : path17.basename(target.folder);
|
|
18620
18925
|
}
|
|
18926
|
+
function resolveBaseSelectorToId(gitRoot, selector) {
|
|
18927
|
+
if (!gitRoot || selector.includes("/") || selector.includes(path17.sep)) return selector;
|
|
18928
|
+
if (!isPathSafeId(selector)) return selector;
|
|
18929
|
+
const id = readBaseMeta(path17.join(resolveBasesDir(gitRoot), selector))?.base_id;
|
|
18930
|
+
return typeof id === "string" && isPathSafeId(id) ? id : selector;
|
|
18931
|
+
}
|
|
18621
18932
|
function hasBaseMetaFile(folder) {
|
|
18622
18933
|
try {
|
|
18623
|
-
return
|
|
18934
|
+
return fs15.lstatSync(path17.join(folder, BASE_META_FILE)).isFile();
|
|
18624
18935
|
} catch {
|
|
18625
18936
|
return false;
|
|
18626
18937
|
}
|
|
@@ -18638,25 +18949,17 @@ var init_base_workspace = __esm({
|
|
|
18638
18949
|
});
|
|
18639
18950
|
|
|
18640
18951
|
// src/lib/subtree-routing.ts
|
|
18641
|
-
import * as fs15 from "fs";
|
|
18642
18952
|
import * as path18 from "path";
|
|
18643
|
-
import * as yaml7 from "js-yaml";
|
|
18644
18953
|
function readRepoDefaults(gitRoot) {
|
|
18645
|
-
const
|
|
18646
|
-
|
|
18647
|
-
|
|
18648
|
-
doc = yaml7.load(fs15.readFileSync(file, "utf-8"));
|
|
18649
|
-
} catch {
|
|
18650
|
-
return {};
|
|
18651
|
-
}
|
|
18652
|
-
if (!doc || typeof doc !== "object") return {};
|
|
18653
|
-
const raw = doc;
|
|
18954
|
+
const load11 = loadWorkspaceManifest(gitRoot);
|
|
18955
|
+
if (load11.kind !== "ok") return {};
|
|
18956
|
+
const raw = load11.doc;
|
|
18654
18957
|
const str = (v) => {
|
|
18655
18958
|
if (typeof v !== "string" || !v.trim()) return void 0;
|
|
18656
18959
|
const value = v.trim();
|
|
18657
18960
|
if (value.includes("/") || value.includes(path18.sep) || value === "." || value === "..") {
|
|
18658
18961
|
console.warn(
|
|
18659
|
-
`Warning: ignoring ${JSON.stringify(value)} in ${
|
|
18962
|
+
`Warning: ignoring ${JSON.stringify(value)} in ${WORKSPACE_MANIFEST_LABEL} \u2014 a default names a hub or base, not a path.`
|
|
18660
18963
|
);
|
|
18661
18964
|
return void 0;
|
|
18662
18965
|
}
|
|
@@ -18690,7 +18993,7 @@ function firstSegment(p) {
|
|
|
18690
18993
|
const [head] = normalized.split("/").filter(Boolean);
|
|
18691
18994
|
return head ?? p;
|
|
18692
18995
|
}
|
|
18693
|
-
function
|
|
18996
|
+
function resolveSelectorSubtree(layout, selector, cwd) {
|
|
18694
18997
|
const parts = selector.split(path18.sep).join("/").split("/").filter(Boolean);
|
|
18695
18998
|
const qualified = parts[0] === WAYAI_LAYOUT.wsDir ? parts.slice(1) : parts;
|
|
18696
18999
|
if (qualified.length > 1) {
|
|
@@ -18744,11 +19047,11 @@ function routeSubtree(options) {
|
|
|
18744
19047
|
return {
|
|
18745
19048
|
ok: false,
|
|
18746
19049
|
refusal: [
|
|
18747
|
-
`\`wayai ${verb}\` does not take --org: it operates on the organization named by
|
|
19050
|
+
`\`wayai ${verb}\` does not take --org: it operates on the organization named by ${WORKSPACE_MANIFEST_LABEL}.`,
|
|
18748
19051
|
"",
|
|
18749
19052
|
"To act on another organization:",
|
|
18750
19053
|
" wayai bases <command> --org <uuid> # the Data surface honors it",
|
|
18751
|
-
" # or run from a checkout whose
|
|
19054
|
+
" # or run from a checkout whose workspace manifest names that organization"
|
|
18752
19055
|
].join("\n")
|
|
18753
19056
|
};
|
|
18754
19057
|
}
|
|
@@ -18756,7 +19059,7 @@ function routeSubtree(options) {
|
|
|
18756
19059
|
if (hubFlag !== void 0 && baseFlag !== void 0) {
|
|
18757
19060
|
return { ok: false, refusal: mixedInvocationRefusal(verb, hubFlag, baseFlag) };
|
|
18758
19061
|
}
|
|
18759
|
-
const fromPositional = positional !== void 0 ?
|
|
19062
|
+
const fromPositional = positional !== void 0 ? resolveSelectorSubtree(layout, positional, cwd) : void 0;
|
|
18760
19063
|
if (fromPositional?.kind === "both") {
|
|
18761
19064
|
return {
|
|
18762
19065
|
ok: false,
|
|
@@ -18815,15 +19118,15 @@ function requireSubtree(verb, args2, gitRoot) {
|
|
|
18815
19118
|
}
|
|
18816
19119
|
return { subtree: result.subtree, selector: result.selector };
|
|
18817
19120
|
}
|
|
18818
|
-
var
|
|
19121
|
+
var VALUE_FLAGS;
|
|
18819
19122
|
var init_subtree_routing = __esm({
|
|
18820
19123
|
"src/lib/subtree-routing.ts"() {
|
|
18821
19124
|
"use strict";
|
|
18822
19125
|
init_layout();
|
|
18823
19126
|
init_terminal_output();
|
|
19127
|
+
init_workspace_manifest();
|
|
18824
19128
|
init_workspace();
|
|
18825
19129
|
init_base_workspace();
|
|
18826
|
-
REPO_DEFAULTS_FILE = "wayai.yaml";
|
|
18827
19130
|
VALUE_FLAGS = /* @__PURE__ */ new Set(["--hub", "--base", "--label", "--org"]);
|
|
18828
19131
|
}
|
|
18829
19132
|
});
|
|
@@ -18850,23 +19153,23 @@ async function createDataClient(orgId) {
|
|
|
18850
19153
|
if (selected !== void 0 && !UUID_RE2.test(selected)) {
|
|
18851
19154
|
throw expected(`Invalid --org: ${JSON.stringify(selected)}. Expected an organization UUID.`);
|
|
18852
19155
|
}
|
|
18853
|
-
const org = selected ??
|
|
19156
|
+
const org = selected ?? readRepoConfigUnlessBlocked()?.organization_id;
|
|
18854
19157
|
async function requireOrgForSetupRoute(what) {
|
|
18855
19158
|
const orgId2 = org ?? (await api.me()).org_id;
|
|
18856
19159
|
if (!orgId2) {
|
|
18857
19160
|
throw expected(
|
|
18858
|
-
`No organization to ${what} against. Pass --org <uuid>, or run this from a repo
|
|
19161
|
+
`No organization to ${what} against. Pass --org <uuid>, or run this from a repo scoped by \`wayai init\`.`
|
|
18859
19162
|
);
|
|
18860
19163
|
}
|
|
18861
19164
|
return orgId2;
|
|
18862
19165
|
}
|
|
18863
19166
|
return {
|
|
18864
|
-
async request(method,
|
|
18865
|
-
const envelope = await api.dataRequest(method,
|
|
19167
|
+
async request(method, path35, body) {
|
|
19168
|
+
const envelope = await api.dataRequest(method, path35, body, org);
|
|
18866
19169
|
return envelope.data;
|
|
18867
19170
|
},
|
|
18868
|
-
async requestRaw(method,
|
|
18869
|
-
const body_ = await api.dataRequest(method,
|
|
19171
|
+
async requestRaw(method, path35, body) {
|
|
19172
|
+
const body_ = await api.dataRequest(method, path35, body, org);
|
|
18870
19173
|
return body_;
|
|
18871
19174
|
},
|
|
18872
19175
|
async collectPages(makePath) {
|
|
@@ -18940,40 +19243,8 @@ var init_client = __esm({
|
|
|
18940
19243
|
}
|
|
18941
19244
|
});
|
|
18942
19245
|
|
|
18943
|
-
// src/lib/base-binding.ts
|
|
18944
|
-
var binding2, getBaseBindingPath, readBaseBinding, writeBaseBinding, clearBaseBinding, autoBindBaseIfUnbound, assertBaseMatchesBinding, assertNoBindingBlocksBaseCreation;
|
|
18945
|
-
var init_base_binding = __esm({
|
|
18946
|
-
"src/lib/base-binding.ts"() {
|
|
18947
|
-
"use strict";
|
|
18948
|
-
init_base_id();
|
|
18949
|
-
init_worktree_binding();
|
|
18950
|
-
binding2 = createWorktreeBinding({
|
|
18951
|
-
filename: "wayai-base-binding",
|
|
18952
|
-
// `isPathSafeId`, not the API's base-id rule. The tripwire's duty is that a
|
|
18953
|
-
// garbled or multi-line file read as unbound, which this grammar delivers;
|
|
18954
|
-
// applying the mint rule instead would refuse to bind a base whose stored id
|
|
18955
|
-
// predates it — a base the API still serves — and so lock the CLI out of the
|
|
18956
|
-
// one workflow that could migrate off it.
|
|
18957
|
-
isValidId: isPathSafeId,
|
|
18958
|
-
noun: "base",
|
|
18959
|
-
// States what is actually checked. "must be a slug" described no rule the
|
|
18960
|
-
// reader could act on, and naming the API's rule here would name the wrong one.
|
|
18961
|
-
idLabel: `base id (${PATH_SAFE_ID_RULE})`,
|
|
18962
|
-
unbindCommand: "wayai bases unbind",
|
|
18963
|
-
useCommand: "wayai bases use"
|
|
18964
|
-
});
|
|
18965
|
-
getBaseBindingPath = binding2.getBindingPath;
|
|
18966
|
-
readBaseBinding = binding2.readBinding;
|
|
18967
|
-
writeBaseBinding = binding2.writeBinding;
|
|
18968
|
-
clearBaseBinding = binding2.clearBinding;
|
|
18969
|
-
autoBindBaseIfUnbound = binding2.autoBindIfUnbound;
|
|
18970
|
-
assertBaseMatchesBinding = binding2.assertMatchesBinding;
|
|
18971
|
-
assertNoBindingBlocksBaseCreation = binding2.assertNoBindingBlocksCreation;
|
|
18972
|
-
}
|
|
18973
|
-
});
|
|
18974
|
-
|
|
18975
19246
|
// src/data/helpers.ts
|
|
18976
|
-
import { readFileSync as
|
|
19247
|
+
import { readFileSync as readFileSync15 } from "fs";
|
|
18977
19248
|
function pathSegment(id, label = "id") {
|
|
18978
19249
|
if (!isPathSafeId(id)) {
|
|
18979
19250
|
throw expected(`Invalid ${label}: ${JSON.stringify(id)}. An id may use ${PATH_SAFE_ID_RULE}.`);
|
|
@@ -19001,7 +19272,7 @@ function parseData(data, flag) {
|
|
|
19001
19272
|
let text = data;
|
|
19002
19273
|
if (source !== void 0) {
|
|
19003
19274
|
try {
|
|
19004
|
-
text =
|
|
19275
|
+
text = readFileSync15(source, "utf-8");
|
|
19005
19276
|
} catch (e) {
|
|
19006
19277
|
throw expected(`${prefix}${source}: ${e instanceof Error ? e.message : "could not be read"}`);
|
|
19007
19278
|
}
|
|
@@ -19128,9 +19399,9 @@ var init_types2 = __esm({
|
|
|
19128
19399
|
// src/data/config-as-code/config-writer.ts
|
|
19129
19400
|
import * as fs16 from "fs";
|
|
19130
19401
|
import * as path19 from "path";
|
|
19131
|
-
import * as
|
|
19132
|
-
function
|
|
19133
|
-
return
|
|
19402
|
+
import * as yaml9 from "js-yaml";
|
|
19403
|
+
function dump5(value) {
|
|
19404
|
+
return yaml9.dump(value, YAML_DUMP_OPTIONS);
|
|
19134
19405
|
}
|
|
19135
19406
|
function omitUndefined(obj) {
|
|
19136
19407
|
const out = {};
|
|
@@ -19188,7 +19459,7 @@ function writeBaseFolder(folder, meta, config) {
|
|
|
19188
19459
|
`Refusing to write ${folder}: the path crosses a symlink. Remove it and pull again.`
|
|
19189
19460
|
);
|
|
19190
19461
|
}
|
|
19191
|
-
writeFileIfChanged(folder, path19.join(folder, BASE_META_FILE),
|
|
19462
|
+
writeFileIfChanged(folder, path19.join(folder, BASE_META_FILE), dump5(metaFileObject(meta)), delta);
|
|
19192
19463
|
for (const kind of ENTITY_KINDS) {
|
|
19193
19464
|
const dir = path19.join(folder, ENTITY_DIRS[kind]);
|
|
19194
19465
|
const entities = config[kind] ?? [];
|
|
@@ -19202,7 +19473,7 @@ function writeBaseFolder(folder, meta, config) {
|
|
|
19202
19473
|
}
|
|
19203
19474
|
const file = `${id}.yaml`;
|
|
19204
19475
|
keep.add(file);
|
|
19205
|
-
writeFileIfChanged(folder, path19.join(dir, file),
|
|
19476
|
+
writeFileIfChanged(folder, path19.join(dir, file), dump5(toFileObject(kind, entity)), delta);
|
|
19206
19477
|
}
|
|
19207
19478
|
pruneOrphans(folder, dir, keep, delta);
|
|
19208
19479
|
}
|
|
@@ -19363,7 +19634,7 @@ var init_api = __esm({
|
|
|
19363
19634
|
// src/data/config-as-code/config-parser.ts
|
|
19364
19635
|
import * as fs17 from "fs";
|
|
19365
19636
|
import * as path20 from "path";
|
|
19366
|
-
import * as
|
|
19637
|
+
import * as yaml10 from "js-yaml";
|
|
19367
19638
|
function readEntityDir(folder, dir) {
|
|
19368
19639
|
if (!ensureRealSubdirNoSymlink(folder, dir, false)) {
|
|
19369
19640
|
throw expected(`Refusing to read ${dir}: it is a symlink, not a config directory.`);
|
|
@@ -19379,7 +19650,7 @@ function readEntityDir(folder, dir) {
|
|
|
19379
19650
|
}
|
|
19380
19651
|
let parsed;
|
|
19381
19652
|
try {
|
|
19382
|
-
parsed =
|
|
19653
|
+
parsed = yaml10.load(bytes.toString("utf-8"));
|
|
19383
19654
|
} catch (err) {
|
|
19384
19655
|
throw expected(`Failed to parse ${abs}: ${err instanceof Error ? err.message : String(err)}`);
|
|
19385
19656
|
}
|
|
@@ -19561,7 +19832,7 @@ async function pullBase(gitRootOrNull, selector, args2) {
|
|
|
19561
19832
|
console.log(`Production base mirrored (read-only) \u2192 ${folder}`);
|
|
19562
19833
|
return;
|
|
19563
19834
|
}
|
|
19564
|
-
|
|
19835
|
+
assertInScope("bases", baseId);
|
|
19565
19836
|
if (target.exists && !autoConfirm) {
|
|
19566
19837
|
const ok = await confirm(
|
|
19567
19838
|
`Overwrite local files in ${path21.relative(gitRoot, target.folder)} with the server config for "${sanitizeTerminalText(baseId)}"?`
|
|
@@ -19580,7 +19851,7 @@ async function pullBase(gitRootOrNull, selector, args2) {
|
|
|
19580
19851
|
);
|
|
19581
19852
|
if (!isFirstPull) printLocalFileChanges(delta);
|
|
19582
19853
|
console.log(" Credential values are not written. Manage them with `wayai bases credentials`.");
|
|
19583
|
-
|
|
19854
|
+
seedScopeIfEmpty("bases", baseId);
|
|
19584
19855
|
if (record.origin_base_id) {
|
|
19585
19856
|
await mirrorLinkedProduction(client, basesDir, record.origin_base_id);
|
|
19586
19857
|
}
|
|
@@ -19605,7 +19876,7 @@ async function createDeclaredPreview(client, target, parsed, autoConfirm) {
|
|
|
19605
19876
|
);
|
|
19606
19877
|
}
|
|
19607
19878
|
const name = meta.name ?? path21.basename(target.folder);
|
|
19608
|
-
|
|
19879
|
+
assertScopeAllowsCreation("bases", name);
|
|
19609
19880
|
if (!autoConfirm) {
|
|
19610
19881
|
const ok = await confirm(
|
|
19611
19882
|
`Create a new preview "${sanitizeTerminalText(name)}" from "${sanitizeTerminalText(meta.origin_base_id)}"?`
|
|
@@ -19624,7 +19895,7 @@ async function createDeclaredPreview(client, target, parsed, autoConfirm) {
|
|
|
19624
19895
|
writeBaseFolder(target.folder, { ...meta, ...metaFromRecord(record, id) }, config);
|
|
19625
19896
|
console.log(`Created preview "${sanitizeTerminalText(id)}".`);
|
|
19626
19897
|
printWarnings((record.warnings ?? []).map((w) => sanitizeTerminalText(w.message)));
|
|
19627
|
-
|
|
19898
|
+
seedScopeIfEmpty("bases", id);
|
|
19628
19899
|
return id;
|
|
19629
19900
|
}
|
|
19630
19901
|
async function pushBase(gitRootOrNull, selector, args2) {
|
|
@@ -19662,13 +19933,13 @@ async function pushBase(gitRootOrNull, selector, args2) {
|
|
|
19662
19933
|
`"${sanitizeTerminalText(baseId)}" is a ${sanitizeTerminalText(record.environment)} base. Push operates on previews \u2014 promote with \`wayai bases promote\`.`
|
|
19663
19934
|
);
|
|
19664
19935
|
}
|
|
19665
|
-
|
|
19936
|
+
assertInScope("bases", baseId);
|
|
19666
19937
|
}
|
|
19667
19938
|
const diff = await diffConfig(client, baseId, config);
|
|
19668
19939
|
printLintWarnings(diff.warnings);
|
|
19669
19940
|
if (isDiffEmpty(diff)) {
|
|
19670
19941
|
console.log(`No changes \u2014 preview "${sanitizeTerminalText(baseId)}" already matches your files.`);
|
|
19671
|
-
if (!dryRun)
|
|
19942
|
+
if (!dryRun) seedScopeIfEmpty("bases", baseId);
|
|
19672
19943
|
return;
|
|
19673
19944
|
}
|
|
19674
19945
|
console.log(renderDiff(diff));
|
|
@@ -19720,7 +19991,7 @@ Delete ${removals.length} server ${word} not in your files? Record types cascade
|
|
|
19720
19991
|
}
|
|
19721
19992
|
console.log(`
|
|
19722
19993
|
Pushed to preview "${sanitizeTerminalText(baseId)}".`);
|
|
19723
|
-
|
|
19994
|
+
seedScopeIfEmpty("bases", baseId);
|
|
19724
19995
|
}
|
|
19725
19996
|
var init_sync = __esm({
|
|
19726
19997
|
"src/data/config-as-code/sync.ts"() {
|
|
@@ -19732,7 +20003,7 @@ var init_sync = __esm({
|
|
|
19732
20003
|
init_terminal_output();
|
|
19733
20004
|
init_base_id();
|
|
19734
20005
|
init_push();
|
|
19735
|
-
|
|
20006
|
+
init_worktree_scope();
|
|
19736
20007
|
init_api();
|
|
19737
20008
|
init_config_parser();
|
|
19738
20009
|
init_config_writer();
|
|
@@ -19759,7 +20030,7 @@ __export(push_exports, {
|
|
|
19759
20030
|
});
|
|
19760
20031
|
import * as fs18 from "fs";
|
|
19761
20032
|
import * as path22 from "path";
|
|
19762
|
-
import * as
|
|
20033
|
+
import * as yaml11 from "js-yaml";
|
|
19763
20034
|
function parseArgs5(args2) {
|
|
19764
20035
|
let autoConfirm = false;
|
|
19765
20036
|
let label;
|
|
@@ -19873,7 +20144,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
|
|
|
19873
20144
|
for (const file of yamlFiles) {
|
|
19874
20145
|
try {
|
|
19875
20146
|
const content = fs18.readFileSync(path22.join(agentsDir, file), "utf-8");
|
|
19876
|
-
const agent =
|
|
20147
|
+
const agent = yaml11.load(content);
|
|
19877
20148
|
if (agent?.id && agent.name) {
|
|
19878
20149
|
agentsWithIds.push({ id: agent.id, name: agent.name });
|
|
19879
20150
|
}
|
|
@@ -19886,7 +20157,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
|
|
|
19886
20157
|
const yamlPath = resolveHubYamlPath(hubFolder);
|
|
19887
20158
|
if (!yamlPath) return;
|
|
19888
20159
|
const yamlContent = fs18.readFileSync(yamlPath, "utf-8");
|
|
19889
|
-
const config =
|
|
20160
|
+
const config = yaml11.load(yamlContent);
|
|
19890
20161
|
agentsWithIds = (config.agents || []).filter((a) => !!a.id && !!a.name);
|
|
19891
20162
|
}
|
|
19892
20163
|
if (agentsWithIds.length === 0) return;
|
|
@@ -20036,7 +20307,7 @@ async function pushSingleHub(client, hubId, hubFolder, autoConfirm, organization
|
|
|
20036
20307
|
} else {
|
|
20037
20308
|
console.log("No changes to push; folder renamed.");
|
|
20038
20309
|
}
|
|
20039
|
-
|
|
20310
|
+
seedScopeIfEmpty("hubs", hubId);
|
|
20040
20311
|
return true;
|
|
20041
20312
|
}
|
|
20042
20313
|
console.log("\nChanges to push:");
|
|
@@ -20052,7 +20323,7 @@ async function pushSingleHub(client, hubId, hubFolder, autoConfirm, organization
|
|
|
20052
20323
|
const result = await client.push(hubId, wireConfig, organizationId);
|
|
20053
20324
|
printSyncResult(result);
|
|
20054
20325
|
await syncAfterPush(client, hubId, hubFolder, organizationId);
|
|
20055
|
-
|
|
20326
|
+
seedScopeIfEmpty("hubs", hubId);
|
|
20056
20327
|
return true;
|
|
20057
20328
|
}
|
|
20058
20329
|
function selectExistingHub(workspaceDir, allHubs, selector, wsLabel) {
|
|
@@ -20118,7 +20389,7 @@ hub_environment: preview
|
|
|
20118
20389
|
${content}`;
|
|
20119
20390
|
}
|
|
20120
20391
|
fs18.writeFileSync(hubYamlPath, updated, "utf-8");
|
|
20121
|
-
|
|
20392
|
+
seedScopeIfEmpty("hubs", hubId);
|
|
20122
20393
|
await pushSingleHub(client, hubId, newHub.hubFolder, opts.autoConfirm, opts.organizationId, { skipAgentRename: true });
|
|
20123
20394
|
}
|
|
20124
20395
|
function reportUnresolvedPushTarget(reason, existingHubs, newHubs, selector, wsLabel) {
|
|
@@ -20188,11 +20459,11 @@ async function pushCommand(args2) {
|
|
|
20188
20459
|
console.warn("Note: --label is only used when creating a new hub. To change an existing hub's label, use `wayai relabel`.");
|
|
20189
20460
|
}
|
|
20190
20461
|
console.log(`Target hub: ${path22.basename(existing.hubFolder)} (${existing.hubId})`);
|
|
20191
|
-
|
|
20462
|
+
assertInScope("hubs", existing.hubId, path22.basename(existing.hubFolder));
|
|
20192
20463
|
await pushSingleHub(client, existing.hubId, existing.hubFolder, autoConfirm, organizationId);
|
|
20193
20464
|
return;
|
|
20194
20465
|
}
|
|
20195
|
-
|
|
20466
|
+
assertScopeAllowsCreation("hubs", resolution.target.hub.hubName);
|
|
20196
20467
|
await createAndPushNewHub(client, resolution.target.hub, { autoConfirm, label, organizationId });
|
|
20197
20468
|
}
|
|
20198
20469
|
var LOCAL_CHANGE_LIST_CAP;
|
|
@@ -20211,7 +20482,7 @@ var init_push = __esm({
|
|
|
20211
20482
|
init_layout();
|
|
20212
20483
|
init_workspace_files();
|
|
20213
20484
|
init_repo_config();
|
|
20214
|
-
|
|
20485
|
+
init_worktree_scope();
|
|
20215
20486
|
init_subtree_routing();
|
|
20216
20487
|
LOCAL_CHANGE_LIST_CAP = 20;
|
|
20217
20488
|
}
|
|
@@ -20285,7 +20556,7 @@ async function pullCommand(args2) {
|
|
|
20285
20556
|
console.log(`Production hub mirrored (read-only) \u2192 ${folder}`);
|
|
20286
20557
|
return;
|
|
20287
20558
|
}
|
|
20288
|
-
|
|
20559
|
+
assertInScope("hubs", hubId);
|
|
20289
20560
|
let hubFolder = existingFolder;
|
|
20290
20561
|
let wroteFiles = false;
|
|
20291
20562
|
if (!hubFolder) {
|
|
@@ -20344,7 +20615,7 @@ async function pullCommand(args2) {
|
|
|
20344
20615
|
printLocalFileChanges(delta);
|
|
20345
20616
|
}
|
|
20346
20617
|
}
|
|
20347
|
-
if (wroteFiles)
|
|
20618
|
+
if (wroteFiles) seedScopeIfEmpty("hubs", hubId);
|
|
20348
20619
|
if (payload.production_hub_id) {
|
|
20349
20620
|
await mirrorLinkedProduction2(client, workspaceDir, payload.production_hub_id, organizationId);
|
|
20350
20621
|
}
|
|
@@ -20406,7 +20677,7 @@ var init_pull = __esm({
|
|
|
20406
20677
|
init_layout();
|
|
20407
20678
|
init_workspace_files();
|
|
20408
20679
|
init_repo_config();
|
|
20409
|
-
|
|
20680
|
+
init_worktree_scope();
|
|
20410
20681
|
init_subtree_routing();
|
|
20411
20682
|
MIRROR_MARKER_PREFIX2 = "# Read-only mirror of production hub";
|
|
20412
20683
|
}
|
|
@@ -20472,7 +20743,7 @@ async function createCommand(args2) {
|
|
|
20472
20743
|
}
|
|
20473
20744
|
process.exit(1);
|
|
20474
20745
|
}
|
|
20475
|
-
|
|
20746
|
+
assertScopeAllowsCreation("hubs", resolution.hub.hubName);
|
|
20476
20747
|
await createAndPushNewHub(client, resolution.hub, { autoConfirm, label, organizationId });
|
|
20477
20748
|
}
|
|
20478
20749
|
var init_create = __esm({
|
|
@@ -20484,7 +20755,7 @@ var init_create = __esm({
|
|
|
20484
20755
|
init_workspace();
|
|
20485
20756
|
init_layout();
|
|
20486
20757
|
init_repo_config();
|
|
20487
|
-
|
|
20758
|
+
init_worktree_scope();
|
|
20488
20759
|
}
|
|
20489
20760
|
});
|
|
20490
20761
|
|
|
@@ -20637,7 +20908,7 @@ async function replicateCommand(args2) {
|
|
|
20637
20908
|
payload.preview_label,
|
|
20638
20909
|
payload.branch_name
|
|
20639
20910
|
);
|
|
20640
|
-
|
|
20911
|
+
seedScopeIfEmpty("hubs", previewHubId);
|
|
20641
20912
|
if (folderPreExisted) printLocalFileChanges(delta);
|
|
20642
20913
|
console.log(`Preview written to ${path25.basename(hubFolder)}`);
|
|
20643
20914
|
console.log(` Switch to it with: wayai use ${path25.basename(hubFolder)}`);
|
|
@@ -20653,7 +20924,7 @@ var init_replicate = __esm({
|
|
|
20653
20924
|
init_workspace();
|
|
20654
20925
|
init_layout();
|
|
20655
20926
|
init_repo_config();
|
|
20656
|
-
|
|
20927
|
+
init_worktree_scope();
|
|
20657
20928
|
init_contracts();
|
|
20658
20929
|
}
|
|
20659
20930
|
});
|
|
@@ -20716,7 +20987,7 @@ async function relabelCommand(args2) {
|
|
|
20716
20987
|
console.log("This is a read-only production mirror \u2014 production hubs have no preview label. Relabel the linked preview hub instead.");
|
|
20717
20988
|
return;
|
|
20718
20989
|
}
|
|
20719
|
-
|
|
20990
|
+
assertInScope("hubs", target.hubId, path26.basename(target.hubFolder));
|
|
20720
20991
|
console.log(normalizedLabel ? `Setting preview label to "${normalizedLabel}"...` : "Clearing preview label...");
|
|
20721
20992
|
const { data } = await client.relabelPreview(target.hubId, normalizedLabel);
|
|
20722
20993
|
const row = data[0];
|
|
@@ -20745,7 +21016,7 @@ var init_relabel = __esm({
|
|
|
20745
21016
|
init_workspace();
|
|
20746
21017
|
init_layout();
|
|
20747
21018
|
init_repo_config();
|
|
20748
|
-
|
|
21019
|
+
init_worktree_scope();
|
|
20749
21020
|
init_contracts();
|
|
20750
21021
|
}
|
|
20751
21022
|
});
|
|
@@ -20872,7 +21143,7 @@ async function publishCommand(args2) {
|
|
|
20872
21143
|
return;
|
|
20873
21144
|
}
|
|
20874
21145
|
}
|
|
20875
|
-
|
|
21146
|
+
assertInScope("hubs", hubId, hubFolder ? path27.basename(hubFolder) : void 0);
|
|
20876
21147
|
await runPublish(client, { hubId, localConfig, organizationId, autoConfirm });
|
|
20877
21148
|
}
|
|
20878
21149
|
var STATUS_STYLE;
|
|
@@ -20888,7 +21159,7 @@ var init_publish = __esm({
|
|
|
20888
21159
|
init_layout();
|
|
20889
21160
|
init_resource_files();
|
|
20890
21161
|
init_repo_config();
|
|
20891
|
-
|
|
21162
|
+
init_worktree_scope();
|
|
20892
21163
|
STATUS_STYLE = {
|
|
20893
21164
|
added: { sym: "+", color: 32 },
|
|
20894
21165
|
// green
|
|
@@ -20900,77 +21171,151 @@ var init_publish = __esm({
|
|
|
20900
21171
|
}
|
|
20901
21172
|
});
|
|
20902
21173
|
|
|
21174
|
+
// src/lib/scope-selector.ts
|
|
21175
|
+
import * as path28 from "path";
|
|
21176
|
+
function findAddFlag(args2) {
|
|
21177
|
+
return args2.find((arg) => arg === "--add" || arg.startsWith("--add="));
|
|
21178
|
+
}
|
|
21179
|
+
function isValuedFlag(token) {
|
|
21180
|
+
return token.includes("=");
|
|
21181
|
+
}
|
|
21182
|
+
function resolveScopeSelector(verb, args2) {
|
|
21183
|
+
const { hubFlag, baseFlag, positional } = parseRoutingTokens(args2);
|
|
21184
|
+
if (hubFlag !== void 0 && baseFlag !== void 0) {
|
|
21185
|
+
throw expected(mixedInvocationRefusal(verb, hubFlag, baseFlag));
|
|
21186
|
+
}
|
|
21187
|
+
assertValueIsNotAFlag(verb, "--hub", hubFlag);
|
|
21188
|
+
assertValueIsNotAFlag(verb, "--base", baseFlag);
|
|
21189
|
+
assertFlagWasGivenAValue(verb, "--hub", args2, hubFlag);
|
|
21190
|
+
assertFlagWasGivenAValue(verb, "--base", args2, baseFlag);
|
|
21191
|
+
if (hubFlag !== void 0) return { axis: "hubs", target: hubFlag, gitRoot: findGitRoot() };
|
|
21192
|
+
if (baseFlag !== void 0) return { axis: "bases", target: baseFlag, gitRoot: findGitRoot() };
|
|
21193
|
+
if (positional === void 0) return null;
|
|
21194
|
+
const gitRoot = findGitRoot();
|
|
21195
|
+
const layout = gitRoot ? resolveLayout(gitRoot) : null;
|
|
21196
|
+
const resolved = resolveSelectorSubtree(layout, positional, process.cwd());
|
|
21197
|
+
if (resolved.kind === "both") {
|
|
21198
|
+
throw expected(mixedInvocationRefusal(verb, resolved.target, resolved.target));
|
|
21199
|
+
}
|
|
21200
|
+
if (resolved.kind === "hubs" || resolved.kind === "bases") {
|
|
21201
|
+
return { axis: resolved.kind, target: resolved.target, gitRoot };
|
|
21202
|
+
}
|
|
21203
|
+
return { axis: "hubs", target: positional, gitRoot };
|
|
21204
|
+
}
|
|
21205
|
+
function assertValueIsNotAFlag(verb, flag, captured) {
|
|
21206
|
+
if (captured === void 0 || !captured.startsWith("-")) return;
|
|
21207
|
+
throw refusal(verb, flag, `but got ${JSON.stringify(captured)} \u2014 which is a flag, not a hub or base`);
|
|
21208
|
+
}
|
|
21209
|
+
function assertFlagWasGivenAValue(verb, flag, args2, captured) {
|
|
21210
|
+
if (captured !== void 0 && captured !== "") return;
|
|
21211
|
+
if (!args2.some((arg) => arg === flag || arg.startsWith(`${flag}=`))) return;
|
|
21212
|
+
throw refusal(verb, flag, "but no target followed it");
|
|
21213
|
+
}
|
|
21214
|
+
function refusal(verb, flag, problem) {
|
|
21215
|
+
return expected(
|
|
21216
|
+
`\`wayai ${verb} ${flag}\` needs a target, ${problem}.
|
|
21217
|
+
wayai ${verb} ${flag} <hub-or-base>`
|
|
21218
|
+
);
|
|
21219
|
+
}
|
|
21220
|
+
function resolveHubSelectorToId(gitRoot, selector) {
|
|
21221
|
+
if (UUID_RE2.test(selector)) return selector;
|
|
21222
|
+
const workspaceDir = detectWorkspace()?.workspaceDir ?? (gitRoot ? resolveLayout(gitRoot).hubsDir : null);
|
|
21223
|
+
if (!workspaceDir) {
|
|
21224
|
+
throw expected("Not inside a git repository, and no UUID provided.");
|
|
21225
|
+
}
|
|
21226
|
+
const match = findHubByFolderName(workspaceDir, selector);
|
|
21227
|
+
if (match) return match.hubId;
|
|
21228
|
+
const newHubs = scanNewHubs(workspaceDir);
|
|
21229
|
+
const pending = newHubs.find((h) => path28.basename(h.hubFolder) === selector);
|
|
21230
|
+
if (pending) {
|
|
21231
|
+
throw expected(
|
|
21232
|
+
`"${selector}" is a new hub that hasn't been created on the platform yet, so it has no id to bind to.
|
|
21233
|
+
Create it first \u2014 the worktree scope picks it up automatically afterward:
|
|
21234
|
+
wayai create ${selector}`
|
|
21235
|
+
);
|
|
21236
|
+
}
|
|
21237
|
+
throw expected(
|
|
21238
|
+
[
|
|
21239
|
+
`No hub matching "${selector}" found in ${hubsDirLabel(gitRoot)}/. Pass a UUID or a folder name from:`,
|
|
21240
|
+
...scanWorkspaceHubs(workspaceDir).map((h) => ` ${path28.basename(h.hubFolder)} (${h.hubId})`),
|
|
21241
|
+
...newHubs.map(
|
|
21242
|
+
(h) => ` ${path28.basename(h.hubFolder)} (new \u2014 "${h.hubName}", run \`wayai create ${path28.basename(h.hubFolder)}\`)`
|
|
21243
|
+
)
|
|
21244
|
+
].join("\n")
|
|
21245
|
+
);
|
|
21246
|
+
}
|
|
21247
|
+
function resolveScopeTarget(selector) {
|
|
21248
|
+
const { axis, target, gitRoot } = selector;
|
|
21249
|
+
if (axis === "hubs") {
|
|
21250
|
+
return { axis, id: resolveHubSelectorToId(gitRoot, target) };
|
|
21251
|
+
}
|
|
21252
|
+
const id = resolveBaseSelectorToId(gitRoot, target);
|
|
21253
|
+
assertValidBaseSelector(id, "base id");
|
|
21254
|
+
return { axis, id };
|
|
21255
|
+
}
|
|
21256
|
+
var init_scope_selector = __esm({
|
|
21257
|
+
"src/lib/scope-selector.ts"() {
|
|
21258
|
+
"use strict";
|
|
21259
|
+
init_expected();
|
|
21260
|
+
init_base_workspace();
|
|
21261
|
+
init_layout();
|
|
21262
|
+
init_subtree_routing();
|
|
21263
|
+
init_utils();
|
|
21264
|
+
init_workspace();
|
|
21265
|
+
}
|
|
21266
|
+
});
|
|
21267
|
+
|
|
20903
21268
|
// src/commands/use.ts
|
|
20904
21269
|
var use_exports = {};
|
|
20905
21270
|
__export(use_exports, {
|
|
20906
21271
|
useCommand: () => useCommand
|
|
20907
21272
|
});
|
|
20908
|
-
import * as path28 from "path";
|
|
20909
21273
|
async function useCommand(args2) {
|
|
20910
|
-
const
|
|
20911
|
-
if (
|
|
20912
|
-
|
|
20913
|
-
|
|
20914
|
-
|
|
20915
|
-
|
|
20916
|
-
|
|
20917
|
-
|
|
20918
|
-
|
|
20919
|
-
const workspace = detectWorkspace();
|
|
20920
|
-
const gitRoot = findGitRoot();
|
|
20921
|
-
const workspaceDir = workspace?.workspaceDir ?? (gitRoot ? resolveLayout(gitRoot).hubsDir : null);
|
|
20922
|
-
if (!workspaceDir) {
|
|
20923
|
-
console.error("Not inside a git repository, and no UUID provided.");
|
|
20924
|
-
process.exit(1);
|
|
20925
|
-
}
|
|
20926
|
-
const wsLabel = hubsDirLabel(gitRoot);
|
|
20927
|
-
const match = findHubByFolderName(workspaceDir, target);
|
|
20928
|
-
if (!match) {
|
|
20929
|
-
const newHubs = scanNewHubs(workspaceDir);
|
|
20930
|
-
const pending = newHubs.find((h) => path28.basename(h.hubFolder) === target);
|
|
20931
|
-
if (pending) {
|
|
20932
|
-
console.error(
|
|
20933
|
-
`"${target}" is a new hub that hasn't been created on the platform yet, so it has no id to bind to.
|
|
20934
|
-
Create it first \u2014 the worktree binds automatically afterward:
|
|
20935
|
-
wayai create ${target}`
|
|
20936
|
-
);
|
|
20937
|
-
process.exit(1);
|
|
20938
|
-
}
|
|
20939
|
-
console.error(`No hub matching "${target}" found in ${wsLabel}/. Pass a UUID or a folder name from:`);
|
|
20940
|
-
for (const h of scanWorkspaceHubs(workspaceDir)) {
|
|
20941
|
-
console.error(` ${path28.basename(h.hubFolder)} (${h.hubId})`);
|
|
20942
|
-
}
|
|
20943
|
-
for (const h of newHubs) {
|
|
20944
|
-
console.error(` ${path28.basename(h.hubFolder)} (new \u2014 "${h.hubName}", run \`wayai create ${path28.basename(h.hubFolder)}\`)`);
|
|
20945
|
-
}
|
|
20946
|
-
process.exit(1);
|
|
20947
|
-
}
|
|
20948
|
-
hubId = match.hubId;
|
|
21274
|
+
const addFlag = findAddFlag(args2);
|
|
21275
|
+
if (addFlag !== void 0 && isValuedFlag(addFlag)) {
|
|
21276
|
+
throw expected(
|
|
21277
|
+
[
|
|
21278
|
+
`\`--add\` is a boolean flag \u2014 write it bare, not ${JSON.stringify(addFlag)}.`,
|
|
21279
|
+
" wayai use --add <selector> # widen the worktree scope",
|
|
21280
|
+
" wayai use <selector> # replace that axis instead"
|
|
21281
|
+
].join("\n")
|
|
21282
|
+
);
|
|
20949
21283
|
}
|
|
20950
|
-
const
|
|
20951
|
-
|
|
20952
|
-
|
|
21284
|
+
const add = addFlag !== void 0;
|
|
21285
|
+
const selector = resolveScopeSelector("use", args2);
|
|
21286
|
+
if (!selector) throw expected(USAGE);
|
|
21287
|
+
const { axis, id } = resolveScopeTarget(selector);
|
|
21288
|
+
const noun = axisNoun(axis);
|
|
21289
|
+
if (add) {
|
|
21290
|
+
const widened = addToScope(axis, id);
|
|
21291
|
+
console.log(
|
|
21292
|
+
widened ? `Worktree scope widened \u2014 now ${describeAxis(axis, widened)}.` : `Worktree scope already includes ${noun} ${id}.`
|
|
21293
|
+
);
|
|
20953
21294
|
return;
|
|
20954
21295
|
}
|
|
20955
|
-
|
|
20956
|
-
|
|
20957
|
-
|
|
20958
|
-
|
|
20959
|
-
process.exit(1);
|
|
20960
|
-
}
|
|
20961
|
-
if (previous) {
|
|
20962
|
-
console.log(`Worktree rebound: ${previous} \u2192 ${hubId}`);
|
|
20963
|
-
} else {
|
|
20964
|
-
console.log(`Worktree bound to hub ${hubId}.`);
|
|
21296
|
+
const previous = readScope()[axis];
|
|
21297
|
+
if (previous.length === 1 && previous[0] === id) {
|
|
21298
|
+
console.log(`Worktree already bound to ${noun} ${id}.`);
|
|
21299
|
+
return;
|
|
20965
21300
|
}
|
|
21301
|
+
setScopeAxis(axis, [id]);
|
|
21302
|
+
console.log(
|
|
21303
|
+
previous.length > 0 ? `Worktree rebound: ${previous.join(", ")} \u2192 ${id}.` : `Worktree bound to ${noun} ${id}.`
|
|
21304
|
+
);
|
|
20966
21305
|
}
|
|
21306
|
+
var USAGE;
|
|
20967
21307
|
var init_use = __esm({
|
|
20968
21308
|
"src/commands/use.ts"() {
|
|
20969
21309
|
"use strict";
|
|
20970
|
-
|
|
20971
|
-
|
|
20972
|
-
|
|
20973
|
-
|
|
21310
|
+
init_expected();
|
|
21311
|
+
init_scope_selector();
|
|
21312
|
+
init_worktree_scope();
|
|
21313
|
+
USAGE = [
|
|
21314
|
+
"Usage: wayai use [--add] <hub_uuid|folder-name|hubs/<name>|bases/<name>>",
|
|
21315
|
+
" wayai use [--add] --hub <hub> | --base <base>",
|
|
21316
|
+
"",
|
|
21317
|
+
" --add widen the worktree scope instead of replacing that axis"
|
|
21318
|
+
].join("\n");
|
|
20974
21319
|
}
|
|
20975
21320
|
});
|
|
20976
21321
|
|
|
@@ -21022,9 +21367,10 @@ async function migrateCommand(_args) {
|
|
|
21022
21367
|
const newOrg = path29.join(newWs, WAYAI_LAYOUT.orgSubdir);
|
|
21023
21368
|
const hasLegacyWs = isDirectory(legacyWs);
|
|
21024
21369
|
const hasLegacyOrg = isDirectory(legacyOrg);
|
|
21025
|
-
|
|
21026
|
-
|
|
21027
|
-
|
|
21370
|
+
const orgPlan = planOrgMigration(gitRoot);
|
|
21371
|
+
if (orgPlan.kind === "refuse") {
|
|
21372
|
+
console.error(orgPlan.message);
|
|
21373
|
+
process.exit(1);
|
|
21028
21374
|
}
|
|
21029
21375
|
if (hasLegacyWs && isDirectory(newHubs)) {
|
|
21030
21376
|
console.error(
|
|
@@ -21050,10 +21396,30 @@ async function migrateCommand(_args) {
|
|
|
21050
21396
|
usedFsFallback ||= how === "fs";
|
|
21051
21397
|
moved.push(`${WAYAI_LAYOUT.legacy.orgAtRoot}/ \u2192 ${rel(newOrg)}/`);
|
|
21052
21398
|
}
|
|
21053
|
-
|
|
21054
|
-
|
|
21055
|
-
|
|
21056
|
-
|
|
21399
|
+
if (moved.length > 0) {
|
|
21400
|
+
console.log(`Migrated to the ${WAYAI_LAYOUT.wsDir}/ layout:`);
|
|
21401
|
+
for (const m of moved) console.log(` ${m}`);
|
|
21402
|
+
if (usedFsFallback) {
|
|
21403
|
+
console.log("\n(Some dirs were moved on disk, not via git \u2014 they will show as untracked.)");
|
|
21404
|
+
}
|
|
21405
|
+
}
|
|
21406
|
+
const copiedOrg = orgPlan.kind === "copy";
|
|
21407
|
+
if (copiedOrg) {
|
|
21408
|
+
writeRepoConfig(orgPlan.config, gitRoot);
|
|
21409
|
+
console.log(`${moved.length > 0 ? "\n" : ""}Copied the organization binding into ${WORKSPACE_MANIFEST_LABEL}.`);
|
|
21410
|
+
console.log(
|
|
21411
|
+
` ${ROOT_CONFIG_FILE} is KEPT on purpose \u2014 an older CLI in a teammate's environment or in CI still requires it.`
|
|
21412
|
+
);
|
|
21413
|
+
console.log(
|
|
21414
|
+
" It stays a supported fallback until the next major, which removes both the fallback and the file."
|
|
21415
|
+
);
|
|
21416
|
+
console.log(" Delete it once every environment that runs this repo reads the manifest.");
|
|
21417
|
+
}
|
|
21418
|
+
if (moved.length === 0 && !copiedOrg) {
|
|
21419
|
+
console.log(
|
|
21420
|
+
`Already migrated \u2014 no legacy ${WAYAI_LAYOUT.legacy.wsDir}/ or ${WAYAI_LAYOUT.legacy.orgAtRoot}/ to move, and no organization binding to copy into ${WORKSPACE_MANIFEST_LABEL}.`
|
|
21421
|
+
);
|
|
21422
|
+
return;
|
|
21057
21423
|
}
|
|
21058
21424
|
console.log("\nNext steps:");
|
|
21059
21425
|
console.log(' git add -A && git commit -m "chore: migrate to wayai-ws layout"');
|
|
@@ -21064,6 +21430,8 @@ var init_migrate = __esm({
|
|
|
21064
21430
|
"use strict";
|
|
21065
21431
|
init_workspace();
|
|
21066
21432
|
init_layout();
|
|
21433
|
+
init_repo_config();
|
|
21434
|
+
init_workspace_manifest();
|
|
21067
21435
|
}
|
|
21068
21436
|
});
|
|
21069
21437
|
|
|
@@ -21072,19 +21440,71 @@ var unbind_exports = {};
|
|
|
21072
21440
|
__export(unbind_exports, {
|
|
21073
21441
|
unbindCommand: () => unbindCommand
|
|
21074
21442
|
});
|
|
21075
|
-
async function unbindCommand(
|
|
21076
|
-
const
|
|
21077
|
-
if (
|
|
21078
|
-
|
|
21443
|
+
async function unbindCommand(args2) {
|
|
21444
|
+
const addFlag = findAddFlag(args2);
|
|
21445
|
+
if (addFlag !== void 0) {
|
|
21446
|
+
throw expected(
|
|
21447
|
+
[
|
|
21448
|
+
`\`wayai unbind\` does not take ${JSON.stringify(addFlag)}.`,
|
|
21449
|
+
" wayai unbind <selector> # remove one entry from the worktree scope",
|
|
21450
|
+
" wayai unbind # clear the whole scope (both hubs and bases)",
|
|
21451
|
+
" wayai use --add <selector> # WIDEN the scope instead (the opposite change)"
|
|
21452
|
+
].join("\n")
|
|
21453
|
+
);
|
|
21454
|
+
}
|
|
21455
|
+
const selector = resolveScopeSelector("unbind", args2);
|
|
21456
|
+
if (!selector) {
|
|
21457
|
+
if (args2.length > 0) {
|
|
21458
|
+
throw expected(
|
|
21459
|
+
[
|
|
21460
|
+
`\`wayai unbind ${args2.join(" ")}\` does not name anything to remove.`,
|
|
21461
|
+
"",
|
|
21462
|
+
"Refusing rather than clearing the whole scope \u2014 that is what a BARE",
|
|
21463
|
+
"`wayai unbind` does, and it is not what this invocation asked for.",
|
|
21464
|
+
" wayai unbind <selector> # remove one entry",
|
|
21465
|
+
" wayai unbind # clear the whole scope (both hubs and bases)"
|
|
21466
|
+
].join("\n")
|
|
21467
|
+
);
|
|
21468
|
+
}
|
|
21469
|
+
const described = describeScope(readScope());
|
|
21470
|
+
clearScope();
|
|
21471
|
+
console.log(
|
|
21472
|
+
described ? `Worktree scope cleared (was ${described}).` : "No worktree scope to clear."
|
|
21473
|
+
);
|
|
21079
21474
|
return;
|
|
21080
21475
|
}
|
|
21081
|
-
|
|
21082
|
-
|
|
21476
|
+
const scope = readScope();
|
|
21477
|
+
const literal = AXIS_ORDER.filter((axis2) => scope[axis2].includes(selector.target));
|
|
21478
|
+
const literalAxis = literal.includes(selector.axis) ? selector.axis : literal.length === 1 ? literal[0] : null;
|
|
21479
|
+
if (literalAxis) {
|
|
21480
|
+
announce(literalAxis, selector.target, removeFromScope(literalAxis, selector.target) ?? []);
|
|
21481
|
+
return;
|
|
21482
|
+
}
|
|
21483
|
+
const { axis, id } = resolveScopeTarget(selector);
|
|
21484
|
+
const remaining = removeFromScope(axis, id);
|
|
21485
|
+
if (!remaining) {
|
|
21486
|
+
const described = describeScope(scope);
|
|
21487
|
+
throw expected(
|
|
21488
|
+
[
|
|
21489
|
+
`${axisNoun(axis)} ${id} is not in this worktree's scope.`,
|
|
21490
|
+
described ? `This worktree is scoped to ${described}.` : "This worktree has no scope."
|
|
21491
|
+
].join("\n")
|
|
21492
|
+
);
|
|
21493
|
+
}
|
|
21494
|
+
announce(axis, id, remaining);
|
|
21495
|
+
}
|
|
21496
|
+
function announce(axis, id, remaining) {
|
|
21497
|
+
const noun = axisNoun(axis);
|
|
21498
|
+
console.log(
|
|
21499
|
+
remaining.length > 0 ? `Removed ${noun} ${id} from the worktree scope (${axis}: ${remaining.join(", ")}).` : `Removed ${noun} ${id} \u2014 this worktree is no longer scoped to any ${noun}.`
|
|
21500
|
+
);
|
|
21083
21501
|
}
|
|
21084
21502
|
var init_unbind = __esm({
|
|
21085
21503
|
"src/commands/unbind.ts"() {
|
|
21086
21504
|
"use strict";
|
|
21087
|
-
|
|
21505
|
+
init_expected();
|
|
21506
|
+
init_scope_selector();
|
|
21507
|
+
init_worktree_scope();
|
|
21088
21508
|
}
|
|
21089
21509
|
});
|
|
21090
21510
|
|
|
@@ -22405,8 +22825,8 @@ function installEvalSignalHandlers(input) {
|
|
|
22405
22825
|
let signalCount = 0;
|
|
22406
22826
|
let disposed = false;
|
|
22407
22827
|
let settle;
|
|
22408
|
-
const settled = new Promise((
|
|
22409
|
-
settle =
|
|
22828
|
+
const settled = new Promise((resolve8) => {
|
|
22829
|
+
settle = resolve8;
|
|
22410
22830
|
});
|
|
22411
22831
|
const listeners = /* @__PURE__ */ new Map();
|
|
22412
22832
|
const dispose = () => {
|
|
@@ -22756,7 +23176,7 @@ Timeout after ${timeoutSeconds}s${queuedSeconds > 0 ? ` (${queuedSeconds}s of it
|
|
|
22756
23176
|
process.exit(1);
|
|
22757
23177
|
}
|
|
22758
23178
|
function sleep(ms) {
|
|
22759
|
-
return new Promise((
|
|
23179
|
+
return new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
22760
23180
|
}
|
|
22761
23181
|
function parseRunNumbers(raw) {
|
|
22762
23182
|
if (!raw || raw.startsWith("--")) {
|
|
@@ -23028,7 +23448,7 @@ __export(eval_capture_exports, {
|
|
|
23028
23448
|
});
|
|
23029
23449
|
import * as fs24 from "fs";
|
|
23030
23450
|
import * as path31 from "path";
|
|
23031
|
-
import * as
|
|
23451
|
+
import * as yaml12 from "js-yaml";
|
|
23032
23452
|
function isValidSetName(name) {
|
|
23033
23453
|
if (name.length === 0 || name === "." || name === "..") return false;
|
|
23034
23454
|
if (name.startsWith(".")) return false;
|
|
@@ -23134,7 +23554,7 @@ async function evalCaptureCommand(args2) {
|
|
|
23134
23554
|
};
|
|
23135
23555
|
const yamlObj = buildEvalYamlObject(evalEntry, slug);
|
|
23136
23556
|
fs24.mkdirSync(targetDir, { recursive: true });
|
|
23137
|
-
fs24.writeFileSync(targetPath,
|
|
23557
|
+
fs24.writeFileSync(targetPath, yaml12.dump(yamlObj, YAML_DUMP_OPTIONS), "utf-8");
|
|
23138
23558
|
const relPath = path31.relative(process.cwd(), targetPath);
|
|
23139
23559
|
console.log(`
|
|
23140
23560
|
Wrote ${relPath}`);
|
|
@@ -24507,7 +24927,7 @@ var init_set_connection_credential = __esm({
|
|
|
24507
24927
|
// src/lib/org-workspace.ts
|
|
24508
24928
|
import * as fs25 from "fs";
|
|
24509
24929
|
import * as path32 from "path";
|
|
24510
|
-
import * as
|
|
24930
|
+
import * as yaml13 from "js-yaml";
|
|
24511
24931
|
function getOrgDir(gitRoot) {
|
|
24512
24932
|
return resolveLayout(gitRoot).orgDir;
|
|
24513
24933
|
}
|
|
@@ -24518,7 +24938,7 @@ function parseOrgResources(orgDir) {
|
|
|
24518
24938
|
const manifestPath = path32.join(orgDir, ORG_MANIFEST_NAME);
|
|
24519
24939
|
let manifest = {};
|
|
24520
24940
|
if (fs25.existsSync(manifestPath)) {
|
|
24521
|
-
manifest =
|
|
24941
|
+
manifest = yaml13.load(fs25.readFileSync(manifestPath, "utf-8")) ?? {};
|
|
24522
24942
|
}
|
|
24523
24943
|
const rawResources = Array.isArray(manifest.resources) ? manifest.resources : [];
|
|
24524
24944
|
const resourcesDir = path32.join(orgDir, "resources");
|
|
@@ -24551,7 +24971,7 @@ function writeOrgResources(orgDir, payload) {
|
|
|
24551
24971
|
});
|
|
24552
24972
|
fs25.writeFileSync(
|
|
24553
24973
|
path32.join(orgDir, ORG_MANIFEST_NAME),
|
|
24554
|
-
|
|
24974
|
+
yaml13.dump({ version: 1, resources: manifestResources }, YAML_DUMP_OPTIONS),
|
|
24555
24975
|
"utf-8"
|
|
24556
24976
|
);
|
|
24557
24977
|
const resourcesDir = path32.join(orgDir, "resources");
|
|
@@ -25373,7 +25793,7 @@ async function runSkillInstall(positional) {
|
|
|
25373
25793
|
console.log("Reload your agent (e.g. restart Claude Code) to pick up the skill.");
|
|
25374
25794
|
}
|
|
25375
25795
|
async function runSandboxExec(positional, flagArgs) {
|
|
25376
|
-
const
|
|
25796
|
+
const USAGE2 = 'wayai admin sandbox exec [--cmd "<command>" | <command>] --hub <hub_id> --connection <connection_id> [--egress open|allowlist|isolated] [--allow <host> ...] [--timeout <ms>] [--json]';
|
|
25377
25797
|
let hubId;
|
|
25378
25798
|
let connectionId;
|
|
25379
25799
|
let egress;
|
|
@@ -25427,7 +25847,7 @@ async function runSandboxExec(positional, flagArgs) {
|
|
|
25427
25847
|
const positionalCmd = positional[0];
|
|
25428
25848
|
if (positional.length > 1) {
|
|
25429
25849
|
console.error("Provide the command as a single quoted argument (or use --cmd).");
|
|
25430
|
-
console.error(
|
|
25850
|
+
console.error(USAGE2);
|
|
25431
25851
|
process.exit(1);
|
|
25432
25852
|
}
|
|
25433
25853
|
if (positionalCmd && cmdFlag) {
|
|
@@ -25436,7 +25856,7 @@ async function runSandboxExec(positional, flagArgs) {
|
|
|
25436
25856
|
}
|
|
25437
25857
|
const cmd = cmdFlag ?? positionalCmd;
|
|
25438
25858
|
if (!cmd || !hubId || !connectionId) {
|
|
25439
|
-
console.error(
|
|
25859
|
+
console.error(USAGE2);
|
|
25440
25860
|
process.exit(1);
|
|
25441
25861
|
}
|
|
25442
25862
|
const body = {
|
|
@@ -25533,8 +25953,8 @@ function parseScopedTargetFlags(flagArgs, usage3, opts = {}) {
|
|
|
25533
25953
|
return { body: { scope: "hub", hub_id: hubId, dry_run: dryRun }, targetLabel: `hub ${hubId}`, dryRun, yes, jsonOutput };
|
|
25534
25954
|
}
|
|
25535
25955
|
async function runRepairTeamOrphans(flagArgs) {
|
|
25536
|
-
const
|
|
25537
|
-
const { body, targetLabel, dryRun, yes, jsonOutput } = parseScopedTargetFlags(flagArgs,
|
|
25956
|
+
const USAGE2 = "wayai admin hubs repair-team-orphans --all | --org <org_id> | --hub <hub_id> [--dry-run] [--yes] [--json]";
|
|
25957
|
+
const { body, targetLabel, dryRun, yes, jsonOutput } = parseScopedTargetFlags(flagArgs, USAGE2);
|
|
25538
25958
|
if (!dryRun && !yes && !jsonOutput) {
|
|
25539
25959
|
console.log(`About to PURGE dangling team references in: ${targetLabel}.`);
|
|
25540
25960
|
console.log("Memberships pointing at a deleted team are removed (HubDO + UserDO mirror); conversations pinned to one are unassigned.");
|
|
@@ -25580,8 +26000,8 @@ async function runRepairTeamOrphans(flagArgs) {
|
|
|
25580
26000
|
}
|
|
25581
26001
|
}
|
|
25582
26002
|
async function runRepairLegacyOrgGrants(flagArgs) {
|
|
25583
|
-
const
|
|
25584
|
-
const scoped = parseScopedTargetFlags(flagArgs,
|
|
26003
|
+
const USAGE2 = "wayai admin orgs repair-legacy-grants --all | --org <org_id> [--dry-run] [--yes] [--json]";
|
|
26004
|
+
const scoped = parseScopedTargetFlags(flagArgs, USAGE2, {
|
|
25585
26005
|
scopes: ["all", "org"],
|
|
25586
26006
|
allLabel: "ALL organizations (platform-wide)"
|
|
25587
26007
|
});
|
|
@@ -25633,8 +26053,8 @@ async function runRepairLegacyOrgGrants(flagArgs) {
|
|
|
25633
26053
|
}
|
|
25634
26054
|
}
|
|
25635
26055
|
async function runHarnessMassDestroy(flagArgs) {
|
|
25636
|
-
const
|
|
25637
|
-
const { body, targetLabel, dryRun, yes, jsonOutput } = parseScopedTargetFlags(flagArgs,
|
|
26056
|
+
const USAGE2 = "wayai admin harness mass-destroy --all | --org <org_id> | --hub <hub_id> [--dry-run] [--yes] [--json]";
|
|
26057
|
+
const { body, targetLabel, dryRun, yes, jsonOutput } = parseScopedTargetFlags(flagArgs, USAGE2);
|
|
25638
26058
|
if (!dryRun && !yes && !jsonOutput) {
|
|
25639
26059
|
console.log(`About to REAP every live harness sandbox / token / slot in: ${targetLabel}.`);
|
|
25640
26060
|
console.log("This destroys running sandboxes and revokes their tokens. Run with --dry-run first to see the blast radius.");
|
|
@@ -25688,8 +26108,8 @@ function rejectHarnessFlags(flagArgs, usage3) {
|
|
|
25688
26108
|
process.exit(1);
|
|
25689
26109
|
}
|
|
25690
26110
|
async function runHarnessToggle(enable, flagArgs) {
|
|
25691
|
-
const
|
|
25692
|
-
rejectHarnessFlags(flagArgs,
|
|
26111
|
+
const USAGE2 = "wayai admin harness enable|disable";
|
|
26112
|
+
rejectHarnessFlags(flagArgs, USAGE2);
|
|
25693
26113
|
const { config, accessToken } = await requireAuth();
|
|
25694
26114
|
const client = new ApiClient({ apiUrl: config.api_url, accessToken });
|
|
25695
26115
|
let value;
|
|
@@ -25710,8 +26130,8 @@ async function runHarnessToggle(enable, flagArgs) {
|
|
|
25710
26130
|
}
|
|
25711
26131
|
}
|
|
25712
26132
|
async function runHarnessStatus(flagArgs) {
|
|
25713
|
-
const
|
|
25714
|
-
rejectHarnessFlags(flagArgs,
|
|
26133
|
+
const USAGE2 = "wayai admin harness status";
|
|
26134
|
+
rejectHarnessFlags(flagArgs, USAGE2);
|
|
25715
26135
|
const { config, accessToken } = await requireAuth();
|
|
25716
26136
|
const client = new ApiClient({ apiUrl: config.api_url, accessToken });
|
|
25717
26137
|
let value = 0;
|
|
@@ -26612,26 +27032,26 @@ async function reportGetCommand(args2) {
|
|
|
26612
27032
|
console.log(JSON.stringify(result, null, 2));
|
|
26613
27033
|
return;
|
|
26614
27034
|
}
|
|
26615
|
-
const { report, messages } = result;
|
|
26616
|
-
const title = sanitizeTerminalText(
|
|
26617
|
-
const description = sanitizeTerminalText(
|
|
26618
|
-
console.log(`Report ${
|
|
27035
|
+
const { report: report2, messages } = result;
|
|
27036
|
+
const title = sanitizeTerminalText(report2.title);
|
|
27037
|
+
const description = sanitizeTerminalText(report2.description);
|
|
27038
|
+
console.log(`Report ${report2.report_id}`);
|
|
26619
27039
|
console.log(` title: ${title}`);
|
|
26620
27040
|
console.log(` description: ${description.replace(/\n/g, "\n ")}`);
|
|
26621
|
-
console.log(` status: ${
|
|
26622
|
-
console.log(` classification: ${
|
|
26623
|
-
if (
|
|
26624
|
-
if (
|
|
27041
|
+
console.log(` status: ${report2.status}`);
|
|
27042
|
+
console.log(` classification: ${report2.classification}`);
|
|
27043
|
+
if (report2.contest_count > 0) console.log(` contests: ${report2.contest_count}`);
|
|
27044
|
+
if (report2.dismissal_final) console.log(" dismissal: final (non-contestable)");
|
|
26625
27045
|
if (messages.length > 0) {
|
|
26626
27046
|
console.log("\n Thread:");
|
|
26627
27047
|
for (const m of messages) {
|
|
26628
27048
|
console.log(` [${m.author_role}] ${sanitizeTerminalText(m.body)}`);
|
|
26629
27049
|
}
|
|
26630
27050
|
}
|
|
26631
|
-
if (
|
|
27051
|
+
if (report2.status === "shipped") {
|
|
26632
27052
|
console.log(`
|
|
26633
|
-
This fix is shipped. Run \`wayai report accept ${
|
|
26634
|
-
console.log(` or \`wayai report contest ${
|
|
27053
|
+
This fix is shipped. Run \`wayai report accept ${report2.report_id}\` if it works,`);
|
|
27054
|
+
console.log(` or \`wayai report contest ${report2.report_id} --reason "..."\` if it does not.`);
|
|
26635
27055
|
}
|
|
26636
27056
|
} catch (err) {
|
|
26637
27057
|
reportActionError(err);
|
|
@@ -26911,7 +27331,7 @@ var init_actions = __esm({
|
|
|
26911
27331
|
|
|
26912
27332
|
// src/data/commands/attachments.ts
|
|
26913
27333
|
import { Command as Command2 } from "commander";
|
|
26914
|
-
import { readFileSync as
|
|
27334
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
26915
27335
|
function findAttachmentByFilename(attachments, filename) {
|
|
26916
27336
|
return attachments.find((a) => a.key.endsWith(`/${filename}`)) ?? null;
|
|
26917
27337
|
}
|
|
@@ -26952,7 +27372,7 @@ function buildAttachmentsCommand() {
|
|
|
26952
27372
|
printOutput(data, outputFormat(this));
|
|
26953
27373
|
return;
|
|
26954
27374
|
}
|
|
26955
|
-
const body =
|
|
27375
|
+
const body = readFileSync20(opts.file);
|
|
26956
27376
|
await client.upload(uploadPathFrom(data?.upload_url), body, opts.contentType);
|
|
26957
27377
|
printOutput({ ...data, uploaded: true }, outputFormat(this));
|
|
26958
27378
|
});
|
|
@@ -27432,16 +27852,16 @@ var init_providers = __esm({
|
|
|
27432
27852
|
|
|
27433
27853
|
// src/data/commands/report.ts
|
|
27434
27854
|
import { Command as Command6 } from "commander";
|
|
27435
|
-
import { readFileSync as
|
|
27436
|
-
import { dirname as
|
|
27855
|
+
import { readFileSync as readFileSync21 } from "fs";
|
|
27856
|
+
import { dirname as dirname12, join as join31 } from "path";
|
|
27437
27857
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
27438
27858
|
function resolveCliVersion() {
|
|
27439
27859
|
for (const candidate of [
|
|
27440
|
-
|
|
27441
|
-
|
|
27860
|
+
join31(here, "..", "package.json"),
|
|
27861
|
+
join31(here, "..", "..", "..", "package.json")
|
|
27442
27862
|
]) {
|
|
27443
27863
|
try {
|
|
27444
|
-
const version = JSON.parse(
|
|
27864
|
+
const version = JSON.parse(readFileSync21(candidate, "utf-8")).version;
|
|
27445
27865
|
if (typeof version === "string" && version) return version;
|
|
27446
27866
|
} catch {
|
|
27447
27867
|
}
|
|
@@ -27475,10 +27895,10 @@ function reportActionError2(err) {
|
|
|
27475
27895
|
throw err;
|
|
27476
27896
|
}
|
|
27477
27897
|
function buildBasesReportCommand() {
|
|
27478
|
-
const
|
|
27898
|
+
const report2 = new Command6("report").description(
|
|
27479
27899
|
"File a report to the Data triage queue and verify the outcome"
|
|
27480
27900
|
);
|
|
27481
|
-
|
|
27901
|
+
report2.command("create").description("Submit a report to the Data triage queue (deduplicated)").requiredOption("--title <title>", "Short summary").requiredOption("--description <text>", "What happened").option("--source <source>", "Origin: cli_report (default) | review | security_audit").option("--classification <c>", "Nature: bug (default) | flaky_test | security | enhancement").option(
|
|
27482
27902
|
"--dedup-key <key>",
|
|
27483
27903
|
'Stable dedup key (e.g. "<file>::<test>"); collapses repeat occurrences'
|
|
27484
27904
|
).option("--severity <level>", "low | medium | high | critical").option("--steps <text>", "Steps to reproduce").option("--error-message <text>", "Exact error text if any").option("--context <text>", "Additional context (logs, request ids)").option("--locale <code>", "Notification locale (en | pt | es)", "en").option("--reporter-email <addr>", "Override reporter email (defaults to session email)").option("--base-id <id>", "Base the error relates to (defaults to the configured base)").option("--record-type <name>", "Record type the error relates to").option("--record-id <id>", "Record id (UUID) the error relates to").option("--external-id <id>", "External id of the related record").option("--external-source <src>", "External source of the related record").option("--relationship-id <id>", "Relationship id the error relates to").action(async function(opts) {
|
|
@@ -27529,7 +27949,7 @@ function buildBasesReportCommand() {
|
|
|
27529
27949
|
);
|
|
27530
27950
|
}
|
|
27531
27951
|
});
|
|
27532
|
-
|
|
27952
|
+
report2.command("list").description("List your reports, newest first").option("--status <s>", "Filter by status (e.g. shipped \u2014 awaiting your verification)").action(async function(opts) {
|
|
27533
27953
|
const client = await createDataClient();
|
|
27534
27954
|
const qs = opts.status ? `?status=${encodeURIComponent(opts.status)}` : "";
|
|
27535
27955
|
try {
|
|
@@ -27552,7 +27972,7 @@ function buildBasesReportCommand() {
|
|
|
27552
27972
|
reportActionError2(err);
|
|
27553
27973
|
}
|
|
27554
27974
|
});
|
|
27555
|
-
|
|
27975
|
+
report2.command("get <report_id>").description("Show one of your reports: status + the message thread").action(async function(reportId) {
|
|
27556
27976
|
const client = await createDataClient();
|
|
27557
27977
|
try {
|
|
27558
27978
|
const data = await client.request("GET", `/v1/reports/${pathSegment(reportId, "report id")}`);
|
|
@@ -27589,7 +28009,7 @@ function buildBasesReportCommand() {
|
|
|
27589
28009
|
reportActionError2(err);
|
|
27590
28010
|
}
|
|
27591
28011
|
});
|
|
27592
|
-
|
|
28012
|
+
report2.command("accept <report_id>").description("Accept a shipped fix (\u2192 addressed)").action(async function(reportId) {
|
|
27593
28013
|
const client = await createDataClient();
|
|
27594
28014
|
try {
|
|
27595
28015
|
const data = await client.request(
|
|
@@ -27605,7 +28025,7 @@ function buildBasesReportCommand() {
|
|
|
27605
28025
|
reportActionError2(err);
|
|
27606
28026
|
}
|
|
27607
28027
|
});
|
|
27608
|
-
|
|
28028
|
+
report2.command("contest <report_id>").description("Contest a shipped fix or a dismissal (\u2192 back to triage)").requiredOption("--reason <text>", "Why the fix/dismissal is wrong").action(async function(reportId, opts) {
|
|
27609
28029
|
const client = await createDataClient();
|
|
27610
28030
|
try {
|
|
27611
28031
|
const data = await client.request(
|
|
@@ -27624,7 +28044,7 @@ function buildBasesReportCommand() {
|
|
|
27624
28044
|
reportActionError2(err);
|
|
27625
28045
|
}
|
|
27626
28046
|
});
|
|
27627
|
-
return
|
|
28047
|
+
return report2;
|
|
27628
28048
|
}
|
|
27629
28049
|
var here;
|
|
27630
28050
|
var init_report2 = __esm({
|
|
@@ -27637,13 +28057,13 @@ var init_report2 = __esm({
|
|
|
27637
28057
|
init_terminal_output();
|
|
27638
28058
|
init_workspace();
|
|
27639
28059
|
init_skill_version();
|
|
27640
|
-
here =
|
|
28060
|
+
here = dirname12(fileURLToPath2(import.meta.url));
|
|
27641
28061
|
}
|
|
27642
28062
|
});
|
|
27643
28063
|
|
|
27644
28064
|
// src/data/commands/credentials.ts
|
|
27645
28065
|
import { Command as Command7 } from "commander";
|
|
27646
|
-
import { readFileSync as
|
|
28066
|
+
import { readFileSync as readFileSync22 } from "fs";
|
|
27647
28067
|
function withValueSourceOptions(cmd, what) {
|
|
27648
28068
|
return cmd.option(
|
|
27649
28069
|
"--file <path>",
|
|
@@ -27656,7 +28076,7 @@ async function resolveValue(opts, label) {
|
|
|
27656
28076
|
throw expected("--file cannot be combined with --value-stdin or --value-prompt \u2014 pass one.");
|
|
27657
28077
|
}
|
|
27658
28078
|
try {
|
|
27659
|
-
return
|
|
28079
|
+
return readFileSync22(opts.file).toString("base64");
|
|
27660
28080
|
} catch (e) {
|
|
27661
28081
|
throw expected(`--file ${opts.file}: ${e instanceof Error ? e.message : "could not be read"}`);
|
|
27662
28082
|
}
|
|
@@ -27805,7 +28225,7 @@ var init_credentials = __esm({
|
|
|
27805
28225
|
|
|
27806
28226
|
// src/data/commands/sql.ts
|
|
27807
28227
|
import { Command as Command8 } from "commander";
|
|
27808
|
-
import { readFileSync as
|
|
28228
|
+
import { readFileSync as readFileSync23 } from "fs";
|
|
27809
28229
|
function buildBasesSqlCommand() {
|
|
27810
28230
|
return withBaseOption(new Command8("sql")).description("Execute a read-only SQL query against base data").argument("[query]", "SQL query (SELECT only)").option("--file <path>", "Read SQL from a file instead of the argument").option(
|
|
27811
28231
|
"--param <kv...>",
|
|
@@ -27815,7 +28235,7 @@ function buildBasesSqlCommand() {
|
|
|
27815
28235
|
let query;
|
|
27816
28236
|
if (opts.file) {
|
|
27817
28237
|
try {
|
|
27818
|
-
query =
|
|
28238
|
+
query = readFileSync23(opts.file, "utf-8").trim();
|
|
27819
28239
|
} catch (e) {
|
|
27820
28240
|
throw expected(`--file ${opts.file}: ${e instanceof Error ? e.message : "could not be read"}`);
|
|
27821
28241
|
}
|
|
@@ -27950,16 +28370,16 @@ MCP URL: ${toolsetMcpUrl(slug)}`);
|
|
|
27950
28370
|
).option("--force", "Revoke even if the token appears to be in live use").action(async function(tokenId, opts) {
|
|
27951
28371
|
const client = await createDataClient();
|
|
27952
28372
|
const id = pathSegment(tokenId, "token id");
|
|
27953
|
-
const
|
|
28373
|
+
const path35 = (force) => `/v1/tokens/${id}${force ? "?force=true" : ""}`;
|
|
27954
28374
|
const format = outputFormat(this);
|
|
27955
28375
|
const revoked = (forced) => printOutput({ token_id: tokenId, revoked: true, forced }, format);
|
|
27956
28376
|
if (opts.force) {
|
|
27957
|
-
await client.request("DELETE",
|
|
28377
|
+
await client.request("DELETE", path35(true));
|
|
27958
28378
|
revoked(true);
|
|
27959
28379
|
return;
|
|
27960
28380
|
}
|
|
27961
28381
|
try {
|
|
27962
|
-
await client.request("DELETE",
|
|
28382
|
+
await client.request("DELETE", path35(false));
|
|
27963
28383
|
revoked(false);
|
|
27964
28384
|
} catch (err) {
|
|
27965
28385
|
if (!(err instanceof ApiError) || err.status !== 409 || dataErrorDetails(err)?.requires_force !== true) {
|
|
@@ -27974,7 +28394,7 @@ MCP URL: ${toolsetMcpUrl(slug)}`);
|
|
|
27974
28394
|
console.error("Aborted.");
|
|
27975
28395
|
return process.exit(1);
|
|
27976
28396
|
}
|
|
27977
|
-
await client.request("DELETE",
|
|
28397
|
+
await client.request("DELETE", path35(true));
|
|
27978
28398
|
revoked(true);
|
|
27979
28399
|
}
|
|
27980
28400
|
});
|
|
@@ -28122,10 +28542,9 @@ var init_base_tags = __esm({
|
|
|
28122
28542
|
|
|
28123
28543
|
// src/data/commands/bases.ts
|
|
28124
28544
|
import { Command as Command10 } from "commander";
|
|
28125
|
-
|
|
28126
|
-
|
|
28127
|
-
|
|
28128
|
-
return `${path36}${path36.includes("?") ? "&" : "?"}cursor=${encodeURIComponent(cursor)}`;
|
|
28545
|
+
function pageOf(path35, cursor) {
|
|
28546
|
+
if (!cursor) return path35;
|
|
28547
|
+
return `${path35}${path35.includes("?") ? "&" : "?"}cursor=${encodeURIComponent(cursor)}`;
|
|
28129
28548
|
}
|
|
28130
28549
|
function parseEnum(flag, value, allowed) {
|
|
28131
28550
|
if (value === void 0) return void 0;
|
|
@@ -28282,9 +28701,9 @@ function buildBasesCommand() {
|
|
|
28282
28701
|
});
|
|
28283
28702
|
bases.command("list-previews <origin-id>").description("List preview bases cloned from a base (production or preview)").action(async function(originId) {
|
|
28284
28703
|
const client = await createDataClient();
|
|
28285
|
-
const
|
|
28704
|
+
const path35 = `/v1/${pathSegment(originId, "origin base id")}/previews`;
|
|
28286
28705
|
printOutput(
|
|
28287
|
-
await client.collectPages((cursor) => pageOf(
|
|
28706
|
+
await client.collectPages((cursor) => pageOf(path35, cursor)),
|
|
28288
28707
|
outputFormat(this)
|
|
28289
28708
|
);
|
|
28290
28709
|
});
|
|
@@ -28331,45 +28750,52 @@ function buildBasesCommand() {
|
|
|
28331
28750
|
});
|
|
28332
28751
|
bases.command("promotions <production-id>").description("List promotion history for a production base").action(async function(productionId) {
|
|
28333
28752
|
const client = await createDataClient();
|
|
28334
|
-
const
|
|
28753
|
+
const path35 = `/v1/${pathSegment(productionId, "production base id")}/promotions`;
|
|
28335
28754
|
printOutput(
|
|
28336
|
-
await client.collectPages((cursor) => pageOf(
|
|
28755
|
+
await client.collectPages((cursor) => pageOf(path35, cursor)),
|
|
28337
28756
|
outputFormat(this)
|
|
28338
28757
|
);
|
|
28339
28758
|
});
|
|
28340
28759
|
bases.command("use <base>").description(
|
|
28341
|
-
"
|
|
28760
|
+
"Deprecated alias of `wayai use bases/<id>` \u2014 scope this worktree to a base"
|
|
28342
28761
|
).action(async function(selector) {
|
|
28343
|
-
const baseId =
|
|
28344
|
-
const previous =
|
|
28345
|
-
|
|
28762
|
+
const baseId = resolveBaseSelectorToId(findGitRoot(), selector);
|
|
28763
|
+
const previous = readScope().bases;
|
|
28764
|
+
const changed = previous.length !== 1 || previous[0] !== baseId;
|
|
28765
|
+
if (changed) {
|
|
28346
28766
|
try {
|
|
28347
|
-
|
|
28767
|
+
setScopeAxis("bases", [baseId]);
|
|
28348
28768
|
} catch (err) {
|
|
28349
28769
|
throw expected(err instanceof Error ? err.message : String(err));
|
|
28350
28770
|
}
|
|
28351
28771
|
}
|
|
28352
28772
|
if (outputFormat(this) === "json") {
|
|
28353
|
-
printOutput(
|
|
28773
|
+
printOutput(
|
|
28774
|
+
{ base_id: baseId, previous_base_id: previous[0] ?? null, changed },
|
|
28775
|
+
"json"
|
|
28776
|
+
);
|
|
28354
28777
|
return;
|
|
28355
28778
|
}
|
|
28356
|
-
if (
|
|
28779
|
+
if (!changed) {
|
|
28357
28780
|
console.log(`Worktree already bound to base ${baseId}.`);
|
|
28358
28781
|
} else {
|
|
28359
28782
|
console.log(
|
|
28360
|
-
previous ? `Worktree rebound: ${previous} -> ${baseId}.` : `Worktree bound to base ${baseId}.`
|
|
28783
|
+
previous.length > 0 ? `Worktree rebound: ${previous.join(", ")} -> ${baseId}.` : `Worktree bound to base ${baseId}.`
|
|
28361
28784
|
);
|
|
28362
28785
|
}
|
|
28363
28786
|
});
|
|
28364
|
-
bases.command("unbind").description("
|
|
28365
|
-
const previous =
|
|
28366
|
-
if (previous)
|
|
28787
|
+
bases.command("unbind").description("Deprecated alias of `wayai unbind bases/<id>` \u2014 clear the base scope").action(async function() {
|
|
28788
|
+
const previous = readScope().bases;
|
|
28789
|
+
if (previous.length > 0) setScopeAxis("bases", []);
|
|
28367
28790
|
if (outputFormat(this) === "json") {
|
|
28368
|
-
printOutput(
|
|
28791
|
+
printOutput(
|
|
28792
|
+
{ previous_base_id: previous[0] ?? null, cleared: previous.length > 0 },
|
|
28793
|
+
"json"
|
|
28794
|
+
);
|
|
28369
28795
|
return;
|
|
28370
28796
|
}
|
|
28371
28797
|
console.log(
|
|
28372
|
-
previous ? `Worktree unbound from base (was: ${previous}).` : "No base binding to clear."
|
|
28798
|
+
previous.length > 0 ? `Worktree unbound from base (was: ${previous.join(", ")}).` : "No base binding to clear."
|
|
28373
28799
|
);
|
|
28374
28800
|
});
|
|
28375
28801
|
bases.addCommand(buildBasesTokensCommand());
|
|
@@ -28381,13 +28807,6 @@ function buildBasesCommand() {
|
|
|
28381
28807
|
bases.addCommand(buildBasesReportCommand());
|
|
28382
28808
|
return bases;
|
|
28383
28809
|
}
|
|
28384
|
-
function resolveSelectorToBaseId(selector) {
|
|
28385
|
-
const gitRoot = findGitRoot();
|
|
28386
|
-
if (!gitRoot || selector.includes("/") || selector.includes(path35.sep)) return selector;
|
|
28387
|
-
if (!isPathSafeId(selector)) return selector;
|
|
28388
|
-
const id = readBaseMeta(path35.join(resolveBasesDir(gitRoot), selector))?.base_id;
|
|
28389
|
-
return typeof id === "string" && isPathSafeId(id) ? id : selector;
|
|
28390
|
-
}
|
|
28391
28810
|
var init_bases = __esm({
|
|
28392
28811
|
"src/data/commands/bases.ts"() {
|
|
28393
28812
|
"use strict";
|
|
@@ -28405,10 +28824,8 @@ var init_bases = __esm({
|
|
|
28405
28824
|
init_utils();
|
|
28406
28825
|
init_terminal_output();
|
|
28407
28826
|
init_workspace();
|
|
28408
|
-
init_layout();
|
|
28409
28827
|
init_base_workspace();
|
|
28410
|
-
|
|
28411
|
-
init_base_id();
|
|
28828
|
+
init_worktree_scope();
|
|
28412
28829
|
init_expected();
|
|
28413
28830
|
}
|
|
28414
28831
|
});
|
|
@@ -28473,7 +28890,7 @@ var init_file_types = __esm({
|
|
|
28473
28890
|
|
|
28474
28891
|
// src/data/commands/files.ts
|
|
28475
28892
|
import { Command as Command12 } from "commander";
|
|
28476
|
-
import { readFileSync as
|
|
28893
|
+
import { readFileSync as readFileSync24, writeFileSync as writeFileSync16 } from "fs";
|
|
28477
28894
|
import { basename as basename18 } from "path";
|
|
28478
28895
|
function renderFileDiff(fileType, filePath, from, to, d) {
|
|
28479
28896
|
console.log(sanitizeTerminalText(`${fileType}/${filePath}: v${from} \u2192 v${to}`));
|
|
@@ -28522,7 +28939,7 @@ function buildFilesCommand() {
|
|
|
28522
28939
|
"Upload a local file to a path (e.g. wayai files put reports q3/summary.pdf --file ./summary.pdf)"
|
|
28523
28940
|
).requiredOption("--file <local>", "Local file to upload").option("--content-type <type>", "MIME type", "application/octet-stream").action(async function(fileType, filePath, opts) {
|
|
28524
28941
|
const base = pathSegment(requireBase(this), "--base");
|
|
28525
|
-
const body =
|
|
28942
|
+
const body = readFileSync24(opts.file);
|
|
28526
28943
|
const client = await createDataClient();
|
|
28527
28944
|
printOutput(
|
|
28528
28945
|
await client.upload(
|
|
@@ -28882,8 +29299,8 @@ function buildRecordsCommand() {
|
|
|
28882
29299
|
const body = { data: parseData(opts.data) };
|
|
28883
29300
|
if (opts.externalId) body.external_id = opts.externalId;
|
|
28884
29301
|
if (opts.externalSource) body.external_source = opts.externalSource;
|
|
28885
|
-
const
|
|
28886
|
-
printOutput(await client.request("PUT",
|
|
29302
|
+
const path35 = opts.id ? `/v1/${base}/records/${pathSegment(recordType2, "record_type")}/${pathSegment(opts.id, "--id")}` : `/v1/${base}/records/${pathSegment(recordType2, "record_type")}`;
|
|
29303
|
+
printOutput(await client.request("PUT", path35, body), outputFormat(this));
|
|
28887
29304
|
});
|
|
28888
29305
|
records.command("query <record_type>").description("List/search records: exact filters + fuzzy `search`, sorting, pagination").option(
|
|
28889
29306
|
"--external-source <source>",
|
|
@@ -28918,9 +29335,9 @@ function buildRecordsCommand() {
|
|
|
28918
29335
|
).action(async function(recordType2, id, opts) {
|
|
28919
29336
|
const base = pathSegment(requireBase(this), "--base");
|
|
28920
29337
|
const client = await createDataClient();
|
|
28921
|
-
let
|
|
28922
|
-
if (opts.externalSource)
|
|
28923
|
-
printOutput(await client.request("GET",
|
|
29338
|
+
let path35 = `/v1/${base}/records/${pathSegment(recordType2, "record_type")}/${recordKey(id, opts.externalSource)}`;
|
|
29339
|
+
if (opts.externalSource) path35 += `?external_source=${encodeURIComponent(opts.externalSource)}`;
|
|
29340
|
+
printOutput(await client.request("GET", path35), outputFormat(this));
|
|
28924
29341
|
});
|
|
28925
29342
|
records.command("delete <record_type> <id>").description(
|
|
28926
29343
|
"Delete a record by internal ID, or by external_id (pass --external-source to scope it)"
|
|
@@ -28934,11 +29351,11 @@ function buildRecordsCommand() {
|
|
|
28934
29351
|
}
|
|
28935
29352
|
const base = pathSegment(requireBase(this), "--base");
|
|
28936
29353
|
const client = await createDataClient();
|
|
28937
|
-
let
|
|
29354
|
+
let path35 = `/v1/${base}/records/${pathSegment(recordType2, "record_type")}/${recordKey(id, opts.externalSource)}`;
|
|
28938
29355
|
if (opts.externalSource) {
|
|
28939
|
-
|
|
29356
|
+
path35 += `?external_source=${encodeURIComponent(opts.externalSource)}&external_id=${encodeURIComponent(id)}`;
|
|
28940
29357
|
}
|
|
28941
|
-
await client.request("DELETE",
|
|
29358
|
+
await client.request("DELETE", path35);
|
|
28942
29359
|
console.log("Deleted");
|
|
28943
29360
|
});
|
|
28944
29361
|
records.command("history <id>").description(
|
|
@@ -29103,8 +29520,8 @@ function buildRelationshipsCommand() {
|
|
|
29103
29520
|
if (opts.data) body.data = parseData(opts.data);
|
|
29104
29521
|
const base = pathSegment(requireBase(this), "--base");
|
|
29105
29522
|
const client = await createDataClient();
|
|
29106
|
-
const
|
|
29107
|
-
printOutput(await client.request("PUT",
|
|
29523
|
+
const path35 = opts.id ? `/v1/${base}/relationships/${pathSegment(opts.id, "--id")}` : `/v1/${base}/relationships`;
|
|
29524
|
+
printOutput(await client.request("PUT", path35, body), outputFormat(this));
|
|
29108
29525
|
});
|
|
29109
29526
|
relationships.command("get <id>").description(
|
|
29110
29527
|
"Get a relationship by ID (or by its external key: pass the external_id with --rel-type)"
|
|
@@ -29337,8 +29754,8 @@ function buildToolsetsCommand() {
|
|
|
29337
29754
|
toolsets.command("get <slug>").description("Get a toolset").option("--resolved", "Include resolved record_type schemas").action(async function(slug, opts) {
|
|
29338
29755
|
const base = pathSegment(requireBase(this), "--base");
|
|
29339
29756
|
const client = await createDataClient();
|
|
29340
|
-
const
|
|
29341
|
-
printOutput(await client.request("GET",
|
|
29757
|
+
const path35 = opts.resolved ? `/v1/${base}/toolsets/${pathSegment(slug, "toolset slug")}/resolved` : `/v1/${base}/toolsets/${pathSegment(slug, "toolset slug")}`;
|
|
29758
|
+
printOutput(await client.request("GET", path35), outputFormat(this));
|
|
29342
29759
|
});
|
|
29343
29760
|
toolsets.command("list").description("List all toolsets").action(async function() {
|
|
29344
29761
|
const base = pathSegment(requireBase(this), "--base");
|
|
@@ -29483,7 +29900,7 @@ __export(program_exports, {
|
|
|
29483
29900
|
});
|
|
29484
29901
|
import { Command as Command22 } from "commander";
|
|
29485
29902
|
function withDataGlobals(command2) {
|
|
29486
|
-
return command2.option("--org <uuid>", "Organization to operate against (overrides
|
|
29903
|
+
return command2.option("--org <uuid>", "Organization to operate against (overrides the repo's org binding)").option("--output <format>", "Output format: json or table", "table").option("--json", "Shorthand for --output json");
|
|
29487
29904
|
}
|
|
29488
29905
|
function routeErrorsToCli(command2) {
|
|
29489
29906
|
command2.exitOverride().configureOutput({ outputError: () => {
|
|
@@ -29571,9 +29988,9 @@ init_errors2();
|
|
|
29571
29988
|
init_mask_secrets();
|
|
29572
29989
|
init_utils();
|
|
29573
29990
|
init_registry();
|
|
29574
|
-
import { readFileSync as
|
|
29991
|
+
import { readFileSync as readFileSync25 } from "fs";
|
|
29575
29992
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
29576
|
-
import { dirname as
|
|
29993
|
+
import { dirname as dirname13, join as join32 } from "path";
|
|
29577
29994
|
|
|
29578
29995
|
// src/lib/version-refresh.ts
|
|
29579
29996
|
init_version_cache();
|
|
@@ -29581,7 +29998,7 @@ init_skill_version();
|
|
|
29581
29998
|
import { exec } from "child_process";
|
|
29582
29999
|
var REFRESH_TIMEOUT_MS = 1e4;
|
|
29583
30000
|
function refreshCliCache() {
|
|
29584
|
-
return new Promise((
|
|
30001
|
+
return new Promise((resolve8) => {
|
|
29585
30002
|
exec("npm view @wayai/cli version", { timeout: REFRESH_TIMEOUT_MS }, (err, stdout) => {
|
|
29586
30003
|
if (!err) {
|
|
29587
30004
|
const latest = stdout.trim();
|
|
@@ -29592,7 +30009,7 @@ function refreshCliCache() {
|
|
|
29592
30009
|
}
|
|
29593
30010
|
}
|
|
29594
30011
|
}
|
|
29595
|
-
|
|
30012
|
+
resolve8();
|
|
29596
30013
|
});
|
|
29597
30014
|
});
|
|
29598
30015
|
}
|
|
@@ -29618,8 +30035,8 @@ async function refreshSkillCache() {
|
|
|
29618
30035
|
}
|
|
29619
30036
|
async function refreshAdminSkillCache() {
|
|
29620
30037
|
let timer;
|
|
29621
|
-
const deadline = new Promise((
|
|
29622
|
-
timer = setTimeout(
|
|
30038
|
+
const deadline = new Promise((resolve8) => {
|
|
30039
|
+
timer = setTimeout(resolve8, REFRESH_TIMEOUT_MS);
|
|
29623
30040
|
});
|
|
29624
30041
|
await Promise.race([deadline, fetchAndCacheAdminSkillVersion().catch(() => {
|
|
29625
30042
|
})]);
|
|
@@ -29728,8 +30145,8 @@ Run \`wayai admin skill install\` to update.`);
|
|
|
29728
30145
|
}
|
|
29729
30146
|
|
|
29730
30147
|
// src/index.ts
|
|
29731
|
-
var __dirname =
|
|
29732
|
-
var pkg = JSON.parse(
|
|
30148
|
+
var __dirname = dirname13(fileURLToPath3(import.meta.url));
|
|
30149
|
+
var pkg = JSON.parse(readFileSync25(join32(__dirname, "..", "package.json"), "utf-8"));
|
|
29733
30150
|
var [, , command, ...args] = process.argv;
|
|
29734
30151
|
var isBackgroundRefresh = command === REFRESH_COMMAND;
|
|
29735
30152
|
if (!isBackgroundRefresh) initSentry(command, pkg.version);
|
|
@@ -29964,7 +30381,7 @@ Commands:
|
|
|
29964
30381
|
logout Clear stored credentials
|
|
29965
30382
|
status Show current auth and config status
|
|
29966
30383
|
whoami Show the authenticated identity (supports --json)
|
|
29967
|
-
init
|
|
30384
|
+
init Scope this repo to an organization (pick one)
|
|
29968
30385
|
create-credential Create an organization credential (API key, token, etc.)
|
|
29969
30386
|
update-credential Update / rotate an organization credential (by name)
|
|
29970
30387
|
set-connection-credential Set a connection's credential directly (org link or --field/--stdin), preview or production
|
|
@@ -29978,9 +30395,9 @@ Commands:
|
|
|
29978
30395
|
sync Alias of \`publish\` (not to be confused with sync-skills / sync-mcp)
|
|
29979
30396
|
org create Create a new organization (you become its owner)
|
|
29980
30397
|
org <pull|push|diff> Sync org-scoped resources as code (wayai-ws/org/)
|
|
29981
|
-
use <
|
|
30398
|
+
use [--add] <sel> Scope this worktree to a hub or base (UUID, folder name, hubs/<n>, bases/<n>; --add widens)
|
|
29982
30399
|
migrate Move a legacy repo to the wayai-ws/{hubs,org} layout
|
|
29983
|
-
unbind
|
|
30400
|
+
unbind [<sel>] Drop one entry from the worktree scope, or clear the whole scope
|
|
29984
30401
|
send-message Send a test message to a hub (preview or production; -f <path> to attach a file)
|
|
29985
30402
|
conversations List or inspect conversations
|
|
29986
30403
|
alerts Show a hub's active connection/credential alerts (run this FIRST when a hub misbehaves)
|
|
@@ -30002,8 +30419,8 @@ Commands:
|
|
|
30002
30419
|
Data \u2014 one namespace per entity. Run \`wayai <namespace> --help\` for its tree.
|
|
30003
30420
|
${await dataHelpBlock()}
|
|
30004
30421
|
bases promote Promote a preview base to production (distinct from \`publish\`, which promotes a hub)
|
|
30005
|
-
bases use <base>
|
|
30006
|
-
bases unbind
|
|
30422
|
+
bases use <base> Deprecated alias of \`wayai use bases/<id>\`
|
|
30423
|
+
bases unbind Deprecated alias of \`wayai unbind bases/<id>\` (clears the base axis)
|
|
30007
30424
|
|
|
30008
30425
|
Flags:
|
|
30009
30426
|
--yes, -y Skip confirmation prompts (useful for CI and scripting)
|
|
@@ -30047,7 +30464,7 @@ Flags:
|
|
|
30047
30464
|
--version, -v Show CLI version
|
|
30048
30465
|
|
|
30049
30466
|
Org-scoped mode:
|
|
30050
|
-
Each repository is scoped to a single organization via
|
|
30467
|
+
Each repository is scoped to a single organization via wayai-ws/wayai.yaml
|
|
30051
30468
|
(only \`organization_id\` is required). Hubs self-identify via \`hub.yaml\`
|
|
30052
30469
|
inside their folder under \`workspace/\`.
|
|
30053
30470
|
|
|
@@ -30055,12 +30472,15 @@ Org-scoped mode:
|
|
|
30055
30472
|
pull/push operate on the single hub in the workspace, or pass
|
|
30056
30473
|
\`--hub <uuid|name>\` to disambiguate when multiple hubs exist.
|
|
30057
30474
|
|
|
30058
|
-
Worktree
|
|
30059
|
-
Each git checkout (main or linked worktree)
|
|
30060
|
-
|
|
30061
|
-
|
|
30062
|
-
|
|
30063
|
-
|
|
30475
|
+
Worktree scope:
|
|
30476
|
+
Each git checkout (main or linked worktree) carries a scope: a set of hubs and
|
|
30477
|
+
a set of bases, at \`<git-dir>/wayai-scope\` \u2014 per-checkout, never tracked.
|
|
30478
|
+
push/pull/publish refuse to run against anything outside a non-empty set. Each
|
|
30479
|
+
axis is seeded by the first successful pull/push/create into a checkout that
|
|
30480
|
+
has none, and only widens on purpose: \`wayai use --add <sel>\` adds one,
|
|
30481
|
+
\`wayai use <sel>\` replaces that axis, \`wayai unbind <sel>\` drops one entry and
|
|
30482
|
+
bare \`wayai unbind\` clears everything. It is a routing tripwire, not a lock
|
|
30483
|
+
and not authorization.
|
|
30064
30484
|
|
|
30065
30485
|
Examples:
|
|
30066
30486
|
wayai login
|