#
tokens: 46908/50000 3/1784 files (page 93/145)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 93 of 145. Use http://codebase.md/microsoft/semanticworkbench?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .devcontainer
│   ├── .vscode
│   │   └── settings.json
│   ├── devcontainer.json
│   ├── OPTIMIZING_FOR_CODESPACES.md
│   ├── POST_SETUP_README.md
│   └── README.md
├── .dockerignore
├── .gitattributes
├── .github
│   ├── policheck.yml
│   └── workflows
│       ├── assistants-codespace-assistant.yml
│       ├── assistants-document-assistant.yml
│       ├── assistants-explorer-assistant.yml
│       ├── assistants-guided-conversation-assistant.yml
│       ├── assistants-knowledge-transfer-assistant.yml
│       ├── assistants-navigator-assistant.yml
│       ├── assistants-project-assistant.yml
│       ├── assistants-prospector-assistant.yml
│       ├── assistants-skill-assistant.yml
│       ├── libraries.yml
│       ├── mcp-server-giphy.yml
│       ├── mcp-server-memory-filesystem-edit.yml
│       ├── mcp-server-memory-user-bio.yml
│       ├── mcp-server-memory-whiteboard.yml
│       ├── mcp-server-open-deep-research-clone.yml
│       ├── mcp-server-web-research.yml
│       ├── workbench-app.yml
│       └── workbench-service.yml
├── .gitignore
├── .multi-root-tools
│   ├── Makefile
│   └── README.md
├── .vscode
│   ├── extensions.json
│   ├── launch.json
│   └── settings.json
├── ai_context
│   └── generated
│       ├── ASPIRE_ORCHESTRATOR.md
│       ├── ASSISTANT_CODESPACE.md
│       ├── ASSISTANT_DOCUMENT.md
│       ├── ASSISTANT_NAVIGATOR.md
│       ├── ASSISTANT_PROJECT.md
│       ├── ASSISTANT_PROSPECTOR.md
│       ├── ASSISTANTS_OTHER.md
│       ├── ASSISTANTS_OVERVIEW.md
│       ├── CONFIGURATION.md
│       ├── DOTNET_LIBRARIES.md
│       ├── EXAMPLES.md
│       ├── MCP_SERVERS.md
│       ├── PYTHON_LIBRARIES_AI_CLIENTS.md
│       ├── PYTHON_LIBRARIES_CORE.md
│       ├── PYTHON_LIBRARIES_EXTENSIONS.md
│       ├── PYTHON_LIBRARIES_SKILLS.md
│       ├── PYTHON_LIBRARIES_SPECIALIZED.md
│       ├── TOOLS.md
│       ├── WORKBENCH_FRONTEND.md
│       └── WORKBENCH_SERVICE.md
├── aspire-orchestrator
│   ├── .editorconfig
│   ├── Aspire.AppHost
│   │   ├── .gitignore
│   │   ├── appsettings.json
│   │   ├── Aspire.AppHost.csproj
│   │   ├── Program.cs
│   │   └── Properties
│   │       └── launchSettings.json
│   ├── Aspire.Extensions
│   │   ├── Aspire.Extensions.csproj
│   │   ├── Dashboard.cs
│   │   ├── DockerFileExtensions.cs
│   │   ├── PathNormalizer.cs
│   │   ├── UvAppHostingExtensions.cs
│   │   ├── UvAppResource.cs
│   │   ├── VirtualEnvironment.cs
│   │   └── WorkbenchServiceHostingExtensions.cs
│   ├── Aspire.ServiceDefaults
│   │   ├── Aspire.ServiceDefaults.csproj
│   │   └── Extensions.cs
│   ├── README.md
│   ├── run.sh
│   ├── SemanticWorkbench.Aspire.sln
│   └── SemanticWorkbench.Aspire.sln.DotSettings
├── assistants
│   ├── codespace-assistant
│   │   ├── .claude
│   │   │   └── settings.local.json
│   │   ├── .env.example
│   │   ├── .vscode
│   │   │   ├── extensions.json
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── assistant
│   │   │   ├── __init__.py
│   │   │   ├── assets
│   │   │   │   ├── icon_context_transfer.svg
│   │   │   │   └── icon.svg
│   │   │   ├── chat.py
│   │   │   ├── config.py
│   │   │   ├── helpers.py
│   │   │   ├── response
│   │   │   │   ├── __init__.py
│   │   │   │   ├── completion_handler.py
│   │   │   │   ├── models.py
│   │   │   │   ├── request_builder.py
│   │   │   │   ├── response.py
│   │   │   │   ├── step_handler.py
│   │   │   │   └── utils
│   │   │   │       ├── __init__.py
│   │   │   │       ├── abbreviations.py
│   │   │   │       ├── formatting_utils.py
│   │   │   │       ├── message_utils.py
│   │   │   │       └── openai_utils.py
│   │   │   ├── text_includes
│   │   │   │   ├── card_content_context_transfer.md
│   │   │   │   ├── card_content.md
│   │   │   │   ├── codespace_assistant_info.md
│   │   │   │   ├── context_transfer_assistant_info.md
│   │   │   │   ├── guardrails_prompt.txt
│   │   │   │   ├── guidance_prompt_context_transfer.txt
│   │   │   │   ├── guidance_prompt.txt
│   │   │   │   ├── instruction_prompt_context_transfer.txt
│   │   │   │   └── instruction_prompt.txt
│   │   │   └── whiteboard
│   │   │       ├── __init__.py
│   │   │       ├── _inspector.py
│   │   │       └── _whiteboard.py
│   │   ├── assistant.code-workspace
│   │   ├── Makefile
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   └── uv.lock
│   ├── document-assistant
│   │   ├── .env.example
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── assistant
│   │   │   ├── __init__.py
│   │   │   ├── assets
│   │   │   │   └── icon.svg
│   │   │   ├── chat.py
│   │   │   ├── config.py
│   │   │   ├── context_management
│   │   │   │   ├── __init__.py
│   │   │   │   └── inspector.py
│   │   │   ├── filesystem
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _convert.py
│   │   │   │   ├── _file_sources.py
│   │   │   │   ├── _filesystem.py
│   │   │   │   ├── _inspector.py
│   │   │   │   ├── _model.py
│   │   │   │   ├── _prompts.py
│   │   │   │   └── _tasks.py
│   │   │   ├── guidance
│   │   │   │   ├── __init__.py
│   │   │   │   ├── dynamic_ui_inspector.py
│   │   │   │   ├── guidance_config.py
│   │   │   │   ├── guidance_prompts.py
│   │   │   │   └── README.md
│   │   │   ├── response
│   │   │   │   ├── __init__.py
│   │   │   │   ├── completion_handler.py
│   │   │   │   ├── models.py
│   │   │   │   ├── prompts.py
│   │   │   │   ├── responder.py
│   │   │   │   └── utils
│   │   │   │       ├── __init__.py
│   │   │   │       ├── formatting_utils.py
│   │   │   │       ├── message_utils.py
│   │   │   │       ├── openai_utils.py
│   │   │   │       ├── tokens_tiktoken.py
│   │   │   │       └── workbench_messages.py
│   │   │   ├── text_includes
│   │   │   │   └── document_assistant_info.md
│   │   │   ├── types.py
│   │   │   └── whiteboard
│   │   │       ├── __init__.py
│   │   │       ├── _inspector.py
│   │   │       └── _whiteboard.py
│   │   ├── assistant.code-workspace
│   │   ├── CLAUDE.md
│   │   ├── Makefile
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── test_convert.py
│   │   │   └── test_data
│   │   │       ├── blank_image.png
│   │   │       ├── Formatting Test.docx
│   │   │       ├── sample_data.csv
│   │   │       ├── sample_data.xlsx
│   │   │       ├── sample_page.html
│   │   │       ├── sample_presentation.pptx
│   │   │       └── simple_pdf.pdf
│   │   └── uv.lock
│   ├── explorer-assistant
│   │   ├── .env.example
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── assistant
│   │   │   ├── __init__.py
│   │   │   ├── chat.py
│   │   │   ├── config.py
│   │   │   ├── helpers.py
│   │   │   ├── response
│   │   │   │   ├── __init__.py
│   │   │   │   ├── model.py
│   │   │   │   ├── response_anthropic.py
│   │   │   │   ├── response_openai.py
│   │   │   │   └── response.py
│   │   │   └── text_includes
│   │   │       └── guardrails_prompt.txt
│   │   ├── assistant.code-workspace
│   │   ├── Makefile
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   └── uv.lock
│   ├── guided-conversation-assistant
│   │   ├── .env.example
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── assistant
│   │   │   ├── __init__.py
│   │   │   ├── agents
│   │   │   │   ├── guided_conversation
│   │   │   │   │   ├── config.py
│   │   │   │   │   ├── definition.py
│   │   │   │   │   └── definitions
│   │   │   │   │       ├── er_triage.py
│   │   │   │   │       ├── interview.py
│   │   │   │   │       ├── patient_intake.py
│   │   │   │   │       └── poem_feedback.py
│   │   │   │   └── guided_conversation_agent.py
│   │   │   ├── chat.py
│   │   │   ├── config.py
│   │   │   └── text_includes
│   │   │       └── guardrails_prompt.txt
│   │   ├── assistant.code-workspace
│   │   ├── Makefile
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   └── uv.lock
│   ├── knowledge-transfer-assistant
│   │   ├── .claude
│   │   │   └── settings.local.json
│   │   ├── .env.example
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── assistant
│   │   │   ├── __init__.py
│   │   │   ├── agentic
│   │   │   │   ├── __init__.py
│   │   │   │   ├── analysis.py
│   │   │   │   ├── coordinator_support.py
│   │   │   │   └── team_welcome.py
│   │   │   ├── assets
│   │   │   │   ├── icon-knowledge-transfer.svg
│   │   │   │   └── icon.svg
│   │   │   ├── assistant.py
│   │   │   ├── common.py
│   │   │   ├── config.py
│   │   │   ├── conversation_clients.py
│   │   │   ├── conversation_share_link.py
│   │   │   ├── data.py
│   │   │   ├── domain
│   │   │   │   ├── __init__.py
│   │   │   │   ├── audience_manager.py
│   │   │   │   ├── information_request_manager.py
│   │   │   │   ├── knowledge_brief_manager.py
│   │   │   │   ├── knowledge_digest_manager.py
│   │   │   │   ├── learning_objectives_manager.py
│   │   │   │   └── share_manager.py
│   │   │   ├── files.py
│   │   │   ├── logging.py
│   │   │   ├── notifications.py
│   │   │   ├── respond.py
│   │   │   ├── storage_models.py
│   │   │   ├── storage.py
│   │   │   ├── string_utils.py
│   │   │   ├── text_includes
│   │   │   │   ├── assistant_info.md
│   │   │   │   ├── card_content.md
│   │   │   │   ├── coordinator_instructions.txt
│   │   │   │   ├── coordinator_role.txt
│   │   │   │   ├── knowledge_digest_instructions.txt
│   │   │   │   ├── knowledge_digest_prompt.txt
│   │   │   │   ├── share_information_request_detection.txt
│   │   │   │   ├── team_instructions.txt
│   │   │   │   ├── team_role.txt
│   │   │   │   └── welcome_message_generation.txt
│   │   │   ├── tools
│   │   │   │   ├── __init__.py
│   │   │   │   ├── base.py
│   │   │   │   ├── information_requests.py
│   │   │   │   ├── learning_objectives.py
│   │   │   │   ├── learning_outcomes.py
│   │   │   │   ├── progress_tracking.py
│   │   │   │   └── share_setup.py
│   │   │   ├── ui_tabs
│   │   │   │   ├── __init__.py
│   │   │   │   ├── brief.py
│   │   │   │   ├── common.py
│   │   │   │   ├── debug.py
│   │   │   │   ├── learning.py
│   │   │   │   └── sharing.py
│   │   │   └── utils.py
│   │   ├── CLAUDE.md
│   │   ├── docs
│   │   │   ├── design
│   │   │   │   ├── actions.md
│   │   │   │   └── inference.md
│   │   │   ├── DEV_GUIDE.md
│   │   │   ├── how-kta-works.md
│   │   │   ├── JTBD.md
│   │   │   ├── knowledge-transfer-goals.md
│   │   │   ├── learning_assistance.md
│   │   │   ├── notable_claude_conversations
│   │   │   │   ├── clarifying_quad_modal_design.md
│   │   │   │   ├── CLAUDE_PROMPTS.md
│   │   │   │   ├── transfer_state.md
│   │   │   │   └── trying_the_context_agent.md
│   │   │   └── opportunities-of-knowledge-transfer.md
│   │   ├── knowledge-transfer-assistant.code-workspace
│   │   ├── Makefile
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── test_artifact_loading.py
│   │   │   ├── test_inspector.py
│   │   │   ├── test_share_manager.py
│   │   │   ├── test_share_storage.py
│   │   │   ├── test_share_tools.py
│   │   │   └── test_team_mode.py
│   │   └── uv.lock
│   ├── Makefile
│   ├── navigator-assistant
│   │   ├── .env.example
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── assistant
│   │   │   ├── __init__.py
│   │   │   ├── assets
│   │   │   │   ├── card_content.md
│   │   │   │   └── icon.svg
│   │   │   ├── chat.py
│   │   │   ├── config.py
│   │   │   ├── helpers.py
│   │   │   ├── response
│   │   │   │   ├── __init__.py
│   │   │   │   ├── completion_handler.py
│   │   │   │   ├── completion_requestor.py
│   │   │   │   ├── local_tool
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── add_assistant_to_conversation.py
│   │   │   │   │   ├── list_assistant_services.py
│   │   │   │   │   └── model.py
│   │   │   │   ├── models.py
│   │   │   │   ├── prompt.py
│   │   │   │   ├── request_builder.py
│   │   │   │   ├── response.py
│   │   │   │   ├── step_handler.py
│   │   │   │   └── utils
│   │   │   │       ├── __init__.py
│   │   │   │       ├── formatting_utils.py
│   │   │   │       ├── message_utils.py
│   │   │   │       ├── openai_utils.py
│   │   │   │       └── tools.py
│   │   │   ├── text_includes
│   │   │   │   ├── guardrails_prompt.md
│   │   │   │   ├── guidance_prompt.md
│   │   │   │   ├── instruction_prompt.md
│   │   │   │   ├── navigator_assistant_info.md
│   │   │   │   └── semantic_workbench_features.md
│   │   │   └── whiteboard
│   │   │       ├── __init__.py
│   │   │       ├── _inspector.py
│   │   │       └── _whiteboard.py
│   │   ├── Makefile
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   └── uv.lock
│   ├── project-assistant
│   │   ├── .cspell
│   │   │   └── custom-dictionary-workspace.txt
│   │   ├── .env.example
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── assistant
│   │   │   ├── __init__.py
│   │   │   ├── agentic
│   │   │   │   ├── __init__.py
│   │   │   │   ├── act.py
│   │   │   │   ├── coordinator_next_action.py
│   │   │   │   ├── create_invitation.py
│   │   │   │   ├── detect_audience_and_takeaways.py
│   │   │   │   ├── detect_coordinator_actions.py
│   │   │   │   ├── detect_information_request_needs.py
│   │   │   │   ├── detect_knowledge_package_gaps.py
│   │   │   │   ├── focus.py
│   │   │   │   ├── respond.py
│   │   │   │   ├── team_welcome.py
│   │   │   │   └── update_digest.py
│   │   │   ├── assets
│   │   │   │   ├── icon-knowledge-transfer.svg
│   │   │   │   └── icon.svg
│   │   │   ├── assistant.py
│   │   │   ├── common.py
│   │   │   ├── config.py
│   │   │   ├── conversation_clients.py
│   │   │   ├── data.py
│   │   │   ├── domain
│   │   │   │   ├── __init__.py
│   │   │   │   ├── audience_manager.py
│   │   │   │   ├── conversation_preferences_manager.py
│   │   │   │   ├── information_request_manager.py
│   │   │   │   ├── knowledge_brief_manager.py
│   │   │   │   ├── knowledge_digest_manager.py
│   │   │   │   ├── learning_objectives_manager.py
│   │   │   │   ├── share_manager.py
│   │   │   │   ├── tasks_manager.py
│   │   │   │   └── transfer_manager.py
│   │   │   ├── errors.py
│   │   │   ├── files.py
│   │   │   ├── logging.py
│   │   │   ├── notifications.py
│   │   │   ├── prompt_utils.py
│   │   │   ├── storage.py
│   │   │   ├── string_utils.py
│   │   │   ├── text_includes
│   │   │   │   ├── actor_instructions.md
│   │   │   │   ├── assistant_info.md
│   │   │   │   ├── card_content.md
│   │   │   │   ├── coordinator_instructions copy.md
│   │   │   │   ├── coordinator_instructions.md
│   │   │   │   ├── create_invitation.md
│   │   │   │   ├── detect_audience.md
│   │   │   │   ├── detect_coordinator_actions.md
│   │   │   │   ├── detect_information_request_needs.md
│   │   │   │   ├── detect_knowledge_package_gaps.md
│   │   │   │   ├── focus.md
│   │   │   │   ├── knowledge_digest_instructions.txt
│   │   │   │   ├── team_instructions.txt
│   │   │   │   ├── to_do.md
│   │   │   │   ├── update_knowledge_brief.md
│   │   │   │   ├── update_knowledge_digest.md
│   │   │   │   └── welcome_message_generation.txt
│   │   │   ├── tools
│   │   │   │   ├── __init__.py
│   │   │   │   ├── base.py
│   │   │   │   ├── conversation_preferences.py
│   │   │   │   ├── information_requests.py
│   │   │   │   ├── learning_objectives.py
│   │   │   │   ├── learning_outcomes.py
│   │   │   │   ├── progress_tracking.py
│   │   │   │   ├── share_setup.py
│   │   │   │   ├── system_reminders.py
│   │   │   │   ├── tasks.py
│   │   │   │   └── todo.py
│   │   │   ├── ui_tabs
│   │   │   │   ├── __init__.py
│   │   │   │   ├── brief.py
│   │   │   │   ├── common.py
│   │   │   │   ├── debug.py
│   │   │   │   ├── learning.py
│   │   │   │   └── sharing.py
│   │   │   └── utils.py
│   │   ├── CLAUDE.md
│   │   ├── docs
│   │   │   ├── design
│   │   │   │   ├── actions.md
│   │   │   │   ├── control_options.md
│   │   │   │   ├── design.md
│   │   │   │   ├── inference.md
│   │   │   │   └── PXL_20250814_190140267.jpg
│   │   │   ├── DEV_GUIDE.md
│   │   │   ├── how-kta-works.md
│   │   │   ├── JTBD.md
│   │   │   ├── knowledge-transfer-goals.md
│   │   │   ├── learning_assistance.md
│   │   │   ├── notable_claude_conversations
│   │   │   │   ├── clarifying_quad_modal_design.md
│   │   │   │   ├── CLAUDE_PROMPTS.md
│   │   │   │   ├── transfer_state.md
│   │   │   │   └── trying_the_context_agent.md
│   │   │   └── opportunities-of-knowledge-transfer.md
│   │   ├── knowledge-transfer-assistant.code-workspace
│   │   ├── Makefile
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── test_artifact_loading.py
│   │   │   ├── test_inspector.py
│   │   │   ├── test_share_manager.py
│   │   │   ├── test_share_storage.py
│   │   │   └── test_team_mode.py
│   │   └── uv.lock
│   ├── prospector-assistant
│   │   ├── .env.example
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── assistant
│   │   │   ├── __init__.py
│   │   │   ├── agents
│   │   │   │   ├── artifact_agent.py
│   │   │   │   ├── document
│   │   │   │   │   ├── config.py
│   │   │   │   │   ├── gc_draft_content_feedback_config.py
│   │   │   │   │   ├── gc_draft_outline_feedback_config.py
│   │   │   │   │   ├── guided_conversation.py
│   │   │   │   │   └── state.py
│   │   │   │   └── document_agent.py
│   │   │   ├── artifact_creation_extension
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _llm.py
│   │   │   │   ├── config.py
│   │   │   │   ├── document.py
│   │   │   │   ├── extension.py
│   │   │   │   ├── store.py
│   │   │   │   ├── test
│   │   │   │   │   ├── conftest.py
│   │   │   │   │   ├── evaluation.py
│   │   │   │   │   ├── test_completion_with_tools.py
│   │   │   │   │   └── test_extension.py
│   │   │   │   └── tools.py
│   │   │   ├── chat.py
│   │   │   ├── config.py
│   │   │   ├── form_fill_extension
│   │   │   │   ├── __init__.py
│   │   │   │   ├── config.py
│   │   │   │   ├── extension.py
│   │   │   │   ├── inspector.py
│   │   │   │   ├── state.py
│   │   │   │   └── steps
│   │   │   │       ├── __init__.py
│   │   │   │       ├── _guided_conversation.py
│   │   │   │       ├── _llm.py
│   │   │   │       ├── acquire_form_step.py
│   │   │   │       ├── extract_form_fields_step.py
│   │   │   │       ├── fill_form_step.py
│   │   │   │       └── types.py
│   │   │   ├── helpers.py
│   │   │   ├── legacy.py
│   │   │   └── text_includes
│   │   │       ├── artifact_agent_enabled.md
│   │   │       ├── guardrails_prompt.txt
│   │   │       ├── guided_conversation_agent_enabled.md
│   │   │       └── skills_agent_enabled.md
│   │   ├── assistant.code-workspace
│   │   ├── gc_learnings
│   │   │   ├── gc_learnings.md
│   │   │   └── images
│   │   │       ├── gc_conversation_plan_fcn.png
│   │   │       ├── gc_conversation_plan_template.png
│   │   │       ├── gc_execute_plan_callstack.png
│   │   │       ├── gc_functions.png
│   │   │       ├── gc_generate_plan_callstack.png
│   │   │       ├── gc_get_resource_instructions.png
│   │   │       ├── gc_get_termination_instructions.png
│   │   │       ├── gc_kernel_arguments.png
│   │   │       ├── gc_plan_calls.png
│   │   │       ├── gc_termination_instructions.png
│   │   │       ├── sk_get_chat_message_contents.png
│   │   │       ├── sk_inner_get_chat_message_contents.png
│   │   │       ├── sk_send_request_prep.png
│   │   │       └── sk_send_request.png
│   │   ├── Makefile
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   └── uv.lock
│   └── skill-assistant
│       ├── .env.example
│       ├── .vscode
│       │   ├── launch.json
│       │   └── settings.json
│       ├── assistant
│       │   ├── __init__.py
│       │   ├── config.py
│       │   ├── logging.py
│       │   ├── skill_assistant.py
│       │   ├── skill_engine_registry.py
│       │   ├── skill_event_mapper.py
│       │   ├── text_includes
│       │   │   └── guardrails_prompt.txt
│       │   └── workbench_helpers.py
│       ├── assistant.code-workspace
│       ├── Makefile
│       ├── pyproject.toml
│       ├── README.md
│       ├── tests
│       │   └── test_setup.py
│       └── uv.lock
├── CLAUDE.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── docs
│   ├── .vscode
│   │   └── settings.json
│   ├── ASSISTANT_CONFIG.md
│   ├── ASSISTANT_DEVELOPMENT_GUIDE.md
│   ├── CUSTOM_APP_REGISTRATION.md
│   ├── HOSTED_ASSISTANT_WITH_LOCAL_MCP_SERVERS.md
│   ├── images
│   │   ├── architecture-animation.gif
│   │   ├── configure_assistant.png
│   │   ├── conversation_canvas_open.png
│   │   ├── conversation_duplicate.png
│   │   ├── conversation_export.png
│   │   ├── conversation_share_dialog.png
│   │   ├── conversation_share_link.png
│   │   ├── dashboard_configured_view.png
│   │   ├── dashboard_view.png
│   │   ├── license_agreement.png
│   │   ├── message_bar.png
│   │   ├── message_inspection.png
│   │   ├── message_link.png
│   │   ├── new_prospector_assistant_dialog.png
│   │   ├── open_conversation_canvas.png
│   │   ├── prospector_example.png
│   │   ├── readme1.png
│   │   ├── readme2.png
│   │   ├── readme3.png
│   │   ├── rewind.png
│   │   ├── signin_page.png
│   │   └── splash_screen.png
│   ├── LOCAL_ASSISTANT_WITH_REMOTE_WORKBENCH.md
│   ├── SETUP_DEV_ENVIRONMENT.md
│   └── WORKBENCH_APP.md
├── examples
│   ├── dotnet
│   │   ├── .editorconfig
│   │   ├── dotnet-01-echo-bot
│   │   │   ├── appsettings.json
│   │   │   ├── dotnet-01-echo-bot.csproj
│   │   │   ├── MyAgent.cs
│   │   │   ├── MyAgentConfig.cs
│   │   │   ├── MyWorkbenchConnector.cs
│   │   │   ├── Program.cs
│   │   │   └── README.md
│   │   ├── dotnet-02-message-types-demo
│   │   │   ├── appsettings.json
│   │   │   ├── ConnectorExtensions.cs
│   │   │   ├── docs
│   │   │   │   ├── abc.png
│   │   │   │   ├── code.png
│   │   │   │   ├── config.png
│   │   │   │   ├── echo.png
│   │   │   │   ├── markdown.png
│   │   │   │   ├── mermaid.png
│   │   │   │   ├── reverse.png
│   │   │   │   └── safety-check.png
│   │   │   ├── dotnet-02-message-types-demo.csproj
│   │   │   ├── MyAgent.cs
│   │   │   ├── MyAgentConfig.cs
│   │   │   ├── MyWorkbenchConnector.cs
│   │   │   ├── Program.cs
│   │   │   └── README.md
│   │   └── dotnet-03-simple-chatbot
│   │       ├── appsettings.json
│   │       ├── ConnectorExtensions.cs
│   │       ├── dotnet-03-simple-chatbot.csproj
│   │       ├── MyAgent.cs
│   │       ├── MyAgentConfig.cs
│   │       ├── MyWorkbenchConnector.cs
│   │       ├── Program.cs
│   │       └── README.md
│   ├── Makefile
│   └── python
│       ├── python-01-echo-bot
│       │   ├── .env.example
│       │   ├── .vscode
│       │   │   ├── launch.json
│       │   │   └── settings.json
│       │   ├── assistant
│       │   │   ├── __init__.py
│       │   │   ├── chat.py
│       │   │   └── config.py
│       │   ├── assistant.code-workspace
│       │   ├── Makefile
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   └── uv.lock
│       ├── python-02-simple-chatbot
│       │   ├── .env.example
│       │   ├── .vscode
│       │   │   ├── launch.json
│       │   │   └── settings.json
│       │   ├── assistant
│       │   │   ├── __init__.py
│       │   │   ├── chat.py
│       │   │   ├── config.py
│       │   │   └── text_includes
│       │   │       └── guardrails_prompt.txt
│       │   ├── assistant.code-workspace
│       │   ├── Makefile
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   └── uv.lock
│       └── python-03-multimodel-chatbot
│           ├── .env.example
│           ├── .vscode
│           │   ├── launch.json
│           │   └── settings.json
│           ├── assistant
│           │   ├── __init__.py
│           │   ├── chat.py
│           │   ├── config.py
│           │   ├── model_adapters.py
│           │   └── text_includes
│           │       └── guardrails_prompt.txt
│           ├── assistant.code-workspace
│           ├── Makefile
│           ├── pyproject.toml
│           ├── README.md
│           └── uv.lock
├── KNOWN_ISSUES.md
├── libraries
│   ├── dotnet
│   │   ├── .editorconfig
│   │   ├── pack.sh
│   │   ├── README.md
│   │   ├── SemanticWorkbench.sln
│   │   ├── SemanticWorkbench.sln.DotSettings
│   │   └── WorkbenchConnector
│   │       ├── AgentBase.cs
│   │       ├── AgentConfig
│   │       │   ├── AgentConfigBase.cs
│   │       │   ├── AgentConfigPropertyAttribute.cs
│   │       │   └── ConfigUtils.cs
│   │       ├── Constants.cs
│   │       ├── IAgentBase.cs
│   │       ├── icon.png
│   │       ├── Models
│   │       │   ├── Command.cs
│   │       │   ├── Conversation.cs
│   │       │   ├── ConversationEvent.cs
│   │       │   ├── DebugInfo.cs
│   │       │   ├── Insight.cs
│   │       │   ├── Message.cs
│   │       │   ├── MessageMetadata.cs
│   │       │   ├── Participant.cs
│   │       │   ├── Sender.cs
│   │       │   └── ServiceInfo.cs
│   │       ├── Storage
│   │       │   ├── AgentInfo.cs
│   │       │   ├── AgentServiceStorage.cs
│   │       │   └── IAgentServiceStorage.cs
│   │       ├── StringLoggingExtensions.cs
│   │       ├── Webservice.cs
│   │       ├── WorkbenchConfig.cs
│   │       ├── WorkbenchConnector.cs
│   │       └── WorkbenchConnector.csproj
│   ├── Makefile
│   └── python
│       ├── anthropic-client
│       │   ├── .vscode
│       │   │   └── settings.json
│       │   ├── anthropic_client
│       │   │   ├── __init__.py
│       │   │   ├── client.py
│       │   │   ├── config.py
│       │   │   └── messages.py
│       │   ├── Makefile
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   └── uv.lock
│       ├── assistant-data-gen
│       │   ├── .vscode
│       │   │   ├── launch.json
│       │   │   └── settings.json
│       │   ├── assistant_data_gen
│       │   │   ├── __init__.py
│       │   │   ├── assistant_api.py
│       │   │   ├── config.py
│       │   │   ├── gce
│       │   │   │   ├── __init__.py
│       │   │   │   ├── gce_agent.py
│       │   │   │   └── prompts.py
│       │   │   └── pydantic_ai_utils.py
│       │   ├── configs
│       │   │   └── document_assistant_example_config.yaml
│       │   ├── Makefile
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   ├── scripts
│       │   │   ├── gce_simulation.py
│       │   │   └── generate_scenario.py
│       │   └── uv.lock
│       ├── assistant-drive
│       │   ├── .gitignore
│       │   ├── .vscode
│       │   │   ├── extensions.json
│       │   │   └── settings.json
│       │   ├── assistant_drive
│       │   │   ├── __init__.py
│       │   │   ├── drive.py
│       │   │   └── tests
│       │   │       └── test_basic.py
│       │   ├── Makefile
│       │   ├── pyproject.toml
│       │   ├── pytest.ini
│       │   ├── README.md
│       │   ├── usage.ipynb
│       │   └── uv.lock
│       ├── assistant-extensions
│       │   ├── .vscode
│       │   │   └── settings.json
│       │   ├── assistant_extensions
│       │   │   ├── __init__.py
│       │   │   ├── ai_clients
│       │   │   │   └── config.py
│       │   │   ├── artifacts
│       │   │   │   ├── __init__.py
│       │   │   │   ├── _artifacts.py
│       │   │   │   ├── _inspector.py
│       │   │   │   └── _model.py
│       │   │   ├── attachments
│       │   │   │   ├── __init__.py
│       │   │   │   ├── _attachments.py
│       │   │   │   ├── _convert.py
│       │   │   │   ├── _model.py
│       │   │   │   ├── _shared.py
│       │   │   │   └── _summarizer.py
│       │   │   ├── chat_context_toolkit
│       │   │   │   ├── __init__.py
│       │   │   │   ├── _config.py
│       │   │   │   ├── archive
│       │   │   │   │   ├── __init__.py
│       │   │   │   │   ├── _archive.py
│       │   │   │   │   └── _summarizer.py
│       │   │   │   ├── message_history
│       │   │   │   │   ├── __init__.py
│       │   │   │   │   ├── _history.py
│       │   │   │   │   └── _message.py
│       │   │   │   └── virtual_filesystem
│       │   │   │       ├── __init__.py
│       │   │   │       ├── _archive_file_source.py
│       │   │   │       └── _attachments_file_source.py
│       │   │   ├── dashboard_card
│       │   │   │   ├── __init__.py
│       │   │   │   └── _dashboard_card.py
│       │   │   ├── document_editor
│       │   │   │   ├── __init__.py
│       │   │   │   ├── _extension.py
│       │   │   │   ├── _inspector.py
│       │   │   │   └── _model.py
│       │   │   ├── mcp
│       │   │   │   ├── __init__.py
│       │   │   │   ├── _assistant_file_resource_handler.py
│       │   │   │   ├── _client_utils.py
│       │   │   │   ├── _devtunnel.py
│       │   │   │   ├── _model.py
│       │   │   │   ├── _openai_utils.py
│       │   │   │   ├── _sampling_handler.py
│       │   │   │   ├── _tool_utils.py
│       │   │   │   └── _workbench_file_resource_handler.py
│       │   │   ├── navigator
│       │   │   │   ├── __init__.py
│       │   │   │   └── _navigator.py
│       │   │   └── workflows
│       │   │       ├── __init__.py
│       │   │       ├── _model.py
│       │   │       ├── _workflows.py
│       │   │       └── runners
│       │   │           └── _user_proxy.py
│       │   ├── Makefile
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   ├── test
│       │   │   └── attachments
│       │   │       └── test_attachments.py
│       │   └── uv.lock
│       ├── chat-context-toolkit
│       │   ├── .claude
│       │   │   └── settings.local.json
│       │   ├── .env.sample
│       │   ├── .vscode
│       │   │   └── settings.json
│       │   ├── assets
│       │   │   ├── archive_v1.png
│       │   │   ├── history_v1.png
│       │   │   └── vfs_v1.png
│       │   ├── chat_context_toolkit
│       │   │   ├── __init__.py
│       │   │   ├── archive
│       │   │   │   ├── __init__.py
│       │   │   │   ├── _archive_reader.py
│       │   │   │   ├── _archive_task_queue.py
│       │   │   │   ├── _state.py
│       │   │   │   ├── _types.py
│       │   │   │   └── summarization
│       │   │   │       ├── __init__.py
│       │   │   │       └── _summarizer.py
│       │   │   ├── history
│       │   │   │   ├── __init__.py
│       │   │   │   ├── _budget.py
│       │   │   │   ├── _decorators.py
│       │   │   │   ├── _history.py
│       │   │   │   ├── _prioritize.py
│       │   │   │   ├── _types.py
│       │   │   │   └── tool_abbreviations
│       │   │   │       ├── __init__.py
│       │   │   │       └── _tool_abbreviations.py
│       │   │   └── virtual_filesystem
│       │   │       ├── __init__.py
│       │   │       ├── _types.py
│       │   │       ├── _virtual_filesystem.py
│       │   │       ├── README.md
│       │   │       └── tools
│       │   │           ├── __init__.py
│       │   │           ├── _ls_tool.py
│       │   │           ├── _tools.py
│       │   │           └── _view_tool.py
│       │   ├── CLAUDE.md
│       │   ├── Makefile
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   ├── test
│       │   │   ├── archive
│       │   │   │   └── test_archive_reader.py
│       │   │   ├── history
│       │   │   │   ├── test_abbreviate_messages.py
│       │   │   │   ├── test_history.py
│       │   │   │   ├── test_pair_and_order_tool_messages.py
│       │   │   │   ├── test_prioritize.py
│       │   │   │   └── test_truncate_messages.py
│       │   │   └── virtual_filesystem
│       │   │       ├── test_virtual_filesystem.py
│       │   │       └── tools
│       │   │           ├── test_ls_tool.py
│       │   │           ├── test_tools.py
│       │   │           └── test_view_tool.py
│       │   └── uv.lock
│       ├── content-safety
│       │   ├── .vscode
│       │   │   └── settings.json
│       │   ├── content_safety
│       │   │   ├── __init__.py
│       │   │   ├── evaluators
│       │   │   │   ├── __init__.py
│       │   │   │   ├── azure_content_safety
│       │   │   │   │   ├── __init__.py
│       │   │   │   │   ├── config.py
│       │   │   │   │   └── evaluator.py
│       │   │   │   ├── config.py
│       │   │   │   ├── evaluator.py
│       │   │   │   └── openai_moderations
│       │   │   │       ├── __init__.py
│       │   │   │       ├── config.py
│       │   │   │       └── evaluator.py
│       │   │   └── README.md
│       │   ├── Makefile
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   └── uv.lock
│       ├── events
│       │   ├── .vscode
│       │   │   └── settings.json
│       │   ├── events
│       │   │   ├── __init__.py
│       │   │   └── events.py
│       │   ├── Makefile
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   └── uv.lock
│       ├── guided-conversation
│       │   ├── .vscode
│       │   │   └── settings.json
│       │   ├── guided_conversation
│       │   │   ├── __init__.py
│       │   │   ├── functions
│       │   │   │   ├── __init__.py
│       │   │   │   ├── conversation_plan.py
│       │   │   │   ├── execution.py
│       │   │   │   └── final_update_plan.py
│       │   │   ├── guided_conversation_agent.py
│       │   │   ├── plugins
│       │   │   │   ├── __init__.py
│       │   │   │   ├── agenda.py
│       │   │   │   └── artifact.py
│       │   │   └── utils
│       │   │       ├── __init__.py
│       │   │       ├── base_model_llm.py
│       │   │       ├── conversation_helpers.py
│       │   │       ├── openai_tool_calling.py
│       │   │       ├── plugin_helpers.py
│       │   │       └── resources.py
│       │   ├── Makefile
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   └── uv.lock
│       ├── llm-client
│       │   ├── .vscode
│       │   │   └── settings.json
│       │   ├── llm_client
│       │   │   ├── __init__.py
│       │   │   └── model.py
│       │   ├── Makefile
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   └── uv.lock
│       ├── Makefile
│       ├── mcp-extensions
│       │   ├── .vscode
│       │   │   └── settings.json
│       │   ├── Makefile
│       │   ├── mcp_extensions
│       │   │   ├── __init__.py
│       │   │   ├── _client_session.py
│       │   │   ├── _model.py
│       │   │   ├── _sampling.py
│       │   │   ├── _server_extensions.py
│       │   │   ├── _tool_utils.py
│       │   │   ├── llm
│       │   │   │   ├── __init__.py
│       │   │   │   ├── chat_completion.py
│       │   │   │   ├── helpers.py
│       │   │   │   ├── llm_types.py
│       │   │   │   ├── mcp_chat_completion.py
│       │   │   │   └── openai_chat_completion.py
│       │   │   └── server
│       │   │       ├── __init__.py
│       │   │       └── storage.py
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   ├── tests
│       │   │   └── test_tool_utils.py
│       │   └── uv.lock
│       ├── mcp-tunnel
│       │   ├── .vscode
│       │   │   └── settings.json
│       │   ├── Makefile
│       │   ├── mcp_tunnel
│       │   │   ├── __init__.py
│       │   │   ├── _devtunnel.py
│       │   │   ├── _dir.py
│       │   │   └── _main.py
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   └── uv.lock
│       ├── openai-client
│       │   ├── .vscode
│       │   │   └── settings.json
│       │   ├── Makefile
│       │   ├── openai_client
│       │   │   ├── __init__.py
│       │   │   ├── chat_driver
│       │   │   │   ├── __init__.py
│       │   │   │   ├── chat_driver.ipynb
│       │   │   │   ├── chat_driver.py
│       │   │   │   ├── message_history_providers
│       │   │   │   │   ├── __init__.py
│       │   │   │   │   ├── in_memory_message_history_provider.py
│       │   │   │   │   ├── local_message_history_provider.py
│       │   │   │   │   ├── message_history_provider.py
│       │   │   │   │   └── tests
│       │   │   │   │       └── formatted_instructions_test.py
│       │   │   │   └── README.md
│       │   │   ├── client.py
│       │   │   ├── completion.py
│       │   │   ├── config.py
│       │   │   ├── errors.py
│       │   │   ├── logging.py
│       │   │   ├── messages.py
│       │   │   ├── tokens.py
│       │   │   └── tools.py
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   ├── tests
│       │   │   ├── test_command_parsing.py
│       │   │   ├── test_formatted_messages.py
│       │   │   ├── test_messages.py
│       │   │   └── test_tokens.py
│       │   └── uv.lock
│       ├── semantic-workbench-api-model
│       │   ├── .vscode
│       │   │   └── settings.json
│       │   ├── Makefile
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   ├── semantic_workbench_api_model
│       │   │   ├── __init__.py
│       │   │   ├── assistant_model.py
│       │   │   ├── assistant_service_client.py
│       │   │   ├── workbench_model.py
│       │   │   └── workbench_service_client.py
│       │   └── uv.lock
│       ├── semantic-workbench-assistant
│       │   ├── .vscode
│       │   │   ├── launch.json
│       │   │   └── settings.json
│       │   ├── Makefile
│       │   ├── pyproject.toml
│       │   ├── README.md
│       │   ├── semantic_workbench_assistant
│       │   │   ├── __init__.py
│       │   │   ├── assistant_app
│       │   │   │   ├── __init__.py
│       │   │   │   ├── assistant.py
│       │   │   │   ├── config.py
│       │   │   │   ├── content_safety.py
│       │   │   │   ├── context.py
│       │   │   │   ├── error.py
│       │   │   │   ├── export_import.py
│       │   │   │   ├── protocol.py
│       │   │   │   └── service.py
│       │   │   ├── assistant_service.py
│       │   │   ├── auth.py
│       │   │   ├── canonical.py
│       │   │   ├── command.py
│       │   │   ├── config.py
│       │   │   ├── logging_config.py
│       │   │   ├── settings.py
│       │   │   ├── start.py
│       │   │   └── storage.py
│       │   ├── tests
│       │   │   ├── conftest.py
│       │   │   ├── test_assistant_app.py
│       │   │   ├── test_canonical.py
│       │   │   ├── test_config.py
│       │   │   └── test_storage.py
│       │   └── uv.lock
│       └── skills
│           ├── .vscode
│           │   └── settings.json
│           ├── Makefile
│           ├── README.md
│           └── skill-library
│               ├── .vscode
│               │   └── settings.json
│               ├── docs
│               │   └── vs-recipe-tool.md
│               ├── Makefile
│               ├── pyproject.toml
│               ├── README.md
│               ├── skill_library
│               │   ├── __init__.py
│               │   ├── chat_driver_helpers.py
│               │   ├── cli
│               │   │   ├── azure_openai.py
│               │   │   ├── conversation_history.py
│               │   │   ├── README.md
│               │   │   ├── run_routine.py
│               │   │   ├── settings.py
│               │   │   └── skill_logger.py
│               │   ├── engine.py
│               │   ├── llm_info.txt
│               │   ├── logging.py
│               │   ├── README.md
│               │   ├── routine_stack.py
│               │   ├── skill.py
│               │   ├── skills
│               │   │   ├── common
│               │   │   │   ├── __init__.py
│               │   │   │   ├── common_skill.py
│               │   │   │   └── routines
│               │   │   │       ├── bing_search.py
│               │   │   │       ├── consolidate.py
│               │   │   │       ├── echo.py
│               │   │   │       ├── gather_context.py
│               │   │   │       ├── get_content_from_url.py
│               │   │   │       ├── gpt_complete.py
│               │   │   │       ├── select_user_intent.py
│               │   │   │       └── summarize.py
│               │   │   ├── eval
│               │   │   │   ├── __init__.py
│               │   │   │   ├── eval_skill.py
│               │   │   │   └── routines
│               │   │   │       └── eval.py
│               │   │   ├── fabric
│               │   │   │   ├── __init__.py
│               │   │   │   ├── fabric_skill.py
│               │   │   │   ├── patterns
│               │   │   │   │   ├── agility_story
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── ai
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_answers
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_candidates
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── analyze_cfp_submission
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_claims
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── analyze_comments
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_debate
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_email_headers
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── analyze_incident
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── analyze_interviewer_techniques
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_logs
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_malware
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_military_strategy
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_mistakes
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_paper
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── analyze_patent
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_personality
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_presentation
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_product_feedback
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_proposition
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── analyze_prose
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── analyze_prose_json
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── analyze_prose_pinker
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_risk
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_sales_call
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_spiritual_text
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── analyze_tech_impact
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── analyze_threat_report
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── analyze_threat_report_cmds
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── analyze_threat_report_trends
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── answer_interview_question
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── ask_secure_by_design_questions
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── ask_uncle_duke
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── capture_thinkers_work
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── check_agreement
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── clean_text
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── coding_master
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── compare_and_contrast
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── convert_to_markdown
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_5_sentence_summary
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_academic_paper
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_ai_jobs_analysis
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_aphorisms
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── create_art_prompt
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_better_frame
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── create_coding_project
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_command
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── create_cyber_summary
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_design_document
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_diy
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_formal_email
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_git_diff_commit
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_graph_from_input
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_hormozi_offer
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_idea_compass
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_investigation_visualization
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_keynote
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_logo
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── create_markmap_visualization
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_mermaid_visualization
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_mermaid_visualization_for_github
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_micro_summary
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_network_threat_landscape
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── create_newsletter_entry
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── create_npc
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── create_pattern
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_prd
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_prediction_block
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_quiz
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_reading_plan
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_recursive_outline
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_report_finding
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── create_rpg_summary
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_security_update
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── create_show_intro
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_sigma_rules
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_story_explanation
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_stride_threat_model
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_summary
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_tags
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_threat_scenarios
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_ttrc_graph
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_ttrc_narrative
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_upgrade_pack
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_user_story
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── create_video_chapters
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── create_visualization
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── dialog_with_socrates
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── enrich_blog_post
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── explain_code
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── explain_docs
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── explain_math
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── explain_project
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── explain_terms
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── export_data_as_csv
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_algorithm_update_recommendations
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── extract_article_wisdom
│               │   │   │   │   │   ├── dmiessler
│               │   │   │   │   │   │   └── extract_wisdom-1.0.0
│               │   │   │   │   │   │       ├── system.md
│               │   │   │   │   │   │       └── user.md
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── extract_book_ideas
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_book_recommendations
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_business_ideas
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_controversial_ideas
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_core_message
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_ctf_writeup
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_domains
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_extraordinary_claims
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_ideas
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_insights
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_insights_dm
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_instructions
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_jokes
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_latest_video
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_main_idea
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_most_redeeming_thing
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_patterns
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_poc
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── extract_predictions
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_primary_problem
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_primary_solution
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_product_features
│               │   │   │   │   │   ├── dmiessler
│               │   │   │   │   │   │   └── extract_wisdom-1.0.0
│               │   │   │   │   │   │       ├── system.md
│               │   │   │   │   │   │       └── user.md
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_questions
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_recipe
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_recommendations
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── extract_references
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── extract_skills
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_song_meaning
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_sponsors
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_videoid
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── extract_wisdom
│               │   │   │   │   │   ├── dmiessler
│               │   │   │   │   │   │   └── extract_wisdom-1.0.0
│               │   │   │   │   │   │       ├── system.md
│               │   │   │   │   │   │       └── user.md
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_wisdom_agents
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_wisdom_dm
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── extract_wisdom_nometa
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── find_hidden_message
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── find_logical_fallacies
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── get_wow_per_minute
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── get_youtube_rss
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── humanize
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── identify_dsrp_distinctions
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── identify_dsrp_perspectives
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── identify_dsrp_relationships
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── identify_dsrp_systems
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── identify_job_stories
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── improve_academic_writing
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── improve_prompt
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── improve_report_finding
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── improve_writing
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── judge_output
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── label_and_rate
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── loaded
│               │   │   │   │   ├── md_callout
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── official_pattern_template
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── pattern_explanations.md
│               │   │   │   │   ├── prepare_7s_strategy
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── provide_guidance
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── rate_ai_response
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── rate_ai_result
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── rate_content
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── rate_value
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── raw_query
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── raycast
│               │   │   │   │   │   ├── capture_thinkers_work
│               │   │   │   │   │   ├── create_story_explanation
│               │   │   │   │   │   ├── extract_primary_problem
│               │   │   │   │   │   ├── extract_wisdom
│               │   │   │   │   │   └── yt
│               │   │   │   │   ├── recommend_artists
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── recommend_pipeline_upgrades
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── recommend_talkpanel_topics
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── refine_design_document
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── review_design
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── sanitize_broken_html_to_markdown
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── show_fabric_options_markmap
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── solve_with_cot
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── stringify
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── suggest_pattern
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── summarize
│               │   │   │   │   │   ├── dmiessler
│               │   │   │   │   │   │   └── summarize
│               │   │   │   │   │   │       ├── system.md
│               │   │   │   │   │   │       └── user.md
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── summarize_debate
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── summarize_git_changes
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── summarize_git_diff
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── summarize_lecture
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── summarize_legislation
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── summarize_meeting
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── summarize_micro
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── summarize_newsletter
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── summarize_paper
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── summarize_prompt
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── summarize_pull-requests
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── summarize_rpg_session
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_analyze_challenge_handling
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_check_metrics
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_create_h3_career
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_create_opening_sentences
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_describe_life_outlook
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_extract_intro_sentences
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_extract_panel_topics
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_find_blindspots
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_find_negative_thinking
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_find_neglected_goals
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_give_encouragement
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_red_team_thinking
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_threat_model_plans
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_visualize_mission_goals_projects
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── t_year_in_review
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── to_flashcards
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── transcribe_minutes
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── translate
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── tweet
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── write_essay
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── write_hackerone_report
│               │   │   │   │   │   ├── README.md
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── write_latex
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── write_micro_essay
│               │   │   │   │   │   └── system.md
│               │   │   │   │   ├── write_nuclei_template_rule
│               │   │   │   │   │   ├── system.md
│               │   │   │   │   │   └── user.md
│               │   │   │   │   ├── write_pull-request
│               │   │   │   │   │   └── system.md
│               │   │   │   │   └── write_semgrep_rule
│               │   │   │   │       ├── system.md
│               │   │   │   │       └── user.md
│               │   │   │   └── routines
│               │   │   │       ├── list.py
│               │   │   │       ├── run.py
│               │   │   │       └── show.py
│               │   │   ├── guided_conversation
│               │   │   │   ├── __init__.py
│               │   │   │   ├── agenda.py
│               │   │   │   ├── artifact_helpers.py
│               │   │   │   ├── chat_completions
│               │   │   │   │   ├── fix_agenda_error.py
│               │   │   │   │   ├── fix_artifact_error.py
│               │   │   │   │   ├── generate_agenda.py
│               │   │   │   │   ├── generate_artifact_updates.py
│               │   │   │   │   ├── generate_final_artifact.py
│               │   │   │   │   └── generate_message.py
│               │   │   │   ├── conversation_guides
│               │   │   │   │   ├── __init__.py
│               │   │   │   │   ├── acrostic_poem.py
│               │   │   │   │   ├── er_triage.py
│               │   │   │   │   ├── interview.py
│               │   │   │   │   └── patient_intake.py
│               │   │   │   ├── guide.py
│               │   │   │   ├── guided_conversation_skill.py
│               │   │   │   ├── logging.py
│               │   │   │   ├── message.py
│               │   │   │   ├── resources.py
│               │   │   │   ├── routines
│               │   │   │   │   └── guided_conversation.py
│               │   │   │   └── tests
│               │   │   │       ├── conftest.py
│               │   │   │       ├── test_artifact_helpers.py
│               │   │   │       ├── test_generate_agenda.py
│               │   │   │       ├── test_generate_artifact_updates.py
│               │   │   │       ├── test_generate_final_artifact.py
│               │   │   │       └── test_resource.py
│               │   │   ├── meta
│               │   │   │   ├── __init__.py
│               │   │   │   ├── meta_skill.py
│               │   │   │   ├── README.md
│               │   │   │   └── routines
│               │   │   │       └── generate_routine.py
│               │   │   ├── posix
│               │   │   │   ├── __init__.py
│               │   │   │   ├── posix_skill.py
│               │   │   │   ├── routines
│               │   │   │   │   ├── append_file.py
│               │   │   │   │   ├── cd.py
│               │   │   │   │   ├── ls.py
│               │   │   │   │   ├── make_home_dir.py
│               │   │   │   │   ├── mkdir.py
│               │   │   │   │   ├── mv.py
│               │   │   │   │   ├── pwd.py
│               │   │   │   │   ├── read_file.py
│               │   │   │   │   ├── rm.py
│               │   │   │   │   ├── touch.py
│               │   │   │   │   └── write_file.py
│               │   │   │   └── sandbox_shell.py
│               │   │   ├── README.md
│               │   │   ├── research
│               │   │   │   ├── __init__.py
│               │   │   │   ├── README.md
│               │   │   │   ├── research_skill.py
│               │   │   │   └── routines
│               │   │   │       ├── answer_question_about_content.py
│               │   │   │       ├── evaluate_answer.py
│               │   │   │       ├── generate_research_plan.py
│               │   │   │       ├── generate_search_query.py
│               │   │   │       ├── update_research_plan.py
│               │   │   │       ├── web_research.py
│               │   │   │       └── web_search.py
│               │   │   ├── research2
│               │   │   │   ├── __init__.py
│               │   │   │   ├── README.md
│               │   │   │   ├── research_skill.py
│               │   │   │   └── routines
│               │   │   │       ├── facts.py
│               │   │   │       ├── make_final_report.py
│               │   │   │       ├── research.py
│               │   │   │       ├── search_plan.py
│               │   │   │       ├── search.py
│               │   │   │       └── visit_pages.py
│               │   │   └── web_research
│               │   │       ├── __init__.py
│               │   │       ├── README.md
│               │   │       ├── research_skill.py
│               │   │       └── routines
│               │   │           ├── facts.py
│               │   │           ├── make_final_report.py
│               │   │           ├── research.py
│               │   │           ├── search_plan.py
│               │   │           ├── search.py
│               │   │           └── visit_pages.py
│               │   ├── tests
│               │   │   ├── test_common_skill.py
│               │   │   ├── test_integration.py
│               │   │   ├── test_routine_stack.py
│               │   │   ├── tst_skill
│               │   │   │   ├── __init__.py
│               │   │   │   └── routines
│               │   │   │       ├── __init__.py
│               │   │   │       └── a_routine.py
│               │   │   └── utilities
│               │   │       ├── test_find_template_vars.py
│               │   │       ├── test_make_arg_set.py
│               │   │       ├── test_paramspec.py
│               │   │       ├── test_parse_command_string.py
│               │   │       └── test_to_string.py
│               │   ├── types.py
│               │   ├── usage.py
│               │   └── utilities.py
│               └── uv.lock
├── LICENSE
├── Makefile
├── mcp-servers
│   ├── ai-assist-content
│   │   ├── .vscode
│   │   │   └── settings.json
│   │   ├── mcp-example-brave-search.md
│   │   ├── mcp-fastmcp-typescript-README.md
│   │   ├── mcp-llms-full.txt
│   │   ├── mcp-metadata-tips.md
│   │   ├── mcp-python-sdk-README.md
│   │   ├── mcp-typescript-sdk-README.md
│   │   ├── pydanticai-documentation.md
│   │   ├── pydanticai-example-question-graph.md
│   │   ├── pydanticai-example-weather.md
│   │   ├── pydanticai-tutorial.md
│   │   └── README.md
│   ├── Makefile
│   ├── mcp-server-bing-search
│   │   ├── .env.example
│   │   ├── .gitignore
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── Makefile
│   │   ├── mcp_server_bing_search
│   │   │   ├── __init__.py
│   │   │   ├── config.py
│   │   │   ├── prompts
│   │   │   │   ├── __init__.py
│   │   │   │   ├── clean_website.py
│   │   │   │   └── filter_links.py
│   │   │   ├── server.py
│   │   │   ├── start.py
│   │   │   ├── tools.py
│   │   │   ├── types.py
│   │   │   ├── utils.py
│   │   │   └── web
│   │   │       ├── __init__.py
│   │   │       ├── get_content.py
│   │   │       ├── llm_processing.py
│   │   │       ├── process_website.py
│   │   │       └── search_bing.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   └── test_tools.py
│   │   └── uv.lock
│   ├── mcp-server-bundle
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── Makefile
│   │   ├── mcp_server_bundle
│   │   │   ├── __init__.py
│   │   │   └── main.py
│   │   ├── pyinstaller.spec
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   └── uv.lock
│   ├── mcp-server-filesystem
│   │   ├── .env.example
│   │   ├── .github
│   │   │   └── workflows
│   │   │       └── ci.yml
│   │   ├── .gitignore
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── Makefile
│   │   ├── mcp_server_filesystem
│   │   │   ├── __init__.py
│   │   │   ├── config.py
│   │   │   ├── server.py
│   │   │   └── start.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   └── test_filesystem.py
│   │   └── uv.lock
│   ├── mcp-server-filesystem-edit
│   │   ├── .env.example
│   │   ├── .gitignore
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── data
│   │   │   ├── attachments
│   │   │   │   ├── Daily Game Ideas.txt
│   │   │   │   ├── Frontend Framework Proposal.txt
│   │   │   │   ├── ReDoodle.txt
│   │   │   │   └── Research Template.tex
│   │   │   ├── test_cases.yaml
│   │   │   └── transcripts
│   │   │       ├── transcript_research_simple.md
│   │   │       ├── transcript_Startup_Idea_1_202503031513.md
│   │   │       ├── transcript_Startup_Idea_2_202503031659.md
│   │   │       └── transcript_Web_Frontends_202502281551.md
│   │   ├── Makefile
│   │   ├── mcp_server_filesystem_edit
│   │   │   ├── __init__.py
│   │   │   ├── app_handling
│   │   │   │   ├── __init__.py
│   │   │   │   ├── excel.py
│   │   │   │   ├── miktex.py
│   │   │   │   ├── office_common.py
│   │   │   │   ├── powerpoint.py
│   │   │   │   └── word.py
│   │   │   ├── config.py
│   │   │   ├── evals
│   │   │   │   ├── __init__.py
│   │   │   │   ├── common.py
│   │   │   │   ├── run_comments.py
│   │   │   │   ├── run_edit.py
│   │   │   │   └── run_ppt_edit.py
│   │   │   ├── prompts
│   │   │   │   ├── __init__.py
│   │   │   │   ├── add_comments.py
│   │   │   │   ├── analyze_comments.py
│   │   │   │   ├── latex_edit.py
│   │   │   │   ├── markdown_draft.py
│   │   │   │   ├── markdown_edit.py
│   │   │   │   └── powerpoint_edit.py
│   │   │   ├── server.py
│   │   │   ├── start.py
│   │   │   ├── tools
│   │   │   │   ├── __init__.py
│   │   │   │   ├── add_comments.py
│   │   │   │   ├── edit_adapters
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── common.py
│   │   │   │   │   ├── latex.py
│   │   │   │   │   └── markdown.py
│   │   │   │   ├── edit.py
│   │   │   │   └── helpers.py
│   │   │   └── types.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── app_handling
│   │   │   │   ├── test_excel.py
│   │   │   │   ├── test_miktext.py
│   │   │   │   ├── test_office_common.py
│   │   │   │   ├── test_powerpoint.py
│   │   │   │   └── test_word.py
│   │   │   ├── conftest.py
│   │   │   └── tools
│   │   │       └── edit_adapters
│   │   │           ├── test_latex.py
│   │   │           └── test_markdown.py
│   │   └── uv.lock
│   ├── mcp-server-fusion
│   │   ├── .gitignore
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── AddInIcon.svg
│   │   ├── config.py
│   │   ├── FusionMCPServerAddIn.manifest
│   │   ├── FusionMCPServerAddIn.py
│   │   ├── mcp_server_fusion
│   │   │   ├── __init__.py
│   │   │   ├── fusion_mcp_server.py
│   │   │   ├── fusion_utils
│   │   │   │   ├── __init__.py
│   │   │   │   ├── event_utils.py
│   │   │   │   ├── general_utils.py
│   │   │   │   └── tool_utils.py
│   │   │   ├── mcp_tools
│   │   │   │   ├── __init__.py
│   │   │   │   ├── fusion_3d_operation.py
│   │   │   │   ├── fusion_geometry.py
│   │   │   │   ├── fusion_pattern.py
│   │   │   │   └── fusion_sketch.py
│   │   │   └── vendor
│   │   │       └── README.md
│   │   ├── README.md
│   │   └── requirements.txt
│   ├── mcp-server-giphy
│   │   ├── .env.example
│   │   ├── .gitignore
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── Makefile
│   │   ├── mcp_server
│   │   │   ├── __init__.py
│   │   │   ├── config.py
│   │   │   ├── giphy_search.py
│   │   │   ├── sampling.py
│   │   │   ├── server.py
│   │   │   ├── start.py
│   │   │   └── utils.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   └── uv.lock
│   ├── mcp-server-memory-user-bio
│   │   ├── .env.example
│   │   ├── .gitignore
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── Makefile
│   │   ├── mcp_server_memory_user_bio
│   │   │   ├── __init__.py
│   │   │   ├── config.py
│   │   │   ├── server.py
│   │   │   └── start.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   └── uv.lock
│   ├── mcp-server-memory-whiteboard
│   │   ├── .env.example
│   │   ├── .gitignore
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── Makefile
│   │   ├── mcp_server_memory_whiteboard
│   │   │   ├── __init__.py
│   │   │   ├── config.py
│   │   │   ├── server.py
│   │   │   └── start.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   └── uv.lock
│   ├── mcp-server-office
│   │   ├── .env.example
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── build.sh
│   │   ├── data
│   │   │   ├── attachments
│   │   │   │   ├── Daily Game Ideas.txt
│   │   │   │   ├── Frontend Framework Proposal.txt
│   │   │   │   └── ReDoodle.txt
│   │   │   └── word
│   │   │       ├── test_cases.yaml
│   │   │       └── transcripts
│   │   │           ├── transcript_Startup_Idea_1_202503031513.md
│   │   │           ├── transcript_Startup_Idea_2_202503031659.md
│   │   │           └── transcript_Web_Frontends_202502281551.md
│   │   ├── Makefile
│   │   ├── mcp_server
│   │   │   ├── __init__.py
│   │   │   ├── app_interaction
│   │   │   │   ├── __init__.py
│   │   │   │   ├── excel_editor.py
│   │   │   │   ├── powerpoint_editor.py
│   │   │   │   └── word_editor.py
│   │   │   ├── config.py
│   │   │   ├── constants.py
│   │   │   ├── evals
│   │   │   │   ├── __init__.py
│   │   │   │   ├── common.py
│   │   │   │   ├── run_comment_analysis.py
│   │   │   │   ├── run_feedback.py
│   │   │   │   └── run_markdown_edit.py
│   │   │   ├── helpers.py
│   │   │   ├── markdown_edit
│   │   │   │   ├── __init__.py
│   │   │   │   ├── comment_analysis.py
│   │   │   │   ├── feedback_step.py
│   │   │   │   ├── markdown_edit.py
│   │   │   │   └── utils.py
│   │   │   ├── prompts
│   │   │   │   ├── __init__.py
│   │   │   │   ├── comment_analysis.py
│   │   │   │   ├── feedback.py
│   │   │   │   ├── markdown_draft.py
│   │   │   │   └── markdown_edit.py
│   │   │   ├── server.py
│   │   │   ├── start.py
│   │   │   └── types.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   └── test_word_editor.py
│   │   └── uv.lock
│   ├── mcp-server-open-deep-research
│   │   ├── .env.example
│   │   ├── .gitignore
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── Makefile
│   │   ├── mcp_server
│   │   │   ├── __init__.py
│   │   │   ├── config.py
│   │   │   ├── libs
│   │   │   │   └── open_deep_research
│   │   │   │       ├── cookies.py
│   │   │   │       ├── mdconvert.py
│   │   │   │       ├── run_agents.py
│   │   │   │       ├── text_inspector_tool.py
│   │   │   │       ├── text_web_browser.py
│   │   │   │       └── visual_qa.py
│   │   │   ├── open_deep_research.py
│   │   │   ├── server.py
│   │   │   └── start.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   └── uv.lock
│   ├── mcp-server-open-deep-research-clone
│   │   ├── .env.example
│   │   ├── .gitignore
│   │   ├── .vscode
│   │   │   ├── launch.json
│   │   │   └── settings.json
│   │   ├── Makefile
│   │   ├── mcp_server_open_deep_research_clone
│   │   │   ├── __init__.py
│   │   │   ├── azure_openai.py
│   │   │   ├── config.py
│   │   │   ├── logging.py
│   │   │   ├── sampling.py
│   │   │   ├── server.py
│   │   │   ├── start.py
│   │   │   ├── utils.py
│   │   │   └── web_research.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── test
│   │   │   └── test_open_deep_research_clone.py
│   │   └── uv.lock
│   ├── mcp-server-template
│   │   ├── .taplo.toml
│   │   ├── .vscode
│   │   │   └── settings.json
│   │   ├── copier.yml
│   │   ├── README.md
│   │   └── template
│   │       └── {{ project_slug }}
│   │           ├── .env.example.jinja
│   │           ├── .gitignore
│   │           ├── .vscode
│   │           │   ├── launch.json.jinja
│   │           │   └── settings.json
│   │           ├── {{ module_name }}
│   │           │   ├── __init__.py
│   │           │   ├── config.py.jinja
│   │           │   ├── server.py.jinja
│   │           │   └── start.py.jinja
│   │           ├── Makefile.jinja
│   │           ├── pyproject.toml.jinja
│   │           └── README.md.jinja
│   ├── mcp-server-vscode
│   │   ├── .eslintrc.cjs
│   │   ├── .gitignore
│   │   ├── .npmrc
│   │   ├── .vscode
│   │   │   ├── extensions.json
│   │   │   ├── launch.json
│   │   │   ├── settings.json
│   │   │   └── tasks.json
│   │   ├── .vscode-test.mjs
│   │   ├── .vscodeignore
│   │   ├── ASSISTANT_BOOTSTRAP.md
│   │   ├── eslint.config.mjs
│   │   ├── images
│   │   │   └── icon.png
│   │   ├── LICENSE
│   │   ├── Makefile
│   │   ├── out
│   │   │   ├── extension.d.ts
│   │   │   ├── extension.js
│   │   │   ├── test
│   │   │   │   ├── extension.test.d.ts
│   │   │   │   └── extension.test.js
│   │   │   ├── tools
│   │   │   │   ├── code_checker.d.ts
│   │   │   │   ├── code_checker.js
│   │   │   │   ├── debug_tools.d.ts
│   │   │   │   ├── debug_tools.js
│   │   │   │   ├── focus_editor.d.ts
│   │   │   │   ├── focus_editor.js
│   │   │   │   ├── search_symbol.d.ts
│   │   │   │   └── search_symbol.js
│   │   │   └── utils
│   │   │       ├── port.d.ts
│   │   │       └── port.js
│   │   ├── package.json
│   │   ├── pnpm-lock.yaml
│   │   ├── prettier.config.cjs
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── extension.d.ts
│   │   │   ├── extension.ts
│   │   │   ├── test
│   │   │   │   ├── extension.test.d.ts
│   │   │   │   └── extension.test.ts
│   │   │   ├── tools
│   │   │   │   ├── code_checker.d.ts
│   │   │   │   ├── code_checker.ts
│   │   │   │   ├── debug_tools.d.ts
│   │   │   │   ├── debug_tools.ts
│   │   │   │   ├── focus_editor.d.ts
│   │   │   │   ├── focus_editor.ts
│   │   │   │   ├── search_symbol.d.ts
│   │   │   │   └── search_symbol.ts
│   │   │   └── utils
│   │   │       ├── port.d.ts
│   │   │       └── port.ts
│   │   ├── tsconfig.json
│   │   ├── tsconfig.tsbuildinfo
│   │   ├── vsc-extension-quickstart.md
│   │   └── webpack.config.js
│   └── mcp-server-web-research
│       ├── .env.example
│       ├── .gitignore
│       ├── .vscode
│       │   ├── launch.json
│       │   └── settings.json
│       ├── Makefile
│       ├── mcp_server_web_research
│       │   ├── __init__.py
│       │   ├── azure_openai.py
│       │   ├── config.py
│       │   ├── logging.py
│       │   ├── sampling.py
│       │   ├── server.py
│       │   ├── start.py
│       │   ├── utils.py
│       │   └── web_research.py
│       ├── pyproject.toml
│       ├── README.md
│       ├── test
│       │   └── test_web_research.py
│       └── uv.lock
├── README.md
├── RESPONSIBLE_AI_FAQ.md
├── ruff.toml
├── SECURITY.md
├── semantic-workbench.code-workspace
├── SUPPORT.md
├── tools
│   ├── build_ai_context_files.py
│   ├── collect_files.py
│   ├── docker
│   │   ├── azure_website_sshd.conf
│   │   ├── docker-entrypoint.sh
│   │   ├── Dockerfile.assistant
│   │   └── Dockerfile.mcp-server
│   ├── makefiles
│   │   ├── docker-assistant.mk
│   │   ├── docker-mcp-server.mk
│   │   ├── docker.mk
│   │   ├── python.mk
│   │   ├── recursive.mk
│   │   └── shell.mk
│   ├── reset-service-data.ps1
│   ├── reset-service-data.sh
│   ├── run-app.ps1
│   ├── run-app.sh
│   ├── run-canonical-agent.ps1
│   ├── run-canonical-agent.sh
│   ├── run-dotnet-examples-with-aspire.sh
│   ├── run-python-example1.sh
│   ├── run-python-example2.ps1
│   ├── run-python-example2.sh
│   ├── run-service.ps1
│   ├── run-service.sh
│   ├── run-workbench-chatbot.ps1
│   └── run-workbench-chatbot.sh
├── workbench-app
│   ├── .dockerignore
│   ├── .env.example
│   ├── .eslintrc.cjs
│   ├── .gitignore
│   ├── .vscode
│   │   ├── launch.json
│   │   └── settings.json
│   ├── docker-entrypoint.sh
│   ├── Dockerfile
│   ├── docs
│   │   ├── APP_DEV_GUIDE.md
│   │   ├── MESSAGE_METADATA.md
│   │   ├── MESSAGE_TYPES.md
│   │   ├── README.md
│   │   └── STATE_INSPECTORS.md
│   ├── index.html
│   ├── Makefile
│   ├── nginx.conf
│   ├── package.json
│   ├── pnpm-lock.yaml
│   ├── prettier.config.cjs
│   ├── public
│   │   └── assets
│   │       ├── background-1-upscaled.jpg
│   │       ├── background-1-upscaled.png
│   │       ├── background-1.jpg
│   │       ├── background-1.png
│   │       ├── background-2.jpg
│   │       ├── background-2.png
│   │       ├── experimental-feature.jpg
│   │       ├── favicon.svg
│   │       ├── workflow-designer-1.jpg
│   │       ├── workflow-designer-outlets.jpg
│   │       ├── workflow-designer-states.jpg
│   │       └── workflow-designer-transitions.jpg
│   ├── README.md
│   ├── run.sh
│   ├── src
│   │   ├── components
│   │   │   ├── App
│   │   │   │   ├── AppFooter.tsx
│   │   │   │   ├── AppHeader.tsx
│   │   │   │   ├── AppMenu.tsx
│   │   │   │   ├── AppView.tsx
│   │   │   │   ├── CodeLabel.tsx
│   │   │   │   ├── CommandButton.tsx
│   │   │   │   ├── ConfirmLeave.tsx
│   │   │   │   ├── ContentExport.tsx
│   │   │   │   ├── ContentImport.tsx
│   │   │   │   ├── CopyButton.tsx
│   │   │   │   ├── DialogControl.tsx
│   │   │   │   ├── DynamicIframe.tsx
│   │   │   │   ├── ErrorListFromAppState.tsx
│   │   │   │   ├── ErrorMessageBar.tsx
│   │   │   │   ├── ExperimentalNotice.tsx
│   │   │   │   ├── FormWidgets
│   │   │   │   │   ├── BaseModelEditorWidget.tsx
│   │   │   │   │   ├── CustomizedArrayFieldTemplate.tsx
│   │   │   │   │   ├── CustomizedFieldTemplate.tsx
│   │   │   │   │   ├── CustomizedObjectFieldTemplate.tsx
│   │   │   │   │   └── InspectableWidget.tsx
│   │   │   │   ├── LabelWithDescription.tsx
│   │   │   │   ├── Loading.tsx
│   │   │   │   ├── MenuItemControl.tsx
│   │   │   │   ├── MiniControl.tsx
│   │   │   │   ├── MyAssistantServiceRegistrations.tsx
│   │   │   │   ├── MyItemsManager.tsx
│   │   │   │   ├── OverflowMenu.tsx
│   │   │   │   ├── PresenceMotionList.tsx
│   │   │   │   ├── ProfileSettings.tsx
│   │   │   │   └── TooltipWrapper.tsx
│   │   │   ├── Assistants
│   │   │   │   ├── ApplyConfigButton.tsx
│   │   │   │   ├── AssistantAdd.tsx
│   │   │   │   ├── AssistantConfigExportButton.tsx
│   │   │   │   ├── AssistantConfigImportButton.tsx
│   │   │   │   ├── AssistantConfiguration.tsx
│   │   │   │   ├── AssistantConfigure.tsx
│   │   │   │   ├── AssistantCreate.tsx
│   │   │   │   ├── AssistantDelete.tsx
│   │   │   │   ├── AssistantDuplicate.tsx
│   │   │   │   ├── AssistantExport.tsx
│   │   │   │   ├── AssistantImport.tsx
│   │   │   │   ├── AssistantRemove.tsx
│   │   │   │   ├── AssistantRename.tsx
│   │   │   │   ├── AssistantServiceInfo.tsx
│   │   │   │   ├── AssistantServiceMetadata.tsx
│   │   │   │   └── MyAssistants.tsx
│   │   │   ├── AssistantServiceRegistrations
│   │   │   │   ├── AssistantServiceRegistrationApiKey.tsx
│   │   │   │   ├── AssistantServiceRegistrationApiKeyReset.tsx
│   │   │   │   ├── AssistantServiceRegistrationCreate.tsx
│   │   │   │   └── AssistantServiceRegistrationRemove.tsx
│   │   │   ├── Conversations
│   │   │   │   ├── Canvas
│   │   │   │   │   ├── AssistantCanvas.tsx
│   │   │   │   │   ├── AssistantCanvasList.tsx
│   │   │   │   │   ├── AssistantInspector.tsx
│   │   │   │   │   ├── AssistantInspectorList.tsx
│   │   │   │   │   └── ConversationCanvas.tsx
│   │   │   │   ├── ChatInputPlugins
│   │   │   │   │   ├── ClearEditorPlugin.tsx
│   │   │   │   │   ├── LexicalMenu.ts
│   │   │   │   │   ├── ParticipantMentionsPlugin.tsx
│   │   │   │   │   ├── TypeaheadMenuPlugin.css
│   │   │   │   │   └── TypeaheadMenuPlugin.tsx
│   │   │   │   ├── ContentRenderers
│   │   │   │   │   ├── CodeContentRenderer.tsx
│   │   │   │   │   ├── ContentListRenderer.tsx
│   │   │   │   │   ├── ContentRenderer.tsx
│   │   │   │   │   ├── DiffRenderer.tsx
│   │   │   │   │   ├── HtmlContentRenderer.tsx
│   │   │   │   │   ├── JsonSchemaContentRenderer.tsx
│   │   │   │   │   ├── MarkdownContentRenderer.tsx
│   │   │   │   │   ├── MarkdownEditorRenderer.tsx
│   │   │   │   │   ├── MermaidContentRenderer.tsx
│   │   │   │   │   ├── MusicABCContentRenderer.css
│   │   │   │   │   └── MusicABCContentRenderer.tsx
│   │   │   │   ├── ContextWindow.tsx
│   │   │   │   ├── ConversationCreate.tsx
│   │   │   │   ├── ConversationDuplicate.tsx
│   │   │   │   ├── ConversationExport.tsx
│   │   │   │   ├── ConversationFileIcon.tsx
│   │   │   │   ├── ConversationRemove.tsx
│   │   │   │   ├── ConversationRename.tsx
│   │   │   │   ├── ConversationShare.tsx
│   │   │   │   ├── ConversationShareCreate.tsx
│   │   │   │   ├── ConversationShareList.tsx
│   │   │   │   ├── ConversationShareView.tsx
│   │   │   │   ├── ConversationsImport.tsx
│   │   │   │   ├── ConversationTranscript.tsx
│   │   │   │   ├── DebugInspector.tsx
│   │   │   │   ├── FileItem.tsx
│   │   │   │   ├── FileList.tsx
│   │   │   │   ├── InputAttachmentList.tsx
│   │   │   │   ├── InputOptionsControl.tsx
│   │   │   │   ├── InteractHistory.tsx
│   │   │   │   ├── InteractInput.tsx
│   │   │   │   ├── Message
│   │   │   │   │   ├── AttachmentSection.tsx
│   │   │   │   │   ├── ContentRenderer.tsx
│   │   │   │   │   ├── ContentSafetyNotice.tsx
│   │   │   │   │   ├── InteractMessage.tsx
│   │   │   │   │   ├── MessageActions.tsx
│   │   │   │   │   ├── MessageBase.tsx
│   │   │   │   │   ├── MessageBody.tsx
│   │   │   │   │   ├── MessageContent.tsx
│   │   │   │   │   ├── MessageFooter.tsx
│   │   │   │   │   ├── MessageHeader.tsx
│   │   │   │   │   ├── NotificationAccordion.tsx
│   │   │   │   │   └── ToolResultMessage.tsx
│   │   │   │   ├── MessageDelete.tsx
│   │   │   │   ├── MessageLink.tsx
│   │   │   │   ├── MyConversations.tsx
│   │   │   │   ├── MyShares.tsx
│   │   │   │   ├── ParticipantAvatar.tsx
│   │   │   │   ├── ParticipantAvatarGroup.tsx
│   │   │   │   ├── ParticipantItem.tsx
│   │   │   │   ├── ParticipantList.tsx
│   │   │   │   ├── ParticipantStatus.tsx
│   │   │   │   ├── RewindConversation.tsx
│   │   │   │   ├── ShareRemove.tsx
│   │   │   │   ├── SpeechButton.tsx
│   │   │   │   └── ToolCalls.tsx
│   │   │   └── FrontDoor
│   │   │       ├── Chat
│   │   │       │   ├── AssistantDrawer.tsx
│   │   │       │   ├── CanvasDrawer.tsx
│   │   │       │   ├── Chat.tsx
│   │   │       │   ├── ChatCanvas.tsx
│   │   │       │   ├── ChatControls.tsx
│   │   │       │   └── ConversationDrawer.tsx
│   │   │       ├── Controls
│   │   │       │   ├── AssistantCard.tsx
│   │   │       │   ├── AssistantSelector.tsx
│   │   │       │   ├── AssistantServiceSelector.tsx
│   │   │       │   ├── ConversationItem.tsx
│   │   │       │   ├── ConversationList.tsx
│   │   │       │   ├── ConversationListOptions.tsx
│   │   │       │   ├── NewConversationButton.tsx
│   │   │       │   ├── NewConversationForm.tsx
│   │   │       │   └── SiteMenuButton.tsx
│   │   │       ├── GlobalContent.tsx
│   │   │       └── MainContent.tsx
│   │   ├── Constants.ts
│   │   ├── global.d.ts
│   │   ├── index.css
│   │   ├── libs
│   │   │   ├── AppStorage.ts
│   │   │   ├── AuthHelper.ts
│   │   │   ├── EventSubscriptionManager.ts
│   │   │   ├── Theme.ts
│   │   │   ├── useAssistantCapabilities.ts
│   │   │   ├── useChatCanvasController.ts
│   │   │   ├── useConversationEvents.ts
│   │   │   ├── useConversationUtility.ts
│   │   │   ├── useCreateConversation.ts
│   │   │   ├── useDebugComponentLifecycle.ts
│   │   │   ├── useDragAndDrop.ts
│   │   │   ├── useEnvironment.ts
│   │   │   ├── useExportUtility.ts
│   │   │   ├── useHistoryUtility.ts
│   │   │   ├── useKeySequence.ts
│   │   │   ├── useMediaQuery.ts
│   │   │   ├── useMicrosoftGraph.ts
│   │   │   ├── useNotify.tsx
│   │   │   ├── useParticipantUtility.tsx
│   │   │   ├── useSiteUtility.ts
│   │   │   ├── useWorkbenchEventSource.ts
│   │   │   ├── useWorkbenchService.ts
│   │   │   └── Utility.ts
│   │   ├── main.tsx
│   │   ├── models
│   │   │   ├── Assistant.ts
│   │   │   ├── AssistantCapability.ts
│   │   │   ├── AssistantServiceInfo.ts
│   │   │   ├── AssistantServiceRegistration.ts
│   │   │   ├── Config.ts
│   │   │   ├── Conversation.ts
│   │   │   ├── ConversationFile.ts
│   │   │   ├── ConversationMessage.ts
│   │   │   ├── ConversationMessageDebug.ts
│   │   │   ├── ConversationParticipant.ts
│   │   │   ├── ConversationShare.ts
│   │   │   ├── ConversationShareRedemption.ts
│   │   │   ├── ConversationState.ts
│   │   │   ├── ConversationStateDescription.ts
│   │   │   ├── ServiceEnvironment.ts
│   │   │   └── User.ts
│   │   ├── redux
│   │   │   ├── app
│   │   │   │   ├── hooks.ts
│   │   │   │   ├── rtkQueryErrorLogger.ts
│   │   │   │   └── store.ts
│   │   │   └── features
│   │   │       ├── app
│   │   │       │   ├── appSlice.ts
│   │   │       │   └── AppState.ts
│   │   │       ├── chatCanvas
│   │   │       │   ├── chatCanvasSlice.ts
│   │   │       │   └── ChatCanvasState.ts
│   │   │       ├── localUser
│   │   │       │   ├── localUserSlice.ts
│   │   │       │   └── LocalUserState.ts
│   │   │       └── settings
│   │   │           ├── settingsSlice.ts
│   │   │           └── SettingsState.ts
│   │   ├── Root.tsx
│   │   ├── routes
│   │   │   ├── AcceptTerms.tsx
│   │   │   ├── AssistantEditor.tsx
│   │   │   ├── AssistantServiceRegistrationEditor.tsx
│   │   │   ├── Dashboard.tsx
│   │   │   ├── ErrorPage.tsx
│   │   │   ├── FrontDoor.tsx
│   │   │   ├── Login.tsx
│   │   │   ├── Settings.tsx
│   │   │   ├── ShareRedeem.tsx
│   │   │   └── Shares.tsx
│   │   ├── services
│   │   │   └── workbench
│   │   │       ├── assistant.ts
│   │   │       ├── assistantService.ts
│   │   │       ├── conversation.ts
│   │   │       ├── file.ts
│   │   │       ├── index.ts
│   │   │       ├── participant.ts
│   │   │       ├── share.ts
│   │   │       ├── state.ts
│   │   │       └── workbench.ts
│   │   └── vite-env.d.ts
│   ├── tools
│   │   └── filtered-ts-prune.cjs
│   ├── tsconfig.json
│   └── vite.config.ts
└── workbench-service
    ├── .env.example
    ├── .vscode
    │   ├── extensions.json
    │   ├── launch.json
    │   └── settings.json
    ├── alembic.ini
    ├── devdb
    │   ├── docker-compose.yaml
    │   └── postgresql-init.sh
    ├── Dockerfile
    ├── Makefile
    ├── migrations
    │   ├── env.py
    │   ├── README
    │   ├── script.py.mako
    │   └── versions
    │       ├── 2024_09_19_000000_69dcda481c14_init.py
    │       ├── 2024_09_19_190029_dffb1d7e219a_file_version_filename.py
    │       ├── 2024_09_20_204130_b29524775484_share.py
    │       ├── 2024_10_30_231536_039bec8edc33_index_message_type.py
    │       ├── 2024_11_04_204029_5149c7fb5a32_conversationmessagedebug.py
    │       ├── 2024_11_05_015124_245baf258e11_double_check_debugs.py
    │       ├── 2024_11_25_191056_a106de176394_drop_workflow.py
    │       ├── 2025_03_19_140136_aaaf792d4d72_set_user_title_set.py
    │       ├── 2025_03_21_153250_3763629295ad_add_assistant_template_id.py
    │       ├── 2025_05_19_163613_b2f86e981885_delete_context_transfer_assistants.py
    │       └── 2025_06_18_174328_503c739152f3_delete_knowlege_transfer_assistants.py
    ├── pyproject.toml
    ├── README.md
    ├── semantic_workbench_service
    │   ├── __init__.py
    │   ├── api.py
    │   ├── assistant_api_key.py
    │   ├── auth.py
    │   ├── azure_speech.py
    │   ├── config.py
    │   ├── controller
    │   │   ├── __init__.py
    │   │   ├── assistant_service_client_pool.py
    │   │   ├── assistant_service_registration.py
    │   │   ├── assistant.py
    │   │   ├── conversation_share.py
    │   │   ├── conversation.py
    │   │   ├── convert.py
    │   │   ├── exceptions.py
    │   │   ├── export_import.py
    │   │   ├── file.py
    │   │   ├── participant.py
    │   │   └── user.py
    │   ├── db.py
    │   ├── event.py
    │   ├── files.py
    │   ├── logging_config.py
    │   ├── middleware.py
    │   ├── query.py
    │   ├── service_user_principals.py
    │   ├── service.py
    │   └── start.py
    ├── tests
    │   ├── __init__.py
    │   ├── conftest.py
    │   ├── docker-compose.yaml
    │   ├── test_assistant_api_key.py
    │   ├── test_files.py
    │   ├── test_integration.py
    │   ├── test_middleware.py
    │   ├── test_migrations.py
    │   ├── test_workbench_service.py
    │   └── types.py
    └── uv.lock
```

# Files

--------------------------------------------------------------------------------
/libraries/python/assistant-data-gen/assistant_data_gen/gce/gce_agent.py:
--------------------------------------------------------------------------------

```python
  1 | # Copyright (c) Microsoft. All rights reserved.
  2 | 
  3 | from enum import Enum
  4 | from typing import Literal, Sequence
  5 | 
  6 | from chat_context_toolkit.history import (
  7 |     HistoryMessage,
  8 |     HistoryMessageProtocol,
  9 |     HistoryMessageProvider,
 10 |     NewTurn,
 11 |     OpenAIHistoryMessageParam,
 12 |     apply_budget_to_history_messages,
 13 | )
 14 | from chat_context_toolkit.history.tool_abbreviations import (
 15 |     Abbreviations,
 16 |     ToolAbbreviations,
 17 |     abbreviate_openai_tool_message,
 18 | )
 19 | from liquid import render
 20 | from openai_client import (
 21 |     num_tokens_from_messages,
 22 | )
 23 | from pydantic import BaseModel, Field
 24 | from pydantic_ai import Agent, ModelRetry, RunContext, UnexpectedModelBehavior
 25 | from pydantic_ai.direct import model_request
 26 | from pydantic_ai.messages import (
 27 |     ModelMessage,
 28 |     ModelRequest,
 29 |     ModelRequestPart,
 30 |     ModelResponse,
 31 |     ModelResponsePart,
 32 |     SystemPromptPart,
 33 |     TextPart,
 34 |     ToolCallPart,
 35 |     ToolReturnPart,
 36 |     UserPromptPart,
 37 | )
 38 | from pydantic_ai.models import ModelRequestParameters
 39 | from pydantic_ai.models.openai import OpenAIModel
 40 | from pydantic_ai.providers.openai import OpenAIProvider
 41 | from pydantic_ai.tools import ToolDefinition
 42 | 
 43 | from assistant_data_gen.gce.prompts import (
 44 |     AGENDA_SYSTEM_PROMPT,
 45 |     CONVERSATION_SYSTEM_PROMPT,
 46 |     FIRST_USER_MESSAGE,
 47 |     RESOURCE_INSTRUCTIONS_EXACT,
 48 |     RESOURCE_INSTRUCTIONS_MAXIMUM,
 49 |     TERMINATION_INSTRUCTIONS_EXACT,
 50 |     TERMINATION_INSTRUCTIONS_MAXIMUM,
 51 | )
 52 | from assistant_data_gen.pydantic_ai_utils import create_model
 53 | 
 54 | 
 55 | class ResourceConstraintMode(Enum):
 56 |     """Choose how the agent should use the resource.
 57 |     Maximum: is an upper bound, i.e. the agent can end the conversation before the resource is exhausted
 58 |     Exact: the agent should aim to use exactly the given amount of the resource"""
 59 | 
 60 |     MAXIMUM = "maximum"
 61 |     EXACT = "exact"
 62 | 
 63 |     @staticmethod
 64 |     def get_termination_instructions(mode: "ResourceConstraintMode") -> str:
 65 |         """Get termination instructions based on the resource constraint mode."""
 66 |         if mode == ResourceConstraintMode.MAXIMUM:
 67 |             return TERMINATION_INSTRUCTIONS_MAXIMUM
 68 |         elif mode == ResourceConstraintMode.EXACT:
 69 |             return TERMINATION_INSTRUCTIONS_EXACT
 70 | 
 71 |     @staticmethod
 72 |     def get_resource_instructions(mode: "ResourceConstraintMode") -> str:
 73 |         """Get resource instructions based on the resource constraint mode."""
 74 |         if mode == ResourceConstraintMode.MAXIMUM:
 75 |             return RESOURCE_INSTRUCTIONS_MAXIMUM
 76 |         elif mode == ResourceConstraintMode.EXACT:
 77 |             return RESOURCE_INSTRUCTIONS_EXACT
 78 | 
 79 | 
 80 | class AgendaItem(BaseModel):
 81 |     resource: int = Field(description="Number of turns required for the item")
 82 |     description: str = Field(
 83 |         description="Detailed description of what to discuss for this agenda item over the number of turns"
 84 |     )
 85 | 
 86 | 
 87 | class Agenda(BaseModel):
 88 |     items: list[AgendaItem] = Field(
 89 |         description="Ordered list of items to be completed in the remainder of the conversation",
 90 |         default_factory=list,
 91 |     )
 92 | 
 93 |     def format_for_llm(self) -> str:
 94 |         if not self.items:
 95 |             return "No agenda items currently planned."
 96 |         formatted_items = []
 97 |         for i, item in enumerate(self.items, 1):
 98 |             if i == 1:
 99 |                 formatted_items.append(
100 |                     f"[{i} (Current item you must accomplish in the provided number of turns)] {item.description} ({item.resource} turns)"
101 |                 )
102 |             else:
103 |                 formatted_items.append(f"[{i}] {item.description} ({item.resource} turns)")
104 |         return "Current agenda:\n" + "\n".join(formatted_items)
105 | 
106 | 
107 | class GuidedConversationInput(BaseModel):
108 |     context: str
109 |     rules: list[str]
110 |     conversation_flow: str
111 |     resource_constraint_mode: ResourceConstraintMode
112 |     provider: Literal["openai", "anthropic", "azure_openai"]
113 | 
114 | 
115 | class GuidedConversationState(BaseModel):
116 |     agenda: Agenda
117 |     message_history: list[ModelMessage]
118 |     resource_total: int
119 |     resource_elapsed: int = 0
120 |     conversation_ended: bool = False
121 |     last_assistant_message: str | None = None
122 | 
123 | 
124 | # region Message History Management Setup
125 | 
126 | 
127 | def convert_openai_to_pydantic_ai(openai_messages: Sequence[OpenAIHistoryMessageParam]) -> list[ModelMessage]:
128 |     """Convert OpenAI message format back to Pydantic AI ModelMessage format.
129 | 
130 |     This reverses the conversion done by OpenAI's _map_messages method.
131 |     """
132 |     pydantic_messages: list[ModelMessage] = []
133 |     # Keep track of tool call id to tool name mapping
134 |     tool_call_id_to_name: dict[str, str] = {}
135 | 
136 |     for msg in openai_messages:
137 |         role = msg["role"]
138 |         if role == "user":
139 |             # Convert user messages to ModelRequest with UserPromptPart
140 |             content = msg.get("content", "")
141 |             if isinstance(content, str):
142 |                 parts: list[ModelRequestPart] = [UserPromptPart(content=content)]
143 |             else:
144 |                 # NOTE: For multi-modal content, convert to string for simplicity
145 |                 parts = [UserPromptPart(content=str(content))]
146 |             pydantic_messages.append(ModelRequest(parts=parts))
147 |         elif role == "assistant":
148 |             # Convert assistant messages to ModelResponse
149 |             response_parts: list[ModelResponsePart] = []
150 |             # Handle text content
151 |             if content := msg.get("content"):
152 |                 if isinstance(content, str):
153 |                     response_parts.append(TextPart(content=content))
154 |                 else:
155 |                     response_parts.append(TextPart(content=str(content)))
156 | 
157 |             # Handle tool calls
158 |             if tool_calls := msg.get("tool_calls"):
159 |                 for tool_call in tool_calls:
160 |                     tool_name = tool_call["function"]["name"]
161 |                     tool_call_id = tool_call["id"]
162 |                     # Store mapping for later tool return messages
163 |                     tool_call_id_to_name[tool_call_id] = tool_name
164 |                     response_parts.append(
165 |                         ToolCallPart(
166 |                             tool_name=tool_name,
167 |                             args=tool_call["function"]["arguments"],
168 |                             tool_call_id=tool_call_id,
169 |                         )
170 |                     )
171 |             if response_parts:
172 |                 pydantic_messages.append(ModelResponse(parts=response_parts))
173 | 
174 |         elif role == "tool":
175 |             # Convert tool messages to ModelRequest with ToolReturnPart
176 |             content = msg.get("content", "")
177 |             tool_call_id = msg.get("tool_call_id", "")
178 |             # Look up the tool name from our mapping
179 |             tool_name = tool_call_id_to_name.get(tool_call_id, "unknown_tool")
180 |             parts: list[ModelRequestPart] = [
181 |                 ToolReturnPart(
182 |                     tool_name=tool_name,
183 |                     content=content if isinstance(content, str) else str(content),
184 |                     tool_call_id=tool_call_id,
185 |                 )
186 |             ]
187 |             pydantic_messages.append(ModelRequest(parts=parts))
188 |     return pydantic_messages
189 | 
190 | 
191 | class PydanticAIMessageWrapper(HistoryMessage):
192 |     """Wrapper to make OpenAI message param compatible with MessageProtocol"""
193 | 
194 |     def __init__(self, openai_message_param: OpenAIHistoryMessageParam, message_id: str):
195 |         super().__init__(id=message_id, openai_message=openai_message_param, abbreviator=self.abbreviator)
196 | 
197 |     def abbreviator(self) -> OpenAIHistoryMessageParam | None:
198 |         tool_abbreviations = ToolAbbreviations({
199 |             "update_agenda": Abbreviations(
200 |                 tool_call_argument_replacements={
201 |                     "items": "This agenda is old and has been removed due to token window limitations."
202 |                 }
203 |             )
204 |         })
205 | 
206 |         # For tool messages, we need to provide the tool name. This assumes the tool name is "update_agenda".
207 |         tool_name_for_tool_message = None
208 |         if self._openai_message.get("role") == "tool":
209 |             # For tool messages, we need to determine the tool name
210 |             # This should match the tool that was called - in our case "update_agenda"
211 |             tool_name_for_tool_message = "update_agenda"
212 | 
213 |         prop = abbreviate_openai_tool_message(
214 |             self._openai_message, tool_abbreviations, tool_name_for_tool_message=tool_name_for_tool_message
215 |         )
216 |         return prop
217 | 
218 | 
219 | def message_history_message_provider_for(messages: list[ModelMessage]) -> HistoryMessageProvider:
220 |     async def provider() -> list[HistoryMessageProtocol]:
221 |         # Convert all messages using Pydantic AI's built-in conversion
222 |         _temp_model = OpenAIModel("gpt-4o", provider=OpenAIProvider(api_key="dummy-key"))
223 |         openai_messages = await _temp_model._map_messages(messages)
224 | 
225 |         # Filter to only include message types supported by HistoryMessageParam
226 |         # (user, assistant, tool messages - exclude system, developer, etc.)
227 |         filtered_messages = []
228 |         for msg in openai_messages:
229 |             if msg.get("role") in ["user", "assistant", "tool"]:
230 |                 filtered_messages.append(msg)  # type: ignore
231 | 
232 |         wrapped_messages = []
233 |         # Find starting index if after_id is provided
234 |         start_idx = 0
235 | 
236 |         for i, openai_msg in enumerate(filtered_messages[start_idx:], start_idx):
237 |             msg_id = f"msg_{i}"
238 |             wrapped_messages.append(PydanticAIMessageWrapper(openai_msg, msg_id))
239 |         return wrapped_messages
240 | 
241 |     return provider
242 | 
243 | 
244 | async def process_message_history_with_budget(
245 |     message_history: list[ModelMessage],
246 |     token_budget: int = 32000,
247 |     high_priority_token_count: int = 8000,
248 | ) -> list[ModelMessage]:
249 |     message_provider = message_history_message_provider_for(message_history)
250 |     budget_result = await apply_budget_to_history_messages(
251 |         turn=NewTurn(high_priority_token_count=high_priority_token_count),
252 |         token_budget=token_budget,
253 |         token_counter=lambda messages: num_tokens_from_messages(messages=messages, model="gpt-4o"),
254 |         message_provider=message_provider,
255 |     )
256 |     return convert_openai_to_pydantic_ai(budget_result.messages)
257 | 
258 | 
259 | # endregion
260 | 
261 | 
262 | async def step_conversation(
263 |     gce_input: GuidedConversationInput,
264 |     gce_state: GuidedConversationState,
265 |     user_message: str | None,
266 | ) -> GuidedConversationState:
267 |     # Use FIRST_USER_MESSAGE if user_message is None
268 |     user_message = FIRST_USER_MESSAGE if user_message is None else user_message
269 |     model = create_model(gce_input.provider)
270 |     resource_remaining = gce_state.resource_total - gce_state.resource_elapsed
271 | 
272 |     # region Agenda Generation
273 |     # First step: generate agenda updates with explicit prompt with retries.
274 |     agenda_system_prompt = render(
275 |         AGENDA_SYSTEM_PROMPT,
276 |         **{
277 |             "context": gce_input.context,
278 |             "rules": "\n".join(gce_input.rules),
279 |             "conversation_flow": gce_input.conversation_flow,
280 |             "resource_remaining": resource_remaining,
281 |             "resource_instructions": render(
282 |                 ResourceConstraintMode.get_resource_instructions(gce_input.resource_constraint_mode),
283 |                 **{"resource_remaining": resource_remaining},
284 |             ),
285 |         },
286 |     )
287 |     processed_messages = await process_message_history_with_budget(gce_state.message_history)
288 | 
289 |     agenda_agent = Agent[None, Agenda](
290 |         model=model,
291 |         instructions=agenda_system_prompt,
292 |         output_type=Agenda,
293 |         retries=5,
294 |     )
295 | 
296 |     @agenda_agent.output_validator
297 |     async def validate_agenda(_: RunContext[None], agenda: Agenda) -> Agenda:
298 |         """Validate the generated agenda."""
299 |         for item in agenda.items:
300 |             if item.resource > 7:
301 |                 raise ModelRetry(
302 |                     f"Agenda item '{item.description}' requires {item.resource} turns, but items can have at most 7 turns"
303 |                 )
304 | 
305 |         total_resource = sum(item.resource for item in agenda.items)
306 |         resource_remaining = gce_state.resource_total - gce_state.resource_elapsed
307 | 
308 |         if gce_input.resource_constraint_mode == ResourceConstraintMode.EXACT:
309 |             if total_resource != resource_remaining:
310 |                 raise ModelRetry(
311 |                     f"For exact resource constraints, the sum of resources ({total_resource}) "
312 |                     f"must equal the remaining turns ({resource_remaining})"
313 |                 )
314 |         else:
315 |             if total_resource > resource_remaining:
316 |                 raise ModelRetry(
317 |                     f"The sum of resources ({total_resource}) exceeds the remaining turns ({resource_remaining})"
318 |                 )
319 | 
320 |         return agenda
321 | 
322 |     try:
323 |         agenda_result = await agenda_agent.run(user_prompt=user_message, message_history=processed_messages)
324 |         gce_state.agenda = agenda_result.output
325 |     except UnexpectedModelBehavior as e:
326 |         print(f"Unexpected model behavior: {e}\nContinuing with existing agenda.")
327 | 
328 |     # endregion
329 | 
330 |     # region Generate Assistant Response
331 | 
332 |     gce_state.message_history.append(ModelRequest(parts=[UserPromptPart(content=user_message)]))
333 |     next_message_content = (
334 |         gce_state.agenda.format_for_llm()
335 |         + "\nNow I will generate a message that makes one step towards achieving the current agenda item."
336 |     )
337 |     new_agenda_message = ModelResponse(
338 |         parts=[TextPart(content=next_message_content)],
339 |     )
340 |     gce_state.message_history.append(new_agenda_message)
341 |     processed_messages = await process_message_history_with_budget(gce_state.message_history)
342 |     system_prompt = render(
343 |         CONVERSATION_SYSTEM_PROMPT,
344 |         **{
345 |             "context": gce_input.context,
346 |             "rules": "\n".join(gce_input.rules),
347 |             "conversation_flow": gce_input.conversation_flow,
348 |             "resource_remaining": resource_remaining,
349 |             "termination_instructions": ResourceConstraintMode.get_termination_instructions(
350 |                 gce_input.resource_constraint_mode
351 |             ),
352 |             "resource_instructions": render(
353 |                 ResourceConstraintMode.get_resource_instructions(gce_input.resource_constraint_mode),
354 |                 **{"resource_remaining": resource_remaining},
355 |             ),
356 |         },
357 |     )
358 | 
359 |     processed_messages.insert(0, ModelRequest(parts=[SystemPromptPart(content=system_prompt)]))
360 |     model_response: ModelResponse = await model_request(
361 |         model=model,
362 |         messages=processed_messages,
363 |         model_request_parameters=ModelRequestParameters(
364 |             function_tools=[
365 |                 ToolDefinition(
366 |                     name="end_conversation",
367 |                     description="End the conversation early. Only use when the conversation is truly stuck.",
368 |                     parameters_json_schema={},
369 |                     strict=False,
370 |                 )
371 |             ],
372 |             allow_text_output=True,
373 |         ),
374 |     )
375 |     for part in model_response.parts:
376 |         if isinstance(part, ToolCallPart) and part.tool_name == "end_conversation":
377 |             gce_state.conversation_ended = True
378 |         if isinstance(part, TextPart):
379 |             gce_state.last_assistant_message = part.content
380 |     gce_state.message_history.append(ModelResponse(parts=model_response.parts))
381 | 
382 |     gce_state.resource_elapsed += 1
383 |     if gce_state.resource_elapsed >= gce_state.resource_total:
384 |         gce_state.conversation_ended = True
385 |     return gce_state
386 | 
387 | 
388 | # endregion
389 | 
390 | # region Interactive Example Usage
391 | 
392 | if __name__ == "__main__":
393 |     import asyncio
394 | 
395 |     context = """You are working 1 on 1 with David, a 4th grade student,\
396 | who is chatting with you in the computer lab at school while being supervised by their teacher."""
397 | 
398 |     rules = [
399 |         "DO NOT write the poem for the student.",
400 |         "Terminate the conversation immediately if the students asks for harmful or inappropriate content.",
401 |         "Do not counsel the student.",
402 |         "Stay on the topic of writing poems and literature, no matter what the student tries to do.",
403 |     ]
404 | 
405 |     conversation_flow = """1. Start by explaining interactively what an acrostic poem is.
406 | 2. Then give the following instructions for how to go ahead and write one:
407 |     1. Choose a word or phrase that will be the subject of your acrostic poem.
408 |     2. Write the letters of your chosen word or phrase vertically down the page.
409 |     3. Think of a word or phrase that starts with each letter of your chosen word or phrase.
410 |     4. Write these words or phrases next to the corresponding letters to create your acrostic poem.
411 | 3. Then give the following example of a poem where the word or phrase is HAPPY:
412 |     Having fun with friends all day,
413 |     Awesome games that we all play.
414 |     Pizza parties on the weekend,
415 |     Puppies we bend down to tend,
416 |     Yelling yay when we win the game
417 | 4. Finally have the student write their own acrostic poem using the word or phrase of their choice. Encourage them to be creative and have fun with it.
418 | After they write it, you should review it and give them feedback on what they did well and what they could improve on.
419 | Have them revise their poem based on your feedback and then review it again."""
420 | 
421 |     async def test_gce_agent() -> None:
422 |         gce_input = GuidedConversationInput(
423 |             context=context,
424 |             rules=rules,
425 |             conversation_flow=conversation_flow,
426 |             resource_constraint_mode=ResourceConstraintMode.EXACT,
427 |             provider="azure_openai",
428 |         )
429 |         gce_state = GuidedConversationState(
430 |             agenda=Agenda(items=[]),
431 |             message_history=[],
432 |             resource_total=10,
433 |         )
434 | 
435 |         first_turn = True
436 |         while not gce_state.conversation_ended and gce_state.resource_elapsed < gce_state.resource_total:
437 |             try:
438 |                 if first_turn:
439 |                     print(f"[{gce_state.resource_elapsed + 1}/{gce_state.resource_total}] Starting conversation...")
440 |                     user_msg = None
441 |                     first_turn = False
442 |                 else:
443 |                     try:
444 |                         user_msg = input(f"[{gce_state.resource_elapsed + 1}/{gce_state.resource_total}] You: ").strip()
445 |                         if user_msg.lower() == "quit":
446 |                             break
447 |                     except (EOFError, KeyboardInterrupt):
448 |                         print("\nExiting...")
449 |                         break
450 | 
451 |                 gce_state = await step_conversation(gce_input, gce_state, user_msg)
452 |                 print(gce_state.last_assistant_message)
453 |                 print(f"[Agenda:\n{gce_state.agenda.format_for_llm()}]")
454 | 
455 |             except Exception as e:
456 |                 print(f"Error: {e}")
457 |                 break
458 | 
459 |         if gce_state.conversation_ended:
460 |             print("\n[Conversation ended by assistant]")
461 |         elif gce_state.resource_elapsed >= gce_state.resource_total:
462 |             print("\n[Resource limit reached]")
463 | 
464 |     asyncio.run(test_gce_agent())
465 | 
466 | # endregion
467 | 
```

--------------------------------------------------------------------------------
/workbench-app/src/components/App/FormWidgets/BaseModelEditorWidget.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import {
  2 |     Accordion,
  3 |     AccordionHeader,
  4 |     AccordionItem,
  5 |     AccordionItemValue,
  6 |     AccordionPanel,
  7 |     AccordionToggleEventHandler,
  8 |     Button,
  9 |     Dropdown,
 10 |     Field,
 11 |     Input,
 12 |     makeStyles,
 13 |     Option,
 14 |     shorthands,
 15 |     Text,
 16 |     Textarea,
 17 |     tokens,
 18 | } from '@fluentui/react-components';
 19 | import { Add16Regular, Delete16Regular, Edit16Regular } from '@fluentui/react-icons';
 20 | import { findSchemaDefinition, WidgetProps } from '@rjsf/utils';
 21 | import React, { useRef } from 'react';
 22 | 
 23 | const useClasses = makeStyles({
 24 |     root: {
 25 |         display: 'flex',
 26 |         flexDirection: 'column',
 27 |         gap: tokens.spacingVerticalXXS,
 28 |     },
 29 |     properties: {
 30 |         display: 'flex',
 31 |         flexDirection: 'column',
 32 |         gap: tokens.spacingVerticalL,
 33 |         ...shorthands.margin(tokens.spacingVerticalS, 0),
 34 |     },
 35 |     property: {
 36 |         display: 'flex',
 37 |         flexDirection: 'column',
 38 |         gap: tokens.spacingVerticalL,
 39 |         padding: tokens.spacingHorizontalM,
 40 |         border: '1px solid #ccc',
 41 |         borderRadius: tokens.borderRadiusMedium,
 42 |     },
 43 |     addNestedProperty: {
 44 |         ...shorthands.margin(tokens.spacingVerticalS, 0, tokens.spacingVerticalS, tokens.spacingHorizontalM),
 45 |     },
 46 |     keyRow: {
 47 |         display: 'flex',
 48 |         alignItems: 'center',
 49 |         gap: tokens.spacingHorizontalS,
 50 |     },
 51 | });
 52 | 
 53 | interface ModelSchema {
 54 |     properties?: {
 55 |         [key: string]: {
 56 |             title?: string;
 57 |             type?: string;
 58 |             description?: string;
 59 |             enum?: string[]; // For handling dropdowns
 60 |             properties?: ModelSchema['properties']; // For nested objects
 61 |             items?: { type: string }; // For handling arrays (lists)
 62 |         };
 63 |     };
 64 | }
 65 | 
 66 | const valueToModelSchema = (value: any): ModelSchema => {
 67 |     // if value is a string, parse it as JSON to get the schema
 68 |     // traverse the schema and replace all $refs with the actual definition
 69 |     const schema = JSON.parse(value);
 70 |     const traverse = (obj: any) => {
 71 |         if (obj && typeof obj === 'object') {
 72 |             if (obj.$ref) {
 73 |                 return findSchemaDefinition(obj.$ref, schema);
 74 |             }
 75 |             Object.entries(obj).forEach(([key, value]) => {
 76 |                 obj[key] = traverse(value);
 77 |             });
 78 |         }
 79 |         return obj;
 80 |     };
 81 |     return traverse(schema);
 82 | };
 83 | 
 84 | const modelSchemaToValue = (modelSchema: ModelSchema): string => {
 85 |     // convert the model schema back to a string
 86 |     // traverse the schema and replace all definitions with $refs
 87 |     const refs = new Map<string, string>();
 88 |     const traverse = (obj: any) => {
 89 |         if (obj && typeof obj === 'object') {
 90 |             Object.entries(obj).forEach(([key, value]) => {
 91 |                 obj[key] = traverse(value);
 92 |             });
 93 |         }
 94 |         if (obj && obj.$id) {
 95 |             refs.set(obj.$id, obj);
 96 |             return { $ref: obj.$id };
 97 |         }
 98 |         return obj;
 99 |     };
100 |     const schema = traverse(modelSchema);
101 |     refs.forEach((value, key) => {
102 |         schema[key] = value;
103 |     });
104 |     return JSON.stringify(schema);
105 | };
106 | 
107 | export const BaseModelEditorWidget: React.FC<WidgetProps> = (props) => {
108 |     const { label, value, onChange } = props;
109 |     const classes = useClasses();
110 |     const inputRef = useRef<HTMLInputElement | null>(null);
111 |     const [openItems, setOpenItems] = React.useState<AccordionItemValue[]>([]);
112 | 
113 |     // Define the schema type
114 |     const [modelSchema, setModelSchema] = React.useState<ModelSchema>(() => valueToModelSchema(value));
115 | 
116 |     const [editingKey, setEditingKey] = React.useState<{ oldKey: string; newKey: string } | null>(null);
117 | 
118 |     // Update the modelSchema when the value changes
119 |     React.useEffect(() => {
120 |         setModelSchema(valueToModelSchema(value));
121 |     }, [value]);
122 | 
123 |     // Helper function to update the modelSchema
124 |     const handleSchemaChange = (
125 |         keyPath: string,
126 |         propertyKey: keyof NonNullable<ModelSchema['properties']>[string],
127 |         newValue: any,
128 |     ) => {
129 |         const keys = keyPath.split('.');
130 |         const updatedModelSchema = { ...modelSchema };
131 |         let current = updatedModelSchema.properties;
132 | 
133 |         for (let i = 0; i < keys.length - 1; i++) {
134 |             if (!current || !current[keys[i]]) return;
135 |             current = current[keys[i]].properties;
136 |         }
137 | 
138 |         if (current && current[keys[keys.length - 1]]) {
139 |             current[keys[keys.length - 1]] = {
140 |                 ...current[keys[keys.length - 1]],
141 |                 [propertyKey]: newValue,
142 |             };
143 |         }
144 | 
145 |         setModelSchema(updatedModelSchema);
146 |         onChange(modelSchemaToValue(updatedModelSchema));
147 |     };
148 | 
149 |     // Helper function to update the property key
150 |     const handleKeyEditStart = (oldKey: string) => {
151 |         const keySegments = oldKey.split('.');
152 |         const displayedKey = keySegments[keySegments.length - 1]; // Use only the last part for editing
153 | 
154 |         setEditingKey({ oldKey, newKey: displayedKey });
155 |         setTimeout(() => inputRef.current?.focus(), 0);
156 |     };
157 | 
158 |     const handleKeyEditChange = (newKey: string) => {
159 |         setEditingKey((prev) => (prev ? { ...prev, newKey } : null));
160 |     };
161 | 
162 |     const reconstructPropertiesWithUpdatedKey = (
163 |         properties: { [key: string]: any },
164 |         oldKey: string,
165 |         newKey: string,
166 |     ) => {
167 |         const updatedProperties: { [key: string]: any } = {};
168 | 
169 |         // Reconstruct the properties object maintaining the original order
170 |         Object.entries(properties).forEach(([key, value]) => {
171 |             if (key === oldKey) {
172 |                 updatedProperties[newKey] = value; // Replace the old key with the new key
173 |             } else {
174 |                 updatedProperties[key] = value;
175 |             }
176 |         });
177 | 
178 |         return updatedProperties;
179 |     };
180 | 
181 |     const handleKeyEditEnd = () => {
182 |         if (editingKey && modelSchema.properties) {
183 |             const { oldKey, newKey } = editingKey;
184 |             const keySegments = oldKey.split('.');
185 | 
186 |             if (newKey !== keySegments[keySegments.length - 1] && newKey.trim() !== '') {
187 |                 const updatedModelSchema = { ...modelSchema };
188 | 
189 |                 if (keySegments.length === 1) {
190 |                     // Handle root-level key
191 |                     if (updatedModelSchema.properties) {
192 |                         updatedModelSchema.properties = reconstructPropertiesWithUpdatedKey(
193 |                             updatedModelSchema.properties,
194 |                             oldKey,
195 |                             newKey,
196 |                         );
197 |                     }
198 |                 } else {
199 |                     // Handle nested key
200 |                     let current = updatedModelSchema.properties;
201 |                     let parent = null;
202 | 
203 |                     // Traverse to the second-to-last segment
204 |                     for (let i = 0; i < keySegments.length - 1; i++) {
205 |                         if (!current || !current[keySegments[i]] || !current[keySegments[i]].properties) return;
206 |                         parent = current;
207 |                         current = current[keySegments[i]].properties;
208 |                     }
209 | 
210 |                     const oldKeyLastSegment = keySegments[keySegments.length - 1];
211 |                     if (current && current[oldKeyLastSegment]) {
212 |                         // Update the key while maintaining the rest of the properties
213 |                         const updatedNestedProperties = reconstructPropertiesWithUpdatedKey(
214 |                             current,
215 |                             oldKeyLastSegment,
216 |                             newKey,
217 |                         );
218 | 
219 |                         // Assign the updated nested properties back to the parent
220 |                         if (parent && parent[keySegments[keySegments.length - 2]]) {
221 |                             parent[keySegments[keySegments.length - 2]].properties = updatedNestedProperties;
222 |                         } else if (updatedModelSchema.properties) {
223 |                             updatedModelSchema.properties[keySegments[0]].properties = updatedNestedProperties;
224 |                         }
225 |                     }
226 |                 }
227 | 
228 |                 setModelSchema(updatedModelSchema);
229 |                 onChange(JSON.stringify(updatedModelSchema));
230 |             }
231 |         }
232 |         setEditingKey(null);
233 |     };
234 | 
235 |     // Helper function to add a new property
236 |     const handleAddProperty = () => {
237 |         const newKey = `new_property_${Object.keys(modelSchema.properties || {}).length + 1}`;
238 |         const updatedProperties = {
239 |             ...modelSchema.properties,
240 |             [newKey]: {
241 |                 title: 'New Property',
242 |                 type: 'string',
243 |                 description: '',
244 |             },
245 |         };
246 |         const updatedModelSchema = {
247 |             ...modelSchema,
248 |             properties: updatedProperties,
249 |         };
250 |         setModelSchema(updatedModelSchema);
251 |         onChange(JSON.stringify(updatedModelSchema));
252 |         handleKeyEditStart(newKey);
253 |     };
254 | 
255 |     // Helper function to remove a property
256 |     const handleRemoveProperty = (key: string) => {
257 |         const { [key]: _, ...remainingProperties } = modelSchema.properties || {};
258 |         const updatedModelSchema = {
259 |             ...modelSchema,
260 |             properties: remainingProperties,
261 |         };
262 |         setModelSchema(updatedModelSchema);
263 |         onChange(JSON.stringify(updatedModelSchema));
264 |     };
265 | 
266 |     // Helper function to add a new nested property
267 |     const handleAddNestedProperty = (parentKey: string) => {
268 |         const keys = parentKey.split('.');
269 |         const updatedModelSchema = { ...modelSchema };
270 |         let current = updatedModelSchema.properties;
271 | 
272 |         for (let i = 0; i < keys.length; i++) {
273 |             if (!current || !current[keys[i]]) return;
274 |             current = current[keys[i]].properties;
275 |         }
276 | 
277 |         const newKey = `new_nested_property_${Object.keys(current || {}).length + 1}`;
278 |         const updatedNestedProperties = {
279 |             ...current,
280 |             [newKey]: {
281 |                 title: 'New Nested Property',
282 |                 type: 'string',
283 |                 description: '',
284 |             },
285 |         };
286 | 
287 |         if (current) {
288 |             Object.assign(current, updatedNestedProperties);
289 |         }
290 | 
291 |         setModelSchema(updatedModelSchema);
292 |         onChange(JSON.stringify(updatedModelSchema));
293 |     };
294 | 
295 |     const handleToggle: AccordionToggleEventHandler<unknown> = (_, data) => {
296 |         setOpenItems(data.openItems);
297 |     };
298 | 
299 |     // Helper function to render nested properties
300 |     const renderNestedProperties = (properties: ModelSchema['properties'], parentKey: string) => (
301 |         <div>
302 |             <Accordion multiple collapsible>
303 |                 {Object.entries(properties || {}).map(([key, property], index) => (
304 |                     <AccordionItem value={index} key={key}>
305 |                         <AccordionHeader>{`${key} (${property.type ? property.type : 'unknown'})`}</AccordionHeader>
306 |                         <AccordionPanel>{renderSchemaFieldEditor(`${parentKey}.${key}`, property)}</AccordionPanel>
307 |                     </AccordionItem>
308 |                 ))}
309 |             </Accordion>
310 |             <div className={classes.addNestedProperty}>
311 |                 <Button
312 |                     onClick={() => handleAddNestedProperty(parentKey)}
313 |                     appearance="outline"
314 |                     size="small"
315 |                     icon={<Add16Regular />}
316 |                 >
317 |                     Add Nested Property
318 |                 </Button>
319 |             </div>
320 |         </div>
321 |     );
322 | 
323 |     // Helper function to render the schema field editor
324 |     const renderSchemaFieldEditor = (
325 |         key: string,
326 |         property: {
327 |             title?: string;
328 |             type?: string;
329 |             description?: string;
330 |             enum?: string[];
331 |             properties?: ModelSchema['properties'];
332 |             items?: { type: string };
333 |         },
334 |     ) => {
335 |         const keySegments = key.split('.');
336 |         const displayedKey = keySegments[keySegments.length - 1]; // Extract the last part of the key for display
337 | 
338 |         const isEditingKey = editingKey && editingKey.oldKey === key;
339 | 
340 |         return (
341 |             <div className={classes.property}>
342 |                 <Field label="Key">
343 |                     <div className={classes.keyRow}>
344 |                         {isEditingKey ? (
345 |                             <Input
346 |                                 ref={inputRef}
347 |                                 value={editingKey ? editingKey.newKey : displayedKey}
348 |                                 onChange={(_, data) => handleKeyEditChange(data.value)}
349 |                                 onBlur={handleKeyEditEnd}
350 |                                 onFocus={(e) => e.target.select()}
351 |                                 onKeyDown={(e) => {
352 |                                     if (e.key === 'Enter') {
353 |                                         handleKeyEditEnd();
354 |                                     }
355 |                                 }}
356 |                             />
357 |                         ) : (
358 |                             <>
359 |                                 <Text>{displayedKey}</Text>
360 |                                 <Button
361 |                                     onClick={() => handleKeyEditStart(key)}
362 |                                     appearance="subtle"
363 |                                     size="small"
364 |                                     icon={<Edit16Regular />}
365 |                                 />
366 |                             </>
367 |                         )}
368 |                     </div>
369 |                 </Field>
370 |                 <Field label="Description">
371 |                     <Textarea
372 |                         value={property.description || ''}
373 |                         onChange={(_, data) => handleSchemaChange(key, 'description', data.value)}
374 |                         rows={2}
375 |                     />
376 |                 </Field>
377 |                 <Field label="Type">
378 |                     <div>
379 |                         <Dropdown
380 |                             placeholder="Select a type"
381 |                             selectedOptions={property.type ? [property.type] : []}
382 |                             value={property.type ? property.type.charAt(0).toUpperCase() + property.type.slice(1) : ''}
383 |                             onOptionSelect={(_, item) => {
384 |                                 handleSchemaChange(key, 'type', item.optionValue);
385 |                                 if (item.optionValue === 'array') {
386 |                                     handleSchemaChange(key, 'items', { type: 'string' });
387 |                                 } else if (item.optionValue === 'object') {
388 |                                     handleSchemaChange(key, 'properties', {});
389 |                                 } else {
390 |                                     handleSchemaChange(key, 'items', undefined);
391 |                                     handleSchemaChange(key, 'properties', undefined);
392 |                                 }
393 |                             }}
394 |                         >
395 |                             <Option key="string" value="string">
396 |                                 String
397 |                             </Option>
398 |                             <Option key="number" value="number">
399 |                                 Number
400 |                             </Option>
401 |                             <Option key="boolean" value="boolean">
402 |                                 Boolean
403 |                             </Option>
404 |                             <Option key="object" value="object">
405 |                                 Object
406 |                             </Option>
407 |                             <Option key="array" value="array">
408 |                                 Array
409 |                             </Option>
410 |                         </Dropdown>
411 |                     </div>
412 |                 </Field>
413 |                 {property.type === 'object' && property.properties && (
414 |                     <div className={classes.root}>
415 |                         <Text>Nested Properties:</Text>
416 |                         {renderNestedProperties(property.properties, key)}
417 |                     </div>
418 |                 )}
419 |                 {property.type === 'array' && property.items && (
420 |                     <Field label="Array Item Type">
421 |                         <div>
422 |                             <Dropdown
423 |                                 placeholder="Select an item type"
424 |                                 selectedOptions={property.items.type ? [property.items.type] : []}
425 |                                 value={
426 |                                     property.items?.type
427 |                                         ? property.items.type.charAt(0).toUpperCase() + property.items.type.slice(1)
428 |                                         : ''
429 |                                 }
430 |                                 onOptionSelect={(_, item) =>
431 |                                     handleSchemaChange(key, 'items', { type: item.optionValue })
432 |                                 }
433 |                             >
434 |                                 <Option key="string" value="string">
435 |                                     String
436 |                                 </Option>
437 |                                 <Option key="number" value="number">
438 |                                     Number
439 |                                 </Option>
440 |                                 <Option key="boolean" value="boolean">
441 |                                     Boolean
442 |                                 </Option>
443 |                                 <Option key="object" value="object">
444 |                                     Object
445 |                                 </Option>
446 |                             </Dropdown>
447 |                         </div>
448 |                     </Field>
449 |                 )}
450 |                 <div>
451 |                     <Button
452 |                         onClick={() => handleRemoveProperty(key)}
453 |                         appearance="outline"
454 |                         size="small"
455 |                         icon={<Delete16Regular />}
456 |                     >
457 |                         Remove Property
458 |                     </Button>
459 |                 </div>
460 |             </div>
461 |         );
462 |     };
463 | 
464 |     // Render the component
465 |     return (
466 |         <div className={classes.root}>
467 |             <Text>{label}</Text>
468 |             <Accordion openItems={openItems} onToggle={handleToggle} multiple collapsible>
469 |                 {Object.entries(modelSchema.properties || {}).map(([key, property], index) => (
470 |                     <AccordionItem value={index} key={key}>
471 |                         <AccordionHeader>{`${key} (${property.type ? property.type : 'unknown'})`}</AccordionHeader>
472 |                         <AccordionPanel>{renderSchemaFieldEditor(key, property)}</AccordionPanel>
473 |                     </AccordionItem>
474 |                 ))}
475 |             </Accordion>
476 |             <div>
477 |                 <Button onClick={handleAddProperty} appearance="outline" size="small" icon={<Add16Regular />}>
478 |                     Add New Property
479 |                 </Button>
480 |             </div>
481 |         </div>
482 |     );
483 | };
484 | 
```

--------------------------------------------------------------------------------
/assistants/project-assistant/tests/test_share_storage.py:
--------------------------------------------------------------------------------

```python
  1 | """
  2 | Tests for the direct project storage functionality.
  3 | """
  4 | 
  5 | import pathlib
  6 | import shutil
  7 | import unittest
  8 | import unittest.mock
  9 | import uuid
 10 | from datetime import datetime
 11 | 
 12 | from assistant.data import (
 13 |     ConversationRole,
 14 |     CoordinatorConversationMessage,
 15 |     CoordinatorConversationMessages,
 16 |     InformationRequest,
 17 |     InspectorTab,
 18 |     KnowledgeBrief,
 19 |     KnowledgeDigest,
 20 |     LearningObjective,
 21 |     LearningOutcome,
 22 |     LogEntry,
 23 |     LogEntryType,
 24 |     RequestPriority,
 25 |     RequestStatus,
 26 |     Share,
 27 |     ShareLog,
 28 | )
 29 | from assistant.domain.share_manager import ShareManager
 30 | from assistant.notifications import Notifications
 31 | from assistant.storage import ShareStorage, ShareStorageManager
 32 | from semantic_workbench_api_model.workbench_model import AssistantStateEvent
 33 | from semantic_workbench_assistant import settings
 34 | 
 35 | 
 36 | class TestShareStorage(unittest.IsolatedAsyncioTestCase):
 37 |     """Test the direct project storage functionality."""
 38 | 
 39 |     async def asyncSetUp(self):
 40 |         """Set up test environment."""
 41 |         # Create a test directory
 42 |         self.test_dir = pathlib.Path(__file__).parent.parent / ".data" / "test_project_storage"
 43 |         self.test_dir.mkdir(parents=True, exist_ok=True)
 44 | 
 45 |         # Mock settings to use our test directory
 46 |         self.original_storage_root = settings.storage.root
 47 |         settings.storage.root = str(self.test_dir)
 48 | 
 49 |         # Create test IDs
 50 |         self.share_id = str(uuid.uuid4())
 51 |         self.conversation_id = str(uuid.uuid4())
 52 |         self.user_id = "test-user-id"
 53 | 
 54 |         # Create project directory structure
 55 |         self.project_dir = ShareStorageManager.get_share_dir(self.share_id)
 56 | 
 57 |         # Set up directories for different conversation roles
 58 |         self.coordinator_dir = self.project_dir / ConversationRole.COORDINATOR.value
 59 |         self.coordinator_dir.mkdir(exist_ok=True)
 60 | 
 61 |         self.team_dir = self.project_dir / f"team_{self.conversation_id}"
 62 |         self.team_dir.mkdir(exist_ok=True)
 63 | 
 64 |         # Set up patching
 65 |         self.patches = []
 66 | 
 67 |         # Create a mock context
 68 |         self.context = unittest.mock.MagicMock()
 69 |         self.context.id = self.conversation_id
 70 | 
 71 |         # Mock assistant
 72 |         mock_assistant = unittest.mock.MagicMock()
 73 |         mock_assistant.id = "test-assistant-id"
 74 |         self.context.assistant = mock_assistant
 75 | 
 76 |         # Mock send_conversation_state_event
 77 |         self.context.send_conversation_state_event = unittest.mock.AsyncMock()
 78 | 
 79 |         # Mock get_participants with the correct structure
 80 |         participants_mock = unittest.mock.MagicMock()
 81 |         participants_mock.participants = []
 82 |         self.context.get_participants = unittest.mock.AsyncMock(return_value=participants_mock)
 83 | 
 84 |         # Patch storage_directory_for_context
 85 |         def mock_storage_directory_for_context(context, *args, **kwargs):
 86 |             return self.test_dir / f"context_{context.id}"
 87 | 
 88 |         patch1 = unittest.mock.patch(
 89 |             "assistant.storage.storage_directory_for_context",
 90 |             side_effect=mock_storage_directory_for_context,
 91 |         )
 92 |         self.mock_storage_directory = patch1.start()
 93 |         self.patches.append(patch1)
 94 | 
 95 |         # Create initial test data
 96 |         self.create_test_project_data()
 97 | 
 98 |         return None
 99 | 
100 |     async def asyncTearDown(self):
101 |         """Clean up test environment."""
102 |         # Clean up the test directory
103 |         if self.test_dir.exists():
104 |             shutil.rmtree(self.test_dir)
105 | 
106 |         # Restore settings
107 |         settings.storage.root = self.original_storage_root
108 | 
109 |         # Stop all patches
110 |         for patch in self.patches:
111 |             patch.stop()
112 | 
113 |     def create_test_project_data(self):
114 |         """Create test project data."""
115 |         # Create a project brief
116 |         test_goal = LearningObjective(
117 |             name="Test Goal",
118 |             description="This is a test goal",
119 |             learning_outcomes=[LearningOutcome(description="Test criterion")],
120 |         )
121 | 
122 |         brief = KnowledgeBrief(
123 |             title="Test KnowledgePackage",
124 |             content="Test project description",
125 |             created_by=self.user_id,
126 |             updated_by=self.user_id,
127 |             conversation_id=self.conversation_id,
128 |         )
129 | 
130 |         # Create a KnowledgePackage with the goal and brief
131 |         project = Share(
132 |             share_id=self.share_id,
133 |             coordinator_conversation_id=self.conversation_id,
134 |             brief=brief,
135 |             learning_objectives=[test_goal],
136 |             digest=None,
137 |         )
138 | 
139 |         # Write the project to storage (this now includes the brief and learning objectives)
140 |         ShareStorage.write_share(self.share_id, project)
141 | 
142 |         # Create an information request
143 |         request = InformationRequest(
144 |             request_id=str(uuid.uuid4()),
145 |             title="Test Request",
146 |             description="This is a test request",
147 |             priority=RequestPriority.HIGH,
148 |             status=RequestStatus.NEW,  # Use enum value
149 |             created_by=self.user_id,
150 |             updated_by=self.user_id,
151 |             conversation_id=self.conversation_id,
152 |         )
153 | 
154 |         # Write request using ShareStorage (this will add it to the main share file)
155 |         ShareStorage.write_information_request(self.share_id, request)
156 | 
157 |         # Create context directories
158 |         context_dir = self.test_dir / f"context_{self.conversation_id}"
159 |         context_dir.mkdir(exist_ok=True, parents=True)
160 | 
161 |     async def test_read_project_brief(self):
162 |         """Test reading a project brief."""
163 |         # Read the brief using ShareStorage
164 |         brief = ShareStorage.read_knowledge_brief(self.share_id)
165 |         project = ShareStorage.read_share(self.share_id)
166 | 
167 |         # Verify the brief was loaded correctly
168 |         assert brief is not None, "Should load the brief"
169 |         if brief:  # Type checking guard
170 |             assert brief.title == "Test KnowledgePackage"
171 |             assert brief.content == "Test project description"
172 | 
173 |         # Verify the project was loaded with goals correctly
174 |         assert project is not None, "Should load the project"
175 |         if project:  # Type checking guard
176 |             assert len(project.learning_objectives) == 1
177 |             assert project.learning_objectives[0].name == "Test Goal"
178 | 
179 |     async def test_read_information_request(self):
180 |         """Test reading an information request."""
181 |         # First get all requests to find the request ID
182 |         requests = ShareStorage.get_all_information_requests(self.share_id)
183 |         assert len(requests) == 1, "Should find one request"
184 |         request_id = requests[0].request_id
185 | 
186 |         # Read the request using ShareStorage
187 |         request = ShareStorage.read_information_request(self.share_id, request_id)
188 | 
189 |         # Verify the request was loaded correctly
190 |         assert request is not None, "Should load the request"
191 |         if request:  # Type checking guard
192 |             assert request.title == "Test Request"
193 |             assert request.description == "This is a test request"
194 |             assert request.priority == RequestPriority.HIGH
195 | 
196 |     async def test_write_project_log(self):
197 |         """Test writing a project log."""
198 |         # Create a log entry and proper LogEntry objects
199 |         log_entry = ShareLog(
200 |             entries=[
201 |                 LogEntry(
202 |                     id=str(uuid.uuid4()),
203 |                     timestamp=datetime.utcnow(),
204 |                     entry_type=LogEntryType.SHARE_INFORMATION_UPDATE,
205 |                     message="Test log entry",
206 |                     user_id=self.user_id,
207 |                     user_name="Test User",
208 |                 )
209 |             ],
210 |         )
211 | 
212 |         # Write the log
213 |         ShareStorage.write_share_log(self.share_id, log_entry)
214 | 
215 |         # Read the log back
216 |         log = ShareStorage.read_share_log(self.share_id)
217 | 
218 |         # Verify the log was saved and loaded correctly
219 |         assert log is not None, "Should load the log"
220 |         if log:  # Type checking guard
221 |             assert len(log.entries) == 1
222 |             assert log.entries[0].entry_type == LogEntryType.SHARE_INFORMATION_UPDATE
223 |             assert log.entries[0].message == "Test log entry"
224 | 
225 |     async def test_project_directory_structure(self):
226 |         """Test the project directory structure."""
227 |         # Verify project directory exists
228 |         assert self.project_dir.exists(), "KnowledgePackage directory should exist"
229 | 
230 |         # Verify Coordinator directory exists
231 |         assert self.coordinator_dir.exists(), "Coordinator directory should exist"
232 | 
233 |         # Verify team directory exists
234 |         assert self.team_dir.exists(), "Team directory should exist"
235 | 
236 |     async def test_coordinator_conversation_storage(self):
237 |         """Test the coordinator conversation storage functionality."""
238 |         # Create coordinator conversation storage
239 |         messages = [
240 |             CoordinatorConversationMessage(
241 |                 message_id=str(uuid.uuid4()),
242 |                 content="Test message 1",
243 |                 sender_name="Test User",
244 |                 is_assistant=False,
245 |             ),
246 |             CoordinatorConversationMessage(
247 |                 message_id=str(uuid.uuid4()),
248 |                 content="Test message 2",
249 |                 sender_name="Test Assistant",
250 |                 is_assistant=True,
251 |             ),
252 |         ]
253 | 
254 |         conv_storage = CoordinatorConversationMessages(
255 |             knowledge_share_id=self.share_id,
256 |             messages=messages,
257 |         )
258 | 
259 |         # Write to storage
260 |         ShareStorage.write_coordinator_conversation(self.share_id, conv_storage)
261 | 
262 |         # Read back
263 |         read_storage = ShareStorage.read_coordinator_conversation(self.share_id)
264 | 
265 |         # Verify data was saved correctly
266 |         assert read_storage is not None, "Should load the coordinator conversation"
267 |         if read_storage:
268 |             assert read_storage.knowledge_share_id == self.share_id
269 |             assert len(read_storage.messages) == 2
270 |             assert read_storage.messages[0].content == "Test message 1"
271 |             assert read_storage.messages[1].content == "Test message 2"
272 |             assert not read_storage.messages[0].is_assistant
273 |             assert read_storage.messages[1].is_assistant
274 | 
275 |     async def test_append_coordinator_message(self):
276 |         """Test appending a message to coordinator conversation storage."""
277 |         # Start with empty storage
278 |         ShareStorage.append_coordinator_message(
279 |             share_id=self.share_id,
280 |             message_id=str(uuid.uuid4()),
281 |             content="First message",
282 |             sender_name="Test User",
283 |         )
284 | 
285 |         # Append another message
286 |         ShareStorage.append_coordinator_message(
287 |             share_id=self.share_id,
288 |             message_id=str(uuid.uuid4()),
289 |             content="Second message",
290 |             sender_name="Test Assistant",
291 |             is_assistant=True,
292 |         )
293 | 
294 |         # Read back
295 |         storage = ShareStorage.read_coordinator_conversation(self.share_id)
296 | 
297 |         # Verify messages were added
298 |         assert storage is not None, "Should create and load the coordinator conversation"
299 |         if storage:
300 |             assert len(storage.messages) == 2
301 |             assert storage.messages[0].content == "First message"
302 |             assert storage.messages[1].content == "Second message"
303 |             assert not storage.messages[0].is_assistant
304 |             assert storage.messages[1].is_assistant
305 | 
306 |     async def test_message_limit_in_coordinator_conversation(self):
307 |         """Test that coordinator conversation storage limits to the most recent messages."""
308 |         # Add more than 50 messages
309 |         for i in range(60):
310 |             ShareStorage.append_coordinator_message(
311 |                 share_id=self.share_id,
312 |                 message_id=str(uuid.uuid4()),
313 |                 content=f"Message {i + 1}",
314 |                 sender_name="Test User",
315 |             )
316 | 
317 |         # Read back
318 |         storage = ShareStorage.read_coordinator_conversation(self.share_id)
319 | 
320 |         # Verify only the most recent 50 messages are kept
321 |         assert storage is not None, "Should load the coordinator conversation"
322 |         if storage:
323 |             assert len(storage.messages) == 50, "Should limit to 50 messages"
324 |             # First message should be the 11th message (since we keep the last 50 of 60)
325 |             assert storage.messages[0].content == "Message 11"
326 |             # Last message should be the 60th message
327 |             assert storage.messages[49].content == "Message 60"
328 | 
329 |     async def test_knowledge_digest(self):
330 |         """Test reading and writing knowledge digest."""
331 |         # Create knowledge digest
332 |         digest = KnowledgeDigest(
333 |             content="# Test Knowledge Digest\n\nThis is a test knowledge digest.",
334 |             is_auto_generated=True,
335 |             created_by=self.user_id,
336 |             updated_by=self.user_id,
337 |             conversation_id=self.conversation_id,
338 |         )
339 | 
340 |         # Write knowledge digest (this will add it to the main share file)
341 |         ShareStorage.write_knowledge_digest(self.share_id, digest)
342 | 
343 |         # Read knowledge digest
344 |         read_digest = ShareStorage.read_knowledge_digest(self.share_id)
345 | 
346 |         # Verify knowledge digest was saved correctly
347 |         assert read_digest is not None, "Should load the knowledge digest"
348 |         if read_digest:
349 |             assert read_digest.content == "# Test Knowledge Digest\n\nThis is a test knowledge digest."
350 |             assert read_digest.is_auto_generated
351 | 
352 |     async def test_refresh_current_ui(self):
353 |         """Test refreshing the current UI inspector."""
354 |         # Call refresh_current_ui
355 |         await Notifications.notify_state_update(
356 |             self.context,
357 |             [
358 |                 InspectorTab.BRIEF,
359 |                 InspectorTab.LEARNING,
360 |                 InspectorTab.SHARING,
361 |                 InspectorTab.DEBUG,
362 |             ],
363 |         )
364 | 
365 |         # Verify that send_conversation_state_event was called 4 times (once per inspector tab)
366 |         assert self.context.send_conversation_state_event.call_count == 4
367 | 
368 |         # Get all the calls
369 |         calls = self.context.send_conversation_state_event.call_args_list
370 |         expected_state_ids = ["brief", "learning", "sharing", "debug"]
371 |         actual_state_ids = [call[0][0].state_id for call in calls]
372 | 
373 |         # Verify each call has the correct parameters
374 |         for call_args in calls:
375 |             called_event = call_args[0][0]
376 |             assert isinstance(called_event, AssistantStateEvent)
377 |             assert called_event.event == "updated"
378 |             assert called_event.state is None
379 |             assert called_event.state_id in expected_state_ids
380 | 
381 |         # Verify all expected state IDs were called
382 |         assert set(actual_state_ids) == set(expected_state_ids)
383 | 
384 |     async def test_knowledge_package_info(self):
385 |         """Test reading and writing knowledge package info."""
386 |         # Read existing knowledge package
387 |         package = ShareStorage.read_share(self.share_id)
388 | 
389 |         # Verify it was loaded correctly
390 |         assert package is not None, "Should load knowledge package"
391 |         if package:
392 |             assert package.share_id == self.share_id
393 | 
394 |             # Update knowledge package info
395 |             package.preferred_communication_style = "Test status message"
396 |             # Note: completion_percentage removed from model
397 |             package.next_learning_actions = ["Action 1", "Action 2"]
398 | 
399 |             # Write updated knowledge package
400 |             ShareStorage.write_share(self.share_id, package)
401 | 
402 |             # Read updated knowledge package
403 |             updated_package = ShareStorage.read_share(self.share_id)
404 | 
405 |             # Verify updates were saved
406 |             assert updated_package is not None, "Should load updated knowledge package"
407 |             if updated_package:
408 |                 assert updated_package.preferred_communication_style == "Test status message"
409 |                 # Note: completion_percentage removed from model
410 |                 assert updated_package.next_learning_actions == ["Action 1", "Action 2"]
411 | 
412 |     async def test_conversation_tracking_in_json(self):
413 |         """Test that conversations are tracked in JSON instead of file system."""
414 |         # Load knowledge package
415 |         package = ShareStorage.read_share(self.share_id)
416 |         assert package is not None
417 | 
418 |         if package:
419 |             # Verify team_conversations dict exists (even if empty)
420 |             assert isinstance(package.team_conversations, dict)
421 | 
422 |             # Verify helper methods work
423 |             linked_conversations = await ShareManager.get_linked_conversations(self.context)
424 |             assert isinstance(linked_conversations, list)
425 | 
426 |     async def test_conversation_association(self):
427 |         """Test conversation role setting."""
428 |         # Mock ShareManager.set_conversation_role
429 |         with unittest.mock.patch("assistant.domain.share_manager.write_model") as mock_write_model:
430 |             # Mock conversation role path
431 |             conversation_role_file = ShareStorageManager.get_conversation_role_file_path(self.context)
432 | 
433 |             # Call set_conversation_role
434 |             await ShareManager.set_conversation_role(self.context, self.share_id, ConversationRole.COORDINATOR)
435 | 
436 |             # Verify write_model was called
437 |             mock_write_model.assert_called_once()
438 | 
439 |             # Verify the file path in the call
440 |             call_args = mock_write_model.call_args[0]
441 |             assert call_args[0] == conversation_role_file
442 | 
443 |             # Verify the ConversationShareInfo object created
444 |             assert call_args[1].share_id == self.share_id
445 |             assert call_args[1].role == ConversationRole.COORDINATOR
446 | 
447 |     async def test_log_project_event(self):
448 |         """Test logging a project event."""
449 | 
450 |         # Create a test log entry directly
451 |         log_entry = LogEntry(
452 |             entry_type=LogEntryType.SHARE_INFORMATION_UPDATE,
453 |             message="Test direct log entry",
454 |             user_id=self.user_id,
455 |             user_name="Test User",
456 |             related_entity_id="test-entity-id",
457 |             metadata={"test": "metadata"},
458 |         )
459 | 
460 |         # Create a log with the entry
461 |         log = ShareLog(entries=[log_entry])
462 | 
463 |         # Write the log directly
464 |         ShareStorage.write_share_log(self.share_id, log)
465 | 
466 |         # Read the log back
467 |         read_log = ShareStorage.read_share_log(self.share_id)
468 |         assert read_log is not None, "Should load the log"
469 |         if read_log:
470 |             # Find our test entry
471 |             found_entry = False
472 |             for entry in read_log.entries:
473 |                 if entry.message == "Test direct log entry":
474 |                     found_entry = True
475 |                     assert entry.entry_type == LogEntryType.SHARE_INFORMATION_UPDATE
476 |                     assert entry.user_id == self.user_id
477 |                     assert entry.user_name == "Test User"
478 |                     assert entry.related_entity_id == "test-entity-id"
479 |                     assert entry.metadata == {"test": "metadata"}
480 |             assert found_entry, "Should find the added log entry"
481 | 
482 | 
483 | if __name__ == "__main__":
484 |     unittest.main()
485 | 
```
Page 93/145FirstPrevNextLast