@nan0web/ui 1.9.0 → 1.11.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 (108) hide show
  1. package/README.md +97 -12
  2. package/package.json +54 -25
  3. package/src/App/Command/DepsCommand.js +3 -4
  4. package/src/Frame/Props.js +12 -18
  5. package/src/InterfaceTemplate/InterfaceTemplate.js +9 -7
  6. package/src/Model/index.js +86 -2
  7. package/src/StdIn.js +2 -6
  8. package/src/cli.js +1 -0
  9. package/src/core/Form/Form.js +8 -7
  10. package/src/core/Form/Message.js +1 -1
  11. package/src/core/GeneratorRunner.js +77 -7
  12. package/src/core/InputAdapter.js +3 -1
  13. package/src/core/Intent.js +214 -16
  14. package/src/core/IntentErrorModel.js +6 -1
  15. package/src/core/Message/Message.js +4 -7
  16. package/src/core/Message/OutputMessage.js +4 -9
  17. package/src/core/Stream.js +16 -5
  18. package/src/core/StreamEntry.js +20 -28
  19. package/src/core/index.js +2 -1
  20. package/src/domain/Content.js +196 -0
  21. package/src/domain/Document.js +17 -0
  22. package/src/domain/FooterModel.js +37 -19
  23. package/src/domain/HeaderModel.js +47 -21
  24. package/src/domain/HeroModel.js +24 -22
  25. package/src/domain/LayoutModel.js +43 -0
  26. package/src/domain/ModelAsApp.js +46 -0
  27. package/src/domain/SandboxModel.js +19 -16
  28. package/src/domain/app/GalleryCommand.js +53 -0
  29. package/src/domain/app/GalleryRenderIntent.js +77 -0
  30. package/src/domain/app/SnapshotAuditor.js +401 -0
  31. package/src/domain/app/SnapshotRunner.js +264 -0
  32. package/src/domain/app/UIApp.js +78 -0
  33. package/src/domain/components/BreadcrumbModel.js +10 -6
  34. package/src/domain/components/FeatureGridModel.js +62 -0
  35. package/src/domain/components/MarkdownModel.js +24 -0
  36. package/src/domain/components/ShellModel.js +243 -0
  37. package/src/domain/components/TableModel.js +10 -6
  38. package/src/domain/components/ToastModel.js +10 -6
  39. package/src/domain/components/index.js +3 -1
  40. package/src/domain/index.js +14 -4
  41. package/src/index.js +21 -2
  42. package/src/inspect.js +2 -0
  43. package/src/test/ScenarioAdapter.js +59 -0
  44. package/src/test/ScenarioTest.js +51 -0
  45. package/src/test/ScenarioTest.story.js +56 -0
  46. package/src/testing/CrashReporter.js +56 -0
  47. package/src/testing/GalleryGenerator.js +29 -0
  48. package/src/testing/LogicInspector.js +55 -0
  49. package/src/testing/SnapshotRunner.js +22 -0
  50. package/src/testing/SpecAdapter.js +115 -0
  51. package/src/testing/SpecRunner.js +121 -0
  52. package/src/testing/VisualAdapter.js +46 -0
  53. package/src/testing/index.js +7 -0
  54. package/src/testing/verifySnapshot.js +17 -0
  55. package/types/App/Command/DepsCommand.d.ts +0 -2
  56. package/types/Model/index.d.ts +56 -4
  57. package/types/StdIn.d.ts +3 -3
  58. package/types/cli.d.ts +1 -0
  59. package/types/core/Form/Form.d.ts +2 -2
  60. package/types/core/GeneratorRunner.d.ts +18 -1
  61. package/types/core/InputAdapter.d.ts +2 -1
  62. package/types/core/Intent.d.ts +232 -26
  63. package/types/core/IntentErrorModel.d.ts +4 -0
  64. package/types/core/Message/Message.d.ts +2 -2
  65. package/types/core/Message/OutputMessage.d.ts +0 -2
  66. package/types/core/index.d.ts +2 -1
  67. package/types/domain/Content.d.ts +340 -0
  68. package/types/domain/Document.d.ts +21 -0
  69. package/types/domain/FooterModel.d.ts +22 -12
  70. package/types/domain/HeaderModel.d.ts +36 -13
  71. package/types/domain/HeroModel.d.ts +19 -17
  72. package/types/domain/LayoutModel.d.ts +34 -0
  73. package/types/domain/ModelAsApp.d.ts +23 -0
  74. package/types/domain/SandboxModel.d.ts +10 -0
  75. package/types/domain/app/GalleryCommand.d.ts +55 -0
  76. package/types/domain/app/GalleryRenderIntent.d.ts +31 -0
  77. package/types/domain/app/SnapshotAuditor.d.ts +99 -0
  78. package/types/domain/app/SnapshotRunner.d.ts +45 -0
  79. package/types/domain/app/UIApp.d.ts +60 -0
  80. package/types/domain/components/BreadcrumbModel.d.ts +6 -8
  81. package/types/domain/components/FeatureGridModel.d.ts +50 -0
  82. package/types/domain/components/MarkdownModel.d.ts +19 -0
  83. package/types/domain/components/ShellModel.d.ts +56 -0
  84. package/types/domain/components/TableModel.d.ts +4 -0
  85. package/types/domain/components/ToastModel.d.ts +4 -0
  86. package/types/domain/components/index.d.ts +3 -0
  87. package/types/domain/index.d.ts +10 -4
  88. package/types/index.d.ts +19 -1
  89. package/types/inspect.d.ts +2 -0
  90. package/types/test/ScenarioAdapter.d.ts +43 -0
  91. package/types/test/ScenarioTest.d.ts +24 -0
  92. package/types/test/ScenarioTest.story.d.ts +1 -0
  93. package/types/testing/CrashReporter.d.ts +13 -0
  94. package/types/testing/GalleryGenerator.d.ts +1 -0
  95. package/types/testing/LogicInspector.d.ts +22 -0
  96. package/types/testing/SnapshotRunner.d.ts +7 -0
  97. package/types/testing/SpecAdapter.d.ts +57 -0
  98. package/types/testing/SpecRunner.d.ts +41 -0
  99. package/types/testing/VisualAdapter.d.ts +9 -0
  100. package/types/testing/index.d.ts +7 -0
  101. package/types/testing/verifySnapshot.d.ts +14 -0
  102. package/src/README.md.js +0 -436
  103. package/types/App/Command/Options.d.ts +0 -43
  104. package/types/App/Command/index.d.ts +0 -8
  105. package/types/App/User/Command/Options.d.ts +0 -34
  106. package/types/core/Message/InputMessage.d.ts +0 -71
  107. package/types/domain/components/HeroModel.d.ts +0 -24
  108. package/types/domain/components/ShowcaseAppModel.d.ts +0 -32
@@ -0,0 +1,55 @@
1
+ import { runGenerator } from '../core/GeneratorRunner.js'
2
+
3
+ /**
4
+ * LogicInspector
5
+ *
6
+ * Базовий клас для захоплення "Логічних зліпків" (Intent Stream) будь-яких моделей OLMUI.
7
+ * Дозволяє виконувати чисто-логічне тестування без прив'язки до рендерингу.
8
+ */
9
+ export class LogicInspector {
10
+ /**
11
+ * Виконує генератор моделі та записує послідовність усіх інтенцій.
12
+ * @param {AsyncGenerator<import('../core/Intent.js').Intent, import('../core/Intent.js').ResultIntent, import('../core/Intent.js').IntentResponse>} modelStream - результат виклику model.run()
13
+ * @param {object} options
14
+ * @param {Array<any> | ((locale: string) => Array<any>)} [options.inputs] - черга вхідних значень для askIntent
15
+ * @param {string} [options.locale] - локаль для тестів
16
+ * @param {function} [options.t] - функція перекладу
17
+ * @returns {Promise<Array<any>>} Intent Stream Log
18
+ */
19
+ static async capture(modelStream, { inputs = [], locale = 'uk', t = (k) => k } = {}) {
20
+ const intents = []
21
+ let inputIdx = 0
22
+ const resolvedInputs = typeof inputs === 'function' ? inputs(locale) : inputs
23
+
24
+ const recordingAdapter = {
25
+ /** @param {import('../core/Intent.js').AskIntent} i */
26
+ ask: async (i) => {
27
+ const value = resolvedInputs[inputIdx++]
28
+ const entry = { type: 'ask', field: i.field, schema: i.schema, input: value }
29
+ intents.push(entry)
30
+ return { value }
31
+ },
32
+ /** @param {import('../core/Intent.js').ShowIntent} i */
33
+ show: async (i) => {
34
+ intents.push({ type: 'show', level: i.level || 'info', message: i.message })
35
+ },
36
+ /** @param {import('../core/Intent.js').ProgressIntent} i */
37
+ progress: async (i) => {
38
+ intents.push({ type: 'progress', message: i.message })
39
+ },
40
+ /** @param {import('../core/Intent.js').RenderIntent} i */
41
+ render: async (i) => {
42
+ intents.push({ type: 'render', component: i.component, props: i.props })
43
+ },
44
+ /** @param {import('../core/Intent.js').ResultIntent} i */
45
+ result: async (i) => {
46
+ intents.push({ type: 'result', data: i.data })
47
+ },
48
+ t
49
+ }
50
+
51
+ // Викликаємо базовий раннер з нашим записуючим адаптером
52
+ await runGenerator(modelStream, recordingAdapter)
53
+ return intents
54
+ }
55
+ }
@@ -0,0 +1,22 @@
1
+ import { SnapshotRunner as Runner } from '../domain/app/SnapshotRunner.js'
2
+ import DBFS from '@nan0web/db-fs'
3
+
4
+ /**
5
+ * Legacy bridge for SnapshotRunner.
6
+ * @deprecated Use SnapshotRunner model from domain/app
7
+ */
8
+ export class SnapshotRunner {
9
+ static async generateAndAudit(options) {
10
+ const db = options.db || new DBFS({ root: options.dataDir })
11
+ const runner = new Runner(options, { db })
12
+ if (options.getCategory) runner.getCategory = options.getCategory
13
+ if (options.createModelStream) runner.createModelStream = options.createModelStream
14
+
15
+ const gen = runner.run()
16
+ let res = await gen.next()
17
+ while (!res.done) {
18
+ res = await gen.next()
19
+ }
20
+ return res.value
21
+ }
22
+ }
@@ -0,0 +1,115 @@
1
+ import assert from 'node:assert/strict'
2
+
3
+ /**
4
+ * @typedef {Object} SpecAdapterOptions
5
+ * @property {typeof import('node:assert/strict')} [assert] Custom assertion library (falls back to node:assert in Node runtime)
6
+ */
7
+
8
+ export class SpecAdapter {
9
+ /** @type {Array<object>} */
10
+ stream
11
+ /** @type {typeof import('node:assert/strict')} */
12
+ assert
13
+
14
+ /**
15
+ * @param {Array<object>} stream The remaining nan0 array without the first element.
16
+ * @param {SpecAdapterOptions} [options={}]
17
+ */
18
+ constructor(stream, options = {}) {
19
+ this.stream = stream
20
+ this.assert = options.assert || assert
21
+ }
22
+
23
+ /**
24
+ * Helper to get the next step and assert type match.
25
+ * @param {string} intentType
26
+ */
27
+ #popExpected(intentType) {
28
+ const step = this.stream.shift()
29
+ if (!step) {
30
+ this.assert.fail(`Model yielded '${intentType}' intent, but Nan0Spec stream is exhausted (no more steps expected).`)
31
+ }
32
+ if (!(intentType in step)) {
33
+ // Find what step type it actually is
34
+ const actualType = Object.keys(step).find(k => !k.startsWith('$'))
35
+ this.assert.fail(`Strict mismatch: Model yielded '${intentType}', but Nan0Spec stream expected '${actualType}'. Trace: ${JSON.stringify(step)}`)
36
+ }
37
+ return step
38
+ }
39
+
40
+ /**
41
+ * @param {import('../core/Intent.js').AskIntent} intent
42
+ */
43
+ async ask(intent) {
44
+ const step = this.#popExpected('ask')
45
+ this.assert.equal(step.ask, intent.field, `Field mismatch on ask. Expected '${step.ask}', got '${intent.field}'`)
46
+
47
+ return { value: step.$value }
48
+ }
49
+
50
+ /**
51
+ * @param {import('../core/Intent.js').ShowIntent} intent
52
+ */
53
+ async show(intent) {
54
+ const step = this.#popExpected('show')
55
+ if (step.show && typeof step.show === 'string') {
56
+ const activeMessage = intent.message
57
+ if (activeMessage && step.show !== '*' && step.show !== '') {
58
+ this.assert.equal(activeMessage, step.show, `Show message mismatch`)
59
+ }
60
+ }
61
+ }
62
+
63
+ /**
64
+ * @param {import('../core/Intent.js').LogIntent} intent
65
+ */
66
+ async log(intent) {
67
+ const step = this.#popExpected('log')
68
+ if (step.log && typeof step.log === 'string') {
69
+ const activeMessage = intent.message
70
+ if (activeMessage && step.log !== '*' && step.log !== '') {
71
+ this.assert.equal(activeMessage, step.log, `Log message mismatch`)
72
+ }
73
+ }
74
+ }
75
+
76
+ /**
77
+ * @param {import('../core/Intent.js').ProgressIntent} intent
78
+ */
79
+ async progress(intent) {
80
+ this.#popExpected('progress')
81
+ }
82
+
83
+ /**
84
+ * @param {import('../core/Intent.js').RenderIntent} intent
85
+ */
86
+ async render(intent) {
87
+ const step = this.#popExpected('render')
88
+ const activeComponent = intent.component
89
+ this.assert.equal(activeComponent, step.render, `Render component mismatch. Expected '${step.render}'.`)
90
+ }
91
+
92
+ /**
93
+ * @param {import('../core/Intent.js').AgentIntent} intent
94
+ */
95
+ async agent(intent) {
96
+ const step = this.#popExpected('agent')
97
+ this.assert.equal(step.agent, intent.task, `Agent task mismatch. Expected '${step.agent}'.`)
98
+
99
+ return { success: step.$success !== false, files: step.$files, message: step.$message }
100
+ }
101
+
102
+ /**
103
+ * @param {import('../core/Intent.js').ResultIntent} intent
104
+ */
105
+ async result(intent) {
106
+ // Only pop result if there's a result recorded in the spec stream
107
+ if (this.stream.length > 0 && typeof this.stream[0] === 'object' && 'result' in this.stream[0]) {
108
+ const step = this.#popExpected('result')
109
+ if (step.result !== undefined && step.result !== '*') {
110
+ const actualData = intent?.data ?? intent
111
+ this.assert.deepEqual(actualData, step.result, `Result object deep mismatch`)
112
+ }
113
+ }
114
+ }
115
+ }
@@ -0,0 +1,121 @@
1
+ import assert from 'node:assert/strict'
2
+ import { runGenerator } from '../core/GeneratorRunner.js'
3
+ import { ModelAsApp } from '../domain/ModelAsApp.js'
4
+ import { result, progress } from '../core/Intent.js'
5
+ import { SpecAdapter } from './SpecAdapter.js'
6
+
7
+ export class SpecRunner extends ModelAsApp {
8
+ static stream = { help: 'The .nan0 intent stream array', default: [] }
9
+ static registry = { help: 'A registry of Model Classes that can be mounted', default: {} }
10
+ static UI = {
11
+ invalidStream: 'Invalid Nan0Spec: stream must be a non-empty array',
12
+ invalidFirstStep: 'Invalid Nan0Spec: first step missing or invalid',
13
+ missingAppName:
14
+ 'Invalid Nan0Spec: first step must define the AppName key (e.g. ShoppingCartApp)',
15
+ appNotFound:
16
+ "SpecRunner: AppName '{app}' not found in provided registry. Did you forget to import it?",
17
+ invalidGenerator: "SpecRunner: Model '{app}' does not have a valid run() async generator",
18
+ running: 'Running {app}...',
19
+ unhandledSteps: 'Model finished execution, but stream still has {count} unhandled steps',
20
+ }
21
+
22
+ /** @type {typeof import('node:assert/strict')} */
23
+ #assert
24
+
25
+ /**
26
+ * @param {Partial<SpecRunner>} [data={}]
27
+ * @param {Partial<import('../index.js').ModelAsAppOptions> & { assert?: typeof import('node:assert/strict') }} [options={}]
28
+ */
29
+ constructor(data = {}, options = {}) {
30
+ super(data, /** @type {import('../index.js').ModelAsAppOptions} */ (options))
31
+ this.#assert = options.assert || assert
32
+ /** @type {Array<object>} The Nan0Spec stream */
33
+ this.stream
34
+ /** @type {Record<string, any>} The registry of Model Classes */
35
+ this.registry
36
+ }
37
+
38
+ /**
39
+ * @throws {Error}
40
+ * @returns {AsyncGenerator<import('../core/Intent.js').Intent, import('../core/Intent.js').ResultIntent, any>}
41
+ */
42
+ async *run() {
43
+ const { t } = this._
44
+ const stream = this.stream
45
+ const registry = this.registry
46
+
47
+ if (!Array.isArray(stream) || stream.length === 0) {
48
+ throw new Error(t(SpecRunner.UI.invalidStream))
49
+ }
50
+
51
+ // Clone the stream so we can shift without destroying the original reference
52
+ const localStream = [...stream]
53
+
54
+ const firstStep = localStream.shift()
55
+ if (!firstStep || typeof firstStep !== 'object') {
56
+ throw new Error(t(SpecRunner.UI.invalidFirstStep))
57
+ }
58
+
59
+ const appName = Object.keys(firstStep).find((k) => !k.startsWith('$'))
60
+ if (!appName) {
61
+ throw new Error(t(SpecRunner.UI.missingAppName))
62
+ }
63
+
64
+ const ModelClass = /** @type {any} */ (registry[appName])
65
+ if (!ModelClass) {
66
+ throw new Error(t(SpecRunner.UI.appNotFound, { app: appName }))
67
+ }
68
+
69
+ const appData = firstStep[appName] || {}
70
+ const adapter = new SpecAdapter(localStream, { assert: this.#assert })
71
+
72
+ // Create the model, passing our own context so it inherits translations etc
73
+ const model = new ModelClass(appData, this._)
74
+ const generator = typeof model.run === 'function' ? model.run() : null
75
+
76
+ if (!generator || typeof generator.next !== 'function') {
77
+ throw new Error(t(SpecRunner.UI.invalidGenerator, { app: appName }))
78
+ }
79
+
80
+ try {
81
+ yield progress(t(SpecRunner.UI.running, { app: appName }))
82
+ await runGenerator(generator, {
83
+ ask: adapter.ask.bind(adapter),
84
+ show: adapter.show.bind(adapter),
85
+ log: adapter.log.bind(adapter),
86
+ progress: adapter.progress.bind(adapter),
87
+ render: adapter.render.bind(adapter),
88
+ agent: adapter.agent.bind(adapter),
89
+ result: adapter.result.bind(adapter),
90
+ })
91
+ } catch (err) {
92
+ // Bubbling assertion errors correctly
93
+ throw err
94
+ }
95
+
96
+ // The stream must be fully consumed
97
+ if (localStream.length > 0) {
98
+ assert.fail(t(SpecRunner.UI.unhandledSteps, { count: localStream.length }))
99
+ }
100
+
101
+ return result({ success: true, appName })
102
+ }
103
+
104
+ /**
105
+ * Run a Nan0Spec sequence programmatically (for unit tests).
106
+ *
107
+ * @param {Array<object>} stream The .nan0 intent stream array
108
+ * @param {Record<string, any>} registry A registry of Model Classes that can be mounted
109
+ * @param {typeof import('node:assert/strict')} [asserter] Custom assertion library
110
+ */
111
+ static async execute(stream, registry, asserter = assert) {
112
+ const runner = new SpecRunner({ stream, registry }, { assert: asserter })
113
+ const it = runner.run()
114
+ while (true) {
115
+ const { value, done } = await it.next()
116
+ if (done) return value?.data
117
+ }
118
+ }
119
+ }
120
+
121
+ export default SpecRunner
@@ -0,0 +1,46 @@
1
+ /**
2
+ * VisualAdapter (Base)
3
+ *
4
+ * Базовий клас для візуальної трансформації інтенцій OLMUI.
5
+ */
6
+ import { NaN0 } from '@nan0web/types'
7
+
8
+ export class VisualAdapter {
9
+ /**
10
+ * Конвертує одну інтенцію у просте текстове представлення.
11
+ * @param {object} intent - Intent entry from LogicInspector
12
+ * @param {function} [t] - i18n translate function
13
+ * @returns {string} Raw description
14
+ */
15
+ static render(intent, t = (k) => k) {
16
+ let node;
17
+ switch (intent.type) {
18
+ case 'ask':
19
+ node = { ask: { field: intent.field, input: intent.input !== undefined ? intent.input : '...' } }
20
+ break
21
+ case 'progress':
22
+ node = { progress: { message: intent.message || '' } }
23
+ break
24
+ case 'log':
25
+ node = { log: { level: intent.level?.toUpperCase() || 'INFO', message: intent.message } }
26
+ break
27
+ case 'render':
28
+ node = { render: { [intent.component]: intent.props || {} } }
29
+ break
30
+ case 'result': {
31
+ const data = intent.data || {}
32
+ node = { result: (typeof data === 'object' && data !== null && Object.keys(data).length === 0) ? {} : data }
33
+ break
34
+ }
35
+ default:
36
+ node = { [intent.type || 'unknown']: intent }
37
+ break
38
+ }
39
+
40
+ try {
41
+ return NaN0.stringify([node]).trim()
42
+ } catch (e) {
43
+ return `- error: ${JSON.stringify(node)}`
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,7 @@
1
+ export * from './LogicInspector.js'
2
+ export * from './VisualAdapter.js'
3
+ export * from '../domain/app/SnapshotAuditor.js'
4
+ export * from './verifySnapshot.js'
5
+ export { SpecRunner } from './SpecRunner.js'
6
+ export { SpecAdapter } from './SpecAdapter.js'
7
+ export * from './CrashReporter.js'
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Saves a logical JSONL snapshot sequence
3
+ * @param {Object} options
4
+ * @param {string} options.name Snapshot file name (e.g. 'uk/ExploreCatalog.jsonl')
5
+ * @param {Array<Object>} options.data Array of intents to serialize
6
+ * @param {typeof import('node:fs/promises')} [options.fs] Injected filesystem
7
+ * @param {typeof import('node:path')} [options.path] Injected path module
8
+ */
9
+ export async function verifySnapshot({ name, data, fs, path }) {
10
+ if (!fs) fs = await import('node:fs/promises')
11
+ if (!path) path = await import('node:path')
12
+
13
+ const outPath = path.resolve(process.cwd(), 'snapshots/jsonl', name)
14
+ await fs.mkdir(path.dirname(outPath), { recursive: true })
15
+ const content = data.map((i) => JSON.stringify(i)).join('\n')
16
+ await fs.writeFile(outPath, content + '\n')
17
+ }
@@ -1,8 +1,6 @@
1
1
  export class DepsCommand extends UiMessage {
2
2
  static Body: typeof DepsCommandBody;
3
3
  constructor(input?: {});
4
- /** @type {DepsCommandBody} */
5
- body: DepsCommandBody;
6
4
  }
7
5
  export default DepsCommand;
8
6
  import UiMessage from '../../core/Message/Message.js';
@@ -1,6 +1,58 @@
1
- export { User };
2
- declare namespace _default {
1
+ export default Model;
2
+ import User from './User/User.js';
3
+ import { HeaderModel } from '../domain/HeaderModel.js';
4
+ import { FooterModel } from '../domain/FooterModel.js';
5
+ import { HeroModel } from '../domain/HeroModel.js';
6
+ import { ButtonModel } from '../domain/components/index.js';
7
+ import { ConfirmModel } from '../domain/components/index.js';
8
+ import { InputModel } from '../domain/components/index.js';
9
+ import { SpinnerModel } from '../domain/components/index.js';
10
+ import { TableModel } from '../domain/components/index.js';
11
+ import { ToastModel } from '../domain/components/index.js';
12
+ import { SelectModel } from '../domain/components/index.js';
13
+ import { AutocompleteModel } from '../domain/components/index.js';
14
+ import { TreeModel } from '../domain/components/index.js';
15
+ import { TabsModel } from '../domain/components/index.js';
16
+ import { AccordionModel } from '../domain/components/index.js';
17
+ import { GalleryModel } from '../domain/components/index.js';
18
+ import { PriceModel } from '../domain/components/index.js';
19
+ import { PricingModel } from '../domain/components/index.js';
20
+ import { CommentModel } from '../domain/components/index.js';
21
+ import { TestimonialModel } from '../domain/components/index.js';
22
+ import { StatsItemModel } from '../domain/components/index.js';
23
+ import { StatsModel } from '../domain/components/index.js';
24
+ import { TimelineItemModel } from '../domain/components/index.js';
25
+ import { TimelineModel } from '../domain/components/index.js';
26
+ import { EmptyStateModel } from '../domain/components/index.js';
27
+ import { BannerModel } from '../domain/components/index.js';
28
+ import { ProfileDropdownModel } from '../domain/components/index.js';
29
+ declare namespace Model {
3
30
  export { User };
31
+ export { HeaderModel };
32
+ export { FooterModel };
33
+ export { HeroModel };
34
+ export { ButtonModel };
35
+ export { ConfirmModel };
36
+ export { InputModel };
37
+ export { SpinnerModel };
38
+ export { TableModel };
39
+ export { ToastModel };
40
+ export { SelectModel };
41
+ export { AutocompleteModel };
42
+ export { TreeModel };
43
+ export { TabsModel };
44
+ export { AccordionModel };
45
+ export { GalleryModel };
46
+ export { PriceModel };
47
+ export { PricingModel };
48
+ export { CommentModel };
49
+ export { TestimonialModel };
50
+ export { StatsItemModel };
51
+ export { StatsModel };
52
+ export { TimelineItemModel };
53
+ export { TimelineModel };
54
+ export { EmptyStateModel };
55
+ export { BannerModel };
56
+ export { ProfileDropdownModel };
4
57
  }
5
- export default _default;
6
- import User from './User/User.js';
58
+ export { User, HeaderModel, FooterModel, HeroModel, ButtonModel, ConfirmModel, InputModel, SpinnerModel, TableModel, ToastModel, SelectModel, AutocompleteModel, TreeModel, TabsModel, AccordionModel, GalleryModel, PriceModel, PricingModel, CommentModel, TestimonialModel, StatsItemModel, StatsModel, TimelineItemModel, TimelineModel, EmptyStateModel, BannerModel, ProfileDropdownModel };
package/types/StdIn.d.ts CHANGED
@@ -22,10 +22,10 @@ export default class StdIn extends EventProcessor {
22
22
  processor?: Processor | undefined;
23
23
  stream?: UiMessage[] | undefined;
24
24
  });
25
- /** @type {UiMessage[]} Input message buffer */
26
- stream: UiMessage[];
27
25
  /** @type {Processor} Input processor */
28
26
  processor: Processor;
27
+ /** @type {UiMessage[]} Input message buffer */
28
+ stream: UiMessage[];
29
29
  /**
30
30
  * Checks if there are messages waiting in the input stream.
31
31
  * @returns {boolean} True if waiting messages, false otherwise
@@ -56,7 +56,7 @@ export default class StdIn extends EventProcessor {
56
56
  decode(message: UiMessage | string[] | any): UiMessage;
57
57
  }
58
58
  import EventProcessor from '@nan0web/event/oop';
59
- import { UiMessage } from './core/index.js';
60
59
  declare class Processor extends EventProcessor {
61
60
  }
61
+ import { UiMessage } from './core/index.js';
62
62
  export {};
package/types/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { UIApp as default } from "./domain/app/UIApp.js";
@@ -89,9 +89,9 @@ export default class UIForm extends FormMessage {
89
89
  /**
90
90
  * Validates the entire form.
91
91
  *
92
- * @returns {Map<string, string>} Map of validation errors, empty if valid.
92
+ * @returns {any}
93
93
  */
94
- validate(): Map<string, string>;
94
+ validate(): any;
95
95
  /**
96
96
  * Validates a single field.
97
97
  *
@@ -29,9 +29,21 @@ export type AdapterHandlers = {
29
29
  */
30
30
  progress?: ((intent: import("./Intent.js").ProgressIntent) => void | Promise<void>) | undefined;
31
31
  /**
32
- * Handler for 'log' intents. Optional (defaults to no-op).
32
+ * Handler for 'show' intents. Optional (defaults to no-op).
33
+ */
34
+ show?: ((intent: import("./Intent.js").ShowIntent) => void | Promise<void>) | undefined;
35
+ /**
36
+ * Handler for 'log' intents. Optional.
33
37
  */
34
38
  log?: ((intent: import("./Intent.js").LogIntent) => void | Promise<void>) | undefined;
39
+ /**
40
+ * Handler for 'agent' intents (AI Subagents). Optional (fallback to show if not implemented).
41
+ */
42
+ agent?: ((intent: import("./Intent.js").AgentIntent) => Promise<import("./Intent.js").AgentResponse>) | undefined;
43
+ /**
44
+ * Handler for 'render' intents (visual component injection). Optional.
45
+ */
46
+ render?: ((intent: import("./Intent.js").RenderIntent) => void | Promise<void>) | undefined;
35
47
  /**
36
48
  * Handler for the final 'result'. Optional (defaults to no-op).
37
49
  */
@@ -48,4 +60,9 @@ export type RunnerOptions = {
48
60
  * External AbortSignal for cancellation from outside.
49
61
  */
50
62
  signal?: AbortSignal | undefined;
63
+ /**
64
+ * Array where all executed intents will be sequentially recorded.
65
+ * Useful for generating 'crash reports' or Nan0Spec files on failure.
66
+ */
67
+ trace?: import("./Intent.js").Intent[] | undefined;
51
68
  };
@@ -4,7 +4,7 @@
4
4
  * @class InputAdapter
5
5
  * @extends Event
6
6
  */
7
- export default class InputAdapter extends Event {
7
+ export class InputAdapter extends Event {
8
8
  static CancelError: typeof CancelError;
9
9
  /** @returns {typeof CancelError} */
10
10
  get CancelError(): typeof CancelError;
@@ -42,5 +42,6 @@ export default class InputAdapter extends Event {
42
42
  value: string | null;
43
43
  }>;
44
44
  }
45
+ export default InputAdapter;
45
46
  import Event from '@nan0web/event/oop';
46
47
  import CancelError from './Error/CancelError.js';