switchroom 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +447 -0
- package/bin/autoaccept.exp +81 -0
- package/bin/boot-self-test.sh +149 -0
- package/bin/bridge-watchdog.sh +967 -0
- package/bin/handoff-briefing.sh +206 -0
- package/bin/run-hook.sh +228 -0
- package/bin/switchroom.ts +4 -0
- package/bin/timezone-hook.sh +67 -0
- package/bin/user-profile-refresh-hook.sh +38 -0
- package/bin/workspace-dynamic-hook.sh +142 -0
- package/bin/workspace-stable-hook.sh +57 -0
- package/dist/cli/autoaccept-poll.js +118 -0
- package/dist/cli/switchroom.js +48557 -0
- package/package.json +95 -0
- package/profiles/_base/settings.json.hbs +15 -0
- package/profiles/_base/start.sh.hbs +383 -0
- package/profiles/_shared/telegram-style.md.hbs +140 -0
- package/profiles/coding/CLAUDE.md.hbs +57 -0
- package/profiles/coding/skills/architecture/SKILL.md +70 -0
- package/profiles/coding/skills/code-review/SKILL.md +58 -0
- package/profiles/coding/workspace/SOUL.md.hbs +25 -0
- package/profiles/default/CLAUDE.md +238 -0
- package/profiles/default/CLAUDE.md.hbs +113 -0
- package/profiles/default/workspace/CLAUDE.md.hbs +126 -0
- package/profiles/default/workspace/HEARTBEAT.md.hbs +40 -0
- package/profiles/default/workspace/IDENTITY.md.hbs +32 -0
- package/profiles/default/workspace/MEMORY.md.hbs +29 -0
- package/profiles/default/workspace/SOUL.md.hbs +61 -0
- package/profiles/default/workspace/TOOLS.md.hbs +29 -0
- package/profiles/default/workspace/USER.md.hbs +52 -0
- package/profiles/default/workspace/memory/.gitkeep +0 -0
- package/profiles/executive-assistant/CLAUDE.md.hbs +51 -0
- package/profiles/executive-assistant/skills/daily-briefing/SKILL.md +55 -0
- package/profiles/executive-assistant/skills/meeting-prep/SKILL.md +58 -0
- package/profiles/executive-assistant/workspace/SOUL.md.hbs +25 -0
- package/profiles/health-coach/CLAUDE.md.hbs +45 -0
- package/profiles/health-coach/skills/check-in/SKILL.md +41 -0
- package/profiles/health-coach/skills/weekly-review/SKILL.md +53 -0
- package/profiles/health-coach/workspace/SOUL.md.hbs +25 -0
- package/skills/buildkite-agent-infrastructure/SKILL.md +302 -0
- package/skills/buildkite-agent-infrastructure/agents/openai.yaml +6 -0
- package/skills/buildkite-agent-infrastructure/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-agent-infrastructure/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-agent-infrastructure/references/audit-logging.md +87 -0
- package/skills/buildkite-agent-infrastructure/references/graphql-mutations.md +690 -0
- package/skills/buildkite-agent-infrastructure/references/instance-shapes.md +38 -0
- package/skills/buildkite-agent-infrastructure/references/pipeline-templates.md +73 -0
- package/skills/buildkite-agent-infrastructure/references/self-hosted-agents.md +137 -0
- package/skills/buildkite-agent-infrastructure/references/sso-saml.md +92 -0
- package/skills/buildkite-agent-runtime/SKILL.md +476 -0
- package/skills/buildkite-agent-runtime/agents/openai.yaml +6 -0
- package/skills/buildkite-agent-runtime/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-agent-runtime/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-agent-runtime/references/flag-reference.md +417 -0
- package/skills/buildkite-agent-runtime/references/patterns-and-recipes.md +555 -0
- package/skills/buildkite-api/SKILL.md +285 -0
- package/skills/buildkite-api/agents/openai.yaml +6 -0
- package/skills/buildkite-api/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-api/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-api/references/graphql-reference.md +195 -0
- package/skills/buildkite-api/references/patterns.md +44 -0
- package/skills/buildkite-api/references/webhooks.md +161 -0
- package/skills/buildkite-cli/SKILL.md +379 -0
- package/skills/buildkite-cli/agents/openai.yaml +6 -0
- package/skills/buildkite-cli/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-cli/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-cli/references/command-reference.md +181 -0
- package/skills/buildkite-migration/SKILL.md +182 -0
- package/skills/buildkite-pipelines/SKILL.md +464 -0
- package/skills/buildkite-pipelines/agents/openai.yaml +6 -0
- package/skills/buildkite-pipelines/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-pipelines/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-pipelines/examples/basic-pipeline.yml +24 -0
- package/skills/buildkite-pipelines/examples/optimized-pipeline.yml +100 -0
- package/skills/buildkite-pipelines/references/advanced-patterns.md +286 -0
- package/skills/buildkite-pipelines/references/retry-and-error-codes.md +131 -0
- package/skills/buildkite-pipelines/references/step-types-reference.md +225 -0
- package/skills/buildkite-secure-delivery/SKILL.md +168 -0
- package/skills/buildkite-secure-delivery/agents/openai.yaml +6 -0
- package/skills/buildkite-secure-delivery/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-secure-delivery/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-secure-delivery/references/oidc-cloud-providers.md +83 -0
- package/skills/buildkite-secure-delivery/references/package-publishing.md +100 -0
- package/skills/buildkite-test-engine/SKILL.md +239 -0
- package/skills/buildkite-test-engine/agents/openai.yaml +6 -0
- package/skills/buildkite-test-engine/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-test-engine/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-test-engine/examples/bktec-splitting.yml +16 -0
- package/skills/buildkite-test-engine/examples/collector-pipeline.yml +11 -0
- package/skills/buildkite-test-engine/references/collectors.md +198 -0
- package/skills/buildkite-test-engine/references/splitting-examples.md +93 -0
- package/skills/docx/LICENSE.txt +30 -0
- package/skills/docx/SKILL.md +590 -0
- package/skills/docx/VENDORED.md +32 -0
- package/skills/docx/scripts/__init__.py +1 -0
- package/skills/docx/scripts/accept_changes.py +135 -0
- package/skills/docx/scripts/comment.py +318 -0
- package/skills/docx/scripts/office/helpers/__init__.py +0 -0
- package/skills/docx/scripts/office/helpers/merge_runs.py +199 -0
- package/skills/docx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/skills/docx/scripts/office/pack.py +159 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills/docx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills/docx/scripts/office/soffice.py +183 -0
- package/skills/docx/scripts/office/unpack.py +132 -0
- package/skills/docx/scripts/office/validate.py +111 -0
- package/skills/docx/scripts/office/validators/__init__.py +15 -0
- package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-313.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/base.cpython-313.pyc +0 -0
- package/skills/docx/scripts/office/validators/base.py +847 -0
- package/skills/docx/scripts/office/validators/docx.py +446 -0
- package/skills/docx/scripts/office/validators/pptx.py +275 -0
- package/skills/docx/scripts/office/validators/redlining.py +247 -0
- package/skills/docx/scripts/templates/comments.xml +3 -0
- package/skills/docx/scripts/templates/commentsExtended.xml +3 -0
- package/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/skills/docx/scripts/templates/commentsIds.xml +3 -0
- package/skills/docx/scripts/templates/people.xml +3 -0
- package/skills/file-bug/SKILL.md +129 -0
- package/skills/humanizer/LICENSE +21 -0
- package/skills/humanizer/SKILL.md +559 -0
- package/skills/humanizer/VENDORED.md +38 -0
- package/skills/humanizer-calibrate/SKILL.md +144 -0
- package/skills/mcp-builder/LICENSE.txt +202 -0
- package/skills/mcp-builder/SKILL.md +236 -0
- package/skills/mcp-builder/VENDORED.md +32 -0
- package/skills/mcp-builder/reference/evaluation.md +602 -0
- package/skills/mcp-builder/reference/mcp_best_practices.md +249 -0
- package/skills/mcp-builder/reference/node_mcp_server.md +970 -0
- package/skills/mcp-builder/reference/python_mcp_server.md +719 -0
- package/skills/mcp-builder/scripts/connections.py +151 -0
- package/skills/mcp-builder/scripts/evaluation.py +373 -0
- package/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/skills/mcp-builder/scripts/requirements.txt +2 -0
- package/skills/pdf/LICENSE.txt +30 -0
- package/skills/pdf/SKILL.md +314 -0
- package/skills/pdf/VENDORED.md +32 -0
- package/skills/pdf/forms.md +294 -0
- package/skills/pdf/reference.md +612 -0
- package/skills/pdf/scripts/check_bounding_boxes.py +65 -0
- package/skills/pdf/scripts/check_fillable_fields.py +11 -0
- package/skills/pdf/scripts/convert_pdf_to_images.py +33 -0
- package/skills/pdf/scripts/create_validation_image.py +37 -0
- package/skills/pdf/scripts/extract_form_field_info.py +122 -0
- package/skills/pdf/scripts/extract_form_structure.py +115 -0
- package/skills/pdf/scripts/fill_fillable_fields.py +98 -0
- package/skills/pdf/scripts/fill_pdf_form_with_annotations.py +107 -0
- package/skills/pptx/LICENSE.txt +30 -0
- package/skills/pptx/SKILL.md +232 -0
- package/skills/pptx/VENDORED.md +32 -0
- package/skills/pptx/editing.md +205 -0
- package/skills/pptx/pptxgenjs.md +420 -0
- package/skills/pptx/scripts/__init__.py +0 -0
- package/skills/pptx/scripts/add_slide.py +195 -0
- package/skills/pptx/scripts/clean.py +286 -0
- package/skills/pptx/scripts/office/helpers/__init__.py +0 -0
- package/skills/pptx/scripts/office/helpers/merge_runs.py +199 -0
- package/skills/pptx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/skills/pptx/scripts/office/pack.py +159 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills/pptx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills/pptx/scripts/office/soffice.py +183 -0
- package/skills/pptx/scripts/office/unpack.py +132 -0
- package/skills/pptx/scripts/office/validate.py +111 -0
- package/skills/pptx/scripts/office/validators/__init__.py +15 -0
- package/skills/pptx/scripts/office/validators/base.py +847 -0
- package/skills/pptx/scripts/office/validators/docx.py +446 -0
- package/skills/pptx/scripts/office/validators/pptx.py +275 -0
- package/skills/pptx/scripts/office/validators/redlining.py +247 -0
- package/skills/pptx/scripts/thumbnail.py +289 -0
- package/skills/skill-creator/LICENSE.txt +202 -0
- package/skills/skill-creator/SKILL.md +485 -0
- package/skills/skill-creator/VENDORED.md +32 -0
- package/skills/skill-creator/agents/analyzer.md +274 -0
- package/skills/skill-creator/agents/comparator.md +202 -0
- package/skills/skill-creator/agents/grader.md +223 -0
- package/skills/skill-creator/assets/eval_review.html +146 -0
- package/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/skills/skill-creator/references/schemas.md +430 -0
- package/skills/skill-creator/scripts/__init__.py +0 -0
- package/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/skills/skill-creator/scripts/generate_report.py +326 -0
- package/skills/skill-creator/scripts/improve_description.py +247 -0
- package/skills/skill-creator/scripts/package_skill.py +136 -0
- package/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/skills/skill-creator/scripts/run_eval.py +310 -0
- package/skills/skill-creator/scripts/run_loop.py +328 -0
- package/skills/skill-creator/scripts/utils.py +47 -0
- package/skills/switchroom-architecture/SKILL.md +60 -0
- package/skills/switchroom-architecture/cascade.md +112 -0
- package/skills/switchroom-architecture/sub-agents.md +87 -0
- package/skills/switchroom-architecture/telegram.md +94 -0
- package/skills/switchroom-cli/SKILL.md +274 -0
- package/skills/switchroom-health/SKILL.md +101 -0
- package/skills/switchroom-install/SKILL.md +116 -0
- package/skills/switchroom-manage/SKILL.md +90 -0
- package/skills/switchroom-status/SKILL.md +69 -0
- package/skills/switchroom-status/scripts/status.sh +69 -0
- package/skills/telegram-test-harness/SKILL.md +191 -0
- package/skills/token-helpers/SKILL.md +73 -0
- package/skills/token-helpers/scripts/google-cal-token.sh +62 -0
- package/skills/token-helpers/scripts/ms-graph-token.sh +70 -0
- package/skills/webapp-testing/LICENSE.txt +202 -0
- package/skills/webapp-testing/SKILL.md +96 -0
- package/skills/webapp-testing/VENDORED.md +32 -0
- package/skills/webapp-testing/examples/console_logging.py +35 -0
- package/skills/webapp-testing/examples/element_discovery.py +40 -0
- package/skills/webapp-testing/examples/static_html_automation.py +33 -0
- package/skills/webapp-testing/scripts/with_server.py +106 -0
- package/skills/xlsx/LICENSE.txt +30 -0
- package/skills/xlsx/SKILL.md +292 -0
- package/skills/xlsx/VENDORED.md +32 -0
- package/skills/xlsx/scripts/office/helpers/__init__.py +0 -0
- package/skills/xlsx/scripts/office/helpers/merge_runs.py +199 -0
- package/skills/xlsx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/skills/xlsx/scripts/office/pack.py +159 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills/xlsx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills/xlsx/scripts/office/soffice.py +183 -0
- package/skills/xlsx/scripts/office/unpack.py +132 -0
- package/skills/xlsx/scripts/office/validate.py +111 -0
- package/skills/xlsx/scripts/office/validators/__init__.py +15 -0
- package/skills/xlsx/scripts/office/validators/base.py +847 -0
- package/skills/xlsx/scripts/office/validators/docx.py +446 -0
- package/skills/xlsx/scripts/office/validators/pptx.py +275 -0
- package/skills/xlsx/scripts/office/validators/redlining.py +247 -0
- package/skills/xlsx/scripts/recalc.py +184 -0
- package/telegram-plugin/.claude-plugin/plugin.json +20 -0
- package/telegram-plugin/.mcp.json +14 -0
- package/telegram-plugin/LICENSE +21 -0
- package/telegram-plugin/README.md +352 -0
- package/telegram-plugin/active-pins-sweep.ts +204 -0
- package/telegram-plugin/active-pins.ts +146 -0
- package/telegram-plugin/active-reactions-sweep.ts +79 -0
- package/telegram-plugin/active-reactions.ts +134 -0
- package/telegram-plugin/admin-commands/dispatch.test.ts +149 -0
- package/telegram-plugin/admin-commands/index.ts +106 -0
- package/telegram-plugin/answer-stream.ts +565 -0
- package/telegram-plugin/ask-user.ts +179 -0
- package/telegram-plugin/attachment-path.ts +80 -0
- package/telegram-plugin/auth-code-redact.ts +83 -0
- package/telegram-plugin/auth-dashboard.ts +1104 -0
- package/telegram-plugin/auth-slot-parser.ts +497 -0
- package/telegram-plugin/auto-fallback-dispatcher.ts +68 -0
- package/telegram-plugin/auto-fallback.ts +348 -0
- package/telegram-plugin/bridge/bridge.ts +687 -0
- package/telegram-plugin/bridge/ipc-client.ts +326 -0
- package/telegram-plugin/bun.lock +218 -0
- package/telegram-plugin/card-format.ts +62 -0
- package/telegram-plugin/channel-envelope-safety.test.ts +56 -0
- package/telegram-plugin/channel-envelope-safety.ts +56 -0
- package/telegram-plugin/chat-lock.ts +65 -0
- package/telegram-plugin/context-exhaustion.ts +38 -0
- package/telegram-plugin/credits-watch.ts +220 -0
- package/telegram-plugin/dist/bridge/bridge.js +24758 -0
- package/telegram-plugin/dist/foreman/foreman.js +30723 -0
- package/telegram-plugin/dist/gateway/gateway.js +46497 -0
- package/telegram-plugin/dist/server.js +24551 -0
- package/telegram-plugin/dm-command-gate.ts +56 -0
- package/telegram-plugin/docs/gateway-server-split.md +133 -0
- package/telegram-plugin/docs/multi-agent-card-design.md +847 -0
- package/telegram-plugin/docs/pinned-progress-card-reliability.md +144 -0
- package/telegram-plugin/docs/stream-json-daemon-mode.md +477 -0
- package/telegram-plugin/docs/waiting-ux-spec.md +233 -0
- package/telegram-plugin/draft-stream.ts +442 -0
- package/telegram-plugin/draft-transport.ts +72 -0
- package/telegram-plugin/first-paint.ts +246 -0
- package/telegram-plugin/fleet-state.ts +246 -0
- package/telegram-plugin/foreman/foreman-create-flow.ts +202 -0
- package/telegram-plugin/foreman/foreman-handlers.ts +493 -0
- package/telegram-plugin/foreman/foreman.ts +1130 -0
- package/telegram-plugin/foreman/setup-flow.ts +345 -0
- package/telegram-plugin/foreman/setup-state.ts +239 -0
- package/telegram-plugin/foreman/state.ts +203 -0
- package/telegram-plugin/format.ts +685 -0
- package/telegram-plugin/gateway/access-validator.test.ts +95 -0
- package/telegram-plugin/gateway/access-validator.ts +37 -0
- package/telegram-plugin/gateway/boot-card.ts +582 -0
- package/telegram-plugin/gateway/boot-probes.ts +863 -0
- package/telegram-plugin/gateway/boot-reason.ts +51 -0
- package/telegram-plugin/gateway/boot-sweep-filter.test.ts +54 -0
- package/telegram-plugin/gateway/boot-sweep-filter.ts +32 -0
- package/telegram-plugin/gateway/clean-shutdown-marker.ts +183 -0
- package/telegram-plugin/gateway/disconnect-flush.ts +109 -0
- package/telegram-plugin/gateway/gateway.ts +10202 -0
- package/telegram-plugin/gateway/inbound-coalesce.ts +147 -0
- package/telegram-plugin/gateway/inject-handler.test.ts +221 -0
- package/telegram-plugin/gateway/inject-handler.ts +190 -0
- package/telegram-plugin/gateway/ipc-protocol.ts +151 -0
- package/telegram-plugin/gateway/ipc-server.ts +494 -0
- package/telegram-plugin/gateway/pid-file.ts +103 -0
- package/telegram-plugin/gateway/poll-health.ts +156 -0
- package/telegram-plugin/gateway/preamble-suppressor.ts +154 -0
- package/telegram-plugin/gateway/quota-cache.ts +125 -0
- package/telegram-plugin/gateway/resolve-calling-subagent.ts +78 -0
- package/telegram-plugin/gateway/restart-watchdog.ts +200 -0
- package/telegram-plugin/gateway/session-marker.ts +83 -0
- package/telegram-plugin/gateway/shutdown-drain.ts +162 -0
- package/telegram-plugin/gateway/startup-mutex.ts +285 -0
- package/telegram-plugin/gateway/startup-network-retry.ts +142 -0
- package/telegram-plugin/gateway/turn-active-marker.ts +176 -0
- package/telegram-plugin/gateway/unhandled-rejection-policy.ts +78 -0
- package/telegram-plugin/handoff-continuity.ts +200 -0
- package/telegram-plugin/history.ts +468 -0
- package/telegram-plugin/hooks/hooks.json +58 -0
- package/telegram-plugin/hooks/secret-guard-pretool.mjs +208 -0
- package/telegram-plugin/hooks/secret-scrub-stop.mjs +98 -0
- package/telegram-plugin/hooks/silent-end-interrupt-stop.mjs +111 -0
- package/telegram-plugin/hooks/subagent-tracker-posttool.mjs +296 -0
- package/telegram-plugin/hooks/subagent-tracker-pretool.mjs +261 -0
- package/telegram-plugin/html-sanitize.ts +244 -0
- package/telegram-plugin/idle-footer.ts +65 -0
- package/telegram-plugin/inline-keyboard-callbacks.ts +166 -0
- package/telegram-plugin/interrupt-marker.ts +66 -0
- package/telegram-plugin/issues-card.ts +371 -0
- package/telegram-plugin/issues-watcher.ts +125 -0
- package/telegram-plugin/model-unavailable.ts +325 -0
- package/telegram-plugin/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/telegram-plugin/operator-events-history.ts +94 -0
- package/telegram-plugin/operator-events.fixtures.json +161 -0
- package/telegram-plugin/operator-events.ts +421 -0
- package/telegram-plugin/package.json +55 -0
- package/telegram-plugin/permission-rule.ts +133 -0
- package/telegram-plugin/permission-title.ts +117 -0
- package/telegram-plugin/pin-event-log.ts +76 -0
- package/telegram-plugin/plugin-logger.ts +136 -0
- package/telegram-plugin/progress-card-driver.ts +2697 -0
- package/telegram-plugin/progress-card-pin-manager.ts +589 -0
- package/telegram-plugin/progress-card-pin-watchdog.ts +98 -0
- package/telegram-plugin/progress-card.ts +1409 -0
- package/telegram-plugin/pty-partial-handler.ts +247 -0
- package/telegram-plugin/pty-tail.ts +730 -0
- package/telegram-plugin/quota-check.ts +474 -0
- package/telegram-plugin/recent-outbound-dedup.ts +169 -0
- package/telegram-plugin/registry/api-registry.test.ts +201 -0
- package/telegram-plugin/registry/subagents-bugs.test.ts +454 -0
- package/telegram-plugin/registry/subagents-schema.ts +509 -0
- package/telegram-plugin/registry/subagents.test.ts +476 -0
- package/telegram-plugin/registry/turns-schema.test.ts +101 -0
- package/telegram-plugin/registry/turns-schema.ts +417 -0
- package/telegram-plugin/retry-api-call.ts +172 -0
- package/telegram-plugin/scripts/build.mjs +78 -0
- package/telegram-plugin/secret-detect/audit.ts +66 -0
- package/telegram-plugin/secret-detect/chunker.ts +37 -0
- package/telegram-plugin/secret-detect/entropy.ts +20 -0
- package/telegram-plugin/secret-detect/gitleaks-loader.ts +74 -0
- package/telegram-plugin/secret-detect/gitleaks.toml +27 -0
- package/telegram-plugin/secret-detect/index.ts +218 -0
- package/telegram-plugin/secret-detect/kv-scanner.ts +60 -0
- package/telegram-plugin/secret-detect/mask.ts +13 -0
- package/telegram-plugin/secret-detect/patterns.ts +115 -0
- package/telegram-plugin/secret-detect/pipeline.ts +144 -0
- package/telegram-plugin/secret-detect/rewrite.ts +26 -0
- package/telegram-plugin/secret-detect/secretlint-source.ts +95 -0
- package/telegram-plugin/secret-detect/slug.ts +44 -0
- package/telegram-plugin/secret-detect/staging.ts +85 -0
- package/telegram-plugin/secret-detect/suppressor.ts +34 -0
- package/telegram-plugin/secret-detect/url-redact.ts +60 -0
- package/telegram-plugin/secret-detect/vault-write.ts +56 -0
- package/telegram-plugin/server.js +41795 -0
- package/telegram-plugin/server.ts +171 -0
- package/telegram-plugin/session-tail.ts +884 -0
- package/telegram-plugin/shared/bot-runtime.ts +324 -0
- package/telegram-plugin/silent-reply.ts +58 -0
- package/telegram-plugin/slot-banner-driver.ts +147 -0
- package/telegram-plugin/slot-banner.ts +86 -0
- package/telegram-plugin/start.js +26 -0
- package/telegram-plugin/startup-reset.ts +45 -0
- package/telegram-plugin/status-reactions.ts +332 -0
- package/telegram-plugin/steering.ts +155 -0
- package/telegram-plugin/sticker-aliases.ts +249 -0
- package/telegram-plugin/stream-controller.ts +311 -0
- package/telegram-plugin/stream-reply-handler.ts +664 -0
- package/telegram-plugin/streaming-metrics.ts +134 -0
- package/telegram-plugin/streaming-report.ts +204 -0
- package/telegram-plugin/subagent-watcher.ts +880 -0
- package/telegram-plugin/telegram-button-constraints.ts +191 -0
- package/telegram-plugin/telegraph.ts +381 -0
- package/telegram-plugin/tests/HARNESS.md +340 -0
- package/telegram-plugin/tests/_progress-card-harness.ts +105 -0
- package/telegram-plugin/tests/active-pins-boot-reaper.test.ts +211 -0
- package/telegram-plugin/tests/active-pins-sweep.test.ts +309 -0
- package/telegram-plugin/tests/active-pins.test.ts +187 -0
- package/telegram-plugin/tests/active-reactions-sweep.test.ts +116 -0
- package/telegram-plugin/tests/active-reactions.test.ts +198 -0
- package/telegram-plugin/tests/answer-stream-dedup.test.ts +352 -0
- package/telegram-plugin/tests/answer-stream-silent-markers.test.ts +236 -0
- package/telegram-plugin/tests/answer-stream.test.ts +878 -0
- package/telegram-plugin/tests/ask-user.test.ts +203 -0
- package/telegram-plugin/tests/attachment-path.test.ts +199 -0
- package/telegram-plugin/tests/auth-account-identity-surface.test.ts +118 -0
- package/telegram-plugin/tests/auth-code-auto-capture.test.ts +144 -0
- package/telegram-plugin/tests/auth-code-redact.test.ts +248 -0
- package/telegram-plugin/tests/auth-dashboard-edge-cases.test.ts +260 -0
- package/telegram-plugin/tests/auth-dashboard-restart-flow.test.ts +140 -0
- package/telegram-plugin/tests/auth-dashboard-v3b.test.ts +559 -0
- package/telegram-plugin/tests/auth-dashboard.test.ts +1045 -0
- package/telegram-plugin/tests/auth-login-url-button.test.ts +122 -0
- package/telegram-plugin/tests/auth-slot-commands.test.ts +640 -0
- package/telegram-plugin/tests/auto-fallback-dispatcher.e2e.test.ts +183 -0
- package/telegram-plugin/tests/auto-fallback.test.ts +381 -0
- package/telegram-plugin/tests/boot-card-account-quota.test.ts +137 -0
- package/telegram-plugin/tests/boot-card-dedupe.test.ts +154 -0
- package/telegram-plugin/tests/boot-card-probe-target.test.ts +194 -0
- package/telegram-plugin/tests/boot-card-reason.test.ts +103 -0
- package/telegram-plugin/tests/boot-card-render.test.ts +219 -0
- package/telegram-plugin/tests/boot-probes.test.ts +451 -0
- package/telegram-plugin/tests/bot-api.harness.ts +116 -0
- package/telegram-plugin/tests/bot-runtime.test.ts +190 -0
- package/telegram-plugin/tests/bridge-anonymous-refuse.test.ts +60 -0
- package/telegram-plugin/tests/context-exhaustion.test.ts +114 -0
- package/telegram-plugin/tests/credits-watch.test.ts +221 -0
- package/telegram-plugin/tests/dm-command-gate.test.ts +176 -0
- package/telegram-plugin/tests/draft-stream.test.ts +752 -0
- package/telegram-plugin/tests/draft-transport.test.ts +141 -0
- package/telegram-plugin/tests/e2e.test.ts +436 -0
- package/telegram-plugin/tests/fake-bot-api.test.ts +213 -0
- package/telegram-plugin/tests/fake-bot-api.ts +617 -0
- package/telegram-plugin/tests/false-restart-banner.test.ts +253 -0
- package/telegram-plugin/tests/first-paint.test.ts +257 -0
- package/telegram-plugin/tests/fixtures/pty-tail-tmux-fragment.bin +6 -0
- package/telegram-plugin/tests/fixtures/service-log-current-claude-code.bin +3624 -0
- package/telegram-plugin/tests/fleet-state-watcher.test.ts +101 -0
- package/telegram-plugin/tests/fleet-state.test.ts +185 -0
- package/telegram-plugin/tests/foreman-create-flow.test.ts +359 -0
- package/telegram-plugin/tests/foreman-handlers.test.ts +347 -0
- package/telegram-plugin/tests/foreman-state.test.ts +164 -0
- package/telegram-plugin/tests/foreman-write-ops.test.ts +214 -0
- package/telegram-plugin/tests/gateway-409-retry-banner.test.ts +173 -0
- package/telegram-plugin/tests/gateway-boot-marker-clear.test.ts +72 -0
- package/telegram-plugin/tests/gateway-bridge.test.ts +811 -0
- package/telegram-plugin/tests/gateway-clean-shutdown-marker.test.ts +414 -0
- package/telegram-plugin/tests/gateway-disconnect-flush.test.ts +144 -0
- package/telegram-plugin/tests/gateway-message-validator.test.ts +133 -0
- package/telegram-plugin/tests/gateway-no-reply-single-emit.test.ts +103 -0
- package/telegram-plugin/tests/gateway-secret-detect.test.ts +127 -0
- package/telegram-plugin/tests/gateway-startup-mutex.test.ts +284 -0
- package/telegram-plugin/tests/gateway-startup-network-retry.test.ts +185 -0
- package/telegram-plugin/tests/gateway-startup-reset.test.ts +72 -0
- package/telegram-plugin/tests/gateway-update-placeholder-dispatch.test.ts +125 -0
- package/telegram-plugin/tests/handoff-continuity.test.ts +249 -0
- package/telegram-plugin/tests/harness-ordering-invariants.test.ts +243 -0
- package/telegram-plugin/tests/harness-parse-mode-validation.test.ts +114 -0
- package/telegram-plugin/tests/history.test.ts +364 -0
- package/telegram-plugin/tests/html-balanced.ts +63 -0
- package/telegram-plugin/tests/html-sanitize.test.ts +146 -0
- package/telegram-plugin/tests/idle-footer-wiring.test.ts +88 -0
- package/telegram-plugin/tests/idle-footer.test.ts +66 -0
- package/telegram-plugin/tests/inbound-coalesce.test.ts +127 -0
- package/telegram-plugin/tests/inline-keyboard-callbacks.test.ts +150 -0
- package/telegram-plugin/tests/interrupt-marker.test.ts +126 -0
- package/telegram-plugin/tests/ipc-protocol.test.ts +218 -0
- package/telegram-plugin/tests/ipc-server-anonymous-refuse.test.ts +82 -0
- package/telegram-plugin/tests/ipc-server-client.test.ts +323 -0
- package/telegram-plugin/tests/ipc-server-race.test.ts +183 -0
- package/telegram-plugin/tests/ipc-server-validate-operator.test.ts +91 -0
- package/telegram-plugin/tests/ipc-server-validate-pty-partial.test.ts +64 -0
- package/telegram-plugin/tests/ipc-server-validate-update-placeholder.test.ts +77 -0
- package/telegram-plugin/tests/ipc-validator.test.ts +274 -0
- package/telegram-plugin/tests/issues-card.test.ts +495 -0
- package/telegram-plugin/tests/issues-watcher.test.ts +165 -0
- package/telegram-plugin/tests/model-unavailable.test.ts +303 -0
- package/telegram-plugin/tests/multi-turn-continuity.test.ts +159 -0
- package/telegram-plugin/tests/operator-events-history.test.ts +125 -0
- package/telegram-plugin/tests/operator-events-session-tail.test.ts +192 -0
- package/telegram-plugin/tests/operator-events.test.ts +331 -0
- package/telegram-plugin/tests/outbound-ordering.test.ts +293 -0
- package/telegram-plugin/tests/parse-mode-rotation.test.ts +164 -0
- package/telegram-plugin/tests/permission-rule.test.ts +121 -0
- package/telegram-plugin/tests/permission-title.test.ts +106 -0
- package/telegram-plugin/tests/pin-event-log.test.ts +124 -0
- package/telegram-plugin/tests/plugin-logger.test.ts +97 -0
- package/telegram-plugin/tests/poll-health.test.ts +86 -0
- package/telegram-plugin/tests/preamble-suppressor.test.ts +285 -0
- package/telegram-plugin/tests/progress-card-api-failure-during-deferred.test.ts +73 -0
- package/telegram-plugin/tests/progress-card-close-paths-converge.test.ts +272 -0
- package/telegram-plugin/tests/progress-card-cross-turn.test.ts +258 -0
- package/telegram-plugin/tests/progress-card-dispose-preservepending.test.ts +81 -0
- package/telegram-plugin/tests/progress-card-draft-flag.test.ts +80 -0
- package/telegram-plugin/tests/progress-card-driver-eviction.test.ts +215 -0
- package/telegram-plugin/tests/progress-card-driver-fleet-shadow.test.ts +123 -0
- package/telegram-plugin/tests/progress-card-driver-force-complete-parent-done.test.ts +76 -0
- package/telegram-plugin/tests/progress-card-edit-timestamps-budget.test.ts +62 -0
- package/telegram-plugin/tests/progress-card-memory-bounds.test.ts +84 -0
- package/telegram-plugin/tests/progress-card-pin-failure-paths.test.ts +139 -0
- package/telegram-plugin/tests/progress-card-pin-manager.test.ts +773 -0
- package/telegram-plugin/tests/progress-card-pin-race-fast-turn.test.ts +66 -0
- package/telegram-plugin/tests/progress-card-pin-sidecar-partial-write.test.ts +64 -0
- package/telegram-plugin/tests/progress-card-pin-watchdog.test.ts +190 -0
- package/telegram-plugin/tests/progress-card-sigterm-pin-flush.test.ts +146 -0
- package/telegram-plugin/tests/progress-update.test.ts +236 -0
- package/telegram-plugin/tests/protocol-fixtures.test.ts +59 -0
- package/telegram-plugin/tests/protocol-fixtures.ts +198 -0
- package/telegram-plugin/tests/pty-partial-handler.test.ts +326 -0
- package/telegram-plugin/tests/pty-tail-real-fixture.test.ts +114 -0
- package/telegram-plugin/tests/pty-tail-tmux-fragment.test.ts +71 -0
- package/telegram-plugin/tests/pty-tail.test.ts +525 -0
- package/telegram-plugin/tests/quota-cache.test.ts +187 -0
- package/telegram-plugin/tests/quota-check.test.ts +622 -0
- package/telegram-plugin/tests/races.test.ts +842 -0
- package/telegram-plugin/tests/real-gateway-f1-ladder-integrity.test.ts +123 -0
- package/telegram-plugin/tests/real-gateway-f2-instant-draft.test.ts +82 -0
- package/telegram-plugin/tests/real-gateway-f3-late-card.test.ts +114 -0
- package/telegram-plugin/tests/real-gateway-harness.ts +699 -0
- package/telegram-plugin/tests/real-gateway-i6-turn-flush-replay-dedup.test.ts +313 -0
- package/telegram-plugin/tests/real-gateway-ipc-lifecycle.test.ts +299 -0
- package/telegram-plugin/tests/real-gateway-spec.test.ts +487 -0
- package/telegram-plugin/tests/real-gateway.smoke.test.ts +101 -0
- package/telegram-plugin/tests/recent-outbound-dedup.test.ts +192 -0
- package/telegram-plugin/tests/registry-turns.test.ts +432 -0
- package/telegram-plugin/tests/reply-terminal-reaction.test.ts +149 -0
- package/telegram-plugin/tests/resolve-calling-subagent.test.ts +269 -0
- package/telegram-plugin/tests/restart-watchdog.test.ts +224 -0
- package/telegram-plugin/tests/retry-api-call.test.ts +287 -0
- package/telegram-plugin/tests/secret-detect-audit.test.ts +58 -0
- package/telegram-plugin/tests/secret-detect-fail-closed.test.ts +83 -0
- package/telegram-plugin/tests/secret-detect-gitleaks.test.ts +32 -0
- package/telegram-plugin/tests/secret-detect-oauth-code.test.ts +308 -0
- package/telegram-plugin/tests/secret-detect-pipeline.test.ts +123 -0
- package/telegram-plugin/tests/secret-detect-secretlint.test.ts +101 -0
- package/telegram-plugin/tests/secret-detect-staging.test.ts +45 -0
- package/telegram-plugin/tests/secret-detect-suppressor-no-silent-allow.test.ts +67 -0
- package/telegram-plugin/tests/secret-detect.test.ts +223 -0
- package/telegram-plugin/tests/secret-guard-pretool.test.ts +194 -0
- package/telegram-plugin/tests/send-typing-action-validation.test.ts +61 -0
- package/telegram-plugin/tests/session-tail-capped.test.ts +285 -0
- package/telegram-plugin/tests/session-tail.test.ts +524 -0
- package/telegram-plugin/tests/setup-flow.test.ts +510 -0
- package/telegram-plugin/tests/setup-state.test.ts +146 -0
- package/telegram-plugin/tests/silent-reply-guard.test.ts +122 -0
- package/telegram-plugin/tests/slot-banner-driver.e2e.test.ts +350 -0
- package/telegram-plugin/tests/slot-banner.test.ts +74 -0
- package/telegram-plugin/tests/snapshot-serializer.ts +79 -0
- package/telegram-plugin/tests/spawn-detached-cgroup-escape.test.ts +51 -0
- package/telegram-plugin/tests/status-accent.test.ts +186 -0
- package/telegram-plugin/tests/status-reactions-allowed-filter.test.ts +132 -0
- package/telegram-plugin/tests/status-reactions.test.ts +314 -0
- package/telegram-plugin/tests/steering.test.ts +282 -0
- package/telegram-plugin/tests/sticker-aliases.test.ts +232 -0
- package/telegram-plugin/tests/stream-controller-html-fallback.test.ts +127 -0
- package/telegram-plugin/tests/stream-controller.test.ts +262 -0
- package/telegram-plugin/tests/stream-reply-error-paths.test.ts +208 -0
- package/telegram-plugin/tests/stream-reply-handler.test.ts +1292 -0
- package/telegram-plugin/tests/streaming-e2e.test.ts +389 -0
- package/telegram-plugin/tests/streaming-metrics.test.ts +201 -0
- package/telegram-plugin/tests/streaming-orchestration.test.ts +756 -0
- package/telegram-plugin/tests/subagent-registry-bugs.test.ts +725 -0
- package/telegram-plugin/tests/subagent-tracker-hooks.test.ts +213 -0
- package/telegram-plugin/tests/subagent-watcher-parent-marker.test.ts +274 -0
- package/telegram-plugin/tests/subagent-watcher-stall-notification.test.ts +243 -0
- package/telegram-plugin/tests/subagent-watcher.test.ts +877 -0
- package/telegram-plugin/tests/subagents-schema-init-order.test.ts +109 -0
- package/telegram-plugin/tests/sync-chat-running-subagents.test.ts +116 -0
- package/telegram-plugin/tests/telegram-button-constraints.test.ts +194 -0
- package/telegram-plugin/tests/telegram-format.test.ts +1093 -0
- package/telegram-plugin/tests/telegraph.test.ts +246 -0
- package/telegram-plugin/tests/tool-labels.test.ts +383 -0
- package/telegram-plugin/tests/turn-active-marker.test.ts +195 -0
- package/telegram-plugin/tests/turn-end-regressions.test.ts +489 -0
- package/telegram-plugin/tests/turn-flush-card-takeover.test.ts +218 -0
- package/telegram-plugin/tests/turn-flush-dedup-controller.test.ts +144 -0
- package/telegram-plugin/tests/turn-flush-prose-recovery.test.ts +78 -0
- package/telegram-plugin/tests/turn-flush-safety.test.ts +189 -0
- package/telegram-plugin/tests/turn-signal-tracker.test.ts +107 -0
- package/telegram-plugin/tests/turns-writer.test.ts +323 -0
- package/telegram-plugin/tests/two-zone-bg-carry-full-lifecycle.test.ts +131 -0
- package/telegram-plugin/tests/two-zone-bg-detection.test.ts +120 -0
- package/telegram-plugin/tests/two-zone-bg-done-when-all-terminal.test.ts +114 -0
- package/telegram-plugin/tests/two-zone-bg-early-turn-end.test.ts +87 -0
- package/telegram-plugin/tests/two-zone-bg-survives-next-turn.test.ts +211 -0
- package/telegram-plugin/tests/two-zone-card-cap.test.ts +62 -0
- package/telegram-plugin/tests/two-zone-card-fleet-row.test.ts +101 -0
- package/telegram-plugin/tests/two-zone-card-header-phases.test.ts +68 -0
- package/telegram-plugin/tests/two-zone-card-html-balance.test.ts +110 -0
- package/telegram-plugin/tests/two-zone-card-lifecycle.test.ts +128 -0
- package/telegram-plugin/tests/two-zone-card-sanitise.test.ts +58 -0
- package/telegram-plugin/tests/two-zone-card-snapshot.test.ts +133 -0
- package/telegram-plugin/tests/two-zone-concurrent-turns-isolation.test.ts +155 -0
- package/telegram-plugin/tests/two-zone-phasefor-precedence.test.ts +117 -0
- package/telegram-plugin/tests/two-zone-snapshot-extras.test.ts +143 -0
- package/telegram-plugin/tests/two-zone-stuck-edit-throttle.test.ts +149 -0
- package/telegram-plugin/tests/two-zone-stuck-header-escalation.test.ts +101 -0
- package/telegram-plugin/tests/two-zone-stuck-per-member.test.ts +114 -0
- package/telegram-plugin/tests/two-zone-stuck-recovery.test.ts +105 -0
- package/telegram-plugin/tests/typing-wrap.test.ts +141 -0
- package/telegram-plugin/tests/unhandled-rejection-policy.test.ts +147 -0
- package/telegram-plugin/tests/update-factory-edited-and-reactions.test.ts +108 -0
- package/telegram-plugin/tests/update-factory.ts +305 -0
- package/telegram-plugin/tests/vault-grant-wizard.test.ts +84 -0
- package/telegram-plugin/tests/vault-grants-revoke.test.ts +265 -0
- package/telegram-plugin/tests/vault-subcommands.test.ts +234 -0
- package/telegram-plugin/tests/voice-transcribe.test.ts +196 -0
- package/telegram-plugin/tests/waiting-ux-harness.ts +381 -0
- package/telegram-plugin/tests/waiting-ux.e2e.test.ts +233 -0
- package/telegram-plugin/tests/welcome-text.test.ts +407 -0
- package/telegram-plugin/tool-error-filter.ts +89 -0
- package/telegram-plugin/tool-labels.ts +330 -0
- package/telegram-plugin/tool-names.ts +53 -0
- package/telegram-plugin/turn-flush-prose-recovery.ts +40 -0
- package/telegram-plugin/turn-flush-safety.ts +109 -0
- package/telegram-plugin/turn-signal-tracker.ts +79 -0
- package/telegram-plugin/two-zone-card.ts +249 -0
- package/telegram-plugin/typing-wrap.ts +92 -0
- package/telegram-plugin/voice-transcribe.ts +166 -0
- package/telegram-plugin/welcome-text.ts +359 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the inline status-accent header feature (issue #320 fallback).
|
|
3
|
+
*
|
|
4
|
+
* Covers both the pure `buildAccentHeader` helper and the integration paths
|
|
5
|
+
* through `handleStreamReply` (stream_reply) and the server reply case
|
|
6
|
+
* (exercised via the handler directly since server.ts wires it the same way).
|
|
7
|
+
*/
|
|
8
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
9
|
+
import { buildAccentHeader, handleStreamReply, type StreamReplyDeps, type StreamReplyState } from '../stream-reply-handler.js'
|
|
10
|
+
import type { DraftStreamHandle } from '../draft-stream.js'
|
|
11
|
+
import { createMockBot, installBotResetHook, microtaskFlush } from './bot-api.harness.js'
|
|
12
|
+
|
|
13
|
+
// ─── buildAccentHeader unit tests ────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
describe('buildAccentHeader', () => {
|
|
16
|
+
it("'in-progress' returns the blue circle header", () => {
|
|
17
|
+
expect(buildAccentHeader('in-progress')).toBe('🔵 <i>In progress…</i>\n\n')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it("'done' returns the checkmark header", () => {
|
|
21
|
+
expect(buildAccentHeader('done')).toBe('✅ <b>Done</b>\n\n')
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it("'issue' returns the warning header", () => {
|
|
25
|
+
expect(buildAccentHeader('issue')).toBe('⚠️ <b>Issue</b>\n\n')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('undefined returns empty string (no header)', () => {
|
|
29
|
+
expect(buildAccentHeader(undefined)).toBe('')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('invalid / unrecognised value is silently ignored (returns empty string)', () => {
|
|
33
|
+
expect(buildAccentHeader('unknown')).toBe('')
|
|
34
|
+
expect(buildAccentHeader('')).toBe('')
|
|
35
|
+
expect(buildAccentHeader('DONE')).toBe('')
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
// ─── handleStreamReply integration tests ─────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
function makeState(): StreamReplyState {
|
|
42
|
+
return {
|
|
43
|
+
activeDraftStreams: new Map<string, DraftStreamHandle>(),
|
|
44
|
+
activeDraftParseModes: new Map<string, 'HTML' | 'MarkdownV2' | undefined>(),
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function makeDeps(
|
|
49
|
+
bot: ReturnType<typeof createMockBot>,
|
|
50
|
+
overrides?: Partial<StreamReplyDeps>,
|
|
51
|
+
): StreamReplyDeps {
|
|
52
|
+
return {
|
|
53
|
+
bot,
|
|
54
|
+
markdownToHtml: (t) => `<b>${t}</b>`,
|
|
55
|
+
escapeMarkdownV2: (t) => `\\${t}\\`,
|
|
56
|
+
repairEscapedWhitespace: (t) => t,
|
|
57
|
+
takeHandoffPrefix: () => '',
|
|
58
|
+
assertAllowedChat: () => {},
|
|
59
|
+
resolveThreadId: (_, explicit) => (explicit != null ? Number(explicit) : undefined),
|
|
60
|
+
disableLinkPreview: true,
|
|
61
|
+
defaultFormat: 'html',
|
|
62
|
+
logStreamingEvent: () => {},
|
|
63
|
+
endStatusReaction: () => {},
|
|
64
|
+
historyEnabled: false,
|
|
65
|
+
recordOutbound: () => {},
|
|
66
|
+
writeError: () => {},
|
|
67
|
+
throttleMs: 600,
|
|
68
|
+
...overrides,
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
describe('handleStreamReply accent integration', () => {
|
|
73
|
+
const bot = createMockBot()
|
|
74
|
+
installBotResetHook(bot)
|
|
75
|
+
|
|
76
|
+
beforeEach(() => vi.useFakeTimers())
|
|
77
|
+
afterEach(() => vi.useRealTimers())
|
|
78
|
+
|
|
79
|
+
it("accent='in-progress' prepends the blue-circle header before the body", async () => {
|
|
80
|
+
const state = makeState()
|
|
81
|
+
const deps = makeDeps(bot)
|
|
82
|
+
|
|
83
|
+
const pending = handleStreamReply(
|
|
84
|
+
{ chat_id: '1', text: 'Still working...', accent: 'in-progress' },
|
|
85
|
+
state,
|
|
86
|
+
deps,
|
|
87
|
+
)
|
|
88
|
+
await microtaskFlush()
|
|
89
|
+
await pending
|
|
90
|
+
|
|
91
|
+
const sent = bot.api.sendMessage.mock.calls[0][1] as string
|
|
92
|
+
expect(sent).toMatch(/^🔵 <i>In progress…<\/i>\n\n/)
|
|
93
|
+
expect(sent).toBe('🔵 <i>In progress…</i>\n\n<b>Still working...</b>')
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it("accent='done' prepends the checkmark header before the body", async () => {
|
|
97
|
+
const state = makeState()
|
|
98
|
+
const deps = makeDeps(bot)
|
|
99
|
+
|
|
100
|
+
const pending = handleStreamReply(
|
|
101
|
+
{ chat_id: '1', text: 'Task complete.', accent: 'done' },
|
|
102
|
+
state,
|
|
103
|
+
deps,
|
|
104
|
+
)
|
|
105
|
+
await microtaskFlush()
|
|
106
|
+
await pending
|
|
107
|
+
|
|
108
|
+
const sent = bot.api.sendMessage.mock.calls[0][1] as string
|
|
109
|
+
expect(sent).toBe('✅ <b>Done</b>\n\n<b>Task complete.</b>')
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it("accent='issue' prepends the warning header before the body", async () => {
|
|
113
|
+
const state = makeState()
|
|
114
|
+
const deps = makeDeps(bot)
|
|
115
|
+
|
|
116
|
+
const pending = handleStreamReply(
|
|
117
|
+
{ chat_id: '1', text: 'Blocked on X.', accent: 'issue' },
|
|
118
|
+
state,
|
|
119
|
+
deps,
|
|
120
|
+
)
|
|
121
|
+
await microtaskFlush()
|
|
122
|
+
await pending
|
|
123
|
+
|
|
124
|
+
const sent = bot.api.sendMessage.mock.calls[0][1] as string
|
|
125
|
+
expect(sent).toBe('⚠️ <b>Issue</b>\n\n<b>Blocked on X.</b>')
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('no accent — output is unchanged from today (regression guard)', async () => {
|
|
129
|
+
const state = makeState()
|
|
130
|
+
const deps = makeDeps(bot)
|
|
131
|
+
|
|
132
|
+
const pending = handleStreamReply(
|
|
133
|
+
{ chat_id: '1', text: 'Hello world' },
|
|
134
|
+
state,
|
|
135
|
+
deps,
|
|
136
|
+
)
|
|
137
|
+
await microtaskFlush()
|
|
138
|
+
await pending
|
|
139
|
+
|
|
140
|
+
const sent = bot.api.sendMessage.mock.calls[0][1] as string
|
|
141
|
+
expect(sent).toBe('<b>Hello world</b>')
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it('invalid accent is silently ignored — output equals no-accent path', async () => {
|
|
145
|
+
const state = makeState()
|
|
146
|
+
const deps = makeDeps(bot)
|
|
147
|
+
|
|
148
|
+
const pending = handleStreamReply(
|
|
149
|
+
{ chat_id: '1', text: 'Hello world', accent: 'rainbow' },
|
|
150
|
+
state,
|
|
151
|
+
deps,
|
|
152
|
+
)
|
|
153
|
+
await microtaskFlush()
|
|
154
|
+
await pending
|
|
155
|
+
|
|
156
|
+
const sent = bot.api.sendMessage.mock.calls[0][1] as string
|
|
157
|
+
expect(sent).toBe('<b>Hello world</b>')
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('accent header is included on every call that passes it (full-text replace model)', async () => {
|
|
161
|
+
const state = makeState()
|
|
162
|
+
const deps = makeDeps(bot)
|
|
163
|
+
|
|
164
|
+
// First call
|
|
165
|
+
const p1 = handleStreamReply(
|
|
166
|
+
{ chat_id: '1', text: 'Part one', accent: 'in-progress' },
|
|
167
|
+
state,
|
|
168
|
+
deps,
|
|
169
|
+
)
|
|
170
|
+
await microtaskFlush()
|
|
171
|
+
await p1
|
|
172
|
+
|
|
173
|
+
// Second call — same turn, same accent
|
|
174
|
+
vi.advanceTimersByTime(1000)
|
|
175
|
+
const p2 = handleStreamReply(
|
|
176
|
+
{ chat_id: '1', text: 'Part one Part two', accent: 'in-progress' },
|
|
177
|
+
state,
|
|
178
|
+
deps,
|
|
179
|
+
)
|
|
180
|
+
await microtaskFlush()
|
|
181
|
+
await p2
|
|
182
|
+
|
|
183
|
+
const edited = bot.api.editMessageText.mock.calls[0][2] as string
|
|
184
|
+
expect(edited).toBe('🔵 <i>In progress…</i>\n\n<b>Part one Part two</b>')
|
|
185
|
+
})
|
|
186
|
+
})
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StatusReactionController — allowedReactions filter (#542 fix path).
|
|
3
|
+
*
|
|
4
|
+
* Background: Telegram supergroups can restrict `available_reactions`
|
|
5
|
+
* to a small set. When the bot calls `setMessageReaction` with an
|
|
6
|
+
* emoji outside that set, Telegram returns 400 REACTION_INVALID.
|
|
7
|
+
* Production silently catches and continues — only the emojis that
|
|
8
|
+
* happen to be in the allowed set ever land. Result: the user sees
|
|
9
|
+
* `👀 → 👍` instead of `👀 → 🤔 → 🔥 → 👍`.
|
|
10
|
+
*
|
|
11
|
+
* The controller has fallback logic in `resolveEmoji` for exactly
|
|
12
|
+
* this case — but it was DEAD CODE because gateway.ts:4458 didn't
|
|
13
|
+
* pass `allowedReactions`. The fix wires `chatAvailableReactions`
|
|
14
|
+
* cache (populated by getChat probe) into the controller constructor.
|
|
15
|
+
*
|
|
16
|
+
* These tests pin the controller's behavior under the filter so the
|
|
17
|
+
* dead-code path stops being dead.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { describe, expect, it } from 'vitest'
|
|
21
|
+
import { StatusReactionController } from '../status-reactions.js'
|
|
22
|
+
|
|
23
|
+
describe('StatusReactionController — allowedReactions filter', () => {
|
|
24
|
+
it('with no filter (null), every state emits its preferred emoji', async () => {
|
|
25
|
+
const emits: string[] = []
|
|
26
|
+
const ctrl = new StatusReactionController(
|
|
27
|
+
async (emoji) => { emits.push(emoji) },
|
|
28
|
+
null, // no filter — current production default before #542 fix
|
|
29
|
+
{ debounceMs: 0 },
|
|
30
|
+
)
|
|
31
|
+
ctrl.setQueued()
|
|
32
|
+
ctrl.setThinking()
|
|
33
|
+
ctrl.setTool('Bash')
|
|
34
|
+
ctrl.setDone()
|
|
35
|
+
// Drain any queued emits.
|
|
36
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
37
|
+
expect(emits).toContain('👀')
|
|
38
|
+
expect(emits[emits.length - 1]).toBe('👍')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('with allowedReactions=[👍], non-allowed states fall back to a permitted emoji', async () => {
|
|
42
|
+
// The #542 reproducer: chat only allows 👍. With the filter wired,
|
|
43
|
+
// resolveEmoji's fallback path activates: it walks REACTION_VARIANTS
|
|
44
|
+
// for each state, skipping anything not in allowedReactions, and
|
|
45
|
+
// falls through to the last-resort set ['👍', '👀', '✍'].
|
|
46
|
+
//
|
|
47
|
+
// fails when: someone removes the fallback in resolveEmoji, or the
|
|
48
|
+
// controller stops respecting the filter. Either way the user
|
|
49
|
+
// would see emojis Telegram is going to reject.
|
|
50
|
+
const emits: string[] = []
|
|
51
|
+
const ctrl = new StatusReactionController(
|
|
52
|
+
async (emoji) => { emits.push(emoji) },
|
|
53
|
+
new Set(['👍']),
|
|
54
|
+
{ debounceMs: 0 },
|
|
55
|
+
)
|
|
56
|
+
ctrl.setQueued()
|
|
57
|
+
ctrl.setThinking()
|
|
58
|
+
ctrl.setTool('Bash')
|
|
59
|
+
ctrl.setDone()
|
|
60
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
61
|
+
|
|
62
|
+
// Every emit must be 👍 — no 👀/🤔/🔥 should slip through to a chat
|
|
63
|
+
// that doesn't allow them. The chain may collapse to a single 👍
|
|
64
|
+
// (the controller dedups consecutive same-emoji emits).
|
|
65
|
+
for (const emoji of emits) {
|
|
66
|
+
expect(emoji).toBe('👍')
|
|
67
|
+
}
|
|
68
|
+
expect(emits).toContain('👍') // and at least one 👍 lands
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('with allowedReactions=[👀, 👍], intermediate states use 👀 fallback', async () => {
|
|
72
|
+
// A chat allowing only 👀 + 👍. Intermediates that are normally
|
|
73
|
+
// 🤔 / 🔥 should fall back to 👀 (the only intermediate-class
|
|
74
|
+
// emoji in the allowed set), and terminal stays 👍.
|
|
75
|
+
const emits: string[] = []
|
|
76
|
+
const ctrl = new StatusReactionController(
|
|
77
|
+
async (emoji) => { emits.push(emoji) },
|
|
78
|
+
new Set(['👀', '👍']),
|
|
79
|
+
{ debounceMs: 0 },
|
|
80
|
+
)
|
|
81
|
+
ctrl.setQueued()
|
|
82
|
+
ctrl.setThinking()
|
|
83
|
+
ctrl.setTool('Bash')
|
|
84
|
+
ctrl.setDone()
|
|
85
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
86
|
+
|
|
87
|
+
for (const emoji of emits) {
|
|
88
|
+
expect(['👀', '👍']).toContain(emoji)
|
|
89
|
+
}
|
|
90
|
+
expect(emits[emits.length - 1]).toBe('👍')
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('with allowedReactions=[] (empty set, no reactions allowed), emits are no-ops', async () => {
|
|
94
|
+
// Edge case: chat has explicitly EMPTY available_reactions
|
|
95
|
+
// (extremely rare — e.g., admin set "no reactions allowed").
|
|
96
|
+
// resolveEmoji returns null for every state; the controller
|
|
97
|
+
// chain skips emit. No exception, no Telegram call attempt.
|
|
98
|
+
const emits: string[] = []
|
|
99
|
+
const ctrl = new StatusReactionController(
|
|
100
|
+
async (emoji) => { emits.push(emoji) },
|
|
101
|
+
new Set(),
|
|
102
|
+
{ debounceMs: 0 },
|
|
103
|
+
)
|
|
104
|
+
ctrl.setQueued()
|
|
105
|
+
ctrl.setThinking()
|
|
106
|
+
ctrl.setDone()
|
|
107
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
108
|
+
expect(emits).toEqual([])
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
it('with allowedReactions excluding 👍 entirely, terminal falls back to first allowed', async () => {
|
|
112
|
+
// Bizarre: allow 🎉 only. Terminal 👍 has to fall back to 🎉
|
|
113
|
+
// (which is in the variants of `done` per REACTION_VARIANTS).
|
|
114
|
+
// Or fall back to the last-resort set if 🎉 isn't even in
|
|
115
|
+
// ['👍', '👀', '✍']. Document actual behavior.
|
|
116
|
+
const emits: string[] = []
|
|
117
|
+
const ctrl = new StatusReactionController(
|
|
118
|
+
async (emoji) => { emits.push(emoji) },
|
|
119
|
+
new Set(['🎉']),
|
|
120
|
+
{ debounceMs: 0 },
|
|
121
|
+
)
|
|
122
|
+
ctrl.setDone()
|
|
123
|
+
await new Promise((r) => setTimeout(r, 10))
|
|
124
|
+
// Either 🎉 (if it's a `done` variant) or empty (if no allowed
|
|
125
|
+
// emoji matches any `done` variant or the last-resort set).
|
|
126
|
+
// Pin actual behavior — current REACTION_VARIANTS for `done`
|
|
127
|
+
// determines this.
|
|
128
|
+
if (emits.length > 0) {
|
|
129
|
+
expect(emits[0]).toBe('🎉')
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
})
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
2
|
+
import {
|
|
3
|
+
StatusReactionController,
|
|
4
|
+
resolveToolReactionState,
|
|
5
|
+
REACTION_VARIANTS,
|
|
6
|
+
TELEGRAM_REACTION_WHITELIST,
|
|
7
|
+
} from '../status-reactions.js'
|
|
8
|
+
|
|
9
|
+
function makeEmitter() {
|
|
10
|
+
const calls: string[] = []
|
|
11
|
+
const emit = vi.fn(async (emoji: string) => {
|
|
12
|
+
calls.push(emoji)
|
|
13
|
+
})
|
|
14
|
+
return { emit, calls }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function flush() {
|
|
18
|
+
// Drain the microtask queue (chainPromise.then callbacks). Cannot use
|
|
19
|
+
// setTimeout here because vi.useFakeTimers() would freeze it.
|
|
20
|
+
for (let i = 0; i < 8; i++) {
|
|
21
|
+
await Promise.resolve()
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('resolveToolReactionState', () => {
|
|
26
|
+
it('maps shell-class tools to coding', () => {
|
|
27
|
+
expect(resolveToolReactionState('Bash')).toBe('coding')
|
|
28
|
+
expect(resolveToolReactionState('exec_command')).toBe('coding')
|
|
29
|
+
expect(resolveToolReactionState('shell_run')).toBe('coding')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('maps file-class tools to coding', () => {
|
|
33
|
+
expect(resolveToolReactionState('Read')).toBe('coding')
|
|
34
|
+
expect(resolveToolReactionState('Write')).toBe('coding')
|
|
35
|
+
expect(resolveToolReactionState('Edit')).toBe('coding')
|
|
36
|
+
expect(resolveToolReactionState('MultiEdit')).toBe('coding')
|
|
37
|
+
expect(resolveToolReactionState('Glob')).toBe('coding')
|
|
38
|
+
expect(resolveToolReactionState('Grep')).toBe('coding')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('maps web-class tools to web', () => {
|
|
42
|
+
expect(resolveToolReactionState('WebFetch')).toBe('web')
|
|
43
|
+
expect(resolveToolReactionState('WebSearch')).toBe('web')
|
|
44
|
+
expect(resolveToolReactionState('browser_navigate')).toBe('web')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('falls back to generic tool for everything else', () => {
|
|
48
|
+
expect(resolveToolReactionState('mcp__hindsight__remember')).toBe('tool')
|
|
49
|
+
expect(resolveToolReactionState('TodoCreate')).toBe('tool')
|
|
50
|
+
// TodoWrite contains "write" so it correctly maps to coding
|
|
51
|
+
expect(resolveToolReactionState('TodoWrite')).toBe('coding')
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
describe('REACTION_VARIANTS', () => {
|
|
56
|
+
it('every variant in every state is in the Telegram whitelist', () => {
|
|
57
|
+
for (const [state, variants] of Object.entries(REACTION_VARIANTS)) {
|
|
58
|
+
for (const v of variants) {
|
|
59
|
+
expect(TELEGRAM_REACTION_WHITELIST.has(v),
|
|
60
|
+
`${state} variant "${v}" is not in Telegram's reaction whitelist`,
|
|
61
|
+
).toBe(true)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('🔥 is not in active-work states (queued/tool/coding/web) — #320', () => {
|
|
67
|
+
const activeWorkStates = ['queued', 'tool', 'coding', 'web'] as const
|
|
68
|
+
for (const state of activeWorkStates) {
|
|
69
|
+
expect(REACTION_VARIANTS[state]).not.toContain('🔥')
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('done includes at least one positive completion emoji (👍 or 💯)', () => {
|
|
74
|
+
const done = REACTION_VARIANTS['done']
|
|
75
|
+
const hasPositive = done.includes('👍') || done.includes('💯')
|
|
76
|
+
expect(hasPositive).toBe(true)
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
describe('StatusReactionController', () => {
|
|
81
|
+
beforeEach(() => {
|
|
82
|
+
vi.useFakeTimers()
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
afterEach(() => {
|
|
86
|
+
vi.useRealTimers()
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('setQueued emits the queued emoji immediately', async () => {
|
|
90
|
+
const { emit, calls } = makeEmitter()
|
|
91
|
+
const ctrl = new StatusReactionController(emit)
|
|
92
|
+
ctrl.setQueued()
|
|
93
|
+
await flush()
|
|
94
|
+
expect(calls).toEqual(['👀'])
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('setThinking is debounced by 700ms', async () => {
|
|
98
|
+
const { emit, calls } = makeEmitter()
|
|
99
|
+
const ctrl = new StatusReactionController(emit)
|
|
100
|
+
ctrl.setQueued()
|
|
101
|
+
await flush()
|
|
102
|
+
expect(calls).toEqual(['👀'])
|
|
103
|
+
|
|
104
|
+
ctrl.setThinking()
|
|
105
|
+
await flush()
|
|
106
|
+
// Not yet — debounce window
|
|
107
|
+
expect(calls).toEqual(['👀'])
|
|
108
|
+
|
|
109
|
+
vi.advanceTimersByTime(700)
|
|
110
|
+
await flush()
|
|
111
|
+
expect(calls).toEqual(['👀', '🤔'])
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it('rapid intermediate transitions only emit the last one (coalesces)', async () => {
|
|
115
|
+
const { emit, calls } = makeEmitter()
|
|
116
|
+
const ctrl = new StatusReactionController(emit)
|
|
117
|
+
ctrl.setQueued()
|
|
118
|
+
await flush()
|
|
119
|
+
|
|
120
|
+
// Simulate model flashing thinking → tool → thinking → coding within 200ms
|
|
121
|
+
ctrl.setThinking()
|
|
122
|
+
vi.advanceTimersByTime(100)
|
|
123
|
+
ctrl.setTool('Bash')
|
|
124
|
+
vi.advanceTimersByTime(100)
|
|
125
|
+
ctrl.setThinking()
|
|
126
|
+
vi.advanceTimersByTime(100)
|
|
127
|
+
ctrl.setTool('Read')
|
|
128
|
+
await flush()
|
|
129
|
+
|
|
130
|
+
// Still nothing — debounce hasn't elapsed
|
|
131
|
+
expect(calls).toEqual(['👀'])
|
|
132
|
+
|
|
133
|
+
vi.advanceTimersByTime(700)
|
|
134
|
+
await flush()
|
|
135
|
+
// Only the final state lands (Read → coding 👨💻)
|
|
136
|
+
expect(calls).toEqual(['👀', '👨💻'])
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
it('setDone is terminal and bypasses debounce', async () => {
|
|
140
|
+
const { emit, calls } = makeEmitter()
|
|
141
|
+
const ctrl = new StatusReactionController(emit)
|
|
142
|
+
ctrl.setQueued()
|
|
143
|
+
await flush()
|
|
144
|
+
|
|
145
|
+
ctrl.setDone()
|
|
146
|
+
await flush()
|
|
147
|
+
expect(calls).toEqual(['👀', '👍'])
|
|
148
|
+
|
|
149
|
+
// Subsequent calls are no-ops
|
|
150
|
+
ctrl.setThinking()
|
|
151
|
+
vi.advanceTimersByTime(5000)
|
|
152
|
+
await flush()
|
|
153
|
+
expect(calls).toEqual(['👀', '👍'])
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('setError is terminal', async () => {
|
|
157
|
+
const { emit, calls } = makeEmitter()
|
|
158
|
+
const ctrl = new StatusReactionController(emit)
|
|
159
|
+
ctrl.setQueued()
|
|
160
|
+
await flush()
|
|
161
|
+
|
|
162
|
+
ctrl.setError()
|
|
163
|
+
await flush()
|
|
164
|
+
expect(calls).toEqual(['👀', '😱'])
|
|
165
|
+
|
|
166
|
+
ctrl.setThinking()
|
|
167
|
+
vi.advanceTimersByTime(5000)
|
|
168
|
+
await flush()
|
|
169
|
+
expect(calls).toEqual(['👀', '😱'])
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
it('issue #132: setSilent is terminal and uses 🙊 (distinct from 👍 done)', async () => {
|
|
173
|
+
const { emit, calls } = makeEmitter()
|
|
174
|
+
const ctrl = new StatusReactionController(emit)
|
|
175
|
+
ctrl.setQueued()
|
|
176
|
+
await flush()
|
|
177
|
+
ctrl.setTool('Bash')
|
|
178
|
+
vi.advanceTimersByTime(800)
|
|
179
|
+
await flush()
|
|
180
|
+
|
|
181
|
+
// Turn ends without producing a reply.
|
|
182
|
+
ctrl.setSilent()
|
|
183
|
+
await flush()
|
|
184
|
+
// 🙊 is in the Telegram bot reaction whitelist (speak-no-evil monkey).
|
|
185
|
+
// The choice signals "agent ran tools but said nothing" — distinct
|
|
186
|
+
// from 👍 which the user reads as "agent acknowledged with a reply".
|
|
187
|
+
// setTool('Bash') resolves to the 'coding' state → 👨💻 (first variant).
|
|
188
|
+
expect(calls).toEqual(['👀', '👨💻', '🙊'])
|
|
189
|
+
|
|
190
|
+
// Subsequent calls are no-ops (terminal).
|
|
191
|
+
ctrl.setThinking()
|
|
192
|
+
vi.advanceTimersByTime(5000)
|
|
193
|
+
await flush()
|
|
194
|
+
expect(calls).toEqual(['👀', '👨💻', '🙊'])
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
it('promotes to stallSoft after 30s of no progress', async () => {
|
|
198
|
+
const { emit, calls } = makeEmitter()
|
|
199
|
+
const ctrl = new StatusReactionController(emit)
|
|
200
|
+
ctrl.setQueued()
|
|
201
|
+
await flush()
|
|
202
|
+
|
|
203
|
+
// No further calls — stall watchdog should fire at 30s
|
|
204
|
+
vi.advanceTimersByTime(30000)
|
|
205
|
+
await flush()
|
|
206
|
+
expect(calls).toContain('🥱')
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
it('promotes to stallHard after 90s of no progress', async () => {
|
|
210
|
+
const { emit, calls } = makeEmitter()
|
|
211
|
+
const ctrl = new StatusReactionController(emit)
|
|
212
|
+
ctrl.setQueued()
|
|
213
|
+
await flush()
|
|
214
|
+
|
|
215
|
+
vi.advanceTimersByTime(30000) // stallSoft
|
|
216
|
+
await flush()
|
|
217
|
+
vi.advanceTimersByTime(60000) // total 90s → stallHard
|
|
218
|
+
await flush()
|
|
219
|
+
expect(calls).toContain('😨')
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it('progress signals reset the stall timer', async () => {
|
|
223
|
+
const { emit, calls } = makeEmitter()
|
|
224
|
+
const ctrl = new StatusReactionController(emit)
|
|
225
|
+
ctrl.setQueued()
|
|
226
|
+
await flush()
|
|
227
|
+
|
|
228
|
+
// Tick 25s, then signal progress
|
|
229
|
+
vi.advanceTimersByTime(25000)
|
|
230
|
+
ctrl.setThinking() // resets stall timers
|
|
231
|
+
vi.advanceTimersByTime(800)
|
|
232
|
+
await flush()
|
|
233
|
+
// We should have queued + thinking, but no stall yet
|
|
234
|
+
expect(calls).toEqual(['👀', '🤔'])
|
|
235
|
+
|
|
236
|
+
// Now wait another 20s (total 45s since queued, but only 20s since thinking)
|
|
237
|
+
vi.advanceTimersByTime(20000)
|
|
238
|
+
await flush()
|
|
239
|
+
// Still no stall — the tick reset the watchdog
|
|
240
|
+
expect(calls).toEqual(['👀', '🤔'])
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
it('cancel stops further reactions silently', async () => {
|
|
244
|
+
const { emit, calls } = makeEmitter()
|
|
245
|
+
const ctrl = new StatusReactionController(emit)
|
|
246
|
+
ctrl.setQueued()
|
|
247
|
+
await flush()
|
|
248
|
+
|
|
249
|
+
ctrl.cancel()
|
|
250
|
+
ctrl.setThinking()
|
|
251
|
+
vi.advanceTimersByTime(5000)
|
|
252
|
+
await flush()
|
|
253
|
+
// Only the queued emoji landed; thinking was suppressed
|
|
254
|
+
expect(calls).toEqual(['👀'])
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
it('skips emoji not in the chat allowed set', async () => {
|
|
258
|
+
const { emit, calls } = makeEmitter()
|
|
259
|
+
// This chat only allows 👍 and 🔥
|
|
260
|
+
const allowed = new Set(['👍', '🔥'])
|
|
261
|
+
const ctrl = new StatusReactionController(emit, allowed)
|
|
262
|
+
|
|
263
|
+
ctrl.setQueued() // wants 👀, then 🤔, then 🤓 — none allowed; broad fallback picks 👍
|
|
264
|
+
await flush()
|
|
265
|
+
// 👀, 🤔, 🤓 — none in allowed; broad fallback hits 👍 → 👍
|
|
266
|
+
expect(calls).toEqual(['👍'])
|
|
267
|
+
|
|
268
|
+
ctrl.setThinking() // wants 🤔, falls back through variants, then generic — none in allowed
|
|
269
|
+
vi.advanceTimersByTime(700)
|
|
270
|
+
await flush()
|
|
271
|
+
// 🤔, 🤓, 👀 — none allowed; broad fallback hits 👍 but it's already current → no emit
|
|
272
|
+
expect(calls).toEqual(['👍'])
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
it('serializes API calls through the chain promise', async () => {
|
|
276
|
+
let resolveFirst: () => void = () => {}
|
|
277
|
+
const firstPromise = new Promise<void>(r => (resolveFirst = r))
|
|
278
|
+
const order: string[] = []
|
|
279
|
+
|
|
280
|
+
const emit = vi.fn(async (emoji: string) => {
|
|
281
|
+
if (emoji === '👀') {
|
|
282
|
+
await firstPromise
|
|
283
|
+
}
|
|
284
|
+
order.push(emoji)
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
const ctrl = new StatusReactionController(emit)
|
|
288
|
+
ctrl.setQueued() // immediate
|
|
289
|
+
await flush()
|
|
290
|
+
// First call is in flight, blocked on firstPromise
|
|
291
|
+
|
|
292
|
+
ctrl.setDone() // also immediate (terminal)
|
|
293
|
+
await flush()
|
|
294
|
+
|
|
295
|
+
// The done call should be queued behind the in-flight queued call
|
|
296
|
+
expect(order).toEqual([])
|
|
297
|
+
|
|
298
|
+
resolveFirst()
|
|
299
|
+
await flush()
|
|
300
|
+
expect(order).toEqual(['👀', '👍'])
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
it('does not re-emit the same emoji', async () => {
|
|
304
|
+
const { emit, calls } = makeEmitter()
|
|
305
|
+
const ctrl = new StatusReactionController(emit)
|
|
306
|
+
ctrl.setQueued()
|
|
307
|
+
await flush()
|
|
308
|
+
ctrl.setQueued()
|
|
309
|
+
await flush()
|
|
310
|
+
ctrl.setQueued()
|
|
311
|
+
await flush()
|
|
312
|
+
expect(calls).toEqual(['👀'])
|
|
313
|
+
})
|
|
314
|
+
})
|