@cmo-so/cli 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cmo.mjs +399 -235
- package/package.json +1 -1
package/dist/cmo.mjs
CHANGED
|
@@ -449,9 +449,9 @@ var require_codegen = __commonJS({
|
|
|
449
449
|
}
|
|
450
450
|
};
|
|
451
451
|
var Label = class extends Node {
|
|
452
|
-
constructor(
|
|
452
|
+
constructor(label2) {
|
|
453
453
|
super();
|
|
454
|
-
this.label =
|
|
454
|
+
this.label = label2;
|
|
455
455
|
this.names = {};
|
|
456
456
|
}
|
|
457
457
|
render({ _n }) {
|
|
@@ -459,14 +459,14 @@ var require_codegen = __commonJS({
|
|
|
459
459
|
}
|
|
460
460
|
};
|
|
461
461
|
var Break = class extends Node {
|
|
462
|
-
constructor(
|
|
462
|
+
constructor(label2) {
|
|
463
463
|
super();
|
|
464
|
-
this.label =
|
|
464
|
+
this.label = label2;
|
|
465
465
|
this.names = {};
|
|
466
466
|
}
|
|
467
467
|
render({ _n }) {
|
|
468
|
-
const
|
|
469
|
-
return `break${
|
|
468
|
+
const label2 = this.label ? ` ${this.label}` : "";
|
|
469
|
+
return `break${label2};` + _n;
|
|
470
470
|
}
|
|
471
471
|
};
|
|
472
472
|
var Throw = class extends Node {
|
|
@@ -506,17 +506,17 @@ var require_codegen = __commonJS({
|
|
|
506
506
|
this.nodes = nodes;
|
|
507
507
|
}
|
|
508
508
|
render(opts) {
|
|
509
|
-
return this.nodes.reduce((code,
|
|
509
|
+
return this.nodes.reduce((code, n2) => code + n2.render(opts), "");
|
|
510
510
|
}
|
|
511
511
|
optimizeNodes() {
|
|
512
512
|
const { nodes } = this;
|
|
513
513
|
let i = nodes.length;
|
|
514
514
|
while (i--) {
|
|
515
|
-
const
|
|
516
|
-
if (Array.isArray(
|
|
517
|
-
nodes.splice(i, 1, ...
|
|
518
|
-
else if (
|
|
519
|
-
nodes[i] =
|
|
515
|
+
const n2 = nodes[i].optimizeNodes();
|
|
516
|
+
if (Array.isArray(n2))
|
|
517
|
+
nodes.splice(i, 1, ...n2);
|
|
518
|
+
else if (n2)
|
|
519
|
+
nodes[i] = n2;
|
|
520
520
|
else
|
|
521
521
|
nodes.splice(i, 1);
|
|
522
522
|
}
|
|
@@ -526,16 +526,16 @@ var require_codegen = __commonJS({
|
|
|
526
526
|
const { nodes } = this;
|
|
527
527
|
let i = nodes.length;
|
|
528
528
|
while (i--) {
|
|
529
|
-
const
|
|
530
|
-
if (
|
|
529
|
+
const n2 = nodes[i];
|
|
530
|
+
if (n2.optimizeNames(names, constants))
|
|
531
531
|
continue;
|
|
532
|
-
subtractNames(names,
|
|
532
|
+
subtractNames(names, n2.names);
|
|
533
533
|
nodes.splice(i, 1);
|
|
534
534
|
}
|
|
535
535
|
return nodes.length > 0 ? this : void 0;
|
|
536
536
|
}
|
|
537
537
|
get names() {
|
|
538
|
-
return this.nodes.reduce((names,
|
|
538
|
+
return this.nodes.reduce((names, n2) => addNames(names, n2.names), {});
|
|
539
539
|
}
|
|
540
540
|
};
|
|
541
541
|
var BlockNode = class extends ParentNode {
|
|
@@ -878,12 +878,12 @@ var require_codegen = __commonJS({
|
|
|
878
878
|
return this._endBlockNode(For);
|
|
879
879
|
}
|
|
880
880
|
// `label` statement
|
|
881
|
-
label(
|
|
882
|
-
return this._leafNode(new Label(
|
|
881
|
+
label(label2) {
|
|
882
|
+
return this._leafNode(new Label(label2));
|
|
883
883
|
}
|
|
884
884
|
// `break` statement
|
|
885
|
-
break(
|
|
886
|
-
return this._leafNode(new Break(
|
|
885
|
+
break(label2) {
|
|
886
|
+
return this._leafNode(new Break(label2));
|
|
887
887
|
}
|
|
888
888
|
// `return` statement
|
|
889
889
|
return(value) {
|
|
@@ -946,8 +946,8 @@ var require_codegen = __commonJS({
|
|
|
946
946
|
endFunc() {
|
|
947
947
|
return this._endBlockNode(Func);
|
|
948
948
|
}
|
|
949
|
-
optimize(
|
|
950
|
-
while (
|
|
949
|
+
optimize(n2 = 1) {
|
|
950
|
+
while (n2-- > 0) {
|
|
951
951
|
this._root.optimizeNodes();
|
|
952
952
|
this._root.optimizeNames(this._root.names, this._constants);
|
|
953
953
|
}
|
|
@@ -961,19 +961,19 @@ var require_codegen = __commonJS({
|
|
|
961
961
|
this._nodes.push(node2);
|
|
962
962
|
}
|
|
963
963
|
_endBlockNode(N1, N2) {
|
|
964
|
-
const
|
|
965
|
-
if (
|
|
964
|
+
const n2 = this._currNode;
|
|
965
|
+
if (n2 instanceof N1 || N2 && n2 instanceof N2) {
|
|
966
966
|
this._nodes.pop();
|
|
967
967
|
return this;
|
|
968
968
|
}
|
|
969
969
|
throw new Error(`CodeGen: not in block "${N2 ? `${N1.kind}/${N2.kind}` : N1.kind}"`);
|
|
970
970
|
}
|
|
971
971
|
_elseNode(node2) {
|
|
972
|
-
const
|
|
973
|
-
if (!(
|
|
972
|
+
const n2 = this._currNode;
|
|
973
|
+
if (!(n2 instanceof If)) {
|
|
974
974
|
throw new Error('CodeGen: "else" without "if"');
|
|
975
975
|
}
|
|
976
|
-
this._currNode =
|
|
976
|
+
this._currNode = n2.else = node2;
|
|
977
977
|
return this;
|
|
978
978
|
}
|
|
979
979
|
get _root() {
|
|
@@ -990,8 +990,8 @@ var require_codegen = __commonJS({
|
|
|
990
990
|
};
|
|
991
991
|
exports.CodeGen = CodeGen;
|
|
992
992
|
function addNames(names, from) {
|
|
993
|
-
for (const
|
|
994
|
-
names[
|
|
993
|
+
for (const n2 in from)
|
|
994
|
+
names[n2] = (names[n2] || 0) + (from[n2] || 0);
|
|
995
995
|
return names;
|
|
996
996
|
}
|
|
997
997
|
function addExprNames(names, from) {
|
|
@@ -1002,20 +1002,20 @@ var require_codegen = __commonJS({
|
|
|
1002
1002
|
return replaceName(expr);
|
|
1003
1003
|
if (!canOptimize(expr))
|
|
1004
1004
|
return expr;
|
|
1005
|
-
return new code_1._Code(expr._items.reduce((
|
|
1005
|
+
return new code_1._Code(expr._items.reduce((items2, c) => {
|
|
1006
1006
|
if (c instanceof code_1.Name)
|
|
1007
1007
|
c = replaceName(c);
|
|
1008
1008
|
if (c instanceof code_1._Code)
|
|
1009
|
-
|
|
1009
|
+
items2.push(...c._items);
|
|
1010
1010
|
else
|
|
1011
|
-
|
|
1012
|
-
return
|
|
1011
|
+
items2.push(c);
|
|
1012
|
+
return items2;
|
|
1013
1013
|
}, []));
|
|
1014
|
-
function replaceName(
|
|
1015
|
-
const c = constants[
|
|
1016
|
-
if (c === void 0 || names[
|
|
1017
|
-
return
|
|
1018
|
-
delete names[
|
|
1014
|
+
function replaceName(n2) {
|
|
1015
|
+
const c = constants[n2.str];
|
|
1016
|
+
if (c === void 0 || names[n2.str] !== 1)
|
|
1017
|
+
return n2;
|
|
1018
|
+
delete names[n2.str];
|
|
1019
1019
|
return c;
|
|
1020
1020
|
}
|
|
1021
1021
|
function canOptimize(e) {
|
|
@@ -1023,8 +1023,8 @@ var require_codegen = __commonJS({
|
|
|
1023
1023
|
}
|
|
1024
1024
|
}
|
|
1025
1025
|
function subtractNames(names, from) {
|
|
1026
|
-
for (const
|
|
1027
|
-
names[
|
|
1026
|
+
for (const n2 in from)
|
|
1027
|
+
names[n2] = (names[n2] || 0) - (from[n2] || 0);
|
|
1028
1028
|
}
|
|
1029
1029
|
function not(x) {
|
|
1030
1030
|
return typeof x == "boolean" || typeof x == "number" || x === null ? !x : (0, code_1._)`!${par(x)}`;
|
|
@@ -1167,7 +1167,7 @@ var require_util = __commonJS({
|
|
|
1167
1167
|
mergeNames: (gen, from, to) => gen.if((0, codegen_1._)`${to} !== true && ${from} !== undefined`, () => gen.assign(to, (0, codegen_1._)`${from} === true ? true : ${to} > ${from} ? ${to} : ${from}`)),
|
|
1168
1168
|
mergeToName: (gen, from, to) => gen.if((0, codegen_1._)`${to} !== true`, () => gen.assign(to, from === true ? true : (0, codegen_1._)`${to} > ${from} ? ${to} : ${from}`)),
|
|
1169
1169
|
mergeValues: (from, to) => from === true ? true : Math.max(from, to),
|
|
1170
|
-
resultToName: (gen,
|
|
1170
|
+
resultToName: (gen, items2) => gen.var("items", items2)
|
|
1171
1171
|
})
|
|
1172
1172
|
};
|
|
1173
1173
|
function evaluatedPropsToName(gen, ps) {
|
|
@@ -1361,12 +1361,12 @@ var require_errors = __commonJS({
|
|
|
1361
1361
|
}
|
|
1362
1362
|
return [E.schemaPath, schPath];
|
|
1363
1363
|
}
|
|
1364
|
-
function extraErrorProps(cxt, { params, message }, keyValues) {
|
|
1364
|
+
function extraErrorProps(cxt, { params, message: message2 }, keyValues) {
|
|
1365
1365
|
const { keyword, data, schemaValue, it } = cxt;
|
|
1366
1366
|
const { opts, propertyName, topSchemaRef, schemaPath } = it;
|
|
1367
1367
|
keyValues.push([E.keyword, keyword], [E.params, typeof params == "function" ? params(cxt) : params || (0, codegen_1._)`{}`]);
|
|
1368
1368
|
if (opts.messages) {
|
|
1369
|
-
keyValues.push([E.message, typeof
|
|
1369
|
+
keyValues.push([E.message, typeof message2 == "function" ? message2(cxt) : message2]);
|
|
1370
1370
|
}
|
|
1371
1371
|
if (opts.verbose) {
|
|
1372
1372
|
keyValues.push([E.schema, schemaValue], [E.parentSchema, (0, codegen_1._)`${topSchemaRef}${schemaPath}`], [names_1.default.data, data]);
|
|
@@ -1675,13 +1675,13 @@ var require_defaults = __commonJS({
|
|
|
1675
1675
|
var codegen_1 = require_codegen();
|
|
1676
1676
|
var util_1 = require_util();
|
|
1677
1677
|
function assignDefaults(it, ty) {
|
|
1678
|
-
const { properties, items } = it.schema;
|
|
1678
|
+
const { properties, items: items2 } = it.schema;
|
|
1679
1679
|
if (ty === "object" && properties) {
|
|
1680
1680
|
for (const key in properties) {
|
|
1681
1681
|
assignDefault(it, key, properties[key].default);
|
|
1682
1682
|
}
|
|
1683
|
-
} else if (ty === "array" && Array.isArray(
|
|
1684
|
-
|
|
1683
|
+
} else if (ty === "array" && Array.isArray(items2)) {
|
|
1684
|
+
items2.forEach((sch, i) => assignDefault(it, i, sch.default));
|
|
1685
1685
|
}
|
|
1686
1686
|
}
|
|
1687
1687
|
exports.assignDefaults = assignDefaults;
|
|
@@ -2485,11 +2485,11 @@ var require_validate = __commonJS({
|
|
|
2485
2485
|
gen.return((0, codegen_1._)`${names_1.default.errors} === 0`);
|
|
2486
2486
|
}
|
|
2487
2487
|
}
|
|
2488
|
-
function assignEvaluated({ gen, evaluated, props, items }) {
|
|
2488
|
+
function assignEvaluated({ gen, evaluated, props, items: items2 }) {
|
|
2489
2489
|
if (props instanceof codegen_1.Name)
|
|
2490
2490
|
gen.assign((0, codegen_1._)`${evaluated}.props`, props);
|
|
2491
|
-
if (
|
|
2492
|
-
gen.assign((0, codegen_1._)`${evaluated}.items`,
|
|
2491
|
+
if (items2 instanceof codegen_1.Name)
|
|
2492
|
+
gen.assign((0, codegen_1._)`${evaluated}.items`, items2);
|
|
2493
2493
|
}
|
|
2494
2494
|
function schemaKeywords(it, types, typeErrors, errsCount) {
|
|
2495
2495
|
const { gen, schema, data, allErrors, opts, self } = it;
|
|
@@ -2952,12 +2952,12 @@ var require_compile = __commonJS({
|
|
|
2952
2952
|
validate2.source = { validateName, validateCode, scopeValues: gen._values };
|
|
2953
2953
|
}
|
|
2954
2954
|
if (this.opts.unevaluated) {
|
|
2955
|
-
const { props, items } = schemaCxt;
|
|
2955
|
+
const { props, items: items2 } = schemaCxt;
|
|
2956
2956
|
validate2.evaluated = {
|
|
2957
2957
|
props: props instanceof codegen_1.Name ? void 0 : props,
|
|
2958
|
-
items:
|
|
2958
|
+
items: items2 instanceof codegen_1.Name ? void 0 : items2,
|
|
2959
2959
|
dynamicProps: props instanceof codegen_1.Name,
|
|
2960
|
-
dynamicItems:
|
|
2960
|
+
dynamicItems: items2 instanceof codegen_1.Name
|
|
2961
2961
|
};
|
|
2962
2962
|
if (validate2.source)
|
|
2963
2963
|
validate2.source.evaluated = (0, codegen_1.stringify)(validate2.evaluated);
|
|
@@ -4496,11 +4496,11 @@ var require_core = __commonJS({
|
|
|
4496
4496
|
}
|
|
4497
4497
|
const valid = this.validate($schema, schema);
|
|
4498
4498
|
if (!valid && throwOrLogError) {
|
|
4499
|
-
const
|
|
4499
|
+
const message2 = "schema is invalid: " + this.errorsText();
|
|
4500
4500
|
if (this.opts.validateSchema === "log")
|
|
4501
|
-
this.logger.error(
|
|
4501
|
+
this.logger.error(message2);
|
|
4502
4502
|
else
|
|
4503
|
-
throw new Error(
|
|
4503
|
+
throw new Error(message2);
|
|
4504
4504
|
}
|
|
4505
4505
|
return valid;
|
|
4506
4506
|
}
|
|
@@ -4967,8 +4967,8 @@ var require_ref = __commonJS({
|
|
|
4967
4967
|
it.items = util_1.mergeEvaluated.items(gen, schEvaluated.items, it.items);
|
|
4968
4968
|
}
|
|
4969
4969
|
} else {
|
|
4970
|
-
const
|
|
4971
|
-
it.items = util_1.mergeEvaluated.items(gen,
|
|
4970
|
+
const items2 = gen.var("items", (0, codegen_1._)`${source}.evaluated.items`);
|
|
4971
|
+
it.items = util_1.mergeEvaluated.items(gen, items2, it.items, codegen_1.Name);
|
|
4972
4972
|
}
|
|
4973
4973
|
}
|
|
4974
4974
|
}
|
|
@@ -5508,28 +5508,28 @@ var require_additionalItems = __commonJS({
|
|
|
5508
5508
|
error: error2,
|
|
5509
5509
|
code(cxt) {
|
|
5510
5510
|
const { parentSchema, it } = cxt;
|
|
5511
|
-
const { items } = parentSchema;
|
|
5512
|
-
if (!Array.isArray(
|
|
5511
|
+
const { items: items2 } = parentSchema;
|
|
5512
|
+
if (!Array.isArray(items2)) {
|
|
5513
5513
|
(0, util_1.checkStrictMode)(it, '"additionalItems" is ignored when "items" is not an array of schemas');
|
|
5514
5514
|
return;
|
|
5515
5515
|
}
|
|
5516
|
-
validateAdditionalItems(cxt,
|
|
5516
|
+
validateAdditionalItems(cxt, items2);
|
|
5517
5517
|
}
|
|
5518
5518
|
};
|
|
5519
|
-
function validateAdditionalItems(cxt,
|
|
5519
|
+
function validateAdditionalItems(cxt, items2) {
|
|
5520
5520
|
const { gen, schema, data, keyword, it } = cxt;
|
|
5521
5521
|
it.items = true;
|
|
5522
5522
|
const len = gen.const("len", (0, codegen_1._)`${data}.length`);
|
|
5523
5523
|
if (schema === false) {
|
|
5524
|
-
cxt.setParams({ len:
|
|
5525
|
-
cxt.pass((0, codegen_1._)`${len} <= ${
|
|
5524
|
+
cxt.setParams({ len: items2.length });
|
|
5525
|
+
cxt.pass((0, codegen_1._)`${len} <= ${items2.length}`);
|
|
5526
5526
|
} else if (typeof schema == "object" && !(0, util_1.alwaysValidSchema)(it, schema)) {
|
|
5527
|
-
const valid = gen.var("valid", (0, codegen_1._)`${len} <= ${
|
|
5527
|
+
const valid = gen.var("valid", (0, codegen_1._)`${len} <= ${items2.length}`);
|
|
5528
5528
|
gen.if((0, codegen_1.not)(valid), () => validateItems(valid));
|
|
5529
5529
|
cxt.ok(valid);
|
|
5530
5530
|
}
|
|
5531
5531
|
function validateItems(valid) {
|
|
5532
|
-
gen.forRange("i",
|
|
5532
|
+
gen.forRange("i", items2.length, len, (i) => {
|
|
5533
5533
|
cxt.subschema({ keyword, dataProp: i, dataPropType: util_1.Type.Num }, valid);
|
|
5534
5534
|
if (!it.allErrors)
|
|
5535
5535
|
gen.if((0, codegen_1.not)(valid), () => gen.break());
|
|
@@ -7211,14 +7211,14 @@ var OAuthError = class extends Error {
|
|
|
7211
7211
|
}
|
|
7212
7212
|
};
|
|
7213
7213
|
var SignInRequiredError = class extends Error {
|
|
7214
|
-
constructor(
|
|
7215
|
-
super(
|
|
7214
|
+
constructor(message2 = "Please sign in again.") {
|
|
7215
|
+
super(message2);
|
|
7216
7216
|
this.name = "SignInRequiredError";
|
|
7217
7217
|
}
|
|
7218
7218
|
};
|
|
7219
7219
|
var ApiError = class extends Error {
|
|
7220
|
-
constructor(status,
|
|
7221
|
-
super(
|
|
7220
|
+
constructor(status, message2, requestId, detail = null) {
|
|
7221
|
+
super(message2);
|
|
7222
7222
|
this.status = status;
|
|
7223
7223
|
this.requestId = requestId;
|
|
7224
7224
|
this.detail = detail;
|
|
@@ -7448,10 +7448,10 @@ function createApi({ baseUrl, session: session2, fetch: fetchImpl = globalThis.f
|
|
|
7448
7448
|
}),
|
|
7449
7449
|
models: () => request("/v1/maggie/bridge/models"),
|
|
7450
7450
|
/** Add a ChatGPT account to the bridge (then connect it). */
|
|
7451
|
-
addAccount: (
|
|
7451
|
+
addAccount: (label2) => request("/v1/maggie/bridge/accounts", {
|
|
7452
7452
|
method: "POST",
|
|
7453
7453
|
headers: { "Content-Type": "application/json" },
|
|
7454
|
-
body: JSON.stringify({ label:
|
|
7454
|
+
body: JSON.stringify({ label: label2 ?? null })
|
|
7455
7455
|
}),
|
|
7456
7456
|
/** Make one of the bridge's ChatGPT accounts the one that answers. */
|
|
7457
7457
|
chooseAccount: (id) => request(`/v1/maggie/bridge/accounts/${encodeURIComponent(id)}/use`, { method: "POST" }),
|
|
@@ -7470,8 +7470,8 @@ function createApi({ baseUrl, session: session2, fetch: fetchImpl = globalThis.f
|
|
|
7470
7470
|
/** The user has read the team's latest reply or status change. */
|
|
7471
7471
|
seen: (id) => request(`/v1/feedback/${encodeURIComponent(id)}/seen`, { method: "POST" }),
|
|
7472
7472
|
/** One of the user's feedback photos as a data: URL (an <Image> source on web and native). */
|
|
7473
|
-
photo: async (id,
|
|
7474
|
-
const { type, bytes } = await requestBytes(`/v1/feedback/${encodeURIComponent(id)}/photos/${
|
|
7473
|
+
photo: async (id, n2) => {
|
|
7474
|
+
const { type, bytes } = await requestBytes(`/v1/feedback/${encodeURIComponent(id)}/photos/${n2}`);
|
|
7475
7475
|
return dataUrl(type, bytes);
|
|
7476
7476
|
}
|
|
7477
7477
|
},
|
|
@@ -7521,8 +7521,8 @@ function errorMessage(data, status) {
|
|
|
7521
7521
|
const detail = data?.detail;
|
|
7522
7522
|
if (typeof detail === "string" && detail) return detail;
|
|
7523
7523
|
if (detail && typeof detail === "object" && !Array.isArray(detail)) {
|
|
7524
|
-
const
|
|
7525
|
-
if (typeof
|
|
7524
|
+
const message2 = detail.message;
|
|
7525
|
+
if (typeof message2 === "string" && message2) return message2;
|
|
7526
7526
|
}
|
|
7527
7527
|
if (Array.isArray(detail)) {
|
|
7528
7528
|
const first = detail[0];
|
|
@@ -7540,8 +7540,8 @@ function dataUrl(type, bytes) {
|
|
|
7540
7540
|
const parts = [];
|
|
7541
7541
|
let chunk = "";
|
|
7542
7542
|
for (let i = 0; i < b.length; i += 3) {
|
|
7543
|
-
const
|
|
7544
|
-
chunk += B64.charAt(
|
|
7543
|
+
const n2 = (b[i] ?? 0) << 16 | (b[i + 1] ?? 0) << 8 | (b[i + 2] ?? 0);
|
|
7544
|
+
chunk += B64.charAt(n2 >> 18 & 63) + B64.charAt(n2 >> 12 & 63) + (i + 1 < b.length ? B64.charAt(n2 >> 6 & 63) : "=") + (i + 2 < b.length ? B64.charAt(n2 & 63) : "=");
|
|
7545
7545
|
if (chunk.length >= 8192) {
|
|
7546
7546
|
parts.push(chunk);
|
|
7547
7547
|
chunk = "";
|
|
@@ -7724,8 +7724,14 @@ function domainApi(api2, domain) {
|
|
|
7724
7724
|
/** How a posted Instagram post is doing (read from Instagram, kept 15 minutes; `refresh` reads again). */
|
|
7725
7725
|
socialInsights: (id, refresh = false) => api2.request(`${base}/social/${id}/insights${refresh ? "?refresh=true" : ""}`),
|
|
7726
7726
|
deletePostedSocial: (id) => api2.request(`${base}/social/${id}/published`, { method: "DELETE" }),
|
|
7727
|
-
/**
|
|
7728
|
-
|
|
7727
|
+
/**
|
|
7728
|
+
* Change a posted post. LinkedIn changes its text in place (likes and comments stay); with `repost`, and on
|
|
7729
|
+
* the other channels, the old one comes down and the new text goes out now.
|
|
7730
|
+
*/
|
|
7731
|
+
republishSocial: (id, socialCopy, repost = false) => post(`${base}/social/${id}/republish`, {
|
|
7732
|
+
...socialCopy ? { social_copy: socialCopy } : {},
|
|
7733
|
+
...repost ? { repost: true } : {}
|
|
7734
|
+
}),
|
|
7729
7735
|
restoreSocial: (id) => post(`${base}/social/${id}/restore`),
|
|
7730
7736
|
pauseSocial: () => post(`${base}/social/pause`),
|
|
7731
7737
|
/**
|
|
@@ -8403,8 +8409,8 @@ function cleanSitemap(entry, domain) {
|
|
|
8403
8409
|
if (!url) return "The sitemap must be a web address starting with http:// or https://.";
|
|
8404
8410
|
let owner = SITEMAP_OWNERS.includes(entry.owner) ? entry.owner : "other";
|
|
8405
8411
|
if (owner === "own" && domain && !onWebsite(url, domain)) owner = "other";
|
|
8406
|
-
const
|
|
8407
|
-
const out = { ...entry, url, owner, label:
|
|
8412
|
+
const label2 = (entry.label ?? "").trim().slice(0, SITEMAP_LABEL_MAX);
|
|
8413
|
+
const out = { ...entry, url, owner, label: label2 || null, uses: sitemapUses(owner, entry.uses) };
|
|
8408
8414
|
if (!out.id) delete out.id;
|
|
8409
8415
|
return out;
|
|
8410
8416
|
}
|
|
@@ -8421,8 +8427,8 @@ function checkSitemaps(list2) {
|
|
|
8421
8427
|
function sitemapCheckLine(check) {
|
|
8422
8428
|
if (!check || check.status === "unchecked") return "Checked when you save";
|
|
8423
8429
|
if (check.status === "error") return check.error?.trim() || "Couldn't read this sitemap.";
|
|
8424
|
-
const
|
|
8425
|
-
const found =
|
|
8430
|
+
const n2 = check.url_count;
|
|
8431
|
+
const found = n2 == null ? "Read" : `Found ${n2.toLocaleString("en-GB")} ${n2 === 1 ? "page" : "pages"}`;
|
|
8426
8432
|
const at = check.checked_at ? new Date(check.checked_at) : null;
|
|
8427
8433
|
const when = at && !Number.isNaN(at.getTime()) ? at.toLocaleDateString("en-GB", { day: "numeric", month: "short", year: "numeric" }) : null;
|
|
8428
8434
|
return when ? `${found} \xB7 checked ${when}` : found;
|
|
@@ -8450,13 +8456,13 @@ var named = (title, id) => {
|
|
|
8450
8456
|
const s = String(id ?? "").trim();
|
|
8451
8457
|
return s && s.length <= 8 ? ` #${s}` : "";
|
|
8452
8458
|
};
|
|
8453
|
-
var list = (xs,
|
|
8459
|
+
var list = (xs, n2 = 5) => {
|
|
8454
8460
|
const a = (Array.isArray(xs) ? xs : xs == null ? [] : [xs]).map(String);
|
|
8455
|
-
return a.length >
|
|
8461
|
+
return a.length > n2 ? `${a.slice(0, n2).join(", ")} +${a.length - n2}` : a.join(", ");
|
|
8456
8462
|
};
|
|
8457
|
-
var placeEn = (p,
|
|
8463
|
+
var placeEn = (p, items2 = "posts") => {
|
|
8458
8464
|
const t = String(p ?? "").trim().toLowerCase();
|
|
8459
|
-
if (t === "end") return `at the end of the queue, after the ${
|
|
8465
|
+
if (t === "end") return `at the end of the queue, after the ${items2} already waiting`;
|
|
8460
8466
|
if (t === "random") return "at a random place in the queue";
|
|
8461
8467
|
if (/^\d+$/.test(t)) return Number(t) === 0 ? null : `after the first ${t} in the queue`;
|
|
8462
8468
|
return null;
|
|
@@ -8547,13 +8553,13 @@ var confirmCopy = {
|
|
|
8547
8553
|
sitemap_upsert: {
|
|
8548
8554
|
en: (a) => {
|
|
8549
8555
|
const whose = { own: "your site's ", competitor: "a competitor's ", other: "another site's " }[a.owner];
|
|
8550
|
-
const
|
|
8551
|
-
return a.url ? `Save ${whose ?? "the "}sitemap ${a.url}${
|
|
8556
|
+
const label2 = a.label ? ` (${q(a.label)})` : "";
|
|
8557
|
+
return a.url ? `Save ${whose ?? "the "}sitemap ${a.url}${label2}.` : `Change the sitemap${label2}: ${keys(a).filter((k) => k !== "id").join(", ")}.`;
|
|
8552
8558
|
},
|
|
8553
8559
|
"zh-Hant": (a) => {
|
|
8554
8560
|
const whose = { own: "\u81EA\u5DF1\u7DB2\u7AD9\u7684", competitor: "\u7AF6\u722D\u5C0D\u624B\u7684", other: "\u5176\u4ED6\u7DB2\u7AD9\u7684" }[a.owner];
|
|
8555
|
-
const
|
|
8556
|
-
return a.url ? `\u5132\u5B58${whose ?? ""} sitemap ${a.url}${
|
|
8561
|
+
const label2 = a.label ? `\uFF08${q(a.label)}\uFF09` : "";
|
|
8562
|
+
return a.url ? `\u5132\u5B58${whose ?? ""} sitemap ${a.url}${label2}\u3002` : `\u4FEE\u6539 sitemap${label2}\uFF1A${keys(a).filter((k) => k !== "id").join("\u3001")}\u3002`;
|
|
8557
8563
|
}
|
|
8558
8564
|
},
|
|
8559
8565
|
sitemap_remove: {
|
|
@@ -8711,20 +8717,32 @@ var confirmCopy = {
|
|
|
8711
8717
|
},
|
|
8712
8718
|
social_approve: {
|
|
8713
8719
|
en: (a) => {
|
|
8714
|
-
const
|
|
8720
|
+
const n2 = ids(a);
|
|
8715
8721
|
const at = placeEn(a.position);
|
|
8716
8722
|
if (at)
|
|
8717
|
-
return `Approve ${
|
|
8718
|
-
return
|
|
8723
|
+
return `Approve ${n2.length > 1 ? `${n2.length} posts: ${n2.map((i) => `#${i}`).join(", ")}` : `post #${n2[0]}`}. ${n2.length > 1 ? "They are" : "It is"} queued ${at}, and go${n2.length > 1 ? "" : "es"} out where your network can see ${n2.length > 1 ? "them" : "it"}.`;
|
|
8724
|
+
return n2.length > 1 ? `Approve ${n2.length} posts: ${n2.map((i) => `#${i}`).join(", ")}. Each goes out at your next posting times, where your network can see it.` : `Approve post #${n2[0]}. It goes out at your next posting time, where your network can see it.`;
|
|
8719
8725
|
},
|
|
8720
8726
|
"zh-Hant": (a) => {
|
|
8721
|
-
const
|
|
8727
|
+
const n2 = ids(a);
|
|
8722
8728
|
const at = placeZh(a.position);
|
|
8723
8729
|
if (at)
|
|
8724
|
-
return `\u6279\u51C6${
|
|
8725
|
-
return
|
|
8730
|
+
return `\u6279\u51C6${n2.length > 1 ? ` ${n2.length} \u7BC7\u8CBC\u6587\uFF1A${n2.map((i) => `#${i}`).join("\u3001")}` : `\u8CBC\u6587 #${n2[0]}`}\u3002${at}\uFF0C\u767C\u51FA\u5F8C\u4F60\u7684\u4EBA\u8108\u90FD\u770B\u5F97\u5230\u3002`;
|
|
8731
|
+
return n2.length > 1 ? `\u6279\u51C6 ${n2.length} \u7BC7\u8CBC\u6587\uFF1A${n2.map((i) => `#${i}`).join("\u3001")}\u3002\u6BCF\u7BC7\u5728\u63A5\u4E0B\u4F86\u7684\u767C\u6587\u6642\u9593\u767C\u51FA\uFF0C\u4F60\u7684\u4EBA\u8108\u90FD\u770B\u5F97\u5230\u3002` : `\u6279\u51C6\u8CBC\u6587 #${n2[0]}\u3002\u5B83\u6703\u5728\u4E0B\u4E00\u500B\u767C\u6587\u6642\u9593\u767C\u51FA\uFF0C\u4F60\u7684\u4EBA\u8108\u90FD\u770B\u5F97\u5230\u3002`;
|
|
8726
8732
|
}
|
|
8727
8733
|
},
|
|
8734
|
+
social_publish_now: {
|
|
8735
|
+
en: (a) => `Post #${a.id} on its channel now, not at its posting time (even while posting is paused). Everyone who follows you can see it.`,
|
|
8736
|
+
"zh-Hant": (a) => `\u7ACB\u5373\u5728\u5B83\u7684\u983B\u9053\u767C\u51FA\u8CBC\u6587 #${a.id}\uFF0C\u4E0D\u7B49\u767C\u6587\u6642\u9593\uFF08\u66AB\u505C\u767C\u6587\u6642\u4E5F\u6703\u767C\uFF09\u3002\u767C\u51FA\u5F8C\u95DC\u6CE8\u4F60\u7684\u4EBA\u90FD\u770B\u5F97\u5230\u3002`
|
|
8737
|
+
},
|
|
8738
|
+
social_posted_update: {
|
|
8739
|
+
en: (a) => a.repost ? `Take post #${a.id} down (its likes and comments go) and put it up again${a.social_copy ? ` as ${q(a.social_copy)}` : ""}.` : `Change the text of the posted post #${a.id} to ${q(a.social_copy)}. On LinkedIn it stays up with its likes and comments; on other channels it comes down and goes out again.`,
|
|
8740
|
+
"zh-Hant": (a) => a.repost ? `\u64A4\u4E0B\u8CBC\u6587 #${a.id}\uFF08\u8B9A\u548C\u7559\u8A00\u6703\u6D88\u5931\uFF09\uFF0C\u518D\u91CD\u65B0\u767C\u51FA${a.social_copy ? `\uFF0C\u5167\u5BB9\u6539\u70BA ${q(a.social_copy)}` : ""}\u3002` : `\u628A\u5DF2\u767C\u51FA\u7684\u8CBC\u6587 #${a.id} \u6539\u70BA ${q(a.social_copy)}\u3002LinkedIn \u4E0A\u539F\u5730\u4FEE\u6539\uFF0C\u8B9A\u548C\u7559\u8A00\u4FDD\u7559\uFF1B\u5176\u4ED6\u983B\u9053\u6703\u64A4\u4E0B\u5F8C\u91CD\u767C\u3002`
|
|
8741
|
+
},
|
|
8742
|
+
social_posted_delete: {
|
|
8743
|
+
en: (a) => `Take post #${a.id} down from its channel, with its likes and comments. This can't be undone.`,
|
|
8744
|
+
"zh-Hant": (a) => `\u628A\u8CBC\u6587 #${a.id} \u5F9E\u5B83\u7684\u983B\u9053\u64A4\u4E0B\uFF0C\u8B9A\u548C\u7559\u8A00\u4E00\u8D77\u522A\u9664\uFF0C\u7121\u6CD5\u5FA9\u539F\u3002`
|
|
8745
|
+
},
|
|
8728
8746
|
social_skip: { en: (a) => `Skip post #${a.id}.`, "zh-Hant": (a) => `\u8DF3\u904E\u8CBC\u6587 #${a.id}\u3002` },
|
|
8729
8747
|
social_restore: {
|
|
8730
8748
|
en: (a) => `Bring back post #${a.id}.`,
|
|
@@ -8778,12 +8796,12 @@ var confirmCopy = {
|
|
|
8778
8796
|
},
|
|
8779
8797
|
social_pictures_attach: {
|
|
8780
8798
|
en: (a) => {
|
|
8781
|
-
const
|
|
8782
|
-
return `${a.append ? "Add" : "Put"} your ${
|
|
8799
|
+
const n2 = (Array.isArray(a.urls) ? a.urls.length : 0) + (Array.isArray(a.files) ? a.files.length : 0);
|
|
8800
|
+
return `${a.append ? "Add" : "Put"} your ${n2} picture${n2 === 1 ? "" : "s"} ${a.append ? "after the pictures on" : "on"} post #${a.id}${a.append ? "" : ", in place of its picture"} (free). On LinkedIn a set goes out as a swipeable PDF carousel.`;
|
|
8783
8801
|
},
|
|
8784
8802
|
"zh-Hant": (a) => {
|
|
8785
|
-
const
|
|
8786
|
-
return `${a.append ? `\u5728\u8CBC\u6587 #${a.id} \u73FE\u6709\u5716\u7247\u5F8C\u52A0\u4E0A` : `\u628A\u8CBC\u6587 #${a.id} \u7684\u5716\u7247\u63DB\u6210`}\u4F60\u7684 ${
|
|
8803
|
+
const n2 = (Array.isArray(a.urls) ? a.urls.length : 0) + (Array.isArray(a.files) ? a.files.length : 0);
|
|
8804
|
+
return `${a.append ? `\u5728\u8CBC\u6587 #${a.id} \u73FE\u6709\u5716\u7247\u5F8C\u52A0\u4E0A` : `\u628A\u8CBC\u6587 #${a.id} \u7684\u5716\u7247\u63DB\u6210`}\u4F60\u7684 ${n2} \u5F35\u5716\u7247\uFF08\u514D\u8CBB\uFF09\u3002\u5728 LinkedIn \u4E0A\uFF0C\u4E00\u7D44\u5716\u7247\u6703\u4EE5\u53EF\u6ED1\u52D5\u7684 PDF \u8F2A\u64AD\u767C\u51FA\u3002`;
|
|
8787
8805
|
}
|
|
8788
8806
|
},
|
|
8789
8807
|
social_carousel_pdf_attach: {
|
|
@@ -9012,17 +9030,17 @@ function confirmText(tool3, args, lang = "en") {
|
|
|
9012
9030
|
function costText(cost2, lang = "en") {
|
|
9013
9031
|
const parts = [];
|
|
9014
9032
|
if (cost2.aiGenerations) {
|
|
9015
|
-
const
|
|
9033
|
+
const n2 = cost2.aiGenerations;
|
|
9016
9034
|
const left = cost2.aiLeft;
|
|
9017
9035
|
parts.push(
|
|
9018
|
-
lang === "zh-Hant" ? `\u7528 ${
|
|
9036
|
+
lang === "zh-Hant" ? `\u7528 ${n2} \u6B21 AI \u751F\u6210${left == null ? "" : `\uFF08\u4ECA\u5929\u5269 ${left} \u6B21\uFF09`}\u3002` : `Uses ${n2} AI generation${n2 === 1 ? "" : "s"}${left == null ? "" : ` (${left} left today)`}.`
|
|
9019
9037
|
);
|
|
9020
9038
|
}
|
|
9021
9039
|
if (cost2.credits) {
|
|
9022
|
-
const
|
|
9040
|
+
const n2 = cost2.credits;
|
|
9023
9041
|
const left = cost2.creditsLeft;
|
|
9024
9042
|
parts.push(
|
|
9025
|
-
lang === "zh-Hant" ? `\u6263 ${
|
|
9043
|
+
lang === "zh-Hant" ? `\u6263 ${n2} \u500B\u984D\u5EA6${left == null ? "" : `\uFF08\u5269 ${left}\uFF09`}\u3002` : `Uses ${n2} credit${n2 === 1 ? "" : "s"}${left == null ? "" : ` (${left} left)`}.`
|
|
9026
9044
|
);
|
|
9027
9045
|
}
|
|
9028
9046
|
return parts.join(" ");
|
|
@@ -9034,13 +9052,13 @@ function ws(ctx) {
|
|
|
9034
9052
|
if (!ctx.domain) throw new Error("No website is selected yet. Add one first.");
|
|
9035
9053
|
return domainApi(ctx.api, ctx.domain);
|
|
9036
9054
|
}
|
|
9037
|
-
var clip = (text3,
|
|
9055
|
+
var clip = (text3, n2 = 280) => typeof text3 === "string" ? text3.length > n2 ? `${text3.slice(0, n2)}\u2026` : text3 : text3 ?? null;
|
|
9038
9056
|
var plain = (html) => String(html ?? "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
9039
9057
|
var untrusted = (value) => ({ untrusted: value });
|
|
9040
9058
|
function upsert(list2, item2, key) {
|
|
9041
9059
|
const k = (key(item2) ?? "").trim().toLowerCase();
|
|
9042
9060
|
const i = list2.findIndex((x) => (key(x) ?? "").trim().toLowerCase() === k);
|
|
9043
|
-
return i >= 0 ? list2.map((x,
|
|
9061
|
+
return i >= 0 ? list2.map((x, n2) => n2 === i ? { ...x, ...item2 } : x) : [...list2, item2];
|
|
9044
9062
|
}
|
|
9045
9063
|
function remove(list2, name, key) {
|
|
9046
9064
|
const k = name.trim().toLowerCase();
|
|
@@ -9049,8 +9067,8 @@ function remove(list2, name, key) {
|
|
|
9049
9067
|
return out;
|
|
9050
9068
|
}
|
|
9051
9069
|
var int = (v, min, max, fallback) => {
|
|
9052
|
-
const
|
|
9053
|
-
return Number.isFinite(
|
|
9070
|
+
const n2 = Math.trunc(Number(v));
|
|
9071
|
+
return Number.isFinite(n2) ? Math.min(max, Math.max(min, n2)) : fallback;
|
|
9054
9072
|
};
|
|
9055
9073
|
var positionParam = (what, fallback) => ({
|
|
9056
9074
|
type: "string",
|
|
@@ -9219,12 +9237,12 @@ var accountTools = [
|
|
|
9219
9237
|
risk: "R0",
|
|
9220
9238
|
run: async (ctx, { platform }) => {
|
|
9221
9239
|
const p = platform && CONNECT_FORMS.includes(platform) ? platform : "";
|
|
9222
|
-
const
|
|
9240
|
+
const label2 = p ? `Connect ${CONNECT_NAMES[p]}` : "Connect your website";
|
|
9223
9241
|
const link = `https://app.cmo.so/posts?connect=${p || "wordpress"}${ctx.domain ? `&site=${encodeURIComponent(ctx.domain)}` : ""}`;
|
|
9224
9242
|
if (ctx.client === "chat")
|
|
9225
9243
|
return {
|
|
9226
|
-
card: { type: "connect", platform: p || null, label },
|
|
9227
|
-
shown: `A "${
|
|
9244
|
+
card: { type: "connect", platform: p || null, label: label2 },
|
|
9245
|
+
shown: `A "${label2}" button now shows under your message. The user fills in the form there; say so in one line.`
|
|
9228
9246
|
};
|
|
9229
9247
|
return { link, shown: "Give the user this link: it opens the form in the cmo.so app (web or phone)." };
|
|
9230
9248
|
}
|
|
@@ -9927,10 +9945,10 @@ var brandTools = [
|
|
|
9927
9945
|
need: write2,
|
|
9928
9946
|
risk: "W1",
|
|
9929
9947
|
run: async (ctx, { count }) => {
|
|
9930
|
-
const
|
|
9931
|
-
if (!Number.isFinite(
|
|
9932
|
-
const out = await ws(ctx).updateBrand({ internal_links: { count:
|
|
9933
|
-
return { internal_links: out.internal_links ?? { count:
|
|
9948
|
+
const n2 = Math.round(Number(count));
|
|
9949
|
+
if (!Number.isFinite(n2) || n2 < 0 || n2 > 10) throw new Error("count must be 0 to 10.");
|
|
9950
|
+
const out = await ws(ctx).updateBrand({ internal_links: { count: n2 } });
|
|
9951
|
+
return { internal_links: out.internal_links ?? { count: n2 } };
|
|
9934
9952
|
}
|
|
9935
9953
|
}),
|
|
9936
9954
|
tool({
|
|
@@ -9951,8 +9969,8 @@ var brandTools = [
|
|
|
9951
9969
|
risk: "W1",
|
|
9952
9970
|
run: async (ctx, { use_in_posts, ...item2 }) => {
|
|
9953
9971
|
const t = (await ws(ctx).brand()).testimonials ?? { enabled: false, items: [] };
|
|
9954
|
-
const
|
|
9955
|
-
return (await ws(ctx).updateBrand({ testimonials: { enabled: use_in_posts ?? t.enabled, items } })).testimonials;
|
|
9972
|
+
const items2 = upsert(t.items, item2, (i) => i.name);
|
|
9973
|
+
return (await ws(ctx).updateBrand({ testimonials: { enabled: use_in_posts ?? t.enabled, items: items2 } })).testimonials;
|
|
9956
9974
|
}
|
|
9957
9975
|
}),
|
|
9958
9976
|
tool({
|
|
@@ -9970,8 +9988,8 @@ var brandTools = [
|
|
|
9970
9988
|
risk: "W1",
|
|
9971
9989
|
run: async (ctx, { name, use_in_posts }) => {
|
|
9972
9990
|
const t = (await ws(ctx).brand()).testimonials ?? { enabled: false, items: [] };
|
|
9973
|
-
const
|
|
9974
|
-
return (await ws(ctx).updateBrand({ testimonials: { enabled: use_in_posts ?? t.enabled, items } })).testimonials;
|
|
9991
|
+
const items2 = name ? remove(t.items, name, (i) => i.name) : t.items;
|
|
9992
|
+
return (await ws(ctx).updateBrand({ testimonials: { enabled: use_in_posts ?? t.enabled, items: items2 } })).testimonials;
|
|
9975
9993
|
}
|
|
9976
9994
|
}),
|
|
9977
9995
|
tool({
|
|
@@ -10173,7 +10191,7 @@ var brandTools = [
|
|
|
10173
10191
|
);
|
|
10174
10192
|
if (typeof entry === "string") throw new Error(entry);
|
|
10175
10193
|
if (old && sitemapUrl(old.url) !== entry.url) delete entry.check;
|
|
10176
|
-
const next = old ? list2.map((x,
|
|
10194
|
+
const next = old ? list2.map((x, n2) => n2 === i ? entry : x) : [...list2, entry];
|
|
10177
10195
|
const problem = checkSitemaps(next);
|
|
10178
10196
|
if (problem) throw new Error(problem);
|
|
10179
10197
|
const saved = (await ws(ctx).updateBrand({ sitemaps: next })).sitemaps ?? next;
|
|
@@ -10197,7 +10215,7 @@ var brandTools = [
|
|
|
10197
10215
|
const list2 = (await ws(ctx).brand()).sitemaps ?? [];
|
|
10198
10216
|
const i = findSitemap(list2, id, url);
|
|
10199
10217
|
if (i < 0) throw new Error(`No sitemap ${id ?? url} was found. Use sitemap_list.`);
|
|
10200
|
-
const saved = (await ws(ctx).updateBrand({ sitemaps: list2.filter((_,
|
|
10218
|
+
const saved = (await ws(ctx).updateBrand({ sitemaps: list2.filter((_, n2) => n2 !== i) })).sitemaps ?? [];
|
|
10201
10219
|
return { removed: list2[i]?.url, sitemaps: saved.map((s) => s.url) };
|
|
10202
10220
|
}
|
|
10203
10221
|
}),
|
|
@@ -10356,7 +10374,7 @@ function sitemapResult(s) {
|
|
|
10356
10374
|
// ../../packages/tools/src/feedback.ts
|
|
10357
10375
|
var account = { resource: "account", level: "read" };
|
|
10358
10376
|
var TYPES = ["bug", "quality", "idea", "praise", "other"];
|
|
10359
|
-
var text = (v,
|
|
10377
|
+
var text = (v, n2) => String(v ?? "").trim().slice(0, n2);
|
|
10360
10378
|
var feedbackTools = [
|
|
10361
10379
|
tool({
|
|
10362
10380
|
name: "feedback_send",
|
|
@@ -11676,17 +11694,70 @@ var socialTools = [
|
|
|
11676
11694
|
const at = positionOf(position);
|
|
11677
11695
|
const api2 = ws(ctx);
|
|
11678
11696
|
const results = [];
|
|
11679
|
-
for (const
|
|
11697
|
+
for (const n2 of list2) {
|
|
11680
11698
|
try {
|
|
11681
|
-
await api2.approveSocial(
|
|
11682
|
-
results.push({ id:
|
|
11699
|
+
await api2.approveSocial(n2, at);
|
|
11700
|
+
results.push({ id: n2, ok: true });
|
|
11683
11701
|
} catch (e) {
|
|
11684
|
-
results.push({ id:
|
|
11702
|
+
results.push({ id: n2, ok: false, error: e instanceof Error ? e.message : String(e) });
|
|
11685
11703
|
}
|
|
11686
11704
|
}
|
|
11687
11705
|
return { approved: results.filter((r) => r.ok).length, results };
|
|
11688
11706
|
}
|
|
11689
11707
|
}),
|
|
11708
|
+
tool({
|
|
11709
|
+
name: "social_publish_now",
|
|
11710
|
+
description: "Post one social post on its channel now instead of at its posting time: a draft waiting for approval, a queued post, or one that didn't go out. It goes even while posting is paused. It goes out in the background: the answer says it is publishing; read social_post_get after a minute for its link (or why it couldn't go). Not while its picture is being made.",
|
|
11711
|
+
parameters: { type: "object", properties: { id: { type: "integer" } }, required: ["id"] },
|
|
11712
|
+
group: "social",
|
|
11713
|
+
need: write5,
|
|
11714
|
+
risk: "W3",
|
|
11715
|
+
gates: ["VER"],
|
|
11716
|
+
run: async (ctx, { id }) => {
|
|
11717
|
+
const n2 = Number(id);
|
|
11718
|
+
if (!Number.isInteger(n2) || n2 <= 0) throw new Error("Which post?");
|
|
11719
|
+
const post = await ws(ctx).publishSocialNow(n2, { background: true });
|
|
11720
|
+
return post.status === "published" ? post : { ...post, note: "Posting now. Check social_post_get in a minute for its link." };
|
|
11721
|
+
}
|
|
11722
|
+
}),
|
|
11723
|
+
tool({
|
|
11724
|
+
name: "social_posted_update",
|
|
11725
|
+
description: "Change a social post that has already gone out. On LinkedIn the new text replaces the old in place: the post keeps its likes and comments (its pictures can't change this way). With repost, and on Facebook, Instagram and Google, the old post comes down with its likes and comments and the new version goes out now. Without social_copy and with repost, it goes out again as it is (e.g. after new pictures).",
|
|
11726
|
+
parameters: {
|
|
11727
|
+
type: "object",
|
|
11728
|
+
properties: {
|
|
11729
|
+
id: { type: "integer" },
|
|
11730
|
+
social_copy: { type: "string", description: "The post's new text" },
|
|
11731
|
+
repost: { type: "boolean", description: "Take it down and put it up again instead of editing it" }
|
|
11732
|
+
},
|
|
11733
|
+
required: ["id"]
|
|
11734
|
+
},
|
|
11735
|
+
group: "social",
|
|
11736
|
+
need: write5,
|
|
11737
|
+
risk: "W3",
|
|
11738
|
+
gates: ["VER"],
|
|
11739
|
+
run: async (ctx, { id, social_copy, repost }) => {
|
|
11740
|
+
const n2 = Number(id);
|
|
11741
|
+
if (!Number.isInteger(n2) || n2 <= 0) throw new Error("Which post?");
|
|
11742
|
+
const copy = typeof social_copy === "string" ? social_copy.trim() : "";
|
|
11743
|
+
if (!copy && repost !== true) throw new Error("Give the new text (social_copy), or repost: true.");
|
|
11744
|
+
return ws(ctx).republishSocial(n2, copy || void 0, repost === true);
|
|
11745
|
+
}
|
|
11746
|
+
}),
|
|
11747
|
+
tool({
|
|
11748
|
+
name: "social_posted_delete",
|
|
11749
|
+
description: "Take a social post that has gone out down from its channel (LinkedIn, Facebook, Instagram, Google). Its likes and comments go with it; this can't be undone.",
|
|
11750
|
+
parameters: { type: "object", properties: { id: { type: "integer" } }, required: ["id"] },
|
|
11751
|
+
group: "social",
|
|
11752
|
+
need: write5,
|
|
11753
|
+
risk: "W3",
|
|
11754
|
+
gates: ["VER"],
|
|
11755
|
+
run: async (ctx, { id }) => {
|
|
11756
|
+
const n2 = Number(id);
|
|
11757
|
+
if (!Number.isInteger(n2) || n2 <= 0) throw new Error("Which post?");
|
|
11758
|
+
return ws(ctx).deletePostedSocial(n2);
|
|
11759
|
+
}
|
|
11760
|
+
}),
|
|
11690
11761
|
tool({
|
|
11691
11762
|
name: "social_skip",
|
|
11692
11763
|
description: "Skip a LinkedIn post (it won't be posted; it can be restored).",
|
|
@@ -13182,8 +13253,8 @@ var CommanderError = class extends Error {
|
|
|
13182
13253
|
* @param {string} code an id string representing the error
|
|
13183
13254
|
* @param {string} message human-readable description of the error
|
|
13184
13255
|
*/
|
|
13185
|
-
constructor(exitCode2, code,
|
|
13186
|
-
super(
|
|
13256
|
+
constructor(exitCode2, code, message2) {
|
|
13257
|
+
super(message2);
|
|
13187
13258
|
Error.captureStackTrace(this, this.constructor);
|
|
13188
13259
|
this.name = this.constructor.name;
|
|
13189
13260
|
this.code = code;
|
|
@@ -13196,8 +13267,8 @@ var InvalidArgumentError = class extends CommanderError {
|
|
|
13196
13267
|
* Constructs the InvalidArgumentError class
|
|
13197
13268
|
* @param {string} [message] explanation of why argument is invalid
|
|
13198
13269
|
*/
|
|
13199
|
-
constructor(
|
|
13200
|
-
super(1, "commander.invalidArgument",
|
|
13270
|
+
constructor(message2) {
|
|
13271
|
+
super(1, "commander.invalidArgument", message2);
|
|
13201
13272
|
Error.captureStackTrace(this, this.constructor);
|
|
13202
13273
|
this.name = this.constructor.name;
|
|
13203
13274
|
}
|
|
@@ -13653,9 +13724,9 @@ var Help = class {
|
|
|
13653
13724
|
* @param {Help} helper
|
|
13654
13725
|
* @returns string[]
|
|
13655
13726
|
*/
|
|
13656
|
-
formatItemList(heading,
|
|
13657
|
-
if (
|
|
13658
|
-
return [helper.styleTitle(heading), ...
|
|
13727
|
+
formatItemList(heading, items2, helper) {
|
|
13728
|
+
if (items2.length === 0) return [];
|
|
13729
|
+
return [helper.styleTitle(heading), ...items2, ""];
|
|
13659
13730
|
}
|
|
13660
13731
|
/**
|
|
13661
13732
|
* Group items by their help group heading.
|
|
@@ -14743,9 +14814,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
14743
14814
|
* @return never
|
|
14744
14815
|
* @private
|
|
14745
14816
|
*/
|
|
14746
|
-
_exit(exitCode2, code,
|
|
14817
|
+
_exit(exitCode2, code, message2) {
|
|
14747
14818
|
if (this._exitCallback) {
|
|
14748
|
-
this._exitCallback(new CommanderError(exitCode2, code,
|
|
14819
|
+
this._exitCallback(new CommanderError(exitCode2, code, message2));
|
|
14749
14820
|
}
|
|
14750
14821
|
process2.exit(exitCode2);
|
|
14751
14822
|
}
|
|
@@ -14805,8 +14876,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
14805
14876
|
return target.parseArg(value, previous);
|
|
14806
14877
|
} catch (err) {
|
|
14807
14878
|
if (err.code === "commander.invalidArgument") {
|
|
14808
|
-
const
|
|
14809
|
-
this.error(
|
|
14879
|
+
const message2 = `${invalidArgumentMessage} ${err.message}`;
|
|
14880
|
+
this.error(message2, { exitCode: err.exitCode, code: err.code });
|
|
14810
14881
|
}
|
|
14811
14882
|
throw err;
|
|
14812
14883
|
}
|
|
@@ -15884,9 +15955,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
15884
15955
|
* @param {string} [errorOptions.code] - an id string representing the error
|
|
15885
15956
|
* @param {number} [errorOptions.exitCode] - used with process.exit
|
|
15886
15957
|
*/
|
|
15887
|
-
error(
|
|
15958
|
+
error(message2, errorOptions) {
|
|
15888
15959
|
this._outputConfiguration.outputError(
|
|
15889
|
-
`${
|
|
15960
|
+
`${message2}
|
|
15890
15961
|
`,
|
|
15891
15962
|
this._outputConfiguration.writeErr
|
|
15892
15963
|
);
|
|
@@ -15900,7 +15971,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
15900
15971
|
const config2 = errorOptions || {};
|
|
15901
15972
|
const exitCode2 = config2.exitCode || 1;
|
|
15902
15973
|
const code = config2.code || "commander.error";
|
|
15903
|
-
this._exit(exitCode2, code,
|
|
15974
|
+
this._exit(exitCode2, code, message2);
|
|
15904
15975
|
}
|
|
15905
15976
|
/**
|
|
15906
15977
|
* Apply any option related environment variables, if option does
|
|
@@ -15956,8 +16027,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
15956
16027
|
* @private
|
|
15957
16028
|
*/
|
|
15958
16029
|
missingArgument(name) {
|
|
15959
|
-
const
|
|
15960
|
-
this.error(
|
|
16030
|
+
const message2 = `error: missing required argument '${name}'`;
|
|
16031
|
+
this.error(message2, { code: "commander.missingArgument" });
|
|
15961
16032
|
}
|
|
15962
16033
|
/**
|
|
15963
16034
|
* `Option` is missing an argument.
|
|
@@ -15966,8 +16037,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
15966
16037
|
* @private
|
|
15967
16038
|
*/
|
|
15968
16039
|
optionMissingArgument(option) {
|
|
15969
|
-
const
|
|
15970
|
-
this.error(
|
|
16040
|
+
const message2 = `error: option '${option.flags}' argument missing`;
|
|
16041
|
+
this.error(message2, { code: "commander.optionMissingArgument" });
|
|
15971
16042
|
}
|
|
15972
16043
|
/**
|
|
15973
16044
|
* `Option` does not have a value, and is a mandatory option.
|
|
@@ -15976,8 +16047,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
15976
16047
|
* @private
|
|
15977
16048
|
*/
|
|
15978
16049
|
missingMandatoryOptionValue(option) {
|
|
15979
|
-
const
|
|
15980
|
-
this.error(
|
|
16050
|
+
const message2 = `error: required option '${option.flags}' not specified`;
|
|
16051
|
+
this.error(message2, { code: "commander.missingMandatoryOptionValue" });
|
|
15981
16052
|
}
|
|
15982
16053
|
/**
|
|
15983
16054
|
* `Option` conflicts with another option.
|
|
@@ -16010,8 +16081,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
16010
16081
|
}
|
|
16011
16082
|
return `option '${bestOption.flags}'`;
|
|
16012
16083
|
};
|
|
16013
|
-
const
|
|
16014
|
-
this.error(
|
|
16084
|
+
const message2 = `error: ${getErrorMessage(option)} cannot be used with ${getErrorMessage(conflictingOption)}`;
|
|
16085
|
+
this.error(message2, { code: "commander.conflictingOption" });
|
|
16015
16086
|
}
|
|
16016
16087
|
/**
|
|
16017
16088
|
* Unknown option `flag`.
|
|
@@ -16032,8 +16103,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
16032
16103
|
} while (command && !command._enablePositionalOptions);
|
|
16033
16104
|
suggestion = suggestSimilar(flag, candidateFlags);
|
|
16034
16105
|
}
|
|
16035
|
-
const
|
|
16036
|
-
this.error(
|
|
16106
|
+
const message2 = `error: unknown option '${flag}'${suggestion}`;
|
|
16107
|
+
this.error(message2, { code: "commander.unknownOption" });
|
|
16037
16108
|
}
|
|
16038
16109
|
/**
|
|
16039
16110
|
* Excess arguments, more than expected.
|
|
@@ -16048,8 +16119,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
16048
16119
|
const received = receivedArgs.length;
|
|
16049
16120
|
const forSubcommand = this.parent ? ` for '${this.name()}'` : "";
|
|
16050
16121
|
const details2 = receivedArgs.join(", ");
|
|
16051
|
-
const
|
|
16052
|
-
this.error(
|
|
16122
|
+
const message2 = `error: too many arguments${forSubcommand}. Expected ${expected} argument${s} but got ${received}: ${details2}.`;
|
|
16123
|
+
this.error(message2, { code: "commander.excessArguments" });
|
|
16053
16124
|
}
|
|
16054
16125
|
/**
|
|
16055
16126
|
* Unknown command.
|
|
@@ -16067,8 +16138,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
16067
16138
|
});
|
|
16068
16139
|
suggestion = suggestSimilar(unknownName, candidateNames);
|
|
16069
16140
|
}
|
|
16070
|
-
const
|
|
16071
|
-
this.error(
|
|
16141
|
+
const message2 = `error: unknown command '${unknownName}'${suggestion}`;
|
|
16142
|
+
this.error(message2, { code: "commander.unknownCommand" });
|
|
16072
16143
|
}
|
|
16073
16144
|
/**
|
|
16074
16145
|
* Get or set the program version.
|
|
@@ -16545,7 +16616,7 @@ var program = new Command();
|
|
|
16545
16616
|
// package.json
|
|
16546
16617
|
var package_default = {
|
|
16547
16618
|
name: "@cmo-so/cli",
|
|
16548
|
-
version: "0.9.
|
|
16619
|
+
version: "0.9.3",
|
|
16549
16620
|
description: "CMO.so on the command line: your websites, ideas, blog posts, LinkedIn queue and results, plus a local MCP server for Claude Desktop, Cursor and other MCP clients.",
|
|
16550
16621
|
type: "module",
|
|
16551
16622
|
license: "MIT",
|
|
@@ -16743,8 +16814,8 @@ function print(value, json, human) {
|
|
|
16743
16814
|
`);
|
|
16744
16815
|
return;
|
|
16745
16816
|
}
|
|
16746
|
-
const
|
|
16747
|
-
const out = human ? human(value) :
|
|
16817
|
+
const items2 = Array.isArray(value) ? value : isObj(value) && Array.isArray(value.items) ? value.items : null;
|
|
16818
|
+
const out = human ? human(value) : items2 && items2.every(isObj) ? table(items2) : details(value);
|
|
16748
16819
|
process.stdout.write(`${out}
|
|
16749
16820
|
`);
|
|
16750
16821
|
}
|
|
@@ -16755,6 +16826,75 @@ import { randomBytes } from "node:crypto";
|
|
|
16755
16826
|
// ../../packages/mcp/src/index.ts
|
|
16756
16827
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
16757
16828
|
|
|
16829
|
+
// ../../packages/mcp/src/messages.ts
|
|
16830
|
+
var UPPER = /* @__PURE__ */ new Set(["seo", "gsc", "gbp", "cta", "cmo", "dns", "ai", "api", "pdf", "url", "id"]);
|
|
16831
|
+
var n = (count, word, plural) => count === 1 ? `1 ${word}` : `${count ? count : "no"} ${plural ?? `${word}s`}`;
|
|
16832
|
+
function titleOf(name) {
|
|
16833
|
+
const words = name.split("_").map((w) => UPPER.has(w) ? w.toUpperCase() : w);
|
|
16834
|
+
const head = words[0] ?? "";
|
|
16835
|
+
return [head.charAt(0).toUpperCase() + head.slice(1), ...words.slice(1)].join(" ");
|
|
16836
|
+
}
|
|
16837
|
+
var LIST_KEYS = ["items", "results", "posts", "ideas", "workspaces", "rows"];
|
|
16838
|
+
function items(value) {
|
|
16839
|
+
if (Array.isArray(value)) return value;
|
|
16840
|
+
if (value && typeof value === "object") {
|
|
16841
|
+
for (const k of LIST_KEYS) {
|
|
16842
|
+
const v = value[k];
|
|
16843
|
+
if (Array.isArray(v)) return v;
|
|
16844
|
+
}
|
|
16845
|
+
}
|
|
16846
|
+
return null;
|
|
16847
|
+
}
|
|
16848
|
+
function label(x) {
|
|
16849
|
+
if (x && typeof x === "object") {
|
|
16850
|
+
const o = x;
|
|
16851
|
+
for (const k of ["title", "name", "domain", "label", "what", "text", "id"]) {
|
|
16852
|
+
if (o[k] !== void 0 && o[k] !== null && o[k] !== "") return String(o[k]);
|
|
16853
|
+
}
|
|
16854
|
+
return Object.entries(o).filter(([, v]) => typeof v !== "object").slice(0, 3).map(([k, v]) => `${k} ${v}`).join(", ");
|
|
16855
|
+
}
|
|
16856
|
+
return String(x);
|
|
16857
|
+
}
|
|
16858
|
+
function bodyLines(value) {
|
|
16859
|
+
const list2 = items(value);
|
|
16860
|
+
if (list2) {
|
|
16861
|
+
const out = list2.slice(0, 8).map((x) => `- ${label(x)}`.slice(0, 200));
|
|
16862
|
+
return list2.length > 8 ? [...out, `\u2026and ${list2.length - 8} more`] : out;
|
|
16863
|
+
}
|
|
16864
|
+
if (value && typeof value === "object") {
|
|
16865
|
+
return Object.entries(value).filter(([k, v]) => v !== null && v !== void 0 && v !== "" && typeof v !== "object" && k !== "next").slice(0, 8).map(([k, v]) => `${k.replace(/_/g, " ")}: ${v}`.slice(0, 200));
|
|
16866
|
+
}
|
|
16867
|
+
return value === null || value === void 0 || value === "" ? [] : [String(value).slice(0, 600)];
|
|
16868
|
+
}
|
|
16869
|
+
function said(name, value) {
|
|
16870
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
16871
|
+
for (const k of ["say", "headline", "summary", "message"]) {
|
|
16872
|
+
const v = value[k];
|
|
16873
|
+
if (typeof v === "string" && v.trim()) return (v.trim().split("\n")[0] ?? "").slice(0, 240);
|
|
16874
|
+
}
|
|
16875
|
+
}
|
|
16876
|
+
const list2 = items(value);
|
|
16877
|
+
if (list2) {
|
|
16878
|
+
let noun = name.endsWith("_list") ? name.slice(0, -5).split("_").pop() ?? "item" : "item";
|
|
16879
|
+
if (noun.endsWith("s")) noun = noun.slice(0, -1);
|
|
16880
|
+
return list2.length ? `I found ${n(list2.length, noun)}.` : "There's nothing there yet.";
|
|
16881
|
+
}
|
|
16882
|
+
if (typeof value === "string") return (value.trim().split("\n")[0] ?? "").slice(0, 240) || "Done.";
|
|
16883
|
+
return "Here it is.";
|
|
16884
|
+
}
|
|
16885
|
+
var lowerFirst = (s) => /^[A-Za-z][a-z]/.test(s) ? s.charAt(0).toLowerCase() + s.slice(1) : s;
|
|
16886
|
+
function message(name, value, opts = {}) {
|
|
16887
|
+
const title = titleOf(name);
|
|
16888
|
+
if (opts.error) return { say: `That didn't work: ${opts.error}`.slice(0, 300), title, lines: [] };
|
|
16889
|
+
if (opts.preview) return { say: "This needs your yes first; nothing has changed yet.", title, lines: [opts.preview] };
|
|
16890
|
+
if (opts.done) return { say: `Done: ${lowerFirst(opts.done)}`, title, lines: bodyLines(value) };
|
|
16891
|
+
return { say: said(name, value), title, lines: bodyLines(value) };
|
|
16892
|
+
}
|
|
16893
|
+
function messageText(m) {
|
|
16894
|
+
const body = [m.title ? `**${m.title}**` : "", ...m.lines].filter(Boolean).join("\n");
|
|
16895
|
+
return [m.say, body].filter(Boolean).join("\n\n").trim();
|
|
16896
|
+
}
|
|
16897
|
+
|
|
16758
16898
|
// ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/util.js
|
|
16759
16899
|
var util_exports = {};
|
|
16760
16900
|
__export(util_exports, {
|
|
@@ -17343,8 +17483,8 @@ function prefixIssues(path2, issues) {
|
|
|
17343
17483
|
return iss;
|
|
17344
17484
|
});
|
|
17345
17485
|
}
|
|
17346
|
-
function unwrapMessage(
|
|
17347
|
-
return typeof
|
|
17486
|
+
function unwrapMessage(message2) {
|
|
17487
|
+
return typeof message2 === "string" ? message2 : message2?.message;
|
|
17348
17488
|
}
|
|
17349
17489
|
function sizeCaps(defChecks) {
|
|
17350
17490
|
const caps = [];
|
|
@@ -17374,7 +17514,7 @@ function finalizeIssue(iss, ctx, config2) {
|
|
|
17374
17514
|
iss.schema = iss.inst;
|
|
17375
17515
|
}
|
|
17376
17516
|
const schemaError = iss.schema !== iss.inst ? iss.schema?._zod.def?.error : void 0;
|
|
17377
|
-
const
|
|
17517
|
+
const message2 = iss.message ? iss.message : unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(schemaError?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config2.customError?.(iss)) ?? unwrapMessage(config2.localeError?.(iss)) ?? "Invalid input";
|
|
17378
17518
|
const full = {};
|
|
17379
17519
|
for (const k of Object.keys(iss)) {
|
|
17380
17520
|
if (k === "inst" || k === "schema" || k === "continue" || k === "input" || k === "__proto__")
|
|
@@ -17382,7 +17522,7 @@ function finalizeIssue(iss, ctx, config2) {
|
|
|
17382
17522
|
full[k] = iss[k];
|
|
17383
17523
|
}
|
|
17384
17524
|
full.path ?? (full.path = []);
|
|
17385
|
-
full.message =
|
|
17525
|
+
full.message = message2;
|
|
17386
17526
|
if (ctx?.reportInput) {
|
|
17387
17527
|
full.input = iss.input;
|
|
17388
17528
|
}
|
|
@@ -18998,10 +19138,10 @@ function capSize(inst, size) {
|
|
|
18998
19138
|
const cap = Math.min(...caps.map((c) => c[0]));
|
|
18999
19139
|
const parse3 = inst._zod.parse;
|
|
19000
19140
|
inst._zod.parse = (payload, ctx) => {
|
|
19001
|
-
const
|
|
19002
|
-
if (
|
|
19141
|
+
const n2 = size(payload.value);
|
|
19142
|
+
if (n2 > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
|
|
19003
19143
|
for (const [max, ch] of sizeCaps(inst._zod.def.checks)) {
|
|
19004
|
-
if (
|
|
19144
|
+
if (n2 > max && ch._zod.def.when(payload)) {
|
|
19005
19145
|
const start = payload.issues.length;
|
|
19006
19146
|
ch._zod.check(payload);
|
|
19007
19147
|
payload.issues[start].continue = false;
|
|
@@ -21097,12 +21237,12 @@ function initializeContext(params) {
|
|
|
21097
21237
|
external: params?.external ?? void 0
|
|
21098
21238
|
};
|
|
21099
21239
|
}
|
|
21100
|
-
function handleUnrepresentable(schema, ctx, json, params,
|
|
21101
|
-
const result = typeof ctx.unrepresentable === "function" ? ctx.unrepresentable({ zodSchema: schema, path: params.path, message }) : ctx.unrepresentable;
|
|
21240
|
+
function handleUnrepresentable(schema, ctx, json, params, message2) {
|
|
21241
|
+
const result = typeof ctx.unrepresentable === "function" ? ctx.unrepresentable({ zodSchema: schema, path: params.path, message: message2 }) : ctx.unrepresentable;
|
|
21102
21242
|
if (result === "any")
|
|
21103
21243
|
return false;
|
|
21104
21244
|
if (result === void 0 || result === "throw")
|
|
21105
|
-
throw new Error(
|
|
21245
|
+
throw new Error(message2);
|
|
21106
21246
|
Object.assign(json, result);
|
|
21107
21247
|
return true;
|
|
21108
21248
|
}
|
|
@@ -22795,17 +22935,17 @@ var ZodArray = /* @__PURE__ */ $constructor("ZodArray", (inst, def) => {
|
|
|
22795
22935
|
inst._zod.processJSONSchema = (ctx, json, params) => arrayProcessor(inst, ctx, json, params);
|
|
22796
22936
|
inst.element = def.element;
|
|
22797
22937
|
}, {
|
|
22798
|
-
min(
|
|
22799
|
-
return this.check(_minLength(
|
|
22938
|
+
min(n2, params) {
|
|
22939
|
+
return this.check(_minLength(n2, params));
|
|
22800
22940
|
},
|
|
22801
22941
|
nonempty(params) {
|
|
22802
22942
|
return this.check(_minLength(1, params));
|
|
22803
22943
|
},
|
|
22804
|
-
max(
|
|
22805
|
-
return this.check(_maxLength(
|
|
22944
|
+
max(n2, params) {
|
|
22945
|
+
return this.check(_maxLength(n2, params));
|
|
22806
22946
|
},
|
|
22807
|
-
length(
|
|
22808
|
-
return this.check(_length(
|
|
22947
|
+
length(n2, params) {
|
|
22948
|
+
return this.check(_length(n2, params));
|
|
22809
22949
|
},
|
|
22810
22950
|
unwrap() {
|
|
22811
22951
|
return this.element;
|
|
@@ -24709,8 +24849,8 @@ var ServerResultSchema = union([
|
|
|
24709
24849
|
CreateTaskResultSchema
|
|
24710
24850
|
]);
|
|
24711
24851
|
var McpError = class _McpError extends Error {
|
|
24712
|
-
constructor(code,
|
|
24713
|
-
super(`MCP error ${code}: ${
|
|
24852
|
+
constructor(code, message2, data) {
|
|
24853
|
+
super(`MCP error ${code}: ${message2}`);
|
|
24714
24854
|
this.code = code;
|
|
24715
24855
|
this.data = data;
|
|
24716
24856
|
this.name = "McpError";
|
|
@@ -24718,19 +24858,19 @@ var McpError = class _McpError extends Error {
|
|
|
24718
24858
|
/**
|
|
24719
24859
|
* Factory method to create the appropriate error type based on the error code and data
|
|
24720
24860
|
*/
|
|
24721
|
-
static fromError(code,
|
|
24861
|
+
static fromError(code, message2, data) {
|
|
24722
24862
|
if (code === ErrorCode.UrlElicitationRequired && data) {
|
|
24723
24863
|
const errorData = data;
|
|
24724
24864
|
if (errorData.elicitations) {
|
|
24725
|
-
return new UrlElicitationRequiredError(errorData.elicitations,
|
|
24865
|
+
return new UrlElicitationRequiredError(errorData.elicitations, message2);
|
|
24726
24866
|
}
|
|
24727
24867
|
}
|
|
24728
|
-
return new _McpError(code,
|
|
24868
|
+
return new _McpError(code, message2, data);
|
|
24729
24869
|
}
|
|
24730
24870
|
};
|
|
24731
24871
|
var UrlElicitationRequiredError = class extends McpError {
|
|
24732
|
-
constructor(elicitations,
|
|
24733
|
-
super(ErrorCode.UrlElicitationRequired,
|
|
24872
|
+
constructor(elicitations, message2 = `URL elicitation${elicitations.length > 1 ? "s" : ""} required`) {
|
|
24873
|
+
super(ErrorCode.UrlElicitationRequired, message2, {
|
|
24734
24874
|
elicitations
|
|
24735
24875
|
});
|
|
24736
24876
|
}
|
|
@@ -24816,15 +24956,15 @@ var Protocol = class {
|
|
|
24816
24956
|
let queuedMessage;
|
|
24817
24957
|
while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
|
|
24818
24958
|
if (queuedMessage.type === "response" || queuedMessage.type === "error") {
|
|
24819
|
-
const
|
|
24820
|
-
const requestId =
|
|
24959
|
+
const message2 = queuedMessage.message;
|
|
24960
|
+
const requestId = message2.id;
|
|
24821
24961
|
const resolver = this._requestResolvers.get(requestId);
|
|
24822
24962
|
if (resolver) {
|
|
24823
24963
|
this._requestResolvers.delete(requestId);
|
|
24824
24964
|
if (queuedMessage.type === "response") {
|
|
24825
|
-
resolver(
|
|
24965
|
+
resolver(message2);
|
|
24826
24966
|
} else {
|
|
24827
|
-
const errorMessage3 =
|
|
24967
|
+
const errorMessage3 = message2;
|
|
24828
24968
|
const error2 = new McpError(errorMessage3.error.code, errorMessage3.error.message, errorMessage3.error.data);
|
|
24829
24969
|
resolver(error2);
|
|
24830
24970
|
}
|
|
@@ -24963,16 +25103,16 @@ var Protocol = class {
|
|
|
24963
25103
|
this._onerror(error2);
|
|
24964
25104
|
};
|
|
24965
25105
|
const _onmessage = this._transport?.onmessage;
|
|
24966
|
-
this._transport.onmessage = (
|
|
24967
|
-
_onmessage?.(
|
|
24968
|
-
if (isJSONRPCResultResponse(
|
|
24969
|
-
this._onresponse(
|
|
24970
|
-
} else if (isJSONRPCRequest(
|
|
24971
|
-
this._onrequest(
|
|
24972
|
-
} else if (isJSONRPCNotification(
|
|
24973
|
-
this._onnotification(
|
|
25106
|
+
this._transport.onmessage = (message2, extra) => {
|
|
25107
|
+
_onmessage?.(message2, extra);
|
|
25108
|
+
if (isJSONRPCResultResponse(message2) || isJSONRPCErrorResponse(message2)) {
|
|
25109
|
+
this._onresponse(message2);
|
|
25110
|
+
} else if (isJSONRPCRequest(message2)) {
|
|
25111
|
+
this._onrequest(message2, extra);
|
|
25112
|
+
} else if (isJSONRPCNotification(message2)) {
|
|
25113
|
+
this._onnotification(message2);
|
|
24974
25114
|
} else {
|
|
24975
|
-
this._onerror(new Error(`Unknown message type: ${JSON.stringify(
|
|
25115
|
+
this._onerror(new Error(`Unknown message type: ${JSON.stringify(message2)}`));
|
|
24976
25116
|
}
|
|
24977
25117
|
};
|
|
24978
25118
|
await this._transport.start();
|
|
@@ -25582,12 +25722,12 @@ var Protocol = class {
|
|
|
25582
25722
|
* the error appropriately (e.g., by failing the task, logging, etc.). The Protocol layer
|
|
25583
25723
|
* simply propagates the error.
|
|
25584
25724
|
*/
|
|
25585
|
-
async _enqueueTaskMessage(taskId,
|
|
25725
|
+
async _enqueueTaskMessage(taskId, message2, sessionId) {
|
|
25586
25726
|
if (!this._taskStore || !this._taskMessageQueue) {
|
|
25587
25727
|
throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
|
|
25588
25728
|
}
|
|
25589
25729
|
const maxQueueSize = this._options?.maxTaskQueueSize;
|
|
25590
|
-
await this._taskMessageQueue.enqueue(taskId,
|
|
25730
|
+
await this._taskMessageQueue.enqueue(taskId, message2, sessionId, maxQueueSize);
|
|
25591
25731
|
}
|
|
25592
25732
|
/**
|
|
25593
25733
|
* Clears the message queue for a task and rejects any pending request resolvers.
|
|
@@ -25597,9 +25737,9 @@ var Protocol = class {
|
|
|
25597
25737
|
async _clearTaskQueue(taskId, sessionId) {
|
|
25598
25738
|
if (this._taskMessageQueue) {
|
|
25599
25739
|
const messages = await this._taskMessageQueue.dequeueAll(taskId, sessionId);
|
|
25600
|
-
for (const
|
|
25601
|
-
if (
|
|
25602
|
-
const requestId =
|
|
25740
|
+
for (const message2 of messages) {
|
|
25741
|
+
if (message2.type === "request" && isJSONRPCRequest(message2.message)) {
|
|
25742
|
+
const requestId = message2.message.id;
|
|
25603
25743
|
const resolver = this._requestResolvers.get(requestId);
|
|
25604
25744
|
if (resolver) {
|
|
25605
25745
|
resolver(new McpError(ErrorCode.InternalError, "Task cancelled or completed"));
|
|
@@ -26764,14 +26904,14 @@ function toolArgs(args) {
|
|
|
26764
26904
|
return out;
|
|
26765
26905
|
}
|
|
26766
26906
|
function withIdempotency(api2, approvalId) {
|
|
26767
|
-
let
|
|
26907
|
+
let n2 = 0;
|
|
26768
26908
|
return {
|
|
26769
26909
|
...api2,
|
|
26770
26910
|
request: (path2, init = {}) => {
|
|
26771
26911
|
const method = (init.method ?? "GET").toUpperCase();
|
|
26772
26912
|
if (method === "GET" || method === "HEAD") return api2.request(path2, init);
|
|
26773
26913
|
const headers = new Headers(init.headers);
|
|
26774
|
-
headers.set("Idempotency-Key", idempotencyKey(approvalId, 0,
|
|
26914
|
+
headers.set("Idempotency-Key", idempotencyKey(approvalId, 0, n2++));
|
|
26775
26915
|
return api2.request(path2, { ...init, headers });
|
|
26776
26916
|
}
|
|
26777
26917
|
};
|
|
@@ -26779,13 +26919,18 @@ function withIdempotency(api2, approvalId) {
|
|
|
26779
26919
|
var text2 = (value) => [
|
|
26780
26920
|
{ type: "text", text: typeof value === "string" ? value : JSON.stringify(value) }
|
|
26781
26921
|
];
|
|
26782
|
-
function ok(result, extra) {
|
|
26922
|
+
function ok(result, extra, msg) {
|
|
26783
26923
|
const value = result ?? { ok: true };
|
|
26784
26924
|
const structured = value && typeof value === "object" && !Array.isArray(value) ? value : { items: value };
|
|
26785
|
-
return { content: text2(value), structuredContent: { ...structured, ...extra } };
|
|
26925
|
+
if (!msg) return { content: text2(value), structuredContent: { ...structured, ...extra } };
|
|
26926
|
+
return {
|
|
26927
|
+
content: [...text2(messageText(msg)), ...text2(value)],
|
|
26928
|
+
structuredContent: { ...structured, ...extra, message: msg }
|
|
26929
|
+
};
|
|
26786
26930
|
}
|
|
26787
|
-
function fail(
|
|
26788
|
-
return { content: text2({ error:
|
|
26931
|
+
function fail(error2, tool3) {
|
|
26932
|
+
if (!tool3) return { content: text2({ error: error2 }), isError: true };
|
|
26933
|
+
return { content: [...text2(messageText(message(tool3, void 0, { error: error2 }))), ...text2({ error: error2 })], isError: true };
|
|
26789
26934
|
}
|
|
26790
26935
|
function errorMessage2(e) {
|
|
26791
26936
|
if (e instanceof SignInRequiredError) return "The sign-in has expired. Reconnect CMO.so and try again.";
|
|
@@ -26925,7 +27070,10 @@ function createMcpServer(deps) {
|
|
|
26925
27070
|
);
|
|
26926
27071
|
const callArgs = approval ? withFreshFiles(t, approval.calls[0]?.args ?? {}, toolArgs(args)) : toolArgs(args);
|
|
26927
27072
|
const ctx = { api: api2, domain, client: "mcp" };
|
|
26928
|
-
if (!isWrite(t))
|
|
27073
|
+
if (!isWrite(t)) {
|
|
27074
|
+
const value = await t.run(ctx, callArgs);
|
|
27075
|
+
return ok(value, viewForTool(t.name) ? { workspace: domain } : void 0, message(t.name, value));
|
|
27076
|
+
}
|
|
26929
27077
|
let standing = null;
|
|
26930
27078
|
if (!approval && !deps.previewOnly && domain && isStanding(t.name)) {
|
|
26931
27079
|
const claim2 = await api2.account?.claimStanding({ website: domain, tool: t.name, units: standingUnits(t.name, callArgs) }).catch(() => null);
|
|
@@ -26947,14 +27095,19 @@ function createMcpServer(deps) {
|
|
|
26947
27095
|
const calls = [{ name: t.name, args: callArgs }];
|
|
26948
27096
|
const summary2 = t.confirm?.(callArgs, "en") ?? t.description;
|
|
26949
27097
|
const cost2 = await previewCost(api2, domain, t);
|
|
26950
|
-
|
|
26951
|
-
|
|
26952
|
-
|
|
26953
|
-
|
|
26954
|
-
|
|
26955
|
-
|
|
26956
|
-
|
|
26957
|
-
|
|
27098
|
+
const preview = cost2 ? `${summary2} ${cost2}` : summary2;
|
|
27099
|
+
return ok(
|
|
27100
|
+
{
|
|
27101
|
+
status: "needs_confirmation",
|
|
27102
|
+
preview,
|
|
27103
|
+
risk: t.risk,
|
|
27104
|
+
workspace: domain,
|
|
27105
|
+
confirmation: signer.sign({ calls, principal, domain }),
|
|
27106
|
+
next: "Show the preview to the user. If they agree, call this tool again with confirm: true and this confirmation (it runs exactly what was previewed). Nothing has changed yet."
|
|
27107
|
+
},
|
|
27108
|
+
void 0,
|
|
27109
|
+
message(t.name, void 0, { preview })
|
|
27110
|
+
);
|
|
26958
27111
|
}
|
|
26959
27112
|
const summary = `${t.confirm?.(callArgs, "en") ?? t.description}${standing ? ` (standing permission #${standing})` : ""}`;
|
|
26960
27113
|
try {
|
|
@@ -26962,14 +27115,14 @@ function createMcpServer(deps) {
|
|
|
26962
27115
|
const added = t.name === "website_add" ? result?.domain : null;
|
|
26963
27116
|
const where = typeof added === "string" && added ? added : domain;
|
|
26964
27117
|
await deps.audit?.({ domain: where, actions: [{ tool: t.name, summary, ok: true, action_id: approval.id }] }).catch(() => void 0);
|
|
26965
|
-
return ok(result);
|
|
27118
|
+
return ok(result, void 0, message(t.name, result, { done: summary }));
|
|
26966
27119
|
} catch (e) {
|
|
26967
27120
|
const error2 = errorMessage2(e);
|
|
26968
27121
|
await deps.audit?.({ domain, actions: [{ tool: t.name, summary, ok: false, error: error2, action_id: approval.id }] }).catch(() => void 0);
|
|
26969
|
-
return fail(error2);
|
|
27122
|
+
return fail(error2, t.name);
|
|
26970
27123
|
}
|
|
26971
27124
|
} catch (e) {
|
|
26972
|
-
return fail(errorMessage2(e));
|
|
27125
|
+
return fail(errorMessage2(e), t.name);
|
|
26973
27126
|
}
|
|
26974
27127
|
});
|
|
26975
27128
|
server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({
|
|
@@ -27099,8 +27252,8 @@ var ReadBuffer = class {
|
|
|
27099
27252
|
function deserializeMessage(line) {
|
|
27100
27253
|
return JSONRPCMessageSchema.parse(JSON.parse(line));
|
|
27101
27254
|
}
|
|
27102
|
-
function serializeMessage(
|
|
27103
|
-
return JSON.stringify(
|
|
27255
|
+
function serializeMessage(message2) {
|
|
27256
|
+
return JSON.stringify(message2) + "\n";
|
|
27104
27257
|
}
|
|
27105
27258
|
|
|
27106
27259
|
// ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.1_zod@4.6.7/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
@@ -27138,11 +27291,11 @@ var StdioServerTransport = class {
|
|
|
27138
27291
|
processReadBuffer() {
|
|
27139
27292
|
while (true) {
|
|
27140
27293
|
try {
|
|
27141
|
-
const
|
|
27142
|
-
if (
|
|
27294
|
+
const message2 = this._readBuffer.readMessage();
|
|
27295
|
+
if (message2 === null) {
|
|
27143
27296
|
break;
|
|
27144
27297
|
}
|
|
27145
|
-
this.onmessage?.(
|
|
27298
|
+
this.onmessage?.(message2);
|
|
27146
27299
|
} catch (error2) {
|
|
27147
27300
|
this.onerror?.(error2);
|
|
27148
27301
|
}
|
|
@@ -27158,9 +27311,9 @@ var StdioServerTransport = class {
|
|
|
27158
27311
|
this._readBuffer.clear();
|
|
27159
27312
|
this.onclose?.();
|
|
27160
27313
|
}
|
|
27161
|
-
send(
|
|
27314
|
+
send(message2) {
|
|
27162
27315
|
return new Promise((resolve) => {
|
|
27163
|
-
const json = serializeMessage(
|
|
27316
|
+
const json = serializeMessage(message2);
|
|
27164
27317
|
if (this._stdout.write(json)) {
|
|
27165
27318
|
resolve();
|
|
27166
27319
|
} else {
|
|
@@ -27188,8 +27341,8 @@ async function serveStdio(version2) {
|
|
|
27188
27341
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
27189
27342
|
import { createInterface } from "node:readline/promises";
|
|
27190
27343
|
var CliError = class extends Error {
|
|
27191
|
-
constructor(
|
|
27192
|
-
super(
|
|
27344
|
+
constructor(message2, code = 2) {
|
|
27345
|
+
super(message2);
|
|
27193
27346
|
this.code = code;
|
|
27194
27347
|
}
|
|
27195
27348
|
};
|
|
@@ -27244,14 +27397,14 @@ async function cost(api2, domain, t) {
|
|
|
27244
27397
|
}
|
|
27245
27398
|
function withIdempotency2(api2) {
|
|
27246
27399
|
const base = randomUUID3();
|
|
27247
|
-
let
|
|
27400
|
+
let n2 = 0;
|
|
27248
27401
|
return {
|
|
27249
27402
|
...api2,
|
|
27250
27403
|
request: (path2, init = {}) => {
|
|
27251
27404
|
const method = (init.method ?? "GET").toUpperCase();
|
|
27252
27405
|
if (method === "GET" || method === "HEAD") return api2.request(path2, init);
|
|
27253
27406
|
const headers = new Headers(init.headers);
|
|
27254
|
-
headers.set("Idempotency-Key", `${base}-${
|
|
27407
|
+
headers.set("Idempotency-Key", `${base}-${n2++}`);
|
|
27255
27408
|
return api2.request(path2, { ...init, headers });
|
|
27256
27409
|
}
|
|
27257
27410
|
};
|
|
@@ -27317,9 +27470,9 @@ async function tool2(opts, name, args = {}, human) {
|
|
|
27317
27470
|
print(out.result, opts.json, human);
|
|
27318
27471
|
}
|
|
27319
27472
|
var ids2 = (list2) => list2.map((x) => {
|
|
27320
|
-
const
|
|
27321
|
-
if (!Number.isInteger(
|
|
27322
|
-
return
|
|
27473
|
+
const n2 = Number(x);
|
|
27474
|
+
if (!Number.isInteger(n2)) throw new CliError(`Not an id: ${x}`);
|
|
27475
|
+
return n2;
|
|
27323
27476
|
});
|
|
27324
27477
|
var program2 = new Command("cmo").description("CMO.so on the command line. Docs: https://ai.cmo.so/hot/mcp").version(VERSION2).option("--json", "machine-readable output").option("-w, --workspace <domain>", "the website to act on").option("-y, --yes", "don't ask before changing things (for scripts and CI)").option("--dry-run", "show what a change would do, without doing it").showHelpAfterError();
|
|
27325
27478
|
program2.command("login").description("sign in in your browser (device code)").option("--no-browser", "only print the link").action(
|
|
@@ -27571,6 +27724,17 @@ social.command("carousel <id>").description("a LinkedIn post with a set of pictu
|
|
|
27571
27724
|
});
|
|
27572
27725
|
})
|
|
27573
27726
|
);
|
|
27727
|
+
social.command("post-now <id>").description("post it on its channel now, not at its posting time (even while posting is paused)").action(act(async (opts, id) => tool2(opts, "social_publish_now", { id: ids2([id])[0] })));
|
|
27728
|
+
social.command("edit-posted <id> [text...]").description("change a post that has gone out (LinkedIn edits it in place, keeping likes and comments)").option("--repost", "take it down and put it up again instead").action(
|
|
27729
|
+
act(
|
|
27730
|
+
async (opts, id, text3) => tool2(opts, "social_posted_update", {
|
|
27731
|
+
id: ids2([id])[0],
|
|
27732
|
+
...text3.length ? { social_copy: text3.join(" ") } : {},
|
|
27733
|
+
...opts.repost ? { repost: true } : {}
|
|
27734
|
+
})
|
|
27735
|
+
)
|
|
27736
|
+
);
|
|
27737
|
+
social.command("delete-posted <id>").description("take a post that has gone out down from its channel, with its likes and comments").action(act(async (opts, id) => tool2(opts, "social_posted_delete", { id: ids2([id])[0] })));
|
|
27574
27738
|
social.command("skip <id>").description("skip a draft").action(act(async (opts, id) => tool2(opts, "social_skip", { id: ids2([id])[0] })));
|
|
27575
27739
|
social.command("restore <id>").description("bring a skipped draft back").action(act(async (opts, id) => tool2(opts, "social_restore", { id: ids2([id])[0] })));
|
|
27576
27740
|
social.command("draft <topic...>").description("add a post idea for Maggie to write (every connected channel unless --channel)").option("--summary <text>", "what the post should say").option("--channel <names>", "linkedin, facebook, instagram, google_business (comma-separated)").action(
|
|
@@ -27778,12 +27942,12 @@ feedback.command("send <summary...>", { isDefault: true }).description("send fee
|
|
|
27778
27942
|
);
|
|
27779
27943
|
feedback.command("ls").description("what you sent, its status and the team's reply").action(
|
|
27780
27944
|
act(async (opts) => {
|
|
27781
|
-
const { items } = await api().feedback.mine();
|
|
27945
|
+
const { items: items2 } = await api().feedback.mine();
|
|
27782
27946
|
print(
|
|
27783
|
-
|
|
27947
|
+
items2,
|
|
27784
27948
|
opts.json,
|
|
27785
|
-
() =>
|
|
27786
|
-
|
|
27949
|
+
() => items2.length ? table(
|
|
27950
|
+
items2.map((f) => ({
|
|
27787
27951
|
sent: f.created_at.slice(0, 10),
|
|
27788
27952
|
type: f.type,
|
|
27789
27953
|
status: f.status.replace("_", " ") + (f.unread ? " (new reply)" : ""),
|