@rubytech/create-realagent-code 0.1.593 → 0.1.594
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/package.json +2 -2
- package/payload/platform/package.json +1 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +5 -3
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +5 -0
- package/payload/platform/plugins/cloudflare/PLUGIN.md +2 -0
- package/payload/platform/plugins/docs/references/internals.md +1 -1
- package/payload/platform/plugins/docs/references/telegram-guide.md +3 -1
- package/payload/platform/scripts/__tests__/agent-identity-reconcile.test.sh +110 -0
- package/payload/platform/scripts/__tests__/check-orphan-dist.test.sh +87 -0
- package/payload/platform/scripts/check-orphan-dist.mjs +143 -0
- package/payload/platform/scripts/lib/agent-identity-reconcile.sh +122 -0
- package/payload/platform/scripts/lib/provision-account-dir.sh +8 -26
- package/payload/platform/scripts/setup-account.sh +15 -0
- package/payload/platform/services/claude-session-manager/dist/index.js +5 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts +5 -0
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js +42 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js.map +1 -1
- package/payload/platform/templates/agents/public/IDENTITY.md +3 -3
- package/payload/platform/lib/anthropic-key/dist/index.d.ts +0 -22
- package/payload/platform/lib/anthropic-key/dist/index.d.ts.map +0 -1
- package/payload/platform/lib/anthropic-key/dist/index.js +0 -232
- package/payload/platform/lib/anthropic-key/dist/index.js.map +0 -1
- package/payload/platform/lib/graph-search/dist/query-expansion.d.ts +0 -37
- package/payload/platform/lib/graph-search/dist/query-expansion.d.ts.map +0 -1
- package/payload/platform/lib/graph-search/dist/query-expansion.js +0 -101
- package/payload/platform/lib/graph-search/dist/query-expansion.js.map +0 -1
- package/payload/platform/lib/oauth-llm/dist/index.d.ts +0 -116
- package/payload/platform/lib/oauth-llm/dist/index.d.ts.map +0 -1
- package/payload/platform/lib/oauth-llm/dist/index.js +0 -386
- package/payload/platform/lib/oauth-llm/dist/index.js.map +0 -1
- package/payload/platform/lib/screening-patterns/dist/index.d.ts +0 -29
- package/payload/platform/lib/screening-patterns/dist/index.d.ts.map +0 -1
- package/payload/platform/lib/screening-patterns/dist/index.js +0 -48
- package/payload/platform/lib/screening-patterns/dist/index.js.map +0 -1
- package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-identity-authenticate.test.d.ts +0 -2
- package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-identity-authenticate.test.d.ts.map +0 -1
- package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-identity-authenticate.test.js +0 -34
- package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-identity-authenticate.test.js.map +0 -1
- package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.d.ts +0 -39
- package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.d.ts.map +0 -1
- package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.js +0 -249
- package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.js.map +0 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/admin-identity-authenticate.d.ts +0 -6
- package/payload/platform/plugins/admin/mcp/dist/tools/admin-identity-authenticate.d.ts.map +0 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/admin-identity-authenticate.js +0 -32
- package/payload/platform/plugins/admin/mcp/dist/tools/admin-identity-authenticate.js.map +0 -1
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.d.ts +0 -283
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.d.ts.map +0 -1
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.js +0 -1155
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.js.map +0 -1
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.d.ts +0 -90
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.d.ts.map +0 -1
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.js +0 -551
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.js.map +0 -1
- package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.d.ts +0 -17
- package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.d.ts.map +0 -1
- package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js +0 -186
- package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js.map +0 -1
- package/payload/platform/plugins/email/mcp/dist/lib/screening.d.ts +0 -29
- package/payload/platform/plugins/email/mcp/dist/lib/screening.d.ts.map +0 -1
- package/payload/platform/plugins/email/mcp/dist/lib/screening.js +0 -105
- package/payload/platform/plugins/email/mcp/dist/lib/screening.js.map +0 -1
- package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.d.ts +0 -38
- package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.d.ts.map +0 -1
- package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.js +0 -817
- package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.js.map +0 -1
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.d.ts +0 -30
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.d.ts.map +0 -1
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js +0 -215
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js.map +0 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-auto-respond-config.d.ts +0 -19
- package/payload/platform/plugins/email/mcp/dist/tools/email-auto-respond-config.d.ts.map +0 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-auto-respond-config.js +0 -151
- package/payload/platform/plugins/email/mcp/dist/tools/email-auto-respond-config.js.map +0 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-classify.d.ts +0 -6
- package/payload/platform/plugins/email/mcp/dist/tools/email-classify.d.ts.map +0 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-classify.js +0 -89
- package/payload/platform/plugins/email/mcp/dist/tools/email-classify.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-rewriter-operator-hint.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-rewriter-operator-hint.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-rewriter-operator-hint.test.js +0 -90
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-rewriter-operator-hint.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js +0 -226
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.d.ts +0 -60
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.js +0 -169
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts +0 -248
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js +0 -824
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.d.ts +0 -63
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.js +0 -210
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts +0 -35
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.js +0 -28
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights-emit.test.js +0 -68
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-emit.test.js +0 -88
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-classify-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-classify-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-classify-emit.test.js +0 -58
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-classify-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-emit.test.js +0 -64
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edit-attachment-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edit-attachment-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edit-attachment-emit.test.js +0 -70
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edit-attachment-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-emit.test.js +0 -48
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-emit.test.js +0 -74
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-extract-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-extract-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-extract-emit.test.js +0 -47
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-extract-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-web-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-web-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-web-emit.test.js +0 -65
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-web-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-emit.test.js +0 -43
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-rename-attachment-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-rename-attachment-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-rename-attachment-emit.test.js +0 -65
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-rename-attachment-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-restore-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-restore-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-restore-emit.test.js +0 -49
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-restore-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js +0 -79
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-operator-hint.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-operator-hint.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-operator-hint.test.js +0 -329
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-operator-hint.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js +0 -81
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-classify.d.ts +0 -34
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-classify.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-classify.js +0 -62
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-classify.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-rank.d.ts +0 -61
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-rank.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-rank.js +0 -102
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-rank.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-signals-recent.d.ts +0 -35
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-signals-recent.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-signals-recent.js +0 -73
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-signals-recent.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +0 -29
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +0 -22
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.d.ts +0 -30
- package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.js +0 -130
- package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.js.map +0 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.d.ts +0 -65
- package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.d.ts.map +0 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.js +0 -262
- package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.js.map +0 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.d.ts +0 -2
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.d.ts.map +0 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.js +0 -100
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.js.map +0 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/scheduled-seat-id.test.d.ts +0 -2
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/scheduled-seat-id.test.d.ts.map +0 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/scheduled-seat-id.test.js +0 -22
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/scheduled-seat-id.test.js.map +0 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/scheduled-seat-id.d.ts +0 -11
- package/payload/platform/plugins/scheduling/mcp/dist/lib/scheduled-seat-id.d.ts.map +0 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/scheduled-seat-id.js +0 -19
- package/payload/platform/plugins/scheduling/mcp/dist/lib/scheduled-seat-id.js.map +0 -1
- package/payload/platform/plugins/url-get/mcp/dist/lib/summarise.d.ts +0 -8
- package/payload/platform/plugins/url-get/mcp/dist/lib/summarise.d.ts.map +0 -1
- package/payload/platform/plugins/url-get/mcp/dist/lib/summarise.js +0 -83
- package/payload/platform/plugins/url-get/mcp/dist/lib/summarise.js.map +0 -1
- package/payload/platform/plugins/workflows/mcp/dist/lib/llm-call.d.ts +0 -151
- package/payload/platform/plugins/workflows/mcp/dist/lib/llm-call.d.ts.map +0 -1
- package/payload/platform/plugins/workflows/mcp/dist/lib/llm-call.js +0 -299
- package/payload/platform/plugins/workflows/mcp/dist/lib/llm-call.js.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/account-admin-census.d.ts +0 -39
- package/payload/platform/services/claude-session-manager/dist/account-admin-census.d.ts.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/account-admin-census.js +0 -122
- package/payload/platform/services/claude-session-manager/dist/account-admin-census.js.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/admin-identity-audit.d.ts +0 -39
- package/payload/platform/services/claude-session-manager/dist/admin-identity-audit.d.ts.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/admin-identity-audit.js +0 -133
- package/payload/platform/services/claude-session-manager/dist/admin-identity-audit.js.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/input-postcondition.d.ts +0 -22
- package/payload/platform/services/claude-session-manager/dist/input-postcondition.d.ts.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/input-postcondition.js +0 -50
- package/payload/platform/services/claude-session-manager/dist/input-postcondition.js.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.d.ts +0 -30
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.d.ts.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js +0 -204
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.d.ts +0 -80
- package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.d.ts.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.js +0 -306
- package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.js.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/session-store.d.ts +0 -49
- package/payload/platform/services/claude-session-manager/dist/session-store.d.ts.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/session-store.js +0 -52
- package/payload/platform/services/claude-session-manager/dist/session-store.js.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/systemd-spawn.d.ts +0 -83
- package/payload/platform/services/claude-session-manager/dist/systemd-spawn.d.ts.map +0 -1
- package/payload/platform/services/claude-session-manager/dist/systemd-spawn.js +0 -345
- package/payload/platform/services/claude-session-manager/dist/systemd-spawn.js.map +0 -1
- package/payload/platform/services/telegram-channel/dist/turn-follow.d.ts +0 -104
- package/payload/platform/services/telegram-channel/dist/turn-follow.d.ts.map +0 -1
- package/payload/platform/services/telegram-channel/dist/turn-follow.js +0 -408
- package/payload/platform/services/telegram-channel/dist/turn-follow.js.map +0 -1
- package/payload/platform/services/whatsapp-channel/dist/turn-follow.d.ts +0 -104
- package/payload/platform/services/whatsapp-channel/dist/turn-follow.d.ts.map +0 -1
- package/payload/platform/services/whatsapp-channel/dist/turn-follow.js +0 -393
- package/payload/platform/services/whatsapp-channel/dist/turn-follow.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rubytech/create-realagent-code",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.594",
|
|
4
4
|
"description": "Install Real Agent — Built for agents. By agents.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-realagent-code": "./dist/index.js"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"build": "tsc",
|
|
14
14
|
"bundle": "node scripts/bundle.js",
|
|
15
15
|
"test": "npm run build && node --test 'dist/__tests__/*.test.js'",
|
|
16
|
-
"prepublishOnly": "bash ../../platform/scripts/verify-skill-tool-surface.sh && node ../../platform/scripts/check-plugin-tools-mcp-consistency.mjs && node ../../platform/scripts/check-risk-class.mjs && node ../../platform/scripts/check-specialist-tool-surface.mjs && node ../../platform/scripts/check-agent-contract.mjs && node ../../platform/scripts/check-routing-prose-bash.mjs && node ../../platform/scripts/check-no-task-id-leaks.mjs && node ../../platform/scripts/check-no-esm-require.mjs && node ../../platform/scripts/check-no-raw-mcp-registrations.mjs && node ../../platform/scripts/check-skill-load-coverage.mjs && node ../../platform/scripts/check-routine-roster-doc.mjs && node ../../platform/scripts/check-architecture-skill-no-drift.mjs && node ../../platform/ui/scripts/check-brand-fonts.mjs && node ../../platform/ui/scripts/check-route-wiring.mjs && node ../../platform/ui/scripts/check-edge-admin-routes.mjs && npm run build && node --test 'dist/__tests__/*.test.js' && chmod +x dist/index.js && npm run bundle && bash ../../platform/scripts/smoke-boot-services.sh && node ../../platform/ui/scripts/check-bundle-node-imports.mjs --dir=./payload/server/public/assets"
|
|
16
|
+
"prepublishOnly": "bash ../../platform/scripts/verify-skill-tool-surface.sh && node ../../platform/scripts/check-plugin-tools-mcp-consistency.mjs && node ../../platform/scripts/check-risk-class.mjs && node ../../platform/scripts/check-specialist-tool-surface.mjs && node ../../platform/scripts/check-agent-contract.mjs && node ../../platform/scripts/check-routing-prose-bash.mjs && node ../../platform/scripts/check-no-task-id-leaks.mjs && node ../../platform/scripts/check-no-esm-require.mjs && node ../../platform/scripts/check-no-raw-mcp-registrations.mjs && node ../../platform/scripts/check-skill-load-coverage.mjs && node ../../platform/scripts/check-routine-roster-doc.mjs && node ../../platform/scripts/check-architecture-skill-no-drift.mjs && node ../../platform/ui/scripts/check-brand-fonts.mjs && node ../../platform/ui/scripts/check-route-wiring.mjs && node ../../platform/ui/scripts/check-edge-admin-routes.mjs && npm run build && node --test 'dist/__tests__/*.test.js' && chmod +x dist/index.js && node ../../platform/scripts/check-orphan-dist.mjs && npm run bundle && bash ../../platform/scripts/smoke-boot-services.sh && node ../../platform/ui/scripts/check-bundle-node-imports.mjs --dir=./payload/server/public/assets"
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"dist",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"scripts": {
|
|
13
13
|
"build": "tsc -p lib/account-schema-regions/tsconfig.json && tsc -p lib/account-ingest-token/tsconfig.json && tsc -p lib/models/tsconfig.json && tsc -p lib/agent-slug/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/mcp-lifeline/tsconfig.json && tsc -p lib/mcp-eager/tsconfig.json && tsc -p lib/account-enumeration/tsconfig.json && tsc -p lib/account-scope/tsconfig.json && tsc -p lib/shared-folder/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/ledger-core/tsconfig.json && tsc -p lib/embed-client/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/active-rules/tsconfig.json && tsc -p lib/admin-conversation-purge/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/graph-style/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p lib/entitlement/tsconfig.json && tsc -p lib/task-secrets/tsconfig.json && tsc -p lib/admins-write/tsconfig.json && tsc -p lib/admin-access-password/tsconfig.json && tsc -p lib/persistent-components/tsconfig.json && tsc -p lib/require-port-env/tsconfig.json && tsc -p lib/aeo-llms-txt-writer/tsconfig.json && tsc -p lib/obsidian-parser/tsconfig.json && tsc -p lib/storage-broker/tsconfig.json && tsc -p lib/routine-templates/tsconfig.json && tsc -p lib/agent-dispatch-rule/tsconfig.json && tsc -p lib/canonical-instant/tsconfig.json && tsc -p lib/dispatch-read/tsconfig.json && tsc -p lib/dispatch-write/tsconfig.json && tsc -p lib/learning-constants/tsconfig.json && tsc -p lib/telegram-media/tsconfig.json && tsc -p lib/telegram-managed-bot/tsconfig.json && tsc -p lib/telegram-reach/tsconfig.json && tsc -p services/claude-session-manager/tsconfig.json && tsc -p services/whatsapp-channel/tsconfig.json && tsc -p services/webchat-channel/tsconfig.json && tsc -p services/telegram-channel/tsconfig.json && NODE_OPTIONS='--max-old-space-size=8192' tsc -b plugins/*/mcp/tsconfig.json",
|
|
14
14
|
"build:lib": "tsc -p lib/account-schema-regions/tsconfig.json && tsc -p lib/account-ingest-token/tsconfig.json && tsc -p lib/models/tsconfig.json && tsc -p lib/agent-slug/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/mcp-lifeline/tsconfig.json && tsc -p lib/mcp-eager/tsconfig.json && tsc -p lib/account-enumeration/tsconfig.json && tsc -p lib/account-scope/tsconfig.json && tsc -p lib/shared-folder/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/ledger-core/tsconfig.json && tsc -p lib/embed-client/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/active-rules/tsconfig.json && tsc -p lib/admin-conversation-purge/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/graph-style/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p lib/entitlement/tsconfig.json && tsc -p lib/task-secrets/tsconfig.json && tsc -p lib/admins-write/tsconfig.json && tsc -p lib/admin-access-password/tsconfig.json && tsc -p lib/persistent-components/tsconfig.json && tsc -p lib/require-port-env/tsconfig.json && tsc -p lib/aeo-llms-txt-writer/tsconfig.json && tsc -p lib/obsidian-parser/tsconfig.json && tsc -p lib/storage-broker/tsconfig.json && tsc -p lib/routine-templates/tsconfig.json && tsc -p lib/agent-dispatch-rule/tsconfig.json && tsc -p lib/shared-folder/tsconfig.json && tsc -p lib/canonical-instant/tsconfig.json && tsc -p lib/dispatch-read/tsconfig.json && tsc -p lib/dispatch-write/tsconfig.json && tsc -p lib/telegram-media/tsconfig.json && tsc -p lib/telegram-managed-bot/tsconfig.json && tsc -p lib/telegram-reach/tsconfig.json",
|
|
15
|
+
"clean:dist": "node scripts/check-orphan-dist.mjs --remove",
|
|
15
16
|
"gen:canonical-tools": "node scripts/generate-canonical-tool-names.mjs",
|
|
16
17
|
"build:memory": "tsc -p plugins/memory/mcp/tsconfig.json",
|
|
17
18
|
"build:contacts": "tsc -p plugins/contacts/mcp/tsconfig.json",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-architecture
|
|
3
3
|
description: Use when grounding any documented-surface claim about what Real Agent ships — plugins, skills, specialists, install/deploy flows, internals. This is the install catalogue, not evidence of what is enabled on the current account. For install state on this account, call `capabilities-here`; for documented surface, cite the `Source:` URL inline.
|
|
4
|
-
content-hash: sha256:
|
|
4
|
+
content-hash: sha256:ea35aa77226e01aad93c7b90e9118e4e993a58cb980330b28541dcbb3122a993
|
|
5
5
|
brand: realagent-code
|
|
6
6
|
product-name: Real Agent
|
|
7
7
|
---
|
|
@@ -2866,7 +2866,9 @@ Real Agent asks for your bot token, then asks what kind of bot this is:
|
|
|
2866
2866
|
|
|
2867
2867
|
- an **admin bot** — only your numeric Telegram IDs may message it, and it answers as your admin agent;
|
|
2868
2868
|
- a **public bot** — customer-facing, with a DM policy, answering as one of your account's agents;
|
|
2869
|
-
- a **specialist bot** — bound to one of your own specialists, so messaging it runs that specialist with its own instructions and its own tools rather than your admin agent. You name the specialist and the numeric IDs allowed to reach it. Both are required: there is no open setting for this kind, because
|
|
2869
|
+
- a **specialist bot** — bound to one of your own specialists, so messaging it runs that specialist with its own instructions and its own tools rather than your admin agent. You name the specialist and the numeric IDs allowed to reach it. Both are required: there is no open setting for this kind, because a specialist carries whatever tools its card gives it, while a public bot is held to a fixed set nobody can widen.
|
|
2870
|
+
|
|
2871
|
+
A public Telegram bot holds five things and nothing else: the reply that carries its answer, cards with tappable buttons, polls and quizzes and map pins, outgoing photos and documents and voice notes, and the ability to open a file a visitor sent it. That set is fixed by the platform for every public agent on every account, so there is no tools setting on an agent to turn any of it on or off. A public bot on webchat or WhatsApp still has the reply alone, because those channels ship no equivalent set.
|
|
2870
2872
|
|
|
2871
2873
|
It verifies the token, registers the bot's webhook on your brand's edge, stores the token under your brand's config (never in a shared system directory), and sets whichever agent or specialist will answer. The bot is now connected.
|
|
2872
2874
|
|
|
@@ -6455,7 +6457,7 @@ For subagents, the same spawn pushes `--add-dir` for every bundled plugin agents
|
|
|
6455
6457
|
|
|
6456
6458
|
A boot gate refuses to start the manager when any admin-allowlisted tool `mcp__<plugin>__*` lacks a registered server. The signal is `boot-failed reason=mcp-allowlist-without-server plugin=<p> tool=<t>` followed by `process.exit(1)`. The remediation is a one-line edit to the named `PLUGIN.md`: add the `mcp:` block. The complementary observability emit `mcp-config-allowlist-coverage admin-tools=A admin-registered=R` (where `A === R`) confirms the invariant per boot.
|
|
6457
6459
|
|
|
6458
|
-
**Whether a plugin's server mounts is decided by the generated manifest, not the `mcp:` block.** A plugin ships its MCP as `mcp/`; the manifest generator ([`scripts/generate-plugin-manifests.mjs`](../../../../scripts/generate-plugin-manifests.mjs), run at bundle time over the payload) reads the plugin's `mcp-manifest:` frontmatter. `auto` emits an `mcpServers` block into the generated `.claude-plugin/plugin.json` — routed through `lib/mcp-spawn-tee`, carrying no per-session env (`LOG_DIR`/`SESSION_ID`/`ACCOUNT_ID`/`NEO4J_*`/`PLATFORM_ROOT` ride the PTY env block described above) — and copies the tee into the plugin's `lib/`; `skip` emits nothing, so Claude Code never spawns the server. The generator recognises two server shapes. A plugin-local `mcp/` (its `hasMcp` check: `mcp/dist/index.js` or `mcp/package.json`) uses `auto` or `skip`. A tool-plugin whose `mcp:` server is a shared `platform/lib/<name>` binary rather than a plugin-local `mcp/` (e.g. `graph`, served by `platform/lib/graph-mcp`) is annotated `mcp-manifest: shared-lib`: the generator emits that plugin's `mcp:` block verbatim into `mcpServers` — command, args (anchored on `${PLATFORM_ROOT}`, routed through the shared `lib/mcp-spawn-tee`), and env — which Claude Code expands at spawn from the PTY env block. No tee copy is made into the plugin, because both the tee and the server resolve from `${PLATFORM_ROOT}` outside the per-plugin cache. `graph` is the one shared-lib tool-plugin; every other tool-plugin ships a plugin-local `mcp/` and uses `auto`. A plugin with an `mcp:` block, no plugin-local `mcp/`, and no `mcp-manifest: shared-lib` annotation is a FATAL at generation time. Premium plugins import platform libs (`mcp-lifeline`, etc.) via a source-tree relative path; the bundler's premium-lib shipper (`packages/create-maxy-code/scripts/bundle.js`) rewrites that path and vendors each referenced `platform/lib/<name>` into `premium-plugins/<bundle>/lib/<name>/`, so the auto-mounted dist resolves its imports. The `mcp-allowlist-without-server` gate above proves only that a plugin's PLUGIN.md `mcp:` block matches its allowlist — it reads source, not the generated manifest — so a plugin left on `skip` passes that gate while its server silently never mounts (its tools are listed but not live). The `tool-registration` gate below closes that blind spot.
|
|
6460
|
+
**Whether a plugin's server mounts is decided by the generated manifest, not the `mcp:` block.** A plugin ships its MCP as `mcp/`; the manifest generator ([`scripts/generate-plugin-manifests.mjs`](../../../../scripts/generate-plugin-manifests.mjs), run at bundle time over the payload) reads the plugin's `mcp-manifest:` frontmatter. `auto` emits an `mcpServers` block into the generated `.claude-plugin/plugin.json` — routed through `lib/mcp-spawn-tee`, carrying no per-session env (`LOG_DIR`/`SESSION_ID`/`ACCOUNT_ID`/`NEO4J_*`/`PLATFORM_ROOT` ride the PTY env block described above) — and copies the tee into the plugin's `lib/`; `skip` emits nothing, so Claude Code never spawns the server. `skip` covers two shapes: a plugin whose canonical surface is a user-scoped MCP, and a plugin that registers zero tools and keeps `mcp/` only as a test host — `cloudflare` is the latter, so its `skip` is not a pointer to a server elsewhere. The generator recognises two server shapes. A plugin-local `mcp/` (its `hasMcp` check: `mcp/dist/index.js` or `mcp/package.json`) uses `auto` or `skip`. A tool-plugin whose `mcp:` server is a shared `platform/lib/<name>` binary rather than a plugin-local `mcp/` (e.g. `graph`, served by `platform/lib/graph-mcp`) is annotated `mcp-manifest: shared-lib`: the generator emits that plugin's `mcp:` block verbatim into `mcpServers` — command, args (anchored on `${PLATFORM_ROOT}`, routed through the shared `lib/mcp-spawn-tee`), and env — which Claude Code expands at spawn from the PTY env block. No tee copy is made into the plugin, because both the tee and the server resolve from `${PLATFORM_ROOT}` outside the per-plugin cache. `graph` is the one shared-lib tool-plugin; every other tool-plugin ships a plugin-local `mcp/` and uses `auto`. A plugin with an `mcp:` block, no plugin-local `mcp/`, and no `mcp-manifest: shared-lib` annotation is a FATAL at generation time. Premium plugins import platform libs (`mcp-lifeline`, etc.) via a source-tree relative path; the bundler's premium-lib shipper (`packages/create-maxy-code/scripts/bundle.js`) rewrites that path and vendors each referenced `platform/lib/<name>` into `premium-plugins/<bundle>/lib/<name>/`, so the auto-mounted dist resolves its imports. The `mcp-allowlist-without-server` gate above proves only that a plugin's PLUGIN.md `mcp:` block matches its allowlist — it reads source, not the generated manifest — so a plugin left on `skip` passes that gate while its server silently never mounts (its tools are listed but not live). The `tool-registration` gate below closes that blind spot.
|
|
6459
6461
|
|
|
6460
6462
|
A second boot gate walks every specialist `.md` under `platform/templates/specialists/agents/`, every bundled `<plugin>/agents/` directory, and the per-account `<accountDir>/specialists/agents/` directory, parses each file's `tools:` frontmatter line (canonical long-prefix names), and classifies every tool name as one of: CC-native (Read, Bash, …), a tool the loaded `PLUGIN.md` set actually serves (matched as the long canonical name in `toolSurface.all`), a third-party MCP bridge (a `mcp__plugin_*` name whose plugin segment is NOT a maxy platform plugin — Playwright etc., upstream-owned, passes unconditionally), `unknown-tool-in-plugin` (maxy plugin namespace served but tool name absent), `unknown-plugin-namespace` (namespace served by nothing), `brand-excluded-plugin` (namespace served by nothing on this brand, **but** the brand's `brand.json#plugins.excluded` list names it), or `malformed-name` (not CC-native and not `mcp__`-shaped). The first three pass. The next two refuse boot with one `boot-failed reason=specialist-tool-drift specialist=<name> tool=<t> drift=<class> path=<…>` line per defect, then `process.exit(1)`. A maxy-plugin `mcp__plugin_*` name is validated against `toolSurface.all`, so a typo or stale long-prefix tool name still refuses boot rather than passing as a bridge; the build-time `check-canonical-tool-names.mjs` gate catches the same drift in instruction files before publish. `brand-excluded-plugin` is a structural pass: it lands in a per-specialist strip-list, the manager continues to boot, and at spawn time `pty-spawner` removes those tool names from the `--agent <name>` spawn's `--allowed-tools` argv. The complementary observability emit `specialist-tool-strip specialist=<name> plugin=<p> tools=<csv> reason=brand-excluded` fires one line per stripped (specialist, plugin) pair so an operator who reads `server.log` sees the brand filter doing work without cross-referencing `brand.json` against the template. The startup-self-test line `startup-self-test specialist-tool-drift=ok inspected=<N> stripped-specialists=<M>` confirms the gate ran and how many specialists carry strip-lists.
|
|
6461
6463
|
|
|
@@ -9,6 +9,11 @@ Invoked by the admin agent directly.
|
|
|
9
9
|
|
|
10
10
|
This is the platform's release timeline, newest first. Each entry shows the date it shipped and the version it shipped in, so you can tell the operator how current their install is. To compare, read the installed version from `capabilities-here` and match it against the versions below. Keep answers high level and in plain English; this is a summary, not a full commit log.
|
|
11
11
|
|
|
12
|
+
## 2026-08-11 (0.1.594)
|
|
13
|
+
|
|
14
|
+
- A public Telegram bot no longer tells people it cannot do things it can. Its own description denied the tools it had actually been given, so it refused work it was equipped for.
|
|
15
|
+
- Code deleted from the platform no longer ships anyway. Removing a source file left its compiled output behind, so retired code was still being packaged and installed.
|
|
16
|
+
|
|
12
17
|
## 2026-08-11 (0.1.593)
|
|
13
18
|
|
|
14
19
|
- A public Telegram bot can now use buttons, media and the rest of the channel. It held no tool at all, so every answer it gave was plain text.
|
|
@@ -28,6 +28,8 @@ Each installation has its own Cloudflare account. Two auth paths serve two opera
|
|
|
28
28
|
|
|
29
29
|
The plugin registers no agent-facing MCP tools. Every Cloudflare operation is the agent invoking `cloudflared` or `wrangler` directly via Bash, or calling the Cloudflare API with a reused per-scope narrow token, with stdout/stderr streamed verbatim into the PTY chat (secrets redacted). The OAuth URL printed by `cloudflared tunnel login` is linkified by the native PTY; the operator clicks it in their own browser. The one shell helper is [bin/cf-token.sh](bin/cf-token.sh), a deterministic per-scope token resolver that faithfully relays the Cloudflare token API (it invents no flags and drives no dashboard); there is no wrapper around `cloudflared` or `wrangler`, no orchestrator state machine, no MCP-tool surface.
|
|
30
30
|
|
|
31
|
+
The frontmatter carries `mcp-manifest: skip` because the manifest generator requires an annotation from any plugin with an `mcp/` directory, and `skip` is the value that emits no `mcpServers` block. It does not mean the tools live in a user-scoped server somewhere else: there are none. `mcp/` survives only as the test host for `bin/` and for the skill templates' Pages Functions; its entry point registers nothing.
|
|
32
|
+
|
|
31
33
|
### Skills
|
|
32
34
|
|
|
33
35
|
| Skill | Purpose |
|
|
@@ -501,7 +501,7 @@ For subagents, the same spawn pushes `--add-dir` for every bundled plugin agents
|
|
|
501
501
|
|
|
502
502
|
A boot gate refuses to start the manager when any admin-allowlisted tool `mcp__<plugin>__*` lacks a registered server. The signal is `boot-failed reason=mcp-allowlist-without-server plugin=<p> tool=<t>` followed by `process.exit(1)`. The remediation is a one-line edit to the named `PLUGIN.md`: add the `mcp:` block. The complementary observability emit `mcp-config-allowlist-coverage admin-tools=A admin-registered=R` (where `A === R`) confirms the invariant per boot.
|
|
503
503
|
|
|
504
|
-
**Whether a plugin's server mounts is decided by the generated manifest, not the `mcp:` block.** A plugin ships its MCP as `mcp/`; the manifest generator ([`scripts/generate-plugin-manifests.mjs`](../../../../scripts/generate-plugin-manifests.mjs), run at bundle time over the payload) reads the plugin's `mcp-manifest:` frontmatter. `auto` emits an `mcpServers` block into the generated `.claude-plugin/plugin.json` — routed through `lib/mcp-spawn-tee`, carrying no per-session env (`LOG_DIR`/`SESSION_ID`/`ACCOUNT_ID`/`NEO4J_*`/`PLATFORM_ROOT` ride the PTY env block described above) — and copies the tee into the plugin's `lib/`; `skip` emits nothing, so Claude Code never spawns the server. The generator recognises two server shapes. A plugin-local `mcp/` (its `hasMcp` check: `mcp/dist/index.js` or `mcp/package.json`) uses `auto` or `skip`. A tool-plugin whose `mcp:` server is a shared `platform/lib/<name>` binary rather than a plugin-local `mcp/` (e.g. `graph`, served by `platform/lib/graph-mcp`) is annotated `mcp-manifest: shared-lib`: the generator emits that plugin's `mcp:` block verbatim into `mcpServers` — command, args (anchored on `${PLATFORM_ROOT}`, routed through the shared `lib/mcp-spawn-tee`), and env — which Claude Code expands at spawn from the PTY env block. No tee copy is made into the plugin, because both the tee and the server resolve from `${PLATFORM_ROOT}` outside the per-plugin cache. `graph` is the one shared-lib tool-plugin; every other tool-plugin ships a plugin-local `mcp/` and uses `auto`. A plugin with an `mcp:` block, no plugin-local `mcp/`, and no `mcp-manifest: shared-lib` annotation is a FATAL at generation time. Premium plugins import platform libs (`mcp-lifeline`, etc.) via a source-tree relative path; the bundler's premium-lib shipper (`packages/create-maxy-code/scripts/bundle.js`) rewrites that path and vendors each referenced `platform/lib/<name>` into `premium-plugins/<bundle>/lib/<name>/`, so the auto-mounted dist resolves its imports. The `mcp-allowlist-without-server` gate above proves only that a plugin's PLUGIN.md `mcp:` block matches its allowlist — it reads source, not the generated manifest — so a plugin left on `skip` passes that gate while its server silently never mounts (its tools are listed but not live). The `tool-registration` gate below closes that blind spot.
|
|
504
|
+
**Whether a plugin's server mounts is decided by the generated manifest, not the `mcp:` block.** A plugin ships its MCP as `mcp/`; the manifest generator ([`scripts/generate-plugin-manifests.mjs`](../../../../scripts/generate-plugin-manifests.mjs), run at bundle time over the payload) reads the plugin's `mcp-manifest:` frontmatter. `auto` emits an `mcpServers` block into the generated `.claude-plugin/plugin.json` — routed through `lib/mcp-spawn-tee`, carrying no per-session env (`LOG_DIR`/`SESSION_ID`/`ACCOUNT_ID`/`NEO4J_*`/`PLATFORM_ROOT` ride the PTY env block described above) — and copies the tee into the plugin's `lib/`; `skip` emits nothing, so Claude Code never spawns the server. `skip` covers two shapes: a plugin whose canonical surface is a user-scoped MCP, and a plugin that registers zero tools and keeps `mcp/` only as a test host — `cloudflare` is the latter, so its `skip` is not a pointer to a server elsewhere. The generator recognises two server shapes. A plugin-local `mcp/` (its `hasMcp` check: `mcp/dist/index.js` or `mcp/package.json`) uses `auto` or `skip`. A tool-plugin whose `mcp:` server is a shared `platform/lib/<name>` binary rather than a plugin-local `mcp/` (e.g. `graph`, served by `platform/lib/graph-mcp`) is annotated `mcp-manifest: shared-lib`: the generator emits that plugin's `mcp:` block verbatim into `mcpServers` — command, args (anchored on `${PLATFORM_ROOT}`, routed through the shared `lib/mcp-spawn-tee`), and env — which Claude Code expands at spawn from the PTY env block. No tee copy is made into the plugin, because both the tee and the server resolve from `${PLATFORM_ROOT}` outside the per-plugin cache. `graph` is the one shared-lib tool-plugin; every other tool-plugin ships a plugin-local `mcp/` and uses `auto`. A plugin with an `mcp:` block, no plugin-local `mcp/`, and no `mcp-manifest: shared-lib` annotation is a FATAL at generation time. Premium plugins import platform libs (`mcp-lifeline`, etc.) via a source-tree relative path; the bundler's premium-lib shipper (`packages/create-maxy-code/scripts/bundle.js`) rewrites that path and vendors each referenced `platform/lib/<name>` into `premium-plugins/<bundle>/lib/<name>/`, so the auto-mounted dist resolves its imports. The `mcp-allowlist-without-server` gate above proves only that a plugin's PLUGIN.md `mcp:` block matches its allowlist — it reads source, not the generated manifest — so a plugin left on `skip` passes that gate while its server silently never mounts (its tools are listed but not live). The `tool-registration` gate below closes that blind spot.
|
|
505
505
|
|
|
506
506
|
A second boot gate walks every specialist `.md` under `platform/templates/specialists/agents/`, every bundled `<plugin>/agents/` directory, and the per-account `<accountDir>/specialists/agents/` directory, parses each file's `tools:` frontmatter line (canonical long-prefix names), and classifies every tool name as one of: CC-native (Read, Bash, …), a tool the loaded `PLUGIN.md` set actually serves (matched as the long canonical name in `toolSurface.all`), a third-party MCP bridge (a `mcp__plugin_*` name whose plugin segment is NOT a maxy platform plugin — Playwright etc., upstream-owned, passes unconditionally), `unknown-tool-in-plugin` (maxy plugin namespace served but tool name absent), `unknown-plugin-namespace` (namespace served by nothing), `brand-excluded-plugin` (namespace served by nothing on this brand, **but** the brand's `brand.json#plugins.excluded` list names it), or `malformed-name` (not CC-native and not `mcp__`-shaped). The first three pass. The next two refuse boot with one `boot-failed reason=specialist-tool-drift specialist=<name> tool=<t> drift=<class> path=<…>` line per defect, then `process.exit(1)`. A maxy-plugin `mcp__plugin_*` name is validated against `toolSurface.all`, so a typo or stale long-prefix tool name still refuses boot rather than passing as a bridge; the build-time `check-canonical-tool-names.mjs` gate catches the same drift in instruction files before publish. `brand-excluded-plugin` is a structural pass: it lands in a per-specialist strip-list, the manager continues to boot, and at spawn time `pty-spawner` removes those tool names from the `--agent <name>` spawn's `--allowed-tools` argv. The complementary observability emit `specialist-tool-strip specialist=<name> plugin=<p> tools=<csv> reason=brand-excluded` fires one line per stripped (specialist, plugin) pair so an operator who reads `server.log` sees the brand filter doing work without cross-referencing `brand.json` against the template. The startup-self-test line `startup-self-test specialist-tool-drift=ok inspected=<N> stripped-specialists=<M>` confirms the gate ran and how many specialists carry strip-lists.
|
|
507
507
|
|
|
@@ -43,7 +43,9 @@ Tell {{productName}}: "Set up Telegram" or "Configure the Telegram bot." Setup r
|
|
|
43
43
|
|
|
44
44
|
- an **admin bot** — only your numeric Telegram IDs may message it, and it answers as your admin agent;
|
|
45
45
|
- a **public bot** — customer-facing, with a DM policy, answering as one of your account's agents;
|
|
46
|
-
- a **specialist bot** — bound to one of your own specialists, so messaging it runs that specialist with its own instructions and its own tools rather than your admin agent. You name the specialist and the numeric IDs allowed to reach it. Both are required: there is no open setting for this kind, because
|
|
46
|
+
- a **specialist bot** — bound to one of your own specialists, so messaging it runs that specialist with its own instructions and its own tools rather than your admin agent. You name the specialist and the numeric IDs allowed to reach it. Both are required: there is no open setting for this kind, because a specialist carries whatever tools its card gives it, while a public bot is held to a fixed set nobody can widen.
|
|
47
|
+
|
|
48
|
+
A public Telegram bot holds five things and nothing else: the reply that carries its answer, cards with tappable buttons, polls and quizzes and map pins, outgoing photos and documents and voice notes, and the ability to open a file a visitor sent it. That set is fixed by the platform for every public agent on every account, so there is no tools setting on an agent to turn any of it on or off. A public bot on webchat or WhatsApp still has the reply alone, because those channels ship no equivalent set.
|
|
47
49
|
|
|
48
50
|
It verifies the token, registers the bot's webhook on your brand's edge, stores the token under your brand's config (never in a shared system directory), and sets whichever agent or specialist will answer. The bot is now connected.
|
|
49
51
|
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Task 2671 — reconcile_all_accounts_identities converges every account's
|
|
3
|
+
# public-agent IDENTITY.md against the shipped template. The failure it exists
|
|
4
|
+
# for is silent: the re-sync it replaces ran for the house account alone, so a
|
|
5
|
+
# sub-account's agent kept a stale prompt indefinitely and nothing said so.
|
|
6
|
+
set -uo pipefail
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
PLAT_SCRIPTS="$SCRIPT_DIR/.."
|
|
9
|
+
PASS=0; FAIL=0; FAILED=()
|
|
10
|
+
assert_eq() { if [ "$1" = "$2" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); FAILED+=("$3: expected [$2] got [$1]"); fi; }
|
|
11
|
+
|
|
12
|
+
. "$PLAT_SCRIPTS/lib/agent-identity-reconcile.sh"
|
|
13
|
+
|
|
14
|
+
T=$(mktemp -d)
|
|
15
|
+
TPL="$T/IDENTITY.md"
|
|
16
|
+
printf '# Public Agent\n\nShipped text.\n' > "$TPL"
|
|
17
|
+
export MAXY_PUBLIC_IDENTITY_TEMPLATE="$TPL"
|
|
18
|
+
|
|
19
|
+
seed_account() {
|
|
20
|
+
# seed_account <accounts_dir> <account_id>
|
|
21
|
+
local root="$1/$2"
|
|
22
|
+
mkdir -p "$root/agents"
|
|
23
|
+
printf '{"accountId":"%s"}\n' "$2" > "$root/account.json"
|
|
24
|
+
echo "$root"
|
|
25
|
+
}
|
|
26
|
+
seed_agent() {
|
|
27
|
+
# seed_agent <account_root> <slug> <body>
|
|
28
|
+
mkdir -p "$1/agents/$2"
|
|
29
|
+
printf '%s' "$3" > "$1/agents/$2/IDENTITY.md"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
ACCTS="$T/accounts"
|
|
33
|
+
A1="$(seed_account "$ACCTS" aaaaaaaa-0000-0000-0000-000000000001)"
|
|
34
|
+
A2="$(seed_account "$ACCTS" bbbbbbbb-0000-0000-0000-000000000002)"
|
|
35
|
+
|
|
36
|
+
seed_agent "$A1" beagle 'STALE — you have no tools.'
|
|
37
|
+
seed_agent "$A1" admin 'ADMIN identity, never touched.'
|
|
38
|
+
seed_agent "$A1" passive 'PASSIVE identity, never touched.'
|
|
39
|
+
# Byte-identical to the template, so `cp` rather than a command substitution:
|
|
40
|
+
# `$(cat …)` strips the trailing newline and the copy would read as drift.
|
|
41
|
+
mkdir -p "$A2/agents/fares" && cp "$TPL" "$A2/agents/fares/IDENTITY.md"
|
|
42
|
+
# An agent dir with no IDENTITY.md: counted by nothing, created by nothing.
|
|
43
|
+
mkdir -p "$A2/agents/halfmade"
|
|
44
|
+
# A dir with no account.json is not an account.
|
|
45
|
+
mkdir -p "$ACCTS/not-an-account/agents"
|
|
46
|
+
|
|
47
|
+
OUT1="$(reconcile_all_accounts_identities "$ACCTS" 2>&1)"; RC1=$?
|
|
48
|
+
|
|
49
|
+
assert_eq "$RC1" "0" "clean-run-exit-zero"
|
|
50
|
+
assert_eq "$(printf '%s' "$OUT1" | grep -c 'accounts=2 agents=2 divergent=1')" "1" "summary-counts"
|
|
51
|
+
assert_eq "$(cat "$A1/agents/beagle/IDENTITY.md")" "$(cat "$TPL")" "stale-rewritten"
|
|
52
|
+
assert_eq "$(cat "$A1/agents/admin/IDENTITY.md")" "ADMIN identity, never touched." "admin-skipped"
|
|
53
|
+
assert_eq "$(cat "$A1/agents/passive/IDENTITY.md")" "PASSIVE identity, never touched." "passive-skipped"
|
|
54
|
+
assert_eq "$(printf '%s' "$OUT1" | grep -c 'agent=beagle status=updated')" "1" "stale-logged-updated"
|
|
55
|
+
assert_eq "$(printf '%s' "$OUT1" | grep -c 'agent=fares status=already-current')" "1" "current-logged-current"
|
|
56
|
+
assert_eq "$(printf '%s' "$OUT1" | grep -c 'agent=admin\|agent=passive\|agent=halfmade')" "0" "excluded-not-logged"
|
|
57
|
+
assert_eq "$([ -e "$A2/agents/halfmade/IDENTITY.md" ] && echo yes || echo no)" "no" "never-creates"
|
|
58
|
+
|
|
59
|
+
# Second run: same agent count, nothing left divergent. A zero that follows a
|
|
60
|
+
# non-zero is the only zero that proves the pass runs — `divergent=0` on its own
|
|
61
|
+
# is what a stopped counter prints too.
|
|
62
|
+
OUT2="$(reconcile_all_accounts_identities "$ACCTS" 2>&1)"; RC2=$?
|
|
63
|
+
assert_eq "$RC2" "0" "idempotent-exit-zero"
|
|
64
|
+
assert_eq "$(printf '%s' "$OUT2" | grep -c 'accounts=2 agents=2 divergent=0')" "1" "idempotent-summary"
|
|
65
|
+
|
|
66
|
+
# Missing template: reported per agent, counted divergent, never fatal, and the
|
|
67
|
+
# agent's file is left exactly as it was rather than truncated.
|
|
68
|
+
export MAXY_PUBLIC_IDENTITY_TEMPLATE="$T/absent.md"
|
|
69
|
+
BEFORE="$(cat "$A1/agents/beagle/IDENTITY.md")"
|
|
70
|
+
OUT3="$(reconcile_all_accounts_identities "$ACCTS" 2>&1)"; RC3=$?
|
|
71
|
+
assert_eq "$RC3" "0" "no-template-not-fatal"
|
|
72
|
+
assert_eq "$(printf '%s' "$OUT3" | grep -c 'status=no-template')" "2" "no-template-logged-per-agent"
|
|
73
|
+
assert_eq "$(printf '%s' "$OUT3" | grep -c 'accounts=2 agents=2 divergent=2')" "1" "no-template-counted-divergent"
|
|
74
|
+
assert_eq "$(cat "$A1/agents/beagle/IDENTITY.md")" "$BEFORE" "no-template-leaves-file"
|
|
75
|
+
|
|
76
|
+
# An empty destination after a copy aborts the install: that state traps the
|
|
77
|
+
# brand server in STARTING and was observed on a live device.
|
|
78
|
+
export MAXY_PUBLIC_IDENTITY_TEMPLATE="$TPL"
|
|
79
|
+
printf 'drifted again' > "$A1/agents/beagle/IDENTITY.md"
|
|
80
|
+
CP_STUB="$T/bin"; mkdir -p "$CP_STUB"
|
|
81
|
+
printf '#!/usr/bin/env bash\n: > "${@: -1}"\nexit 0\n' > "$CP_STUB/cp"; chmod +x "$CP_STUB/cp"
|
|
82
|
+
OUT4="$(PATH="$CP_STUB:$PATH" reconcile_all_accounts_identities "$ACCTS" 2>&1)"; RC4=$?
|
|
83
|
+
assert_eq "$RC4" "1" "empty-copy-is-fatal"
|
|
84
|
+
assert_eq "$(printf '%s' "$OUT4" | grep -c 'status=empty-after-copy')" "1" "empty-copy-logged"
|
|
85
|
+
assert_eq "$(printf '%s' "$OUT4" | grep -c 'FATAL')" "1" "empty-copy-fatal-line"
|
|
86
|
+
|
|
87
|
+
# setup-account.sh runs under `set -euo pipefail`, and the reconciler is called
|
|
88
|
+
# there as a bare command. A non-zero from any per-agent call therefore kills the
|
|
89
|
+
# whole install, and it kills it on exactly the runs that had work to do — the
|
|
90
|
+
# ones where an agent diverged. Reproduced before the fix: the summary line never
|
|
91
|
+
# printed and the sourcing shell exited 1 after the first `status=updated`.
|
|
92
|
+
export MAXY_PUBLIC_IDENTITY_TEMPLATE="$TPL"
|
|
93
|
+
printf 'drifted under set -e' > "$A1/agents/beagle/IDENTITY.md"
|
|
94
|
+
OUT5="$(bash -c '
|
|
95
|
+
set -euo pipefail
|
|
96
|
+
. "'"$PLAT_SCRIPTS"'/lib/agent-identity-reconcile.sh"
|
|
97
|
+
reconcile_all_accounts_identities "'"$ACCTS"'"
|
|
98
|
+
echo REACHED-END' 2>&1)"; RC5=$?
|
|
99
|
+
assert_eq "$RC5" "0" "set-e-does-not-abort"
|
|
100
|
+
assert_eq "$(printf '%s' "$OUT5" | grep -c 'REACHED-END')" "1" "set-e-reaches-end"
|
|
101
|
+
assert_eq "$(printf '%s' "$OUT5" | grep -c 'accounts=2 agents=2 divergent=1')" "1" "set-e-summary-printed"
|
|
102
|
+
|
|
103
|
+
rm -rf "$T"
|
|
104
|
+
|
|
105
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
106
|
+
printf 'FAIL %d, PASS %d\n' "$FAIL" "$PASS"
|
|
107
|
+
printf ' %s\n' "${FAILED[@]}"
|
|
108
|
+
exit 1
|
|
109
|
+
fi
|
|
110
|
+
printf 'PASS %d\n' "$PASS"
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# The orphan-dist gate. A compiled .js whose .ts was deleted must fail; a
|
|
3
|
+
# nested path must map by its relative path, not its basename; a dist whose
|
|
4
|
+
# whole project is gone must be reported as a project orphan rather than one
|
|
5
|
+
# line per file; and a run that finds no dist tree at all must fail rather
|
|
6
|
+
# than report a clean zero, because "measured nothing" and "found nothing"
|
|
7
|
+
# are different answers.
|
|
8
|
+
set -u
|
|
9
|
+
GATE="$(cd "$(dirname "$0")/.." && pwd)/check-orphan-dist.mjs"
|
|
10
|
+
[[ -f "$GATE" ]] || { echo "FAIL: gate script missing at $GATE" >&2; exit 1; }
|
|
11
|
+
PASS=0; FAIL=0
|
|
12
|
+
|
|
13
|
+
ROOT=$(mktemp -d)
|
|
14
|
+
trap 'rm -rf "$ROOT"' EXIT
|
|
15
|
+
|
|
16
|
+
reset_root() { rm -rf "$ROOT/platform"; mkdir -p "$ROOT/platform"; }
|
|
17
|
+
|
|
18
|
+
# The plugins family nests its project under mcp/; lib and services do not.
|
|
19
|
+
fam_base() { # $1=family $2=project $3=dist|src
|
|
20
|
+
if [[ "$1" == plugins ]]; then echo "$ROOT/platform/$1/$2/mcp/$3"; else echo "$ROOT/platform/$1/$2/$3"; fi
|
|
21
|
+
}
|
|
22
|
+
make_out() { local b; b="$(fam_base "$1" "$2" dist)"; mkdir -p "$b/$(dirname "$3")"; printf 'export {};\n' > "$b/$3"; }
|
|
23
|
+
make_src() { local b; b="$(fam_base "$1" "$2" src)"; mkdir -p "$b/$(dirname "$3")"; printf 'export {};\n' > "$b/$3"; }
|
|
24
|
+
|
|
25
|
+
check() { # $1=desc $2=expected-exit $3=expected substring (may be empty)
|
|
26
|
+
local desc="$1" expected="$2" needle="${3:-}" out got
|
|
27
|
+
out=$(node "$GATE" "$ROOT/platform" 2>&1); got=$?
|
|
28
|
+
if [[ "$got" -ne "$expected" ]]; then
|
|
29
|
+
echo "FAIL: $desc — expected exit $expected, got $got"; printf '%s\n' "$out" | sed 's/^/ /'
|
|
30
|
+
FAIL=$((FAIL+1)); return
|
|
31
|
+
fi
|
|
32
|
+
if [[ -n "$needle" ]] && ! printf '%s' "$out" | grep -qF -- "$needle"; then
|
|
33
|
+
echo "FAIL: $desc — output missing [$needle]"; printf '%s\n' "$out" | sed 's/^/ /'
|
|
34
|
+
FAIL=$((FAIL+1)); return
|
|
35
|
+
fi
|
|
36
|
+
echo "PASS: $desc"; PASS=$((PASS+1))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
reset_root
|
|
40
|
+
make_src plugins alpha index.ts; make_out plugins alpha index.js
|
|
41
|
+
check "a compiled file with its source passes" 0 "orphans=0"
|
|
42
|
+
|
|
43
|
+
reset_root
|
|
44
|
+
make_src plugins alpha lib/nested.ts; make_out plugins alpha lib/nested.js
|
|
45
|
+
check "a nested path maps by relative path, not basename" 0 "orphans=0"
|
|
46
|
+
|
|
47
|
+
reset_root
|
|
48
|
+
make_src lib beta index.ts; make_out lib beta index.js
|
|
49
|
+
make_src services gamma index.ts; make_out services gamma index.js
|
|
50
|
+
check "lib and services trees are scanned too" 0 "trees=2"
|
|
51
|
+
|
|
52
|
+
reset_root
|
|
53
|
+
make_src plugins alpha index.ts; make_out plugins alpha index.js
|
|
54
|
+
make_out plugins alpha lib/gone.js
|
|
55
|
+
check "a compiled file whose source was deleted fails" 1 "orphan=plugins/alpha/mcp/dist/lib/gone.js"
|
|
56
|
+
|
|
57
|
+
reset_root
|
|
58
|
+
make_out lib deleted-project index.js; make_out lib deleted-project helper.js
|
|
59
|
+
check "a dist whose whole project is gone is one project orphan" 1 "orphan-project=lib/deleted-project/dist"
|
|
60
|
+
|
|
61
|
+
reset_root
|
|
62
|
+
check "no dist tree at all fails rather than reporting a clean zero" 1 "trees=0"
|
|
63
|
+
|
|
64
|
+
# --remove deletes exactly what it reported, and leaves the live file alone.
|
|
65
|
+
reset_root
|
|
66
|
+
make_src plugins alpha index.ts; make_out plugins alpha index.js
|
|
67
|
+
make_out plugins alpha lib/gone.js
|
|
68
|
+
printf '{}\n' > "$(fam_base plugins alpha dist)/lib/gone.js.map"
|
|
69
|
+
REMOVE_OUT=$(node "$GATE" "$ROOT/platform" --remove 2>&1); REMOVE_EXIT=$?
|
|
70
|
+
if [[ ! -e "$(fam_base plugins alpha dist)/lib/gone.js" \
|
|
71
|
+
&& ! -e "$(fam_base plugins alpha dist)/lib/gone.js.map" \
|
|
72
|
+
&& -f "$(fam_base plugins alpha dist)/index.js" ]]; then
|
|
73
|
+
echo "PASS: --remove deletes the orphan and its sidecars, keeps the live file"; PASS=$((PASS+1))
|
|
74
|
+
else
|
|
75
|
+
echo "FAIL: --remove did not delete exactly the orphan set"; FAIL=$((FAIL+1))
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# The removal must report the state on disk afterwards, not that a delete ran.
|
|
79
|
+
if printf '%s' "$REMOVE_OUT" | grep -qF -- "removed=1 remaining=0" && [[ "$REMOVE_EXIT" -eq 0 ]]; then
|
|
80
|
+
echo "PASS: --remove re-scans and reports the post-condition"; PASS=$((PASS+1))
|
|
81
|
+
else
|
|
82
|
+
echo "FAIL: --remove did not re-scan — expected 'removed=1 remaining=0' and exit 0, got exit $REMOVE_EXIT"
|
|
83
|
+
printf '%s\n' "$REMOVE_OUT" | sed 's/^/ /'; FAIL=$((FAIL+1))
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
echo "---"; echo "PASS=$PASS FAIL=$FAIL"
|
|
87
|
+
[[ "$FAIL" -eq 0 ]]
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Reconciles every compiled output tree under platform/ against its sources.
|
|
3
|
+
//
|
|
4
|
+
// Why this is a standing check and not a log line: `tsc` never removes output
|
|
5
|
+
// for a source that was deleted, and the bundler copies each tree — `dist`
|
|
6
|
+
// included — into the payload that `npm publish` ships. The deletion emits no
|
|
7
|
+
// event, and rebuilding does not surface the leftover, so nothing short of an
|
|
8
|
+
// independent reconcile can see it.
|
|
9
|
+
//
|
|
10
|
+
// Every project compiles `rootDir: src` to `outDir: dist`, so `dist/<rel>.js`
|
|
11
|
+
// maps to exactly one source, `src/<rel>.ts`. Two shapes of orphan exist:
|
|
12
|
+
// file — the .ts was deleted, the project still exists. `tsc -b --clean`
|
|
13
|
+
// would remove it.
|
|
14
|
+
// project — the whole project was deleted; `dist` survives with no `src` and
|
|
15
|
+
// no tsconfig, so no tsc invocation can ever reach it. Reported
|
|
16
|
+
// once per directory rather than once per file.
|
|
17
|
+
//
|
|
18
|
+
// Usage: node check-orphan-dist.mjs [platformRoot] [--remove]
|
|
19
|
+
// Exit 0 when every .js has a source. Exit 1 on any orphan, and exit 1 when no
|
|
20
|
+
// dist tree was found at all — a zero-orphan pass must never be
|
|
21
|
+
// indistinguishable from having measured nothing.
|
|
22
|
+
//
|
|
23
|
+
// With --remove it deletes exactly the set it just reported (each orphan .js
|
|
24
|
+
// plus its .js.map/.d.ts/.d.ts.map sidecars; a project orphan's whole dist
|
|
25
|
+
// directory) and then re-scans, so the exit code reflects the state on disk
|
|
26
|
+
// afterwards rather than the fact that a delete was called. Sharing one rule
|
|
27
|
+
// between the detector and the repair is what stops the two drifting apart.
|
|
28
|
+
|
|
29
|
+
import { existsSync, readdirSync, rmSync } from "node:fs";
|
|
30
|
+
import { join, resolve, relative, dirname } from "node:path";
|
|
31
|
+
import { fileURLToPath } from "node:url";
|
|
32
|
+
|
|
33
|
+
const args = process.argv.slice(2);
|
|
34
|
+
const remove = args.includes("--remove");
|
|
35
|
+
const rootArg = args.find((a) => !a.startsWith("--"));
|
|
36
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
37
|
+
const platformRoot = resolve(rootArg ?? join(scriptDir, ".."));
|
|
38
|
+
|
|
39
|
+
// Each family maps a project directory to its dist/src pair. `sub` is the
|
|
40
|
+
// directory between the project and its dist/src, empty where there is none.
|
|
41
|
+
const FAMILIES = [
|
|
42
|
+
{ dir: "plugins", sub: "mcp" },
|
|
43
|
+
{ dir: "lib", sub: "" },
|
|
44
|
+
{ dir: "services", sub: "" },
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
function subdirs(dir) {
|
|
48
|
+
if (!existsSync(dir)) return [];
|
|
49
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
50
|
+
.filter((e) => e.isDirectory())
|
|
51
|
+
.map((e) => e.name)
|
|
52
|
+
.sort();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function walkJs(dir, out) {
|
|
56
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
57
|
+
const full = join(dir, entry.name);
|
|
58
|
+
if (entry.isDirectory()) walkJs(full, out);
|
|
59
|
+
else if (entry.name.endsWith(".js")) out.push(full);
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function scan() {
|
|
65
|
+
let trees = 0;
|
|
66
|
+
let files = 0;
|
|
67
|
+
const fileOrphans = [];
|
|
68
|
+
const projectOrphans = [];
|
|
69
|
+
|
|
70
|
+
for (const family of FAMILIES) {
|
|
71
|
+
const familyDir = join(platformRoot, family.dir);
|
|
72
|
+
for (const project of subdirs(familyDir)) {
|
|
73
|
+
const base = family.sub
|
|
74
|
+
? join(familyDir, project, family.sub)
|
|
75
|
+
: join(familyDir, project);
|
|
76
|
+
const distDir = join(base, "dist");
|
|
77
|
+
if (!existsSync(distDir)) continue;
|
|
78
|
+
trees += 1;
|
|
79
|
+
const srcDir = join(base, "src");
|
|
80
|
+
if (!existsSync(srcDir)) {
|
|
81
|
+
projectOrphans.push(distDir);
|
|
82
|
+
files += walkJs(distDir, []).length;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
for (const js of walkJs(distDir, [])) {
|
|
86
|
+
files += 1;
|
|
87
|
+
const rel = js.slice(distDir.length + 1);
|
|
88
|
+
if (!existsSync(join(srcDir, `${rel.slice(0, -3)}.ts`))) fileOrphans.push(js);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return { trees, files, fileOrphans, projectOrphans, total: fileOrphans.length + projectOrphans.length };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const rel = (p) => relative(platformRoot, p);
|
|
96
|
+
|
|
97
|
+
function report(r) {
|
|
98
|
+
console.log(`[orphan-dist] trees=${r.trees} files=${r.files} orphans=${r.total}`);
|
|
99
|
+
for (const p of r.projectOrphans) console.log(`[orphan-dist] orphan-project=${rel(p)}`);
|
|
100
|
+
for (const f of r.fileOrphans) console.log(`[orphan-dist] orphan=${rel(f)}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const first = scan();
|
|
104
|
+
report(first);
|
|
105
|
+
|
|
106
|
+
if (first.trees === 0) {
|
|
107
|
+
console.error(
|
|
108
|
+
"[orphan-dist] FATAL: no dist tree found under platform/{plugins,lib,services} — " +
|
|
109
|
+
"the check measured nothing rather than finding nothing. Build platform first.",
|
|
110
|
+
);
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (remove && first.total > 0) {
|
|
115
|
+
for (const dir of first.projectOrphans) rmSync(dir, { recursive: true, force: true });
|
|
116
|
+
for (const js of first.fileOrphans) {
|
|
117
|
+
const stem = js.slice(0, -3);
|
|
118
|
+
for (const ext of [".js", ".js.map", ".d.ts", ".d.ts.map"]) {
|
|
119
|
+
rmSync(`${stem}${ext}`, { force: true });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Re-scan rather than trust the delete. The exit code must reflect what is
|
|
123
|
+
// on disk now, not the fact that rmSync was called.
|
|
124
|
+
const after = scan();
|
|
125
|
+
console.log(`[orphan-dist] removed=${first.total - after.total} remaining=${after.total}`);
|
|
126
|
+
if (after.total > 0) {
|
|
127
|
+
console.error(
|
|
128
|
+
`[orphan-dist] FATAL: ${after.total} orphan(s) survived removal. Check permissions on the ` +
|
|
129
|
+
"paths listed above.",
|
|
130
|
+
);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
process.exit(0);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (first.total > 0) {
|
|
137
|
+
console.error(
|
|
138
|
+
`[orphan-dist] FATAL: ${first.total} compiled output(s) have no source. Their .ts was deleted and ` +
|
|
139
|
+
"the compiler left the .js behind, where the bundler copies it into the published payload. " +
|
|
140
|
+
"Run `npm run clean:dist` in platform/ to remove exactly this set.",
|
|
141
|
+
);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# agent-identity-reconcile.sh — converge every account's public-agent IDENTITY.md
|
|
2
|
+
# against the shipped template, and state the divergence count.
|
|
3
|
+
#
|
|
4
|
+
# Task 2671. The re-sync this replaces lived inside provision_account_dir, and
|
|
5
|
+
# setup-account.sh calls that for the house account and no other, so an agent
|
|
6
|
+
# created on a client sub-account keeps whatever identity text it was seeded
|
|
7
|
+
# with for ever. Measured on laptop 192.168.88.10 on 2026-08-11: the house
|
|
8
|
+
# account's agents were refreshed by that morning's install while
|
|
9
|
+
# `5bc2c0e2/agents/beagle` still carried the 2026-07-31 text and
|
|
10
|
+
# `.../fares` the 2026-08-04 one, both of them telling a spawn that now holds
|
|
11
|
+
# five tools that it holds none.
|
|
12
|
+
#
|
|
13
|
+
# This is the identity twin of account-settings-reconcile.sh, written the same
|
|
14
|
+
# way and for the same reason, and it is the file's only writer: the in-place
|
|
15
|
+
# loop was deleted when this landed.
|
|
16
|
+
#
|
|
17
|
+
# IDENTITY.md is Rubytech-controlled and copied verbatim (agent-write.ts:113), so
|
|
18
|
+
# an operator edit here is drift to be corrected, not content to preserve. That
|
|
19
|
+
# is the one place this diverges from the settings reconciler, which leaves an
|
|
20
|
+
# unparseable file alone because it may carry an operator edit worth keeping.
|
|
21
|
+
#
|
|
22
|
+
# Idempotent. Never creates an agent dir, never writes SOUL/KNOWLEDGE/config,
|
|
23
|
+
# never echoes file contents.
|
|
24
|
+
#
|
|
25
|
+
# Sourced by setup-account.sh; also runnable standalone for a manual repair.
|
|
26
|
+
|
|
27
|
+
# ensure_agent_identity <identity_file> <template_file> <account_id> <agent_slug>
|
|
28
|
+
# Returns 0 when the file already matched the template, 1 when it diverged, and
|
|
29
|
+
# 2 when the copy landed empty. Logs exactly one
|
|
30
|
+
# [identity-reconcile] account=<id> agent=<slug> status=<already-current|updated|rewrite-failed|empty-after-copy|no-template>
|
|
31
|
+
ensure_agent_identity() {
|
|
32
|
+
local f="$1" tpl="$2" acct="$3" slug="$4"
|
|
33
|
+
|
|
34
|
+
if [ ! -s "$tpl" ]; then
|
|
35
|
+
echo "[identity-reconcile] account=$acct agent=$slug status=no-template"
|
|
36
|
+
return 1
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
if cmp -s "$f" "$tpl"; then
|
|
40
|
+
echo "[identity-reconcile] account=$acct agent=$slug status=already-current"
|
|
41
|
+
return 0
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
if ! cp "$tpl" "$f" 2>/dev/null; then
|
|
45
|
+
echo "[identity-reconcile] account=$acct agent=$slug status=rewrite-failed"
|
|
46
|
+
return 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# A 0-byte cp traps the brand server in STARTING: the reachability auditor
|
|
50
|
+
# then reports `reachable=false reason=files-missing IDENTITY.md:empty` every
|
|
51
|
+
# minute and the operator sees the splash for ever. Observed on
|
|
52
|
+
# 192.168.88.16 after a re-install, source 1655 bytes and destination 0. This
|
|
53
|
+
# is the one condition the pass refuses to continue past, carried over from
|
|
54
|
+
# the loop it replaces.
|
|
55
|
+
if [ ! -s "$f" ]; then
|
|
56
|
+
echo "[identity-reconcile] account=$acct agent=$slug status=empty-after-copy" >&2
|
|
57
|
+
return 2
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Divergent, like every other non-matching outcome: `divergent=` counts files
|
|
61
|
+
# this pass had to act on, so a run that rewrote one and a run that rewrote
|
|
62
|
+
# none are distinguishable in the summary line.
|
|
63
|
+
echo "[identity-reconcile] account=$acct agent=$slug status=updated"
|
|
64
|
+
return 1
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# reconcile_all_accounts_identities <accounts_dir>
|
|
68
|
+
# Standing check + durable backfill across every account carrying an
|
|
69
|
+
# account.json. Emits one status line per agent plus one summary line on every
|
|
70
|
+
# run, including a zero count — silence is not evidence of convergence, and
|
|
71
|
+
# `agents=0` on an install that has accounts is a stopped counter rather than a
|
|
72
|
+
# clean pass.
|
|
73
|
+
#
|
|
74
|
+
# Returns 1 only when a copy landed empty, so the caller aborts before the brand
|
|
75
|
+
# server starts. Every other failure is reported and stepped over.
|
|
76
|
+
reconcile_all_accounts_identities() {
|
|
77
|
+
local accts="$1"
|
|
78
|
+
local tpl="${MAXY_PUBLIC_IDENTITY_TEMPLATE:-${TEMPLATES_DIR:-}/agents/public/IDENTITY.md}"
|
|
79
|
+
local n=0 agents=0 divergent=0 fatal=0
|
|
80
|
+
local acct acct_id agent_dir slug rc
|
|
81
|
+
|
|
82
|
+
if [ -d "$accts" ]; then
|
|
83
|
+
for acct in "$accts"/*/; do
|
|
84
|
+
[ -f "$acct/account.json" ] || continue
|
|
85
|
+
n=$((n + 1))
|
|
86
|
+
acct_id="$(basename "$acct")"
|
|
87
|
+
for agent_dir in "$acct/agents"/*/; do
|
|
88
|
+
[ -d "$agent_dir" ] || continue
|
|
89
|
+
slug="$(basename "$agent_dir")"
|
|
90
|
+
# admin has its own Rubytech identity; passive has a third (Task 1483),
|
|
91
|
+
# and re-syncing either from the public visitor template would replace a
|
|
92
|
+
# correct prompt with the wrong one.
|
|
93
|
+
[ "$slug" = "admin" ] && continue
|
|
94
|
+
[ "$slug" = "passive" ] && continue
|
|
95
|
+
# Never create. An agent dir with no IDENTITY.md is a half-made agent,
|
|
96
|
+
# which agent-create's rollback already prevents; seeding one here would
|
|
97
|
+
# make it look whole.
|
|
98
|
+
[ -f "$agent_dir/IDENTITY.md" ] || continue
|
|
99
|
+
agents=$((agents + 1))
|
|
100
|
+
# `|| rc=$?` rather than a bare call followed by `rc=$?`: setup-account.sh
|
|
101
|
+
# runs under `set -e`, and a bare call returning non-zero kills the
|
|
102
|
+
# install the first time any agent diverges — which is every upgrade
|
|
103
|
+
# that has work to do. The `||` puts the call in a tested context, the
|
|
104
|
+
# same shape account-settings-reconcile.sh uses for the same reason.
|
|
105
|
+
rc=0
|
|
106
|
+
ensure_agent_identity "$agent_dir/IDENTITY.md" "$tpl" "$acct_id" "$slug" || rc=$?
|
|
107
|
+
# if-blocks rather than `[ … ] && …` lists: an AND-list whose test fails
|
|
108
|
+
# returns non-zero, and as the last command in this loop body that is
|
|
109
|
+
# another way `set -e` kills the install.
|
|
110
|
+
if [ "$rc" -ne 0 ]; then divergent=$((divergent + 1)); fi
|
|
111
|
+
if [ "$rc" -eq 2 ]; then fatal=1; fi
|
|
112
|
+
done
|
|
113
|
+
done
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
echo "[identity-reconcile] accounts=$n agents=$agents divergent=$divergent"
|
|
117
|
+
if [ "$fatal" -eq 1 ]; then
|
|
118
|
+
echo " [setup] FATAL a public IDENTITY.md is empty after copy from $tpl ($(wc -c < "$tpl" 2>/dev/null || echo 0) bytes); aborting before the brand server starts" >&2
|
|
119
|
+
return 1
|
|
120
|
+
fi
|
|
121
|
+
return 0
|
|
122
|
+
}
|