@wix/mcp 1.0.28 → 1.0.30
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/README.md +1 -0
- package/build/bin-standalone.js +214 -5
- package/build/bin-standalone.js.map +2 -2
- package/build/cjs/index.cjs +388 -16
- package/build/cjs/index.cjs.map +4 -4
- package/build/dts/bin.d.ts +1 -1
- package/build/dts/bin.d.ts.map +1 -1
- package/build/dts/code-mode/index.d.ts +10 -0
- package/build/dts/code-mode/index.d.ts.map +1 -0
- package/build/dts/code-mode/index.js +150 -0
- package/build/dts/code-mode/index.js.map +1 -0
- package/build/dts/config/default-config.d.ts +1 -0
- package/build/dts/config/default-config.d.ts.map +1 -1
- package/build/dts/config/default-config.js +147 -2
- package/build/dts/config/default-config.js.map +1 -1
- package/build/dts/config/param-descriptions.d.ts +5 -0
- package/build/dts/config/param-descriptions.d.ts.map +1 -1
- package/build/dts/config/param-descriptions.js +7 -2
- package/build/dts/config/param-descriptions.js.map +1 -1
- package/build/dts/docs/docs.d.ts +1 -1
- package/build/dts/docs/docs.d.ts.map +1 -1
- package/build/dts/docs/docs.js +56 -2
- package/build/dts/docs/docs.js.map +1 -1
- package/build/dts/docs/semanticSearch.d.ts.map +1 -1
- package/build/dts/docs/semanticSearch.js +3 -0
- package/build/dts/docs/semanticSearch.js.map +1 -1
- package/build/dts/docs/semanticSearch.test.js +33 -0
- package/build/dts/docs/semanticSearch.test.js.map +1 -1
- package/build/dts/index.d.ts +1 -0
- package/build/dts/index.d.ts.map +1 -1
- package/build/dts/index.js +2 -0
- package/build/dts/index.js.map +1 -1
- package/build/dts/site-widget-tools/site-builder-tool/index.d.ts +0 -7
- package/build/dts/site-widget-tools/site-builder-tool/index.d.ts.map +1 -1
- package/build/dts/site-widget-tools/site-builder-tool/index.js +6 -10
- package/build/dts/site-widget-tools/site-builder-tool/index.js.map +1 -1
- package/build/esm/index.js +387 -16
- package/build/esm/index.js.map +4 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -70,6 +70,7 @@ Set logging output:
|
|
|
70
70
|
- `WIX_HEADLESS`: Wix Headless Documentation (`SearchWixHeadlessDocumentation`)
|
|
71
71
|
- `VELO`: Velo Documentation (`SearchWixVeloDocumentation`)
|
|
72
72
|
- `BUSINESS_SOLUTIONS`: Business solutions recipes (`WixBusinessFlowsDocumentation`)
|
|
73
|
+
- `CLI`: Wix CLI Documentation (`SearchWixCLIDocumentation`)
|
|
73
74
|
|
|
74
75
|
**Experimental Tools:**
|
|
75
76
|
|
package/build/bin-standalone.js
CHANGED
|
@@ -10329,6 +10329,8 @@ var runSemanticSearch = async (toolName, toolParams, maxResults = 20, rerank = f
|
|
|
10329
10329
|
kbNames.push("HEADLESS_KB_ID");
|
|
10330
10330
|
} else if (toolName === "VELO") {
|
|
10331
10331
|
kbNames.push("VELO_DOCS_KB_ID", "VELO_METHODS_KB_ID");
|
|
10332
|
+
} else if (toolName === "CLI") {
|
|
10333
|
+
kbNames.push("CLI_KB_ID");
|
|
10332
10334
|
}
|
|
10333
10335
|
logger.log(
|
|
10334
10336
|
`[SemanticSearch] Tool: ${toolName}, KBs: [${kbNames.join(", ")}], Query: "${toolParams.searchTerm}"`
|
|
@@ -10772,7 +10774,8 @@ var defaultToolDescriptions = {
|
|
|
10772
10774
|
${SYSTEM_REMINDER}
|
|
10773
10775
|
`,
|
|
10774
10776
|
CallWixSiteAPI: dedent_default`
|
|
10775
|
-
Call Wix apis on a business or site. Use this to create, read, update, and delete data and other Wix entities in your Wix site
|
|
10777
|
+
Call Wix apis on a business or site. Use this to create, read, update, and delete data and other Wix entities in your Wix site.
|
|
10778
|
+
For POST/PATCH/PUT requests, pass the request body as a JSON object in the "body" parameter with all the required fields and values as described in the API schema, code examples, or docs you retrieved (e.g. body: {"name": "value", "nested": {"key": "value"}}).
|
|
10776
10779
|
The API endpoint url param MUST ALWAYS be taken from the conversation context.
|
|
10777
10780
|
By conversation context we mean the endpoint url was given in the user prompt OR got into the conversation context by the "WixREADME" tool OR by the "SearchWixRESTDocumentation" tool OR by the "BrowseWixRESTDocsMenu" tool OR by the "ReadFullDocsArticle" tool.
|
|
10778
10781
|
Error Handling:
|
|
@@ -10789,6 +10792,7 @@ var defaultToolDescriptions = {
|
|
|
10789
10792
|
`,
|
|
10790
10793
|
ManageWixSite: dedent_default`
|
|
10791
10794
|
Use account level API in order to create a site, update a site and publish site.
|
|
10795
|
+
For POST/PATCH/PUT requests, pass the request body as a JSON object in the "body" parameter with all the required fields and values as described in the API schema, code examples, or docs you retrieved (e.g. body: {"name": "value", "nested": {"key": "value"}}).
|
|
10792
10796
|
The API endpoint url param MUST ALWAYS be taken from the conversation context.
|
|
10793
10797
|
By conversation context we mean the endpoint url was given in the user prompt or got into the conversation context by the "WixREADME" tool or by the "SearchWixRESTDocumentation" tool or by the "BrowseWixRESTDocsMenu" tool or by the "ReadFullDocsArticle" tool.
|
|
10794
10798
|
${SYSTEM_REMINDER}
|
|
@@ -10866,6 +10870,148 @@ var defaultToolDescriptions = {
|
|
|
10866
10870
|
`,
|
|
10867
10871
|
VeloREADME: dedent_default`
|
|
10868
10872
|
This tool is set for providing Velo context in order to be used by the agent for executing Velo-related tasks.
|
|
10873
|
+
`,
|
|
10874
|
+
SearchWixCLIDocumentation: dedent_default`
|
|
10875
|
+
Searches the Wix CLI documentation for website development and CLI commands.
|
|
10876
|
+
Use this tool when you need information about Wix CLI commands, local development workflows, or CLI-based website development.
|
|
10877
|
+
Specify what you need information about (e.g., 'wix dev command', 'local development setup', 'CLI authentication', 'wix deploy').
|
|
10878
|
+
If you can't find what you need, try to rephrase your search term or use bigger maxResults value.
|
|
10879
|
+
${SYSTEM_REMINDER}
|
|
10880
|
+
`,
|
|
10881
|
+
SearchWixAPISpec: dedent_default`
|
|
10882
|
+
Search the Wix REST API documentation by writing JavaScript code that runs in a sandboxed environment.
|
|
10883
|
+
Your code has access to two globals:
|
|
10884
|
+
|
|
10885
|
+
**lightIndex** — Array of all Wix REST API resources (~330):
|
|
10886
|
+
\`\`\`typescript
|
|
10887
|
+
interface LightResource {
|
|
10888
|
+
name: string; // e.g. "Products V3", "Contact V4"
|
|
10889
|
+
resourceId: string;
|
|
10890
|
+
menuPath: string[]; // e.g. ["business-solutions", "stores", "catalog-v3", "products-v3"]
|
|
10891
|
+
methods: Array<{
|
|
10892
|
+
operationId: string; // e.g. "wix.stores.catalog.v3.CatalogApi.CreateProduct"
|
|
10893
|
+
summary: string; // e.g. "Create Product"
|
|
10894
|
+
httpMethod: string; // "get" | "post" | "patch" | "delete"
|
|
10895
|
+
path: string; // e.g. "/v3/products"
|
|
10896
|
+
description: string; // truncated to 200 chars
|
|
10897
|
+
}>;
|
|
10898
|
+
}
|
|
10899
|
+
\`\`\`
|
|
10900
|
+
|
|
10901
|
+
**getResourceSchema(resourceId)** — Async function returning the full schema for a resource:
|
|
10902
|
+
\`\`\`typescript
|
|
10903
|
+
interface FullSchema {
|
|
10904
|
+
title: string;
|
|
10905
|
+
description: string;
|
|
10906
|
+
fqdn: string;
|
|
10907
|
+
methods: Array<{
|
|
10908
|
+
summary: string;
|
|
10909
|
+
description: string;
|
|
10910
|
+
operationId: string;
|
|
10911
|
+
httpMethod: string;
|
|
10912
|
+
path: string;
|
|
10913
|
+
servers: Array<{ url: string }>; // Base URLs (e.g. "https://www.wixapis.com/...")
|
|
10914
|
+
requestBody: object | null;
|
|
10915
|
+
responses: object;
|
|
10916
|
+
parameters: Array<object>;
|
|
10917
|
+
permissions: string[];
|
|
10918
|
+
legacyExamples: Array<{ // Curl examples
|
|
10919
|
+
content: { title: string; request: string; response: string };
|
|
10920
|
+
}>;
|
|
10921
|
+
sdkData: { // JS SDK examples
|
|
10922
|
+
packageName: string;
|
|
10923
|
+
namespace: string;
|
|
10924
|
+
methodExamples: Array<{ title: string; content: string }>;
|
|
10925
|
+
};
|
|
10926
|
+
}>;
|
|
10927
|
+
components: { schemas: object };
|
|
10928
|
+
}
|
|
10929
|
+
\`\`\`
|
|
10930
|
+
|
|
10931
|
+
Your code MUST be an \`async function()\` expression that returns a value.
|
|
10932
|
+
|
|
10933
|
+
Top-level verticals: business-solutions (stores, e-commerce, bookings, events, restaurants, pricing-plans, coupons), crm (contacts, members, loyalty-program, forms, community), business-management (payments, invoices, automations), assets (media, files), app-management (oauth, billing), account-level, site.
|
|
10934
|
+
|
|
10935
|
+
Examples:
|
|
10936
|
+
|
|
10937
|
+
Find APIs by keyword:
|
|
10938
|
+
\`\`\`javascript
|
|
10939
|
+
async function() {
|
|
10940
|
+
return lightIndex.filter(r => r.methods.some(m => m.summary.toLowerCase().includes("query products")))
|
|
10941
|
+
.map(r => ({ name: r.name, methods: r.methods.map(m => m.summary + " (" + m.httpMethod.toUpperCase() + " " + m.path + ")") }));
|
|
10942
|
+
}
|
|
10943
|
+
\`\`\`
|
|
10944
|
+
|
|
10945
|
+
Get full schema with base URL, curl examples, and permissions:
|
|
10946
|
+
\`\`\`javascript
|
|
10947
|
+
async function() {
|
|
10948
|
+
const resource = lightIndex.find(r => r.name === "Contact V4");
|
|
10949
|
+
const schema = await getResourceSchema(resource.resourceId);
|
|
10950
|
+
const method = schema.methods.find(m => m.summary === "Query Contacts");
|
|
10951
|
+
return {
|
|
10952
|
+
baseUrl: method.servers?.find(s => s.url.includes("wixapis.com"))?.url,
|
|
10953
|
+
path: method.path,
|
|
10954
|
+
httpMethod: method.httpMethod,
|
|
10955
|
+
permissions: method.permissions,
|
|
10956
|
+
requestBody: method.requestBody,
|
|
10957
|
+
curlExample: method.legacyExamples?.[0]?.content,
|
|
10958
|
+
sdkExample: method.sdkData?.methodExamples?.[0]?.content
|
|
10959
|
+
};
|
|
10960
|
+
}
|
|
10961
|
+
\`\`\`
|
|
10962
|
+
|
|
10963
|
+
Browse a vertical:
|
|
10964
|
+
\`\`\`javascript
|
|
10965
|
+
async function() {
|
|
10966
|
+
return lightIndex.filter(r => r.menuPath[0] === "crm")
|
|
10967
|
+
.map(r => ({ name: r.name, path: r.menuPath.join(" > "), methods: r.methods.length }));
|
|
10968
|
+
}
|
|
10969
|
+
\`\`\`
|
|
10970
|
+
`,
|
|
10971
|
+
ExecuteWixAPI: dedent_default`
|
|
10972
|
+
Execute JavaScript code against the Wix REST API. First use the 'SearchWixAPISpec' tool to find the right endpoints, base URLs, and request/response schemas. Then write code using the wix.request() function. Auth is handled automatically — do not set Authorization headers.
|
|
10973
|
+
|
|
10974
|
+
Available in your code:
|
|
10975
|
+
\`\`\`typescript
|
|
10976
|
+
interface WixRequestOptions {
|
|
10977
|
+
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
10978
|
+
url: string; // Full URL from schema servers field, e.g. "https://www.wixapis.com/contacts/v4/contacts"
|
|
10979
|
+
body?: unknown;
|
|
10980
|
+
headers?: Record<string, string>; // Do NOT set Authorization — it is injected automatically
|
|
10981
|
+
}
|
|
10982
|
+
|
|
10983
|
+
interface WixResponse<T = unknown> {
|
|
10984
|
+
status: number;
|
|
10985
|
+
data: T;
|
|
10986
|
+
}
|
|
10987
|
+
|
|
10988
|
+
declare const wix: {
|
|
10989
|
+
request<T = unknown>(options: WixRequestOptions): Promise<WixResponse<T>>;
|
|
10990
|
+
};
|
|
10991
|
+
|
|
10992
|
+
declare const siteId: string | undefined;
|
|
10993
|
+
\`\`\`
|
|
10994
|
+
|
|
10995
|
+
Your code MUST be an \`async function()\` expression that returns the result.
|
|
10996
|
+
|
|
10997
|
+
Example — query products then update one:
|
|
10998
|
+
\`\`\`javascript
|
|
10999
|
+
async function() {
|
|
11000
|
+
const list = await wix.request({
|
|
11001
|
+
method: "POST",
|
|
11002
|
+
url: "https://www.wixapis.com/stores/v1/products/query",
|
|
11003
|
+
body: { query: { paging: { limit: 5 } } }
|
|
11004
|
+
});
|
|
11005
|
+
const product = list.data.products[0];
|
|
11006
|
+
if (!product) return { error: "No products found" };
|
|
11007
|
+
const updated = await wix.request({
|
|
11008
|
+
method: "PATCH",
|
|
11009
|
+
url: \`https://www.wixapis.com/stores/v1/products/\${product.id}\`,
|
|
11010
|
+
body: { product: { name: "Updated Name" } }
|
|
11011
|
+
});
|
|
11012
|
+
return updated.data;
|
|
11013
|
+
}
|
|
11014
|
+
\`\`\`
|
|
10869
11015
|
`
|
|
10870
11016
|
};
|
|
10871
11017
|
var defaultReadmeDocs = [
|
|
@@ -11159,7 +11305,7 @@ var paramDescriptions = {
|
|
|
11159
11305
|
`Docs urls like https://dev.wix.com/docs/... are not API urls, if you want to read the docs, use the "ReadFullDocsArticle" tool`
|
|
11160
11306
|
].join("\n"),
|
|
11161
11307
|
method: "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)",
|
|
11162
|
-
body: 'The request body object. YOU MUST NEVER MAKE UP A BODY - the body should be based on the conversation context, i.e from the user prompt OR got into the conversation context by the "ReadFullDocsArticle" tool OR by the "ReadFullDocsMethodSchema" tool - i.e based on the API docs, a relevant recipe you read (preferably), a code example you found in the docs, a schema you read etc.. YOU MUST NEVER ASSUME YOU KNOW WHAT THE BODY SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT. Prefer reading relevant recipes if you have them in context for understand the body schema for API calls.',
|
|
11308
|
+
body: 'The request body as a JSON object with all the required fields and values, including nested objects. Pass the actual object, NOT a JSON string. YOU MUST NEVER MAKE UP A BODY - the body should be based on the conversation context, i.e from the user prompt OR got into the conversation context by the "ReadFullDocsArticle" tool OR by the "ReadFullDocsMethodSchema" tool - i.e based on the API docs, a relevant recipe you read (preferably), a code example you found in the docs, a schema you read etc.. YOU MUST NEVER ASSUME YOU KNOW WHAT THE BODY SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT. Prefer reading relevant recipes if you have them in context for understand the body schema for API calls.',
|
|
11163
11309
|
reason: "One sentence explaining the original user request and why you are calling this API to complete it.",
|
|
11164
11310
|
sourceDocUrl: [
|
|
11165
11311
|
"The URL of the documentation or recipe where you found this API endpoint.",
|
|
@@ -11177,7 +11323,7 @@ var paramDescriptions = {
|
|
|
11177
11323
|
ManageWixSite: {
|
|
11178
11324
|
url: "The url of the api to call - ALWAYS get the information from the Wix REST docs DONT GUESS IT, the URL MUST BE ABSOLUTE URL",
|
|
11179
11325
|
method: "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)",
|
|
11180
|
-
body: 'The request body object. YOU MUST NEVER MAKE UP A BODY - this should be based on the conversation context, i.e from the user prompt or from the "WixREADME" tool or from the "SearchWixRESTDocumentation" tool or from the "BrowseWixRESTDocsMenu" tool or from the "ReadFullDocsArticle" tool or from the "ReadFullDocsMethodSchema" tool - i.e based on the API docs. YOU MUST NEVER ASSUME YOU KNOW WHAT THE SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT.'
|
|
11326
|
+
body: 'The request body as a JSON object with all the required fields and values, including nested objects. Pass the actual object, NOT a JSON string. YOU MUST NEVER MAKE UP A BODY - this should be based on the conversation context, i.e from the user prompt or from the "WixREADME" tool or from the "SearchWixRESTDocumentation" tool or from the "BrowseWixRESTDocsMenu" tool or from the "ReadFullDocsArticle" tool or from the "ReadFullDocsMethodSchema" tool - i.e based on the API docs. YOU MUST NEVER ASSUME YOU KNOW WHAT THE SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT.'
|
|
11181
11327
|
},
|
|
11182
11328
|
SearchWixWDSDocumentation: {
|
|
11183
11329
|
searchTerm: "The search term to search for in the Wix Design System Documentation",
|
|
@@ -11208,6 +11354,11 @@ var paramDescriptions = {
|
|
|
11208
11354
|
searchTerm: "The search term to search for in the Velo Documentation",
|
|
11209
11355
|
maxResults: "The maximum number of results to return, default is 5, max is 15"
|
|
11210
11356
|
},
|
|
11357
|
+
SearchWixCLIDocumentation: {
|
|
11358
|
+
searchTerm: "The search term to search for in the Wix CLI Documentation",
|
|
11359
|
+
maxResults: "The maximum number of results to return, default is 5, max is 15",
|
|
11360
|
+
reason: "One sentence describing the original user request and the task you are trying to accomplish with this search."
|
|
11361
|
+
},
|
|
11211
11362
|
ReadFullDocsArticle: {
|
|
11212
11363
|
articleUrl: "The URL of the docs article or method article to fetch. Should be something like https://dev.wix.com/docs/.../.../..."
|
|
11213
11364
|
},
|
|
@@ -11246,7 +11397,8 @@ var VALID_DOCS_TOOLS = [
|
|
|
11246
11397
|
"BUILD_APPS",
|
|
11247
11398
|
"WIX_HEADLESS",
|
|
11248
11399
|
"VELO",
|
|
11249
|
-
"BUSINESS_SOLUTIONS"
|
|
11400
|
+
"BUSINESS_SOLUTIONS",
|
|
11401
|
+
"CLI"
|
|
11250
11402
|
];
|
|
11251
11403
|
var addDocsTools = (server2, allowedTools = [
|
|
11252
11404
|
"WDS",
|
|
@@ -11254,7 +11406,8 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
11254
11406
|
"SDK",
|
|
11255
11407
|
"BUILD_APPS",
|
|
11256
11408
|
"WIX_HEADLESS",
|
|
11257
|
-
"BUSINESS_SOLUTIONS"
|
|
11409
|
+
"BUSINESS_SOLUTIONS",
|
|
11410
|
+
"CLI"
|
|
11258
11411
|
], options = {}) => {
|
|
11259
11412
|
const {
|
|
11260
11413
|
getToKnowWixEnabled = false,
|
|
@@ -11663,6 +11816,62 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
11663
11816
|
}
|
|
11664
11817
|
);
|
|
11665
11818
|
}
|
|
11819
|
+
if (allowedTools.includes("CLI") && !disableTools?.includes("SearchWixCLIDocumentation")) {
|
|
11820
|
+
server2.tool(
|
|
11821
|
+
"SearchWixCLIDocumentation",
|
|
11822
|
+
getDescription(
|
|
11823
|
+
"SearchWixCLIDocumentation",
|
|
11824
|
+
defaultToolDescriptions.SearchWixCLIDocumentation ?? ""
|
|
11825
|
+
),
|
|
11826
|
+
(() => {
|
|
11827
|
+
const d = desc("SearchWixCLIDocumentation");
|
|
11828
|
+
return {
|
|
11829
|
+
searchTerm: z.string().describe(d.searchTerm),
|
|
11830
|
+
maxResults: z.number().describe(d.maxResults).min(1).max(15).optional().default(10),
|
|
11831
|
+
reason: z.string().describe(d.reason)
|
|
11832
|
+
};
|
|
11833
|
+
})(),
|
|
11834
|
+
{ readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
11835
|
+
async ({ searchTerm, maxResults, reason }, { panorama }) => {
|
|
11836
|
+
try {
|
|
11837
|
+
logger.log(
|
|
11838
|
+
`[SearchWixCLIDocumentation] searchTerm="${searchTerm}", reason="${reason}"`
|
|
11839
|
+
);
|
|
11840
|
+
const result = await runSemanticSearchAndFormat({
|
|
11841
|
+
toolName: "CLI",
|
|
11842
|
+
toolParams: {
|
|
11843
|
+
searchTerm
|
|
11844
|
+
},
|
|
11845
|
+
maxResults: Math.max(1, Math.min(maxResults ?? 5, 15)),
|
|
11846
|
+
linesInEachResult: 15
|
|
11847
|
+
});
|
|
11848
|
+
return {
|
|
11849
|
+
content: [
|
|
11850
|
+
{
|
|
11851
|
+
type: "text",
|
|
11852
|
+
text: result
|
|
11853
|
+
}
|
|
11854
|
+
]
|
|
11855
|
+
};
|
|
11856
|
+
} catch (error) {
|
|
11857
|
+
panorama.errorMonitor().reportError(error);
|
|
11858
|
+
captureException(error, {
|
|
11859
|
+
tags: {
|
|
11860
|
+
componentId: "SearchWixCLIDocumentation",
|
|
11861
|
+
toolName: "SearchWixCLIDocumentation"
|
|
11862
|
+
}
|
|
11863
|
+
});
|
|
11864
|
+
logger.error(
|
|
11865
|
+
`Error searching for ${searchTerm} in Wix CLI: ${error}`
|
|
11866
|
+
);
|
|
11867
|
+
return {
|
|
11868
|
+
isError: true,
|
|
11869
|
+
content: [{ type: "text", text: "Error: " + error.message }]
|
|
11870
|
+
};
|
|
11871
|
+
}
|
|
11872
|
+
}
|
|
11873
|
+
);
|
|
11874
|
+
}
|
|
11666
11875
|
if (!disableTools?.includes("ReadFullDocsArticle")) {
|
|
11667
11876
|
server2.tool(
|
|
11668
11877
|
"ReadFullDocsArticle",
|