clitrigger 0.2.38 → 0.2.39

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 (121) hide show
  1. package/README.md +3 -0
  2. package/README_KR.md +3 -0
  3. package/dist/client/assets/{AnalyticsPanel-BPbFXNYf.js → AnalyticsPanel-Df0aWU0a.js} +1 -1
  4. package/dist/client/assets/{FloatingComposerController-5A3GJtK4-EXxtzhVS.js → FloatingComposerController-5A3GJtK4-B8T-_8pV.js} +1 -1
  5. package/dist/client/assets/{PlannerPageEditor-BUu3u9yc.js → PlannerPageEditor-CjUDjnQD.js} +57 -57
  6. package/dist/client/assets/TaskGraph-DfqS4zAU.js +2 -0
  7. package/dist/client/assets/{VaultLayout-Ycg6gPuo.js → VaultLayout-BIaAPLa9.js} +45 -50
  8. package/dist/client/assets/index-CuDDtdo3.js +686 -0
  9. package/dist/client/assets/index-DjpDYatq.css +32 -0
  10. package/dist/client/assets/{style-BGauwU60.js → style-BkiTZ2ql.js} +1 -1
  11. package/dist/client/assets/{with-selector-BSzErFZZ.js → with-selector-DxsS_tCL.js} +1 -1
  12. package/dist/client/index.html +2 -2
  13. package/dist/server/db/queries.d.ts +3 -16
  14. package/dist/server/db/queries.d.ts.map +1 -1
  15. package/dist/server/db/queries.js +4 -56
  16. package/dist/server/db/queries.js.map +1 -1
  17. package/dist/server/db/schema.d.ts.map +1 -1
  18. package/dist/server/db/schema.js +4 -82
  19. package/dist/server/db/schema.js.map +1 -1
  20. package/dist/server/index.d.ts.map +1 -1
  21. package/dist/server/index.js +14 -8
  22. package/dist/server/index.js.map +1 -1
  23. package/dist/server/lib/jira-client.d.ts.map +1 -1
  24. package/dist/server/lib/jira-client.js +3 -4
  25. package/dist/server/lib/jira-client.js.map +1 -1
  26. package/dist/server/mcp/index.d.ts +3 -0
  27. package/dist/server/mcp/index.d.ts.map +1 -0
  28. package/dist/server/mcp/index.js +121 -0
  29. package/dist/server/mcp/index.js.map +1 -0
  30. package/dist/server/mcp/index.test.d.ts +2 -0
  31. package/dist/server/mcp/index.test.d.ts.map +1 -0
  32. package/dist/server/mcp/index.test.js +68 -0
  33. package/dist/server/mcp/index.test.js.map +1 -0
  34. package/dist/server/middleware/auth.d.ts +3 -0
  35. package/dist/server/middleware/auth.d.ts.map +1 -1
  36. package/dist/server/middleware/auth.js +19 -0
  37. package/dist/server/middleware/auth.js.map +1 -1
  38. package/dist/server/plugins/registry.d.ts +0 -1
  39. package/dist/server/plugins/registry.d.ts.map +1 -1
  40. package/dist/server/plugins/registry.js +0 -3
  41. package/dist/server/plugins/registry.js.map +1 -1
  42. package/dist/server/plugins/types.d.ts +1 -10
  43. package/dist/server/plugins/types.d.ts.map +1 -1
  44. package/dist/server/routes/images.d.ts +4 -0
  45. package/dist/server/routes/images.d.ts.map +1 -1
  46. package/dist/server/routes/images.js +99 -1
  47. package/dist/server/routes/images.js.map +1 -1
  48. package/dist/server/routes/{jira.d.ts → mcp.d.ts} +1 -1
  49. package/dist/server/routes/mcp.d.ts.map +1 -0
  50. package/dist/server/routes/mcp.js +23 -0
  51. package/dist/server/routes/mcp.js.map +1 -0
  52. package/dist/server/routes/planner.d.ts.map +1 -1
  53. package/dist/server/routes/planner.js +15 -3
  54. package/dist/server/routes/planner.js.map +1 -1
  55. package/dist/server/routes/projects.js +3 -3
  56. package/dist/server/routes/projects.js.map +1 -1
  57. package/dist/server/services/orchestrator.d.ts.map +1 -1
  58. package/dist/server/services/orchestrator.js +0 -18
  59. package/dist/server/services/orchestrator.js.map +1 -1
  60. package/electron/main.cjs +21 -0
  61. package/electron/preload.cjs +8 -1
  62. package/package.json +5 -3
  63. package/dist/client/assets/TaskGraph-DxebSt6u.js +0 -2
  64. package/dist/client/assets/index-6AAO37M8.css +0 -32
  65. package/dist/client/assets/index-Bs4Fr1qI.js +0 -686
  66. package/dist/server/plugins/github/index.d.ts +0 -3
  67. package/dist/server/plugins/github/index.d.ts.map +0 -1
  68. package/dist/server/plugins/github/index.js +0 -18
  69. package/dist/server/plugins/github/index.js.map +0 -1
  70. package/dist/server/plugins/github/router.d.ts +0 -4
  71. package/dist/server/plugins/github/router.d.ts.map +0 -1
  72. package/dist/server/plugins/github/router.js +0 -250
  73. package/dist/server/plugins/github/router.js.map +0 -1
  74. package/dist/server/plugins/gstack/index.d.ts +0 -3
  75. package/dist/server/plugins/gstack/index.d.ts.map +0 -1
  76. package/dist/server/plugins/gstack/index.js +0 -36
  77. package/dist/server/plugins/gstack/index.js.map +0 -1
  78. package/dist/server/plugins/jira/index.d.ts +0 -3
  79. package/dist/server/plugins/jira/index.d.ts.map +0 -1
  80. package/dist/server/plugins/jira/index.js +0 -19
  81. package/dist/server/plugins/jira/index.js.map +0 -1
  82. package/dist/server/plugins/jira/router.d.ts +0 -4
  83. package/dist/server/plugins/jira/router.d.ts.map +0 -1
  84. package/dist/server/plugins/jira/router.js +0 -326
  85. package/dist/server/plugins/jira/router.js.map +0 -1
  86. package/dist/server/plugins/notion/index.d.ts +0 -3
  87. package/dist/server/plugins/notion/index.d.ts.map +0 -1
  88. package/dist/server/plugins/notion/index.js +0 -17
  89. package/dist/server/plugins/notion/index.js.map +0 -1
  90. package/dist/server/plugins/notion/router.d.ts +0 -4
  91. package/dist/server/plugins/notion/router.d.ts.map +0 -1
  92. package/dist/server/plugins/notion/router.js +0 -313
  93. package/dist/server/plugins/notion/router.js.map +0 -1
  94. package/dist/server/resources/gstack-skills/LICENSE +0 -21
  95. package/dist/server/resources/gstack-skills/benchmark/SKILL.md +0 -528
  96. package/dist/server/resources/gstack-skills/careful/SKILL.md +0 -59
  97. package/dist/server/resources/gstack-skills/cso/SKILL.md +0 -898
  98. package/dist/server/resources/gstack-skills/investigate/SKILL.md +0 -474
  99. package/dist/server/resources/gstack-skills/qa/SKILL.md +0 -1055
  100. package/dist/server/resources/gstack-skills/qa-only/SKILL.md +0 -672
  101. package/dist/server/resources/gstack-skills/review/SKILL.md +0 -1044
  102. package/dist/server/resources/gstack-skills/skills-manifest.d.ts +0 -9
  103. package/dist/server/resources/gstack-skills/skills-manifest.d.ts.map +0 -1
  104. package/dist/server/resources/gstack-skills/skills-manifest.js +0 -52
  105. package/dist/server/resources/gstack-skills/skills-manifest.js.map +0 -1
  106. package/dist/server/resources/gstack-skills/skills-manifest.ts +0 -59
  107. package/dist/server/routes/github.d.ts +0 -3
  108. package/dist/server/routes/github.d.ts.map +0 -1
  109. package/dist/server/routes/github.js +0 -251
  110. package/dist/server/routes/github.js.map +0 -1
  111. package/dist/server/routes/jira.d.ts.map +0 -1
  112. package/dist/server/routes/jira.js +0 -333
  113. package/dist/server/routes/jira.js.map +0 -1
  114. package/dist/server/routes/notion.d.ts +0 -3
  115. package/dist/server/routes/notion.d.ts.map +0 -1
  116. package/dist/server/routes/notion.js +0 -312
  117. package/dist/server/routes/notion.js.map +0 -1
  118. package/dist/server/services/skill-injector.d.ts +0 -17
  119. package/dist/server/services/skill-injector.d.ts.map +0 -1
  120. package/dist/server/services/skill-injector.js +0 -60
  121. package/dist/server/services/skill-injector.js.map +0 -1
@@ -1,333 +0,0 @@
1
- import { Router } from 'express';
2
- import { getProjectById } from '../db/queries.js';
3
- import { validatePromptContent, MAX_DESCRIPTION_LENGTH } from '../services/prompt-guard.js';
4
- const router = Router();
5
- function getJiraConfig(projectId) {
6
- const project = getProjectById(projectId);
7
- if (!project || !project.jira_enabled || !project.jira_base_url || !project.jira_email || !project.jira_api_token) {
8
- return null;
9
- }
10
- return {
11
- baseUrl: project.jira_base_url.replace(/\/+$/, ''),
12
- email: project.jira_email,
13
- apiToken: project.jira_api_token,
14
- projectKey: project.jira_project_key || '',
15
- };
16
- }
17
- function jiraHeaders(config) {
18
- const auth = Buffer.from(`${config.email}:${config.apiToken}`).toString('base64');
19
- return {
20
- 'Authorization': `Basic ${auth}`,
21
- 'Accept': 'application/json',
22
- 'Content-Type': 'application/json',
23
- };
24
- }
25
- async function jiraFetch(config, path, options = {}) {
26
- const url = `${config.baseUrl}${path}`;
27
- return fetch(url, {
28
- ...options,
29
- headers: {
30
- ...jiraHeaders(config),
31
- ...(options.headers || {}),
32
- },
33
- });
34
- }
35
- // Test connection
36
- router.get('/:projectId/test', async (req, res) => {
37
- const config = getJiraConfig(req.params.projectId);
38
- if (!config) {
39
- res.status(400).json({ error: 'Jira not configured for this project' });
40
- return;
41
- }
42
- try {
43
- const resp = await jiraFetch(config, '/rest/api/3/myself');
44
- if (!resp.ok) {
45
- const text = await resp.text();
46
- res.status(resp.status).json({ error: text });
47
- return;
48
- }
49
- const data = await resp.json();
50
- res.json({ ok: true, user: data.displayName, email: data.emailAddress });
51
- }
52
- catch (err) {
53
- res.status(500).json({ error: err.message });
54
- }
55
- });
56
- // List issues (with JQL search)
57
- router.get('/:projectId/issues', async (req, res) => {
58
- const config = getJiraConfig(req.params.projectId);
59
- if (!config) {
60
- res.status(400).json({ error: 'Jira not configured for this project' });
61
- return;
62
- }
63
- try {
64
- const status = req.query.status;
65
- const search = req.query.search;
66
- const maxResults = parseInt(req.query.maxResults || '50', 10);
67
- const startAt = parseInt(req.query.startAt || '0', 10);
68
- let jql = config.projectKey ? `project = "${config.projectKey}"` : '';
69
- if (status && status !== 'all') {
70
- const statusClause = `status = "${status}"`;
71
- jql = jql ? `${jql} AND ${statusClause}` : statusClause;
72
- }
73
- if (search) {
74
- const searchClause = `summary ~ "${search.replace(/"/g, '\\"')}"`;
75
- jql = jql ? `${jql} AND ${searchClause}` : searchClause;
76
- }
77
- if (jql) {
78
- jql += ' ORDER BY updated DESC';
79
- }
80
- else {
81
- jql = 'ORDER BY updated DESC';
82
- }
83
- const params = new URLSearchParams({
84
- jql,
85
- maxResults: String(maxResults),
86
- startAt: String(startAt),
87
- fields: 'summary,status,assignee,priority,issuetype,created,updated,labels',
88
- });
89
- const resp = await jiraFetch(config, `/rest/api/3/search?${params}`);
90
- if (!resp.ok) {
91
- const text = await resp.text();
92
- res.status(resp.status).json({ error: text });
93
- return;
94
- }
95
- const data = await resp.json();
96
- res.json(data);
97
- }
98
- catch (err) {
99
- res.status(500).json({ error: err.message });
100
- }
101
- });
102
- // Get single issue
103
- router.get('/:projectId/issue/:issueKey', async (req, res) => {
104
- const config = getJiraConfig(req.params.projectId);
105
- if (!config) {
106
- res.status(400).json({ error: 'Jira not configured for this project' });
107
- return;
108
- }
109
- try {
110
- const resp = await jiraFetch(config, `/rest/api/3/issue/${encodeURIComponent(req.params.issueKey)}`);
111
- if (!resp.ok) {
112
- const text = await resp.text();
113
- res.status(resp.status).json({ error: text });
114
- return;
115
- }
116
- const data = await resp.json();
117
- res.json(data);
118
- }
119
- catch (err) {
120
- res.status(500).json({ error: err.message });
121
- }
122
- });
123
- // Get transitions for an issue
124
- router.get('/:projectId/issue/:issueKey/transitions', async (req, res) => {
125
- const config = getJiraConfig(req.params.projectId);
126
- if (!config) {
127
- res.status(400).json({ error: 'Jira not configured for this project' });
128
- return;
129
- }
130
- try {
131
- const resp = await jiraFetch(config, `/rest/api/3/issue/${encodeURIComponent(req.params.issueKey)}/transitions`);
132
- if (!resp.ok) {
133
- const text = await resp.text();
134
- res.status(resp.status).json({ error: text });
135
- return;
136
- }
137
- const data = await resp.json();
138
- res.json(data);
139
- }
140
- catch (err) {
141
- res.status(500).json({ error: err.message });
142
- }
143
- });
144
- // Transition issue (change status)
145
- router.post('/:projectId/issue/:issueKey/transition', async (req, res) => {
146
- const config = getJiraConfig(req.params.projectId);
147
- if (!config) {
148
- res.status(400).json({ error: 'Jira not configured for this project' });
149
- return;
150
- }
151
- try {
152
- const { transitionId } = req.body;
153
- if (!transitionId) {
154
- res.status(400).json({ error: 'transitionId is required' });
155
- return;
156
- }
157
- const resp = await jiraFetch(config, `/rest/api/3/issue/${encodeURIComponent(req.params.issueKey)}/transitions`, {
158
- method: 'POST',
159
- body: JSON.stringify({ transition: { id: transitionId } }),
160
- });
161
- if (!resp.ok) {
162
- const text = await resp.text();
163
- res.status(resp.status).json({ error: text });
164
- return;
165
- }
166
- res.json({ ok: true });
167
- }
168
- catch (err) {
169
- res.status(500).json({ error: err.message });
170
- }
171
- });
172
- // Add comment to issue
173
- router.post('/:projectId/issue/:issueKey/comment', async (req, res) => {
174
- const config = getJiraConfig(req.params.projectId);
175
- if (!config) {
176
- res.status(400).json({ error: 'Jira not configured for this project' });
177
- return;
178
- }
179
- try {
180
- const { body: commentBody } = req.body;
181
- if (!commentBody) {
182
- res.status(400).json({ error: 'body is required' });
183
- return;
184
- }
185
- const resp = await jiraFetch(config, `/rest/api/3/issue/${encodeURIComponent(req.params.issueKey)}/comment`, {
186
- method: 'POST',
187
- body: JSON.stringify({
188
- body: {
189
- type: 'doc',
190
- version: 1,
191
- content: [{ type: 'paragraph', content: [{ type: 'text', text: commentBody }] }],
192
- },
193
- }),
194
- });
195
- if (!resp.ok) {
196
- const text = await resp.text();
197
- res.status(resp.status).json({ error: text });
198
- return;
199
- }
200
- const data = await resp.json();
201
- res.json(data);
202
- }
203
- catch (err) {
204
- res.status(500).json({ error: err.message });
205
- }
206
- });
207
- // Create issue
208
- router.post('/:projectId/issues', async (req, res) => {
209
- const config = getJiraConfig(req.params.projectId);
210
- if (!config) {
211
- res.status(400).json({ error: 'Jira not configured for this project' });
212
- return;
213
- }
214
- try {
215
- const { summary, description, issueType } = req.body;
216
- if (!summary) {
217
- res.status(400).json({ error: 'summary is required' });
218
- return;
219
- }
220
- const fields = {
221
- project: { key: config.projectKey },
222
- summary,
223
- issuetype: { name: issueType || 'Task' },
224
- };
225
- if (description) {
226
- fields.description = {
227
- type: 'doc',
228
- version: 1,
229
- content: [{ type: 'paragraph', content: [{ type: 'text', text: description }] }],
230
- };
231
- }
232
- const resp = await jiraFetch(config, '/rest/api/3/issue', {
233
- method: 'POST',
234
- body: JSON.stringify({ fields }),
235
- });
236
- if (!resp.ok) {
237
- const text = await resp.text();
238
- res.status(resp.status).json({ error: text });
239
- return;
240
- }
241
- const data = await resp.json();
242
- res.json(data);
243
- }
244
- catch (err) {
245
- res.status(500).json({ error: err.message });
246
- }
247
- });
248
- // Import issue as task
249
- router.post('/:projectId/import/:issueKey', async (req, res) => {
250
- const config = getJiraConfig(req.params.projectId);
251
- if (!config) {
252
- res.status(400).json({ error: 'Jira not configured for this project' });
253
- return;
254
- }
255
- try {
256
- const resp = await jiraFetch(config, `/rest/api/3/issue/${encodeURIComponent(req.params.issueKey)}`);
257
- if (!resp.ok) {
258
- const text = await resp.text();
259
- res.status(resp.status).json({ error: text });
260
- return;
261
- }
262
- const issue = await resp.json();
263
- const summary = issue.fields?.summary || req.params.issueKey;
264
- let description = '';
265
- // Extract plain text from ADF description
266
- if (issue.fields?.description?.content) {
267
- description = extractAdfText(issue.fields.description.content);
268
- }
269
- const title = `[${req.params.issueKey}] ${summary}`;
270
- const validation = validatePromptContent(description, MAX_DESCRIPTION_LENGTH);
271
- if (!validation.valid) {
272
- console.warn(`[prompt-guard] Jira import ${req.params.issueKey}: ${validation.warnings.join('; ')}`);
273
- }
274
- res.json({ title, description: validation.sanitized, issueKey: req.params.issueKey, warnings: validation.warnings });
275
- }
276
- catch (err) {
277
- res.status(500).json({ error: err.message });
278
- }
279
- });
280
- // Get project statuses (for filter dropdown)
281
- router.get('/:projectId/statuses', async (req, res) => {
282
- const config = getJiraConfig(req.params.projectId);
283
- if (!config) {
284
- res.status(400).json({ error: 'Jira not configured for this project' });
285
- return;
286
- }
287
- try {
288
- if (!config.projectKey) {
289
- res.json([]);
290
- return;
291
- }
292
- const resp = await jiraFetch(config, `/rest/api/3/project/${encodeURIComponent(config.projectKey)}/statuses`);
293
- if (!resp.ok) {
294
- const text = await resp.text();
295
- res.status(resp.status).json({ error: text });
296
- return;
297
- }
298
- const data = await resp.json();
299
- // Extract unique status names
300
- const statuses = new Set();
301
- for (const issueType of data) {
302
- for (const s of issueType.statuses || []) {
303
- statuses.add(s.name);
304
- }
305
- }
306
- res.json([...statuses]);
307
- }
308
- catch (err) {
309
- res.status(500).json({ error: err.message });
310
- }
311
- });
312
- function extractAdfText(content) {
313
- let text = '';
314
- for (const node of content) {
315
- if (node.type === 'text') {
316
- text += node.text;
317
- }
318
- else if (node.type === 'paragraph' || node.type === 'heading') {
319
- text += extractAdfText(node.content || []) + '\n';
320
- }
321
- else if (node.type === 'bulletList' || node.type === 'orderedList') {
322
- for (const item of node.content || []) {
323
- text += '- ' + extractAdfText(item.content || []);
324
- }
325
- }
326
- else if (node.content) {
327
- text += extractAdfText(node.content);
328
- }
329
- }
330
- return text;
331
- }
332
- export default router;
333
- //# sourceMappingURL=jira.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jira.js","sourceRoot":"","sources":["../../../src/server/routes/jira.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA+B,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAE5F,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAYxB,SAAS,aAAa,CAAC,SAAiB;IACtC,MAAM,OAAO,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAC1C,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAClH,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QAClD,KAAK,EAAE,OAAO,CAAC,UAAU;QACzB,QAAQ,EAAE,OAAO,CAAC,cAAc;QAChC,UAAU,EAAE,OAAO,CAAC,gBAAgB,IAAI,EAAE;KAC3C,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,MAAkB;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAClF,OAAO;QACL,eAAe,EAAE,SAAS,IAAI,EAAE;QAChC,QAAQ,EAAE,kBAAkB;QAC5B,cAAc,EAAE,kBAAkB;KACnC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,MAAkB,EAAE,IAAY,EAAE,UAAuB,EAAE;IAClF,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;IACvC,OAAO,KAAK,CAAC,GAAG,EAAE;QAChB,GAAG,OAAO;QACV,OAAO,EAAE;YACP,GAAG,WAAW,CAAC,MAAM,CAAC;YACtB,GAAG,CAAC,OAAO,CAAC,OAAiC,IAAI,EAAE,CAAC;SACrD;KACF,CAAC,CAAC;AACL,CAAC;AAED,kBAAkB;AAClB,MAAM,CAAC,GAAG,CAAC,kBAAkB,EAAE,KAAK,EAAE,GAAW,EAAE,GAAa,EAAE,EAAE;IAClE,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;IAC3E,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,gCAAgC;AAChC,MAAM,CAAC,GAAG,CAAC,oBAAoB,EAAE,KAAK,EAAE,GAAW,EAAE,GAAa,EAAE,EAAE;IACpE,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,MAA4B,CAAC;QACtD,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,MAA4B,CAAC;QACtD,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,UAAoB,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;QACxE,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,OAAiB,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;QAEjE,IAAI,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,cAAc,MAAM,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAEtE,IAAI,MAAM,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YAC/B,MAAM,YAAY,GAAG,aAAa,MAAM,GAAG,CAAC;YAC5C,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,QAAQ,YAAY,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;QAC1D,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,YAAY,GAAG,cAAc,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;YAClE,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,QAAQ,YAAY,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;QAC1D,CAAC;QAED,IAAI,GAAG,EAAE,CAAC;YACR,GAAG,IAAI,wBAAwB,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,GAAG,GAAG,uBAAuB,CAAC;QAChC,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;YACjC,GAAG;YACH,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;YAC9B,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC;YACxB,MAAM,EAAE,mEAAmE;SAC5E,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,sBAAsB,MAAM,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,mBAAmB;AACnB,MAAM,CAAC,GAAG,CAAC,6BAA6B,EAAE,KAAK,EAAE,GAAgB,EAAE,GAAa,EAAE,EAAE;IAClF,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,qBAAqB,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACrG,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,+BAA+B;AAC/B,MAAM,CAAC,GAAG,CAAC,yCAAyC,EAAE,KAAK,EAAE,GAAgB,EAAE,GAAa,EAAE,EAAE;IAC9F,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,qBAAqB,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QACjH,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,mCAAmC;AACnC,MAAM,CAAC,IAAI,CAAC,wCAAwC,EAAE,KAAK,EAAE,GAAgB,EAAE,GAAa,EAAE,EAAE;IAC9F,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,YAAY,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,qBAAqB,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE;YAC/G,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,CAAC;SAC3D,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,uBAAuB;AACvB,MAAM,CAAC,IAAI,CAAC,qCAAqC,EAAE,KAAK,EAAE,GAAgB,EAAE,GAAa,EAAE,EAAE;IAC3F,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;QACvC,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;YACpD,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,qBAAqB,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE;YAC3G,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,IAAI,EAAE;oBACJ,IAAI,EAAE,KAAK;oBACX,OAAO,EAAE,CAAC;oBACV,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;iBACjF;aACF,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,eAAe;AACf,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,KAAK,EAAE,GAAW,EAAE,GAAa,EAAE,EAAE;IACrE,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;QACrD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAA4B;YACtC,OAAO,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE;YACnC,OAAO;YACP,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,IAAI,MAAM,EAAE;SACzC,CAAC;QAEF,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,CAAC,WAAW,GAAG;gBACnB,IAAI,EAAE,KAAK;gBACX,OAAO,EAAE,CAAC;gBACV,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;aACjF,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,mBAAmB,EAAE;YACxD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;SACjC,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,uBAAuB;AACvB,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,KAAK,EAAE,GAAgB,EAAE,GAAa,EAAE,EAAE;IACpF,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,qBAAqB,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACrG,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAEhC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC7D,IAAI,WAAW,GAAG,EAAE,CAAC;QACrB,0CAA0C;QAC1C,IAAI,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;YACvC,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACpD,MAAM,UAAU,GAAG,qBAAqB,CAAC,WAAW,EAAE,sBAAsB,CAAC,CAAC;QAC9E,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,8BAA8B,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvG,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvH,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,6CAA6C;AAC7C,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,KAAK,EAAE,GAAW,EAAE,GAAa,EAAE,EAAE;IACtE,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YACvB,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACb,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,uBAAuB,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAC9G,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,8BAA8B;QAC9B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;QACnC,KAAK,MAAM,SAAS,IAAI,IAAI,EAAE,CAAC;YAC7B,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;gBACzC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,SAAS,cAAc,CAAC,OAAc;IACpC,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC;QACpB,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAChE,IAAI,IAAI,cAAc,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACpD,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACrE,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;gBACtC,IAAI,IAAI,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;aAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACxB,IAAI,IAAI,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,eAAe,MAAM,CAAC"}
@@ -1,3 +0,0 @@
1
- declare const router: import("express-serve-static-core").Router;
2
- export default router;
3
- //# sourceMappingURL=notion.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"notion.d.ts","sourceRoot":"","sources":["../../../src/server/routes/notion.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAgVxB,eAAe,MAAM,CAAC"}
@@ -1,312 +0,0 @@
1
- import { Router } from 'express';
2
- import { getProjectById } from '../db/queries.js';
3
- import { validatePromptContent, MAX_DESCRIPTION_LENGTH } from '../services/prompt-guard.js';
4
- const router = Router();
5
- function getNotionConfig(projectId) {
6
- const project = getProjectById(projectId);
7
- if (!project || !project.notion_enabled || !project.notion_api_key || !project.notion_database_id) {
8
- return null;
9
- }
10
- return {
11
- apiKey: project.notion_api_key,
12
- databaseId: project.notion_database_id,
13
- };
14
- }
15
- function notionHeaders(config) {
16
- return {
17
- 'Authorization': `Bearer ${config.apiKey}`,
18
- 'Notion-Version': '2022-06-28',
19
- 'Content-Type': 'application/json',
20
- };
21
- }
22
- async function notionFetch(config, path, options = {}) {
23
- const url = `https://api.notion.com/v1${path}`;
24
- return fetch(url, {
25
- ...options,
26
- headers: {
27
- ...notionHeaders(config),
28
- ...(options.headers || {}),
29
- },
30
- });
31
- }
32
- // Test connection
33
- router.get('/:projectId/test', async (req, res) => {
34
- const config = getNotionConfig(req.params.projectId);
35
- if (!config) {
36
- res.status(400).json({ error: 'Notion not configured for this project' });
37
- return;
38
- }
39
- try {
40
- const resp = await notionFetch(config, '/users/me');
41
- if (!resp.ok) {
42
- const text = await resp.text();
43
- res.status(resp.status).json({ error: text });
44
- return;
45
- }
46
- const data = await resp.json();
47
- res.json({ ok: true, name: data.name || data.bot?.owner?.user?.name || 'Notion Bot', type: data.type });
48
- }
49
- catch (err) {
50
- res.status(500).json({ error: err.message });
51
- }
52
- });
53
- // Query database pages (list items)
54
- router.post('/:projectId/pages', async (req, res) => {
55
- const config = getNotionConfig(req.params.projectId);
56
- if (!config) {
57
- res.status(400).json({ error: 'Notion not configured for this project' });
58
- return;
59
- }
60
- try {
61
- const { startCursor, filter, search } = req.body || {};
62
- const body = {
63
- page_size: 20,
64
- };
65
- if (startCursor) {
66
- body.start_cursor = startCursor;
67
- }
68
- if (filter) {
69
- body.filter = filter;
70
- }
71
- else if (search) {
72
- body.filter = {
73
- property: 'title',
74
- title: { contains: search },
75
- };
76
- }
77
- body.sorts = [{ timestamp: 'last_edited_time', direction: 'descending' }];
78
- const resp = await notionFetch(config, `/databases/${config.databaseId}/query`, {
79
- method: 'POST',
80
- body: JSON.stringify(body),
81
- });
82
- if (!resp.ok) {
83
- const text = await resp.text();
84
- res.status(resp.status).json({ error: text });
85
- return;
86
- }
87
- const data = await resp.json();
88
- res.json(data);
89
- }
90
- catch (err) {
91
- res.status(500).json({ error: err.message });
92
- }
93
- });
94
- // Get single page
95
- router.get('/:projectId/page/:pageId', async (req, res) => {
96
- const config = getNotionConfig(req.params.projectId);
97
- if (!config) {
98
- res.status(400).json({ error: 'Notion not configured for this project' });
99
- return;
100
- }
101
- try {
102
- const resp = await notionFetch(config, `/pages/${req.params.pageId}`);
103
- if (!resp.ok) {
104
- const text = await resp.text();
105
- res.status(resp.status).json({ error: text });
106
- return;
107
- }
108
- const data = await resp.json();
109
- res.json(data);
110
- }
111
- catch (err) {
112
- res.status(500).json({ error: err.message });
113
- }
114
- });
115
- // Get page content (blocks)
116
- router.get('/:projectId/page/:pageId/blocks', async (req, res) => {
117
- const config = getNotionConfig(req.params.projectId);
118
- if (!config) {
119
- res.status(400).json({ error: 'Notion not configured for this project' });
120
- return;
121
- }
122
- try {
123
- const resp = await notionFetch(config, `/blocks/${req.params.pageId}/children?page_size=100`);
124
- if (!resp.ok) {
125
- const text = await resp.text();
126
- res.status(resp.status).json({ error: text });
127
- return;
128
- }
129
- const data = await resp.json();
130
- res.json(data);
131
- }
132
- catch (err) {
133
- res.status(500).json({ error: err.message });
134
- }
135
- });
136
- // Update page property (e.g. status)
137
- router.post('/:projectId/page/:pageId/update', async (req, res) => {
138
- const config = getNotionConfig(req.params.projectId);
139
- if (!config) {
140
- res.status(400).json({ error: 'Notion not configured for this project' });
141
- return;
142
- }
143
- try {
144
- const { properties } = req.body;
145
- if (!properties) {
146
- res.status(400).json({ error: 'properties is required' });
147
- return;
148
- }
149
- const resp = await notionFetch(config, `/pages/${req.params.pageId}`, {
150
- method: 'PATCH',
151
- body: JSON.stringify({ properties }),
152
- });
153
- if (!resp.ok) {
154
- const text = await resp.text();
155
- res.status(resp.status).json({ error: text });
156
- return;
157
- }
158
- const data = await resp.json();
159
- res.json(data);
160
- }
161
- catch (err) {
162
- res.status(500).json({ error: err.message });
163
- }
164
- });
165
- // Create page in database
166
- router.post('/:projectId/create', async (req, res) => {
167
- const config = getNotionConfig(req.params.projectId);
168
- if (!config) {
169
- res.status(400).json({ error: 'Notion not configured for this project' });
170
- return;
171
- }
172
- try {
173
- const { title, properties } = req.body;
174
- if (!title) {
175
- res.status(400).json({ error: 'title is required' });
176
- return;
177
- }
178
- const pageProperties = {
179
- ...properties,
180
- };
181
- if (!properties?.title) {
182
- pageProperties.title = {
183
- title: [{ text: { content: title } }],
184
- };
185
- }
186
- const resp = await notionFetch(config, '/pages', {
187
- method: 'POST',
188
- body: JSON.stringify({
189
- parent: { database_id: config.databaseId },
190
- properties: pageProperties,
191
- }),
192
- });
193
- if (!resp.ok) {
194
- const text = await resp.text();
195
- res.status(resp.status).json({ error: text });
196
- return;
197
- }
198
- const data = await resp.json();
199
- res.json(data);
200
- }
201
- catch (err) {
202
- res.status(500).json({ error: err.message });
203
- }
204
- });
205
- // Import page as task
206
- router.post('/:projectId/import/:pageId', async (req, res) => {
207
- const config = getNotionConfig(req.params.projectId);
208
- if (!config) {
209
- res.status(400).json({ error: 'Notion not configured for this project' });
210
- return;
211
- }
212
- try {
213
- const pageResp = await notionFetch(config, `/pages/${req.params.pageId}`);
214
- if (!pageResp.ok) {
215
- const text = await pageResp.text();
216
- res.status(pageResp.status).json({ error: text });
217
- return;
218
- }
219
- const page = await pageResp.json();
220
- const blocksResp = await notionFetch(config, `/blocks/${req.params.pageId}/children?page_size=100`);
221
- let description = '';
222
- if (blocksResp.ok) {
223
- const blocksData = await blocksResp.json();
224
- description = extractBlocksText(blocksData.results || []);
225
- }
226
- const title = extractPageTitle(page);
227
- const validation = validatePromptContent(description, MAX_DESCRIPTION_LENGTH);
228
- if (!validation.valid) {
229
- console.warn(`[prompt-guard] Notion import ${req.params.pageId}: ${validation.warnings.join('; ')}`);
230
- }
231
- res.json({ title, description: validation.sanitized, pageId: req.params.pageId, warnings: validation.warnings });
232
- }
233
- catch (err) {
234
- res.status(500).json({ error: err.message });
235
- }
236
- });
237
- // Get database schema (properties)
238
- router.get('/:projectId/schema', async (req, res) => {
239
- const config = getNotionConfig(req.params.projectId);
240
- if (!config) {
241
- res.status(400).json({ error: 'Notion not configured for this project' });
242
- return;
243
- }
244
- try {
245
- const resp = await notionFetch(config, `/databases/${config.databaseId}`);
246
- if (!resp.ok) {
247
- const text = await resp.text();
248
- res.status(resp.status).json({ error: text });
249
- return;
250
- }
251
- const data = await resp.json();
252
- res.json({
253
- title: extractRichText(data.title || []),
254
- properties: data.properties,
255
- });
256
- }
257
- catch (err) {
258
- res.status(500).json({ error: err.message });
259
- }
260
- });
261
- function extractPageTitle(page) {
262
- if (!page.properties)
263
- return 'Untitled';
264
- for (const prop of Object.values(page.properties)) {
265
- if (prop.type === 'title' && prop.title?.length > 0) {
266
- return extractRichText(prop.title);
267
- }
268
- }
269
- return 'Untitled';
270
- }
271
- function extractRichText(richText) {
272
- return richText.map((t) => t.plain_text || t.text?.content || '').join('');
273
- }
274
- function extractBlocksText(blocks) {
275
- const lines = [];
276
- for (const block of blocks) {
277
- const type = block.type;
278
- if (!type)
279
- continue;
280
- const content = block[type];
281
- if (!content)
282
- continue;
283
- if (content.rich_text) {
284
- const text = extractRichText(content.rich_text);
285
- if (type === 'heading_1' || type === 'heading_2' || type === 'heading_3') {
286
- lines.push(`# ${text}`);
287
- }
288
- else if (type === 'bulleted_list_item') {
289
- lines.push(`- ${text}`);
290
- }
291
- else if (type === 'numbered_list_item') {
292
- lines.push(`1. ${text}`);
293
- }
294
- else if (type === 'to_do') {
295
- const checked = content.checked ? 'x' : ' ';
296
- lines.push(`- [${checked}] ${text}`);
297
- }
298
- else if (type === 'code') {
299
- lines.push(`\`\`\`\n${text}\n\`\`\``);
300
- }
301
- else {
302
- lines.push(text);
303
- }
304
- }
305
- else if (type === 'divider') {
306
- lines.push('---');
307
- }
308
- }
309
- return lines.join('\n');
310
- }
311
- export default router;
312
- //# sourceMappingURL=notion.js.map