@synapta/skills 0.1.0 → 0.1.2
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/dist/index.js +11 -4
- package/package.json +3 -4
- package/skills/ATTRIBUTION.md +80 -0
- package/skills/accessibility-audit/SKILL.md +325 -0
- package/skills/accessibility-audit/reference/wcag-checklist.md +103 -0
- package/skills/apns-notifier/SKILL.md +86 -0
- package/skills/approval-policy-enforcer/SKILL.md +66 -0
- package/skills/apps-sdk-builder/LICENSE.txt +201 -0
- package/skills/apps-sdk-builder/SKILL.md +328 -0
- package/skills/apps-sdk-builder/agents/openai.yaml +13 -0
- package/skills/apps-sdk-builder/references/app-archetypes.md +132 -0
- package/skills/apps-sdk-builder/references/apps-sdk-docs-workflow.md +135 -0
- package/skills/apps-sdk-builder/references/interactive-state-sync-patterns.md +113 -0
- package/skills/apps-sdk-builder/references/repo-contract-and-validation.md +93 -0
- package/skills/apps-sdk-builder/references/search-fetch-standard.md +67 -0
- package/skills/apps-sdk-builder/references/upstream-example-workflow.md +79 -0
- package/skills/apps-sdk-builder/references/window-openai-patterns.md +79 -0
- package/skills/apps-sdk-builder/scripts/scaffold_node_ext_apps.mjs +606 -0
- package/skills/architecture-selector/SKILL.md +64 -0
- package/skills/backlog-planner/SKILL.md +68 -0
- package/skills/carplay-entitlement-checker/SKILL.md +82 -0
- package/skills/concept-discovery/SKILL.md +517 -0
- package/skills/concept-discovery/assets/sample-analysis.json +81 -0
- package/skills/concept-discovery/expected_outputs/sample-enum-dictionary.md +25 -0
- package/skills/concept-discovery/expected_outputs/sample-page-user-list.md +83 -0
- package/skills/concept-discovery/expected_outputs/sample-prd-readme.md +43 -0
- package/skills/concept-discovery/references/framework-patterns.md +228 -0
- package/skills/concept-discovery/references/prd-quality-checklist.md +65 -0
- package/skills/concept-discovery/scripts/codebase_analyzer.py +732 -0
- package/skills/concept-discovery/scripts/prd_scaffolder.py +435 -0
- package/skills/dast-zap/SKILL.md +453 -0
- package/skills/dast-zap/assets/.gitkeep +9 -0
- package/skills/dast-zap/assets/github_action.yml +207 -0
- package/skills/dast-zap/assets/gitlab_ci.yml +226 -0
- package/skills/dast-zap/assets/zap_automation.yaml +196 -0
- package/skills/dast-zap/assets/zap_context.xml +192 -0
- package/skills/dast-zap/references/EXAMPLE.md +40 -0
- package/skills/dast-zap/references/api_testing_guide.md +475 -0
- package/skills/dast-zap/references/authentication_guide.md +431 -0
- package/skills/dast-zap/references/false_positive_handling.md +427 -0
- package/skills/dast-zap/references/owasp_mapping.md +255 -0
- package/skills/dep-sbom-scan/SKILL.md +466 -0
- package/skills/deploy-cloudflare/SKILL.md +930 -0
- package/skills/deploy-docker/SKILL.md +55 -0
- package/skills/deploy-fly/SKILL.md +228 -0
- package/skills/deploy-k8s/SKILL.md +108 -0
- package/skills/deploy-k8s/assets/logo.png +0 -0
- package/skills/deploy-k8s/docs/README.md +29 -0
- package/skills/deploy-k8s/docs/SUMMARY.md +56 -0
- package/skills/deploy-k8s/docs/advanced/token-efficiency.md +61 -0
- package/skills/deploy-k8s/docs/architecture/multi-tenancy.md +96 -0
- package/skills/deploy-k8s/docs/architecture/storage-and-state.md +102 -0
- package/skills/deploy-k8s/docs/architecture/workload-patterns.md +87 -0
- package/skills/deploy-k8s/docs/book.json +16 -0
- package/skills/deploy-k8s/docs/community/changelog.md +34 -0
- package/skills/deploy-k8s/docs/community/contributing.md +67 -0
- package/skills/deploy-k8s/docs/core-concepts/failure-modes.md +153 -0
- package/skills/deploy-k8s/docs/core-concepts/philosophy.md +83 -0
- package/skills/deploy-k8s/docs/core-concepts/workflow.md +124 -0
- package/skills/deploy-k8s/docs/examples/bad-patterns.md +47 -0
- package/skills/deploy-k8s/docs/examples/do-dont-checklist.md +37 -0
- package/skills/deploy-k8s/docs/examples/good-patterns.md +49 -0
- package/skills/deploy-k8s/docs/failure-modes/api-drift.md +104 -0
- package/skills/deploy-k8s/docs/failure-modes/fragile-rollouts.md +99 -0
- package/skills/deploy-k8s/docs/failure-modes/insecure-workload-defaults.md +80 -0
- package/skills/deploy-k8s/docs/failure-modes/network-exposure.md +98 -0
- package/skills/deploy-k8s/docs/failure-modes/privilege-sprawl.md +91 -0
- package/skills/deploy-k8s/docs/failure-modes/resource-starvation.md +85 -0
- package/skills/deploy-k8s/docs/getting-started/installation.md +152 -0
- package/skills/deploy-k8s/docs/getting-started/quick-start.md +115 -0
- package/skills/deploy-k8s/docs/guides/helm-patterns.md +71 -0
- package/skills/deploy-k8s/docs/guides/kustomize-patterns.md +65 -0
- package/skills/deploy-k8s/docs/guides/observability.md +67 -0
- package/skills/deploy-k8s/docs/guides/security-hardening.md +59 -0
- package/skills/deploy-k8s/docs/guides/validation-and-policy.md +66 -0
- package/skills/deploy-k8s/docs/integrations/mcp-integration.md +52 -0
- package/skills/deploy-k8s/docs/package-lock.json +2892 -0
- package/skills/deploy-k8s/docs/package.json +13 -0
- package/skills/deploy-k8s/references/api-drift.md +298 -0
- package/skills/deploy-k8s/references/conditional/aks-patterns.md +70 -0
- package/skills/deploy-k8s/references/conditional/eks-patterns.md +79 -0
- package/skills/deploy-k8s/references/conditional/gitops-controllers.md +71 -0
- package/skills/deploy-k8s/references/conditional/gke-patterns.md +74 -0
- package/skills/deploy-k8s/references/conditional/observability-stacks.md +80 -0
- package/skills/deploy-k8s/references/conditional/openshift-patterns.md +67 -0
- package/skills/deploy-k8s/references/daemonset-operator-patterns.md +155 -0
- package/skills/deploy-k8s/references/deployment-patterns.md +146 -0
- package/skills/deploy-k8s/references/do-dont-patterns.md +87 -0
- package/skills/deploy-k8s/references/examples-bad.md +282 -0
- package/skills/deploy-k8s/references/examples-good.md +440 -0
- package/skills/deploy-k8s/references/fragile-rollouts.md +303 -0
- package/skills/deploy-k8s/references/helm-patterns.md +203 -0
- package/skills/deploy-k8s/references/insecure-workload-defaults.md +300 -0
- package/skills/deploy-k8s/references/job-patterns.md +120 -0
- package/skills/deploy-k8s/references/kustomize-patterns.md +239 -0
- package/skills/deploy-k8s/references/multi-tenancy.md +343 -0
- package/skills/deploy-k8s/references/network-exposure.md +481 -0
- package/skills/deploy-k8s/references/observability.md +302 -0
- package/skills/deploy-k8s/references/privilege-sprawl.md +273 -0
- package/skills/deploy-k8s/references/resource-starvation.md +374 -0
- package/skills/deploy-k8s/references/security-hardening.md +209 -0
- package/skills/deploy-k8s/references/stateful-patterns.md +130 -0
- package/skills/deploy-k8s/references/storage-and-state.md +330 -0
- package/skills/deploy-k8s/references/validation-and-policy.md +242 -0
- package/skills/deploy-railway/SKILL.md +235 -0
- package/skills/deploy-railway/references/analyze-db-mongo.md +84 -0
- package/skills/deploy-railway/references/analyze-db-mysql.md +254 -0
- package/skills/deploy-railway/references/analyze-db-postgres.md +479 -0
- package/skills/deploy-railway/references/analyze-db-redis.md +208 -0
- package/skills/deploy-railway/references/analyze-db.md +344 -0
- package/skills/deploy-railway/references/configure.md +309 -0
- package/skills/deploy-railway/references/deploy.md +195 -0
- package/skills/deploy-railway/references/operate.md +214 -0
- package/skills/deploy-railway/references/request.md +248 -0
- package/skills/deploy-railway/references/setup.md +312 -0
- package/skills/deploy-railway/scripts/analyze-mongo.py +1549 -0
- package/skills/deploy-railway/scripts/analyze-mysql.py +1195 -0
- package/skills/deploy-railway/scripts/analyze-postgres.py +3058 -0
- package/skills/deploy-railway/scripts/analyze-redis.py +1090 -0
- package/skills/deploy-railway/scripts/dal.py +671 -0
- package/skills/deploy-railway/scripts/enable-pg-stats.py +170 -0
- package/skills/deploy-railway/scripts/pg-extensions.py +370 -0
- package/skills/deploy-railway/scripts/railway-api.sh +52 -0
- package/skills/deploy-ssh/SKILL.md +91 -0
- package/skills/deploy-vercel/SKILL.md +304 -0
- package/skills/deploy-vercel/resources/deploy-codex.sh +301 -0
- package/skills/deploy-vercel/resources/deploy.sh +301 -0
- package/skills/docs-runbooks/SKILL.md +399 -0
- package/skills/drive-status-renderer/SKILL.md +62 -0
- package/skills/iac-scan/SKILL.md +680 -0
- package/skills/iac-scan/assets/.gitkeep +9 -0
- package/skills/iac-scan/assets/checkov_config.yaml +94 -0
- package/skills/iac-scan/assets/github_actions.yml +199 -0
- package/skills/iac-scan/assets/gitlab_ci.yml +218 -0
- package/skills/iac-scan/assets/pre_commit_config.yaml +92 -0
- package/skills/iac-scan/references/EXAMPLE.md +40 -0
- package/skills/iac-scan/references/compliance_mapping.md +237 -0
- package/skills/iac-scan/references/custom_policies.md +460 -0
- package/skills/iac-scan/references/suppression_guide.md +431 -0
- package/skills/incident-briefing/SKILL.md +66 -0
- package/skills/incident-triage/SKILL.md +481 -0
- package/{LICENSE → skills/mcp-builder/LICENSE.txt} +15 -14
- package/skills/mcp-builder/SKILL.md +244 -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/mobile-pairing/SKILL.md +52 -0
- package/skills/ops-sre/SKILL.md +297 -0
- package/skills/playwright-qa/LICENSE.txt +201 -0
- package/skills/playwright-qa/NOTICE.txt +14 -0
- package/skills/playwright-qa/SKILL.md +156 -0
- package/skills/playwright-qa/agents/openai.yaml +6 -0
- package/skills/playwright-qa/assets/playwright-small.svg +3 -0
- package/skills/playwright-qa/assets/playwright.png +0 -0
- package/skills/playwright-qa/references/cli.md +116 -0
- package/skills/playwright-qa/references/workflows.md +95 -0
- package/skills/playwright-qa/scripts/playwright_cli.sh +25 -0
- package/skills/release-publish/SKILL.md +85 -0
- package/skills/repo-bootstrap/SKILL.md +92 -0
- package/skills/repo-bootstrap/assets/example-workflows/validate-agents.yml +89 -0
- package/skills/repo-bootstrap/assets/root-thin.md +141 -0
- package/skills/repo-bootstrap/assets/root-verbose.md +149 -0
- package/skills/repo-bootstrap/assets/scoped/backend-go.md +107 -0
- package/skills/repo-bootstrap/assets/scoped/backend-php.md +94 -0
- package/skills/repo-bootstrap/assets/scoped/backend-python.md +84 -0
- package/skills/repo-bootstrap/assets/scoped/backend-typescript.md +89 -0
- package/skills/repo-bootstrap/assets/scoped/claude-code-skill.md +101 -0
- package/skills/repo-bootstrap/assets/scoped/cli.md +83 -0
- package/skills/repo-bootstrap/assets/scoped/concourse.md +196 -0
- package/skills/repo-bootstrap/assets/scoped/ddev.md +68 -0
- package/skills/repo-bootstrap/assets/scoped/docker.md +160 -0
- package/skills/repo-bootstrap/assets/scoped/documentation.md +98 -0
- package/skills/repo-bootstrap/assets/scoped/examples.md +96 -0
- package/skills/repo-bootstrap/assets/scoped/frontend-typescript.md +88 -0
- package/skills/repo-bootstrap/assets/scoped/github-actions.md +174 -0
- package/skills/repo-bootstrap/assets/scoped/gitlab-ci.md +174 -0
- package/skills/repo-bootstrap/assets/scoped/oro-bundle.md +209 -0
- package/skills/repo-bootstrap/assets/scoped/oro-project.md +170 -0
- package/skills/repo-bootstrap/assets/scoped/python-modern.md +170 -0
- package/skills/repo-bootstrap/assets/scoped/resources.md +96 -0
- package/skills/repo-bootstrap/assets/scoped/skill-repo.md +139 -0
- package/skills/repo-bootstrap/assets/scoped/symfony.md +168 -0
- package/skills/repo-bootstrap/assets/scoped/testing.md +87 -0
- package/skills/repo-bootstrap/assets/scoped/typo3-docs.md +103 -0
- package/skills/repo-bootstrap/assets/scoped/typo3-extension.md +133 -0
- package/skills/repo-bootstrap/assets/scoped/typo3-project.md +137 -0
- package/skills/repo-bootstrap/assets/scoped/typo3-testing.md +80 -0
- package/skills/repo-bootstrap/checkpoints.yaml +279 -0
- package/skills/repo-bootstrap/evals/evals.json +385 -0
- package/skills/repo-bootstrap/references/ai-contribution-guidelines.md +63 -0
- package/skills/repo-bootstrap/references/ai-tool-compatibility.md +223 -0
- package/skills/repo-bootstrap/references/directory-coverage.md +82 -0
- package/skills/repo-bootstrap/references/examples/coding-agent-cli/AGENTS.md +70 -0
- package/skills/repo-bootstrap/references/examples/coding-agent-cli/go.mod +3 -0
- package/skills/repo-bootstrap/references/examples/coding-agent-cli/scripts-AGENTS.md +389 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/.env.example +13 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/AGENTS.md +91 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/package.json +33 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/pnpm-lock.yaml +3 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/src/AGENTS.md +91 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/src/config.ts +28 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/src/controllers/userController.ts +74 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/src/index.ts +26 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/src/middleware/errorHandler.ts +45 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/src/middleware/requestLogger.ts +18 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/src/routes/health.ts +18 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/src/routes/users.ts +13 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/src/utils/errors.ts +40 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/src/utils/logger.ts +14 -0
- package/skills/repo-bootstrap/references/examples/express-api-ts/tsconfig.json +24 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/.env.example +19 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/AGENTS.md +92 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/pyproject.toml +88 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/AGENTS.md +85 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/__init__.py +3 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/config.py +49 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/main.py +66 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/models/__init__.py +13 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/models/item.py +43 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/models/user.py +40 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/routes/__init__.py +5 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/routes/health.py +20 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/routes/items.py +61 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/routes/users.py +55 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/services/__init__.py +6 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/services/item_service.py +77 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/src/services/user_service.py +69 -0
- package/skills/repo-bootstrap/references/examples/fastapi-app/uv.lock +4 -0
- package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/.scopes +3 -0
- package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/AGENTS.md +86 -0
- package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/admin/package.json +20 -0
- package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/admin/src/App.tsx +5 -0
- package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/cmd/api/main.go +7 -0
- package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/go.mod +2 -0
- package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/main.go +7 -0
- package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/.scopes +3 -0
- package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/AGENTS.md +89 -0
- package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/go.mod +2 -0
- package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/AGENTS.md +90 -0
- package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/package.json +17 -0
- package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/src/App.tsx +1 -0
- package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/src/Button.tsx +1 -0
- package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/src/Footer.tsx +1 -0
- package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/src/Header.tsx +1 -0
- package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/src/Sidebar.tsx +1 -0
- package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/main.go +7 -0
- package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/package-lock.json +0 -0
- package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/package.json +12 -0
- package/skills/repo-bootstrap/references/examples/ldap-selfservice/AGENTS.md +70 -0
- package/skills/repo-bootstrap/references/examples/ldap-selfservice/go.mod +3 -0
- package/skills/repo-bootstrap/references/examples/ldap-selfservice/internal-AGENTS.md +371 -0
- package/skills/repo-bootstrap/references/examples/ldap-selfservice/internal-web-AGENTS.md +448 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/.scopes +3 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/AGENTS.md +91 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/composer.json +8 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/package.json +15 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/pnpm-lock.yaml +0 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/src/Controller.php +3 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/web/AGENTS.md +92 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/web/package.json +26 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/web/src/App.tsx +3 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/web/src/Button.tsx +10 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/web/src/Footer.tsx +9 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/web/src/Header.tsx +9 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/web/src/main.tsx +3 -0
- package/skills/repo-bootstrap/references/examples/php-with-frontend/web/tsconfig.json +13 -0
- package/skills/repo-bootstrap/references/examples/pnpm-workspace/AGENTS.md +75 -0
- package/skills/repo-bootstrap/references/examples/pnpm-workspace/package.json +7 -0
- package/skills/repo-bootstrap/references/examples/pnpm-workspace/packages/web/package.json +11 -0
- package/skills/repo-bootstrap/references/examples/pnpm-workspace/packages/web/src/index.ts +11 -0
- package/skills/repo-bootstrap/references/examples/pnpm-workspace/pnpm-lock.yaml +42 -0
- package/skills/repo-bootstrap/references/examples/pnpm-workspace/pnpm-workspace.yaml +2 -0
- package/skills/repo-bootstrap/references/examples/simple-ldap-go/AGENTS.md +70 -0
- package/skills/repo-bootstrap/references/examples/simple-ldap-go/examples-AGENTS.md +45 -0
- package/skills/repo-bootstrap/references/examples/simple-ldap-go/go.mod +3 -0
- package/skills/repo-bootstrap/references/examples/t3x-rte-ckeditor-image/AGENTS.md +70 -0
- package/skills/repo-bootstrap/references/examples/t3x-rte-ckeditor-image/Classes-AGENTS.md +392 -0
- package/skills/repo-bootstrap/references/examples/t3x-rte-ckeditor-image/composer.json +8 -0
- package/skills/repo-bootstrap/references/feedback-memory-schema.md +135 -0
- package/skills/repo-bootstrap/references/git-hooks-setup.md +79 -0
- package/skills/repo-bootstrap/references/output-structure.md +124 -0
- package/skills/repo-bootstrap/references/scripts-guide.md +175 -0
- package/skills/repo-bootstrap/references/verification-guide.md +137 -0
- package/skills/repo-bootstrap/scripts/analyze-git-history.sh +315 -0
- package/skills/repo-bootstrap/scripts/check-freshness.sh +230 -0
- package/skills/repo-bootstrap/scripts/detect-golden-samples.sh +161 -0
- package/skills/repo-bootstrap/scripts/detect-heuristics.sh +93 -0
- package/skills/repo-bootstrap/scripts/detect-project.sh +486 -0
- package/skills/repo-bootstrap/scripts/detect-scopes.sh +330 -0
- package/skills/repo-bootstrap/scripts/detect-utilities.sh +133 -0
- package/skills/repo-bootstrap/scripts/extract-adrs.sh +194 -0
- package/skills/repo-bootstrap/scripts/extract-agent-configs.sh +331 -0
- package/skills/repo-bootstrap/scripts/extract-architecture-rules.sh +522 -0
- package/skills/repo-bootstrap/scripts/extract-ci-commands.sh +385 -0
- package/skills/repo-bootstrap/scripts/extract-ci-rules.sh +384 -0
- package/skills/repo-bootstrap/scripts/extract-commands.sh +358 -0
- package/skills/repo-bootstrap/scripts/extract-documentation.sh +308 -0
- package/skills/repo-bootstrap/scripts/extract-github-rulesets.sh +96 -0
- package/skills/repo-bootstrap/scripts/extract-github-settings.sh +88 -0
- package/skills/repo-bootstrap/scripts/extract-ide-settings.sh +228 -0
- package/skills/repo-bootstrap/scripts/extract-platform-files.sh +290 -0
- package/skills/repo-bootstrap/scripts/extract-quality-configs.sh +442 -0
- package/skills/repo-bootstrap/scripts/generate-agents.sh +2424 -0
- package/skills/repo-bootstrap/scripts/generate-file-map.sh +153 -0
- package/skills/repo-bootstrap/scripts/lib/config-root.sh +211 -0
- package/skills/repo-bootstrap/scripts/lib/summary.sh +244 -0
- package/skills/repo-bootstrap/scripts/lib/template.sh +397 -0
- package/skills/repo-bootstrap/scripts/validate-structure.sh +324 -0
- package/skills/repo-bootstrap/scripts/verify-commands.sh +615 -0
- package/skills/repo-bootstrap/scripts/verify-content.sh +302 -0
- package/skills/schema-api-contracts/SKILL.md +56 -0
- package/skills/secret-hygiene/SKILL.md +511 -0
- package/skills/secret-hygiene/assets/.gitkeep +9 -0
- package/skills/secret-hygiene/assets/config-balanced.toml +81 -0
- package/skills/secret-hygiene/assets/config-custom.toml +178 -0
- package/skills/secret-hygiene/assets/config-strict.toml +48 -0
- package/skills/secret-hygiene/assets/github-action.yml +181 -0
- package/skills/secret-hygiene/assets/gitlab-ci.yml +257 -0
- package/skills/secret-hygiene/assets/precommit-config.yaml +70 -0
- package/skills/secret-hygiene/references/EXAMPLE.md +40 -0
- package/skills/secret-hygiene/references/compliance_mapping.md +538 -0
- package/skills/secret-hygiene/references/detection_rules.md +276 -0
- package/skills/secret-hygiene/references/false_positives.md +598 -0
- package/skills/secret-hygiene/references/remediation_guide.md +530 -0
- package/skills/stack-selector/SKILL.md +56 -0
- package/skills/telegram-control/SKILL.md +110 -0
- package/skills/telegram-control/references/architecture.md +184 -0
- package/skills/telegram-control/references/convex.md +173 -0
- package/skills/telegram-control/references/error_handling.md +212 -0
- package/skills/telegram-control/references/initial_setup.md +165 -0
- package/skills/telegram-control/references/telegram_api.md +156 -0
- package/skills/telegram-control/scripts/cancel_message.ts +53 -0
- package/skills/telegram-control/scripts/list_scheduled.ts +103 -0
- package/skills/telegram-control/scripts/logger.ts +121 -0
- package/skills/telegram-control/scripts/proxy-util.ts +11 -0
- package/skills/telegram-control/scripts/schedule_message.ts +216 -0
- package/skills/telegram-control/scripts/send_message.ts +115 -0
- package/skills/telegram-control/scripts/setup.ts +185 -0
- package/skills/telegram-control/scripts/types.ts +75 -0
- package/skills/telegram-control/scripts/view_history.ts +74 -0
- package/skills/test-strategy/SKILL.md +352 -0
- package/skills/threat-model/SKILL.md +303 -0
- package/skills/threat-model/examples/example-output.md +196 -0
- package/skills/threat-model/template.md +96 -0
- package/skills/ts-lint/SKILL.md +80 -0
- package/skills/ui-flow/SKILL.md +668 -0
- package/skills/voice-command-router/SKILL.md +51 -0
- package/skills/widget-live-activity-sync/SKILL.md +66 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
|
|
3
|
+
import { ConvexHttpClient } from 'convex/browser';
|
|
4
|
+
import { readFileSync, existsSync } from 'fs';
|
|
5
|
+
import { api } from '../convex/_generated/api.js';
|
|
6
|
+
import * as chrono from 'chrono-node';
|
|
7
|
+
import { Config, CONFIG_PATH, ParsedTime, getConvexUrl } from './types.js';
|
|
8
|
+
import { setupProxy } from './proxy-util.js';
|
|
9
|
+
import {
|
|
10
|
+
logError,
|
|
11
|
+
logSuccess,
|
|
12
|
+
logInfo,
|
|
13
|
+
logDetail,
|
|
14
|
+
logUsage,
|
|
15
|
+
logNotConfigured,
|
|
16
|
+
} from './logger.js';
|
|
17
|
+
|
|
18
|
+
// Blob is available globally in Node.js 18+
|
|
19
|
+
declare const Blob: typeof globalThis extends { Blob: infer B } ? B : any;
|
|
20
|
+
|
|
21
|
+
setupProxy();
|
|
22
|
+
|
|
23
|
+
async function scheduleMessage(): Promise<void> {
|
|
24
|
+
const args = process.argv.slice(2);
|
|
25
|
+
|
|
26
|
+
if (args.length < 2) {
|
|
27
|
+
logUsage(
|
|
28
|
+
'Usage: tsx schedule_message.ts <time_expression> <title> [message_text] [file_path]',
|
|
29
|
+
[
|
|
30
|
+
'tsx schedule_message.ts "tomorrow 10am" "Meeting" "Team standup"',
|
|
31
|
+
'tsx schedule_message.ts "in 5 minutes" "Quick reminder" "Check email"',
|
|
32
|
+
'tsx schedule_message.ts "next Monday 9am" "Report" "Weekly report" /path/to/file.pdf',
|
|
33
|
+
'tsx schedule_message.ts "every day at 9am" "Daily" "Good morning!"',
|
|
34
|
+
'tsx schedule_message.ts "every 2 hours" "Hydration" "Drink water!"',
|
|
35
|
+
]
|
|
36
|
+
);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const [timeExpression, title, messageText, filePath] = args;
|
|
41
|
+
|
|
42
|
+
// Load config
|
|
43
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
44
|
+
logNotConfigured();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const config: Config = JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'));
|
|
48
|
+
|
|
49
|
+
// Parse time
|
|
50
|
+
const { scheduledTime, recurring } = parseTime(timeExpression);
|
|
51
|
+
|
|
52
|
+
logInfo('📅', 'Scheduling message...');
|
|
53
|
+
logDetail(`Title: ${title}`);
|
|
54
|
+
logDetail(`Time: ${new Date(scheduledTime).toLocaleString()}`);
|
|
55
|
+
if (recurring) {
|
|
56
|
+
logDetail(`Recurring: ${recurring}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Get Convex URL
|
|
60
|
+
const deploymentUrl = getConvexUrl(config.deployKey);
|
|
61
|
+
const client = new ConvexHttpClient(deploymentUrl);
|
|
62
|
+
|
|
63
|
+
// Verify file exists if provided
|
|
64
|
+
if (filePath && !existsSync(filePath)) {
|
|
65
|
+
logError(`File not found: ${filePath}`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
// Build args, only including optional fields if they have values
|
|
71
|
+
const scheduleArgs: any = {
|
|
72
|
+
title,
|
|
73
|
+
message_text: messageText,
|
|
74
|
+
scheduled_time: scheduledTime,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Only add recurring if it exists
|
|
78
|
+
if (recurring) {
|
|
79
|
+
scheduleArgs.recurring = recurring;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Handle file upload if provided
|
|
83
|
+
if (filePath) {
|
|
84
|
+
logInfo('📁', 'Uploading file to Convex Storage...');
|
|
85
|
+
|
|
86
|
+
// Get upload URL from Convex
|
|
87
|
+
const uploadUrl = await client.mutation(api.messages.generateUploadUrl);
|
|
88
|
+
|
|
89
|
+
// Read file
|
|
90
|
+
const fileBuffer = readFileSync(filePath);
|
|
91
|
+
const fileName = filePath.split('/').pop() || 'file';
|
|
92
|
+
|
|
93
|
+
// Convert buffer to Blob for fetch compatibility
|
|
94
|
+
const fileBlob = new Blob([fileBuffer], { type: 'application/octet-stream' });
|
|
95
|
+
|
|
96
|
+
// Upload file to Convex Storage (proxy is set globally via setGlobalDispatcher)
|
|
97
|
+
const uploadResponse = await fetch(uploadUrl, {
|
|
98
|
+
method: 'POST',
|
|
99
|
+
headers: { 'Content-Type': 'application/octet-stream' },
|
|
100
|
+
body: fileBlob,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (!uploadResponse.ok) {
|
|
104
|
+
throw new Error(`Upload failed: ${uploadResponse.statusText}`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const { storageId } = (await uploadResponse.json()) as {
|
|
108
|
+
storageId: string;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
scheduleArgs.storage_id = storageId;
|
|
112
|
+
scheduleArgs.file_name = fileName;
|
|
113
|
+
|
|
114
|
+
logDetail(`✓ File uploaded: ${fileName}`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const messageId = await client.mutation(
|
|
118
|
+
api.messages.scheduleMessage,
|
|
119
|
+
scheduleArgs
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
logSuccess('Message scheduled successfully!');
|
|
123
|
+
logDetail(`ID: ${messageId}`);
|
|
124
|
+
if (filePath) {
|
|
125
|
+
logDetail(
|
|
126
|
+
`→ File will be sent and deleted from storage when message is delivered`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
} catch (error: any) {
|
|
130
|
+
logError(`Failed to schedule: ${error.message}`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function parseTime(expression: string): ParsedTime {
|
|
136
|
+
const lowerExpr = expression.toLowerCase();
|
|
137
|
+
|
|
138
|
+
// Check for recurring patterns
|
|
139
|
+
const recurringPatterns = [
|
|
140
|
+
{ pattern: /every (\d+) minutes?/, type: 'interval' as const },
|
|
141
|
+
{ pattern: /every (\d+) hours?/, type: 'interval' as const },
|
|
142
|
+
{
|
|
143
|
+
pattern: /every day at (\d+(?::\d+)?(?:am|pm)?)/i,
|
|
144
|
+
type: 'daily' as const,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
pattern:
|
|
148
|
+
/every (monday|tuesday|wednesday|thursday|friday|saturday|sunday) at (\d+(?::\d+)?(?:am|pm)?)/i,
|
|
149
|
+
type: 'weekly' as const,
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
pattern: /every (weekday|weekend) at (\d+(?::\d+)?(?:am|pm)?)/i,
|
|
153
|
+
type: 'weekday' as const,
|
|
154
|
+
},
|
|
155
|
+
];
|
|
156
|
+
|
|
157
|
+
for (const { pattern, type } of recurringPatterns) {
|
|
158
|
+
const match = lowerExpr.match(pattern);
|
|
159
|
+
if (match) {
|
|
160
|
+
return parseRecurring(expression, type, match);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Parse one-time scheduled time
|
|
165
|
+
const parsedDate = chrono.parseDate(expression, new Date(), {
|
|
166
|
+
forwardDate: true,
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
if (!parsedDate) {
|
|
170
|
+
throw new Error(`Could not parse time expression: ${expression}`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
scheduledTime: parsedDate.getTime(),
|
|
175
|
+
recurring: undefined,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function parseRecurring(
|
|
180
|
+
expression: string,
|
|
181
|
+
type: 'interval' | 'daily' | 'weekly' | 'weekday',
|
|
182
|
+
match: RegExpMatchArray
|
|
183
|
+
): ParsedTime {
|
|
184
|
+
const now = Date.now();
|
|
185
|
+
|
|
186
|
+
if (type === 'interval') {
|
|
187
|
+
const amount = parseInt(match[1]);
|
|
188
|
+
const unit = expression.includes('hour') ? 'hours' : 'minutes';
|
|
189
|
+
const ms = unit === 'hours' ? amount * 60 * 60 * 1000 : amount * 60 * 1000;
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
scheduledTime: now + ms,
|
|
193
|
+
recurring: `every ${amount} ${unit}`,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// For daily, weekly, weekday patterns - use chrono to parse the time part
|
|
198
|
+
const timeStr = match[match.length - 1];
|
|
199
|
+
const parsedDate = chrono.parseDate(timeStr, new Date(), {
|
|
200
|
+
forwardDate: true,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
if (!parsedDate) {
|
|
204
|
+
throw new Error(`Could not parse time: ${timeStr}`);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
scheduledTime: parsedDate.getTime(),
|
|
209
|
+
recurring: expression,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
scheduleMessage().catch((error: Error) => {
|
|
214
|
+
logError(error.message);
|
|
215
|
+
process.exit(1);
|
|
216
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
|
|
3
|
+
import { ConvexHttpClient } from 'convex/browser';
|
|
4
|
+
import { readFileSync, existsSync } from 'fs';
|
|
5
|
+
import { api } from '../convex/_generated/api.js';
|
|
6
|
+
import { Config, CONFIG_PATH, getConvexUrl } from './types.js';
|
|
7
|
+
import { setupProxy } from './proxy-util.js';
|
|
8
|
+
import {
|
|
9
|
+
logError,
|
|
10
|
+
logSuccess,
|
|
11
|
+
logInfo,
|
|
12
|
+
logDetail,
|
|
13
|
+
logUsage,
|
|
14
|
+
logNotConfigured,
|
|
15
|
+
} from './logger.js';
|
|
16
|
+
|
|
17
|
+
setupProxy();
|
|
18
|
+
|
|
19
|
+
async function sendMessage(): Promise<void> {
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
|
|
22
|
+
if (args.length < 1) {
|
|
23
|
+
logUsage('Usage: tsx send_message.ts <message_text> [file_path]', [
|
|
24
|
+
'tsx send_message.ts "Hello from Claude!"',
|
|
25
|
+
'tsx send_message.ts "Meeting notes" /home/claude/notes.md',
|
|
26
|
+
'tsx send_message.ts "Report" /home/claude/report.pdf',
|
|
27
|
+
]);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const [messageText, filePath] = args;
|
|
32
|
+
|
|
33
|
+
// Load config
|
|
34
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
35
|
+
logNotConfigured();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const config: Config = JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'));
|
|
39
|
+
|
|
40
|
+
// Get Convex URL from deployment
|
|
41
|
+
logInfo('📡', 'Connecting to Convex...');
|
|
42
|
+
const deploymentUrl = getConvexUrl(config.deployKey);
|
|
43
|
+
|
|
44
|
+
const client = new ConvexHttpClient(deploymentUrl);
|
|
45
|
+
|
|
46
|
+
// Verify file exists if provided
|
|
47
|
+
if (filePath && !existsSync(filePath)) {
|
|
48
|
+
logError(`File not found: ${filePath}`);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
logInfo('📤', 'Sending message...');
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
// Build args
|
|
56
|
+
const sendArgs: any = {
|
|
57
|
+
message_text: messageText,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
if (filePath) {
|
|
61
|
+
logInfo('📁', 'Uploading file to Convex Storage...');
|
|
62
|
+
|
|
63
|
+
// Get upload URL from Convex
|
|
64
|
+
const uploadUrl = await client.mutation(api.messages.generateUploadUrl);
|
|
65
|
+
|
|
66
|
+
// Read file
|
|
67
|
+
const fileBuffer = readFileSync(filePath);
|
|
68
|
+
const fileName = filePath.split('/').pop() || 'file';
|
|
69
|
+
|
|
70
|
+
// Convert buffer to Blob for fetch compatibility
|
|
71
|
+
const fileBlob = new Blob([fileBuffer], {
|
|
72
|
+
type: 'application/octet-stream',
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Upload file to Convex Storage (proxy is set globally via setGlobalDispatcher)
|
|
76
|
+
const uploadResponse = await fetch(uploadUrl, {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
headers: { 'Content-Type': 'application/octet-stream' },
|
|
79
|
+
body: fileBlob,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
if (!uploadResponse.ok) {
|
|
83
|
+
throw new Error(`Upload failed: ${uploadResponse.statusText}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const { storageId } = (await uploadResponse.json()) as {
|
|
87
|
+
storageId: string;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
sendArgs.storage_id = storageId;
|
|
91
|
+
sendArgs.file_name = fileName;
|
|
92
|
+
|
|
93
|
+
logDetail(`✓ File uploaded: ${fileName}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
await client.action(api.telegram.sendMessage, sendArgs);
|
|
97
|
+
|
|
98
|
+
logSuccess('Message sent successfully!');
|
|
99
|
+
if (filePath) {
|
|
100
|
+
logDetail(`→ Text: ${messageText}`);
|
|
101
|
+
logDetail(`→ File: ${filePath.split('/').pop()}`);
|
|
102
|
+
logDetail(
|
|
103
|
+
`→ File will be automatically deleted from storage after sending`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
} catch (error: any) {
|
|
107
|
+
logError(`Failed to send: ${error.message}`);
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
sendMessage().catch((error: Error) => {
|
|
113
|
+
logError(error.message);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
});
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
|
|
3
|
+
import { writeFileSync } from 'fs';
|
|
4
|
+
import { execSync } from 'child_process';
|
|
5
|
+
import { Config, CONFIG_PATH, BotInfo } from './types.js';
|
|
6
|
+
import { logError, logSuccess, logInfo, logDetail, log } from './logger.js';
|
|
7
|
+
import { setupProxy } from './proxy-util.js';
|
|
8
|
+
|
|
9
|
+
setupProxy();
|
|
10
|
+
|
|
11
|
+
async function setup(): Promise<void> {
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
|
|
14
|
+
if (args.length < 3) {
|
|
15
|
+
console.error(
|
|
16
|
+
'Usage: tsx setup.ts <bot_token> <user_id> <convex_deploy_key>'
|
|
17
|
+
);
|
|
18
|
+
console.error('');
|
|
19
|
+
console.error('Steps to get credentials:');
|
|
20
|
+
console.error('1. Bot Token: Message @BotFather on Telegram, create a bot');
|
|
21
|
+
console.error('2. User ID: Message @userinfobot on Telegram');
|
|
22
|
+
console.error(
|
|
23
|
+
'3. Deploy Key: Get from Convex dashboard (Settings > Deploy Keys)'
|
|
24
|
+
);
|
|
25
|
+
logDetail('- Login at https://dashboard.convex.dev', ' ');
|
|
26
|
+
logDetail('- Create a new project', ' ');
|
|
27
|
+
logDetail('- Go to Settings > Deploy Keys', ' ');
|
|
28
|
+
logDetail("- Create a 'Production' deploy key", ' ');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const [botToken, userId, deployKey] = args;
|
|
33
|
+
|
|
34
|
+
logInfo('🔧', 'Setting up Telegram Reminders with Convex...\n');
|
|
35
|
+
|
|
36
|
+
// Step 1: Verify Telegram credentials (skip in sandboxed environments)
|
|
37
|
+
logInfo('1️⃣', 'Verifying Telegram bot...');
|
|
38
|
+
try {
|
|
39
|
+
const botInfo = await verifyTelegramBot(botToken);
|
|
40
|
+
logDetail(`✓ Bot verified: @${botInfo.username}`);
|
|
41
|
+
} catch (error: any) {
|
|
42
|
+
console.warn(
|
|
43
|
+
` ⚠ Could not verify bot (fetch may be unavailable): ${error.message}`
|
|
44
|
+
);
|
|
45
|
+
logDetail('→ Proceeding with setup anyway...');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Step 2: Save configuration FIRST (so other tools can work)
|
|
49
|
+
logInfo('\n2️⃣', 'Saving configuration...');
|
|
50
|
+
const config: Config = {
|
|
51
|
+
botToken,
|
|
52
|
+
userId,
|
|
53
|
+
deployKey,
|
|
54
|
+
setupDate: new Date().toISOString(),
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
58
|
+
logDetail(`✓ Config saved to ${CONFIG_PATH}`);
|
|
59
|
+
|
|
60
|
+
// Step 3: Install dependencies
|
|
61
|
+
logInfo('\n3️⃣', 'Installing dependencies...');
|
|
62
|
+
try {
|
|
63
|
+
execSync('npm install', { stdio: 'inherit' });
|
|
64
|
+
logDetail('✓ Dependencies installed');
|
|
65
|
+
} catch (error) {
|
|
66
|
+
logDetail('✗ Failed to install dependencies');
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Step 4: Deploy to Convex
|
|
71
|
+
logInfo('\n4️⃣', 'Deploying to Convex...');
|
|
72
|
+
try {
|
|
73
|
+
// Set deploy key as environment variable
|
|
74
|
+
process.env.CONVEX_DEPLOY_KEY = deployKey;
|
|
75
|
+
|
|
76
|
+
// Create .env.local for local development
|
|
77
|
+
writeFileSync('.env.local', `CONVEX_DEPLOY_KEY=${deployKey}\n`);
|
|
78
|
+
|
|
79
|
+
// Deploy
|
|
80
|
+
execSync('npx convex deploy', { stdio: 'inherit' });
|
|
81
|
+
logDetail('✓ Deployed to Convex');
|
|
82
|
+
|
|
83
|
+
// Set environment variables in Convex
|
|
84
|
+
logInfo('\n5️⃣', 'Setting Telegram credentials in Convex...');
|
|
85
|
+
execSync(`npx convex env set TELEGRAM_BOT_TOKEN "${botToken}"`, {
|
|
86
|
+
stdio: 'inherit',
|
|
87
|
+
});
|
|
88
|
+
execSync(`npx convex env set TELEGRAM_USER_ID "${userId}"`, {
|
|
89
|
+
stdio: 'inherit',
|
|
90
|
+
});
|
|
91
|
+
logDetail('✓ Environment variables set');
|
|
92
|
+
} catch (error) {
|
|
93
|
+
logDetail('✗ Deployment failed');
|
|
94
|
+
logDetail('→ Make sure your deploy key is valid');
|
|
95
|
+
logDetail('→ Check https://dashboard.convex.dev for errors');
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Step 6: Test sending a message via Convex
|
|
100
|
+
logInfo('\n6️⃣', 'Testing message send...');
|
|
101
|
+
try {
|
|
102
|
+
await sendTestMessageViaConvex(deployKey);
|
|
103
|
+
logDetail('✓ Test message sent successfully!');
|
|
104
|
+
logDetail('→ Check your Telegram for the test message');
|
|
105
|
+
logDetail(
|
|
106
|
+
"→ If you don't see it, make sure you've started a chat with your bot"
|
|
107
|
+
);
|
|
108
|
+
} catch (error: any) {
|
|
109
|
+
console.warn(` ⚠ Could not send test message: ${error.message}`);
|
|
110
|
+
logDetail(
|
|
111
|
+
'→ You can test manually with: npx convex run telegram:sendMessage \'{"message_text":"Test"}\''
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
logSuccess('\nSetup complete!');
|
|
116
|
+
log('\nYour Telegram reminder system is now running 24/7 in Convex Cloud!');
|
|
117
|
+
log("\n⚠️ IMPORTANT: Make sure you've started a chat with your bot!");
|
|
118
|
+
logDetail('→ Search for your bot on Telegram');
|
|
119
|
+
logDetail("→ Press 'Start' to enable messages");
|
|
120
|
+
log(
|
|
121
|
+
'\nTo send messages (use Convex CLI instead of npm scripts in sandboxed environments):'
|
|
122
|
+
);
|
|
123
|
+
log(
|
|
124
|
+
' • Send: npx convex run telegram:sendMessage \'{"message_text":"Your message"}\''
|
|
125
|
+
);
|
|
126
|
+
log(
|
|
127
|
+
' • Schedule: npx convex run messages:schedule \'{"scheduled_time":1234567890,"title":"Title","message":"Text"}\''
|
|
128
|
+
);
|
|
129
|
+
log('\nMonitor your deployment:');
|
|
130
|
+
log(' → https://dashboard.convex.dev');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
interface TelegramResponse<T = unknown> {
|
|
134
|
+
ok: boolean;
|
|
135
|
+
description?: string;
|
|
136
|
+
result?: T;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function verifyTelegramBot(botToken: string): Promise<BotInfo> {
|
|
140
|
+
const url = `https://api.telegram.org/bot${botToken}/getMe`;
|
|
141
|
+
const response = await fetch(url);
|
|
142
|
+
const result = (await response.json()) as TelegramResponse<BotInfo>;
|
|
143
|
+
|
|
144
|
+
if (!result.ok) {
|
|
145
|
+
throw new Error(result.description || 'Invalid bot token');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return result.result!;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function sendTestMessage(
|
|
152
|
+
botToken: string,
|
|
153
|
+
userId: string
|
|
154
|
+
): Promise<void> {
|
|
155
|
+
const url = `https://api.telegram.org/bot${botToken}/sendMessage`;
|
|
156
|
+
const response = await fetch(url, {
|
|
157
|
+
method: 'POST',
|
|
158
|
+
headers: { 'Content-Type': 'application/json' },
|
|
159
|
+
body: JSON.stringify({
|
|
160
|
+
chat_id: userId,
|
|
161
|
+
text: '✅ Telegram Reminders setup successful! Your bot is ready to send messages.',
|
|
162
|
+
}),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const result = (await response.json()) as TelegramResponse;
|
|
166
|
+
if (!result.ok) {
|
|
167
|
+
throw new Error(result.description || 'Failed to send test message');
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async function sendTestMessageViaConvex(deployKey: string): Promise<void> {
|
|
172
|
+
try {
|
|
173
|
+
execSync(
|
|
174
|
+
`npx convex run telegram:sendMessage '{"message_text":"✅ Telegram Reminders setup successful! Your bot is ready to send messages."}'`,
|
|
175
|
+
{ stdio: 'inherit' }
|
|
176
|
+
);
|
|
177
|
+
} catch (error: any) {
|
|
178
|
+
throw new Error('Convex test message failed');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
setup().catch((error: Error) => {
|
|
183
|
+
logError(`\nSetup failed: ${error.message}`);
|
|
184
|
+
process.exit(1);
|
|
185
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Id } from "../convex/_generated/dataModel.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration stored in /mnt/user-data/outputs/telegram_config.json
|
|
5
|
+
*/
|
|
6
|
+
export interface Config {
|
|
7
|
+
botToken: string;
|
|
8
|
+
userId: string;
|
|
9
|
+
deployKey: string;
|
|
10
|
+
setupDate: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Scheduled message record from database
|
|
15
|
+
*/
|
|
16
|
+
export interface ScheduledMessage {
|
|
17
|
+
_id: Id<"scheduled_messages">;
|
|
18
|
+
title: string;
|
|
19
|
+
message_text?: string;
|
|
20
|
+
storage_id?: Id<"_storage">;
|
|
21
|
+
file_name?: string;
|
|
22
|
+
scheduled_time: number;
|
|
23
|
+
recurring?: string;
|
|
24
|
+
status: string;
|
|
25
|
+
created_at: number;
|
|
26
|
+
last_sent_at?: number;
|
|
27
|
+
error_message?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Message history record from database
|
|
32
|
+
*/
|
|
33
|
+
export interface MessageHistory {
|
|
34
|
+
_id: Id<"message_history">;
|
|
35
|
+
title: string;
|
|
36
|
+
message_text?: string;
|
|
37
|
+
sent_at: number;
|
|
38
|
+
status: string;
|
|
39
|
+
error_message?: string;
|
|
40
|
+
scheduled_message_id?: Id<"scheduled_messages">;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Telegram bot info from getMe API
|
|
45
|
+
*/
|
|
46
|
+
export interface BotInfo {
|
|
47
|
+
username: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Parsed time result from natural language processing
|
|
52
|
+
*/
|
|
53
|
+
export interface ParsedTime {
|
|
54
|
+
scheduledTime: number;
|
|
55
|
+
recurring?: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Configuration file path
|
|
60
|
+
*/
|
|
61
|
+
export const CONFIG_PATH = "/mnt/user-data/outputs/telegram_config.json";
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Extract Convex deployment URL from deploy key
|
|
65
|
+
* @param deployKey - Convex deploy key in format "prod:deployment-name|key"
|
|
66
|
+
* @returns Convex deployment URL
|
|
67
|
+
*/
|
|
68
|
+
export function getConvexUrl(deployKey: string): string {
|
|
69
|
+
const parts = deployKey.split("|")[0].split(":");
|
|
70
|
+
if (parts.length < 2) {
|
|
71
|
+
throw new Error("Invalid deploy key format");
|
|
72
|
+
}
|
|
73
|
+
const deploymentName = parts[1];
|
|
74
|
+
return `https://${deploymentName}.convex.cloud`;
|
|
75
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
|
|
3
|
+
import { ConvexHttpClient } from "convex/browser";
|
|
4
|
+
import { readFileSync, existsSync } from "fs";
|
|
5
|
+
import { api } from "../convex/_generated/api.js";
|
|
6
|
+
import { Config, CONFIG_PATH, MessageHistory, getConvexUrl } from "./types.js";
|
|
7
|
+
import { setupProxy } from "./proxy-util.js";
|
|
8
|
+
import {
|
|
9
|
+
logError,
|
|
10
|
+
logInfo,
|
|
11
|
+
log,
|
|
12
|
+
logSeparator,
|
|
13
|
+
logNotConfigured,
|
|
14
|
+
logMessageEntry,
|
|
15
|
+
} from "./logger.js";
|
|
16
|
+
|
|
17
|
+
setupProxy();
|
|
18
|
+
|
|
19
|
+
async function viewHistory(): Promise<void> {
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
const limit = args[0] ? parseInt(args[0]) : 50;
|
|
22
|
+
|
|
23
|
+
// Load config
|
|
24
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
25
|
+
logNotConfigured();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const config: Config = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
29
|
+
|
|
30
|
+
// Get Convex URL
|
|
31
|
+
const deploymentUrl = getConvexUrl(config.deployKey);
|
|
32
|
+
const client = new ConvexHttpClient(deploymentUrl);
|
|
33
|
+
|
|
34
|
+
logInfo("📜", `Fetching last ${limit} messages...\n`);
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const history = await client.query(api.messages.viewHistory, { limit }) as MessageHistory[];
|
|
38
|
+
|
|
39
|
+
if (history.length === 0) {
|
|
40
|
+
log("No message history found.");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
log("MESSAGE HISTORY:");
|
|
45
|
+
logSeparator();
|
|
46
|
+
|
|
47
|
+
history.forEach((msg, index) => {
|
|
48
|
+
const time = new Date(msg.sent_at).toLocaleString();
|
|
49
|
+
const preview = msg.message_text
|
|
50
|
+
? msg.message_text.substring(0, 50) + (msg.message_text.length > 50 ? "..." : "")
|
|
51
|
+
: undefined;
|
|
52
|
+
|
|
53
|
+
logMessageEntry({
|
|
54
|
+
index: index + 1,
|
|
55
|
+
status: msg.status,
|
|
56
|
+
title: msg.title,
|
|
57
|
+
time,
|
|
58
|
+
message: preview,
|
|
59
|
+
error: msg.status === "failed" ? msg.error_message : undefined,
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
log("\n" + "─".repeat(60));
|
|
64
|
+
log(`Total: ${history.length} messages`);
|
|
65
|
+
} catch (error: any) {
|
|
66
|
+
logError(`Failed to view history: ${error.message}`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
viewHistory().catch((error: Error) => {
|
|
72
|
+
logError(error.message);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
});
|