@rubytech/create-maxy-code 0.1.33 → 0.1.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/account-id-env.test.js +1 -1
- package/dist/__tests__/apt-resolve.test.js +7 -7
- package/dist/__tests__/brew-install.test.js +1 -1
- package/dist/__tests__/brew-resolve.test.js +1 -1
- package/dist/__tests__/cdp-port-no-silent-fallback.test.js +4 -4
- package/dist/__tests__/init-logging.test.js +1 -1
- package/dist/__tests__/launchd-plist.test.js +1 -1
- package/dist/__tests__/macos-version.test.js +1 -1
- package/dist/__tests__/peer-brand-detect.test.js +1 -1
- package/dist/__tests__/platform-detect.test.js +2 -2
- package/dist/__tests__/port-canonicalisation.test.js +1 -1
- package/dist/__tests__/preflight-port-classifier.test.js +6 -6
- package/dist/__tests__/samba-provision.test.js +1 -1
- package/dist/__tests__/snap-chromium.test.js +1 -1
- package/dist/apt-resolve.js +5 -5
- package/dist/brew-install.js +1 -1
- package/dist/brew-resolve.js +3 -3
- package/dist/index.js +146 -122
- package/dist/init-logging.js +1 -1
- package/dist/launchd-plist.js +1 -1
- package/dist/macos-version.js +2 -2
- package/dist/peer-brand-detect.js +1 -1
- package/dist/pinned-binaries.js +1 -1
- package/dist/platform-detect.js +1 -1
- package/dist/port-resolution.js +2 -2
- package/dist/preflight-port-classifier.js +3 -3
- package/dist/samba-provision.js +1 -1
- package/dist/snap-chromium.js +3 -3
- package/dist/uninstall.js +28 -28
- package/package.json +1 -1
- package/payload/platform/lib/account-enumeration/dist/__tests__/validate-env.test.js +1 -1
- package/payload/platform/lib/account-enumeration/dist/__tests__/validate-env.test.js.map +1 -1
- package/payload/platform/lib/account-enumeration/dist/index.d.ts +1 -1
- package/payload/platform/lib/account-enumeration/src/__tests__/validate-env.test.ts +1 -1
- package/payload/platform/lib/account-enumeration/src/index.ts +1 -1
- package/payload/platform/lib/admins-write/dist/index.js +3 -3
- package/payload/platform/lib/admins-write/dist/index.js.map +1 -1
- package/payload/platform/lib/admins-write/src/index.ts +4 -4
- package/payload/platform/lib/entitlement/dist/index.d.ts +1 -1
- package/payload/platform/lib/entitlement/dist/index.js +2 -2
- package/payload/platform/lib/entitlement/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-mcp/dist/__tests__/warnings-envelope.test.js +1 -1
- package/payload/platform/lib/graph-mcp/dist/__tests__/warnings-envelope.test.js.map +1 -1
- package/payload/platform/lib/graph-mcp/dist/cypher-rewrite-stamp.d.ts +3 -3
- package/payload/platform/lib/graph-mcp/dist/cypher-rewrite-stamp.js +3 -3
- package/payload/platform/lib/graph-mcp/dist/cypher-shim-read.d.ts +1 -1
- package/payload/platform/lib/graph-mcp/dist/cypher-shim-read.js +1 -1
- package/payload/platform/lib/graph-mcp/dist/cypher-shim-write.d.ts +1 -1
- package/payload/platform/lib/graph-mcp/dist/cypher-shim-write.js +1 -1
- package/payload/platform/lib/graph-mcp/dist/cypher-validate.d.ts +1 -1
- package/payload/platform/lib/graph-mcp/dist/cypher-validate.js +1 -1
- package/payload/platform/lib/graph-mcp/dist/index.d.ts +1 -1
- package/payload/platform/lib/graph-mcp/dist/index.js +24 -24
- package/payload/platform/lib/graph-mcp/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-mcp/dist/schema-cache.d.ts +1 -1
- package/payload/platform/lib/graph-mcp/dist/schema-cache.js +2 -2
- package/payload/platform/lib/graph-mcp/dist/schema-cypher-parser.d.ts +3 -3
- package/payload/platform/lib/graph-mcp/dist/schema-cypher-parser.js +3 -3
- package/payload/platform/lib/graph-mcp/src/__tests__/warnings-envelope.test.ts +1 -1
- package/payload/platform/lib/graph-mcp/src/cypher-rewrite-stamp.ts +3 -3
- package/payload/platform/lib/graph-mcp/src/cypher-shim-read.ts +1 -1
- package/payload/platform/lib/graph-mcp/src/cypher-shim-write.ts +1 -1
- package/payload/platform/lib/graph-mcp/src/cypher-validate.ts +1 -1
- package/payload/platform/lib/graph-mcp/src/index.ts +29 -29
- package/payload/platform/lib/graph-mcp/src/schema-cache.ts +2 -2
- package/payload/platform/lib/graph-mcp/src/schema-cypher-parser.ts +3 -3
- package/payload/platform/lib/graph-search/dist/index.d.ts +12 -12
- package/payload/platform/lib/graph-search/dist/index.js +11 -11
- package/payload/platform/lib/graph-search/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-search/src/__tests__/bm25-label-gate.test.ts +2 -2
- package/payload/platform/lib/graph-search/src/__tests__/bm25-strong-bypass-threshold.test.ts +2 -2
- package/payload/platform/lib/graph-search/src/__tests__/brochure-threshold.test.ts +3 -3
- package/payload/platform/lib/graph-search/src/__tests__/expand-batch.test.ts +2 -2
- package/payload/platform/lib/graph-search/src/__tests__/fulltext-coverage.test.ts +6 -6
- package/payload/platform/lib/graph-search/src/__tests__/hybrid.test.ts +5 -5
- package/payload/platform/lib/graph-search/src/__tests__/vector-threshold.test.ts +2 -2
- package/payload/platform/lib/graph-search/src/index.ts +18 -18
- package/payload/platform/lib/graph-trash/dist/index.d.ts +3 -3
- package/payload/platform/lib/graph-trash/dist/index.js +3 -3
- package/payload/platform/lib/graph-trash/src/index.ts +3 -3
- package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js +4 -4
- package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js.map +1 -1
- package/payload/platform/lib/graph-write/dist/audit.d.ts +2 -2
- package/payload/platform/lib/graph-write/dist/audit.js +2 -2
- package/payload/platform/lib/graph-write/dist/conversation-provenance.js +1 -1
- package/payload/platform/lib/graph-write/dist/conversation-provenance.js.map +1 -1
- package/payload/platform/lib/graph-write/dist/index.d.ts +5 -5
- package/payload/platform/lib/graph-write/dist/index.js +12 -12
- package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-write/src/__tests__/action-provenance-gate.test.ts +4 -4
- package/payload/platform/lib/graph-write/src/audit.ts +2 -2
- package/payload/platform/lib/graph-write/src/conversation-provenance.ts +1 -1
- package/payload/platform/lib/graph-write/src/index.ts +13 -13
- package/payload/platform/lib/mcp-eager/dist/index.d.ts +2 -2
- package/payload/platform/lib/mcp-eager/dist/index.js +2 -2
- package/payload/platform/lib/mcp-eager/src/index.ts +2 -2
- package/payload/platform/lib/mcp-spawn-tee/dist/index.d.ts +2 -2
- package/payload/platform/lib/mcp-spawn-tee/dist/index.js +2 -2
- package/payload/platform/lib/mcp-spawn-tee/src/index.ts +2 -2
- package/payload/platform/lib/mcp-stderr-tee/dist/index.d.ts +1 -1
- package/payload/platform/lib/mcp-stderr-tee/dist/index.js +4 -4
- package/payload/platform/lib/mcp-stderr-tee/dist/index.js.map +1 -1
- package/payload/platform/lib/mcp-stderr-tee/src/index.ts +4 -4
- package/payload/platform/lib/oauth-llm/dist/index.d.ts +4 -4
- package/payload/platform/lib/oauth-llm/dist/index.js +3 -3
- package/payload/platform/lib/oauth-llm/dist/index.js.map +1 -1
- package/payload/platform/lib/oauth-llm/src/index.ts +6 -6
- package/payload/platform/lib/persistent-components/dist/index.d.ts +1 -1
- package/payload/platform/lib/persistent-components/dist/index.js +1 -1
- package/payload/platform/lib/persistent-components/src/index.ts +1 -1
- package/payload/platform/lib/task-secrets/dist/index.js +1 -1
- package/payload/platform/lib/task-secrets/dist/index.js.map +1 -1
- package/payload/platform/lib/task-secrets/src/__tests__/redact-secrets.test.ts +1 -1
- package/payload/platform/lib/task-secrets/src/index.ts +1 -1
- package/payload/platform/neo4j/edge-annotations.json +9 -9
- package/payload/platform/neo4j/schema.cypher +32 -33
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/PLUGIN.md +0 -2
- package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +4 -4
- package/payload/platform/plugins/admin/hooks/__tests__/playwright-file-guard.test.sh +1 -1
- package/payload/platform/plugins/admin/hooks/__tests__/pre-tool-use-base64-guard.test.sh +1 -1
- package/payload/platform/plugins/admin/hooks/archive-ingest-surface-gate.sh +13 -13
- package/payload/platform/plugins/admin/hooks/pre-tool-use.sh +7 -7
- package/payload/platform/plugins/admin/mcp/dist/__tests__/plugin-read-skill-resolution.test.js +2 -2
- package/payload/platform/plugins/admin/mcp/dist/__tests__/plugin-read-skill-resolution.test.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/__tests__/public-hostname.test.js +1 -1
- package/payload/platform/plugins/admin/mcp/dist/__tests__/public-hostname.test.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-load-required-inputs.test.js +2 -2
- package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-load-required-inputs.test.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-load.test.js +1 -1
- package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-load.test.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/index.js +38 -65
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/lib/neo4j.js +2 -2
- package/payload/platform/plugins/admin/mcp/dist/lib/neo4j.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/lib/public-hostname.js +2 -2
- package/payload/platform/plugins/admin/mcp/dist/lib/public-hostname.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js +5 -5
- package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js.map +1 -1
- package/payload/platform/plugins/admin/skills/plugin-management/SKILL.md +1 -1
- package/payload/platform/plugins/admin/skills/public-agent-manager/SKILL.md +0 -1
- package/payload/platform/plugins/admin/skills/publish-site/SKILL.md +1 -1
- package/payload/platform/plugins/admin/skills/unzip-attachment/SKILL.md +2 -2
- package/payload/platform/plugins/cloudflare/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/cloudflare/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.d.ts +1 -1
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.js +6 -6
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.js.map +1 -1
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.d.ts +2 -2
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.js +2 -2
- package/payload/platform/plugins/cloudflare/references/dashboard-guide.md +1 -1
- package/payload/platform/plugins/cloudflare/references/manual-setup.md +4 -4
- package/payload/platform/plugins/cloudflare/scripts/__tests__/tunnel-ingress.test.ts +1 -1
- package/payload/platform/plugins/cloudflare/scripts/_stream-log.sh +8 -8
- package/payload/platform/plugins/cloudflare/scripts/list-cf-domains.sh +2 -2
- package/payload/platform/plugins/cloudflare/scripts/list-cf-domains.ts +16 -16
- package/payload/platform/plugins/cloudflare/scripts/reset-tunnel.sh +1 -1
- package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +28 -28
- package/payload/platform/plugins/cloudflare/scripts/tunnel-ingress.ts +5 -5
- package/payload/platform/plugins/cloudflare/skills/setup-tunnel/SKILL.md +3 -3
- package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.js +2 -2
- package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/lib/resolve-person.d.ts +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/lib/resolve-person.js +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +2 -2
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js.map +1 -1
- package/payload/platform/plugins/docs/references/deployment.md +30 -1
- package/payload/platform/plugins/docs/references/plugins-guide.md +2 -5
- package/payload/platform/plugins/docs/references/troubleshooting.md +3 -3
- package/payload/platform/plugins/email/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js +2 -2
- package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.js +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/neo4j.js +2 -2
- package/payload/platform/plugins/email/mcp/dist/lib/neo4j.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/screening.d.ts +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/screening.js +1 -1
- package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.js +6 -6
- package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.d.ts +1 -1
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js +2 -2
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js.map +1 -1
- package/payload/platform/plugins/email/references/email-reference.md +2 -2
- package/payload/platform/plugins/loop/mcp/dist/lib/neo4j.js +3 -3
- package/payload/platform/plugins/loop/mcp/dist/lib/neo4j.js.map +1 -1
- package/payload/platform/plugins/loop/mcp/src/lib/neo4j.ts +3 -3
- package/payload/platform/plugins/memory/bin/conversation-archive-ingest.mjs +24 -24
- package/payload/platform/plugins/memory/bin/conversation-archive-ingest.sh +6 -6
- package/payload/platform/plugins/memory/mcp/dist/index.js +8 -8
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js +33 -33
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js +12 -12
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js +3 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.js +1 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.d.ts +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/document-hierarchy.js +6 -6
- package/payload/platform/plugins/memory/mcp/dist/lib/document-hierarchy.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.d.ts +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js +7 -7
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/live-schema-source.d.ts +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/live-schema-source.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts +9 -9
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js +25 -25
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.js +5 -5
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts +4 -4
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js +3 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.d.ts +3 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js +5 -5
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/uuid.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/uuid.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.js +5 -5
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.js +4 -4
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js +6 -6
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js +7 -7
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-not-applicable.test.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-not-applicable.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js +3 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js +3 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-classify.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-classify.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts +3 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-extract.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-extract.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts +9 -9
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +10 -11
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +3 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js +9 -9
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts +5 -5
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +9 -9
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/scripts/boot-smoke.sh +1 -1
- package/payload/platform/plugins/memory/mcp/scripts/graph/fixture.cypher +1 -1
- package/payload/platform/plugins/memory/mcp/vitest.config.ts +2 -2
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/scripts/verify-doc-impl.sh +1 -1
- package/payload/platform/plugins/scheduling/PLUGIN.md +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/time-resolve-description.test.js +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/time-resolve-description.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/getUserTimezone.test.js +3 -3
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/getUserTimezone.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/neo4j.d.ts +2 -2
- package/payload/platform/plugins/scheduling/mcp/dist/lib/neo4j.js +5 -5
- package/payload/platform/plugins/scheduling/mcp/dist/lib/neo4j.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.d.ts +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +6 -6
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
- package/payload/platform/plugins/tasks/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/tasks/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/tasks/mcp/dist/lib/neo4j.js +2 -2
- package/payload/platform/plugins/tasks/mcp/dist/lib/neo4j.js.map +1 -1
- package/payload/platform/plugins/tasks/mcp/dist/tools/project-create.js +2 -2
- package/payload/platform/plugins/tasks/mcp/dist/tools/project-create.js.map +1 -1
- package/payload/platform/plugins/tasks/mcp/dist/tools/session-name.d.ts +1 -1
- package/payload/platform/plugins/tasks/mcp/dist/tools/session-name.d.ts.map +1 -1
- package/payload/platform/plugins/tasks/mcp/dist/tools/task-create.d.ts +5 -5
- package/payload/platform/plugins/tasks/mcp/dist/tools/task-create.js +3 -3
- package/payload/platform/plugins/tasks/mcp/dist/tools/task-create.js.map +1 -1
- package/payload/platform/plugins/tasks/mcp/dist/tools/task-update.d.ts +4 -4
- package/payload/platform/plugins/tasks/mcp/dist/tools/task-update.js +2 -2
- package/payload/platform/plugins/tasks/mcp/dist/tools/task-update.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.js +2 -2
- package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.js.map +1 -1
- package/payload/platform/plugins/waitlist/mcp/dist/lib/neo4j.js +2 -2
- package/payload/platform/plugins/waitlist/mcp/dist/lib/neo4j.js.map +1 -1
- package/payload/platform/plugins/waitlist/mcp/dist/tools/__tests__/waitlist-persist.test.js +3 -3
- package/payload/platform/plugins/waitlist/mcp/dist/tools/__tests__/waitlist-persist.test.js.map +1 -1
- package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-persist.d.ts +1 -1
- package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-persist.js +3 -3
- package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-persist.js.map +1 -1
- package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-setup.js +5 -5
- package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-setup.js.map +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/call-api.d.ts +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/call-api.js +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/lib/active-runs.d.ts +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/lib/active-runs.js +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/lib/llm-call.d.ts +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/lib/neo4j.js +2 -2
- package/payload/platform/plugins/workflows/mcp/dist/lib/neo4j.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js +4 -4
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.js +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/test-workflows.sh +2 -2
- package/payload/platform/scripts/__tests__/first-token-creates-stream-log.test.sh +1 -1
- package/payload/platform/scripts/__tests__/logs-read-prefix.sh +6 -6
- package/payload/platform/scripts/admin-conversation-recover.mjs +5 -5
- package/payload/platform/scripts/admin-persist-audit.ts +4 -4
- package/payload/platform/scripts/check-no-conversation-id-leaks.mjs +1 -1
- package/payload/platform/scripts/check-no-direct-clipboard.mjs +1 -1
- package/payload/platform/scripts/check-no-task-id-leaks.mjs +2 -2
- package/payload/platform/scripts/check-skill-load-coverage.mjs +1 -1
- package/payload/platform/scripts/component-knowledgedoc-backfill.ts +1 -1
- package/payload/platform/scripts/dedupe-userprofile-ghosts.sh +2 -2
- package/payload/platform/scripts/generate-entitlement-fixture.mjs +1 -1
- package/payload/platform/scripts/installer-device-verify.sh +6 -6
- package/payload/platform/scripts/lib/resolve-account-dir.sh +6 -6
- package/payload/platform/scripts/log-adherence-check.sh +3 -3
- package/payload/platform/scripts/logs-read.sh +13 -13
- package/payload/platform/scripts/logs-read.test.sh +1 -1
- package/payload/platform/scripts/migrate-import.sh +4 -4
- package/payload/platform/scripts/redact-install-logs.sh +1 -1
- package/payload/platform/scripts/seed-neo4j.sh +26 -32
- package/payload/platform/scripts/test-laptop-vnc-boot.sh +3 -3
- package/payload/platform/scripts/verify-skill-tool-surface.sh +17 -2
- package/payload/platform/scripts/vnc.sh +9 -9
- package/payload/platform/services/claude-session-manager/dist/config.d.ts +7 -2
- package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.js +3 -1
- package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +2 -2
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +133 -90
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +17 -4
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.d.ts +2 -2
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.js +4 -4
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.js +2 -2
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +37 -18
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +101 -44
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-tool-audit.js +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-tool-audit.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-store.d.ts +36 -11
- package/payload/platform/services/claude-session-manager/dist/session-store.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-store.js +53 -2
- package/payload/platform/services/claude-session-manager/dist/session-store.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/spawn-rate-limiter.js +2 -2
- package/payload/platform/services/claude-session-manager/dist/spawn-rate-limiter.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +46 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +131 -24
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/tool-surface.js +1 -1
- package/payload/platform/services/claude-session-manager/dist/tool-surface.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/types.d.ts +8 -1
- package/payload/platform/services/claude-session-manager/dist/types.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/url-capture.js +1 -1
- package/payload/platform/services/claude-session-manager/dist/url-capture.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +14 -0
- package/payload/platform/templates/agents/admin/SOUL.md +1 -3
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -3
- package/payload/platform/templates/specialists/agents/project-manager.md +1 -1
- package/payload/platform/templates/systemd/edge.service.template +3 -3
- package/payload/premium-plugins/real-agent/BUNDLE.md +2 -4
- package/payload/premium-plugins/real-agent/plugins/.claude-plugin/marketplace.json +0 -5
- package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/neo4j.js +3 -3
- package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/neo4j.js.map +1 -1
- package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/lib/neo4j.ts +3 -3
- package/payload/server/{chunk-ZGJ6CUU2.js → chunk-3G6JMV7N.js} +1 -1
- package/payload/server/{chunk-KVGTWNKQ.js → chunk-NNHHGQJL.js} +314 -5
- package/payload/server/{chunk-RZQMYJVY.js → chunk-QC5LHYPH.js} +3 -3
- package/payload/server/{cloudflare-task-tracker-4PKOLE4H.js → cloudflare-task-tracker-NEB3X6O2.js} +2 -2
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/public/assets/{admin-Cuu1QdAA.js → admin-CF2ZQvXu.js} +1 -1
- package/payload/server/public/index.html +1 -1
- package/payload/server/server.js +274 -396
- package/payload/platform/plugins/anthropic/.claude-plugin/plugin.json +0 -8
- package/payload/platform/plugins/anthropic/PLUGIN.md +0 -40
- package/payload/platform/plugins/anthropic/references/console-api.md +0 -186
- package/payload/platform/plugins/anthropic/references/setup-guide.md +0 -36
- package/payload/platform/plugins/anthropic/skills/get-api-key/SKILL.md +0 -136
- package/payload/platform/plugins/estate-onboarding/.claude-plugin/plugin.json +0 -8
- package/payload/platform/plugins/estate-onboarding/PLUGIN.md +0 -30
- package/payload/platform/plugins/estate-onboarding/skills/bootstrap/SKILL.md +0 -26
- package/payload/platform/plugins/estate-onboarding/skills/bootstrap/references/onboarding-flow.md +0 -63
- package/payload/premium-plugins/real-agent/plugins/estate-onboarding/.claude-plugin/plugin.json +0 -8
- package/payload/premium-plugins/real-agent/plugins/estate-onboarding/PLUGIN.md +0 -30
- package/payload/premium-plugins/real-agent/plugins/estate-onboarding/skills/bootstrap/SKILL.md +0 -26
- package/payload/premium-plugins/real-agent/plugins/estate-onboarding/skills/bootstrap/references/onboarding-flow.md +0 -63
package/dist/index.js
CHANGED
|
@@ -38,7 +38,7 @@ const INSTALL_DIR = resolve(process.env.HOME ?? "/root", BRAND.installDir);
|
|
|
38
38
|
const PERSIST_DIR = resolve(process.env.HOME ?? "/root", BRAND.configDir);
|
|
39
39
|
const LOG_DIR = join(PERSIST_DIR, "logs");
|
|
40
40
|
const LOG_FILE = join(LOG_DIR, `install-${new Date().toISOString().replace(/[:.]/g, "-")}.log`);
|
|
41
|
-
//
|
|
41
|
+
// every `claude plugin` shellout must read/write the per-brand
|
|
42
42
|
// CLAUDE_CONFIG_DIR that the systemd unit at port-resolution.ts:229,286 uses
|
|
43
43
|
// at runtime. Without this override, the installer writes marketplaces and
|
|
44
44
|
// enabledPlugins to $HOME/.claude/settings.json (user-default), and the
|
|
@@ -49,8 +49,9 @@ function claudePluginEnv() {
|
|
|
49
49
|
return { ...process.env, CLAUDE_CONFIG_DIR };
|
|
50
50
|
}
|
|
51
51
|
/** Known brand hostnames in the Maxy ecosystem. Each brand ships a main unit
|
|
52
|
-
* (`<hostname>.service`) and a per-brand edge unit
|
|
53
|
-
*
|
|
52
|
+
* (`<hostname>.service`) and a per-brand edge unit
|
|
53
|
+
* (`<hostname>-edge.service`). Peer-brand detection matches only these
|
|
54
|
+
* filenames — stale units,
|
|
54
55
|
* gnome-keyring disable markers, and unrelated user services are not peer
|
|
55
56
|
* evidence. When a third brand is added under `brands/`, append its hostname
|
|
56
57
|
* here AND in the matching constant in `uninstall.ts` (intentional duplication
|
|
@@ -59,7 +60,7 @@ const KNOWN_BRAND_HOSTNAMES = ["maxy", "realagent", "maxy-2", "maxy-3", "maxy-4"
|
|
|
59
60
|
// The device's actual hostname — may differ from BRAND.hostname if the user customized it.
|
|
60
61
|
// Updated by installSystemDeps() after hostname setup; used for user-facing URLs.
|
|
61
62
|
let DEVICE_HOSTNAME = BRAND.hostname;
|
|
62
|
-
//
|
|
63
|
+
// absolute path to the non-snap Chromium binary chosen during
|
|
63
64
|
// installSystemDeps(). Defaults to /usr/bin/chromium so non-Linux installs
|
|
64
65
|
// (which never call ensureNonSnapChromium) and the systemd unit's
|
|
65
66
|
// PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH still see a sensible value. On Linux,
|
|
@@ -162,7 +163,7 @@ function shell(command, args, options) {
|
|
|
162
163
|
const cmd = options?.sudo ? "sudo" : command;
|
|
163
164
|
const cmdArgs = options?.sudo ? [command, ...args] : args;
|
|
164
165
|
const start = Date.now();
|
|
165
|
-
// Redaction
|
|
166
|
+
// Redaction: callers handling secrets pass redact: true so the
|
|
166
167
|
// wrapper records the command name only, not the secret-bearing args. The
|
|
167
168
|
// child process still receives the real args via spawnSync below; only the
|
|
168
169
|
// install log line is sanitised. The grep-able audit shape stays:
|
|
@@ -178,7 +179,7 @@ function shell(command, args, options) {
|
|
|
178
179
|
env: options?.env,
|
|
179
180
|
});
|
|
180
181
|
const dur = ((Date.now() - start) / 1000).toFixed(1);
|
|
181
|
-
// bestEffort
|
|
182
|
+
// bestEffort: tear-down ops on units/state that may or may not
|
|
182
183
|
// exist (stop/disable a system service we may never have started, reset-failed
|
|
183
184
|
// a freshly-created unit) log the non-zero exit but do not throw. Reserved
|
|
184
185
|
// for the "may not exist" pattern only — never use for ops that must succeed.
|
|
@@ -269,12 +270,12 @@ function canSudo() {
|
|
|
269
270
|
const result = spawnSync("sudo", ["-n", "true"], { stdio: "pipe", timeout: 5_000 });
|
|
270
271
|
return result.status === 0;
|
|
271
272
|
}
|
|
272
|
-
//
|
|
273
|
-
//
|
|
273
|
+
// verified-not-asserted apt-dep reconciliation.
|
|
274
|
+
// resolve package-name aliases before probing dpkg, so the
|
|
274
275
|
// post-install check no longer false-negatives when apt resolves a virtual
|
|
275
276
|
// name (e.g. Noble's `chromium` → `chromium-browser`).
|
|
276
277
|
// UBUNTU_ALIASES, parseOsRelease, isUbuntuLike, and decideAptResolution moved
|
|
277
|
-
// to
|
|
278
|
+
// to./apt-resolve.ts. The pure logic lives there so a unit test
|
|
278
279
|
// can hit every branch without spawning real apt/dpkg or reading
|
|
279
280
|
// /etc/os-release. The thin wrappers below feed real spawn + fs results into
|
|
280
281
|
// that pure decision.
|
|
@@ -297,7 +298,7 @@ function aptCachePolicySummary(pkg) {
|
|
|
297
298
|
return cand === "(none)" ? "candidate-none" : `candidate=${cand}`;
|
|
298
299
|
}
|
|
299
300
|
/**
|
|
300
|
-
*
|
|
301
|
+
* map an apt-level package name to the concrete name dpkg will
|
|
301
302
|
* record after install. Resolution order:
|
|
302
303
|
* 1. `dpkg -s pkg` exits 0 → name is concrete and installed; return pkg.
|
|
303
304
|
* 2. `apt-cache policy pkg` reports a real Candidate → concrete-but-missing;
|
|
@@ -306,7 +307,7 @@ function aptCachePolicySummary(pkg) {
|
|
|
306
307
|
* UBUNTU_ALIASES on an Ubuntu-like host → return the alias. Log the
|
|
307
308
|
* resolution so the install log answers "what did apt resolve this to?".
|
|
308
309
|
* 4. Otherwise return pkg unchanged — the post-check will throw loudly,
|
|
309
|
-
* preserving
|
|
310
|
+
* preserving the fail-loud contract for genuinely missing packages.
|
|
310
311
|
*/
|
|
311
312
|
function resolveAptName(pkg) {
|
|
312
313
|
const dpkg = spawnSync("dpkg", ["-s", pkg], { stdio: "pipe", timeout: 5_000 });
|
|
@@ -371,7 +372,7 @@ function pkgsMissing(pkgs) {
|
|
|
371
372
|
* surface at runtime when the binary is missing.
|
|
372
373
|
*
|
|
373
374
|
* Resolves each package through `resolveAptName` before both the install
|
|
374
|
-
* command and the post-check, so alias packages
|
|
375
|
+
* command and the post-check, so alias packages pass through
|
|
375
376
|
* cleanly on distros where the apt-level name differs from the dpkg-recorded
|
|
376
377
|
* name (e.g. Noble's chromium → chromium-browser). Resolution is computed
|
|
377
378
|
* once per package and reused across install, post-check, and error
|
|
@@ -396,7 +397,7 @@ function installAptGroup(label, pkgs) {
|
|
|
396
397
|
// ---------------------------------------------------------------------------
|
|
397
398
|
const TOTAL = "11";
|
|
398
399
|
/**
|
|
399
|
-
*
|
|
400
|
+
* set macOS hostname via scutil. Three sequential `sudo scutil
|
|
400
401
|
* --set` calls (HostName, LocalHostName, ComputerName) — `hostnamectl` is
|
|
401
402
|
* Linux-only and `--hostname <h>` silently no-ops on darwin. All-or-nothing
|
|
402
403
|
* rollback within the 3-call batch: if any call fails, we restore the
|
|
@@ -430,7 +431,7 @@ function setMacosHostnameViaScutil(hostname) {
|
|
|
430
431
|
console.log(` [scutil] HostName=${hostname} LocalHostName=${hostname} ComputerName=${hostname} set ok`);
|
|
431
432
|
}
|
|
432
433
|
/**
|
|
433
|
-
*
|
|
434
|
+
* detect snap-confined Chromium on Linux and install Google Chrome
|
|
434
435
|
* stable as the non-snap replacement. Runs after `installAptGroup("VNC stack")`
|
|
435
436
|
* inside `installSystemDeps`. Resolution rules live in `snap-chromium.ts`
|
|
436
437
|
* (pure decision); this wrapper does the spawnSync + apt-repo writes + post-
|
|
@@ -452,7 +453,7 @@ function setMacosHostnameViaScutil(hostname) {
|
|
|
452
453
|
*
|
|
453
454
|
* Post-install gate: spawn the resolved binary headless against a throwaway
|
|
454
455
|
* profile dir under persistDir, assert exit 0. The AppArmor denial that
|
|
455
|
-
* triggered
|
|
456
|
+
* triggered the original denial was on SingletonLock writes which `--headless=new` still
|
|
456
457
|
* attempts, so the headless probe fires the same EACCES path that production
|
|
457
458
|
* VNC headed launches do — closing the post-fix-sibling-audit-skipped gap.
|
|
458
459
|
*/
|
|
@@ -544,7 +545,7 @@ function ensureNonSnapChromium() {
|
|
|
544
545
|
runChromiumPostInstallGate(RESOLVED_CHROMIUM_BIN);
|
|
545
546
|
}
|
|
546
547
|
/**
|
|
547
|
-
*
|
|
548
|
+
* post-install gate. Spawns the resolved Chromium binary headless
|
|
548
549
|
* against a throwaway profile dir under persistDir (`~/.{brand}/chromium-
|
|
549
550
|
* gate-profile/`). The AppArmor denial that triggered the task was on
|
|
550
551
|
* SingletonLock writes which `--headless=new` still attempts, so this probe
|
|
@@ -556,7 +557,7 @@ function runChromiumPostInstallGate(chromiumBin) {
|
|
|
556
557
|
const persistDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
|
|
557
558
|
const gateProfileDir = join(persistDir, "chromium-gate-profile");
|
|
558
559
|
mkdirSync(gateProfileDir, { recursive: true });
|
|
559
|
-
console.log(` Verifying ${chromiumBin} can write to ${gateProfileDir} (
|
|
560
|
+
console.log(` Verifying ${chromiumBin} can write to ${gateProfileDir} (post-install gate)...`);
|
|
560
561
|
const r = spawnSync(chromiumBin, [
|
|
561
562
|
`--user-data-dir=${gateProfileDir}`,
|
|
562
563
|
"--headless=new",
|
|
@@ -575,7 +576,7 @@ function runChromiumPostInstallGate(chromiumBin) {
|
|
|
575
576
|
const stderr = (r.stderr ?? "").slice(-2000);
|
|
576
577
|
const eaccesHit = /Permission denied/i.test(stderr) || /EACCES/i.test(stderr);
|
|
577
578
|
const taskRef = eaccesHit
|
|
578
|
-
? "
|
|
579
|
+
? "chromium-profile not writable (likely AppArmor denial on snap-confined binary). "
|
|
579
580
|
: "";
|
|
580
581
|
throw new Error(`${taskRef}Chromium post-install gate failed: ${chromiumBin} exited ${r.status} signal=${r.signal ?? "none"}. stderr:\n${stderr}`);
|
|
581
582
|
}
|
|
@@ -583,7 +584,7 @@ function runChromiumPostInstallGate(chromiumBin) {
|
|
|
583
584
|
logFile(` [snap-chromium] post-install gate ok: ${chromiumBin} exit=0`);
|
|
584
585
|
}
|
|
585
586
|
/**
|
|
586
|
-
*
|
|
587
|
+
* write the resolved Chromium absolute path to
|
|
587
588
|
* `<INSTALL_DIR>/platform/config/chromium-binary.path` so vnc.sh,
|
|
588
589
|
* writeChromiumWrapper, and setup-tunnel.sh all read the same value. Called
|
|
589
590
|
* after deployPayload so the platform/config/ directory exists. Idempotent:
|
|
@@ -606,7 +607,7 @@ function installSystemDeps() {
|
|
|
606
607
|
log("1", TOTAL, "System dependencies and network...");
|
|
607
608
|
const platform = requireSupportedPlatform(process.platform);
|
|
608
609
|
if (platform === "darwin") {
|
|
609
|
-
//
|
|
610
|
+
// darwin hostname via scutil when --hostname is supplied,
|
|
610
611
|
// otherwise preserve the existing system hostname.
|
|
611
612
|
if (HOSTNAME_FLAG) {
|
|
612
613
|
console.log(` Hostname: ${HOSTNAME_FLAG} (from --hostname flag)`);
|
|
@@ -625,8 +626,8 @@ function installSystemDeps() {
|
|
|
625
626
|
}
|
|
626
627
|
catch { /* fallback to brand — set at declaration */ }
|
|
627
628
|
}
|
|
628
|
-
//
|
|
629
|
-
// (kiosk display + hostapd/dnsmasq are Pi-specific
|
|
629
|
+
// macOS has no apt analogue for the VNC/WiFi-AP stacks
|
|
630
|
+
// (kiosk display + hostapd/dnsmasq are Pi-specific's
|
|
630
631
|
// out-of-scope note). mDNS is provided by the OS, so avahi-* drop out.
|
|
631
632
|
// Translate the remaining apt names through decideBrewResolution and
|
|
632
633
|
// let installAllBrewPackages handle the install + verify pattern.
|
|
@@ -636,25 +637,25 @@ function installSystemDeps() {
|
|
|
636
637
|
}
|
|
637
638
|
const BASE_DEPS = ["curl", "git", "unzip", "jq", "avahi-daemon", "avahi-utils", "poppler-utils", "ffmpeg", "bind9-dnsutils"];
|
|
638
639
|
// xterm is the *preferred* terminal-emulator binary for the VNC-rendered
|
|
639
|
-
// Terminal surface
|
|
640
|
+
// Terminal surface
|
|
640
641
|
// delegates window creation to the session's gnome-terminal-server,
|
|
641
642
|
// opening windows on the wrong display; xterm has no IPC layer and
|
|
642
643
|
// honours DISPLAY directly). Kept in the apt list unconditionally so
|
|
643
644
|
// vnc.sh's resolve_terminal_bin has a display-safe binary on every
|
|
644
645
|
// supported distro (Ubuntu 24.04 noble/universe, Debian 12 bookworm/main
|
|
645
|
-
// verified). xdotool
|
|
646
|
+
// verified). xdotool backs the post-spawn display-membership
|
|
646
647
|
// assertion in vnc.sh check_window_on_display, closing the silent-fail
|
|
647
648
|
// class where PID is alive but no window is mapped on the target display.
|
|
648
649
|
const VNC_DEPS = ["tigervnc-standalone-server", "python3-websockify", "novnc", "xdg-utils", "chromium", "xterm", "xdotool"];
|
|
649
|
-
//
|
|
650
|
+
// retired the ttyd/tmux admin terminal stack — upgrades run via
|
|
650
651
|
// the action runner (systemd-run --user transient units) and no longer
|
|
651
652
|
// need a shared tmux session. `tmux` was only required by the retired
|
|
652
653
|
// byte-stream terminal; removing it shrinks the apt footprint.
|
|
653
654
|
const WIFI_DEPS = ["hostapd", "dnsmasq"];
|
|
654
655
|
const ALL_APT_DEPS = [...BASE_DEPS, ...VNC_DEPS, ...WIFI_DEPS];
|
|
655
|
-
//
|
|
656
|
+
// verify the "deps are present" assumption with `dpkg -s` instead
|
|
656
657
|
// of asserting it (feedback_loud_failures.md). The previous silent-skip
|
|
657
|
-
// branch was benign
|
|
658
|
+
// branch was benign added xdotool (the first new apt dep
|
|
658
659
|
// since the skip path became load-bearing on user-password-sudo devices).
|
|
659
660
|
const missing = pkgsMissing(ALL_APT_DEPS);
|
|
660
661
|
if (missing.length === 0) {
|
|
@@ -680,7 +681,7 @@ function installSystemDeps() {
|
|
|
680
681
|
installAptGroup("VNC stack", VNC_DEPS);
|
|
681
682
|
installAptGroup("WiFi AP", WIFI_DEPS);
|
|
682
683
|
}
|
|
683
|
-
//
|
|
684
|
+
// replace snap-confined Chromium with Google Chrome stable on
|
|
684
685
|
// Linux laptops (Ubuntu Noble) where `/usr/bin/chromium` realpaths to the
|
|
685
686
|
// snap launcher. The snap AppArmor profile denies writes to hidden top-level
|
|
686
687
|
// paths under $HOME, so any write to `~/.{brand}/chromium-profile/SingletonLock`
|
|
@@ -733,11 +734,11 @@ function installSystemDeps() {
|
|
|
733
734
|
// set by the user or the first installer — subsequent brands must not overwrite it.
|
|
734
735
|
const systemdUserDir = resolve(process.env.HOME ?? "/root", ".config/systemd/user");
|
|
735
736
|
const serviceExists = existsSync(join(systemdUserDir, BRAND.serviceName));
|
|
736
|
-
//
|
|
737
|
+
// narrow peer detection to KNOWN_BRAND_HOSTNAMES. The previous
|
|
737
738
|
// predicate ("any *.service that isn't ours") matched stray user units
|
|
738
739
|
// such as a `gnome-keyring-daemon.service -> /dev/null` disable marker,
|
|
739
740
|
// silently flipping single-brand fresh installs into the "preserve hostname"
|
|
740
|
-
// branch. Mirrors
|
|
741
|
+
// branch. Mirrors the `peerBrandPresent` allowlist in `uninstall.ts`.
|
|
741
742
|
let otherBrandService = false;
|
|
742
743
|
if (!serviceExists) {
|
|
743
744
|
const peerUnits = KNOWN_BRAND_HOSTNAMES
|
|
@@ -876,7 +877,7 @@ function installNodejs() {
|
|
|
876
877
|
if (platform === "darwin") {
|
|
877
878
|
// Pass the apt-side `nodejs` name; decideBrewResolution maps it to
|
|
878
879
|
// `node@22` per DARWIN_ALIASES so the cellar formula matches Maxy's
|
|
879
|
-
// pinned-binaries floor
|
|
880
|
+
// pinned-binaries floor.
|
|
880
881
|
installAllBrewPackages(["nodejs"], logFile);
|
|
881
882
|
return;
|
|
882
883
|
}
|
|
@@ -931,14 +932,14 @@ function installClaudeCode() {
|
|
|
931
932
|
}
|
|
932
933
|
}
|
|
933
934
|
console.log(" Registering Claude plugin marketplaces...");
|
|
934
|
-
//
|
|
935
|
+
// pre-create the per-brand CLAUDE_CONFIG_DIR so the first
|
|
935
936
|
// `claude plugin marketplace add` has a directory to write into.
|
|
936
937
|
mkdirSync(CLAUDE_CONFIG_DIR, { recursive: true });
|
|
937
938
|
const marketplaceList = spawnSync("claude", ["plugin", "marketplace", "list"], { stdio: "pipe", encoding: "utf-8", env: claudePluginEnv() });
|
|
938
939
|
if (marketplaceList.stderr)
|
|
939
940
|
process.stderr.write(marketplaceList.stderr);
|
|
940
941
|
const listed = marketplaceList.stdout ?? "";
|
|
941
|
-
//
|
|
942
|
+
// register three Anthropic marketplaces uniformly with
|
|
942
943
|
// [plugin-marketplace] observability. Each slug is grep-checked against
|
|
943
944
|
// `marketplace list` for idempotence; failures log exit + first stderr
|
|
944
945
|
// line but do not abort the installer (one marketplace's outage must not
|
|
@@ -1052,7 +1053,7 @@ function resetNeo4jAuth(port = DEFAULT_NEO4J_PORT, dataDir = "/var/lib/neo4j") {
|
|
|
1052
1053
|
return password;
|
|
1053
1054
|
}
|
|
1054
1055
|
/**
|
|
1055
|
-
*
|
|
1056
|
+
* scrub plaintext neo4j passwords from pre-fix install-*.log files.
|
|
1056
1057
|
* Calls platform/scripts/redact-install-logs.sh against the installer's LOG_DIR.
|
|
1057
1058
|
* The script is idempotent; re-running on clean logs is a no-op. Failures here
|
|
1058
1059
|
* are non-fatal — credential redaction is best-effort cleanup, not a blocker
|
|
@@ -1099,7 +1100,7 @@ function ensureNeo4jPassword() {
|
|
|
1099
1100
|
}
|
|
1100
1101
|
}
|
|
1101
1102
|
// 2. Fresh install or recovery: no working same-brand password. Generate and set a new one.
|
|
1102
|
-
// Brand isolation
|
|
1103
|
+
// Brand isolation: never read another brand's.neo4j-password.
|
|
1103
1104
|
if (!existsSync(passwordFile)) {
|
|
1104
1105
|
console.log(" No Neo4j password file found. Setting initial password...");
|
|
1105
1106
|
}
|
|
@@ -1135,7 +1136,7 @@ function installNeo4j() {
|
|
|
1135
1136
|
if (platform === "darwin") {
|
|
1136
1137
|
// Homebrew's neo4j formula declares openjdk as a runtime dependency, so
|
|
1137
1138
|
// Java is pulled in transitively — no separate openjdk install step.
|
|
1138
|
-
// Process supervision (launchd LaunchAgent) is owned
|
|
1139
|
+
// Process supervision (launchd LaunchAgent) is owned; this
|
|
1139
1140
|
// step ends after `brew install neo4j` + initial-password seeding so the
|
|
1140
1141
|
// payload deploy step finds the shared password file.
|
|
1141
1142
|
installAllBrewPackages(["neo4j"], logFile);
|
|
@@ -1190,7 +1191,7 @@ function installNeo4j() {
|
|
|
1190
1191
|
console.log(" Neo4j started. Password stored securely.");
|
|
1191
1192
|
}
|
|
1192
1193
|
/**
|
|
1193
|
-
*
|
|
1194
|
+
* does any peer brand on this host pin `NEO4J_URI=bolt://localhost:<default>`
|
|
1194
1195
|
* in its `.env`? If yes, the apt-installed `neo4j.service` is its database and the
|
|
1195
1196
|
* dedicated-unit installer must NOT stop+disable it. Returns the first matching
|
|
1196
1197
|
* peer's hostname, or `null` when no peer pins the default port.
|
|
@@ -1200,7 +1201,7 @@ function installNeo4j() {
|
|
|
1200
1201
|
* (permissions, transient I/O), the wrapper treats that peer as a *potential*
|
|
1201
1202
|
* dependency and short-circuits to the kept-active path. Disabling the system
|
|
1202
1203
|
* unit on faulty evidence would silently kill the peer's database (the exact
|
|
1203
|
-
* failure
|
|
1204
|
+
* failure mode the kept-active path prevents); a conservatively-skipped disable is recoverable
|
|
1204
1205
|
* because the dedicated-unit bind check at the end of `setupDedicatedNeo4j`
|
|
1205
1206
|
* fails loud if the system unit is actually free.
|
|
1206
1207
|
*/
|
|
@@ -1235,12 +1236,12 @@ function peerBrandUsingSystemUnit() {
|
|
|
1235
1236
|
* Create a dedicated Neo4j instance for this brand when NEO4J_DEDICATED is true.
|
|
1236
1237
|
* Produces: separate config dir, data dir, log dir, systemd service, and password.
|
|
1237
1238
|
* On upgrade (config already exists), skips conf creation — but always runs the
|
|
1238
|
-
*
|
|
1239
|
+
* state-remediation block (stop/disable system unit, reset-failed
|
|
1239
1240
|
* dedicated, start, verify) so a half-installed Pi recovers in-place without
|
|
1240
1241
|
* manual systemctl. ensureNeo4jPassword() handles password verification on the
|
|
1241
1242
|
* recovery path.
|
|
1242
1243
|
*
|
|
1243
|
-
*
|
|
1244
|
+
* on multi-brand hosts where a peer brand still depends on the apt
|
|
1244
1245
|
* `neo4j.service` (port 7687), the stop+disable step is skipped — disabling
|
|
1245
1246
|
* the system unit would kill the peer's database.
|
|
1246
1247
|
*/
|
|
@@ -1255,8 +1256,8 @@ function setupDedicatedNeo4j() {
|
|
|
1255
1256
|
const httpPort = NEO4J_PORT - 213; // Preserve standard 7687/7474 offset
|
|
1256
1257
|
// Per-brand state (sed, mkdir, chown, unit-write) is idempotent and runs on
|
|
1257
1258
|
// every install. Only the base-config copy and initial-password rotation are
|
|
1258
|
-
// gated to first install
|
|
1259
|
-
// run every install
|
|
1259
|
+
// gated to first install established that state remediation must
|
|
1260
|
+
// run every install extended the same principle to the conf and
|
|
1260
1261
|
// unit emission so a half-installed host (broken unit missing NEO4J_HOME)
|
|
1261
1262
|
// recovers on retry without an out-of-band manual reset.
|
|
1262
1263
|
const confExists = spawnSync("test", ["-f", `${confDir}/neo4j.conf`], { stdio: "pipe" }).status === 0;
|
|
@@ -1279,12 +1280,12 @@ function setupDedicatedNeo4j() {
|
|
|
1279
1280
|
console.log(" [privileged] cp -r");
|
|
1280
1281
|
shell("cp", ["-r", "/etc/neo4j", confDir], { sudo: true });
|
|
1281
1282
|
}
|
|
1282
|
-
// Idempotent per-brand state — runs on every install
|
|
1283
|
+
// Idempotent per-brand state — runs on every install.
|
|
1283
1284
|
// sed `s|^#?key=.*|key=value|` no-ops when the file already has the target
|
|
1284
1285
|
// value; mkdir -p, chown -R, and unit-write are idempotent by definition.
|
|
1285
1286
|
// NEO4J_HOME=${dataDir} makes server.directories.run resolve per-brand to
|
|
1286
1287
|
// ${dataDir}/run, so the launcher's pre-flight does not collide with the
|
|
1287
|
-
// system unit's /var/lib/neo4j/run/neo4j.pid (
|
|
1288
|
+
// system unit's /var/lib/neo4j/run/neo4j.pid (root cause). Plugins
|
|
1288
1289
|
// and import are sed-overridden because the apt base conf pins them to
|
|
1289
1290
|
// absolute /var/lib/neo4j/plugins and /var/lib/neo4j/import (shared).
|
|
1290
1291
|
console.log(" [privileged] sed -i");
|
|
@@ -1347,7 +1348,7 @@ WantedBy=multi-user.target
|
|
|
1347
1348
|
});
|
|
1348
1349
|
}
|
|
1349
1350
|
// ============================================================================
|
|
1350
|
-
//
|
|
1351
|
+
// unified state remediation + start + verify.
|
|
1351
1352
|
//
|
|
1352
1353
|
// Runs on both fresh and recovery paths. The dedicated unit and the apt
|
|
1353
1354
|
// package's system unit both exec /usr/bin/neo4j console without overriding
|
|
@@ -1360,9 +1361,9 @@ WantedBy=multi-user.target
|
|
|
1360
1361
|
spawnSync("sudo", ["systemctl", "daemon-reload"], { stdio: "inherit" });
|
|
1361
1362
|
console.log(" [privileged] systemctl enable");
|
|
1362
1363
|
shell("systemctl", ["enable", serviceName], { sudo: true });
|
|
1363
|
-
//
|
|
1364
|
+
// skip stop+disable when a peer brand on this host still depends
|
|
1364
1365
|
// on the apt `neo4j.service` (port 7687). Disabling it would kill the peer's
|
|
1365
|
-
// database
|
|
1366
|
+
// database reproducer on Neo's laptop. The kept-active path is
|
|
1366
1367
|
// mutually exclusive with the disable path: exactly one log line per install.
|
|
1367
1368
|
const peerOnSystemUnit = peerBrandUsingSystemUnit();
|
|
1368
1369
|
if (peerOnSystemUnit !== null) {
|
|
@@ -1397,7 +1398,7 @@ WantedBy=multi-user.target
|
|
|
1397
1398
|
spawnSync("sleep", ["2"]);
|
|
1398
1399
|
}
|
|
1399
1400
|
if (!listening) {
|
|
1400
|
-
// Loud failure — no silent fallback to the system instance
|
|
1401
|
+
// Loud failure — no silent fallback to the system instance.
|
|
1401
1402
|
const portCheck = spawnSync("ss", ["-tlnp"], { stdio: "pipe", timeout: 5000 });
|
|
1402
1403
|
const portLines = (portCheck.stdout?.toString() ?? "").split("\n").filter((l) => l.includes(String(NEO4J_PORT)));
|
|
1403
1404
|
const diagnostic = portLines.length > 0 ? portLines.join("; ") : "nothing listening on port";
|
|
@@ -1477,7 +1478,7 @@ function installOllama(embedModel) {
|
|
|
1477
1478
|
logFile(` Pulling embedding model: ${embedModel}`);
|
|
1478
1479
|
shellRetry("ollama", ["pull", embedModel], { timeout: 600_000 }, 3, 15);
|
|
1479
1480
|
}
|
|
1480
|
-
//
|
|
1481
|
+
// uv/uvx bootstrap. Required by the `graph` MCP server which
|
|
1481
1482
|
// spawns `uvx mcp-neo4j-cypher@0.6.0 --transport stdio`. Idempotent: when
|
|
1482
1483
|
// uvx is already on PATH (or under $HOME/.local/bin) we skip. Non-fatal on
|
|
1483
1484
|
// failure — the installer continues; the graph server will loudly fail
|
|
@@ -1524,7 +1525,7 @@ function installCloudflared() {
|
|
|
1524
1525
|
// Homebrew's `cloudflared` formula tracks the Cloudflare release stream;
|
|
1525
1526
|
// tunnel-login flow stays unchanged (`feedback_no_api_token_route.md`).
|
|
1526
1527
|
// `cloudflared service install` is invoked by the launchd supervisor in
|
|
1527
|
-
//
|
|
1528
|
+
// out of scope here.
|
|
1528
1529
|
installAllBrewPackages(["cloudflared"], logFile);
|
|
1529
1530
|
return;
|
|
1530
1531
|
}
|
|
@@ -1573,7 +1574,7 @@ function installWhisperCpp() {
|
|
|
1573
1574
|
}
|
|
1574
1575
|
/**
|
|
1575
1576
|
* Provision the shared HMAC secret used to sign remote-session cookies
|
|
1576
|
-
|
|
1577
|
+
*. Both `maxy-edge` and `maxy-ui` read this file; without it
|
|
1577
1578
|
* they independently mint ephemeral secrets on first use and the
|
|
1578
1579
|
* cross-process session namespace silently diverges again.
|
|
1579
1580
|
*
|
|
@@ -1593,7 +1594,7 @@ function provisionRemoteSessionSecret() {
|
|
|
1593
1594
|
writeFileSync(secretFile, randomBytes(32).toString("hex"), { mode: 0o600 });
|
|
1594
1595
|
console.log(` [install] remote-session-secret provisioned path=${secretFile}`);
|
|
1595
1596
|
}
|
|
1596
|
-
//
|
|
1597
|
+
// install-time admin-auth invariant. Walks every account.json
|
|
1597
1598
|
// under accountsDir and compares its admins[] to the persistent users.json,
|
|
1598
1599
|
// emitting one [install-invariant] line per divergence and one summary line.
|
|
1599
1600
|
// Log-only (no install abort) so pre-Task-904 devices with already-divergent
|
|
@@ -1697,7 +1698,7 @@ function deployPayload() {
|
|
|
1697
1698
|
mkdirSync(persistentDir, { recursive: true });
|
|
1698
1699
|
cpSync(oldAccountsDir, persistentAccountsDir, { recursive: true });
|
|
1699
1700
|
}
|
|
1700
|
-
//
|
|
1701
|
+
// users.json lives at <persistentDir>/users.json. earlier
|
|
1701
1702
|
// installs wrote to <INSTALL_DIR>/platform/config/users.json (the wipe zone)
|
|
1702
1703
|
// and relied on a one-shot copy-up at first install plus a copy-back after
|
|
1703
1704
|
// every wipe. The copy-back overwrote LIVE with the FROZEN-AT-FIRST-INSTALL
|
|
@@ -1707,7 +1708,7 @@ function deployPayload() {
|
|
|
1707
1708
|
//
|
|
1708
1709
|
// Legacy pickup: if a pre-Task-904 install left users.json inside the wipe
|
|
1709
1710
|
// zone, copy it up once. Idempotent — guarded by !existsSync(persistentUsersFile).
|
|
1710
|
-
// Safe to delete this block one release
|
|
1711
|
+
// Safe to delete this block one release has been deployed
|
|
1711
1712
|
// everywhere; until then it absorbs upgrades from any pre-Task-904 version.
|
|
1712
1713
|
const persistentUsersFile = join(persistentDir, "users.json");
|
|
1713
1714
|
const oldUsersFile = join(INSTALL_DIR, "platform/config/users.json");
|
|
@@ -1716,7 +1717,7 @@ function deployPayload() {
|
|
|
1716
1717
|
cpSync(oldUsersFile, persistentUsersFile);
|
|
1717
1718
|
console.log(" Migrated pre-Task-904 users.json to persistent storage.");
|
|
1718
1719
|
}
|
|
1719
|
-
//
|
|
1720
|
+
// Claude Code OAuth credentials legacy pickup. earlier
|
|
1720
1721
|
// installs shared `~/.claude/.credentials.json` across brands; the brand
|
|
1721
1722
|
// main service's `claude` SDK subprocess and admin server now read from
|
|
1722
1723
|
// `${persistDir}/.claude/.credentials.json` per the new
|
|
@@ -1750,7 +1751,7 @@ function deployPayload() {
|
|
|
1750
1751
|
}
|
|
1751
1752
|
writeFileSync(credsMigratedStamp, new Date().toISOString() + "\n");
|
|
1752
1753
|
}
|
|
1753
|
-
//
|
|
1754
|
+
// pre-populate the brand `.claude.json` so the manager's
|
|
1754
1755
|
// PTY-spawned `claude --verbose --remote-control` boots straight into the
|
|
1755
1756
|
// session URL without stopping at the first-run theme picker or the
|
|
1756
1757
|
// workspace-trust dialog. Both prompts ate the manager's 30 s url-capture
|
|
@@ -1783,11 +1784,11 @@ function deployPayload() {
|
|
|
1783
1784
|
console.log(` [install] claude-state primed: ${claudeStateFile} hasCompletedOnboarding=true trustedWorkspace=${homeWorkspace}`);
|
|
1784
1785
|
// Brand isolation: installer does not read ~/.maxy/, ~/.cloudflared/, or
|
|
1785
1786
|
// ~/.cloudflare/ on non-default brands. These are peer-brand or shared-singleton
|
|
1786
|
-
// paths
|
|
1787
|
+
// paths. earlier installs that need to recover legacy state
|
|
1787
1788
|
// follow the manual recovery paragraph in .docs/deployment.md.
|
|
1788
1789
|
// Stop the running service before wiping directories (upgrade path).
|
|
1789
1790
|
// The server holds open files in platform/ — rmSync fails with ENOTEMPTY if it's running.
|
|
1790
|
-
//
|
|
1791
|
+
// darwin uses `launchctl bootout` instead of systemctl; bootout
|
|
1791
1792
|
// returns synchronously when the agent has exited.
|
|
1792
1793
|
if (requireSupportedPlatform(process.platform) === "darwin") {
|
|
1793
1794
|
spawnSync("launchctl", ["bootout", `${gui()}/${launchdLabel()}`], { stdio: "pipe", timeout: 15_000 });
|
|
@@ -1858,7 +1859,7 @@ function deployPayload() {
|
|
|
1858
1859
|
cpSync(persistentPasswordFile, join(configDir, ".neo4j-password"));
|
|
1859
1860
|
console.log(" Restored Neo4j password.");
|
|
1860
1861
|
}
|
|
1861
|
-
//
|
|
1862
|
+
// users.json is read directly from persistentDir by both
|
|
1862
1863
|
// platform/ui/app/lib/paths.ts (USERS_FILE = MAXY_DIR/users.json) and the
|
|
1863
1864
|
// admin MCP plugin (USERS_FILE = CONFIG_DIR/users.json). No copy into the
|
|
1864
1865
|
// wipe zone — the pre-Task-904 cpSync to platform/config/users.json was the
|
|
@@ -1883,7 +1884,7 @@ function deployPayload() {
|
|
|
1883
1884
|
else {
|
|
1884
1885
|
console.log(" [install] users.json: no persistent file (fresh install — set-pin will create it)");
|
|
1885
1886
|
}
|
|
1886
|
-
//
|
|
1887
|
+
// install-time admin-auth invariant check. Walks every
|
|
1887
1888
|
// data/accounts/*/account.json admins[] and compares to the persistent
|
|
1888
1889
|
// users.json. Log-only (does NOT refuse install) so pre-Task-904 devices
|
|
1889
1890
|
// with already-divergent state still upgrade; the [install-invariant]
|
|
@@ -1897,7 +1898,7 @@ function deployPayload() {
|
|
|
1897
1898
|
writeFileSync(join(configDir, `.${BRAND.hostname}-version`), PKG_VERSION, "utf-8");
|
|
1898
1899
|
console.log(` Deployed to ${INSTALL_DIR}`);
|
|
1899
1900
|
}
|
|
1900
|
-
//
|
|
1901
|
+
// register the local + external Claude Code plugins after the
|
|
1901
1902
|
// payload is on disk. The bundler stamps `.claude-plugin/marketplace.json`
|
|
1902
1903
|
// at each plugin-tree root (platform/plugins/, premium-plugins/real-agent/
|
|
1903
1904
|
// plugins/, premium-plugins/) so this function discovers them generically
|
|
@@ -1940,7 +1941,7 @@ function registerLocalAndExternalPlugins() {
|
|
|
1940
1941
|
}
|
|
1941
1942
|
}
|
|
1942
1943
|
// Add each local marketplace. Idempotence via `marketplace list` grep.
|
|
1943
|
-
//
|
|
1944
|
+
// every `claude plugin …` call carries CLAUDE_CONFIG_DIR so
|
|
1944
1945
|
// marketplaces register into the per-brand config dir that the runtime
|
|
1945
1946
|
// session-manager unit reads from.
|
|
1946
1947
|
const mkList = spawnSync("claude", ["plugin", "marketplace", "list"], { stdio: "pipe", encoding: "utf-8", env: claudePluginEnv() });
|
|
@@ -2030,7 +2031,7 @@ function registerLocalAndExternalPlugins() {
|
|
|
2030
2031
|
logFile(`[plugin-configure] ERROR ${action.plugin.name} exit=${configure.status} stderr=${JSON.stringify(stderrShort)}`);
|
|
2031
2032
|
}
|
|
2032
2033
|
}
|
|
2033
|
-
//
|
|
2034
|
+
// post-install assertion. The per-brand CLAUDE_CONFIG_DIR is the
|
|
2034
2035
|
// only surface the runtime session-manager reads from; if any expected
|
|
2035
2036
|
// marketplace is missing under .claude/plugins/marketplaces/, the operator
|
|
2036
2037
|
// will hit "Unknown skill: onboarding" at step 6 of the bring-up. Fail the
|
|
@@ -2045,7 +2046,7 @@ function registerLocalAndExternalPlugins() {
|
|
|
2045
2046
|
"claude-for-financial-services",
|
|
2046
2047
|
...localTrees.map(t => t.name),
|
|
2047
2048
|
]);
|
|
2048
|
-
//
|
|
2049
|
+
// `claude plugin marketplace list` is the authoritative source.
|
|
2049
2050
|
// The `.claude/plugins/marketplaces/` directory only contains subdirs for
|
|
2050
2051
|
// remote (git-cloned) marketplaces — local-source marketplaces registered
|
|
2051
2052
|
// via `claude plugin marketplace add <directory-path>` live in user
|
|
@@ -2111,7 +2112,7 @@ function buildPlatform() {
|
|
|
2111
2112
|
}
|
|
2112
2113
|
console.log(` Installing server dependencies (${join(INSTALL_DIR, "server")})...`);
|
|
2113
2114
|
shellRetry("npm", ["install", "--omit=dev", ...NPM_NET_FLAGS], { cwd: join(INSTALL_DIR, "server") }, 3, 15);
|
|
2114
|
-
//
|
|
2115
|
+
// (maxy-code) — claude-session-manager has its own package.json
|
|
2115
2116
|
// declaring hono + @hono/node-server + node-pty. node-pty is a native
|
|
2116
2117
|
// binding; it MUST be installed on the Pi, not shipped pre-built (different
|
|
2117
2118
|
// architecture between the build host and the Pi). Wipe + reinstall on
|
|
@@ -2231,7 +2232,7 @@ function setupVncViewer() {
|
|
|
2231
2232
|
} catch (e) { /* swallow */ }
|
|
2232
2233
|
}
|
|
2233
2234
|
|
|
2234
|
-
// Layer-6 beacon
|
|
2235
|
+
// Layer-6 beacon: emit event=rfb-connected and
|
|
2235
2236
|
// event=rfb-error to the operator-grep lifecycle endpoint so
|
|
2236
2237
|
// server.log shows the noVNC outcome alongside [setup-tunnel] /
|
|
2237
2238
|
// [cloudflare-setup] / [device-url:click] / [http] / [websockify].
|
|
@@ -2351,7 +2352,7 @@ function setupVncViewer() {
|
|
|
2351
2352
|
}
|
|
2352
2353
|
function setupAccount() {
|
|
2353
2354
|
log("10", TOTAL, "Setting up...");
|
|
2354
|
-
//
|
|
2355
|
+
// seed-neo4j.sh hard-exits without NEO4J_URI. The installer
|
|
2355
2356
|
// owns the brand-correct URI and password, so we derive them once.
|
|
2356
2357
|
// Missing password file is a hard error: ensureNeo4jPassword() ran
|
|
2357
2358
|
// upstream and would have thrown already if it couldn't reach the
|
|
@@ -2369,11 +2370,11 @@ function setupAccount() {
|
|
|
2369
2370
|
logFile(` [neo4j] passing NEO4J_URI=${neo4jUri} to seed`);
|
|
2370
2371
|
shell("bash", [seedScript], { cwd: INSTALL_DIR, env: neo4jEnv });
|
|
2371
2372
|
}
|
|
2372
|
-
//
|
|
2373
|
+
// install-time defaults. Stamp `account.json` with the
|
|
2373
2374
|
// brand's default plugin set + default outputStyle / thinkingView, and
|
|
2374
2375
|
// write a minimal admin SOUL.md. The agent boots into a working state
|
|
2375
2376
|
// with no onboarding state machine; the operator builds personality up
|
|
2376
|
-
// through use. The graph-write gate
|
|
2377
|
+
// through use. The graph-write gate blocks user-domain writes
|
|
2377
2378
|
// until AdminUser + LocalBusiness/personal-profile Person exist, so the
|
|
2378
2379
|
// persona is elicited the first time the operator triggers a write.
|
|
2379
2380
|
const accountId = resolveInstallAccountId();
|
|
@@ -2410,6 +2411,29 @@ function writeInstallDefaults(accountId) {
|
|
|
2410
2411
|
writeFileSync(soulPath, `You are ${BRAND.productName}, an AI operations manager.\n`);
|
|
2411
2412
|
console.log(` [install-defaults] soul-md path=${soulPath}`);
|
|
2412
2413
|
logFile(` [install-defaults] soul-md path=${soulPath}`);
|
|
2414
|
+
// Public agent files — IDENTITY.md is always overwritten (Rubytech-controlled);
|
|
2415
|
+
// SOUL.md and config.json are created if missing (user-controlled). All three
|
|
2416
|
+
// are sourced from the payload templates under
|
|
2417
|
+
// <INSTALL_DIR>/platform/templates/agents/public/.
|
|
2418
|
+
const publicDir = join(accountDir, "agents/public");
|
|
2419
|
+
mkdirSync(publicDir, { recursive: true });
|
|
2420
|
+
const publicTemplatesDir = join(INSTALL_DIR, "platform/templates/agents/public");
|
|
2421
|
+
const publicIdentityDst = join(publicDir, "IDENTITY.md");
|
|
2422
|
+
cpSync(join(publicTemplatesDir, "IDENTITY.md"), publicIdentityDst);
|
|
2423
|
+
console.log(` [install-defaults] public-identity path=${publicIdentityDst}`);
|
|
2424
|
+
logFile(` [install-defaults] public-identity path=${publicIdentityDst}`);
|
|
2425
|
+
const publicSoulDst = join(publicDir, "SOUL.md");
|
|
2426
|
+
if (!existsSync(publicSoulDst)) {
|
|
2427
|
+
cpSync(join(publicTemplatesDir, "SOUL.md"), publicSoulDst);
|
|
2428
|
+
console.log(` [install-defaults] public-soul path=${publicSoulDst}`);
|
|
2429
|
+
logFile(` [install-defaults] public-soul path=${publicSoulDst}`);
|
|
2430
|
+
}
|
|
2431
|
+
const publicConfigDst = join(publicDir, "config.json");
|
|
2432
|
+
if (!existsSync(publicConfigDst)) {
|
|
2433
|
+
cpSync(join(publicTemplatesDir, "config.json"), publicConfigDst);
|
|
2434
|
+
console.log(` [install-defaults] public-config path=${publicConfigDst}`);
|
|
2435
|
+
logFile(` [install-defaults] public-config path=${publicConfigDst}`);
|
|
2436
|
+
}
|
|
2413
2437
|
}
|
|
2414
2438
|
// ---------------------------------------------------------------------------
|
|
2415
2439
|
// Tunnel script shortcuts
|
|
@@ -2418,9 +2442,9 @@ function writeInstallDefaults(accountId) {
|
|
|
2418
2442
|
// invocation `~/setup-tunnel.sh` (and `~/reset-tunnel.sh`). The filesystem
|
|
2419
2443
|
// reality is <INSTALL_DIR>/platform/plugins/cloudflare/scripts/*.sh. Without
|
|
2420
2444
|
// the symlink the agent's first SKILL-compliant invocation fails with exit
|
|
2421
|
-
// 127 — the discipline-violation loop
|
|
2445
|
+
// 127 — the discipline-violation loop the symlink exists to close.
|
|
2422
2446
|
//
|
|
2423
|
-
// Collision discipline (
|
|
2447
|
+
// Collision discipline (last-writer-wins across brands):
|
|
2424
2448
|
// - absent path → create
|
|
2425
2449
|
// - regular file → exit 1 (operator-owned file, do not clobber)
|
|
2426
2450
|
// - symlink → same target → no-op
|
|
@@ -2458,7 +2482,7 @@ function createTunnelSymlink(linkPath, target) {
|
|
|
2458
2482
|
console.error(` Remove the file and re-run: npx -y @rubytech/create-maxy`);
|
|
2459
2483
|
process.exit(1);
|
|
2460
2484
|
}
|
|
2461
|
-
// Brand isolation
|
|
2485
|
+
// Brand isolation: a symlink at this path is either stale-same-brand,
|
|
2462
2486
|
// dangling, unreadable, or pointing at another brand. All four cases are resolved
|
|
2463
2487
|
// by last-writer-wins overwrite — setup-tunnel.sh takes <brand> as argv, so
|
|
2464
2488
|
// whichever brand's installer ran last owns the shortcut.
|
|
@@ -2505,13 +2529,13 @@ function installTunnelScripts() {
|
|
|
2505
2529
|
// ---------------------------------------------------------------------------
|
|
2506
2530
|
// Account discovery (shared by installService + the post-install summary)
|
|
2507
2531
|
//
|
|
2508
|
-
//
|
|
2532
|
+
// `installService` stamps `Environment=ACCOUNT_ID=` into the brand
|
|
2509
2533
|
// systemd unit so the writeNodeWithEdges gate has a non-undefined identity to
|
|
2510
2534
|
// compare against. Pulled from `INSTALL_DIR/data/accounts/<uuid>/account.json`
|
|
2511
2535
|
// written by seed-neo4j.sh during setupAccount(). One reader, one shape, one
|
|
2512
2536
|
// source of truth.
|
|
2513
2537
|
//
|
|
2514
|
-
//
|
|
2538
|
+
// retired the installer's cron registration — `resolveInstallAccountId`
|
|
2515
2539
|
// kept its second consumer (installService) and is referenced again at print
|
|
2516
2540
|
// time for the post-install banner.
|
|
2517
2541
|
// ---------------------------------------------------------------------------
|
|
@@ -2528,26 +2552,26 @@ function resolveInstallAccountId() {
|
|
|
2528
2552
|
catch { /* directory unreadable */ }
|
|
2529
2553
|
return "";
|
|
2530
2554
|
}
|
|
2531
|
-
//
|
|
2555
|
+
// `installCrons()` and the `# BEGIN/END <BRAND> CRONS` block lived
|
|
2532
2556
|
// here. All such events must be user-driven, not scheduled by the installer.
|
|
2533
2557
|
// The legacy block recreated `data/accounts/<accountId>/logs/` every 60s via
|
|
2534
2558
|
// `mkdir -p`, which tripped seed-neo4j.sh's stub-account-dirs guard on every
|
|
2535
2559
|
// reinstall after `rm -rf ~/<installDir>`. Uninstall now strips the legacy
|
|
2536
2560
|
// block (uninstall.ts `removeLegacyCronBlock`) so older installs migrate
|
|
2537
2561
|
// cleanly. Consumer-side dispatcher replacement is tracked separately.
|
|
2538
|
-
//
|
|
2562
|
+
// retired the ttyd/tmux/xterm admin terminal stack. Upgrades run
|
|
2539
2563
|
// via the action runner — `systemd-run --user` transient units spawned by
|
|
2540
2564
|
// POST /api/admin/actions/upgrade — whose lifetime is independent of
|
|
2541
|
-
// maxy-ui, achieving the
|
|
2565
|
+
// maxy-ui, achieving the invariant structurally rather than via
|
|
2542
2566
|
// a peer edge service proxying a ttyd process. The installer no longer
|
|
2543
2567
|
// provisions the ttyd binary, writes a tmux conf, or installs a ttyd
|
|
2544
2568
|
// systemd unit. The corresponding admin UI (RemoteTerminal, TerminalOverlay,
|
|
2545
2569
|
// xterm.js) was deleted in the same task.
|
|
2546
|
-
//
|
|
2570
|
+
// reverse-DNS LaunchAgent label. Becomes both the plist's
|
|
2547
2571
|
// <key>Label</key> value and the file basename
|
|
2548
2572
|
// (`~/Library/LaunchAgents/com.rubytech.<hostname>.plist`). Per-brand so
|
|
2549
2573
|
// installing brand B never displaces brand A's agent (mirrors the per-brand
|
|
2550
|
-
// systemd unit invariant
|
|
2574
|
+
// systemd unit invariant).
|
|
2551
2575
|
function launchdLabel() {
|
|
2552
2576
|
return `com.rubytech.${BRAND.hostname}`;
|
|
2553
2577
|
}
|
|
@@ -2563,12 +2587,12 @@ function gui() {
|
|
|
2563
2587
|
const uid = typeof process.getuid === "function" ? process.getuid() : 0;
|
|
2564
2588
|
return `gui/${uid}`;
|
|
2565
2589
|
}
|
|
2566
|
-
//
|
|
2590
|
+
// darwin LaunchAgent supervisor. Mirrors the systemd-user body
|
|
2567
2591
|
// below at the success-criteria level: process registered with the user's
|
|
2568
2592
|
// session manager, KeepAlive respawns on crash, RunAtLoad starts the agent
|
|
2569
|
-
// on every login. Out-of-scope today
|
|
2593
|
+
// on every login. Out-of-scope today: brew-resolved node path,
|
|
2570
2594
|
// dedicated Neo4j on a non-default port. Falls back to /usr/local/bin/node
|
|
2571
|
-
// (homebrew Intel + manual Apple-silicon installs)
|
|
2595
|
+
// (homebrew Intel + manual Apple-silicon installs) will replace
|
|
2572
2596
|
// this with the resolver.
|
|
2573
2597
|
function installServiceDarwin() {
|
|
2574
2598
|
const persistDir = resolve(process.env.HOME ?? "/", BRAND.configDir);
|
|
@@ -2617,7 +2641,7 @@ function installServiceDarwin() {
|
|
|
2617
2641
|
const nodeBin = (nodeProbe.stdout ?? "").trim() || "/usr/local/bin/node";
|
|
2618
2642
|
const wrapperBody = [
|
|
2619
2643
|
"#!/bin/bash",
|
|
2620
|
-
"#
|
|
2644
|
+
"# generated by create-maxy installService(). Reads.env then",
|
|
2621
2645
|
"# execs node so launchd's child inherits PORT, NEO4J_URI, etc. Replaces",
|
|
2622
2646
|
"# the systemd EnvironmentFile= directive that has no launchd analogue.",
|
|
2623
2647
|
`set -a; [ -f "${envPath}" ] && . "${envPath}"; set +a`,
|
|
@@ -2679,7 +2703,7 @@ function installServiceDarwin() {
|
|
|
2679
2703
|
}
|
|
2680
2704
|
function installService() {
|
|
2681
2705
|
log("11", TOTAL, `Starting ${BRAND.productName}...`);
|
|
2682
|
-
//
|
|
2706
|
+
// branch ternary instead of the legacy
|
|
2683
2707
|
// `isLinux()` boolean. Linux falls through to the systemd-user body
|
|
2684
2708
|
// below; darwin renders + bootstraps a LaunchAgent and returns;
|
|
2685
2709
|
// unsupported throws the literal refusal at requireSupportedPlatform.
|
|
@@ -2756,13 +2780,13 @@ function installService() {
|
|
|
2756
2780
|
// Propagate to child processes — seed-neo4j.sh reads both variables.
|
|
2757
2781
|
process.env.EMBED_DIMENSIONS = String(EMBED_DIMS);
|
|
2758
2782
|
process.env.NEO4J_URI = `bolt://localhost:${NEO4J_PORT}`;
|
|
2759
|
-
//
|
|
2783
|
+
// maxy-ui runs on an internal-only port so a restart does not
|
|
2760
2784
|
// drop the public TCP socket. maxy-edge.service owns the public port and
|
|
2761
2785
|
// the VNC stack; maxy-ui sits behind it on 127.0.0.1:MAXY_UI_INTERNAL_PORT.
|
|
2762
2786
|
// PORT + 1 (derived) avoids a fixed-port collision if the operator chose a
|
|
2763
2787
|
// non-default --port.
|
|
2764
2788
|
//
|
|
2765
|
-
//
|
|
2789
|
+
// PORT in maxy.service's Environment block is the PUBLIC port,
|
|
2766
2790
|
// not the internal one. Previously we wrote `Environment=PORT=<internal>`,
|
|
2767
2791
|
// which collided with the install-time reader further down, which
|
|
2768
2792
|
// correctly treats Environment=PORT= as public. The overload caused +1
|
|
@@ -2772,10 +2796,10 @@ function installService() {
|
|
|
2772
2796
|
const MAXY_UI_INTERNAL_PORT = PORT + 1;
|
|
2773
2797
|
const edgeUnitShort = `${BRAND.hostname}-edge`;
|
|
2774
2798
|
const edgeUnitName = `${edgeUnitShort}.service`;
|
|
2775
|
-
// Per-brand X display
|
|
2799
|
+
// Per-brand X display. Same value used for the edge unit's
|
|
2776
2800
|
// DISPLAY env (stamped via __VNC_DISPLAY__ a few lines down) so the main
|
|
2777
2801
|
// brand service and the edge service agree on which display Chromium runs.
|
|
2778
|
-
//
|
|
2802
|
+
// brand.json (BRAND) is the single source of truth for
|
|
2779
2803
|
// these fields at install time. The vncDisplay-derived offset rule lives
|
|
2780
2804
|
// in the brand-creation tooling; at this point in the installer BRAND
|
|
2781
2805
|
// already represents a parsed, validated brand manifest, and any missing
|
|
@@ -2796,13 +2820,13 @@ function installService() {
|
|
|
2796
2820
|
const WEBSOCKIFY_PORT_BRAND = BRAND.websockifyPort;
|
|
2797
2821
|
const CDP_PORT_BRAND = BRAND.cdpPort;
|
|
2798
2822
|
const CLAUDE_SESSION_MANAGER_PORT_BRAND = BRAND.claudeSessionManagerPort;
|
|
2799
|
-
//
|
|
2823
|
+
// pre-flight — refuse to write service files if any of the
|
|
2800
2824
|
// three brand-scoped ports is already held by a process that is NOT this
|
|
2801
2825
|
// brand's own on-demand browser nor a peer brand's edge stack.
|
|
2802
2826
|
//
|
|
2803
|
-
// Classification (
|
|
2804
|
-
// `/proc/<pid>/cmdline` and applies a holder-specific argv anchor.
|
|
2805
|
-
// covered chromium-only via `--user-data-dir
|
|
2827
|
+
// Classification (chromium Xtigervnc + websockify) reads
|
|
2828
|
+
// `/proc/<pid>/cmdline` and applies a holder-specific argv anchor.
|
|
2829
|
+
// covered chromium-only via `--user-data-dir=` closed the gap on
|
|
2806
2830
|
// Xtigervnc (no such flag — anchor on the `:N` display literal) and
|
|
2807
2831
|
// websockify (anchor on bind port). Brand identities (configDir,
|
|
2808
2832
|
// vncDisplay, websockifyPort) come from brand-registry.json which the
|
|
@@ -2821,11 +2845,11 @@ function installService() {
|
|
|
2821
2845
|
websockifyPort: WEBSOCKIFY_PORT_BRAND,
|
|
2822
2846
|
};
|
|
2823
2847
|
// Peer registry — load from payload/platform/config/brand-registry.json
|
|
2824
|
-
// when present
|
|
2848
|
+
// when present. Older bundles ship without the
|
|
2825
2849
|
// registry; in that case peerBrands stays empty. PEER_BRAND classification
|
|
2826
2850
|
// for Xtigervnc/websockify is a defence-in-depth case anyway (port sets
|
|
2827
|
-
// are disjoint
|
|
2828
|
-
// chromium will fall through to UNRELATED, matching
|
|
2851
|
+
// are disjoint), so the empty-list fallback is safe — peer
|
|
2852
|
+
// chromium will fall through to UNRELATED, matching earlier behaviour
|
|
2829
2853
|
// for the only realistic scenario (a stale peer browser on the wrong CDP
|
|
2830
2854
|
// port).
|
|
2831
2855
|
const peerBrands = (() => {
|
|
@@ -2892,7 +2916,7 @@ function installService() {
|
|
|
2892
2916
|
const classify = (ssOutput) => classifyPortHolder({
|
|
2893
2917
|
ssOutput, ownBrand, peerBrands, getCmdline: readCmdline,
|
|
2894
2918
|
});
|
|
2895
|
-
//
|
|
2919
|
+
// log line varies by detected holder so the operator can see
|
|
2896
2920
|
// which OWN_BRAND stack is being killed. The kill loop is identical for
|
|
2897
2921
|
// all three holders (SIGTERM → 300ms → recheck → SIGKILL → recheck), so
|
|
2898
2922
|
// only the announce line differs.
|
|
@@ -2983,7 +3007,7 @@ function installService() {
|
|
|
2983
3007
|
checkInstallPortFree("rfbPort", RFB_PORT);
|
|
2984
3008
|
checkInstallPortFree("websockifyPort", WEBSOCKIFY_PORT_BRAND);
|
|
2985
3009
|
checkInstallPortFree("cdpPort", CDP_PORT_BRAND);
|
|
2986
|
-
//
|
|
3010
|
+
// ACCOUNT_ID stamped into the brand unit so the writeNodeWithEdges
|
|
2987
3011
|
// gate at platform/lib/graph-write/src/index.ts:170 has a real identity to
|
|
2988
3012
|
// compare against (instead of process.env.ACCOUNT_ID === undefined). Resolved
|
|
2989
3013
|
// here AFTER setupAccount() ran upstream — seed-neo4j.sh wrote account.json,
|
|
@@ -3007,12 +3031,12 @@ function installService() {
|
|
|
3007
3031
|
rfbPort: RFB_PORT,
|
|
3008
3032
|
websockifyPort: WEBSOCKIFY_PORT_BRAND,
|
|
3009
3033
|
cdpPort: CDP_PORT_BRAND,
|
|
3010
|
-
claudeSessionManagerPort: CLAUDE_SESSION_MANAGER_PORT_BRAND,
|
|
3011
|
-
chromiumBin: RESOLVED_CHROMIUM_BIN,
|
|
3012
|
-
accountId: installAccountId,
|
|
3034
|
+
claudeSessionManagerPort: CLAUDE_SESSION_MANAGER_PORT_BRAND,
|
|
3035
|
+
chromiumBin: RESOLVED_CHROMIUM_BIN,
|
|
3036
|
+
accountId: installAccountId,
|
|
3013
3037
|
});
|
|
3014
3038
|
writeFileSync(join(serviceDir, BRAND.serviceName), serviceFile);
|
|
3015
|
-
//
|
|
3039
|
+
// (maxy-code) — write the claude-session-manager unit. The main
|
|
3016
3040
|
// brand unit Requires= + After= this one, so systemd starts it first.
|
|
3017
3041
|
const claudeSessionManagerUnitName = `${BRAND.hostname}-claude-session-manager.service`;
|
|
3018
3042
|
const claudeSessionManagerUnit = buildClaudeSessionManagerUnitFile({
|
|
@@ -3026,13 +3050,13 @@ function installService() {
|
|
|
3026
3050
|
});
|
|
3027
3051
|
writeFileSync(join(serviceDir, claudeSessionManagerUnitName), claudeSessionManagerUnit);
|
|
3028
3052
|
logFile(` ${claudeSessionManagerUnitName}: CLAUDE_SESSION_MANAGER_PORT=${CLAUDE_SESSION_MANAGER_PORT_BRAND}`);
|
|
3029
|
-
//
|
|
3053
|
+
// the edge service: always-on front door that owns the public
|
|
3030
3054
|
// port (PORT) and the VNC stack (Xtigervnc + websockify). Its lifecycle is
|
|
3031
3055
|
// independent of the main brand service, so an in-place upgrade triggered
|
|
3032
3056
|
// from the admin terminal can restart the main brand service without
|
|
3033
3057
|
// disconnecting the browser's remote terminal WebSocket.
|
|
3034
3058
|
//
|
|
3035
|
-
//
|
|
3059
|
+
// the unit is per-brand so two brands on the same device each
|
|
3036
3060
|
// own their own edge listener on their own EDGE_PORT — installing brand B
|
|
3037
3061
|
// never rewrites brand A's unit or steals brand A's public port. Upgrades
|
|
3038
3062
|
// from pre-662 installs require the manual recovery paragraph in
|
|
@@ -3040,7 +3064,7 @@ function installService() {
|
|
|
3040
3064
|
// intentionally scoped out.
|
|
3041
3065
|
// VNC_DISPLAY (defined above for the main brand unit) is also stamped into
|
|
3042
3066
|
// the edge unit so both services agree on the X display. Per-brand display
|
|
3043
|
-
// closes the cross-brand cookie leak documented
|
|
3067
|
+
// closes the cross-brand cookie leak documented.
|
|
3044
3068
|
const edgeTemplatePath = resolve(INSTALL_DIR, "platform/templates/systemd/edge.service.template");
|
|
3045
3069
|
if (existsSync(edgeTemplatePath)) {
|
|
3046
3070
|
const edgeServiceContent = readFileSync(edgeTemplatePath, "utf-8")
|
|
@@ -3058,7 +3082,7 @@ function installService() {
|
|
|
3058
3082
|
else {
|
|
3059
3083
|
console.error(` WARNING: edge.service.template missing at ${edgeTemplatePath} — VNC transport unavailable`);
|
|
3060
3084
|
}
|
|
3061
|
-
//
|
|
3085
|
+
// the unit declares Environment=PATH=%h/.local/bin:... so the graph
|
|
3062
3086
|
// MCP shim's spawn("uvx", ...) resolves against uv's install location. Without
|
|
3063
3087
|
// this line, the service inherits the default systemd-user PATH — which
|
|
3064
3088
|
// excludes ~/.local/bin — and the shim exits ENOENT before any query lands.
|
|
@@ -3113,7 +3137,7 @@ WantedBy=multi-user.target
|
|
|
3113
3137
|
catch { /* not critical */ }
|
|
3114
3138
|
// Reload and (re)start.
|
|
3115
3139
|
//
|
|
3116
|
-
//
|
|
3140
|
+
// ordering: on upgrades, the old main brand service still holds
|
|
3117
3141
|
// the public port (PORT). Stop it FIRST so the edge can bind that socket;
|
|
3118
3142
|
// starting the edge first would race against the old main brand service
|
|
3119
3143
|
// and fail with EADDRINUSE. Fresh installs: the stop is a no-op.
|
|
@@ -3184,7 +3208,7 @@ WantedBy=multi-user.target
|
|
|
3184
3208
|
// Tunnel script smoke check — the cloudflare SKILL contract invokes
|
|
3185
3209
|
// ~/setup-tunnel.sh directly. If the install-time symlink creation in
|
|
3186
3210
|
// installTunnelScripts() didn't land, fail the install loudly here rather
|
|
3187
|
-
// than shipping
|
|
3211
|
+
// than shipping a missing-symlink gap that would loop the agent on exit 127.
|
|
3188
3212
|
for (const linkPath of [
|
|
3189
3213
|
resolve(process.env.HOME ?? "/root", "setup-tunnel.sh"),
|
|
3190
3214
|
resolve(process.env.HOME ?? "/root", "reset-tunnel.sh"),
|
|
@@ -3204,7 +3228,7 @@ WantedBy=multi-user.target
|
|
|
3204
3228
|
}
|
|
3205
3229
|
}
|
|
3206
3230
|
// ---------------------------------------------------------------------------
|
|
3207
|
-
//
|
|
3231
|
+
// Samba provisioning. Runs after installService() so SMB never
|
|
3208
3232
|
// blocks the admin server starting; pure decisions live in samba-provision.ts.
|
|
3209
3233
|
//
|
|
3210
3234
|
// Four steps, each emitting one [install-invariant] samba-provision-<step>
|
|
@@ -3274,7 +3298,7 @@ function provisionSamba() {
|
|
|
3274
3298
|
// the PIN. Scoped tight: only these two literal arg-vectors are
|
|
3275
3299
|
// permitted; every other smbpasswd flavour still prompts.
|
|
3276
3300
|
const SUDOERS = "/etc/sudoers.d/maxy-samba";
|
|
3277
|
-
const sudoersBody = "#
|
|
3301
|
+
const sudoersBody = "# maxy-code Samba provisioning (smbpasswd sync from platform set-pin route).\n" +
|
|
3278
3302
|
"admin ALL=(root) NOPASSWD: /usr/bin/smbpasswd -a -s admin, /usr/bin/smbpasswd -x admin\n";
|
|
3279
3303
|
const sudoersTee = spawnSync("sudo", ["tee", SUDOERS], { input: sudoersBody, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 5_000 });
|
|
3280
3304
|
if (sudoersTee.status !== 0) {
|
|
@@ -3333,7 +3357,7 @@ if (_args.includes("--uninstall")) {
|
|
|
3333
3357
|
// systemd applies EnvironmentFile=-~/.{brand}/.env AFTER Environment=PORT,
|
|
3334
3358
|
// so .env is the final runtime truth and must be checked first on upgrade.
|
|
3335
3359
|
//
|
|
3336
|
-
//
|
|
3360
|
+
// this block also performs one-shot port-drift recovery against
|
|
3337
3361
|
// maxy-edge.service's Environment=EDGE_PORT=. See port-resolution.ts for the
|
|
3338
3362
|
// pure logic; unit tests live at __tests__/port-canonicalisation.test.mjs.
|
|
3339
3363
|
// ---------------------------------------------------------------------------
|
|
@@ -3514,7 +3538,7 @@ else {
|
|
|
3514
3538
|
//
|
|
3515
3539
|
// Default Maxy brand: 7687 (shared system Neo4j instance). Branded builds ship
|
|
3516
3540
|
// a dedicated port in brand.json (e.g. Real Agent = 7688) so installing a
|
|
3517
|
-
// second brand on the same device gets its own database by default
|
|
3541
|
+
// second brand on the same device gets its own database by default.
|
|
3518
3542
|
//
|
|
3519
3543
|
// Priority: --neo4j-port flag > .env NEO4J_URI (upgrade preserve) > BRAND.neo4jPort > 7687.
|
|
3520
3544
|
// ---------------------------------------------------------------------------
|
|
@@ -3556,24 +3580,24 @@ else {
|
|
|
3556
3580
|
// Dedicated = port differs from the default shared instance
|
|
3557
3581
|
const NEO4J_DEDICATED = NEO4J_PORT !== DEFAULT_NEO4J_PORT;
|
|
3558
3582
|
// ---------------------------------------------------------------------------
|
|
3559
|
-
//
|
|
3583
|
+
// removed the per-brand ttyd port — the admin terminal stack
|
|
3560
3584
|
// (ttyd, tmux, xterm.js) was retired in favour of the action runner that
|
|
3561
3585
|
// spawns transient `systemd-run --user` units per upgrade or setup-tunnel
|
|
3562
3586
|
// invocation. No TCP listener on the device needs to be reserved for an
|
|
3563
3587
|
// interactive-shell surface any more.
|
|
3564
3588
|
const PKG_VERSION = JSON.parse(readFileSync(resolve(import.meta.dirname, "../package.json"), "utf-8")).version;
|
|
3565
3589
|
// ---------------------------------------------------------------------------
|
|
3566
|
-
//
|
|
3590
|
+
// pre-flight platform refusal.
|
|
3567
3591
|
//
|
|
3568
3592
|
// Runs BEFORE initLogging() (LOG_DIR creation), port resolution, and any
|
|
3569
|
-
// brew/scutil/hostnamectl probe. Only Linux + darwin are supported
|
|
3593
|
+
// brew/scutil/hostnamectl probe. Only Linux + darwin are supported;
|
|
3570
3594
|
// on darwin, macOS major must be ≥ 14 (the floor required by Tasks 838/839).
|
|
3571
3595
|
// Older macOS partially succeeds, then breaks at the supervisor or brew-cellar
|
|
3572
3596
|
// layer with cryptic errors — refusing loudly here is the contract.
|
|
3573
3597
|
//
|
|
3574
3598
|
// Platform-header line is emitted on every install start so operators can grep
|
|
3575
3599
|
// `[create-maxy] platform=` to confirm pre-flight ran. On darwin the line also
|
|
3576
|
-
// carries `macos=<v>` (
|
|
3600
|
+
// carries `macos=<v>` (token) so the macOS-14 floor check is visible.
|
|
3577
3601
|
// ---------------------------------------------------------------------------
|
|
3578
3602
|
const PLATFORM = requireSupportedPlatform(process.platform);
|
|
3579
3603
|
let MACOS_VERSION = null;
|
|
@@ -3593,13 +3617,13 @@ if (PLATFORM === "darwin") {
|
|
|
3593
3617
|
}
|
|
3594
3618
|
}
|
|
3595
3619
|
// Platform-header — first log line. Operators grep `[create-maxy] platform=`
|
|
3596
|
-
// to confirm pre-flight ran. The /* macos=<v> */ token is the
|
|
3620
|
+
// to confirm pre-flight ran. The /* macos=<v> */ token is the marker;
|
|
3597
3621
|
// keep it on this same line so 3-way merges with parallel installer edits stay
|
|
3598
3622
|
// mechanical (no rewrap, no split into two log lines).
|
|
3599
3623
|
const PLATFORM_HEADER = `[create-maxy] platform=${PLATFORM} arch=${process.arch}` +
|
|
3600
3624
|
(MACOS_VERSION ? ` macos=${MACOS_VERSION}` : ``) +
|
|
3601
3625
|
` version=${PKG_VERSION}`;
|
|
3602
|
-
//
|
|
3626
|
+
// emit platform header and the resolved log/persist paths to
|
|
3603
3627
|
// stdout BEFORE the log file is opened. If initLogging's mkdir or first
|
|
3604
3628
|
// appendFileSync throws, the operator still sees brand/version/arch and the
|
|
3605
3629
|
// exact path the log file SHOULD live at, instead of a silent exit between
|
|
@@ -3631,24 +3655,24 @@ try {
|
|
|
3631
3655
|
installCloudflared();
|
|
3632
3656
|
installWhisperCpp();
|
|
3633
3657
|
deployPayload(); // Must happen before ensureNeo4jPassword — restores config backup
|
|
3634
|
-
//
|
|
3658
|
+
// write the resolved Chromium absolute path into the deployed
|
|
3635
3659
|
// platform/config/ so vnc.sh, writeChromiumWrapper, and setup-tunnel.sh
|
|
3636
3660
|
// all read the same value. Must run after deployPayload (config dir is
|
|
3637
3661
|
// a payload subdirectory). Linux-only; no-op on darwin/non-linux.
|
|
3638
3662
|
writeChromiumBinaryPathFile();
|
|
3639
|
-
//
|
|
3663
|
+
// scrub plaintext neo4j passwords from any pre-fix install-*.log.
|
|
3640
3664
|
// Idempotent — re-running on already-redacted logs is a no-op. Runs after
|
|
3641
3665
|
// payload deploy so the bundled redact-install-logs.sh is on disk.
|
|
3642
3666
|
redactInstallLogs();
|
|
3643
3667
|
ensureNeo4jPassword(); // Now config/.neo4j-password is available if it existed before
|
|
3644
|
-
provisionRemoteSessionSecret(); //
|
|
3668
|
+
provisionRemoteSessionSecret(); // shared HMAC key readable by maxy-edge + maxy-ui
|
|
3645
3669
|
buildPlatform();
|
|
3646
|
-
registerLocalAndExternalPlugins(); //
|
|
3670
|
+
registerLocalAndExternalPlugins(); // install-time plugin registration
|
|
3647
3671
|
setupVncViewer();
|
|
3648
3672
|
setupAccount();
|
|
3649
3673
|
installTunnelScripts(); // ~/setup-tunnel.sh, ~/reset-tunnel.sh — the SKILL contract
|
|
3650
3674
|
installService();
|
|
3651
|
-
//
|
|
3675
|
+
// Samba on the LAN. Runs after the brand systemd unit is up so
|
|
3652
3676
|
// SMB provisioning never blocks the admin server starting; loud-fail per
|
|
3653
3677
|
// step. The smbpasswd `user` step is deferred at install time and synced
|
|
3654
3678
|
// by the platform's /set-pin route when the operator sets a PIN.
|