@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
@@ -12,6 +12,65 @@ export function isModelSchema(schema: any): boolean;
12
12
  * @returns {intent is Intent}
13
13
  */
14
14
  export function validateIntent(intent: any): intent is Intent;
15
+ /**
16
+ * Create an ask intent.
17
+ *
18
+ * Two modes:
19
+ * ask('amount', { help: 'Enter amount', type: 'number' }) → single field
20
+ * ask('transfer', TransferMoneyModel) → full Model form
21
+ *
22
+ * @param {string} field - Field name or form name.
23
+ * @param {object | Function} schema - Field descriptor or Model-as-Schema class.
24
+ * @returns {AskIntent}
25
+ */
26
+ export function ask(field: string, schema: object | Function): AskIntent;
27
+ /**
28
+ * Create a progress intent.
29
+ * @param {string} message - Status message from Model (i18n static field value).
30
+ * @param {number} [value=0] - Progress value (current step or percentage).
31
+ * @param {number|string} [totalOrId] - Absolute total steps (number) OR progress tracking ID (string).
32
+ * @param {string} [id='default'] - Progress ID (if total is provided).
33
+ * @returns {ProgressIntent}
34
+ */
35
+ export function progress(message: string, value?: number, totalOrId?: number | string, id?: string): ProgressIntent;
36
+ export function log(level: any, message: any, data?: {}): {
37
+ type: string;
38
+ level: any;
39
+ message: any;
40
+ };
41
+ /**
42
+ * Create a render intent.
43
+ * @param {string} component - Component name (e.g. 'App.Layout.Header').
44
+ * @param {object} [props] - Static props for the component.
45
+ * @returns {RenderIntent}
46
+ */
47
+ export function render(component: string, props?: object): RenderIntent;
48
+ /**
49
+ * Create a result intent.
50
+ * @param {*} data - The raw result data.
51
+ * @returns {ResultIntent}
52
+ */
53
+ export function result(data: any): ResultIntent;
54
+ /**
55
+ * @typedef {Object} ShowData
56
+ * @property {any} [component]
57
+ * @property {import('@nan0web/types').Model} [model]
58
+ */
59
+ /**
60
+ * Create a show intent.
61
+ * @param {string | any} message Message to display.
62
+ * @param {ShowLevel|ShowData} [level='info'] Level of message or additional data then `level = 'info'`.
63
+ * @param {ShowData} [data={}] Additional data to display.
64
+ * @returns {ShowIntent}
65
+ */
66
+ export function show(message: string | any, level?: ShowLevel | ShowData, data?: ShowData): ShowIntent;
67
+ /**
68
+ * Create an agent intent to delegate a task to an AI subagent.
69
+ * @param {string} task - The instructional task for the AI agent.
70
+ * @param {AgentContext} [context={}] - Contextual data (files, errors, docs).
71
+ * @returns {AgentIntent}
72
+ */
73
+ export function agent(task: string, context?: AgentContext): AgentIntent;
15
74
  /**
16
75
  * @typedef {Object} FieldSchema
17
76
  * @property {string} help - Human-readable label / i18n key.
@@ -36,16 +95,28 @@ export function validateIntent(intent: any): intent is Intent;
36
95
  * @typedef {Object} ProgressIntent
37
96
  * @property {'progress'} type
38
97
  * @property {number} [value] - Progress value (0-1).
39
- * @property {string} [id] - Progress ID for tracking multiple parallel operations.
98
+ * @property {number} [total] - Absolute total (if value is absolute).
99
+ * @property {string} [id] - Progress ID for tracking by Adapter to calculate speed/eta.
40
100
  * @property {string} message - Status message from Model (i18n static field value).
41
101
  */
42
102
  /**
43
- * Model emits a log message. No response expected.
103
+ * @typedef {'info' | 'warn' | 'error' | 'success'} ShowLevel
104
+ */
105
+ /** @typedef {ShowLevel} LogLevel */
106
+ /**
107
+ * Model emits a show message. No response expected.
44
108
  * Message MUST come from the Model (i18n static field value).
109
+ * @typedef {Object} ShowIntent
110
+ * @property {'show'} type
111
+ * @property {ShowLevel} level
112
+ * @property {string} message - Show message from Model (i18n static field value).
113
+ */
114
+ /**
115
+ * Model emits a log message intended for debugging/developer (Not UI).
45
116
  * @typedef {Object} LogIntent
46
117
  * @property {'log'} type
47
- * @property {'info' | 'warn' | 'error' | 'success'} level
48
- * @property {string} message - Log message from Model (i18n static field value).
118
+ * @property {LogLevel} level
119
+ * @property {string} message - Internal log message.
49
120
  */
50
121
  /**
51
122
  * Final return value from the generator.
@@ -53,9 +124,39 @@ export function validateIntent(intent: any): intent is Intent;
53
124
  * @property {'result'} type
54
125
  * @property {*} data - The raw result data (JSON-serializable).
55
126
  */
127
+ /**
128
+ * Model requests rendering of a pure UI component (Header, Footer, Static Map).
129
+ * No response expected from the logic loop.
130
+ * @typedef {Object} RenderIntent
131
+ * @property {'render'} type
132
+ * @property {string} component - Component name (e.g. 'App.Layout.Header').
133
+ * @property {object} props - Static props for the component.
134
+ */
135
+ /**
136
+ * Contextual data and attachments for the AI subagent.
137
+ * @typedef {Object} AgentContext
138
+ * @property {string[]} [instructions] - List of instructions or guidelines (e.g. ['Use 1-char emojis only']).
139
+ * @property {Record<string, string>} [files] - Hash map of file paths to their string contents.
140
+ * @property {Record<string, any>} [data] - Any arbitrary JSON data (e.g. parsed errors, ASTs, metadata) useful for the task.
141
+ */
142
+ /**
143
+ * Model delegates a task to an AI subagent. The Adapter should launch the agent
144
+ * with the provided task and context, and return the result. If the agent is skipped,
145
+ * it returns { success: false } but allows user to generate a prompt.
146
+ * @typedef {Object} AgentIntent
147
+ * @property {'agent'} type
148
+ * @property {string} task - The instructional task for the AI agent.
149
+ * @property {AgentContext} context - Contextual data, files, and instructions for the task.
150
+ * @property {() => string} toPrompt - Helper to format task and context as an LLM prompt.
151
+ */
56
152
  /**
57
153
  * Union of all possible yielded intents.
58
- * @typedef {AskIntent | ProgressIntent | LogIntent} Intent
154
+ * @typedef {(AskIntent | ProgressIntent | LogIntent | ShowIntent | RenderIntent | AgentIntent | ResultIntent) & {
155
+ * $value?: any;
156
+ * $success?: boolean;
157
+ * $files?: Record<string, string>;
158
+ * $message?: string;
159
+ * }} Intent
59
160
  */
60
161
  /**
61
162
  * Response to an AskIntent. Adapter provides the collected value.
@@ -64,6 +165,20 @@ export function validateIntent(intent: any): intent is Intent;
64
165
  * @property {*} value - The value matching schema.type (collected from user / LLM / test fixture).
65
166
  * @property {boolean} [cancelled] - Whether the user cancelled this interaction (e.g. pressed ESC).
66
167
  */
168
+ /**
169
+ * Response to an AgentIntent.
170
+ * The underlying Adapter (Orchestrator) is responsible for communicating with the LLM,
171
+ * enforcing output formats (e.g. Unified Diff or Tool Calls like `updateFile`),
172
+ * and resolving common LLM hallucinations (like Grok truncating code with `// ...`).
173
+ *
174
+ * The Model (e.g. IconsAuditor) receives this clean, resolved response and does not
175
+ * need to parse Markdown or interpret diffs itself.
176
+ *
177
+ * @typedef {Object} AgentResponse
178
+ * @property {boolean} success - True if the agent successfully processed the task.
179
+ * @property {Record<string, string>} [files] - Hash map of fully resolved, updated file contents.
180
+ * @property {string} [message] - Optional summary or explanation returned by the AI.
181
+ */
67
182
  /**
68
183
  * Special response that Adapters can send to abort the generator.
69
184
  *
@@ -80,22 +195,15 @@ export function validateIntent(intent: any): intent is Intent;
80
195
  */
81
196
  /**
82
197
  * Union of all possible responses an Adapter can send back via iterator.next().
83
- * @typedef {AskResponse | AbortResponse | undefined} IntentResponse
198
+ * @typedef {AskResponse | AgentResponse | AbortResponse | undefined} IntentResponse
84
199
  */
85
- export const INTENT_TYPES: readonly ["ask", "progress", "log"];
86
- export function ask(field: string, schema: object | Function): AskIntent;
87
- export function progress(message: any): {
88
- type: string;
89
- message: any;
90
- };
91
- export function log(level: any, message: any, data?: {}): {
92
- type: string;
93
- level: any;
94
- message: any;
95
- };
96
- export function result(data: any): {
97
- type: string;
98
- data: any;
200
+ /**
201
+ * @typedef {'ask' | 'show' | 'progress' | 'render' | 'agent'} IntentType
202
+ */
203
+ export const INTENT_TYPES: readonly ["ask", "progress", "show", "log", "render", "agent"];
204
+ export type ShowData = {
205
+ component?: any;
206
+ model?: import("@nan0web/types").Model | undefined;
99
207
  };
100
208
  export type FieldSchema = {
101
209
  /**
@@ -156,7 +264,11 @@ export type ProgressIntent = {
156
264
  */
157
265
  value?: number | undefined;
158
266
  /**
159
- * - Progress ID for tracking multiple parallel operations.
267
+ * - Absolute total (if value is absolute).
268
+ */
269
+ total?: number | undefined;
270
+ /**
271
+ * - Progress ID for tracking by Adapter to calculate speed/eta.
160
272
  */
161
273
  id?: string | undefined;
162
274
  /**
@@ -164,15 +276,28 @@ export type ProgressIntent = {
164
276
  */
165
277
  message: string;
166
278
  };
279
+ export type ShowLevel = "info" | "warn" | "error" | "success";
280
+ export type LogLevel = ShowLevel;
167
281
  /**
168
- * Model emits a log message. No response expected.
282
+ * Model emits a show message. No response expected.
169
283
  * Message MUST come from the Model (i18n static field value).
170
284
  */
285
+ export type ShowIntent = {
286
+ type: "show";
287
+ level: ShowLevel;
288
+ /**
289
+ * - Show message from Model (i18n static field value).
290
+ */
291
+ message: string;
292
+ };
293
+ /**
294
+ * Model emits a log message intended for debugging/developer (Not UI).
295
+ */
171
296
  export type LogIntent = {
172
297
  type: "log";
173
- level: "info" | "warn" | "error" | "success";
298
+ level: LogLevel;
174
299
  /**
175
- * - Log message from Model (i18n static field value).
300
+ * - Internal log message.
176
301
  */
177
302
  message: string;
178
303
  };
@@ -186,10 +311,67 @@ export type ResultIntent = {
186
311
  */
187
312
  data: any;
188
313
  };
314
+ /**
315
+ * Model requests rendering of a pure UI component (Header, Footer, Static Map).
316
+ * No response expected from the logic loop.
317
+ */
318
+ export type RenderIntent = {
319
+ type: "render";
320
+ /**
321
+ * - Component name (e.g. 'App.Layout.Header').
322
+ */
323
+ component: string;
324
+ /**
325
+ * - Static props for the component.
326
+ */
327
+ props: object;
328
+ };
329
+ /**
330
+ * Contextual data and attachments for the AI subagent.
331
+ */
332
+ export type AgentContext = {
333
+ /**
334
+ * - List of instructions or guidelines (e.g. ['Use 1-char emojis only']).
335
+ */
336
+ instructions?: string[] | undefined;
337
+ /**
338
+ * - Hash map of file paths to their string contents.
339
+ */
340
+ files?: Record<string, string> | undefined;
341
+ /**
342
+ * - Any arbitrary JSON data (e.g. parsed errors, ASTs, metadata) useful for the task.
343
+ */
344
+ data?: Record<string, any> | undefined;
345
+ };
346
+ /**
347
+ * Model delegates a task to an AI subagent. The Adapter should launch the agent
348
+ * with the provided task and context, and return the result. If the agent is skipped,
349
+ * it returns { success: false } but allows user to generate a prompt.
350
+ */
351
+ export type AgentIntent = {
352
+ type: "agent";
353
+ /**
354
+ * - The instructional task for the AI agent.
355
+ */
356
+ task: string;
357
+ /**
358
+ * - Contextual data, files, and instructions for the task.
359
+ */
360
+ context: AgentContext;
361
+ /**
362
+ * - Helper to format task and context as an LLM prompt.
363
+ */
364
+ toPrompt: () => string;
365
+ };
189
366
  /**
190
367
  * Union of all possible yielded intents.
191
368
  */
192
- export type Intent = AskIntent | ProgressIntent | LogIntent;
369
+ export type Intent = (AskIntent | ProgressIntent | LogIntent | ShowIntent | RenderIntent | AgentIntent | ResultIntent) & {
370
+ $value?: any;
371
+ $success?: boolean;
372
+ $files?: Record<string, string>;
373
+ $message?: string;
374
+ };
193
375
  /**
194
376
  * Response to an AskIntent. Adapter provides the collected value.
195
377
  * The value MUST conform to the type described in the requested FieldSchema.
@@ -204,6 +386,29 @@ export type AskResponse = {
204
386
  */
205
387
  cancelled?: boolean | undefined;
206
388
  };
389
+ /**
390
+ * Response to an AgentIntent.
391
+ * The underlying Adapter (Orchestrator) is responsible for communicating with the LLM,
392
+ * enforcing output formats (e.g. Unified Diff or Tool Calls like `updateFile`),
393
+ * and resolving common LLM hallucinations (like Grok truncating code with `// ...`).
394
+ *
395
+ * The Model (e.g. IconsAuditor) receives this clean, resolved response and does not
396
+ * need to parse Markdown or interpret diffs itself.
397
+ */
398
+ export type AgentResponse = {
399
+ /**
400
+ * - True if the agent successfully processed the task.
401
+ */
402
+ success: boolean;
403
+ /**
404
+ * - Hash map of fully resolved, updated file contents.
405
+ */
406
+ files?: Record<string, string> | undefined;
407
+ /**
408
+ * - Optional summary or explanation returned by the AI.
409
+ */
410
+ message?: string | undefined;
411
+ };
207
412
  /**
208
413
  * Special response that Adapters can send to abort the generator.
209
414
  *
@@ -227,4 +432,5 @@ export type AbortResponse = {
227
432
  /**
228
433
  * Union of all possible responses an Adapter can send back via iterator.next().
229
434
  */
230
- export type IntentResponse = AskResponse | AbortResponse | undefined;
435
+ export type IntentResponse = AskResponse | AgentResponse | AbortResponse | undefined;
436
+ export type IntentType = "ask" | "show" | "progress" | "render" | "agent";
@@ -19,6 +19,10 @@ export class IntentErrorModel {
19
19
  help: string;
20
20
  error: string;
21
21
  };
22
+ static render_missing_component: {
23
+ help: string;
24
+ error: string;
25
+ };
22
26
  static adapter_missing_ask: {
23
27
  help: string;
24
28
  error: string;
@@ -61,9 +61,9 @@ export default class UiMessage extends Message {
61
61
  */
62
62
  constructor(input?: any);
63
63
  /** @type {string} */
64
- type: string;
65
- /** @type {string} */
66
64
  id: string;
65
+ /** @type {string} */
66
+ type: string;
67
67
  /**
68
68
  * Validates the message body against its schema.
69
69
  *
@@ -18,8 +18,6 @@ export default class OutputMessage extends UiMessage {
18
18
  * @returns {OutputMessage}
19
19
  */
20
20
  static from(input: any): OutputMessage;
21
- /** @type {string[]} */
22
- body: string[];
23
21
  /** @type {Object} */
24
22
  meta: any;
25
23
  /** @type {Error|null} */
@@ -7,10 +7,11 @@ export { default as UiAdapter } from "./UiAdapter.js";
7
7
  export { IntentErrorModel } from "./IntentErrorModel.js";
8
8
  export { runGenerator } from "./GeneratorRunner.js";
9
9
  export { MaskHandler } from "./MaskHandler.js";
10
+ export { LayoutModel } from "../domain/LayoutModel.js";
10
11
  import UIStream from './Stream.js';
11
12
  import StreamEntry from './StreamEntry.js';
12
13
  import UIForm from './Form/Form.js';
13
14
  export { UIStream, UIStream as UiStream, StreamEntry, StreamEntry as UiStreamEntry, UIForm, UIForm as UiForm };
14
15
  export { default as Error, CancelError } from "./Error/index.js";
15
16
  export { runFlow, flow, View, Prompt, Stream, Alert, Toast, Badge, Text, Table, Input, Select, Confirm, Multiselect, Mask, Password, Spinner, Progress, default as Flow } from "./Flow.js";
16
- export { validateIntent, ask, progress, log, result, INTENT_TYPES, isModelSchema } from "./Intent.js";
17
+ export { validateIntent, ask, progress, log, render, result, INTENT_TYPES, isModelSchema } from "./Intent.js";