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,417 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn-tracking schema for the per-agent registry.
|
|
3
|
+
*
|
|
4
|
+
* Phase 0 of #250 (the SQLite event registry). This module ships only what
|
|
5
|
+
* subsequent stages of the simplify-restart plan need to detect "this turn
|
|
6
|
+
* was orphaned by a restart" — a minimal, strictly-subset design so later
|
|
7
|
+
* registry work can extend without breaking changes.
|
|
8
|
+
*
|
|
9
|
+
* The DB file lives at `<agentDir>/telegram/registry.db`. Storage is
|
|
10
|
+
* `bun:sqlite` (Bun's bundled SQLite, no extra dep), same as history.ts.
|
|
11
|
+
*
|
|
12
|
+
* Schema (one table):
|
|
13
|
+
*
|
|
14
|
+
* turns
|
|
15
|
+
* turn_key TEXT PK -- e.g. "8248703757:11"
|
|
16
|
+
* chat_id TEXT NOT NULL
|
|
17
|
+
* thread_id TEXT -- nullable: forum topics only
|
|
18
|
+
* started_at INTEGER NOT NULL -- unix ms
|
|
19
|
+
* ended_at INTEGER -- nullable until turn ends
|
|
20
|
+
* ended_via TEXT -- 'stop' | 'sigterm' | 'restart' | 'timeout' | 'unknown'
|
|
21
|
+
* last_assistant_msg_id TEXT -- last outbound message_id in this turn
|
|
22
|
+
* last_assistant_done INTEGER -- 0|1; 1 = stream_reply done=true sent
|
|
23
|
+
* last_user_msg_id TEXT -- inbound message_id that started the turn
|
|
24
|
+
* user_prompt_preview TEXT -- first ~200 chars of user message (Phase 1)
|
|
25
|
+
* assistant_reply_preview TEXT -- first ~200 chars of bot's terminal message (Phase 1)
|
|
26
|
+
* tool_call_count INTEGER -- count of tool_use events in the turn (Phase 1)
|
|
27
|
+
* created_at INTEGER NOT NULL
|
|
28
|
+
* updated_at INTEGER NOT NULL
|
|
29
|
+
*
|
|
30
|
+
* Boot-time usage:
|
|
31
|
+
* On every gateway boot, call `markOrphanedAsRestarted(db)` immediately
|
|
32
|
+
* after opening the DB. Any turn with `ended_at IS NULL` was killed
|
|
33
|
+
* mid-flight (SIGKILL, OOM, power loss) — it never got a chance to write
|
|
34
|
+
* a clean-shutdown marker. Stage 3 of simplify-restart will wire this up
|
|
35
|
+
* from the gateway entry point.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import { chmodSync, mkdirSync } from 'fs'
|
|
39
|
+
import { join } from 'path'
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// bun:sqlite lazy-loader (same pattern as history.ts)
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* `bun:sqlite` is a Bun built-in — Vite/Node loaders can't resolve it
|
|
47
|
+
* statically, which would crash any vitest test that transitively imports
|
|
48
|
+
* this module. Hide the require behind `import.meta.require` so static
|
|
49
|
+
* analysis passes; runtime resolution is per-Bun and works fine.
|
|
50
|
+
*/
|
|
51
|
+
type SqliteDatabase = {
|
|
52
|
+
exec(sql: string): void
|
|
53
|
+
prepare(sql: string): {
|
|
54
|
+
run(...params: unknown[]): unknown
|
|
55
|
+
all(...params: unknown[]): unknown[]
|
|
56
|
+
get(...params: unknown[]): unknown
|
|
57
|
+
}
|
|
58
|
+
transaction(fn: (...args: unknown[]) => unknown): (...args: unknown[]) => unknown
|
|
59
|
+
close(): void
|
|
60
|
+
}
|
|
61
|
+
type SqliteDatabaseConstructor = new (path: string, opts?: { create?: boolean }) => SqliteDatabase
|
|
62
|
+
|
|
63
|
+
let DatabaseClass: SqliteDatabaseConstructor | null = null
|
|
64
|
+
function loadDatabaseClass(): SqliteDatabaseConstructor {
|
|
65
|
+
if (DatabaseClass != null) return DatabaseClass
|
|
66
|
+
try {
|
|
67
|
+
const metaRequire = (import.meta as { require?: (id: string) => unknown }).require
|
|
68
|
+
if (typeof metaRequire !== 'function') {
|
|
69
|
+
throw new Error('import.meta.require not available — Bun runtime required')
|
|
70
|
+
}
|
|
71
|
+
const mod = metaRequire('bun:sqlite') as { Database?: SqliteDatabaseConstructor }
|
|
72
|
+
if (!mod.Database) throw new Error('bun:sqlite did not export Database')
|
|
73
|
+
DatabaseClass = mod.Database
|
|
74
|
+
return DatabaseClass
|
|
75
|
+
} catch (err) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
`turns-schema.ts requires Bun runtime (bun:sqlite). Caller: ${(err as Error).message}`,
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// Types
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
|
|
86
|
+
export type TurnEndedVia = 'stop' | 'sigterm' | 'restart' | 'timeout' | 'unknown'
|
|
87
|
+
|
|
88
|
+
export interface Turn {
|
|
89
|
+
turn_key: string
|
|
90
|
+
chat_id: string
|
|
91
|
+
thread_id: string | null
|
|
92
|
+
started_at: number
|
|
93
|
+
ended_at: number | null
|
|
94
|
+
ended_via: TurnEndedVia | null
|
|
95
|
+
last_assistant_msg_id: string | null
|
|
96
|
+
last_assistant_done: boolean | null
|
|
97
|
+
last_user_msg_id: string | null
|
|
98
|
+
user_prompt_preview: string | null
|
|
99
|
+
assistant_reply_preview: string | null
|
|
100
|
+
tool_call_count: number | null
|
|
101
|
+
created_at: number
|
|
102
|
+
updated_at: number
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface RecordTurnStartArgs {
|
|
106
|
+
turnKey: string
|
|
107
|
+
chatId: string
|
|
108
|
+
threadId?: string | null
|
|
109
|
+
lastUserMsgId?: string | null
|
|
110
|
+
userPromptPreview?: string | null
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface RecordTurnEndArgs {
|
|
114
|
+
turnKey: string
|
|
115
|
+
endedVia: TurnEndedVia
|
|
116
|
+
lastAssistantMsgId?: string | null
|
|
117
|
+
lastAssistantDone?: boolean
|
|
118
|
+
assistantReplyPreview?: string | null
|
|
119
|
+
toolCallCount?: number
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
// Schema
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
|
|
126
|
+
const SCHEMA_SQL = `
|
|
127
|
+
CREATE TABLE IF NOT EXISTS turns (
|
|
128
|
+
turn_key TEXT PRIMARY KEY,
|
|
129
|
+
chat_id TEXT NOT NULL,
|
|
130
|
+
thread_id TEXT,
|
|
131
|
+
started_at INTEGER NOT NULL,
|
|
132
|
+
ended_at INTEGER,
|
|
133
|
+
ended_via TEXT,
|
|
134
|
+
last_assistant_msg_id TEXT,
|
|
135
|
+
last_assistant_done INTEGER,
|
|
136
|
+
last_user_msg_id TEXT,
|
|
137
|
+
user_prompt_preview TEXT,
|
|
138
|
+
assistant_reply_preview TEXT,
|
|
139
|
+
tool_call_count INTEGER,
|
|
140
|
+
created_at INTEGER NOT NULL,
|
|
141
|
+
updated_at INTEGER NOT NULL
|
|
142
|
+
);
|
|
143
|
+
CREATE INDEX IF NOT EXISTS idx_turns_chat_ended ON turns(chat_id, ended_at);
|
|
144
|
+
`
|
|
145
|
+
|
|
146
|
+
// Columns added in Phase 1 of #332. Applied via ALTER TABLE so existing
|
|
147
|
+
// registry.db files on disk are migrated non-destructively on first open.
|
|
148
|
+
const PHASE1_MIGRATIONS = [
|
|
149
|
+
`ALTER TABLE turns ADD COLUMN user_prompt_preview TEXT`,
|
|
150
|
+
`ALTER TABLE turns ADD COLUMN assistant_reply_preview TEXT`,
|
|
151
|
+
`ALTER TABLE turns ADD COLUMN tool_call_count INTEGER`,
|
|
152
|
+
]
|
|
153
|
+
|
|
154
|
+
function applySchema(db: SqliteDatabase): void {
|
|
155
|
+
db.exec('PRAGMA journal_mode = WAL')
|
|
156
|
+
db.exec('PRAGMA synchronous = NORMAL')
|
|
157
|
+
db.exec(SCHEMA_SQL)
|
|
158
|
+
// Run migrations for Phase 1 columns. SQLite doesn't support
|
|
159
|
+
// "ADD COLUMN IF NOT EXISTS", so we swallow the "duplicate column" error.
|
|
160
|
+
for (const sql of PHASE1_MIGRATIONS) {
|
|
161
|
+
try {
|
|
162
|
+
db.exec(sql)
|
|
163
|
+
} catch (err) {
|
|
164
|
+
const msg = (err as Error).message ?? ''
|
|
165
|
+
if (!msg.includes('duplicate column')) throw err
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
// openTurnsDb
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Open (or create) the per-agent registry DB at
|
|
176
|
+
* `<agentDir>/telegram/registry.db`.
|
|
177
|
+
*
|
|
178
|
+
* Returns the raw Database instance — callers hold it and pass it to the
|
|
179
|
+
* helpers below. This is intentionally NOT a singleton so tests can use
|
|
180
|
+
* in-memory or temp-file DBs without global state pollution.
|
|
181
|
+
*
|
|
182
|
+
* Callers that need a singleton can wrap this themselves. The gateway will
|
|
183
|
+
* hold one instance for the lifetime of the process (Stage 3).
|
|
184
|
+
*/
|
|
185
|
+
export function openTurnsDb(agentDir: string): SqliteDatabase {
|
|
186
|
+
const Database = loadDatabaseClass()
|
|
187
|
+
const dir = join(agentDir, 'telegram')
|
|
188
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 })
|
|
189
|
+
const path = join(dir, 'registry.db')
|
|
190
|
+
const db = new Database(path, { create: true })
|
|
191
|
+
applySchema(db)
|
|
192
|
+
try {
|
|
193
|
+
chmodSync(path, 0o600)
|
|
194
|
+
} catch {
|
|
195
|
+
/* ignore — chmod not supported on some FUSE mounts */
|
|
196
|
+
}
|
|
197
|
+
return db
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Open an in-memory DB with the turns schema applied.
|
|
202
|
+
* Useful for tests without touching the filesystem.
|
|
203
|
+
*/
|
|
204
|
+
export function openTurnsDbInMemory(): SqliteDatabase {
|
|
205
|
+
const Database = loadDatabaseClass()
|
|
206
|
+
const db = new Database(':memory:')
|
|
207
|
+
applySchema(db)
|
|
208
|
+
return db
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
// Row mapper
|
|
213
|
+
// ---------------------------------------------------------------------------
|
|
214
|
+
|
|
215
|
+
interface RawTurnRow {
|
|
216
|
+
turn_key: string
|
|
217
|
+
chat_id: string
|
|
218
|
+
thread_id: string | null
|
|
219
|
+
started_at: number
|
|
220
|
+
ended_at: number | null
|
|
221
|
+
ended_via: string | null
|
|
222
|
+
last_assistant_msg_id: string | null
|
|
223
|
+
last_assistant_done: number | null
|
|
224
|
+
last_user_msg_id: string | null
|
|
225
|
+
user_prompt_preview: string | null
|
|
226
|
+
assistant_reply_preview: string | null
|
|
227
|
+
tool_call_count: number | null
|
|
228
|
+
created_at: number
|
|
229
|
+
updated_at: number
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function mapRow(row: RawTurnRow): Turn {
|
|
233
|
+
return {
|
|
234
|
+
turn_key: row.turn_key,
|
|
235
|
+
chat_id: row.chat_id,
|
|
236
|
+
thread_id: row.thread_id,
|
|
237
|
+
started_at: row.started_at,
|
|
238
|
+
ended_at: row.ended_at,
|
|
239
|
+
ended_via: (row.ended_via as TurnEndedVia | null) ?? null,
|
|
240
|
+
last_assistant_msg_id: row.last_assistant_msg_id,
|
|
241
|
+
last_assistant_done:
|
|
242
|
+
row.last_assistant_done === null ? null : row.last_assistant_done !== 0,
|
|
243
|
+
last_user_msg_id: row.last_user_msg_id,
|
|
244
|
+
user_prompt_preview: row.user_prompt_preview,
|
|
245
|
+
assistant_reply_preview: row.assistant_reply_preview,
|
|
246
|
+
tool_call_count: row.tool_call_count,
|
|
247
|
+
created_at: row.created_at,
|
|
248
|
+
updated_at: row.updated_at,
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// ---------------------------------------------------------------------------
|
|
253
|
+
// Helpers
|
|
254
|
+
// ---------------------------------------------------------------------------
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Record that a new turn has started. Inserts a row with `ended_at = NULL`.
|
|
258
|
+
* If a row with the same `turnKey` already exists it is left unchanged
|
|
259
|
+
* (INSERT OR IGNORE) — callers should generate unique keys.
|
|
260
|
+
*/
|
|
261
|
+
export function recordTurnStart(db: SqliteDatabase, args: RecordTurnStartArgs): void {
|
|
262
|
+
const now = Date.now()
|
|
263
|
+
db.prepare(`
|
|
264
|
+
INSERT OR IGNORE INTO turns
|
|
265
|
+
(turn_key, chat_id, thread_id, started_at, last_user_msg_id,
|
|
266
|
+
user_prompt_preview, created_at, updated_at)
|
|
267
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
268
|
+
`).run(
|
|
269
|
+
args.turnKey,
|
|
270
|
+
args.chatId,
|
|
271
|
+
args.threadId ?? null,
|
|
272
|
+
now,
|
|
273
|
+
args.lastUserMsgId ?? null,
|
|
274
|
+
args.userPromptPreview ?? null,
|
|
275
|
+
now,
|
|
276
|
+
now,
|
|
277
|
+
)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Record that a turn has ended cleanly. Updates `ended_at`, `ended_via`,
|
|
282
|
+
* and optionally the last outbound message fields, reply preview, and
|
|
283
|
+
* tool-call count.
|
|
284
|
+
*
|
|
285
|
+
* No-ops gracefully if `turnKey` is not found (turn may have already been
|
|
286
|
+
* swept by `markOrphanedAsRestarted` on a prior boot).
|
|
287
|
+
*/
|
|
288
|
+
export function recordTurnEnd(db: SqliteDatabase, args: RecordTurnEndArgs): void {
|
|
289
|
+
const now = Date.now()
|
|
290
|
+
db.prepare(`
|
|
291
|
+
UPDATE turns
|
|
292
|
+
SET
|
|
293
|
+
ended_at = ?,
|
|
294
|
+
ended_via = ?,
|
|
295
|
+
last_assistant_msg_id = COALESCE(?, last_assistant_msg_id),
|
|
296
|
+
last_assistant_done = COALESCE(?, last_assistant_done),
|
|
297
|
+
assistant_reply_preview = COALESCE(?, assistant_reply_preview),
|
|
298
|
+
tool_call_count = COALESCE(?, tool_call_count),
|
|
299
|
+
updated_at = ?
|
|
300
|
+
WHERE turn_key = ?
|
|
301
|
+
`).run(
|
|
302
|
+
now,
|
|
303
|
+
args.endedVia,
|
|
304
|
+
args.lastAssistantMsgId ?? null,
|
|
305
|
+
args.lastAssistantDone !== undefined ? (args.lastAssistantDone ? 1 : 0) : null,
|
|
306
|
+
args.assistantReplyPreview ?? null,
|
|
307
|
+
args.toolCallCount !== undefined ? args.toolCallCount : null,
|
|
308
|
+
now,
|
|
309
|
+
args.turnKey,
|
|
310
|
+
)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Return all turns for `chatId` where `ended_at IS NULL` — these are
|
|
315
|
+
* candidates for "killed mid-turn" (the gateway crashed before the turn
|
|
316
|
+
* completed and wrote its end record).
|
|
317
|
+
*
|
|
318
|
+
* Results are ordered by `started_at ASC` so callers can process
|
|
319
|
+
* oldest-first if they need to replay or report them.
|
|
320
|
+
*/
|
|
321
|
+
export function findOrphanedTurns(db: SqliteDatabase, chatId: string): Turn[] {
|
|
322
|
+
const rows = db.prepare(`
|
|
323
|
+
SELECT * FROM turns
|
|
324
|
+
WHERE chat_id = ? AND ended_at IS NULL
|
|
325
|
+
ORDER BY started_at ASC
|
|
326
|
+
`).all(chatId) as RawTurnRow[]
|
|
327
|
+
return rows.map(mapRow)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Boot-time reaper. Sweeps ALL turns (across all chats) that have
|
|
332
|
+
* `ended_at IS NULL` and stamps them with `ended_via = 'restart'` and
|
|
333
|
+
* `ended_at = now()`.
|
|
334
|
+
*
|
|
335
|
+
* Call this once, immediately after `openTurnsDb`, before any new turns
|
|
336
|
+
* are recorded for the current boot. That way the current boot's turns
|
|
337
|
+
* are cleanly separable from orphans inherited from the prior process.
|
|
338
|
+
*
|
|
339
|
+
* Returns the number of rows updated.
|
|
340
|
+
*/
|
|
341
|
+
export function markOrphanedAsRestarted(db: SqliteDatabase): number {
|
|
342
|
+
const now = Date.now()
|
|
343
|
+
const result = db.prepare(`
|
|
344
|
+
UPDATE turns
|
|
345
|
+
SET ended_at = ?,
|
|
346
|
+
ended_via = 'restart',
|
|
347
|
+
updated_at = ?
|
|
348
|
+
WHERE ended_at IS NULL
|
|
349
|
+
`).run(now, now) as { changes: number }
|
|
350
|
+
return result.changes
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Return the most recent N turns for `chatId` (any state — running or ended),
|
|
355
|
+
* ordered by started_at DESC. Used by the idle-footer renderer to decide
|
|
356
|
+
* whether to render "working since" vs "idle · last reply".
|
|
357
|
+
*
|
|
358
|
+
* `limit` defaults to 1 because the renderer only inspects the top row, but
|
|
359
|
+
* callers can pass more if they need backfill.
|
|
360
|
+
*/
|
|
361
|
+
export function findRecentTurnsForChat(
|
|
362
|
+
db: SqliteDatabase,
|
|
363
|
+
chatId: string,
|
|
364
|
+
limit = 1,
|
|
365
|
+
): Turn[] {
|
|
366
|
+
const rows = db.prepare(`
|
|
367
|
+
SELECT * FROM turns
|
|
368
|
+
WHERE chat_id = ?
|
|
369
|
+
ORDER BY started_at DESC
|
|
370
|
+
LIMIT ?
|
|
371
|
+
`).all(chatId, limit) as RawTurnRow[]
|
|
372
|
+
return rows.map(mapRow)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Return the most recent N turns across all chats for an agent, ordered by
|
|
377
|
+
* started_at DESC. Intended for the REST API endpoint
|
|
378
|
+
* `GET /api/agents/:name/turns?limit=20`.
|
|
379
|
+
*
|
|
380
|
+
* `limit` defaults to 20, max 200.
|
|
381
|
+
*/
|
|
382
|
+
export function listTurnsForAgent(
|
|
383
|
+
db: SqliteDatabase,
|
|
384
|
+
opts: { limit?: number } = {},
|
|
385
|
+
): Turn[] {
|
|
386
|
+
const limit = Math.min(Math.max(1, opts.limit ?? 20), 200)
|
|
387
|
+
const rows = db.prepare(`
|
|
388
|
+
SELECT * FROM turns
|
|
389
|
+
ORDER BY started_at DESC
|
|
390
|
+
LIMIT ?
|
|
391
|
+
`).all(limit) as RawTurnRow[]
|
|
392
|
+
return rows.map(mapRow)
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Find the single most-recently-started turn that ended via an interrupt
|
|
397
|
+
* (`'restart'` | `'sigterm'` | `'timeout'`) OR is still open
|
|
398
|
+
* (`ended_at IS NULL`). Used by Stage 4 to surface "you had pending work"
|
|
399
|
+
* to the agent on cold start.
|
|
400
|
+
*
|
|
401
|
+
* Returns null if no such turn exists (clean boot — last turn ended 'stop').
|
|
402
|
+
*
|
|
403
|
+
* Note on ordering: we use `started_at DESC` (not `updated_at`) so the
|
|
404
|
+
* boot-time reaper (which mass-stamps orphans with the SAME `ended_at` /
|
|
405
|
+
* `updated_at`) doesn't reorder them; the temporal "last turn" is what
|
|
406
|
+
* the user remembers, and that's `started_at`.
|
|
407
|
+
*/
|
|
408
|
+
export function findMostRecentInterruptedTurn(db: SqliteDatabase): Turn | null {
|
|
409
|
+
const row = db.prepare(`
|
|
410
|
+
SELECT * FROM turns
|
|
411
|
+
WHERE ended_at IS NULL
|
|
412
|
+
OR ended_via IN ('restart', 'sigterm', 'timeout')
|
|
413
|
+
ORDER BY started_at DESC
|
|
414
|
+
LIMIT 1
|
|
415
|
+
`).get() as RawTurnRow | undefined
|
|
416
|
+
return row ? mapRow(row) : null
|
|
417
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry wrapper for Telegram Bot API calls — the single policy the rest
|
|
3
|
+
* of the plugin relies on for flood-wait handling, benign 400 swallowing,
|
|
4
|
+
* and thread-not-found fallback.
|
|
5
|
+
*
|
|
6
|
+
* Extracted from gateway.ts so that:
|
|
7
|
+
* - it's unit-testable (the previous in-gateway definition couldn't be
|
|
8
|
+
* exercised without spinning up the whole bot runner)
|
|
9
|
+
* - stream-reply-handler / server.ts can share one implementation
|
|
10
|
+
* instead of each threading a `retry` dep through every callsite
|
|
11
|
+
* - callers can install an observer (`onRetry`, `onGiveUp`) for tests
|
|
12
|
+
* and production logging without reaching into the function body.
|
|
13
|
+
*
|
|
14
|
+
* Behaviour contract — each case is independently tested in
|
|
15
|
+
* `tests/retry-api-call.test.ts`:
|
|
16
|
+
*
|
|
17
|
+
* | Thrown error | This wrapper does |
|
|
18
|
+
* |-----------------------------------------------|--------------------------------------------|
|
|
19
|
+
* | GrammyError 429 | sleep retry_after seconds, retry |
|
|
20
|
+
* | GrammyError 400 "message is not modified" | swallow, return undefined |
|
|
21
|
+
* | GrammyError 400 "message to edit not found" | swallow, return undefined |
|
|
22
|
+
* | GrammyError 400 "message to delete not found" | swallow, return undefined |
|
|
23
|
+
* | GrammyError 400 "thread not found" (w/ opts) | throw `THREAD_NOT_FOUND` wrapper |
|
|
24
|
+
* | Network error (fetch failed / ECONN…) | exponential backoff retry, 3 attempts |
|
|
25
|
+
* | Anything else | rethrow immediately |
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { GrammyError } from 'grammy'
|
|
29
|
+
|
|
30
|
+
export interface RetryCallOpts {
|
|
31
|
+
/**
|
|
32
|
+
* The forum-topic thread id, used only to decide whether the
|
|
33
|
+
* "thread not found" 400 is retryable for a fallback path. If both
|
|
34
|
+
* `threadId` and `chat_id` are set, a thread-not-found 400 is rethrown
|
|
35
|
+
* as `THREAD_NOT_FOUND` so callers can drop the thread and retry on
|
|
36
|
+
* the main chat.
|
|
37
|
+
*/
|
|
38
|
+
threadId?: number
|
|
39
|
+
chat_id?: string
|
|
40
|
+
/**
|
|
41
|
+
* Optional caller-supplied label for the API call (e.g. "sendMessage",
|
|
42
|
+
* "editMessageText"). Currently informational only — accepted to allow
|
|
43
|
+
* call sites to self-document. Future: surface in retry logs / metrics.
|
|
44
|
+
*/
|
|
45
|
+
verb?: string
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface RetryObserver {
|
|
49
|
+
/** Fires just before sleeping for a retry. */
|
|
50
|
+
onRetry?(info: { attempt: number; reason: 'flood_wait' | 'network'; delayMs: number }): void
|
|
51
|
+
/** Fires when max retries is reached and the wrapper gives up. */
|
|
52
|
+
onGiveUp?(info: { attempts: number; error: unknown }): void
|
|
53
|
+
/** Fires for each benign error we swallowed (not-modified, not-found). */
|
|
54
|
+
onBenign?(info: { kind: 'not_modified' | 'message_not_found' | 'delete_not_found' }): void
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface RetryApiCallConfig {
|
|
58
|
+
/** Max retries before giving up. Defaults to 3. */
|
|
59
|
+
maxRetries?: number
|
|
60
|
+
/** Sleep helper — injected so tests can use fake timers. */
|
|
61
|
+
sleep?: (ms: number) => Promise<void>
|
|
62
|
+
/** Optional observer hooks. */
|
|
63
|
+
observer?: RetryObserver
|
|
64
|
+
/** Optional log sink for flood-wait / network lines. */
|
|
65
|
+
log?: (line: string) => void
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const DEFAULT_SLEEP = (ms: number) => new Promise<void>((r) => setTimeout(r, ms))
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Wrap a Telegram API call with the standard retry policy.
|
|
72
|
+
*
|
|
73
|
+
* Returns `fn`'s resolved value on success. Returns `undefined` for the
|
|
74
|
+
* swallowed-400 cases (caller must tolerate this — the typical caller is
|
|
75
|
+
* a `bot.api.editMessageText` which returns `true` on success, so
|
|
76
|
+
* `undefined` cleanly flags "no-op, target gone or identical"). Throws
|
|
77
|
+
* on 3rd network-error attempt or on any non-retryable error.
|
|
78
|
+
*/
|
|
79
|
+
export function createRetryApiCall(
|
|
80
|
+
config: RetryApiCallConfig = {},
|
|
81
|
+
): <T>(fn: () => Promise<T>, opts?: RetryCallOpts) => Promise<T> {
|
|
82
|
+
const maxRetries = config.maxRetries ?? 3
|
|
83
|
+
const sleep = config.sleep ?? DEFAULT_SLEEP
|
|
84
|
+
const observer = config.observer
|
|
85
|
+
const log = config.log
|
|
86
|
+
|
|
87
|
+
return async function retryApiCall<T>(
|
|
88
|
+
fn: () => Promise<T>,
|
|
89
|
+
opts?: RetryCallOpts,
|
|
90
|
+
): Promise<T> {
|
|
91
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
92
|
+
try {
|
|
93
|
+
return await fn()
|
|
94
|
+
} catch (err) {
|
|
95
|
+
const isGrammyErr = err instanceof GrammyError
|
|
96
|
+
const msg = err instanceof Error ? err.message : String(err)
|
|
97
|
+
const desc = isGrammyErr ? (err as GrammyError).description : msg
|
|
98
|
+
|
|
99
|
+
// Flood-wait — sleep retry_after and try again.
|
|
100
|
+
if (isGrammyErr && (err as GrammyError).error_code === 429) {
|
|
101
|
+
const retryAfter = Number(
|
|
102
|
+
(err as GrammyError).parameters?.retry_after ?? 5,
|
|
103
|
+
)
|
|
104
|
+
const delayMs = retryAfter * 1000
|
|
105
|
+
log?.(`telegram gateway: 429 rate limited, waiting ${retryAfter}s\n`)
|
|
106
|
+
observer?.onRetry?.({ attempt, reason: 'flood_wait', delayMs })
|
|
107
|
+
await sleep(delayMs)
|
|
108
|
+
continue
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Swallow "message is not modified" — Telegram's no-op-on-equal-text.
|
|
112
|
+
if (
|
|
113
|
+
isGrammyErr &&
|
|
114
|
+
(err as GrammyError).error_code === 400 &&
|
|
115
|
+
desc.includes('not modified')
|
|
116
|
+
) {
|
|
117
|
+
observer?.onBenign?.({ kind: 'not_modified' })
|
|
118
|
+
return undefined as unknown as T
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Swallow "message to edit/delete not found" — target vanished.
|
|
122
|
+
if (
|
|
123
|
+
isGrammyErr &&
|
|
124
|
+
(err as GrammyError).error_code === 400 &&
|
|
125
|
+
(desc.includes('message to edit not found') ||
|
|
126
|
+
desc.includes('message to delete not found'))
|
|
127
|
+
) {
|
|
128
|
+
observer?.onBenign?.({
|
|
129
|
+
kind: desc.includes('edit') ? 'message_not_found' : 'delete_not_found',
|
|
130
|
+
})
|
|
131
|
+
return undefined as unknown as T
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Stale forum-thread — caller may want to fall back to main chat.
|
|
135
|
+
if (
|
|
136
|
+
isGrammyErr &&
|
|
137
|
+
(err as GrammyError).error_code === 400 &&
|
|
138
|
+
desc.includes('thread not found') &&
|
|
139
|
+
opts?.threadId &&
|
|
140
|
+
opts?.chat_id
|
|
141
|
+
) {
|
|
142
|
+
throw Object.assign(new Error('THREAD_NOT_FOUND'), { original: err })
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Network-level transient errors — exponential backoff, bounded.
|
|
146
|
+
if (
|
|
147
|
+
!isGrammyErr &&
|
|
148
|
+
(msg.includes('ECONNRESET') ||
|
|
149
|
+
msg.includes('ETIMEDOUT') ||
|
|
150
|
+
msg.includes('fetch failed') ||
|
|
151
|
+
msg.includes('ENOTFOUND'))
|
|
152
|
+
) {
|
|
153
|
+
if (attempt < maxRetries - 1) {
|
|
154
|
+
const delayMs = Math.pow(2, attempt) * 1000
|
|
155
|
+
log?.(
|
|
156
|
+
`telegram gateway: network error, retrying in ${delayMs / 1000}s: ${msg}\n`,
|
|
157
|
+
)
|
|
158
|
+
observer?.onRetry?.({ attempt, reason: 'network', delayMs })
|
|
159
|
+
await sleep(delayMs)
|
|
160
|
+
continue
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
observer?.onGiveUp?.({ attempts: attempt + 1, error: err })
|
|
165
|
+
throw err
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const giveUpErr = new Error('retryApiCall: max retries exceeded')
|
|
169
|
+
observer?.onGiveUp?.({ attempts: maxRetries, error: giveUpErr })
|
|
170
|
+
throw giveUpErr
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Build script for @switchroom-ai/telegram-plugin npm publish.
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
import { readFileSync, writeFileSync, chmodSync, mkdirSync, rmSync } from "node:fs";
|
|
5
|
+
import { resolve, dirname } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { escapeBundleNonAscii } from "../../scripts/escape-bundle-non-ascii.mjs";
|
|
8
|
+
|
|
9
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
|
+
const outDir = resolve(root, "dist");
|
|
11
|
+
|
|
12
|
+
console.log("[build] cleaning dist/");
|
|
13
|
+
rmSync(outDir, { recursive: true, force: true });
|
|
14
|
+
mkdirSync(outDir, { recursive: true });
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
execSync("bun --version", { stdio: "ignore" });
|
|
18
|
+
} catch {
|
|
19
|
+
console.error("[build] bun is required to build. Install from https://bun.sh");
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const entries = [
|
|
24
|
+
{ src: "server.ts", out: "server.js", label: "server (legacy + dual-mode shim)" },
|
|
25
|
+
{ src: "gateway/gateway.ts", out: "gateway/gateway.js", label: "gateway (persistent service)" },
|
|
26
|
+
{ src: "bridge/bridge.ts", out: "bridge/bridge.js", label: "bridge (MCP proxy)" },
|
|
27
|
+
{ src: "foreman/foreman.ts", out: "foreman/foreman.js", label: "foreman (admin bot)" },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
for (const { src, out, label } of entries) {
|
|
31
|
+
const srcPath = resolve(root, src);
|
|
32
|
+
const outPath = resolve(outDir, out);
|
|
33
|
+
const outDirForEntry = dirname(outPath);
|
|
34
|
+
mkdirSync(outDirForEntry, { recursive: true });
|
|
35
|
+
|
|
36
|
+
console.log(`[build] bundling ${src} -> dist/${out}`);
|
|
37
|
+
// `--external node-fetch`: grammy depends on node-fetch@2 which is a
|
|
38
|
+
// CJS package using node's `http`/`stream` directly. When bundled with
|
|
39
|
+
// `--target node`, bun's bundler INLINES node-fetch as the fetch
|
|
40
|
+
// implementation. Under bun runtime that inlined node-fetch breaks
|
|
41
|
+
// grammy's API calls with a generic "Network request failed!" — the
|
|
42
|
+
// gateway boot then loops 8x retrying getMe and exits, rendering the
|
|
43
|
+
// entire fleet unresponsive (every reply path fails, agent thumbs-up
|
|
44
|
+
// works but no message lands).
|
|
45
|
+
//
|
|
46
|
+
// Externalizing node-fetch keeps the bundle target-node compatible
|
|
47
|
+
// for npm-i-g users on a node runtime (grammy declares node-fetch as
|
|
48
|
+
// a dep so it'll be present in node_modules) AND lets bun's native
|
|
49
|
+
// fetch shim take over when the bundle runs under bun (the actual
|
|
50
|
+
// production deployment via `systemd ExecStart=bun gateway.js`).
|
|
51
|
+
//
|
|
52
|
+
// Verified: the un-externalized bundle reproducibly fails under bun
|
|
53
|
+
// with "HttpError: Network request for 'getMe' failed!" within 1s of
|
|
54
|
+
// boot. The externalized bundle boots cleanly and polls successfully.
|
|
55
|
+
execSync(
|
|
56
|
+
`bun build ${JSON.stringify(srcPath)} --outdir ${JSON.stringify(outDirForEntry)} --target node --external node-fetch`,
|
|
57
|
+
{ stdio: "inherit", cwd: root }
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
let content = readFileSync(outPath, "utf8");
|
|
61
|
+
if (content.startsWith("#!/usr/bin/env bun")) {
|
|
62
|
+
content = content.replace(/^#!\/usr\/bin\/env bun/, "#!/usr/bin/env node");
|
|
63
|
+
writeFileSync(outPath, content);
|
|
64
|
+
}
|
|
65
|
+
chmodSync(outPath, 0o755);
|
|
66
|
+
|
|
67
|
+
// Bun parser bug workaround — see scripts/escape-bundle-non-ascii.mjs.
|
|
68
|
+
// Required for the gateway bundle: without it, the boot card's `✅`
|
|
69
|
+
// and the inline `·` separator in the ack-line template literal get
|
|
70
|
+
// double-UTF-8 encoded on the wire (#642 follow-up; mojibake reported
|
|
71
|
+
// as `â LawGPT back up · v0.6.3`).
|
|
72
|
+
const escResult = escapeBundleNonAscii(outPath);
|
|
73
|
+
if (escResult.changed) {
|
|
74
|
+
console.log(`[build] ASCII-escaped ${escResult.nonAsciiCount} non-ASCII code units in dist/${out}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log("[build] done");
|