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,582 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boot card — posts a quiet, contextual ack at gateway startup. Closes
|
|
3
|
+
* #60 and is PR 1 of 3 in #142's "telegram surfaces: quiet, contextual
|
|
4
|
+
* cards" workstream.
|
|
5
|
+
*
|
|
6
|
+
* Default state is a single line: `✅ <agent> back up · <version>`.
|
|
7
|
+
*
|
|
8
|
+
* Probes still run, but only at a settle window (6s by default) — long
|
|
9
|
+
* enough that systemd transients (`deactivating`, `activating`, crons
|
|
10
|
+
* mid-re-register) self-heal before any row could surface. If after the
|
|
11
|
+
* settle a probe is genuinely degraded or failed, the card edits to
|
|
12
|
+
* append a row for THAT probe only. Healthy probes never produce rows.
|
|
13
|
+
*
|
|
14
|
+
* What's deleted (relative to pre-#142):
|
|
15
|
+
* - The always-rendered six-row checklist (Account/Agent/Gateway/
|
|
16
|
+
* Quota/Hindsight/Crons) — all replaced by the silent-when-healthy
|
|
17
|
+
* contract.
|
|
18
|
+
* - The skeleton "probing…" placeholder edit dance — the immediate
|
|
19
|
+
* post is now the final post for healthy boots.
|
|
20
|
+
* - The session-greeting card written by scaffold.ts (~750 lines of
|
|
21
|
+
* curl + heredoc bash that baked Profile/Tools/Skills/Limits/
|
|
22
|
+
* Channel/Memory at scaffold time and re-posted on every
|
|
23
|
+
* SessionStart). That content moves to the future `/status`
|
|
24
|
+
* command (PR 3).
|
|
25
|
+
*
|
|
26
|
+
* What's kept:
|
|
27
|
+
* - The probe layer in `boot-probes.ts` — same probe set, same shapes,
|
|
28
|
+
* same defensive-against-throw discipline.
|
|
29
|
+
* - `BotApiForBootCard` / `BootCardHandle` / dedupe gate
|
|
30
|
+
* (`shouldSkipDuplicateBootCard`) — public API stable for the
|
|
31
|
+
* gateway's two call sites (boot path + bridge-reconnect).
|
|
32
|
+
* - `BootCardHandle` / `complete()` (called from the first user-turn handler).
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import type { ProbeResult, GatewayRuntimeInfo } from './boot-probes.js'
|
|
36
|
+
import type { AccountSummary } from '../auth-dashboard.js'
|
|
37
|
+
import { formatAccountQuotaLine } from '../auth-dashboard.js'
|
|
38
|
+
import {
|
|
39
|
+
probeAccount,
|
|
40
|
+
probeAgentProcess,
|
|
41
|
+
probeGateway,
|
|
42
|
+
probeQuota,
|
|
43
|
+
probeHindsight,
|
|
44
|
+
probeCronTimers,
|
|
45
|
+
watchAgentProcess,
|
|
46
|
+
AGENT_LIVE_WINDOW_MS,
|
|
47
|
+
AGENT_LIVE_POLL_INTERVAL_MS,
|
|
48
|
+
} from './boot-probes.js'
|
|
49
|
+
import { escapeHtml } from '../card-format.js'
|
|
50
|
+
import { join } from 'path'
|
|
51
|
+
import { loadConfig as _loadSwitchroomConfig } from '../../src/config/loader.js'
|
|
52
|
+
|
|
53
|
+
// ─── Persona name resolution ─────────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Resolve the display name for an agent from its config's soul.name field.
|
|
57
|
+
*
|
|
58
|
+
* The slug (e.g. "finn") is an operator-facing identifier: agent directory,
|
|
59
|
+
* systemd unit name, vault key prefix. It should never appear in
|
|
60
|
+
* user-facing Telegram output. soul.name (e.g. "Finn") is the persona
|
|
61
|
+
* the user knows through the bot username, topic emoji, and conversation.
|
|
62
|
+
*
|
|
63
|
+
* Falls back to the slug when:
|
|
64
|
+
* - soul is not set in the agent config
|
|
65
|
+
* - the agent key is not found in switchroom.yaml
|
|
66
|
+
* - the config cannot be loaded (gateway running outside a switchroom env)
|
|
67
|
+
*
|
|
68
|
+
* The optional `loadConfig` override exists purely for unit-test injection.
|
|
69
|
+
* Production callers pass no second argument and get the live config.
|
|
70
|
+
*
|
|
71
|
+
* Closes #169.
|
|
72
|
+
*/
|
|
73
|
+
export function resolvePersonaName(
|
|
74
|
+
slug: string,
|
|
75
|
+
loadConfig?: () => { agents?: Record<string, { soul?: { name?: string } | null }> } | null,
|
|
76
|
+
): string {
|
|
77
|
+
try {
|
|
78
|
+
const config = loadConfig ? loadConfig() : _loadSwitchroomConfig()
|
|
79
|
+
const name = config?.agents?.[slug]?.soul?.name
|
|
80
|
+
return name && name.trim().length > 0 ? name : slug
|
|
81
|
+
} catch {
|
|
82
|
+
// Config unreadable (gateway running in a test env or outside a
|
|
83
|
+
// switchroom workspace). Degrade gracefully to the slug.
|
|
84
|
+
return slug
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ─── Types ──────────────────────────────────────────────────────────────────
|
|
89
|
+
|
|
90
|
+
export type RestartReason = 'planned' | 'graceful' | 'crash' | 'fresh'
|
|
91
|
+
|
|
92
|
+
export type ProbeKey = 'account' | 'agent' | 'gateway' | 'quota' | 'hindsight' | 'crons'
|
|
93
|
+
|
|
94
|
+
export type ProbeMap = Partial<Record<ProbeKey, ProbeResult | null>>
|
|
95
|
+
|
|
96
|
+
export interface BotApiForBootCard {
|
|
97
|
+
sendMessage(
|
|
98
|
+
chatId: string,
|
|
99
|
+
text: string,
|
|
100
|
+
opts?: Record<string, unknown>,
|
|
101
|
+
): Promise<{ message_id: number }>
|
|
102
|
+
editMessageText(
|
|
103
|
+
chatId: string,
|
|
104
|
+
messageId: number,
|
|
105
|
+
text: string,
|
|
106
|
+
opts?: Record<string, unknown>,
|
|
107
|
+
): Promise<unknown>
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface BootCardHandle {
|
|
111
|
+
messageId: number
|
|
112
|
+
/** Call when the first user turn starts. */
|
|
113
|
+
complete(): void
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export type BootCardSite = 'boot' | 'bridge-reconnect'
|
|
117
|
+
|
|
118
|
+
export interface BootCardGate {
|
|
119
|
+
/**
|
|
120
|
+
* Set after the boot path successfully posts a card. The bridge-reconnect
|
|
121
|
+
* path checks this to avoid posting a second card on the same gateway
|
|
122
|
+
* lifetime — observed in the wild as klanker msgId 2245 + 2248 within 5s
|
|
123
|
+
* (2026-04-26 11:19:47).
|
|
124
|
+
*/
|
|
125
|
+
activeBootCard: { messageId: number } | null
|
|
126
|
+
/**
|
|
127
|
+
* True while a boot card emission is in-flight (sendMessage round-trip
|
|
128
|
+
* not yet resolved). Closes the race window where bridge-reconnect ran
|
|
129
|
+
* during the boot path's await and saw activeBootCard still null —
|
|
130
|
+
* observed as klanker msgId 4715 + 4716 (2026-05-01 10:13:15, issue #489).
|
|
131
|
+
* Optional for backward compatibility with callers that pre-date the flag.
|
|
132
|
+
*/
|
|
133
|
+
bootCardPending?: boolean
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface BootCardSkipDecision {
|
|
137
|
+
skip: boolean
|
|
138
|
+
/** Human-readable reason (only present when skip=true). */
|
|
139
|
+
reason?: string
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Decide whether to skip posting the boot card based on gateway state.
|
|
144
|
+
*
|
|
145
|
+
* Two emit sites contend on every gateway lifetime:
|
|
146
|
+
*
|
|
147
|
+
* - `boot`: the gateway IIFE startup path (long: probes session
|
|
148
|
+
* marker, clean-shutdown marker, restart marker, etc).
|
|
149
|
+
* - `bridge-reconnect`: fires when the agent's IPC client connects
|
|
150
|
+
* to the gateway socket.
|
|
151
|
+
*
|
|
152
|
+
* Earlier versions of this gate special-cased `boot` as "primary"
|
|
153
|
+
* and let it post unconditionally. Empirically that assumption is
|
|
154
|
+
* wrong: when the agent process boots faster than the gateway IIFE
|
|
155
|
+
* reaches its emit, bridge-reconnect runs first, posts its card,
|
|
156
|
+
* and then boot fires its own card too — both with reason=graceful
|
|
157
|
+
* within ~100ms (observed in finn 2026-05-02: msgId 673 + 674
|
|
158
|
+
* with both `posted` log lines on consecutive lines).
|
|
159
|
+
*
|
|
160
|
+
* The fix is first-write-wins: whichever site fires first claims
|
|
161
|
+
* `bootCardPending` synchronously, posts the card, and releases.
|
|
162
|
+
* The other site sees pending or active and defers. Both sites'
|
|
163
|
+
* chat resolution is identical (same restart-marker / clean-shutdown
|
|
164
|
+
* / session-marker pipeline), so it doesn't matter which one wins.
|
|
165
|
+
*/
|
|
166
|
+
export function shouldSkipDuplicateBootCard(
|
|
167
|
+
gate: BootCardGate,
|
|
168
|
+
site: BootCardSite,
|
|
169
|
+
): BootCardSkipDecision {
|
|
170
|
+
if (gate.bootCardPending) {
|
|
171
|
+
return { skip: true, reason: `in-flight-other-site site=${site}` }
|
|
172
|
+
}
|
|
173
|
+
if (gate.activeBootCard != null) {
|
|
174
|
+
return {
|
|
175
|
+
skip: true,
|
|
176
|
+
reason: `already-posted-msgId=${gate.activeBootCard.messageId} site=${site}`,
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return { skip: false }
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ─── Rendering ───────────────────────────────────────────────────────────────
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Settle window before probes run. Long enough that systemd transients
|
|
186
|
+
* (`deactivating`/`activating`, dbus contention during reload, crons
|
|
187
|
+
* mid-re-register) self-heal so a transient red can't reach the user.
|
|
188
|
+
*
|
|
189
|
+
* Constant by design — not a config field. The issue is explicit:
|
|
190
|
+
* "Falls out of design, not a config knob." 6s is at the high end of the
|
|
191
|
+
* 5–7s range called out in #142 for headroom under load.
|
|
192
|
+
*/
|
|
193
|
+
const SETTLE_WINDOW_MS = 6000
|
|
194
|
+
|
|
195
|
+
const DOT: Record<string, string> = {
|
|
196
|
+
ok: '🟢',
|
|
197
|
+
degraded: '🟡',
|
|
198
|
+
fail: '🔴',
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const PROBE_LABELS: Record<ProbeKey, string> = {
|
|
202
|
+
account: 'Account',
|
|
203
|
+
agent: 'Agent',
|
|
204
|
+
gateway: 'Gateway',
|
|
205
|
+
quota: 'Quota',
|
|
206
|
+
hindsight: 'Hindsight',
|
|
207
|
+
crons: 'Crons',
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const PROBE_KEYS: ReadonlyArray<ProbeKey> = [
|
|
211
|
+
'account', 'agent', 'gateway', 'quota', 'hindsight', 'crons',
|
|
212
|
+
]
|
|
213
|
+
|
|
214
|
+
const REASON_EMOJI: Record<RestartReason, string> = {
|
|
215
|
+
planned: '✅',
|
|
216
|
+
graceful: '✅',
|
|
217
|
+
crash: '⚠️',
|
|
218
|
+
fresh: '🆕',
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const REASON_LABEL: Record<RestartReason, string> = {
|
|
222
|
+
planned: 'planned restart',
|
|
223
|
+
graceful: 'graceful restart',
|
|
224
|
+
crash: 'crash recovery',
|
|
225
|
+
fresh: 'fresh start',
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export interface RenderBootCardOpts {
|
|
229
|
+
agentName: string
|
|
230
|
+
/** Pre-formatted version string, e.g. "v0.3.0+44" or "v0.3.0 · #143 · 2h ago". */
|
|
231
|
+
version: string
|
|
232
|
+
/** Probe results (only present after the settle window). When absent or
|
|
233
|
+
* empty, the card is the bare ack line — no probe rows. */
|
|
234
|
+
probes?: ProbeMap
|
|
235
|
+
/** What kind of restart this is. Crash flips the ack emoji to ⚠️ AND
|
|
236
|
+
* appends a "Crash recovery" row underneath. Other reasons just set
|
|
237
|
+
* the emoji. */
|
|
238
|
+
restartReason?: RestartReason
|
|
239
|
+
/** Age of the restart marker in ms — shown in the crash row. */
|
|
240
|
+
restartAgeMs?: number
|
|
241
|
+
/**
|
|
242
|
+
* Per-account quota snapshots to render below the probe rows.
|
|
243
|
+
* One line per enabled account showing 5h % / 7d % and the
|
|
244
|
+
* nearest reset countdown so users see headroom without running
|
|
245
|
+
* `/auth` or `/usage` after every restart.
|
|
246
|
+
*
|
|
247
|
+
* Empty / undefined hides the section entirely — preserves the
|
|
248
|
+
* silent-when-healthy contract for callers that don't pass account
|
|
249
|
+
* data (tests, harnesses, gateways without the auth model).
|
|
250
|
+
*
|
|
251
|
+
* Closes #708.
|
|
252
|
+
*/
|
|
253
|
+
accounts?: ReadonlyArray<AccountSummary>
|
|
254
|
+
/** Clock injection point for tests; defaults to `new Date()`. */
|
|
255
|
+
now?: Date
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Render the boot card. Single line by default; appends one row per
|
|
260
|
+
* fail/degraded probe (and one for crash recovery, if applicable).
|
|
261
|
+
*
|
|
262
|
+
* Healthy probes never produce a row. The ack line is sufficient — the
|
|
263
|
+
* user only needs to know the agent came back up. Anything red catches
|
|
264
|
+
* the eye; everything else stays out of the way.
|
|
265
|
+
*/
|
|
266
|
+
export function renderBootCard(opts: RenderBootCardOpts): string {
|
|
267
|
+
const { agentName, version, probes, restartReason, restartAgeMs } = opts
|
|
268
|
+
const ackEmoji = restartReason ? REASON_EMOJI[restartReason] : '✅'
|
|
269
|
+
const ack = `${ackEmoji} <b>${escapeHtml(agentName)}</b> back up · ${escapeHtml(version)}`
|
|
270
|
+
|
|
271
|
+
const degradedRows: string[] = []
|
|
272
|
+
|
|
273
|
+
// Crash recovery: surface explicitly so the user can tell whether
|
|
274
|
+
// their next message will land on a fresh process. The agent-crashed
|
|
275
|
+
// operator event from #92/#147 is a separate notification surface;
|
|
276
|
+
// this row exists for users who only check the boot card.
|
|
277
|
+
if (restartReason === 'crash') {
|
|
278
|
+
const ageStr = restartAgeMs != null && restartAgeMs > 0
|
|
279
|
+
? ` · ${(restartAgeMs / 1000).toFixed(1)}s ago`
|
|
280
|
+
: ''
|
|
281
|
+
degradedRows.push(`⚠️ <b>Restart</b> ${escapeHtml(REASON_LABEL.crash)}${ageStr}`)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Probe rows — only those that surfaced as degraded/fail. Healthy
|
|
285
|
+
// (`ok`) probes don't render at all.
|
|
286
|
+
if (probes) {
|
|
287
|
+
for (const key of PROBE_KEYS) {
|
|
288
|
+
const r = probes[key]
|
|
289
|
+
if (!r) continue
|
|
290
|
+
if (r.status === 'ok') continue
|
|
291
|
+
const dot = DOT[r.status] ?? DOT.fail
|
|
292
|
+
degradedRows.push(`${dot} <b>${PROBE_LABELS[key]}</b> ${escapeHtml(r.detail)}`)
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Per-account quota section (issue #708) — one line per enabled
|
|
297
|
+
// account showing 5h % / 7d % / nearest reset, with the active
|
|
298
|
+
// account marked. Renders alongside the ack line so users see
|
|
299
|
+
// headroom without running /auth or /usage.
|
|
300
|
+
const accountRows = renderAccountRows(opts.accounts, opts.now ?? new Date())
|
|
301
|
+
|
|
302
|
+
const sections: string[] = [ack]
|
|
303
|
+
if (degradedRows.length > 0) sections.push('', ...degradedRows)
|
|
304
|
+
if (accountRows.length > 0) sections.push('', ...accountRows)
|
|
305
|
+
if (sections.length === 1) return ack
|
|
306
|
+
return sections.join('\n')
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Render the per-account quota rows. Returns an empty array when no
|
|
311
|
+
* accounts are passed — keeping the boot card's silent-when-healthy
|
|
312
|
+
* default for callers that don't supply account data.
|
|
313
|
+
*
|
|
314
|
+
* Reuses the dashboard's `formatAccountQuotaLine` so the two surfaces
|
|
315
|
+
* speak with one voice.
|
|
316
|
+
*/
|
|
317
|
+
export function renderAccountRows(
|
|
318
|
+
accounts: ReadonlyArray<AccountSummary> | undefined,
|
|
319
|
+
now: Date,
|
|
320
|
+
): string[] {
|
|
321
|
+
if (!accounts || accounts.length === 0) return []
|
|
322
|
+
const rows: string[] = []
|
|
323
|
+
rows.push(`<b>Accounts (${accounts.length})</b>`)
|
|
324
|
+
const nowMs = now.getTime()
|
|
325
|
+
for (const a of accounts) {
|
|
326
|
+
const marker = a.activeForThisAgent ? '▶' : '↳'
|
|
327
|
+
const labelHtml = `<code>${escapeHtml(a.label)}</code>`
|
|
328
|
+
// formatAccountQuotaLine returns HTML (with <i> tags) so we don't
|
|
329
|
+
// re-escape — pass it through verbatim.
|
|
330
|
+
const quotaLine = formatAccountQuotaLine(a, nowMs)
|
|
331
|
+
rows.push(quotaLine ? `${marker} ${labelHtml} ${quotaLine}` : `${marker} ${labelHtml}`)
|
|
332
|
+
}
|
|
333
|
+
return rows
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// ─── Probe orchestration ─────────────────────────────────────────────────────
|
|
337
|
+
|
|
338
|
+
export interface RunProbesOpts {
|
|
339
|
+
/** Persona display name — used only for rendering (ack line, probe rows). */
|
|
340
|
+
agentName: string
|
|
341
|
+
/** Lowercase systemd slug (e.g. "klanker") — used for systemctl unit targets.
|
|
342
|
+
* Must differ from agentName when the soul.name differs in case from the slug.
|
|
343
|
+
* Falls back to agentName when not provided (backwards-compat). */
|
|
344
|
+
agentSlug?: string
|
|
345
|
+
/** Pre-formatted version string passed through to the renderer. */
|
|
346
|
+
version: string
|
|
347
|
+
agentDir: string
|
|
348
|
+
gatewayInfo: GatewayRuntimeInfo
|
|
349
|
+
bankName?: string
|
|
350
|
+
/** Why the gateway is starting — feeds the ack-line emoji and the
|
|
351
|
+
* optional crash-recovery row. */
|
|
352
|
+
restartReason?: RestartReason
|
|
353
|
+
/** Age of the restart marker in ms — shown in the crash row. */
|
|
354
|
+
restartAgeMs?: number
|
|
355
|
+
/** Override fetch for tests. */
|
|
356
|
+
fetchImpl?: typeof fetch
|
|
357
|
+
/** Override settle window for tests; production uses SETTLE_WINDOW_MS. */
|
|
358
|
+
settleWindowMs?: number
|
|
359
|
+
/** Override setTimeout for tests. */
|
|
360
|
+
setTimeoutImpl?: typeof setTimeout
|
|
361
|
+
/**
|
|
362
|
+
* How long the live-agent-status loop keeps editing the card after the
|
|
363
|
+
* initial probe run. Defaults to AGENT_LIVE_WINDOW_MS (45s). Set to 0
|
|
364
|
+
* to disable the live loop entirely (e.g. in tests that only need the
|
|
365
|
+
* one-shot settle-window behaviour).
|
|
366
|
+
*/
|
|
367
|
+
agentLiveWindowMs?: number
|
|
368
|
+
/** How often the live loop re-polls systemd. Defaults to
|
|
369
|
+
* AGENT_LIVE_POLL_INTERVAL_MS (2s). Override in tests for speed. */
|
|
370
|
+
agentLivePollIntervalMs?: number
|
|
371
|
+
/** Override for tests — replaces real execFile calls in the initial probe run
|
|
372
|
+
* (probeAgentProcess + probeCronTimers). Distinct from agentLiveExecFileImpl
|
|
373
|
+
* which covers the post-settle live-watch loop. */
|
|
374
|
+
probeExecFileImpl?: (cmd: string, args: string[]) => Promise<{ stdout: string; stderr: string }>
|
|
375
|
+
/** Override for tests — replaces real execFile calls in the live loop. */
|
|
376
|
+
agentLiveExecFileImpl?: (cmd: string, args: string[]) => Promise<{ stdout: string; stderr: string }>
|
|
377
|
+
/** Override for tests — replaces real delays in the live loop. */
|
|
378
|
+
agentLiveSleepImpl?: (ms: number) => Promise<void>
|
|
379
|
+
/**
|
|
380
|
+
* Loader for the per-account rows that get appended below the probe
|
|
381
|
+
* rows on the boot card (issue #708). Returns the account list
|
|
382
|
+
* synchronously or via a Promise; an empty array / null disables
|
|
383
|
+
* the section. Skipped on the immediate ack post — only consulted
|
|
384
|
+
* during the post-settle re-render so the first paint stays fast.
|
|
385
|
+
*/
|
|
386
|
+
loadAccounts?: () =>
|
|
387
|
+
| ReadonlyArray<AccountSummary>
|
|
388
|
+
| null
|
|
389
|
+
| Promise<ReadonlyArray<AccountSummary> | null>
|
|
390
|
+
/** When true, resolve the agent PID via cgroup walk instead of MainPID
|
|
391
|
+
* (which is the tmux server pid under tmux supervisor). */
|
|
392
|
+
tmuxSupervisor?: boolean
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/** Run all six probes concurrently with their own per-probe timeouts.
|
|
396
|
+
* Used by both the production startBootCard flow and any caller that
|
|
397
|
+
* wants the probe set without the post/edit dance. */
|
|
398
|
+
export async function runAllProbes(opts: RunProbesOpts): Promise<ProbeMap> {
|
|
399
|
+
const claudeDir = join(opts.agentDir, '.claude')
|
|
400
|
+
const probes: ProbeMap = {}
|
|
401
|
+
// Use the explicit slug for systemd unit targets; fall back to agentName for
|
|
402
|
+
// callers that haven't been updated yet (backwards-compat).
|
|
403
|
+
const slug = opts.agentSlug ?? opts.agentName
|
|
404
|
+
|
|
405
|
+
await Promise.allSettled([
|
|
406
|
+
probeAccount(opts.agentDir).then(r => { probes.account = r }),
|
|
407
|
+
probeAgentProcess(slug, { execFileImpl: opts.probeExecFileImpl, tmuxSupervisor: opts.tmuxSupervisor }).then(r => { probes.agent = r }),
|
|
408
|
+
probeGateway(opts.gatewayInfo).then(r => { probes.gateway = r }),
|
|
409
|
+
probeQuota(claudeDir, opts.agentDir, opts.fetchImpl).then(r => { probes.quota = r }),
|
|
410
|
+
probeHindsight(opts.bankName, opts.fetchImpl).then(r => { probes.hindsight = r }),
|
|
411
|
+
probeCronTimers(slug, { execFileImpl: opts.probeExecFileImpl }).then(r => { probes.crons = r }),
|
|
412
|
+
])
|
|
413
|
+
|
|
414
|
+
return probes
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/** Post the boot card, then run probes after a settle window and edit
|
|
418
|
+
* the card in-place if any probe came back degraded/failed. Healthy
|
|
419
|
+
* boots stay as the bare ack line forever.
|
|
420
|
+
*
|
|
421
|
+
* Returns a handle. The probe edit
|
|
422
|
+
* is fire-and-forget — failures are swallowed so the ack line is never
|
|
423
|
+
* rolled back to a worse state. */
|
|
424
|
+
export async function startBootCard(
|
|
425
|
+
chatId: string,
|
|
426
|
+
threadId: number | undefined,
|
|
427
|
+
bot: BotApiForBootCard,
|
|
428
|
+
opts: RunProbesOpts,
|
|
429
|
+
ackMessageId?: number,
|
|
430
|
+
log?: (line: string) => void,
|
|
431
|
+
): Promise<BootCardHandle> {
|
|
432
|
+
const logger = log ?? ((l: string) => process.stderr.write(l))
|
|
433
|
+
const setTimeoutFn = opts.setTimeoutImpl ?? setTimeout
|
|
434
|
+
const settleMs = opts.settleWindowMs ?? SETTLE_WINDOW_MS
|
|
435
|
+
|
|
436
|
+
// Render and post the bare ack line immediately. The user gets
|
|
437
|
+
// confirmation that the agent is back without waiting on probes.
|
|
438
|
+
const ackText = renderBootCard({
|
|
439
|
+
agentName: opts.agentName,
|
|
440
|
+
version: opts.version,
|
|
441
|
+
restartReason: opts.restartReason,
|
|
442
|
+
restartAgeMs: opts.restartAgeMs,
|
|
443
|
+
})
|
|
444
|
+
|
|
445
|
+
let messageId: number
|
|
446
|
+
try {
|
|
447
|
+
const sent = await bot.sendMessage(chatId, ackText, {
|
|
448
|
+
parse_mode: 'HTML',
|
|
449
|
+
link_preview_options: { is_disabled: true },
|
|
450
|
+
...(threadId != null ? { message_thread_id: threadId } : {}),
|
|
451
|
+
...(ackMessageId != null ? { reply_parameters: { message_id: ackMessageId } } : {}),
|
|
452
|
+
})
|
|
453
|
+
messageId = sent.message_id
|
|
454
|
+
logger(`telegram gateway: boot-card: posted msgId=${messageId} chatId=${chatId} reason=${opts.restartReason ?? '-'}\n`)
|
|
455
|
+
} catch (err: unknown) {
|
|
456
|
+
logger(`telegram gateway: boot-card: failed to post ack: ${(err as Error)?.message ?? String(err)}\n`)
|
|
457
|
+
return { messageId: -1, complete: () => {} }
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Determine the live window for agent-service status updates. Callers
|
|
461
|
+
// can pass 0 to disable the live loop (e.g. in tests that only need
|
|
462
|
+
// the one-shot settle-window behaviour). Defaults to AGENT_LIVE_WINDOW_MS.
|
|
463
|
+
const liveWindowMs = opts.agentLiveWindowMs ?? AGENT_LIVE_WINDOW_MS
|
|
464
|
+
|
|
465
|
+
// Schedule the post-settle probe run + live agent-status loop. Wrapped
|
|
466
|
+
// in setTimeout so the boot path returns the handle immediately — the
|
|
467
|
+
// gateway can continue setup without waiting on probes.
|
|
468
|
+
setTimeoutFn(() => {
|
|
469
|
+
void (async () => {
|
|
470
|
+
try {
|
|
471
|
+
// ── Phase 1: one-shot probe run after the settle window ───────────
|
|
472
|
+
// Run all probes concurrently. If the agent probe comes back ok at
|
|
473
|
+
// this point, no live loop is needed. If it's degraded/fail we
|
|
474
|
+
// start the live watch (Phase 2) to keep updating the card.
|
|
475
|
+
const probes = await runAllProbes(opts)
|
|
476
|
+
|
|
477
|
+
// Per-account rows (issue #708). Loaded best-effort
|
|
478
|
+
// alongside probes; failures are swallowed so the card still
|
|
479
|
+
// renders correctly with no accounts section.
|
|
480
|
+
let accountRows: ReadonlyArray<AccountSummary> | null = null
|
|
481
|
+
if (opts.loadAccounts) {
|
|
482
|
+
try {
|
|
483
|
+
accountRows = await opts.loadAccounts()
|
|
484
|
+
} catch (loadErr: unknown) {
|
|
485
|
+
logger(
|
|
486
|
+
`telegram gateway: boot-card: loadAccounts failed: ${
|
|
487
|
+
(loadErr as Error)?.message ?? String(loadErr)
|
|
488
|
+
}\n`,
|
|
489
|
+
)
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Render with current probe state and edit if anything changed.
|
|
494
|
+
let currentText = renderBootCard({
|
|
495
|
+
agentName: opts.agentName,
|
|
496
|
+
version: opts.version,
|
|
497
|
+
probes,
|
|
498
|
+
restartReason: opts.restartReason,
|
|
499
|
+
restartAgeMs: opts.restartAgeMs,
|
|
500
|
+
...(accountRows ? { accounts: accountRows } : {}),
|
|
501
|
+
})
|
|
502
|
+
|
|
503
|
+
if (currentText !== ackText) {
|
|
504
|
+
try {
|
|
505
|
+
await bot.editMessageText(chatId, messageId, currentText, {
|
|
506
|
+
parse_mode: 'HTML',
|
|
507
|
+
link_preview_options: { is_disabled: true },
|
|
508
|
+
...(threadId != null ? { message_thread_id: threadId } : {}),
|
|
509
|
+
})
|
|
510
|
+
logger(`telegram gateway: boot-card: probes settled with degraded rows msgId=${messageId}\n`)
|
|
511
|
+
} catch (editErr: unknown) {
|
|
512
|
+
logger(`telegram gateway: boot-card: probe-edit error msgId=${messageId}: ${(editErr as Error)?.message ?? String(editErr)}\n`)
|
|
513
|
+
}
|
|
514
|
+
} else {
|
|
515
|
+
logger(`telegram gateway: boot-card: probes settled all-green msgId=${messageId}\n`)
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// ── Phase 2: live agent-status watch loop ─────────────────────────
|
|
519
|
+
// If the agent probe is already ok, no need to keep watching.
|
|
520
|
+
if (probes.agent?.status === 'ok' || liveWindowMs <= 0) {
|
|
521
|
+
return
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Iterate watchAgentProcess — it yields on each meaningful state
|
|
525
|
+
// change and exits when active, failed, or the window expires.
|
|
526
|
+
// Use the slug for the systemd unit target, not the display name.
|
|
527
|
+
const watcher = watchAgentProcess(opts.agentSlug ?? opts.agentName, {
|
|
528
|
+
liveWindowMs,
|
|
529
|
+
pollIntervalMs: opts.agentLivePollIntervalMs,
|
|
530
|
+
sleepImpl: opts.agentLiveSleepImpl,
|
|
531
|
+
execFileImpl: opts.agentLiveExecFileImpl,
|
|
532
|
+
tmuxSupervisor: opts.tmuxSupervisor,
|
|
533
|
+
})
|
|
534
|
+
|
|
535
|
+
for await (const agentResult of watcher) {
|
|
536
|
+
// Merge the new agent result into the probes snapshot so all
|
|
537
|
+
// probe rows are re-rendered consistently.
|
|
538
|
+
const updatedProbes: ProbeMap = { ...probes, agent: agentResult }
|
|
539
|
+
const updatedText = renderBootCard({
|
|
540
|
+
agentName: opts.agentName,
|
|
541
|
+
version: opts.version,
|
|
542
|
+
probes: updatedProbes,
|
|
543
|
+
restartReason: opts.restartReason,
|
|
544
|
+
restartAgeMs: opts.restartAgeMs,
|
|
545
|
+
...(accountRows ? { accounts: accountRows } : {}),
|
|
546
|
+
})
|
|
547
|
+
|
|
548
|
+
if (updatedText === currentText) continue
|
|
549
|
+
|
|
550
|
+
try {
|
|
551
|
+
await bot.editMessageText(chatId, messageId, updatedText, {
|
|
552
|
+
parse_mode: 'HTML',
|
|
553
|
+
link_preview_options: { is_disabled: true },
|
|
554
|
+
...(threadId != null ? { message_thread_id: threadId } : {}),
|
|
555
|
+
})
|
|
556
|
+
logger(`telegram gateway: boot-card: live agent update msgId=${messageId} state=${agentResult.status} "${agentResult.detail}"\n`)
|
|
557
|
+
currentText = updatedText
|
|
558
|
+
} catch (editErr: unknown) {
|
|
559
|
+
// Swallow edit errors — the card may have been deleted or the
|
|
560
|
+
// user dismissed it. Don't let this crash the whole loop.
|
|
561
|
+
logger(`telegram gateway: boot-card: live edit error msgId=${messageId}: ${(editErr as Error)?.message ?? String(editErr)}\n`)
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// Once agent is active (ok), we're done — no more edits needed.
|
|
565
|
+
if (agentResult.status === 'ok') break
|
|
566
|
+
}
|
|
567
|
+
} catch (err: unknown) {
|
|
568
|
+
logger(`telegram gateway: boot-card: probe-edit error msgId=${messageId}: ${(err as Error)?.message ?? String(err)}\n`)
|
|
569
|
+
}
|
|
570
|
+
})()
|
|
571
|
+
}, settleMs)
|
|
572
|
+
|
|
573
|
+
let completed = false
|
|
574
|
+
return {
|
|
575
|
+
messageId,
|
|
576
|
+
complete() {
|
|
577
|
+
if (completed) return
|
|
578
|
+
completed = true
|
|
579
|
+
logger(`telegram gateway: boot-card: completed msgId=${messageId}\n`)
|
|
580
|
+
},
|
|
581
|
+
}
|
|
582
|
+
}
|