gentyr 1.3.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/.claude/agents/antipattern-hunter.md +176 -0
- package/.claude/agents/code-reviewer.md +205 -0
- package/.claude/agents/code-writer.md +154 -0
- package/.claude/agents/deputy-cto.md +309 -0
- package/.claude/agents/feedback-agent.md +101 -0
- package/.claude/agents/investigator.md +136 -0
- package/.claude/agents/product-manager.md +97 -0
- package/.claude/agents/project-manager.md +116 -0
- package/.claude/agents/repo-hygiene-expert.md +626 -0
- package/.claude/agents/secret-manager.md +324 -0
- package/.claude/agents/test-writer.md +354 -0
- package/.claude/commands/configure-personas.md +144 -0
- package/.claude/commands/cto-report.md +36 -0
- package/.claude/commands/demo.md +89 -0
- package/.claude/commands/deputy-cto.md +345 -0
- package/.claude/commands/hotfix.md +31 -0
- package/.claude/commands/overdrive-gentyr.md +167 -0
- package/.claude/commands/product-manager.md +32 -0
- package/.claude/commands/push-migrations.md +86 -0
- package/.claude/commands/push-secrets.md +97 -0
- package/.claude/commands/services.json.example +30 -0
- package/.claude/commands/setup-gentyr.md +396 -0
- package/.claude/commands/show.md +42 -0
- package/.claude/commands/spawn-tasks.md +79 -0
- package/.claude/commands/toggle-automation-gentyr.md +75 -0
- package/.claude/commands/toggle-product-manager.md +19 -0
- package/.claude/commands/triage.md +69 -0
- package/.claude/hooks/README.md +686 -0
- package/.claude/hooks/__tests__/README.md +129 -0
- package/.claude/hooks/agent-tracker.js +434 -0
- package/.claude/hooks/antipattern-hunter-hook.js +401 -0
- package/.claude/hooks/api-key-watcher.js +289 -0
- package/.claude/hooks/block-no-verify.js +301 -0
- package/.claude/hooks/bypass-approval-hook.js +313 -0
- package/.claude/hooks/compliance-checker.js +1309 -0
- package/.claude/hooks/config-reader.js +143 -0
- package/.claude/hooks/credential-file-guard.js +1139 -0
- package/.claude/hooks/credential-health-check.js +168 -0
- package/.claude/hooks/credential-sync-hook.js +79 -0
- package/.claude/hooks/cto-notification-hook.js +656 -0
- package/.claude/hooks/feedback-launcher.js +424 -0
- package/.claude/hooks/feedback-orchestrator.js +367 -0
- package/.claude/hooks/gentyr-splash.js +47 -0
- package/.claude/hooks/gentyr-sync.js +389 -0
- package/.claude/hooks/hourly-automation.js +3340 -0
- package/.claude/hooks/key-sync.js +899 -0
- package/.claude/hooks/lib/approval-utils.js +731 -0
- package/.claude/hooks/lib/feature-branch-helper.js +102 -0
- package/.claude/hooks/lib/worktree-manager.js +330 -0
- package/.claude/hooks/mapping-validator.js +285 -0
- package/.claude/hooks/plan-executor.js +398 -0
- package/.claude/hooks/playwright-cli-guard.js +104 -0
- package/.claude/hooks/playwright-health-check.js +71 -0
- package/.claude/hooks/pre-commit-review.js +725 -0
- package/.claude/hooks/prompts/local-spec-enforcement.md +310 -0
- package/.claude/hooks/prompts/mapping-fix.md +92 -0
- package/.claude/hooks/prompts/mapping-review.md +140 -0
- package/.claude/hooks/prompts/schema-mapper.md +185 -0
- package/.claude/hooks/prompts/spec-enforcement.md +233 -0
- package/.claude/hooks/protected-action-approval-hook.js +336 -0
- package/.claude/hooks/protected-action-gate.js +562 -0
- package/.claude/hooks/protected-actions.json +208 -0
- package/.claude/hooks/protected-actions.json.template +122 -0
- package/.claude/hooks/quota-monitor.js +490 -0
- package/.claude/hooks/reporters/jest-failure-reporter.js +401 -0
- package/.claude/hooks/reporters/playwright-failure-reporter.js +446 -0
- package/.claude/hooks/reporters/vitest-failure-reporter.js +443 -0
- package/.claude/hooks/schema-mapper-hook.js +544 -0
- package/.claude/hooks/secret-leak-detector.js +216 -0
- package/.claude/hooks/session-reviver.js +514 -0
- package/.claude/hooks/slash-command-prefetch.js +1145 -0
- package/.claude/hooks/stale-work-detector.js +205 -0
- package/.claude/hooks/stop-continue-hook.js +414 -0
- package/.claude/hooks/todo-maintenance.js +522 -0
- package/.claude/hooks/todo-processing-prompt.md +75 -0
- package/.claude/hooks/usage-optimizer.js +791 -0
- package/.claude/mcp/README.md +246 -0
- package/.claude/settings.json.template +168 -0
- package/.mcp.json.template +207 -0
- package/CLAUDE.md +340 -0
- package/CLAUDE.md.gentyr-section +89 -0
- package/LICENSE +21 -0
- package/README.md +297 -0
- package/cli/commands/init.js +471 -0
- package/cli/commands/migrate.js +132 -0
- package/cli/commands/protect.js +271 -0
- package/cli/commands/scaffold.js +48 -0
- package/cli/commands/status.js +133 -0
- package/cli/commands/sync.js +101 -0
- package/cli/commands/uninstall.js +207 -0
- package/cli/index.js +111 -0
- package/cli/lib/config-gen.js +214 -0
- package/cli/lib/resolve-framework.js +97 -0
- package/cli/lib/state.js +140 -0
- package/cli/lib/symlinks.js +260 -0
- package/docs/AUTOMATION-SYSTEMS.md +484 -0
- package/docs/BINARY-PATCHING.md +212 -0
- package/docs/CHANGELOG.md +2830 -0
- package/docs/CREDENTIAL-DETECTION.md +151 -0
- package/docs/CTO-DASHBOARD.md +476 -0
- package/docs/DEPLOYMENT-FLOW.md +477 -0
- package/docs/DEVELOPER.md +116 -0
- package/docs/Executive.md +372 -0
- package/docs/SECRET-PATHS.md +77 -0
- package/docs/SETUP-GUIDE.md +419 -0
- package/docs/STACK.md +109 -0
- package/docs/TESTING.md +440 -0
- package/docs/assets/claude-logo.svg +3 -0
- package/docs/sessions/2026-01-24-spec-suite-implementation.md +190 -0
- package/docs/sessions/2026-02-15-feedback-e2e-audit.md +484 -0
- package/docs/sessions/2026-02-20-credential-rotation-experiments.md +340 -0
- package/docs/sessions/TEST-COVERAGE-REPORT-2026-02-20.md +168 -0
- package/docs/shared/EPHEMERAL-STATE-FILES.md +115 -0
- package/docs/shared/PROTECTION-SYSTEM.md +341 -0
- package/husky/post-commit +10 -0
- package/husky/pre-commit +40 -0
- package/husky/pre-push +94 -0
- package/package.json +43 -0
- package/packages/cto-dashboard/package-lock.json +3510 -0
- package/packages/cto-dashboard/package.json +41 -0
- package/packages/cto-dashboard/pnpm-lock.yaml +2168 -0
- package/packages/mcp-servers/dist/__testUtils__/fixtures.d.ts +220 -0
- package/packages/mcp-servers/dist/__testUtils__/fixtures.d.ts.map +1 -0
- package/packages/mcp-servers/dist/__testUtils__/fixtures.js +376 -0
- package/packages/mcp-servers/dist/__testUtils__/fixtures.js.map +1 -0
- package/packages/mcp-servers/dist/__testUtils__/index.d.ts +121 -0
- package/packages/mcp-servers/dist/__testUtils__/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/__testUtils__/index.js +180 -0
- package/packages/mcp-servers/dist/__testUtils__/index.js.map +1 -0
- package/packages/mcp-servers/dist/__testUtils__/schemas.d.ts +84 -0
- package/packages/mcp-servers/dist/__testUtils__/schemas.d.ts.map +1 -0
- package/packages/mcp-servers/dist/__testUtils__/schemas.js +309 -0
- package/packages/mcp-servers/dist/__testUtils__/schemas.js.map +1 -0
- package/packages/mcp-servers/dist/agent-reports/index.d.ts +7 -0
- package/packages/mcp-servers/dist/agent-reports/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/agent-reports/index.js +8 -0
- package/packages/mcp-servers/dist/agent-reports/index.js.map +1 -0
- package/packages/mcp-servers/dist/agent-reports/server.d.ts +22 -0
- package/packages/mcp-servers/dist/agent-reports/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/agent-reports/server.js +535 -0
- package/packages/mcp-servers/dist/agent-reports/server.js.map +1 -0
- package/packages/mcp-servers/dist/agent-reports/types.d.ts +258 -0
- package/packages/mcp-servers/dist/agent-reports/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/agent-reports/types.js +81 -0
- package/packages/mcp-servers/dist/agent-reports/types.js.map +1 -0
- package/packages/mcp-servers/dist/agent-tracker/index.d.ts +5 -0
- package/packages/mcp-servers/dist/agent-tracker/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/agent-tracker/index.js +5 -0
- package/packages/mcp-servers/dist/agent-tracker/index.js.map +1 -0
- package/packages/mcp-servers/dist/agent-tracker/server.d.ts +12 -0
- package/packages/mcp-servers/dist/agent-tracker/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/agent-tracker/server.js +919 -0
- package/packages/mcp-servers/dist/agent-tracker/server.js.map +1 -0
- package/packages/mcp-servers/dist/agent-tracker/types.d.ts +328 -0
- package/packages/mcp-servers/dist/agent-tracker/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/agent-tracker/types.js +128 -0
- package/packages/mcp-servers/dist/agent-tracker/types.js.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/browser-tips.d.ts +27 -0
- package/packages/mcp-servers/dist/chrome-bridge/browser-tips.d.ts.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/browser-tips.js +167 -0
- package/packages/mcp-servers/dist/chrome-bridge/browser-tips.js.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/index.d.ts +6 -0
- package/packages/mcp-servers/dist/chrome-bridge/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/index.js +6 -0
- package/packages/mcp-servers/dist/chrome-bridge/index.js.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/server.d.ts +13 -0
- package/packages/mcp-servers/dist/chrome-bridge/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/server.js +959 -0
- package/packages/mcp-servers/dist/chrome-bridge/server.js.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/types.d.ts +41 -0
- package/packages/mcp-servers/dist/chrome-bridge/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/types.js +8 -0
- package/packages/mcp-servers/dist/chrome-bridge/types.js.map +1 -0
- package/packages/mcp-servers/dist/cloudflare/index.d.ts +8 -0
- package/packages/mcp-servers/dist/cloudflare/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cloudflare/index.js +8 -0
- package/packages/mcp-servers/dist/cloudflare/index.js.map +1 -0
- package/packages/mcp-servers/dist/cloudflare/server.d.ts +16 -0
- package/packages/mcp-servers/dist/cloudflare/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cloudflare/server.js +253 -0
- package/packages/mcp-servers/dist/cloudflare/server.js.map +1 -0
- package/packages/mcp-servers/dist/cloudflare/types.d.ts +141 -0
- package/packages/mcp-servers/dist/cloudflare/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cloudflare/types.js +53 -0
- package/packages/mcp-servers/dist/cloudflare/types.js.map +1 -0
- package/packages/mcp-servers/dist/codecov/index.d.ts +7 -0
- package/packages/mcp-servers/dist/codecov/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/codecov/index.js +7 -0
- package/packages/mcp-servers/dist/codecov/index.js.map +1 -0
- package/packages/mcp-servers/dist/codecov/server.d.ts +21 -0
- package/packages/mcp-servers/dist/codecov/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/codecov/server.js +376 -0
- package/packages/mcp-servers/dist/codecov/server.js.map +1 -0
- package/packages/mcp-servers/dist/codecov/types.d.ts +269 -0
- package/packages/mcp-servers/dist/codecov/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/codecov/types.js +128 -0
- package/packages/mcp-servers/dist/codecov/types.js.map +1 -0
- package/packages/mcp-servers/dist/cto-report/index.d.ts +9 -0
- package/packages/mcp-servers/dist/cto-report/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cto-report/index.js +9 -0
- package/packages/mcp-servers/dist/cto-report/index.js.map +1 -0
- package/packages/mcp-servers/dist/cto-report/server.d.ts +14 -0
- package/packages/mcp-servers/dist/cto-report/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cto-report/server.js +859 -0
- package/packages/mcp-servers/dist/cto-report/server.js.map +1 -0
- package/packages/mcp-servers/dist/cto-report/types.d.ts +213 -0
- package/packages/mcp-servers/dist/cto-report/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cto-report/types.js +29 -0
- package/packages/mcp-servers/dist/cto-report/types.js.map +1 -0
- package/packages/mcp-servers/dist/cto-reports/index.d.ts +7 -0
- package/packages/mcp-servers/dist/cto-reports/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cto-reports/index.js +8 -0
- package/packages/mcp-servers/dist/cto-reports/index.js.map +1 -0
- package/packages/mcp-servers/dist/cto-reports/server.d.ts +20 -0
- package/packages/mcp-servers/dist/cto-reports/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cto-reports/server.js +538 -0
- package/packages/mcp-servers/dist/cto-reports/server.js.map +1 -0
- package/packages/mcp-servers/dist/cto-reports/types.d.ts +236 -0
- package/packages/mcp-servers/dist/cto-reports/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cto-reports/types.js +77 -0
- package/packages/mcp-servers/dist/cto-reports/types.js.map +1 -0
- package/packages/mcp-servers/dist/deputy-cto/index.d.ts +7 -0
- package/packages/mcp-servers/dist/deputy-cto/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/deputy-cto/index.js +8 -0
- package/packages/mcp-servers/dist/deputy-cto/index.js.map +1 -0
- package/packages/mcp-servers/dist/deputy-cto/server.d.ts +23 -0
- package/packages/mcp-servers/dist/deputy-cto/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/deputy-cto/server.js +1700 -0
- package/packages/mcp-servers/dist/deputy-cto/server.js.map +1 -0
- package/packages/mcp-servers/dist/deputy-cto/types.d.ts +439 -0
- package/packages/mcp-servers/dist/deputy-cto/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/deputy-cto/types.js +102 -0
- package/packages/mcp-servers/dist/deputy-cto/types.js.map +1 -0
- package/packages/mcp-servers/dist/elastic-logs/index.d.ts +5 -0
- package/packages/mcp-servers/dist/elastic-logs/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/elastic-logs/index.js +5 -0
- package/packages/mcp-servers/dist/elastic-logs/index.js.map +1 -0
- package/packages/mcp-servers/dist/elastic-logs/server.d.ts +18 -0
- package/packages/mcp-servers/dist/elastic-logs/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/elastic-logs/server.js +259 -0
- package/packages/mcp-servers/dist/elastic-logs/server.js.map +1 -0
- package/packages/mcp-servers/dist/elastic-logs/types.d.ts +107 -0
- package/packages/mcp-servers/dist/elastic-logs/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/elastic-logs/types.js +31 -0
- package/packages/mcp-servers/dist/elastic-logs/types.js.map +1 -0
- package/packages/mcp-servers/dist/feedback-explorer/index.d.ts +2 -0
- package/packages/mcp-servers/dist/feedback-explorer/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/feedback-explorer/index.js +2 -0
- package/packages/mcp-servers/dist/feedback-explorer/index.js.map +1 -0
- package/packages/mcp-servers/dist/feedback-explorer/server.d.ts +21 -0
- package/packages/mcp-servers/dist/feedback-explorer/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/feedback-explorer/server.js +580 -0
- package/packages/mcp-servers/dist/feedback-explorer/server.js.map +1 -0
- package/packages/mcp-servers/dist/feedback-explorer/types.d.ts +331 -0
- package/packages/mcp-servers/dist/feedback-explorer/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/feedback-explorer/types.js +40 -0
- package/packages/mcp-servers/dist/feedback-explorer/types.js.map +1 -0
- package/packages/mcp-servers/dist/feedback-reporter/index.d.ts +9 -0
- package/packages/mcp-servers/dist/feedback-reporter/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/feedback-reporter/index.js +9 -0
- package/packages/mcp-servers/dist/feedback-reporter/index.js.map +1 -0
- package/packages/mcp-servers/dist/feedback-reporter/server.d.ts +36 -0
- package/packages/mcp-servers/dist/feedback-reporter/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/feedback-reporter/server.js +392 -0
- package/packages/mcp-servers/dist/feedback-reporter/server.js.map +1 -0
- package/packages/mcp-servers/dist/feedback-reporter/types.d.ts +152 -0
- package/packages/mcp-servers/dist/feedback-reporter/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/feedback-reporter/types.js +67 -0
- package/packages/mcp-servers/dist/feedback-reporter/types.js.map +1 -0
- package/packages/mcp-servers/dist/github/index.d.ts +7 -0
- package/packages/mcp-servers/dist/github/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/github/index.js +7 -0
- package/packages/mcp-servers/dist/github/index.js.map +1 -0
- package/packages/mcp-servers/dist/github/server.d.ts +15 -0
- package/packages/mcp-servers/dist/github/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/github/server.js +686 -0
- package/packages/mcp-servers/dist/github/server.js.map +1 -0
- package/packages/mcp-servers/dist/github/types.d.ts +660 -0
- package/packages/mcp-servers/dist/github/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/github/types.js +209 -0
- package/packages/mcp-servers/dist/github/types.js.map +1 -0
- package/packages/mcp-servers/dist/index.d.ts +30 -0
- package/packages/mcp-servers/dist/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/index.js +32 -0
- package/packages/mcp-servers/dist/index.js.map +1 -0
- package/packages/mcp-servers/dist/makerkit-docs/index.d.ts +5 -0
- package/packages/mcp-servers/dist/makerkit-docs/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/makerkit-docs/index.js +5 -0
- package/packages/mcp-servers/dist/makerkit-docs/index.js.map +1 -0
- package/packages/mcp-servers/dist/makerkit-docs/server.d.ts +15 -0
- package/packages/mcp-servers/dist/makerkit-docs/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/makerkit-docs/server.js +252 -0
- package/packages/mcp-servers/dist/makerkit-docs/server.js.map +1 -0
- package/packages/mcp-servers/dist/makerkit-docs/types.d.ts +74 -0
- package/packages/mcp-servers/dist/makerkit-docs/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/makerkit-docs/types.js +20 -0
- package/packages/mcp-servers/dist/makerkit-docs/types.js.map +1 -0
- package/packages/mcp-servers/dist/onepassword/index.d.ts +2 -0
- package/packages/mcp-servers/dist/onepassword/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/onepassword/index.js +2 -0
- package/packages/mcp-servers/dist/onepassword/index.js.map +1 -0
- package/packages/mcp-servers/dist/onepassword/server.d.ts +2 -0
- package/packages/mcp-servers/dist/onepassword/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/onepassword/server.js +159 -0
- package/packages/mcp-servers/dist/onepassword/server.js.map +1 -0
- package/packages/mcp-servers/dist/onepassword/types.d.ts +55 -0
- package/packages/mcp-servers/dist/onepassword/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/onepassword/types.js +22 -0
- package/packages/mcp-servers/dist/onepassword/types.js.map +1 -0
- package/packages/mcp-servers/dist/playwright/helpers.d.ts +20 -0
- package/packages/mcp-servers/dist/playwright/helpers.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright/helpers.js +31 -0
- package/packages/mcp-servers/dist/playwright/helpers.js.map +1 -0
- package/packages/mcp-servers/dist/playwright/index.d.ts +5 -0
- package/packages/mcp-servers/dist/playwright/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright/index.js +5 -0
- package/packages/mcp-servers/dist/playwright/index.js.map +1 -0
- package/packages/mcp-servers/dist/playwright/server.d.ts +13 -0
- package/packages/mcp-servers/dist/playwright/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright/server.js +1201 -0
- package/packages/mcp-servers/dist/playwright/server.js.map +1 -0
- package/packages/mcp-servers/dist/playwright/types.d.ts +216 -0
- package/packages/mcp-servers/dist/playwright/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright/types.js +172 -0
- package/packages/mcp-servers/dist/playwright/types.js.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/browser-manager.d.ts +39 -0
- package/packages/mcp-servers/dist/playwright-feedback/browser-manager.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/browser-manager.js +71 -0
- package/packages/mcp-servers/dist/playwright-feedback/browser-manager.js.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/index.d.ts +5 -0
- package/packages/mcp-servers/dist/playwright-feedback/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/index.js +5 -0
- package/packages/mcp-servers/dist/playwright-feedback/index.js.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/server.d.ts +34 -0
- package/packages/mcp-servers/dist/playwright-feedback/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/server.js +538 -0
- package/packages/mcp-servers/dist/playwright-feedback/server.js.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/types.d.ts +305 -0
- package/packages/mcp-servers/dist/playwright-feedback/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/types.js +123 -0
- package/packages/mcp-servers/dist/playwright-feedback/types.js.map +1 -0
- package/packages/mcp-servers/dist/product-manager/server.d.ts +17 -0
- package/packages/mcp-servers/dist/product-manager/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/product-manager/server.js +690 -0
- package/packages/mcp-servers/dist/product-manager/server.js.map +1 -0
- package/packages/mcp-servers/dist/product-manager/types.d.ts +286 -0
- package/packages/mcp-servers/dist/product-manager/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/product-manager/types.js +99 -0
- package/packages/mcp-servers/dist/product-manager/types.js.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/index.d.ts +7 -0
- package/packages/mcp-servers/dist/programmatic-feedback/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/index.js +7 -0
- package/packages/mcp-servers/dist/programmatic-feedback/index.js.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/sandbox.d.ts +19 -0
- package/packages/mcp-servers/dist/programmatic-feedback/sandbox.d.ts.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/sandbox.js +174 -0
- package/packages/mcp-servers/dist/programmatic-feedback/sandbox.js.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/server.d.ts +35 -0
- package/packages/mcp-servers/dist/programmatic-feedback/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/server.js +465 -0
- package/packages/mcp-servers/dist/programmatic-feedback/server.js.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/types.d.ts +127 -0
- package/packages/mcp-servers/dist/programmatic-feedback/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/types.js +80 -0
- package/packages/mcp-servers/dist/programmatic-feedback/types.js.map +1 -0
- package/packages/mcp-servers/dist/render/index.d.ts +8 -0
- package/packages/mcp-servers/dist/render/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/render/index.js +8 -0
- package/packages/mcp-servers/dist/render/index.js.map +1 -0
- package/packages/mcp-servers/dist/render/server.d.ts +15 -0
- package/packages/mcp-servers/dist/render/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/render/server.js +428 -0
- package/packages/mcp-servers/dist/render/server.js.map +1 -0
- package/packages/mcp-servers/dist/render/types.d.ts +273 -0
- package/packages/mcp-servers/dist/render/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/render/types.js +102 -0
- package/packages/mcp-servers/dist/render/types.js.map +1 -0
- package/packages/mcp-servers/dist/resend/index.d.ts +7 -0
- package/packages/mcp-servers/dist/resend/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/resend/index.js +7 -0
- package/packages/mcp-servers/dist/resend/index.js.map +1 -0
- package/packages/mcp-servers/dist/resend/server.d.ts +15 -0
- package/packages/mcp-servers/dist/resend/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/resend/server.js +298 -0
- package/packages/mcp-servers/dist/resend/server.js.map +1 -0
- package/packages/mcp-servers/dist/resend/types.d.ts +222 -0
- package/packages/mcp-servers/dist/resend/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/resend/types.js +58 -0
- package/packages/mcp-servers/dist/resend/types.js.map +1 -0
- package/packages/mcp-servers/dist/review-queue/index.d.ts +6 -0
- package/packages/mcp-servers/dist/review-queue/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/review-queue/index.js +6 -0
- package/packages/mcp-servers/dist/review-queue/index.js.map +1 -0
- package/packages/mcp-servers/dist/review-queue/server.d.ts +17 -0
- package/packages/mcp-servers/dist/review-queue/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/review-queue/server.js +348 -0
- package/packages/mcp-servers/dist/review-queue/server.js.map +1 -0
- package/packages/mcp-servers/dist/review-queue/types.d.ts +162 -0
- package/packages/mcp-servers/dist/review-queue/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/review-queue/types.js +56 -0
- package/packages/mcp-servers/dist/review-queue/types.js.map +1 -0
- package/packages/mcp-servers/dist/secret-sync/server.d.ts +19 -0
- package/packages/mcp-servers/dist/secret-sync/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/secret-sync/server.js +1139 -0
- package/packages/mcp-servers/dist/secret-sync/server.js.map +1 -0
- package/packages/mcp-servers/dist/secret-sync/types.d.ts +442 -0
- package/packages/mcp-servers/dist/secret-sync/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/secret-sync/types.js +113 -0
- package/packages/mcp-servers/dist/secret-sync/types.js.map +1 -0
- package/packages/mcp-servers/dist/session-events/index.d.ts +5 -0
- package/packages/mcp-servers/dist/session-events/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/session-events/index.js +5 -0
- package/packages/mcp-servers/dist/session-events/index.js.map +1 -0
- package/packages/mcp-servers/dist/session-events/server.d.ts +11 -0
- package/packages/mcp-servers/dist/session-events/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/session-events/server.js +290 -0
- package/packages/mcp-servers/dist/session-events/server.js.map +1 -0
- package/packages/mcp-servers/dist/session-events/types.d.ts +213 -0
- package/packages/mcp-servers/dist/session-events/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/session-events/types.js +69 -0
- package/packages/mcp-servers/dist/session-events/types.js.map +1 -0
- package/packages/mcp-servers/dist/session-restart/index.d.ts +9 -0
- package/packages/mcp-servers/dist/session-restart/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/session-restart/index.js +9 -0
- package/packages/mcp-servers/dist/session-restart/index.js.map +1 -0
- package/packages/mcp-servers/dist/session-restart/server.d.ts +20 -0
- package/packages/mcp-servers/dist/session-restart/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/session-restart/server.js +411 -0
- package/packages/mcp-servers/dist/session-restart/server.js.map +1 -0
- package/packages/mcp-servers/dist/session-restart/types.d.ts +26 -0
- package/packages/mcp-servers/dist/session-restart/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/session-restart/types.js +16 -0
- package/packages/mcp-servers/dist/session-restart/types.js.map +1 -0
- package/packages/mcp-servers/dist/setup-helper/index.d.ts +5 -0
- package/packages/mcp-servers/dist/setup-helper/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/setup-helper/index.js +5 -0
- package/packages/mcp-servers/dist/setup-helper/index.js.map +1 -0
- package/packages/mcp-servers/dist/setup-helper/server.d.ts +14 -0
- package/packages/mcp-servers/dist/setup-helper/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/setup-helper/server.js +454 -0
- package/packages/mcp-servers/dist/setup-helper/server.js.map +1 -0
- package/packages/mcp-servers/dist/setup-helper/types.d.ts +81 -0
- package/packages/mcp-servers/dist/setup-helper/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/setup-helper/types.js +41 -0
- package/packages/mcp-servers/dist/setup-helper/types.js.map +1 -0
- package/packages/mcp-servers/dist/shared/audited-server.d.ts +31 -0
- package/packages/mcp-servers/dist/shared/audited-server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/audited-server.js +126 -0
- package/packages/mcp-servers/dist/shared/audited-server.js.map +1 -0
- package/packages/mcp-servers/dist/shared/constants.d.ts +26 -0
- package/packages/mcp-servers/dist/shared/constants.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/constants.js +41 -0
- package/packages/mcp-servers/dist/shared/constants.js.map +1 -0
- package/packages/mcp-servers/dist/shared/index.d.ts +6 -0
- package/packages/mcp-servers/dist/shared/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/index.js +6 -0
- package/packages/mcp-servers/dist/shared/index.js.map +1 -0
- package/packages/mcp-servers/dist/shared/readonly-db.d.ts +11 -0
- package/packages/mcp-servers/dist/shared/readonly-db.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/readonly-db.js +47 -0
- package/packages/mcp-servers/dist/shared/readonly-db.js.map +1 -0
- package/packages/mcp-servers/dist/shared/resolve-framework.d.ts +20 -0
- package/packages/mcp-servers/dist/shared/resolve-framework.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/resolve-framework.js +65 -0
- package/packages/mcp-servers/dist/shared/resolve-framework.js.map +1 -0
- package/packages/mcp-servers/dist/shared/server.d.ts +86 -0
- package/packages/mcp-servers/dist/shared/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/server.js +291 -0
- package/packages/mcp-servers/dist/shared/server.js.map +1 -0
- package/packages/mcp-servers/dist/shared/types.d.ts +113 -0
- package/packages/mcp-servers/dist/shared/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/types.js +36 -0
- package/packages/mcp-servers/dist/shared/types.js.map +1 -0
- package/packages/mcp-servers/dist/show/server.d.ts +12 -0
- package/packages/mcp-servers/dist/show/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/show/server.js +97 -0
- package/packages/mcp-servers/dist/show/server.js.map +1 -0
- package/packages/mcp-servers/dist/show/types.d.ts +19 -0
- package/packages/mcp-servers/dist/show/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/show/types.js +32 -0
- package/packages/mcp-servers/dist/show/types.js.map +1 -0
- package/packages/mcp-servers/dist/specs-browser/index.d.ts +5 -0
- package/packages/mcp-servers/dist/specs-browser/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/specs-browser/index.js +5 -0
- package/packages/mcp-servers/dist/specs-browser/index.js.map +1 -0
- package/packages/mcp-servers/dist/specs-browser/server.d.ts +13 -0
- package/packages/mcp-servers/dist/specs-browser/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/specs-browser/server.js +692 -0
- package/packages/mcp-servers/dist/specs-browser/server.js.map +1 -0
- package/packages/mcp-servers/dist/specs-browser/types.d.ts +337 -0
- package/packages/mcp-servers/dist/specs-browser/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/specs-browser/types.js +134 -0
- package/packages/mcp-servers/dist/specs-browser/types.js.map +1 -0
- package/packages/mcp-servers/dist/supabase/index.d.ts +10 -0
- package/packages/mcp-servers/dist/supabase/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/supabase/index.js +10 -0
- package/packages/mcp-servers/dist/supabase/index.js.map +1 -0
- package/packages/mcp-servers/dist/supabase/server.d.ts +20 -0
- package/packages/mcp-servers/dist/supabase/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/supabase/server.js +451 -0
- package/packages/mcp-servers/dist/supabase/server.js.map +1 -0
- package/packages/mcp-servers/dist/supabase/types.d.ts +196 -0
- package/packages/mcp-servers/dist/supabase/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/supabase/types.js +76 -0
- package/packages/mcp-servers/dist/supabase/types.js.map +1 -0
- package/packages/mcp-servers/dist/todo-db/index.d.ts +5 -0
- package/packages/mcp-servers/dist/todo-db/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/todo-db/index.js +5 -0
- package/packages/mcp-servers/dist/todo-db/index.js.map +1 -0
- package/packages/mcp-servers/dist/todo-db/server.d.ts +13 -0
- package/packages/mcp-servers/dist/todo-db/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/todo-db/server.js +649 -0
- package/packages/mcp-servers/dist/todo-db/server.js.map +1 -0
- package/packages/mcp-servers/dist/todo-db/types.d.ts +225 -0
- package/packages/mcp-servers/dist/todo-db/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/todo-db/types.js +69 -0
- package/packages/mcp-servers/dist/todo-db/types.js.map +1 -0
- package/packages/mcp-servers/dist/user-feedback/index.d.ts +7 -0
- package/packages/mcp-servers/dist/user-feedback/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/user-feedback/index.js +8 -0
- package/packages/mcp-servers/dist/user-feedback/index.js.map +1 -0
- package/packages/mcp-servers/dist/user-feedback/server.d.ts +25 -0
- package/packages/mcp-servers/dist/user-feedback/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/user-feedback/server.js +914 -0
- package/packages/mcp-servers/dist/user-feedback/server.js.map +1 -0
- package/packages/mcp-servers/dist/user-feedback/types.d.ts +415 -0
- package/packages/mcp-servers/dist/user-feedback/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/user-feedback/types.js +132 -0
- package/packages/mcp-servers/dist/user-feedback/types.js.map +1 -0
- package/packages/mcp-servers/dist/vercel/index.d.ts +9 -0
- package/packages/mcp-servers/dist/vercel/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/vercel/index.js +9 -0
- package/packages/mcp-servers/dist/vercel/index.js.map +1 -0
- package/packages/mcp-servers/dist/vercel/server.d.ts +17 -0
- package/packages/mcp-servers/dist/vercel/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/vercel/server.js +265 -0
- package/packages/mcp-servers/dist/vercel/server.js.map +1 -0
- package/packages/mcp-servers/dist/vercel/types.d.ts +189 -0
- package/packages/mcp-servers/dist/vercel/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/vercel/types.js +65 -0
- package/packages/mcp-servers/dist/vercel/types.js.map +1 -0
- package/packages/mcp-servers/package-lock.json +3765 -0
- package/packages/mcp-servers/package.json +64 -0
- package/packages/mcp-servers/test/reporters/test-failure-reporter.ts +372 -0
- package/packages/mcp-servers/vitest.config.ts +27 -0
- package/scripts/__tests__/README.md +163 -0
- package/scripts/apply-credential-hardening.sh +271 -0
- package/scripts/credential-providers/manual.js +56 -0
- package/scripts/credential-providers/onepassword.js +85 -0
- package/scripts/credential-providers/provider-interface.js +104 -0
- package/scripts/encrypt-credential.js +337 -0
- package/scripts/feedback-launcher.js +338 -0
- package/scripts/feedback-orchestrator.js +373 -0
- package/scripts/fix-mcp-launcher-issues.sh +97 -0
- package/scripts/force-spawn-tasks.js +651 -0
- package/scripts/force-triage-reports.js +560 -0
- package/scripts/generate-protected-actions-spec.js +142 -0
- package/scripts/generate-proxy-certs.sh +158 -0
- package/scripts/grant-chrome-ext-permissions.sh +242 -0
- package/scripts/mcp-launcher.js +125 -0
- package/scripts/merge-settings.cjs +167 -0
- package/scripts/patch-clawd.py +844 -0
- package/scripts/patch-credential-cache.py +313 -0
- package/scripts/patches/credential-file-guard-patched.mjs +573 -0
- package/scripts/patches/credential-file-guard.js.patched +573 -0
- package/scripts/patches/verify-tokenizer.mjs +132 -0
- package/scripts/protect-framework.sh +478 -0
- package/scripts/readme-chrome.template +12 -0
- package/scripts/reap-completed-agents.js +439 -0
- package/scripts/reinstall.sh +86 -0
- package/scripts/resign-node.sh +185 -0
- package/scripts/rotation-proxy.js +656 -0
- package/scripts/rotation-stress-monitor.mjs +862 -0
- package/scripts/setup-automation-service.sh +648 -0
- package/scripts/setup-check.js +251 -0
- package/scripts/watch-claude-version.js +142 -0
- package/specs/framework/CORE-INVARIANTS.md +161 -0
- package/specs/patterns/AGENT-PATTERNS.md +223 -0
- package/specs/patterns/HOOK-PATTERNS.md +242 -0
- package/specs/patterns/MCP-SERVER-PATTERNS.md +144 -0
- package/templates/config/gitignore.template +14 -0
- package/templates/config/merge-chain-check.yml.template +51 -0
- package/templates/config/package.json.template +18 -0
- package/templates/config/pnpm-workspace.yaml +5 -0
- package/templates/config/services.json.template +18 -0
- package/templates/config/tsconfig.base.json +17 -0
- package/templates/scaffold/integrations/_template/.gitkeep +0 -0
- package/templates/scaffold/packages/logger/package.json +17 -0
- package/templates/scaffold/packages/logger/src/logger.ts +44 -0
- package/templates/scaffold/packages/shared/package.json +17 -0
- package/templates/scaffold/packages/shared/src/errors.ts +43 -0
- package/templates/scaffold/products/_product/apps/backend/package.json +21 -0
- package/templates/scaffold/products/_product/apps/backend/src/index.ts +17 -0
- package/templates/scaffold/products/_product/apps/extension/.gitkeep +0 -0
- package/templates/scaffold/products/_product/apps/web/.gitkeep +0 -0
- package/templates/scaffold/specs/global/.gitkeep +0 -0
- package/templates/scaffold/specs/local/.gitkeep +0 -0
- package/templates/scaffold/specs/reference/.gitkeep +0 -0
- package/version.json +15 -0
|
@@ -0,0 +1,919 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Agent Tracker MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Tracks all Claude agents spawned by hooks in this project.
|
|
6
|
+
* Provides tools to list agents, view prompts, and access session transcripts.
|
|
7
|
+
* Extended with unified session browser for ALL Claude Code sessions.
|
|
8
|
+
*
|
|
9
|
+
* @version 4.0.0
|
|
10
|
+
*/
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
import * as os from 'os';
|
|
14
|
+
import { execSync, execFileSync } from 'child_process';
|
|
15
|
+
import { fileURLToPath } from 'url';
|
|
16
|
+
import { McpServer } from '../shared/server.js';
|
|
17
|
+
import { ListSpawnedAgentsArgsSchema, GetAgentPromptArgsSchema, GetAgentSessionArgsSchema, GetAgentStatsArgsSchema, GetConcurrencyStatusArgsSchema, ForceSpawnTasksArgsSchema, ForceTriageReportsArgsSchema, ListSessionsArgsSchema, SearchSessionsArgsSchema, GetSessionSummaryArgsSchema, AGENT_TYPES, } from './types.js';
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Configuration
|
|
20
|
+
// ============================================================================
|
|
21
|
+
const PROJECT_DIR = path.resolve(process.env.CLAUDE_PROJECT_DIR || process.cwd());
|
|
22
|
+
const TRACKER_FILE = path.join(PROJECT_DIR, '.claude', 'state', 'agent-tracker-history.json');
|
|
23
|
+
const CLAUDE_PROJECTS_DIR = path.join(os.homedir(), '.claude', 'projects');
|
|
24
|
+
const MAX_PROMPT_PREVIEW_LENGTH = 200;
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// Helper Functions
|
|
27
|
+
// ============================================================================
|
|
28
|
+
/**
|
|
29
|
+
* Read the agent history from file
|
|
30
|
+
*/
|
|
31
|
+
function readHistory() {
|
|
32
|
+
// G001: File-not-found is different from corruption
|
|
33
|
+
if (!fs.existsSync(TRACKER_FILE)) {
|
|
34
|
+
return { agents: [], stats: {} };
|
|
35
|
+
}
|
|
36
|
+
// File exists - must read successfully or throw (G001: no silent corruption)
|
|
37
|
+
try {
|
|
38
|
+
const content = fs.readFileSync(TRACKER_FILE, 'utf8');
|
|
39
|
+
return JSON.parse(content);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
43
|
+
throw new Error(`[agent-tracker] History file corrupted at ${TRACKER_FILE}: ${message}. Delete file to reset.`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Find Claude session transcript for a given spawn
|
|
48
|
+
*/
|
|
49
|
+
function findSessionFile(agent) {
|
|
50
|
+
if (!agent.projectDir) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
// Claude stores sessions in ~/.claude/projects/-path-to-project/
|
|
55
|
+
// Normalize path: replace / with - to get leading-dash format (e.g., "-home-user-project")
|
|
56
|
+
const projectPath = agent.projectDir.replace(/[^a-zA-Z0-9]/g, '-');
|
|
57
|
+
const sessionDir = path.join(CLAUDE_PROJECTS_DIR, projectPath);
|
|
58
|
+
if (!fs.existsSync(sessionDir)) {
|
|
59
|
+
// Try alternative path format (without leading dash, for backwards compatibility)
|
|
60
|
+
const altPath = path.join(CLAUDE_PROJECTS_DIR, projectPath.replace(/^-/, ''));
|
|
61
|
+
if (!fs.existsSync(altPath)) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const actualDir = fs.existsSync(sessionDir)
|
|
66
|
+
? sessionDir
|
|
67
|
+
: path.join(CLAUDE_PROJECTS_DIR, projectPath.replace(/^-/, ''));
|
|
68
|
+
// List all JSONL files and find one close to spawn time
|
|
69
|
+
const files = fs.readdirSync(actualDir)
|
|
70
|
+
.filter(f => f.endsWith('.jsonl'))
|
|
71
|
+
.map(f => ({
|
|
72
|
+
name: f,
|
|
73
|
+
path: path.join(actualDir, f),
|
|
74
|
+
mtime: fs.statSync(path.join(actualDir, f)).mtime.getTime(),
|
|
75
|
+
}))
|
|
76
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
77
|
+
if (files.length === 0) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
// Find session file created around spawn time (within 5 minutes)
|
|
81
|
+
const spawnTime = new Date(agent.timestamp).getTime();
|
|
82
|
+
const matchingFile = files.find(f => {
|
|
83
|
+
const diff = Math.abs(f.mtime - spawnTime);
|
|
84
|
+
return diff < 5 * 60 * 1000; // Within 5 minutes
|
|
85
|
+
});
|
|
86
|
+
return matchingFile ? matchingFile.path : files[0].path;
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
// G001: Log session search errors (non-critical, return null)
|
|
90
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
91
|
+
process.stderr.write(`[agent-tracker] Error finding session file: ${message}\n`);
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Read and parse a session JSONL file
|
|
97
|
+
*/
|
|
98
|
+
function readSessionFile(filePath) {
|
|
99
|
+
// G001: File read errors should be logged, not silently ignored
|
|
100
|
+
if (!fs.existsSync(filePath)) {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
105
|
+
const lines = content.trim().split('\n');
|
|
106
|
+
const messages = [];
|
|
107
|
+
let parseErrors = 0;
|
|
108
|
+
for (const line of lines) {
|
|
109
|
+
try {
|
|
110
|
+
const parsed = JSON.parse(line);
|
|
111
|
+
messages.push(parsed);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// JSONL files may have occasional malformed lines - count but don't fail
|
|
115
|
+
parseErrors++;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Log if significant parse failures (>10%)
|
|
119
|
+
if (parseErrors > 0 && parseErrors > lines.length * 0.1) {
|
|
120
|
+
process.stderr.write(`[agent-tracker] Warning: ${parseErrors}/${lines.length} lines failed to parse in ${filePath}\n`);
|
|
121
|
+
}
|
|
122
|
+
return messages;
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
// G001: Log file read errors
|
|
126
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
127
|
+
process.stderr.write(`[agent-tracker] Error reading session file ${filePath}: ${message}\n`);
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Format session messages for display
|
|
133
|
+
*/
|
|
134
|
+
function formatSession(messages) {
|
|
135
|
+
const formatted = {
|
|
136
|
+
messageCount: messages.length,
|
|
137
|
+
summary: {
|
|
138
|
+
userMessages: 0,
|
|
139
|
+
assistantMessages: 0,
|
|
140
|
+
toolResults: 0,
|
|
141
|
+
totalMessages: messages.length,
|
|
142
|
+
},
|
|
143
|
+
messages: [],
|
|
144
|
+
};
|
|
145
|
+
for (const msg of messages) {
|
|
146
|
+
const entry = {
|
|
147
|
+
type: msg.type ?? 'unknown',
|
|
148
|
+
timestamp: msg.timestamp ?? null,
|
|
149
|
+
};
|
|
150
|
+
if (msg.type === 'human' || msg.type === 'user') {
|
|
151
|
+
entry.role = 'user';
|
|
152
|
+
entry.content = typeof msg.message?.content === 'string'
|
|
153
|
+
? msg.message.content
|
|
154
|
+
: (msg.content ?? '[no content]');
|
|
155
|
+
formatted.summary.userMessages++;
|
|
156
|
+
}
|
|
157
|
+
else if (msg.type === 'assistant') {
|
|
158
|
+
entry.role = 'assistant';
|
|
159
|
+
// Extract text content from assistant messages
|
|
160
|
+
if (Array.isArray(msg.message?.content)) {
|
|
161
|
+
entry.content = msg.message.content
|
|
162
|
+
.filter((c) => c.type === 'text' && typeof c.text === 'string')
|
|
163
|
+
.map(c => c.text)
|
|
164
|
+
.join('\n');
|
|
165
|
+
entry.toolCalls = msg.message.content
|
|
166
|
+
.filter((c) => c.type === 'tool_use' && typeof c.name === 'string' && typeof c.id === 'string')
|
|
167
|
+
.map(c => ({ name: c.name, id: c.id }));
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
entry.content = typeof msg.message?.content === 'string'
|
|
171
|
+
? msg.message.content
|
|
172
|
+
: (msg.content ?? '[no content]');
|
|
173
|
+
}
|
|
174
|
+
formatted.summary.assistantMessages++;
|
|
175
|
+
}
|
|
176
|
+
else if (msg.type === 'tool_result') {
|
|
177
|
+
entry.role = 'tool_result';
|
|
178
|
+
entry.toolId = msg.tool_use_id;
|
|
179
|
+
entry.content = typeof msg.content === 'string'
|
|
180
|
+
? msg.content.substring(0, 500) + (msg.content.length > 500 ? '...' : '')
|
|
181
|
+
: '[complex content]';
|
|
182
|
+
formatted.summary.toolResults++;
|
|
183
|
+
}
|
|
184
|
+
formatted.messages.push(entry);
|
|
185
|
+
}
|
|
186
|
+
return formatted;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Discover all session files for the current project
|
|
190
|
+
*/
|
|
191
|
+
function discoverSessions() {
|
|
192
|
+
try {
|
|
193
|
+
// Normalize path: replace / with - to get leading-dash format (e.g., "-home-user-project")
|
|
194
|
+
const projectPath = PROJECT_DIR.replace(/[^a-zA-Z0-9]/g, '-');
|
|
195
|
+
const sessionDir = path.join(CLAUDE_PROJECTS_DIR, projectPath);
|
|
196
|
+
if (!fs.existsSync(sessionDir)) {
|
|
197
|
+
// Try alternative path format (without leading dash, for backwards compatibility)
|
|
198
|
+
const altPath = path.join(CLAUDE_PROJECTS_DIR, projectPath.replace(/^-/, ''));
|
|
199
|
+
if (!fs.existsSync(altPath)) {
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const actualDir = fs.existsSync(sessionDir)
|
|
204
|
+
? sessionDir
|
|
205
|
+
: path.join(CLAUDE_PROJECTS_DIR, projectPath.replace(/^-/, ''));
|
|
206
|
+
const files = fs.readdirSync(actualDir);
|
|
207
|
+
const sessions = [];
|
|
208
|
+
for (const f of files) {
|
|
209
|
+
// Only top-level JSONL files (not in subdirectories)
|
|
210
|
+
if (!f.endsWith('.jsonl')) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const filePath = path.join(actualDir, f);
|
|
214
|
+
try {
|
|
215
|
+
const stats = fs.statSync(filePath);
|
|
216
|
+
if (stats.isFile()) {
|
|
217
|
+
sessions.push({
|
|
218
|
+
session_id: f.replace('.jsonl', ''),
|
|
219
|
+
file_path: filePath,
|
|
220
|
+
mtime: stats.mtime,
|
|
221
|
+
size_bytes: stats.size,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
// Skip files we can't stat
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return sessions;
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
233
|
+
process.stderr.write(`[agent-tracker] Error discovering sessions: ${message}\n`);
|
|
234
|
+
return [];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Match a session to a hook-spawned agent using timestamp proximity
|
|
239
|
+
*/
|
|
240
|
+
function matchSessionToHook(session, agentHistory) {
|
|
241
|
+
const sessionTime = session.mtime.getTime();
|
|
242
|
+
// Find agent spawned within 5 minutes of session modification
|
|
243
|
+
const match = agentHistory.find(agent => {
|
|
244
|
+
const agentTime = new Date(agent.timestamp).getTime();
|
|
245
|
+
return Math.abs(sessionTime - agentTime) < 5 * 60 * 1000;
|
|
246
|
+
});
|
|
247
|
+
if (!match) {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
agent_id: match.id,
|
|
252
|
+
type: match.type,
|
|
253
|
+
hook_type: match.hookType,
|
|
254
|
+
description: match.description,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Read session file lines (for searching)
|
|
259
|
+
*/
|
|
260
|
+
function readSessionLines(filePath) {
|
|
261
|
+
if (!fs.existsSync(filePath)) {
|
|
262
|
+
return [];
|
|
263
|
+
}
|
|
264
|
+
try {
|
|
265
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
266
|
+
const lines = content.split('\n');
|
|
267
|
+
const result = [];
|
|
268
|
+
for (let i = 0; i < lines.length; i++) {
|
|
269
|
+
if (lines[i].trim()) {
|
|
270
|
+
result.push({ line: lines[i], lineNum: i + 1 });
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
catch (err) {
|
|
276
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
277
|
+
process.stderr.write(`[agent-tracker] Error reading session: ${message}\n`);
|
|
278
|
+
return [];
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Get message type from parsed session entry
|
|
283
|
+
*/
|
|
284
|
+
function getMessageType(entry) {
|
|
285
|
+
if (entry.type === 'human' || entry.type === 'user') {
|
|
286
|
+
return 'user';
|
|
287
|
+
}
|
|
288
|
+
if (entry.type === 'assistant') {
|
|
289
|
+
return 'assistant';
|
|
290
|
+
}
|
|
291
|
+
if (entry.type === 'tool_result') {
|
|
292
|
+
return 'tool_result';
|
|
293
|
+
}
|
|
294
|
+
return 'unknown';
|
|
295
|
+
}
|
|
296
|
+
// ============================================================================
|
|
297
|
+
// Tool Implementations
|
|
298
|
+
// ============================================================================
|
|
299
|
+
/**
|
|
300
|
+
* List all spawned agents
|
|
301
|
+
*/
|
|
302
|
+
function listAgents(args) {
|
|
303
|
+
const history = readHistory();
|
|
304
|
+
let agents = history.agents ?? [];
|
|
305
|
+
// Apply filters
|
|
306
|
+
if (args.type) {
|
|
307
|
+
agents = agents.filter(a => a.type === args.type);
|
|
308
|
+
}
|
|
309
|
+
if (args.hookType) {
|
|
310
|
+
agents = agents.filter(a => a.hookType === args.hookType);
|
|
311
|
+
}
|
|
312
|
+
if (args.since) {
|
|
313
|
+
const sinceDate = new Date(args.since);
|
|
314
|
+
agents = agents.filter(a => new Date(a.timestamp) >= sinceDate);
|
|
315
|
+
}
|
|
316
|
+
const limit = args.limit ?? 50;
|
|
317
|
+
agents = agents.slice(0, limit);
|
|
318
|
+
// Format for display
|
|
319
|
+
const formatted = agents.map((a, index) => ({
|
|
320
|
+
id: a.id,
|
|
321
|
+
index,
|
|
322
|
+
type: a.type,
|
|
323
|
+
hookType: a.hookType,
|
|
324
|
+
description: a.description,
|
|
325
|
+
timestamp: a.timestamp,
|
|
326
|
+
promptPreview: a.prompt
|
|
327
|
+
? a.prompt.substring(0, MAX_PROMPT_PREVIEW_LENGTH) +
|
|
328
|
+
(a.prompt.length > MAX_PROMPT_PREVIEW_LENGTH ? '...' : '')
|
|
329
|
+
: '[no prompt stored]',
|
|
330
|
+
hasSession: Boolean(findSessionFile(a)),
|
|
331
|
+
pid: a.pid,
|
|
332
|
+
status: a.status,
|
|
333
|
+
reapedAt: a.reapedAt,
|
|
334
|
+
reapReason: a.reapReason,
|
|
335
|
+
}));
|
|
336
|
+
return {
|
|
337
|
+
total: formatted.length,
|
|
338
|
+
agents: formatted,
|
|
339
|
+
availableTypes: Object.values(AGENT_TYPES),
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Get full prompt for an agent
|
|
344
|
+
*/
|
|
345
|
+
function getAgentPrompt(args) {
|
|
346
|
+
const history = readHistory();
|
|
347
|
+
const agent = history.agents.find(a => a.id === args.agentId);
|
|
348
|
+
if (!agent) {
|
|
349
|
+
return { error: `Agent not found: ${args.agentId}` };
|
|
350
|
+
}
|
|
351
|
+
return {
|
|
352
|
+
id: agent.id,
|
|
353
|
+
type: agent.type,
|
|
354
|
+
hookType: agent.hookType,
|
|
355
|
+
description: agent.description,
|
|
356
|
+
timestamp: agent.timestamp,
|
|
357
|
+
prompt: agent.prompt ?? '[no prompt stored]',
|
|
358
|
+
promptLength: agent.prompt ? agent.prompt.length : 0,
|
|
359
|
+
metadata: agent.metadata ?? {},
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Get session transcript for an agent
|
|
364
|
+
*/
|
|
365
|
+
function getAgentSession(args) {
|
|
366
|
+
const history = readHistory();
|
|
367
|
+
const agent = history.agents.find(a => a.id === args.agentId);
|
|
368
|
+
if (!agent) {
|
|
369
|
+
return { error: `Agent not found: ${args.agentId}` };
|
|
370
|
+
}
|
|
371
|
+
const sessionPath = findSessionFile(agent);
|
|
372
|
+
if (!sessionPath) {
|
|
373
|
+
return {
|
|
374
|
+
id: agent.id,
|
|
375
|
+
type: agent.type,
|
|
376
|
+
description: agent.description,
|
|
377
|
+
timestamp: agent.timestamp,
|
|
378
|
+
session: null,
|
|
379
|
+
sessionPath: null,
|
|
380
|
+
message: 'No session file found. Session may have been cleaned up or not yet created.',
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
const messages = readSessionFile(sessionPath);
|
|
384
|
+
const formatted = formatSession(messages);
|
|
385
|
+
// Limit messages if requested
|
|
386
|
+
const limit = args.limit ?? 100;
|
|
387
|
+
if (formatted.messages.length > limit) {
|
|
388
|
+
formatted.messages = formatted.messages.slice(0, limit);
|
|
389
|
+
formatted.truncated = true;
|
|
390
|
+
}
|
|
391
|
+
return {
|
|
392
|
+
id: agent.id,
|
|
393
|
+
type: agent.type,
|
|
394
|
+
description: agent.description,
|
|
395
|
+
timestamp: agent.timestamp,
|
|
396
|
+
sessionPath,
|
|
397
|
+
session: formatted,
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Get statistics about spawned agents
|
|
402
|
+
*/
|
|
403
|
+
function getAgentStats() {
|
|
404
|
+
const history = readHistory();
|
|
405
|
+
const agents = history.agents ?? [];
|
|
406
|
+
const stats = {
|
|
407
|
+
totalSpawns: agents.length,
|
|
408
|
+
byType: {},
|
|
409
|
+
byHookType: {},
|
|
410
|
+
last24Hours: 0,
|
|
411
|
+
last7Days: 0,
|
|
412
|
+
oldestSpawn: null,
|
|
413
|
+
newestSpawn: null,
|
|
414
|
+
byStatus: {},
|
|
415
|
+
totalReaped: 0,
|
|
416
|
+
};
|
|
417
|
+
const now = Date.now();
|
|
418
|
+
const day = 24 * 60 * 60 * 1000;
|
|
419
|
+
for (const agent of agents) {
|
|
420
|
+
// Count by type
|
|
421
|
+
stats.byType[agent.type] = (stats.byType[agent.type] || 0) + 1;
|
|
422
|
+
// Count by hook type
|
|
423
|
+
stats.byHookType[agent.hookType] = (stats.byHookType[agent.hookType] || 0) + 1;
|
|
424
|
+
// Count by status (running/completed/reaped)
|
|
425
|
+
if (agent.status) {
|
|
426
|
+
stats.byStatus[agent.status] = (stats.byStatus[agent.status] || 0) + 1;
|
|
427
|
+
if (agent.status === 'reaped') {
|
|
428
|
+
stats.totalReaped++;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
// Time-based stats
|
|
432
|
+
const spawnTime = new Date(agent.timestamp).getTime();
|
|
433
|
+
if (now - spawnTime < day) {
|
|
434
|
+
stats.last24Hours++;
|
|
435
|
+
}
|
|
436
|
+
if (now - spawnTime < 7 * day) {
|
|
437
|
+
stats.last7Days++;
|
|
438
|
+
}
|
|
439
|
+
// Track oldest/newest
|
|
440
|
+
if (!stats.oldestSpawn || spawnTime < new Date(stats.oldestSpawn).getTime()) {
|
|
441
|
+
stats.oldestSpawn = agent.timestamp;
|
|
442
|
+
}
|
|
443
|
+
if (!stats.newestSpawn || spawnTime > new Date(stats.newestSpawn).getTime()) {
|
|
444
|
+
stats.newestSpawn = agent.timestamp;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
return stats;
|
|
448
|
+
}
|
|
449
|
+
// ============================================================================
|
|
450
|
+
// Session Browser Tool Implementations
|
|
451
|
+
// ============================================================================
|
|
452
|
+
/**
|
|
453
|
+
* List all sessions with optional hook metadata annotation
|
|
454
|
+
*/
|
|
455
|
+
function listSessions(args) {
|
|
456
|
+
const history = readHistory();
|
|
457
|
+
const agentHistory = history.agents ?? [];
|
|
458
|
+
// Discover all sessions
|
|
459
|
+
let sessions = discoverSessions();
|
|
460
|
+
// Apply time filters - explicit 'since' overrides maxAgeDays
|
|
461
|
+
if (args.since) {
|
|
462
|
+
const sinceDate = new Date(args.since);
|
|
463
|
+
sessions = sessions.filter(s => s.mtime >= sinceDate);
|
|
464
|
+
}
|
|
465
|
+
else if (args.maxAgeDays && args.maxAgeDays > 0) {
|
|
466
|
+
// Default: only include sessions from last N days (performance optimization)
|
|
467
|
+
const cutoffDate = new Date(Date.now() - args.maxAgeDays * 24 * 60 * 60 * 1000);
|
|
468
|
+
sessions = sessions.filter(s => s.mtime >= cutoffDate);
|
|
469
|
+
}
|
|
470
|
+
if (args.before) {
|
|
471
|
+
const beforeDate = new Date(args.before);
|
|
472
|
+
sessions = sessions.filter(s => s.mtime <= beforeDate);
|
|
473
|
+
}
|
|
474
|
+
// Match sessions to hooks and build enriched list
|
|
475
|
+
const enriched = sessions.map(s => ({
|
|
476
|
+
...s,
|
|
477
|
+
hook_info: matchSessionToHook(s, agentHistory) ?? undefined,
|
|
478
|
+
}));
|
|
479
|
+
// Apply filter (all, hook-spawned, manual)
|
|
480
|
+
let filtered = enriched;
|
|
481
|
+
if (args.filter === 'hook-spawned') {
|
|
482
|
+
filtered = enriched.filter(s => s.hook_info !== undefined);
|
|
483
|
+
}
|
|
484
|
+
else if (args.filter === 'manual') {
|
|
485
|
+
filtered = enriched.filter(s => s.hook_info === undefined);
|
|
486
|
+
}
|
|
487
|
+
// Apply hookType filter if specified
|
|
488
|
+
if (args.hookType) {
|
|
489
|
+
filtered = filtered.filter(s => s.hook_info?.hook_type === args.hookType);
|
|
490
|
+
}
|
|
491
|
+
// Sort
|
|
492
|
+
const sortBy = args.sortBy ?? 'newest';
|
|
493
|
+
if (sortBy === 'newest') {
|
|
494
|
+
filtered.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
495
|
+
}
|
|
496
|
+
else if (sortBy === 'oldest') {
|
|
497
|
+
filtered.sort((a, b) => a.mtime.getTime() - b.mtime.getTime());
|
|
498
|
+
}
|
|
499
|
+
else if (sortBy === 'largest') {
|
|
500
|
+
filtered.sort((a, b) => b.size_bytes - a.size_bytes);
|
|
501
|
+
}
|
|
502
|
+
// Pagination
|
|
503
|
+
const offset = args.offset ?? 0;
|
|
504
|
+
const limit = args.limit ?? 50;
|
|
505
|
+
const total = filtered.length;
|
|
506
|
+
const paginated = filtered.slice(offset, offset + limit);
|
|
507
|
+
// Format result
|
|
508
|
+
const sessionList = paginated.map(s => ({
|
|
509
|
+
session_id: s.session_id,
|
|
510
|
+
file_path: s.file_path,
|
|
511
|
+
mtime: s.mtime.toISOString(),
|
|
512
|
+
size_bytes: s.size_bytes,
|
|
513
|
+
hook_info: s.hook_info,
|
|
514
|
+
}));
|
|
515
|
+
return {
|
|
516
|
+
total,
|
|
517
|
+
sessions: sessionList,
|
|
518
|
+
offset,
|
|
519
|
+
limit,
|
|
520
|
+
hasMore: offset + limit < total,
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Search across session content
|
|
525
|
+
*/
|
|
526
|
+
function searchSessions(args) {
|
|
527
|
+
const history = readHistory();
|
|
528
|
+
const agentHistory = history.agents ?? [];
|
|
529
|
+
const query = args.query.toLowerCase();
|
|
530
|
+
const limit = args.limit ?? 20;
|
|
531
|
+
// Discover and filter sessions
|
|
532
|
+
let sessions = discoverSessions();
|
|
533
|
+
// Apply time filters - explicit 'since' overrides maxAgeDays
|
|
534
|
+
if (args.since) {
|
|
535
|
+
const sinceDate = new Date(args.since);
|
|
536
|
+
sessions = sessions.filter(s => s.mtime >= sinceDate);
|
|
537
|
+
}
|
|
538
|
+
else if (args.maxAgeDays && args.maxAgeDays > 0) {
|
|
539
|
+
// Default: only search sessions from last N days (major performance optimization)
|
|
540
|
+
const cutoffDate = new Date(Date.now() - args.maxAgeDays * 24 * 60 * 60 * 1000);
|
|
541
|
+
sessions = sessions.filter(s => s.mtime >= cutoffDate);
|
|
542
|
+
}
|
|
543
|
+
// Match sessions to hooks
|
|
544
|
+
const enriched = sessions.map(s => ({
|
|
545
|
+
...s,
|
|
546
|
+
hook_info: matchSessionToHook(s, agentHistory) ?? undefined,
|
|
547
|
+
}));
|
|
548
|
+
// Apply filter
|
|
549
|
+
let filtered = enriched;
|
|
550
|
+
if (args.filter === 'hook-spawned') {
|
|
551
|
+
filtered = enriched.filter(s => s.hook_info !== undefined);
|
|
552
|
+
}
|
|
553
|
+
else if (args.filter === 'manual') {
|
|
554
|
+
filtered = enriched.filter(s => s.hook_info === undefined);
|
|
555
|
+
}
|
|
556
|
+
if (args.hookType) {
|
|
557
|
+
filtered = filtered.filter(s => s.hook_info?.hook_type === args.hookType);
|
|
558
|
+
}
|
|
559
|
+
// Sort by newest first for search
|
|
560
|
+
filtered.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
561
|
+
const results = [];
|
|
562
|
+
let totalMatches = 0;
|
|
563
|
+
// Search through sessions
|
|
564
|
+
for (const session of filtered) {
|
|
565
|
+
if (results.length >= limit) {
|
|
566
|
+
break;
|
|
567
|
+
}
|
|
568
|
+
const matches = [];
|
|
569
|
+
for (const { line, lineNum } of readSessionLines(session.file_path)) {
|
|
570
|
+
if (line.toLowerCase().includes(query)) {
|
|
571
|
+
try {
|
|
572
|
+
const parsed = JSON.parse(line);
|
|
573
|
+
const messageType = getMessageType(parsed);
|
|
574
|
+
// Extract content for preview
|
|
575
|
+
const content = (() => {
|
|
576
|
+
if (typeof parsed.message?.content === 'string') {
|
|
577
|
+
return parsed.message.content;
|
|
578
|
+
}
|
|
579
|
+
if (Array.isArray(parsed.message?.content)) {
|
|
580
|
+
return parsed.message.content
|
|
581
|
+
.filter((c) => c.type === 'text')
|
|
582
|
+
.map(c => c.text)
|
|
583
|
+
.join(' ');
|
|
584
|
+
}
|
|
585
|
+
if (typeof parsed.content === 'string') {
|
|
586
|
+
return parsed.content;
|
|
587
|
+
}
|
|
588
|
+
return '';
|
|
589
|
+
})();
|
|
590
|
+
// Find the match position and create preview
|
|
591
|
+
const lowerContent = content.toLowerCase();
|
|
592
|
+
const matchIndex = lowerContent.indexOf(query);
|
|
593
|
+
const start = Math.max(0, matchIndex - 50);
|
|
594
|
+
const end = Math.min(content.length, matchIndex + query.length + 50);
|
|
595
|
+
const preview = (start > 0 ? '...' : '') +
|
|
596
|
+
content.substring(start, end) +
|
|
597
|
+
(end < content.length ? '...' : '');
|
|
598
|
+
matches.push({
|
|
599
|
+
line_number: lineNum,
|
|
600
|
+
content_preview: preview || '[match in metadata]',
|
|
601
|
+
message_type: messageType,
|
|
602
|
+
});
|
|
603
|
+
totalMatches++;
|
|
604
|
+
// Limit matches per session for performance
|
|
605
|
+
if (matches.length >= 10) {
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
catch {
|
|
610
|
+
// Skip unparseable lines
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
if (matches.length > 0) {
|
|
615
|
+
results.push({
|
|
616
|
+
session_id: session.session_id,
|
|
617
|
+
file_path: session.file_path,
|
|
618
|
+
mtime: session.mtime.toISOString(),
|
|
619
|
+
matches,
|
|
620
|
+
hook_info: session.hook_info,
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
return {
|
|
625
|
+
query: args.query,
|
|
626
|
+
total_sessions: results.length,
|
|
627
|
+
total_matches: totalMatches,
|
|
628
|
+
results,
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Get detailed summary of a specific session
|
|
633
|
+
*/
|
|
634
|
+
function getSessionSummary(args) {
|
|
635
|
+
const history = readHistory();
|
|
636
|
+
const agentHistory = history.agents ?? [];
|
|
637
|
+
// Find the session file
|
|
638
|
+
const sessions = discoverSessions();
|
|
639
|
+
const session = sessions.find(s => s.session_id === args.session_id);
|
|
640
|
+
if (!session) {
|
|
641
|
+
return { error: `Session not found: ${args.session_id}` };
|
|
642
|
+
}
|
|
643
|
+
// Get hook info
|
|
644
|
+
const hookInfo = matchSessionToHook(session, agentHistory) ?? undefined;
|
|
645
|
+
// Parse session content
|
|
646
|
+
const messages = readSessionFile(session.file_path);
|
|
647
|
+
const messageCounts = {
|
|
648
|
+
user: 0,
|
|
649
|
+
assistant: 0,
|
|
650
|
+
tool_result: 0,
|
|
651
|
+
other: 0,
|
|
652
|
+
};
|
|
653
|
+
const toolsUsed = new Set();
|
|
654
|
+
let firstTimestamp = null;
|
|
655
|
+
let lastTimestamp = null;
|
|
656
|
+
let firstUserMessage;
|
|
657
|
+
for (const msg of messages) {
|
|
658
|
+
const msgType = getMessageType(msg);
|
|
659
|
+
// Count message types
|
|
660
|
+
if (msgType === 'user') {
|
|
661
|
+
messageCounts.user++;
|
|
662
|
+
// Capture first user message
|
|
663
|
+
if (!firstUserMessage) {
|
|
664
|
+
if (typeof msg.message?.content === 'string') {
|
|
665
|
+
firstUserMessage = msg.message.content.substring(0, 200) +
|
|
666
|
+
(msg.message.content.length > 200 ? '...' : '');
|
|
667
|
+
}
|
|
668
|
+
else if (typeof msg.content === 'string') {
|
|
669
|
+
firstUserMessage = msg.content.substring(0, 200) +
|
|
670
|
+
(msg.content.length > 200 ? '...' : '');
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
else if (msgType === 'assistant') {
|
|
675
|
+
messageCounts.assistant++;
|
|
676
|
+
// Extract tool calls
|
|
677
|
+
if (Array.isArray(msg.message?.content)) {
|
|
678
|
+
for (const c of msg.message.content) {
|
|
679
|
+
if (c.type === 'tool_use' && typeof c.name === 'string') {
|
|
680
|
+
toolsUsed.add(c.name);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
else if (msgType === 'tool_result') {
|
|
686
|
+
messageCounts.tool_result++;
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
messageCounts.other++;
|
|
690
|
+
}
|
|
691
|
+
// Track timestamps
|
|
692
|
+
if (msg.timestamp) {
|
|
693
|
+
if (!firstTimestamp) {
|
|
694
|
+
firstTimestamp = msg.timestamp;
|
|
695
|
+
}
|
|
696
|
+
lastTimestamp = msg.timestamp;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
// Calculate duration estimate
|
|
700
|
+
let durationEstimate;
|
|
701
|
+
if (firstTimestamp && lastTimestamp) {
|
|
702
|
+
const first = new Date(firstTimestamp).getTime();
|
|
703
|
+
const last = new Date(lastTimestamp).getTime();
|
|
704
|
+
const durationMs = last - first;
|
|
705
|
+
if (durationMs > 0) {
|
|
706
|
+
const minutes = Math.floor(durationMs / 60000);
|
|
707
|
+
const seconds = Math.floor((durationMs % 60000) / 1000);
|
|
708
|
+
if (minutes > 60) {
|
|
709
|
+
const hours = Math.floor(minutes / 60);
|
|
710
|
+
durationEstimate = `${hours}h ${minutes % 60}m`;
|
|
711
|
+
}
|
|
712
|
+
else if (minutes > 0) {
|
|
713
|
+
durationEstimate = `${minutes}m ${seconds}s`;
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
durationEstimate = `${seconds}s`;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
return {
|
|
721
|
+
session_id: session.session_id,
|
|
722
|
+
file_path: session.file_path,
|
|
723
|
+
mtime: session.mtime.toISOString(),
|
|
724
|
+
size_bytes: session.size_bytes,
|
|
725
|
+
message_counts: messageCounts,
|
|
726
|
+
tools_used: Array.from(toolsUsed).sort(),
|
|
727
|
+
duration_estimate: durationEstimate,
|
|
728
|
+
hook_info: hookInfo,
|
|
729
|
+
first_user_message: firstUserMessage,
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
// ============================================================================
|
|
733
|
+
// Concurrency & Force-Spawn Tool Implementations
|
|
734
|
+
// ============================================================================
|
|
735
|
+
/**
|
|
736
|
+
* Get real-time concurrency status: running agents, max allowed, available slots
|
|
737
|
+
*/
|
|
738
|
+
function getConcurrencyStatus(_args) {
|
|
739
|
+
// Count running agents via pgrep (same pattern as force-spawn-tasks.js)
|
|
740
|
+
let running = 0;
|
|
741
|
+
try {
|
|
742
|
+
const result = execSync("pgrep -cf 'claude.*--dangerously-skip-permissions'", { encoding: 'utf8', timeout: 5000, stdio: 'pipe' }).trim();
|
|
743
|
+
running = parseInt(result, 10) || 0;
|
|
744
|
+
}
|
|
745
|
+
catch {
|
|
746
|
+
// pgrep returns exit code 1 when no processes match
|
|
747
|
+
}
|
|
748
|
+
// Read max concurrent from automation-config.json
|
|
749
|
+
let maxConcurrent = 10;
|
|
750
|
+
const automationConfigPath = path.join(PROJECT_DIR, '.claude', 'state', 'automation-config.json');
|
|
751
|
+
try {
|
|
752
|
+
const config = JSON.parse(fs.readFileSync(automationConfigPath, 'utf8'));
|
|
753
|
+
if (config?.effective?.MAX_CONCURRENT_AGENTS) {
|
|
754
|
+
maxConcurrent = config.effective.MAX_CONCURRENT_AGENTS;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
catch {
|
|
758
|
+
// Fall back to default
|
|
759
|
+
}
|
|
760
|
+
// Read agent-tracker-history.json, count agents with status === 'running' by type
|
|
761
|
+
const history = readHistory();
|
|
762
|
+
const trackedByType = {};
|
|
763
|
+
for (const agent of history.agents ?? []) {
|
|
764
|
+
if (agent.status === 'running') {
|
|
765
|
+
trackedByType[agent.type] = (trackedByType[agent.type] || 0) + 1;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
return {
|
|
769
|
+
running,
|
|
770
|
+
maxConcurrent,
|
|
771
|
+
available: Math.max(0, maxConcurrent - running),
|
|
772
|
+
trackedRunning: { byType: trackedByType },
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Force-spawn pending tasks by wrapping the existing force-spawn-tasks.js script
|
|
777
|
+
*/
|
|
778
|
+
function forceSpawnTasks(args) {
|
|
779
|
+
// Derive framework path from import.meta.url
|
|
780
|
+
// Compiled path: <framework>/packages/mcp-servers/dist/agent-tracker/server.js
|
|
781
|
+
// Navigate up 4 levels to reach framework root
|
|
782
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
783
|
+
const frameworkRoot = path.resolve(path.dirname(thisFile), '..', '..', '..', '..');
|
|
784
|
+
const scriptPath = path.join(frameworkRoot, 'scripts', 'force-spawn-tasks.js');
|
|
785
|
+
if (!fs.existsSync(scriptPath)) {
|
|
786
|
+
return { error: `force-spawn-tasks.js not found at ${scriptPath}. Framework root resolved to: ${frameworkRoot}` };
|
|
787
|
+
}
|
|
788
|
+
try {
|
|
789
|
+
const output = execFileSync('node', [
|
|
790
|
+
scriptPath,
|
|
791
|
+
'--sections', args.sections.join(','),
|
|
792
|
+
'--project-dir', PROJECT_DIR,
|
|
793
|
+
'--max-concurrent', String(args.maxConcurrent),
|
|
794
|
+
], {
|
|
795
|
+
encoding: 'utf8',
|
|
796
|
+
timeout: 120000,
|
|
797
|
+
env: { ...process.env, CLAUDE_PROJECT_DIR: PROJECT_DIR },
|
|
798
|
+
});
|
|
799
|
+
return JSON.parse(output.trim());
|
|
800
|
+
}
|
|
801
|
+
catch (err) {
|
|
802
|
+
// Attempt to parse stdout from the error (script may have written partial results)
|
|
803
|
+
const execErr = err;
|
|
804
|
+
if (execErr.stdout) {
|
|
805
|
+
try {
|
|
806
|
+
return JSON.parse(execErr.stdout.trim());
|
|
807
|
+
}
|
|
808
|
+
catch {
|
|
809
|
+
// Fall through to error return
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
return { error: `force-spawn-tasks.js failed: ${execErr.message ?? String(err)}` };
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
function forceTriageReports() {
|
|
816
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
817
|
+
const frameworkRoot = path.resolve(path.dirname(thisFile), '..', '..', '..', '..');
|
|
818
|
+
const scriptPath = path.join(frameworkRoot, 'scripts', 'force-triage-reports.js');
|
|
819
|
+
if (!fs.existsSync(scriptPath)) {
|
|
820
|
+
return { error: `force-triage-reports.js not found at ${scriptPath}. Framework root resolved to: ${frameworkRoot}` };
|
|
821
|
+
}
|
|
822
|
+
try {
|
|
823
|
+
const output = execFileSync('node', [
|
|
824
|
+
scriptPath,
|
|
825
|
+
'--project-dir', PROJECT_DIR,
|
|
826
|
+
], {
|
|
827
|
+
encoding: 'utf8',
|
|
828
|
+
timeout: 120000,
|
|
829
|
+
env: { ...process.env, CLAUDE_PROJECT_DIR: PROJECT_DIR },
|
|
830
|
+
});
|
|
831
|
+
return JSON.parse(output.trim());
|
|
832
|
+
}
|
|
833
|
+
catch (err) {
|
|
834
|
+
const execErr = err;
|
|
835
|
+
if (execErr.stdout) {
|
|
836
|
+
try {
|
|
837
|
+
return JSON.parse(execErr.stdout.trim());
|
|
838
|
+
}
|
|
839
|
+
catch {
|
|
840
|
+
// Fall through to error return
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
return { error: `force-triage-reports.js failed: ${execErr.message ?? String(err)}` };
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
// ============================================================================
|
|
847
|
+
// Server Setup
|
|
848
|
+
// ============================================================================
|
|
849
|
+
const tools = [
|
|
850
|
+
{
|
|
851
|
+
name: 'list_spawned_agents',
|
|
852
|
+
description: 'List all Claude agents spawned by hooks. Returns agent ID, type, description, timestamp, and prompt preview.',
|
|
853
|
+
schema: ListSpawnedAgentsArgsSchema,
|
|
854
|
+
handler: listAgents,
|
|
855
|
+
},
|
|
856
|
+
{
|
|
857
|
+
name: 'get_agent_prompt',
|
|
858
|
+
description: 'Get the full prompt that was given to a spawned agent',
|
|
859
|
+
schema: GetAgentPromptArgsSchema,
|
|
860
|
+
handler: getAgentPrompt,
|
|
861
|
+
},
|
|
862
|
+
{
|
|
863
|
+
name: 'get_agent_session',
|
|
864
|
+
description: 'Get the full session transcript for a spawned agent (if available). Sessions are stored in ~/.claude/projects/ as JSONL files.',
|
|
865
|
+
schema: GetAgentSessionArgsSchema,
|
|
866
|
+
handler: getAgentSession,
|
|
867
|
+
},
|
|
868
|
+
{
|
|
869
|
+
name: 'get_agent_stats',
|
|
870
|
+
description: 'Get statistics about spawned agents: totals by type, by hook, and time-based metrics',
|
|
871
|
+
schema: GetAgentStatsArgsSchema,
|
|
872
|
+
handler: getAgentStats,
|
|
873
|
+
},
|
|
874
|
+
// Concurrency & Force-Spawn Tools
|
|
875
|
+
{
|
|
876
|
+
name: 'get_concurrency_status',
|
|
877
|
+
description: 'Get real-time concurrency status: running agent count, max allowed, available slots, and tracked running agents by type.',
|
|
878
|
+
schema: GetConcurrencyStatusArgsSchema,
|
|
879
|
+
handler: getConcurrencyStatus,
|
|
880
|
+
},
|
|
881
|
+
{
|
|
882
|
+
name: 'force_spawn_tasks',
|
|
883
|
+
description: 'Force-spawn all pending TODO tasks for the specified sections immediately, bypassing age filters, batch limits, cooldowns, and CTO activity gate. Preserves concurrency guard and task tracking.',
|
|
884
|
+
schema: ForceSpawnTasksArgsSchema,
|
|
885
|
+
handler: forceSpawnTasks,
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
name: 'force_triage_reports',
|
|
889
|
+
description: 'Force-spawn a deputy-CTO triage agent to process all pending reports immediately, bypassing the hourly automation triage interval. Returns the spawned agent ID, PID, and session ID.',
|
|
890
|
+
schema: ForceTriageReportsArgsSchema,
|
|
891
|
+
handler: forceTriageReports,
|
|
892
|
+
},
|
|
893
|
+
// Session Browser Tools
|
|
894
|
+
{
|
|
895
|
+
name: 'list_sessions',
|
|
896
|
+
description: 'List all Claude Code sessions for this project with optional hook metadata. Shows which sessions were spawned by hooks vs manual user sessions.',
|
|
897
|
+
schema: ListSessionsArgsSchema,
|
|
898
|
+
handler: listSessions,
|
|
899
|
+
},
|
|
900
|
+
{
|
|
901
|
+
name: 'search_sessions',
|
|
902
|
+
description: 'Search across all session content. Returns matching sessions with preview context. Useful for finding specific conversations or debugging.',
|
|
903
|
+
schema: SearchSessionsArgsSchema,
|
|
904
|
+
handler: searchSessions,
|
|
905
|
+
},
|
|
906
|
+
{
|
|
907
|
+
name: 'get_session_summary',
|
|
908
|
+
description: 'Get detailed summary of a specific session including message counts, tools used, duration estimate, and first user message.',
|
|
909
|
+
schema: GetSessionSummaryArgsSchema,
|
|
910
|
+
handler: getSessionSummary,
|
|
911
|
+
},
|
|
912
|
+
];
|
|
913
|
+
const server = new McpServer({
|
|
914
|
+
name: 'agent-tracker',
|
|
915
|
+
version: '4.0.0', // Added concurrency status + force-spawn tools
|
|
916
|
+
tools,
|
|
917
|
+
});
|
|
918
|
+
server.start();
|
|
919
|
+
//# sourceMappingURL=server.js.map
|