@nextclaw/ui 0.17.2 → 0.18.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 (59) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/assets/{api-CuPWhNDM.js → api-BJioGtWS.js} +1 -1
  3. package/dist/assets/{appearance-settings-page-DRjg6UP3.js → appearance-settings-page-DAF1fd14.js} +1 -1
  4. package/dist/assets/{book-open-B4ovWX14.js → book-open-aDv6R1av.js} +1 -1
  5. package/dist/assets/{channels-list-page-B26GXq63.js → channels-list-page-Dubt8r9S.js} +1 -1
  6. package/dist/assets/{chat-page-QA0dpNyU.js → chat-page-JbwjeUo4.js} +1 -1
  7. package/dist/assets/{config-split-page-Box_-aBK.js → config-split-page-Bs1wArsX.js} +1 -1
  8. package/dist/assets/{confirm-dialog-uqcCxomz.js → confirm-dialog-BFatCZUq.js} +1 -1
  9. package/dist/assets/{desktop-update-config-DkDor159.js → desktop-update-config-DFefhK96.js} +1 -1
  10. package/dist/assets/{dist-CZLIZntJ.js → dist-CV9wIyME.js} +1 -1
  11. package/dist/assets/{dist-Co2G-YjN.js → dist-D1I3blO_.js} +1 -1
  12. package/dist/assets/{doc-browser-CbCBDdap.js → doc-browser-BFfstBoh.js} +1 -1
  13. package/dist/assets/doc-browser-DEdoMb3X.js +1 -0
  14. package/dist/assets/{doc-browser-context-aeZu0FHR.js → doc-browser-context-BcwcVwX_.js} +1 -1
  15. package/dist/assets/{form-actions-C3Pa1HQb.js → form-actions-YSnn7q_U.js} +1 -1
  16. package/dist/assets/{index-CCWgeWoR.js → index-L58BO782.js} +18 -18
  17. package/dist/assets/loader-circle-CsNiT6VM.js +1 -0
  18. package/dist/assets/mcp-marketplace-page-DfUCF-L5.js +1 -0
  19. package/dist/assets/{mcp-marketplace-page-BmqbIQQQ.js → mcp-marketplace-page-ZTHpQTvi.js} +1 -1
  20. package/dist/assets/{model-config-page-BXUoZEEZ.js → model-config-page-jYCwpq4U.js} +1 -1
  21. package/dist/assets/{navigation-link-DngetDmN.js → navigation-link-7oSjAC9R.js} +1 -1
  22. package/dist/assets/plus-D6UN8XN5.js +1 -0
  23. package/dist/assets/{provider-scoped-model-input-C4a2TuV7.js → provider-scoped-model-input-C1CUHVJx.js} +1 -1
  24. package/dist/assets/{providers-config-page-CHSka1kQ.js → providers-config-page-CMvI4R1e.js} +1 -1
  25. package/dist/assets/{react-CPH0zySO.js → react-7zG0fz1I.js} +1 -1
  26. package/dist/assets/{refresh-cw-vTYZqC0b.js → refresh-cw-BUg7hI3u.js} +1 -1
  27. package/dist/assets/remote-BYPq49kD.js +1 -0
  28. package/dist/assets/rotate-cw-B3qmXtfJ.js +1 -0
  29. package/dist/assets/{runtime-config-page-V75_zqXa.js → runtime-config-page-DYuYv5yM.js} +1 -1
  30. package/dist/assets/{save-lWb6TI69.js → save-CTCYuZqu.js} +1 -1
  31. package/dist/assets/{search-BuUX_0KY.js → search-CfFUpaf7.js} +1 -1
  32. package/dist/assets/{search-config-page-rlkRJZCF.js → search-config-page-GUtGbk6i.js} +1 -1
  33. package/dist/assets/{secrets-config-page-BxCEc8r5.js → secrets-config-page-Delo8ab0.js} +1 -1
  34. package/dist/assets/security-config-DoVoel5I.js +1 -0
  35. package/dist/assets/{select-oalsltZV.js → select-MSvkWmPP.js} +1 -1
  36. package/dist/assets/{settings-2-Bd9xiNAY.js → settings-2-DXUfAWgg.js} +1 -1
  37. package/dist/assets/skeleton-DDFivi9Y.js +1 -0
  38. package/dist/assets/{tag-chip-B324d_Xk.js → tag-chip-u8g0b0Nf.js} +1 -1
  39. package/dist/assets/x-DdOEUmR4.js +1 -0
  40. package/dist/index.html +19 -19
  41. package/package.json +6 -6
  42. package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +2 -0
  43. package/src/features/chat/features/conversation/components/session-conversation-area.tsx +2 -0
  44. package/src/features/chat/features/conversation/components/session-conversation-input.tsx +2 -0
  45. package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-controller.test.tsx +46 -0
  46. package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-slash-commands.test.tsx +20 -0
  47. package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +138 -54
  48. package/src/features/chat/features/conversation/hooks/use-session-conversation-slash-commands.ts +25 -2
  49. package/src/shared/lib/i18n/locales/en-US/chat.json +4 -0
  50. package/src/shared/lib/i18n/locales/zh-CN/chat.json +4 -0
  51. package/dist/assets/doc-browser-DUqckL2E.js +0 -1
  52. package/dist/assets/loader-circle-DfbWUPdI.js +0 -1
  53. package/dist/assets/mcp-marketplace-page-B2D7ciJL.js +0 -1
  54. package/dist/assets/plus-wNpOxBfP.js +0 -1
  55. package/dist/assets/remote-DgfRmokf.js +0 -1
  56. package/dist/assets/rotate-cw-L_seGUwq.js +0 -1
  57. package/dist/assets/security-config-Cqxe13za.js +0 -1
  58. package/dist/assets/skeleton-D72EdBNa.js +0 -1
  59. package/dist/assets/x-Cps-je1K.js +0 -1
@@ -3,7 +3,10 @@ import { buildNcpRequestEnvelope } from '@nextclaw/ncp-react';
3
3
  import type { UiNcpSessionQueuedInputView } from '@nextclaw/client-sdk';
4
4
  import type { NcpAgentSendEnvelope, NcpRunHandle } from '@nextclaw/ncp';
5
5
 
6
- import { deriveNcpMessagePartsFromComposer } from '@/features/chat/features/input/utils/chat-composer-state.utils';
6
+ import {
7
+ createChatComposerNodesFromDraft,
8
+ deriveNcpMessagePartsFromComposer,
9
+ } from '@/features/chat/features/input/utils/chat-composer-state.utils';
7
10
  import { isNcpChatSendDisabled } from '@/features/chat/features/input/utils/ncp-chat-input-availability.utils';
8
11
  import { buildChatRunMetadata } from '@/features/chat/features/session/utils/chat-run-metadata.utils';
9
12
  import { createNcpSessionId } from '@/features/chat/features/session/utils/ncp-session-adapter.utils';
@@ -74,6 +77,7 @@ type UseSessionConversationControllerParams = {
74
77
 
75
78
  type BuildSubmissionDraftParams = {
76
79
  readonly agentIsSending: boolean;
80
+ readonly composerSnapshot?: ComposerDraftSnapshot;
77
81
  readonly inputSnapshot: SessionConversationInputSnapshot;
78
82
  readonly inputQuery: SessionConversationInputQuery;
79
83
  readonly isRuntimeBlocked: boolean;
@@ -87,6 +91,8 @@ type SubmissionDraft = {
87
91
  readonly metadata: Record<string, unknown>;
88
92
  };
89
93
 
94
+ type SubmissionComposerBehavior = 'preserve' | 'reset-and-restore';
95
+
90
96
  type SubmittingQueuedInput = {
91
97
  readonly id: string;
92
98
  readonly preview: string;
@@ -113,6 +119,7 @@ function buildInputAvailabilitySnapshot(inputQuery: SessionConversationInputQuer
113
119
  function buildSubmissionDraft(params: BuildSubmissionDraftParams): SubmissionDraft | null {
114
120
  const {
115
121
  agentIsSending,
122
+ composerSnapshot: requestedComposerSnapshot,
116
123
  inputQuery,
117
124
  inputSnapshot,
118
125
  isRuntimeBlocked,
@@ -120,9 +127,16 @@ function buildSubmissionDraft(params: BuildSubmissionDraftParams): SubmissionDra
120
127
  selectedAgentId,
121
128
  sessionKey,
122
129
  } = params;
130
+ const composerSnapshot: ComposerDraftSnapshot = requestedComposerSnapshot ?? {
131
+ text: inputSnapshot.text,
132
+ nodes: [...inputSnapshot.nodes],
133
+ selectedSkills: [...inputSnapshot.selectedSkills],
134
+ skillRecords: [...inputSnapshot.skillRecords],
135
+ attachments: [...inputSnapshot.attachments],
136
+ };
123
137
  const currentParts = deriveNcpMessagePartsFromComposer(
124
- [...inputSnapshot.nodes],
125
- inputSnapshot.attachments,
138
+ [...composerSnapshot.nodes],
139
+ composerSnapshot.attachments,
126
140
  );
127
141
  if (
128
142
  isNcpChatSendDisabled({
@@ -134,13 +148,6 @@ function buildSubmissionDraft(params: BuildSubmissionDraftParams): SubmissionDra
134
148
  ) {
135
149
  return null;
136
150
  }
137
- const composerSnapshot: ComposerDraftSnapshot = {
138
- text: inputSnapshot.text,
139
- nodes: [...inputSnapshot.nodes],
140
- selectedSkills: [...inputSnapshot.selectedSkills],
141
- skillRecords: [...inputSnapshot.skillRecords],
142
- attachments: [...inputSnapshot.attachments],
143
- };
144
151
  return {
145
152
  composerSnapshot,
146
153
  metadata: buildChatRunMetadata({
@@ -165,11 +172,11 @@ function buildSubmissionDraft(params: BuildSubmissionDraftParams): SubmissionDra
165
172
  : sessionKey
166
173
  ? inputQuery.selectedSession?.projectRoot ?? null
167
174
  : inputSnapshot.pendingProjectRoot,
168
- requestedSkills: [...inputSnapshot.selectedSkills],
175
+ requestedSkills: [...composerSnapshot.selectedSkills],
169
176
  skillRecords: inputQuery.skillRecords.filter((record) =>
170
- inputSnapshot.selectedSkills.includes(record.ref)
177
+ composerSnapshot.selectedSkills.includes(record.ref)
171
178
  ),
172
- composerNodes: [...inputSnapshot.nodes],
179
+ composerNodes: [...composerSnapshot.nodes],
173
180
  sessionMaterialization: materializationContext
174
181
  ? {
175
182
  kind: materializationContext.kind,
@@ -288,6 +295,72 @@ function useQueuedInputActions(params: {
288
295
  return { deleteQueuedInput, editQueuedInput };
289
296
  }
290
297
 
298
+ function useSubmissionDraftRunner(params: {
299
+ readonly agent: SessionConversationAgent;
300
+ readonly clearSubmittingInput: (input: SubmittingQueuedInput) => void;
301
+ readonly materializationContext?: SessionConversationMaterializationContext | null;
302
+ readonly onSessionMaterialized?: (sessionKey: string) => void;
303
+ readonly resetComposer: () => void;
304
+ readonly restoreComposer: (snapshot: ComposerDraftSnapshot) => void;
305
+ readonly runQueue: SessionRunQueue;
306
+ readonly sessionKey: string | null;
307
+ readonly setSendError: (message: string | null) => void;
308
+ readonly stageSubmittingInput: (envelope: NcpAgentSendEnvelope) => SubmittingQueuedInput | null;
309
+ }) {
310
+ const {
311
+ agent,
312
+ clearSubmittingInput,
313
+ materializationContext,
314
+ onSessionMaterialized,
315
+ resetComposer,
316
+ restoreComposer,
317
+ runQueue,
318
+ sessionKey,
319
+ setSendError,
320
+ stageSubmittingInput,
321
+ } = params;
322
+ return useCallback(async (
323
+ draft: SubmissionDraft,
324
+ composerBehavior: SubmissionComposerBehavior,
325
+ ) => {
326
+ const submissionSessionKey =
327
+ sessionKey ?? (materializationContext ? null : createNcpSessionId());
328
+ const envelope = buildSubmissionEnvelope(draft, submissionSessionKey);
329
+ if (!envelope) return;
330
+ const queuedSubmission = agent.isRunning ? stageSubmittingInput(envelope) : null;
331
+ if (composerBehavior === 'reset-and-restore') resetComposer();
332
+ setSendError(null);
333
+ try {
334
+ const handle = await agent.send(envelope);
335
+ if (queuedSubmission && handle?.runId === null) {
336
+ await runQueue.refreshQueuedInputs().catch(() => undefined);
337
+ }
338
+ if (queuedSubmission) clearSubmittingInput(queuedSubmission);
339
+ const materializedSessionKey =
340
+ handle?.sessionId?.trim() || agent.snapshot.activeRun?.sessionId?.trim() || null;
341
+ if (!sessionKey && materializedSessionKey) {
342
+ onSessionMaterialized?.(materializedSessionKey);
343
+ }
344
+ } catch (error) {
345
+ if (queuedSubmission) clearSubmittingInput(queuedSubmission);
346
+ if (composerBehavior === 'reset-and-restore') restoreComposer(draft.composerSnapshot);
347
+ setSendError(error instanceof Error ? error.message : String(error));
348
+ throw error;
349
+ }
350
+ }, [
351
+ agent,
352
+ clearSubmittingInput,
353
+ materializationContext,
354
+ onSessionMaterialized,
355
+ resetComposer,
356
+ restoreComposer,
357
+ runQueue,
358
+ sessionKey,
359
+ setSendError,
360
+ stageSubmittingInput,
361
+ ]);
362
+ }
363
+
291
364
  export function useSessionConversationController(params: UseSessionConversationControllerParams) {
292
365
  const {
293
366
  agent,
@@ -343,6 +416,19 @@ export function useSessionConversationController(params: UseSessionConversationC
343
416
  setSendError,
344
417
  });
345
418
 
419
+ const submitDraft = useSubmissionDraftRunner({
420
+ agent,
421
+ clearSubmittingInput,
422
+ materializationContext,
423
+ onSessionMaterialized,
424
+ resetComposer,
425
+ restoreComposer,
426
+ runQueue,
427
+ sessionKey,
428
+ setSendError,
429
+ stageSubmittingInput,
430
+ });
431
+
346
432
  const send = useCallback(async () => {
347
433
  if (primaryAction === 'continue') {
348
434
  await continueRun();
@@ -357,58 +443,55 @@ export function useSessionConversationController(params: UseSessionConversationC
357
443
  selectedAgentId,
358
444
  sessionKey,
359
445
  });
360
- if (!draft) {
361
- return;
446
+ if (draft) {
447
+ await submitDraft(draft, 'reset-and-restore');
362
448
  }
363
- const submissionSessionKey =
364
- sessionKey ?? (materializationContext ? null : createNcpSessionId());
365
- const envelope = buildSubmissionEnvelope(draft, submissionSessionKey);
366
- if (!envelope) {
449
+ }, [
450
+ agent.isSending,
451
+ continueRun,
452
+ inputQuery,
453
+ inputSnapshot,
454
+ isRuntimeBlocked,
455
+ materializationContext,
456
+ primaryAction,
457
+ selectedAgentId,
458
+ sessionKey,
459
+ submitDraft,
460
+ ]);
461
+
462
+ const sendPresetMessage = useCallback(async (message: string) => {
463
+ const text = message.trim();
464
+ if (!text) {
367
465
  return;
368
466
  }
369
- const queuedSubmission = agent.isRunning ? stageSubmittingInput(envelope) : null;
370
- resetComposer();
371
- setSendError(null);
372
- try {
373
- const handle = await agent.send(envelope);
374
- if (queuedSubmission && handle?.runId === null) {
375
- await runQueue.refreshQueuedInputs().catch(() => undefined);
376
- }
377
- if (queuedSubmission) {
378
- clearSubmittingInput(queuedSubmission);
379
- }
380
- const materializedSessionKey =
381
- handle?.sessionId?.trim() ||
382
- agent.snapshot.activeRun?.sessionId?.trim() ||
383
- null;
384
- if (!sessionKey && materializedSessionKey) {
385
- onSessionMaterialized?.(materializedSessionKey);
386
- }
387
- } catch (error) {
388
- if (queuedSubmission) {
389
- clearSubmittingInput(queuedSubmission);
390
- }
391
- restoreComposer(draft.composerSnapshot);
392
- setSendError(error instanceof Error ? error.message : String(error));
393
- throw error;
467
+ const draft = buildSubmissionDraft({
468
+ agentIsSending: agent.isSending,
469
+ composerSnapshot: {
470
+ text,
471
+ nodes: createChatComposerNodesFromDraft(text),
472
+ selectedSkills: [],
473
+ skillRecords: [],
474
+ attachments: [],
475
+ },
476
+ inputSnapshot,
477
+ inputQuery,
478
+ isRuntimeBlocked,
479
+ materializationContext,
480
+ selectedAgentId,
481
+ sessionKey,
482
+ });
483
+ if (draft) {
484
+ await submitDraft(draft, 'preserve');
394
485
  }
395
486
  }, [
396
- agent,
397
- clearSubmittingInput,
398
- continueRun,
487
+ agent.isSending,
399
488
  inputQuery,
400
489
  inputSnapshot,
401
490
  isRuntimeBlocked,
402
491
  materializationContext,
403
- onSessionMaterialized,
404
- resetComposer,
405
- restoreComposer,
406
492
  selectedAgentId,
407
493
  sessionKey,
408
- setSendError,
409
- stageSubmittingInput,
410
- primaryAction,
411
- runQueue,
494
+ submitDraft,
412
495
  ]);
413
496
 
414
497
  const stop = useCallback(async () => {
@@ -426,6 +509,7 @@ export function useSessionConversationController(params: UseSessionConversationC
426
509
  isSending,
427
510
  queuedInputs,
428
511
  send,
512
+ sendPresetMessage,
429
513
  sendDisabled,
430
514
  primaryAction,
431
515
  stop,
@@ -8,9 +8,15 @@ import type { ChatSlashCommandDescriptor } from '@/features/chat/features/input/
8
8
  export function useSessionConversationSlashCommands(params: {
9
9
  language: I18nLanguage;
10
10
  onContextCompactingChange?: (sessionId: string, isCompacting: boolean) => void;
11
+ onSendPresetMessage: (message: string) => Promise<void> | void;
11
12
  selectedSessionKey?: string | null;
12
13
  }): readonly ChatSlashCommandDescriptor[] {
13
- const { language, onContextCompactingChange, selectedSessionKey } = params;
14
+ const {
15
+ language,
16
+ onContextCompactingChange,
17
+ onSendPresetMessage,
18
+ selectedSessionKey,
19
+ } = params;
14
20
  const presenter = usePresenter();
15
21
  const compactingSessionIdsRef = useRef(new Set<string>());
16
22
  const compactContext = useCallback(async (sessionId: string) => {
@@ -46,6 +52,17 @@ export function useSessionConversationSlashCommands(params: {
46
52
  keywords: ['side', 'chat', 'child', 'branch', 'new'],
47
53
  onSelect: () => presenter.chatThreadManager.openSideChatDraft(sessionId),
48
54
  },
55
+ {
56
+ key: 'update-session-title',
57
+ icon: 'command',
58
+ title: t('chatSlashCommandUpdateSessionTitleTitle', language),
59
+ description: t('chatSlashCommandUpdateSessionTitleDescription', language),
60
+ detailLines: [t('chatSlashCommandUpdateSessionTitleDetail', language)],
61
+ keywords: ['update', 'rename', 'title', 'session', '更新', '重命名', '标题', '会话'],
62
+ onSelect: () => void onSendPresetMessage(
63
+ t('chatSlashCommandUpdateSessionTitlePrompt', language),
64
+ ),
65
+ },
49
66
  {
50
67
  key: 'compact-context',
51
68
  icon: 'list-collapse',
@@ -56,5 +73,11 @@ export function useSessionConversationSlashCommands(params: {
56
73
  onSelect: () => void compactContext(sessionId),
57
74
  },
58
75
  ];
59
- }, [compactContext, language, presenter.chatThreadManager, selectedSessionKey]);
76
+ }, [
77
+ compactContext,
78
+ language,
79
+ onSendPresetMessage,
80
+ presenter.chatThreadManager,
81
+ selectedSessionKey,
82
+ ]);
60
83
  }
@@ -296,6 +296,10 @@
296
296
  "chatSlashCommandCompactContextDetail": "Keeps the latest turn and the active task available for continuation.",
297
297
  "chatSlashCommandCompactContextSuccess": "Context compacted",
298
298
  "chatSlashCommandCompactContextFailed": "Couldn't compact context",
299
+ "chatSlashCommandUpdateSessionTitleTitle": "Update session title",
300
+ "chatSlashCommandUpdateSessionTitleDescription": "Ask AI to create a concise title from this conversation and update the session.",
301
+ "chatSlashCommandUpdateSessionTitleDetail": "Sends a message automatically without replacing your current draft.",
302
+ "chatSlashCommandUpdateSessionTitlePrompt": "Create a concise, accurate title based on this conversation, then use the sessions_update tool to update the current session title now. Do not only suggest a title.",
299
303
  "chatSlashPanelAppHint": "Press Enter to open this panel app on the right.",
300
304
  "chatSlashSkillHint": "Press Enter to add this skill for the next turn.",
301
305
  "chatPanelAppReferenceLoading": "Loading panel apps...",
@@ -296,6 +296,10 @@
296
296
  "chatSlashCommandCompactContextDetail": "保留最近一轮和当前任务,供后续继续处理。",
297
297
  "chatSlashCommandCompactContextSuccess": "上下文已压缩",
298
298
  "chatSlashCommandCompactContextFailed": "无法压缩上下文",
299
+ "chatSlashCommandUpdateSessionTitleTitle": "更新会话标题",
300
+ "chatSlashCommandUpdateSessionTitleDescription": "让 AI 根据当前会话内容生成简洁标题并完成更新。",
301
+ "chatSlashCommandUpdateSessionTitleDetail": "命令会自动发送一条消息,不会覆盖输入框中的草稿。",
302
+ "chatSlashCommandUpdateSessionTitlePrompt": "请根据当前会话内容生成一个简洁、准确的标题,然后立即使用 sessions_update 工具更新当前会话标题。不要只给出标题建议。",
299
303
  "chatSlashPanelAppHint": "回车在右侧打开这个面板应用。",
300
304
  "chatSlashSkillHint": "回车把该技能加入本轮请求。",
301
305
  "chatPanelAppReferenceLoading": "加载面板应用中…",
@@ -1 +0,0 @@
1
- import{t as e}from"./doc-browser-CbCBDdap.js";export{e as DocBrowser};
@@ -1 +0,0 @@
1
- import{c as e}from"./dist-CZLIZntJ.js";var t=e(`LoaderCircle`,[[`path`,{d:`M21 12a9 9 0 1 1-6.219-8.56`,key:`13zald`}]]);export{t};
@@ -1 +0,0 @@
1
- import{t as e}from"./mcp-marketplace-page-BmqbIQQQ.js";export{e as McpMarketplacePage};
@@ -1 +0,0 @@
1
- import{c as e}from"./dist-CZLIZntJ.js";var t=e(`Plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]);export{t};
@@ -1 +0,0 @@
1
- import{Mt as e}from"./index-CCWgeWoR.js";export{e as RemoteAccessPage};
@@ -1 +0,0 @@
1
- import{c as e}from"./dist-CZLIZntJ.js";var t=e(`RotateCw`,[[`path`,{d:`M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8`,key:`1p45f6`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}]]);export{t};
@@ -1 +0,0 @@
1
- import{kt as e}from"./api-CuPWhNDM.js";export{e as SecurityConfig};
@@ -1 +0,0 @@
1
- import{I as e,z as t}from"./react-CPH0zySO.js";var n=t();function r({className:t,...r}){return(0,n.jsx)(`div`,{className:e(`animate-pulse rounded-md bg-slate-200`,t),...r})}export{r as t};
@@ -1 +0,0 @@
1
- import{c as e}from"./dist-CZLIZntJ.js";var t=e(`X`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]);export{t};