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,525 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { Terminal } from '@xterm/headless'
|
|
3
|
+
import {
|
|
4
|
+
V1Extractor,
|
|
5
|
+
V1ToolActivityExtractor,
|
|
6
|
+
shouldSuppressToolActivity,
|
|
7
|
+
startPtyTail,
|
|
8
|
+
} from '../pty-tail.js'
|
|
9
|
+
import { mkdtempSync, writeFileSync, appendFileSync, rmSync } from 'fs'
|
|
10
|
+
import { tmpdir } from 'os'
|
|
11
|
+
import { join } from 'path'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Helper: feed a string into a fresh xterm Terminal and return it after
|
|
15
|
+
* the parser has processed all bytes. Real Claude Code TUI output uses
|
|
16
|
+
* ANSI escapes; we synthesize them here.
|
|
17
|
+
*/
|
|
18
|
+
async function feedToTerm(input: string, opts: { cols?: number; rows?: number } = {}): Promise<Terminal> {
|
|
19
|
+
const term = new Terminal({
|
|
20
|
+
cols: opts.cols ?? 132,
|
|
21
|
+
rows: opts.rows ?? 40,
|
|
22
|
+
scrollback: 5000,
|
|
23
|
+
allowProposedApi: true,
|
|
24
|
+
})
|
|
25
|
+
await new Promise<void>(resolve => {
|
|
26
|
+
term.write(input, () => resolve())
|
|
27
|
+
})
|
|
28
|
+
return term
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
describe('V1Extractor', () => {
|
|
32
|
+
const extractor = new V1Extractor()
|
|
33
|
+
|
|
34
|
+
it('returns null for an empty terminal', async () => {
|
|
35
|
+
const term = await feedToTerm('')
|
|
36
|
+
expect(extractor.extract(term)).toBeNull()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('returns null when no switchroom-telegram tool block is present', async () => {
|
|
40
|
+
const term = await feedToTerm('● Bash(ls -la)\r\n ⎿ total 4\r\n drwx 2 user user\r\n')
|
|
41
|
+
expect(extractor.extract(term)).toBeNull()
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('extracts a complete reply text on a single line', async () => {
|
|
45
|
+
const tui = '● switchroom-telegram - reply (MCP)(chat_id: "123", text: "Hello world")\r\n'
|
|
46
|
+
const term = await feedToTerm(tui)
|
|
47
|
+
expect(extractor.extract(term)).toBe('Hello world')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('extracts a multi-line reply with continuation indentation', async () => {
|
|
51
|
+
// Synthesized to match the real shape from the live server's service.log
|
|
52
|
+
const tui = [
|
|
53
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "-1009999999999", text: "Yes — I can',
|
|
54
|
+
' attach files to replies. Images send as inline',
|
|
55
|
+
' photos, and other file types go as documents (up',
|
|
56
|
+
' to 50MB each). Just point me at a file path or ask',
|
|
57
|
+
' me to generate/fetch something and I\'ll send it',
|
|
58
|
+
' along.")',
|
|
59
|
+
'',
|
|
60
|
+
].join('\r\n')
|
|
61
|
+
const term = await feedToTerm(tui)
|
|
62
|
+
const result = extractor.extract(term)
|
|
63
|
+
expect(result).not.toBeNull()
|
|
64
|
+
expect(result).toContain('Yes — I can attach files to replies')
|
|
65
|
+
expect(result).toContain('Images send as inline photos')
|
|
66
|
+
expect(result).toContain("along.")
|
|
67
|
+
// Should NOT contain the closing '")'
|
|
68
|
+
expect(result).not.toContain('")')
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('extracts an in-progress reply (no closing paren yet)', async () => {
|
|
72
|
+
// Mid-stream: the text is still being generated, no `")` closer
|
|
73
|
+
const tui = [
|
|
74
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "123", text: "Working on this',
|
|
75
|
+
' for you, just need a second',
|
|
76
|
+
].join('\r\n')
|
|
77
|
+
const term = await feedToTerm(tui)
|
|
78
|
+
const result = extractor.extract(term)
|
|
79
|
+
expect(result).not.toBeNull()
|
|
80
|
+
expect(result).toContain('Working on this')
|
|
81
|
+
expect(result).toContain('for you')
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('takes the most recent reply when there are several in the buffer', async () => {
|
|
85
|
+
const tui = [
|
|
86
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "123", text: "First reply")',
|
|
87
|
+
'',
|
|
88
|
+
'● Bash(echo hi)',
|
|
89
|
+
' ⎿ hi',
|
|
90
|
+
'',
|
|
91
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "123", text: "Second reply, the latest one")',
|
|
92
|
+
'',
|
|
93
|
+
].join('\r\n')
|
|
94
|
+
const term = await feedToTerm(tui)
|
|
95
|
+
expect(extractor.extract(term)).toBe('Second reply, the latest one')
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('also matches stream_reply tool calls', async () => {
|
|
99
|
+
const tui = '● switchroom-telegram - stream_reply (MCP)(chat_id: "123", text: "Streaming partial")\r\n'
|
|
100
|
+
const term = await feedToTerm(tui)
|
|
101
|
+
expect(extractor.extract(term)).toBe('Streaming partial')
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('stops accumulating at a new tool block (next bullet)', async () => {
|
|
105
|
+
const tui = [
|
|
106
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "123", text: "Reply text',
|
|
107
|
+
' continuation here',
|
|
108
|
+
'● Bash(ls)',
|
|
109
|
+
' ⎿ output',
|
|
110
|
+
].join('\r\n')
|
|
111
|
+
const term = await feedToTerm(tui)
|
|
112
|
+
const result = extractor.extract(term)
|
|
113
|
+
expect(result).toContain('Reply text')
|
|
114
|
+
expect(result).toContain('continuation here')
|
|
115
|
+
expect(result).not.toContain('Bash')
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('stops accumulating at a tool result marker (⎿)', async () => {
|
|
119
|
+
const tui = [
|
|
120
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "123", text: "Done")',
|
|
121
|
+
' ⎿ sent (id: 100)',
|
|
122
|
+
'',
|
|
123
|
+
].join('\r\n')
|
|
124
|
+
const term = await feedToTerm(tui)
|
|
125
|
+
expect(extractor.extract(term)).toBe('Done')
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('handles ANSI escape sequences in the input correctly', async () => {
|
|
129
|
+
// Real Claude Code output is wrapped in cursor positioning + colors.
|
|
130
|
+
// The xterm parser should strip them; we just see the rendered text.
|
|
131
|
+
const tui =
|
|
132
|
+
'\x1b[2C\x1b[1;36m●\x1b[0m\x1b[1C\x1b[1mswitchroom-telegram - reply (MCP)\x1b[0m(chat_id: "123", text: "Bold reply")\r\n'
|
|
133
|
+
const term = await feedToTerm(tui)
|
|
134
|
+
expect(extractor.extract(term)).toBe('Bold reply')
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
it('reports progressive growth as more bytes arrive', async () => {
|
|
138
|
+
const term = new Terminal({ cols: 132, rows: 40, scrollback: 5000, allowProposedApi: true })
|
|
139
|
+
// Feed in chunks
|
|
140
|
+
await new Promise<void>(r => term.write('● switchroom-telegram - reply (MCP)(chat_id: "1", text: "Hel', () => r()))
|
|
141
|
+
expect(extractor.extract(term)).toBe('Hel')
|
|
142
|
+
|
|
143
|
+
await new Promise<void>(r => term.write('lo wo', () => r()))
|
|
144
|
+
expect(extractor.extract(term)).toBe('Hello wo')
|
|
145
|
+
|
|
146
|
+
await new Promise<void>(r => term.write('rld")', () => r()))
|
|
147
|
+
expect(extractor.extract(term)).toBe('Hello world')
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
it('returns null when buffer contains only banner / startup noise', async () => {
|
|
151
|
+
const tui = [
|
|
152
|
+
'────────────────────────────────────────',
|
|
153
|
+
'▐▛███▜▌ Claude Code v2.1.101',
|
|
154
|
+
'▝▜█████▛▘ Opus 4.6 (1M context) · Claude Max',
|
|
155
|
+
' Listening for channel messages from: server:switchroom-telegram',
|
|
156
|
+
' Experimental · inbound messages will be pushed into this session',
|
|
157
|
+
'────────────────────────────────────────',
|
|
158
|
+
'❯',
|
|
159
|
+
'────────────────────────────────────────',
|
|
160
|
+
'⏵⏵ accept edits on (shift+tab to cycle)',
|
|
161
|
+
].join('\r\n')
|
|
162
|
+
const term = await feedToTerm(tui)
|
|
163
|
+
expect(extractor.extract(term)).toBeNull()
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
it('has a stable version identifier for logging', () => {
|
|
167
|
+
expect(extractor.version).toMatch(/^v1/)
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
// ─── Regression: text is NOT the last parameter ─────────────────────────
|
|
171
|
+
//
|
|
172
|
+
// The user-visible "duplicate Telegram message with leaked JSON" bug
|
|
173
|
+
// came from V1Extractor assuming `text` was always the final param in
|
|
174
|
+
// the tool call and terminating on the `")` close-paren sequence. When
|
|
175
|
+
// the model passed `text` before `reply_to` / `format` / etc., the
|
|
176
|
+
// extractor grabbed everything from `text: "` to the end-of-call `")`,
|
|
177
|
+
// including `", reply_to: "86"` in the middle — which then got edited
|
|
178
|
+
// into a draft-stream preview and surfaced as a second Telegram message
|
|
179
|
+
// whose body contained literal JSON.
|
|
180
|
+
|
|
181
|
+
it('extracts text correctly when it is NOT the last parameter', async () => {
|
|
182
|
+
const tui = '● switchroom-telegram - reply (MCP)(chat_id: "123", text: "Hello", reply_to: "86")\r\n'
|
|
183
|
+
const term = await feedToTerm(tui)
|
|
184
|
+
expect(extractor.extract(term)).toBe('Hello')
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
it('extracts text when followed by multiple trailing params', async () => {
|
|
188
|
+
const tui =
|
|
189
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "123", text: "Done now", reply_to: "86", format: "text")\r\n'
|
|
190
|
+
const term = await feedToTerm(tui)
|
|
191
|
+
expect(extractor.extract(term)).toBe('Done now')
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
it('handles escaped double quotes inside text without early termination', async () => {
|
|
195
|
+
const tui =
|
|
196
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "123", text: "Understood — I\\"ll stop the duplicate \\"progress stream + final reply\\" pattern", reply_to: "86")\r\n'
|
|
197
|
+
// Widen the terminal so the long single line doesn't get hard-wrapped
|
|
198
|
+
// by xterm at the default 132 cols — which would truncate the trailing
|
|
199
|
+
// characters and look like a regression even though the parser is
|
|
200
|
+
// fine.
|
|
201
|
+
const term = await feedToTerm(tui, { cols: 400 })
|
|
202
|
+
const result = extractor.extract(term)
|
|
203
|
+
// Inner escaped quotes should appear as real quotes in the extracted
|
|
204
|
+
// text. The terminator is the unescaped `"` after `pattern`.
|
|
205
|
+
expect(result).toBe(
|
|
206
|
+
'Understood — I"ll stop the duplicate "progress stream + final reply" pattern',
|
|
207
|
+
)
|
|
208
|
+
// And crucially: no `reply_to` leakage.
|
|
209
|
+
expect(result).not.toContain('reply_to')
|
|
210
|
+
expect(result).not.toContain('"86"')
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
it('handles escaped backslashes correctly', async () => {
|
|
214
|
+
const tui =
|
|
215
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "123", text: "Windows path: C:\\\\temp\\\\file.txt", reply_to: "1")\r\n'
|
|
216
|
+
const term = await feedToTerm(tui)
|
|
217
|
+
const result = extractor.extract(term)
|
|
218
|
+
expect(result).toBe('Windows path: C:\\temp\\file.txt')
|
|
219
|
+
expect(result).not.toContain('reply_to')
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it('handles escaped newline sequences inside text', async () => {
|
|
223
|
+
const tui =
|
|
224
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "123", text: "Line one\\nLine two", reply_to: "1")\r\n'
|
|
225
|
+
const term = await feedToTerm(tui)
|
|
226
|
+
const result = extractor.extract(term)
|
|
227
|
+
// The continuation-line collapse turns the unescaped \n into a space.
|
|
228
|
+
expect(result).toMatch(/^Line one\s+Line two$/)
|
|
229
|
+
expect(result).not.toContain('reply_to')
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
it('does not include subsequent param names when text is mid-call', async () => {
|
|
233
|
+
// This is the exact scenario that produced the bug screenshot.
|
|
234
|
+
const tui =
|
|
235
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "100000001", text: "Short answer coming once I\\"ve looked.", reply_to: "86")\r\n'
|
|
236
|
+
const term = await feedToTerm(tui)
|
|
237
|
+
const result = extractor.extract(term)
|
|
238
|
+
expect(result).toBe('Short answer coming once I"ve looked.')
|
|
239
|
+
expect(result).not.toMatch(/reply_to/)
|
|
240
|
+
expect(result).not.toMatch(/"86"/)
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
it('still handles the open-ended mid-stream case with text NOT last', async () => {
|
|
244
|
+
// Partial render: text parameter has started but the closing quote
|
|
245
|
+
// hasn't arrived yet. The extractor should return what it has so far.
|
|
246
|
+
const tui =
|
|
247
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "123", text: "Halfway through a thou'
|
|
248
|
+
const term = await feedToTerm(tui)
|
|
249
|
+
const result = extractor.extract(term)
|
|
250
|
+
expect(result).toBe('Halfway through a thou')
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
it('stops at first unescaped closing quote even if more text follows', async () => {
|
|
254
|
+
// Only the FIRST unescaped `"` terminates the string. Anything after
|
|
255
|
+
// is a different param (or the tool-call close paren).
|
|
256
|
+
const tui = '● switchroom-telegram - reply (MCP)(chat_id: "1", text: "First", text: "Second")\r\n'
|
|
257
|
+
const term = await feedToTerm(tui)
|
|
258
|
+
// Extractor should latch onto the FIRST `text: "` and return its value
|
|
259
|
+
// cleanly, NOT merge the two values.
|
|
260
|
+
expect(extractor.extract(term)).toBe('First')
|
|
261
|
+
})
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
describe('V1Extractor against real captured production output', () => {
|
|
265
|
+
const extractor = new V1Extractor()
|
|
266
|
+
it('extracts the rendered reply text from a real script -qfc service.log fragment', async () => {
|
|
267
|
+
// This is the literal pattern observed in the live server's service.log:
|
|
268
|
+
// "Yes — I can / attach files to replies. Images send as inline / photos..."
|
|
269
|
+
// verified manually via xterm.js dump in earlier debugging.
|
|
270
|
+
const tui = [
|
|
271
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "-1009999999999", text: "Yes — I can',
|
|
272
|
+
' attach files to replies. Images send as inline',
|
|
273
|
+
' photos, and other file types go as documents (up',
|
|
274
|
+
' to 50MB each). Just point me at a file path or ask',
|
|
275
|
+
' me to generate/fetch something and I\'ll send it',
|
|
276
|
+
' along.")',
|
|
277
|
+
'',
|
|
278
|
+
'● Sent. Confirmed to the user that I can attach images (inline) and other file',
|
|
279
|
+
' types (as documents), up to 50MB each.',
|
|
280
|
+
].join('\r\n')
|
|
281
|
+
const term = await feedToTerm(tui)
|
|
282
|
+
const result = extractor.extract(term)
|
|
283
|
+
expect(result).not.toBeNull()
|
|
284
|
+
// The extractor's continuation logic collapses newlines + indentation
|
|
285
|
+
// into spaces, so the final text reads as one flowing sentence.
|
|
286
|
+
expect(result).toMatch(/^Yes — I can attach files to replies/)
|
|
287
|
+
expect(result).toMatch(/along\.$/)
|
|
288
|
+
})
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
describe('V1ToolActivityExtractor', () => {
|
|
292
|
+
const ax = new V1ToolActivityExtractor()
|
|
293
|
+
|
|
294
|
+
it('returns null for an empty terminal', async () => {
|
|
295
|
+
const term = await feedToTerm('')
|
|
296
|
+
expect(ax.extract(term)).toBeNull()
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
it('extracts a Bash tool call as a short status', async () => {
|
|
300
|
+
const term = await feedToTerm('● Bash(git status)\r\n')
|
|
301
|
+
expect(ax.extract(term)).toBe('Running Bash: git status')
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
it('extracts a Read tool call', async () => {
|
|
305
|
+
const term = await feedToTerm('● Read(/home/user/foo.ts)\r\n')
|
|
306
|
+
expect(ax.extract(term)).toBe('Reading file: /home/user/foo.ts')
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
it('extracts a Grep tool call, keeping only the first arg', async () => {
|
|
310
|
+
const term = await feedToTerm('● Grep(pattern: "foo", path: "/bar")\r\n')
|
|
311
|
+
const out = ax.extract(term)
|
|
312
|
+
expect(out).toMatch(/^Searching with Grep: /)
|
|
313
|
+
// Must NOT include the second `path:` arg
|
|
314
|
+
expect(out).not.toContain('/bar')
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
it('returns null for switchroom-telegram tool calls (owned by V1Extractor)', async () => {
|
|
318
|
+
const term = await feedToTerm(
|
|
319
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "1", text: "hi")\r\n',
|
|
320
|
+
)
|
|
321
|
+
expect(ax.extract(term)).toBeNull()
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
it('takes the most recent tool call when several are in the buffer', async () => {
|
|
325
|
+
const tui = [
|
|
326
|
+
'● Bash(ls)',
|
|
327
|
+
' ⎿ output',
|
|
328
|
+
'● Read(/tmp/a.ts)',
|
|
329
|
+
' ⎿ ...',
|
|
330
|
+
'● Grep(foo)',
|
|
331
|
+
'',
|
|
332
|
+
].join('\r\n')
|
|
333
|
+
const term = await feedToTerm(tui)
|
|
334
|
+
expect(ax.extract(term)).toBe('Searching with Grep: foo')
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
it('truncates overlong inner arg', async () => {
|
|
338
|
+
const longArg = 'x'.repeat(200)
|
|
339
|
+
const term = await feedToTerm(`● Bash(${longArg})\r\n`, { cols: 400 })
|
|
340
|
+
const out = ax.extract(term) ?? ''
|
|
341
|
+
expect(out.length).toBeLessThanOrEqual(120)
|
|
342
|
+
expect(out.startsWith('Running Bash: ')).toBe(true)
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
it('has a stable version identifier', () => {
|
|
346
|
+
expect(ax.version).toMatch(/^v1/)
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
it('handles an unknown tool name with a generic verb', async () => {
|
|
350
|
+
const term = await feedToTerm('● MyCustomTool(xyz)\r\n')
|
|
351
|
+
expect(ax.extract(term)).toBe('Running MyCustomTool: xyz')
|
|
352
|
+
})
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
describe('startPtyTail integration — onActivity wiring + dedup + throttle', () => {
|
|
356
|
+
it('emits activity lines as tool-call bullets appear, deduping repeats', async () => {
|
|
357
|
+
const dir = mkdtempSync(join(tmpdir(), 'pty-activity-'))
|
|
358
|
+
const logFile = join(dir, 'service.log')
|
|
359
|
+
writeFileSync(logFile, '')
|
|
360
|
+
|
|
361
|
+
const activities: string[] = []
|
|
362
|
+
const partials: string[] = []
|
|
363
|
+
const handle = startPtyTail({
|
|
364
|
+
logFile,
|
|
365
|
+
throttleMs: 10,
|
|
366
|
+
onPartial: (t) => { partials.push(t) },
|
|
367
|
+
activityExtractor: new V1ToolActivityExtractor(),
|
|
368
|
+
onActivity: (t) => { activities.push(t) },
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
try {
|
|
372
|
+
// Give the poll loop a chance to attach
|
|
373
|
+
await new Promise(r => setTimeout(r, 250))
|
|
374
|
+
|
|
375
|
+
appendFileSync(logFile, '● Bash(echo hi)\r\n')
|
|
376
|
+
await new Promise(r => setTimeout(r, 400))
|
|
377
|
+
|
|
378
|
+
// Duplicate buffer state → should NOT re-emit
|
|
379
|
+
appendFileSync(logFile, ' ⎿ hi\r\n')
|
|
380
|
+
await new Promise(r => setTimeout(r, 400))
|
|
381
|
+
|
|
382
|
+
appendFileSync(logFile, '● Read(/tmp/foo.ts)\r\n')
|
|
383
|
+
await new Promise(r => setTimeout(r, 400))
|
|
384
|
+
|
|
385
|
+
expect(activities).toContain('Running Bash: echo hi')
|
|
386
|
+
expect(activities).toContain('Reading file: /tmp/foo.ts')
|
|
387
|
+
// Dedup check: 'Running Bash: echo hi' should appear exactly once,
|
|
388
|
+
// not once per byte-batch.
|
|
389
|
+
const bashCount = activities.filter(a => a === 'Running Bash: echo hi').length
|
|
390
|
+
expect(bashCount).toBe(1)
|
|
391
|
+
// Reply text should not have been emitted — no switchroom-telegram marker in the log.
|
|
392
|
+
expect(partials).toHaveLength(0)
|
|
393
|
+
} finally {
|
|
394
|
+
handle.stop()
|
|
395
|
+
rmSync(dir, { recursive: true, force: true })
|
|
396
|
+
}
|
|
397
|
+
}, 10_000)
|
|
398
|
+
|
|
399
|
+
it('preserves onPartial reply extraction when onActivity is also wired', async () => {
|
|
400
|
+
const dir = mkdtempSync(join(tmpdir(), 'pty-mixed-'))
|
|
401
|
+
const logFile = join(dir, 'service.log')
|
|
402
|
+
writeFileSync(logFile, '')
|
|
403
|
+
|
|
404
|
+
const activities: string[] = []
|
|
405
|
+
const partials: string[] = []
|
|
406
|
+
const handle = startPtyTail({
|
|
407
|
+
logFile,
|
|
408
|
+
throttleMs: 10,
|
|
409
|
+
onPartial: (t) => { partials.push(t) },
|
|
410
|
+
activityExtractor: new V1ToolActivityExtractor(),
|
|
411
|
+
onActivity: (t) => { activities.push(t) },
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
await new Promise(r => setTimeout(r, 250))
|
|
416
|
+
appendFileSync(logFile, '● Bash(ls)\r\n')
|
|
417
|
+
await new Promise(r => setTimeout(r, 300))
|
|
418
|
+
appendFileSync(
|
|
419
|
+
logFile,
|
|
420
|
+
'● switchroom-telegram - reply (MCP)(chat_id: "1", text: "hello world")\r\n',
|
|
421
|
+
)
|
|
422
|
+
await new Promise(r => setTimeout(r, 400))
|
|
423
|
+
|
|
424
|
+
expect(activities).toContain('Running Bash: ls')
|
|
425
|
+
expect(partials.some(p => p.includes('hello world'))).toBe(true)
|
|
426
|
+
} finally {
|
|
427
|
+
handle.stop()
|
|
428
|
+
rmSync(dir, { recursive: true, force: true })
|
|
429
|
+
}
|
|
430
|
+
}, 10_000)
|
|
431
|
+
})
|
|
432
|
+
|
|
433
|
+
describe('shouldSuppressToolActivity (bug 2: suppress noisy per-tool narration)', () => {
|
|
434
|
+
it('suppresses Bash/Read/Write/Edit/Grep/Glob per-call narration', () => {
|
|
435
|
+
// These are the core tools the user complained about — rapid-fire
|
|
436
|
+
// narration like "Running Bash: cd .." per call is noise.
|
|
437
|
+
expect(shouldSuppressToolActivity('Running Bash: git status')).toBe(true)
|
|
438
|
+
expect(shouldSuppressToolActivity('Reading file: /tmp/foo.ts')).toBe(true)
|
|
439
|
+
expect(shouldSuppressToolActivity('Writing file: /tmp/out.md')).toBe(true)
|
|
440
|
+
expect(shouldSuppressToolActivity('Editing file: server.ts')).toBe(true)
|
|
441
|
+
expect(shouldSuppressToolActivity('Searching with Grep: foo')).toBe(true)
|
|
442
|
+
expect(shouldSuppressToolActivity('Searching with Glob: **/*.ts')).toBe(true)
|
|
443
|
+
})
|
|
444
|
+
|
|
445
|
+
it('passes through human-meaningful activity (sub-agent, web, custom tools)', () => {
|
|
446
|
+
// These ARE useful to surface — they run long, and the user actually
|
|
447
|
+
// wants to know the agent is doing them.
|
|
448
|
+
expect(shouldSuppressToolActivity('Running sub-agent: @researcher')).toBe(false)
|
|
449
|
+
expect(shouldSuppressToolActivity('Fetching URL: https://example.com')).toBe(false)
|
|
450
|
+
expect(shouldSuppressToolActivity('Searching the web: foo')).toBe(false)
|
|
451
|
+
// Unknown / custom tool goes through the generic "Running <Tool>"
|
|
452
|
+
// path and must NOT be suppressed — only the named noisy set is.
|
|
453
|
+
expect(shouldSuppressToolActivity('Running MyCustomTool: xyz')).toBe(false)
|
|
454
|
+
})
|
|
455
|
+
|
|
456
|
+
it('bug 2: sequence of Bash/Grep/Read activity lines is entirely suppressed from outbound stream', async () => {
|
|
457
|
+
// End-to-end shape: simulate the V1ToolActivityExtractor emitting the
|
|
458
|
+
// noisy per-tool lines (as it still will — the filter is at the
|
|
459
|
+
// consumer layer). The filter should drop all of them before they
|
|
460
|
+
// reach the stream. The test uses the extractor directly to produce
|
|
461
|
+
// realistic strings, then runs them through the suppression check
|
|
462
|
+
// to assert nothing leaks to outbound.
|
|
463
|
+
const ax = new V1ToolActivityExtractor()
|
|
464
|
+
const outbound: string[] = []
|
|
465
|
+
const emitToStream = (line: string) => {
|
|
466
|
+
if (shouldSuppressToolActivity(line)) return
|
|
467
|
+
outbound.push(line)
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
for (const tui of [
|
|
471
|
+
'● Bash(cd /tmp && ls)\r\n',
|
|
472
|
+
'● Grep(pattern: "foo")\r\n',
|
|
473
|
+
'● Read(/home/user/bar.ts)\r\n',
|
|
474
|
+
'● Bash(git status)\r\n',
|
|
475
|
+
]) {
|
|
476
|
+
const term = await feedToTerm(tui)
|
|
477
|
+
const line = ax.extract(term)
|
|
478
|
+
expect(line).not.toBeNull()
|
|
479
|
+
emitToStream(line!)
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// All four were noisy-core-tool narration → outbound must be empty.
|
|
483
|
+
expect(outbound).toEqual([])
|
|
484
|
+
})
|
|
485
|
+
|
|
486
|
+
it('regression: suppresses spinner-verb prefixes (Reading/Writing/Editing/Searching)', () => {
|
|
487
|
+
// Real production leak: Claude Code's in-progress spinner uses bare
|
|
488
|
+
// verbs ("Reading…", "Writing…") which the bullet-line regex captures
|
|
489
|
+
// as the tool token. activityVerb falls through to default
|
|
490
|
+
// `Running ${tool}`, producing "Running Reading: ctrl+o to expand"
|
|
491
|
+
// and friends. Prior suppression list (formatted "Reading file"
|
|
492
|
+
// prefix only) missed these. Pin the fix.
|
|
493
|
+
expect(shouldSuppressToolActivity('Running Reading: ctrl+o to expand')).toBe(true)
|
|
494
|
+
expect(shouldSuppressToolActivity('Running Writing: ctrl+o to expand')).toBe(true)
|
|
495
|
+
expect(shouldSuppressToolActivity('Running Editing: foo.ts')).toBe(true)
|
|
496
|
+
expect(shouldSuppressToolActivity('Running Searching: pattern')).toBe(true)
|
|
497
|
+
// Also the short tool-token aliases ("Read"/"Write"/"Edit") that the
|
|
498
|
+
// generic default verb produces when the bullet line shows "● Read".
|
|
499
|
+
expect(shouldSuppressToolActivity('Running Read: foo.ts')).toBe(true)
|
|
500
|
+
expect(shouldSuppressToolActivity('Running Write: bar.md')).toBe(true)
|
|
501
|
+
expect(shouldSuppressToolActivity('Running Edit: baz.ts')).toBe(true)
|
|
502
|
+
expect(shouldSuppressToolActivity('Running Grep: pat')).toBe(true)
|
|
503
|
+
expect(shouldSuppressToolActivity('Running Glob: **/*.ts')).toBe(true)
|
|
504
|
+
})
|
|
505
|
+
|
|
506
|
+
it('suppresses any line carrying a Claude Code TUI keyboard hint', () => {
|
|
507
|
+
// The Telegram user cannot press ctrl+o, esc, shift+tab — surfacing
|
|
508
|
+
// these hints in the activity lane is confusing UX (they tap and
|
|
509
|
+
// nothing happens). Drop the line regardless of which tool prefix
|
|
510
|
+
// dressed it up.
|
|
511
|
+
expect(shouldSuppressToolActivity('Running sub-agent: ctrl+o to expand')).toBe(true)
|
|
512
|
+
expect(shouldSuppressToolActivity('Fetching URL: esc to interrupt')).toBe(true)
|
|
513
|
+
expect(shouldSuppressToolActivity('Running MyCustomTool: shift+tab to cycle')).toBe(true)
|
|
514
|
+
expect(shouldSuppressToolActivity('Doing thing (Ctrl+O to expand)')).toBe(true) // case-insensitive
|
|
515
|
+
expect(shouldSuppressToolActivity('Doing thing alt+enter to send')).toBe(true)
|
|
516
|
+
})
|
|
517
|
+
|
|
518
|
+
it('still passes clean human-meaningful activity through', () => {
|
|
519
|
+
// Make sure the broadened filter didn't over-trigger on normal lines.
|
|
520
|
+
expect(shouldSuppressToolActivity('Running sub-agent: @researcher')).toBe(false)
|
|
521
|
+
expect(shouldSuppressToolActivity('Fetching URL: https://example.com')).toBe(false)
|
|
522
|
+
expect(shouldSuppressToolActivity('Searching the web: claude api')).toBe(false)
|
|
523
|
+
expect(shouldSuppressToolActivity('Running MyCustomTool: payload')).toBe(false)
|
|
524
|
+
})
|
|
525
|
+
})
|