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,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status reaction state machine for Telegram bot messages.
|
|
3
|
+
*
|
|
4
|
+
* Ports the pattern from openclaw's src/channels/status-reactions.ts +
|
|
5
|
+
* extensions/telegram/src/status-reaction-variants.ts. The goal is to give
|
|
6
|
+
* the user a glanceable, non-spammy progress signal on their inbound
|
|
7
|
+
* message: 👀 received → 🤔 thinking → ✍/👨💻/⚡ working → 👍 done → 😱 error.
|
|
8
|
+
*
|
|
9
|
+
* Three load-bearing properties (all from openclaw research):
|
|
10
|
+
*
|
|
11
|
+
* 1. Debounce intermediate transitions by 700ms so a model that flashes
|
|
12
|
+
* thinking → tool → thinking → tool doesn't burn the rate limit.
|
|
13
|
+
*
|
|
14
|
+
* 2. Terminal states (queued / done / error) bypass the debounce.
|
|
15
|
+
*
|
|
16
|
+
* 3. Serialize all API calls through a single chain promise so two
|
|
17
|
+
* concurrent transitions never race the Telegram API. Telegram's
|
|
18
|
+
* setMessageReaction replaces atomically — no removeReaction needed.
|
|
19
|
+
*
|
|
20
|
+
* Stall watchdogs auto-promote to 🥱 / 😨 if no transition arrives within
|
|
21
|
+
* 30s / 90s, so a stuck/dead inference loop is visually distinguishable
|
|
22
|
+
* from a long but healthy one.
|
|
23
|
+
*
|
|
24
|
+
* Emoji choices use Telegram's bot reaction whitelist
|
|
25
|
+
* (https://core.telegram.org/bots/api#reactiontype). The fallback chain
|
|
26
|
+
* tries each variant in order — if a chat restricts available reactions
|
|
27
|
+
* (admin-configured in some groups) the controller silently no-ops the
|
|
28
|
+
* unsupported choice instead of throwing.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/** Telegram allows only this fixed set of emoji as bot reactions. */
|
|
32
|
+
export const TELEGRAM_REACTION_WHITELIST = new Set([
|
|
33
|
+
'👍', '👎', '❤', '🔥', '🥰', '👏', '😁', '🤔', '🤯', '😱',
|
|
34
|
+
'🤬', '😢', '🎉', '🤩', '🤮', '💩', '🙏', '👌', '🕊', '🤡',
|
|
35
|
+
'🥱', '🥴', '😍', '🐳', '❤🔥', '🌚', '🌭', '💯', '🤣', '⚡',
|
|
36
|
+
'🍌', '🏆', '💔', '🤨', '😐', '🍓', '🍾', '💋', '🖕', '😈',
|
|
37
|
+
'😴', '😭', '🤓', '👻', '👨💻', '👀', '🎃', '🙈', '😇', '😨',
|
|
38
|
+
'🤝', '✍', '🤗', '🫡', '🎅', '🎄', '☃', '💅', '🤪', '🗿',
|
|
39
|
+
'🆒', '💘', '🙉', '🦄', '😘', '💊', '🙊', '😎', '👾',
|
|
40
|
+
'🤷♂', '🤷', '🤷♀', '😡',
|
|
41
|
+
])
|
|
42
|
+
|
|
43
|
+
/** Logical reaction states the controller tracks. */
|
|
44
|
+
export type ReactionState =
|
|
45
|
+
| 'queued'
|
|
46
|
+
| 'thinking'
|
|
47
|
+
| 'coding'
|
|
48
|
+
| 'web'
|
|
49
|
+
| 'tool'
|
|
50
|
+
| 'compacting'
|
|
51
|
+
| 'done'
|
|
52
|
+
| 'silent'
|
|
53
|
+
| 'error'
|
|
54
|
+
| 'stallSoft'
|
|
55
|
+
| 'stallHard'
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Per-state emoji preference, with fallbacks if the first isn't allowed
|
|
59
|
+
* in this particular chat. Modeled on openclaw's
|
|
60
|
+
* TELEGRAM_STATUS_REACTION_VARIANTS.
|
|
61
|
+
*
|
|
62
|
+
* Semantic split — do not conflate these three tiers:
|
|
63
|
+
* READ 👀 = "I have seen your message" (acknowledgement only)
|
|
64
|
+
* WORKING ✍ = actively doing something (tools, coding, compacting)
|
|
65
|
+
* FINISHED 👍/💯/🎉 = definitively done; a reply landed
|
|
66
|
+
*
|
|
67
|
+
* 🔥 is reserved for genuine 5xx server errors (operator-events.ts).
|
|
68
|
+
* It reads as "on fire / broken" — keep it out of normal active-work states.
|
|
69
|
+
*/
|
|
70
|
+
export const REACTION_VARIANTS: Record<ReactionState, string[]> = {
|
|
71
|
+
queued: ['👀', '🤔', '🤓'], // READ: I see your message
|
|
72
|
+
thinking: ['🤔', '🤓', '👀'], // unchanged
|
|
73
|
+
tool: ['✍', '⚡', '👌'], // WORKING: actively using a tool
|
|
74
|
+
coding: ['👨💻', '✍', '⚡'], // WORKING: writing / running code
|
|
75
|
+
web: ['⚡', '🤔', '👌'], // WORKING: lookup in motion (👀 reserved for READ)
|
|
76
|
+
compacting:['✍', '🤔', '👀'], // unchanged
|
|
77
|
+
done: ['👍', '💯', '🎉'], // FINISHED: reply landed
|
|
78
|
+
// 🙊 — turn ended without producing a user-visible reply. Distinct from
|
|
79
|
+
// 'done' (which means "reply landed") so the user doesn't read 👍 as
|
|
80
|
+
// "agent acknowledged" when actually nothing was sent. See issue #132.
|
|
81
|
+
silent: ['🙊', '🤔', '😐'], // unchanged
|
|
82
|
+
error: ['😱', '😨', '🤯'], // unchanged (genuine alarm)
|
|
83
|
+
stallSoft: ['🥱', '😴', '🤔'], // unchanged
|
|
84
|
+
stallHard: ['😨', '🤯', '😱'], // unchanged
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Map a tool name string from a CallToolRequest into the appropriate
|
|
89
|
+
* reaction state. Falls back to generic 'tool' for anything we don't
|
|
90
|
+
* have a more specific bucket for.
|
|
91
|
+
*/
|
|
92
|
+
export function resolveToolReactionState(toolName: string): ReactionState {
|
|
93
|
+
const n = toolName.toLowerCase()
|
|
94
|
+
if (n.includes('bash') || n.includes('exec') || n.includes('shell')) return 'coding'
|
|
95
|
+
if (n.includes('read') || n.includes('write') || n.includes('edit')
|
|
96
|
+
|| n.includes('multiedit') || n.includes('notebook') || n.includes('glob')
|
|
97
|
+
|| n.includes('grep')) return 'coding'
|
|
98
|
+
if (n.includes('webfetch') || n.includes('websearch') || n.includes('browser')
|
|
99
|
+
|| n.includes('fetch') || n.includes('search')) return 'web'
|
|
100
|
+
return 'tool'
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Configuration knobs the controller respects. */
|
|
104
|
+
export interface StatusReactionConfig {
|
|
105
|
+
/** Milliseconds to wait before applying a non-immediate transition. Default 700. */
|
|
106
|
+
debounceMs?: number
|
|
107
|
+
/** Milliseconds without progress before promoting to stallSoft. Default 30000. */
|
|
108
|
+
stallSoftMs?: number
|
|
109
|
+
/** Milliseconds without progress before promoting to stallHard. Default 90000. */
|
|
110
|
+
stallHardMs?: number
|
|
111
|
+
/** Optional logger for debugging — receives a single string per event. */
|
|
112
|
+
log?: (msg: string) => void
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Function the controller calls to actually emit a reaction. Receives the
|
|
117
|
+
* resolved emoji (already filtered through the chat's allowed set) and
|
|
118
|
+
* should return a promise that resolves once the API call completes.
|
|
119
|
+
*
|
|
120
|
+
* The function should NOT throw on Telegram errors — silently swallow
|
|
121
|
+
* unsupported-reaction failures so the controller can move on.
|
|
122
|
+
*/
|
|
123
|
+
export type ReactionEmitter = (emoji: string) => Promise<void>
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Controller managing the reaction lifecycle for a single inbound message.
|
|
127
|
+
*
|
|
128
|
+
* Lifecycle: construct → setQueued() → arbitrary intermediate transitions
|
|
129
|
+
* → setDone() / setError() to terminate. After termination, all further
|
|
130
|
+
* setX calls are no-ops.
|
|
131
|
+
*/
|
|
132
|
+
export class StatusReactionController {
|
|
133
|
+
private currentEmoji: string | null = null
|
|
134
|
+
private pendingEmoji: string | null = null
|
|
135
|
+
private chainPromise: Promise<unknown> = Promise.resolve()
|
|
136
|
+
private debounceTimer: ReturnType<typeof setTimeout> | null = null
|
|
137
|
+
private stallSoftTimer: ReturnType<typeof setTimeout> | null = null
|
|
138
|
+
private stallHardTimer: ReturnType<typeof setTimeout> | null = null
|
|
139
|
+
private finished = false
|
|
140
|
+
private readonly debounceMs: number
|
|
141
|
+
private readonly stallSoftMs: number
|
|
142
|
+
private readonly stallHardMs: number
|
|
143
|
+
private readonly log?: (msg: string) => void
|
|
144
|
+
|
|
145
|
+
constructor(
|
|
146
|
+
private readonly emit: ReactionEmitter,
|
|
147
|
+
/** Chat reactions allowed in this specific chat (null = all whitelisted). */
|
|
148
|
+
private readonly allowedReactions: Set<string> | null = null,
|
|
149
|
+
config: StatusReactionConfig = {},
|
|
150
|
+
) {
|
|
151
|
+
this.debounceMs = config.debounceMs ?? 700
|
|
152
|
+
this.stallSoftMs = config.stallSoftMs ?? 30000
|
|
153
|
+
this.stallHardMs = config.stallHardMs ?? 90000
|
|
154
|
+
this.log = config.log
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** 👀 — message received and queued for processing. Bypasses debounce. */
|
|
158
|
+
setQueued(): void {
|
|
159
|
+
this.scheduleState('queued', { immediate: true })
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** 🤔 — model is generating. Debounced. */
|
|
163
|
+
setThinking(): void {
|
|
164
|
+
this.scheduleState('thinking')
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** Tool-specific reaction. Debounced. */
|
|
168
|
+
setTool(toolName?: string): void {
|
|
169
|
+
const state = toolName ? resolveToolReactionState(toolName) : 'tool'
|
|
170
|
+
this.scheduleState(state)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** ✍ — context compaction in progress. */
|
|
174
|
+
setCompacting(): void {
|
|
175
|
+
this.scheduleState('compacting')
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** 👍 — final reply delivered. Terminal, bypasses debounce. */
|
|
179
|
+
setDone(): void {
|
|
180
|
+
this.finishWithState('done')
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* 🙊 — turn ended without producing a user-visible reply.
|
|
185
|
+
*
|
|
186
|
+
* Distinct from `setDone()` so the user doesn't read 👍 as "agent
|
|
187
|
+
* acknowledged but stayed silent on purpose" when in fact nothing was
|
|
188
|
+
* actually sent. Common case (#132): agent ran a long Bash chain to
|
|
189
|
+
* answer a question, never called `reply` / `stream_reply`, and the
|
|
190
|
+
* orphaned-reply backstop had no captured text to forward either.
|
|
191
|
+
* Terminal, bypasses debounce.
|
|
192
|
+
*/
|
|
193
|
+
setSilent(): void {
|
|
194
|
+
this.finishWithState('silent')
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** 😱 — generation failed. Terminal, bypasses debounce. */
|
|
198
|
+
setError(): void {
|
|
199
|
+
this.finishWithState('error')
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Stop the controller without applying any new reaction. Terminal. */
|
|
203
|
+
cancel(): void {
|
|
204
|
+
if (this.finished) return
|
|
205
|
+
this.finished = true
|
|
206
|
+
this.clearDebounceTimer()
|
|
207
|
+
this.clearStallTimers()
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
211
|
+
|
|
212
|
+
private scheduleState(
|
|
213
|
+
state: ReactionState,
|
|
214
|
+
opts: { immediate?: boolean; skipStallReset?: boolean } = {},
|
|
215
|
+
): void {
|
|
216
|
+
if (this.finished) return
|
|
217
|
+
const emoji = this.resolveEmoji(state)
|
|
218
|
+
if (emoji == null) {
|
|
219
|
+
// No allowed variant for this chat — silently skip rather than fall
|
|
220
|
+
// through to the chain. We still reset stall timers so that progress
|
|
221
|
+
// signals continue to keep the watchdogs at bay.
|
|
222
|
+
if (!opts.skipStallReset) this.resetStallTimers()
|
|
223
|
+
return
|
|
224
|
+
}
|
|
225
|
+
if (emoji === this.currentEmoji || emoji === this.pendingEmoji) {
|
|
226
|
+
if (!opts.skipStallReset) this.resetStallTimers()
|
|
227
|
+
return
|
|
228
|
+
}
|
|
229
|
+
this.pendingEmoji = emoji
|
|
230
|
+
this.clearDebounceTimer()
|
|
231
|
+
if (opts.immediate) {
|
|
232
|
+
this.enqueue(emoji)
|
|
233
|
+
} else {
|
|
234
|
+
this.debounceTimer = setTimeout(() => {
|
|
235
|
+
this.debounceTimer = null
|
|
236
|
+
this.enqueue(emoji)
|
|
237
|
+
}, this.debounceMs)
|
|
238
|
+
}
|
|
239
|
+
if (!opts.skipStallReset) this.resetStallTimers()
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private finishWithState(state: ReactionState): void {
|
|
243
|
+
if (this.finished) return
|
|
244
|
+
this.finished = true
|
|
245
|
+
this.clearStallTimers()
|
|
246
|
+
// F1 fix (#553): if a non-terminal reaction is sitting in the
|
|
247
|
+
// debounce window when the turn ends, flush it BEFORE the terminal
|
|
248
|
+
// emoji emits. Pre-fix, `clearDebounceTimer()` here silently
|
|
249
|
+
// dropped the pending state — every Class B turn that completed in
|
|
250
|
+
// under `debounceMs` (default 700ms) collapsed to 👀 → 👍 with no
|
|
251
|
+
// intermediate signal that the agent did any work.
|
|
252
|
+
//
|
|
253
|
+
// Gate on `debounceTimer != null`: a `pendingEmoji` with no timer
|
|
254
|
+
// is already enqueued (immediate emit waiting on chainPromise) and
|
|
255
|
+
// re-enqueuing would produce a duplicate. Only debounced-but-not-
|
|
256
|
+
// yet-enqueued emojis need to be flushed here.
|
|
257
|
+
const flushPending = this.debounceTimer != null && this.pendingEmoji != null
|
|
258
|
+
? this.pendingEmoji
|
|
259
|
+
: null
|
|
260
|
+
this.clearDebounceTimer()
|
|
261
|
+
if (flushPending != null && flushPending !== this.currentEmoji) {
|
|
262
|
+
this.enqueue(flushPending)
|
|
263
|
+
}
|
|
264
|
+
const emoji = this.resolveEmoji(state)
|
|
265
|
+
if (emoji != null && emoji !== this.currentEmoji && emoji !== flushPending) {
|
|
266
|
+
this.enqueue(emoji)
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
private enqueue(emoji: string): void {
|
|
271
|
+
this.chainPromise = this.chainPromise.then(async () => {
|
|
272
|
+
try {
|
|
273
|
+
await this.emit(emoji)
|
|
274
|
+
this.currentEmoji = emoji
|
|
275
|
+
if (this.pendingEmoji === emoji) this.pendingEmoji = null
|
|
276
|
+
this.log?.(`reaction → ${emoji}`)
|
|
277
|
+
} catch (err) {
|
|
278
|
+
this.log?.(`reaction emit failed (${emoji}): ${(err as Error).message}`)
|
|
279
|
+
}
|
|
280
|
+
})
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
private resolveEmoji(state: ReactionState): string | null {
|
|
284
|
+
const variants = REACTION_VARIANTS[state]
|
|
285
|
+
for (const v of variants) {
|
|
286
|
+
if (!TELEGRAM_REACTION_WHITELIST.has(v)) continue
|
|
287
|
+
if (this.allowedReactions == null || this.allowedReactions.has(v)) {
|
|
288
|
+
return v
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// Last resort: any whitelisted-and-allowed emoji from the broad fallback set
|
|
292
|
+
for (const v of ['👍', '👀', '✍']) {
|
|
293
|
+
if (this.allowedReactions == null || this.allowedReactions.has(v)) {
|
|
294
|
+
return v
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return null
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
private resetStallTimers(): void {
|
|
301
|
+
this.clearStallTimers()
|
|
302
|
+
if (this.finished) return
|
|
303
|
+
this.stallSoftTimer = setTimeout(() => {
|
|
304
|
+
this.stallSoftTimer = null
|
|
305
|
+
// Don't reset the stall timers when the stall transition itself fires —
|
|
306
|
+
// otherwise stallHard would never get a chance to run after stallSoft.
|
|
307
|
+
this.scheduleState('stallSoft', { immediate: true, skipStallReset: true })
|
|
308
|
+
}, this.stallSoftMs)
|
|
309
|
+
this.stallHardTimer = setTimeout(() => {
|
|
310
|
+
this.stallHardTimer = null
|
|
311
|
+
this.scheduleState('stallHard', { immediate: true, skipStallReset: true })
|
|
312
|
+
}, this.stallHardMs)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
private clearStallTimers(): void {
|
|
316
|
+
if (this.stallSoftTimer) {
|
|
317
|
+
clearTimeout(this.stallSoftTimer)
|
|
318
|
+
this.stallSoftTimer = null
|
|
319
|
+
}
|
|
320
|
+
if (this.stallHardTimer) {
|
|
321
|
+
clearTimeout(this.stallHardTimer)
|
|
322
|
+
this.stallHardTimer = null
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
private clearDebounceTimer(): void {
|
|
327
|
+
if (this.debounceTimer) {
|
|
328
|
+
clearTimeout(this.debounceTimer)
|
|
329
|
+
this.debounceTimer = null
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers for mid-turn steering and the `/queue` opt-in.
|
|
3
|
+
*
|
|
4
|
+
* Context: Telegram messages that arrive while a prior turn is still in
|
|
5
|
+
* flight are now queued by default (queued="true"). The user can explicitly
|
|
6
|
+
* prefix with `/steer ` or `/s ` to declare "this is a course-correction,
|
|
7
|
+
* not a new task" (steering="true"). The legacy `/queue ` / `/q ` prefix
|
|
8
|
+
* still works as an alias for the new default (queued) behavior.
|
|
9
|
+
* These helpers are pure so server.ts stays testable without standing up
|
|
10
|
+
* grammy.
|
|
11
|
+
*/
|
|
12
|
+
import { escapeHtml } from './format.js'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Detect and strip the `/queue ` or `/q ` prefix.
|
|
16
|
+
*
|
|
17
|
+
* These are now aliases for the default queued behavior (mid-turn messages
|
|
18
|
+
* default to queued="true"), but the prefix is still accepted so existing
|
|
19
|
+
* muscle-memory and scripts keep working.
|
|
20
|
+
*
|
|
21
|
+
* Rules (intentionally strict so we don't match `/queued` or `/q\nfoo`):
|
|
22
|
+
* - Must start with `/queue ` or `/q ` (exactly one leading slash,
|
|
23
|
+
* keyword case-insensitive, MANDATORY single space after keyword).
|
|
24
|
+
* - No leading whitespace — first character must be `/`.
|
|
25
|
+
* - Keyword must be `queue` or `q` exactly; `/queued`, `/queuefoo`,
|
|
26
|
+
* `/queue\tfoo` all fail to match.
|
|
27
|
+
* - On match, only the first prefix is stripped. `/queue /q foo`
|
|
28
|
+
* returns `{queued: true, body: "/q foo"}` — we do not recurse.
|
|
29
|
+
* - On match, the returned body is whitespace-trimmed.
|
|
30
|
+
* - `/queue` alone (no trailing space) does NOT match (we require the
|
|
31
|
+
* space so the prefix can't collide with a message that literally
|
|
32
|
+
* starts with the word "queue"). Document in tests.
|
|
33
|
+
*/
|
|
34
|
+
export function parseQueuePrefix(body: string): { queued: boolean; body: string } {
|
|
35
|
+
const m = /^\/(queue|q) (.*)$/is.exec(body)
|
|
36
|
+
if (!m) return { queued: false, body }
|
|
37
|
+
return { queued: true, body: m[2]!.trim() }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Detect and strip the `/steer ` or `/s ` explicit steer prefix.
|
|
42
|
+
*
|
|
43
|
+
* Mid-turn messages now default to queued="true". To explicitly mark a
|
|
44
|
+
* message as a course-correction for the in-flight turn, the user can
|
|
45
|
+
* prefix with `/steer ` or `/s `.
|
|
46
|
+
*
|
|
47
|
+
* Rules mirror parseQueuePrefix exactly:
|
|
48
|
+
* - Must start with `/steer ` or `/s ` (keyword case-insensitive,
|
|
49
|
+
* MANDATORY single space after keyword).
|
|
50
|
+
* - No leading whitespace — first character must be `/`.
|
|
51
|
+
* - Keyword must be `steer` or `s` exactly; `/steered`, `/steerfoo`,
|
|
52
|
+
* `/steer\tfoo` all fail to match.
|
|
53
|
+
* - On match, only the first prefix is stripped; body is trimmed.
|
|
54
|
+
* - `/steer` alone (no trailing space) does NOT match.
|
|
55
|
+
*/
|
|
56
|
+
export function parseSteerPrefix(body: string): { steering: boolean; body: string } {
|
|
57
|
+
const m = /^\/(steer|s) (.*)$/is.exec(body)
|
|
58
|
+
if (!m) return { steering: false, body }
|
|
59
|
+
return { steering: true, body: m[2]!.trim() }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Escape the five XML attribute entities. Idempotent on already-safe
|
|
64
|
+
* strings because the order is &-first (any `&` we produce won't be
|
|
65
|
+
* re-processed — the first pass only rewrites bare `&`).
|
|
66
|
+
*/
|
|
67
|
+
export function escapeXmlAttribute(s: string): string {
|
|
68
|
+
return s
|
|
69
|
+
.replace(/&/g, '&')
|
|
70
|
+
.replace(/</g, '<')
|
|
71
|
+
.replace(/>/g, '>')
|
|
72
|
+
.replace(/"/g, '"')
|
|
73
|
+
.replace(/'/g, ''')
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Produce a short, safe preview of the last assistant turn for injection
|
|
78
|
+
* as an XML attribute. Strips HTML tags (so `<b>foo</b>` becomes `foo`),
|
|
79
|
+
* collapses all whitespace runs into single spaces, truncates to
|
|
80
|
+
* `maxChars` visible characters, then XML-escapes.
|
|
81
|
+
*
|
|
82
|
+
* We do NOT decode HTML entities — a literal `&` in the source
|
|
83
|
+
* survives as `&amp;` after escape, which is fine: the attribute is
|
|
84
|
+
* for the model's situational awareness, not faithful rendering.
|
|
85
|
+
*/
|
|
86
|
+
export function formatPriorAssistantPreview(text: string, maxChars = 200): string {
|
|
87
|
+
// Strip HTML tags. Anything angle-bracketed between < and > goes away;
|
|
88
|
+
// this is deliberately liberal (no tag-name whitelist) because the
|
|
89
|
+
// preview is for the model's eyes only.
|
|
90
|
+
const stripped = text.replace(/<[^>]*>/g, '')
|
|
91
|
+
const collapsed = stripped.replace(/\s+/g, ' ').trim()
|
|
92
|
+
const truncated = collapsed.length > maxChars ? collapsed.slice(0, maxChars) : collapsed
|
|
93
|
+
return escapeXmlAttribute(truncated)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Format the `reply_to_text` channel-meta attribute (issue #119) — used by
|
|
98
|
+
* both `server.ts` and `gateway/gateway.ts` so the two paths can't drift.
|
|
99
|
+
*
|
|
100
|
+
* Difference from `formatPriorAssistantPreview`: we do NOT strip HTML or
|
|
101
|
+
* collapse whitespace. The original Telegram message text is plain text
|
|
102
|
+
* already, and preserving its shape (line breaks excluded by truncation,
|
|
103
|
+
* special chars escaped at the boundary) helps the agent see what the
|
|
104
|
+
* user was looking at when they hit "Reply".
|
|
105
|
+
*
|
|
106
|
+
* Returns undefined when `text` is null/undefined so the call site can
|
|
107
|
+
* conditionally include the attribute via spread without an extra guard.
|
|
108
|
+
*/
|
|
109
|
+
export function formatReplyToText(text: string | null | undefined, maxChars: number): string | undefined {
|
|
110
|
+
if (text == null) return undefined
|
|
111
|
+
const truncated = text.length > maxChars
|
|
112
|
+
? text.slice(0, maxChars - 1) + '…'
|
|
113
|
+
: text
|
|
114
|
+
return escapeXmlAttribute(truncated)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface ChannelMetaAttributeOptions {
|
|
118
|
+
queued?: boolean
|
|
119
|
+
steering?: boolean
|
|
120
|
+
priorTurnInProgress?: boolean
|
|
121
|
+
secondsSinceTurnStart?: number
|
|
122
|
+
/** Already-escaped preview (as returned by formatPriorAssistantPreview). */
|
|
123
|
+
priorAssistantPreview?: string
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Build the extra attributes for the `<channel>` open tag. Returns a
|
|
128
|
+
* space-prefixed string (or empty string if no attributes apply) so the
|
|
129
|
+
* caller can concatenate it directly after the existing attributes.
|
|
130
|
+
*
|
|
131
|
+
* Order is fixed (documented here, tested in steering.test.ts):
|
|
132
|
+
* queued, steering, prior_turn_in_progress,
|
|
133
|
+
* seconds_since_turn_start, prior_assistant_preview
|
|
134
|
+
*
|
|
135
|
+
* Attributes with missing / undefined values are omitted entirely rather
|
|
136
|
+
* than emitted as empty strings. `queued` and `steering` are treated as
|
|
137
|
+
* mutually exclusive by the caller in server.ts — this helper does not
|
|
138
|
+
* enforce that invariant; if both are true, both are emitted.
|
|
139
|
+
*/
|
|
140
|
+
export function buildChannelMetaAttributes(opts: ChannelMetaAttributeOptions): string {
|
|
141
|
+
const parts: string[] = []
|
|
142
|
+
if (opts.queued) parts.push('queued="true"')
|
|
143
|
+
if (opts.steering) parts.push('steering="true"')
|
|
144
|
+
if (opts.priorTurnInProgress) parts.push('prior_turn_in_progress="true"')
|
|
145
|
+
if (opts.priorTurnInProgress && typeof opts.secondsSinceTurnStart === 'number') {
|
|
146
|
+
parts.push(`seconds_since_turn_start="${Math.max(0, Math.floor(opts.secondsSinceTurnStart))}"`)
|
|
147
|
+
}
|
|
148
|
+
if (opts.priorTurnInProgress && opts.priorAssistantPreview != null && opts.priorAssistantPreview.length > 0) {
|
|
149
|
+
parts.push(`prior_assistant_preview="${opts.priorAssistantPreview}"`)
|
|
150
|
+
}
|
|
151
|
+
return parts.length === 0 ? '' : ' ' + parts.join(' ')
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Re-export so callers that want HTML-escape for body content don't need a second import. */
|
|
155
|
+
export { escapeHtml }
|