#
tokens: 46734/50000 3/1784 files (page 91/145)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 91 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

--------------------------------------------------------------------------------
/mcp-servers/mcp-server-office/mcp_server/app_interaction/word_editor.py:
--------------------------------------------------------------------------------

```python
  1 | # Copyright (c) Microsoft. All rights reserved.
  2 | 
  3 | 
  4 | import sys
  5 | 
  6 | from mcp_server.types import WordCommentData
  7 | 
  8 | 
  9 | def get_word_app():
 10 |     if sys.platform != "win32":
 11 |         raise EnvironmentError("This script only works on Windows.")
 12 | 
 13 |     import win32com.client as win32
 14 | 
 15 |     """Connect to Word if it is running, or start a new instance."""
 16 |     try:
 17 |         # Try connecting to an existing instance of Word
 18 |         word = win32.GetActiveObject("Word.Application")
 19 |     except Exception:
 20 |         # If not running, create a new instance
 21 |         word = win32.Dispatch("Word.Application")
 22 |     # Make sure Word is visible so you can see your edits
 23 |     word.Visible = True
 24 |     return word
 25 | 
 26 | 
 27 | def get_active_document(word):
 28 |     """Return an active Word document, or create one if none is open."""
 29 |     if word.Documents.Count == 0:
 30 |         # If there are no documents, add a new one
 31 |         return word.Documents.Add()
 32 |     else:
 33 |         return word.ActiveDocument
 34 | 
 35 | 
 36 | def get_document_content(doc):
 37 |     """Return the content of the document."""
 38 |     return doc.Content.Text
 39 | 
 40 | 
 41 | def replace_document_content(doc, content):
 42 |     """Replace the content of the document with the given content."""
 43 |     doc.Content.Text = content
 44 | 
 45 | 
 46 | def get_markdown_representation(doc, include_comments: bool = False) -> str:
 47 |     """
 48 |     Get the markdown representation of the document.
 49 |     Supports Headings, plaintext, bulleted/numbered lists, bold, italic, and code blocks.
 50 |     """
 51 |     markdown_text = []
 52 |     in_code_block = False
 53 |     for i in range(1, doc.Paragraphs.Count + 1):
 54 |         paragraph = doc.Paragraphs(i)
 55 |         style_name = paragraph.Style.NameLocal
 56 | 
 57 |         # Handle Code style for code blocks
 58 |         if style_name == "Code":
 59 |             if not in_code_block:
 60 |                 markdown_text.append("```")
 61 |                 in_code_block = True
 62 |             markdown_text.append(paragraph.Range.Text.rstrip())
 63 |             continue
 64 |         elif in_code_block:
 65 |             # Close code block when style changes
 66 |             markdown_text.append("```")
 67 |             in_code_block = False
 68 | 
 69 |         # Process paragraph style first
 70 |         prefix = ""
 71 |         if "Heading" in style_name:
 72 |             try:
 73 |                 level = int(style_name.split("Heading")[1].strip())
 74 |                 prefix = "#" * level + " "
 75 |             except (ValueError, IndexError):
 76 |                 pass
 77 | 
 78 |         para_text = ""
 79 |         para_range = paragraph.Range
 80 |         # For performance, check if there's any formatting at all
 81 |         if para_range.Text.strip():
 82 |             if para_range.Font.Bold or para_range.Font.Italic:
 83 |                 # Process words instead of characters for better performance
 84 |                 current_run = {"text": "", "bold": False, "italic": False}
 85 | 
 86 |                 # Get all words in this paragraph
 87 |                 for w in range(1, para_range.Words.Count + 1):
 88 |                     word_range = para_range.Words(w)
 89 |                     word_text = word_range.Text  # Keep original with potential spaces
 90 | 
 91 |                     # Skip if empty
 92 |                     if not word_text.strip():
 93 |                         continue
 94 | 
 95 |                     # Get formatting for this word
 96 |                     is_bold = word_range.Font.Bold
 97 |                     is_italic = word_range.Font.Italic
 98 | 
 99 |                     # If formatting changed, start a new run
100 |                     if is_bold != current_run["bold"] or is_italic != current_run["italic"]:
101 |                         # Finish the previous run if it exists
102 |                         if current_run["text"]:
103 |                             if current_run["bold"] and current_run["italic"]:
104 |                                 para_text += f"***{current_run['text'].rstrip()}***"
105 |                             elif current_run["bold"]:
106 |                                 para_text += f"**{current_run['text'].rstrip()}**"
107 |                             elif current_run["italic"]:
108 |                                 para_text += f"*{current_run['text'].rstrip()}*"
109 |                             else:
110 |                                 para_text += current_run["text"].rstrip()
111 | 
112 |                             # Add a space if the previous run ended with a space
113 |                             if current_run["text"].endswith(" "):
114 |                                 para_text += " "
115 | 
116 |                         # Start a new run with the current word
117 |                         current_run = {"text": word_text, "bold": is_bold, "italic": is_italic}
118 |                     else:
119 |                         # Continue the current run - but be careful with spaces
120 |                         if current_run["text"]:
121 |                             current_run["text"] += word_text
122 |                         else:
123 |                             current_run["text"] = word_text
124 | 
125 |                 # Process the final run
126 |                 if current_run["text"]:
127 |                     if current_run["bold"] and current_run["italic"]:
128 |                         para_text += f"***{current_run['text'].rstrip()}***"
129 |                     elif current_run["bold"]:
130 |                         para_text += f"**{current_run['text'].rstrip()}**"
131 |                     elif current_run["italic"]:
132 |                         para_text += f"*{current_run['text'].rstrip()}*"
133 |                     else:
134 |                         para_text += current_run["text"].rstrip()
135 |             else:
136 |                 # No special formatting, just get the text
137 |                 para_text = para_range.Text.strip()
138 |         else:
139 |             para_text = para_range.Text.strip()
140 | 
141 |         if not para_text:
142 |             continue
143 | 
144 |         # Handle list formatting
145 |         if paragraph.Range.ListFormat.ListType == 2:
146 |             markdown_text.append(f"- {para_text}")
147 |         elif paragraph.Range.ListFormat.ListType == 3:
148 |             markdown_text.append(f"1. {para_text}")
149 |         else:
150 |             markdown_text.append(f"{prefix}{para_text}")
151 | 
152 |     # Close any open code block at the end of document
153 |     if in_code_block:
154 |         markdown_text.append("```")
155 | 
156 |     if include_comments:
157 |         comment_section = get_comments_markdown_representation(doc)
158 |         if comment_section:
159 |             markdown_text.append(comment_section)
160 | 
161 |     return "\n".join(markdown_text)
162 | 
163 | 
164 | def _write_formatted_text(selection, text):
165 |     """
166 |     Helper function to write text with markdown formatting (bold, italic) to the document.
167 |     Processes text in chunks for better performance.
168 | 
169 |     Args:
170 |         selection: Word selection object where text will be inserted
171 |         text: Markdown-formatted text string to process
172 |     """
173 | 
174 |     segments = []
175 |     i = 0
176 |     while i < len(text):
177 |         # Bold+Italic (***text***)
178 |         if i + 2 < len(text) and text[i : i + 3] == "***" and "***" in text[i + 3 :]:
179 |             end_pos = text.find("***", i + 3)
180 |             if end_pos != -1:
181 |                 segments.append(("bold_italic", text[i + 3 : end_pos]))
182 |                 i = end_pos + 3
183 |                 continue
184 | 
185 |         # Bold (**text**)
186 |         elif i + 1 < len(text) and text[i : i + 2] == "**" and "**" in text[i + 2 :]:
187 |             end_pos = text.find("**", i + 2)
188 |             if end_pos != -1:
189 |                 segments.append(("bold", text[i + 2 : end_pos]))
190 |                 i = end_pos + 2
191 |                 continue
192 | 
193 |         # Italic (*text*)
194 |         elif text[i] == "*" and i + 1 < len(text) and text[i + 1] != "*" and "*" in text[i + 1 :]:
195 |             end_pos = text.find("*", i + 1)
196 |             if end_pos != -1:
197 |                 segments.append(("italic", text[i + 1 : end_pos]))
198 |                 i = end_pos + 1
199 |                 continue
200 | 
201 |         # Find the next special marker or end of string
202 |         next_marker = float("inf")
203 |         for marker in ["***", "**", "*"]:
204 |             pos = text.find(marker, i)
205 |             if pos != -1 and pos < next_marker:
206 |                 next_marker = pos
207 | 
208 |         # Add plain text segment
209 |         if next_marker == float("inf"):
210 |             segments.append(("plain", text[i:]))
211 |             break
212 |         else:
213 |             segments.append(("plain", text[i:next_marker]))
214 |             i = next_marker
215 | 
216 |     # Now write all segments with minimal formatting changes
217 |     current_format = None
218 |     for format_type, content in segments:
219 |         if format_type != current_format:
220 |             selection.Font.Bold = False
221 |             selection.Font.Italic = False
222 | 
223 |             if format_type == "bold" or format_type == "bold_italic":
224 |                 selection.Font.Bold = True
225 |             if format_type == "italic" or format_type == "bold_italic":
226 |                 selection.Font.Italic = True
227 | 
228 |             current_format = format_type
229 |         selection.TypeText(content)
230 | 
231 |     selection.Font.Bold = False
232 |     selection.Font.Italic = False
233 | 
234 | 
235 | def write_markdown_to_document(doc, markdown_text: str) -> None:
236 |     """Writes markdown text to a Word document with appropriate formatting.
237 | 
238 |     Converts markdown syntax to Word formatting, including:
239 |     - Headings (# to Heading styles)
240 |     - Lists (bulleted and numbered)
241 |     - Text formatting (bold, italic)
242 |     - Code blocks (``` to Code style)
243 |     """
244 |     comments = get_document_comments(doc)
245 | 
246 |     doc.Content.Delete()
247 | 
248 |     word_app = doc.Application
249 |     selection = word_app.Selection
250 | 
251 |     # Create "Code" style if it doesn't exist
252 |     try:
253 |         # Check if Code style exists
254 |         code_style = word_app.ActiveDocument.Styles("Code")
255 |     except Exception:
256 |         # Create the Code style
257 |         code_style = word_app.ActiveDocument.Styles.Add("Code", 1)
258 |         code_style.Font.Name = "Cascadia Code"
259 |         code_style.Font.Size = 10
260 |         code_style.ParagraphFormat.SpaceAfter = 0
261 |         code_style.QuickStyle = True
262 |         code_style.LinkStyle = True
263 | 
264 |     # This fixes an issue where if there are comments on a doc, there is no selection
265 |     # which causes insertion to fail
266 |     doc.Range(0, 0).Select()
267 | 
268 |     # Ensure we start with normal style
269 |     selection.Style = word_app.ActiveDocument.Styles("Normal")
270 | 
271 |     lines = markdown_text.split("\n")
272 |     i = 0
273 |     while i < len(lines):
274 |         line = lines[i].strip()
275 |         i += 1
276 | 
277 |         if not line:
278 |             continue
279 | 
280 |         if line.startswith("```"):
281 |             i_start = i
282 | 
283 |             # Find the end of the code block
284 |             while i < len(lines) and not lines[i].strip().startswith("```"):
285 |                 i += 1
286 | 
287 |             # Process all lines in the code block
288 |             for j in range(i_start, i):
289 |                 code_line = lines[j]
290 |                 selection.TypeText(code_line)
291 |                 selection.Style = word_app.ActiveDocument.Styles("Code")
292 |                 selection.TypeParagraph()
293 | 
294 |             # Skip the closing code fence
295 |             if i < len(lines):
296 |                 i += 1
297 | 
298 |             # Restore normal style for next paragraph
299 |             selection.Style = word_app.ActiveDocument.Styles("Normal")
300 |             continue
301 | 
302 |         # Check if the line is a heading
303 |         if line.startswith("#"):
304 |             heading_level = 0
305 |             for char in line:
306 |                 if char == "#":
307 |                     heading_level += 1
308 |                 else:
309 |                     break
310 | 
311 |             # Remove the # characters and any leading space
312 |             text = line[heading_level:].strip()
313 | 
314 |             _write_formatted_text(selection, text)
315 | 
316 |             # Get the current paragraph and set its style
317 |             current_paragraph = selection.Paragraphs.Last
318 |             if 1 <= heading_level <= 9:  # Word supports Heading 1-9
319 |                 current_paragraph.Style = f"Heading {heading_level}"
320 | 
321 |             selection.TypeParagraph()
322 | 
323 |         # Check if line is a bulleted list item
324 |         elif line.startswith(("- ", "* ")):
325 |             # Extract the text after the bullet marker
326 |             text = line[2:].strip()
327 | 
328 |             _write_formatted_text(selection, text)
329 | 
330 |             # Apply bullet formatting
331 |             selection.Range.ListFormat.ApplyBulletDefault()
332 | 
333 |             selection.TypeParagraph()
334 |             selection.Style = word_app.ActiveDocument.Styles("Normal")
335 | 
336 |         # Check if line is a numbered list item
337 |         elif line.strip().startswith(tuple(f"{i}. " for i in range(1, 100)) + tuple(f"{i})" for i in range(1, 100))):
338 |             # Extract the text after the number and period/parenthesis
339 |             text = ""
340 |             if ". " in line:
341 |                 parts = line.strip().split(". ", 1)
342 |                 if len(parts) > 1:
343 |                     text = parts[1]
344 |             elif ") " in line:
345 |                 parts = line.strip().split(") ", 1)
346 |                 if len(parts) > 1:
347 |                     text = parts[1]
348 | 
349 |             if text:
350 |                 _write_formatted_text(selection, text)
351 | 
352 |                 # Apply numbered list formatting
353 |                 selection.Range.ListFormat.ApplyNumberDefault()
354 |                 selection.TypeParagraph()
355 |                 selection.Style = word_app.ActiveDocument.Styles("Normal")
356 |             else:
357 |                 # If parsing failed, just add the line as normal text
358 |                 _write_formatted_text(selection, line)
359 |                 selection.TypeParagraph()
360 | 
361 |         else:
362 |             # Regular paragraph text with formatting support
363 |             _write_formatted_text(selection, line)
364 |             selection.TypeParagraph()
365 | 
366 |     # Move cursor to the beginning of the document
367 |     doc.Range(0, 0).Select()
368 | 
369 |     # Reapply comments. Note this implicitly will remove any comments that have locations not in the new text.
370 |     for comment in comments:
371 |         add_document_comment(doc, comment)
372 | 
373 | 
374 | def add_document_comment(
375 |     doc,
376 |     comment_data: WordCommentData,
377 | ) -> bool:
378 |     """
379 |     Add a comment to specific text within a Word document.
380 | 
381 |     Returns:
382 |         bool: True if comment was added successfully, False otherwise
383 |     """
384 |     try:
385 |         content_range = doc.Content
386 |         found_range = None
387 | 
388 |         # Find the specified occurrence of the text
389 |         found_count = 0
390 | 
391 |         # Use FindText to locate the text
392 |         content_range.Find.ClearFormatting()
393 |         found = content_range.Find.Execute(FindText=comment_data.location_text, MatchCase=True, MatchWholeWord=False)
394 | 
395 |         while found:
396 |             found_count += 1
397 |             if found_count == comment_data.occurrence:
398 |                 found_range = content_range.Duplicate
399 |                 break
400 | 
401 |             # Continue searching from the end of the current match
402 |             content_range.Collapse(Direction=0)  # Collapse to end
403 |             found = content_range.Find.Execute(
404 |                 FindText=comment_data.location_text, MatchCase=True, MatchWholeWord=False
405 |             )
406 | 
407 |         if not found_range:
408 |             return False
409 | 
410 |         # Add a comment to the found range
411 |         comment = doc.Comments.Add(Range=found_range, Text=comment_data.comment_text)
412 |         if comment_data.author:
413 |             comment.Author = comment_data.author
414 |         return True
415 |     except Exception:
416 |         return False
417 | 
418 | 
419 | def get_document_comments(doc) -> list[WordCommentData]:
420 |     """
421 |     Retrieve all comments from a Word document.
422 |     """
423 |     comments: list[WordCommentData] = []
424 | 
425 |     try:
426 |         if doc.Comments.Count == 0:
427 |             return comments
428 | 
429 |         for i in range(1, doc.Comments.Count + 1):
430 |             try:
431 |                 comment = doc.Comments(i)
432 | 
433 |                 comment_text = ""
434 |                 try:
435 |                     comment_text = comment.Range.Text
436 |                 except Exception:
437 |                     pass
438 | 
439 |                 author = "Unknown"
440 |                 try:
441 |                     author = comment.Author
442 |                 except Exception:
443 |                     pass
444 | 
445 |                 date = ""
446 |                 try:
447 |                     date = str(comment.Date)
448 |                 except Exception:
449 |                     pass
450 | 
451 |                 reference_text = ""
452 |                 try:
453 |                     if hasattr(comment, "Scope"):
454 |                         reference_text = comment.Scope.Text
455 |                 except Exception:
456 |                     pass
457 | 
458 |                 comment_info = WordCommentData(
459 |                     id=str(i),
460 |                     comment_text=comment_text,
461 |                     location_text=reference_text,
462 |                     date=date,
463 |                     author=author,
464 |                 )
465 |                 comments.append(comment_info)
466 |             except Exception:
467 |                 continue
468 | 
469 |         return comments
470 |     except Exception as e:
471 |         print(f"Error retrieving comments: {e}")
472 |         return comments
473 | 
474 | 
475 | def get_comments_markdown_representation(doc) -> str:
476 |     comments = get_document_comments(doc)
477 | 
478 |     if not comments:
479 |         return ""
480 | 
481 |     comment_section = "\n\n<comments>\n"
482 |     for i, comment in enumerate(comments, 1):
483 |         comment_section += f'<comment id={i} author="{comment.author}">\n'
484 |         comment_section += f"  <location_text>{comment.location_text}</location_text>\n"
485 |         comment_section += f"  <comment_text>{comment.comment_text}</comment_text>\n"
486 |         comment_section += "</comment>\n"
487 |     comment_section.rstrip()
488 |     comment_section += "</comments>"
489 |     return comment_section
490 | 
491 | 
492 | def delete_comments_containing_text(doc, search_text: str, case_sensitive: bool = False) -> int:
493 |     """
494 |     Delete comments containing specific text.
495 | 
496 |     Args:
497 |         doc: Word document object
498 |         search_text: Text to search for in comments
499 |         case_sensitive: Whether the search should be case-sensitive
500 | 
501 |     Returns:
502 |         int: Number of comments deleted
503 |     """
504 |     deleted_count = 0
505 |     try:
506 |         if not case_sensitive:
507 |             search_text = search_text.lower()
508 | 
509 |         # Work backwards to avoid index shifting issues when deleting
510 |         for i in range(doc.Comments.Count, 0, -1):
511 |             comment = doc.Comments(i)
512 |             comment_text = comment.Range.Text
513 | 
514 |             if not case_sensitive:
515 |                 comment_text = comment_text.lower()
516 | 
517 |             if search_text in comment_text:
518 |                 comment.Delete()
519 |                 deleted_count += 1
520 |         return deleted_count
521 |     except Exception:
522 |         return deleted_count
523 | 
```

--------------------------------------------------------------------------------
/workbench-app/src/components/Conversations/ChatInputPlugins/LexicalMenu.ts:
--------------------------------------------------------------------------------

```typescript
  1 | // Copyright (c) Microsoft. All rights reserved.
  2 | // Based on code from: https://github.com/facebook/lexical/blob/main/packages/lexical-react/src/shared/LexicalMenu.ts
  3 | 
  4 | import { useLexicalComposerContext } from '@fluentui-copilot/react-copilot';
  5 | import { mergeRegister } from '@lexical/utils';
  6 | import {
  7 |     $getSelection,
  8 |     $isRangeSelection,
  9 |     COMMAND_PRIORITY_LOW,
 10 |     CommandListenerPriority,
 11 |     KEY_ARROW_DOWN_COMMAND,
 12 |     KEY_ARROW_UP_COMMAND,
 13 |     KEY_ENTER_COMMAND,
 14 |     KEY_ESCAPE_COMMAND,
 15 |     KEY_TAB_COMMAND,
 16 |     LexicalEditor,
 17 |     TextNode,
 18 | } from 'lexical';
 19 | import React from 'react';
 20 | import { SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND } from './TypeaheadMenuPlugin';
 21 | 
 22 | export type MenuTextMatch = {
 23 |     leadOffset: number;
 24 |     matchingString: string;
 25 |     replaceableString: string;
 26 | };
 27 | 
 28 | export type MenuResolution = {
 29 |     match?: MenuTextMatch;
 30 |     getRect: () => DOMRect;
 31 | };
 32 | 
 33 | export class MenuOption {
 34 |     key: string;
 35 |     ref?: React.MutableRefObject<HTMLElement | null>;
 36 | 
 37 |     constructor(key: string) {
 38 |         this.key = key;
 39 |         this.ref = { current: null };
 40 |         this.setRefElement = this.setRefElement.bind(this);
 41 |     }
 42 | 
 43 |     setRefElement(element: HTMLElement | null) {
 44 |         this.ref = { current: element };
 45 |     }
 46 | }
 47 | 
 48 | export type MenuRenderFn<TOption extends MenuOption> = (
 49 |     anchorElementRef: React.MutableRefObject<HTMLElement | null>,
 50 |     itemProps: {
 51 |         selectedIndex: number | null;
 52 |         selectOptionAndCleanUp: (option: TOption) => void;
 53 |         setHighlightedIndex: (index: number) => void;
 54 |         options: Array<TOption>;
 55 |     },
 56 |     matchingString: string | null,
 57 | ) => React.ReactPortal | JSX.Element | null;
 58 | 
 59 | const scrollIntoViewIfNeeded = (target: HTMLElement) => {
 60 |     const typeaheadContainerNode = document.getElementById('typeahead-menu');
 61 |     if (!typeaheadContainerNode) {
 62 |         return;
 63 |     }
 64 | 
 65 |     const typeaheadRect = typeaheadContainerNode.getBoundingClientRect();
 66 | 
 67 |     if (typeaheadRect.top + typeaheadRect.height > window.innerHeight) {
 68 |         typeaheadContainerNode.scrollIntoView({
 69 |             block: 'center',
 70 |         });
 71 |     }
 72 | 
 73 |     if (typeaheadRect.top < 0) {
 74 |         typeaheadContainerNode.scrollIntoView({
 75 |             block: 'center',
 76 |         });
 77 |     }
 78 | 
 79 |     target.scrollIntoView({ block: 'nearest' });
 80 | };
 81 | 
 82 | /**
 83 |  * Walk backwards along user input and forward through entity title to try
 84 |  * and replace more of the user's text with entity.
 85 |  */
 86 | const getFullMatchOffset = (documentText: string, entryText: string, offset: number): number => {
 87 |     let triggerOffset = offset;
 88 |     for (let i = triggerOffset; i <= entryText.length; i++) {
 89 |         if (documentText.slice(-i) === entryText.slice(0, i)) {
 90 |             triggerOffset = i;
 91 |         }
 92 |     }
 93 |     return triggerOffset;
 94 | };
 95 | 
 96 | /**
 97 |  * Split Lexical TextNode and return a new TextNode only containing matched text.
 98 |  * Common use cases include: removing the node, replacing with a new node.
 99 |  */
100 | const $splitNodeContainingQuery = (match: MenuTextMatch): TextNode | null => {
101 |     const selection = $getSelection();
102 |     if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
103 |         return null;
104 |     }
105 |     const anchor = selection.anchor;
106 |     if (anchor.type !== 'text') {
107 |         return null;
108 |     }
109 |     const anchorNode = anchor.getNode();
110 |     if (!anchorNode.isSimpleText()) {
111 |         return null;
112 |     }
113 |     const selectionOffset = anchor.offset;
114 |     const textContent = anchorNode.getTextContent().slice(0, selectionOffset);
115 |     const characterOffset = match.replaceableString.length;
116 |     const queryOffset = getFullMatchOffset(textContent, match.matchingString, characterOffset);
117 |     const startOffset = selectionOffset - queryOffset;
118 |     if (startOffset < 0) {
119 |         return null;
120 |     }
121 |     let newNode;
122 |     if (startOffset === 0) {
123 |         [newNode] = anchorNode.splitText(selectionOffset);
124 |     } else {
125 |         [, newNode] = anchorNode.splitText(startOffset, selectionOffset);
126 |     }
127 | 
128 |     return newNode;
129 | };
130 | 
131 | // Got from https://stackoverflow.com/a/42543908/2013580
132 | export const getScrollParent = (element: HTMLElement, includeHidden: boolean): HTMLElement | HTMLBodyElement => {
133 |     let style = getComputedStyle(element);
134 |     const excludeStaticParent = style.position === 'absolute';
135 |     const overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/;
136 |     if (style.position === 'fixed') {
137 |         return document.body;
138 |     }
139 |     for (let parent: HTMLElement | null = element; (parent = parent.parentElement); ) {
140 |         style = getComputedStyle(parent);
141 |         if (excludeStaticParent && style.position === 'static') {
142 |             continue;
143 |         }
144 |         if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) {
145 |             return parent;
146 |         }
147 |     }
148 |     return document.body;
149 | };
150 | 
151 | const isTriggerVisibleInNearestScrollContainer = (
152 |     targetElement: HTMLElement,
153 |     containerElement: HTMLElement,
154 | ): boolean => {
155 |     const tRect = targetElement.getBoundingClientRect();
156 |     const cRect = containerElement.getBoundingClientRect();
157 |     return tRect.top > cRect.top && tRect.top < cRect.bottom;
158 | };
159 | 
160 | // Reposition the menu on scroll, window resize, and element resize.
161 | export const useDynamicPositioning = (
162 |     resolution: MenuResolution | null,
163 |     targetElement: HTMLElement | null,
164 |     onReposition: () => void,
165 |     onVisibilityChange?: (isInView: boolean) => void,
166 | ) => {
167 |     const [editor] = useLexicalComposerContext();
168 |     React.useEffect(() => {
169 |         if (targetElement != null && resolution != null) {
170 |             const rootElement = editor.getRootElement();
171 |             const rootScrollParent = rootElement != null ? getScrollParent(rootElement, false) : document.body;
172 |             let ticking = false;
173 |             let previousIsInView = isTriggerVisibleInNearestScrollContainer(targetElement, rootScrollParent);
174 |             const handleScroll = () => {
175 |                 if (!ticking) {
176 |                     window.requestAnimationFrame(() => {
177 |                         onReposition();
178 |                         ticking = false;
179 |                     });
180 |                     ticking = true;
181 |                 }
182 |                 const isInView = isTriggerVisibleInNearestScrollContainer(targetElement, rootScrollParent);
183 |                 if (isInView !== previousIsInView) {
184 |                     previousIsInView = isInView;
185 |                     if (onVisibilityChange != null) {
186 |                         onVisibilityChange(isInView);
187 |                     }
188 |                 }
189 |             };
190 |             const resizeObserver = new ResizeObserver(onReposition);
191 |             window.addEventListener('resize', onReposition);
192 |             document.addEventListener('scroll', handleScroll, {
193 |                 capture: true,
194 |                 passive: true,
195 |             });
196 |             resizeObserver.observe(targetElement);
197 |             return () => {
198 |                 resizeObserver.unobserve(targetElement);
199 |                 window.removeEventListener('resize', onReposition);
200 |                 document.removeEventListener('scroll', handleScroll, true);
201 |             };
202 |         }
203 | 
204 |         return;
205 |     }, [targetElement, editor, onVisibilityChange, onReposition, resolution]);
206 | };
207 | 
208 | export const LexicalMenu = <TOption extends MenuOption>({
209 |     close,
210 |     editor,
211 |     anchorElementRef,
212 |     resolution,
213 |     options,
214 |     menuRenderFn,
215 |     onSelectOption,
216 |     shouldSplitNodeWithQuery = false,
217 |     commandPriority = COMMAND_PRIORITY_LOW,
218 | }: {
219 |     close: () => void;
220 |     editor: LexicalEditor;
221 |     anchorElementRef: React.MutableRefObject<HTMLElement>;
222 |     resolution: MenuResolution;
223 |     options: Array<TOption>;
224 |     shouldSplitNodeWithQuery?: boolean;
225 |     menuRenderFn: MenuRenderFn<TOption>;
226 |     onSelectOption: (
227 |         option: TOption,
228 |         textNodeContainingQuery: TextNode | null,
229 |         closeMenu: () => void,
230 |         matchingString: string,
231 |     ) => void;
232 |     commandPriority?: CommandListenerPriority;
233 | }): JSX.Element | null => {
234 |     const [selectedIndex, setHighlightedIndex] = React.useState<null | number>(null);
235 | 
236 |     const matchingString = resolution.match && resolution.match.matchingString;
237 | 
238 |     React.useEffect(() => {
239 |         setHighlightedIndex(0);
240 |     }, [matchingString]);
241 | 
242 |     const selectOptionAndCleanUp = React.useCallback(
243 |         (selectedEntry: TOption) => {
244 |             editor.update(() => {
245 |                 const textNodeContainingQuery =
246 |                     resolution.match != null && shouldSplitNodeWithQuery
247 |                         ? $splitNodeContainingQuery(resolution.match)
248 |                         : null;
249 | 
250 |                 onSelectOption(
251 |                     selectedEntry,
252 |                     textNodeContainingQuery,
253 |                     close,
254 |                     resolution.match ? resolution.match.matchingString : '',
255 |                 );
256 |             });
257 |         },
258 |         [editor, shouldSplitNodeWithQuery, resolution.match, onSelectOption, close],
259 |     );
260 | 
261 |     const updateSelectedIndex = React.useCallback(
262 |         (index: number) => {
263 |             const rootElem = editor.getRootElement();
264 |             if (rootElem !== null) {
265 |                 rootElem.setAttribute('aria-activedescendant', 'typeahead-item-' + index);
266 |                 setHighlightedIndex(index);
267 |             }
268 |         },
269 |         [editor],
270 |     );
271 | 
272 |     React.useEffect(() => {
273 |         return () => {
274 |             const rootElem = editor.getRootElement();
275 |             if (rootElem !== null) {
276 |                 rootElem.removeAttribute('aria-activedescendant');
277 |             }
278 |         };
279 |     }, [editor]);
280 | 
281 |     React.useLayoutEffect(() => {
282 |         if (options === null) {
283 |             setHighlightedIndex(null);
284 |         } else if (selectedIndex === null) {
285 |             updateSelectedIndex(0);
286 |         }
287 |     }, [options, selectedIndex, updateSelectedIndex]);
288 | 
289 |     React.useEffect(() => {
290 |         return mergeRegister(
291 |             editor.registerCommand(
292 |                 SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND,
293 |                 ({ option }) => {
294 |                     if (option.ref && option.ref.current != null) {
295 |                         scrollIntoViewIfNeeded(option.ref.current);
296 |                         return true;
297 |                     }
298 | 
299 |                     return false;
300 |                 },
301 |                 commandPriority,
302 |             ),
303 |         );
304 |     }, [editor, updateSelectedIndex, commandPriority]);
305 | 
306 |     React.useEffect(() => {
307 |         return mergeRegister(
308 |             editor.registerCommand<KeyboardEvent>(
309 |                 KEY_ARROW_DOWN_COMMAND,
310 |                 (payload) => {
311 |                     const event = payload;
312 |                     if (options !== null && options.length && selectedIndex !== null) {
313 |                         const newSelectedIndex = selectedIndex !== options.length - 1 ? selectedIndex + 1 : 0;
314 |                         updateSelectedIndex(newSelectedIndex);
315 |                         const option = options[newSelectedIndex];
316 |                         if (option.ref != null && option.ref.current) {
317 |                             editor.dispatchCommand(SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND, {
318 |                                 index: newSelectedIndex,
319 |                                 option,
320 |                             });
321 |                         }
322 |                         event.preventDefault();
323 |                         event.stopImmediatePropagation();
324 |                     }
325 |                     return true;
326 |                 },
327 |                 commandPriority,
328 |             ),
329 |             editor.registerCommand<KeyboardEvent>(
330 |                 KEY_ARROW_UP_COMMAND,
331 |                 (payload) => {
332 |                     const event = payload;
333 |                     if (options !== null && options.length && selectedIndex !== null) {
334 |                         const newSelectedIndex = selectedIndex !== 0 ? selectedIndex - 1 : options.length - 1;
335 |                         updateSelectedIndex(newSelectedIndex);
336 |                         const option = options[newSelectedIndex];
337 |                         if (option.ref != null && option.ref.current) {
338 |                             scrollIntoViewIfNeeded(option.ref.current);
339 |                         }
340 |                         event.preventDefault();
341 |                         event.stopImmediatePropagation();
342 |                     }
343 |                     return true;
344 |                 },
345 |                 commandPriority,
346 |             ),
347 |             editor.registerCommand<KeyboardEvent>(
348 |                 KEY_ESCAPE_COMMAND,
349 |                 (payload) => {
350 |                     const event = payload;
351 |                     event.preventDefault();
352 |                     event.stopImmediatePropagation();
353 |                     close();
354 |                     return true;
355 |                 },
356 |                 commandPriority,
357 |             ),
358 |             editor.registerCommand<KeyboardEvent>(
359 |                 KEY_TAB_COMMAND,
360 |                 (payload) => {
361 |                     const event = payload;
362 |                     if (options === null || selectedIndex === null || options[selectedIndex] == null) {
363 |                         return false;
364 |                     }
365 |                     event.preventDefault();
366 |                     event.stopImmediatePropagation();
367 |                     selectOptionAndCleanUp(options[selectedIndex]);
368 |                     return true;
369 |                 },
370 |                 commandPriority,
371 |             ),
372 |             editor.registerCommand(
373 |                 KEY_ENTER_COMMAND,
374 |                 (event: KeyboardEvent | null) => {
375 |                     if (options === null || selectedIndex === null || options[selectedIndex] == null) {
376 |                         return false;
377 |                     }
378 |                     if (event !== null) {
379 |                         event.preventDefault();
380 |                         event.stopImmediatePropagation();
381 |                     }
382 |                     selectOptionAndCleanUp(options[selectedIndex]);
383 |                     return true;
384 |                 },
385 |                 commandPriority,
386 |             ),
387 |         );
388 |     }, [selectOptionAndCleanUp, close, editor, options, selectedIndex, updateSelectedIndex, commandPriority]);
389 | 
390 |     const listItemProps = React.useMemo(
391 |         () => ({
392 |             options,
393 |             selectOptionAndCleanUp,
394 |             selectedIndex,
395 |             setHighlightedIndex,
396 |         }),
397 |         [selectOptionAndCleanUp, selectedIndex, options],
398 |     );
399 | 
400 |     return menuRenderFn(anchorElementRef, listItemProps, resolution.match ? resolution.match.matchingString : '');
401 | };
402 | 
403 | export const useMenuAnchorRef = (
404 |     resolution: MenuResolution | null,
405 |     setResolution: (r: MenuResolution | null) => void,
406 |     className?: string,
407 |     parent: HTMLElement = document.body,
408 | ): React.MutableRefObject<HTMLElement> => {
409 |     const [editor] = useLexicalComposerContext();
410 |     const anchorElementRef = React.useRef<HTMLElement>(document.createElement('div'));
411 |     const positionMenu = React.useCallback(() => {
412 |         anchorElementRef.current.style.top = anchorElementRef.current.style.bottom;
413 |         const rootElement = editor.getRootElement();
414 |         const containerDiv = anchorElementRef.current;
415 | 
416 |         const menuEle = containerDiv.firstChild as HTMLElement;
417 |         if (rootElement !== null && resolution !== null) {
418 |             const { left, top, width, height } = resolution.getRect();
419 |             containerDiv.style.bottom = `${top + window.scrollY}px`;
420 |             containerDiv.style.left = `${left + window.scrollX}px`;
421 |             containerDiv.style.height = `${height}px`;
422 |             containerDiv.style.width = `${width}px`;
423 |             if (menuEle !== null) {
424 |                 menuEle.style.top = `${top}`;
425 |                 const menuRect = menuEle.getBoundingClientRect();
426 |                 const menuHeight = menuRect.height;
427 |                 const menuWidth = menuRect.width;
428 | 
429 |                 const rootElementRect = rootElement.getBoundingClientRect();
430 | 
431 |                 if (left + menuWidth > rootElementRect.right) {
432 |                     containerDiv.style.left = `${rootElementRect.right - menuWidth + window.scrollX}px`;
433 |                 }
434 |                 if (
435 |                     (top + menuHeight > window.innerHeight || top + menuHeight > rootElementRect.bottom) &&
436 |                     top - rootElementRect.top > menuHeight + height
437 |                 ) {
438 |                     containerDiv.style.top = `${top - menuHeight + window.scrollY - height}px`;
439 |                 }
440 |             }
441 | 
442 |             if (!containerDiv.isConnected) {
443 |                 if (className != null) {
444 |                     containerDiv.className = className;
445 |                 }
446 |                 containerDiv.setAttribute('aria-label', 'Typeahead menu');
447 |                 containerDiv.setAttribute('id', 'typeahead-menu');
448 |                 containerDiv.setAttribute('role', 'listbox');
449 |                 containerDiv.style.display = 'block';
450 |                 containerDiv.style.position = 'absolute';
451 |                 parent.append(containerDiv);
452 |             }
453 |             anchorElementRef.current = containerDiv;
454 |             rootElement.setAttribute('aria-controls', 'typeahead-menu');
455 |         }
456 |     }, [editor, resolution, className, parent]);
457 | 
458 |     React.useEffect(() => {
459 |         const rootElement = editor.getRootElement();
460 |         if (resolution !== null) {
461 |             positionMenu();
462 |             return () => {
463 |                 if (rootElement !== null) {
464 |                     rootElement.removeAttribute('aria-controls');
465 |                 }
466 | 
467 |                 const containerDiv = anchorElementRef.current;
468 |                 if (containerDiv !== null && containerDiv.isConnected) {
469 |                     containerDiv.remove();
470 |                 }
471 |             };
472 |         }
473 | 
474 |         return;
475 |     }, [editor, positionMenu, resolution]);
476 | 
477 |     const onVisibilityChange = React.useCallback(
478 |         (isInView: boolean) => {
479 |             if (resolution !== null) {
480 |                 if (!isInView) {
481 |                     setResolution(null);
482 |                 }
483 |             }
484 |         },
485 |         [resolution, setResolution],
486 |     );
487 | 
488 |     useDynamicPositioning(resolution, anchorElementRef.current, positionMenu, onVisibilityChange);
489 | 
490 |     return anchorElementRef;
491 | };
492 | 
493 | export type TriggerFn = (text: string, editor: LexicalEditor) => MenuTextMatch | null;
494 | 
```

--------------------------------------------------------------------------------
/assistants/knowledge-transfer-assistant/assistant/domain/learning_objectives_manager.py:
--------------------------------------------------------------------------------

```python
  1 | """
  2 | Learning objectives and outcomes management for Knowledge Transfer Assistant.
  3 | 
  4 | Handles learning objectives, outcomes creation, updates, and deletion.
  5 | """
  6 | 
  7 | from typing import List, Optional, Tuple
  8 | 
  9 | from semantic_workbench_assistant.assistant_app import ConversationContext
 10 | 
 11 | from ..data import InspectorTab, KnowledgePackage, LearningObjective, LearningOutcome, LogEntryType
 12 | from ..logging import logger
 13 | from ..notifications import Notifications
 14 | from ..storage import ShareStorage
 15 | from ..utils import require_current_user
 16 | from .share_manager import ShareManager
 17 | 
 18 | 
 19 | class LearningObjectivesManager:
 20 |     """Manages learning objectives and outcomes operations."""
 21 | 
 22 |     @staticmethod
 23 |     async def add_learning_objective(
 24 |         context: ConversationContext,
 25 |         objective_name: str,
 26 |         description: str,
 27 |         outcomes: Optional[List[str]] = None,
 28 |         priority: int = 1,
 29 |     ) -> Optional[LearningObjective]:
 30 |         share_id = await ShareManager.get_share_id(context)
 31 |         if not share_id:
 32 |             logger.error("Cannot add learning objective: no share associated with this conversation")
 33 |             return None
 34 | 
 35 |         current_user_id = await require_current_user(context, "add learning objective")
 36 |         if not current_user_id:
 37 |             return None
 38 | 
 39 |         criterion_objects = []
 40 |         if outcomes:
 41 |             for criterion in outcomes:
 42 |                 criterion_objects.append(LearningOutcome(description=criterion))
 43 | 
 44 |         new_learning_objective = LearningObjective(
 45 |             name=objective_name,
 46 |             description=description,
 47 |             priority=priority,
 48 |             learning_outcomes=criterion_objects,
 49 |         )
 50 | 
 51 |         share = ShareStorage.read_share(share_id)
 52 |         if not share:
 53 |             # Create a new share if it doesn't exist
 54 |             share = KnowledgePackage(
 55 |                 share_id=share_id,
 56 |                 brief=None,
 57 |                 learning_objectives=[new_learning_objective],
 58 |                 digest=None,
 59 |                 requests=[],
 60 |                 log=None,
 61 |             )
 62 |         else:
 63 |             share.learning_objectives.append(new_learning_objective)
 64 | 
 65 |         ShareStorage.write_share(share_id, share)
 66 | 
 67 |         await ShareStorage.log_share_event(
 68 |             context=context,
 69 |             share_id=share_id,
 70 |             entry_type=LogEntryType.LEARNING_OBJECTIVE_ADDED.value,
 71 |             message=f"Added learning objective: {objective_name}",
 72 |         )
 73 | 
 74 |         await Notifications.notify_all(context, share_id, f"Learning objective '{objective_name}' was added")
 75 |         await Notifications.notify_all_state_update(context, share_id, [InspectorTab.LEARNING, InspectorTab.BRIEF])
 76 | 
 77 |         return new_learning_objective
 78 | 
 79 |     @staticmethod
 80 |     async def update_learning_objective(
 81 |         context: ConversationContext,
 82 |         objective_id: str,
 83 |         objective_name: Optional[str] = None,
 84 |         description: Optional[str] = None,
 85 |     ) -> Tuple[bool, Optional[str]]:
 86 |         """Update an existing learning objective's name or description."""
 87 |         share_id = await ShareManager.get_share_id(context)
 88 |         if not share_id:
 89 |             logger.error("Cannot update learning objective: no share associated with this conversation")
 90 |             return False, "No share associated with this conversation."
 91 | 
 92 |         current_user_id = await require_current_user(context, "update learning objective")
 93 |         if not current_user_id:
 94 |             return False, "Could not identify current user."
 95 | 
 96 |         share = ShareStorage.read_share(share_id)
 97 |         if not share or not share.learning_objectives:
 98 |             return False, "No learning objectives found."
 99 | 
100 |         # Find objective by ID
101 |         objective = None
102 |         for obj in share.learning_objectives:
103 |             if obj.id == objective_id:
104 |                 objective = obj
105 |                 break
106 | 
107 |         if not objective:
108 |             available_ids = [obj.id for obj in share.learning_objectives]
109 |             return (
110 |                 False,
111 |                 f"Learning objective with ID '{objective_id}' not found. Available objective IDs: {', '.join(available_ids[:3]) + ('...' if len(available_ids) > 3 else '')}",
112 |             )
113 | 
114 |         original_name = objective.name
115 |         changes_made = []
116 | 
117 |         # Update fields if provided
118 |         if objective_name and objective_name.strip():
119 |             objective.name = objective_name.strip()
120 |             changes_made.append(f"name: '{original_name}' → '{objective_name.strip()}'")
121 | 
122 |         if description and description.strip():
123 |             objective.description = description.strip()
124 |             changes_made.append("description updated")
125 | 
126 |         if not changes_made:
127 |             return True, "No changes specified"
128 | 
129 |         ShareStorage.write_share(share_id, share)
130 | 
131 |         changes_text = ", ".join(changes_made)
132 |         await ShareStorage.log_share_event(
133 |             context=context,
134 |             share_id=share_id,
135 |             entry_type=LogEntryType.LEARNING_OBJECTIVE_UPDATED.value,
136 |             message=f"Updated learning objective '{objective.name}': {changes_text}",
137 |             metadata={
138 |                 "objective_id": objective_id,
139 |                 "objective_name": objective.name,
140 |                 "changes": changes_text,
141 |             },
142 |         )
143 | 
144 |         await Notifications.notify_all(context, share_id, f"Learning objective '{objective.name}' has been updated")
145 |         await Notifications.notify_all_state_update(context, share_id, [InspectorTab.LEARNING, InspectorTab.BRIEF])
146 | 
147 |         return True, f"Learning objective '{objective.name}' has been successfully updated: {changes_text}."
148 | 
149 |     @staticmethod
150 |     async def delete_learning_objective(
151 |         context: ConversationContext,
152 |         objective_id: str,
153 |     ) -> Tuple[bool, Optional[str]]:
154 |         """Delete a learning objective by ID."""
155 |         share_id = await ShareManager.get_share_id(context)
156 |         if not share_id:
157 |             logger.error("Cannot delete learning objective: no share associated with this conversation")
158 |             return False, "No share associated with this conversation."
159 | 
160 |         current_user_id = await require_current_user(context, "delete learning objective")
161 |         if not current_user_id:
162 |             return False, "Could not identify current user."
163 | 
164 |         share = ShareStorage.read_share(share_id)
165 |         if not share or not share.learning_objectives:
166 |             return False, "No learning objectives found."
167 | 
168 |         # Find objective by ID
169 |         objective = None
170 |         objective_index = -1
171 |         for idx, obj in enumerate(share.learning_objectives):
172 |             if obj.id == objective_id:
173 |                 objective = obj
174 |                 objective_index = idx
175 |                 break
176 | 
177 |         if not objective:
178 |             available_ids = [obj.id for obj in share.learning_objectives]
179 |             return (
180 |                 False,
181 |                 f"Learning objective with ID '{objective_id}' not found. Available objective IDs: {', '.join(available_ids[:3]) + ('...' if len(available_ids) > 3 else '')}",
182 |             )
183 | 
184 |         objective_name = objective.name
185 | 
186 |         # Clean up any achievement records for all outcomes in this objective across all team conversations
187 |         for outcome in objective.learning_outcomes:
188 |             for team_info in share.team_conversations.values():
189 |                 team_info.outcome_achievements = [
190 |                     achievement
191 |                     for achievement in team_info.outcome_achievements
192 |                     if achievement.outcome_id != outcome.id
193 |                 ]
194 | 
195 |         # Remove the objective from the share
196 |         share.learning_objectives.pop(objective_index)
197 | 
198 |         ShareStorage.write_share(share_id, share)
199 | 
200 |         await ShareStorage.log_share_event(
201 |             context=context,
202 |             share_id=share_id,
203 |             entry_type=LogEntryType.LEARNING_OBJECTIVE_UPDATED.value,
204 |             message=f"Deleted learning objective '{objective_name}' and all its outcomes",
205 |             metadata={
206 |                 "objective_id": objective_id,
207 |                 "objective_name": objective_name,
208 |                 "outcomes_count": len(objective.learning_outcomes),
209 |             },
210 |         )
211 | 
212 |         await Notifications.notify_all(context, share_id, f"Learning objective '{objective_name}' has been deleted")
213 |         await Notifications.notify_all_state_update(context, share_id, [InspectorTab.LEARNING, InspectorTab.BRIEF])
214 | 
215 |         return True, f"Learning objective '{objective_name}' has been successfully deleted from the knowledge package."
216 | 
217 |     @staticmethod
218 |     async def get_learning_outcomes(context: ConversationContext) -> List[LearningOutcome]:
219 |         share_id = await ShareManager.get_share_id(context)
220 |         if not share_id:
221 |             return []
222 | 
223 |         share = ShareStorage.read_share(share_id)
224 |         if not share:
225 |             return []
226 | 
227 |         objectives = share.learning_objectives
228 |         outcomes = []
229 |         for objective in objectives:
230 |             outcomes.extend(objective.learning_outcomes)
231 | 
232 |         return outcomes
233 | 
234 |     @staticmethod
235 |     async def add_learning_outcome(
236 |         context: ConversationContext,
237 |         objective_id: str,
238 |         outcome_description: str,
239 |     ) -> Tuple[bool, Optional[str]]:
240 |         """Add a new learning outcome to an existing learning objective."""
241 |         share_id = await ShareManager.get_share_id(context)
242 |         if not share_id:
243 |             logger.error("Cannot add learning outcome: no share associated with this conversation")
244 |             return False, "No knowledge package associated with this conversation."
245 | 
246 |         current_user_id = await require_current_user(context, "add learning outcome")
247 |         if not current_user_id:
248 |             return False, "Could not identify current user."
249 | 
250 |         share = ShareStorage.read_share(share_id)
251 |         if not share or not share.learning_objectives:
252 |             return False, "No learning objectives found. Please add objectives before adding outcomes."
253 | 
254 |         # Find the objective by ID
255 |         objective = None
256 |         for obj in share.learning_objectives:
257 |             if obj.id == objective_id:
258 |                 objective = obj
259 |                 break
260 | 
261 |         if objective is None:
262 |             available_ids = [obj.id for obj in share.learning_objectives]
263 |             return (
264 |                 False,
265 |                 f"Learning objective with ID '{objective_id}' not found. Available objective IDs: {', '.join(available_ids[:3]) + ('...' if len(available_ids) > 3 else '')}",
266 |             )
267 | 
268 |         # Create the new outcome
269 |         new_outcome = LearningOutcome(description=outcome_description.strip())
270 | 
271 |         # Add the outcome to the objective
272 |         objective.learning_outcomes.append(new_outcome)
273 | 
274 |         # Save the updated knowledge package
275 |         ShareStorage.write_share(share_id, share)
276 | 
277 |         # Log the outcome addition
278 |         await ShareStorage.log_share_event(
279 |             context=context,
280 |             share_id=share_id,
281 |             entry_type=LogEntryType.LEARNING_OBJECTIVE_UPDATED.value,
282 |             message=f"Added learning outcome to objective '{objective.name}': {outcome_description}",
283 |             metadata={
284 |                 "objective_id": objective_id,
285 |                 "objective_name": objective.name,
286 |                 "outcome_added": outcome_description,
287 |                 "outcome_id": new_outcome.id,
288 |             },
289 |         )
290 | 
291 |         # Notify linked conversations
292 |         await Notifications.notify_all(context, share_id, f"Learning outcome '{outcome_description}' has been added")
293 |         await Notifications.notify_all_state_update(context, share_id, [InspectorTab.LEARNING, InspectorTab.BRIEF])
294 | 
295 |         return True, f"Learning outcome added successfully to objective '{objective.name}': {outcome_description}"
296 | 
297 |     @staticmethod
298 |     async def update_learning_outcome(
299 |         context: ConversationContext,
300 |         outcome_id: str,
301 |         new_description: str,
302 |     ) -> Tuple[bool, Optional[str]]:
303 |         """Update the description of an existing learning outcome."""
304 |         share_id = await ShareManager.get_share_id(context)
305 |         if not share_id:
306 |             logger.error("Cannot update learning outcome: no share associated with this conversation")
307 |             return False, "No knowledge package associated with this conversation."
308 | 
309 |         current_user_id = await require_current_user(context, "update learning outcome")
310 |         if not current_user_id:
311 |             return False, "Could not identify current user."
312 | 
313 |         share = ShareStorage.read_share(share_id)
314 |         if not share or not share.learning_objectives:
315 |             return False, "No learning objectives found. Please add objectives before updating outcomes."
316 | 
317 |         # Find the outcome by ID across all objectives
318 |         objective = None
319 |         outcome = None
320 |         for obj in share.learning_objectives:
321 |             for out in obj.learning_outcomes:
322 |                 if out.id == outcome_id:
323 |                     objective = obj
324 |                     outcome = out
325 |                     break
326 |             if outcome:
327 |                 break
328 | 
329 |         if outcome is None or objective is None:
330 |             # Collect available outcome IDs for error message
331 |             available_outcome_ids = []
332 |             for obj in share.learning_objectives:
333 |                 for out in obj.learning_outcomes:
334 |                     available_outcome_ids.append(out.id)
335 |             return (
336 |                 False,
337 |                 f"Learning outcome with ID '{outcome_id}' not found. Available outcome IDs: {', '.join(available_outcome_ids[:3]) + ('...' if len(available_outcome_ids) > 3 else '')}",
338 |             )
339 | 
340 |         old_description = outcome.description
341 | 
342 |         # Update the outcome description
343 |         outcome.description = new_description.strip()
344 | 
345 |         # Save the updated knowledge package
346 |         ShareStorage.write_share(share_id, share)
347 | 
348 |         # Log the outcome update
349 |         await ShareStorage.log_share_event(
350 |             context=context,
351 |             share_id=share_id,
352 |             entry_type=LogEntryType.LEARNING_OBJECTIVE_UPDATED.value,
353 |             message=f"Updated learning outcome in objective '{objective.name}': '{old_description}' → '{new_description}'",
354 |             metadata={
355 |                 "objective_id": objective.id,
356 |                 "objective_name": objective.name,
357 |                 "outcome_id": outcome_id,
358 |                 "old_description": old_description,
359 |                 "new_description": new_description,
360 |             },
361 |         )
362 | 
363 |         # Notify linked conversations
364 |         await Notifications.notify_all(context, share_id, f"Learning outcome '{new_description}' has been updated")
365 |         await Notifications.notify_all_state_update(context, share_id, [InspectorTab.LEARNING, InspectorTab.BRIEF])
366 | 
367 |         return True, f"Learning outcome updated successfully in objective '{objective.name}': {new_description}"
368 | 
369 |     @staticmethod
370 |     async def delete_learning_outcome(
371 |         context: ConversationContext,
372 |         outcome_id: str,
373 |     ) -> Tuple[bool, Optional[str]]:
374 |         """Delete a learning outcome from a learning objective."""
375 |         share_id = await ShareManager.get_share_id(context)
376 |         if not share_id:
377 |             logger.error("Cannot delete learning outcome: no share associated with this conversation")
378 |             return False, "No knowledge package associated with this conversation."
379 | 
380 |         current_user_id = await require_current_user(context, "delete learning outcome")
381 |         if not current_user_id:
382 |             return False, "Could not identify current user."
383 | 
384 |         share = ShareStorage.read_share(share_id)
385 |         if not share or not share.learning_objectives:
386 |             return False, "No learning objectives found. Please add objectives before deleting outcomes."
387 | 
388 |         # Find the outcome by ID across all objectives
389 |         objective = None
390 |         outcome_to_delete = None
391 |         outcome_index = -1
392 |         for obj in share.learning_objectives:
393 |             for idx, out in enumerate(obj.learning_outcomes):
394 |                 if out.id == outcome_id:
395 |                     objective = obj
396 |                     outcome_to_delete = out
397 |                     outcome_index = idx
398 |                     break
399 |             if outcome_to_delete:
400 |                 break
401 | 
402 |         if outcome_to_delete is None or objective is None:
403 |             # Collect available outcome IDs for error message
404 |             available_outcome_ids = []
405 |             for obj in share.learning_objectives:
406 |                 for out in obj.learning_outcomes:
407 |                     available_outcome_ids.append(out.id)
408 |             return (
409 |                 False,
410 |                 f"Learning outcome with ID '{outcome_id}' not found. Available outcome IDs: {', '.join(available_outcome_ids[:3]) + ('...' if len(available_outcome_ids) > 3 else '')}",
411 |             )
412 | 
413 |         deleted_description = outcome_to_delete.description
414 | 
415 |         # Remove the outcome from the objective
416 |         objective.learning_outcomes.pop(outcome_index)
417 | 
418 |         # Clean up any achievement records for this outcome across all team conversations
419 |         for team_info in share.team_conversations.values():
420 |             team_info.outcome_achievements = [
421 |                 achievement for achievement in team_info.outcome_achievements if achievement.outcome_id != outcome_id
422 |             ]
423 | 
424 |         # Save the updated knowledge package
425 |         ShareStorage.write_share(share_id, share)
426 | 
427 |         # Log the outcome deletion
428 |         await ShareStorage.log_share_event(
429 |             context=context,
430 |             share_id=share_id,
431 |             entry_type=LogEntryType.LEARNING_OBJECTIVE_UPDATED.value,
432 |             message=f"Deleted learning outcome from objective '{objective.name}': {deleted_description}",
433 |             metadata={
434 |                 "objective_id": objective.id,
435 |                 "objective_name": objective.name,
436 |                 "outcome_index": outcome_index,
437 |                 "outcome_id": outcome_id,
438 |                 "deleted_description": deleted_description,
439 |             },
440 |         )
441 | 
442 |         # Notify linked conversations
443 |         await Notifications.notify_all(context, share_id, f"Learning outcome '{deleted_description}' has been removed")
444 |         await Notifications.notify_all_state_update(context, share_id, [InspectorTab.LEARNING, InspectorTab.BRIEF])
445 | 
446 |         return True, f"Learning outcome deleted successfully from objective '{objective.name}': {deleted_description}"
447 | 
```
Page 91/145FirstPrevNextLast