@loom-framework/core 0.1.0-alpha.161 → 0.1.0-alpha.163

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 (39) hide show
  1. package/builtin-skills/app-skill/SKILL.md +1 -1
  2. package/builtin-skills/loom/SKILL.md +41 -24
  3. package/builtin-skills/loom/references/dashboard.md +6 -4
  4. package/builtin-skills/loom/references/data-model.md +2 -2
  5. package/dist/backend/ai/engine.d.ts.map +1 -1
  6. package/dist/backend/ai/engine.js +1 -0
  7. package/dist/backend/ai/engine.js.map +1 -1
  8. package/dist/backend/index.d.ts.map +1 -1
  9. package/dist/backend/index.js +3 -1
  10. package/dist/backend/index.js.map +1 -1
  11. package/dist/backend/process/engine.d.ts +10 -2
  12. package/dist/backend/process/engine.d.ts.map +1 -1
  13. package/dist/backend/process/engine.js +55 -36
  14. package/dist/backend/process/engine.js.map +1 -1
  15. package/dist/backend/process/logger.d.ts +6 -0
  16. package/dist/backend/process/logger.d.ts.map +1 -1
  17. package/dist/backend/process/logger.js +54 -4
  18. package/dist/backend/process/logger.js.map +1 -1
  19. package/dist/backend/routes/notification-routes.d.ts.map +1 -1
  20. package/dist/backend/routes/notification-routes.js +1 -0
  21. package/dist/backend/routes/notification-routes.js.map +1 -1
  22. package/dist/backend/routes/process-routes.d.ts.map +1 -1
  23. package/dist/backend/routes/process-routes.js +11 -5
  24. package/dist/backend/routes/process-routes.js.map +1 -1
  25. package/dist/cli/commands/notification.d.ts.map +1 -1
  26. package/dist/cli/commands/notification.js +4 -0
  27. package/dist/cli/commands/notification.js.map +1 -1
  28. package/dist/cli/templates/notification-center-page.d.ts.map +1 -1
  29. package/dist/cli/templates/notification-center-page.js +19 -3
  30. package/dist/cli/templates/notification-center-page.js.map +1 -1
  31. package/dist/cli/templates/notification-detail-page.d.ts.map +1 -1
  32. package/dist/cli/templates/notification-detail-page.js +15 -5
  33. package/dist/cli/templates/notification-detail-page.js.map +1 -1
  34. package/dist/cli/templates/process-management-page.d.ts.map +1 -1
  35. package/dist/cli/templates/process-management-page.js +155 -72
  36. package/dist/cli/templates/process-management-page.js.map +1 -1
  37. package/dist/types/notification.d.ts +2 -0
  38. package/dist/types/notification.d.ts.map +1 -1
  39. package/package.json +1 -1
@@ -27,6 +27,7 @@ import {
27
27
  message,
28
28
  Typography,
29
29
  theme,
30
+ DatePicker,
30
31
  } from 'antd';
31
32
  import {
32
33
  PlayCircleOutlined,
@@ -58,10 +59,11 @@ import {
58
59
  AIContext,
59
60
  } from '@loom-framework/frontend-antd';
60
61
  import type {
61
- ProcessInfo, ProcessLogEntry, ProcessMetricsAggregate, FileContent,
62
+ ProcessInfo, ProcessLogEntry, ProcessLogListResponse, ProcessMetricsAggregate, FileContent,
62
63
  ProcessMetricSnapshot, ProcessMetricsViewConfig,
63
64
  } from '@loom-framework/frontend-antd';
64
65
  import { DashboardChart } from '@loom-framework/frontend-antd';
66
+ import type { Dayjs } from 'dayjs';
65
67
 
66
68
  const { Text } = Typography;
67
69
 
@@ -104,6 +106,11 @@ registerMessages('zh-CN', {
104
106
  'process.noProcesses': '暂无过程',
105
107
  'process.noMetrics': '未配置指标',
106
108
  'process.noLogs': '暂无执行日志',
109
+ 'process.timeRange': '时间范围',
110
+ 'process.total': '共 {total} 条',
111
+ 'process.runId': '运行 ID',
112
+ 'process.triggerType': '触发方式',
113
+ 'process.startedAt': '开始时间',
107
114
  'process.queue': '执行队列',
108
115
  'process.queueRunning': '运行中',
109
116
  'process.queueQueued': '等待中',
@@ -142,7 +149,7 @@ registerMessages('zh-CN', {
142
149
  'process.colTriggerType': '触发类型',
143
150
  'process.colResult': '结果',
144
151
  'process.colTime': '时间',
145
- 'process.viewSession': '查看 AI 会话',
152
+ 'process.viewSession': '查看 Loom 会话',
146
153
  'process.businessMetrics': '业务指标',
147
154
  'process.operationalMetrics': '运行统计',
148
155
  'process.noBusinessMetrics': '暂无业务指标数据',
@@ -177,6 +184,11 @@ registerMessages('en-US', {
177
184
  'process.noProcesses': 'No processes',
178
185
  'process.noMetrics': 'No metrics configured',
179
186
  'process.noLogs': 'No execution logs',
187
+ 'process.timeRange': 'Time Range',
188
+ 'process.total': '{total} total',
189
+ 'process.runId': 'Run ID',
190
+ 'process.triggerType': 'Trigger',
191
+ 'process.startedAt': 'Started At',
180
192
  'process.queue': 'Execution Queue',
181
193
  'process.queueRunning': 'Running',
182
194
  'process.queueQueued': 'Queued',
@@ -215,7 +227,7 @@ registerMessages('en-US', {
215
227
  'process.colTriggerType': 'Trigger',
216
228
  'process.colResult': 'Result',
217
229
  'process.colTime': 'Time',
218
- 'process.viewSession': 'View AI Session',
230
+ 'process.viewSession': 'View Loom Session',
219
231
  'process.businessMetrics': 'Business Metrics',
220
232
  'process.operationalMetrics': 'Operational Metrics',
221
233
  'process.noBusinessMetrics': 'No business metrics data',
@@ -264,6 +276,10 @@ export default function ProcessManagementPage(): React.ReactElement {
264
276
  const [viewMode, setViewMode] = useState<'preview' | 'source'>('preview');
265
277
  const [activeTab, setActiveTab] = useState('overview');
266
278
  const [logs, setLogs] = useState<ProcessLogEntry[]>([]);
279
+ const [logsTotal, setLogsTotal] = useState(0);
280
+ const [logsPagination, setLogsPagination] = useState({ current: 1, pageSize: 20 });
281
+ const [logsDateRange, setLogsDateRange] = useState<[Dayjs | null, Dayjs | null] | null>(null);
282
+ const [logsLoading, setLogsLoading] = useState(false);
267
283
  const [metrics, setMetrics] = useState<ProcessMetricsAggregate[]>([]);
268
284
  const [metricsConfig, setMetricsConfig] = useState<Record<string, unknown>[]>([]);
269
285
  const [metricSnapshots, setMetricSnapshots] = useState<ProcessMetricSnapshot[]>([]);
@@ -284,17 +300,6 @@ export default function ProcessManagementPage(): React.ReactElement {
284
300
  filePath: 'PROCESS.md',
285
301
  processName: proc.name,
286
302
  });
287
- children.push({
288
- key: \`\${proc.name}/references\`,
289
- title: 'references/',
290
- icon: <FolderOutlined style={{ color: token.colorWarning }} />,
291
- isLeaf: false,
292
- isFile: false,
293
- isDir: true,
294
- filePath: 'references',
295
- children: [],
296
- processName: proc.name,
297
- });
298
303
  }
299
304
 
300
305
  return {
@@ -316,14 +321,48 @@ export default function ProcessManagementPage(): React.ReactElement {
316
321
  const result = await fetchProcesses();
317
322
  const list = result.data ?? [];
318
323
  setProcesses(list);
319
- setTreeData(buildTreeData(list));
324
+ const initialTree = buildTreeData(list);
325
+ setTreeData(initialTree);
320
326
  setExpandedKeys(list.map((p) => p.name));
327
+ // Enrich tree with actual file structure (e.g. references/ directories)
328
+ for (let i = 0; i < initialTree.length; i++) {
329
+ const node = initialTree[i]!;
330
+ if (!node.isProcess || !node.processName) continue;
331
+ const proc = list.find(p => p.name === node.processName);
332
+ if (!proc?.hasProcessFile) continue;
333
+ const hasReferences = node.children?.some(c => c.filePath === 'references' && c.isDir);
334
+ if (hasReferences) continue;
335
+ try {
336
+ const files = await fetchProcessFiles(node.processName);
337
+ const flatFiles: typeof files = [];
338
+ const flatten = (fs: typeof files) => { for (const f of fs) { if (f.isDirectory && f.children) { flatten(f.children); } else if (!f.isDirectory) { flatFiles.push(f); } } };
339
+ flatten(files);
340
+ const refFiles = flatFiles.filter(f => f.path.startsWith('references/'));
341
+ if (refFiles.length > 0) {
342
+ const { children: refChildren } = await loadDirChildren(node.processName, 'references');
343
+ if (!refChildren.length) continue;
344
+ const updated = { ...node, children: [...(node.children ?? []), {
345
+ key: \`\${node.processName}/references\`,
346
+ title: 'references/',
347
+ icon: <FolderOutlined style={{ color: token.colorWarning }} />,
348
+ isLeaf: false,
349
+ isFile: false,
350
+ isDir: true,
351
+ filePath: 'references',
352
+ children: refChildren,
353
+ processName: node.processName,
354
+ }] };
355
+ initialTree[i] = updated;
356
+ setTreeData([...initialTree]);
357
+ }
358
+ } catch { /* ignore */ }
359
+ }
321
360
  } catch {
322
361
  // error handled silently
323
362
  } finally {
324
363
  setLoading(false);
325
364
  }
326
- }, [buildTreeData]);
365
+ }, [buildTreeData, loadDirChildren]);
327
366
 
328
367
  useEffect(() => { loadProcesses(); }, [loadProcesses]);
329
368
 
@@ -348,9 +387,16 @@ export default function ProcessManagementPage(): React.ReactElement {
348
387
  };
349
388
  }, [loadProcesses]);
350
389
 
351
- const loadDirChildren = useCallback(async (processName: string, dirName: string): Promise<ProcessTreeNode[]> => {
390
+ const loadDirChildren = useCallback(async (processName: string, dirName: string): Promise<{ children: ProcessTreeNode[]; empty: boolean }> => {
352
391
  const data = await fetchProcessFiles(processName);
353
- const dirFiles = data.filter((f) => f.path.startsWith(\`\${dirName}/\`) && !f.isDirectory);
392
+ const flatFiles: typeof data = [];
393
+ const flatten = (files: typeof data) => { for (const f of files) { if (f.isDirectory && f.children) { flatten(f.children); } else if (!f.isDirectory) { flatFiles.push(f); } } };
394
+ flatten(data);
395
+ const dirFiles = flatFiles.filter((f) => f.path.startsWith(\`\${dirName}/\`));
396
+
397
+ if (dirFiles.length === 0) {
398
+ return { children: [], empty: true };
399
+ }
354
400
 
355
401
  const dirChildren: ProcessTreeNode[] = [];
356
402
  for (const f of dirFiles) {
@@ -393,7 +439,7 @@ export default function ProcessManagementPage(): React.ReactElement {
393
439
  }
394
440
  }
395
441
  }
396
- return dirChildren;
442
+ return { children: dirChildren, empty: false };
397
443
  }, [token]);
398
444
 
399
445
  const handleTreeExpand = useCallback(
@@ -404,20 +450,29 @@ export default function ProcessManagementPage(): React.ReactElement {
404
450
  if (node.processName && node.isDir) {
405
451
  if (node.children && node.children.length > 0) return;
406
452
  const dirName = node.filePath || node.title.replace(/\\/$/, '');
407
- const dirChildren = await loadDirChildren(node.processName, dirName);
408
-
409
- const updateNode = (nodes: ProcessTreeNode[]): ProcessTreeNode[] =>
410
- nodes.map((n) => {
411
- if (n.key === node.key) {
412
- return { ...n, children: dirChildren };
413
- }
414
- if (n.children) {
415
- return { ...n, children: updateNode(n.children) };
416
- }
417
- return n;
418
- });
453
+ const result = await loadDirChildren(node.processName, dirName);
454
+
455
+ if (result.empty) {
456
+ const removeTreeNode = (nodes: ProcessTreeNode[], key: string): ProcessTreeNode[] =>
457
+ nodes
458
+ .filter((n) => n.key !== key)
459
+ .map((n) => (n.children ? { ...n, children: removeTreeNode(n.children, key) } : n));
460
+ setTreeData((prev) => removeTreeNode(prev, node.key as string));
461
+ setExpandedKeys((prev) => prev.filter((k) => k !== node.key));
462
+ } else {
463
+ const updateNode = (nodes: ProcessTreeNode[]): ProcessTreeNode[] =>
464
+ nodes.map((n) => {
465
+ if (n.key === node.key) {
466
+ return { ...n, children: result.children };
467
+ }
468
+ if (n.children) {
469
+ return { ...n, children: updateNode(n.children) };
470
+ }
471
+ return n;
472
+ });
419
473
 
420
- setTreeData((prev) => updateNode(prev));
474
+ setTreeData((prev) => updateNode(prev));
475
+ }
421
476
  }
422
477
  },
423
478
  [loadDirChildren],
@@ -532,13 +587,27 @@ export default function ProcessManagementPage(): React.ReactElement {
532
587
  [loadProcesses, t],
533
588
  );
534
589
 
535
- const loadLogs = useCallback(async () => {
590
+ const loadLogs = useCallback(async (page?: number, pageSize?: number, from?: string, to?: string) => {
536
591
  if (!selectedProcess) return;
592
+ setLogsLoading(true);
537
593
  try {
538
- const data = await fetchProcessLogs(selectedProcess.name, 50);
539
- setLogs(data);
540
- } catch { /* ignore */ }
541
- }, [selectedProcess]);
594
+ const p = page ?? logsPagination.current;
595
+ const ps = pageSize ?? logsPagination.pageSize;
596
+ const result = await fetchProcessLogs(selectedProcess.name, {
597
+ limit: ps,
598
+ offset: (p - 1) * ps,
599
+ from,
600
+ to,
601
+ });
602
+ setLogs(result.data);
603
+ setLogsTotal(result.total);
604
+ } catch {
605
+ setLogs([]);
606
+ setLogsTotal(0);
607
+ } finally {
608
+ setLogsLoading(false);
609
+ }
610
+ }, [selectedProcess, logsPagination.current, logsPagination.pageSize]);
542
611
 
543
612
  const loadMetrics = useCallback(async () => {
544
613
  if (!selectedProcess) return;
@@ -558,7 +627,7 @@ export default function ProcessManagementPage(): React.ReactElement {
558
627
 
559
628
  const handleTabChange = useCallback((key: string) => {
560
629
  setActiveTab(key);
561
- if (key === 'logs') loadLogs();
630
+ if (key === 'logs') loadLogs(1, logsPagination.pageSize);
562
631
  if (key === 'metrics') loadMetrics();
563
632
  }, [loadLogs, loadMetrics]);
564
633
 
@@ -743,40 +812,54 @@ export default function ProcessManagementPage(): React.ReactElement {
743
812
  key: 'logs',
744
813
  label: t('process.logs'),
745
814
  children: (
746
- <Space direction="vertical" style={{ width: '100%' }}>
747
- <Button icon={<ReloadOutlined />} onClick={loadLogs} size="small">
748
- {t('process.refresh')}
749
- </Button>
750
- {logs.length === 0 ? (
751
- <Empty description={t('process.noLogs')} />
752
- ) : (
753
- <Timeline
754
- items={logs.map(log => ({
755
- color: log.status === 'completed' ? 'green' : log.status === 'failed' ? 'red' : log.status === 'timeout' ? 'orange' : 'blue',
756
- content: (
757
- <div>
758
- <Space>
759
- <Tooltip title={log.runId}>
760
- <Text strong>{log.runId.slice(0, 12)}</Text>
761
- </Tooltip>
762
- <Tag icon={TRIGGER_ICONS[log.triggerType]}>{log.triggerType}</Tag>
763
- <Tag color={log.status === 'completed' ? 'success' : 'error'}>{log.status}</Tag>
764
- {log.sessionId && aiContext?.switchToSession && (
765
- <Tooltip title={t('process.viewSession')}>
766
- <Button type="link" size="small" icon={<MessageOutlined />} onClick={() => aiContext.switchToSession!(log.sessionId)} />
767
- </Tooltip>
768
- )}
769
- </Space>
770
- <div>
771
- <Text type="secondary">{new Date(log.startedAt).toLocaleString()}</Text>
772
- {log.durationMs > 0 && <Text type="secondary"> · {(log.durationMs / 1000).toFixed(1)}s</Text>}
773
- </div>
774
- {log.error && <Text type="danger" style={{ fontSize: 12 }}>{log.error}</Text>}
775
- </div>
776
- ),
777
- }))}
778
- />
779
- )}
815
+ <Space direction="vertical" style={{ width: '100%' }} size="middle">
816
+ <Flex justify="flex-end" align="center">
817
+ <Space>
818
+ <DatePicker.RangePicker
819
+ placeholder={[t('process.timeRange'), '']}
820
+ onChange={(dates: [Dayjs | null, Dayjs | null] | null) => {
821
+ setLogsDateRange(dates);
822
+ setLogsPagination(prev => ({ ...prev, current: 1 }));
823
+ const from = dates?.[0]?.startOf('day')?.toISOString();
824
+ const to = dates?.[1]?.endOf('day')?.toISOString();
825
+ loadLogs(1, logsPagination.pageSize, from, to);
826
+ }}
827
+ size="small"
828
+ value={logsDateRange}
829
+ />
830
+ <Button icon={<ReloadOutlined />} onClick={() => { setLogsPagination(prev => ({ ...prev, current: 1 })); const from = logsDateRange?.[0]?.startOf('day')?.toISOString(); const to = logsDateRange?.[1]?.endOf('day')?.toISOString(); loadLogs(1, logsPagination.pageSize, from, to); }} size="small" loading={logsLoading}>
831
+ {t('process.refresh')}
832
+ </Button>
833
+ </Space>
834
+ </Flex>
835
+ <Table<ProcessLogEntry>
836
+ dataSource={logs}
837
+ columns={[
838
+ { title: t('process.runId'), dataIndex: 'runId', key: 'runId', width: 180, render: (runId: string) => <Tooltip title={runId}><Text strong style={{ fontFamily: 'monospace', fontSize: 12 }}>{runId.slice(0, 16)}</Text></Tooltip> },
839
+ { title: t('process.triggerType'), dataIndex: 'triggerType', key: 'triggerType', width: 120, render: (triggerType: ProcessLogEntry['triggerType']) => <Tag icon={TRIGGER_ICONS[triggerType]}>{triggerType}</Tag> },
840
+ { title: t('process.status'), dataIndex: 'status', key: 'status', width: 100, render: (status: ProcessLogEntry['status']) => <Tag color={status === 'completed' ? 'success' : status === 'failed' ? 'error' : status === 'timeout' ? 'warning' : 'processing'}>{status}</Tag> },
841
+ { title: t('process.startedAt'), dataIndex: 'startedAt', key: 'startedAt', width: 180, render: (startedAt: string) => <Text type="secondary">{new Date(startedAt).toLocaleString()}</Text> },
842
+ { title: t('process.duration'), dataIndex: 'durationMs', key: 'durationMs', width: 100, render: (durationMs: number) => durationMs > 0 ? <Text type="secondary">{(durationMs / 1000).toFixed(1)}s</Text> : <Text type="secondary">—</Text> },
843
+ { title: '', key: 'actions', width: 48, render: (_: unknown, record: ProcessLogEntry) => record.sessionId && aiContext?.switchToSession ? <Tooltip title={t('process.viewSession')}><Button type="link" size="small" icon={<MessageOutlined />} onClick={() => aiContext.switchToSession!(record.sessionId)} /></Tooltip> : null },
844
+ ]}
845
+ rowKey="runId"
846
+ size="small"
847
+ loading={logsLoading}
848
+ pagination={{
849
+ current: logsPagination.current,
850
+ pageSize: logsPagination.pageSize,
851
+ total: logsTotal,
852
+ showSizeChanger: true,
853
+ showTotal: (tot: number) => t('process.total').replace('{total}', String(tot)),
854
+ onChange: (page: number, pageSize: number) => {
855
+ setLogsPagination({ current: page, pageSize });
856
+ const from = logsDateRange?.[0]?.startOf('day')?.toISOString();
857
+ const to = logsDateRange?.[1]?.endOf('day')?.toISOString();
858
+ loadLogs(page, pageSize, from, to);
859
+ },
860
+ }}
861
+ locale={{ emptyText: t('process.noLogs') }}
862
+ />
780
863
  </Space>
781
864
  ),
782
865
  },
@@ -1 +1 @@
1
- {"version":3,"file":"process-management-page.js","sourceRoot":"","sources":["../../../src/cli/templates/process-management-page.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,UAAU,6BAA6B;IAC3C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA43BR,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"process-management-page.js","sourceRoot":"","sources":["../../../src/cli/templates/process-management-page.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,UAAU,6BAA6B;IAC3C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+8BR,CAAC;AACF,CAAC"}
@@ -9,6 +9,8 @@ export interface LoomNotification {
9
9
  description?: string;
10
10
  source?: 'system' | 'event' | 'cli';
11
11
  eventPattern?: string;
12
+ /** Link to AI session for "View Session" navigation */
13
+ sessionId?: string;
12
14
  read: boolean;
13
15
  createdAt: string;
14
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../../src/types/notification.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB"}
1
+ {"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../../src/types/notification.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loom-framework/core",
3
- "version": "0.1.0-alpha.161",
3
+ "version": "0.1.0-alpha.163",
4
4
  "description": "Loom framework - DataAdapter, Capability Generator, config system, backend server, CLI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",