@awesomate/hosting-mcp 0.93.0 → 0.94.1
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 +58 -11
- package/package.json +1 -1
- package/skill/CHANGELOG.json +28 -0
- package/skill/awesomate-knowledge/SKILL.md +1 -1
- package/skill/awesomate-knowledge/references/ingestion-sources.md +1 -1
- package/skill/awesomate-knowledge/references/quotas-and-packs.md +15 -5
- package/skill/awesomate-knowledge/references/showing-media.md +30 -4
package/dist/index.js
CHANGED
|
@@ -40954,7 +40954,8 @@ async function knowledgeStatus(config3) {
|
|
|
40954
40954
|
...status,
|
|
40955
40955
|
usage_glossary: {
|
|
40956
40956
|
pages: "month-to-date hub-submitted page quota used (vs usage.included.pages): NOT the size of the library",
|
|
40957
|
-
sources_total: 'sources currently in the library; kinds in usage.sources_by_kind or awesomate_knowledge_sources {action:"summary"}'
|
|
40957
|
+
sources_total: 'sources currently in the library; kinds in usage.sources_by_kind or awesomate_knowledge_sources {action:"summary"}',
|
|
40958
|
+
playback_gb: "GB of video and audio people played this month (in the hub and on the public player for videos anyone can watch); shown, not limited"
|
|
40958
40959
|
}
|
|
40959
40960
|
};
|
|
40960
40961
|
if (usage.sources_total_source === "hourly_gauge") {
|
|
@@ -41132,6 +41133,25 @@ async function knowledgeSources(config3, args) {
|
|
|
41132
41133
|
}
|
|
41133
41134
|
return await hubPatch(config3, `/api/knowledge/sources/${encodeURIComponent(args.sourceId)}`, { title: args.title.trim() });
|
|
41134
41135
|
}
|
|
41136
|
+
if (args.action === "share_video") {
|
|
41137
|
+
if (!args.sourceId) return { error: "invalid_request", note: "share_video needs sourceId (a video source, from search or list)" };
|
|
41138
|
+
const path = `/api/knowledge/sources/${encodeURIComponent(args.sourceId)}/public-video`;
|
|
41139
|
+
const title = args.title?.trim() ?? "";
|
|
41140
|
+
if (args.enabled === void 0) {
|
|
41141
|
+
return await hubGet(config3, `${path}?${new URLSearchParams({ title: title.slice(0, 100) })}`);
|
|
41142
|
+
}
|
|
41143
|
+
if (args.enabled && !args.confirm) {
|
|
41144
|
+
return {
|
|
41145
|
+
error: "confirmation_required",
|
|
41146
|
+
note: "Switching on Anyone can watch lets anyone with the link watch the WHOLE video, and lets it be embedded on any website. Explain this to the user, then call again with confirm set to their account slug (awesomate_whoami \u2192 account) only after they have agreed in so many words. Switching off needs no confirmation."
|
|
41147
|
+
};
|
|
41148
|
+
}
|
|
41149
|
+
return await hubPut(config3, path, {
|
|
41150
|
+
enabled: args.enabled,
|
|
41151
|
+
...title ? { title: title.slice(0, 100) } : {},
|
|
41152
|
+
...args.enabled && args.confirm ? { confirm: args.confirm } : {}
|
|
41153
|
+
});
|
|
41154
|
+
}
|
|
41135
41155
|
if (args.action === "set_visibility") {
|
|
41136
41156
|
const ids = args.sourceIds?.length ? args.sourceIds : args.sourceId ? [args.sourceId] : [];
|
|
41137
41157
|
if (!ids.length || !args.visibility) return { error: "invalid_request", note: "set_visibility needs sourceId (or sourceIds) and visibility" };
|
|
@@ -41275,14 +41295,41 @@ function renderAnswer(meta, streamedAnswer, streamError = null) {
|
|
|
41275
41295
|
note: "UNGROUNDED: the platform returned ok but ZERO sources, which means this answer came from the model, NOT from the verified content. Do NOT present it as an answer from their knowledge base, do not quote it as fact, and do not build on it. Tell the user their content does not cover this. If they need it to refuse instead of improvising, the agent's grounding setting is not strict \u2014 a purpose-built agent (awesomate_knowledge_agents) can be scoped and set strict, and that is what should be wired to anything customer-facing."
|
|
41276
41296
|
};
|
|
41277
41297
|
}
|
|
41298
|
+
if (meta.reason === "hedged") {
|
|
41299
|
+
return {
|
|
41300
|
+
status: "ok",
|
|
41301
|
+
grounded: false,
|
|
41302
|
+
hedged: true,
|
|
41303
|
+
answer,
|
|
41304
|
+
sources,
|
|
41305
|
+
not_in_verified_content: true,
|
|
41306
|
+
configured_fallback: typeof meta.no_answer_message === "string" && meta.no_answer_message ? meta.no_answer_message : null,
|
|
41307
|
+
...typeof meta.score === "number" ? { score: meta.score } : {},
|
|
41308
|
+
...session,
|
|
41309
|
+
note: 'The assistant replied that it does not know (a hedge such as "not sure, please contact us"), so their content does not answer this. Tell the user so plainly and do not treat the cited sources as an answer.'
|
|
41310
|
+
};
|
|
41311
|
+
}
|
|
41312
|
+
const refFor = (docId, section) => {
|
|
41313
|
+
const i = rawSources.findIndex((s) => s.doc_id === docId && (section == null || s.section_path === section));
|
|
41314
|
+
const j = i >= 0 ? i : rawSources.findIndex((s) => s.doc_id === docId);
|
|
41315
|
+
return j >= 0 ? rawSources[j].ref ?? j + 1 : null;
|
|
41316
|
+
};
|
|
41317
|
+
const conflicts = Array.isArray(meta.conflicts) ? meta.conflicts.map((c) => ({
|
|
41318
|
+
item: typeof c.item === "string" ? c.item : null,
|
|
41319
|
+
values: (Array.isArray(c.values) ? c.values : []).map((v) => ({
|
|
41320
|
+
amount: v.amount ?? null,
|
|
41321
|
+
source_ref: refFor(v.doc_id, v.section_path)
|
|
41322
|
+
}))
|
|
41323
|
+
})) : null;
|
|
41278
41324
|
return {
|
|
41279
41325
|
status: "ok",
|
|
41280
41326
|
grounded: true,
|
|
41281
41327
|
answer,
|
|
41282
41328
|
sources,
|
|
41329
|
+
...conflicts && conflicts.length ? { conflicts } : {},
|
|
41283
41330
|
...typeof meta.score === "number" ? { score: meta.score } : {},
|
|
41284
41331
|
...session,
|
|
41285
|
-
note: "Present the answer with its numbered sources; the citations are the product."
|
|
41332
|
+
note: conflicts && conflicts.length ? "Two of their documents disagree on this (see conflicts: each figure names the numbered source it came from). Present the answer with its sources, say which sources disagree, and suggest the user correct or remove the out-of-date one." : "Present the answer with its numbered sources; the citations are the product."
|
|
41286
41333
|
};
|
|
41287
41334
|
}
|
|
41288
41335
|
async function knowledgeAsk(config3, args) {
|
|
@@ -42998,7 +43045,7 @@ server.registerTool(
|
|
|
42998
43045
|
"awesomate_domain_add",
|
|
42999
43046
|
{
|
|
43000
43047
|
annotations: annotate("awesomate_domain_add", MUTATING),
|
|
43001
|
-
description: "Add a custom domain to the user's hosting account. Returns the DNS steps they need to complete at their registrar: `dnsInstructions` (A rows only when there is a public address; CNAME rows
|
|
43048
|
+
description: "Add a custom domain to the user's hosting account. Returns the DNS steps they need to complete at their registrar: `dnsInstructions` (A rows only when there is a public address; no CNAME rows on a server where the name resolves to an address that takes Cloudflare traffic only) and `dnsNote`. When `dnsNote` is set, relay it word for word: it says either which address to use instead when the domain is on Cloudflare with Proxy status set to Proxied (orange cloud), or that every record must be Proxied; either way SSL/TLS is Full, not Flexible (Full (strict) only once HTTPS is on). **Needs Support Plus or above from Claude**: Essentials gets 403 `upgrade_required` even though its plan DOES include one custom domain, because adding it from a machine token is Support Plus; tell them it takes two clicks at hub.awesomate.ai/sites/domains instead. Plan COUNT limits are enforced separately on top. Pass `site` (a WordPress site's domain, as awesomate_list_sites shows it) to make the new domain show that site in the same call; the answer's `attached` says it worked, and `attachError` says why not (the domain is still added). For a domain ALREADY on the account, pass `alreadyAdded:true` with `site` to attach it to that site only: nothing is added and no plan count is used.",
|
|
43002
43049
|
inputSchema: {
|
|
43003
43050
|
domain: external_exports.string().describe("The domain to add, e.g. example.com"),
|
|
43004
43051
|
site: external_exports.string().max(253).optional().describe("The WordPress site this domain should show, by its domain from awesomate_list_sites"),
|
|
@@ -43628,11 +43675,11 @@ server.registerTool(
|
|
|
43628
43675
|
"awesomate_knowledge_sources",
|
|
43629
43676
|
{
|
|
43630
43677
|
annotations: annotate("awesomate_knowledge_sources", MUTATING),
|
|
43631
|
-
description: "The knowledge base's content sources: the LIBRARY. action 'search' {q?, kind?, visibility?, tags?, collectionIds?, cursor?, limit?}: find sources by title/tag substring and metadata filters (instant, free; for CONTENT search use awesomate_knowledge_search); each row carries visibility (private|internal|public: who may retrieve it, ENFORCED), tags and collections. 'tag' {sourceId, tags}: REPLACE a source's free-form tags. 'rename' {sourceId, title}: set the source's display TITLE in the library. An UPLOADED file is titled from its FILENAME, slugified with underscores, and every non-ASCII letter becomes _ too (\"K\u014Dwhai Dance: Questions parents ask us\" lands as K_whai_Dance_Questions_parents_ask_us), even when a title was passed to the upload; renaming is the only way to fix it. Rename AFTER the ingest job succeeds. The library shows the new title at once, but search hits and citations may keep showing the old title for a while: never tell the user citations have changed until a search shows it. 'set_visibility' {sourceId|sourceIds, visibility, confirm?}: change who may retrieve the source(s); 'public' is irreversible once fetched, so it needs the user's explicit agreement and their account slug as confirm. 'move' {sourceId|sourceIds, collectionIds?, removeCollectionIds?}: add to / remove from collections. 'sync_rules' / 'sync_rule_create' {pathPrefix, includeGlobs?, visibility?, tags?, collectionIds?, onFileRemoved?, sheetKind?} / 'sync_rule_delete' {ruleId} / 'sync_run' / 'sync_state': keep a folder of the account's File Manager (their n8n file system: public/, private/, temp/) synced into the knowledge base, so files their workflows write become searchable; a public rule needs confirm. Spreadsheets in the folder are added only when the rule has sheetKind ('sheet' or 'data-import', the same choice as an upload; ask the user, never guess); without it each spreadsheet is skipped and sync_state says why. 'list': ONE page of sources, most recently ingested first (default 50, max 200 via limit): read `page.has_more`/`next_cursor` and pass cursor to continue: a page is never the whole library. 'summary': exact whole-library counts {total, by_kind, chunks, indexed_chunks, failed_sources, failed_jobs_7d}: use THIS to say what the knowledge base contains, and if failed_jobs_7d > 0 say so: those ingests are missing from every other count. 'jobs': ingest job statuses, the answer to 'has my YouTube channel / website / upload finished importing?' (optional status filter: queued|running|succeeded|failed). 'add': ingest a public page {url} or a whole site {sitemap, since?}, optionally with visibility (default private; 'public' needs confirm, the account slug, after the user agrees in so many words), tags and collectionIds; ALWAYS get explicit approval first (ingest costs money and counts against quota), for a local FILE on the user's machine use awesomate_knowledge_upload instead (it streams the file from disk; this tool takes URLs only). A pack_required response means the allowance is exhausted: NOTHING was purchased: present the pack price (1 credit = $100) and let the user buy from the hub if they want it. 'remove' {sourceId}: deletes the source AND its indexed content; explicit approval required. 'video_imports': read-only: the Vimeo or Wistia library imports, newest first; with importId, that import's quote, transcription price and progress plus a page of its videos (itemState filters them, cursor and limit page them). 'video_connections': read-only: which video libraries are connected. Connecting a library (it takes the provider's token) and starting, pausing or cancelling an import (transcription is charged) stay in the hub at Knowledge, Video library: send the user there. 'get' {sourceId}: one source with its library row and detail. 'visibility_summary': how many sources sit at each audience (private, internal, public) and what each level means. 'job_retry' {jobId}: queue a failed or cancelled ingest job again (from jobs); ask first, since it ingests again. 'sync_rule_update' {ruleId, pathPrefix?, includeGlobs?, collectionIds?, visibility?, tags?, onFileRemoved?, sheetKind?, enabled?}: change a synced-folder rule, or switch it off with enabled:false; making it public needs confirm, the account slug, after the user agrees in words.",
|
|
43678
|
+
description: "The knowledge base's content sources: the LIBRARY. action 'search' {q?, kind?, visibility?, tags?, collectionIds?, cursor?, limit?}: find sources by title/tag substring and metadata filters (instant, free; for CONTENT search use awesomate_knowledge_search); each row carries visibility (private|internal|public: who may retrieve it, ENFORCED), tags and collections. 'tag' {sourceId, tags}: REPLACE a source's free-form tags. 'rename' {sourceId, title}: set the source's display TITLE in the library. An UPLOADED file is titled from its FILENAME, slugified with underscores, and every non-ASCII letter becomes _ too (\"K\u014Dwhai Dance: Questions parents ask us\" lands as K_whai_Dance_Questions_parents_ask_us), even when a title was passed to the upload; renaming is the only way to fix it. Rename AFTER the ingest job succeeds. The library shows the new title at once, but search hits and citations may keep showing the old title for a while: never tell the user citations have changed until a search shows it. 'set_visibility' {sourceId|sourceIds, visibility, confirm?}: change who may retrieve the source(s); 'public' is irreversible once fetched, so it needs the user's explicit agreement and their account slug as confirm. 'move' {sourceId|sourceIds, collectionIds?, removeCollectionIds?}: add to / remove from collections. 'sync_rules' / 'sync_rule_create' {pathPrefix, includeGlobs?, visibility?, tags?, collectionIds?, onFileRemoved?, sheetKind?} / 'sync_rule_delete' {ruleId} / 'sync_run' / 'sync_state': keep a folder of the account's File Manager (their n8n file system: public/, private/, temp/) synced into the knowledge base, so files their workflows write become searchable; a public rule needs confirm. Spreadsheets in the folder are added only when the rule has sheetKind ('sheet' or 'data-import', the same choice as an upload; ask the user, never guess); without it each spreadsheet is skipped and sync_state says why. 'list': ONE page of sources, most recently ingested first (default 50, max 200 via limit): read `page.has_more`/`next_cursor` and pass cursor to continue: a page is never the whole library. 'summary': exact whole-library counts {total, by_kind, chunks, indexed_chunks, failed_sources, failed_jobs_7d}: use THIS to say what the knowledge base contains, and if failed_jobs_7d > 0 say so: those ingests are missing from every other count. 'jobs': ingest job statuses, the answer to 'has my YouTube channel / website / upload finished importing?' (optional status filter: queued|running|succeeded|failed). 'add': ingest a public page {url} or a whole site {sitemap, since?}, optionally with visibility (default private; 'public' needs confirm, the account slug, after the user agrees in so many words), tags and collectionIds; ALWAYS get explicit approval first (ingest costs money and counts against quota), for a local FILE on the user's machine use awesomate_knowledge_upload instead (it streams the file from disk; this tool takes URLs only). A pack_required response means the allowance is exhausted: NOTHING was purchased: present the pack price (1 credit = $100) and let the user buy from the hub if they want it. 'remove' {sourceId}: deletes the source AND its indexed content; explicit approval required. 'video_imports': read-only: the Vimeo or Wistia library imports, newest first; with importId, that import's quote, transcription price and progress plus a page of its videos (itemState filters them, cursor and limit page them). 'video_connections': read-only: which video libraries are connected. Connecting a library (it takes the provider's token) and starting, pausing or cancelling an import (transcription is charged) stay in the hub at Knowledge, Video library: send the user there. 'get' {sourceId}: one source with its library row and detail. 'visibility_summary': how many sources sit at each audience (private, internal, public) and what each level means. 'job_retry' {jobId}: queue a failed or cancelled ingest job again (from jobs); ask first, since it ingests again. 'sync_rule_update' {ruleId, pathPrefix?, includeGlobs?, collectionIds?, visibility?, tags?, onFileRemoved?, sheetKind?, enabled?}: change a synced-folder rule, or switch it off with enabled:false; making it public needs confirm, the account slug, after the user agrees in words. 'share_video' {sourceId, title?, enabled?, confirm?}: a video anyone can watch. Without enabled it READS {enabled, watchable, link, embed}: link is the video's permanent player page (on the account's own links. address when it sends email from its own domain) and embed is an iframe of it, safe to put on a website; title names the video in the embed. enabled:true switches it on (Owners only, the video must already be Public, and it needs confirm, the account slug, after the user agrees in so many words, because anyone with the link can then watch the whole video); enabled:false switches it off at once, no confirmation. watchable false with enabled true means the video is no longer Public, so nobody can watch it.",
|
|
43632
43679
|
inputSchema: {
|
|
43633
|
-
action: external_exports.enum(["list", "summary", "add", "remove", "jobs", "search", "tag", "rename", "set_visibility", "move", "sync_rules", "sync_rule_create", "sync_rule_update", "sync_rule_delete", "sync_run", "sync_state", "video_imports", "video_connections", "get", "visibility_summary", "job_retry"]),
|
|
43680
|
+
action: external_exports.enum(["list", "summary", "add", "remove", "jobs", "search", "tag", "rename", "set_visibility", "move", "sync_rules", "sync_rule_create", "sync_rule_update", "sync_rule_delete", "sync_run", "sync_state", "video_imports", "video_connections", "get", "visibility_summary", "job_retry", "share_video"]),
|
|
43634
43681
|
jobId: external_exports.string().max(64).optional().describe("job_retry: a failed or cancelled job_id from jobs"),
|
|
43635
|
-
enabled: external_exports.boolean().optional().describe("sync_rule_update: false switches the rule off, true back on"),
|
|
43682
|
+
enabled: external_exports.boolean().optional().describe("sync_rule_update: false switches the rule off, true back on; share_video: switch Anyone can watch on or off (omit to read the link and embed code)"),
|
|
43636
43683
|
importId: external_exports.string().uuid().optional().describe("video_imports: one import, from the list"),
|
|
43637
43684
|
itemState: external_exports.enum(VIDEO_ITEM_STATES).optional().describe("video_imports with importId: only videos in this state (e.g. 'failed')"),
|
|
43638
43685
|
pathPrefix: external_exports.string().max(512).optional().describe("sync_rule_create: a File Manager folder to keep synced, e.g. 'public/reports'"),
|
|
@@ -43644,15 +43691,15 @@ server.registerTool(
|
|
|
43644
43691
|
kind: external_exports.string().max(32).optional().describe("search: source kind filter (web, document, video, audio, image, book, dataset)"),
|
|
43645
43692
|
visibility: external_exports.enum(["private", "internal", "public"]).optional().describe("add: the audience the new source is cleared for (default private); set_visibility: the level to apply; search: filter"),
|
|
43646
43693
|
tags: external_exports.array(external_exports.string().max(64)).max(64).optional().describe("add: free-form tags; tag: the REPLACEMENT list; search: filter (AND)"),
|
|
43647
|
-
title: external_exports.string().min(1).max(300).optional().describe("rename: the source's new display title (shown in the library at once; citations may lag)"),
|
|
43694
|
+
title: external_exports.string().min(1).max(300).optional().describe("rename: the source's new display title (shown in the library at once; citations may lag); share_video: the name written into the embed code"),
|
|
43648
43695
|
collectionIds: external_exports.array(external_exports.string().max(64)).max(16).optional().describe("add: put the source in these collections; move: add to; search: filter"),
|
|
43649
43696
|
removeCollectionIds: external_exports.array(external_exports.string().max(64)).max(16).optional().describe("move: remove from these collections"),
|
|
43650
43697
|
sourceIds: external_exports.array(external_exports.string().max(300)).max(200).optional().describe("set_visibility/move: several sources at once"),
|
|
43651
|
-
confirm: external_exports.string().max(64).optional().describe("add, set_visibility, sync_rule_create or sync_rule_update with visibility 'public' only: the account slug, after the user agreed in so many words"),
|
|
43698
|
+
confirm: external_exports.string().max(64).optional().describe("add, set_visibility, sync_rule_create or sync_rule_update with visibility 'public', and share_video with enabled:true only: the account slug, after the user agreed in so many words"),
|
|
43652
43699
|
url: external_exports.string().url().optional().describe("add: one public page or blog post. On Pro, a link to one Vimeo or Wistia video comes in as the video itself (copied, with its captions or a transcript from the monthly media hours) when that library is connected on the hub's Video library page; a YouTube or other video link is read as a page (title and description). Below Pro a video link is refused. To transcribe any other recording, upload the file"),
|
|
43653
43700
|
sitemap: external_exports.string().url().optional().describe("add: sitemap.xml URL \u2014 ingests every listed page"),
|
|
43654
43701
|
since: external_exports.string().optional().describe("add+sitemap only: skip entries with lastmod older than this ISO date"),
|
|
43655
|
-
sourceId: external_exports.string().max(300).optional().describe("remove, get: the source id"),
|
|
43702
|
+
sourceId: external_exports.string().max(300).optional().describe("remove, get, share_video: the source id"),
|
|
43656
43703
|
status: external_exports.string().optional().describe("jobs only: queued|running|succeeded|failed"),
|
|
43657
43704
|
cursor: external_exports.string().max(512).optional().describe("list, video_imports: next_cursor from the previous page"),
|
|
43658
43705
|
limit: external_exports.number().int().min(1).max(200).optional().describe("list, video_imports: page size (default 50, max 200)")
|
|
@@ -43672,7 +43719,7 @@ server.registerTool(
|
|
|
43672
43719
|
"awesomate_knowledge_search",
|
|
43673
43720
|
{
|
|
43674
43721
|
annotations: annotate("awesomate_knowledge_search", READ_ONLY),
|
|
43675
|
-
description: "Instant search over the knowledge library with live facet counts: the fastest way to see WHAT is in there and to find the exact video moment, book page, dataset or web section. Returns hits (title, kind, locator like t=612-640 or p.42, snippet with **matched words**, score) plus facets {kind, year, category, author, people, places, topics} whose counts describe the current filters: repeat a facet value to OR within it, combine facets to AND. include_media adds presigned url/poster_url to hits: they expire in minutes, use immediately, never store. Keyword-only and free (no answer quota); for a verified ANSWER use awesomate_knowledge_ask, optionally with the same filters. Citations from awesomate_knowledge_ask carry NO media URLs \u2014 when a cited source is an image/video and the user wants to SEE it, re-query here with include_media (ideally filtered by its doc id). The returned url/poster_url expire in minutes: fine to show in chat, never safe to embed in a page \u2014 see the awesomate-knowledge skill's showing-media.md.",
|
|
43722
|
+
description: "Instant search over the knowledge library with live facet counts: the fastest way to see WHAT is in there and to find the exact video moment, book page, dataset or web section. Returns hits (title, kind, locator like t=612-640 or p.42, snippet with **matched words**, score) plus facets {kind, year, category, author, people, places, topics} whose counts describe the current filters: repeat a facet value to OR within it, combine facets to AND. include_media adds presigned url/poster_url to hits: they expire in minutes, use immediately, never store. Keyword-only and free (no answer quota); for a verified ANSWER use awesomate_knowledge_ask, optionally with the same filters. Citations from awesomate_knowledge_ask carry NO media URLs \u2014 when a cited source is an image/video and the user wants to SEE it, re-query here with include_media (ideally filtered by its doc id). The returned url/poster_url expire in minutes: fine to show in chat, never safe to embed in a page \u2014 see the awesomate-knowledge skill's showing-media.md. For a video's PERMANENT player link or embed code, use awesomate_knowledge_sources {action:'share_video'}.",
|
|
43676
43723
|
inputSchema: {
|
|
43677
43724
|
q: external_exports.string().max(2e3).optional().describe("Search words; empty lists the library filtered by the facets"),
|
|
43678
43725
|
kind: external_exports.enum(["book", "document", "web", "image", "video", "audio", "post", "dataset"]).optional(),
|
|
@@ -44812,7 +44859,7 @@ readTool(
|
|
|
44812
44859
|
);
|
|
44813
44860
|
readTool(
|
|
44814
44861
|
"awesomate_dns_check",
|
|
44815
|
-
"Live DNS check for the account's primary domain
|
|
44862
|
+
"Live DNS check for the account's primary domain: where it ACTUALLY resolves right now versus where Awesomate hosting expects it. The first call when 'my domain isn't working': it separates a DNS problem (user must change records at their registrar) from a hosting problem (ours). `expected.aRecordIp` is for A records without Cloudflare's proxy; when `expected.proxiedIp` is set, that address is for records Proxied through Cloudflare (orange cloud) only, and `expected.cnameTarget` is null because a CNAME to the server would not load. `behindCloudflare: true` means the user's own Cloudflare is in front: the domain counts as connected once our server holds its certificate, so tell them to check the record is Proxied with SSL/TLS Full and to check again in a few minutes.",
|
|
44816
44863
|
"/api/client-hosting/dns-check"
|
|
44817
44864
|
);
|
|
44818
44865
|
readTool(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awesomate/hosting-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.94.1",
|
|
4
4
|
"description": "Awesomate MCP server — lets Claude manage your Awesomate WordPress hosting, plan, limits, n8n automations, and build Node/static apps + databases",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
package/skill/CHANGELOG.json
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"versions": [
|
|
3
|
+
{
|
|
4
|
+
"version": "0.94.1",
|
|
5
|
+
"highlights": [
|
|
6
|
+
"Adding a domain now gives the address that works with any DNS provider, and the one to use instead when your domain is on Cloudflare with the proxy on",
|
|
7
|
+
"The DNS check tells Claude which address to use with and without Cloudflare's proxy, and when a domain behind your own Cloudflare is still being confirmed"
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"version": "0.94.0",
|
|
12
|
+
"highlights": [
|
|
13
|
+
"Claude can give you a permanent link and embed code for a video in your Knowledge, so anyone can watch it on your website or from an email, with captions",
|
|
14
|
+
"Sharing a video needs an Owner and your account name typed back, because anyone with the link can then watch the whole video. Switching it off takes one step",
|
|
15
|
+
"Your Knowledge status shows how many GB of video people watched this month"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"version": "0.93.2",
|
|
20
|
+
"highlights": [
|
|
21
|
+
"Knowledge monthly allowances now start again at midnight on the 1st in your business's own time zone, not UTC, and Claude quotes the date from your Knowledge status"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"version": "0.93.1",
|
|
26
|
+
"highlights": [
|
|
27
|
+
"When a Knowledge agent replies that it does not know (\"not sure, please contact us\"), Claude says your content does not cover it instead of passing that on as an answer",
|
|
28
|
+
"When two of your documents disagree, Claude says so and suggests correcting the out-of-date one"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
3
31
|
{
|
|
4
32
|
"version": "0.93.0",
|
|
5
33
|
"highlights": [
|
|
@@ -106,7 +106,7 @@ Ask when it is not obvious; never guess.
|
|
|
106
106
|
| **"Train this on my files and put a chat on my site"** — the full path | [from-your-files.md](references/from-your-files.md) |
|
|
107
107
|
| **"Import my FAQs"**, from their website, a spreadsheet or typed in; keeping them current | [faqs.md](references/faqs.md) |
|
|
108
108
|
| **"What couldn't my chatbot answer?"**, "improve my assistant", unanswered questions | [faqs.md](references/faqs.md) § Questions |
|
|
109
|
-
| Showing a cited image or video (and why a built page breaks) | [showing-media.md](references/showing-media.md) |
|
|
109
|
+
| Showing a cited image or video (and why a built page breaks); sharing a whole video with a permanent link or embed code | [showing-media.md](references/showing-media.md) |
|
|
110
110
|
| Choosing/adding sources, estimating ingest cost & time | [ingestion-sources.md](references/ingestion-sources.md) |
|
|
111
111
|
| Explaining citations, refusals, "verified" semantics | [citations-and-grounding.md](references/citations-and-grounding.md) |
|
|
112
112
|
| Wiring the knowledge base into n8n agents | [n8n-connection.md](references/n8n-connection.md) |
|
|
@@ -10,7 +10,7 @@ estimating BEFORE asking approval.
|
|
|
10
10
|
|---|---|---|
|
|
11
11
|
| Web page / blog post | `add {url}` | One page per URL; extraction skips pages under ~200 chars of real text |
|
|
12
12
|
| Whole site / blog | `add {sitemap, since?}` | sitemap.xml; default cap 500 pages per job — a bigger sitemap FAILS the job loudly rather than truncating silently. `since` skips entries with older `<lastmod>` |
|
|
13
|
-
| YouTube / hosted video, podcast audio | `add {url}` | **Not transcribed today
|
|
13
|
+
| YouTube / hosted video, podcast audio | `add {url}` | **Not transcribed today.** A YouTube link is refused ("YouTube links are not supported yet"); another link to a recording is read as a web page (title and description). Pro and above only; below Pro, or in a trial, it is refused (403 `media_ingest`). To transcribe a recording, upload the file |
|
|
14
14
|
| PDF / book / document / markdown | hub upload page | Text layer used; scanned pages OCR'd automatically (`auto` mode, capped at 300 OCR pages per job — over that the job fails BEFORE any vision spend) |
|
|
15
15
|
| Video/audio FILES | hub upload page (≤ 100 MB) | Transcribed (Deepgram, language defaults to English). Pro and above, within the month's media hours. A longer recording: split or compress it and upload each part |
|
|
16
16
|
| Images | hub upload page | Vision-described, then indexed |
|
|
@@ -33,9 +33,12 @@ Knowledge → Usage page. A full library on Support Plus and up answers 402
|
|
|
33
33
|
`addon_required` with the add-on's details when the owner can buy it, or 402
|
|
34
34
|
`storage_full` with a sentence when they can't (in a trial, at the cap, or
|
|
35
35
|
not the owner). Relay either one as it is; never buy anything.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
Every monthly allowance runs from midnight on the 1st in the business's own
|
|
37
|
+
time zone (its Timezone on Your business), not UTC. The status reports the zone
|
|
38
|
+
in force as `usage.time_zone` and when the month starts again as
|
|
39
|
+
`usage.resets_at`; quote that date rather than working one out. An answers pack
|
|
40
|
+
and a media-hours pack count only for the month they are bought in, so buying
|
|
41
|
+
one late in the month buys less; say so before they confirm. A media-hours pack is Pro and above (audio and video are).
|
|
39
42
|
|
|
40
43
|
- An ingest that would exceed included+packs returns `pack_required`. The
|
|
41
44
|
tool response purchases NOTHING and queues NOTHING.
|
|
@@ -52,7 +55,7 @@ Audio and video are Pro and above. The month's media hours are where
|
|
|
52
55
|
transcription stops: the plan's hours, plus the one-off onboarding hours in the
|
|
53
56
|
workspace's first month, plus this month's media-hours packs, plus the monthly
|
|
54
57
|
media-hours add-on. Past them, a new recording is refused (`media_hours_exceeded`)
|
|
55
|
-
until the 1st of next month (
|
|
58
|
+
until the 1st of next month (`usage.resets_at`); a recording already transcribed once is never
|
|
56
59
|
charged again. The owner is told at 80% and 100%.
|
|
57
60
|
|
|
58
61
|
The ways past it: a media-hours pack (40 hours for the rest of this month,
|
|
@@ -65,7 +68,7 @@ in every month it runs, $100 a month on the card, added by the owner on Knowledg
|
|
|
65
68
|
Answers are a hard stop. The allowance is the plan's monthly answers plus
|
|
66
69
|
every answer pack held. When it is used up, every answer route (widget, agent
|
|
67
70
|
chat, n8n, `ask`) returns 429 `quota_exceeded` until the 1st of next month
|
|
68
|
-
|
|
71
|
+
in the business's time zone, and a visitor sees "This assistant has reached its limit for this
|
|
69
72
|
month". Answers on the client's own OpenRouter key never count.
|
|
70
73
|
|
|
71
74
|
- The owner is emailed at 80% and again when the limit is reached.
|
|
@@ -82,3 +85,10 @@ month". Answers on the client's own OpenRouter key never count.
|
|
|
82
85
|
- If a 429 `quota_exceeded` comes back from `ask` or a test chat, say so
|
|
83
86
|
plainly and offer those two routes. Don't retry: nothing changes until the
|
|
84
87
|
month turns or the allowance rises.
|
|
88
|
+
|
|
89
|
+
## Videos watched
|
|
90
|
+
|
|
91
|
+
`usage.playback_gb` in `awesomate_knowledge_status` is the GB of video and
|
|
92
|
+
audio people played this month: in the hub, and on the public player for
|
|
93
|
+
videos anyone can watch. It is shown, not limited, so never call it an
|
|
94
|
+
allowance or say anything will stop.
|
|
@@ -33,10 +33,12 @@ So:
|
|
|
33
33
|
|
|
34
34
|
- **Showing it in chat, now** — fetch with `include_media` and display it.
|
|
35
35
|
Fine. Re-fetch if the user comes back later; do not reuse an old URL.
|
|
36
|
-
- **
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
- **A whole video on a page or in an email** — use its permanent player
|
|
37
|
+
link instead (next section). It never expires and plays with captions.
|
|
38
|
+
- **Building a page, app, or an n8n chat that displays other assets** (images,
|
|
39
|
+
audio, a video that is not shared) — a presigned URL will 403 by the time a
|
|
40
|
+
visitor loads it. Do not embed one. Only a shared video has a stable address,
|
|
41
|
+
so for anything else the page must resolve the asset at request time:
|
|
40
42
|
- the app calls `explore?include=media` server-side (holding the key
|
|
41
43
|
server-side, never in browser JavaScript) and returns a fresh URL per
|
|
42
44
|
request, or
|
|
@@ -49,11 +51,35 @@ Say this to the user plainly when they ask for a gallery or an image-rich page:
|
|
|
49
51
|
the knowledge base is the index, not the CDN. Getting that wrong produces a
|
|
50
52
|
page that looks right when built and is full of broken images an hour later.
|
|
51
53
|
|
|
54
|
+
## A video anyone can watch: the permanent link and embed code
|
|
55
|
+
|
|
56
|
+
A video can have a permanent player page that anyone can open, with captions,
|
|
57
|
+
and an embed code for a website. It is off by default: the video must be
|
|
58
|
+
**Public**, and an Owner switches on **Anyone can watch** (in the hub on the
|
|
59
|
+
video's page, or through Claude).
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
awesomate_knowledge_sources { action: "share_video", sourceId: "<video source id>", title: "<its title>" }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
answers `{enabled, watchable, link, embed}`. `link` is the player page (on the
|
|
66
|
+
account's own `links.` address when it sends email from its own domain);
|
|
67
|
+
`embed` is an iframe of it, safe to paste into a website. Both are null until
|
|
68
|
+
the video is shared.
|
|
69
|
+
|
|
70
|
+
To switch it on, explain that anyone with the link can watch the WHOLE video,
|
|
71
|
+
then call again with `enabled: true` and `confirm` set to the account slug,
|
|
72
|
+
only after the user agrees in so many words. A video that is not Public is
|
|
73
|
+
refused (make it Public first, which needs its own confirmation). `enabled:
|
|
74
|
+
false` switches it off at once and needs no confirmation. `enabled` true with
|
|
75
|
+
`watchable` false means the video is no longer Public, so nobody can watch it.
|
|
76
|
+
|
|
52
77
|
## Deciding quickly
|
|
53
78
|
|
|
54
79
|
| The user wants | Do |
|
|
55
80
|
|---|---|
|
|
56
81
|
| "show me that photo" | search with `include_media`, display it |
|
|
57
82
|
| "which images mention X" | search `kind:image`, list titles + show a few |
|
|
83
|
+
| a video on a web page, in an email or a post | `share_video`: the permanent link or embed code (switching on needs the slug, after the user agrees) |
|
|
58
84
|
| a gallery page / a site section | resolve server-side per request, or re-host the assets; never embed a presigned URL |
|
|
59
85
|
| an n8n chat that returns images | have the workflow call the search endpoint at answer time and return fresh URLs in the reply |
|