nardial 0.2.2__tar.gz → 0.3.2__tar.gz

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 (63) hide show
  1. {nardial-0.2.2/src/nardial.egg-info → nardial-0.3.2}/PKG-INFO +130 -27
  2. nardial-0.2.2/PKG-INFO → nardial-0.3.2/README.md +123 -48
  3. {nardial-0.2.2 → nardial-0.3.2}/pyproject.toml +11 -3
  4. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/authoring/factory.py +14 -0
  5. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/conversation_agent.py +104 -14
  6. nardial-0.3.2/src/nardial/events/__init__.py +11 -0
  7. nardial-0.3.2/src/nardial/events/bus.py +182 -0
  8. nardial-0.3.2/src/nardial/events/types.py +68 -0
  9. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/interaction_orchestrator.py +86 -52
  10. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/mini_dialogs.py +249 -49
  11. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/moves.py +210 -1
  12. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/__init__.py +2 -0
  13. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/device/__init__.py +1 -1
  14. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/nlu/__init__.py +9 -0
  15. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/nlu/dialogflow.py +3 -0
  16. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/nlu/written_keyword.py +3 -0
  17. nardial-0.3.2/src/nardial/providers/screen/__init__.py +126 -0
  18. nardial-0.3.2/src/nardial/providers/screen/null.py +46 -0
  19. nardial-0.3.2/src/nardial/providers/screen/pepper_tablet.py +155 -0
  20. nardial-0.3.2/src/nardial/providers/screen/sic_adapter.py +272 -0
  21. nardial-0.3.2/src/nardial/providers/screen/web/static/screen.css +190 -0
  22. nardial-0.3.2/src/nardial/providers/screen/web/static/screen.js +215 -0
  23. nardial-0.3.2/src/nardial/providers/screen/web/static/socket.io.min.js +7 -0
  24. nardial-0.3.2/src/nardial/providers/screen/web/templates/index.html +32 -0
  25. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/tts/__init__.py +9 -0
  26. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/tts/elevenlabs.py +3 -0
  27. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/tts/google.py +3 -0
  28. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/tts/naoqi.py +3 -0
  29. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/tts/null.py +3 -0
  30. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/session_manager.py +61 -11
  31. nardial-0.2.2/README.md → nardial-0.3.2/src/nardial.egg-info/PKG-INFO +151 -25
  32. {nardial-0.2.2 → nardial-0.3.2}/src/nardial.egg-info/SOURCES.txt +12 -0
  33. {nardial-0.2.2 → nardial-0.3.2}/src/nardial.egg-info/requires.txt +8 -1
  34. {nardial-0.2.2 → nardial-0.3.2}/tests/test_conversation_agent.py +43 -21
  35. nardial-0.3.2/tests/test_event_bus.py +60 -0
  36. {nardial-0.2.2 → nardial-0.3.2}/tests/test_llm.py +35 -22
  37. {nardial-0.2.2 → nardial-0.3.2}/tests/test_mini_dialogs_extra.py +39 -26
  38. {nardial-0.2.2 → nardial-0.3.2}/tests/test_moves.py +28 -19
  39. {nardial-0.2.2 → nardial-0.3.2}/LICENSE +0 -0
  40. {nardial-0.2.2 → nardial-0.3.2}/setup.cfg +0 -0
  41. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/__init__.py +0 -0
  42. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/authoring/__init__.py +0 -0
  43. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/authoring/export_html.py +0 -0
  44. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/authoring/loader.py +0 -0
  45. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/conversation_state.py +0 -0
  46. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/dialog_logic.py +0 -0
  47. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/device/alphamini.py +0 -0
  48. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/device/desktop.py +0 -0
  49. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/device/nao.py +0 -0
  50. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/device/pepper.py +0 -0
  51. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/llm/__init__.py +0 -0
  52. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/llm/echo.py +0 -0
  53. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/llm/openai_gpt.py +0 -0
  54. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/tts/cacher.py +0 -0
  55. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/vector_store/__init__.py +0 -0
  56. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/vector_store/null.py +0 -0
  57. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/vector_store/redis_store.py +0 -0
  58. {nardial-0.2.2 → nardial-0.3.2}/src/nardial/user_model.py +0 -0
  59. {nardial-0.2.2 → nardial-0.3.2}/src/nardial.egg-info/dependency_links.txt +0 -0
  60. {nardial-0.2.2 → nardial-0.3.2}/src/nardial.egg-info/top_level.txt +0 -0
  61. {nardial-0.2.2 → nardial-0.3.2}/tests/test_authoring_factory.py +0 -0
  62. {nardial-0.2.2 → nardial-0.3.2}/tests/test_conversation_state.py +0 -0
  63. {nardial-0.2.2 → nardial-0.3.2}/tests/test_providers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nardial
3
- Version: 0.2.2
3
+ Version: 0.3.2
4
4
  Summary: Nardial Dialog System
5
5
  Author-email: Mike Ligthart <m.e.u.ligthart@vu.nl>
6
6
  Maintainer: Clara Fayyad, Landon Brown, Evelyne Prodescu
@@ -17,15 +17,20 @@ Provides-Extra: dialogflow
17
17
  Requires-Dist: social-interaction-cloud[dialogflow]; extra == "dialogflow"
18
18
  Provides-Extra: openai
19
19
  Requires-Dist: social-interaction-cloud[openai-gpt]; extra == "openai"
20
+ Provides-Extra: webserver
21
+ Requires-Dist: social-interaction-cloud[webserver]; extra == "webserver"
20
22
  Provides-Extra: all
21
- Requires-Dist: nardial[dialogflow,elevenlabs,google-tts,openai]; extra == "all"
23
+ Requires-Dist: nardial[dialogflow,elevenlabs,google-tts,openai,webserver]; extra == "all"
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest; extra == "dev"
26
+ Requires-Dist: pytest-asyncio; extra == "dev"
22
27
  Dynamic: license-file
23
28
 
24
29
  # NarDialPy
25
30
 
26
31
  **NarDialPy** is a Python package for building and running **narrative-driven, structured dialog systems** — designed for social robots and conversational agents.
27
32
 
28
- It lets you author complete conversations declaratively in JSON, then drive them from Python using voice, NLU, and LLM services. The package handles session flow, branching logic, topic tracking, and personalization so you can focus on what the robot says and how conversations unfold.
33
+ It lets you author complete conversations declaratively in JSON, then drive them from Python using voice, NLU, LLM, and browser-based screen services. The package handles session flow, branching logic, topic tracking, personalization, and screen output so you can focus on what the robot says and how conversations unfold.
29
34
 
30
35
  ---
31
36
 
@@ -53,6 +58,7 @@ The `nardial` package provides the building blocks for authoring and executing m
53
58
  | **Dialog JSON** | Conversations are written as structured JSON files. Each file holds one or more *dialogs*, each containing a sequence of *moves* that the robot performs. |
54
59
  | **Session Manager** | Loads your dialog JSON, resolves a session agenda, and runs dialogs in order — checking dependencies and tracking state. |
55
60
  | **ConversationAgent** | The runtime bridge to the hardware: it calls TTS, STT, LLM, and motion services on your chosen device. |
61
+ | **Screen Provider** | Optional browser-based display layer for transcripts, images, videos, HTML, buttons, and web input. |
56
62
  | **Dialog Logic** | Checks eligibility rules (dependencies, variable requirements) before executing each dialog. |
57
63
 
58
64
  Typical use case:
@@ -165,6 +171,7 @@ NarDialPy is built around a set of provider protocols. Each protocol defines a r
165
171
  | | `WrittenKeywordNLUProvider` | `nardial.providers.nlu.written_keyword` | base (keyboard input) |
166
172
  | **LLM** | `OpenAIGPTProvider` | `nardial.providers.llm.openai_gpt` | `nardial[openai]` |
167
173
  | | `EchoLLMProvider` | `nardial.providers.llm.echo` | base (echoes user input) |
174
+ | **Screen** | `ScreenProvider` / `SICScreenAdapter` / `PepperTabletScreenAdapter` | `nardial.providers.screen` | browser display via SIC webserver |
168
175
  | **Vector store** | `RedisVectorStoreProvider` | `nardial.providers.vector_store.redis_store` | base + running Redis |
169
176
  | | `NullVectorStoreProvider` | `nardial.providers.vector_store.null` | base |
170
177
 
@@ -351,7 +358,7 @@ Utility dialogs for session management — greetings, farewells, and structural
351
358
  {
352
359
  "type": "ask_open",
353
360
  "text": "Please tell me your name.",
354
- "set_variable": "first_name",
361
+ "set_variable": "first_name"
355
362
  }
356
363
  ]
357
364
  }
@@ -366,7 +373,7 @@ Short, theme-based conversations on everyday topics. Chitchat dialogs can be see
366
373
  | Extra field | Type | Required | Description |
367
374
  |---|---|---|---|
368
375
  | `theme` | string | ✅ | Broad category (e.g. `"nature"`, `"animals"`, `"robots"`) |
369
- | `topics` | array of strings | | Specific keywords used for relevance matching |
376
+ | `topics` | array of strings | | Specific keywords used to drive relevance matching |
370
377
 
371
378
  ```json
372
379
  {
@@ -501,7 +508,7 @@ Asks a free-text question and listens for any spoken reply. The answer can be st
501
508
  "type": "ask_open",
502
509
  "text": "What is your favorite color?",
503
510
  "set_variable": "favorite_color",
504
- "add_interest_from_answer": true,
511
+ "add_interest_from_answer": true
505
512
  }
506
513
  ```
507
514
 
@@ -675,29 +682,125 @@ Triggers a named animation behavior on the robot.
675
682
 
676
683
  ---
677
684
 
685
+ #### `timed_wait`
686
+
687
+ Pause execution for a fixed duration before proceeding to the next move. Useful to add natural pauses or give the user time to look at the screen.
688
+
689
+ | Field | Type | Required | Description |
690
+ |---|---|---|---|
691
+ | `type` | string | ✅ | `"timed_wait"` |
692
+ | `duration_seconds` | number | ✅ | Seconds to wait. (Alias: `duration` is also accepted.) |
693
+
694
+ ```json
695
+ { "type": "timed_wait", "duration_seconds": 2.5 }
696
+ ```
697
+
698
+ ---
699
+
700
+ #### `wait_for_web_input`
701
+
702
+ Suspend dialog execution until a matching web input event arrives or until a timeout elapses. The web UI can present buttons or a short input and emit `web_input` events which this move listens for.
703
+
704
+ | Field | Type | Required | Description |
705
+ |---|---|---|---|
706
+ | `type` | string | ✅ | `"wait_for_web_input"` |
707
+ | `prompt` | string | | Hint text shown in the web UI (not spoken) |
708
+ | `options` | array of strings | | Accepted `value` strings from the web event (if omitted, any value is accepted) |
709
+ | `timeout` | number | | Seconds to wait before falling back (omit for indefinite wait) |
710
+ | `outcomes` | object | | Maps option value → outcome label for branching |
711
+ | `default_outcome` | string | | Outcome used on timeout or when no event matches |
712
+
713
+ ```json
714
+ {
715
+ "type": "wait_for_web_input",
716
+ "prompt": "Choose a sticker to show",
717
+ "options": ["smile","thumbs","surprised"],
718
+ "timeout": 15,
719
+ "outcomes": {"smile": "picked_smile"},
720
+ "default_outcome": "no_choice"
721
+ }
722
+ ```
723
+
724
+ ---
725
+
726
+ #### `show_image`
727
+
728
+ Display an image on the connected screen (browser / tablet). Accepts a local path relative to the static assets directory or a full URL.
729
+
730
+ | Field | Type | Required | Description |
731
+ |---|---|---|---|
732
+ | `type` | string | ✅ | `"show_image"` |
733
+ | `src` | string | ✅ | Path or URL to the image (aliases: `image`, `path`) |
734
+
735
+ ```json
736
+ { "type": "show_image", "src": "assets/images/robot_pet.png" }
737
+ ```
738
+
739
+ ---
740
+
741
+ #### `show_video`
742
+
743
+ Display a video on the screen. Can accept a local file path or an embeddable URL (e.g. a YouTube embed link).
744
+
745
+ | Field | Type | Required | Description |
746
+ |---|---|---|---|
747
+ | `type` | string | ✅ | `"show_video"` |
748
+ | `src` | string | ✅ | Video file path or embeddable URL (aliases: `video`, `path`) |
749
+
750
+ ```json
751
+ { "type": "show_video", "src": "https://www.youtube.com/embed/VIDEO_ID" }
752
+ ```
753
+
754
+ ---
755
+
756
+ #### `show_iframe`
757
+
758
+ Embed an external web page inside an iframe on the screen. Use this for interactive web content served from a trusted origin.
759
+
760
+ | Field | Type | Required | Description |
761
+ |---|---|---|---|
762
+ | `type` | string | ✅ | `"show_iframe"` |
763
+ | `url` | string | ✅ | URL to embed (aliases: `src`, `iframe_url`) |
764
+
765
+ ```json
766
+ { "type": "show_iframe", "url": "https://example.com/mini-game" }
767
+ ```
768
+
769
+ ---
770
+
771
+ #### `show_html`
772
+
773
+ Render a raw HTML snippet directly into the display area. The frontend inserts this via innerHTML — treat content as trusted and avoid injecting untrusted user data.
774
+
775
+ | Field | Type | Required | Description |
776
+ |---|---|---|---|
777
+ | `type` | string | ✅ | `"show_html"` |
778
+ | `html` | string | ✅ | HTML snippet to render |
779
+
780
+ ```json
781
+ { "type": "show_html", "html": "<div class=\"card\">Hi there!</div>" }
782
+ ```
783
+
784
+ ---
785
+
786
+ #### `black_screen`
787
+
788
+ Clear the display (show a blank/black screen). No parameters — the next display move will restore content.
789
+
790
+ | Field | Type | Required | Description |
791
+ |---|---|---|---|
792
+ | `type` | string | ✅ | `"black_screen"` |
793
+
794
+ ```json
795
+ { "type": "black_screen" }
796
+ ```
797
+
798
+ ---
799
+
678
800
  ### Key JSON Attributes
679
801
 
680
802
  | Attribute | Where used | Description |
681
803
  |---|---|---|
682
- | `id` | dialog | Unique dialog identifier |
683
- | `type` | dialog | Dialog type: `functional`, `chitchat`, `narrative`, `llm_based` |
684
- | `functional_type` | functional dialog | `"greeting"` or `"farewell"` |
685
- | `thread` | narrative dialog | Story thread name |
686
- | `position` | narrative dialog | Order within the thread |
687
- | `theme` | chitchat dialog | Broad topic category |
688
- | `topics` | chitchat dialog | Keywords for relevance matching |
689
- | `prompt` | llm_based dialog / `ask_llm` | LLM system prompt |
690
- | `moves` | dialog | Ordered list of move objects |
691
- | `dependencies` | dialog | Dialog IDs that must be completed first |
692
- | `variable_dependencies` | dialog | Variables that must exist in the user model |
693
- | `set_variable` | move | Saves the user's answer into the user model |
694
- | `outcomes` | move | Maps answers/intents to outcome labels for branching |
695
- | `default_outcome` | move | Fallback outcome when no match is found |
696
- | `add_interest` | `ask_yesno` move | Adds a fixed topic when user says yes |
697
- | `add_interest_from_answer` | `ask_open` move | Adds the spoken answer as a topic of interest |
698
- | `add_interest_from_variable` | `ask_open` / `ask_options` move | Adds the stored variable's value as a topic |
699
- | `llm_followup` | ask moves | System prompt for an inline LLM follow-up response |
700
- | `%variable%` | `text` values | Placeholder replaced at runtime with the stored variable value |
701
804
 
702
805
  ---
703
806
 
@@ -708,6 +811,8 @@ All you need is a minimal Python script that wires up the device, loads the dial
708
811
  Two ready-to-run demos are included in the `examples/` directory:
709
812
  * Demo 1 — General Conversation (`demo_general_conversation.py`): A simple four-step conversation using a mix of narrative and functional dialogs
710
813
  * Demo 2 — Structured Conversation (`demo_structured_conversation.py`): A more complete example that demonstrates all dialog types and move types, including `ask_llm`, `play`, `motion_sequence`, and `animation`
814
+ * Demo 3 — Screen Display (`demo_screen_provider.py`): Shows the browser-based screen UI with transcripts, images, iframes, HTML snippets, buttons, and text input
815
+ * Demo 4 — Pepper Tablet (`demo_pepper_tablet.py`): Uses the same screen UI on Pepper's tablet through the SIC webserver
711
816
 
712
817
  You can find additional demos in the [SIC Applications repository](https://github.com/Social-AI-VU/sic_applications/tree/main/demos/nardial)
713
818
 
@@ -720,5 +825,3 @@ Run tests from the repository root:
720
825
  ```bash
721
826
  python -m pytest -q
722
827
  ```
723
-
724
- ---
@@ -1,31 +1,8 @@
1
- Metadata-Version: 2.4
2
- Name: nardial
3
- Version: 0.2.2
4
- Summary: Nardial Dialog System
5
- Author-email: Mike Ligthart <m.e.u.ligthart@vu.nl>
6
- Maintainer: Clara Fayyad, Landon Brown, Evelyne Prodescu
7
- License-Expression: AGPL-3.0-only
8
- Requires-Python: >=3.12
9
- Description-Content-Type: text/markdown
10
- License-File: LICENSE
11
- Requires-Dist: social-interaction-cloud
12
- Provides-Extra: google-tts
13
- Requires-Dist: social-interaction-cloud[google-tts]; extra == "google-tts"
14
- Provides-Extra: elevenlabs
15
- Requires-Dist: social-interaction-cloud[elevenlabs-tts]; extra == "elevenlabs"
16
- Provides-Extra: dialogflow
17
- Requires-Dist: social-interaction-cloud[dialogflow]; extra == "dialogflow"
18
- Provides-Extra: openai
19
- Requires-Dist: social-interaction-cloud[openai-gpt]; extra == "openai"
20
- Provides-Extra: all
21
- Requires-Dist: nardial[dialogflow,elevenlabs,google-tts,openai]; extra == "all"
22
- Dynamic: license-file
23
-
24
1
  # NarDialPy
25
2
 
26
3
  **NarDialPy** is a Python package for building and running **narrative-driven, structured dialog systems** — designed for social robots and conversational agents.
27
4
 
28
- It lets you author complete conversations declaratively in JSON, then drive them from Python using voice, NLU, and LLM services. The package handles session flow, branching logic, topic tracking, and personalization so you can focus on what the robot says and how conversations unfold.
5
+ It lets you author complete conversations declaratively in JSON, then drive them from Python using voice, NLU, LLM, and browser-based screen services. The package handles session flow, branching logic, topic tracking, personalization, and screen output so you can focus on what the robot says and how conversations unfold.
29
6
 
30
7
  ---
31
8
 
@@ -53,6 +30,7 @@ The `nardial` package provides the building blocks for authoring and executing m
53
30
  | **Dialog JSON** | Conversations are written as structured JSON files. Each file holds one or more *dialogs*, each containing a sequence of *moves* that the robot performs. |
54
31
  | **Session Manager** | Loads your dialog JSON, resolves a session agenda, and runs dialogs in order — checking dependencies and tracking state. |
55
32
  | **ConversationAgent** | The runtime bridge to the hardware: it calls TTS, STT, LLM, and motion services on your chosen device. |
33
+ | **Screen Provider** | Optional browser-based display layer for transcripts, images, videos, HTML, buttons, and web input. |
56
34
  | **Dialog Logic** | Checks eligibility rules (dependencies, variable requirements) before executing each dialog. |
57
35
 
58
36
  Typical use case:
@@ -165,6 +143,7 @@ NarDialPy is built around a set of provider protocols. Each protocol defines a r
165
143
  | | `WrittenKeywordNLUProvider` | `nardial.providers.nlu.written_keyword` | base (keyboard input) |
166
144
  | **LLM** | `OpenAIGPTProvider` | `nardial.providers.llm.openai_gpt` | `nardial[openai]` |
167
145
  | | `EchoLLMProvider` | `nardial.providers.llm.echo` | base (echoes user input) |
146
+ | **Screen** | `ScreenProvider` / `SICScreenAdapter` / `PepperTabletScreenAdapter` | `nardial.providers.screen` | browser display via SIC webserver |
168
147
  | **Vector store** | `RedisVectorStoreProvider` | `nardial.providers.vector_store.redis_store` | base + running Redis |
169
148
  | | `NullVectorStoreProvider` | `nardial.providers.vector_store.null` | base |
170
149
 
@@ -351,7 +330,7 @@ Utility dialogs for session management — greetings, farewells, and structural
351
330
  {
352
331
  "type": "ask_open",
353
332
  "text": "Please tell me your name.",
354
- "set_variable": "first_name",
333
+ "set_variable": "first_name"
355
334
  }
356
335
  ]
357
336
  }
@@ -366,7 +345,7 @@ Short, theme-based conversations on everyday topics. Chitchat dialogs can be see
366
345
  | Extra field | Type | Required | Description |
367
346
  |---|---|---|---|
368
347
  | `theme` | string | ✅ | Broad category (e.g. `"nature"`, `"animals"`, `"robots"`) |
369
- | `topics` | array of strings | | Specific keywords used for relevance matching |
348
+ | `topics` | array of strings | | Specific keywords used to drive relevance matching |
370
349
 
371
350
  ```json
372
351
  {
@@ -501,7 +480,7 @@ Asks a free-text question and listens for any spoken reply. The answer can be st
501
480
  "type": "ask_open",
502
481
  "text": "What is your favorite color?",
503
482
  "set_variable": "favorite_color",
504
- "add_interest_from_answer": true,
483
+ "add_interest_from_answer": true
505
484
  }
506
485
  ```
507
486
 
@@ -675,29 +654,125 @@ Triggers a named animation behavior on the robot.
675
654
 
676
655
  ---
677
656
 
657
+ #### `timed_wait`
658
+
659
+ Pause execution for a fixed duration before proceeding to the next move. Useful to add natural pauses or give the user time to look at the screen.
660
+
661
+ | Field | Type | Required | Description |
662
+ |---|---|---|---|
663
+ | `type` | string | ✅ | `"timed_wait"` |
664
+ | `duration_seconds` | number | ✅ | Seconds to wait. (Alias: `duration` is also accepted.) |
665
+
666
+ ```json
667
+ { "type": "timed_wait", "duration_seconds": 2.5 }
668
+ ```
669
+
670
+ ---
671
+
672
+ #### `wait_for_web_input`
673
+
674
+ Suspend dialog execution until a matching web input event arrives or until a timeout elapses. The web UI can present buttons or a short input and emit `web_input` events which this move listens for.
675
+
676
+ | Field | Type | Required | Description |
677
+ |---|---|---|---|
678
+ | `type` | string | ✅ | `"wait_for_web_input"` |
679
+ | `prompt` | string | | Hint text shown in the web UI (not spoken) |
680
+ | `options` | array of strings | | Accepted `value` strings from the web event (if omitted, any value is accepted) |
681
+ | `timeout` | number | | Seconds to wait before falling back (omit for indefinite wait) |
682
+ | `outcomes` | object | | Maps option value → outcome label for branching |
683
+ | `default_outcome` | string | | Outcome used on timeout or when no event matches |
684
+
685
+ ```json
686
+ {
687
+ "type": "wait_for_web_input",
688
+ "prompt": "Choose a sticker to show",
689
+ "options": ["smile","thumbs","surprised"],
690
+ "timeout": 15,
691
+ "outcomes": {"smile": "picked_smile"},
692
+ "default_outcome": "no_choice"
693
+ }
694
+ ```
695
+
696
+ ---
697
+
698
+ #### `show_image`
699
+
700
+ Display an image on the connected screen (browser / tablet). Accepts a local path relative to the static assets directory or a full URL.
701
+
702
+ | Field | Type | Required | Description |
703
+ |---|---|---|---|
704
+ | `type` | string | ✅ | `"show_image"` |
705
+ | `src` | string | ✅ | Path or URL to the image (aliases: `image`, `path`) |
706
+
707
+ ```json
708
+ { "type": "show_image", "src": "assets/images/robot_pet.png" }
709
+ ```
710
+
711
+ ---
712
+
713
+ #### `show_video`
714
+
715
+ Display a video on the screen. Can accept a local file path or an embeddable URL (e.g. a YouTube embed link).
716
+
717
+ | Field | Type | Required | Description |
718
+ |---|---|---|---|
719
+ | `type` | string | ✅ | `"show_video"` |
720
+ | `src` | string | ✅ | Video file path or embeddable URL (aliases: `video`, `path`) |
721
+
722
+ ```json
723
+ { "type": "show_video", "src": "https://www.youtube.com/embed/VIDEO_ID" }
724
+ ```
725
+
726
+ ---
727
+
728
+ #### `show_iframe`
729
+
730
+ Embed an external web page inside an iframe on the screen. Use this for interactive web content served from a trusted origin.
731
+
732
+ | Field | Type | Required | Description |
733
+ |---|---|---|---|
734
+ | `type` | string | ✅ | `"show_iframe"` |
735
+ | `url` | string | ✅ | URL to embed (aliases: `src`, `iframe_url`) |
736
+
737
+ ```json
738
+ { "type": "show_iframe", "url": "https://example.com/mini-game" }
739
+ ```
740
+
741
+ ---
742
+
743
+ #### `show_html`
744
+
745
+ Render a raw HTML snippet directly into the display area. The frontend inserts this via innerHTML — treat content as trusted and avoid injecting untrusted user data.
746
+
747
+ | Field | Type | Required | Description |
748
+ |---|---|---|---|
749
+ | `type` | string | ✅ | `"show_html"` |
750
+ | `html` | string | ✅ | HTML snippet to render |
751
+
752
+ ```json
753
+ { "type": "show_html", "html": "<div class=\"card\">Hi there!</div>" }
754
+ ```
755
+
756
+ ---
757
+
758
+ #### `black_screen`
759
+
760
+ Clear the display (show a blank/black screen). No parameters — the next display move will restore content.
761
+
762
+ | Field | Type | Required | Description |
763
+ |---|---|---|---|
764
+ | `type` | string | ✅ | `"black_screen"` |
765
+
766
+ ```json
767
+ { "type": "black_screen" }
768
+ ```
769
+
770
+ ---
771
+
678
772
  ### Key JSON Attributes
679
773
 
680
774
  | Attribute | Where used | Description |
681
775
  |---|---|---|
682
- | `id` | dialog | Unique dialog identifier |
683
- | `type` | dialog | Dialog type: `functional`, `chitchat`, `narrative`, `llm_based` |
684
- | `functional_type` | functional dialog | `"greeting"` or `"farewell"` |
685
- | `thread` | narrative dialog | Story thread name |
686
- | `position` | narrative dialog | Order within the thread |
687
- | `theme` | chitchat dialog | Broad topic category |
688
- | `topics` | chitchat dialog | Keywords for relevance matching |
689
- | `prompt` | llm_based dialog / `ask_llm` | LLM system prompt |
690
- | `moves` | dialog | Ordered list of move objects |
691
- | `dependencies` | dialog | Dialog IDs that must be completed first |
692
- | `variable_dependencies` | dialog | Variables that must exist in the user model |
693
- | `set_variable` | move | Saves the user's answer into the user model |
694
- | `outcomes` | move | Maps answers/intents to outcome labels for branching |
695
- | `default_outcome` | move | Fallback outcome when no match is found |
696
- | `add_interest` | `ask_yesno` move | Adds a fixed topic when user says yes |
697
- | `add_interest_from_answer` | `ask_open` move | Adds the spoken answer as a topic of interest |
698
- | `add_interest_from_variable` | `ask_open` / `ask_options` move | Adds the stored variable's value as a topic |
699
- | `llm_followup` | ask moves | System prompt for an inline LLM follow-up response |
700
- | `%variable%` | `text` values | Placeholder replaced at runtime with the stored variable value |
701
776
 
702
777
  ---
703
778
 
@@ -708,6 +783,8 @@ All you need is a minimal Python script that wires up the device, loads the dial
708
783
  Two ready-to-run demos are included in the `examples/` directory:
709
784
  * Demo 1 — General Conversation (`demo_general_conversation.py`): A simple four-step conversation using a mix of narrative and functional dialogs
710
785
  * Demo 2 — Structured Conversation (`demo_structured_conversation.py`): A more complete example that demonstrates all dialog types and move types, including `ask_llm`, `play`, `motion_sequence`, and `animation`
786
+ * Demo 3 — Screen Display (`demo_screen_provider.py`): Shows the browser-based screen UI with transcripts, images, iframes, HTML snippets, buttons, and text input
787
+ * Demo 4 — Pepper Tablet (`demo_pepper_tablet.py`): Uses the same screen UI on Pepper's tablet through the SIC webserver
711
788
 
712
789
  You can find additional demos in the [SIC Applications repository](https://github.com/Social-AI-VU/sic_applications/tree/main/demos/nardial)
713
790
 
@@ -720,5 +797,3 @@ Run tests from the repository root:
720
797
  ```bash
721
798
  python -m pytest -q
722
799
  ```
723
-
724
- ---
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "nardial"
7
- version = "0.2.2"
7
+ version = "0.3.2"
8
8
  description = "Nardial Dialog System"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -28,8 +28,13 @@ dependencies = [
28
28
  google-tts = ["social-interaction-cloud[google-tts]"]
29
29
  elevenlabs = ["social-interaction-cloud[elevenlabs-tts]"]
30
30
  dialogflow = ["social-interaction-cloud[dialogflow]"]
31
- openai = ["social-interaction-cloud[openai-gpt]"]
32
- all = ["nardial[google-tts,elevenlabs,dialogflow,openai]"]
31
+ openai = ["social-interaction-cloud[openai-gpt]"]
32
+ webserver = ["social-interaction-cloud[webserver]"]
33
+ all = ["nardial[google-tts,elevenlabs,dialogflow,openai,webserver]"]
34
+ dev = ["pytest", "pytest-asyncio"]
35
+
36
+ [tool.pytest.ini_options]
37
+ asyncio_mode = "auto"
33
38
 
34
39
  [tool.setuptools]
35
40
  package-dir = {"" = "src"}
@@ -37,3 +42,6 @@ license-files = ["LICENSE"]
37
42
 
38
43
  [tool.setuptools.packages.find]
39
44
  where = ["src"]
45
+
46
+ [tool.setuptools.package-data]
47
+ "nardial.providers.screen" = ["web/templates/*.html", "web/static/*.css", "web/static/*.js"]
@@ -11,6 +11,13 @@ from nardial.moves import (
11
11
  MOVE_MOTION_SEQUENCE,
12
12
  MOVE_ANIMATION,
13
13
  MOVE_BRANCH,
14
+ MOVE_TIMED_WAIT,
15
+ MOVE_WAIT_FOR_WEB_INPUT,
16
+ MOVE_SHOW_IMAGE,
17
+ MOVE_SHOW_VIDEO,
18
+ MOVE_SHOW_IFRAME,
19
+ MOVE_SHOW_HTML,
20
+ MOVE_BLACK_SCREEN,
14
21
  )
15
22
 
16
23
 
@@ -24,6 +31,13 @@ ALLOWED_MOVE_TYPES = {
24
31
  MOVE_MOTION_SEQUENCE,
25
32
  MOVE_ANIMATION,
26
33
  MOVE_BRANCH,
34
+ MOVE_TIMED_WAIT,
35
+ MOVE_WAIT_FOR_WEB_INPUT,
36
+ MOVE_SHOW_IMAGE,
37
+ MOVE_SHOW_VIDEO,
38
+ MOVE_SHOW_IFRAME,
39
+ MOVE_SHOW_HTML,
40
+ MOVE_BLACK_SCREEN,
27
41
  }
28
42
 
29
43