@ezmodo/mcp-server 0.13.0

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.
Files changed (98) hide show
  1. package/README.md +305 -0
  2. package/config/development.js +20 -0
  3. package/config/endpoint-map.js +351 -0
  4. package/config/index.js +34 -0
  5. package/config/production.js +18 -0
  6. package/config/staging.js +18 -0
  7. package/handlers/access.js +141 -0
  8. package/handlers/activity.js +112 -0
  9. package/handlers/agents.js +95 -0
  10. package/handlers/ai-intelligence.js +55 -0
  11. package/handlers/attachments.js +30 -0
  12. package/handlers/catalogs.js +169 -0
  13. package/handlers/components.js +282 -0
  14. package/handlers/context-manifest.js +1150 -0
  15. package/handlers/decisions.js +114 -0
  16. package/handlers/designs.js +118 -0
  17. package/handlers/documents.js +227 -0
  18. package/handlers/entities.js +95 -0
  19. package/handlers/epics.js +190 -0
  20. package/handlers/facts.js +62 -0
  21. package/handlers/feature-flags.js +142 -0
  22. package/handlers/features.js +137 -0
  23. package/handlers/folders.js +127 -0
  24. package/handlers/git-context.js +917 -0
  25. package/handlers/github.js +72 -0
  26. package/handlers/graph.js +23 -0
  27. package/handlers/index.js +205 -0
  28. package/handlers/links.js +156 -0
  29. package/handlers/milestones.js +131 -0
  30. package/handlers/organizations.js +14 -0
  31. package/handlers/projects.js +122 -0
  32. package/handlers/recurring-tasks.js +33 -0
  33. package/handlers/tags.js +124 -0
  34. package/handlers/tasks.js +561 -0
  35. package/handlers/testing.js +116 -0
  36. package/handlers/todos.js +43 -0
  37. package/handlers/watchers.js +54 -0
  38. package/handlers/work-templates.js +32 -0
  39. package/index.js +175 -0
  40. package/lib/active-session.js +86 -0
  41. package/lib/auto-assign.js +93 -0
  42. package/lib/autolink.js +176 -0
  43. package/lib/changed-files.js +22 -0
  44. package/lib/env.js +45 -0
  45. package/lib/git-helpers.js +553 -0
  46. package/lib/git-utils.js +73 -0
  47. package/lib/http-client.js +164 -0
  48. package/lib/links-at-create.js +94 -0
  49. package/lib/local-cache.js +140 -0
  50. package/lib/logger.js +109 -0
  51. package/lib/manifest-loader.js +182 -0
  52. package/lib/manifest-query.js +686 -0
  53. package/lib/repo-config-dir.js +118 -0
  54. package/lib/version.js +10 -0
  55. package/lib/web-url.js +69 -0
  56. package/lib/worktree-tools.js +950 -0
  57. package/package.json +62 -0
  58. package/prompts/ai-workflow-automation.js +96 -0
  59. package/prompts/index.js +39 -0
  60. package/prompts/zephly-usage-guide-content.txt +631 -0
  61. package/prompts/zephly-usage-guide.js +119 -0
  62. package/tools/access-entity-types.js +28 -0
  63. package/tools/access.js +152 -0
  64. package/tools/activity.js +38 -0
  65. package/tools/agents.js +208 -0
  66. package/tools/ai-intelligence.js +111 -0
  67. package/tools/attachments.js +92 -0
  68. package/tools/catalogs.js +341 -0
  69. package/tools/components.js +249 -0
  70. package/tools/context-manifest.js +236 -0
  71. package/tools/decisions.js +168 -0
  72. package/tools/designs.js +222 -0
  73. package/tools/documents.js +287 -0
  74. package/tools/entities.js +223 -0
  75. package/tools/epics.js +267 -0
  76. package/tools/facts.js +70 -0
  77. package/tools/feature-flags.js +300 -0
  78. package/tools/features.js +246 -0
  79. package/tools/folders.js +122 -0
  80. package/tools/git-context.js +109 -0
  81. package/tools/github.js +172 -0
  82. package/tools/graph.js +70 -0
  83. package/tools/index.js +77 -0
  84. package/tools/link-params.js +93 -0
  85. package/tools/linkable-types.js +36 -0
  86. package/tools/links.js +199 -0
  87. package/tools/milestones.js +176 -0
  88. package/tools/organizations.js +23 -0
  89. package/tools/projects.js +172 -0
  90. package/tools/recurring-tasks.js +115 -0
  91. package/tools/tags.js +219 -0
  92. package/tools/task-item-schema.js +57 -0
  93. package/tools/task-type.js +33 -0
  94. package/tools/tasks.js +680 -0
  95. package/tools/testing.js +344 -0
  96. package/tools/todos.js +69 -0
  97. package/tools/watchers.js +81 -0
  98. package/tools/work-templates.js +96 -0
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Design Tools
3
+ * MCP tools for Designs (the in-product living design system).
4
+ *
5
+ * A Design is an AI-authored HTML/CSS artifact that captures the product's house
6
+ * style. kind ∈ theme|component|page. Designs are org-level (projectId nullable)
7
+ * and LINK to features and other artifacts via the generic link graph — they do
8
+ * not contain them.
9
+ *
10
+ * An agent should read the design system (get_design_system) to learn the
11
+ * established house style before authoring or designing any new UI, so new
12
+ * designs match the existing theme + components.
13
+ */
14
+
15
+ import { LINKABLE_TYPES } from './linkable-types.js';
16
+ import { LINKS_ARRAY_SCHEMA } from './link-params.js';
17
+
18
+ export const DESIGN_TOOLS = [
19
+ {
20
+ name: 'manage_design',
21
+ description: 'Create, update, or delete a Design (an AI-authored HTML/CSS artifact in the living ' +
22
+ 'design system: kind theme|component|page, name, html, css, status), or link/unlink it to ' +
23
+ 'existing artifacts. Designs are org-level and LINK to features/epics/tasks/milestones/etc., ' +
24
+ 'they do not contain them. Before authoring a new design, call get_design_system first to ' +
25
+ 'learn the established house style.',
26
+ inputSchema: {
27
+ type: 'object',
28
+ properties: {
29
+ action: {
30
+ type: 'string',
31
+ enum: ['create', 'update', 'delete', 'link', 'unlink'],
32
+ description: 'Action to perform. "link"/"unlink" attach/detach the design to an artifact ' +
33
+ '(pass designId + targetType + targetId).',
34
+ },
35
+ // --- Identifiers ---
36
+ organizationId: {
37
+ type: 'string',
38
+ description: 'Organization ID (required for create)',
39
+ },
40
+ designId: {
41
+ type: 'string',
42
+ description: 'Design ID (required for update, delete, link, unlink)',
43
+ },
44
+ // --- Create / update fields ---
45
+ kind: {
46
+ type: 'string',
47
+ enum: ['theme', 'component', 'page'],
48
+ description: 'Design kind: "theme" (the house style/tokens), "component" (a reusable UI ' +
49
+ 'piece), or "page" (a full page layout). Required for create (create, update).',
50
+ },
51
+ name: {
52
+ type: 'string',
53
+ description: 'Design name (required for create), e.g. "Primary Button" or "Dashboard Theme" ' +
54
+ '(create, update)',
55
+ },
56
+ slug: {
57
+ type: 'string',
58
+ description: 'URL-friendly slug for the design (create, update)',
59
+ },
60
+ html: {
61
+ type: 'string',
62
+ description: 'The HTML markup of the design, typically Tailwind-classed (create, update)',
63
+ },
64
+ css: {
65
+ type: 'string',
66
+ description: 'The CSS for the design (create, update)',
67
+ },
68
+ description: {
69
+ type: 'string',
70
+ description: 'Description of the design / how it is used, supports markdown (create, update)',
71
+ },
72
+ parentDesignId: {
73
+ type: 'string',
74
+ description: 'Parent design ID for nesting (e.g. a component within a theme) (create, update)',
75
+ },
76
+ status: {
77
+ type: 'string',
78
+ enum: ['draft', 'active', 'deprecated'],
79
+ description: 'Design lifecycle status (default: "draft") (create, update)',
80
+ },
81
+ projectId: {
82
+ type: 'string',
83
+ description: 'Scope the design to a project. Omit/empty = cross-project / org-wide ' +
84
+ '(create, update)',
85
+ },
86
+ // --- link / unlink fields ---
87
+ targetType: {
88
+ type: 'string',
89
+ enum: LINKABLE_TYPES,
90
+ description: 'Type of artifact to link/unlink (required for link, unlink)',
91
+ },
92
+ targetId: {
93
+ type: 'string',
94
+ description: 'ID of the artifact to link/unlink (required for link, unlink)',
95
+ },
96
+ // --- create-time link fields ---
97
+ linkToType: {
98
+ type: 'string',
99
+ enum: LINKABLE_TYPES,
100
+ description: 'Optionally link the new design to this artifact type on creation (create)',
101
+ },
102
+ linkToId: {
103
+ type: 'string',
104
+ description: 'ID of the artifact to link the new design to on creation ' +
105
+ '(create; requires linkToType)',
106
+ },
107
+ links: LINKS_ARRAY_SCHEMA,
108
+ },
109
+ required: ['action'],
110
+ },
111
+ },
112
+ {
113
+ name: 'get_design',
114
+ description: 'Retrieve a single Design, or list the designs linked to a given entity (e.g. all ' +
115
+ 'designs on a feature). Provide designId for a single lookup; provide linkedType + linkedId to ' +
116
+ 'list designs linked to that entity.',
117
+ inputSchema: {
118
+ type: 'object',
119
+ properties: {
120
+ designId: {
121
+ type: 'string',
122
+ description: 'Design ID for a single lookup',
123
+ },
124
+ organizationId: {
125
+ type: 'string',
126
+ description: 'Organization ID (optional; scopes a linkedType + linkedId lookup)',
127
+ },
128
+ linkedType: {
129
+ type: 'string',
130
+ enum: LINKABLE_TYPES,
131
+ description: 'List designs linked to this entity type (requires linkedId), ' +
132
+ 'e.g. all designs on a feature',
133
+ },
134
+ linkedId: {
135
+ type: 'string',
136
+ description: 'ID of the entity to list linked designs for (requires linkedType)',
137
+ },
138
+ includeLinks: {
139
+ type: 'boolean',
140
+ description: 'If true (single lookup), also return the design\'s linked artifacts',
141
+ },
142
+ // --- List filters (linkedType mode) ---
143
+ projectId: {
144
+ type: 'string',
145
+ description: 'Filter to a single project\'s designs',
146
+ },
147
+ kind: {
148
+ type: 'string',
149
+ enum: ['theme', 'component', 'page'],
150
+ description: 'Filter by design kind',
151
+ },
152
+ status: {
153
+ type: 'string',
154
+ enum: ['draft', 'active', 'deprecated'],
155
+ description: 'Filter by status',
156
+ },
157
+ limit: {
158
+ type: 'number',
159
+ description: 'Maximum number of results',
160
+ },
161
+ },
162
+ },
163
+ },
164
+ {
165
+ name: 'list_designs',
166
+ description: 'List an organization\'s Designs, optionally filtered by project, kind, or status. ' +
167
+ 'Returns the design artifacts (theme/component/page) in the living design system.',
168
+ inputSchema: {
169
+ type: 'object',
170
+ properties: {
171
+ organizationId: {
172
+ type: 'string',
173
+ description: 'Organization ID (required)',
174
+ },
175
+ projectId: {
176
+ type: 'string',
177
+ description: 'Filter to a single project\'s designs',
178
+ },
179
+ kind: {
180
+ type: 'string',
181
+ enum: ['theme', 'component', 'page'],
182
+ description: 'Filter by design kind',
183
+ },
184
+ status: {
185
+ type: 'string',
186
+ enum: ['draft', 'active', 'deprecated'],
187
+ description: 'Filter by status',
188
+ },
189
+ includeOrgWide: {
190
+ type: 'boolean',
191
+ description: 'When filtering by projectId, also include org-wide (project-less) designs',
192
+ },
193
+ limit: {
194
+ type: 'number',
195
+ description: 'Maximum number of results',
196
+ },
197
+ },
198
+ required: ['organizationId'],
199
+ },
200
+ },
201
+ {
202
+ name: 'get_design_system',
203
+ description: 'ALWAYS CALL THIS FIRST before authoring or designing any new UI, page, or component. ' +
204
+ 'Returns the established house style — the design system\'s theme plus its component designs ' +
205
+ '(Tailwind-classed HTML/CSS) — for the given org/project. Read it to learn the existing visual ' +
206
+ 'language so any new designs you create match the established style instead of inventing a new one.',
207
+ inputSchema: {
208
+ type: 'object',
209
+ properties: {
210
+ organizationId: {
211
+ type: 'string',
212
+ description: 'Organization ID (required)',
213
+ },
214
+ projectId: {
215
+ type: 'string',
216
+ description: 'Scope the design system to a project (optional; org-wide if omitted)',
217
+ },
218
+ },
219
+ required: ['organizationId'],
220
+ },
221
+ },
222
+ ];
@@ -0,0 +1,287 @@
1
+ /**
2
+ * Documentation Tools
3
+ * MCP tools for managing project documentation, versions, and templates
4
+ */
5
+
6
+ import { LINKS_ARRAY_SCHEMA, RELATED_ITEM_SCHEMA } from './link-params.js';
7
+
8
+ export const DOCUMENT_TOOLS = [
9
+ {
10
+ name: 'manage_document',
11
+ description: 'Create or update documents. ' +
12
+ 'Provide markdown `content` — it is converted to the unified document body (E-192) automatically. ' +
13
+ 'Markdown is the whole write contract: an update replaces the document body with what you send, ' +
14
+ 'so pass the full document, not a fragment. ' +
15
+ '(The legacy section model is gone — `sections` and the section ops were removed; sending them is an error.)',
16
+ inputSchema: {
17
+ type: 'object',
18
+ properties: {
19
+ action: {
20
+ type: 'string',
21
+ enum: ['create', 'update'],
22
+ description: 'Action to perform',
23
+ },
24
+ // --- Identifiers ---
25
+ projectId: {
26
+ type: 'string',
27
+ description: 'Project ID. Provide for a PROJECT-SCOPED document. ' +
28
+ 'Mutually exclusive with organizationId — supply exactly one when creating.',
29
+ },
30
+ organizationId: {
31
+ type: 'string',
32
+ description: 'Org scope — provide organizationId with NO projectId to create an ' +
33
+ 'ORG-SCOPED (project-less) document. Exactly one of projectId or organizationId. ' +
34
+ 'Org-scoped docs live in the org\'s document areas (Goals, Features, ADRs, How it ' +
35
+ 'works — see get_org_areas / list_org_documents); leaving folderId empty for an ' +
36
+ '"adr" or "how-it-works" type auto-files the doc into the matching reserved area. (E-195)',
37
+ },
38
+ documentId: {
39
+ type: 'string',
40
+ description: 'Document ID (required for update)',
41
+ },
42
+ // --- Create / Update fields ---
43
+ title: {
44
+ type: 'string',
45
+ description: 'Document title (required for create, optional for update)',
46
+ },
47
+ content: {
48
+ type: 'string',
49
+ description: 'Document content in markdown format. Converted to the unified document body automatically. (create, update)',
50
+ },
51
+ type: {
52
+ type: 'string',
53
+ enum: ['setup', 'api', 'architecture', 'troubleshooting', 'guide', 'diagram', 'description', 'adr', 'how-it-works', 'other'],
54
+ description: 'Document type/category. Use "diagram" to create a project-scoped diagram ' +
55
+ '(auto-placed in the Diagrams folder, seeded as mermaid; pass content="excalidraw" for excalidraw, ' +
56
+ 'content="sitemap" for a sitemap). Use "adr" for an Architecture ' +
57
+ 'Decision Record: an org-scoped "adr" document (pass organizationId, no projectId) with no folderId ' +
58
+ 'is auto-placed in the org\'s reserved "ADRs" area (E-195); seed structure from the "Architecture ' +
59
+ 'Decision Record" system template. Use "how-it-works" for a human-authored, ' +
60
+ 'cross-project overview: an org-scoped "how-it-works" doc with no folderId is auto-placed ' +
61
+ 'in the org\'s reserved "How it works" area (E-195), then relate it to the projects/epics/' +
62
+ 'features/components it describes via manage_link relates_to (distinct from the AI-generated ' +
63
+ 'how_it_works field on entities). The "description" type is ' +
64
+ 'system-managed (E-189): it marks a document that backs an entity\'s description and is ' +
65
+ 'normally created automatically when a description is promoted to a rich document — editing ' +
66
+ 'such a document re-syncs the linked entity\'s plain-text excerpt. (create, update)',
67
+ default: 'guide',
68
+ },
69
+ publicAccess: {
70
+ type: 'boolean',
71
+ description: 'Whether publicly accessible (default: true) (create, update)',
72
+ default: true,
73
+ },
74
+ folderId: {
75
+ type: 'string',
76
+ description: 'Folder ID to organize the document (create, update)',
77
+ },
78
+ isIndex: {
79
+ type: 'boolean',
80
+ description: 'Make this the index/landing page for its folder or project root. Only one index per location. (create, update)',
81
+ },
82
+ order: {
83
+ type: 'number',
84
+ description: 'Sort order within folder (lower = higher in list). Auto-assigned if omitted on create. (create, update)',
85
+ },
86
+ tags: {
87
+ type: 'array',
88
+ items: { type: 'string' },
89
+ description: 'Tags for categorizing and searching (create, update)',
90
+ },
91
+ relatedTaskIds: {
92
+ type: 'array',
93
+ items: { type: 'string' },
94
+ description: 'IDs of related tasks (create, update)',
95
+ },
96
+ summary: {
97
+ type: 'string',
98
+ description: 'AI-generated summary of the document content (create, update)',
99
+ },
100
+ keyPoints: {
101
+ type: 'array',
102
+ items: { type: 'string' },
103
+ description: 'AI-generated key points from the document (create, update)',
104
+ },
105
+ aiContext: {
106
+ type: 'object',
107
+ description: 'Alternative to top-level summary/keyPoints. Nested object with summary, keyPoints, relatedTasks, relatedDocs. (create, update)',
108
+ properties: {
109
+ summary: { type: 'string' },
110
+ keyPoints: { type: 'array', items: { type: 'string' } },
111
+ relatedTasks: { type: 'array', items: { type: 'string' } },
112
+ relatedDocs: { type: 'array', items: { type: 'string' } },
113
+ },
114
+ },
115
+ links: LINKS_ARRAY_SCHEMA,
116
+ addRelatedItem: {
117
+ ...RELATED_ITEM_SCHEMA,
118
+ description: 'DEPRECATED — use manage_link (or `links` on create). Add a ' +
119
+ 'cross-entity related item link (update only). Still works.',
120
+ },
121
+ removeRelatedItem: {
122
+ ...RELATED_ITEM_SCHEMA,
123
+ description: 'DEPRECATED — use manage_link. Remove a cross-entity related ' +
124
+ 'item link (update only). Still works.',
125
+ },
126
+ },
127
+ required: ['action'],
128
+ },
129
+ },
130
+ {
131
+ name: 'list_org_documents',
132
+ description: 'List an organization\'s ORG-SCOPED (project-less) documents (E-195). ' +
133
+ 'These are documents created with organizationId and no projectId — e.g. cross-project ' +
134
+ 'ADRs and "how it works" overviews living in the org\'s reserved document areas ' +
135
+ '(Goals, Features, ADRs, How it works; see get_org_areas). ' +
136
+ 'Optionally filter to a single area/folder via folderId.',
137
+ inputSchema: {
138
+ type: 'object',
139
+ properties: {
140
+ organizationId: {
141
+ type: 'string',
142
+ description: 'Organization ID (required)',
143
+ },
144
+ folderId: {
145
+ type: 'string',
146
+ description: 'Optional area/folder ID to scope the list to. Omit to list all of ' +
147
+ 'the org\'s project-less documents.',
148
+ },
149
+ limit: {
150
+ type: 'number',
151
+ description: 'Maximum number of documents to return (default 50, max 100)',
152
+ },
153
+ },
154
+ required: ['organizationId'],
155
+ },
156
+ },
157
+ {
158
+ name: 'manage_document_template',
159
+ description: 'Create or delete custom document templates. Templates provide pre-built ' +
160
+ 'document structures for common use cases.',
161
+ inputSchema: {
162
+ type: 'object',
163
+ properties: {
164
+ action: {
165
+ type: 'string',
166
+ enum: ['create', 'delete'],
167
+ description: 'Action to perform',
168
+ },
169
+ // --- Identifiers ---
170
+ templateId: {
171
+ type: 'string',
172
+ description: 'Template ID (required for delete)',
173
+ },
174
+ // --- Create fields ---
175
+ name: {
176
+ type: 'string',
177
+ description: 'Template name (required for create)',
178
+ },
179
+ description: {
180
+ type: 'string',
181
+ description: 'Brief description of what this template is for (create only)',
182
+ },
183
+ content: {
184
+ type: 'string',
185
+ description: 'Template content in markdown format. Use {{PLACEHOLDER}} for variable parts. (required for create)',
186
+ },
187
+ category: {
188
+ type: 'string',
189
+ enum: ['api', 'architecture', 'guide', 'troubleshooting', 'setup', 'other'],
190
+ description: 'Template category (create only)',
191
+ default: 'other',
192
+ },
193
+ tags: {
194
+ type: 'array',
195
+ items: { type: 'string' },
196
+ description: 'Tags for categorizing the template (create only)',
197
+ },
198
+ },
199
+ required: ['action'],
200
+ },
201
+ },
202
+ {
203
+ name: 'get_document',
204
+ description: 'Retrieve a single document, or list all docs for a project. ' +
205
+ 'Provide documentId (or projectId + slug) for single lookup. ' +
206
+ 'Provide just projectId to list all docs. ' +
207
+ 'Single-doc content is saved to <repo-config-dir>/docs/ (.ezmodo/docs/ or legacy .zephly/docs/) and returns a file path. ' +
208
+ 'Optionally include version history or fetch a specific version.',
209
+ inputSchema: {
210
+ type: 'object',
211
+ properties: {
212
+ documentId: {
213
+ type: 'string',
214
+ description: 'Document ID for single lookup',
215
+ },
216
+ projectId: {
217
+ type: 'string',
218
+ description: 'Project ID (required for list mode, or used with slug for single lookup)',
219
+ },
220
+ slug: {
221
+ type: 'string',
222
+ description: 'Document slug for single lookup (requires projectId)',
223
+ },
224
+ format: {
225
+ type: 'string',
226
+ enum: ['markdown', 'body'],
227
+ description: 'Output format. "markdown" (default) renders the document body as markdown. "body" returns the raw ProseMirror JSON body (for editor clients).',
228
+ default: 'markdown',
229
+ },
230
+ // --- List mode filters ---
231
+ docType: {
232
+ type: 'string',
233
+ enum: ['setup', 'api', 'architecture', 'troubleshooting', 'guide', 'diagram', 'process', 'context', 'other'],
234
+ description: 'Filter by document type (list mode only)',
235
+ },
236
+ tags: {
237
+ type: 'array',
238
+ items: { type: 'string' },
239
+ description: 'Filter by tags (list mode only)',
240
+ },
241
+ status: {
242
+ type: 'string',
243
+ enum: ['draft', 'in_review', 'published', 'archived'],
244
+ description: 'Filter by document status (list mode only)',
245
+ },
246
+ // --- Version fields ---
247
+ includeVersions: {
248
+ type: 'boolean',
249
+ description: 'If true, include version history for the document (single lookup only)',
250
+ },
251
+ versionNumber: {
252
+ type: 'number',
253
+ description: 'Specific version number to retrieve (single lookup only, e.g., 1, 2, 3)',
254
+ },
255
+ versionLimit: {
256
+ type: 'number',
257
+ description: 'Maximum number of versions to return (default: 20, max: 100)',
258
+ },
259
+ },
260
+ },
261
+ },
262
+ {
263
+ name: 'get_document_template',
264
+ description: 'Retrieve a single template by ID, or list all templates. ' +
265
+ 'Provide templateId for single lookup, or omit to list all.',
266
+ inputSchema: {
267
+ type: 'object',
268
+ properties: {
269
+ templateId: {
270
+ type: 'string',
271
+ description: 'Template ID for single lookup',
272
+ },
273
+ // --- List filters ---
274
+ category: {
275
+ type: 'string',
276
+ enum: ['api', 'architecture', 'guide', 'troubleshooting', 'setup', 'other'],
277
+ description: 'Filter templates by category (list mode only)',
278
+ },
279
+ type: {
280
+ type: 'string',
281
+ enum: ['system', 'custom'],
282
+ description: 'Filter by template type: system (built-in) or custom (user-created) (list mode only)',
283
+ },
284
+ },
285
+ },
286
+ },
287
+ ];