@nan0web/ui 1.12.3 → 3.1.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 (135) hide show
  1. package/package.json +29 -20
  2. package/src/Component/index.js +1 -5
  3. package/src/Model/Element.js +183 -0
  4. package/src/Theme/AppTheme.js +19 -0
  5. package/src/Theme/CustomTheme.js +32 -0
  6. package/src/Theme/DarkLightTheme.js +34 -0
  7. package/src/Theme/Theme.js +25 -0
  8. package/src/Theme/atoms/Avatar.js +20 -0
  9. package/src/Theme/atoms/Badge.js +28 -0
  10. package/src/Theme/atoms/Button.js +88 -0
  11. package/src/Theme/atoms/Checkbox.js +26 -0
  12. package/src/Theme/atoms/Input.js +28 -0
  13. package/src/Theme/atoms/Radio.js +26 -0
  14. package/src/Theme/atoms/Select.js +16 -0
  15. package/src/Theme/atoms/TextArea.js +17 -0
  16. package/src/Theme/atoms/Typography.js +26 -0
  17. package/src/Theme/atoms/index.js +11 -0
  18. package/src/Theme/createTheme.js +22 -0
  19. package/src/Theme/index.js +20 -0
  20. package/src/Theme/molecules/Card.js +24 -0
  21. package/src/Theme/molecules/index.js +3 -0
  22. package/src/Theme/organisms/Modal.js +24 -0
  23. package/src/Theme/organisms/index.js +3 -0
  24. package/src/Theme/presets/HighContrastTheme.js +65 -0
  25. package/src/Theme/presets/NightTheme.js +66 -0
  26. package/src/Theme/presets/index.js +4 -0
  27. package/src/Theme/tokens.js +115 -0
  28. package/src/core/InputAdapter.js +1 -2
  29. package/src/core/Intent.js +22 -8
  30. package/src/core/Message/Message.js +3 -0
  31. package/src/core/OutputAdapter.js +9 -13
  32. package/src/core/index.js +7 -4
  33. package/src/domain/app/IntentAuditor.js +53 -0
  34. package/src/domain/app/JsIntentAuditor.js +145 -0
  35. package/src/domain/app/PyIntentAuditor.js +144 -0
  36. package/src/domain/app/SnapshotAuditor.js +8 -8
  37. package/src/domain/components/ShellModel.js +2 -2
  38. package/src/index.js +35 -9
  39. package/src/inspect.js +3 -0
  40. package/src/utils/format.js +21 -0
  41. package/src/utils/processI18n.js +27 -0
  42. package/src/utils/resolveContext.js +79 -0
  43. package/types/Component/index.d.ts +1 -5
  44. package/types/Model/Element.d.ts +87 -0
  45. package/types/Theme/AppTheme.d.ts +14 -0
  46. package/types/Theme/CustomTheme.d.ts +21 -0
  47. package/types/Theme/DarkLightTheme.d.ts +16 -0
  48. package/types/Theme/Theme.d.ts +18 -0
  49. package/types/Theme/atoms/Avatar.d.ts +14 -0
  50. package/types/Theme/atoms/Badge.d.ts +22 -0
  51. package/types/Theme/atoms/Button.d.ts +144 -0
  52. package/types/Theme/atoms/Checkbox.d.ts +20 -0
  53. package/types/Theme/atoms/Input.d.ts +22 -0
  54. package/types/Theme/atoms/Radio.d.ts +20 -0
  55. package/types/Theme/atoms/Select.d.ts +15 -0
  56. package/types/Theme/atoms/TextArea.d.ts +17 -0
  57. package/types/Theme/atoms/Typography.d.ts +47 -0
  58. package/types/Theme/atoms/index.d.ts +10 -0
  59. package/types/Theme/createTheme.d.ts +7 -0
  60. package/types/Theme/index.d.ts +10 -0
  61. package/types/Theme/molecules/Card.d.ts +18 -0
  62. package/types/Theme/molecules/index.d.ts +2 -0
  63. package/types/Theme/organisms/Modal.d.ts +18 -0
  64. package/types/Theme/organisms/index.d.ts +2 -0
  65. package/types/Theme/presets/HighContrastTheme.d.ts +2 -0
  66. package/types/Theme/presets/NightTheme.d.ts +2 -0
  67. package/types/Theme/presets/index.d.ts +3 -0
  68. package/types/Theme/tokens.d.ts +119 -0
  69. package/types/core/Intent.d.ts +10 -7
  70. package/types/core/Message/Message.d.ts +3 -0
  71. package/types/core/OutputAdapter.d.ts +2 -4
  72. package/types/core/index.d.ts +5 -2
  73. package/types/domain/Document.d.ts +2 -1
  74. package/types/domain/FooterModel.d.ts +2 -1
  75. package/types/domain/ModelAsApp.d.ts +1 -1
  76. package/types/domain/app/IntentAuditor.d.ts +23 -0
  77. package/types/domain/app/JsIntentAuditor.d.ts +22 -0
  78. package/types/domain/app/PyIntentAuditor.d.ts +22 -0
  79. package/types/domain/app/SnapshotAuditor.d.ts +5 -6
  80. package/types/domain/components/ShellModel.d.ts +1 -5
  81. package/types/index.d.ts +7 -9
  82. package/types/inspect.d.ts +3 -0
  83. package/types/utils/format.d.ts +5 -0
  84. package/types/utils/processI18n.d.ts +8 -0
  85. package/types/utils/resolveContext.d.ts +21 -0
  86. package/src/App/Command/DepsCommand.js +0 -24
  87. package/src/App/Core/CoreApp.js +0 -125
  88. package/src/App/Core/UI.js +0 -63
  89. package/src/App/Core/Widget.js +0 -61
  90. package/src/App/Core/index.js +0 -11
  91. package/src/App/Scenario.js +0 -45
  92. package/src/App/User/Command/Message.js +0 -3
  93. package/src/App/User/Command/index.js +0 -5
  94. package/src/App/User/UserApp.js +0 -85
  95. package/src/App/User/UserUI.js +0 -20
  96. package/src/App/User/index.js +0 -9
  97. package/src/App/index.js +0 -14
  98. package/src/Component/Process/Input.js +0 -63
  99. package/src/Component/Process/Process.js +0 -24
  100. package/src/Component/Process/index.js +0 -5
  101. package/src/Component/Welcome/Input.js +0 -48
  102. package/src/Component/Welcome/Welcome.js +0 -22
  103. package/src/Component/Welcome/index.js +0 -5
  104. package/src/Frame/Frame.js +0 -608
  105. package/src/Frame/Props.js +0 -96
  106. package/src/StdIn.js +0 -100
  107. package/src/StdOut.js +0 -95
  108. package/src/View/RenderOptions.js +0 -48
  109. package/src/View/View.js +0 -306
  110. package/src/core/Message/index.js +0 -6
  111. package/types/App/Command/DepsCommand.d.ts +0 -14
  112. package/types/App/Core/CoreApp.d.ts +0 -70
  113. package/types/App/Core/UI.d.ts +0 -38
  114. package/types/App/Core/Widget.d.ts +0 -39
  115. package/types/App/Core/index.d.ts +0 -10
  116. package/types/App/Scenario.d.ts +0 -26
  117. package/types/App/User/Command/Message.d.ts +0 -2
  118. package/types/App/User/Command/index.d.ts +0 -3
  119. package/types/App/User/UserApp.d.ts +0 -41
  120. package/types/App/User/UserUI.d.ts +0 -9
  121. package/types/App/User/index.d.ts +0 -8
  122. package/types/App/index.d.ts +0 -12
  123. package/types/Component/Process/Input.d.ts +0 -48
  124. package/types/Component/Process/Process.d.ts +0 -13
  125. package/types/Component/Process/index.d.ts +0 -4
  126. package/types/Component/Welcome/Input.d.ts +0 -34
  127. package/types/Component/Welcome/Welcome.d.ts +0 -13
  128. package/types/Component/Welcome/index.d.ts +0 -4
  129. package/types/Frame/Frame.d.ts +0 -186
  130. package/types/Frame/Props.d.ts +0 -77
  131. package/types/StdIn.d.ts +0 -62
  132. package/types/StdOut.d.ts +0 -52
  133. package/types/View/RenderOptions.d.ts +0 -29
  134. package/types/View/View.d.ts +0 -124
  135. package/types/core/Message/index.d.ts +0 -4
@@ -0,0 +1,22 @@
1
+ import { merge } from '@nan0web/types'
2
+ import Theme from './Theme.js'
3
+
4
+ /**
5
+ * Creates a theme instance with merged configuration.
6
+ *
7
+ * @param {Partial<import('./Theme.js').ThemeConfig>} overrides
8
+ * @returns {import('./Theme.js').ThemeConfig}
9
+ */
10
+ export function createTheme(overrides = {}) {
11
+ /**
12
+ * This function uses merge from @nan0web/types to create a new theme.
13
+ * It ensures nested theme properties like atoms, molecules, organisms are deeply merged.
14
+ */
15
+ const base = {
16
+ atoms: { ...Theme.atoms },
17
+ molecules: { ...Theme.molecules },
18
+ organisms: { ...Theme.organisms },
19
+ }
20
+
21
+ return merge(base, overrides)
22
+ }
@@ -0,0 +1,20 @@
1
+ import Theme from './Theme.js'
2
+ import CustomTheme, { getUserTheme } from './CustomTheme.js'
3
+ import AppTheme from './AppTheme.js'
4
+ import DarkLightTheme from './DarkLightTheme.js'
5
+ import HighContrastTheme from './presets/HighContrastTheme.js'
6
+ import NightTheme from './presets/NightTheme.js'
7
+ import { createTheme } from './createTheme.js'
8
+
9
+ export {
10
+ Theme,
11
+ CustomTheme,
12
+ getUserTheme,
13
+ AppTheme,
14
+ DarkLightTheme,
15
+ HighContrastTheme,
16
+ NightTheme,
17
+ createTheme,
18
+ }
19
+
20
+ export default Theme
@@ -0,0 +1,24 @@
1
+ import { tokens } from '../tokens.js'
2
+
3
+ /**
4
+ * Theme definition for Card molecule.
5
+ *
6
+ * @typedef {Object} CardTheme
7
+ * @property {string} borderRadius
8
+ * @property {string} boxShadow
9
+ * @property {string} padding
10
+ * @property {string} backgroundColor
11
+ * @property {string} borderColor
12
+ */
13
+
14
+ /**
15
+ * Card molecule theme.
16
+ * @type {CardTheme}
17
+ */
18
+ export default {
19
+ borderRadius: tokens.radius.lg,
20
+ boxShadow: tokens.shadow.md,
21
+ padding: tokens.space.lg,
22
+ backgroundColor: tokens.color.background,
23
+ borderColor: tokens.border.color.muted,
24
+ }
@@ -0,0 +1,3 @@
1
+ import Card from './Card.js'
2
+
3
+ export { Card }
@@ -0,0 +1,24 @@
1
+ import { tokens } from '../tokens.js'
2
+
3
+ /**
4
+ * Theme definition for Modal organism.
5
+ *
6
+ * @typedef {Object} ModalTheme
7
+ * @property {string} overlayBackground
8
+ * @property {string} borderRadius
9
+ * @property {string} boxShadow
10
+ * @property {string} padding
11
+ * @property {string} backgroundColor
12
+ */
13
+
14
+ /**
15
+ * Modal organism theme.
16
+ * @type {ModalTheme}
17
+ */
18
+ export default {
19
+ overlayBackground: 'rgba(0, 0, 0, 0.5)',
20
+ borderRadius: tokens.radius.lg,
21
+ boxShadow: tokens.shadow.lg,
22
+ padding: tokens.space.xl,
23
+ backgroundColor: tokens.color.background,
24
+ }
@@ -0,0 +1,3 @@
1
+ import Modal from './Modal.js'
2
+
3
+ export { Modal }
@@ -0,0 +1,65 @@
1
+ import { createTheme } from '../createTheme.js'
2
+ import { tokens } from '../tokens.js'
3
+
4
+ /**
5
+ * High contrast theme preset.
6
+ * Designed for maximum readability by increasing contrast between text and background.
7
+ */
8
+ export default createTheme({
9
+ atoms: {
10
+ Button: {
11
+ fontFamily: tokens.font.family,
12
+ color: tokens.color.text,
13
+ background: tokens.color.primary,
14
+ shadow: tokens.shadow.sm,
15
+ hoverBackground: 'color-mix(in srgb, var(--color-primary) 80%, black)',
16
+ borderColor: tokens.border.color.default,
17
+ borderRadius: tokens.radius.sm,
18
+ borderWidth: tokens.border.width.sm,
19
+ fontSize: tokens.font.size.base,
20
+ paddingX: tokens.space.lg,
21
+ paddingY: tokens.space.md,
22
+ solid: {
23
+ primary: { background: '#000000', color: '#ffffff', border: '#000000' },
24
+ secondary: { background: '#333333', color: '#ffffff', border: '#333333' },
25
+ success: { background: '#006600', color: '#ffffff', border: '#006600' },
26
+ warning: { background: '#996600', color: '#000000', border: '#996600' },
27
+ danger: { background: '#990000', color: '#ffffff', border: '#990000' },
28
+ info: { background: '#006699', color: '#ffffff', border: '#006699' },
29
+ light: { background: '#dddddd', color: '#000000', border: '#dddddd' },
30
+ dark: { background: '#222222', color: '#ffffff', border: '#222222' },
31
+ link: { background: 'transparent', color: '#000099', border: 'transparent' },
32
+ },
33
+ outline: {
34
+ primary: { background: '#ffffff', color: '#000000', border: '#000000' },
35
+ secondary: { background: '#ffffff', color: '#333333', border: '#333333' },
36
+ success: { background: '#ffffff', color: '#006600', border: '#006600' },
37
+ warning: { background: '#ffffff', color: '#996600', border: '#996600' },
38
+ danger: { background: '#ffffff', color: '#990000', border: '#990000' },
39
+ info: { background: '#ffffff', color: '#006699', border: '#006699' },
40
+ light: { background: '#ffffff', color: '#000000', border: '#000000' },
41
+ dark: { background: '#ffffff', color: '#222222', border: '#222222' },
42
+ },
43
+ size: {
44
+ sm: {
45
+ fontSize: '0.875rem',
46
+ paddingX: '0.5rem',
47
+ paddingY: '0.25rem',
48
+ },
49
+ md: {
50
+ fontSize: '1rem',
51
+ paddingX: '1rem',
52
+ paddingY: '0.5rem',
53
+ },
54
+ },
55
+ animation: {
56
+ transition: 'background 0.15s ease, transform 0.1s ease',
57
+ hoverAdjust: 20,
58
+ activeAdjust: -30,
59
+ focusScale: 1.02,
60
+ activeScale: 0.98,
61
+ disabledOpacity: 0.65,
62
+ },
63
+ },
64
+ },
65
+ })
@@ -0,0 +1,66 @@
1
+ import { createTheme } from '../createTheme.js'
2
+ import { tokens } from '../tokens.js'
3
+
4
+ /**
5
+ * Night (dark) theme preset.
6
+ * Optimized for low-light environments with deep background colors and vibrant text.
7
+ * Overrides solid button styles while keeping contrast high.
8
+ */
9
+ export default createTheme({
10
+ atoms: {
11
+ Button: {
12
+ fontFamily: tokens.font.family,
13
+ color: tokens.color.text,
14
+ background: tokens.color.primary,
15
+ shadow: tokens.shadow.sm,
16
+ hoverBackground: 'color-mix(in srgb, var(--color-primary) 80%, black)',
17
+ borderColor: tokens.border.color.default,
18
+ borderRadius: tokens.radius.sm,
19
+ borderWidth: tokens.border.width.sm,
20
+ fontSize: tokens.font.size.base,
21
+ paddingX: tokens.space.lg,
22
+ paddingY: tokens.space.md,
23
+ solid: {
24
+ primary: { background: '#0d6efd', color: '#ffffff', border: '#0d6efd' },
25
+ secondary: { background: '#6c757d', color: '#ffffff', border: '#6c757d' },
26
+ success: { background: '#198754', color: '#ffffff', border: '#198754' },
27
+ warning: { background: '#ffc107', color: '#000000', border: '#ffc107' },
28
+ danger: { background: '#dc3545', color: '#ffffff', border: '#dc3545' },
29
+ info: { background: '#0dcaf0', color: '#000000', border: '#0dcaf0' },
30
+ light: { background: '#aaaaaa', color: '#000000', border: '#aaaaaa' },
31
+ dark: { background: '#212529', color: '#ffffff', border: '#212529' },
32
+ link: { background: 'transparent', color: '#6ea8fe', border: 'transparent' },
33
+ },
34
+ outline: {
35
+ primary: { background: 'transparent', color: '#0d6efd', border: '#0d6efd' },
36
+ secondary: { background: 'transparent', color: '#6c757d', border: '#6c757d' },
37
+ success: { background: 'transparent', color: '#198754', border: '#198754' },
38
+ warning: { background: 'transparent', color: '#ffc107', border: '#ffc107' },
39
+ danger: { background: 'transparent', color: '#dc3545', border: '#dc3545' },
40
+ info: { background: 'transparent', color: '#0dcaf0', border: '#0dcaf0' },
41
+ light: { background: 'transparent', color: '#aaaaaa', border: '#aaaaaa' },
42
+ dark: { background: 'transparent', color: '#212529', border: '#212529' },
43
+ },
44
+ size: {
45
+ sm: {
46
+ fontSize: '0.875rem',
47
+ paddingX: '0.5rem',
48
+ paddingY: '0.25rem',
49
+ },
50
+ md: {
51
+ fontSize: '1rem',
52
+ paddingX: '1rem',
53
+ paddingY: '0.5rem',
54
+ },
55
+ },
56
+ animation: {
57
+ transition: 'background 0.15s ease, transform 0.1s ease',
58
+ hoverAdjust: 20,
59
+ activeAdjust: -30,
60
+ focusScale: 1.02,
61
+ activeScale: 0.98,
62
+ disabledOpacity: 0.65,
63
+ },
64
+ },
65
+ },
66
+ })
@@ -0,0 +1,4 @@
1
+ import HighContrastTheme from './HighContrastTheme.js'
2
+ import NightTheme from './NightTheme.js'
3
+
4
+ export { HighContrastTheme, NightTheme }
@@ -0,0 +1,115 @@
1
+ // src/tokens.js
2
+ export const tokens = {
3
+ // Spacing
4
+ space: {
5
+ xs: '0.25rem',
6
+ sm: '0.5rem',
7
+ md: '0.75rem',
8
+ lg: '1rem',
9
+ xl: '1.5rem',
10
+ },
11
+
12
+ // Radius
13
+ radius: {
14
+ none: '0',
15
+ sm: '0.125rem',
16
+ md: '0.25rem',
17
+ lg: '0.5rem',
18
+ full: '9999px',
19
+ },
20
+
21
+ // Border
22
+ border: {
23
+ width: {
24
+ sm: '1px',
25
+ md: '2px',
26
+ },
27
+ color: {
28
+ default: 'var(--color-border)',
29
+ muted: 'var(--color-border-muted)',
30
+ error: 'var(--color-error)',
31
+ },
32
+ },
33
+
34
+ // Color
35
+ color: {
36
+ text: 'var(--color-text)',
37
+ background: 'var(--color-background)',
38
+ primary: 'var(--color-primary)',
39
+ success: 'var(--color-success)',
40
+ warning: 'var(--color-warning)',
41
+ error: 'var(--color-error)',
42
+ },
43
+
44
+ // Typography
45
+ font: {
46
+ family: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
47
+ size: {
48
+ xs: '0.75rem',
49
+ sm: '0.875rem',
50
+ base: '1rem',
51
+ lg: '1.125rem',
52
+ xl: '1.25rem',
53
+ },
54
+ weight: {
55
+ normal: '400',
56
+ medium: '500',
57
+ bold: '700',
58
+ },
59
+ },
60
+
61
+ // Shadows
62
+ shadow: {
63
+ sm: '0 1px 2px rgba(0,0,0,0.05)',
64
+ md: '0 4px 6px rgba(0,0,0,0.1)',
65
+ lg: '0 10px 25px rgba(0,0,0,0.15)',
66
+ },
67
+
68
+ // Breakpoints (Bootstrap 5)
69
+ breakpoint: {
70
+ xs: '0', // extra‑small
71
+ sm: '576px',
72
+ md: '768px',
73
+ lg: '992px',
74
+ xl: '1200px',
75
+ xxl: '1400px',
76
+ },
77
+
78
+ // Container max‑widths (Bootstrap 5)
79
+ container: {
80
+ sm: '540px',
81
+ md: '720px',
82
+ lg: '960px',
83
+ xl: '1140px',
84
+ xxl: '1320px',
85
+ },
86
+
87
+ // Z‑index scale (Bootstrap)
88
+ zIndex: {
89
+ dropdown: 1000,
90
+ sticky: 1020,
91
+ fixed: 1030,
92
+ modalBackdrop: 1040,
93
+ modal: 1050,
94
+ popover: 1060,
95
+ tooltip: 1070,
96
+ },
97
+
98
+ // Opacity scale
99
+ opacity: {
100
+ 0: '0',
101
+ 10: '0.1',
102
+ 25: '0.25',
103
+ 50: '0.5',
104
+ 75: '0.75',
105
+ 90: '0.9',
106
+ 100: '1',
107
+ },
108
+
109
+ // Transition durations
110
+ transition: {
111
+ fast: '150ms',
112
+ medium: '300ms',
113
+ slow: '500ms',
114
+ },
115
+ }
@@ -1,6 +1,5 @@
1
1
  import Event from '@nan0web/event/oop'
2
2
  import CancelError from './Error/CancelError.js'
3
- import UiMessage from './Message/Message.js'
4
3
 
5
4
  /**
6
5
  * @typedef {Object} AskOptions
@@ -32,7 +31,7 @@ export class InputAdapter extends Event {
32
31
  * @returns {void}
33
32
  */
34
33
  start() {
35
- this.emit('input', UiMessage.from({ body: 'Adapter started' }))
34
+ this.emit('input', { body: 'Adapter started' })
36
35
  }
37
36
 
38
37
  /**
@@ -48,7 +48,7 @@ import { IntentErrorModel } from './IntentErrorModel.js'
48
48
  * @typedef {'info' | 'warn' | 'error' | 'success'} ShowLevel
49
49
  */
50
50
 
51
- /** @typedef {ShowLevel} LogLevel */
51
+ /** @typedef {ShowLevel | 'debug'} LogLevel */
52
52
 
53
53
  /**
54
54
  * Model emits a show message. No response expected.
@@ -168,7 +168,14 @@ import { IntentErrorModel } from './IntentErrorModel.js'
168
168
  * @typedef {'ask' | 'show' | 'progress' | 'render' | 'agent'} IntentType
169
169
  */
170
170
 
171
- export const INTENT_TYPES = /** @type {const} */ (['ask', 'progress', 'show', 'log', 'render', 'agent'])
171
+ export const INTENT_TYPES = /** @type {const} */ ([
172
+ 'ask',
173
+ 'progress',
174
+ 'show',
175
+ 'log',
176
+ 'render',
177
+ 'agent',
178
+ ])
172
179
 
173
180
  /**
174
181
  * Detects if a value is a Model-as-Schema class (has static fields with `help`).
@@ -286,16 +293,23 @@ export function progress(message, value = 0, optionsOrTotalOrId, id) {
286
293
  }
287
294
  }
288
295
 
289
- return {
290
- type: 'progress',
291
- message,
292
- value,
296
+ return {
297
+ type: 'progress',
298
+ message,
299
+ value,
293
300
  total: options.total,
294
- id: options.id || 'default',
295
- options
301
+ id: options.id || 'default',
302
+ options,
296
303
  }
297
304
  }
298
305
 
306
+ /**
307
+ * Lgs a message if level is greater or equal the current view level.
308
+ * @param {LogLevel} level
309
+ * @param {string} message
310
+ * @param {object} [data={}]
311
+ * @returns {LogIntent}
312
+ */
299
313
  export function log(level, message, data = {}) {
300
314
  return { type: 'log', level, message, ...data }
301
315
  }
@@ -17,6 +17,9 @@ import { Message } from '@nan0web/co'
17
17
  *
18
18
  * @class UiMessage
19
19
  * @extends Message
20
+ * @property {Record<string, any>} head - Message head.
21
+ * @property {boolean} isValid - True if message is valid.
22
+ * @property {Date} time - Creation timestamp.
20
23
  *
21
24
  * @example
22
25
  * class UserLoginMessage extends UiMessage {
@@ -1,6 +1,4 @@
1
1
  import Event from '@nan0web/event/oop'
2
- import OutputMessage from './Message/OutputMessage.js'
3
- import FormMessage from './Form/Message.js'
4
2
 
5
3
  /**
6
4
  * Abstract output adapter for UI implementations.
@@ -12,7 +10,7 @@ class OutputAdapter extends Event {
12
10
  /**
13
11
  * Renders a message to the user.
14
12
  *
15
- * @param {OutputMessage|FormMessage} message - Message to render.
13
+ * @param {object} message - Message to render.
16
14
  * @throws {Error} If not overridden by a subclass.
17
15
  */
18
16
  render(message) {
@@ -27,16 +25,14 @@ class OutputAdapter extends Event {
27
25
  * @returns {void}
28
26
  */
29
27
  progress(progress, metadata = {}) {
30
- this.render(
31
- OutputMessage.from({
32
- content: [],
33
- metadata: {
34
- ...metadata,
35
- progress,
36
- elementType: 'progress',
37
- },
38
- }),
39
- )
28
+ this.render({
29
+ content: [],
30
+ metadata: {
31
+ ...metadata,
32
+ progress,
33
+ elementType: 'progress',
34
+ },
35
+ })
40
36
  }
41
37
 
42
38
  /**
package/src/core/index.js CHANGED
@@ -6,16 +6,16 @@ export { UIStream, UIStream as UiStream }
6
6
  import StreamEntry from './StreamEntry.js'
7
7
  export { StreamEntry, StreamEntry as UiStreamEntry }
8
8
 
9
- export { default as UiMessage } from './Message/Message.js'
10
- export { default as FormMessage } from './Form/Message.js'
11
9
  export { default as FormInput } from './Form/Input.js'
12
10
 
13
11
  import UIForm from './Form/Form.js'
14
12
  export { UIForm, UIForm as UiForm }
15
13
 
16
- export { default as Error, CancelError } from './Error/index.js'
14
+ export { default as UiMessage } from './Message/Message.js'
15
+ export { default as FormMessage } from './Form/Message.js'
16
+ export { default as OutputMessage } from './Message/OutputMessage.js'
17
17
 
18
- export { default as UiAdapter } from './UiAdapter.js'
18
+ export { default as Error, CancelError } from './Error/index.js'
19
19
 
20
20
  // Flow — Yield-Based Universal UI Architecture
21
21
  export {
@@ -43,6 +43,9 @@ export { default as Flow } from './Flow.js'
43
43
  // OLMUI Generator Engine — Intent-based Model→Adapter contract
44
44
  export { validateIntent, ask, progress, log, render, result, INTENT_TYPES, isModelSchema } from './Intent.js'
45
45
  /** @typedef {import('./Intent.js').Intent} Intent */
46
+ /** @typedef {import('./Intent.js').ShowLevel} ShowLevel */
47
+ /** @typedef {import('./Intent.js').ShowIntent} ShowIntent */
48
+ /** @typedef {import('./Intent.js').ShowData} ShowData */
46
49
  /** @typedef {import('./Intent.js').AskResponse} AskResponse */
47
50
  /** @typedef {import('./InputAdapter.js').AskOptions} AskOptions */
48
51
  export { IntentErrorModel } from './IntentErrorModel.js'
@@ -0,0 +1,53 @@
1
+ import { AuditorModel } from '@nan0web/inspect/domain/AuditorModel'
2
+ import { result } from '../../core/Intent.js'
3
+ import { JsIntentAuditor } from './JsIntentAuditor.js'
4
+ import { PyIntentAuditor } from './PyIntentAuditor.js'
5
+
6
+ /**
7
+ * IntentAuditor — Base model for OLMUI Intent hygiene audits.
8
+ * Polymorphically delegates execution to JS or Python subclasses.
9
+ */
10
+ export class IntentAuditor extends AuditorModel {
11
+ static alias = 'intents'
12
+
13
+ static dir = {
14
+ type: 'string',
15
+ help: 'Target directory to scan for output hygiene',
16
+ positional: true,
17
+ default: 'src',
18
+ }
19
+
20
+ static UI = {
21
+ title: 'OLMUI Intent Hygiene Audit',
22
+ description: 'Validates code files to ensure raw console statements are purged and proper yield intents are used.',
23
+ icon: '📡',
24
+ starting: 'Scanning {dir} for intent and output hygiene...',
25
+ auditPassed: 'Hygiene OK: {file}',
26
+ auditFailed: 'Hygiene Leak in {file}: {errors}',
27
+ doneSuccess: 'Pristine output hygiene! Zero leaks found.',
28
+ doneErrors: 'Intent hygiene audit failed with errors. Check above.',
29
+
30
+ errorDb: 'Database not provided to auditor',
31
+ errorConsoleLeak: 'Line {line}: Found direct system write "{match}" (violates OLMUI/TLI isolation, use yield show | log | ask).',
32
+ errorProcessLeak: 'Line {line}: Found direct process write "{match}" (violates total logic isolation, use yield intents).',
33
+ errorPrintLeak: 'Line {line}: Found direct print statement "{match}" (violates Python TLI isolation, use yield intents).',
34
+ errorSysWriteLeak: 'Line {line}: Found direct system stream write "{match}" (violates Python TLI isolation).',
35
+ }
36
+
37
+ /**
38
+ * Run the intent audit, delegating to the appropriate platform subclass.
39
+ * @returns {AsyncGenerator<import('@nan0web/ui').Intent, import('@nan0web/ui').ResultIntent, any>}
40
+ */
41
+ async *run() {
42
+ const AuditorClass = /** @type {any} */ (this).platform === 'python' ? PyIntentAuditor : JsIntentAuditor
43
+ const delegate = new (/** @type {any} */ (AuditorClass))({
44
+ dir: /** @type {any} */ (this).dir,
45
+ fix: /** @type {any} */ (this).fix,
46
+ platform: /** @type {any} */ (this).platform,
47
+ }, /** @type {any} */ (this)._)
48
+
49
+ return yield* delegate.run()
50
+ }
51
+ }
52
+
53
+ export default IntentAuditor