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,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "switchroom-telegram",
|
|
3
|
+
"description": "Switchroom's enhanced Telegram channel: HTML formatting, smart message chunking, message coalescing, attachment helpers, progress card with sub-agent visibility, vault-grant wizard, and slash-command admin surface (/restart, /usage, /auth, /vault, /issues).",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Ken Thompson",
|
|
7
|
+
"email": "me@kenthompson.com.au"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/mekenthompson/switchroom",
|
|
10
|
+
"repository": "https://github.com/mekenthompson/switchroom",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"telegram",
|
|
14
|
+
"switchroom",
|
|
15
|
+
"channel",
|
|
16
|
+
"multi-agent",
|
|
17
|
+
"progress-card",
|
|
18
|
+
"vault"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ken Thompson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
# Switchroom Telegram Plugin
|
|
2
|
+
|
|
3
|
+
A production-grade Telegram channel for Claude Code. Forked from the
|
|
4
|
+
[official Claude Code Telegram plugin](https://github.com/anthropics/claude-plugins-official)
|
|
5
|
+
and substantially extended for long-running, multi-agent deployments.
|
|
6
|
+
|
|
7
|
+
## Why this fork exists
|
|
8
|
+
|
|
9
|
+
The upstream plugin handles the basic send/receive wire protocol. This fork
|
|
10
|
+
adds the ergonomics and reliability that an always-on agent fleet needs:
|
|
11
|
+
|
|
12
|
+
- **Streaming replies** — `stream_reply` edits a single message in place as
|
|
13
|
+
work progresses (~1/sec throttle), so users see live progress instead of
|
|
14
|
+
silent gaps followed by a wall-of-text. Optional `lane` parameter lets each
|
|
15
|
+
lane (e.g. `thinking` vs default `answer`) get its own message per chat+thread.
|
|
16
|
+
- **Status reactions** — emoji lifecycle (👀 queued → 🤔 thinking → 👨💻 tool
|
|
17
|
+
use → 🔥 streaming → 👍 done) on the user's own message gives "I'm working"
|
|
18
|
+
feedback for free, plus stall watchdogs (🥱 30s idle, 😨 90s).
|
|
19
|
+
- **Forum topic routing** — `message_thread_id` is auto-captured from inbound
|
|
20
|
+
messages and applied to all replies, so multi-agent setups can run one bot
|
|
21
|
+
per topic in a shared group.
|
|
22
|
+
- **Smart HTML chunking** — long messages split at paragraph/line boundaries
|
|
23
|
+
with tag integrity preserved across the boundary (including `tg-spoiler`,
|
|
24
|
+
`tg-emoji`, and tags with attributes like `<a href>` / `<code class>`).
|
|
25
|
+
- **Persistent SQLite history** — every inbound and outbound message is
|
|
26
|
+
recorded locally. After a process restart, agents call `get_recent_messages`
|
|
27
|
+
to recover context instead of asking "what were we doing?".
|
|
28
|
+
- **Inbound coalescing** — rapid multi-line user messages are buffered and
|
|
29
|
+
delivered as a single turn, so agents see complete thoughts.
|
|
30
|
+
- **Edit-404 recovery + pre-send debounce** — handles the race where a
|
|
31
|
+
message we're trying to edit was deleted, and avoids redundant edits when
|
|
32
|
+
several updates arrive within `idleMs`.
|
|
33
|
+
- **Activity lane suppression** — filters Claude Code TUI noise (spinner verbs
|
|
34
|
+
like "Running Reading", keyboard hints like "ctrl+o to expand") that the
|
|
35
|
+
user can't action and shouldn't see.
|
|
36
|
+
- **Switchroom slash-commands** — `/agents`, `/restart`, `/logs`, `/memory`,
|
|
37
|
+
`/grant`, `/dangerous`, `/permissions`, `/reconcile` etc., handled by the
|
|
38
|
+
plugin without consuming Claude Code tokens.
|
|
39
|
+
- **12 MCP tools** — `reply`, `stream_reply`, `react`, `edit_message`,
|
|
40
|
+
`delete_message`, `forward_message`, `pin_message`, `send_typing`,
|
|
41
|
+
`download_attachment`, `get_recent_messages`, `send_checklist`,
|
|
42
|
+
`update_checklist` (the latter two ship native Telegram checklists,
|
|
43
|
+
see #272).
|
|
44
|
+
|
|
45
|
+
The fork is the **default** for switchroom agents (no config needed). Set
|
|
46
|
+
`channels.telegram.plugin: official` to fall back to the upstream plugin.
|
|
47
|
+
|
|
48
|
+
## What changed from the official plugin
|
|
49
|
+
|
|
50
|
+
All existing functionality is preserved. The following additions enable topic/forum routing:
|
|
51
|
+
|
|
52
|
+
### 1. Topic filtering via `TELEGRAM_TOPIC_ID`
|
|
53
|
+
|
|
54
|
+
Set this env var to restrict the plugin to a single forum topic. Messages from other topics are silently ignored.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# In ~/.claude/channels/telegram/.env
|
|
58
|
+
TELEGRAM_TOPIC_ID=12345
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
If unset, all messages are processed as before (fully backwards compatible).
|
|
62
|
+
|
|
63
|
+
### 2. Inbound topic metadata
|
|
64
|
+
|
|
65
|
+
When a message arrives from a forum topic, the MCP notification metadata includes:
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
message_thread_id: "12345"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This lets downstream agents know which topic the message came from.
|
|
72
|
+
|
|
73
|
+
### 3. Reply tool: `message_thread_id` parameter
|
|
74
|
+
|
|
75
|
+
The `reply` tool accepts an optional `message_thread_id` parameter to target a specific forum topic.
|
|
76
|
+
|
|
77
|
+
**Auto-capture**: When an inbound message has a `message_thread_id`, the plugin stores it per `chat_id`. Subsequent replies to that chat automatically route to the same topic without the agent needing to specify it. An explicit `message_thread_id` in the tool call overrides the auto-captured value.
|
|
78
|
+
|
|
79
|
+
### 4. File sending: thread-aware
|
|
80
|
+
|
|
81
|
+
All file-sending methods (`sendPhoto`, `sendDocument`) pass `message_thread_id` so attachments land in the correct topic.
|
|
82
|
+
|
|
83
|
+
### 5. Edit tool: unchanged
|
|
84
|
+
|
|
85
|
+
`edit_message` targets a specific `message_id` and does not need `message_thread_id`.
|
|
86
|
+
|
|
87
|
+
## Setup
|
|
88
|
+
|
|
89
|
+
Same as the official plugin. Requires:
|
|
90
|
+
|
|
91
|
+
- [Bun](https://bun.sh) runtime
|
|
92
|
+
- `TELEGRAM_BOT_TOKEN` in `~/.claude/channels/telegram/.env`
|
|
93
|
+
- Optionally `TELEGRAM_TOPIC_ID` for topic filtering
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
cd telegram-plugin
|
|
97
|
+
bun install
|
|
98
|
+
bun server.ts
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## How topic routing works
|
|
102
|
+
|
|
103
|
+
1. Bot receives a message in a supergroup forum topic
|
|
104
|
+
2. Grammy provides `ctx.message.is_topic_message` and `ctx.message.message_thread_id`
|
|
105
|
+
3. If `TELEGRAM_TOPIC_ID` is set and doesn't match, the message is dropped early
|
|
106
|
+
4. Otherwise, the `message_thread_id` is included in the MCP notification metadata and auto-captured for replies
|
|
107
|
+
5. When the agent calls the `reply` tool, `message_thread_id` is passed to `bot.api.sendMessage()` so the response lands in the correct topic thread
|
|
108
|
+
|
|
109
|
+
## Enhanced features
|
|
110
|
+
|
|
111
|
+
### HTML formatting (default)
|
|
112
|
+
|
|
113
|
+
Outbound messages now default to `"html"` parse mode. Markdown in reply/edit text is auto-converted to Telegram HTML:
|
|
114
|
+
|
|
115
|
+
| Markdown | Telegram HTML |
|
|
116
|
+
|----------|---------------|
|
|
117
|
+
| `**bold**` | `<b>bold</b>` |
|
|
118
|
+
| `*italic*` | `<i>italic</i>` |
|
|
119
|
+
| `` `code` `` | `<code>code</code>` |
|
|
120
|
+
| ```` ```lang\ncode\n``` ```` | `<pre><code class="language-lang">code</code></pre>` |
|
|
121
|
+
| `~~strike~~` | `<s>strike</s>` |
|
|
122
|
+
| `[text](url)` | `<a href="url">text</a>` |
|
|
123
|
+
|
|
124
|
+
File references like `server.ts` or `package.json` are auto-wrapped in `<code>` tags. HTML entities (`<`, `>`, `&`) are escaped in plain text.
|
|
125
|
+
|
|
126
|
+
The `format` parameter accepts `"html"` (default), `"markdownv2"`, or `"text"`. Configure the default via `parseMode` in `access.json`.
|
|
127
|
+
|
|
128
|
+
### Smart HTML chunking
|
|
129
|
+
|
|
130
|
+
Long HTML messages are split at paragraph (`\n\n`), line (`\n`), or space boundaries. Open HTML tags are automatically closed at chunk boundaries and reopened in the next chunk, preventing broken formatting.
|
|
131
|
+
|
|
132
|
+
Default chunk limit: 4000 characters (configurable via `textChunkLimit` in `access.json`).
|
|
133
|
+
|
|
134
|
+
### Inbound message coalescing
|
|
135
|
+
|
|
136
|
+
Rapid consecutive messages from the same user/chat are buffered and combined into a single delivery (joined with `\n`). The buffer flushes after `coalescingGapMs` milliseconds of silence (default: 500ms — lowered from 1500ms in #553 PR 3 to shrink the silent gap before the agent's first text lands).
|
|
137
|
+
|
|
138
|
+
This prevents fragmented context when users send multi-line thoughts across several quick messages. Non-text messages (photos, documents, etc.) bypass coalescing.
|
|
139
|
+
|
|
140
|
+
Set `coalescingGapMs` to `0` in `access.json` to disable.
|
|
141
|
+
|
|
142
|
+
### Typing indicator auto-refresh
|
|
143
|
+
|
|
144
|
+
The `send_typing` tool now auto-refreshes the typing indicator every 4 seconds (Telegram's indicator expires after ~5s). Auto-stops after 30 seconds or when the next reply is sent.
|
|
145
|
+
|
|
146
|
+
On 401/Unauthorized errors, uses exponential backoff (up to 5 min) and resets on success.
|
|
147
|
+
|
|
148
|
+
### Error handling and retry
|
|
149
|
+
|
|
150
|
+
All outbound API calls use robust error handling:
|
|
151
|
+
|
|
152
|
+
| Error | Behavior |
|
|
153
|
+
|-------|----------|
|
|
154
|
+
| **429 Too Many Requests** | Wait `retry_after` seconds, then retry |
|
|
155
|
+
| **400 "not modified"** | Silent ignore (edit with same content) |
|
|
156
|
+
| **400 "thread not found"** | Retry without `message_thread_id` |
|
|
157
|
+
| **Network errors** | Retry up to 3 times with exponential backoff |
|
|
158
|
+
|
|
159
|
+
### Link preview control
|
|
160
|
+
|
|
161
|
+
Link previews are disabled by default in outbound messages. Control via:
|
|
162
|
+
- `disable_web_page_preview` parameter in the `reply` tool call
|
|
163
|
+
- `disableLinkPreview` in `access.json` (default: `true`)
|
|
164
|
+
|
|
165
|
+
### Configurable settings in access.json
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"textChunkLimit": 4000,
|
|
170
|
+
"parseMode": "html",
|
|
171
|
+
"disableLinkPreview": true,
|
|
172
|
+
"coalescingGapMs": 500
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
| Setting | Type | Default | Description |
|
|
177
|
+
|---------|------|---------|-------------|
|
|
178
|
+
| `textChunkLimit` | number | 4000 | Max chars per outbound message before splitting |
|
|
179
|
+
| `parseMode` | `"html"` \| `"markdownv2"` \| `"text"` | `"html"` | Default parse mode for outbound messages |
|
|
180
|
+
| `disableLinkPreview` | boolean | `true` | Disable link preview thumbnails |
|
|
181
|
+
| `coalescingGapMs` | number | 500 | Debounce gap for inbound message coalescing (0 = disabled) |
|
|
182
|
+
|
|
183
|
+
### Read receipt indicator
|
|
184
|
+
|
|
185
|
+
When an inbound message is received, the plugin immediately reacts with an emoji to indicate it was seen. Configure via `ackReaction` in `access.json`:
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{
|
|
189
|
+
"ackReaction": "👀"
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Set to an empty string `""` to disable. Only Telegram's fixed emoji whitelist is accepted (👍 👎 ❤ 🔥 👀 🎉 etc). A typing indicator is also sent automatically.
|
|
194
|
+
|
|
195
|
+
### `stream_reply` tool (preferred for multi-step work)
|
|
196
|
+
|
|
197
|
+
Sends or updates a streaming reply that edits one message in-place rather
|
|
198
|
+
than sending many. Call repeatedly during long tasks with full snapshots of
|
|
199
|
+
the current message; the plugin throttles edits to ~1/sec to respect
|
|
200
|
+
Telegram's rate limit. Set `done=true` on the final call to lock the
|
|
201
|
+
message.
|
|
202
|
+
|
|
203
|
+
| Parameter | Required | Description |
|
|
204
|
+
|-----------|----------|-------------|
|
|
205
|
+
| `chat_id` | yes | Target chat ID |
|
|
206
|
+
| `text` | yes | Full text snapshot (NOT a delta — pass the complete current content each call) |
|
|
207
|
+
| `done` | no | `true` on final call. After `done=true` the stream is locked and further calls are no-ops. Default `false`. |
|
|
208
|
+
| `format` | no | `"html"` (default), `"markdownv2"`, or `"text"` |
|
|
209
|
+
| `lane` | no | Optional lane name. Each lane gets its own Telegram message per chat+thread. Use `lane: "thinking"` to surface reasoning progress alongside the main answer stream. Omit for the default answer lane. |
|
|
210
|
+
| `message_thread_id` | no | Forum topic thread ID (auto-applied from the last inbound message if not specified) |
|
|
211
|
+
|
|
212
|
+
Hard-stops at 4096 chars (Telegram message limit). On edit-404 (the message
|
|
213
|
+
we're editing was deleted), the plugin sends a fresh message and continues
|
|
214
|
+
the stream against the new id. A short `idleMs` pre-send debounce coalesces
|
|
215
|
+
back-to-back snapshots before the first wire send, avoiding a redundant
|
|
216
|
+
edit when several updates arrive in the same tick.
|
|
217
|
+
|
|
218
|
+
### Manual streaming progress via `edit_message`
|
|
219
|
+
|
|
220
|
+
If you need finer control than `stream_reply` offers, you can drive the
|
|
221
|
+
edit loop yourself:
|
|
222
|
+
|
|
223
|
+
1. Send an initial "thinking..." message with `reply` — note the returned `message_id`
|
|
224
|
+
2. Call `edit_message` with updated text as work progresses (edits are silent — no push notification)
|
|
225
|
+
3. Call `send_typing` between steps to keep the typing indicator alive (it expires after ~5s)
|
|
226
|
+
4. When done, send a **new** `reply` so the user's device pings with a push notification
|
|
227
|
+
|
|
228
|
+
In most cases `stream_reply` is simpler and is the recommended path.
|
|
229
|
+
|
|
230
|
+
### `send_typing` tool
|
|
231
|
+
|
|
232
|
+
Sends a typing indicator ("Bot is typing...") to a chat. Auto-expires after ~5 seconds. Call repeatedly during long operations.
|
|
233
|
+
|
|
234
|
+
| Parameter | Required | Description |
|
|
235
|
+
|-----------|----------|-------------|
|
|
236
|
+
| `chat_id` | yes | Target chat ID |
|
|
237
|
+
|
|
238
|
+
### `pin_message` tool
|
|
239
|
+
|
|
240
|
+
Pins a message in a chat. Requires admin rights in groups.
|
|
241
|
+
|
|
242
|
+
| Parameter | Required | Description |
|
|
243
|
+
|-----------|----------|-------------|
|
|
244
|
+
| `chat_id` | yes | Chat ID |
|
|
245
|
+
| `message_id` | yes | Message to pin |
|
|
246
|
+
|
|
247
|
+
### `forward_message` tool
|
|
248
|
+
|
|
249
|
+
Forwards an existing message to a chat, preserving original sender attribution. In forum topics, the forwarded message lands in the correct thread (auto-detected or explicit).
|
|
250
|
+
|
|
251
|
+
| Parameter | Required | Description |
|
|
252
|
+
|-----------|----------|-------------|
|
|
253
|
+
| `chat_id` | yes | Destination chat ID |
|
|
254
|
+
| `from_chat_id` | yes | Source chat ID |
|
|
255
|
+
| `message_id` | yes | Message ID to forward |
|
|
256
|
+
| `message_thread_id` | no | Forum topic thread ID (auto-applied if not specified) |
|
|
257
|
+
|
|
258
|
+
### Improved MarkdownV2 formatting
|
|
259
|
+
|
|
260
|
+
When using `format: "markdownv2"` in the `reply` or `edit_message` tools, special characters are now **auto-escaped** outside of code blocks and inline code spans. Agents can write natural markdown without manually escaping Telegram's special characters (`_ * [ ] ( ) ~ > # + - = | { } . !`).
|
|
261
|
+
|
|
262
|
+
Code blocks (`` ``` ... ``` ``) and inline code (`` ` ... ` ``) are preserved as-is.
|
|
263
|
+
|
|
264
|
+
### Voice message metadata
|
|
265
|
+
|
|
266
|
+
When a voice message or audio file is received, the inbound metadata includes:
|
|
267
|
+
|
|
268
|
+
- `attachment_kind: "voice"` or `"audio"`
|
|
269
|
+
- `attachment_file_id` — use with `download_attachment` to fetch the file
|
|
270
|
+
- `attachment_mime` — MIME type (e.g. `audio/ogg` for voice messages)
|
|
271
|
+
|
|
272
|
+
**Whisper transcription**: To auto-transcribe voice messages, set up a Whisper MCP server (e.g. [whisper-mcp](https://github.com/modelcontextprotocol/servers)) and instruct your agent to download voice attachments and pass them to the Whisper tool for transcription.
|
|
273
|
+
|
|
274
|
+
## Switchroom bot commands
|
|
275
|
+
|
|
276
|
+
The plugin includes built-in `/commands` that execute `switchroom` CLI operations directly — no Claude Code tokens consumed, instant response.
|
|
277
|
+
|
|
278
|
+
### Available commands
|
|
279
|
+
|
|
280
|
+
Each plugin instance is bound to one agent (via `SWITCHROOM_AGENT_NAME` set by `start.sh`), so per-agent commands default to **the current agent**. Pass an explicit name only when you want to act on a different one.
|
|
281
|
+
|
|
282
|
+
| Command | Description |
|
|
283
|
+
|---------|-------------|
|
|
284
|
+
| `/agents` | List all agents and their status |
|
|
285
|
+
| `/agentstart [name]` | Start an agent (default: this agent) |
|
|
286
|
+
| `/stop [name]` | Stop an agent (default: this agent) |
|
|
287
|
+
| `/restart [name\|all]` | Restart an agent (default: this agent; pass `all` for every agent) |
|
|
288
|
+
| `/auth` | Show auth/token status |
|
|
289
|
+
| `/topics` | Show topic-to-agent mappings |
|
|
290
|
+
| `/logs [name] [lines]` | Show agent logs (default: this agent, 20 lines, max: 200). `/logs 50` works too. |
|
|
291
|
+
| `/memory <query>` | Search agent memory |
|
|
292
|
+
| `/reconcile [name\|all]` | Re-apply switchroom.yaml + restart (default: this agent) |
|
|
293
|
+
| `/permissions [agent]` | Show allow/deny list (default: this agent) |
|
|
294
|
+
| `/grant <tool>` / `/grant <agent> <tool>` | Grant a tool permission and reconcile (default: this agent) |
|
|
295
|
+
| `/dangerous [off]` / `/dangerous <agent> [off]` | Toggle full tool access (default: this agent) |
|
|
296
|
+
| `/commands` | List all available switchroom bot commands |
|
|
297
|
+
|
|
298
|
+
### How it works
|
|
299
|
+
|
|
300
|
+
Commands are intercepted by Grammy's command handlers *before* reaching the general message handler, so they never trigger Claude Code. Each command:
|
|
301
|
+
|
|
302
|
+
1. Checks sender authorization (must be in the allowlist or an allowed group)
|
|
303
|
+
2. Runs the corresponding `switchroom` CLI command via `execFileSync`
|
|
304
|
+
3. Formats the output for Telegram (monospace code block, truncated at 4000 chars)
|
|
305
|
+
4. Replies in the correct forum topic if applicable
|
|
306
|
+
|
|
307
|
+
### Configuration
|
|
308
|
+
|
|
309
|
+
| Env var | Description |
|
|
310
|
+
|---------|-------------|
|
|
311
|
+
| `SWITCHROOM_CLI_PATH` | Path to the `switchroom` binary (default: `switchroom` on PATH) |
|
|
312
|
+
| `SWITCHROOM_CONFIG` | Path to switchroom config file — passed as `--config` to all commands |
|
|
313
|
+
|
|
314
|
+
### Notes
|
|
315
|
+
|
|
316
|
+
- `/agentstart` is used instead of `/start` to avoid conflicting with Telegram's built-in `/start` command (used for pairing).
|
|
317
|
+
- Commands work in both DM and group/topic contexts.
|
|
318
|
+
- In groups, only users in the group's allowlist can execute commands.
|
|
319
|
+
- Commands are registered with BotFather automatically on startup.
|
|
320
|
+
|
|
321
|
+
## Testing
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
cd telegram-plugin
|
|
325
|
+
bun test
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
402 tests across 19 files (~975 expectations, ~3s). Coverage spans:
|
|
329
|
+
|
|
330
|
+
- `markdownToHtml` — bold, italic, code, code blocks, links, strikethrough,
|
|
331
|
+
escaping, file references, nested formatting, raw-HTML detection
|
|
332
|
+
- `splitHtmlChunks` — basic splitting, tag preservation across boundaries
|
|
333
|
+
(incl. `tg-spoiler`/`tg-emoji` hyphen tags, `<a href>` / `<code class>`
|
|
334
|
+
attribute preservation on reopen, mid-tag-cut back-off), paragraph-
|
|
335
|
+
preference splitting, nested tags
|
|
336
|
+
- `stream_reply` handler — first-call create, subsequent edits, `done=true`
|
|
337
|
+
finalisation, PTY suppression registration (prevents duplicate messages
|
|
338
|
+
after stream finalises), lane separation
|
|
339
|
+
- PTY tail / activity lane — V1 extractor, spinner-verb suppression
|
|
340
|
+
(`Running Reading: ctrl+o to expand` regression pinned), TUI keyboard hint
|
|
341
|
+
suppression (`ctrl+`, `esc to`, `shift+`, `alt+`, `tab to`), continuation-
|
|
342
|
+
line heuristic
|
|
343
|
+
- Outbound ordering — per-chat queue, parseMode rotation on retry, noisy-tool
|
|
344
|
+
suppression
|
|
345
|
+
- Coalescing — key uniqueness, message combining, newline handling
|
|
346
|
+
- Edit-404 recovery + idleMs pre-send debounce
|
|
347
|
+
- Status reactions lifecycle, stall watchdogs
|
|
348
|
+
- Steering, handoff continuity, context exhaustion, history (SQLite)
|
|
349
|
+
|
|
350
|
+
## Use case: multi-agent orchestration
|
|
351
|
+
|
|
352
|
+
In a Switchroom multi-agent setup, each agent instance runs this plugin with its **own bot token** (one bot per agent — Telegram's `getUpdates` long-poll holds an exclusive lock per token, so sharing a token between processes drops messages at random) and its own `TELEGRAM_TOPIC_ID`, routing each forum topic in a shared group to a dedicated agent.
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sweep logic for the active-pins sidecar.
|
|
3
|
+
*
|
|
4
|
+
* The sidecar (see `active-pins.ts`) records every progress-card
|
|
5
|
+
* message the bot has pinned but not yet unpinned. Two lifecycle
|
|
6
|
+
* events consume it:
|
|
7
|
+
*
|
|
8
|
+
* 1. Startup — when a new bot process boots, it sweeps any entries
|
|
9
|
+
* left over from a prior session that crashed or was killed
|
|
10
|
+
* mid-turn. Without this, the pins stay on Telegram forever
|
|
11
|
+
* because the in-memory map that tracks them died with the old
|
|
12
|
+
* process.
|
|
13
|
+
*
|
|
14
|
+
* 2. Pre-restart — when the /restart, /reconcile --restart, or
|
|
15
|
+
* /update commands fire a self-restart, the bot proactively
|
|
16
|
+
* unpins any still-pinned cards before it gets SIGTERM'd. This
|
|
17
|
+
* avoids a ~1s window where the restart ack is visible in chat
|
|
18
|
+
* but the previous turn's progress card is still pinned.
|
|
19
|
+
*
|
|
20
|
+
* Both consumers call `sweepActivePins`, which is shaped as a pure
|
|
21
|
+
* function that takes the unpin callback as an argument. That keeps
|
|
22
|
+
* it testable in isolation — the tests pass a fake unpin and assert
|
|
23
|
+
* which pins were visited and whether the sidecar was cleared.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { readActivePins, clearActivePins, type ActivePin } from "./active-pins.js";
|
|
27
|
+
|
|
28
|
+
export type UnpinFn = (chatId: string, messageId: number) => Promise<unknown>;
|
|
29
|
+
/**
|
|
30
|
+
* Optional pre-unpin hook. Called once per sidecar entry before the
|
|
31
|
+
* unpin fires. Used by the boot-time orphan-pin reaper (#689) to edit
|
|
32
|
+
* the message body to a "Restart interrupted this work" banner, so the
|
|
33
|
+
* user sees WHY the card stopped updating rather than silently losing
|
|
34
|
+
* the pin.
|
|
35
|
+
*
|
|
36
|
+
* Hook errors are logged and swallowed: a banner edit failing must
|
|
37
|
+
* never block the unpin (frozen card is worse than no card).
|
|
38
|
+
*/
|
|
39
|
+
export type EditBeforeUnpinFn = (pin: ActivePin) => Promise<unknown>;
|
|
40
|
+
|
|
41
|
+
export interface SweepOptions {
|
|
42
|
+
/** Upper bound on how long to wait for all unpin calls before returning. */
|
|
43
|
+
timeoutMs?: number;
|
|
44
|
+
/** Optional log hook — called with human-readable progress/error lines. */
|
|
45
|
+
log?: (msg: string) => void;
|
|
46
|
+
/**
|
|
47
|
+
* Optional per-pin edit hook fired BEFORE the unpin. Failures are
|
|
48
|
+
* caught and logged; the unpin still runs. See {@link EditBeforeUnpinFn}.
|
|
49
|
+
*/
|
|
50
|
+
editBeforeUnpin?: EditBeforeUnpinFn;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface SweepResult {
|
|
54
|
+
swept: ActivePin[];
|
|
55
|
+
timedOut: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Unpin every entry in the sidecar, then clear it. Bounded by
|
|
60
|
+
* `timeoutMs` (default 2s) so a slow Telegram API can't block a
|
|
61
|
+
* restart indefinitely. Unpin failures are logged and swallowed —
|
|
62
|
+
* the sidecar is cleared regardless so stale entries don't pile up
|
|
63
|
+
* on subsequent boots.
|
|
64
|
+
*/
|
|
65
|
+
export async function sweepActivePins(
|
|
66
|
+
agentDir: string,
|
|
67
|
+
unpin: UnpinFn,
|
|
68
|
+
options: SweepOptions = {},
|
|
69
|
+
): Promise<SweepResult> {
|
|
70
|
+
const log = options.log ?? (() => {});
|
|
71
|
+
const timeoutMs = options.timeoutMs ?? 2000;
|
|
72
|
+
const pins = readActivePins(agentDir);
|
|
73
|
+
if (pins.length === 0) return { swept: [], timedOut: false };
|
|
74
|
+
|
|
75
|
+
log(`sweeping ${pins.length} active pin(s)`);
|
|
76
|
+
const editBeforeUnpin = options.editBeforeUnpin;
|
|
77
|
+
const attempts = pins.map((pin) =>
|
|
78
|
+
Promise.resolve()
|
|
79
|
+
.then(async () => {
|
|
80
|
+
if (editBeforeUnpin != null) {
|
|
81
|
+
try {
|
|
82
|
+
await editBeforeUnpin(pin);
|
|
83
|
+
} catch (err) {
|
|
84
|
+
// Banner edits are best-effort — message may already be gone
|
|
85
|
+
// or the bot may have lost edit rights. Don't block unpin.
|
|
86
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
87
|
+
log(`banner edit failed for ${pin.chatId}/${pin.messageId}: ${msg}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return unpin(pin.chatId, pin.messageId);
|
|
91
|
+
})
|
|
92
|
+
.catch((err: unknown) => {
|
|
93
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
94
|
+
log(`unpin failed for ${pin.chatId}/${pin.messageId}: ${msg}`);
|
|
95
|
+
}),
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
let timedOut = false;
|
|
99
|
+
await Promise.race([
|
|
100
|
+
Promise.allSettled(attempts),
|
|
101
|
+
new Promise<void>((resolve) =>
|
|
102
|
+
setTimeout(() => {
|
|
103
|
+
timedOut = true;
|
|
104
|
+
resolve();
|
|
105
|
+
}, timeoutMs),
|
|
106
|
+
),
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
// By design: clear the sidecar on timeout even though in-flight unpins
|
|
110
|
+
// may not have landed. Telegram's unpin is idempotent, so a retried unpin
|
|
111
|
+
// on the next boot is a cheap no-op, whereas keeping the sidecar entries
|
|
112
|
+
// around would have the sweep re-fire forever whenever Telegram is slow.
|
|
113
|
+
clearActivePins(agentDir);
|
|
114
|
+
return { swept: pins, timedOut };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* A single pinned message returned from Telegram's `getChat` API,
|
|
119
|
+
* narrowed to the fields this sweep needs. `fromId` is null when the
|
|
120
|
+
* pinned message has no `from` (e.g., anonymous channel posts) — in
|
|
121
|
+
* that case the sweep treats the pin as foreign and stops, since we
|
|
122
|
+
* can only confidently unpin messages we authored ourselves.
|
|
123
|
+
*/
|
|
124
|
+
export interface PinnedMessageInfo {
|
|
125
|
+
messageId: number;
|
|
126
|
+
fromId: number | null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export type GetTopPinFn = (chatId: string) => Promise<PinnedMessageInfo | null>;
|
|
130
|
+
|
|
131
|
+
export interface BotAuthoredSweepResult {
|
|
132
|
+
/** One entry per chat — how many bot-authored pins were unpinned there. */
|
|
133
|
+
perChat: Record<string, number>;
|
|
134
|
+
/** Total across all chats. */
|
|
135
|
+
total: number;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Sweep bot-authored pinned messages from the given chats. Telegram's
|
|
140
|
+
* Bot API doesn't expose a "list all pinned messages" endpoint, only
|
|
141
|
+
* `getChat().pinned_message` which returns the topmost pin. This
|
|
142
|
+
* iterates that endpoint: if the top pin is authored by our bot, we
|
|
143
|
+
* unpin it and re-check — the next most recent pin bubbles up. We
|
|
144
|
+
* stop when the top pin is either missing or authored by someone
|
|
145
|
+
* else, which is the safe behavior: a user-pinned message acts as a
|
|
146
|
+
* barrier so we never interfere with pins the user made themselves.
|
|
147
|
+
*
|
|
148
|
+
* The per-chat loop is bounded by `maxPerChat` (default 32) so a
|
|
149
|
+
* chat with an unexpected pile of bot pins can't spin forever.
|
|
150
|
+
* Failures from `getChat` or `unpin` are logged and tolerated — the
|
|
151
|
+
* sweep advances to the next chat rather than aborting the boot
|
|
152
|
+
* sequence.
|
|
153
|
+
*
|
|
154
|
+
* This complements `sweepActivePins`, which only touches entries
|
|
155
|
+
* previously recorded in the sidecar. Some stale pins never land in
|
|
156
|
+
* the sidecar (e.g., if a pin write raced a crash before `addActivePin`
|
|
157
|
+
* ran, or if the sidecar file itself was lost). This function is the
|
|
158
|
+
* belt-and-suspenders backstop that picks those up on the next boot.
|
|
159
|
+
*/
|
|
160
|
+
export async function sweepBotAuthoredPins(
|
|
161
|
+
chatIds: ReadonlyArray<string>,
|
|
162
|
+
botUserId: number,
|
|
163
|
+
getTopPin: GetTopPinFn,
|
|
164
|
+
unpin: UnpinFn,
|
|
165
|
+
options: SweepOptions & { maxPerChat?: number } = {},
|
|
166
|
+
): Promise<BotAuthoredSweepResult> {
|
|
167
|
+
const log = options.log ?? (() => {});
|
|
168
|
+
const maxPerChat = options.maxPerChat ?? 32;
|
|
169
|
+
const perChat: Record<string, number> = {};
|
|
170
|
+
let total = 0;
|
|
171
|
+
|
|
172
|
+
for (const chatId of chatIds) {
|
|
173
|
+
let unpinnedHere = 0;
|
|
174
|
+
for (let i = 0; i < maxPerChat; i++) {
|
|
175
|
+
let top: PinnedMessageInfo | null;
|
|
176
|
+
try {
|
|
177
|
+
top = await getTopPin(chatId);
|
|
178
|
+
} catch (err) {
|
|
179
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
180
|
+
log(`getChat failed for ${chatId}: ${msg}`);
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
if (top == null) break;
|
|
184
|
+
if (top.fromId !== botUserId) break;
|
|
185
|
+
try {
|
|
186
|
+
await unpin(chatId, top.messageId);
|
|
187
|
+
unpinnedHere++;
|
|
188
|
+
total++;
|
|
189
|
+
} catch (err) {
|
|
190
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
191
|
+
log(`unpin failed for ${chatId}/${top.messageId}: ${msg}`);
|
|
192
|
+
// If unpin fails, the top pin stays — another loop iteration
|
|
193
|
+
// would fetch the same one and loop forever. Break out.
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (unpinnedHere > 0) {
|
|
198
|
+
perChat[chatId] = unpinnedHere;
|
|
199
|
+
log(`unpinned ${unpinnedHere} bot-authored pin(s) in ${chatId}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return { perChat, total };
|
|
204
|
+
}
|