@okostream/mcp 0.12.3 → 0.12.5
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/server.js +58 -13
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -116223,7 +116223,7 @@ function sanitizeScopes(scopes) {
|
|
|
116223
116223
|
}
|
|
116224
116224
|
|
|
116225
116225
|
// build/version.js
|
|
116226
|
-
var OKO_MCP_VERSION = "0.12.
|
|
116226
|
+
var OKO_MCP_VERSION = "0.12.5";
|
|
116227
116227
|
|
|
116228
116228
|
// build/auth.js
|
|
116229
116229
|
var state = null;
|
|
@@ -116518,6 +116518,11 @@ async function readEvent(eventId, uid, mode = "read") {
|
|
|
116518
116518
|
|
|
116519
116519
|
// build/tools/imagePipeline.js
|
|
116520
116520
|
var IMAGE_KINDS = ["promoBanner", "videoPlaceholder", "card"];
|
|
116521
|
+
var IMAGE_ADVICE = {
|
|
116522
|
+
promoBanner: "Banner advice: a wide landscape image at least 1600 px wide (3:1 to 5:1 works best, for example 1600\xD7400); keep text inside the middle 80% so it survives mobile scaling; JPEG/PNG/WebP/AVIF up to 15 MB, stored as WebP with 320/800/1600 px variants.",
|
|
116523
|
+
videoPlaceholder: "Placeholder advice: it covers the 16:9 video slot, so use a 16:9 image at least 1600\xD7900 px; avoid small text; JPEG/PNG/WebP/AVIF up to 15 MB, stored as WebP with 320/800/1600 px variants.",
|
|
116524
|
+
card: "Card advice: match the cardImageRatio chosen in oko_configure_cards (1:1 is the safest), at least 800 px on the short side; JPEG/PNG/WebP/AVIF up to 15 MB, stored as WebP with 320/800/1600 px variants."
|
|
116525
|
+
};
|
|
116521
116526
|
var IMAGE_VARIANT_NAMES = ["thumb_320.webp", "card_800.webp", "hero_1600.webp"];
|
|
116522
116527
|
var CARD_IMAGE_RATIOS = ["auto", "1:1", "4:3", "3:2", "16:9", "2:3", "3:4"];
|
|
116523
116528
|
var CARD_ID_PATTERN = /^[A-Za-z0-9_-]{1,80}$/;
|
|
@@ -117004,6 +117009,16 @@ async function uploadEventImageForUser(uid, eventId, kind, cardId, source) {
|
|
|
117004
117009
|
const previous = readImageRef(event, kind, cardId);
|
|
117005
117010
|
const sourceBuffer = await readImageSource(source);
|
|
117006
117011
|
const remoteNotes = takeRemoteFetchNotes();
|
|
117012
|
+
const eventBlocks = event.blocks && typeof event.blocks === "object" ? event.blocks : {};
|
|
117013
|
+
const placeholderCfg = eventBlocks.video?.placeholder && typeof eventBlocks.video.placeholder === "object" ? eventBlocks.video.placeholder : {};
|
|
117014
|
+
const blockEnabled = kind === "promoBanner" ? eventBlocks.promoBanner?.enabled === true : kind === "videoPlaceholder" ? placeholderCfg.enabled === true : readCardsConfig(event).enabled;
|
|
117015
|
+
const enableInstruction = kind === "promoBanner" ? "oko_configure_blocks promoBanner.enabled=true" : kind === "videoPlaceholder" ? "oko_configure_blocks videoPlaceholder.enabled=true" : "oko_configure_cards enabled=true";
|
|
117016
|
+
const uploadHints = [
|
|
117017
|
+
blockEnabled ? `The ${kind} block is enabled: the new image appears on the page as soon as the variants are ready.` : `The ${kind} block is disabled in setup, so viewers will not see this image until it is enabled (${enableInstruction}). Uploading never enables a block by itself.`,
|
|
117018
|
+
...kind === "videoPlaceholder" && placeholderCfg.mode !== "image" ? ['The placeholder mode is not "image": set oko_configure_blocks videoPlaceholder.mode="image" for this picture to be used.'] : [],
|
|
117019
|
+
...kind === "videoPlaceholder" ? ['The placeholder is shown to viewers only while its live switch is on: oko_set_block_visibility block "placeholder" visible=true.'] : [],
|
|
117020
|
+
IMAGE_ADVICE[kind]
|
|
117021
|
+
];
|
|
117007
117022
|
const previousMasterPath = storagePathFromDownloadUrl(previous.imageMasterUrl);
|
|
117008
117023
|
const deleteWarnings = [];
|
|
117009
117024
|
let deletesAttempted = 0;
|
|
@@ -117029,7 +117044,7 @@ async function uploadEventImageForUser(uid, eventId, kind, cardId, source) {
|
|
|
117029
117044
|
note: "Image master uploaded. CF generateImageVariants should publish thumb/card/hero variants and update imageUrl/imageVariants in about 10-30 seconds.",
|
|
117030
117045
|
storageDeletesAttempted: deletesAttempted,
|
|
117031
117046
|
storageDeleteWarnings: deleteWarnings,
|
|
117032
|
-
|
|
117047
|
+
hints: [...remoteNotes, ...uploadHints]
|
|
117033
117048
|
};
|
|
117034
117049
|
}
|
|
117035
117050
|
|
|
@@ -117348,7 +117363,7 @@ var SCOPE_UNLOCKS = {
|
|
|
117348
117363
|
"chat:moderate": "chat mode, moderation, bans and mutes",
|
|
117349
117364
|
"telegram:write": "claiming channels and publishing Telegram posts",
|
|
117350
117365
|
"workspace:read": "listing workspaces, members, invites, notifications",
|
|
117351
|
-
"workspace:write": "workspace management, invites, profile edits
|
|
117366
|
+
"workspace:write": "workspace management, invites, profile edits",
|
|
117352
117367
|
"leads:read": "reading and exporting leads"
|
|
117353
117368
|
};
|
|
117354
117369
|
function presetsWithScope(scope) {
|
|
@@ -118086,6 +118101,8 @@ function validateEventSetup(eventId, event) {
|
|
|
118086
118101
|
} else if (safeString(promo.imageMasterUrl).trim() && !readImageVariants(promo.imageVariants)) {
|
|
118087
118102
|
add(warnings, "promo_variants_pending", "blocks.promoBanner.imageVariants", "Promo banner image variants are not ready yet.");
|
|
118088
118103
|
}
|
|
118104
|
+
} else if (safeString(promo.imageUrl).trim() || safeString(promo.imageMasterUrl).trim()) {
|
|
118105
|
+
add(suggestions, "promo_disabled_with_image", "blocks.promoBanner.enabled", 'Promo banner has an uploaded image but is disabled in setup, so viewers never see it. Enable it with oko_configure_blocks promoBanner.enabled=true; to hide it only during the live show, keep it enabled and use oko_set_block_visibility block "banner" visible=false.');
|
|
118089
118106
|
}
|
|
118090
118107
|
const cta = asRecord(blocks.primaryCta);
|
|
118091
118108
|
if (cta.enabled === true) {
|
|
@@ -118108,6 +118125,9 @@ function validateEventSetup(eventId, event) {
|
|
|
118108
118125
|
add(warnings, "placeholder_variants_pending", "blocks.video.placeholder.imageVariants", "Video placeholder image variants are not ready yet.");
|
|
118109
118126
|
}
|
|
118110
118127
|
}
|
|
118128
|
+
if (videoPlaceholder.enabled === true) {
|
|
118129
|
+
add(suggestions, "placeholder_needs_live_switch", "blocks.video.placeholder", 'The video placeholder is shown to viewers only while its live switch is on: call oko_set_block_visibility block "placeholder" visible=true before the start and visible=false (or null) once the stream is playing.');
|
|
118130
|
+
}
|
|
118111
118131
|
const cards = readCardsConfig(event);
|
|
118112
118132
|
cards.repairedIdPositions.forEach((position) => {
|
|
118113
118133
|
add(errors, "card_id_missing", `blocks.cards.items[${position}].id`, "Card has no usable id in Firestore; its image cannot be matched and will be dropped on the next update.");
|
|
@@ -118410,7 +118430,8 @@ function registerEventTools(server2) {
|
|
|
118410
118430
|
notes: [
|
|
118411
118431
|
"A block toggle and its image are independent: enabling a block here works with an image already uploaded via oko_upload_image, and uploading an image never enables the block by itself.",
|
|
118412
118432
|
"promoBanner has no text field by design: the banner is image+link. blocks.promoBanner.text seen in event documents is legacy and is never rendered on the event page.",
|
|
118413
|
-
'videoPlaceholder.enabled only allows the placeholder; viewers see it after oko_set_block_visibility with block "placeholder" and visible true (a live override, stored outside the event document). Chat, CTA, banner and cards appear as soon as they are enabled here.'
|
|
118433
|
+
'videoPlaceholder.enabled only allows the placeholder; viewers see it after oko_set_block_visibility with block "placeholder" and visible true (a live override, stored outside the event document). Chat, CTA, banner and cards appear as soon as they are enabled here.',
|
|
118434
|
+
"Setup toggle vs live override: enabled=false removes a block from the page for everyone and persists (its uploaded image stays); oko_set_block_visibility hides or shows an enabled block temporarily and is the tool for the live show. Uploading an image never enables a block."
|
|
118414
118435
|
]
|
|
118415
118436
|
}),
|
|
118416
118437
|
inputSchema: {
|
|
@@ -118498,6 +118519,17 @@ function registerEventTools(server2) {
|
|
|
118498
118519
|
}
|
|
118499
118520
|
await updateDoc(doc(firestore, "events", args.eventId), patch);
|
|
118500
118521
|
const hints = [];
|
|
118522
|
+
const currentBlocks = current.blocks && typeof current.blocks === "object" ? current.blocks : {};
|
|
118523
|
+
const bannerHasImage = Boolean(safeString(currentBlocks.promoBanner?.imageUrl) || safeString(currentBlocks.promoBanner?.imageMasterUrl));
|
|
118524
|
+
if (args.promoBanner?.enabled === false && bannerHasImage) {
|
|
118525
|
+
hints.push('The promo banner is now disabled in setup: it disappears from the page for everyone, while its uploaded image stays in place. If the goal was to hide it only during the live show and bring it back with one call, re-enable it here and use oko_set_block_visibility block "banner" visible=false instead.');
|
|
118526
|
+
}
|
|
118527
|
+
if (args.promoBanner?.enabled === true && !bannerHasImage) {
|
|
118528
|
+
hints.push(`The promo banner is enabled but has no image yet: upload one with oko_upload_image kind "promoBanner". ${IMAGE_ADVICE.promoBanner}`);
|
|
118529
|
+
}
|
|
118530
|
+
if (args.chat?.enabled !== void 0 || args.promoBanner?.enabled !== void 0 || args.primaryCta?.enabled !== void 0 || args.videoPlaceholder?.enabled !== void 0) {
|
|
118531
|
+
hints.push("Setup toggles (enabled) decide whether a block exists on the page and persist; live overrides (oko_set_block_visibility) show or hide an enabled block temporarily during the show. Uploading an image never enables a block.");
|
|
118532
|
+
}
|
|
118501
118533
|
if (args.videoPlaceholder?.enabled === true) {
|
|
118502
118534
|
hints.push('The video placeholder is enabled but not yet visible to viewers: call oko_set_block_visibility with block "placeholder" and visible true (confirm true) to show it. It is a live override stored outside the event document.');
|
|
118503
118535
|
}
|
|
@@ -118623,7 +118655,11 @@ function registerImageTools(server2) {
|
|
|
118623
118655
|
"Uploading an image does not enable its block: toggle the block independently via oko_configure_blocks, in either order.",
|
|
118624
118656
|
"The MCP server reads local paths on the organizer machine.",
|
|
118625
118657
|
"Remote URLs must be public HTTPS images, max 15MB; private/local hosts are blocked.",
|
|
118626
|
-
"For card images, imageId is the cardId so OKO CF4 can update the correct item."
|
|
118658
|
+
"For card images, imageId is the cardId so OKO CF4 can update the correct item.",
|
|
118659
|
+
IMAGE_ADVICE.promoBanner,
|
|
118660
|
+
IMAGE_ADVICE.videoPlaceholder,
|
|
118661
|
+
IMAGE_ADVICE.card,
|
|
118662
|
+
"The result carries hints: whether the target block is enabled, what still hides the image (placeholder mode/live switch), and the advice above."
|
|
118627
118663
|
]
|
|
118628
118664
|
}),
|
|
118629
118665
|
inputSchema: {
|
|
@@ -118855,7 +118891,6 @@ async function recordToolAudit(toolName, outcome, args, startedAt, error3) {
|
|
|
118855
118891
|
var REPORT_URL = `${APP_ORIGIN}/contact`;
|
|
118856
118892
|
var KEYS_URL = `${APP_ORIGIN}/app/mcp`;
|
|
118857
118893
|
var SCOPE_WORKAROUNDS = {
|
|
118858
|
-
oko_move_event: "Without workspace:write you can still place the event in another workspace: call oko_duplicate_event with targetWorkspaceId to create a copy there. The original stays where it is; live overrides (chat mode, placeholder visibility) are not copied and must be set again on the copy.",
|
|
118859
118894
|
oko_trash_event: "This key cannot delete events. Tell the organizer which event to remove; they can do it in the OKO cabinet, or create a key with the full preset.",
|
|
118860
118895
|
oko_delete_event_permanently: "This key cannot delete events. Tell the organizer which event to remove; they can do it in the OKO cabinet, or create a key with the full preset.",
|
|
118861
118896
|
oko_publish_telegram_post: "This key cannot publish to Telegram. The organizer can publish the announcement from the OKO cabinet, or create a key with the full preset."
|
|
@@ -119169,7 +119204,7 @@ function registerLifecycleTools(server2) {
|
|
|
119169
119204
|
notes: [
|
|
119170
119205
|
"Copies title, video, meta, blocks, forms, and Telegram config; does not copy analytics sessions or leads.",
|
|
119171
119206
|
"Live overrides are NOT copied: the copy starts with chat mode public and the placeholder hidden, whatever the source had. Set them again with oko_set_chat_mode and oko_set_block_visibility on the new event.",
|
|
119172
|
-
"Requires only events:write plus createEvents in the target workspace
|
|
119207
|
+
"Requires only events:write plus createEvents in the target workspace. To move (not copy) an event, use oko_move_event with the same scope."
|
|
119173
119208
|
]
|
|
119174
119209
|
}),
|
|
119175
119210
|
inputSchema: {
|
|
@@ -119222,7 +119257,7 @@ function registerLifecycleTools(server2) {
|
|
|
119222
119257
|
examples: ["Use when an event belongs in another workspace. Call oko_list_workspaces first to choose the target."],
|
|
119223
119258
|
notes: [
|
|
119224
119259
|
"Reads target workspace shares from Firestore with permissions; does not use RTDB workspaceMembers.",
|
|
119225
|
-
"Requires
|
|
119260
|
+
"Requires events:write plus ownership of the event (or of its source workspace) and createEvents in the target workspace; no workspace:write needed. Live overrides (chat mode, placeholder) travel with the event: they live in the event's own RTDB node."
|
|
119226
119261
|
]
|
|
119227
119262
|
}),
|
|
119228
119263
|
inputSchema: {
|
|
@@ -119233,7 +119268,7 @@ function registerLifecycleTools(server2) {
|
|
|
119233
119268
|
outputSchema: updateOutputSchema,
|
|
119234
119269
|
annotations: writeTool
|
|
119235
119270
|
}, async ({ eventId, targetWorkspaceId, confirm }) => {
|
|
119236
|
-
await authed(["events:write"
|
|
119271
|
+
await authed(["events:write"]);
|
|
119237
119272
|
requireConfirm(confirm, "oko_move_event", { eventId, targetWorkspaceId });
|
|
119238
119273
|
const moveEvent = httpsCallable(functions, "moveEventToWorkspace");
|
|
119239
119274
|
const result = await moveEvent({ eventId, targetWorkspaceId });
|
|
@@ -119273,7 +119308,8 @@ function registerLiveTools(server2) {
|
|
|
119273
119308
|
returns: "eventId, block, and effective override value.",
|
|
119274
119309
|
examples: ["Use visible=false to hide the CTA live; use visible=null to return to setup defaults."],
|
|
119275
119310
|
notes: [
|
|
119276
|
-
"block=chat with visible=false PAUSES message input: viewers keep seeing the chat history but cannot send. It does not hide the chat panel."
|
|
119311
|
+
"block=chat with visible=false PAUSES message input: viewers keep seeing the chat history but cannot send. It does not hide the chat panel.",
|
|
119312
|
+
"Live overrides sit on top of setup: a block disabled in setup (oko_configure_blocks enabled=false) stays absent whatever the override; visible=null returns an enabled block to its setup default. Use overrides for the live show, setup toggles for permanent changes."
|
|
119277
119313
|
]
|
|
119278
119314
|
}),
|
|
119279
119315
|
inputSchema: {
|
|
@@ -119286,8 +119322,17 @@ function registerLiveTools(server2) {
|
|
|
119286
119322
|
annotations: idempotentWriteTool
|
|
119287
119323
|
}, async ({ eventId, block, visible, confirm }) => {
|
|
119288
119324
|
const { uid } = await authed(["live:control"]);
|
|
119289
|
-
await readEvent(eventId, uid, "live");
|
|
119325
|
+
const event = await readEvent(eventId, uid, "live");
|
|
119290
119326
|
requireConfirm(confirm, "oko_set_block_visibility", { eventId, block, visible });
|
|
119327
|
+
const setupBlocks = event.blocks && typeof event.blocks === "object" ? event.blocks : {};
|
|
119328
|
+
const setupEnabled = {
|
|
119329
|
+
chat: setupBlocks.chat?.enabled === true,
|
|
119330
|
+
banner: setupBlocks.promoBanner?.enabled === true,
|
|
119331
|
+
cta: setupBlocks.primaryCta?.enabled === true,
|
|
119332
|
+
cards: setupBlocks.cards?.enabled === true,
|
|
119333
|
+
placeholder: setupBlocks.video?.placeholder?.enabled === true
|
|
119334
|
+
};
|
|
119335
|
+
const hints = setupEnabled[block] ? [visible === null ? "Override removed: the block follows its setup visibility again." : `Live override applied on top of setup; visible=null returns the ${block} block to its setup default.`] : [`The ${block} block is disabled in setup, so this live override has no visible effect until it is enabled (${block === "cards" ? "oko_configure_cards enabled=true" : "oko_configure_blocks"}).`];
|
|
119291
119336
|
const paths = {
|
|
119292
119337
|
chat: "chatVisible",
|
|
119293
119338
|
banner: "bannerVisible",
|
|
@@ -119309,14 +119354,14 @@ function registerLiveTools(server2) {
|
|
|
119309
119354
|
await remove(modeRef);
|
|
119310
119355
|
await remove(legacyRef);
|
|
119311
119356
|
}
|
|
119312
|
-
return textResult({ eventId, block, visible });
|
|
119357
|
+
return textResult({ eventId, block, visible, hints });
|
|
119313
119358
|
}
|
|
119314
119359
|
const target = ref(rtdb, `events/${eventId}/ctrl/${paths[block]}`);
|
|
119315
119360
|
if (visible === null)
|
|
119316
119361
|
await remove(target);
|
|
119317
119362
|
else
|
|
119318
119363
|
await set(target, visible);
|
|
119319
|
-
return textResult({ eventId, block, visible });
|
|
119364
|
+
return textResult({ eventId, block, visible, hints });
|
|
119320
119365
|
});
|
|
119321
119366
|
server2.registerTool("oko_refresh_viewers", {
|
|
119322
119367
|
title: "Refresh viewers",
|