@ebitex/content-mcp 0.5.119 → 0.5.122
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.
|
@@ -16,12 +16,12 @@ export const HELP_TOPICS = [
|
|
|
16
16
|
{
|
|
17
17
|
"slug": "components",
|
|
18
18
|
"title": "Authoring Components",
|
|
19
|
-
"body": "# Authoring Components\n\nA Component is one piece of content built from a Contract — for example,\na specific article. This guide covers creating and editing Components,\norganizing them in folders, and the friction the app shows you when a\nContract changes underneath a Component you've already created. See\n[Modeling content with Contracts](contracts.md) first if you haven't\ncreated a Contract yet.\n\n## Creating a Component\n\n1. From the Content page, select **New Component** (optionally after\n opening the folder you want it created in).\n2. Enter a **Name** — the **Id** fills in from it automatically and can\n still be edited by hand.\n3. Choose a **Contract**. If you started from a specific folder that\n restricts which Contracts are allowed there, only those (and their\n descendants) are offered.\n4. Fill in the form that appears — every field from the Contract, laid\n out in order. Fields marked with a red **\\*** are required.\n5. Select **Create**. If a required field is missing or a value doesn't\n match the Contract's rules, the field is highlighted with an\n explanation — fix it and select **Create** again.\n\n## Filling in fields\n\nMost fields are a straightforward text box, number box, or checkbox.\nA few work differently:\n\n- **Reference** and **Nested** are older field types kept working for\n existing Contracts, but no longer offered when adding a new field — new\n Contracts should use **Component** instead (below), which offers the\n same two behaviors plus a third, chosen per value instead of committed\n to for the whole field.\n- **Component** fields ask you to choose, each time you fill one in:\n **Choose…** to link to an existing Component (same search box as\n Reference, with **Change**/**Remove** once chosen); **Create new…** to\n create a brand-new Component and link to it in one step (fill in its\n name, Contract, and any required fields right there); or **Create\n inline…** to embed a value that only ever exists inside this one — pick\n a Contract and an **Edit** panel slides in, exactly like Nested below.\n If the Contract only allows one of these choices, only that one is\n offered. If a linked Component can't be found — most often because it\n was skipped during a promotion into this environment (see\n [content-environments.md](content-environments.md)'s \"Unresolved\n references\" section) — you'll see a distinct **Unresolved** badge\n instead of the usual resolved name, with a link to Component Sync to\n see the full picture and fix it. **Change**/**Remove** still work\n normally on an unresolved value.\n- **Blob** fields (images and other files) show an **Upload** button.\n Once uploaded, you'll see a preview (for images) and a link to download\n the file, plus a **Replace** button.\n- **Nested** fields show a small **Edit** panel once a Contract is chosen\n for them (automatically, if only one is allowed for that field, or via a\n picker if more than one is allowed) — selecting **Edit** opens the\n nested content in its own panel, sliding in over the current one. Any\n unsaved changes you've made — at every level — are kept even if you\n drill several levels deep and back out again; nothing is lost until you\n actually leave the page without saving. A Component field's own **Create\n inline…** choice opens the identical panel.\n- Fields marked **Localizable** always show a small translations icon next\n to their label — select it to add per-locale overrides alongside the\n default value. It's disabled (with an explanation on hover) until your\n organization has a language configured under **Localization** settings\n with at least one language added under it to translate into; once one\n exists, the icon becomes selectable. This works the same way for every\n field type, including Blob, Reference, Nested, Component, and\n Presentation fields: each locale gets its own independent\n **Upload**/**Edit**/**Choose…** affordance, so a Nested value's translated\n content — or a different linked Component or uploaded file per locale —\n is fully separate from the default. The default-locale row in the\n translations panel is always read-only (a reflection of the default\n value, not a second copy of it); translate from the other locale rows.\n- **Presentation** fields let you instantiate a Template inline — pick a\n Template, bind it to a Component, and set contextual values and settings\n for this specific placement. See\n [Presenting content with Templates](templates.md) for the full flow.\n\n## Contextual defaults\n\nFields marked Contextual on the Contract appear in a separate\n**\"Defaults for usage sites\"** section, clearly labeled optional — even if\nthe Contract also marks them Mandatory. That's intentional: a Contextual\nfield's real value is supplied wherever the content is *used*, not here;\nwhat you set in this section is only a fallback for places that don't\nsupply their own value.\n\n### Setting per-usage values on a Reference\n\nWhen you link to another Component via a Reference field (or a Component\nfield's **Choose…**/**Create new…** path — both link the same way), select\n**Contextual values** to open a panel listing that target's own Contextual\nfields, each with three distinct states you can switch between:\n\n- **Inheriting the Component's default** — nothing set here; the linked\n Component's own default value is used.\n- **Overridden** — set a value here to use instead of the default, just\n for this one link. This works for every field type the target Contract\n declares as Contextual, not just simple text/number/checkbox fields — a\n Contextual Reference field gets the same **Choose…** picker, a Contextual\n Blob field the same **Upload** button, and a Contextual Nested field the\n same drill-in **Edit** panel you'd see editing that field directly on a\n Component.\n- **Explicitly cleared** — select **Clear** to force \"no value\" at this\n usage, ignoring the default entirely (only available when the field\n isn't required).\n\nSelect **Reset to default** at any time to go back to inheriting. The same\nthree states and the same per-type widgets apply to a Presentation field's\nown contextual-values panel (see\n[Presenting content with Templates](templates.md)).\n\n### Editing the linked Component itself\n\nNext to **Contextual values**, a linked Component also offers **Quick\nedit**, which opens that Component in a layer over the page you're on —\nits own fields, its own **Save**, and a note of everywhere else it's used,\nsince saving changes it there too. How layers stack, and the difference\nbetween a layer that saves on its own and one that's part of your page, is\nexplained in\n[Editing something from where it's used](content-authoring.md#editing-something-from-where-its-used).\n\n## Organizing with folders\n\nThe **Content** page shows your folder tree on the left. Select the\n**+** icon next to a folder to create a subfolder inside it, the pencil\nicon to rename or move it, or the trash icon to delete it (only possible\nonce it's empty). Selecting a folder shows two tabs: **Contents** (the\nComponents inside it) and, if you have the right permissions, **Settings**\n(that folder's **Access rules**, **Allowed Contracts**, and editorial\nworkflow assignment).\n\nEach Component in the Contents tab is shown as a row with its Contract,\nName, Id, Version, and when it was last updated. Select the **Name** or\n**Last updated** column heading to sort by it. Above the list, a search\nbox and a single **Filter** button (showing a count once you've set any\nfilters) let you narrow by category and/or Contract; pagination appears\nonce a folder holds more Components than fit on one page.\n\nUnder **Settings**:\n\n- **Access rules** restrict which roles can view, edit, delete, or publish\n content in that folder and everything below it (until a subfolder sets\n its own, narrower rules). No rules anywhere on a branch means it's open\n to every member. Select **Add Rule** to grant a role access: pick the\n role from the list and check whichever of View/Edit/Delete/Publish it\n should have. Editing, deleting, or publishing all imply viewing, so you\n don't need to check View separately for those.\n- **Allowed Contracts** restrict which Contracts new Components in that\n folder (and its subfolders, unless they set their own) can use — useful\n for keeping a folder focused on one kind of content. Select **Add\n Contract** and search for the Contract to allow; select **Remove** next\n to an already-allowed Contract to take it off the list. This only\n affects *new* or *moved* Components; it never breaks ones already there,\n though they'll show a **Non-conforming** badge as a reminder.\n\nIf you don't have permission to manage a folder's access rules or allowed\nContracts, you can still see what you're allowed to do there — the panel\njust won't let you change it.\n\n### Moving a Component to another folder\n\nOpen the Component, select the **Settings** tab, and select **Move…**\nnext to the **Folder** label. A picker lists every folder (and **Root**);\npick one to move the Component there once you save. A folder you don't\nhave edit access to is shown but disabled, with an explanation. A folder\nwhose **Allowed Contracts** don't include this Component's Contract is\ndisabled too — unlike an *existing* Component whose folder's rules later\nchange (the **Non-conforming** badge case above), a move that would\nviolate the target folder's rules is rejected outright, so the picker\nwon't offer it as an option in the first place.\n\n### Finding your way back to a folder\n\nThe Component editor shows a breadcrumb above its title (**Content** /\nthe folder it's in / the Component's name) — select the folder name to\nreturn straight to that folder's Contents tab, rather than using your\nbrowser's back button.\n\n## The upgrade badge\n\nIf a Contract changes after a Component was created from it, that\nComponent keeps working exactly as it did — nothing breaks automatically.\nInstead:\n\n- If the Component still satisfies the Contract's latest version, you'll\n see a badge offering **Upgrade to v_N_** — select it to move the\n Component onto the latest version immediately.\n- If it no longer satisfies the latest version, you'll see a\n **Not valid against latest** badge listing exactly what's wrong. Select\n **Start guided upgrade** to switch into editing against the latest\n version, fix the listed issues, and save — the Component moves onto the\n new version as part of that save.\n\nYou're never forced to upgrade; an older Component keeps validating against\nthe version it was created with until you choose to move it forward.\n"
|
|
19
|
+
"body": "# Authoring Components\n\nA Component is one piece of content built from a Contract — for example,\na specific article. This guide covers creating and editing Components,\norganizing them in folders, and the friction the app shows you when a\nContract changes underneath a Component you've already created. See\n[Modeling content with Contracts](contracts.md) first if you haven't\ncreated a Contract yet.\n\n## Creating a Component\n\n1. From the Content page, select **New Component** (optionally after\n opening the folder you want it created in).\n2. Enter a **Name** — the **Id** fills in from it automatically and can\n still be edited by hand.\n3. Choose a **Contract**. If you started from a specific folder that\n restricts which Contracts are allowed there, only those (and their\n descendants) are offered.\n4. Fill in the form that appears — every field from the Contract, laid\n out in order. Fields marked with a red **\\*** are required.\n5. Select **Create**. If a required field is missing or a value doesn't\n match the Contract's rules, the field is highlighted with an\n explanation — fix it and select **Create** again.\n\n## Filling in fields\n\nMost fields are a straightforward text box, number box, or checkbox.\nA few work differently:\n\n- **Reference** and **Nested** are older field types kept working for\n existing Contracts, but no longer offered when adding a new field — new\n Contracts should use **Component** instead (below), which offers the\n same two behaviors plus a third, chosen per value instead of committed\n to for the whole field.\n- **Component** fields ask you to choose, each time you fill one in:\n **Choose…** to link to an existing Component (same search box as\n Reference, with **Change**/**Remove** once chosen); **Create new…** to\n create a brand-new Component and link to it in one step (fill in its\n name, Contract, and any required fields right there); or **Create\n inline…** to embed a value that only ever exists inside this one — pick\n a Contract and an **Edit** panel slides in, exactly like Nested below.\n If the Contract only allows one of these choices, only that one is\n offered. If a linked Component can't be found — most often because it\n was skipped during a promotion into this environment (see\n [content-environments.md](content-environments.md)'s \"Unresolved\n references\" section) — you'll see a distinct **Unresolved** badge\n instead of the usual resolved name, with a link to Component Sync to\n see the full picture and fix it. **Change**/**Remove** still work\n normally on an unresolved value.\n- **Blob** fields (images and other files) show an **Upload** button.\n Once uploaded, you'll see a preview (for images) and a link to download\n the file, plus a **Replace** button.\n- **Nested** fields show a small **Edit** panel once a Contract is chosen\n for them (automatically, if only one is allowed for that field, or via a\n picker if more than one is allowed) — selecting **Edit** opens the\n nested content in its own panel, sliding in over the current one. Any\n unsaved changes you've made — at every level — are kept even if you\n drill several levels deep and back out again; nothing is lost until you\n actually leave the page without saving. A Component field's own **Create\n inline…** choice opens the identical panel.\n- Fields marked **Localizable** always show a small translations icon next\n to their label — select it to add per-locale overrides alongside the\n default value. It's disabled (with an explanation on hover) until your\n organization has a language configured under **Localization** settings\n with at least one language added under it to translate into; once one\n exists, the icon becomes selectable. This works the same way for every\n field type, including Blob, Reference, Nested, Component, and\n Presentation fields: each locale gets its own independent\n **Upload**/**Edit**/**Choose…** affordance, so a Nested value's translated\n content — or a different linked Component or uploaded file per locale —\n is fully separate from the default. The default-locale row in the\n translations panel is always read-only (a reflection of the default\n value, not a second copy of it); translate from the other locale rows.\n- **Presentation** fields let you instantiate a Template inline — pick a\n Template, bind it to a Component, and set contextual values and settings\n for this specific placement. See\n [Presenting content with Templates](templates.md) for the full flow.\n\n## Contextual defaults\n\nFields marked Contextual on the Contract appear in a separate\n**\"Defaults for usage sites\"** section, clearly labeled optional — even if\nthe Contract also marks them Mandatory. That's intentional: a Contextual\nfield's real value is supplied wherever the content is *used*, not here;\nwhat you set in this section is only a fallback for places that don't\nsupply their own value.\n\n### Setting per-usage values on a Reference\n\nWhen you link to another Component via a Reference field (or a Component\nfield's **Choose…**/**Create new…** path — both link the same way), select\n**Contextual values** to open a panel listing that target's own Contextual\nfields, each with three distinct states you can switch between:\n\n- **Inheriting the Component's default** — nothing set here; the linked\n Component's own default value is used.\n- **Overridden** — set a value here to use instead of the default, just\n for this one link. This works for every field type the target Contract\n declares as Contextual, not just simple text/number/checkbox fields — a\n Contextual Reference field gets the same **Choose…** picker, a Contextual\n Blob field the same **Upload** button, and a Contextual Nested field the\n same drill-in **Edit** panel you'd see editing that field directly on a\n Component.\n- **Explicitly cleared** — select **Clear** to force \"no value\" at this\n usage, ignoring the default entirely (only available when the field\n isn't required).\n\nSelect **Reset to default** at any time to go back to inheriting. The same\nthree states and the same per-type widgets apply to a Presentation field's\nown contextual-values panel (see\n[Presenting content with Templates](templates.md)).\n\n### Editing the linked Component itself\n\nNext to **Contextual values**, a linked Component also offers **Quick\nedit**, which opens that Component in a layer over the page you're on —\nits own fields, its own **Save**, and a note of everywhere else it's used,\nsince saving changes it there too. How layers stack, and the difference\nbetween a layer that saves on its own and one that's part of your page, is\nexplained in\n[Editing something from where it's used](content-authoring.md#editing-something-from-where-its-used).\n\n## Organizing with folders\n\nThe **Content** page shows your folder tree on the left. Select the\n**+** icon next to a folder to create a subfolder inside it, the pencil\nicon to rename or move it, or the trash icon to delete it (only possible\nonce it's empty). Selecting a folder shows two tabs: **Contents** (the\nComponents inside it) and, if you have the right permissions, **Settings**\n(that folder's **Access rules**, **Allowed Contracts**, and editorial\nworkflow assignment).\n\nEach Component in the Contents tab is shown as a row with its Contract,\nName, Id, Version, and when it was last updated. Select the **Name** or\n**Last updated** column heading to sort by it. Above the list, a search\nbox and a single **Filter** button (showing a count once you've set any\nfilters) let you narrow by category and/or Contract; pagination appears\nonce a folder holds more Components than fit on one page.\n\nUnder **Settings**:\n\n- **Access rules** restrict which roles can view, edit, delete, or publish\n content in that folder and everything below it (until a subfolder sets\n its own, narrower rules). No rules anywhere on a branch means it's open\n to every member. Select **Add Rule** to grant a role access: pick the\n role from the list and check whichever of View/Edit/Delete/Publish it\n should have. Editing, deleting, or publishing all imply viewing, so you\n don't need to check View separately for those.\n- **Allowed Contracts** restrict which Contracts new Components in that\n folder (and its subfolders, unless they set their own) can use — useful\n for keeping a folder focused on one kind of content. Select **Add\n Contract** and search for the Contract to allow; select **Remove** next\n to an already-allowed Contract to take it off the list. This only\n affects *new* or *moved* Components; it never breaks ones already there,\n though they'll show a **Non-conforming** badge as a reminder.\n\nIf you don't have permission to manage a folder's access rules or allowed\nContracts, you can still see what you're allowed to do there — the panel\njust won't let you change it.\n\n### Moving a Component to another folder\n\nOpen the Component, select the **Settings** tab, and select **Move…**\nnext to the **Folder** label. A picker lists every folder (and **Root**);\npick one to move the Component there once you save. A folder you don't\nhave edit access to is shown but disabled, with an explanation. A folder\nwhose **Allowed Contracts** don't include this Component's Contract is\ndisabled too — unlike an *existing* Component whose folder's rules later\nchange (the **Non-conforming** badge case above), a move that would\nviolate the target folder's rules is rejected outright, so the picker\nwon't offer it as an option in the first place.\n\n### Finding your way back to a folder\n\nThe Component editor shows a breadcrumb above its title (**Content** /\nthe folder it's in / the Component's name) — select the folder name to\nreturn straight to that folder's Contents tab, rather than using your\nbrowser's back button.\n\n## The upgrade badge\n\nIf a Contract changes after a Component was created from it, that\nComponent keeps working exactly as it did — nothing breaks automatically.\nInstead:\n\n- If the Component still satisfies the Contract's latest version, you'll\n see a badge offering **Upgrade to v_N_** — select it to move the\n Component onto the latest version immediately.\n- If it no longer satisfies the latest version, you'll see a\n **Not valid against latest** badge listing exactly what's wrong. Select\n **Start guided upgrade** to switch into editing against the latest\n version, fix the listed issues, and save — the Component moves onto the\n new version as part of that save.\n\nYou're never forced to upgrade; an older Component keeps validating against\nthe version it was created with until you choose to move it forward.\n\n## Asking the assistant to edit this Component\n\nThe help panel's question box (open it from the **?** icon) can see and edit the Component you have\nopen, not only answer questions about it — see **When the assistant can read and edit** in\n[Getting help](../general/getting-help.md). A field edit it makes saves immediately with the same\nversion history a manual edit gets; anything bigger, like deleting the Component, is proposed for\nyou to review first.\n"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"slug": "content-adapters",
|
|
23
23
|
"title": "Bridging Contracts with Adapters",
|
|
24
|
-
"body": "# Bridging Contracts with Adapters\n\nWhen you bind a Component to a Template (see [Authoring a presentation](content-authoring.md)), the\nComponent's Contract normally has to be exactly what the Template needs, or a more specific kind of\nit. Sometimes the Component you want to use has a *different* Contract entirely — an **Adapter**\nbridges that gap by mapping the mismatched Contract's fields onto the ones the Template expects.\n\n## When the wizard offers one\n\nIn the Presentation wizard's **Select existing** tab, a Component whose Contract the Template\ndoesn't recognize at all lands in the **Needs an Adapter** group. Selecting one shows why it doesn't\nfit, and three buttons appear:\n\n- **Use existing Adapter** — pick an already-created Adapter that maps this Component's Contract onto\n something the Template accepts.\n- **Create Adapter** — build a new, reusable, named Adapter right there in the wizard, for this\n Contract pairing. It's saved to the **Adapters** page (under Configure) so anyone can reuse it\n later.\n- **Connect manually** — build a one-off mapping that's saved directly on this Presentation only,\n never listed on the Adapters page. Useful for a mapping you don't expect to need again. A **Save as\n Adapter…** action turns it into a named one later, without redoing the mapping.\n\nEither way, once a mapping is attached the field-by-field connections are drawn between the\nComponent's fields and the Template's, Complete becomes available, and the banner reads \"Mapped via\n*Adapter name*\" (or \"Mapped manually\" for a one-off).\n\nA Component that's already Compatible can still get an Adapter attached deliberately — useful when\nyou want to reshape its content on the way into this particular Template, even though it didn't\nstrictly need mapping.\n\n## After it's mapped\n\nOnce a mapping is attached, the set-value card offers a few more actions beside the Adapter's name:\n\n- **Edit mapping** — reopens the same field-by-field canvas, already filled in with the current\n mapping, so you can adjust it without starting over. This never changes *which* Component is\n bound, and editing a named Adapter's mapping this way never touches the shared Adapter itself (so\n every other Presentation using it is unaffected) — it becomes this Presentation's own one-off\n mapping instead, which you can turn back into a named Adapter with **Save as Adapter…** if you\n want to reuse it elsewhere.\n- **Change** — picks a different Component for this Presentation entirely. If the new Component's\n Contract still works with the mapping that was already in place, it's kept automatically; if not,\n it's dropped and the reason is explained right there, so you can map fresh.\n- **Save as Adapter…** — only shown for a one-off (\"manual mapping\") — turns it into a named,\n reusable Adapter without redoing any of the mapping work.\n\n## The four rule kinds, in plain language\n\nEvery field the Template needs gets exactly one rule saying where its value comes from:\n\n- **Copy** — take the value straight from one of the Component's own fields (the field types have to\n be compatible — see below).\n- **Compute** — build the value from a small set of building blocks: one of the Component's fields, a\n fixed piece of text, joining a few things together with an optional separator, falling back\n through a list of options until one isn't empty, converting a value from one field type to a\n compatible one (e.g. plain text into rich text), taking just the first item of a list, reading a\n field out of a referenced/nested item, mapping every item of a list, dispatching on which kind of\n item you have, or a simple condition/comparison — see **Logic and structure blocks** below for all\n of these. There's no free-text formula box — you build the computation visually, block by block, on\n the canvas.\n- **Map inner content** — for a field that holds another whole piece of content inside it (a nested\n or embedded Component), apply a second, smaller Adapter to that inner content: pick an existing\n named Adapter, or **Connect manually** to name that inner content's own two Contracts and map them\n right there, the same way you'd map the outer fields. (This is also available as the **For each\n item** block's own \"Adapt to another Contract\" mode — see below — which is the way to reach it when\n you're adding a fresh block rather than mapping a whole field.)\n- **Look up a fixed item** — instead of taking a value from the Component being mapped, always pull it\n from one specific, chosen Component or item.\n\n## Field compatibility\n\nTwo fields need to either already match, or be *coercible*, to connect — you can't map a text field\nstraight onto a number field, for example, but a few kinds of mismatch have a small conversion block\nthe canvas offers to insert for you automatically:\n\n- A single value can feed a field that accepts multiple values (it becomes a one-item list) — no\n extra block needed.\n- A field that accepts multiple values can feed a single-value field by inserting a **Take first\n item** block, which uses the first value and drops the rest.\n- Some field types can be converted into others by inserting a **Convert** block — plain text into\n rich text, plain text into a number (fails at delivery time if the text isn't actually numeric), a\n number into text, or rich text into plain text (its formatting is discarded).\n- A field that isn't translatable can feed a translatable one (it becomes that language's default,\n with no translations yet).\n- A field restricted to certain kinds of related content requires the source to already be\n restricted to the same (or a more specific) set.\n\nWhen you connect two fields that need one of these conversions, a small prompt appears offering to\ninsert the right block between them — accept it and the connection completes with that block already\nwired in place. Everything else — a translatable field into a non-translatable one, a personalizable\nfield into a non-personalizable one (or vice versa), or two field types with no registered\nconversion at all — isn't allowed, and the canvas explains why right there instead of drawing a\nconnection (incompatible fields are also visibly dimmed while you have a source selected).\n\n## What \"unmapped — delivers null\" means\n\nEvery field the Template *requires* needs a rule — the canvas won't let you save until they all do.\nA field that's merely optional can be left unmapped; the card for it reads **unmapped — delivers\nnull**, meaning a person or system reading this content afterward will see that field as empty,\nexactly as if it had no value at all. This is often exactly what you want for a field the source\nContract has no equivalent of.\n\n## The mapping canvas\n\nWhether you're on the standalone **Adapters** page (Configure → Adapters → New Adapter) or inside the\nwizard, mapping works the same way: every building block you add is its own node on one draggable,\nzoomable canvas — the **Input document** card starts on the left, the Template's (or the other\nContract's) fields on the right. Drag a line from one connector to another to connect them, or click a\nname to select it as the starting point and then click the one it should feed — both do exactly\nthe same thing, so use whichever is easier at the time. Click an existing connection, or the field's own\ndelete button, to remove it. `Escape` cancels a pending click-to-connect selection.\n\nThe **Input document** card is everything you're mapping *from*, in one place. It's always there, and\nit has three parts:\n\n- **Fields** — one connector per field of the Contract you're mapping from. This is the everyday\n one: drag a field straight across to the output it should fill.\n- **Input document** — the whole piece of content, as one thing. Use this when the same Adapter runs\n over several *different* kinds of content (a search result over every kind of page, say) and you\n need to branch on which kind each one actually is — connect it to a **Switch on Contract** block.\n- **System** — facts about the run itself rather than about the content: **Source contract external\n id** and **Source contract id**, which tell a consumer *which kind* of content a result came from.\n\nThe **+ Add node** button adds a building block to the canvas — **Join text**, **First non-null**, a\n**Constant value**, **Convert type**, **Take first item**, **Look up in** (a fixed reference to one\nComponent), **Expand fields**, **Build value**, **For each item**, **Switch on Contract**, **If / else**,\n**Equals**, or **Exists** (the last seven are covered in **Logic and structure blocks** below). Drag or click to\nwire fields into and out of it just like any other node; each block has its own small settings right on\nthe node itself (which characters to join with, what to convert into, and so on). Delete a block with\nthe **✕** in its own corner.\n\nA required field the Template needs that's still unconnected is called out in red at the bottom of the\ncanvas, and saving stays disabled until every one of them has a rule.\n\nA **Full screen** button, above the canvas, expands it to fill the whole screen for a more complex\nmapping that needs more room to work in — nothing about the mapping is lost switching in or out, and\n`Escape` exits back to the normal view.\n\nA **Preview** button lets you pick a sample piece of content of the source Contract and see exactly\nwhat the mapped result looks like, using the real mapping engine — no guessing.\n\nThe canvas remembers however you arrange the nodes — drag them into a layout that makes sense to\nyou, save, and it's still that way next time you (or anyone else) open this mapping, whether it's a\nnamed Adapter or a one-off mapping on a single Presentation. Dragging snaps each node to a light\ngrid so things line up cleanly. A node you add but never connect to anything doesn't have its\nposition remembered, since it isn't part of the saved mapping at all yet.\n\n## Logic and structure blocks\n\n**Lists always go through a \"For each item\" block.** None of the other blocks below — Expand fields,\nSwitch on Contract, If/else, Equals, Exists — ever work directly on a list; each expects one item.\nWhen the field you're reading from holds a list, add a **For each item** block first: it's the one\nblock that turns a list into \"one item at a time\" and back into a list again. Everything else you\nconnect after it (an Expand, a Switch, a comparison, whatever the mapping needs for one item) runs\nonce per item automatically.\n\n- **Expand fields** — reads a field out of something that isn't a plain value: a referenced item, a\n nested piece of content, or a component field. Pick which Contract you're expecting (skipped\n automatically when there's only one possibility), and the block grows one output for each of that\n Contract's own fields — connect whichever ones you need onward, just like any other field.\n- **Expand Linked Experience** — for a link field that points at a page in your Experience tree:\n opens the linked page in one step. Its outputs are the page's **Name**, **URL**, **Component** (the\n content it's built from — pick a Contract under \"Read content as…\" to get that content's own fields\n as further outputs) and **Presentation** — the page's own rendering, exactly as it's configured\n (its Template, its content, its settings). Connect **Presentation** to a Presentation-typed output\n to show that page's presentation inline on yours — a \"featured pages\" section that re-hosts each\n page's real rendering rather than rebuilding a card from its fields. An outside link, or a page\n with no presentation of its own, gives nothing here; inside a **For each item**, pair it with\n **Keep item when** (below) to drop those. If the output field only allows certain Templates, a\n relayed presentation built on a different Template comes out empty (with a warning) rather than\n slipping through — widen the field's allowed Templates if that's not what you want.\n- **Build value** — the opposite of Expand fields: assembles a nested piece of content, or a component\n field's inline value, out of other fields in this mapping. Pick which Contract you're building, and\n the block grows one input for each of that Contract's own fields (fields with no separate override —\n the \"context\" ones you'd only ever fill in on a specific usage — never appear here at all). Fields\n marked **Required** need a connection before the mapping can be saved; anything else is optional and\n comes out empty if you leave it unconnected. Pick **Nested** or **Component** to match whatever field\n you're feeding the result into.\n- **For each item** — the only block that crosses a list boundary, as above. Choose one of two modes:\n - **Map each item** — click **Edit mapping** to open a dedicated screen (it takes over the whole\n canvas, with a **Back** button to return) where you build the per-item transformation using an\n **Item** starting point and a **Result** ending point, with any of the other blocks in between —\n including another **For each item**, for a list inside a list. That screen also has a second\n ending point, **Keep item when**: wire a yes/no value into it (an Exists or Equals block,\n usually) and only the items where it comes out *yes* make it into the list — the rest are left\n out entirely, with no empty placeholder and no warning for them. Leave it unconnected to keep\n every item. The typical use is a list of links that mixes pages with outside links: **Expand\n Linked Experience → Component → Exists → Keep item when** drops everything that isn't a real\n page, instead of shipping an empty card for it. One output can feed several blocks at once, so\n the same Expand can supply both the check and the result.\n - **Adapt to another Contract** — apply a whole second, smaller Adapter to each item, exactly like\n **Map inner content** above (pick an existing named Adapter, or **Connect manually**).\n- **Switch on Contract** — for a field that could hold more than one kind of thing (several different\n Contracts), branch the mapping by which one it actually is. Add a case for each Contract you want to\n handle by name; each case gets its own **As *(Contract name)*** output (typically feeding an Expand\n fields block for that specific Contract) and its own **Value for this case** input for what should\n come out when it matches. An optional **Default** input covers any Contract you didn't add a case\n for. See **Reading one page type's fields into several outputs**, below, for the two ways to wire\n it up.\n- **If / else** — picks between two values based on a yes/no condition: wire something into **When**\n (must resolve to yes/no — an Exists or Equals block is the usual source), and one value each into\n **Then** and **Else**.\n- **Equals** — compares two values and outputs yes/no; both sides need to already be the same field\n type (no automatic conversion here — insert a Convert type block first if they aren't).\n- **Exists** — outputs yes unless the value it's checking is completely missing or an empty piece of\n text; useful as the condition for an If/else block (\"only use this if there's actually something\n there\").\n\n## Reading one page type's fields into several outputs\n\nA common shape: the same Adapter runs over several kinds of content, and one of those kinds has a\nhandful of extra fields you want to carry through. A search result over every kind of page, where a\nblog post additionally has a heading, an author, a publish date, an image, topics and an excerpt, is\nthe worked example.\n\nWire it exactly the way you'd draw it:\n\n1. **Input document → Switch on Contract** (its **Value to switch on** connector). Add one case,\n *Blog post*.\n2. **As Blog post → Expand fields.** The Expand grows one output per field a blog post has.\n3. Connect each of those outputs **straight across to the output field it fills** — heading to\n Heading, author to Author, and so on. You do not wire anything back into the Switch.\n\nThat's it. Behind the scenes each of those outputs becomes its own rule, gated on \"only when this\nreally is a blog post\"; anything that isn't a blog post simply leaves those fields empty, which is\nwhat you want. Reopening the Adapter later shows you the same one Switch and one Expand you drew.\n\n**Fields every kind of content has come off the Input document, not through the Switch.** Title and\nDescription exist on every page, so wire them straight from the Input document's **Fields** section.\nRouting them through a case would gain nothing and would leave them empty for anything the Switch\ndoesn't have a case for.\n\n**When one output needs a *different* value per type**, that's the Switch's own arms — \"Title is the\nblog post's heading if it's a blog post, otherwise the page's own title\":\n\n1. **Expand fields → heading → Value for this case** (the *Blog post* arm).\n2. **Input document → Fields → Title → Default.**\n3. **Switch → Result → Title.**\n\nOne connector can feed several places at once, so the same Expand's *heading* output can go to both\nthe Heading output field and the Switch's arm — it's still one Switch and one Expand on the canvas.\n\n**One thing the canvas won't do:** read *two different cases'* fields into a single output without\ngoing through the arms. If you try, that output field shows \"Fields read from different cases of one\nSwitch must go through the case arms and Output\" and saving is blocked until you rewire it — combining\nper-case values is exactly what the arms and **Result** are for. Every other output field keeps\nworking normally in the meantime.\n\n## Editing a named Adapter later\n\nAdapters created via **Create Adapter**, or saved via **Save as Adapter…**, live on the **Adapters**\npage (Configure → Adapters), listed with their input and output Contracts. Editing one there updates\nevery Presentation using it — but only once each of those is **published again**. Content that's\nalready published keeps its existing shape until republished, so a mapping change never silently\nchanges something a visitor is looking at right now.\n\nIf a named Adapter is deleted while still bound to a Presentation, the field-by-field connections stop\nresolving correctly — a warning appears on the affected field, and saving is blocked until you either\nrestore the Adapter, pick a different one, or unbind it.\n"
|
|
24
|
+
"body": "# Bridging Contracts with Adapters\n\nWhen you bind a Component to a Template (see [Authoring a presentation](content-authoring.md)), the\nComponent's Contract normally has to be exactly what the Template needs, or a more specific kind of\nit. Sometimes the Component you want to use has a *different* Contract entirely — an **Adapter**\nbridges that gap by mapping the mismatched Contract's fields onto the ones the Template expects.\n\n## When the wizard offers one\n\nIn the Presentation wizard's **Select existing** tab, a Component whose Contract the Template\ndoesn't recognize at all lands in the **Needs an Adapter** group. Selecting one shows why it doesn't\nfit, and three buttons appear:\n\n- **Use existing Adapter** — pick an already-created Adapter that maps this Component's Contract onto\n something the Template accepts.\n- **Create Adapter** — build a new, reusable, named Adapter right there in the wizard, for this\n Contract pairing. It's saved to the **Adapters** page (under Configure) so anyone can reuse it\n later.\n- **Connect manually** — build a one-off mapping that's saved directly on this Presentation only,\n never listed on the Adapters page. Useful for a mapping you don't expect to need again. A **Save as\n Adapter…** action turns it into a named one later, without redoing the mapping.\n\nEither way, once a mapping is attached the field-by-field connections are drawn between the\nComponent's fields and the Template's, Complete becomes available, and the banner reads \"Mapped via\n*Adapter name*\" (or \"Mapped manually\" for a one-off).\n\nA Component that's already Compatible can still get an Adapter attached deliberately — useful when\nyou want to reshape its content on the way into this particular Template, even though it didn't\nstrictly need mapping.\n\n## After it's mapped\n\nOnce a mapping is attached, the set-value card offers a few more actions beside the Adapter's name:\n\n- **Edit mapping** — reopens the same field-by-field canvas, already filled in with the current\n mapping, so you can adjust it without starting over. This never changes *which* Component is\n bound, and editing a named Adapter's mapping this way never touches the shared Adapter itself (so\n every other Presentation using it is unaffected) — it becomes this Presentation's own one-off\n mapping instead, which you can turn back into a named Adapter with **Save as Adapter…** if you\n want to reuse it elsewhere.\n- **Change** — picks a different Component for this Presentation entirely. If the new Component's\n Contract still works with the mapping that was already in place, it's kept automatically; if not,\n it's dropped and the reason is explained right there, so you can map fresh.\n- **Save as Adapter…** — only shown for a one-off (\"manual mapping\") — turns it into a named,\n reusable Adapter without redoing any of the mapping work.\n\n## The four rule kinds, in plain language\n\nEvery field the Template needs gets exactly one rule saying where its value comes from:\n\n- **Copy** — take the value straight from one of the Component's own fields (the field types have to\n be compatible — see below).\n- **Compute** — build the value from a small set of building blocks: one of the Component's fields, a\n fixed piece of text, joining a few things together with an optional separator, falling back\n through a list of options until one isn't empty, converting a value from one field type to a\n compatible one (e.g. plain text into rich text), taking just the first item of a list, reading a\n field out of a referenced/nested item, mapping every item of a list, dispatching on which kind of\n item you have, or a simple condition/comparison — see **Logic and structure blocks** below for all\n of these. There's no free-text formula box — you build the computation visually, block by block, on\n the canvas.\n- **Map inner content** — for a field that holds another whole piece of content inside it (a nested\n or embedded Component), apply a second, smaller Adapter to that inner content: pick an existing\n named Adapter, or **Connect manually** to name that inner content's own two Contracts and map them\n right there, the same way you'd map the outer fields. (This is also available as the **For each\n item** block's own \"Adapt to another Contract\" mode — see below — which is the way to reach it when\n you're adding a fresh block rather than mapping a whole field.)\n- **Look up a fixed item** — instead of taking a value from the Component being mapped, always pull it\n from one specific, chosen Component or item.\n\n## Field compatibility\n\nTwo fields need to either already match, or be *coercible*, to connect — you can't map a text field\nstraight onto a number field, for example, but a few kinds of mismatch have a small conversion block\nthe canvas offers to insert for you automatically:\n\n- A single value can feed a field that accepts multiple values (it becomes a one-item list) — no\n extra block needed.\n- A field that accepts multiple values can feed a single-value field by inserting a **Take first\n item** block, which uses the first value and drops the rest.\n- Some field types can be converted into others by inserting a **Convert** block — plain text into\n rich text, plain text into a number (fails at delivery time if the text isn't actually numeric), a\n number into text, or rich text into plain text (its formatting is discarded).\n- A field that isn't translatable can feed a translatable one (it becomes that language's default,\n with no translations yet).\n- A field restricted to certain kinds of related content requires the source to already be\n restricted to the same (or a more specific) set.\n\nWhen you connect two fields that need one of these conversions, a small prompt appears offering to\ninsert the right block between them — accept it and the connection completes with that block already\nwired in place. Everything else — a translatable field into a non-translatable one, a personalizable\nfield into a non-personalizable one (or vice versa), or two field types with no registered\nconversion at all — isn't allowed, and the canvas explains why right there instead of drawing a\nconnection (incompatible fields are also visibly dimmed while you have a source selected).\n\n## What \"unmapped — delivers null\" means\n\nEvery field the Template *requires* needs a rule — the canvas won't let you save until they all do.\nA field that's merely optional can be left unmapped; the card for it reads **unmapped — delivers\nnull**, meaning a person or system reading this content afterward will see that field as empty,\nexactly as if it had no value at all. This is often exactly what you want for a field the source\nContract has no equivalent of.\n\n## The mapping canvas\n\nWhether you're on the standalone **Adapters** page (Configure → Adapters → New Adapter) or inside the\nwizard, mapping works the same way: every building block you add is its own node on one draggable,\nzoomable canvas — the **Input document** card starts on the left, the Template's (or the other\nContract's) fields on the right. Drag a line from one connector to another to connect them, or click a\nname to select it as the starting point and then click the one it should feed — both do exactly\nthe same thing, so use whichever is easier at the time. Click an existing connection, or the field's own\ndelete button, to remove it. `Escape` cancels a pending click-to-connect selection.\n\nThe **Input document** card is everything you're mapping *from*, in one place. It's always there, and\nit has three parts:\n\n- **Fields** — one connector per field of the Contract you're mapping from. This is the everyday\n one: drag a field straight across to the output it should fill.\n- **Input document** — the whole piece of content, as one thing. Use this when the same Adapter runs\n over several *different* kinds of content (a search result over every kind of page, say) and you\n need to branch on which kind each one actually is — connect it to a **Switch on Contract** block.\n- **System** — facts about the run itself rather than about the content: **Source contract external\n id** and **Source contract id**, which tell a consumer *which kind* of content a result came from.\n\nThe **+ Add node** button adds a building block to the canvas — **Join text**, **First non-null**, a\n**Constant value**, **Convert type**, **Take first item**, **Look up in** (a fixed reference to one\nComponent), **Expand fields**, **Build value**, **For each item**, **Switch on Contract**, **If / else**,\n**Equals**, or **Exists** (the last seven are covered in **Logic and structure blocks** below). Drag or click to\nwire fields into and out of it just like any other node; each block has its own small settings right on\nthe node itself (which characters to join with, what to convert into, and so on). Delete a block with\nthe **✕** in its own corner.\n\nA required field the Template needs that's still unconnected is called out in red at the bottom of the\ncanvas, and saving stays disabled until every one of them has a rule.\n\nA **Full screen** button, above the canvas, expands it to fill the whole screen for a more complex\nmapping that needs more room to work in — nothing about the mapping is lost switching in or out, and\n`Escape` exits back to the normal view.\n\nA **Preview** button lets you pick a sample piece of content of the source Contract and see exactly\nwhat the mapped result looks like, using the real mapping engine — no guessing.\n\nThe canvas remembers however you arrange the nodes — drag them into a layout that makes sense to\nyou, save, and it's still that way next time you (or anyone else) open this mapping, whether it's a\nnamed Adapter or a one-off mapping on a single Presentation. Dragging snaps each node to a light\ngrid so things line up cleanly. A node you add but never connect to anything doesn't have its\nposition remembered, since it isn't part of the saved mapping at all yet.\n\n## Logic and structure blocks\n\n**Lists always go through a \"For each item\" block.** None of the other blocks below — Expand fields,\nSwitch on Contract, If/else, Equals, Exists — ever work directly on a list; each expects one item.\nWhen the field you're reading from holds a list, add a **For each item** block first: it's the one\nblock that turns a list into \"one item at a time\" and back into a list again. Everything else you\nconnect after it (an Expand, a Switch, a comparison, whatever the mapping needs for one item) runs\nonce per item automatically.\n\n- **Expand fields** — reads a field out of something that isn't a plain value: a referenced item, a\n nested piece of content, or a component field. Pick which Contract you're expecting (skipped\n automatically when there's only one possibility), and the block grows one output for each of that\n Contract's own fields — connect whichever ones you need onward, just like any other field.\n- **Expand Linked Experience** — for a link field that points at a page in your Experience tree:\n opens the linked page in one step. Its outputs are the page's **Name**, **URL**, **Component** (the\n content it's built from — pick a Contract under \"Read content as…\" to get that content's own fields\n as further outputs) and **Presentation** — the page's own rendering, exactly as it's configured\n (its Template, its content, its settings). Connect **Presentation** to a Presentation-typed output\n to show that page's presentation inline on yours — a \"featured pages\" section that re-hosts each\n page's real rendering rather than rebuilding a card from its fields. An outside link, or a page\n with no presentation of its own, gives nothing here; inside a **For each item**, pair it with\n **Keep item when** (below) to drop those. If the output field only allows certain Templates, a\n relayed presentation built on a different Template comes out empty (with a warning) rather than\n slipping through — widen the field's allowed Templates if that's not what you want.\n- **Build value** — the opposite of Expand fields: assembles a nested piece of content, or a component\n field's inline value, out of other fields in this mapping. Pick which Contract you're building, and\n the block grows one input for each of that Contract's own fields (fields with no separate override —\n the \"context\" ones you'd only ever fill in on a specific usage — never appear here at all). Fields\n marked **Required** need a connection before the mapping can be saved; anything else is optional and\n comes out empty if you leave it unconnected. Pick **Nested** or **Component** to match whatever field\n you're feeding the result into.\n- **For each item** — the only block that crosses a list boundary, as above. Choose one of two modes:\n - **Map each item** — click **Edit mapping** to open a dedicated screen (it takes over the whole\n canvas, with a **Back** button to return) where you build the per-item transformation using an\n **Item** starting point and a **Result** ending point, with any of the other blocks in between —\n including another **For each item**, for a list inside a list. That screen also has a second\n ending point, **Keep item when**: wire a yes/no value into it (an Exists or Equals block,\n usually) and only the items where it comes out *yes* make it into the list — the rest are left\n out entirely, with no empty placeholder and no warning for them. Leave it unconnected to keep\n every item. The typical use is a list of links that mixes pages with outside links: **Expand\n Linked Experience → Component → Exists → Keep item when** drops everything that isn't a real\n page, instead of shipping an empty card for it. One output can feed several blocks at once, so\n the same Expand can supply both the check and the result.\n - **Adapt to another Contract** — apply a whole second, smaller Adapter to each item, exactly like\n **Map inner content** above (pick an existing named Adapter, or **Connect manually**).\n- **Switch on Contract** — for a field that could hold more than one kind of thing (several different\n Contracts), branch the mapping by which one it actually is. Add a case for each Contract you want to\n handle by name; each case gets its own **As *(Contract name)*** output (typically feeding an Expand\n fields block for that specific Contract) and its own **Value for this case** input for what should\n come out when it matches. An optional **Default** input covers any Contract you didn't add a case\n for. See **Reading one page type's fields into several outputs**, below, for the two ways to wire\n it up.\n- **If / else** — picks between two values based on a yes/no condition: wire something into **When**\n (must resolve to yes/no — an Exists or Equals block is the usual source), and one value each into\n **Then** and **Else**.\n- **Equals** — compares two values and outputs yes/no; both sides need to already be the same field\n type (no automatic conversion here — insert a Convert type block first if they aren't).\n- **Exists** — outputs yes unless the value it's checking is completely missing or an empty piece of\n text; useful as the condition for an If/else block (\"only use this if there's actually something\n there\").\n\n## Reading one page type's fields into several outputs\n\nA common shape: the same Adapter runs over several kinds of content, and one of those kinds has a\nhandful of extra fields you want to carry through. A search result over every kind of page, where a\nblog post additionally has a heading, an author, a publish date, an image, topics and an excerpt, is\nthe worked example.\n\nWire it exactly the way you'd draw it:\n\n1. **Input document → Switch on Contract** (its **Value to switch on** connector). Add one case,\n *Blog post*.\n2. **As Blog post → Expand fields.** The Expand grows one output per field a blog post has.\n3. Connect each of those outputs **straight across to the output field it fills** — heading to\n Heading, author to Author, and so on. You do not wire anything back into the Switch.\n\nThat's it. Behind the scenes each of those outputs becomes its own rule, gated on \"only when this\nreally is a blog post\"; anything that isn't a blog post simply leaves those fields empty, which is\nwhat you want. Reopening the Adapter later shows you the same one Switch and one Expand you drew.\n\n**Fields every kind of content has come off the Input document, not through the Switch.** Title and\nDescription exist on every page, so wire them straight from the Input document's **Fields** section.\nRouting them through a case would gain nothing and would leave them empty for anything the Switch\ndoesn't have a case for.\n\n**When one output needs a *different* value per type**, that's the Switch's own arms — \"Title is the\nblog post's heading if it's a blog post, otherwise the page's own title\":\n\n1. **Expand fields → heading → Value for this case** (the *Blog post* arm).\n2. **Input document → Fields → Title → Default.**\n3. **Switch → Result → Title.**\n\nOne connector can feed several places at once, so the same Expand's *heading* output can go to both\nthe Heading output field and the Switch's arm — it's still one Switch and one Expand on the canvas.\n\n**One thing the canvas won't do:** read *two different cases'* fields into a single output without\ngoing through the arms. If you try, that output field shows \"Fields read from different cases of one\nSwitch must go through the case arms and Output\" and saving is blocked until you rewire it — combining\nper-case values is exactly what the arms and **Result** are for. Every other output field keeps\nworking normally in the meantime.\n\n## Suggest rules (Early Access)\n\nFor an organization with this Early Access feature turned on, a **Suggest rules** button appears\nabove the mapping canvas. Describe what you want in plain language — \"map the product's name to the\ncard's title, and its price to the subtitle as a formatted string\" — and it reads the two Contracts\ninvolved, drafts a candidate mapping, and checks its own work against the same validation the canvas\nalready runs, retrying until it's valid or it gives up and says so.\n\n**Nothing is written until you say so.** The panel shows the proposed rules — never the saved\nAdapter — with **Accept** and **Dismiss**. Accept merges the proposal into the mapping you're\ncurrently editing; you still have to press **Save** afterward, exactly as if you'd drawn the\nconnections yourself. Dismiss discards the proposal with no trace. If you already have some of the\nmapping done, describe what's missing — it's told what's already there and builds on it rather than\nstarting over.\n\nIf it can't produce a valid mapping, it says so rather than proposing something broken. If your\norganization has connected its own AI provider credential (see the **AI** section of your\norganization's settings), suggestions run on that provider instead of ebitex's, and a provider-side\nproblem (an expired key, exhausted credit) is reported by name so you know where to look.\n\n## Editing a named Adapter later\n\nAdapters created via **Create Adapter**, or saved via **Save as Adapter…**, live on the **Adapters**\npage (Configure → Adapters), listed with their input and output Contracts. Editing one there updates\nevery Presentation using it — but only once each of those is **published again**. Content that's\nalready published keeps its existing shape until republished, so a mapping change never silently\nchanges something a visitor is looking at right now.\n\nIf a named Adapter is deleted while still bound to a Presentation, the field-by-field connections stop\nresolving correctly — a warning appears on the affected field, and saving is blocked until you either\nrestore the Adapter, pick a different one, or unbind it.\n"
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"slug": "content-authoring",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpCorpus.generated.js","sourceRoot":"","sources":["../../src/resources/helpCorpus.generated.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,kGAAkG;AAClG,oGAAoG;AAIpG,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,0CAA0C;QACnD,MAAM,EAAE,knWAAknW;KAC3nW;IACD;QACE,MAAM,EAAE,aAAa;QACrB,OAAO,EAAE,aAAa;QACtB,MAAM,EAAE,wnGAAwnG;KACjoG;IACD;QACE,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,sBAAsB;QAC/B,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"helpCorpus.generated.js","sourceRoot":"","sources":["../../src/resources/helpCorpus.generated.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,kGAAkG;AAClG,oGAAoG;AAIpG,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,0CAA0C;QACnD,MAAM,EAAE,knWAAknW;KAC3nW;IACD;QACE,MAAM,EAAE,aAAa;QACrB,OAAO,EAAE,aAAa;QACtB,MAAM,EAAE,wnGAAwnG;KACjoG;IACD;QACE,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,sBAAsB;QAC/B,MAAM,EAAE,k9VAAk9V;KAC39V;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,kCAAkC;QAC3C,MAAM,EAAE,ggnBAAggnB;KACzgnB;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,0BAA0B;QACnC,MAAM,EAAE,6oLAA6oL;KACtpL;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,gCAAgC;QACzC,MAAM,EAAE,qyfAAqyf;KAC9yf;IACD;QACE,MAAM,EAAE,sBAAsB;QAC9B,OAAO,EAAE,sBAAsB;QAC/B,MAAM,EAAE,s3qBAAs3qB;KAC/3qB;IACD;QACE,MAAM,EAAE,eAAe;QACvB,OAAO,EAAE,qCAAqC;QAC9C,MAAM,EAAE,q3FAAq3F;KAC93F;IACD;QACE,MAAM,EAAE,yBAAyB;QACjC,OAAO,EAAE,4BAA4B;QACrC,MAAM,EAAE,2jRAA2jR;KACpkR;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,6/HAA6/H;KACtgI;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,4CAA4C;QACrD,MAAM,EAAE,22GAA22G;KACp3G;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,UAAU;QACnB,MAAM,EAAE,wvJAAwvJ;KACjwJ;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,oBAAoB;QAC7B,MAAM,EAAE,82WAA82W;KACv3W;IACD;QACE,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,iCAAiC;QAC1C,MAAM,EAAE,s2XAAs2X;KAC/2X;IACD;QACE,MAAM,EAAE,qBAAqB;QAC7B,OAAO,EAAE,qBAAqB;QAC9B,MAAM,EAAE,+iFAA+iF;KACxjF;IACD;QACE,MAAM,EAAE,eAAe;QACvB,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,u/JAAu/J;KAChgK;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,upIAAupI;KAChqI;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,iBAAiB;QAC1B,MAAM,EAAE,ugNAAugN;KAChhN;IACD;QACE,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,WAAW;QACpB,MAAM,EAAE,m7KAAm7K;KAC57K;IACD;QACE,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,oBAAoB;QAC7B,MAAM,EAAE,2hVAA2hV;KACpiV;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,+BAA+B;QACxC,MAAM,EAAE,g2EAAg2E;KACz2E;IACD;QACE,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,i7FAAi7F;KAC17F;IACD;QACE,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,mCAAmC;QAC5C,MAAM,EAAE,8vKAA8vK;KACvwK;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,kBAAkB;QAC3B,MAAM,EAAE,6hJAA6hJ;KACtiJ;CACF,CAAA"}
|
package/dist/tools/catalog.d.ts
CHANGED
|
@@ -21,12 +21,27 @@ import { type EntityKind } from '../routes.js';
|
|
|
21
21
|
* key acquiring one.
|
|
22
22
|
*/
|
|
23
23
|
export declare const AUTHENTICATED: "*";
|
|
24
|
+
/**
|
|
25
|
+
* The three entity kinds `content_write` may commit immediately from the in-app assistant (spec
|
|
26
|
+
* 939-ai-inline-assistant) rather than as a deferred suggestion: `component` and `node` implement
|
|
27
|
+
* `IVersionedEntity` server-side; `nodePayload` writes the same `ExperienceNode` row through its own
|
|
28
|
+
* route (`PUT /experience/nodes/{id}/payload`) and so qualifies too. `contract` does **not** — it
|
|
29
|
+
* implements only `IConcurrencyProtected` (a bespoke additive/breaking generation counter, not the
|
|
30
|
+
* generic save-history surface) — so it stays deferred like every other non-versioned kind. This
|
|
31
|
+
* field carries no meaning for `content-mcp` itself (an external agent's write always executes
|
|
32
|
+
* directly, immediately, regardless of tier); it exists here only so this file stays the one place
|
|
33
|
+
* that states the fact, mirrored server-side by `ManagementToolCatalog.ContentWriteImmediateKinds`
|
|
34
|
+
* and held in parity by `tool-catalogue.json`.
|
|
35
|
+
*/
|
|
36
|
+
export declare const CONTENT_WRITE_IMMEDIATE_KINDS: readonly ["component", "node", "nodePayload"];
|
|
24
37
|
export type ToolDescriptor = {
|
|
25
38
|
name: string;
|
|
26
39
|
requiredScope: string;
|
|
27
40
|
readOnly: boolean;
|
|
28
41
|
/** Present only for the three tools whose `kind` parameter is drawn from `WRITABLE_KINDS`. */
|
|
29
42
|
kinds?: readonly EntityKind[];
|
|
43
|
+
/** Present only for `content_write` — see {@link CONTENT_WRITE_IMMEDIATE_KINDS}. */
|
|
44
|
+
immediateKinds?: readonly EntityKind[];
|
|
30
45
|
};
|
|
31
46
|
export declare const TOOL_CATALOG: readonly ToolDescriptor[];
|
|
32
47
|
/** Whether `session` may see the named tool, per the catalogue's `requiredScope`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/tools/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAA;AAG9D;;;;;;;;;;;;GAYG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAG,GAAY,CAAA;AAEzC,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,OAAO,CAAA;IACjB,8FAA8F;IAC9F,KAAK,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/tools/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAA;AAG9D;;;;;;;;;;;;GAYG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAG,GAAY,CAAA;AAEzC;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,6BAA6B,+CAAgD,CAAA;AAE1F,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,OAAO,CAAA;IACjB,8FAA8F;IAC9F,KAAK,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;IAC7B,oFAAoF;IACpF,cAAc,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;CACvC,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,SAAS,cAAc,EAqBxC,CAAA;AAQV,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGjG"}
|
package/dist/tools/catalog.js
CHANGED
|
@@ -22,6 +22,19 @@ import { SCOPE_AUTHORING, SCOPE_PUBLISH, SCOPE_READ } from '../session.js';
|
|
|
22
22
|
* key acquiring one.
|
|
23
23
|
*/
|
|
24
24
|
export const AUTHENTICATED = '*';
|
|
25
|
+
/**
|
|
26
|
+
* The three entity kinds `content_write` may commit immediately from the in-app assistant (spec
|
|
27
|
+
* 939-ai-inline-assistant) rather than as a deferred suggestion: `component` and `node` implement
|
|
28
|
+
* `IVersionedEntity` server-side; `nodePayload` writes the same `ExperienceNode` row through its own
|
|
29
|
+
* route (`PUT /experience/nodes/{id}/payload`) and so qualifies too. `contract` does **not** — it
|
|
30
|
+
* implements only `IConcurrencyProtected` (a bespoke additive/breaking generation counter, not the
|
|
31
|
+
* generic save-history surface) — so it stays deferred like every other non-versioned kind. This
|
|
32
|
+
* field carries no meaning for `content-mcp` itself (an external agent's write always executes
|
|
33
|
+
* directly, immediately, regardless of tier); it exists here only so this file stays the one place
|
|
34
|
+
* that states the fact, mirrored server-side by `ManagementToolCatalog.ContentWriteImmediateKinds`
|
|
35
|
+
* and held in parity by `tool-catalogue.json`.
|
|
36
|
+
*/
|
|
37
|
+
export const CONTENT_WRITE_IMMEDIATE_KINDS = ['component', 'node', 'nodePayload'];
|
|
25
38
|
export const TOOL_CATALOG = [
|
|
26
39
|
{ name: 'content_whoami', requiredScope: AUTHENTICATED, readOnly: true },
|
|
27
40
|
{ name: 'content_describe', requiredScope: SCOPE_READ, readOnly: true },
|
|
@@ -29,7 +42,13 @@ export const TOOL_CATALOG = [
|
|
|
29
42
|
{ name: 'content_get', requiredScope: SCOPE_READ, readOnly: true, kinds: WRITABLE_KINDS },
|
|
30
43
|
{ name: 'content_topology', requiredScope: SCOPE_READ, readOnly: true },
|
|
31
44
|
{ name: 'content_operation_status', requiredScope: SCOPE_READ, readOnly: true },
|
|
32
|
-
{
|
|
45
|
+
{
|
|
46
|
+
name: 'content_write',
|
|
47
|
+
requiredScope: SCOPE_AUTHORING,
|
|
48
|
+
readOnly: false,
|
|
49
|
+
kinds: WRITABLE_KINDS,
|
|
50
|
+
immediateKinds: CONTENT_WRITE_IMMEDIATE_KINDS,
|
|
51
|
+
},
|
|
33
52
|
{ name: 'content_delete', requiredScope: SCOPE_AUTHORING, readOnly: false, kinds: WRITABLE_KINDS },
|
|
34
53
|
{ name: 'content_publish', requiredScope: SCOPE_PUBLISH, readOnly: false },
|
|
35
54
|
// Corrected from SCOPE_WRITE (spec 887): the tool's own always-executed first call, /export,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/tools/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAmB,MAAM,cAAc,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE1E;;;;;;;;;;;;GAYG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/tools/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAmB,MAAM,cAAc,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE1E;;;;;;;;;;;;GAYG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAY,CAAA;AAEzC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,CAAU,CAAA;AAY1F,MAAM,CAAC,MAAM,YAAY,GAA8B;IACrD,EAAE,IAAI,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;IACxE,EAAE,IAAI,EAAE,kBAAkB,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE;IACvE,EAAE,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE;IACnE,EAAE,IAAI,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE;IACzF,EAAE,IAAI,EAAE,kBAAkB,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE;IACvE,EAAE,IAAI,EAAE,0BAA0B,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC/E;QACE,IAAI,EAAE,eAAe;QACrB,aAAa,EAAE,eAAe;QAC9B,QAAQ,EAAE,KAAK;QACf,KAAK,EAAE,cAAc;QACrB,cAAc,EAAE,6BAA6B;KAC9C;IACD,EAAE,IAAI,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE;IAClG,EAAE,IAAI,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE;IAC1E,6FAA6F;IAC7F,8FAA8F;IAC9F,iGAAiG;IACjG,6FAA6F;IAC7F,EAAE,IAAI,EAAE,kBAAkB,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE;CAChE,CAAA;AAEV,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;IAClE,IAAI,CAAC,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,8BAA8B,CAAC,CAAA;IAClG,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,aAAa,CAAC,OAAwC,EAAE,QAAgB;IACtF,MAAM,EAAE,aAAa,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAA;IACjD,OAAO,aAAa,KAAK,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;AACtE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ebitex/content-mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.122",
|
|
4
4
|
"description": "An MCP server for ebitex Content: build and publish a content model from an AI agent.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://developers.ebitex.io/getting-started/content-as-code/",
|