ponch-mcp-server 1.0.88 → 1.0.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +48 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -171,29 +171,36 @@ var Session = class {
|
|
|
171
171
|
this.context.brandId = brandId;
|
|
172
172
|
}
|
|
173
173
|
/**
|
|
174
|
-
* Cambia la brand activa SIN cambiar tenant. Disponible para
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
174
|
+
* Cambia la brand activa SIN cambiar tenant. Disponible para:
|
|
175
|
+
* - User Modo B con multi-brand (brands.length > 1) — agency mode.
|
|
176
|
+
* - Super_admin Modo A (canSwitchTenant=true) — service account
|
|
177
|
+
* puede operar cualquier brand dentro del tenant activo seteado
|
|
178
|
+
* previamente vía set_context.
|
|
179
|
+
*
|
|
180
|
+
* DEUDA 3 sesión 211.1 H/I + fix J post-smoke 1.0.88.
|
|
178
181
|
*
|
|
179
182
|
* Lanza si:
|
|
180
|
-
* - El user no tiene multi-brand
|
|
181
|
-
* - El brandId
|
|
182
|
-
*
|
|
183
|
-
*
|
|
183
|
+
* - El user no es super_admin Y no tiene multi-brand.
|
|
184
|
+
* - El brandId NO está en lista del user (defensa cross-brand Modo B).
|
|
185
|
+
* Para super_admin Modo A se delega validación al helper (Firestore
|
|
186
|
+
* existence check) — no hay "lista accesible" porque tiene acceso
|
|
187
|
+
* total al tenant.
|
|
184
188
|
*/
|
|
185
189
|
setBrand(brandId) {
|
|
186
190
|
const brands = this._authContext.brands ?? [];
|
|
187
|
-
|
|
191
|
+
const isSuperAdmin = this._authContext.canSwitchTenant;
|
|
192
|
+
if (!isSuperAdmin && brands.length <= 1) {
|
|
188
193
|
throw new Error(
|
|
189
|
-
`select_brand requires multi-brand access. This user has access to ${brands.length} brand(s).`
|
|
194
|
+
`select_brand requires multi-brand access or super_admin. This user has access to ${brands.length} brand(s) and is not super_admin.`
|
|
190
195
|
);
|
|
191
196
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
+
if (!isSuperAdmin) {
|
|
198
|
+
const allowed = brands.some((b) => b.id === brandId);
|
|
199
|
+
if (!allowed) {
|
|
200
|
+
throw new Error(
|
|
201
|
+
`Brand "${brandId}" is not in the user's accessible brands list [${brands.map((b) => b.id).join(", ")}].`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
197
204
|
}
|
|
198
205
|
this.context.brandId = brandId;
|
|
199
206
|
this._authContext.brandId = brandId;
|
|
@@ -1525,7 +1532,7 @@ var ORIGENES_CONTENIDO = [
|
|
|
1525
1532
|
"imported"
|
|
1526
1533
|
// sync Shopify/WordPress
|
|
1527
1534
|
];
|
|
1528
|
-
var
|
|
1535
|
+
var ESTADO_CONTENIDO = {
|
|
1529
1536
|
BORRADOR: "borrador",
|
|
1530
1537
|
GENERADO: "generado",
|
|
1531
1538
|
PENDIENTE_APROBACION: "pendiente_aprobacion",
|
|
@@ -1723,7 +1730,7 @@ var ESTADOS_FOTO = [
|
|
|
1723
1730
|
var ESTRATEGIAS_EDICION = ["gemini_edit", "tal_cual"];
|
|
1724
1731
|
var FotoEstadoEnum = import_zod13.z.enum(ESTADOS_FOTO);
|
|
1725
1732
|
var FotoEstrategiaEdicionEnum = import_zod13.z.enum(ESTRATEGIAS_EDICION);
|
|
1726
|
-
var
|
|
1733
|
+
var ESTADO_FOTO = {
|
|
1727
1734
|
NUEVA: "nueva",
|
|
1728
1735
|
PROCESANDO: "procesando",
|
|
1729
1736
|
EDITADA: "editada",
|
|
@@ -11869,7 +11876,7 @@ async function calendarSlotUpdater(input) {
|
|
|
11869
11876
|
const contenidoQuery = await db.collection("tenants").doc(tenantId).collection("marketing_contenido").where("brandId", "==", brandId).where("calendarioItemRef", "==", oldContenidoRef).limit(10).get();
|
|
11870
11877
|
contenidosADescartar = contenidoQuery.docs.filter((c) => {
|
|
11871
11878
|
const data = c.data();
|
|
11872
|
-
return data.estado !== "descartado" && data.estado !==
|
|
11879
|
+
return data.estado !== "descartado" && data.estado !== ESTADO_CONTENIDO.PUBLICADO;
|
|
11873
11880
|
});
|
|
11874
11881
|
}
|
|
11875
11882
|
if (accionContenidoExistente === "nuevo_slot") {
|
|
@@ -12784,7 +12791,7 @@ async function contenidoApprover(input) {
|
|
|
12784
12791
|
}
|
|
12785
12792
|
const data = snap.data();
|
|
12786
12793
|
const estadoActual = typeof data.estado === "string" ? data.estado : "";
|
|
12787
|
-
if (!esTransicionValida(estadoActual,
|
|
12794
|
+
if (!esTransicionValida(estadoActual, ESTADO_CONTENIDO.APROBADO)) {
|
|
12788
12795
|
return {
|
|
12789
12796
|
ok: false,
|
|
12790
12797
|
code: "INVALID_STATE_TRANSITION",
|
|
@@ -12792,7 +12799,7 @@ async function contenidoApprover(input) {
|
|
|
12792
12799
|
};
|
|
12793
12800
|
}
|
|
12794
12801
|
await ref.update({
|
|
12795
|
-
estado:
|
|
12802
|
+
estado: ESTADO_CONTENIDO.APROBADO,
|
|
12796
12803
|
aprobadoAt: import_firebase_admin8.firestore.FieldValue.serverTimestamp(),
|
|
12797
12804
|
aprobadoPorId: actor.uid,
|
|
12798
12805
|
aprobadoPorNombre: actor.nombre,
|
|
@@ -12803,7 +12810,7 @@ async function contenidoApprover(input) {
|
|
|
12803
12810
|
ok: true,
|
|
12804
12811
|
contenidoId,
|
|
12805
12812
|
estadoAnterior: estadoActual,
|
|
12806
|
-
nuevoEstado:
|
|
12813
|
+
nuevoEstado: ESTADO_CONTENIDO.APROBADO
|
|
12807
12814
|
};
|
|
12808
12815
|
}
|
|
12809
12816
|
var ParamsSchema12 = import_zod47.z.object({
|
|
@@ -12873,7 +12880,7 @@ async function contenidoRejecter(input) {
|
|
|
12873
12880
|
}
|
|
12874
12881
|
const data = snap.data();
|
|
12875
12882
|
const estadoActual = typeof data.estado === "string" ? data.estado : "";
|
|
12876
|
-
if (!esTransicionValida(estadoActual,
|
|
12883
|
+
if (!esTransicionValida(estadoActual, ESTADO_CONTENIDO.RECHAZADO)) {
|
|
12877
12884
|
return {
|
|
12878
12885
|
ok: false,
|
|
12879
12886
|
code: "INVALID_STATE_TRANSITION",
|
|
@@ -12881,7 +12888,7 @@ async function contenidoRejecter(input) {
|
|
|
12881
12888
|
};
|
|
12882
12889
|
}
|
|
12883
12890
|
await ref.update({
|
|
12884
|
-
estado:
|
|
12891
|
+
estado: ESTADO_CONTENIDO.RECHAZADO,
|
|
12885
12892
|
rechazadoAt: import_firebase_admin9.firestore.FieldValue.serverTimestamp(),
|
|
12886
12893
|
rechazadoMotivo: motivo,
|
|
12887
12894
|
rechazadoPorId: actor.uid,
|
|
@@ -12893,7 +12900,7 @@ async function contenidoRejecter(input) {
|
|
|
12893
12900
|
ok: true,
|
|
12894
12901
|
contenidoId,
|
|
12895
12902
|
estadoAnterior: estadoActual,
|
|
12896
|
-
nuevoEstado:
|
|
12903
|
+
nuevoEstado: ESTADO_CONTENIDO.RECHAZADO,
|
|
12897
12904
|
motivo
|
|
12898
12905
|
};
|
|
12899
12906
|
}
|
|
@@ -13178,7 +13185,7 @@ async function photoDescarter(input) {
|
|
|
13178
13185
|
}
|
|
13179
13186
|
const data = snap.data();
|
|
13180
13187
|
const estadoActual = typeof data.estado === "string" ? data.estado : "";
|
|
13181
|
-
if (!validarTransicionFoto(estadoActual,
|
|
13188
|
+
if (!validarTransicionFoto(estadoActual, ESTADO_FOTO.DESCARTADA)) {
|
|
13182
13189
|
return {
|
|
13183
13190
|
ok: false,
|
|
13184
13191
|
code: "INVALID_STATE_TRANSITION",
|
|
@@ -13186,7 +13193,7 @@ async function photoDescarter(input) {
|
|
|
13186
13193
|
};
|
|
13187
13194
|
}
|
|
13188
13195
|
await ref.update({
|
|
13189
|
-
estado:
|
|
13196
|
+
estado: ESTADO_FOTO.DESCARTADA,
|
|
13190
13197
|
descartadaAt: import_firebase_admin11.firestore.FieldValue.serverTimestamp(),
|
|
13191
13198
|
descartadaPorId: actor.uid,
|
|
13192
13199
|
descartadaPorNombre: actor.nombre,
|
|
@@ -13197,7 +13204,7 @@ async function photoDescarter(input) {
|
|
|
13197
13204
|
ok: true,
|
|
13198
13205
|
fotoId,
|
|
13199
13206
|
estadoAnterior: estadoActual,
|
|
13200
|
-
nuevoEstado:
|
|
13207
|
+
nuevoEstado: ESTADO_FOTO.DESCARTADA
|
|
13201
13208
|
};
|
|
13202
13209
|
}
|
|
13203
13210
|
var ParamsSchema16 = import_zod51.z.object({
|
|
@@ -13268,7 +13275,7 @@ async function photoEditadaMarker(input) {
|
|
|
13268
13275
|
const data = snap.data();
|
|
13269
13276
|
const estadoActual = typeof data.estado === "string" ? data.estado : "";
|
|
13270
13277
|
const archivoOriginal = typeof data.archivoOriginal === "string" ? data.archivoOriginal : null;
|
|
13271
|
-
if (!validarTransicionFoto(estadoActual,
|
|
13278
|
+
if (!validarTransicionFoto(estadoActual, ESTADO_FOTO.EDITADA)) {
|
|
13272
13279
|
return {
|
|
13273
13280
|
ok: false,
|
|
13274
13281
|
code: "INVALID_STATE_TRANSITION",
|
|
@@ -13279,7 +13286,7 @@ async function photoEditadaMarker(input) {
|
|
|
13279
13286
|
return { ok: false, code: "FOTO_SIN_ARCHIVO_ORIGINAL", estadoActual };
|
|
13280
13287
|
}
|
|
13281
13288
|
await ref.update({
|
|
13282
|
-
estado:
|
|
13289
|
+
estado: ESTADO_FOTO.EDITADA,
|
|
13283
13290
|
archivoEditado: archivoOriginal,
|
|
13284
13291
|
fechaEdicion: import_firebase_admin12.firestore.FieldValue.serverTimestamp(),
|
|
13285
13292
|
marcadaEditadaPorId: actor.uid,
|
|
@@ -13291,7 +13298,7 @@ async function photoEditadaMarker(input) {
|
|
|
13291
13298
|
ok: true,
|
|
13292
13299
|
fotoId,
|
|
13293
13300
|
estadoAnterior: estadoActual,
|
|
13294
|
-
nuevoEstado:
|
|
13301
|
+
nuevoEstado: ESTADO_FOTO.EDITADA,
|
|
13295
13302
|
archivoEditado: archivoOriginal
|
|
13296
13303
|
};
|
|
13297
13304
|
}
|
|
@@ -13444,7 +13451,7 @@ async function photoAssigner(input) {
|
|
|
13444
13451
|
return { ok: false, error: `Foto ${fotoId} no encontrada`, code: "PHOTO_NOT_FOUND" };
|
|
13445
13452
|
}
|
|
13446
13453
|
const foto = fotoQuery.docs[0].data();
|
|
13447
|
-
if (foto.estado !==
|
|
13454
|
+
if (foto.estado !== ESTADO_FOTO.EDITADA && foto.estado !== "usada") {
|
|
13448
13455
|
return {
|
|
13449
13456
|
ok: false,
|
|
13450
13457
|
error: `Foto en estado "${foto.estado}", debe ser "editada"`,
|
|
@@ -13861,7 +13868,7 @@ async function marketingPlanBuilder(input) {
|
|
|
13861
13868
|
}
|
|
13862
13869
|
const productosQ = await db.collection("productos").where("tenantId", "==", tenantId).limit(100).get();
|
|
13863
13870
|
const productos = productosQ.docs.map((d) => d.data());
|
|
13864
|
-
const histQ = await db.collection("tenants").doc(tenantId).collection("marketing_contenido").where("brandId", "==", brandId).where("estado", "==",
|
|
13871
|
+
const histQ = await db.collection("tenants").doc(tenantId).collection("marketing_contenido").where("brandId", "==", brandId).where("estado", "==", ESTADO_CONTENIDO.PUBLICADO).limit(20).get();
|
|
13865
13872
|
const historial = histQ.docs.map((d) => d.data());
|
|
13866
13873
|
const lastImportId = await resolveLastImportId(db, tenantId, brandId);
|
|
13867
13874
|
let colecciones = [];
|
|
@@ -14182,7 +14189,7 @@ async function contenidoWriter(input) {
|
|
|
14182
14189
|
tipo: tipo ?? "post",
|
|
14183
14190
|
keyword: keyword ?? null,
|
|
14184
14191
|
languageCode,
|
|
14185
|
-
estado:
|
|
14192
|
+
estado: ESTADO_CONTENIDO.PENDIENTE_APROBACION,
|
|
14186
14193
|
fotoId: fotoId ?? null,
|
|
14187
14194
|
mediaUrl: null,
|
|
14188
14195
|
calendarioItemRef: calendarioItemRef ?? null,
|
|
@@ -14308,7 +14315,7 @@ async function contenidoWriter(input) {
|
|
|
14308
14315
|
return {
|
|
14309
14316
|
ok: true,
|
|
14310
14317
|
contenidoId: id,
|
|
14311
|
-
estado:
|
|
14318
|
+
estado: ESTADO_CONTENIDO.PENDIENTE_APROBACION,
|
|
14312
14319
|
plataforma,
|
|
14313
14320
|
descartados,
|
|
14314
14321
|
pipelineLinked
|
|
@@ -14542,7 +14549,7 @@ async function weeklyContentBuilder(input) {
|
|
|
14542
14549
|
}
|
|
14543
14550
|
};
|
|
14544
14551
|
}
|
|
14545
|
-
const fotosQ = await db.collection("tenants").doc(tenantId).collection("marketing_fotos").where("brandId", "==", brandId).where("estado", "==",
|
|
14552
|
+
const fotosQ = await db.collection("tenants").doc(tenantId).collection("marketing_fotos").where("brandId", "==", brandId).where("estado", "==", ESTADO_FOTO.EDITADA).limit(20).get();
|
|
14546
14553
|
const fotosDisponibles = fotosQ.docs.map((d) => d.data());
|
|
14547
14554
|
const histQ = await db.collection("tenants").doc(tenantId).collection("marketing_contenido").where("brandId", "==", brandId).limit(20).get();
|
|
14548
14555
|
const historial = histQ.docs.map((d) => d.data());
|
|
@@ -14552,7 +14559,7 @@ async function weeklyContentBuilder(input) {
|
|
|
14552
14559
|
const blogStrategy = brand.blogStrategy;
|
|
14553
14560
|
const blogs = blogStrategy?.blogs ?? [];
|
|
14554
14561
|
const idiomas = brand.idiomas;
|
|
14555
|
-
const articulosQ = await db.collection("tenants").doc(tenantId).collection("marketing_contenido").where("brandId", "==", brandId).where("plataforma", "==", "shopify_blog").where("estado", "==",
|
|
14562
|
+
const articulosQ = await db.collection("tenants").doc(tenantId).collection("marketing_contenido").where("brandId", "==", brandId).where("plataforma", "==", "shopify_blog").where("estado", "==", ESTADO_CONTENIDO.PUBLICADO).limit(20).get();
|
|
14556
14563
|
const articulosExistentes = articulosQ.docs.map(
|
|
14557
14564
|
(d) => d.data()
|
|
14558
14565
|
);
|
|
@@ -16108,8 +16115,8 @@ async function buildTenantContext(db, tenantId, brandId) {
|
|
|
16108
16115
|
if (!configSnap.exists) return "";
|
|
16109
16116
|
const brand = configSnap.data();
|
|
16110
16117
|
const [fotosQ, contenidoQ, productosQ] = await Promise.all([
|
|
16111
|
-
db.collection("tenants").doc(tenantId).collection("marketing_fotos").where("brandId", "==", brandId).where("estado", "==",
|
|
16112
|
-
db.collection("tenants").doc(tenantId).collection("marketing_contenido").where("brandId", "==", brandId).where("estado", "==",
|
|
16118
|
+
db.collection("tenants").doc(tenantId).collection("marketing_fotos").where("brandId", "==", brandId).where("estado", "==", ESTADO_FOTO.EDITADA).limit(10).get(),
|
|
16119
|
+
db.collection("tenants").doc(tenantId).collection("marketing_contenido").where("brandId", "==", brandId).where("estado", "==", ESTADO_CONTENIDO.PUBLICADO).limit(10).get(),
|
|
16113
16120
|
db.collection("productos").where("tenantId", "==", tenantId).limit(50).get()
|
|
16114
16121
|
]);
|
|
16115
16122
|
const fotosEditadas = fotosQ.docs.map((d) => d.data());
|
|
@@ -16576,7 +16583,9 @@ function registerContextTools(server, session) {
|
|
|
16576
16583
|
}
|
|
16577
16584
|
);
|
|
16578
16585
|
}
|
|
16579
|
-
|
|
16586
|
+
const isMultiBrand = session.brands && session.brands.length > 1;
|
|
16587
|
+
const isSuperAdmin = session.canSwitchTenant;
|
|
16588
|
+
if (isMultiBrand || isSuperAdmin) {
|
|
16580
16589
|
server.tool(
|
|
16581
16590
|
"select_brand",
|
|
16582
16591
|
"Switch the active brand within your tenant. Use when you have multi-brand access (agency mode) and want to work with a different brand without passing brandId on every tool call. Does NOT change tenant.",
|