beplus-mcp 0.27.0 → 0.29.0
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/README.md +50 -6
- package/dist/index.js +2084 -671
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7678,15 +7678,15 @@ var $ZodCheckLessThan = /* @__PURE__ */ $constructor("$ZodCheckLessThan", (inst,
|
|
|
7678
7678
|
bag.exclusiveMaximum = def.value;
|
|
7679
7679
|
}
|
|
7680
7680
|
});
|
|
7681
|
-
inst._zod.check = (
|
|
7682
|
-
if (def.inclusive ?
|
|
7681
|
+
inst._zod.check = (payload2) => {
|
|
7682
|
+
if (def.inclusive ? payload2.value <= def.value : payload2.value < def.value) {
|
|
7683
7683
|
return;
|
|
7684
7684
|
}
|
|
7685
|
-
|
|
7685
|
+
payload2.issues.push({
|
|
7686
7686
|
origin,
|
|
7687
7687
|
code: "too_big",
|
|
7688
7688
|
maximum: def.value,
|
|
7689
|
-
input:
|
|
7689
|
+
input: payload2.value,
|
|
7690
7690
|
inclusive: def.inclusive,
|
|
7691
7691
|
inst,
|
|
7692
7692
|
continue: !def.abort
|
|
@@ -7706,15 +7706,15 @@ var $ZodCheckGreaterThan = /* @__PURE__ */ $constructor("$ZodCheckGreaterThan",
|
|
|
7706
7706
|
bag.exclusiveMinimum = def.value;
|
|
7707
7707
|
}
|
|
7708
7708
|
});
|
|
7709
|
-
inst._zod.check = (
|
|
7710
|
-
if (def.inclusive ?
|
|
7709
|
+
inst._zod.check = (payload2) => {
|
|
7710
|
+
if (def.inclusive ? payload2.value >= def.value : payload2.value > def.value) {
|
|
7711
7711
|
return;
|
|
7712
7712
|
}
|
|
7713
|
-
|
|
7713
|
+
payload2.issues.push({
|
|
7714
7714
|
origin,
|
|
7715
7715
|
code: "too_small",
|
|
7716
7716
|
minimum: def.value,
|
|
7717
|
-
input:
|
|
7717
|
+
input: payload2.value,
|
|
7718
7718
|
inclusive: def.inclusive,
|
|
7719
7719
|
inst,
|
|
7720
7720
|
continue: !def.abort
|
|
@@ -7727,17 +7727,17 @@ var $ZodCheckMultipleOf = /* @__PURE__ */ $constructor("$ZodCheckMultipleOf", (i
|
|
|
7727
7727
|
var _a;
|
|
7728
7728
|
(_a = inst2._zod.bag).multipleOf ?? (_a.multipleOf = def.value);
|
|
7729
7729
|
});
|
|
7730
|
-
inst._zod.check = (
|
|
7731
|
-
if (typeof
|
|
7730
|
+
inst._zod.check = (payload2) => {
|
|
7731
|
+
if (typeof payload2.value !== typeof def.value)
|
|
7732
7732
|
throw new Error("Cannot mix number and bigint in multiple_of check.");
|
|
7733
|
-
const isMultiple = typeof
|
|
7733
|
+
const isMultiple = typeof payload2.value === "bigint" ? payload2.value % def.value === BigInt(0) : floatSafeRemainder(payload2.value, def.value) === 0;
|
|
7734
7734
|
if (isMultiple)
|
|
7735
7735
|
return;
|
|
7736
|
-
|
|
7737
|
-
origin: typeof
|
|
7736
|
+
payload2.issues.push({
|
|
7737
|
+
origin: typeof payload2.value,
|
|
7738
7738
|
code: "not_multiple_of",
|
|
7739
7739
|
divisor: def.value,
|
|
7740
|
-
input:
|
|
7740
|
+
input: payload2.value,
|
|
7741
7741
|
inst,
|
|
7742
7742
|
continue: !def.abort
|
|
7743
7743
|
});
|
|
@@ -7757,11 +7757,11 @@ var $ZodCheckNumberFormat = /* @__PURE__ */ $constructor("$ZodCheckNumberFormat"
|
|
|
7757
7757
|
if (isInt)
|
|
7758
7758
|
bag.pattern = integer;
|
|
7759
7759
|
});
|
|
7760
|
-
inst._zod.check = (
|
|
7761
|
-
const input =
|
|
7760
|
+
inst._zod.check = (payload2) => {
|
|
7761
|
+
const input = payload2.value;
|
|
7762
7762
|
if (isInt) {
|
|
7763
7763
|
if (!Number.isInteger(input)) {
|
|
7764
|
-
|
|
7764
|
+
payload2.issues.push({
|
|
7765
7765
|
expected: origin,
|
|
7766
7766
|
format: def.format,
|
|
7767
7767
|
code: "invalid_type",
|
|
@@ -7772,7 +7772,7 @@ var $ZodCheckNumberFormat = /* @__PURE__ */ $constructor("$ZodCheckNumberFormat"
|
|
|
7772
7772
|
}
|
|
7773
7773
|
if (!Number.isSafeInteger(input)) {
|
|
7774
7774
|
if (input > 0) {
|
|
7775
|
-
|
|
7775
|
+
payload2.issues.push({
|
|
7776
7776
|
input,
|
|
7777
7777
|
code: "too_big",
|
|
7778
7778
|
maximum: Number.MAX_SAFE_INTEGER,
|
|
@@ -7782,7 +7782,7 @@ var $ZodCheckNumberFormat = /* @__PURE__ */ $constructor("$ZodCheckNumberFormat"
|
|
|
7782
7782
|
continue: !def.abort
|
|
7783
7783
|
});
|
|
7784
7784
|
} else {
|
|
7785
|
-
|
|
7785
|
+
payload2.issues.push({
|
|
7786
7786
|
input,
|
|
7787
7787
|
code: "too_small",
|
|
7788
7788
|
minimum: Number.MIN_SAFE_INTEGER,
|
|
@@ -7796,7 +7796,7 @@ var $ZodCheckNumberFormat = /* @__PURE__ */ $constructor("$ZodCheckNumberFormat"
|
|
|
7796
7796
|
}
|
|
7797
7797
|
}
|
|
7798
7798
|
if (input < minimum) {
|
|
7799
|
-
|
|
7799
|
+
payload2.issues.push({
|
|
7800
7800
|
origin: "number",
|
|
7801
7801
|
input,
|
|
7802
7802
|
code: "too_small",
|
|
@@ -7807,7 +7807,7 @@ var $ZodCheckNumberFormat = /* @__PURE__ */ $constructor("$ZodCheckNumberFormat"
|
|
|
7807
7807
|
});
|
|
7808
7808
|
}
|
|
7809
7809
|
if (input > maximum) {
|
|
7810
|
-
|
|
7810
|
+
payload2.issues.push({
|
|
7811
7811
|
origin: "number",
|
|
7812
7812
|
input,
|
|
7813
7813
|
code: "too_big",
|
|
@@ -7820,8 +7820,8 @@ var $ZodCheckNumberFormat = /* @__PURE__ */ $constructor("$ZodCheckNumberFormat"
|
|
|
7820
7820
|
var $ZodCheckMaxLength = /* @__PURE__ */ $constructor("$ZodCheckMaxLength", (inst, def) => {
|
|
7821
7821
|
var _a;
|
|
7822
7822
|
$ZodCheck.init(inst, def);
|
|
7823
|
-
(_a = inst._zod.def).when ?? (_a.when = (
|
|
7824
|
-
const val =
|
|
7823
|
+
(_a = inst._zod.def).when ?? (_a.when = (payload2) => {
|
|
7824
|
+
const val = payload2.value;
|
|
7825
7825
|
return !nullish(val) && val.length !== void 0;
|
|
7826
7826
|
});
|
|
7827
7827
|
inst._zod.onattach.push((inst2) => {
|
|
@@ -7829,13 +7829,13 @@ var $ZodCheckMaxLength = /* @__PURE__ */ $constructor("$ZodCheckMaxLength", (ins
|
|
|
7829
7829
|
if (def.maximum < curr)
|
|
7830
7830
|
inst2._zod.bag.maximum = def.maximum;
|
|
7831
7831
|
});
|
|
7832
|
-
inst._zod.check = (
|
|
7833
|
-
const input =
|
|
7832
|
+
inst._zod.check = (payload2) => {
|
|
7833
|
+
const input = payload2.value;
|
|
7834
7834
|
const length = input.length;
|
|
7835
7835
|
if (length <= def.maximum)
|
|
7836
7836
|
return;
|
|
7837
7837
|
const origin = getLengthableOrigin(input);
|
|
7838
|
-
|
|
7838
|
+
payload2.issues.push({
|
|
7839
7839
|
origin,
|
|
7840
7840
|
code: "too_big",
|
|
7841
7841
|
maximum: def.maximum,
|
|
@@ -7849,8 +7849,8 @@ var $ZodCheckMaxLength = /* @__PURE__ */ $constructor("$ZodCheckMaxLength", (ins
|
|
|
7849
7849
|
var $ZodCheckMinLength = /* @__PURE__ */ $constructor("$ZodCheckMinLength", (inst, def) => {
|
|
7850
7850
|
var _a;
|
|
7851
7851
|
$ZodCheck.init(inst, def);
|
|
7852
|
-
(_a = inst._zod.def).when ?? (_a.when = (
|
|
7853
|
-
const val =
|
|
7852
|
+
(_a = inst._zod.def).when ?? (_a.when = (payload2) => {
|
|
7853
|
+
const val = payload2.value;
|
|
7854
7854
|
return !nullish(val) && val.length !== void 0;
|
|
7855
7855
|
});
|
|
7856
7856
|
inst._zod.onattach.push((inst2) => {
|
|
@@ -7858,13 +7858,13 @@ var $ZodCheckMinLength = /* @__PURE__ */ $constructor("$ZodCheckMinLength", (ins
|
|
|
7858
7858
|
if (def.minimum > curr)
|
|
7859
7859
|
inst2._zod.bag.minimum = def.minimum;
|
|
7860
7860
|
});
|
|
7861
|
-
inst._zod.check = (
|
|
7862
|
-
const input =
|
|
7861
|
+
inst._zod.check = (payload2) => {
|
|
7862
|
+
const input = payload2.value;
|
|
7863
7863
|
const length = input.length;
|
|
7864
7864
|
if (length >= def.minimum)
|
|
7865
7865
|
return;
|
|
7866
7866
|
const origin = getLengthableOrigin(input);
|
|
7867
|
-
|
|
7867
|
+
payload2.issues.push({
|
|
7868
7868
|
origin,
|
|
7869
7869
|
code: "too_small",
|
|
7870
7870
|
minimum: def.minimum,
|
|
@@ -7878,8 +7878,8 @@ var $ZodCheckMinLength = /* @__PURE__ */ $constructor("$ZodCheckMinLength", (ins
|
|
|
7878
7878
|
var $ZodCheckLengthEquals = /* @__PURE__ */ $constructor("$ZodCheckLengthEquals", (inst, def) => {
|
|
7879
7879
|
var _a;
|
|
7880
7880
|
$ZodCheck.init(inst, def);
|
|
7881
|
-
(_a = inst._zod.def).when ?? (_a.when = (
|
|
7882
|
-
const val =
|
|
7881
|
+
(_a = inst._zod.def).when ?? (_a.when = (payload2) => {
|
|
7882
|
+
const val = payload2.value;
|
|
7883
7883
|
return !nullish(val) && val.length !== void 0;
|
|
7884
7884
|
});
|
|
7885
7885
|
inst._zod.onattach.push((inst2) => {
|
|
@@ -7888,19 +7888,19 @@ var $ZodCheckLengthEquals = /* @__PURE__ */ $constructor("$ZodCheckLengthEquals"
|
|
|
7888
7888
|
bag.maximum = def.length;
|
|
7889
7889
|
bag.length = def.length;
|
|
7890
7890
|
});
|
|
7891
|
-
inst._zod.check = (
|
|
7892
|
-
const input =
|
|
7891
|
+
inst._zod.check = (payload2) => {
|
|
7892
|
+
const input = payload2.value;
|
|
7893
7893
|
const length = input.length;
|
|
7894
7894
|
if (length === def.length)
|
|
7895
7895
|
return;
|
|
7896
7896
|
const origin = getLengthableOrigin(input);
|
|
7897
7897
|
const tooBig = length > def.length;
|
|
7898
|
-
|
|
7898
|
+
payload2.issues.push({
|
|
7899
7899
|
origin,
|
|
7900
7900
|
...tooBig ? { code: "too_big", maximum: def.length } : { code: "too_small", minimum: def.length },
|
|
7901
7901
|
inclusive: true,
|
|
7902
7902
|
exact: true,
|
|
7903
|
-
input:
|
|
7903
|
+
input: payload2.value,
|
|
7904
7904
|
inst,
|
|
7905
7905
|
continue: !def.abort
|
|
7906
7906
|
});
|
|
@@ -7918,15 +7918,15 @@ var $ZodCheckStringFormat = /* @__PURE__ */ $constructor("$ZodCheckStringFormat"
|
|
|
7918
7918
|
}
|
|
7919
7919
|
});
|
|
7920
7920
|
if (def.pattern)
|
|
7921
|
-
(_a = inst._zod).check ?? (_a.check = (
|
|
7921
|
+
(_a = inst._zod).check ?? (_a.check = (payload2) => {
|
|
7922
7922
|
def.pattern.lastIndex = 0;
|
|
7923
|
-
if (def.pattern.test(
|
|
7923
|
+
if (def.pattern.test(payload2.value))
|
|
7924
7924
|
return;
|
|
7925
|
-
|
|
7925
|
+
payload2.issues.push({
|
|
7926
7926
|
origin: "string",
|
|
7927
7927
|
code: "invalid_format",
|
|
7928
7928
|
format: def.format,
|
|
7929
|
-
input:
|
|
7929
|
+
input: payload2.value,
|
|
7930
7930
|
...def.pattern ? { pattern: def.pattern.toString() } : {},
|
|
7931
7931
|
inst,
|
|
7932
7932
|
continue: !def.abort
|
|
@@ -7938,15 +7938,15 @@ var $ZodCheckStringFormat = /* @__PURE__ */ $constructor("$ZodCheckStringFormat"
|
|
|
7938
7938
|
});
|
|
7939
7939
|
var $ZodCheckRegex = /* @__PURE__ */ $constructor("$ZodCheckRegex", (inst, def) => {
|
|
7940
7940
|
$ZodCheckStringFormat.init(inst, def);
|
|
7941
|
-
inst._zod.check = (
|
|
7941
|
+
inst._zod.check = (payload2) => {
|
|
7942
7942
|
def.pattern.lastIndex = 0;
|
|
7943
|
-
if (def.pattern.test(
|
|
7943
|
+
if (def.pattern.test(payload2.value))
|
|
7944
7944
|
return;
|
|
7945
|
-
|
|
7945
|
+
payload2.issues.push({
|
|
7946
7946
|
origin: "string",
|
|
7947
7947
|
code: "invalid_format",
|
|
7948
7948
|
format: "regex",
|
|
7949
|
-
input:
|
|
7949
|
+
input: payload2.value,
|
|
7950
7950
|
pattern: def.pattern.toString(),
|
|
7951
7951
|
inst,
|
|
7952
7952
|
continue: !def.abort
|
|
@@ -7971,15 +7971,15 @@ var $ZodCheckIncludes = /* @__PURE__ */ $constructor("$ZodCheckIncludes", (inst,
|
|
|
7971
7971
|
bag.patterns ?? (bag.patterns = /* @__PURE__ */ new Set());
|
|
7972
7972
|
bag.patterns.add(pattern);
|
|
7973
7973
|
});
|
|
7974
|
-
inst._zod.check = (
|
|
7975
|
-
if (
|
|
7974
|
+
inst._zod.check = (payload2) => {
|
|
7975
|
+
if (payload2.value.includes(def.includes, def.position))
|
|
7976
7976
|
return;
|
|
7977
|
-
|
|
7977
|
+
payload2.issues.push({
|
|
7978
7978
|
origin: "string",
|
|
7979
7979
|
code: "invalid_format",
|
|
7980
7980
|
format: "includes",
|
|
7981
7981
|
includes: def.includes,
|
|
7982
|
-
input:
|
|
7982
|
+
input: payload2.value,
|
|
7983
7983
|
inst,
|
|
7984
7984
|
continue: !def.abort
|
|
7985
7985
|
});
|
|
@@ -7994,15 +7994,15 @@ var $ZodCheckStartsWith = /* @__PURE__ */ $constructor("$ZodCheckStartsWith", (i
|
|
|
7994
7994
|
bag.patterns ?? (bag.patterns = /* @__PURE__ */ new Set());
|
|
7995
7995
|
bag.patterns.add(pattern);
|
|
7996
7996
|
});
|
|
7997
|
-
inst._zod.check = (
|
|
7998
|
-
if (
|
|
7997
|
+
inst._zod.check = (payload2) => {
|
|
7998
|
+
if (payload2.value.startsWith(def.prefix))
|
|
7999
7999
|
return;
|
|
8000
|
-
|
|
8000
|
+
payload2.issues.push({
|
|
8001
8001
|
origin: "string",
|
|
8002
8002
|
code: "invalid_format",
|
|
8003
8003
|
format: "starts_with",
|
|
8004
8004
|
prefix: def.prefix,
|
|
8005
|
-
input:
|
|
8005
|
+
input: payload2.value,
|
|
8006
8006
|
inst,
|
|
8007
8007
|
continue: !def.abort
|
|
8008
8008
|
});
|
|
@@ -8017,15 +8017,15 @@ var $ZodCheckEndsWith = /* @__PURE__ */ $constructor("$ZodCheckEndsWith", (inst,
|
|
|
8017
8017
|
bag.patterns ?? (bag.patterns = /* @__PURE__ */ new Set());
|
|
8018
8018
|
bag.patterns.add(pattern);
|
|
8019
8019
|
});
|
|
8020
|
-
inst._zod.check = (
|
|
8021
|
-
if (
|
|
8020
|
+
inst._zod.check = (payload2) => {
|
|
8021
|
+
if (payload2.value.endsWith(def.suffix))
|
|
8022
8022
|
return;
|
|
8023
|
-
|
|
8023
|
+
payload2.issues.push({
|
|
8024
8024
|
origin: "string",
|
|
8025
8025
|
code: "invalid_format",
|
|
8026
8026
|
format: "ends_with",
|
|
8027
8027
|
suffix: def.suffix,
|
|
8028
|
-
input:
|
|
8028
|
+
input: payload2.value,
|
|
8029
8029
|
inst,
|
|
8030
8030
|
continue: !def.abort
|
|
8031
8031
|
});
|
|
@@ -8033,8 +8033,8 @@ var $ZodCheckEndsWith = /* @__PURE__ */ $constructor("$ZodCheckEndsWith", (inst,
|
|
|
8033
8033
|
});
|
|
8034
8034
|
var $ZodCheckOverwrite = /* @__PURE__ */ $constructor("$ZodCheckOverwrite", (inst, def) => {
|
|
8035
8035
|
$ZodCheck.init(inst, def);
|
|
8036
|
-
inst._zod.check = (
|
|
8037
|
-
|
|
8036
|
+
inst._zod.check = (payload2) => {
|
|
8037
|
+
payload2.value = def.tx(payload2.value);
|
|
8038
8038
|
};
|
|
8039
8039
|
});
|
|
8040
8040
|
|
|
@@ -8103,48 +8103,48 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
|
8103
8103
|
inst._zod.run = inst._zod.parse;
|
|
8104
8104
|
});
|
|
8105
8105
|
} else {
|
|
8106
|
-
const runChecks = (
|
|
8107
|
-
let isAborted2 = aborted(
|
|
8106
|
+
const runChecks = (payload2, checks2, ctx) => {
|
|
8107
|
+
let isAborted2 = aborted(payload2);
|
|
8108
8108
|
let asyncResult;
|
|
8109
8109
|
for (const ch of checks2) {
|
|
8110
8110
|
if (ch._zod.def.when) {
|
|
8111
|
-
const shouldRun = ch._zod.def.when(
|
|
8111
|
+
const shouldRun = ch._zod.def.when(payload2);
|
|
8112
8112
|
if (!shouldRun)
|
|
8113
8113
|
continue;
|
|
8114
8114
|
} else if (isAborted2) {
|
|
8115
8115
|
continue;
|
|
8116
8116
|
}
|
|
8117
|
-
const currLen =
|
|
8118
|
-
const _ = ch._zod.check(
|
|
8117
|
+
const currLen = payload2.issues.length;
|
|
8118
|
+
const _ = ch._zod.check(payload2);
|
|
8119
8119
|
if (_ instanceof Promise && ctx?.async === false) {
|
|
8120
8120
|
throw new $ZodAsyncError();
|
|
8121
8121
|
}
|
|
8122
8122
|
if (asyncResult || _ instanceof Promise) {
|
|
8123
8123
|
asyncResult = (asyncResult ?? Promise.resolve()).then(async () => {
|
|
8124
8124
|
await _;
|
|
8125
|
-
const nextLen =
|
|
8125
|
+
const nextLen = payload2.issues.length;
|
|
8126
8126
|
if (nextLen === currLen)
|
|
8127
8127
|
return;
|
|
8128
8128
|
if (!isAborted2)
|
|
8129
|
-
isAborted2 = aborted(
|
|
8129
|
+
isAborted2 = aborted(payload2, currLen);
|
|
8130
8130
|
});
|
|
8131
8131
|
} else {
|
|
8132
|
-
const nextLen =
|
|
8132
|
+
const nextLen = payload2.issues.length;
|
|
8133
8133
|
if (nextLen === currLen)
|
|
8134
8134
|
continue;
|
|
8135
8135
|
if (!isAborted2)
|
|
8136
|
-
isAborted2 = aborted(
|
|
8136
|
+
isAborted2 = aborted(payload2, currLen);
|
|
8137
8137
|
}
|
|
8138
8138
|
}
|
|
8139
8139
|
if (asyncResult) {
|
|
8140
8140
|
return asyncResult.then(() => {
|
|
8141
|
-
return
|
|
8141
|
+
return payload2;
|
|
8142
8142
|
});
|
|
8143
8143
|
}
|
|
8144
|
-
return
|
|
8144
|
+
return payload2;
|
|
8145
8145
|
};
|
|
8146
|
-
inst._zod.run = (
|
|
8147
|
-
const result = inst._zod.parse(
|
|
8146
|
+
inst._zod.run = (payload2, ctx) => {
|
|
8147
|
+
const result = inst._zod.parse(payload2, ctx);
|
|
8148
8148
|
if (result instanceof Promise) {
|
|
8149
8149
|
if (ctx.async === false)
|
|
8150
8150
|
throw new $ZodAsyncError();
|
|
@@ -8169,21 +8169,21 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
|
8169
8169
|
var $ZodString = /* @__PURE__ */ $constructor("$ZodString", (inst, def) => {
|
|
8170
8170
|
$ZodType.init(inst, def);
|
|
8171
8171
|
inst._zod.pattern = [...inst?._zod.bag?.patterns ?? []].pop() ?? string(inst._zod.bag);
|
|
8172
|
-
inst._zod.parse = (
|
|
8172
|
+
inst._zod.parse = (payload2, _) => {
|
|
8173
8173
|
if (def.coerce)
|
|
8174
8174
|
try {
|
|
8175
|
-
|
|
8175
|
+
payload2.value = String(payload2.value);
|
|
8176
8176
|
} catch (_2) {
|
|
8177
8177
|
}
|
|
8178
|
-
if (typeof
|
|
8179
|
-
return
|
|
8180
|
-
|
|
8178
|
+
if (typeof payload2.value === "string")
|
|
8179
|
+
return payload2;
|
|
8180
|
+
payload2.issues.push({
|
|
8181
8181
|
expected: "string",
|
|
8182
8182
|
code: "invalid_type",
|
|
8183
|
-
input:
|
|
8183
|
+
input: payload2.value,
|
|
8184
8184
|
inst
|
|
8185
8185
|
});
|
|
8186
|
-
return
|
|
8186
|
+
return payload2;
|
|
8187
8187
|
};
|
|
8188
8188
|
});
|
|
8189
8189
|
var $ZodStringFormat = /* @__PURE__ */ $constructor("$ZodStringFormat", (inst, def) => {
|
|
@@ -8220,20 +8220,20 @@ var $ZodEmail = /* @__PURE__ */ $constructor("$ZodEmail", (inst, def) => {
|
|
|
8220
8220
|
});
|
|
8221
8221
|
var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
|
|
8222
8222
|
$ZodStringFormat.init(inst, def);
|
|
8223
|
-
inst._zod.check = (
|
|
8223
|
+
inst._zod.check = (payload2) => {
|
|
8224
8224
|
try {
|
|
8225
|
-
const orig =
|
|
8225
|
+
const orig = payload2.value;
|
|
8226
8226
|
const url = new URL(orig);
|
|
8227
8227
|
const href = url.href;
|
|
8228
8228
|
if (def.hostname) {
|
|
8229
8229
|
def.hostname.lastIndex = 0;
|
|
8230
8230
|
if (!def.hostname.test(url.hostname)) {
|
|
8231
|
-
|
|
8231
|
+
payload2.issues.push({
|
|
8232
8232
|
code: "invalid_format",
|
|
8233
8233
|
format: "url",
|
|
8234
8234
|
note: "Invalid hostname",
|
|
8235
8235
|
pattern: hostname.source,
|
|
8236
|
-
input:
|
|
8236
|
+
input: payload2.value,
|
|
8237
8237
|
inst,
|
|
8238
8238
|
continue: !def.abort
|
|
8239
8239
|
});
|
|
@@ -8242,28 +8242,28 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
|
|
|
8242
8242
|
if (def.protocol) {
|
|
8243
8243
|
def.protocol.lastIndex = 0;
|
|
8244
8244
|
if (!def.protocol.test(url.protocol.endsWith(":") ? url.protocol.slice(0, -1) : url.protocol)) {
|
|
8245
|
-
|
|
8245
|
+
payload2.issues.push({
|
|
8246
8246
|
code: "invalid_format",
|
|
8247
8247
|
format: "url",
|
|
8248
8248
|
note: "Invalid protocol",
|
|
8249
8249
|
pattern: def.protocol.source,
|
|
8250
|
-
input:
|
|
8250
|
+
input: payload2.value,
|
|
8251
8251
|
inst,
|
|
8252
8252
|
continue: !def.abort
|
|
8253
8253
|
});
|
|
8254
8254
|
}
|
|
8255
8255
|
}
|
|
8256
8256
|
if (!orig.endsWith("/") && href.endsWith("/")) {
|
|
8257
|
-
|
|
8257
|
+
payload2.value = href.slice(0, -1);
|
|
8258
8258
|
} else {
|
|
8259
|
-
|
|
8259
|
+
payload2.value = href;
|
|
8260
8260
|
}
|
|
8261
8261
|
return;
|
|
8262
8262
|
} catch (_) {
|
|
8263
|
-
|
|
8263
|
+
payload2.issues.push({
|
|
8264
8264
|
code: "invalid_format",
|
|
8265
8265
|
format: "url",
|
|
8266
|
-
input:
|
|
8266
|
+
input: payload2.value,
|
|
8267
8267
|
inst,
|
|
8268
8268
|
continue: !def.abort
|
|
8269
8269
|
});
|
|
@@ -8329,14 +8329,14 @@ var $ZodIPv6 = /* @__PURE__ */ $constructor("$ZodIPv6", (inst, def) => {
|
|
|
8329
8329
|
const bag = inst2._zod.bag;
|
|
8330
8330
|
bag.format = `ipv6`;
|
|
8331
8331
|
});
|
|
8332
|
-
inst._zod.check = (
|
|
8332
|
+
inst._zod.check = (payload2) => {
|
|
8333
8333
|
try {
|
|
8334
|
-
new URL(`http://[${
|
|
8334
|
+
new URL(`http://[${payload2.value}]`);
|
|
8335
8335
|
} catch {
|
|
8336
|
-
|
|
8336
|
+
payload2.issues.push({
|
|
8337
8337
|
code: "invalid_format",
|
|
8338
8338
|
format: "ipv6",
|
|
8339
|
-
input:
|
|
8339
|
+
input: payload2.value,
|
|
8340
8340
|
inst,
|
|
8341
8341
|
continue: !def.abort
|
|
8342
8342
|
});
|
|
@@ -8350,8 +8350,8 @@ var $ZodCIDRv4 = /* @__PURE__ */ $constructor("$ZodCIDRv4", (inst, def) => {
|
|
|
8350
8350
|
var $ZodCIDRv6 = /* @__PURE__ */ $constructor("$ZodCIDRv6", (inst, def) => {
|
|
8351
8351
|
def.pattern ?? (def.pattern = cidrv6);
|
|
8352
8352
|
$ZodStringFormat.init(inst, def);
|
|
8353
|
-
inst._zod.check = (
|
|
8354
|
-
const [address, prefix] =
|
|
8353
|
+
inst._zod.check = (payload2) => {
|
|
8354
|
+
const [address, prefix] = payload2.value.split("/");
|
|
8355
8355
|
try {
|
|
8356
8356
|
if (!prefix)
|
|
8357
8357
|
throw new Error();
|
|
@@ -8362,10 +8362,10 @@ var $ZodCIDRv6 = /* @__PURE__ */ $constructor("$ZodCIDRv6", (inst, def) => {
|
|
|
8362
8362
|
throw new Error();
|
|
8363
8363
|
new URL(`http://[${address}]`);
|
|
8364
8364
|
} catch {
|
|
8365
|
-
|
|
8365
|
+
payload2.issues.push({
|
|
8366
8366
|
code: "invalid_format",
|
|
8367
8367
|
format: "cidrv6",
|
|
8368
|
-
input:
|
|
8368
|
+
input: payload2.value,
|
|
8369
8369
|
inst,
|
|
8370
8370
|
continue: !def.abort
|
|
8371
8371
|
});
|
|
@@ -8390,13 +8390,13 @@ var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
|
|
|
8390
8390
|
inst._zod.onattach.push((inst2) => {
|
|
8391
8391
|
inst2._zod.bag.contentEncoding = "base64";
|
|
8392
8392
|
});
|
|
8393
|
-
inst._zod.check = (
|
|
8394
|
-
if (isValidBase64(
|
|
8393
|
+
inst._zod.check = (payload2) => {
|
|
8394
|
+
if (isValidBase64(payload2.value))
|
|
8395
8395
|
return;
|
|
8396
|
-
|
|
8396
|
+
payload2.issues.push({
|
|
8397
8397
|
code: "invalid_format",
|
|
8398
8398
|
format: "base64",
|
|
8399
|
-
input:
|
|
8399
|
+
input: payload2.value,
|
|
8400
8400
|
inst,
|
|
8401
8401
|
continue: !def.abort
|
|
8402
8402
|
});
|
|
@@ -8415,13 +8415,13 @@ var $ZodBase64URL = /* @__PURE__ */ $constructor("$ZodBase64URL", (inst, def) =>
|
|
|
8415
8415
|
inst._zod.onattach.push((inst2) => {
|
|
8416
8416
|
inst2._zod.bag.contentEncoding = "base64url";
|
|
8417
8417
|
});
|
|
8418
|
-
inst._zod.check = (
|
|
8419
|
-
if (isValidBase64URL(
|
|
8418
|
+
inst._zod.check = (payload2) => {
|
|
8419
|
+
if (isValidBase64URL(payload2.value))
|
|
8420
8420
|
return;
|
|
8421
|
-
|
|
8421
|
+
payload2.issues.push({
|
|
8422
8422
|
code: "invalid_format",
|
|
8423
8423
|
format: "base64url",
|
|
8424
|
-
input:
|
|
8424
|
+
input: payload2.value,
|
|
8425
8425
|
inst,
|
|
8426
8426
|
continue: !def.abort
|
|
8427
8427
|
});
|
|
@@ -8453,13 +8453,13 @@ function isValidJWT(token, algorithm = null) {
|
|
|
8453
8453
|
}
|
|
8454
8454
|
var $ZodJWT = /* @__PURE__ */ $constructor("$ZodJWT", (inst, def) => {
|
|
8455
8455
|
$ZodStringFormat.init(inst, def);
|
|
8456
|
-
inst._zod.check = (
|
|
8457
|
-
if (isValidJWT(
|
|
8456
|
+
inst._zod.check = (payload2) => {
|
|
8457
|
+
if (isValidJWT(payload2.value, def.alg))
|
|
8458
8458
|
return;
|
|
8459
|
-
|
|
8459
|
+
payload2.issues.push({
|
|
8460
8460
|
code: "invalid_format",
|
|
8461
8461
|
format: "jwt",
|
|
8462
|
-
input:
|
|
8462
|
+
input: payload2.value,
|
|
8463
8463
|
inst,
|
|
8464
8464
|
continue: !def.abort
|
|
8465
8465
|
});
|
|
@@ -8468,25 +8468,25 @@ var $ZodJWT = /* @__PURE__ */ $constructor("$ZodJWT", (inst, def) => {
|
|
|
8468
8468
|
var $ZodNumber = /* @__PURE__ */ $constructor("$ZodNumber", (inst, def) => {
|
|
8469
8469
|
$ZodType.init(inst, def);
|
|
8470
8470
|
inst._zod.pattern = inst._zod.bag.pattern ?? number;
|
|
8471
|
-
inst._zod.parse = (
|
|
8471
|
+
inst._zod.parse = (payload2, _ctx) => {
|
|
8472
8472
|
if (def.coerce)
|
|
8473
8473
|
try {
|
|
8474
|
-
|
|
8474
|
+
payload2.value = Number(payload2.value);
|
|
8475
8475
|
} catch (_) {
|
|
8476
8476
|
}
|
|
8477
|
-
const input =
|
|
8477
|
+
const input = payload2.value;
|
|
8478
8478
|
if (typeof input === "number" && !Number.isNaN(input) && Number.isFinite(input)) {
|
|
8479
|
-
return
|
|
8479
|
+
return payload2;
|
|
8480
8480
|
}
|
|
8481
8481
|
const received = typeof input === "number" ? Number.isNaN(input) ? "NaN" : !Number.isFinite(input) ? "Infinity" : void 0 : void 0;
|
|
8482
|
-
|
|
8482
|
+
payload2.issues.push({
|
|
8483
8483
|
expected: "number",
|
|
8484
8484
|
code: "invalid_type",
|
|
8485
8485
|
input,
|
|
8486
8486
|
inst,
|
|
8487
8487
|
...received ? { received } : {}
|
|
8488
8488
|
});
|
|
8489
|
-
return
|
|
8489
|
+
return payload2;
|
|
8490
8490
|
};
|
|
8491
8491
|
});
|
|
8492
8492
|
var $ZodNumberFormat = /* @__PURE__ */ $constructor("$ZodNumber", (inst, def) => {
|
|
@@ -8496,55 +8496,55 @@ var $ZodNumberFormat = /* @__PURE__ */ $constructor("$ZodNumber", (inst, def) =>
|
|
|
8496
8496
|
var $ZodBoolean = /* @__PURE__ */ $constructor("$ZodBoolean", (inst, def) => {
|
|
8497
8497
|
$ZodType.init(inst, def);
|
|
8498
8498
|
inst._zod.pattern = boolean;
|
|
8499
|
-
inst._zod.parse = (
|
|
8499
|
+
inst._zod.parse = (payload2, _ctx) => {
|
|
8500
8500
|
if (def.coerce)
|
|
8501
8501
|
try {
|
|
8502
|
-
|
|
8502
|
+
payload2.value = Boolean(payload2.value);
|
|
8503
8503
|
} catch (_) {
|
|
8504
8504
|
}
|
|
8505
|
-
const input =
|
|
8505
|
+
const input = payload2.value;
|
|
8506
8506
|
if (typeof input === "boolean")
|
|
8507
|
-
return
|
|
8508
|
-
|
|
8507
|
+
return payload2;
|
|
8508
|
+
payload2.issues.push({
|
|
8509
8509
|
expected: "boolean",
|
|
8510
8510
|
code: "invalid_type",
|
|
8511
8511
|
input,
|
|
8512
8512
|
inst
|
|
8513
8513
|
});
|
|
8514
|
-
return
|
|
8514
|
+
return payload2;
|
|
8515
8515
|
};
|
|
8516
8516
|
});
|
|
8517
8517
|
var $ZodNull = /* @__PURE__ */ $constructor("$ZodNull", (inst, def) => {
|
|
8518
8518
|
$ZodType.init(inst, def);
|
|
8519
8519
|
inst._zod.pattern = _null;
|
|
8520
8520
|
inst._zod.values = /* @__PURE__ */ new Set([null]);
|
|
8521
|
-
inst._zod.parse = (
|
|
8522
|
-
const input =
|
|
8521
|
+
inst._zod.parse = (payload2, _ctx) => {
|
|
8522
|
+
const input = payload2.value;
|
|
8523
8523
|
if (input === null)
|
|
8524
|
-
return
|
|
8525
|
-
|
|
8524
|
+
return payload2;
|
|
8525
|
+
payload2.issues.push({
|
|
8526
8526
|
expected: "null",
|
|
8527
8527
|
code: "invalid_type",
|
|
8528
8528
|
input,
|
|
8529
8529
|
inst
|
|
8530
8530
|
});
|
|
8531
|
-
return
|
|
8531
|
+
return payload2;
|
|
8532
8532
|
};
|
|
8533
8533
|
});
|
|
8534
8534
|
var $ZodUnknown = /* @__PURE__ */ $constructor("$ZodUnknown", (inst, def) => {
|
|
8535
8535
|
$ZodType.init(inst, def);
|
|
8536
|
-
inst._zod.parse = (
|
|
8536
|
+
inst._zod.parse = (payload2) => payload2;
|
|
8537
8537
|
});
|
|
8538
8538
|
var $ZodNever = /* @__PURE__ */ $constructor("$ZodNever", (inst, def) => {
|
|
8539
8539
|
$ZodType.init(inst, def);
|
|
8540
|
-
inst._zod.parse = (
|
|
8541
|
-
|
|
8540
|
+
inst._zod.parse = (payload2, _ctx) => {
|
|
8541
|
+
payload2.issues.push({
|
|
8542
8542
|
expected: "never",
|
|
8543
8543
|
code: "invalid_type",
|
|
8544
|
-
input:
|
|
8544
|
+
input: payload2.value,
|
|
8545
8545
|
inst
|
|
8546
8546
|
});
|
|
8547
|
-
return
|
|
8547
|
+
return payload2;
|
|
8548
8548
|
};
|
|
8549
8549
|
});
|
|
8550
8550
|
function handleArrayResult(result, final, index) {
|
|
@@ -8555,18 +8555,18 @@ function handleArrayResult(result, final, index) {
|
|
|
8555
8555
|
}
|
|
8556
8556
|
var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
|
|
8557
8557
|
$ZodType.init(inst, def);
|
|
8558
|
-
inst._zod.parse = (
|
|
8559
|
-
const input =
|
|
8558
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
8559
|
+
const input = payload2.value;
|
|
8560
8560
|
if (!Array.isArray(input)) {
|
|
8561
|
-
|
|
8561
|
+
payload2.issues.push({
|
|
8562
8562
|
expected: "array",
|
|
8563
8563
|
code: "invalid_type",
|
|
8564
8564
|
input,
|
|
8565
8565
|
inst
|
|
8566
8566
|
});
|
|
8567
|
-
return
|
|
8567
|
+
return payload2;
|
|
8568
8568
|
}
|
|
8569
|
-
|
|
8569
|
+
payload2.value = Array(input.length);
|
|
8570
8570
|
const proms = [];
|
|
8571
8571
|
for (let i = 0; i < input.length; i++) {
|
|
8572
8572
|
const item = input[i];
|
|
@@ -8575,15 +8575,15 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
|
|
|
8575
8575
|
issues: []
|
|
8576
8576
|
}, ctx);
|
|
8577
8577
|
if (result instanceof Promise) {
|
|
8578
|
-
proms.push(result.then((result2) => handleArrayResult(result2,
|
|
8578
|
+
proms.push(result.then((result2) => handleArrayResult(result2, payload2, i)));
|
|
8579
8579
|
} else {
|
|
8580
|
-
handleArrayResult(result,
|
|
8580
|
+
handleArrayResult(result, payload2, i);
|
|
8581
8581
|
}
|
|
8582
8582
|
}
|
|
8583
8583
|
if (proms.length) {
|
|
8584
|
-
return Promise.all(proms).then(() =>
|
|
8584
|
+
return Promise.all(proms).then(() => payload2);
|
|
8585
8585
|
}
|
|
8586
|
-
return
|
|
8586
|
+
return payload2;
|
|
8587
8587
|
};
|
|
8588
8588
|
});
|
|
8589
8589
|
function handleObjectResult(result, final, key) {
|
|
@@ -8694,7 +8694,7 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
8694
8694
|
doc.write(`payload.value = newResult;`);
|
|
8695
8695
|
doc.write(`return payload;`);
|
|
8696
8696
|
const fn = doc.compile();
|
|
8697
|
-
return (
|
|
8697
|
+
return (payload2, ctx) => fn(shape, payload2, ctx);
|
|
8698
8698
|
};
|
|
8699
8699
|
let fastpass;
|
|
8700
8700
|
const isObject2 = isObject;
|
|
@@ -8703,41 +8703,41 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
8703
8703
|
const fastEnabled = jit && allowsEval2.value;
|
|
8704
8704
|
const catchall = def.catchall;
|
|
8705
8705
|
let value;
|
|
8706
|
-
inst._zod.parse = (
|
|
8706
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
8707
8707
|
value ?? (value = _normalized.value);
|
|
8708
|
-
const input =
|
|
8708
|
+
const input = payload2.value;
|
|
8709
8709
|
if (!isObject2(input)) {
|
|
8710
|
-
|
|
8710
|
+
payload2.issues.push({
|
|
8711
8711
|
expected: "object",
|
|
8712
8712
|
code: "invalid_type",
|
|
8713
8713
|
input,
|
|
8714
8714
|
inst
|
|
8715
8715
|
});
|
|
8716
|
-
return
|
|
8716
|
+
return payload2;
|
|
8717
8717
|
}
|
|
8718
8718
|
const proms = [];
|
|
8719
8719
|
if (jit && fastEnabled && ctx?.async === false && ctx.jitless !== true) {
|
|
8720
8720
|
if (!fastpass)
|
|
8721
8721
|
fastpass = generateFastpass(def.shape);
|
|
8722
|
-
|
|
8722
|
+
payload2 = fastpass(payload2, ctx);
|
|
8723
8723
|
} else {
|
|
8724
|
-
|
|
8724
|
+
payload2.value = {};
|
|
8725
8725
|
const shape = value.shape;
|
|
8726
8726
|
for (const key of value.keys) {
|
|
8727
8727
|
const el = shape[key];
|
|
8728
8728
|
const r = el._zod.run({ value: input[key], issues: [] }, ctx);
|
|
8729
8729
|
const isOptional = el._zod.optin === "optional" && el._zod.optout === "optional";
|
|
8730
8730
|
if (r instanceof Promise) {
|
|
8731
|
-
proms.push(r.then((r2) => isOptional ? handleOptionalObjectResult(r2,
|
|
8731
|
+
proms.push(r.then((r2) => isOptional ? handleOptionalObjectResult(r2, payload2, key, input) : handleObjectResult(r2, payload2, key)));
|
|
8732
8732
|
} else if (isOptional) {
|
|
8733
|
-
handleOptionalObjectResult(r,
|
|
8733
|
+
handleOptionalObjectResult(r, payload2, key, input);
|
|
8734
8734
|
} else {
|
|
8735
|
-
handleObjectResult(r,
|
|
8735
|
+
handleObjectResult(r, payload2, key);
|
|
8736
8736
|
}
|
|
8737
8737
|
}
|
|
8738
8738
|
}
|
|
8739
8739
|
if (!catchall) {
|
|
8740
|
-
return proms.length ? Promise.all(proms).then(() =>
|
|
8740
|
+
return proms.length ? Promise.all(proms).then(() => payload2) : payload2;
|
|
8741
8741
|
}
|
|
8742
8742
|
const unrecognized = [];
|
|
8743
8743
|
const keySet = value.keySet;
|
|
@@ -8752,13 +8752,13 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
8752
8752
|
}
|
|
8753
8753
|
const r = _catchall.run({ value: input[key], issues: [] }, ctx);
|
|
8754
8754
|
if (r instanceof Promise) {
|
|
8755
|
-
proms.push(r.then((r2) => handleObjectResult(r2,
|
|
8755
|
+
proms.push(r.then((r2) => handleObjectResult(r2, payload2, key)));
|
|
8756
8756
|
} else {
|
|
8757
|
-
handleObjectResult(r,
|
|
8757
|
+
handleObjectResult(r, payload2, key);
|
|
8758
8758
|
}
|
|
8759
8759
|
}
|
|
8760
8760
|
if (unrecognized.length) {
|
|
8761
|
-
|
|
8761
|
+
payload2.issues.push({
|
|
8762
8762
|
code: "unrecognized_keys",
|
|
8763
8763
|
keys: unrecognized,
|
|
8764
8764
|
input,
|
|
@@ -8766,9 +8766,9 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
8766
8766
|
});
|
|
8767
8767
|
}
|
|
8768
8768
|
if (!proms.length)
|
|
8769
|
-
return
|
|
8769
|
+
return payload2;
|
|
8770
8770
|
return Promise.all(proms).then(() => {
|
|
8771
|
-
return
|
|
8771
|
+
return payload2;
|
|
8772
8772
|
});
|
|
8773
8773
|
};
|
|
8774
8774
|
});
|
|
@@ -8804,12 +8804,12 @@ var $ZodUnion = /* @__PURE__ */ $constructor("$ZodUnion", (inst, def) => {
|
|
|
8804
8804
|
}
|
|
8805
8805
|
return void 0;
|
|
8806
8806
|
});
|
|
8807
|
-
inst._zod.parse = (
|
|
8807
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
8808
8808
|
let async = false;
|
|
8809
8809
|
const results = [];
|
|
8810
8810
|
for (const option of def.options) {
|
|
8811
8811
|
const result = option._zod.run({
|
|
8812
|
-
value:
|
|
8812
|
+
value: payload2.value,
|
|
8813
8813
|
issues: []
|
|
8814
8814
|
}, ctx);
|
|
8815
8815
|
if (result instanceof Promise) {
|
|
@@ -8822,9 +8822,9 @@ var $ZodUnion = /* @__PURE__ */ $constructor("$ZodUnion", (inst, def) => {
|
|
|
8822
8822
|
}
|
|
8823
8823
|
}
|
|
8824
8824
|
if (!async)
|
|
8825
|
-
return handleUnionResults(results,
|
|
8825
|
+
return handleUnionResults(results, payload2, inst, ctx);
|
|
8826
8826
|
return Promise.all(results).then((results2) => {
|
|
8827
|
-
return handleUnionResults(results2,
|
|
8827
|
+
return handleUnionResults(results2, payload2, inst, ctx);
|
|
8828
8828
|
});
|
|
8829
8829
|
};
|
|
8830
8830
|
});
|
|
@@ -8863,25 +8863,25 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
|
|
|
8863
8863
|
}
|
|
8864
8864
|
return map;
|
|
8865
8865
|
});
|
|
8866
|
-
inst._zod.parse = (
|
|
8867
|
-
const input =
|
|
8866
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
8867
|
+
const input = payload2.value;
|
|
8868
8868
|
if (!isObject(input)) {
|
|
8869
|
-
|
|
8869
|
+
payload2.issues.push({
|
|
8870
8870
|
code: "invalid_type",
|
|
8871
8871
|
expected: "object",
|
|
8872
8872
|
input,
|
|
8873
8873
|
inst
|
|
8874
8874
|
});
|
|
8875
|
-
return
|
|
8875
|
+
return payload2;
|
|
8876
8876
|
}
|
|
8877
8877
|
const opt = disc.value.get(input?.[def.discriminator]);
|
|
8878
8878
|
if (opt) {
|
|
8879
|
-
return opt._zod.run(
|
|
8879
|
+
return opt._zod.run(payload2, ctx);
|
|
8880
8880
|
}
|
|
8881
8881
|
if (def.unionFallback) {
|
|
8882
|
-
return _super(
|
|
8882
|
+
return _super(payload2, ctx);
|
|
8883
8883
|
}
|
|
8884
|
-
|
|
8884
|
+
payload2.issues.push({
|
|
8885
8885
|
code: "invalid_union",
|
|
8886
8886
|
errors: [],
|
|
8887
8887
|
note: "No matching discriminator",
|
|
@@ -8889,22 +8889,22 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
|
|
|
8889
8889
|
path: [def.discriminator],
|
|
8890
8890
|
inst
|
|
8891
8891
|
});
|
|
8892
|
-
return
|
|
8892
|
+
return payload2;
|
|
8893
8893
|
};
|
|
8894
8894
|
});
|
|
8895
8895
|
var $ZodIntersection = /* @__PURE__ */ $constructor("$ZodIntersection", (inst, def) => {
|
|
8896
8896
|
$ZodType.init(inst, def);
|
|
8897
|
-
inst._zod.parse = (
|
|
8898
|
-
const input =
|
|
8897
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
8898
|
+
const input = payload2.value;
|
|
8899
8899
|
const left = def.left._zod.run({ value: input, issues: [] }, ctx);
|
|
8900
8900
|
const right = def.right._zod.run({ value: input, issues: [] }, ctx);
|
|
8901
8901
|
const async = left instanceof Promise || right instanceof Promise;
|
|
8902
8902
|
if (async) {
|
|
8903
8903
|
return Promise.all([left, right]).then(([left2, right2]) => {
|
|
8904
|
-
return handleIntersectionResults(
|
|
8904
|
+
return handleIntersectionResults(payload2, left2, right2);
|
|
8905
8905
|
});
|
|
8906
8906
|
}
|
|
8907
|
-
return handleIntersectionResults(
|
|
8907
|
+
return handleIntersectionResults(payload2, left, right);
|
|
8908
8908
|
};
|
|
8909
8909
|
});
|
|
8910
8910
|
function mergeValues(a, b) {
|
|
@@ -8969,36 +8969,36 @@ function handleIntersectionResults(result, left, right) {
|
|
|
8969
8969
|
}
|
|
8970
8970
|
var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
8971
8971
|
$ZodType.init(inst, def);
|
|
8972
|
-
inst._zod.parse = (
|
|
8973
|
-
const input =
|
|
8972
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
8973
|
+
const input = payload2.value;
|
|
8974
8974
|
if (!isPlainObject(input)) {
|
|
8975
|
-
|
|
8975
|
+
payload2.issues.push({
|
|
8976
8976
|
expected: "record",
|
|
8977
8977
|
code: "invalid_type",
|
|
8978
8978
|
input,
|
|
8979
8979
|
inst
|
|
8980
8980
|
});
|
|
8981
|
-
return
|
|
8981
|
+
return payload2;
|
|
8982
8982
|
}
|
|
8983
8983
|
const proms = [];
|
|
8984
8984
|
if (def.keyType._zod.values) {
|
|
8985
8985
|
const values = def.keyType._zod.values;
|
|
8986
|
-
|
|
8986
|
+
payload2.value = {};
|
|
8987
8987
|
for (const key of values) {
|
|
8988
8988
|
if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
|
|
8989
8989
|
const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
|
|
8990
8990
|
if (result instanceof Promise) {
|
|
8991
8991
|
proms.push(result.then((result2) => {
|
|
8992
8992
|
if (result2.issues.length) {
|
|
8993
|
-
|
|
8993
|
+
payload2.issues.push(...prefixIssues(key, result2.issues));
|
|
8994
8994
|
}
|
|
8995
|
-
|
|
8995
|
+
payload2.value[key] = result2.value;
|
|
8996
8996
|
}));
|
|
8997
8997
|
} else {
|
|
8998
8998
|
if (result.issues.length) {
|
|
8999
|
-
|
|
8999
|
+
payload2.issues.push(...prefixIssues(key, result.issues));
|
|
9000
9000
|
}
|
|
9001
|
-
|
|
9001
|
+
payload2.value[key] = result.value;
|
|
9002
9002
|
}
|
|
9003
9003
|
}
|
|
9004
9004
|
}
|
|
@@ -9010,7 +9010,7 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
9010
9010
|
}
|
|
9011
9011
|
}
|
|
9012
9012
|
if (unrecognized && unrecognized.length > 0) {
|
|
9013
|
-
|
|
9013
|
+
payload2.issues.push({
|
|
9014
9014
|
code: "unrecognized_keys",
|
|
9015
9015
|
input,
|
|
9016
9016
|
inst,
|
|
@@ -9018,7 +9018,7 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
9018
9018
|
});
|
|
9019
9019
|
}
|
|
9020
9020
|
} else {
|
|
9021
|
-
|
|
9021
|
+
payload2.value = {};
|
|
9022
9022
|
for (const key of Reflect.ownKeys(input)) {
|
|
9023
9023
|
if (key === "__proto__")
|
|
9024
9024
|
continue;
|
|
@@ -9027,7 +9027,7 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
9027
9027
|
throw new Error("Async schemas not supported in object keys currently");
|
|
9028
9028
|
}
|
|
9029
9029
|
if (keyResult.issues.length) {
|
|
9030
|
-
|
|
9030
|
+
payload2.issues.push({
|
|
9031
9031
|
origin: "record",
|
|
9032
9032
|
code: "invalid_key",
|
|
9033
9033
|
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
@@ -9035,29 +9035,29 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
9035
9035
|
path: [key],
|
|
9036
9036
|
inst
|
|
9037
9037
|
});
|
|
9038
|
-
|
|
9038
|
+
payload2.value[keyResult.value] = keyResult.value;
|
|
9039
9039
|
continue;
|
|
9040
9040
|
}
|
|
9041
9041
|
const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
|
|
9042
9042
|
if (result instanceof Promise) {
|
|
9043
9043
|
proms.push(result.then((result2) => {
|
|
9044
9044
|
if (result2.issues.length) {
|
|
9045
|
-
|
|
9045
|
+
payload2.issues.push(...prefixIssues(key, result2.issues));
|
|
9046
9046
|
}
|
|
9047
|
-
|
|
9047
|
+
payload2.value[keyResult.value] = result2.value;
|
|
9048
9048
|
}));
|
|
9049
9049
|
} else {
|
|
9050
9050
|
if (result.issues.length) {
|
|
9051
|
-
|
|
9051
|
+
payload2.issues.push(...prefixIssues(key, result.issues));
|
|
9052
9052
|
}
|
|
9053
|
-
|
|
9053
|
+
payload2.value[keyResult.value] = result.value;
|
|
9054
9054
|
}
|
|
9055
9055
|
}
|
|
9056
9056
|
}
|
|
9057
9057
|
if (proms.length) {
|
|
9058
|
-
return Promise.all(proms).then(() =>
|
|
9058
|
+
return Promise.all(proms).then(() => payload2);
|
|
9059
9059
|
}
|
|
9060
|
-
return
|
|
9060
|
+
return payload2;
|
|
9061
9061
|
};
|
|
9062
9062
|
});
|
|
9063
9063
|
var $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
|
|
@@ -9065,54 +9065,54 @@ var $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
|
|
|
9065
9065
|
const values = getEnumValues(def.entries);
|
|
9066
9066
|
inst._zod.values = new Set(values);
|
|
9067
9067
|
inst._zod.pattern = new RegExp(`^(${values.filter((k) => propertyKeyTypes.has(typeof k)).map((o) => typeof o === "string" ? escapeRegex(o) : o.toString()).join("|")})$`);
|
|
9068
|
-
inst._zod.parse = (
|
|
9069
|
-
const input =
|
|
9068
|
+
inst._zod.parse = (payload2, _ctx) => {
|
|
9069
|
+
const input = payload2.value;
|
|
9070
9070
|
if (inst._zod.values.has(input)) {
|
|
9071
|
-
return
|
|
9071
|
+
return payload2;
|
|
9072
9072
|
}
|
|
9073
|
-
|
|
9073
|
+
payload2.issues.push({
|
|
9074
9074
|
code: "invalid_value",
|
|
9075
9075
|
values,
|
|
9076
9076
|
input,
|
|
9077
9077
|
inst
|
|
9078
9078
|
});
|
|
9079
|
-
return
|
|
9079
|
+
return payload2;
|
|
9080
9080
|
};
|
|
9081
9081
|
});
|
|
9082
9082
|
var $ZodLiteral = /* @__PURE__ */ $constructor("$ZodLiteral", (inst, def) => {
|
|
9083
9083
|
$ZodType.init(inst, def);
|
|
9084
9084
|
inst._zod.values = new Set(def.values);
|
|
9085
9085
|
inst._zod.pattern = new RegExp(`^(${def.values.map((o) => typeof o === "string" ? escapeRegex(o) : o ? o.toString() : String(o)).join("|")})$`);
|
|
9086
|
-
inst._zod.parse = (
|
|
9087
|
-
const input =
|
|
9086
|
+
inst._zod.parse = (payload2, _ctx) => {
|
|
9087
|
+
const input = payload2.value;
|
|
9088
9088
|
if (inst._zod.values.has(input)) {
|
|
9089
|
-
return
|
|
9089
|
+
return payload2;
|
|
9090
9090
|
}
|
|
9091
|
-
|
|
9091
|
+
payload2.issues.push({
|
|
9092
9092
|
code: "invalid_value",
|
|
9093
9093
|
values: def.values,
|
|
9094
9094
|
input,
|
|
9095
9095
|
inst
|
|
9096
9096
|
});
|
|
9097
|
-
return
|
|
9097
|
+
return payload2;
|
|
9098
9098
|
};
|
|
9099
9099
|
});
|
|
9100
9100
|
var $ZodTransform = /* @__PURE__ */ $constructor("$ZodTransform", (inst, def) => {
|
|
9101
9101
|
$ZodType.init(inst, def);
|
|
9102
|
-
inst._zod.parse = (
|
|
9103
|
-
const _out = def.transform(
|
|
9102
|
+
inst._zod.parse = (payload2, _ctx) => {
|
|
9103
|
+
const _out = def.transform(payload2.value, payload2);
|
|
9104
9104
|
if (_ctx.async) {
|
|
9105
9105
|
const output = _out instanceof Promise ? _out : Promise.resolve(_out);
|
|
9106
9106
|
return output.then((output2) => {
|
|
9107
|
-
|
|
9108
|
-
return
|
|
9107
|
+
payload2.value = output2;
|
|
9108
|
+
return payload2;
|
|
9109
9109
|
});
|
|
9110
9110
|
}
|
|
9111
9111
|
if (_out instanceof Promise) {
|
|
9112
9112
|
throw new $ZodAsyncError();
|
|
9113
9113
|
}
|
|
9114
|
-
|
|
9115
|
-
return
|
|
9114
|
+
payload2.value = _out;
|
|
9115
|
+
return payload2;
|
|
9116
9116
|
};
|
|
9117
9117
|
});
|
|
9118
9118
|
var $ZodOptional = /* @__PURE__ */ $constructor("$ZodOptional", (inst, def) => {
|
|
@@ -9126,14 +9126,14 @@ var $ZodOptional = /* @__PURE__ */ $constructor("$ZodOptional", (inst, def) => {
|
|
|
9126
9126
|
const pattern = def.innerType._zod.pattern;
|
|
9127
9127
|
return pattern ? new RegExp(`^(${cleanRegex(pattern.source)})?$`) : void 0;
|
|
9128
9128
|
});
|
|
9129
|
-
inst._zod.parse = (
|
|
9129
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
9130
9130
|
if (def.innerType._zod.optin === "optional") {
|
|
9131
|
-
return def.innerType._zod.run(
|
|
9131
|
+
return def.innerType._zod.run(payload2, ctx);
|
|
9132
9132
|
}
|
|
9133
|
-
if (
|
|
9134
|
-
return
|
|
9133
|
+
if (payload2.value === void 0) {
|
|
9134
|
+
return payload2;
|
|
9135
9135
|
}
|
|
9136
|
-
return def.innerType._zod.run(
|
|
9136
|
+
return def.innerType._zod.run(payload2, ctx);
|
|
9137
9137
|
};
|
|
9138
9138
|
});
|
|
9139
9139
|
var $ZodNullable = /* @__PURE__ */ $constructor("$ZodNullable", (inst, def) => {
|
|
@@ -9147,43 +9147,43 @@ var $ZodNullable = /* @__PURE__ */ $constructor("$ZodNullable", (inst, def) => {
|
|
|
9147
9147
|
defineLazy(inst._zod, "values", () => {
|
|
9148
9148
|
return def.innerType._zod.values ? /* @__PURE__ */ new Set([...def.innerType._zod.values, null]) : void 0;
|
|
9149
9149
|
});
|
|
9150
|
-
inst._zod.parse = (
|
|
9151
|
-
if (
|
|
9152
|
-
return
|
|
9153
|
-
return def.innerType._zod.run(
|
|
9150
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
9151
|
+
if (payload2.value === null)
|
|
9152
|
+
return payload2;
|
|
9153
|
+
return def.innerType._zod.run(payload2, ctx);
|
|
9154
9154
|
};
|
|
9155
9155
|
});
|
|
9156
9156
|
var $ZodDefault = /* @__PURE__ */ $constructor("$ZodDefault", (inst, def) => {
|
|
9157
9157
|
$ZodType.init(inst, def);
|
|
9158
9158
|
inst._zod.optin = "optional";
|
|
9159
9159
|
defineLazy(inst._zod, "values", () => def.innerType._zod.values);
|
|
9160
|
-
inst._zod.parse = (
|
|
9161
|
-
if (
|
|
9162
|
-
|
|
9163
|
-
return
|
|
9160
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
9161
|
+
if (payload2.value === void 0) {
|
|
9162
|
+
payload2.value = def.defaultValue;
|
|
9163
|
+
return payload2;
|
|
9164
9164
|
}
|
|
9165
|
-
const result = def.innerType._zod.run(
|
|
9165
|
+
const result = def.innerType._zod.run(payload2, ctx);
|
|
9166
9166
|
if (result instanceof Promise) {
|
|
9167
9167
|
return result.then((result2) => handleDefaultResult(result2, def));
|
|
9168
9168
|
}
|
|
9169
9169
|
return handleDefaultResult(result, def);
|
|
9170
9170
|
};
|
|
9171
9171
|
});
|
|
9172
|
-
function handleDefaultResult(
|
|
9173
|
-
if (
|
|
9174
|
-
|
|
9172
|
+
function handleDefaultResult(payload2, def) {
|
|
9173
|
+
if (payload2.value === void 0) {
|
|
9174
|
+
payload2.value = def.defaultValue;
|
|
9175
9175
|
}
|
|
9176
|
-
return
|
|
9176
|
+
return payload2;
|
|
9177
9177
|
}
|
|
9178
9178
|
var $ZodPrefault = /* @__PURE__ */ $constructor("$ZodPrefault", (inst, def) => {
|
|
9179
9179
|
$ZodType.init(inst, def);
|
|
9180
9180
|
inst._zod.optin = "optional";
|
|
9181
9181
|
defineLazy(inst._zod, "values", () => def.innerType._zod.values);
|
|
9182
|
-
inst._zod.parse = (
|
|
9183
|
-
if (
|
|
9184
|
-
|
|
9182
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
9183
|
+
if (payload2.value === void 0) {
|
|
9184
|
+
payload2.value = def.defaultValue;
|
|
9185
9185
|
}
|
|
9186
|
-
return def.innerType._zod.run(
|
|
9186
|
+
return def.innerType._zod.run(payload2, ctx);
|
|
9187
9187
|
};
|
|
9188
9188
|
});
|
|
9189
9189
|
var $ZodNonOptional = /* @__PURE__ */ $constructor("$ZodNonOptional", (inst, def) => {
|
|
@@ -9192,60 +9192,60 @@ var $ZodNonOptional = /* @__PURE__ */ $constructor("$ZodNonOptional", (inst, def
|
|
|
9192
9192
|
const v = def.innerType._zod.values;
|
|
9193
9193
|
return v ? new Set([...v].filter((x) => x !== void 0)) : void 0;
|
|
9194
9194
|
});
|
|
9195
|
-
inst._zod.parse = (
|
|
9196
|
-
const result = def.innerType._zod.run(
|
|
9195
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
9196
|
+
const result = def.innerType._zod.run(payload2, ctx);
|
|
9197
9197
|
if (result instanceof Promise) {
|
|
9198
9198
|
return result.then((result2) => handleNonOptionalResult(result2, inst));
|
|
9199
9199
|
}
|
|
9200
9200
|
return handleNonOptionalResult(result, inst);
|
|
9201
9201
|
};
|
|
9202
9202
|
});
|
|
9203
|
-
function handleNonOptionalResult(
|
|
9204
|
-
if (!
|
|
9205
|
-
|
|
9203
|
+
function handleNonOptionalResult(payload2, inst) {
|
|
9204
|
+
if (!payload2.issues.length && payload2.value === void 0) {
|
|
9205
|
+
payload2.issues.push({
|
|
9206
9206
|
code: "invalid_type",
|
|
9207
9207
|
expected: "nonoptional",
|
|
9208
|
-
input:
|
|
9208
|
+
input: payload2.value,
|
|
9209
9209
|
inst
|
|
9210
9210
|
});
|
|
9211
9211
|
}
|
|
9212
|
-
return
|
|
9212
|
+
return payload2;
|
|
9213
9213
|
}
|
|
9214
9214
|
var $ZodCatch = /* @__PURE__ */ $constructor("$ZodCatch", (inst, def) => {
|
|
9215
9215
|
$ZodType.init(inst, def);
|
|
9216
9216
|
inst._zod.optin = "optional";
|
|
9217
9217
|
defineLazy(inst._zod, "optout", () => def.innerType._zod.optout);
|
|
9218
9218
|
defineLazy(inst._zod, "values", () => def.innerType._zod.values);
|
|
9219
|
-
inst._zod.parse = (
|
|
9220
|
-
const result = def.innerType._zod.run(
|
|
9219
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
9220
|
+
const result = def.innerType._zod.run(payload2, ctx);
|
|
9221
9221
|
if (result instanceof Promise) {
|
|
9222
9222
|
return result.then((result2) => {
|
|
9223
|
-
|
|
9223
|
+
payload2.value = result2.value;
|
|
9224
9224
|
if (result2.issues.length) {
|
|
9225
|
-
|
|
9226
|
-
...
|
|
9225
|
+
payload2.value = def.catchValue({
|
|
9226
|
+
...payload2,
|
|
9227
9227
|
error: {
|
|
9228
9228
|
issues: result2.issues.map((iss) => finalizeIssue(iss, ctx, config()))
|
|
9229
9229
|
},
|
|
9230
|
-
input:
|
|
9230
|
+
input: payload2.value
|
|
9231
9231
|
});
|
|
9232
|
-
|
|
9232
|
+
payload2.issues = [];
|
|
9233
9233
|
}
|
|
9234
|
-
return
|
|
9234
|
+
return payload2;
|
|
9235
9235
|
});
|
|
9236
9236
|
}
|
|
9237
|
-
|
|
9237
|
+
payload2.value = result.value;
|
|
9238
9238
|
if (result.issues.length) {
|
|
9239
|
-
|
|
9240
|
-
...
|
|
9239
|
+
payload2.value = def.catchValue({
|
|
9240
|
+
...payload2,
|
|
9241
9241
|
error: {
|
|
9242
9242
|
issues: result.issues.map((iss) => finalizeIssue(iss, ctx, config()))
|
|
9243
9243
|
},
|
|
9244
|
-
input:
|
|
9244
|
+
input: payload2.value
|
|
9245
9245
|
});
|
|
9246
|
-
|
|
9246
|
+
payload2.issues = [];
|
|
9247
9247
|
}
|
|
9248
|
-
return
|
|
9248
|
+
return payload2;
|
|
9249
9249
|
};
|
|
9250
9250
|
});
|
|
9251
9251
|
var $ZodPipe = /* @__PURE__ */ $constructor("$ZodPipe", (inst, def) => {
|
|
@@ -9253,8 +9253,8 @@ var $ZodPipe = /* @__PURE__ */ $constructor("$ZodPipe", (inst, def) => {
|
|
|
9253
9253
|
defineLazy(inst._zod, "values", () => def.in._zod.values);
|
|
9254
9254
|
defineLazy(inst._zod, "optin", () => def.in._zod.optin);
|
|
9255
9255
|
defineLazy(inst._zod, "optout", () => def.out._zod.optout);
|
|
9256
|
-
inst._zod.parse = (
|
|
9257
|
-
const left = def.in._zod.run(
|
|
9256
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
9257
|
+
const left = def.in._zod.run(payload2, ctx);
|
|
9258
9258
|
if (left instanceof Promise) {
|
|
9259
9259
|
return left.then((left2) => handlePipeResult(left2, def, ctx));
|
|
9260
9260
|
}
|
|
@@ -9273,35 +9273,35 @@ var $ZodReadonly = /* @__PURE__ */ $constructor("$ZodReadonly", (inst, def) => {
|
|
|
9273
9273
|
defineLazy(inst._zod, "values", () => def.innerType._zod.values);
|
|
9274
9274
|
defineLazy(inst._zod, "optin", () => def.innerType._zod.optin);
|
|
9275
9275
|
defineLazy(inst._zod, "optout", () => def.innerType._zod.optout);
|
|
9276
|
-
inst._zod.parse = (
|
|
9277
|
-
const result = def.innerType._zod.run(
|
|
9276
|
+
inst._zod.parse = (payload2, ctx) => {
|
|
9277
|
+
const result = def.innerType._zod.run(payload2, ctx);
|
|
9278
9278
|
if (result instanceof Promise) {
|
|
9279
9279
|
return result.then(handleReadonlyResult);
|
|
9280
9280
|
}
|
|
9281
9281
|
return handleReadonlyResult(result);
|
|
9282
9282
|
};
|
|
9283
9283
|
});
|
|
9284
|
-
function handleReadonlyResult(
|
|
9285
|
-
|
|
9286
|
-
return
|
|
9284
|
+
function handleReadonlyResult(payload2) {
|
|
9285
|
+
payload2.value = Object.freeze(payload2.value);
|
|
9286
|
+
return payload2;
|
|
9287
9287
|
}
|
|
9288
9288
|
var $ZodCustom = /* @__PURE__ */ $constructor("$ZodCustom", (inst, def) => {
|
|
9289
9289
|
$ZodCheck.init(inst, def);
|
|
9290
9290
|
$ZodType.init(inst, def);
|
|
9291
|
-
inst._zod.parse = (
|
|
9292
|
-
return
|
|
9291
|
+
inst._zod.parse = (payload2, _) => {
|
|
9292
|
+
return payload2;
|
|
9293
9293
|
};
|
|
9294
|
-
inst._zod.check = (
|
|
9295
|
-
const input =
|
|
9294
|
+
inst._zod.check = (payload2) => {
|
|
9295
|
+
const input = payload2.value;
|
|
9296
9296
|
const r = def.fn(input);
|
|
9297
9297
|
if (r instanceof Promise) {
|
|
9298
|
-
return r.then((r2) => handleRefineResult(r2,
|
|
9298
|
+
return r.then((r2) => handleRefineResult(r2, payload2, input, inst));
|
|
9299
9299
|
}
|
|
9300
|
-
handleRefineResult(r,
|
|
9300
|
+
handleRefineResult(r, payload2, input, inst);
|
|
9301
9301
|
return;
|
|
9302
9302
|
};
|
|
9303
9303
|
});
|
|
9304
|
-
function handleRefineResult(result,
|
|
9304
|
+
function handleRefineResult(result, payload2, input, inst) {
|
|
9305
9305
|
if (!result) {
|
|
9306
9306
|
const _iss = {
|
|
9307
9307
|
code: "custom",
|
|
@@ -9315,7 +9315,7 @@ function handleRefineResult(result, payload, input, inst) {
|
|
|
9315
9315
|
};
|
|
9316
9316
|
if (inst._zod.def.params)
|
|
9317
9317
|
_iss.params = inst._zod.def.params;
|
|
9318
|
-
|
|
9318
|
+
payload2.issues.push(issue(_iss));
|
|
9319
9319
|
}
|
|
9320
9320
|
}
|
|
9321
9321
|
|
|
@@ -11209,30 +11209,30 @@ function literal(value, params) {
|
|
|
11209
11209
|
var ZodTransform = /* @__PURE__ */ $constructor("ZodTransform", (inst, def) => {
|
|
11210
11210
|
$ZodTransform.init(inst, def);
|
|
11211
11211
|
ZodType.init(inst, def);
|
|
11212
|
-
inst._zod.parse = (
|
|
11213
|
-
|
|
11212
|
+
inst._zod.parse = (payload2, _ctx) => {
|
|
11213
|
+
payload2.addIssue = (issue2) => {
|
|
11214
11214
|
if (typeof issue2 === "string") {
|
|
11215
|
-
|
|
11215
|
+
payload2.issues.push(util_exports.issue(issue2, payload2.value, def));
|
|
11216
11216
|
} else {
|
|
11217
11217
|
const _issue = issue2;
|
|
11218
11218
|
if (_issue.fatal)
|
|
11219
11219
|
_issue.continue = false;
|
|
11220
11220
|
_issue.code ?? (_issue.code = "custom");
|
|
11221
|
-
_issue.input ?? (_issue.input =
|
|
11221
|
+
_issue.input ?? (_issue.input = payload2.value);
|
|
11222
11222
|
_issue.inst ?? (_issue.inst = inst);
|
|
11223
11223
|
_issue.continue ?? (_issue.continue = true);
|
|
11224
|
-
|
|
11224
|
+
payload2.issues.push(util_exports.issue(_issue));
|
|
11225
11225
|
}
|
|
11226
11226
|
};
|
|
11227
|
-
const output = def.transform(
|
|
11227
|
+
const output = def.transform(payload2.value, payload2);
|
|
11228
11228
|
if (output instanceof Promise) {
|
|
11229
11229
|
return output.then((output2) => {
|
|
11230
|
-
|
|
11231
|
-
return
|
|
11230
|
+
payload2.value = output2;
|
|
11231
|
+
return payload2;
|
|
11232
11232
|
});
|
|
11233
11233
|
}
|
|
11234
|
-
|
|
11235
|
-
return
|
|
11234
|
+
payload2.value = output;
|
|
11235
|
+
return payload2;
|
|
11236
11236
|
};
|
|
11237
11237
|
});
|
|
11238
11238
|
function transform(fn) {
|
|
@@ -11360,22 +11360,22 @@ function refine(fn, _params = {}) {
|
|
|
11360
11360
|
return _refine(ZodCustom, fn, _params);
|
|
11361
11361
|
}
|
|
11362
11362
|
function superRefine(fn) {
|
|
11363
|
-
const ch = check((
|
|
11364
|
-
|
|
11363
|
+
const ch = check((payload2) => {
|
|
11364
|
+
payload2.addIssue = (issue2) => {
|
|
11365
11365
|
if (typeof issue2 === "string") {
|
|
11366
|
-
|
|
11366
|
+
payload2.issues.push(util_exports.issue(issue2, payload2.value, ch._zod.def));
|
|
11367
11367
|
} else {
|
|
11368
11368
|
const _issue = issue2;
|
|
11369
11369
|
if (_issue.fatal)
|
|
11370
11370
|
_issue.continue = false;
|
|
11371
11371
|
_issue.code ?? (_issue.code = "custom");
|
|
11372
|
-
_issue.input ?? (_issue.input =
|
|
11372
|
+
_issue.input ?? (_issue.input = payload2.value);
|
|
11373
11373
|
_issue.inst ?? (_issue.inst = ch);
|
|
11374
11374
|
_issue.continue ?? (_issue.continue = !ch._zod.def.abort);
|
|
11375
|
-
|
|
11375
|
+
payload2.issues.push(util_exports.issue(_issue));
|
|
11376
11376
|
}
|
|
11377
11377
|
};
|
|
11378
|
-
return fn(
|
|
11378
|
+
return fn(payload2.value, payload2);
|
|
11379
11379
|
});
|
|
11380
11380
|
return ch;
|
|
11381
11381
|
}
|
|
@@ -21163,7 +21163,17 @@ var ApiError = class extends Error {
|
|
|
21163
21163
|
this.body = body2;
|
|
21164
21164
|
}
|
|
21165
21165
|
};
|
|
21166
|
+
var LoginExpiredError = class extends ApiError {
|
|
21167
|
+
constructor() {
|
|
21168
|
+
super(
|
|
21169
|
+
401,
|
|
21170
|
+
"O acesso pelo navegador expirou e n\xE3o deu para renovar sozinho. Rode `beplus-mcp login` de novo e autorize; n\xE3o precisa reiniciar o agente, a pr\xF3xima chamada j\xE1 usa o login novo."
|
|
21171
|
+
);
|
|
21172
|
+
this.name = "LoginExpiredError";
|
|
21173
|
+
}
|
|
21174
|
+
};
|
|
21166
21175
|
function apiErrorToUserMessage(err) {
|
|
21176
|
+
if (err instanceof LoginExpiredError) return err.message;
|
|
21167
21177
|
if (err instanceof ApiError) {
|
|
21168
21178
|
const detail = err.message || "";
|
|
21169
21179
|
switch (err.httpStatus) {
|
|
@@ -21195,6 +21205,333 @@ function apiErrorToUserMessage(err) {
|
|
|
21195
21205
|
return String(err);
|
|
21196
21206
|
}
|
|
21197
21207
|
|
|
21208
|
+
// src/credentials.ts
|
|
21209
|
+
import { chmod, mkdir, open, readFile, rename, stat, unlink, writeFile } from "fs/promises";
|
|
21210
|
+
import { homedir } from "os";
|
|
21211
|
+
import { dirname, join } from "path";
|
|
21212
|
+
function credentialsPath() {
|
|
21213
|
+
const base = process.env.XDG_CONFIG_HOME?.trim() || join(homedir(), ".config");
|
|
21214
|
+
return join(base, "beplus-mcp", "credentials.json");
|
|
21215
|
+
}
|
|
21216
|
+
async function readCredentials() {
|
|
21217
|
+
try {
|
|
21218
|
+
const raw = await readFile(credentialsPath(), "utf8");
|
|
21219
|
+
const parsed = JSON.parse(raw);
|
|
21220
|
+
if (!parsed.accessToken || !parsed.apiUrl) return null;
|
|
21221
|
+
return parsed;
|
|
21222
|
+
} catch {
|
|
21223
|
+
return null;
|
|
21224
|
+
}
|
|
21225
|
+
}
|
|
21226
|
+
async function writeCredentials(creds) {
|
|
21227
|
+
const path = credentialsPath();
|
|
21228
|
+
await mkdir(dirname(path), { recursive: true, mode: 448 });
|
|
21229
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
21230
|
+
await writeFile(tmp, `${JSON.stringify(creds, null, 2)}
|
|
21231
|
+
`, { mode: 384 });
|
|
21232
|
+
await chmod(tmp, 384);
|
|
21233
|
+
await rename(tmp, path);
|
|
21234
|
+
return path;
|
|
21235
|
+
}
|
|
21236
|
+
async function clearCredentials() {
|
|
21237
|
+
try {
|
|
21238
|
+
await unlink(credentialsPath());
|
|
21239
|
+
return true;
|
|
21240
|
+
} catch {
|
|
21241
|
+
return false;
|
|
21242
|
+
}
|
|
21243
|
+
}
|
|
21244
|
+
var RENEW_MARGIN_MS = 6e4;
|
|
21245
|
+
function isExpired(creds) {
|
|
21246
|
+
return typeof creds.expiresAt === "number" && creds.expiresAt - RENEW_MARGIN_MS <= Date.now();
|
|
21247
|
+
}
|
|
21248
|
+
var credentialsLock = {
|
|
21249
|
+
staleMs: 3e4,
|
|
21250
|
+
waitMs: 35e3,
|
|
21251
|
+
pollMs: 100
|
|
21252
|
+
};
|
|
21253
|
+
async function withCredentialsLock(fn) {
|
|
21254
|
+
const path = credentialsPath();
|
|
21255
|
+
const lock = `${path}.lock`;
|
|
21256
|
+
await mkdir(dirname(path), { recursive: true, mode: 448 });
|
|
21257
|
+
const started = Date.now();
|
|
21258
|
+
for (; ; ) {
|
|
21259
|
+
try {
|
|
21260
|
+
const fh = await open(lock, "wx", 384);
|
|
21261
|
+
await fh.writeFile(String(process.pid));
|
|
21262
|
+
await fh.close();
|
|
21263
|
+
break;
|
|
21264
|
+
} catch (e) {
|
|
21265
|
+
if (e.code !== "EEXIST") throw e;
|
|
21266
|
+
try {
|
|
21267
|
+
const age = Date.now() - (await stat(lock)).mtimeMs;
|
|
21268
|
+
if (age > credentialsLock.staleMs) {
|
|
21269
|
+
await unlink(lock).catch(() => {
|
|
21270
|
+
});
|
|
21271
|
+
continue;
|
|
21272
|
+
}
|
|
21273
|
+
} catch {
|
|
21274
|
+
continue;
|
|
21275
|
+
}
|
|
21276
|
+
if (Date.now() - started > credentialsLock.waitMs) {
|
|
21277
|
+
throw new Error("Outro processo do beplus-mcp est\xE1 renovando o login h\xE1 tempo demais. Tente de novo em instantes.");
|
|
21278
|
+
}
|
|
21279
|
+
await new Promise((r) => setTimeout(r, credentialsLock.pollMs));
|
|
21280
|
+
}
|
|
21281
|
+
}
|
|
21282
|
+
try {
|
|
21283
|
+
return await fn();
|
|
21284
|
+
} finally {
|
|
21285
|
+
await unlink(lock).catch(() => {
|
|
21286
|
+
});
|
|
21287
|
+
}
|
|
21288
|
+
}
|
|
21289
|
+
|
|
21290
|
+
// src/oauth.ts
|
|
21291
|
+
import crypto from "crypto";
|
|
21292
|
+
import { createServer } from "http";
|
|
21293
|
+
import { spawn } from "child_process";
|
|
21294
|
+
var CALLBACK_TIMEOUT_MS = 5 * 6e4;
|
|
21295
|
+
var REQUEST_TIMEOUT_MS = 1e4;
|
|
21296
|
+
async function json(url, init) {
|
|
21297
|
+
let res;
|
|
21298
|
+
try {
|
|
21299
|
+
res = await fetch(url, { ...init, signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) });
|
|
21300
|
+
} catch {
|
|
21301
|
+
throw new Error(`Nao consegui falar com ${new URL(url).origin}. Confira a rede e o BEPLUS_API_URL.`);
|
|
21302
|
+
}
|
|
21303
|
+
const text = await res.text();
|
|
21304
|
+
let body2;
|
|
21305
|
+
try {
|
|
21306
|
+
body2 = text ? JSON.parse(text) : void 0;
|
|
21307
|
+
} catch {
|
|
21308
|
+
}
|
|
21309
|
+
if (!res.ok) {
|
|
21310
|
+
const msg = body2?.message ?? body2?.error_description ?? body2?.error ?? `HTTP ${res.status}`;
|
|
21311
|
+
throw new Error(`${msg} (${url})`);
|
|
21312
|
+
}
|
|
21313
|
+
return body2;
|
|
21314
|
+
}
|
|
21315
|
+
async function discover(apiUrl2) {
|
|
21316
|
+
const meta = await json(`${apiUrl2}/.well-known/oauth-authorization-server`);
|
|
21317
|
+
if (!meta.authorization_endpoint || !meta.token_endpoint || !meta.registration_endpoint) {
|
|
21318
|
+
throw new Error("O servidor respondeu a descoberta sem os endpoints obrigatorios.");
|
|
21319
|
+
}
|
|
21320
|
+
return meta;
|
|
21321
|
+
}
|
|
21322
|
+
function pkce() {
|
|
21323
|
+
const verifier = crypto.randomBytes(32).toString("base64url");
|
|
21324
|
+
return { verifier, challenge: crypto.createHash("sha256").update(verifier).digest("base64url") };
|
|
21325
|
+
}
|
|
21326
|
+
function openBrowser(url) {
|
|
21327
|
+
try {
|
|
21328
|
+
if (process.platform === "win32") {
|
|
21329
|
+
spawn("cmd.exe", ["/c", "start", '""', "/b", url.replace(/&/g, "^&")], {
|
|
21330
|
+
stdio: "ignore",
|
|
21331
|
+
detached: true,
|
|
21332
|
+
windowsVerbatimArguments: true
|
|
21333
|
+
}).unref();
|
|
21334
|
+
return;
|
|
21335
|
+
}
|
|
21336
|
+
const cmd = process.platform === "darwin" ? "open" : "xdg-open";
|
|
21337
|
+
spawn(cmd, [url], { stdio: "ignore", detached: true }).unref();
|
|
21338
|
+
} catch {
|
|
21339
|
+
}
|
|
21340
|
+
}
|
|
21341
|
+
var PAGINA_OK = `<!doctype html><meta charset="utf-8"><title>Pronto</title>
|
|
21342
|
+
<body style="margin:0;min-height:100vh;display:grid;place-items:center;font:16px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#0e1433;color:#f7f6f2">
|
|
21343
|
+
<div style="text-align:center;padding:24px"><h1 style="font-size:22px;margin:0 0 8px">Tudo certo</h1>
|
|
21344
|
+
<p style="margin:0;opacity:.7">Pode fechar esta aba e voltar para o seu agente.</p></div>`;
|
|
21345
|
+
var PAGINA_ERRO = `<!doctype html><meta charset="utf-8"><title>Nao deu</title>
|
|
21346
|
+
<body style="margin:0;min-height:100vh;display:grid;place-items:center;font:16px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#0e1433;color:#f7f6f2">
|
|
21347
|
+
<div style="text-align:center;padding:24px"><h1 style="font-size:22px;margin:0 0 8px">Nao foi dessa vez</h1>
|
|
21348
|
+
<p style="margin:0;opacity:.7">Volte ao terminal para ver o motivo.</p></div>`;
|
|
21349
|
+
function listenForCallback(expectedState) {
|
|
21350
|
+
return new Promise((resolvePort, rejectPort) => {
|
|
21351
|
+
let settle;
|
|
21352
|
+
let fail;
|
|
21353
|
+
const code = new Promise((res, rej) => {
|
|
21354
|
+
settle = res;
|
|
21355
|
+
fail = rej;
|
|
21356
|
+
});
|
|
21357
|
+
const server = createServer((req, res) => {
|
|
21358
|
+
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
21359
|
+
if (url.pathname !== "/callback") {
|
|
21360
|
+
res.writeHead(404).end();
|
|
21361
|
+
return;
|
|
21362
|
+
}
|
|
21363
|
+
const erro = url.searchParams.get("error");
|
|
21364
|
+
const recebido = url.searchParams.get("code");
|
|
21365
|
+
const state = url.searchParams.get("state") ?? "";
|
|
21366
|
+
const ok = !erro && recebido && state === expectedState;
|
|
21367
|
+
res.writeHead(ok ? 200 : 400, { "content-type": "text/html; charset=utf-8" });
|
|
21368
|
+
res.end(ok ? PAGINA_OK : PAGINA_ERRO);
|
|
21369
|
+
server.close();
|
|
21370
|
+
if (erro) return fail(new Error(url.searchParams.get("error_description") || erro));
|
|
21371
|
+
if (!recebido || state !== expectedState) return fail(new Error("Resposta de autorizacao invalida."));
|
|
21372
|
+
settle({ code: recebido, state });
|
|
21373
|
+
});
|
|
21374
|
+
server.on("error", rejectPort);
|
|
21375
|
+
server.listen(0, "127.0.0.1", () => {
|
|
21376
|
+
const addr = server.address();
|
|
21377
|
+
if (!addr || typeof addr === "string") return rejectPort(new Error("Nao consegui abrir a porta local."));
|
|
21378
|
+
const timer = setTimeout(() => {
|
|
21379
|
+
server.close();
|
|
21380
|
+
fail(new Error("Tempo esgotado esperando a autorizacao no navegador."));
|
|
21381
|
+
}, CALLBACK_TIMEOUT_MS);
|
|
21382
|
+
void code.finally(() => clearTimeout(timer));
|
|
21383
|
+
resolvePort({ port: addr.port, code });
|
|
21384
|
+
});
|
|
21385
|
+
});
|
|
21386
|
+
}
|
|
21387
|
+
function toStored(t, apiUrl2, clientId) {
|
|
21388
|
+
return {
|
|
21389
|
+
accessToken: t.access_token,
|
|
21390
|
+
refreshToken: t.refresh_token,
|
|
21391
|
+
expiresAt: t.expires_in ? Date.now() + t.expires_in * 1e3 : void 0,
|
|
21392
|
+
apiUrl: apiUrl2,
|
|
21393
|
+
clientId
|
|
21394
|
+
};
|
|
21395
|
+
}
|
|
21396
|
+
async function login(apiUrl2, onUrl) {
|
|
21397
|
+
const meta = await discover(apiUrl2);
|
|
21398
|
+
const state = crypto.randomBytes(24).toString("base64url");
|
|
21399
|
+
const { verifier, challenge } = pkce();
|
|
21400
|
+
const { port, code } = await listenForCallback(state);
|
|
21401
|
+
const redirectUri = `http://127.0.0.1:${port}/callback`;
|
|
21402
|
+
const client = await json(meta.registration_endpoint, {
|
|
21403
|
+
method: "POST",
|
|
21404
|
+
headers: { "content-type": "application/json" },
|
|
21405
|
+
body: JSON.stringify({
|
|
21406
|
+
client_name: "beplus-mcp (CLI)",
|
|
21407
|
+
redirect_uris: [redirectUri],
|
|
21408
|
+
token_endpoint_auth_method: "none",
|
|
21409
|
+
grant_types: ["authorization_code", "refresh_token"]
|
|
21410
|
+
})
|
|
21411
|
+
});
|
|
21412
|
+
const authorizeUrl = new URL(meta.authorization_endpoint);
|
|
21413
|
+
authorizeUrl.searchParams.set("response_type", "code");
|
|
21414
|
+
authorizeUrl.searchParams.set("client_id", client.client_id);
|
|
21415
|
+
authorizeUrl.searchParams.set("redirect_uri", redirectUri);
|
|
21416
|
+
authorizeUrl.searchParams.set("code_challenge", challenge);
|
|
21417
|
+
authorizeUrl.searchParams.set("code_challenge_method", "S256");
|
|
21418
|
+
authorizeUrl.searchParams.set("state", state);
|
|
21419
|
+
onUrl(authorizeUrl.toString());
|
|
21420
|
+
openBrowser(authorizeUrl.toString());
|
|
21421
|
+
const { code: authCode } = await code;
|
|
21422
|
+
const token = await json(meta.token_endpoint, {
|
|
21423
|
+
method: "POST",
|
|
21424
|
+
headers: { "content-type": "application/json" },
|
|
21425
|
+
body: JSON.stringify({
|
|
21426
|
+
grant_type: "authorization_code",
|
|
21427
|
+
code: authCode,
|
|
21428
|
+
code_verifier: verifier,
|
|
21429
|
+
client_id: client.client_id,
|
|
21430
|
+
redirect_uri: redirectUri
|
|
21431
|
+
})
|
|
21432
|
+
});
|
|
21433
|
+
const path = await writeCredentials(toStored(token, apiUrl2, client.client_id));
|
|
21434
|
+
return { path, authorizeUrl: authorizeUrl.toString() };
|
|
21435
|
+
}
|
|
21436
|
+
var sameApi = (a, b) => a.replace(/\/+$/, "") === b.replace(/\/+$/, "");
|
|
21437
|
+
async function refreshGrant(apiUrl2, creds) {
|
|
21438
|
+
const meta = await discover(apiUrl2);
|
|
21439
|
+
const token = await json(meta.token_endpoint, {
|
|
21440
|
+
method: "POST",
|
|
21441
|
+
headers: { "content-type": "application/json" },
|
|
21442
|
+
body: JSON.stringify({
|
|
21443
|
+
grant_type: "refresh_token",
|
|
21444
|
+
refresh_token: creds.refreshToken,
|
|
21445
|
+
client_id: creds.clientId
|
|
21446
|
+
})
|
|
21447
|
+
});
|
|
21448
|
+
return toStored(token, apiUrl2, creds.clientId);
|
|
21449
|
+
}
|
|
21450
|
+
async function renewFromDisk(apiUrl2, rejected) {
|
|
21451
|
+
try {
|
|
21452
|
+
return await withCredentialsLock(async () => {
|
|
21453
|
+
const creds = await readCredentials();
|
|
21454
|
+
if (!creds || !sameApi(creds.apiUrl, apiUrl2)) return null;
|
|
21455
|
+
if (creds.accessToken !== rejected && !isExpired(creds)) return creds.accessToken;
|
|
21456
|
+
if (!creds.refreshToken) return null;
|
|
21457
|
+
const fresh = await refreshGrant(apiUrl2, creds);
|
|
21458
|
+
await writeCredentials(fresh);
|
|
21459
|
+
return fresh.accessToken;
|
|
21460
|
+
});
|
|
21461
|
+
} catch {
|
|
21462
|
+
return null;
|
|
21463
|
+
}
|
|
21464
|
+
}
|
|
21465
|
+
async function tokenFromDisk(apiUrl2) {
|
|
21466
|
+
const creds = await readCredentials();
|
|
21467
|
+
if (!creds || !sameApi(creds.apiUrl, apiUrl2)) return null;
|
|
21468
|
+
if (!isExpired(creds)) return creds.accessToken;
|
|
21469
|
+
if (!creds.refreshToken) return null;
|
|
21470
|
+
return renewFromDisk(apiUrl2, creds.accessToken);
|
|
21471
|
+
}
|
|
21472
|
+
|
|
21473
|
+
// src/auth.ts
|
|
21474
|
+
function staticToken(token) {
|
|
21475
|
+
return { renewable: false, current: async () => token, refresh: async () => null };
|
|
21476
|
+
}
|
|
21477
|
+
var LoginToken = class {
|
|
21478
|
+
constructor(apiUrl2, last) {
|
|
21479
|
+
this.apiUrl = apiUrl2;
|
|
21480
|
+
this.last = last;
|
|
21481
|
+
}
|
|
21482
|
+
apiUrl;
|
|
21483
|
+
last;
|
|
21484
|
+
renewable = true;
|
|
21485
|
+
/** Token cuja renovação antecipada acabou de falhar: o 401 dele não tenta de novo. */
|
|
21486
|
+
failedFor = null;
|
|
21487
|
+
async current() {
|
|
21488
|
+
const creds = await readCredentials();
|
|
21489
|
+
if (!creds || creds.apiUrl.replace(/\/+$/, "") !== this.apiUrl.replace(/\/+$/, "")) return this.last;
|
|
21490
|
+
if (isExpired(creds) && creds.refreshToken) {
|
|
21491
|
+
const fresh = await renewFromDisk(this.apiUrl, creds.accessToken);
|
|
21492
|
+
if (fresh) return this.last = fresh;
|
|
21493
|
+
this.failedFor = creds.accessToken;
|
|
21494
|
+
}
|
|
21495
|
+
return this.last = creds.accessToken;
|
|
21496
|
+
}
|
|
21497
|
+
async refresh(rejected) {
|
|
21498
|
+
if (rejected === this.failedFor) return null;
|
|
21499
|
+
const fresh = await renewFromDisk(this.apiUrl, rejected);
|
|
21500
|
+
if (fresh) this.last = fresh;
|
|
21501
|
+
return fresh;
|
|
21502
|
+
}
|
|
21503
|
+
};
|
|
21504
|
+
function tokenProvider(cfg) {
|
|
21505
|
+
return cfg.auth ?? staticToken(cfg.token);
|
|
21506
|
+
}
|
|
21507
|
+
async function fetchWithAuth(cfg, url, init, what) {
|
|
21508
|
+
const auth = tokenProvider(cfg);
|
|
21509
|
+
const send = async (token2) => {
|
|
21510
|
+
const { timeoutMs, headers, ...rest } = init;
|
|
21511
|
+
try {
|
|
21512
|
+
return await fetch(url, {
|
|
21513
|
+
...rest,
|
|
21514
|
+
headers: { ...headers, Authorization: `Bearer ${token2}` },
|
|
21515
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
21516
|
+
});
|
|
21517
|
+
} catch (e) {
|
|
21518
|
+
const name = e?.name;
|
|
21519
|
+
if (name === "TimeoutError" || name === "AbortError") {
|
|
21520
|
+
throw new ApiError(408, `Tempo esgotado ao falar com a API BePlus (${what}).`);
|
|
21521
|
+
}
|
|
21522
|
+
throw new ApiError(0, `Falha de rede ao falar com a API BePlus (${what}). Confira BEPLUS_API_URL.`);
|
|
21523
|
+
}
|
|
21524
|
+
};
|
|
21525
|
+
const token = await auth.current();
|
|
21526
|
+
const res = await send(token);
|
|
21527
|
+
if (res.status !== 401 || !auth.renewable) return res;
|
|
21528
|
+
await res.body?.cancel().catch(() => {
|
|
21529
|
+
});
|
|
21530
|
+
const fresh = await auth.refresh(token);
|
|
21531
|
+
if (!fresh) throw new LoginExpiredError();
|
|
21532
|
+
return send(fresh);
|
|
21533
|
+
}
|
|
21534
|
+
|
|
21198
21535
|
// src/api/client.ts
|
|
21199
21536
|
var BeplusClient = class {
|
|
21200
21537
|
constructor(cfg) {
|
|
@@ -21209,28 +21546,23 @@ var BeplusClient = class {
|
|
|
21209
21546
|
if (v !== void 0 && v !== null && v !== "") url.searchParams.set(k, String(v));
|
|
21210
21547
|
}
|
|
21211
21548
|
}
|
|
21212
|
-
const
|
|
21213
|
-
|
|
21214
|
-
|
|
21215
|
-
|
|
21216
|
-
res = await fetch(url, {
|
|
21549
|
+
const res = await fetchWithAuth(
|
|
21550
|
+
this.cfg,
|
|
21551
|
+
url,
|
|
21552
|
+
{
|
|
21217
21553
|
method,
|
|
21218
|
-
headers: {
|
|
21219
|
-
Authorization: `Bearer ${this.cfg.token}`,
|
|
21220
|
-
...opts.body ? { "Content-Type": "application/json" } : {}
|
|
21221
|
-
},
|
|
21554
|
+
headers: opts.body ? { "Content-Type": "application/json" } : {},
|
|
21222
21555
|
body: opts.body ? JSON.stringify(opts.body) : void 0,
|
|
21223
|
-
|
|
21224
|
-
}
|
|
21225
|
-
|
|
21226
|
-
|
|
21227
|
-
|
|
21228
|
-
|
|
21229
|
-
|
|
21230
|
-
}
|
|
21231
|
-
|
|
21556
|
+
timeoutMs: opts.timeoutMs ?? 3e4
|
|
21557
|
+
},
|
|
21558
|
+
path
|
|
21559
|
+
);
|
|
21560
|
+
let text;
|
|
21561
|
+
try {
|
|
21562
|
+
text = await res.text();
|
|
21563
|
+
} catch {
|
|
21564
|
+
throw new ApiError(408, `Tempo esgotado ao falar com a API BePlus (${path}).`);
|
|
21232
21565
|
}
|
|
21233
|
-
const text = await res.text();
|
|
21234
21566
|
let json2;
|
|
21235
21567
|
if (text) {
|
|
21236
21568
|
try {
|
|
@@ -21386,9 +21718,9 @@ async function pollUntilDone(client, generationId, budgetMs, jitterSeed = 0) {
|
|
|
21386
21718
|
}
|
|
21387
21719
|
|
|
21388
21720
|
// src/media.ts
|
|
21389
|
-
import { readFile } from "fs/promises";
|
|
21721
|
+
import { readFile as readFile2, stat as stat2 } from "fs/promises";
|
|
21390
21722
|
import { basename, extname, isAbsolute, resolve } from "path";
|
|
21391
|
-
import { homedir } from "os";
|
|
21723
|
+
import { homedir as homedir2 } from "os";
|
|
21392
21724
|
import { fileURLToPath } from "url";
|
|
21393
21725
|
var MIME_BY_EXT = {
|
|
21394
21726
|
".png": "image/png",
|
|
@@ -21396,82 +21728,207 @@ var MIME_BY_EXT = {
|
|
|
21396
21728
|
".jpeg": "image/jpeg",
|
|
21397
21729
|
".webp": "image/webp",
|
|
21398
21730
|
".gif": "image/gif",
|
|
21731
|
+
".avif": "image/avif",
|
|
21732
|
+
".heic": "image/heic",
|
|
21733
|
+
".heif": "image/heif",
|
|
21399
21734
|
".bmp": "image/bmp",
|
|
21735
|
+
".tif": "image/tiff",
|
|
21736
|
+
".tiff": "image/tiff",
|
|
21400
21737
|
".svg": "image/svg+xml",
|
|
21401
21738
|
".mp4": "video/mp4",
|
|
21402
21739
|
".mov": "video/quicktime",
|
|
21403
21740
|
".webm": "video/webm",
|
|
21404
21741
|
".m4v": "video/x-m4v",
|
|
21742
|
+
".mkv": "video/x-matroska",
|
|
21743
|
+
".mpeg": "video/mpeg",
|
|
21744
|
+
".mpg": "video/mpeg",
|
|
21745
|
+
".avi": "video/x-msvideo",
|
|
21746
|
+
".3gp": "video/3gpp",
|
|
21405
21747
|
".mp3": "audio/mpeg",
|
|
21406
21748
|
".wav": "audio/wav",
|
|
21407
21749
|
".m4a": "audio/mp4",
|
|
21408
21750
|
".aac": "audio/aac",
|
|
21409
21751
|
".ogg": "audio/ogg",
|
|
21752
|
+
".oga": "audio/ogg",
|
|
21753
|
+
".opus": "audio/opus",
|
|
21410
21754
|
".flac": "audio/flac",
|
|
21411
|
-
".
|
|
21755
|
+
".aiff": "audio/aiff",
|
|
21756
|
+
".aif": "audio/aiff",
|
|
21757
|
+
".pdf": "application/pdf",
|
|
21758
|
+
".md": "text/markdown",
|
|
21759
|
+
".txt": "text/plain"
|
|
21412
21760
|
};
|
|
21413
|
-
var
|
|
21761
|
+
var UPLOAD_EXTENSIONS = [
|
|
21762
|
+
"jpg",
|
|
21763
|
+
"jpeg",
|
|
21764
|
+
"png",
|
|
21765
|
+
"gif",
|
|
21766
|
+
"webp",
|
|
21767
|
+
"avif",
|
|
21768
|
+
"heic",
|
|
21769
|
+
"heif",
|
|
21770
|
+
"bmp",
|
|
21771
|
+
"tif",
|
|
21772
|
+
"tiff",
|
|
21773
|
+
"mp4",
|
|
21774
|
+
"webm",
|
|
21775
|
+
"mov",
|
|
21776
|
+
"m4v",
|
|
21777
|
+
"mkv",
|
|
21778
|
+
"mpeg",
|
|
21779
|
+
"mpg",
|
|
21780
|
+
"avi",
|
|
21781
|
+
"flv",
|
|
21782
|
+
"wmv",
|
|
21783
|
+
"3gp",
|
|
21784
|
+
"3gpp",
|
|
21785
|
+
"mp3",
|
|
21786
|
+
"wav",
|
|
21787
|
+
"ogg",
|
|
21788
|
+
"oga",
|
|
21789
|
+
"aac",
|
|
21790
|
+
"flac",
|
|
21791
|
+
"m4a",
|
|
21792
|
+
"opus",
|
|
21793
|
+
"wma",
|
|
21794
|
+
"aiff",
|
|
21795
|
+
"aif",
|
|
21796
|
+
"pdf",
|
|
21797
|
+
"md",
|
|
21798
|
+
"txt",
|
|
21799
|
+
"markdown"
|
|
21800
|
+
];
|
|
21801
|
+
var MAX_UPLOAD_BYTES = 95 * 1024 * 1024;
|
|
21414
21802
|
var UPLOAD_TIMEOUT_MS = 12e4;
|
|
21803
|
+
var DOWNLOAD_TIMEOUT_MS = 12e4;
|
|
21804
|
+
var BEPLUS_STORAGE_HOST = "storage.beplus.academy";
|
|
21415
21805
|
function isRemoteRef(ref) {
|
|
21416
21806
|
return /^https?:\/\//i.test(ref);
|
|
21417
21807
|
}
|
|
21418
21808
|
function toLocalPath(ref) {
|
|
21419
21809
|
if (ref.startsWith("file://")) return fileURLToPath(ref);
|
|
21420
|
-
if (ref === "~") return
|
|
21421
|
-
if (ref.startsWith("~/")) return resolve(
|
|
21810
|
+
if (ref === "~") return homedir2();
|
|
21811
|
+
if (ref.startsWith("~/")) return resolve(homedir2(), ref.slice(2));
|
|
21422
21812
|
return isAbsolute(ref) ? ref : resolve(process.cwd(), ref);
|
|
21423
21813
|
}
|
|
21424
|
-
function
|
|
21425
|
-
return MIME_BY_EXT[extname(
|
|
21814
|
+
function mimeForName(name) {
|
|
21815
|
+
return MIME_BY_EXT[extname(name).toLowerCase()] ?? "application/octet-stream";
|
|
21426
21816
|
}
|
|
21427
|
-
|
|
21817
|
+
var extOf = (name) => extname(name).slice(1).toLowerCase();
|
|
21818
|
+
function mb(bytes) {
|
|
21819
|
+
return (bytes / 1024 / 1024).toFixed(1).replace(".", ",");
|
|
21820
|
+
}
|
|
21821
|
+
function tooLarge(name, bytes) {
|
|
21822
|
+
const size = bytes === null ? "passa" : `tem ${mb(bytes)} MB,`;
|
|
21823
|
+
return new ApiError(
|
|
21824
|
+
413,
|
|
21825
|
+
`"${name}" ${size} acima do teto de 95 MB para subir pela API (o proxy da Cloudflare corta corpo acima de 100 MB antes de chegar no servidor). Comprima ou corte o arquivo (ex.: ffmpeg -i entrada.mp4 -crf 26 saida.mp4) e tente de novo.`
|
|
21826
|
+
);
|
|
21827
|
+
}
|
|
21828
|
+
async function loadLocal(ref) {
|
|
21428
21829
|
const abs = toLocalPath(ref);
|
|
21429
|
-
|
|
21830
|
+
const name = basename(abs);
|
|
21831
|
+
let size;
|
|
21430
21832
|
try {
|
|
21431
|
-
|
|
21833
|
+
size = (await stat2(abs)).size;
|
|
21432
21834
|
} catch {
|
|
21433
21835
|
throw new ApiError(
|
|
21434
21836
|
0,
|
|
21435
21837
|
`Arquivo local n\xE3o encontrado: "${ref}". Passe um caminho v\xE1lido ou uma URL p\xFAblica (http/https).`
|
|
21436
21838
|
);
|
|
21437
21839
|
}
|
|
21438
|
-
|
|
21439
|
-
|
|
21440
|
-
|
|
21441
|
-
|
|
21442
|
-
|
|
21443
|
-
|
|
21444
|
-
}
|
|
21445
|
-
const form = new FormData();
|
|
21446
|
-
form.append("file", new Blob([buf], { type: mimeForPath(abs) }), name);
|
|
21447
|
-
const controller = new AbortController();
|
|
21448
|
-
const timer = setTimeout(() => controller.abort(), UPLOAD_TIMEOUT_MS);
|
|
21840
|
+
if (size > MAX_UPLOAD_BYTES) throw tooLarge(name, size);
|
|
21841
|
+
return { buf: await readFile2(abs), name, mime: mimeForName(abs), localPath: abs };
|
|
21842
|
+
}
|
|
21843
|
+
async function loadRemote(url) {
|
|
21844
|
+
const u = new URL(url);
|
|
21845
|
+
let name = decodeURIComponent(basename(u.pathname)) || "arquivo";
|
|
21449
21846
|
let res;
|
|
21450
21847
|
try {
|
|
21451
|
-
res = await fetch(
|
|
21452
|
-
|
|
21453
|
-
|
|
21454
|
-
|
|
21455
|
-
|
|
21848
|
+
res = await fetch(url, { signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS) });
|
|
21849
|
+
} catch {
|
|
21850
|
+
throw new ApiError(0, `N\xE3o consegui baixar ${url} (rede ou tempo esgotado).`);
|
|
21851
|
+
}
|
|
21852
|
+
if (!res.ok) {
|
|
21853
|
+
await res.body?.cancel().catch(() => {
|
|
21456
21854
|
});
|
|
21855
|
+
throw new ApiError(res.status, `N\xE3o consegui baixar ${url}: a origem respondeu HTTP ${res.status}.`);
|
|
21856
|
+
}
|
|
21857
|
+
const declared = Number(res.headers.get("content-length") ?? NaN);
|
|
21858
|
+
if (Number.isFinite(declared) && declared > MAX_UPLOAD_BYTES) {
|
|
21859
|
+
await res.body?.cancel().catch(() => {
|
|
21860
|
+
});
|
|
21861
|
+
throw tooLarge(name, declared);
|
|
21862
|
+
}
|
|
21863
|
+
const chunks = [];
|
|
21864
|
+
let total = 0;
|
|
21865
|
+
try {
|
|
21866
|
+
const reader = res.body?.getReader();
|
|
21867
|
+
if (reader) {
|
|
21868
|
+
for (; ; ) {
|
|
21869
|
+
const { done, value } = await reader.read();
|
|
21870
|
+
if (done) break;
|
|
21871
|
+
total += value.byteLength;
|
|
21872
|
+
if (total > MAX_UPLOAD_BYTES) {
|
|
21873
|
+
await reader.cancel().catch(() => {
|
|
21874
|
+
});
|
|
21875
|
+
throw tooLarge(name, null);
|
|
21876
|
+
}
|
|
21877
|
+
chunks.push(Buffer.from(value.buffer, value.byteOffset, value.byteLength));
|
|
21878
|
+
}
|
|
21879
|
+
}
|
|
21457
21880
|
} catch (e) {
|
|
21458
|
-
if (e
|
|
21459
|
-
|
|
21881
|
+
if (e instanceof ApiError) throw e;
|
|
21882
|
+
throw new ApiError(0, `O download de ${url} caiu no meio (rede ou tempo esgotado).`);
|
|
21883
|
+
}
|
|
21884
|
+
const buf = Buffer.concat(chunks);
|
|
21885
|
+
const typed = (res.headers.get("content-type") ?? "").split(";")[0].trim().toLowerCase();
|
|
21886
|
+
let mime = mimeForName(name);
|
|
21887
|
+
if (mime === "application/octet-stream" && typed) {
|
|
21888
|
+
const ext = Object.entries(MIME_BY_EXT).find(([, m]) => m === typed)?.[0];
|
|
21889
|
+
if (ext) {
|
|
21890
|
+
name = `${name.replace(/\.$/, "")}${ext}`;
|
|
21891
|
+
mime = typed;
|
|
21460
21892
|
}
|
|
21461
|
-
throw new ApiError(0, `Falha de rede ao subir "${name}" para o R2. Confira BEPLUS_API_URL.`);
|
|
21462
|
-
} finally {
|
|
21463
|
-
clearTimeout(timer);
|
|
21464
21893
|
}
|
|
21465
|
-
|
|
21894
|
+
return { buf, name, mime };
|
|
21895
|
+
}
|
|
21896
|
+
async function uploadBytes(cfg, file) {
|
|
21897
|
+
const { buf, name, mime } = file;
|
|
21898
|
+
if (!UPLOAD_EXTENSIONS.includes(extOf(name))) {
|
|
21899
|
+
throw new ApiError(
|
|
21900
|
+
422,
|
|
21901
|
+
`"${name}" n\xE3o sobe pela rota de arquivos da BePlus: a extens\xE3o n\xE3o est\xE1 na lista aceita (${UPLOAD_EXTENSIONS.join(", ")}). Converta para um desses formatos.`
|
|
21902
|
+
);
|
|
21903
|
+
}
|
|
21904
|
+
if (buf.byteLength > MAX_UPLOAD_BYTES) throw tooLarge(name, buf.byteLength);
|
|
21905
|
+
const form = new FormData();
|
|
21906
|
+
form.append("file", new Blob([buf], { type: mime }), name);
|
|
21907
|
+
const res = await fetchWithAuth(
|
|
21908
|
+
cfg,
|
|
21909
|
+
`${cfg.baseUrl}/api/v1/files/upload`,
|
|
21910
|
+
{ method: "POST", body: form, timeoutMs: UPLOAD_TIMEOUT_MS },
|
|
21911
|
+
`upload de "${name}"`
|
|
21912
|
+
);
|
|
21466
21913
|
let json2;
|
|
21467
|
-
|
|
21468
|
-
|
|
21469
|
-
|
|
21470
|
-
|
|
21471
|
-
}
|
|
21914
|
+
try {
|
|
21915
|
+
const text = await res.text();
|
|
21916
|
+
json2 = text ? JSON.parse(text) : void 0;
|
|
21917
|
+
} catch {
|
|
21472
21918
|
}
|
|
21473
21919
|
if (!res.ok) {
|
|
21474
21920
|
const message = json2?.message || res.statusText || `HTTP ${res.status}`;
|
|
21921
|
+
if (res.status === 413) throw tooLarge(name, buf.byteLength);
|
|
21922
|
+
if (res.status === 403) {
|
|
21923
|
+
throw new ApiError(
|
|
21924
|
+
403,
|
|
21925
|
+
`Sem permiss\xE3o para subir "${name}" (${message}). No login pelo navegador, subir arquivo exige a permiss\xE3o ialab:spend: rode \`beplus-mcp login\` e autorize.`,
|
|
21926
|
+
json2
|
|
21927
|
+
);
|
|
21928
|
+
}
|
|
21929
|
+
if (res.status === 422) {
|
|
21930
|
+
throw new ApiError(422, `O servidor n\xE3o aceitou "${name}" (${message}). Confira o formato do arquivo.`, json2);
|
|
21931
|
+
}
|
|
21475
21932
|
throw new ApiError(res.status, `Upload de "${name}" falhou: ${message}`, json2);
|
|
21476
21933
|
}
|
|
21477
21934
|
const fileUrl = json2?.result?.file_url ?? json2?.file_url;
|
|
@@ -21480,6 +21937,9 @@ async function uploadFile(cfg, ref) {
|
|
|
21480
21937
|
}
|
|
21481
21938
|
return fileUrl;
|
|
21482
21939
|
}
|
|
21940
|
+
async function uploadFile(cfg, ref) {
|
|
21941
|
+
return uploadBytes(cfg, await loadLocal(ref));
|
|
21942
|
+
}
|
|
21483
21943
|
async function resolveRef(cfg, ref) {
|
|
21484
21944
|
if (!ref) return ref;
|
|
21485
21945
|
return isRemoteRef(ref) ? ref : uploadFile(cfg, ref);
|
|
@@ -22395,9 +22855,9 @@ ${list}${flagsLine(status)}${draftHint}` }, ...blocks] };
|
|
|
22395
22855
|
}
|
|
22396
22856
|
|
|
22397
22857
|
// src/probe.ts
|
|
22398
|
-
import { open, stat } from "fs/promises";
|
|
22858
|
+
import { open as open2, stat as stat3 } from "fs/promises";
|
|
22399
22859
|
import { extname as extname2, isAbsolute as isAbsolute2, resolve as resolve2 } from "path";
|
|
22400
|
-
import { homedir as
|
|
22860
|
+
import { homedir as homedir3 } from "os";
|
|
22401
22861
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
22402
22862
|
var IMAGE_EXT = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".webp"]);
|
|
22403
22863
|
var VIDEO_EXT = /* @__PURE__ */ new Set([".mp4", ".mov", ".m4v"]);
|
|
@@ -22409,8 +22869,8 @@ function isRemote(ref) {
|
|
|
22409
22869
|
}
|
|
22410
22870
|
function toLocalPath2(ref) {
|
|
22411
22871
|
if (ref.startsWith("file://")) return fileURLToPath2(ref);
|
|
22412
|
-
if (ref === "~") return
|
|
22413
|
-
if (ref.startsWith("~/")) return resolve2(
|
|
22872
|
+
if (ref === "~") return homedir3();
|
|
22873
|
+
if (ref.startsWith("~/")) return resolve2(homedir3(), ref.slice(2));
|
|
22414
22874
|
return isAbsolute2(ref) ? ref : resolve2(process.cwd(), ref);
|
|
22415
22875
|
}
|
|
22416
22876
|
function kindFromExt(ref) {
|
|
@@ -22421,7 +22881,7 @@ function kindFromExt(ref) {
|
|
|
22421
22881
|
}
|
|
22422
22882
|
async function readAt(ref, offset, len) {
|
|
22423
22883
|
if (!isRemote(ref)) {
|
|
22424
|
-
const fh = await
|
|
22884
|
+
const fh = await open2(toLocalPath2(ref), "r");
|
|
22425
22885
|
try {
|
|
22426
22886
|
const buf = Buffer.alloc(len);
|
|
22427
22887
|
const { bytesRead } = await fh.read(buf, 0, len, offset);
|
|
@@ -22464,7 +22924,7 @@ async function findMoov(ref, fileSize) {
|
|
|
22464
22924
|
}
|
|
22465
22925
|
async function readHead(ref, bytes) {
|
|
22466
22926
|
if (!isRemote(ref)) {
|
|
22467
|
-
const fh = await
|
|
22927
|
+
const fh = await open2(toLocalPath2(ref), "r");
|
|
22468
22928
|
try {
|
|
22469
22929
|
const buf = Buffer.alloc(bytes);
|
|
22470
22930
|
const { bytesRead } = await fh.read(buf, 0, bytes, 0);
|
|
@@ -22542,9 +23002,9 @@ function probeWebp(b) {
|
|
|
22542
23002
|
}
|
|
22543
23003
|
return null;
|
|
22544
23004
|
}
|
|
22545
|
-
function
|
|
23005
|
+
function mp4Info(b) {
|
|
22546
23006
|
let duration3;
|
|
22547
|
-
let
|
|
23007
|
+
let width2 = 0;
|
|
22548
23008
|
let height = 0;
|
|
22549
23009
|
let frames = 0;
|
|
22550
23010
|
let mediaDuration;
|
|
@@ -22586,8 +23046,8 @@ function probeMp4(b) {
|
|
|
22586
23046
|
const rotated = Math.abs(a) < 0.01 && Math.abs(d) < 0.01;
|
|
22587
23047
|
const tw = Math.round(rotated ? h : w);
|
|
22588
23048
|
const th = Math.round(rotated ? w : h);
|
|
22589
|
-
if (tw * th >
|
|
22590
|
-
|
|
23049
|
+
if (tw * th > width2 * height) {
|
|
23050
|
+
width2 = tw;
|
|
22591
23051
|
height = th;
|
|
22592
23052
|
}
|
|
22593
23053
|
}
|
|
@@ -22610,13 +23070,16 @@ function probeMp4(b) {
|
|
|
22610
23070
|
}
|
|
22611
23071
|
};
|
|
22612
23072
|
walk(0, b.length, 0);
|
|
22613
|
-
if (!width || !height) return null;
|
|
22614
23073
|
const dur = duration3 ?? mediaDuration;
|
|
22615
|
-
const fps = dur && frames ? Math.round(frames / dur * 100) / 100 : void 0;
|
|
22616
|
-
return { width, height, duration: dur, fps };
|
|
23074
|
+
const fps = width2 && height && dur && frames ? Math.round(frames / dur * 100) / 100 : void 0;
|
|
23075
|
+
return { width: width2, height, duration: dur, fps };
|
|
23076
|
+
}
|
|
23077
|
+
function probeMp4(b) {
|
|
23078
|
+
const info = mp4Info(b);
|
|
23079
|
+
return info.width && info.height ? info : null;
|
|
22617
23080
|
}
|
|
22618
23081
|
async function fileSizeOf(ref) {
|
|
22619
|
-
if (!isRemote(ref)) return (await
|
|
23082
|
+
if (!isRemote(ref)) return (await stat3(toLocalPath2(ref))).size;
|
|
22620
23083
|
const res = await fetch(ref, { method: "HEAD" });
|
|
22621
23084
|
return Number(res.headers.get("content-length") ?? 0);
|
|
22622
23085
|
}
|
|
@@ -22637,9 +23100,9 @@ async function probeMedia(ref) {
|
|
|
22637
23100
|
}
|
|
22638
23101
|
if (!head.length) throw new ProbeError("Arquivo vazio.");
|
|
22639
23102
|
if (kind === "image") {
|
|
22640
|
-
const
|
|
22641
|
-
if (!
|
|
22642
|
-
return { kind, width:
|
|
23103
|
+
const dim2 = probePng(head) ?? probeJpeg(head) ?? probeWebp(head);
|
|
23104
|
+
if (!dim2) throw new ProbeError("N\xE3o consegui ler as dimens\xF5es da imagem pelo cabe\xE7alho.");
|
|
23105
|
+
return { kind, width: dim2.width, height: dim2.height };
|
|
22643
23106
|
}
|
|
22644
23107
|
let info = probeMp4(head);
|
|
22645
23108
|
if (!info) {
|
|
@@ -22659,6 +23122,124 @@ async function probeMedia(ref) {
|
|
|
22659
23122
|
}
|
|
22660
23123
|
return { kind, width: info.width, height: info.height, duration: info.duration, fps: info.fps };
|
|
22661
23124
|
}
|
|
23125
|
+
function probeGif(b) {
|
|
23126
|
+
if (b.length < 10 || b.toString("ascii", 0, 4) !== "GIF8") return null;
|
|
23127
|
+
return { width: b.readUInt16LE(6), height: b.readUInt16LE(8) };
|
|
23128
|
+
}
|
|
23129
|
+
function probeWav(b) {
|
|
23130
|
+
if (b.length < 12 || b.toString("ascii", 0, 4) !== "RIFF" || b.toString("ascii", 8, 12) !== "WAVE") return null;
|
|
23131
|
+
let byteRate = 0;
|
|
23132
|
+
for (let i = 12; i + 8 <= b.length; ) {
|
|
23133
|
+
const id = b.toString("ascii", i, i + 4);
|
|
23134
|
+
const size = b.readUInt32LE(i + 4);
|
|
23135
|
+
if (id === "fmt " && i + 16 <= b.length) byteRate = b.readUInt32LE(i + 16);
|
|
23136
|
+
if (id === "data") {
|
|
23137
|
+
const bytes = size === 0 || size === 4294967295 || i + 8 + size > b.length ? b.length - i - 8 : size;
|
|
23138
|
+
return byteRate ? bytes / byteRate : null;
|
|
23139
|
+
}
|
|
23140
|
+
i += 8 + size + size % 2;
|
|
23141
|
+
}
|
|
23142
|
+
return null;
|
|
23143
|
+
}
|
|
23144
|
+
function probeFlac(b) {
|
|
23145
|
+
if (b.length < 42 || b.toString("ascii", 0, 4) !== "fLaC" || (b[4] & 127) !== 0) return null;
|
|
23146
|
+
const d = 8;
|
|
23147
|
+
const rate = b[d + 10] << 12 | b[d + 11] << 4 | b[d + 12] >> 4;
|
|
23148
|
+
const total = (b[d + 13] & 15) * 2 ** 32 + b.readUInt32BE(d + 14);
|
|
23149
|
+
return rate && total ? total / rate : null;
|
|
23150
|
+
}
|
|
23151
|
+
var MP3_KBPS = {
|
|
23152
|
+
v1: [0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320],
|
|
23153
|
+
v2: [0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160]
|
|
23154
|
+
};
|
|
23155
|
+
var MP3_RATES = { 3: [44100, 48e3, 32e3], 2: [22050, 24e3, 16e3], 0: [11025, 12e3, 8e3] };
|
|
23156
|
+
function probeMp3(b) {
|
|
23157
|
+
let i = 0;
|
|
23158
|
+
if (b.length > 10 && b.toString("ascii", 0, 3) === "ID3") {
|
|
23159
|
+
const size = (b[6] & 127) << 21 | (b[7] & 127) << 14 | (b[8] & 127) << 7 | b[9] & 127;
|
|
23160
|
+
i = 10 + size + (b[5] & 16 ? 10 : 0);
|
|
23161
|
+
}
|
|
23162
|
+
for (const end = Math.min(b.length - 4, i + 64 * 1024); i < end; i++) {
|
|
23163
|
+
if (b[i] !== 255 || (b[i + 1] & 224) !== 224) continue;
|
|
23164
|
+
const version2 = b[i + 1] >> 3 & 3;
|
|
23165
|
+
const layer = b[i + 1] >> 1 & 3;
|
|
23166
|
+
const kbps = MP3_KBPS[version2 === 3 ? "v1" : "v2"][b[i + 2] >> 4 & 15];
|
|
23167
|
+
const rate = MP3_RATES[version2]?.[b[i + 2] >> 2 & 3];
|
|
23168
|
+
if (version2 === 1 || layer !== 1 || !kbps || !rate) continue;
|
|
23169
|
+
const mono = (b[i + 3] >> 6 & 3) === 3;
|
|
23170
|
+
const spf = version2 === 3 ? 1152 : 576;
|
|
23171
|
+
const side = version2 === 3 ? mono ? 17 : 32 : mono ? 9 : 17;
|
|
23172
|
+
const xing = i + 4 + side;
|
|
23173
|
+
const tag = b.toString("ascii", xing, xing + 4);
|
|
23174
|
+
if ((tag === "Xing" || tag === "Info") && b[xing + 7] & 1) {
|
|
23175
|
+
const flags = b[xing + 7];
|
|
23176
|
+
const lame = xing + 12 + (flags & 2 ? 4 : 0) + (flags & 4 ? 100 : 0) + (flags & 8 ? 4 : 0);
|
|
23177
|
+
const gap = lame + 24 <= b.length && /^(LAME|Lavc|Lavf)/.test(b.toString("ascii", lame, lame + 4)) ? (b[lame + 21] << 4) + (b[lame + 22] >> 4) + ((b[lame + 22] & 15) << 8 | b[lame + 23]) : 0;
|
|
23178
|
+
return (b.readUInt32BE(xing + 8) * spf - gap) / rate;
|
|
23179
|
+
}
|
|
23180
|
+
if (b.toString("ascii", i + 36, i + 40) === "VBRI") return b.readUInt32BE(i + 36 + 14) * spf / rate;
|
|
23181
|
+
const tail = b.length >= 128 && b.toString("ascii", b.length - 128, b.length - 125) === "TAG" ? 128 : 0;
|
|
23182
|
+
return (b.length - i - tail) * 8 / (kbps * 1e3);
|
|
23183
|
+
}
|
|
23184
|
+
return null;
|
|
23185
|
+
}
|
|
23186
|
+
function probeBuffer(b, mime) {
|
|
23187
|
+
const round = (n) => Math.round(n * 1e3) / 1e3;
|
|
23188
|
+
if (mime.startsWith("image/")) {
|
|
23189
|
+
const dim2 = probePng(b) ?? probeJpeg(b) ?? probeWebp(b) ?? probeGif(b);
|
|
23190
|
+
return dim2 ? { width: dim2.width, height: dim2.height } : null;
|
|
23191
|
+
}
|
|
23192
|
+
if (/^(video|audio)\/(mp4|quicktime|x-m4v|x-m4a|aac)$/.test(mime) || probeMp4Head(b)) {
|
|
23193
|
+
const info = mp4Info(b);
|
|
23194
|
+
if (!info.duration && !info.width) return null;
|
|
23195
|
+
const meta = {};
|
|
23196
|
+
if (info.width && info.height && mime.startsWith("video/")) {
|
|
23197
|
+
meta.width = info.width;
|
|
23198
|
+
meta.height = info.height;
|
|
23199
|
+
if (info.fps) meta.fps = info.fps;
|
|
23200
|
+
}
|
|
23201
|
+
if (info.duration) meta.duration = round(info.duration);
|
|
23202
|
+
return meta;
|
|
23203
|
+
}
|
|
23204
|
+
if (mime.startsWith("audio/")) {
|
|
23205
|
+
const seconds = probeWav(b) ?? probeFlac(b) ?? (mime === "audio/mpeg" ? probeMp3(b) : null);
|
|
23206
|
+
return seconds ? { duration: round(seconds) } : null;
|
|
23207
|
+
}
|
|
23208
|
+
return null;
|
|
23209
|
+
}
|
|
23210
|
+
function probeMp4Head(b) {
|
|
23211
|
+
return b.length > 12 && b.toString("ascii", 4, 8) === "ftyp";
|
|
23212
|
+
}
|
|
23213
|
+
async function ffprobeFile(path, timeoutMs = 2e4) {
|
|
23214
|
+
const bin = process.env.BEPLUS_FFPROBE?.trim() || "ffprobe";
|
|
23215
|
+
if (bin === "0") return null;
|
|
23216
|
+
const { execFile } = await import("child_process");
|
|
23217
|
+
const out = await new Promise((done) => {
|
|
23218
|
+
execFile(
|
|
23219
|
+
bin,
|
|
23220
|
+
["-v", "error", "-print_format", "json", "-show_entries", "format=duration:stream=codec_type,width,height,avg_frame_rate", path],
|
|
23221
|
+
{ timeout: timeoutMs, maxBuffer: 1024 * 1024 },
|
|
23222
|
+
(err, stdout) => done(err ? null : stdout)
|
|
23223
|
+
);
|
|
23224
|
+
});
|
|
23225
|
+
if (!out) return null;
|
|
23226
|
+
try {
|
|
23227
|
+
const j = JSON.parse(out);
|
|
23228
|
+
const meta = {};
|
|
23229
|
+
const video = j.streams?.find((s) => s.codec_type === "video" && s.width && s.height);
|
|
23230
|
+
if (video) {
|
|
23231
|
+
meta.width = video.width;
|
|
23232
|
+
meta.height = video.height;
|
|
23233
|
+
const [n, d] = String(video.avg_frame_rate ?? "").split("/").map(Number);
|
|
23234
|
+
if (n && d) meta.fps = Math.round(n / d * 100) / 100;
|
|
23235
|
+
}
|
|
23236
|
+
const duration3 = Number(j.format?.duration);
|
|
23237
|
+
if (Number.isFinite(duration3) && duration3 > 0) meta.duration = Math.round(duration3 * 1e3) / 1e3;
|
|
23238
|
+
return Object.keys(meta).length ? meta : null;
|
|
23239
|
+
} catch {
|
|
23240
|
+
return null;
|
|
23241
|
+
}
|
|
23242
|
+
}
|
|
22662
23243
|
|
|
22663
23244
|
// src/tools/upscale.ts
|
|
22664
23245
|
var IMAGE_MODEL = "topaz/upscale/image/generative";
|
|
@@ -22735,14 +23316,14 @@ function registerUpscaleTools(server, client, cfg) {
|
|
|
22735
23316
|
`"${variant}" n\xE3o \xE9 um modelo de ${isVideo ? "v\xEDdeo" : "imagem"}. Use um destes: ${allowed.join(", ")}.`
|
|
22736
23317
|
);
|
|
22737
23318
|
}
|
|
22738
|
-
let
|
|
23319
|
+
let width2 = args.source_width;
|
|
22739
23320
|
let height = args.source_height;
|
|
22740
23321
|
let duration3 = args.source_duration;
|
|
22741
23322
|
let fps = args.source_fps;
|
|
22742
|
-
if (!
|
|
23323
|
+
if (!width2 || !height || isVideo && !duration3) {
|
|
22743
23324
|
try {
|
|
22744
23325
|
const probed = await probeMedia(args.file);
|
|
22745
|
-
|
|
23326
|
+
width2 = width2 ?? probed.width;
|
|
22746
23327
|
height = height ?? probed.height;
|
|
22747
23328
|
duration3 = duration3 ?? probed.duration;
|
|
22748
23329
|
fps = fps ?? probed.fps;
|
|
@@ -22777,7 +23358,7 @@ function registerUpscaleTools(server, client, cfg) {
|
|
|
22777
23358
|
model: variant,
|
|
22778
23359
|
upscale_factor: factor,
|
|
22779
23360
|
prompt: args.prompt || label,
|
|
22780
|
-
source_width:
|
|
23361
|
+
source_width: width2,
|
|
22781
23362
|
source_height: height,
|
|
22782
23363
|
source_duration: duration3,
|
|
22783
23364
|
source_fps: fps,
|
|
@@ -22833,7 +23414,7 @@ ${footer}`);
|
|
|
22833
23414
|
}
|
|
22834
23415
|
const urls = outputUrls(status);
|
|
22835
23416
|
const list = urls.map((u, i) => `${i + 1}. ${u}`).join("\n") || "(sem URLs)";
|
|
22836
|
-
const saida =
|
|
23417
|
+
const saida = width2 && height ? ` \u2014 sa\xEDda ${width2 * factor} \xD7 ${height * factor}` : "";
|
|
22837
23418
|
const semAudio = isVideo ? "\nO \xE1udio n\xE3o foi mantido (o Topaz descarta a faixa)." : "";
|
|
22838
23419
|
return textResult(
|
|
22839
23420
|
`\u2705 ${isVideo ? "V\xEDdeo" : "Imagem"} melhorado em ${factor}x com ${variant}${saida}.
|
|
@@ -23107,14 +23688,14 @@ Limites simult\xE2neos por usu\xE1rio: imagem=${m.limits.perUserMaxImage}, v\xED
|
|
|
23107
23688
|
},
|
|
23108
23689
|
async (args) => {
|
|
23109
23690
|
try {
|
|
23110
|
-
let
|
|
23691
|
+
let width2 = args.source_width;
|
|
23111
23692
|
let height = args.source_height;
|
|
23112
23693
|
let duration3 = args.source_duration;
|
|
23113
23694
|
let fps = args.source_fps;
|
|
23114
|
-
if (args.file && (!
|
|
23695
|
+
if (args.file && (!width2 || !height)) {
|
|
23115
23696
|
try {
|
|
23116
23697
|
const probed = await probeMedia(args.file);
|
|
23117
|
-
|
|
23698
|
+
width2 = width2 ?? probed.width;
|
|
23118
23699
|
height = height ?? probed.height;
|
|
23119
23700
|
duration3 = duration3 ?? probed.duration;
|
|
23120
23701
|
fps = fps ?? probed.fps;
|
|
@@ -23133,7 +23714,7 @@ Limites simult\xE2neos por usu\xE1rio: imagem=${m.limits.perUserMaxImage}, v\xED
|
|
|
23133
23714
|
quality: args.quality,
|
|
23134
23715
|
upscale_factor: args.upscale_factor,
|
|
23135
23716
|
model_variant: args.model_variant,
|
|
23136
|
-
source_width:
|
|
23717
|
+
source_width: width2,
|
|
23137
23718
|
source_height: height,
|
|
23138
23719
|
source_duration: duration3,
|
|
23139
23720
|
source_fps: fps
|
|
@@ -23468,6 +24049,9 @@ ${calls.map(callLine).join("\n\n")}`);
|
|
|
23468
24049
|
);
|
|
23469
24050
|
}
|
|
23470
24051
|
|
|
24052
|
+
// src/tools/canvas.ts
|
|
24053
|
+
import { createHash } from "crypto";
|
|
24054
|
+
|
|
23471
24055
|
// src/canvas/api.ts
|
|
23472
24056
|
var PINNED_CORE_VERSION = "ca7b3b406184c7f679f555c3a008013197182b23";
|
|
23473
24057
|
function errorRaw(err) {
|
|
@@ -23784,6 +24368,7 @@ function knownPort(kind, side, port) {
|
|
|
23784
24368
|
// src/canvas/core.ts
|
|
23785
24369
|
import { randomBytes, randomUUID } from "crypto";
|
|
23786
24370
|
var SCHEMA_VERSION = 1;
|
|
24371
|
+
var MAX_ENVELOPES_PER_COMMIT = 200;
|
|
23787
24372
|
var MAX_OP_BYTES = 64 * 1024;
|
|
23788
24373
|
var MAX_DATA_URL_BYTES = 8 * 1024;
|
|
23789
24374
|
var CLIENT_ID = `mcp-${randomBytes(6).toString("hex")}`;
|
|
@@ -23812,11 +24397,14 @@ function isValidNode(key, v) {
|
|
|
23812
24397
|
function isValidEdge(key, v) {
|
|
23813
24398
|
return isRecord(v) && hasOnlyKeys(v, EDGE_KEYS) && v.id === key && typeof v.source === "string" && typeof v.sourcePort === "string" && typeof v.target === "string" && typeof v.targetPort === "string" && isJsonBag(v.data) && isStringOrNull(v.createdBy) && isFiniteNumber(v.createdAt);
|
|
23814
24399
|
}
|
|
24400
|
+
var MEASURED_KEY = "__measured";
|
|
23815
24401
|
function checkNodePath(path) {
|
|
23816
24402
|
const segments = path.split(".");
|
|
23817
24403
|
if (segments.some((s) => s.length === 0)) return `caminho inv\xE1lido "${path}"`;
|
|
23818
24404
|
if (segments.some((s) => FORBIDDEN_SEGMENTS.includes(s))) return `segmento proibido em "${path}"`;
|
|
23819
24405
|
const [root, ...rest] = segments;
|
|
24406
|
+
if (root === "data" && rest[0] === MEASURED_KEY)
|
|
24407
|
+
return `data.${MEASURED_KEY} \xE9 o tamanho medido pela tela do Canvas: s\xF3 o Canvas grava`;
|
|
23820
24408
|
if (root === "data" && rest.length >= 1) return null;
|
|
23821
24409
|
if (root === "position" && rest.length === 1 && ["x", "y"].includes(rest[0]) || root === "size" && rest.length === 1 && ["w", "h"].includes(rest[0])) return null;
|
|
23822
24410
|
return `s\xF3 d\xE1 para editar data.*, position.x/y e size.w/h (recebido "${path}")`;
|
|
@@ -23931,6 +24519,152 @@ function removeNodeOps(doc, nodeId) {
|
|
|
23931
24519
|
function batchOf(ops) {
|
|
23932
24520
|
return ops.length === 1 ? ops[0] : { type: "batch", ops };
|
|
23933
24521
|
}
|
|
24522
|
+
var OpTooLargeError = class extends Error {
|
|
24523
|
+
constructor(op, bytes) {
|
|
24524
|
+
super(`opera\xE7\xE3o de ${bytes} bytes`);
|
|
24525
|
+
this.op = op;
|
|
24526
|
+
this.bytes = bytes;
|
|
24527
|
+
this.name = "OpTooLargeError";
|
|
24528
|
+
}
|
|
24529
|
+
op;
|
|
24530
|
+
bytes;
|
|
24531
|
+
};
|
|
24532
|
+
function packEnvelopes(boardId3, ops, actorId, limit = MAX_OP_BYTES - 1024) {
|
|
24533
|
+
const bytes = (v) => Buffer.byteLength(JSON.stringify(v));
|
|
24534
|
+
const overhead = bytes(envelope(boardId3, { type: "batch", ops: [] }, actorId));
|
|
24535
|
+
const out = [];
|
|
24536
|
+
let cur = [];
|
|
24537
|
+
let size = overhead;
|
|
24538
|
+
const flush = () => {
|
|
24539
|
+
if (cur.length) out.push(envelope(boardId3, batchOf(cur), actorId));
|
|
24540
|
+
cur = [];
|
|
24541
|
+
size = overhead;
|
|
24542
|
+
};
|
|
24543
|
+
for (const op of ops) {
|
|
24544
|
+
const b = bytes(op);
|
|
24545
|
+
if (overhead + b > limit) throw new OpTooLargeError(op, b);
|
|
24546
|
+
const next = size + b + (cur.length ? 1 : 0);
|
|
24547
|
+
if (next > limit) flush();
|
|
24548
|
+
size += b + (cur.length ? 1 : 0);
|
|
24549
|
+
cur.push(op);
|
|
24550
|
+
}
|
|
24551
|
+
flush();
|
|
24552
|
+
return out;
|
|
24553
|
+
}
|
|
24554
|
+
|
|
24555
|
+
// src/canvas/layout.ts
|
|
24556
|
+
function readMeasured(node) {
|
|
24557
|
+
const m = node.data[MEASURED_KEY];
|
|
24558
|
+
if (!m || typeof m !== "object" || Array.isArray(m)) return null;
|
|
24559
|
+
const { w, h, at } = m;
|
|
24560
|
+
if (typeof w !== "number" || typeof h !== "number" || !Number.isFinite(w) || !Number.isFinite(h) || w <= 0 || h <= 0) return null;
|
|
24561
|
+
return { w, h, at: typeof at === "string" ? at : null };
|
|
24562
|
+
}
|
|
24563
|
+
var SAME_WIDTH = 2;
|
|
24564
|
+
var WRAP_KINDS = /* @__PURE__ */ new Set(["prompt", "text", "block", "note", "label", "llm", "narration", "copy", "review", "shotlist"]);
|
|
24565
|
+
var SCALE_KINDS = /* @__PURE__ */ new Set(["image", "video", "media"]);
|
|
24566
|
+
var kindOf = (node) => typeof node.data[KIND_FIELD] === "string" ? node.data[KIND_FIELD] : "";
|
|
24567
|
+
function heightAt(kind, baseW, baseH, newW) {
|
|
24568
|
+
if (Math.abs(newW - baseW) <= SAME_WIDTH) return baseH;
|
|
24569
|
+
if (SCALE_KINDS.has(kind) && newW > baseW) return Math.ceil(baseH * newW / baseW);
|
|
24570
|
+
if (WRAP_KINDS.has(kind) && newW < baseW) return Math.ceil(baseH * baseW / newW);
|
|
24571
|
+
return baseH;
|
|
24572
|
+
}
|
|
24573
|
+
function usedSize(node, floorW = node.size.w) {
|
|
24574
|
+
const kind = kindOf(node);
|
|
24575
|
+
const m = readMeasured(node);
|
|
24576
|
+
if (!m) {
|
|
24577
|
+
const h = Math.max(node.size.h, heightAt(kind, node.size.w, node.size.h, floorW));
|
|
24578
|
+
return { w: floorW, h, source: "gravado", at: null, estimated: h !== node.size.h };
|
|
24579
|
+
}
|
|
24580
|
+
const keepsWidth = Math.abs(floorW - node.size.w) <= SAME_WIDTH;
|
|
24581
|
+
return {
|
|
24582
|
+
w: keepsWidth ? Math.max(floorW, m.w) : floorW,
|
|
24583
|
+
h: Math.max(node.size.h, heightAt(kind, m.w, m.h, floorW)),
|
|
24584
|
+
source: "medido",
|
|
24585
|
+
at: m.at,
|
|
24586
|
+
estimated: Math.abs(floorW - m.w) > SAME_WIDTH
|
|
24587
|
+
};
|
|
24588
|
+
}
|
|
24589
|
+
function sizeLabel(node) {
|
|
24590
|
+
const u = usedSize(node);
|
|
24591
|
+
const base = `${Math.round(u.w)}\xD7${Math.round(u.h)} ${u.source}`;
|
|
24592
|
+
if (u.source === "medido" && u.estimated) return `${base} (medido em ${Math.round(readMeasured(node).w)} de largura: altura estimada)`;
|
|
24593
|
+
return base;
|
|
24594
|
+
}
|
|
24595
|
+
var DEFAULT_WIDTHS = { prompt: 1024, image: 560, video: 560, reference: 320, frame: 320, title: 1024 };
|
|
24596
|
+
var DEFAULT_GAP = 80;
|
|
24597
|
+
var FRAME_PORTS = /* @__PURE__ */ new Set(["frame"]);
|
|
24598
|
+
var FEEDS = /* @__PURE__ */ new Set(["prompt", "image", "video"]);
|
|
24599
|
+
var outOf = (doc, id) => Object.values(doc.edges).filter((e) => e.source === id);
|
|
24600
|
+
function roleOf(doc, node, asTitle) {
|
|
24601
|
+
if (asTitle) return "title";
|
|
24602
|
+
const kind = kindOf(node);
|
|
24603
|
+
if (kind === "prompt" || kind === "video") return kind;
|
|
24604
|
+
if (kind !== "media" && kind !== "image") return "other";
|
|
24605
|
+
const feedsFrame = outOf(doc, node.id).some((e) => FRAME_PORTS.has(e.targetPort) && doc.nodes[e.target] && kindOf(doc.nodes[e.target]) === "video");
|
|
24606
|
+
if (feedsFrame) return "frame";
|
|
24607
|
+
return kind === "media" ? "reference" : "image";
|
|
24608
|
+
}
|
|
24609
|
+
function hangsRight(doc, node) {
|
|
24610
|
+
const kind = kindOf(node);
|
|
24611
|
+
if (kind !== "media" && kind !== "image") return false;
|
|
24612
|
+
const out = outOf(doc, node.id);
|
|
24613
|
+
if (!out.length) return kind === "media";
|
|
24614
|
+
return out.some((e) => doc.nodes[e.target] && FEEDS.has(kindOf(doc.nodes[e.target])));
|
|
24615
|
+
}
|
|
24616
|
+
var overlap = (a, b) => a.x < b.x + b.w && b.x < a.x + a.w && a.y < b.y + b.h && b.y < a.y + a.h;
|
|
24617
|
+
function arrangeRows(doc, rows, origin, gap = DEFAULT_GAP, widths = DEFAULT_WIDTHS) {
|
|
24618
|
+
const placed = [];
|
|
24619
|
+
const floorOf = (node, role) => role === "other" ? node.size.w : widths[role];
|
|
24620
|
+
const place = (id, row, asTitle, x, y2, alignRight) => {
|
|
24621
|
+
const node = doc.nodes[id];
|
|
24622
|
+
const role = roleOf(doc, node, asTitle);
|
|
24623
|
+
const floorW = floorOf(node, role);
|
|
24624
|
+
const u = usedSize(node, floorW);
|
|
24625
|
+
const w = Math.ceil(u.w);
|
|
24626
|
+
const h = Math.ceil(u.h);
|
|
24627
|
+
const px = alignRight !== void 0 ? alignRight - w : x;
|
|
24628
|
+
const p = { id, row, role, x: Math.round(px), y: Math.round(y2), w, h, source: u.source, estimated: u.estimated, floorW };
|
|
24629
|
+
placed.push(p);
|
|
24630
|
+
return p;
|
|
24631
|
+
};
|
|
24632
|
+
let y = origin.y;
|
|
24633
|
+
rows.forEach((row, r) => {
|
|
24634
|
+
if (row.title) {
|
|
24635
|
+
const t = place(row.title, r, true, origin.x, y);
|
|
24636
|
+
y = t.y + t.h + Math.round(gap / 2);
|
|
24637
|
+
}
|
|
24638
|
+
const top = y;
|
|
24639
|
+
const leftW = Math.max(0, ...row.left.map((id) => Math.ceil(usedSize(doc.nodes[id], floorOf(doc.nodes[id], roleOf(doc, doc.nodes[id], false))).w)));
|
|
24640
|
+
let leftEnd = top;
|
|
24641
|
+
row.left.forEach((id, i) => {
|
|
24642
|
+
const right2 = hangsRight(doc, doc.nodes[id]);
|
|
24643
|
+
const p = place(id, r, false, origin.x, i === 0 ? top : leftEnd + gap, right2 ? origin.x + leftW : void 0);
|
|
24644
|
+
leftEnd = p.y + p.h;
|
|
24645
|
+
});
|
|
24646
|
+
const rightX = origin.x + (row.left.length ? leftW + gap : 0);
|
|
24647
|
+
let rightEnd = top;
|
|
24648
|
+
row.right.forEach((id, i) => {
|
|
24649
|
+
const p = place(id, r, false, rightX, i === 0 ? top : rightEnd + gap);
|
|
24650
|
+
rightEnd = p.y + p.h;
|
|
24651
|
+
});
|
|
24652
|
+
y = Math.max(leftEnd, rightEnd, top) + gap * 2;
|
|
24653
|
+
});
|
|
24654
|
+
const inner = [];
|
|
24655
|
+
for (let i = 0; i < placed.length; i++) {
|
|
24656
|
+
for (let j = i + 1; j < placed.length; j++) if (overlap(placed[i], placed[j])) inner.push([placed[i].id, placed[j].id]);
|
|
24657
|
+
}
|
|
24658
|
+
const ids = new Set(placed.map((p) => p.id));
|
|
24659
|
+
const others = Object.values(doc.nodes).filter((n) => !ids.has(n.id) && kindOf(n) !== "section").map((n) => ({ id: n.id, x: n.position.x, y: n.position.y, ...usedSize(n) }));
|
|
24660
|
+
const outer = [];
|
|
24661
|
+
for (const p of placed) for (const o of others) if (overlap(p, o)) outer.push([p.id, o.id]);
|
|
24662
|
+
const left = Math.min(origin.x, ...placed.map((p) => p.x));
|
|
24663
|
+
const right = Math.max(origin.x, ...placed.map((p) => p.x + p.w));
|
|
24664
|
+
const below = others.filter((o) => o.x < right && left < o.x + o.w).map((o) => o.y + o.h);
|
|
24665
|
+
const freeOrigin = { x: origin.x, y: below.length ? Math.max(origin.y, Math.ceil(Math.max(...below) + gap * 2)) : origin.y };
|
|
24666
|
+
return { placed, inner, outer, freeOrigin };
|
|
24667
|
+
}
|
|
23934
24668
|
|
|
23935
24669
|
// src/canvas/summary.ts
|
|
23936
24670
|
var MAX_TEXT = 160;
|
|
@@ -23941,6 +24675,7 @@ var HEAVY_KEYS = /* @__PURE__ */ new Set([
|
|
|
23941
24675
|
"main",
|
|
23942
24676
|
"lastFrame",
|
|
23943
24677
|
"sequence",
|
|
24678
|
+
"timeline",
|
|
23944
24679
|
"points",
|
|
23945
24680
|
"extra",
|
|
23946
24681
|
"mentions",
|
|
@@ -23953,8 +24688,14 @@ var HEAVY_KEYS = /* @__PURE__ */ new Set([
|
|
|
23953
24688
|
"settings",
|
|
23954
24689
|
"enabledKeys",
|
|
23955
24690
|
"checks",
|
|
23956
|
-
"versions"
|
|
24691
|
+
"versions",
|
|
24692
|
+
MEASURED_KEY
|
|
23957
24693
|
]);
|
|
24694
|
+
function visibleData(data) {
|
|
24695
|
+
if (!Object.hasOwn(data, MEASURED_KEY)) return data;
|
|
24696
|
+
const { [MEASURED_KEY]: _measured, ...rest } = data;
|
|
24697
|
+
return rest;
|
|
24698
|
+
}
|
|
23958
24699
|
var NAME_KEYS = /* @__PURE__ */ new Set([KIND_FIELD, "label", "nodeTitle"]);
|
|
23959
24700
|
function oneLine(text, max = MAX_TEXT) {
|
|
23960
24701
|
const flat = text.replace(/\s+/g, " ").trim();
|
|
@@ -24007,7 +24748,7 @@ function rowsLines(rows) {
|
|
|
24007
24748
|
function nodeLines(node, run) {
|
|
24008
24749
|
const kind = nodeKind(node);
|
|
24009
24750
|
const spec = kind ? KINDS[kind] : void 0;
|
|
24010
|
-
const head = `- ${node.id} \xB7 ${kind ?? node.type} \xB7 "${oneLine(nodeName(node), 60)}" @(${Math.round(node.position.x)},${Math.round(node.position.y)})`;
|
|
24751
|
+
const head = `- ${node.id} \xB7 ${kind ?? node.type} \xB7 "${oneLine(nodeName(node), 60)}" @(${Math.round(node.position.x)},${Math.round(node.position.y)}) ${sizeLabel(node)}`;
|
|
24011
24752
|
const facts = [];
|
|
24012
24753
|
const extra = [];
|
|
24013
24754
|
const d = node.data;
|
|
@@ -24027,6 +24768,10 @@ function nodeLines(node, run) {
|
|
|
24027
24768
|
facts.push(`${d.rows.length} linha(s)`);
|
|
24028
24769
|
extra.push(...rowsLines(d.rows));
|
|
24029
24770
|
}
|
|
24771
|
+
if (kind === "montage") {
|
|
24772
|
+
const fact = timelineFact(d);
|
|
24773
|
+
if (fact) facts.push(fact);
|
|
24774
|
+
}
|
|
24030
24775
|
const main2 = spec?.main;
|
|
24031
24776
|
if (main2 && typeof d[main2] === "string" && d[main2]) facts.push(`${main2}: "${oneLine(d[main2])}"`);
|
|
24032
24777
|
for (const [key, value] of Object.entries(d)) {
|
|
@@ -24041,6 +24786,18 @@ function nodeLines(node, run) {
|
|
|
24041
24786
|
if (run?.claimedBy) facts.push("rodando agora");
|
|
24042
24787
|
return [facts.length ? `${head} \xB7 ${facts.join(" \xB7 ")}` : head, ...extra];
|
|
24043
24788
|
}
|
|
24789
|
+
function timelineFact(d) {
|
|
24790
|
+
const volume = "musicGainDb/duckingDb n\xE3o valem para ela: o volume fica nos clipes e faixas";
|
|
24791
|
+
if (d.timeline !== void 0) {
|
|
24792
|
+
const legacy = d.sequence !== void 0 ? "; data.sequence \xE9 o legado congelado" : "";
|
|
24793
|
+
return `timeline (v3): ${JSON.stringify(d.timeline).length} caracteres (inteira em canvas_read_node sem path${legacy}; ${volume})`;
|
|
24794
|
+
}
|
|
24795
|
+
const seq = d.sequence;
|
|
24796
|
+
if (!seq || typeof seq !== "object" || Array.isArray(seq)) return null;
|
|
24797
|
+
const plans = Array.isArray(seq.plans) ? seq.plans.length : 0;
|
|
24798
|
+
const clips = seq.audioClips && typeof seq.audioClips === "object" && !Array.isArray(seq.audioClips) ? Object.values(seq.audioClips).reduce((t, list) => t + (Array.isArray(list) ? list.length : 0), 0) : 0;
|
|
24799
|
+
return `sequ\xEAncia (legado, sem data.timeline): ${plans} plano(s), ${clips} clipe(s) de \xE1udio, ${JSON.stringify(seq).length} caracteres (inteira em canvas_read_node sem path; ${volume})`;
|
|
24800
|
+
}
|
|
24044
24801
|
function boardSummary(snap) {
|
|
24045
24802
|
const doc = snap.doc;
|
|
24046
24803
|
const nodes = Object.values(doc.nodes).sort((a, b) => a.position.x - b.position.x || a.position.y - b.position.y);
|
|
@@ -24056,7 +24813,7 @@ function boardSummary(snap) {
|
|
|
24056
24813
|
lines.push(`IA Lab: vinculado${label ? ` a ${String(label)}` : ""}.`);
|
|
24057
24814
|
}
|
|
24058
24815
|
if (doc.meta?.guide) lines.push(`Guia: ${oneLine(doc.meta.guide)}`);
|
|
24059
|
-
lines.push("", "N\xF3s:");
|
|
24816
|
+
lines.push("", "N\xF3s (tamanho: medido = como est\xE1 na tela; gravado = piso, o cart\xE3o pode ser maior):");
|
|
24060
24817
|
if (!nodes.length) lines.push("(vazio)");
|
|
24061
24818
|
for (const n of nodes) lines.push(...nodeLines(n, runs.get(n.id)));
|
|
24062
24819
|
lines.push("", "Liga\xE7\xF5es:");
|
|
@@ -24065,28 +24822,62 @@ function boardSummary(snap) {
|
|
|
24065
24822
|
return lines.join("\n");
|
|
24066
24823
|
}
|
|
24067
24824
|
function nodeDetail(node) {
|
|
24068
|
-
|
|
24825
|
+
let cuts = 0;
|
|
24826
|
+
const strip = (v, depth, path) => {
|
|
24069
24827
|
if (typeof v === "string") {
|
|
24070
24828
|
if (v.startsWith("data:")) return `[data-url ${v.length}b]`;
|
|
24071
|
-
|
|
24829
|
+
if (v.length <= 2e3) return v;
|
|
24830
|
+
cuts++;
|
|
24831
|
+
return `${v.slice(0, 2e3)}\u2026 [+${v.length - 2e3} caracteres: path=${path}]`;
|
|
24072
24832
|
}
|
|
24073
24833
|
if (Array.isArray(v)) {
|
|
24074
|
-
if (depth > 4)
|
|
24075
|
-
|
|
24076
|
-
|
|
24834
|
+
if (depth > 4) {
|
|
24835
|
+
cuts++;
|
|
24836
|
+
return `[${v.length} itens, ${JSON.stringify(v).length} caracteres: path=${path}]`;
|
|
24837
|
+
}
|
|
24838
|
+
const head = v.slice(0, 60).map((x, i) => strip(x, depth + 1, `${path}.${i}`));
|
|
24839
|
+
if (v.length <= 60) return head;
|
|
24840
|
+
cuts++;
|
|
24841
|
+
return [...head, `\u2026 +${v.length - 60} itens: path=${path}`];
|
|
24077
24842
|
}
|
|
24078
24843
|
if (v && typeof v === "object") {
|
|
24079
|
-
if (depth > 4)
|
|
24844
|
+
if (depth > 4) {
|
|
24845
|
+
cuts++;
|
|
24846
|
+
return `{${JSON.stringify(v).length} caracteres: path=${path}}`;
|
|
24847
|
+
}
|
|
24080
24848
|
const out = {};
|
|
24081
24849
|
for (const [k, x] of Object.entries(v)) {
|
|
24082
|
-
|
|
24850
|
+
const at = path ? `${path}.${k}` : k;
|
|
24851
|
+
if (depth === 0 && (k === "points" || k === "sequence" || k === "timeline")) {
|
|
24852
|
+
cuts++;
|
|
24853
|
+
out[k] = `[omitido: ${JSON.stringify(x).length} caracteres: path=${k}]`;
|
|
24854
|
+
} else out[k] = strip(x, depth + 1, at);
|
|
24083
24855
|
}
|
|
24084
24856
|
return out;
|
|
24085
24857
|
}
|
|
24086
24858
|
return v;
|
|
24087
24859
|
};
|
|
24088
|
-
|
|
24089
|
-
|
|
24860
|
+
const json2 = JSON.stringify(strip(visibleData(node.data), 0, ""));
|
|
24861
|
+
const note = cuts ? `
|
|
24862
|
+
(${cuts} corte(s) marcado(s) com path=\u2026: leia inteiro com canvas_read_node e esse path)` : "";
|
|
24863
|
+
return `${node.id} \xB7 ${nodeKind(node) ?? node.type} \xB7 "${nodeName(node)}" \xB7 ${sizeLabel(node)}
|
|
24864
|
+
${json2}${note}`;
|
|
24865
|
+
}
|
|
24866
|
+
var isMeasureNoise = (op) => op.type === "node.set" && typeof op.path === "string" && (op.path === `data.${MEASURED_KEY}` || op.path.startsWith(`data.${MEASURED_KEY}.`));
|
|
24867
|
+
function withoutMeasureNoise(envelopes) {
|
|
24868
|
+
const clean = (op) => {
|
|
24869
|
+
if (op.type === "batch" && Array.isArray(op.ops)) {
|
|
24870
|
+
const ops = op.ops.map((o) => clean(o)).filter((o) => o !== null);
|
|
24871
|
+
return ops.length ? { ...op, ops } : null;
|
|
24872
|
+
}
|
|
24873
|
+
return isMeasureNoise(op) ? null : op;
|
|
24874
|
+
};
|
|
24875
|
+
const out = [];
|
|
24876
|
+
for (const e of envelopes) {
|
|
24877
|
+
const op = clean(e.op);
|
|
24878
|
+
if (op) out.push({ ...e, op });
|
|
24879
|
+
}
|
|
24880
|
+
return out;
|
|
24090
24881
|
}
|
|
24091
24882
|
function changesSince(envelopes, doc) {
|
|
24092
24883
|
const count = /* @__PURE__ */ new Map();
|
|
@@ -24283,8 +25074,8 @@ function registerCanvasCommentTools(server, api, run) {
|
|
|
24283
25074
|
const st = status ?? "open";
|
|
24284
25075
|
const [snap, threads] = await Promise.all([api.snapshot(board_id), api.listComments(board_id, st)]);
|
|
24285
25076
|
const text = commentsSummary(threads, snap.doc, st);
|
|
24286
|
-
const
|
|
24287
|
-
return
|
|
25077
|
+
const open3 = threads.some((t) => !t.resolvedAt);
|
|
25078
|
+
return open3 ? `${text}
|
|
24288
25079
|
|
|
24289
25080
|
Para aplicar: leia o n\xF3 com canvas_read_board (node_ids), edite pelas canvas_* e feche com canvas_resolve_comment dizendo o que fez.` : text;
|
|
24290
25081
|
})
|
|
@@ -24301,8 +25092,8 @@ Para aplicar: leia o n\xF3 com canvas_read_board (node_ids), edite pelas canvas_
|
|
|
24301
25092
|
const thread = await onComment(
|
|
24302
25093
|
() => api.createComment(board_id, { body: text, parentId: comment_id, ...m?.length ? { mentions: m } : {} })
|
|
24303
25094
|
);
|
|
24304
|
-
const
|
|
24305
|
-
return `\u2705 Resposta ${newReplyId(thread)} em ${comment_id}: "${oneLine(text, 120)}". ${
|
|
25095
|
+
const open3 = thread?.resolvedAt ? "A thread est\xE1 resolvida; reabra com canvas_reopen_comment se precisar." : "A thread segue aberta.";
|
|
25096
|
+
return `\u2705 Resposta ${newReplyId(thread)} em ${comment_id}: "${oneLine(text, 120)}". ${open3}`;
|
|
24306
25097
|
})
|
|
24307
25098
|
);
|
|
24308
25099
|
server.registerTool(
|
|
@@ -24397,6 +25188,497 @@ Para aplicar: leia o n\xF3 com canvas_read_board (node_ids), edite pelas canvas_
|
|
|
24397
25188
|
);
|
|
24398
25189
|
}
|
|
24399
25190
|
|
|
25191
|
+
// src/tools/canvas-layout.ts
|
|
25192
|
+
var nodeIdArg = external_exports.string().min(1).max(128);
|
|
25193
|
+
var width = external_exports.number().finite().min(40).max(2e4);
|
|
25194
|
+
var ROLE_TEXT = {
|
|
25195
|
+
title: "t\xEDtulo",
|
|
25196
|
+
prompt: "prompt",
|
|
25197
|
+
image: "imagem",
|
|
25198
|
+
video: "v\xEDdeo",
|
|
25199
|
+
reference: "ref",
|
|
25200
|
+
frame: "frame",
|
|
25201
|
+
other: "outro"
|
|
25202
|
+
};
|
|
25203
|
+
function checkRows(doc, rows) {
|
|
25204
|
+
const seen = /* @__PURE__ */ new Set();
|
|
25205
|
+
for (const [i, row] of rows.entries()) {
|
|
25206
|
+
const ids = [...row.title ? [row.title] : [], ...row.left, ...row.right];
|
|
25207
|
+
if (!ids.length) throw new CanvasToolError(`rows[${i}] est\xE1 vazia: informe title, left ou right.`);
|
|
25208
|
+
for (const id of ids) {
|
|
25209
|
+
const node = doc.nodes[id];
|
|
25210
|
+
if (!node) throw new CanvasToolError(`rows[${i}]: o n\xF3 ${id} n\xE3o existe no board. Releia com canvas_read_board.`);
|
|
25211
|
+
if (node.data[KIND_FIELD] === "section") throw new CanvasToolError(`rows[${i}]: ${id} \xE9 uma Se\xE7\xE3o (fundo), n\xE3o entra no arranjo.`);
|
|
25212
|
+
if (seen.has(id)) throw new CanvasToolError(`O n\xF3 ${id} aparece duas vezes nas linhas: cada n\xF3 entra uma vez s\xF3.`);
|
|
25213
|
+
seen.add(id);
|
|
25214
|
+
}
|
|
25215
|
+
}
|
|
25216
|
+
}
|
|
25217
|
+
function layoutOps(doc, a) {
|
|
25218
|
+
const ops = [];
|
|
25219
|
+
for (const p of a.placed) {
|
|
25220
|
+
const node = doc.nodes[p.id];
|
|
25221
|
+
const set = (path, now, next) => {
|
|
25222
|
+
if (now !== next) ops.push({ type: "node.set", nodeId: p.id, path, value: setValue(next) });
|
|
25223
|
+
};
|
|
25224
|
+
set("position.x", node.position.x, p.x);
|
|
25225
|
+
set("position.y", node.position.y, p.y);
|
|
25226
|
+
set("size.w", node.size.w, p.floorW);
|
|
25227
|
+
}
|
|
25228
|
+
return ops;
|
|
25229
|
+
}
|
|
25230
|
+
function report(doc, a) {
|
|
25231
|
+
const name = (id) => `"${oneLine(nodeName(doc.nodes[id]), 36)}"`;
|
|
25232
|
+
const lines = [];
|
|
25233
|
+
const unmeasured = a.placed.filter((p) => p.source === "gravado");
|
|
25234
|
+
const estimated = a.placed.filter((p) => p.source === "medido" && p.estimated);
|
|
25235
|
+
if (unmeasured.length || estimated.length) {
|
|
25236
|
+
lines.push("A conferir (a altura usada pode n\xE3o ser a da tela):");
|
|
25237
|
+
if (unmeasured.length) {
|
|
25238
|
+
lines.push(
|
|
25239
|
+
`- sem medida da tela (usei o gravado): o cart\xE3o est\xE1 no piso, e a\xED o gravado \xE9 o da tela, ou o board n\xE3o abriu desde a \xFAltima mudan\xE7a, e a\xED pode ser maior: ${unmeasured.map((p) => name(p.id)).join(", ")}`
|
|
25240
|
+
);
|
|
25241
|
+
}
|
|
25242
|
+
if (estimated.length) {
|
|
25243
|
+
const how = estimated.map((p) => `${name(p.id)} (medido com ${Math.round(readMeasured(doc.nodes[p.id]).w)} de largura)`);
|
|
25244
|
+
lines.push(`- altura estimada com folga porque a largura mudou: ${how.join(", ")}`);
|
|
25245
|
+
}
|
|
25246
|
+
lines.push(
|
|
25247
|
+
"Se o board n\xE3o abriu desde a \xFAltima mudan\xE7a, abra (o Canvas mede o cart\xE3o que passa do piso) e rode o mesmo canvas_arrange_rows de novo para fechar sobra ou encosto."
|
|
25248
|
+
);
|
|
25249
|
+
} else {
|
|
25250
|
+
lines.push("Todos os n\xF3s arrumados t\xEAm medida da tela.");
|
|
25251
|
+
}
|
|
25252
|
+
const pairs = (list) => list.map(([x, y]) => `${name(x)} \xD7 ${name(y)}`).join("; ");
|
|
25253
|
+
lines.push(
|
|
25254
|
+
a.inner.length || a.outer.length ? `Sobreposi\xE7\xF5es com os tamanhos usados: ${pairs([...a.inner, ...a.outer])}.` : "Sobreposi\xE7\xF5es com os tamanhos usados: nenhuma."
|
|
25255
|
+
);
|
|
25256
|
+
lines.push('Caixas ([papel] id "nome" @(x,y) largura\xD7altura usada, origem da altura):');
|
|
25257
|
+
const rows = /* @__PURE__ */ new Map();
|
|
25258
|
+
for (const p of a.placed) {
|
|
25259
|
+
const item = `[${ROLE_TEXT[p.role]}] ${p.id} ${name(p.id)} @(${p.x},${p.y}) ${p.w}\xD7${p.h} ${p.source}${p.estimated ? " estimado" : ""}`;
|
|
25260
|
+
rows.set(p.row, [...rows.get(p.row) ?? [], item]);
|
|
25261
|
+
}
|
|
25262
|
+
for (const [r, items] of rows) lines.push(`- linha ${r + 1}: ${items.join(" \xB7 ")}`);
|
|
25263
|
+
const resized = a.placed.filter((p) => p.floorW !== doc.nodes[p.id].size.w);
|
|
25264
|
+
if (resized.length) lines.push(`Largura (size.w): ${resized.map((p) => `${name(p.id)} ${doc.nodes[p.id].size.w}\u2192${p.floorW}`).join(", ")}.`);
|
|
25265
|
+
const titles = a.placed.filter((p) => p.role === "title" && doc.nodes[p.id].data[KIND_FIELD] === "label" && doc.nodes[p.id].data.size !== "titulo");
|
|
25266
|
+
if (titles.length) {
|
|
25267
|
+
lines.push(
|
|
25268
|
+
`T\xEDtulo sem o texto de t\xEDtulo: ${titles.map((p) => name(p.id)).join(", ")}. Troque com canvas_update_node size:"titulo" (o arranjo s\xF3 grava posi\xE7\xE3o e tamanho).`
|
|
25269
|
+
);
|
|
25270
|
+
}
|
|
25271
|
+
return lines.join("\n");
|
|
25272
|
+
}
|
|
25273
|
+
function registerCanvasLayoutTools(server, deps) {
|
|
25274
|
+
const { api, run, edit } = deps;
|
|
25275
|
+
server.registerTool(
|
|
25276
|
+
"canvas_arrange_rows",
|
|
25277
|
+
{
|
|
25278
|
+
title: "Canvas: arrumar em linhas",
|
|
25279
|
+
description: "Arruma n\xF3s em linhas, uma por vers\xE3o (revis\xE3o de imagem) ou por take (anima\xE7\xE3o), de cima para baixo a partir de origin: title em cima; \xE0 esquerda a coluna left (prompt; m\xEDdia/imagem que alimenta o prompt ou o gerador, como a refer\xEAncia e o frame de entrada, fica alinhada \xE0 direita embaixo dele); \xE0 direita a coluna right (gerador) com o topo no do prompt. Qualquer tipo entra em qualquer coluna. Usa o tamanho medido da tela (ou o gravado, avisando) e p\xF5e a largura pelo tipo real do n\xF3: prompt 1024, gerador de imagem 560, de v\xEDdeo 560, refer\xEAncia (m\xEDdia) 320, frame (m\xEDdia/imagem ligada na porta frame do v\xEDdeo) 320, t\xEDtulo 1024. Grava s\xF3 posi\xE7\xE3o e tamanho num passo, sem pedir releitura. Devolve as caixas, as sobreposi\xE7\xF5es com os tamanhos usados e os n\xF3s sem medida (a altura deles pode crescer quando o board abrir: rode de novo depois). Se a \xE1rea encostar em outro n\xF3 do board, n\xE3o grava nada e sugere uma origem livre. dry_run: true s\xF3 calcula.",
|
|
25280
|
+
inputSchema: {
|
|
25281
|
+
board_id: external_exports.string().uuid(),
|
|
25282
|
+
origin: external_exports.object({ x: external_exports.number().finite(), y: external_exports.number().finite() }).describe("Canto de cima \xE0 esquerda da \xE1rea."),
|
|
25283
|
+
rows: external_exports.array(
|
|
25284
|
+
external_exports.object({
|
|
25285
|
+
title: nodeIdArg.optional().describe("N\xF3 do t\xEDtulo da linha (Texto livre)."),
|
|
25286
|
+
left: external_exports.array(nodeIdArg).max(20).optional().describe("Coluna da esquerda, de cima para baixo: prompt, depois a refer\xEAncia."),
|
|
25287
|
+
right: external_exports.array(nodeIdArg).max(20).optional().describe("Coluna da direita: gerador(es).")
|
|
25288
|
+
}).strict()
|
|
25289
|
+
).min(1).max(50),
|
|
25290
|
+
gap: external_exports.number().finite().min(0).max(1e3).optional().describe(`Espa\xE7o entre cart\xF5es (padr\xE3o ${DEFAULT_GAP}); o dobro entre linhas.`),
|
|
25291
|
+
widths: external_exports.object({
|
|
25292
|
+
prompt: width.optional(),
|
|
25293
|
+
image: width.optional(),
|
|
25294
|
+
video: width.optional(),
|
|
25295
|
+
generator: width.optional().describe("Atalho: image e video juntos."),
|
|
25296
|
+
reference: width.optional(),
|
|
25297
|
+
frame: width.optional(),
|
|
25298
|
+
title: width.optional()
|
|
25299
|
+
}).strict().optional().describe("Troca larguras da conven\xE7\xE3o (prompt 1024, image 560, video 560, reference 320, frame 320, title 1024)."),
|
|
25300
|
+
dry_run: external_exports.boolean().optional().describe("true: s\xF3 calcula e mostra, sem gravar.")
|
|
25301
|
+
},
|
|
25302
|
+
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false }
|
|
25303
|
+
},
|
|
25304
|
+
async (args) => run(async () => {
|
|
25305
|
+
const rows = args.rows.map((r) => ({ title: r.title, left: r.left ?? [], right: r.right ?? [] }));
|
|
25306
|
+
const { generator, ...own } = args.widths ?? {};
|
|
25307
|
+
const widths = { ...DEFAULT_WIDTHS, ...generator ? { image: generator, video: generator } : {}, ...own };
|
|
25308
|
+
const gap = args.gap ?? DEFAULT_GAP;
|
|
25309
|
+
const plan = (doc) => {
|
|
25310
|
+
checkRows(doc, rows);
|
|
25311
|
+
const a = arrangeRows(doc, rows, args.origin, gap, widths);
|
|
25312
|
+
return { a, ops: layoutOps(doc, a), text: report(doc, a) };
|
|
25313
|
+
};
|
|
25314
|
+
const count = (ops) => new Set(ops.map((o) => o.type === "node.set" ? o.nodeId : "")).size;
|
|
25315
|
+
const blocked = (a) => `A \xE1rea encosta em n\xF3s que n\xE3o est\xE3o no arranjo. Nada foi gravado. Origem livre sugerida: {"x":${a.freeOrigin.x},"y":${a.freeOrigin.y}} (abaixo de tudo nessa faixa), ou tire esses n\xF3s do caminho.`;
|
|
25316
|
+
if (args.dry_run) {
|
|
25317
|
+
const { a, ops, text: text2 } = plan((await api.snapshot(args.board_id)).doc);
|
|
25318
|
+
const head = `Pr\xE9via, nada gravado: ${ops.length ? `${count(ops)} n\xF3(s) mudariam de lugar ou largura` : "tudo j\xE1 est\xE1 assim"}.`;
|
|
25319
|
+
return [head, ...a.outer.length ? [blocked(a)] : [], text2].join("\n");
|
|
25320
|
+
}
|
|
25321
|
+
let text = "";
|
|
25322
|
+
const done = await edit(
|
|
25323
|
+
args.board_id,
|
|
25324
|
+
async (doc) => {
|
|
25325
|
+
const p = plan(doc);
|
|
25326
|
+
text = p.text;
|
|
25327
|
+
if (p.a.outer.length) throw new CanvasToolError(`${blocked(p.a)}
|
|
25328
|
+
${p.text}`);
|
|
25329
|
+
return {
|
|
25330
|
+
ops: p.ops,
|
|
25331
|
+
targets: [],
|
|
25332
|
+
done: `Arranjo: ${rows.length} linha(s), ${p.a.placed.length} n\xF3(s), ${count(p.ops)} mudaram de lugar ou largura`
|
|
25333
|
+
};
|
|
25334
|
+
},
|
|
25335
|
+
{ split: true, layoutOnly: true }
|
|
25336
|
+
);
|
|
25337
|
+
return `${done}
|
|
25338
|
+
${text}`;
|
|
25339
|
+
})
|
|
25340
|
+
);
|
|
25341
|
+
}
|
|
25342
|
+
|
|
25343
|
+
// src/canvas/upload.ts
|
|
25344
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
25345
|
+
import { basename as basename2, extname as extname3 } from "path";
|
|
25346
|
+
function kindOfMime(mime) {
|
|
25347
|
+
if (mime.startsWith("image/")) return "image";
|
|
25348
|
+
if (mime.startsWith("video/")) return "video";
|
|
25349
|
+
if (mime.startsWith("audio/")) return "audio";
|
|
25350
|
+
return "file";
|
|
25351
|
+
}
|
|
25352
|
+
function withExtension(name, file) {
|
|
25353
|
+
if (!name?.trim()) return file.name;
|
|
25354
|
+
const ext = extname3(file.name);
|
|
25355
|
+
const clean = basename2(name.trim());
|
|
25356
|
+
return ext && extname3(clean).toLowerCase() !== ext.toLowerCase() ? `${clean}${ext}` : clean;
|
|
25357
|
+
}
|
|
25358
|
+
async function uploadMedia(cfg, source, name) {
|
|
25359
|
+
const remote = isRemoteRef(source);
|
|
25360
|
+
const loaded = remote ? await loadRemote(source) : await loadLocal(source);
|
|
25361
|
+
const file = { ...loaded, name: withExtension(name, loaded) };
|
|
25362
|
+
const reused = remote && new URL(source).host === BEPLUS_STORAGE_HOST;
|
|
25363
|
+
const url = reused ? source : await uploadBytes(cfg, file);
|
|
25364
|
+
const kind = kindOfMime(file.mime);
|
|
25365
|
+
let meta = null;
|
|
25366
|
+
let measuredBy = "n\xE3o medido";
|
|
25367
|
+
if (kind !== "file") {
|
|
25368
|
+
meta = probeBuffer(file.buf, file.mime);
|
|
25369
|
+
if (meta) measuredBy = "cabe\xE7alho";
|
|
25370
|
+
else {
|
|
25371
|
+
meta = await ffprobeFile(file.localPath ?? url);
|
|
25372
|
+
if (meta) measuredBy = "ffprobe";
|
|
25373
|
+
}
|
|
25374
|
+
}
|
|
25375
|
+
return {
|
|
25376
|
+
url,
|
|
25377
|
+
name: file.name,
|
|
25378
|
+
mime: file.mime,
|
|
25379
|
+
bytes: file.buf.byteLength,
|
|
25380
|
+
kind,
|
|
25381
|
+
meta: meta ?? {},
|
|
25382
|
+
measuredBy,
|
|
25383
|
+
reused,
|
|
25384
|
+
assetId: `asset_${randomUUID2()}`
|
|
25385
|
+
};
|
|
25386
|
+
}
|
|
25387
|
+
function mediaItem(u) {
|
|
25388
|
+
const item = { assetId: u.assetId, name: u.name, mime: u.mime, size: u.bytes };
|
|
25389
|
+
if (u.meta.width !== void 0) item.width = u.meta.width;
|
|
25390
|
+
if (u.meta.height !== void 0) item.height = u.meta.height;
|
|
25391
|
+
if (u.meta.duration !== void 0) item.duration = u.meta.duration;
|
|
25392
|
+
item.remoteUrl = u.url;
|
|
25393
|
+
return item;
|
|
25394
|
+
}
|
|
25395
|
+
function sequenceAsset(u) {
|
|
25396
|
+
return { assetId: u.assetId, name: u.name, mime: u.mime, size: u.bytes, origin: "imported" };
|
|
25397
|
+
}
|
|
25398
|
+
function libraryItemId(u, mediaNodeId) {
|
|
25399
|
+
return `${mediaNodeId ?? "<id do n\xF3 M\xEDdia>"}|${u.kind}::${u.url}`;
|
|
25400
|
+
}
|
|
25401
|
+
function describeUpload(u) {
|
|
25402
|
+
const parts = [u.mime, `${mb(u.bytes)} MB`];
|
|
25403
|
+
if (u.meta.width && u.meta.height) parts.push(`${u.meta.width}\xD7${u.meta.height}`);
|
|
25404
|
+
if (u.meta.duration !== void 0) parts.push(`${String(u.meta.duration).replace(".", ",")} s`);
|
|
25405
|
+
if (u.meta.fps) parts.push(`${String(u.meta.fps).replace(".", ",")} fps`);
|
|
25406
|
+
const measured = u.kind === "file" ? "" : u.measuredBy === "n\xE3o medido" ? " (dura\xE7\xE3o e dimens\xF5es n\xE3o medidas: formato sem leitor de cabe\xE7alho e sem ffprobe no PATH)" : ` (medido pelo ${u.measuredBy})`;
|
|
25407
|
+
return `"${u.name}" \xB7 ${parts.join(" \xB7 ")}${measured}`;
|
|
25408
|
+
}
|
|
25409
|
+
|
|
25410
|
+
// src/tools/canvas-media.ts
|
|
25411
|
+
var MAX_MEDIA_ITEMS = 60;
|
|
25412
|
+
var itemsOf = (node) => Array.isArray(node.data.items) ? node.data.items : [];
|
|
25413
|
+
function holdsOne(doc, node) {
|
|
25414
|
+
if (node.data.holds === "one") return true;
|
|
25415
|
+
if (node.data.holds === "many") return false;
|
|
25416
|
+
return itemsOf(node).length === 1 && Object.values(doc.edges).some((e) => e.source === node.id);
|
|
25417
|
+
}
|
|
25418
|
+
function needMediaNode(doc, nodeId) {
|
|
25419
|
+
const node = doc.nodes[nodeId];
|
|
25420
|
+
if (!node) throw new CanvasToolError(`N\xF3 ${nodeId} n\xE3o existe no board. Releia com canvas_read_board.`);
|
|
25421
|
+
if (nodeKind(node) !== "media") {
|
|
25422
|
+
throw new CanvasToolError(
|
|
25423
|
+
`O n\xF3 ${nodeId} ("${oneLine(nodeName(node), 40)}") \xE9 ${nodeKind(node) ?? node.type}, n\xE3o M\xEDdia. Passe o id de um n\xF3 media, ou omita node_id para criar um n\xF3 M\xEDdia novo.`
|
|
25424
|
+
);
|
|
25425
|
+
}
|
|
25426
|
+
return node;
|
|
25427
|
+
}
|
|
25428
|
+
function payload(u, nodeId) {
|
|
25429
|
+
const out = { url: u.url, mime: u.mime, bytes: u.bytes };
|
|
25430
|
+
if (u.meta.duration !== void 0) out.duration = u.meta.duration;
|
|
25431
|
+
if (u.meta.width !== void 0) out.width = u.meta.width;
|
|
25432
|
+
if (u.meta.height !== void 0) out.height = u.meta.height;
|
|
25433
|
+
if (u.meta.fps !== void 0) out.fps = u.meta.fps;
|
|
25434
|
+
out.media_item = mediaItem(u);
|
|
25435
|
+
if (u.kind !== "file") {
|
|
25436
|
+
out.sequence_asset = sequenceAsset(u);
|
|
25437
|
+
out.libraryItemId = libraryItemId(u, nodeId);
|
|
25438
|
+
}
|
|
25439
|
+
return JSON.stringify(out);
|
|
25440
|
+
}
|
|
25441
|
+
function sequenceHint(u, nodeId) {
|
|
25442
|
+
if (u.kind === "file") return "Documento: entra no n\xF3 M\xEDdia, n\xE3o na timeline da Montagem.";
|
|
25443
|
+
const lines = [
|
|
25444
|
+
"Num clipe da timeline da Montagem (data.timeline; data.sequence s\xF3 em n\xF3 que ainda n\xE3o migrou): use sequence_asset como `asset` e libraryItemId como est\xE1" + (nodeId ? "." : ", trocando <id do n\xF3 M\xEDdia> pelo id do n\xF3 onde o item ficou.")
|
|
25445
|
+
];
|
|
25446
|
+
if (u.meta.duration !== void 0) {
|
|
25447
|
+
const at30 = Math.floor(u.meta.duration * 30 + 1e-9);
|
|
25448
|
+
lines.push(`Quadros = dura\xE7\xE3o \xD7 fps da timeline, para baixo (ex.: ${at30} a 30 fps).`);
|
|
25449
|
+
}
|
|
25450
|
+
return lines.join(" ");
|
|
25451
|
+
}
|
|
25452
|
+
function registerCanvasMediaTools(server, deps) {
|
|
25453
|
+
const { api, cfg, run, edit, seen, placeFor } = deps;
|
|
25454
|
+
server.registerTool(
|
|
25455
|
+
"canvas_upload_media",
|
|
25456
|
+
{
|
|
25457
|
+
title: "Canvas: subir arquivo",
|
|
25458
|
+
description: "Sobe um arquivo (caminho local ou URL) pela rota de arquivos da BePlus e devolve o item pronto: url, mime, bytes, dura\xE7\xE3o/largura/altura quando \xE9 m\xEDdia, media_item (data.items do n\xF3 M\xEDdia), sequence_asset e libraryItemId (clipe da timeline da Montagem). Com board_id grava no n\xF3 M\xEDdia node_id, ou cria um n\xF3 M\xEDdia novo sem node_id; a\xED exige canvas_read_board nesta sess\xE3o. Teto de 95 MB. N\xE3o gera m\xEDdia nem gasta diamantes.",
|
|
25459
|
+
inputSchema: {
|
|
25460
|
+
source: external_exports.string().trim().min(1).max(2e3).describe("Caminho local (/\u2026, ~/\u2026, file://) ou URL http(s)."),
|
|
25461
|
+
name: external_exports.string().trim().min(1).max(120).optional().describe("Nome do arquivo no Canvas (a extens\xE3o \xE9 mantida)."),
|
|
25462
|
+
board_id: external_exports.string().uuid().optional().describe("Board onde gravar o item (opcional)."),
|
|
25463
|
+
node_id: external_exports.string().min(1).max(128).optional().describe("N\xF3 M\xEDdia que recebe o item. Sem ele, cria um n\xF3 M\xEDdia novo."),
|
|
25464
|
+
label: external_exports.string().trim().min(1).max(120).optional().describe("Nome do n\xF3 M\xEDdia novo (padr\xE3o: nome do arquivo)."),
|
|
25465
|
+
replace: external_exports.boolean().optional().describe("true troca a lista do n\xF3 por este arquivo; false acrescenta. Padr\xE3o: a regra do Canvas (n\xF3 de um arquivo s\xF3, ligado, troca).")
|
|
25466
|
+
},
|
|
25467
|
+
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true }
|
|
25468
|
+
},
|
|
25469
|
+
async (args) => run(async () => {
|
|
25470
|
+
if (!args.board_id && (args.node_id || args.label || args.replace !== void 0)) {
|
|
25471
|
+
throw new CanvasToolError("node_id, label e replace s\xF3 valem com board_id.");
|
|
25472
|
+
}
|
|
25473
|
+
if (args.board_id) {
|
|
25474
|
+
if (!seen.has(args.board_id)) {
|
|
25475
|
+
throw new CanvasToolError("Leia o board com canvas_read_board antes de gravar nele (a leitura vale para a sess\xE3o).");
|
|
25476
|
+
}
|
|
25477
|
+
const snap = await api.snapshot(args.board_id);
|
|
25478
|
+
if (snap.role === "viewer") throw new CanvasToolError("Voc\xEA \xE9 s\xF3 leitor neste board: pe\xE7a ao dono para te dar papel de editor.");
|
|
25479
|
+
if (args.node_id) {
|
|
25480
|
+
const node = needMediaNode(snap.doc, args.node_id);
|
|
25481
|
+
const replacing = args.replace ?? holdsOne(snap.doc, node);
|
|
25482
|
+
if (!replacing && itemsOf(node).length >= MAX_MEDIA_ITEMS) {
|
|
25483
|
+
throw new CanvasToolError(
|
|
25484
|
+
`O n\xF3 "${oneLine(nodeName(node), 40)}" j\xE1 tem ${MAX_MEDIA_ITEMS} arquivos (teto do Canvas). Omita node_id para criar outro n\xF3 M\xEDdia.`
|
|
25485
|
+
);
|
|
25486
|
+
}
|
|
25487
|
+
}
|
|
25488
|
+
}
|
|
25489
|
+
let u;
|
|
25490
|
+
try {
|
|
25491
|
+
u = await uploadMedia(cfg, args.source, args.name);
|
|
25492
|
+
} catch (e) {
|
|
25493
|
+
if (e instanceof ApiError && e.httpStatus !== 401) throw new CanvasToolError(e.message);
|
|
25494
|
+
throw e;
|
|
25495
|
+
}
|
|
25496
|
+
const head = `\u2705 ${u.reused ? "J\xE1 estava no armazenamento da BePlus (n\xE3o subiu de novo)" : "Subiu"}: ${describeUpload(u)}
|
|
25497
|
+
URL: ${u.url}`;
|
|
25498
|
+
if (!args.board_id) {
|
|
25499
|
+
return [head, "", payload(u), "", sequenceHint(u)].join("\n");
|
|
25500
|
+
}
|
|
25501
|
+
const boardId3 = args.board_id;
|
|
25502
|
+
let nodeId = args.node_id;
|
|
25503
|
+
let done;
|
|
25504
|
+
try {
|
|
25505
|
+
done = await edit(boardId3, async (doc) => {
|
|
25506
|
+
const item = mediaItem(u);
|
|
25507
|
+
if (nodeId) {
|
|
25508
|
+
const node = needMediaNode(doc, nodeId);
|
|
25509
|
+
const replacing = args.replace ?? holdsOne(doc, node);
|
|
25510
|
+
const items = replacing ? [item] : [...itemsOf(node), item];
|
|
25511
|
+
if (items.length > MAX_MEDIA_ITEMS) {
|
|
25512
|
+
throw new CanvasToolError(`O n\xF3 j\xE1 tem ${MAX_MEDIA_ITEMS} arquivos (teto do Canvas).`);
|
|
25513
|
+
}
|
|
25514
|
+
const before = itemsOf(node).length;
|
|
25515
|
+
return {
|
|
25516
|
+
ops: [{ type: "node.set", nodeId: node.id, path: "data.items", value: setValue(items) }],
|
|
25517
|
+
targets: [node.id],
|
|
25518
|
+
done: `N\xF3 M\xEDdia "${oneLine(nodeName(node), 40)}" (${node.id}): ` + (replacing ? `arquivo trocado (${before} \u2192 1)` : `arquivo acrescentado, agora com ${items.length}`)
|
|
25519
|
+
};
|
|
25520
|
+
}
|
|
25521
|
+
const spec = KINDS.media;
|
|
25522
|
+
const created = makeNode({
|
|
25523
|
+
type: WORKFLOW_NODE_TYPE,
|
|
25524
|
+
data: { ...spec.data, [KIND_FIELD]: "media", label: args.label ?? u.name, items: [item] },
|
|
25525
|
+
position: placeFor(doc, spec.size),
|
|
25526
|
+
size: spec.size,
|
|
25527
|
+
zIndex: Object.values(doc.nodes).reduce((t, n) => Math.max(t, n.zIndex), 0) + 1,
|
|
25528
|
+
createdBy: await api.me()
|
|
25529
|
+
});
|
|
25530
|
+
nodeId = created.id;
|
|
25531
|
+
return {
|
|
25532
|
+
ops: [{ type: "node.add", nodeId: created.id, node: created }],
|
|
25533
|
+
targets: [],
|
|
25534
|
+
done: `N\xF3 M\xEDdia "${oneLine(nodeName(created), 40)}" criado: ${created.id}`
|
|
25535
|
+
};
|
|
25536
|
+
});
|
|
25537
|
+
} catch (e) {
|
|
25538
|
+
const why = e instanceof CanvasToolError ? e.message : apiErrorToUserMessage(e);
|
|
25539
|
+
throw new CanvasToolError(
|
|
25540
|
+
`${head}
|
|
25541
|
+
Mas o item N\xC3O entrou no board: ${why}
|
|
25542
|
+
N\xE3o suba de novo: releia com canvas_read_board e grave media_item em data.items do n\xF3 M\xEDdia (canvas_update_node com a lista inteira) ou em um n\xF3 novo.
|
|
25543
|
+
${payload(u)}`
|
|
25544
|
+
);
|
|
25545
|
+
}
|
|
25546
|
+
return [head, done, "", payload(u, nodeId), "", sequenceHint(u, nodeId)].join("\n");
|
|
25547
|
+
})
|
|
25548
|
+
);
|
|
25549
|
+
}
|
|
25550
|
+
|
|
25551
|
+
// src/canvas/mentions.ts
|
|
25552
|
+
var VIA_MENTION = "viaMention";
|
|
25553
|
+
var PROMPT_REFS_INPUT = "refs";
|
|
25554
|
+
var PROMPT_MENTION_REFS_INPUT = "mentionRefs";
|
|
25555
|
+
var MENTION_KEYS = ["template", "fields", "mentions"];
|
|
25556
|
+
var VARIABLE_SOURCE = String.raw`\{\{[ \t]*([\p{L}\p{N}_-]+)[ \t]*\}\}`;
|
|
25557
|
+
function extractVariables(text) {
|
|
25558
|
+
const names = /* @__PURE__ */ new Set();
|
|
25559
|
+
for (const m of text.matchAll(new RegExp(VARIABLE_SOURCE, "gu"))) if (m[1]) names.add(m[1]);
|
|
25560
|
+
return [...names];
|
|
25561
|
+
}
|
|
25562
|
+
function allVariableNames(data) {
|
|
25563
|
+
const names = new Set(extractVariables(typeof data.template === "string" ? data.template : ""));
|
|
25564
|
+
const fields = data.fields;
|
|
25565
|
+
if (fields && typeof fields === "object" && !Array.isArray(fields)) {
|
|
25566
|
+
for (const [id, text] of Object.entries(fields)) {
|
|
25567
|
+
if (id !== "" && typeof text === "string" && text !== "") for (const n of extractVariables(text)) names.add(n);
|
|
25568
|
+
}
|
|
25569
|
+
}
|
|
25570
|
+
return [...names];
|
|
25571
|
+
}
|
|
25572
|
+
function normalizeMentions(value) {
|
|
25573
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
25574
|
+
const out = {};
|
|
25575
|
+
for (const [name, entry] of Object.entries(value)) {
|
|
25576
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
25577
|
+
const { node, port } = entry;
|
|
25578
|
+
if (name.trim() !== "" && typeof node === "string" && node !== "" && typeof port === "string" && port !== "") {
|
|
25579
|
+
out[name] = { node, port };
|
|
25580
|
+
}
|
|
25581
|
+
}
|
|
25582
|
+
return out;
|
|
25583
|
+
}
|
|
25584
|
+
function mentionEdgeId(e) {
|
|
25585
|
+
return `mention:${e.source}:${e.sourcePort}>${e.target}:${e.targetPort}`;
|
|
25586
|
+
}
|
|
25587
|
+
var edgeKey = (e) => `${e.source}\0${e.sourcePort}\0${e.target}\0${e.targetPort}`;
|
|
25588
|
+
var isViaMention = (e) => e.data[VIA_MENTION] === true;
|
|
25589
|
+
function reachability(doc) {
|
|
25590
|
+
const adj = /* @__PURE__ */ new Map();
|
|
25591
|
+
const link = (s, t) => adj.set(s, (adj.get(s) ?? /* @__PURE__ */ new Set()).add(t));
|
|
25592
|
+
for (const e of Object.values(doc.edges)) link(e.source, e.target);
|
|
25593
|
+
const reaches = (from, to) => {
|
|
25594
|
+
const seen = /* @__PURE__ */ new Set();
|
|
25595
|
+
const stack = [from];
|
|
25596
|
+
while (stack.length) {
|
|
25597
|
+
for (const next of adj.get(stack.pop()) ?? []) {
|
|
25598
|
+
if (next === to) return true;
|
|
25599
|
+
if (!seen.has(next)) {
|
|
25600
|
+
seen.add(next);
|
|
25601
|
+
stack.push(next);
|
|
25602
|
+
}
|
|
25603
|
+
}
|
|
25604
|
+
}
|
|
25605
|
+
return false;
|
|
25606
|
+
};
|
|
25607
|
+
return { wouldCycle: (s, t) => s === t || reaches(t, s), accept: link };
|
|
25608
|
+
}
|
|
25609
|
+
function originHasPort(doc, origin) {
|
|
25610
|
+
const node = doc.nodes[origin.node];
|
|
25611
|
+
if (!node) return false;
|
|
25612
|
+
const kind = typeof node.data[KIND_FIELD] === "string" ? node.data[KIND_FIELD] : null;
|
|
25613
|
+
if (!kind || !KINDS[kind]) return false;
|
|
25614
|
+
return knownPort(kind, "out", origin.port) !== false;
|
|
25615
|
+
}
|
|
25616
|
+
function mentionEdgeOps(doc, promptIds, actorId, now = Date.now()) {
|
|
25617
|
+
const out = { ops: [], added: [], removed: [], skipped: [] };
|
|
25618
|
+
const reach = reachability(doc);
|
|
25619
|
+
const edges = Object.values(doc.edges);
|
|
25620
|
+
const desired = /* @__PURE__ */ new Map();
|
|
25621
|
+
const managed = [];
|
|
25622
|
+
for (const id of [...new Set(promptIds)]) {
|
|
25623
|
+
const prompt = doc.nodes[id];
|
|
25624
|
+
if (!prompt || prompt.data[KIND_FIELD] !== "prompt") continue;
|
|
25625
|
+
const into = edges.filter((e) => e.target === id);
|
|
25626
|
+
const vars = new Set(allVariableNames(prompt.data));
|
|
25627
|
+
const mentions2 = normalizeMentions(prompt.data.mentions);
|
|
25628
|
+
const mentionPorts = new Set(into.filter(isViaMention).map((e) => e.targetPort));
|
|
25629
|
+
managed.push(...into.filter((e) => isViaMention(e) && e.targetPort !== PROMPT_REFS_INPUT && e.targetPort !== PROMPT_MENTION_REFS_INPUT));
|
|
25630
|
+
for (const port of /* @__PURE__ */ new Set([...vars, ...mentionPorts])) {
|
|
25631
|
+
if (port === PROMPT_REFS_INPUT || port === PROMPT_MENTION_REFS_INPUT) continue;
|
|
25632
|
+
const origin = vars.has(port) ? mentions2[port] : void 0;
|
|
25633
|
+
if (!origin) continue;
|
|
25634
|
+
if (into.some((e) => e.targetPort === port && !isViaMention(e))) {
|
|
25635
|
+
out.skipped.push(`{{${port}}}: a porta j\xE1 recebe uma liga\xE7\xE3o feita \xE0 m\xE3o`);
|
|
25636
|
+
continue;
|
|
25637
|
+
}
|
|
25638
|
+
if (!doc.nodes[origin.node]) {
|
|
25639
|
+
out.skipped.push(`{{${port}}}: o n\xF3 de origem ${origin.node} n\xE3o existe`);
|
|
25640
|
+
continue;
|
|
25641
|
+
}
|
|
25642
|
+
if (!originHasPort(doc, origin)) {
|
|
25643
|
+
out.skipped.push(`{{${port}}}: a porta "${origin.port}" n\xE3o existe em ${origin.node}`);
|
|
25644
|
+
continue;
|
|
25645
|
+
}
|
|
25646
|
+
if (reach.wouldCycle(origin.node, id)) {
|
|
25647
|
+
out.skipped.push(`{{${port}}}: a liga\xE7\xE3o fecharia um ciclo`);
|
|
25648
|
+
continue;
|
|
25649
|
+
}
|
|
25650
|
+
const link = { source: origin.node, sourcePort: origin.port, target: id, targetPort: port };
|
|
25651
|
+
desired.set(edgeKey(link), link);
|
|
25652
|
+
reach.accept(origin.node, id);
|
|
25653
|
+
}
|
|
25654
|
+
}
|
|
25655
|
+
for (const e of managed) {
|
|
25656
|
+
if (desired.has(edgeKey(e))) continue;
|
|
25657
|
+
out.ops.push({ type: "edge.remove", edgeId: e.id });
|
|
25658
|
+
out.removed.push(e);
|
|
25659
|
+
}
|
|
25660
|
+
for (const [key, link] of desired) {
|
|
25661
|
+
if (edges.some((e) => edgeKey(e) === key)) continue;
|
|
25662
|
+
const edgeId = mentionEdgeId(link);
|
|
25663
|
+
out.ops.push({
|
|
25664
|
+
type: "edge.add",
|
|
25665
|
+
edgeId,
|
|
25666
|
+
edge: { id: edgeId, ...link, data: { [VIA_MENTION]: true }, createdBy: actorId, createdAt: now }
|
|
25667
|
+
});
|
|
25668
|
+
out.added.push(link);
|
|
25669
|
+
}
|
|
25670
|
+
return out;
|
|
25671
|
+
}
|
|
25672
|
+
function describeMentionSync(sync, name) {
|
|
25673
|
+
const parts = [];
|
|
25674
|
+
if (sync.added.length) {
|
|
25675
|
+
parts.push(`liga\xE7\xE3o de men\xE7\xE3o criada: ${sync.added.map((l) => `${name(l.source)}.${l.sourcePort} \u2192 {{${l.targetPort}}}`).join(", ")}`);
|
|
25676
|
+
}
|
|
25677
|
+
if (sync.removed.length) parts.push(`liga\xE7\xE3o de men\xE7\xE3o removida: ${sync.removed.map((e) => `{{${e.targetPort}}}`).join(", ")}`);
|
|
25678
|
+
if (sync.skipped.length) parts.push(`men\xE7\xE3o sem liga\xE7\xE3o: ${sync.skipped.join("; ")}`);
|
|
25679
|
+
return parts.length ? ` ${parts.join(". ")}.` : "";
|
|
25680
|
+
}
|
|
25681
|
+
|
|
24400
25682
|
// src/tools/canvas.ts
|
|
24401
25683
|
var REJECT_TEXT = {
|
|
24402
25684
|
"node-missing": "o n\xF3 n\xE3o existe mais (algu\xE9m apagou)",
|
|
@@ -24404,20 +25686,54 @@ var REJECT_TEXT = {
|
|
|
24404
25686
|
"invalid-op": "opera\xE7\xE3o inv\xE1lida ou repetida",
|
|
24405
25687
|
"too-large": "opera\xE7\xE3o grande demais (64 KB) ou com m\xEDdia embutida"
|
|
24406
25688
|
};
|
|
25689
|
+
var READ = "Exige canvas_read_board nesta sess\xE3o (e de novo depois de uma recusa). ";
|
|
25690
|
+
var MENTION_NOTE = 'Prompt: {{var}} no template + data.mentions {var: {node, port}} (o !! de um Bloco \xE9 port "text") j\xE1 cria, no mesmo passo, a liga\xE7\xE3o fina de men\xE7\xE3o que o Canvas desenha; tirar a var ou a men\xE7\xE3o tira a liga\xE7\xE3o. ';
|
|
25691
|
+
var MONTAGE_NOTE = "Montagem: musicGainDb, duckingDb e fadeMs valem s\xF3 para a montagem autom\xE1tica (clipes ligados) e n\xE3o mexem na timeline do editor (data.timeline; data.sequence \xE9 o legado); o volume dela fica nos clipes (gainDb, gainKeyframes, fades) e nas faixas (gainDb de cada faixa, master).";
|
|
25692
|
+
function dataSegments(path) {
|
|
25693
|
+
const p = path?.trim() ?? "";
|
|
25694
|
+
if (!p || p === "data") return [];
|
|
25695
|
+
const segs = (p.startsWith("data.") ? p.slice(5) : p).split(".");
|
|
25696
|
+
if (segs.some((seg) => !seg)) throw new CanvasToolError(`Caminho "${p}" tem segmento vazio (dois pontos seguidos ou ponto na ponta).`);
|
|
25697
|
+
return segs;
|
|
25698
|
+
}
|
|
25699
|
+
function legacySequenceGuard(node, key) {
|
|
25700
|
+
if (key === "sequence" && nodeKind(node) === "montage" && node.data.timeline !== void 0) {
|
|
25701
|
+
throw new CanvasToolError(
|
|
25702
|
+
"Este n\xF3 Montagem j\xE1 grava em data.timeline; data.sequence \xE9 o legado congelado e n\xE3o se escreve mais. Leia a timeline com canvas_read_node e grave por caminho em data.timeline com canvas_patch_node."
|
|
25703
|
+
);
|
|
25704
|
+
}
|
|
25705
|
+
}
|
|
24407
25706
|
var SECTION_Z = -1e3;
|
|
24408
25707
|
var GAP = 80;
|
|
24409
25708
|
var boardId2 = external_exports.string().uuid().describe("Id (uuid) do board, como sai em canvas_list_boards.");
|
|
24410
|
-
var
|
|
25709
|
+
var nodeIdArg2 = external_exports.string().min(1).max(128);
|
|
24411
25710
|
var point = external_exports.object({ x: external_exports.number().finite(), y: external_exports.number().finite() });
|
|
25711
|
+
var LABEL_TEXT_SIZES = ["titulo", "subtitulo", "corpo"];
|
|
25712
|
+
var dim = external_exports.number().finite().min(16).max(2e4);
|
|
25713
|
+
var sizeArg = external_exports.union([external_exports.object({ w: dim.optional(), h: dim.optional() }).strict(), external_exports.enum(LABEL_TEXT_SIZES)]).describe(
|
|
25714
|
+
'{w, h}: caixa do n\xF3 (piso: o cart\xE3o cresce com o conte\xFAdo; um lado s\xF3 vale). "titulo" | "subtitulo" | "corpo": tamanho do texto do Texto livre (label), gravado em data.size.'
|
|
25715
|
+
);
|
|
25716
|
+
var isLayoutOp = (op) => op.type === "batch" ? op.ops.every(isLayoutOp) : op.type === "node.set" && /^(position\.[xy]|size\.[wh])$/.test(op.path);
|
|
25717
|
+
function textSizeFor(kind, size) {
|
|
25718
|
+
if (kind !== "label") {
|
|
25719
|
+
throw new CanvasToolError(
|
|
25720
|
+
`size "${size}" \xE9 o tamanho do texto do Texto livre (label); para ${kind ?? "este n\xF3"} use size {w, h}.`
|
|
25721
|
+
);
|
|
25722
|
+
}
|
|
25723
|
+
return size;
|
|
25724
|
+
}
|
|
25725
|
+
function boxOf(size) {
|
|
25726
|
+
if (size.w === void 0 && size.h === void 0) throw new CanvasToolError("size {w, h}: informe w, h ou os dois.");
|
|
25727
|
+
return size;
|
|
25728
|
+
}
|
|
24412
25729
|
function registerCanvasTools(server, client, cfg) {
|
|
24413
25730
|
const api = new CanvasApi(client, cfg);
|
|
24414
25731
|
const seen = /* @__PURE__ */ new Map();
|
|
24415
25732
|
function fail(e) {
|
|
24416
25733
|
if (e instanceof CanvasToolError || e instanceof CoreMismatchError) return errorResult(e.message);
|
|
25734
|
+
if (e instanceof LoginExpiredError) return errorResult(e.message);
|
|
24417
25735
|
if (e instanceof ApiError && e.httpStatus === 401 && !api.usesPat) {
|
|
24418
|
-
return errorResult(
|
|
24419
|
-
"O acesso pelo navegador expirou ou foi revogado. Rode `beplus-mcp login` de novo e autorize."
|
|
24420
|
-
);
|
|
25736
|
+
return errorResult(`O servidor recusou o acesso pelo navegador (${e.message}). Rode \`beplus-mcp login\` de novo e autorize.`);
|
|
24421
25737
|
}
|
|
24422
25738
|
if (e instanceof ApiError && e.httpStatus === 404) {
|
|
24423
25739
|
return errorResult("Board n\xE3o encontrado, ou voc\xEA n\xE3o \xE9 membro dele. Confira o id em canvas_list_boards.");
|
|
@@ -24431,9 +25747,9 @@ function registerCanvasTools(server, client, cfg) {
|
|
|
24431
25747
|
return fail(e);
|
|
24432
25748
|
}
|
|
24433
25749
|
}
|
|
24434
|
-
async function edit(id, build) {
|
|
25750
|
+
async function edit(id, build, opts = {}) {
|
|
24435
25751
|
const last = seen.get(id);
|
|
24436
|
-
if (last === void 0) {
|
|
25752
|
+
if (last === void 0 && !opts.layoutOnly) {
|
|
24437
25753
|
throw new CanvasToolError("Leia o board com canvas_read_board antes de editar (a leitura vale para a sess\xE3o).");
|
|
24438
25754
|
}
|
|
24439
25755
|
const snap = await api.snapshot(id);
|
|
@@ -24441,10 +25757,11 @@ function registerCanvasTools(server, client, cfg) {
|
|
|
24441
25757
|
const doc = snap.doc;
|
|
24442
25758
|
const { ops, done, targets } = await build(doc, snap);
|
|
24443
25759
|
if (!ops.length) return `Nada a mudar. ${done}`;
|
|
25760
|
+
if (opts.layoutOnly && !ops.every(isLayoutOp)) throw new Error("layout_only com opera\xE7\xE3o fora de posi\xE7\xE3o/tamanho");
|
|
24444
25761
|
let note = "";
|
|
24445
|
-
if (snap.seq > last) {
|
|
25762
|
+
if (!opts.layoutOnly && last !== void 0 && snap.seq > last) {
|
|
24446
25763
|
const since = await api.opsAfter(id, last);
|
|
24447
|
-
const theirs = since
|
|
25764
|
+
const theirs = since === null ? null : withoutMeasureNoise(since.filter((e) => e.clientId !== CLIENT_ID));
|
|
24448
25765
|
if (theirs === null) {
|
|
24449
25766
|
seen.delete(id);
|
|
24450
25767
|
throw new CanvasToolError(
|
|
@@ -24462,19 +25779,65 @@ function registerCanvasTools(server, client, cfg) {
|
|
|
24462
25779
|
if (theirs.length) note = `
|
|
24463
25780
|
Aviso: ${changesSince(theirs, doc)}.`;
|
|
24464
25781
|
}
|
|
25782
|
+
if (opts.split) return commitSplit(id, ops, done, note, !!opts.layoutOnly);
|
|
24465
25783
|
const env = envelope(id, batchOf(ops), await api.me());
|
|
24466
25784
|
const bad = checkEnvelope(env);
|
|
24467
25785
|
if (bad) throw new CanvasToolError(`Edi\xE7\xE3o recusada antes de enviar: ${bad}.`);
|
|
24468
25786
|
const res = await api.commit(id, [env]);
|
|
24469
25787
|
const outcome = res.outcomes.find((o) => o.opId === env.id);
|
|
24470
25788
|
if (!outcome || "rejected" in outcome) {
|
|
24471
|
-
seen.delete(id);
|
|
25789
|
+
if (!opts.layoutOnly) seen.delete(id);
|
|
24472
25790
|
const why = outcome && "rejected" in outcome ? REJECT_TEXT[outcome.rejected] ?? outcome.rejected : "sem resposta do servidor";
|
|
24473
25791
|
throw new CanvasToolError(`O servidor recusou a edi\xE7\xE3o: ${why}. Nada foi aplicado. Releia com canvas_read_board.`);
|
|
24474
25792
|
}
|
|
24475
|
-
seen.set(id, res.seq);
|
|
25793
|
+
if (!opts.layoutOnly) seen.set(id, res.seq);
|
|
24476
25794
|
return `\u2705 ${done} (seq ${res.seq}).${note}`;
|
|
24477
25795
|
}
|
|
25796
|
+
async function commitSplit(id, ops, done, note, layoutOnly = false) {
|
|
25797
|
+
let envs;
|
|
25798
|
+
try {
|
|
25799
|
+
envs = packEnvelopes(id, ops, await api.me());
|
|
25800
|
+
} catch (e) {
|
|
25801
|
+
if (!(e instanceof OpTooLargeError)) throw e;
|
|
25802
|
+
const path = e.op.type === "node.set" ? e.op.path.replace(/^data\./, "") : e.op.type;
|
|
25803
|
+
throw new CanvasToolError(
|
|
25804
|
+
`O valor de ${path} tem ${Math.round(e.bytes / 1024)} KB e n\xE3o cabe num envelope (64 KB). Nada foi enviado: grave por partes menores (um caminho por item, ex.: <cole\xE7\xE3o>.<id>).`
|
|
25805
|
+
);
|
|
25806
|
+
}
|
|
25807
|
+
for (const env of envs) {
|
|
25808
|
+
const bad = checkEnvelope(env);
|
|
25809
|
+
if (bad) throw new CanvasToolError(`Edi\xE7\xE3o recusada antes de enviar: ${bad}. Nada foi enviado.`);
|
|
25810
|
+
}
|
|
25811
|
+
const outcomes = /* @__PURE__ */ new Map();
|
|
25812
|
+
let last = null;
|
|
25813
|
+
for (let i = 0; i < envs.length; i += MAX_ENVELOPES_PER_COMMIT) {
|
|
25814
|
+
const res = await api.commit(id, envs.slice(i, i + MAX_ENVELOPES_PER_COMMIT));
|
|
25815
|
+
for (const o of res.outcomes) outcomes.set(o.opId, o);
|
|
25816
|
+
last = res.seq;
|
|
25817
|
+
}
|
|
25818
|
+
const setNodes = new Set(ops.flatMap((op) => op.type === "batch" ? op.ops : [op]).flatMap((op) => op.type === "node.set" ? [op.nodeId] : []));
|
|
25819
|
+
const pathsOf = (op) => op.type === "batch" ? op.ops.flatMap(pathsOf) : op.type === "node.set" ? [`${setNodes.size > 1 ? `${op.nodeId}:` : ""}${op.path.replace(/^data\./, "")}`] : [op.type];
|
|
25820
|
+
let failed = 0;
|
|
25821
|
+
const lines = envs.map((env, i) => {
|
|
25822
|
+
const paths = pathsOf(env.op);
|
|
25823
|
+
const span = paths.length > 1 ? `${paths[0]} \u2026 ${paths[paths.length - 1]}` : paths[0];
|
|
25824
|
+
const kb = (Buffer.byteLength(JSON.stringify(env)) / 1024).toFixed(1).replace(".", ",");
|
|
25825
|
+
const o = outcomes.get(env.id);
|
|
25826
|
+
const result = o && "seq" in o ? `seq ${o.seq}` : (failed++, `RECUSADO (${o && "rejected" in o ? REJECT_TEXT[o.rejected] ?? o.rejected : "sem resposta do servidor"}): nada deste envelope entrou`);
|
|
25827
|
+
return `- envelope ${i + 1}/${envs.length}: ${paths.length} caminho(s) (${span}), ${kb} KB \u2192 ${result}`;
|
|
25828
|
+
});
|
|
25829
|
+
if (failed) {
|
|
25830
|
+
if (!layoutOnly) seen.delete(id);
|
|
25831
|
+
throw new CanvasToolError(
|
|
25832
|
+
`${done}: ${envs.length - failed} de ${envs.length} envelope(s) entraram, ${failed} recusado(s).
|
|
25833
|
+
${lines.join("\n")}
|
|
25834
|
+
` + (layoutOnly ? "Os aceitos ficam. Rode de novo: posi\xE7\xE3o e tamanho n\xE3o pedem releitura." : "Os aceitos ficam. Releia com canvas_read_board e canvas_read_node e reenvie s\xF3 os caminhos dos envelopes recusados.") + note
|
|
25835
|
+
);
|
|
25836
|
+
}
|
|
25837
|
+
if (last !== null && !layoutOnly) seen.set(id, last);
|
|
25838
|
+
return `\u2705 ${done} em ${envs.length} envelope(s) (seq at\xE9 ${last}).
|
|
25839
|
+
${lines.join("\n")}${note}`;
|
|
25840
|
+
}
|
|
24478
25841
|
function needNode(doc, nodeId) {
|
|
24479
25842
|
const node = doc.nodes[nodeId];
|
|
24480
25843
|
if (!node) throw new CanvasToolError(`N\xF3 ${nodeId} n\xE3o existe no board. Releia com canvas_read_board.`);
|
|
@@ -24525,11 +25888,53 @@ Aviso: ${changesSince(theirs, doc)}.`;
|
|
|
24525
25888
|
const out = {};
|
|
24526
25889
|
for (const [k, v] of Object.entries(raw ?? {})) {
|
|
24527
25890
|
if (k === KIND_FIELD) throw new CanvasToolError("data.kind n\xE3o muda: apague o n\xF3 e crie outro do tipo certo.");
|
|
25891
|
+
if (k === MEASURED_KEY) {
|
|
25892
|
+
throw new CanvasToolError(`data.${MEASURED_KEY} \xE9 o tamanho medido pela tela do Canvas: s\xF3 o Canvas grava. Para mudar a caixa, use size {w, h}.`);
|
|
25893
|
+
}
|
|
24528
25894
|
if (!isJson(v)) throw new CanvasToolError(`data.${k} n\xE3o \xE9 JSON v\xE1lido.`);
|
|
24529
25895
|
out[k] = v;
|
|
24530
25896
|
}
|
|
24531
25897
|
return out;
|
|
24532
25898
|
}
|
|
25899
|
+
function changeOps(node, change) {
|
|
25900
|
+
const ops = [];
|
|
25901
|
+
const patch = parseData(change.data);
|
|
25902
|
+
for (const key of Object.keys(patch)) legacySequenceGuard(node, key);
|
|
25903
|
+
if (change.label) patch.label = change.label;
|
|
25904
|
+
let box;
|
|
25905
|
+
if (typeof change.size === "string") patch.size = textSizeFor(nodeKind(node), change.size);
|
|
25906
|
+
else if (change.size) box = boxOf(change.size);
|
|
25907
|
+
const data = { ...node.data };
|
|
25908
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
25909
|
+
const path = `data.${k}`;
|
|
25910
|
+
if (v === null) {
|
|
25911
|
+
if (Object.hasOwn(node.data, k)) ops.push({ type: "node.set", nodeId: node.id, path, value: unsetValue() });
|
|
25912
|
+
delete data[k];
|
|
25913
|
+
} else if (JSON.stringify(node.data[k]) !== JSON.stringify(v)) {
|
|
25914
|
+
ops.push({ type: "node.set", nodeId: node.id, path, value: setValue(v) });
|
|
25915
|
+
data[k] = v;
|
|
25916
|
+
}
|
|
25917
|
+
}
|
|
25918
|
+
const set = (path, now, next) => {
|
|
25919
|
+
if (next !== void 0 && next !== now) ops.push({ type: "node.set", nodeId: node.id, path, value: setValue(next) });
|
|
25920
|
+
};
|
|
25921
|
+
set("position.x", node.position.x, change.position?.x);
|
|
25922
|
+
set("position.y", node.position.y, change.position?.y);
|
|
25923
|
+
set("size.w", node.size.w, box?.w);
|
|
25924
|
+
set("size.h", node.size.h, box?.h);
|
|
25925
|
+
const keys = ops.map((o) => o.type === "node.set" ? o.path.replace(/^data\./, "") : "");
|
|
25926
|
+
return { ops, keys, data, dataKeys: Object.keys(patch) };
|
|
25927
|
+
}
|
|
25928
|
+
async function mentionOps(doc, changed, newEdges = []) {
|
|
25929
|
+
const prompts = changed.filter((c) => nodeKind(c.node) === "prompt" && c.keys.some((k) => MENTION_KEYS.includes(k)));
|
|
25930
|
+
if (!prompts.length) return { ops: [], note: "" };
|
|
25931
|
+
const after = { ...doc, nodes: { ...doc.nodes }, edges: { ...doc.edges } };
|
|
25932
|
+
for (const c of changed) after.nodes[c.node.id] = { ...c.node, data: c.data };
|
|
25933
|
+
for (const e of newEdges) after.edges[e.id] = e;
|
|
25934
|
+
const sync = mentionEdgeOps(after, prompts.map((c) => c.node.id), await api.me());
|
|
25935
|
+
const name = (id) => after.nodes[id] ? `"${oneLine(nodeName(after.nodes[id]), 40)}"` : id;
|
|
25936
|
+
return { ops: sync.ops, note: describeMentionSync(sync, name) };
|
|
25937
|
+
}
|
|
24533
25938
|
server.registerTool(
|
|
24534
25939
|
"canvas_list_boards",
|
|
24535
25940
|
{
|
|
@@ -24548,10 +25953,10 @@ Aviso: ${changesSince(theirs, doc)}.`;
|
|
|
24548
25953
|
"canvas_read_board",
|
|
24549
25954
|
{
|
|
24550
25955
|
title: "Canvas: ler board",
|
|
24551
|
-
description:
|
|
25956
|
+
description: 'L\xEA um board: n\xF3s (id, tipo, nome, posi\xE7\xE3o, tamanho, campos principais), liga\xE7\xF5es e v\xEDnculo com o IA Lab, sem m\xEDdia. Tamanho "medido" \xE9 o da tela; "gravado" \xE9 o piso (o cart\xE3o cresce com o conte\xFAdo). Obrigat\xF3rio antes de editar (vale para a sess\xE3o). node_ids devolve o data desses n\xF3s, com cada corte marcado (path=\u2026); o valor inteiro (ex.: data.sequence da Montagem) sai no canvas_read_node.',
|
|
24552
25957
|
inputSchema: {
|
|
24553
25958
|
board_id: boardId2,
|
|
24554
|
-
node_ids: external_exports.array(
|
|
25959
|
+
node_ids: external_exports.array(nodeIdArg2).max(20).optional().describe("N\xF3s para ver o data (sem blobs, cortes marcados).")
|
|
24555
25960
|
},
|
|
24556
25961
|
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
24557
25962
|
},
|
|
@@ -24566,6 +25971,65 @@ Aviso: ${changesSince(theirs, doc)}.`;
|
|
|
24566
25971
|
return parts.join("\n");
|
|
24567
25972
|
})
|
|
24568
25973
|
);
|
|
25974
|
+
server.registerTool(
|
|
25975
|
+
"canvas_read_node",
|
|
25976
|
+
{
|
|
25977
|
+
title: "Canvas: ler n\xF3 inteiro",
|
|
25978
|
+
description: 'Devolve o data de UM n\xF3 sem corte nenhum, em JSON compacto, para conferir e fazer diff. Na Montagem, sem path, vem a timeline do editor: data.timeline, ou data.sequence (legado) quando o n\xF3 ainda n\xE3o tem timeline, e o cabe\xE7alho diz qual veio. path escolhe um peda\xE7o ("items" da M\xEDdia, "timeline.meta"); "data" traz o data todo. Diz o tamanho total e o sha256; acima de max_chars vem em partes expl\xEDcitas (offset). N\xE3o substitui o canvas_read_board, que continua obrigat\xF3rio antes de editar. ' + MONTAGE_NOTE,
|
|
25979
|
+
inputSchema: {
|
|
25980
|
+
board_id: boardId2,
|
|
25981
|
+
node_id: nodeIdArg2,
|
|
25982
|
+
path: external_exports.string().trim().max(200).optional().describe('Caminho dentro do data, com pontos (ex.: "timeline.meta", "items.0"). "data" = o data todo.'),
|
|
25983
|
+
offset: external_exports.number().int().min(0).optional().describe("In\xEDcio da parte, em caracteres (padr\xE3o 0)."),
|
|
25984
|
+
max_chars: external_exports.number().int().min(1e3).max(6e4).optional().describe("Tamanho da parte (padr\xE3o 40000).")
|
|
25985
|
+
},
|
|
25986
|
+
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
25987
|
+
},
|
|
25988
|
+
async ({ board_id, node_id, path, offset, max_chars }) => run(async () => {
|
|
25989
|
+
const snap = await api.snapshot(board_id);
|
|
25990
|
+
const node = snap.doc.nodes[node_id];
|
|
25991
|
+
if (!node) throw new CanvasToolError(`N\xF3 ${node_id} n\xE3o existe no board. Releia com canvas_read_board.`);
|
|
25992
|
+
let value = visibleData(node.data);
|
|
25993
|
+
let segments = dataSegments(path);
|
|
25994
|
+
if (segments[0] === MEASURED_KEY) {
|
|
25995
|
+
throw new CanvasToolError(`data.${MEASURED_KEY} \xE9 interno do Canvas (tamanho medido da tela): ele sai no cabe\xE7alho desta leitura.`);
|
|
25996
|
+
}
|
|
25997
|
+
let which = "";
|
|
25998
|
+
if (!path?.trim() && nodeKind(node) === "montage") {
|
|
25999
|
+
if (node.data.timeline !== void 0) {
|
|
26000
|
+
segments = ["timeline"];
|
|
26001
|
+
which = " (a timeline do editor, formato v3)";
|
|
26002
|
+
} else if (node.data.sequence !== void 0) {
|
|
26003
|
+
segments = ["sequence"];
|
|
26004
|
+
which = " (legado: este n\xF3 ainda n\xE3o tem data.timeline)";
|
|
26005
|
+
} else which = " (sem timeline nem sequence: o data todo)";
|
|
26006
|
+
} else if (segments[0] === "sequence" && nodeKind(node) === "montage" && node.data.timeline !== void 0) {
|
|
26007
|
+
which = " (LEGADO congelado: o editor l\xEA data.timeline)";
|
|
26008
|
+
}
|
|
26009
|
+
for (const [i, seg] of segments.entries()) {
|
|
26010
|
+
const here = value;
|
|
26011
|
+
value = Array.isArray(here) ? here[Number(seg)] : here && typeof here === "object" ? here[seg] : void 0;
|
|
26012
|
+
if (value === void 0) {
|
|
26013
|
+
const at2 = segments.slice(0, i).join(".");
|
|
26014
|
+
const keys = Array.isArray(here) ? `\xEDndices 0 a ${here.length - 1}` : here && typeof here === "object" ? Object.keys(here).join(", ") : "\u2014";
|
|
26015
|
+
throw new CanvasToolError(`"${seg}" n\xE3o existe em data${at2 ? `.${at2}` : ""}. Existe: ${keys || "\u2014"}.`);
|
|
26016
|
+
}
|
|
26017
|
+
}
|
|
26018
|
+
const json2 = JSON.stringify(value);
|
|
26019
|
+
const total = json2.length;
|
|
26020
|
+
const from = Math.min(offset ?? 0, total);
|
|
26021
|
+
const size = max_chars ?? 4e4;
|
|
26022
|
+
const to = Math.min(from + size, total);
|
|
26023
|
+
const hash = createHash("sha256").update(json2).digest("hex").slice(0, 12);
|
|
26024
|
+
const where = `data${segments.length ? `.${segments.join(".")}` : ""}`;
|
|
26025
|
+
const at = readMeasured(node)?.at;
|
|
26026
|
+
const head = `${node.id} \xB7 ${nodeKind(node) ?? node.type} \xB7 "${oneLine(nodeName(node), 60)}" \xB7 board seq ${snap.seq} \xB7 tamanho ${sizeLabel(node)}${at ? ` \xB7 medido em ${at}` : ""} \xB7 ${where}${which}: ${total} caracteres (JSON compacto) \xB7 sha256 ${hash}`;
|
|
26027
|
+
const part = from === 0 && to === total ? "Inteiro, abaixo." : `Parte: caracteres ${from} a ${to} de ${total}. ${to < total ? `Falta o resto: chame de novo com offset=${to}.` : "Esta \xE9 a \xFAltima parte."}`;
|
|
26028
|
+
return `${head}
|
|
26029
|
+
${part}
|
|
26030
|
+
${json2.slice(from, to)}`;
|
|
26031
|
+
})
|
|
26032
|
+
);
|
|
24569
26033
|
server.registerTool(
|
|
24570
26034
|
"canvas_create_board",
|
|
24571
26035
|
{
|
|
@@ -24620,15 +26084,16 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
24620
26084
|
"canvas_add_node",
|
|
24621
26085
|
{
|
|
24622
26086
|
title: "Canvas: adicionar n\xF3",
|
|
24623
|
-
description: `Adiciona um n\xF3 (n\xE3o executa). kind: ${kindList()}. data completa o padr\xE3o do tipo; label d\xE1 o nome. Sem position, nasce ao lado do n\xF3 ligado ou \xE0 direita do board. inputs/outputs j\xE1 ligam o n\xF3 no mesmo passo
|
|
26087
|
+
description: `Adiciona um n\xF3 (n\xE3o executa). ${READ}kind: ${kindList()}. data completa o padr\xE3o do tipo; label d\xE1 o nome. Sem position, nasce ao lado do n\xF3 ligado ou \xE0 direita do board. inputs/outputs j\xE1 ligam o n\xF3 no mesmo passo. ` + MENTION_NOTE + MONTAGE_NOTE,
|
|
24624
26088
|
inputSchema: {
|
|
24625
26089
|
board_id: boardId2,
|
|
24626
26090
|
kind: external_exports.string().min(1).max(40),
|
|
24627
26091
|
label: external_exports.string().trim().min(1).max(120).optional().describe("Nome do cart\xE3o (data.label)."),
|
|
24628
26092
|
data: external_exports.record(external_exports.unknown()).optional().describe("Campos do data. Ex.: narration {blocks:[{id,text}]}, text {text}, prompt {template}."),
|
|
24629
26093
|
position: point.optional(),
|
|
24630
|
-
|
|
24631
|
-
|
|
26094
|
+
size: sizeArg.optional(),
|
|
26095
|
+
inputs: external_exports.array(external_exports.object({ from: nodeIdArg2, from_port: external_exports.string().min(1), to_port: external_exports.string().min(1) })).max(20).optional().describe("Liga\xE7\xF5es que CHEGAM no n\xF3 novo: from.from_port \u2192 novo.to_port."),
|
|
26096
|
+
outputs: external_exports.array(external_exports.object({ from_port: external_exports.string().min(1), to: nodeIdArg2, to_port: external_exports.string().min(1) })).max(20).optional().describe("Liga\xE7\xF5es que SAEM do n\xF3 novo: novo.from_port \u2192 to.to_port.")
|
|
24632
26097
|
},
|
|
24633
26098
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false }
|
|
24634
26099
|
},
|
|
@@ -24639,10 +26104,16 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
24639
26104
|
const me = await api.me();
|
|
24640
26105
|
const data = { ...spec.data, ...parseData(args.data), [KIND_FIELD]: args.kind };
|
|
24641
26106
|
if (args.label) data.label = args.label;
|
|
26107
|
+
let box = spec.size;
|
|
26108
|
+
if (typeof args.size === "string") data.size = textSizeFor(args.kind, args.size);
|
|
26109
|
+
else if (args.size) {
|
|
26110
|
+
const b = boxOf(args.size);
|
|
26111
|
+
box = { w: b.w ?? spec.size.w, h: b.h ?? spec.size.h };
|
|
26112
|
+
}
|
|
24642
26113
|
const near = args.inputs?.[0] ? doc.nodes[args.inputs[0].from] : args.outputs?.[0] ? doc.nodes[args.outputs[0].to] : void 0;
|
|
24643
|
-
const position = args.position ?? placeFor(doc,
|
|
26114
|
+
const position = args.position ?? placeFor(doc, box, near, args.inputs?.[0] ? "right" : "left");
|
|
24644
26115
|
const zIndex = args.kind === "section" ? SECTION_Z : Object.values(doc.nodes).reduce((t, n) => Math.max(t, n.zIndex), 0) + 1;
|
|
24645
|
-
const node = makeNode({ type: WORKFLOW_NODE_TYPE, data, position, size:
|
|
26116
|
+
const node = makeNode({ type: WORKFLOW_NODE_TYPE, data, position, size: box, zIndex, createdBy: me });
|
|
24646
26117
|
const links = [
|
|
24647
26118
|
...(args.inputs ?? []).map((l) => ({ source: l.from, sourcePort: l.from_port, target: node.id, targetPort: l.to_port })),
|
|
24648
26119
|
...(args.outputs ?? []).map((l) => ({ source: node.id, sourcePort: l.from_port, target: l.to, targetPort: l.to_port }))
|
|
@@ -24656,10 +26127,12 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
24656
26127
|
}
|
|
24657
26128
|
}
|
|
24658
26129
|
const edges = edgeOps(doc, links, me, /* @__PURE__ */ new Set([node.id]));
|
|
26130
|
+
const drawn = edges.ops.flatMap((op) => op.type === "edge.add" ? [op.edge] : []);
|
|
26131
|
+
const mention = await mentionOps(doc, [{ node, data: node.data, keys: Object.keys(args.data ?? {}) }], drawn);
|
|
24659
26132
|
return {
|
|
24660
|
-
ops: [{ type: "node.add", nodeId: node.id, node }, ...edges.ops],
|
|
26133
|
+
ops: [{ type: "node.add", nodeId: node.id, node }, ...edges.ops, ...mention.ops],
|
|
24661
26134
|
targets: links.map((l) => l.source === node.id ? l.target : l.source),
|
|
24662
|
-
done: `N\xF3 ${args.kind} "${nodeName(node)}" criado: ${node.id}${edges.ops.length ? ` com ${edges.ops.length} liga\xE7\xE3o(\xF5es)` : ""}.${edges.warn}`
|
|
26135
|
+
done: `N\xF3 ${args.kind} "${nodeName(node)}" criado: ${node.id}${edges.ops.length ? ` com ${edges.ops.length} liga\xE7\xE3o(\xF5es)` : ""}.${edges.warn}${mention.note}`
|
|
24663
26136
|
};
|
|
24664
26137
|
})
|
|
24665
26138
|
)
|
|
@@ -24668,49 +26141,191 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
24668
26141
|
"canvas_update_node",
|
|
24669
26142
|
{
|
|
24670
26143
|
title: "Canvas: editar n\xF3",
|
|
24671
|
-
description:
|
|
26144
|
+
description: `Muda campos do data de um n\xF3, chave a chave (null apaga a chave), sem executar. ${READ}label renomeia; position move; size {w, h} muda a caixa (piso: o cart\xE3o cresce com o conte\xFAdo). N\xE3o troca o tipo. Cada chave \xE9 gravada inteira: leia antes com canvas_read_node e mande o valor completo j\xE1 revisado, para n\xE3o apagar o que outra pessoa escreveu. Para mudar partes de uma estrutura grande (clipes da timeline), use canvas_patch_node, por caminho; v\xE1rios n\xF3s de uma vez, canvas_update_nodes. ` + MENTION_NOTE + MONTAGE_NOTE,
|
|
24672
26145
|
inputSchema: {
|
|
24673
26146
|
board_id: boardId2,
|
|
24674
|
-
node_id:
|
|
26147
|
+
node_id: nodeIdArg2,
|
|
24675
26148
|
data: external_exports.record(external_exports.unknown()).optional().describe("Chaves de data a gravar. Valor null apaga a chave."),
|
|
24676
26149
|
label: external_exports.string().trim().min(1).max(120).optional(),
|
|
24677
|
-
position: point.optional()
|
|
26150
|
+
position: point.optional(),
|
|
26151
|
+
size: sizeArg.optional()
|
|
24678
26152
|
},
|
|
24679
26153
|
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false }
|
|
24680
26154
|
},
|
|
24681
26155
|
async (args) => run(
|
|
24682
26156
|
() => edit(args.board_id, async (doc) => {
|
|
24683
26157
|
const node = needNode(doc, args.node_id);
|
|
24684
|
-
const
|
|
24685
|
-
const
|
|
24686
|
-
|
|
24687
|
-
|
|
24688
|
-
|
|
24689
|
-
|
|
24690
|
-
|
|
24691
|
-
} else if (JSON.stringify(node.data[k]) !== JSON.stringify(v)) {
|
|
24692
|
-
ops.push({ type: "node.set", nodeId: node.id, path, value: setValue(v) });
|
|
24693
|
-
}
|
|
24694
|
-
}
|
|
24695
|
-
if (args.position) {
|
|
24696
|
-
ops.push({ type: "node.set", nodeId: node.id, path: "position.x", value: setValue(args.position.x) });
|
|
24697
|
-
ops.push({ type: "node.set", nodeId: node.id, path: "position.y", value: setValue(args.position.y) });
|
|
24698
|
-
}
|
|
24699
|
-
const keys = ops.map((o) => o.type === "node.set" ? o.path.replace(/^data\./, "") : "").join(", ");
|
|
24700
|
-
return { ops, targets: [node.id], done: `N\xF3 "${nodeName(node)}" atualizado: ${keys || "nada mudou"}` };
|
|
26158
|
+
const c = changeOps(node, args);
|
|
26159
|
+
const mention = await mentionOps(doc, [{ node, data: c.data, keys: c.dataKeys }]);
|
|
26160
|
+
return {
|
|
26161
|
+
ops: [...c.ops, ...mention.ops],
|
|
26162
|
+
targets: [node.id],
|
|
26163
|
+
done: `N\xF3 "${nodeName(node)}" atualizado: ${c.keys.join(", ") || "nada mudou"}${mention.note}`
|
|
26164
|
+
};
|
|
24701
26165
|
})
|
|
24702
26166
|
)
|
|
24703
26167
|
);
|
|
26168
|
+
server.registerTool(
|
|
26169
|
+
"canvas_update_nodes",
|
|
26170
|
+
{
|
|
26171
|
+
title: "Canvas: editar v\xE1rios n\xF3s",
|
|
26172
|
+
description: 'Muda v\xE1rios n\xF3s num passo s\xF3, cada um como no canvas_update_node (position, size, label, data com null apagando). layout_only: true aceita s\xF3 position e size {w, h}, n\xE3o exige leitura e n\xE3o recusa por "outra pessoa mexeu" (nesses dois campos vale quem grava por \xFAltimo). Sem layout_only, exige canvas_read_board nesta sess\xE3o e recusa se outra pessoa mexeu em algum desses n\xF3s. Quebra em envelopes de at\xE9 64 KB e relata cada um. Para arrumar linhas inteiras (t\xEDtulo, prompt, refer\xEAncia, gerador), use canvas_arrange_rows.',
|
|
26173
|
+
inputSchema: {
|
|
26174
|
+
board_id: boardId2,
|
|
26175
|
+
nodes: external_exports.array(
|
|
26176
|
+
external_exports.object({
|
|
26177
|
+
node_id: nodeIdArg2,
|
|
26178
|
+
position: point.optional(),
|
|
26179
|
+
size: sizeArg.optional(),
|
|
26180
|
+
label: external_exports.string().trim().min(1).max(120).optional(),
|
|
26181
|
+
data: external_exports.record(external_exports.unknown()).optional().describe("Chaves de data a gravar. Valor null apaga a chave.")
|
|
26182
|
+
}).strict()
|
|
26183
|
+
).min(1).max(200),
|
|
26184
|
+
layout_only: external_exports.boolean().optional().describe("true: s\xF3 position e size, sem releitura nem recusa por conflito.")
|
|
26185
|
+
},
|
|
26186
|
+
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false }
|
|
26187
|
+
},
|
|
26188
|
+
async (args) => run(
|
|
26189
|
+
() => edit(
|
|
26190
|
+
args.board_id,
|
|
26191
|
+
async (doc) => {
|
|
26192
|
+
const ids = args.nodes.map((n) => n.node_id);
|
|
26193
|
+
const dup = ids.find((id, i) => ids.indexOf(id) !== i);
|
|
26194
|
+
if (dup) throw new CanvasToolError(`O n\xF3 ${dup} aparece duas vezes: junte as mudan\xE7as dele num item s\xF3.`);
|
|
26195
|
+
if (args.layout_only) {
|
|
26196
|
+
const bad = args.nodes.find((n) => n.data !== void 0 || n.label !== void 0 || typeof n.size === "string");
|
|
26197
|
+
if (bad) {
|
|
26198
|
+
throw new CanvasToolError(
|
|
26199
|
+
`layout_only aceita s\xF3 position e size {w, h} (o n\xF3 ${bad.node_id} traz ${bad.data !== void 0 ? "data" : bad.label !== void 0 ? "label" : `size "${String(bad.size)}"`}). Tire layout_only para gravar data e label com a checagem de conflito.`
|
|
26200
|
+
);
|
|
26201
|
+
}
|
|
26202
|
+
}
|
|
26203
|
+
const changes = args.nodes.map((n) => {
|
|
26204
|
+
const node = needNode(doc, n.node_id);
|
|
26205
|
+
return { node, ...changeOps(node, n) };
|
|
26206
|
+
});
|
|
26207
|
+
const mention = args.layout_only ? { ops: [], note: "" } : await mentionOps(doc, changes.map((c) => ({ node: c.node, data: c.data, keys: c.dataKeys })));
|
|
26208
|
+
const touched = changes.filter((c) => c.ops.length);
|
|
26209
|
+
const list = touched.slice(0, 12).map((c) => `"${oneLine(nodeName(c.node), 30)}" (${c.keys.join(", ")})`).join("; ");
|
|
26210
|
+
return {
|
|
26211
|
+
ops: [...changes.flatMap((c) => c.ops), ...mention.ops],
|
|
26212
|
+
targets: ids,
|
|
26213
|
+
done: `${touched.length} de ${ids.length} n\xF3(s) atualizado(s)${args.layout_only ? " (layout_only)" : ""}` + (list ? `: ${list}${touched.length > 12 ? `; \u2026 +${touched.length - 12}` : ""}` : "") + mention.note
|
|
26214
|
+
};
|
|
26215
|
+
},
|
|
26216
|
+
{ split: true, layoutOnly: !!args.layout_only }
|
|
26217
|
+
)
|
|
26218
|
+
)
|
|
26219
|
+
);
|
|
26220
|
+
server.registerTool(
|
|
26221
|
+
"canvas_patch_node",
|
|
26222
|
+
{
|
|
26223
|
+
title: "Canvas: gravar por caminho",
|
|
26224
|
+
description: `Grava v\xE1rios caminhos dentro do data de um n\xF3, sem executar: {path, value} grava, {path, unset: true} apaga. ${READ}O caminho atravessa objetos (o n\xEDvel que falta \xE9 criado) e n\xE3o entra em lista: para mudar um item de lista, grave a lista inteira. Quebra sozinho em envelopes de at\xE9 64 KB, em ordem, e devolve o resultado de cada um; entre envelopes n\xE3o h\xE1 atomicidade (o que entrou fica). Serve para mexer em partes de uma estrutura grande, como clipes da timeline da Montagem, sem reenviar tudo. Leia antes com canvas_read_node. ` + MENTION_NOTE + MONTAGE_NOTE,
|
|
26225
|
+
inputSchema: {
|
|
26226
|
+
board_id: boardId2,
|
|
26227
|
+
node_id: nodeIdArg2,
|
|
26228
|
+
sets: external_exports.array(
|
|
26229
|
+
external_exports.object({
|
|
26230
|
+
path: external_exports.string().trim().min(1).max(500).describe('Caminho dentro do data (ex.: "timeline.meta.fps"); aceita o prefixo "data.".'),
|
|
26231
|
+
value: external_exports.unknown().optional().describe("Valor JSON a gravar (null grava null)."),
|
|
26232
|
+
unset: external_exports.literal(true).optional().describe("true apaga a chave.")
|
|
26233
|
+
})
|
|
26234
|
+
).min(1).max(5e3)
|
|
26235
|
+
},
|
|
26236
|
+
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false }
|
|
26237
|
+
},
|
|
26238
|
+
async (args) => run(
|
|
26239
|
+
() => edit(
|
|
26240
|
+
args.board_id,
|
|
26241
|
+
async (doc) => {
|
|
26242
|
+
const node = needNode(doc, args.node_id);
|
|
26243
|
+
const work = structuredClone(node.data);
|
|
26244
|
+
const ops = [];
|
|
26245
|
+
let same = 0;
|
|
26246
|
+
let absent = 0;
|
|
26247
|
+
const mentionKeys = /* @__PURE__ */ new Set();
|
|
26248
|
+
let mentionAt = -1;
|
|
26249
|
+
for (const [i, item] of args.sets.entries()) {
|
|
26250
|
+
const at = `sets[${i}] (${item.path})`;
|
|
26251
|
+
const segs = dataSegments(item.path);
|
|
26252
|
+
if (!segs.length) throw new CanvasToolError(`${at}: informe um caminho dentro do data, n\xE3o o data inteiro.`);
|
|
26253
|
+
if (segs[0] === KIND_FIELD) throw new CanvasToolError(`${at}: data.kind n\xE3o muda (apague o n\xF3 e crie outro do tipo certo).`);
|
|
26254
|
+
legacySequenceGuard(node, segs[0]);
|
|
26255
|
+
const path = `data.${segs.join(".")}`;
|
|
26256
|
+
const badPath = checkNodePath(path);
|
|
26257
|
+
if (badPath) throw new CanvasToolError(`${at}: ${badPath}.`);
|
|
26258
|
+
if (MENTION_KEYS.includes(segs[0])) mentionKeys.add(segs[0]);
|
|
26259
|
+
const unset = item.unset === true;
|
|
26260
|
+
const hasValue = item.value !== void 0;
|
|
26261
|
+
if (unset === hasValue) throw new CanvasToolError(`${at}: mande value OU unset: true.`);
|
|
26262
|
+
if (hasValue && !isJson(item.value)) throw new CanvasToolError(`${at}: value n\xE3o \xE9 JSON v\xE1lido.`);
|
|
26263
|
+
let cur = work;
|
|
26264
|
+
for (const [j, seg] of segs.slice(0, -1).entries()) {
|
|
26265
|
+
const next = Object.hasOwn(cur, seg) ? cur[seg] : void 0;
|
|
26266
|
+
const isObject2 = !!next && typeof next === "object" && !Array.isArray(next);
|
|
26267
|
+
if (isObject2) {
|
|
26268
|
+
cur = next;
|
|
26269
|
+
continue;
|
|
26270
|
+
}
|
|
26271
|
+
if (unset) {
|
|
26272
|
+
cur = null;
|
|
26273
|
+
break;
|
|
26274
|
+
}
|
|
26275
|
+
if (next === void 0) {
|
|
26276
|
+
const created = {};
|
|
26277
|
+
cur[seg] = created;
|
|
26278
|
+
cur = created;
|
|
26279
|
+
continue;
|
|
26280
|
+
}
|
|
26281
|
+
throw new CanvasToolError(
|
|
26282
|
+
`${at}: data.${segs.slice(0, j + 1).join(".")} \xE9 ${Array.isArray(next) ? "uma lista" : "um valor simples"}, e o caminho n\xE3o entra nele. Grave o n\xEDvel de cima inteiro.`
|
|
26283
|
+
);
|
|
26284
|
+
}
|
|
26285
|
+
const leaf = segs[segs.length - 1];
|
|
26286
|
+
if (unset) {
|
|
26287
|
+
if (!cur || !Object.hasOwn(cur, leaf)) {
|
|
26288
|
+
absent++;
|
|
26289
|
+
continue;
|
|
26290
|
+
}
|
|
26291
|
+
delete cur[leaf];
|
|
26292
|
+
ops.push({ type: "node.set", nodeId: node.id, path, value: unsetValue() });
|
|
26293
|
+
if (MENTION_KEYS.includes(segs[0])) mentionAt = ops.length;
|
|
26294
|
+
continue;
|
|
26295
|
+
}
|
|
26296
|
+
const value = item.value;
|
|
26297
|
+
if (cur && Object.hasOwn(cur, leaf) && JSON.stringify(cur[leaf]) === JSON.stringify(value)) {
|
|
26298
|
+
same++;
|
|
26299
|
+
continue;
|
|
26300
|
+
}
|
|
26301
|
+
if (cur) cur[leaf] = value;
|
|
26302
|
+
ops.push({ type: "node.set", nodeId: node.id, path, value: setValue(value) });
|
|
26303
|
+
if (MENTION_KEYS.includes(segs[0])) mentionAt = ops.length;
|
|
26304
|
+
}
|
|
26305
|
+
const skipped = [same ? `${same} igual(is) ao que j\xE1 estava` : "", absent ? `${absent} unset de caminho que n\xE3o existe` : ""].filter(Boolean).join(", ");
|
|
26306
|
+
const written = ops.length;
|
|
26307
|
+
const mention = await mentionOps(doc, [{ node, data: work, keys: [...mentionKeys] }]);
|
|
26308
|
+
ops.splice(mentionAt < 0 ? ops.length : mentionAt, 0, ...mention.ops);
|
|
26309
|
+
return {
|
|
26310
|
+
ops,
|
|
26311
|
+
targets: [node.id],
|
|
26312
|
+
done: `N\xF3 "${oneLine(nodeName(node), 40)}" (${node.id}): ${written} caminho(s) gravado(s)` + (skipped ? ` (ignorados: ${skipped})` : "") + mention.note
|
|
26313
|
+
};
|
|
26314
|
+
},
|
|
26315
|
+
{ split: true }
|
|
26316
|
+
)
|
|
26317
|
+
)
|
|
26318
|
+
);
|
|
24704
26319
|
server.registerTool(
|
|
24705
26320
|
"canvas_connect",
|
|
24706
26321
|
{
|
|
24707
26322
|
title: "Canvas: ligar portas",
|
|
24708
|
-
description:
|
|
26323
|
+
description: `Liga a sa\xEDda de um n\xF3 \xE0 entrada de outro (ids e portas de canvas_read_board). ${READ}Liga\xE7\xE3o repetida \xE9 ignorada.`,
|
|
24709
26324
|
inputSchema: {
|
|
24710
26325
|
board_id: boardId2,
|
|
24711
|
-
source:
|
|
26326
|
+
source: nodeIdArg2,
|
|
24712
26327
|
source_port: external_exports.string().min(1).max(80),
|
|
24713
|
-
target:
|
|
26328
|
+
target: nodeIdArg2,
|
|
24714
26329
|
target_port: external_exports.string().min(1).max(80)
|
|
24715
26330
|
},
|
|
24716
26331
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false }
|
|
@@ -24732,11 +26347,11 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
24732
26347
|
"canvas_delete",
|
|
24733
26348
|
{
|
|
24734
26349
|
title: "Canvas: apagar n\xF3s/liga\xE7\xF5es",
|
|
24735
|
-
description:
|
|
26350
|
+
description: `Apaga n\xF3s (com as liga\xE7\xF5es e varia\xE7\xF5es deles) e/ou liga\xE7\xF5es, num passo s\xF3. Irrevers\xEDvel pelo MCP: confirme com o usu\xE1rio antes. ${READ}N\xE3o apaga o board.`,
|
|
24736
26351
|
inputSchema: {
|
|
24737
26352
|
board_id: boardId2,
|
|
24738
|
-
node_ids: external_exports.array(
|
|
24739
|
-
edge_ids: external_exports.array(
|
|
26353
|
+
node_ids: external_exports.array(nodeIdArg2).max(200).optional(),
|
|
26354
|
+
edge_ids: external_exports.array(nodeIdArg2).max(200).optional()
|
|
24740
26355
|
},
|
|
24741
26356
|
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false }
|
|
24742
26357
|
},
|
|
@@ -24777,7 +26392,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
24777
26392
|
"canvas_rename_board",
|
|
24778
26393
|
{
|
|
24779
26394
|
title: "Canvas: renomear board",
|
|
24780
|
-
description:
|
|
26395
|
+
description: `Troca o t\xEDtulo do board (board.set). ${READ}Precisa de papel de editor ou dono.`,
|
|
24781
26396
|
inputSchema: { board_id: boardId2, title: external_exports.string().trim().min(1).max(200) },
|
|
24782
26397
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false }
|
|
24783
26398
|
},
|
|
@@ -24836,13 +26451,15 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
24836
26451
|
})
|
|
24837
26452
|
);
|
|
24838
26453
|
registerCanvasCommentTools(server, api, run);
|
|
26454
|
+
registerCanvasMediaTools(server, { api, cfg, run, edit, seen, placeFor });
|
|
26455
|
+
registerCanvasLayoutTools(server, { api, run, edit });
|
|
24839
26456
|
}
|
|
24840
26457
|
|
|
24841
26458
|
// src/version.ts
|
|
24842
26459
|
import { createRequire } from "module";
|
|
24843
26460
|
var require2 = createRequire(import.meta.url);
|
|
24844
26461
|
function readVersion() {
|
|
24845
|
-
if ("0.
|
|
26462
|
+
if ("0.29.0") return "0.29.0";
|
|
24846
26463
|
try {
|
|
24847
26464
|
const pkg = require2("../package.json");
|
|
24848
26465
|
return pkg.version ?? "0.0.0-unknown";
|
|
@@ -24858,6 +26475,7 @@ var SERVER_INSTRUCTIONS = [
|
|
|
24858
26475
|
'M\xEDdia: generate_* gasta diamantes; confira com estimate_cost antes de lotes grandes. Sem project, a gera\xE7\xE3o cai no projeto ativo; billing:"personal" cobra do usu\xE1rio.',
|
|
24859
26476
|
"Calls: search_calls acha, get_call traz a transcri\xE7\xE3o.",
|
|
24860
26477
|
"Canvas online (canvas_*): leia com canvas_read_board antes de editar e siga o estado lido. Cada edi\xE7\xE3o vai num passo s\xF3; se outra pessoa mexeu nos mesmos n\xF3s, a ferramenta recusa e pede releitura. As ferramentas canvas_* n\xE3o geram m\xEDdia nem gastam diamantes: quem roda os n\xF3s \xE9 o usu\xE1rio no Canvas. D\xEA nome (label) aos n\xF3s, n\xE3o invente tipos nem portas, e confirme antes de canvas_delete.",
|
|
26478
|
+
'Arrumar o board: o size gravado \xE9 piso (o cart\xE3o cresce com o conte\xFAdo); use o tamanho "medido" do canvas_read_board. \xC1rea de revis\xE3o: canvas_arrange_rows (uma linha por vers\xE3o); posi\xE7\xE3o/tamanho em lote: canvas_update_nodes com layout_only. N\xE3o afirme que nada se sobrep\xF5e com n\xF3 sem medida.',
|
|
24861
26479
|
'"Aplica os coment\xE1rios" do board: canvas_list_comments (abertos) \u2192 para cada um, leia o n\xF3 ancorado com canvas_read_board (node_ids), aplique a edi\xE7\xE3o pelas canvas_* e feche com canvas_resolve_comment dizendo em uma frase o que fez. Coment\xE1rio amb\xEDguo ou com alvo sumido: responda com pergunta (canvas_reply_comment) e n\xE3o resolva. D\xFAvida sua sobre um n\xF3: canvas_comment ancorado nele. As escritas j\xE1 saem espa\xE7adas (60/min); se ainda vier limite, pare e diga de onde seguir.'
|
|
24862
26480
|
].join("\n");
|
|
24863
26481
|
function buildServer(cfg) {
|
|
@@ -24899,8 +26517,8 @@ function assertSupportedNode() {
|
|
|
24899
26517
|
|
|
24900
26518
|
// src/doctor.ts
|
|
24901
26519
|
import { readFileSync } from "fs";
|
|
24902
|
-
import { homedir as
|
|
24903
|
-
import { join } from "path";
|
|
26520
|
+
import { homedir as homedir4 } from "os";
|
|
26521
|
+
import { join as join2 } from "path";
|
|
24904
26522
|
var LABEL = { ok: "[ok] ", aviso: "[aviso]", erro: "[erro] " };
|
|
24905
26523
|
var Report = class {
|
|
24906
26524
|
failed = false;
|
|
@@ -24920,27 +26538,27 @@ function maskToken(token) {
|
|
|
24920
26538
|
return `${token.slice(0, 4)}...${token.slice(-4)}`;
|
|
24921
26539
|
}
|
|
24922
26540
|
function configCandidates() {
|
|
24923
|
-
const home =
|
|
26541
|
+
const home = homedir4();
|
|
24924
26542
|
const cwd = process.cwd();
|
|
24925
26543
|
const list = [
|
|
24926
|
-
{ path:
|
|
24927
|
-
{ path:
|
|
24928
|
-
{ path:
|
|
24929
|
-
{ path:
|
|
26544
|
+
{ path: join2(home, ".claude.json"), client: "Claude Code (global)" },
|
|
26545
|
+
{ path: join2(cwd, ".mcp.json"), client: "Claude Code (projeto)" },
|
|
26546
|
+
{ path: join2(home, ".cursor", "mcp.json"), client: "Cursor (global)" },
|
|
26547
|
+
{ path: join2(cwd, ".cursor", "mcp.json"), client: "Cursor (projeto)" }
|
|
24930
26548
|
];
|
|
24931
26549
|
if (process.platform === "darwin") {
|
|
24932
26550
|
list.push({
|
|
24933
|
-
path:
|
|
26551
|
+
path: join2(home, "Library", "Application Support", "Claude", "claude_desktop_config.json"),
|
|
24934
26552
|
client: "Claude Desktop"
|
|
24935
26553
|
});
|
|
24936
26554
|
} else if (process.platform === "win32") {
|
|
24937
26555
|
const appData = process.env.APPDATA;
|
|
24938
26556
|
if (appData) {
|
|
24939
|
-
list.push({ path:
|
|
26557
|
+
list.push({ path: join2(appData, "Claude", "claude_desktop_config.json"), client: "Claude Desktop" });
|
|
24940
26558
|
}
|
|
24941
26559
|
} else {
|
|
24942
26560
|
list.push({
|
|
24943
|
-
path:
|
|
26561
|
+
path: join2(home, ".config", "Claude", "claude_desktop_config.json"),
|
|
24944
26562
|
client: "Claude Desktop"
|
|
24945
26563
|
});
|
|
24946
26564
|
}
|
|
@@ -24952,7 +26570,7 @@ function serversNaming(entry) {
|
|
|
24952
26570
|
if (!servers || typeof servers !== "object") return [];
|
|
24953
26571
|
return Object.entries(servers).filter(([name, value]) => name === "beplus" || JSON.stringify(value ?? null).includes("beplus-mcp")).map(([name]) => name);
|
|
24954
26572
|
}
|
|
24955
|
-
function checkConfigs(
|
|
26573
|
+
function checkConfigs(report2) {
|
|
24956
26574
|
let found = 0;
|
|
24957
26575
|
for (const { path, client } of configCandidates()) {
|
|
24958
26576
|
let raw;
|
|
@@ -24965,7 +26583,7 @@ function checkConfigs(report) {
|
|
|
24965
26583
|
try {
|
|
24966
26584
|
parsed = JSON.parse(raw);
|
|
24967
26585
|
} catch {
|
|
24968
|
-
|
|
26586
|
+
report2.line("aviso", `Config ilegivel: ${path}`, "O arquivo existe mas nao e JSON valido.");
|
|
24969
26587
|
continue;
|
|
24970
26588
|
}
|
|
24971
26589
|
const names = new Set(serversNaming(parsed));
|
|
@@ -24975,25 +26593,25 @@ function checkConfigs(report) {
|
|
|
24975
26593
|
}
|
|
24976
26594
|
if (names.size === 0) continue;
|
|
24977
26595
|
found += 1;
|
|
24978
|
-
|
|
26596
|
+
report2.line("ok", `Config detectado: ${path}`, `${client}, servidor ${[...names].join(", ")}`);
|
|
24979
26597
|
}
|
|
24980
26598
|
if (found === 0) {
|
|
24981
|
-
|
|
26599
|
+
report2.line(
|
|
24982
26600
|
"aviso",
|
|
24983
26601
|
"Nenhum config de cliente MCP com o beplus foi encontrado.",
|
|
24984
26602
|
"Isso e normal se voce ainda nao instalou o servidor, ou se o cliente guarda o config em outro lugar."
|
|
24985
26603
|
);
|
|
24986
26604
|
}
|
|
24987
26605
|
}
|
|
24988
|
-
async function checkApiReachable(
|
|
26606
|
+
async function checkApiReachable(report2, baseUrl) {
|
|
24989
26607
|
const controller = new AbortController();
|
|
24990
26608
|
const timer = setTimeout(() => controller.abort(), 1e4);
|
|
24991
26609
|
try {
|
|
24992
26610
|
const res = await fetch(`${baseUrl}/api/v1/mcp/me`, { signal: controller.signal });
|
|
24993
|
-
|
|
26611
|
+
report2.line("ok", `API responde: ${baseUrl}`, `GET /api/v1/mcp/me sem token devolveu HTTP ${res.status}.`);
|
|
24994
26612
|
} catch (e) {
|
|
24995
26613
|
const aborted2 = e?.name === "AbortError";
|
|
24996
|
-
|
|
26614
|
+
report2.line(
|
|
24997
26615
|
"erro",
|
|
24998
26616
|
`API nao respondeu: ${baseUrl}`,
|
|
24999
26617
|
aborted2 ? "Tempo esgotado em 10s. Confira a rede, o proxy ou a VPN." : `Falha de rede: ${e?.message ?? "desconhecida"}. Confira a rede e o valor de BEPLUS_API_URL.`
|
|
@@ -25002,10 +26620,10 @@ async function checkApiReachable(report, baseUrl) {
|
|
|
25002
26620
|
clearTimeout(timer);
|
|
25003
26621
|
}
|
|
25004
26622
|
}
|
|
25005
|
-
async function checkToken(
|
|
26623
|
+
async function checkToken(report2) {
|
|
25006
26624
|
const token = process.env.BEPLUS_API_TOKEN?.trim();
|
|
25007
26625
|
if (!token) {
|
|
25008
|
-
|
|
26626
|
+
report2.line(
|
|
25009
26627
|
"aviso",
|
|
25010
26628
|
"BEPLUS_API_TOKEN nao esta definido.",
|
|
25011
26629
|
"Gere um Personal Access Token em Tokens de acesso, no painel BePlus, e coloque no config do MCP."
|
|
@@ -25014,260 +26632,50 @@ async function checkToken(report) {
|
|
|
25014
26632
|
}
|
|
25015
26633
|
try {
|
|
25016
26634
|
const me = await new BeplusClient(loadConfig()).me();
|
|
25017
|
-
|
|
26635
|
+
report2.line(
|
|
25018
26636
|
"ok",
|
|
25019
26637
|
`Token valido (${maskToken(token)})`,
|
|
25020
26638
|
`Conta: ${me.name ?? me.email ?? me.userId}, ${me.diamonds} diamantes.`
|
|
25021
26639
|
);
|
|
25022
26640
|
} catch (e) {
|
|
25023
26641
|
if (e instanceof ApiError && e.httpStatus === 401) {
|
|
25024
|
-
|
|
26642
|
+
report2.line(
|
|
25025
26643
|
"erro",
|
|
25026
26644
|
`Token invalido ou revogado (${maskToken(token)})`,
|
|
25027
26645
|
"Gere um novo Personal Access Token no painel BePlus e atualize BEPLUS_API_TOKEN no config do MCP."
|
|
25028
26646
|
);
|
|
25029
26647
|
return;
|
|
25030
26648
|
}
|
|
25031
|
-
|
|
26649
|
+
report2.line("aviso", "Nao deu para validar o token agora.", e?.message ?? "erro desconhecido");
|
|
25032
26650
|
}
|
|
25033
26651
|
}
|
|
25034
26652
|
async function runDoctor() {
|
|
25035
|
-
const
|
|
26653
|
+
const report2 = new Report();
|
|
25036
26654
|
process.stdout.write(`beplus-mcp doctor, versao ${VERSION}
|
|
25037
26655
|
|
|
25038
26656
|
`);
|
|
25039
26657
|
if (isSupportedNode()) {
|
|
25040
|
-
|
|
26658
|
+
report2.line("ok", `Node ${process.versions.node}`, `Minimo exigido: Node ${MIN_NODE_MAJOR}.`);
|
|
25041
26659
|
} else {
|
|
25042
|
-
|
|
26660
|
+
report2.line("erro", `Node ${process.versions.node}`, unsupportedNodeMessage());
|
|
25043
26661
|
}
|
|
25044
26662
|
let baseUrl = null;
|
|
25045
26663
|
try {
|
|
25046
26664
|
baseUrl = resolveBaseUrl();
|
|
25047
|
-
|
|
26665
|
+
report2.line("ok", `BEPLUS_API_URL: ${baseUrl}`);
|
|
25048
26666
|
} catch (e) {
|
|
25049
|
-
|
|
26667
|
+
report2.line("erro", "BEPLUS_API_URL invalida", e.message);
|
|
25050
26668
|
}
|
|
25051
26669
|
if (baseUrl) {
|
|
25052
|
-
await checkApiReachable(
|
|
25053
|
-
await checkToken(
|
|
26670
|
+
await checkApiReachable(report2, baseUrl);
|
|
26671
|
+
await checkToken(report2);
|
|
25054
26672
|
}
|
|
25055
|
-
checkConfigs(
|
|
25056
|
-
const code =
|
|
26673
|
+
checkConfigs(report2);
|
|
26674
|
+
const code = report2.exitCode;
|
|
25057
26675
|
process.stdout.write(code === 0 ? "\nTudo certo.\n" : "\nTem item com [erro] acima. Resolva antes de usar o MCP.\n");
|
|
25058
26676
|
return code;
|
|
25059
26677
|
}
|
|
25060
26678
|
|
|
25061
|
-
// src/oauth.ts
|
|
25062
|
-
import crypto from "crypto";
|
|
25063
|
-
import { createServer } from "http";
|
|
25064
|
-
import { spawn } from "child_process";
|
|
25065
|
-
|
|
25066
|
-
// src/credentials.ts
|
|
25067
|
-
import { chmod, mkdir, readFile as readFile2, writeFile, unlink } from "fs/promises";
|
|
25068
|
-
import { homedir as homedir4 } from "os";
|
|
25069
|
-
import { dirname, join as join2 } from "path";
|
|
25070
|
-
function credentialsPath() {
|
|
25071
|
-
const base = process.env.XDG_CONFIG_HOME?.trim() || join2(homedir4(), ".config");
|
|
25072
|
-
return join2(base, "beplus-mcp", "credentials.json");
|
|
25073
|
-
}
|
|
25074
|
-
async function readCredentials() {
|
|
25075
|
-
try {
|
|
25076
|
-
const raw = await readFile2(credentialsPath(), "utf8");
|
|
25077
|
-
const parsed = JSON.parse(raw);
|
|
25078
|
-
if (!parsed.accessToken || !parsed.apiUrl) return null;
|
|
25079
|
-
return parsed;
|
|
25080
|
-
} catch {
|
|
25081
|
-
return null;
|
|
25082
|
-
}
|
|
25083
|
-
}
|
|
25084
|
-
async function writeCredentials(creds) {
|
|
25085
|
-
const path = credentialsPath();
|
|
25086
|
-
await mkdir(dirname(path), { recursive: true, mode: 448 });
|
|
25087
|
-
await writeFile(path, `${JSON.stringify(creds, null, 2)}
|
|
25088
|
-
`, { mode: 384 });
|
|
25089
|
-
await chmod(path, 384);
|
|
25090
|
-
return path;
|
|
25091
|
-
}
|
|
25092
|
-
async function clearCredentials() {
|
|
25093
|
-
try {
|
|
25094
|
-
await unlink(credentialsPath());
|
|
25095
|
-
return true;
|
|
25096
|
-
} catch {
|
|
25097
|
-
return false;
|
|
25098
|
-
}
|
|
25099
|
-
}
|
|
25100
|
-
var RENEW_MARGIN_MS = 6e4;
|
|
25101
|
-
function isExpired(creds) {
|
|
25102
|
-
return typeof creds.expiresAt === "number" && creds.expiresAt - RENEW_MARGIN_MS <= Date.now();
|
|
25103
|
-
}
|
|
25104
|
-
|
|
25105
|
-
// src/oauth.ts
|
|
25106
|
-
var CALLBACK_TIMEOUT_MS = 5 * 6e4;
|
|
25107
|
-
async function json(url, init) {
|
|
25108
|
-
let res;
|
|
25109
|
-
try {
|
|
25110
|
-
res = await fetch(url, init);
|
|
25111
|
-
} catch {
|
|
25112
|
-
throw new Error(`Nao consegui falar com ${new URL(url).origin}. Confira a rede e o BEPLUS_API_URL.`);
|
|
25113
|
-
}
|
|
25114
|
-
const text = await res.text();
|
|
25115
|
-
let body2;
|
|
25116
|
-
try {
|
|
25117
|
-
body2 = text ? JSON.parse(text) : void 0;
|
|
25118
|
-
} catch {
|
|
25119
|
-
}
|
|
25120
|
-
if (!res.ok) {
|
|
25121
|
-
const msg = body2?.message ?? body2?.error_description ?? body2?.error ?? `HTTP ${res.status}`;
|
|
25122
|
-
throw new Error(`${msg} (${url})`);
|
|
25123
|
-
}
|
|
25124
|
-
return body2;
|
|
25125
|
-
}
|
|
25126
|
-
async function discover(apiUrl2) {
|
|
25127
|
-
const meta = await json(`${apiUrl2}/.well-known/oauth-authorization-server`);
|
|
25128
|
-
if (!meta.authorization_endpoint || !meta.token_endpoint || !meta.registration_endpoint) {
|
|
25129
|
-
throw new Error("O servidor respondeu a descoberta sem os endpoints obrigatorios.");
|
|
25130
|
-
}
|
|
25131
|
-
return meta;
|
|
25132
|
-
}
|
|
25133
|
-
function pkce() {
|
|
25134
|
-
const verifier = crypto.randomBytes(32).toString("base64url");
|
|
25135
|
-
return { verifier, challenge: crypto.createHash("sha256").update(verifier).digest("base64url") };
|
|
25136
|
-
}
|
|
25137
|
-
function openBrowser(url) {
|
|
25138
|
-
try {
|
|
25139
|
-
if (process.platform === "win32") {
|
|
25140
|
-
spawn("cmd.exe", ["/c", "start", '""', "/b", url.replace(/&/g, "^&")], {
|
|
25141
|
-
stdio: "ignore",
|
|
25142
|
-
detached: true,
|
|
25143
|
-
windowsVerbatimArguments: true
|
|
25144
|
-
}).unref();
|
|
25145
|
-
return;
|
|
25146
|
-
}
|
|
25147
|
-
const cmd = process.platform === "darwin" ? "open" : "xdg-open";
|
|
25148
|
-
spawn(cmd, [url], { stdio: "ignore", detached: true }).unref();
|
|
25149
|
-
} catch {
|
|
25150
|
-
}
|
|
25151
|
-
}
|
|
25152
|
-
var PAGINA_OK = `<!doctype html><meta charset="utf-8"><title>Pronto</title>
|
|
25153
|
-
<body style="margin:0;min-height:100vh;display:grid;place-items:center;font:16px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#0e1433;color:#f7f6f2">
|
|
25154
|
-
<div style="text-align:center;padding:24px"><h1 style="font-size:22px;margin:0 0 8px">Tudo certo</h1>
|
|
25155
|
-
<p style="margin:0;opacity:.7">Pode fechar esta aba e voltar para o seu agente.</p></div>`;
|
|
25156
|
-
var PAGINA_ERRO = `<!doctype html><meta charset="utf-8"><title>Nao deu</title>
|
|
25157
|
-
<body style="margin:0;min-height:100vh;display:grid;place-items:center;font:16px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#0e1433;color:#f7f6f2">
|
|
25158
|
-
<div style="text-align:center;padding:24px"><h1 style="font-size:22px;margin:0 0 8px">Nao foi dessa vez</h1>
|
|
25159
|
-
<p style="margin:0;opacity:.7">Volte ao terminal para ver o motivo.</p></div>`;
|
|
25160
|
-
function listenForCallback(expectedState) {
|
|
25161
|
-
return new Promise((resolvePort, rejectPort) => {
|
|
25162
|
-
let settle;
|
|
25163
|
-
let fail;
|
|
25164
|
-
const code = new Promise((res, rej) => {
|
|
25165
|
-
settle = res;
|
|
25166
|
-
fail = rej;
|
|
25167
|
-
});
|
|
25168
|
-
const server = createServer((req, res) => {
|
|
25169
|
-
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
25170
|
-
if (url.pathname !== "/callback") {
|
|
25171
|
-
res.writeHead(404).end();
|
|
25172
|
-
return;
|
|
25173
|
-
}
|
|
25174
|
-
const erro = url.searchParams.get("error");
|
|
25175
|
-
const recebido = url.searchParams.get("code");
|
|
25176
|
-
const state = url.searchParams.get("state") ?? "";
|
|
25177
|
-
const ok = !erro && recebido && state === expectedState;
|
|
25178
|
-
res.writeHead(ok ? 200 : 400, { "content-type": "text/html; charset=utf-8" });
|
|
25179
|
-
res.end(ok ? PAGINA_OK : PAGINA_ERRO);
|
|
25180
|
-
server.close();
|
|
25181
|
-
if (erro) return fail(new Error(url.searchParams.get("error_description") || erro));
|
|
25182
|
-
if (!recebido || state !== expectedState) return fail(new Error("Resposta de autorizacao invalida."));
|
|
25183
|
-
settle({ code: recebido, state });
|
|
25184
|
-
});
|
|
25185
|
-
server.on("error", rejectPort);
|
|
25186
|
-
server.listen(0, "127.0.0.1", () => {
|
|
25187
|
-
const addr = server.address();
|
|
25188
|
-
if (!addr || typeof addr === "string") return rejectPort(new Error("Nao consegui abrir a porta local."));
|
|
25189
|
-
const timer = setTimeout(() => {
|
|
25190
|
-
server.close();
|
|
25191
|
-
fail(new Error("Tempo esgotado esperando a autorizacao no navegador."));
|
|
25192
|
-
}, CALLBACK_TIMEOUT_MS);
|
|
25193
|
-
void code.finally(() => clearTimeout(timer));
|
|
25194
|
-
resolvePort({ port: addr.port, code });
|
|
25195
|
-
});
|
|
25196
|
-
});
|
|
25197
|
-
}
|
|
25198
|
-
function toStored(t, apiUrl2, clientId) {
|
|
25199
|
-
return {
|
|
25200
|
-
accessToken: t.access_token,
|
|
25201
|
-
refreshToken: t.refresh_token,
|
|
25202
|
-
expiresAt: t.expires_in ? Date.now() + t.expires_in * 1e3 : void 0,
|
|
25203
|
-
apiUrl: apiUrl2,
|
|
25204
|
-
clientId
|
|
25205
|
-
};
|
|
25206
|
-
}
|
|
25207
|
-
async function login(apiUrl2, onUrl) {
|
|
25208
|
-
const meta = await discover(apiUrl2);
|
|
25209
|
-
const state = crypto.randomBytes(24).toString("base64url");
|
|
25210
|
-
const { verifier, challenge } = pkce();
|
|
25211
|
-
const { port, code } = await listenForCallback(state);
|
|
25212
|
-
const redirectUri = `http://127.0.0.1:${port}/callback`;
|
|
25213
|
-
const client = await json(meta.registration_endpoint, {
|
|
25214
|
-
method: "POST",
|
|
25215
|
-
headers: { "content-type": "application/json" },
|
|
25216
|
-
body: JSON.stringify({
|
|
25217
|
-
client_name: "beplus-mcp (CLI)",
|
|
25218
|
-
redirect_uris: [redirectUri],
|
|
25219
|
-
token_endpoint_auth_method: "none",
|
|
25220
|
-
grant_types: ["authorization_code", "refresh_token"]
|
|
25221
|
-
})
|
|
25222
|
-
});
|
|
25223
|
-
const authorizeUrl = new URL(meta.authorization_endpoint);
|
|
25224
|
-
authorizeUrl.searchParams.set("response_type", "code");
|
|
25225
|
-
authorizeUrl.searchParams.set("client_id", client.client_id);
|
|
25226
|
-
authorizeUrl.searchParams.set("redirect_uri", redirectUri);
|
|
25227
|
-
authorizeUrl.searchParams.set("code_challenge", challenge);
|
|
25228
|
-
authorizeUrl.searchParams.set("code_challenge_method", "S256");
|
|
25229
|
-
authorizeUrl.searchParams.set("state", state);
|
|
25230
|
-
onUrl(authorizeUrl.toString());
|
|
25231
|
-
openBrowser(authorizeUrl.toString());
|
|
25232
|
-
const { code: authCode } = await code;
|
|
25233
|
-
const token = await json(meta.token_endpoint, {
|
|
25234
|
-
method: "POST",
|
|
25235
|
-
headers: { "content-type": "application/json" },
|
|
25236
|
-
body: JSON.stringify({
|
|
25237
|
-
grant_type: "authorization_code",
|
|
25238
|
-
code: authCode,
|
|
25239
|
-
code_verifier: verifier,
|
|
25240
|
-
client_id: client.client_id,
|
|
25241
|
-
redirect_uri: redirectUri
|
|
25242
|
-
})
|
|
25243
|
-
});
|
|
25244
|
-
const path = await writeCredentials(toStored(token, apiUrl2, client.client_id));
|
|
25245
|
-
return { path, authorizeUrl: authorizeUrl.toString() };
|
|
25246
|
-
}
|
|
25247
|
-
async function tokenFromDisk(apiUrl2) {
|
|
25248
|
-
const creds = await readCredentials();
|
|
25249
|
-
if (!creds) return null;
|
|
25250
|
-
if (creds.apiUrl.replace(/\/$/, "") !== apiUrl2.replace(/\/$/, "")) return null;
|
|
25251
|
-
if (!isExpired(creds)) return creds.accessToken;
|
|
25252
|
-
if (!creds.refreshToken) return null;
|
|
25253
|
-
try {
|
|
25254
|
-
const meta = await discover(apiUrl2);
|
|
25255
|
-
const token = await json(meta.token_endpoint, {
|
|
25256
|
-
method: "POST",
|
|
25257
|
-
headers: { "content-type": "application/json" },
|
|
25258
|
-
body: JSON.stringify({
|
|
25259
|
-
grant_type: "refresh_token",
|
|
25260
|
-
refresh_token: creds.refreshToken,
|
|
25261
|
-
client_id: creds.clientId
|
|
25262
|
-
})
|
|
25263
|
-
});
|
|
25264
|
-
await writeCredentials(toStored(token, apiUrl2, creds.clientId));
|
|
25265
|
-
return token.access_token;
|
|
25266
|
-
} catch {
|
|
25267
|
-
return null;
|
|
25268
|
-
}
|
|
25269
|
-
}
|
|
25270
|
-
|
|
25271
26679
|
// src/index.ts
|
|
25272
26680
|
if (process.argv.length <= 2) assertSupportedNode();
|
|
25273
26681
|
var HELP = `beplus-mcp ${VERSION}
|
|
@@ -25332,7 +26740,7 @@ Se ele nao abrir, acesse:
|
|
|
25332
26740
|
});
|
|
25333
26741
|
process.stdout.write(`Pronto. Credencial guardada em ${path}
|
|
25334
26742
|
`);
|
|
25335
|
-
process.stdout.write("
|
|
26743
|
+
process.stdout.write("Se as ferramentas beplus ainda nao aparecem no agente, reinicie o agente.\n");
|
|
25336
26744
|
return 0;
|
|
25337
26745
|
} catch (e) {
|
|
25338
26746
|
logError(e.message);
|
|
@@ -25344,9 +26752,13 @@ async function main() {
|
|
|
25344
26752
|
if (handled !== null) {
|
|
25345
26753
|
process.exit(handled);
|
|
25346
26754
|
}
|
|
26755
|
+
let doLogin = false;
|
|
25347
26756
|
if (!process.env.BEPLUS_API_TOKEN?.trim()) {
|
|
25348
26757
|
const doDisco = await tokenFromDisk(apiUrl());
|
|
25349
|
-
if (doDisco)
|
|
26758
|
+
if (doDisco) {
|
|
26759
|
+
process.env.BEPLUS_API_TOKEN = doDisco;
|
|
26760
|
+
doLogin = true;
|
|
26761
|
+
}
|
|
25350
26762
|
}
|
|
25351
26763
|
let cfg;
|
|
25352
26764
|
try {
|
|
@@ -25355,6 +26767,7 @@ async function main() {
|
|
|
25355
26767
|
logError(e.message);
|
|
25356
26768
|
process.exit(1);
|
|
25357
26769
|
}
|
|
26770
|
+
if (doLogin) cfg.auth = new LoginToken(cfg.baseUrl, cfg.token);
|
|
25358
26771
|
const { server, client } = buildServer(cfg);
|
|
25359
26772
|
if (cfg.verifyOnStart) {
|
|
25360
26773
|
try {
|
|
@@ -25363,7 +26776,7 @@ async function main() {
|
|
|
25363
26776
|
} catch (e) {
|
|
25364
26777
|
if (e instanceof ApiError && e.httpStatus === 401) {
|
|
25365
26778
|
logError(
|
|
25366
|
-
'Token invalido ou revogado. Gere um novo Personal Access Token no painel BePlus e atualize BEPLUS_API_TOKEN no config do MCP. Rode "beplus-mcp doctor" para conferir.'
|
|
26779
|
+
doLogin ? 'O login pelo navegador expirou e nao deu para renovar. Rode "beplus-mcp login" de novo.' : 'Token invalido ou revogado. Gere um novo Personal Access Token no painel BePlus e atualize BEPLUS_API_TOKEN no config do MCP. Rode "beplus-mcp doctor" para conferir.'
|
|
25367
26780
|
);
|
|
25368
26781
|
process.exit(1);
|
|
25369
26782
|
}
|