@ouro.bot/cli 0.1.0-alpha.97 → 0.1.0-alpha.971
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +154 -23
- package/RepairGuide.ouro/agent.json +5 -0
- package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
- package/RepairGuide.ouro/psyche/SOUL.md +55 -0
- package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
- package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
- package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
- package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
- package/assets/bluebubbles-host +264 -0
- package/assets/sanctuary-host-launcher.sh +16 -0
- package/changelog.json +6141 -16
- package/deploy/unraid/Dockerfile +58 -0
- package/deploy/unraid/INSTALL.md +64 -0
- package/deploy/unraid/README.txt +2997 -0
- package/deploy/unraid/audit-container-spec.sh +4 -0
- package/deploy/unraid/container-runtime.json +1 -0
- package/deploy/unraid/credit-gateway.md +95 -0
- package/deploy/unraid/docker-man-template-transaction.mjs +727 -0
- package/deploy/unraid/docker-man-template-xml.cjs +105 -0
- package/deploy/unraid/install.sh +274 -0
- package/deploy/unraid/migrate-sanctuary-bundle.mjs +63 -0
- package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
- package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
- package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
- package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
- package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
- package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
- package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
- package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
- package/deploy/unraid/sanctuary-authority-installation.json +36 -0
- package/deploy/unraid/sanctuary-authority-service.sh +30 -0
- package/deploy/unraid/sanctuary-butler-upgrade.mjs +1356 -0
- package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
- package/deploy/unraid/sanctuary-replay-gate.mjs +1761 -0
- package/deploy/unraid/sanctuary-safe-rename.py +24 -0
- package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2086 -0
- package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
- package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
- package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
- package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
- package/deploy/unraid/sanctuary.ouro/awaiting/house-care-sweep.md +17 -0
- package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
- package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
- package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +2255 -0
- package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
- package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
- package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
- package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +27 -0
- package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +27 -0
- package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +22 -0
- package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
- package/deploy/unraid/sanctuary.ouro/tool-profiles.json +232 -0
- package/deploy/unraid/sanctuary.xml +30 -0
- package/dist/a2a/card.js +57 -0
- package/dist/a2a/client.js +250 -0
- package/dist/a2a/config.js +50 -0
- package/dist/a2a/delegated-command-grants.js +93 -0
- package/dist/a2a/delegated-command.js +197 -0
- package/dist/a2a/delegation-stores.js +56 -0
- package/dist/a2a/did-resolution.js +93 -0
- package/dist/a2a/escalation-grants.js +84 -0
- package/dist/a2a/escalation-wiring.js +60 -0
- package/dist/a2a/identity.js +258 -0
- package/dist/a2a/inbound-share.js +110 -0
- package/dist/a2a/mission-result-wire.js +196 -0
- package/dist/a2a/onboarding.js +133 -0
- package/dist/a2a/operator-trust.js +399 -0
- package/dist/a2a/outbox-client.js +57 -0
- package/dist/a2a/outbox-store.js +188 -0
- package/dist/a2a/outbox-wire.js +95 -0
- package/dist/a2a/pin-store.js +132 -0
- package/dist/a2a/replay-grant-holders.js +33 -0
- package/dist/a2a/replay-harness.js +188 -0
- package/dist/a2a/resolution-proof.js +53 -0
- package/dist/a2a/sealed-chat.js +113 -0
- package/dist/a2a/seen-ledger.js +120 -0
- package/dist/a2a/server.js +771 -0
- package/dist/a2a/task-store.js +69 -0
- package/dist/a2a/transport.js +45 -0
- package/dist/a2a/trust-commands.js +203 -0
- package/dist/a2a/trusted-files.js +185 -0
- package/dist/a2a/types.js +3 -0
- package/dist/arc/attention-types.js +8 -0
- package/dist/arc/cares.js +360 -0
- package/dist/arc/episodes.js +118 -0
- package/dist/arc/evolution.js +490 -0
- package/dist/arc/flight-recorder.js +1034 -0
- package/dist/arc/intentions.js +134 -0
- package/dist/arc/json-store.js +117 -0
- package/dist/arc/obligations.js +386 -0
- package/dist/arc/packets.js +336 -0
- package/dist/arc/presence.js +185 -0
- package/dist/arc/task-lifecycle.js +57 -0
- package/dist/commerce/store.js +755 -0
- package/dist/commerce/types.js +3 -0
- package/dist/gateway/keys.js +117 -0
- package/dist/gateway/server.js +429 -0
- package/dist/heart/active-work.js +798 -40
- package/dist/heart/agent-entry.js +252 -3
- package/dist/heart/approval-files.js +113 -0
- package/dist/heart/approval-store.js +960 -0
- package/dist/heart/attachments/image-normalize.js +201 -0
- package/dist/heart/attachments/materialize.js +97 -0
- package/dist/heart/attachments/originals.js +88 -0
- package/dist/heart/attachments/render.js +29 -0
- package/dist/heart/attachments/sources/bluebubbles.js +156 -0
- package/dist/heart/attachments/sources/cli-local-file.js +78 -0
- package/dist/heart/attachments/sources/index.js +18 -0
- package/dist/heart/attachments/sources/telegram.js +71 -0
- package/dist/heart/attachments/store.js +132 -0
- package/dist/heart/attachments/types.js +93 -0
- package/dist/heart/auth/auth-flow.js +511 -0
- package/dist/heart/autonomy-budget.js +478 -0
- package/dist/heart/awaiting/a2a-await-delivery.js +109 -0
- package/dist/heart/awaiting/await-alert.js +152 -0
- package/dist/heart/awaiting/await-expiry.js +143 -0
- package/dist/heart/awaiting/await-loader.js +91 -0
- package/dist/heart/awaiting/await-parser.js +152 -0
- package/dist/heart/awaiting/await-runtime-state.js +130 -0
- package/dist/heart/awaiting/await-scheduler.js +391 -0
- package/dist/heart/background-operations.js +281 -0
- package/dist/heart/bluebubbles-host-account.js +78 -0
- package/dist/heart/bridges/manager.js +137 -17
- package/dist/heart/bridges/store.js +14 -2
- package/dist/heart/bundle-state.js +168 -0
- package/dist/heart/commitments.js +44 -18
- package/dist/heart/config-registry.js +331 -0
- package/dist/heart/config.js +178 -131
- package/dist/heart/context-loss-gauntlet.js +387 -0
- package/dist/heart/context-loss-sentinel.js +1204 -0
- package/dist/heart/core.js +2377 -586
- package/dist/heart/cross-chat-delivery.js +9 -22
- package/dist/heart/daemon/agent-config-check.js +474 -0
- package/dist/heart/daemon/agent-discovery.js +283 -3
- package/dist/heart/daemon/agent-home.js +319 -0
- package/dist/heart/daemon/agent-service.js +542 -0
- package/dist/heart/daemon/agentic-repair.js +547 -0
- package/dist/heart/daemon/await-private-wake.js +59 -0
- package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
- package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
- package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
- package/dist/heart/daemon/bluebubbles-host.js +273 -0
- package/dist/heart/daemon/boot-sync-probe.js +197 -0
- package/dist/heart/daemon/cadence.js +180 -0
- package/dist/heart/daemon/cli-arg-redaction.js +26 -0
- package/dist/heart/daemon/cli-defaults.js +881 -0
- package/dist/heart/daemon/cli-desk.js +322 -0
- package/dist/heart/daemon/cli-exec.js +9267 -0
- package/dist/heart/daemon/cli-help.js +754 -0
- package/dist/heart/daemon/cli-parse.js +3329 -0
- package/dist/heart/daemon/cli-render-doctor.js +57 -0
- package/dist/heart/daemon/cli-render.js +819 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/connect-bay.js +323 -0
- package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
- package/dist/heart/daemon/container-healthcheck.js +112 -0
- package/dist/heart/daemon/container-runtime.js +97 -0
- package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
- package/dist/heart/daemon/container-spec-auditor.js +235 -0
- package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
- package/dist/heart/daemon/daemon-cli.js +29 -2360
- package/dist/heart/daemon/daemon-entry.js +953 -11
- package/dist/heart/daemon/daemon-health.js +186 -0
- package/dist/heart/daemon/daemon-rollup.js +57 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
- package/dist/heart/daemon/daemon-tombstone.js +236 -0
- package/dist/heart/daemon/daemon.js +2110 -104
- package/dist/heart/daemon/dns-workflow.js +394 -0
- package/dist/heart/daemon/doctor-types.js +8 -0
- package/dist/heart/daemon/doctor.js +1766 -0
- package/dist/heart/daemon/freshness.js +345 -0
- package/dist/heart/daemon/habit-private-wake.js +61 -0
- package/dist/heart/daemon/health-monitor.js +154 -11
- package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
- package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
- package/dist/heart/daemon/http-health-probe.js +80 -0
- package/dist/heart/daemon/human-command-screens.js +234 -0
- package/dist/heart/daemon/human-readiness.js +114 -0
- package/dist/heart/daemon/inner-status.js +78 -0
- package/dist/heart/daemon/interactive-repair.js +394 -0
- package/dist/heart/daemon/launchd.js +37 -8
- package/dist/heart/daemon/log-tailer.js +79 -10
- package/dist/heart/daemon/logs-prune.js +132 -0
- package/dist/heart/daemon/mcp-canary.js +524 -0
- package/dist/heart/daemon/message-router.js +65 -5
- package/dist/heart/daemon/migrate-to-desk.js +848 -0
- package/dist/heart/daemon/os-cron-deps.js +135 -0
- package/dist/heart/daemon/os-cron.js +22 -14
- package/dist/heart/daemon/ouro-bot-entry.js +6 -3
- package/dist/heart/daemon/ouro-entry.js +9 -3
- package/dist/heart/daemon/plugin-cli.js +432 -0
- package/dist/heart/daemon/process-manager.js +760 -61
- package/dist/heart/daemon/provider-discovery.js +137 -0
- package/dist/heart/daemon/provider-ping-progress.js +83 -0
- package/dist/heart/daemon/prunable-bundle.js +144 -0
- package/dist/heart/daemon/pulse.js +511 -0
- package/dist/heart/daemon/readiness-repair.js +365 -0
- package/dist/heart/daemon/run-hooks.js +2 -0
- package/dist/heart/daemon/runtime-logging.js +47 -14
- package/dist/heart/daemon/runtime-metadata.js +2 -30
- package/dist/heart/daemon/runtime-mode.js +13 -2
- package/dist/heart/daemon/safe-mode.js +161 -0
- package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
- package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
- package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
- package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
- package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
- package/dist/heart/daemon/sanctuary-authority-epoch.js +291 -0
- package/dist/heart/daemon/sanctuary-authority-installation.js +161 -0
- package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
- package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +1324 -0
- package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
- package/dist/heart/daemon/sanctuary-bundle-migration.js +730 -0
- package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
- package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +493 -0
- package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
- package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
- package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
- package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
- package/dist/heart/daemon/sanctuary-package-management.js +103 -0
- package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
- package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +475 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-service.js +676 -0
- package/dist/heart/daemon/sense-manager.js +786 -48
- package/dist/heart/daemon/session-id-resolver.js +131 -0
- package/dist/heart/daemon/skill-management-installer.js +1 -1
- package/dist/heart/daemon/socket-client.js +180 -12
- package/dist/heart/daemon/stale-bundle-prune.js +113 -0
- package/dist/heart/daemon/startup-tui.js +339 -0
- package/dist/heart/daemon/supercronic-supervisor.js +282 -0
- package/dist/heart/daemon/task-scheduler.js +117 -39
- package/dist/heart/daemon/terminal-ui.js +503 -0
- package/dist/heart/daemon/thoughts.js +138 -54
- package/dist/heart/daemon/up-progress.js +366 -0
- package/dist/heart/daemon/vault-items.js +56 -0
- package/dist/heart/delegation.js +1 -4
- package/dist/heart/external-events/router.js +1531 -0
- package/dist/heart/failure-reports.js +336 -0
- package/dist/heart/file-lock.js +109 -0
- package/dist/heart/frontend-approval-runtime.js +506 -0
- package/dist/heart/frontend-journal.js +215 -0
- package/dist/heart/frontend-session-service.js +271 -0
- package/dist/heart/frontend-socket-client.js +173 -0
- package/dist/heart/frontend-socket.js +434 -0
- package/dist/heart/frontend-turn-errors.js +20 -0
- package/dist/heart/habits/habit-cancel.js +810 -0
- package/dist/heart/habits/habit-lifecycle.js +1327 -0
- package/dist/heart/habits/habit-migration.js +194 -0
- package/dist/heart/habits/habit-parser.js +278 -0
- package/dist/heart/habits/habit-runtime-state.js +93 -0
- package/dist/heart/habits/habit-scheduler.js +653 -0
- package/dist/heart/habits/habit-session-summary.js +318 -0
- package/dist/heart/habits/habit-session.js +636 -0
- package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
- package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
- package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
- package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
- package/dist/heart/identity.js +239 -59
- package/dist/heart/kept-notes.js +289 -0
- package/dist/heart/kicks.js +1 -1
- package/dist/heart/machine-identity.js +175 -0
- package/dist/heart/mail-import-discovery.js +356 -0
- package/dist/heart/mailbox/mailbox-http-hooks.js +99 -0
- package/dist/heart/mailbox/mailbox-http-response.js +7 -0
- package/dist/heart/mailbox/mailbox-http-routes.js +406 -0
- package/dist/heart/mailbox/mailbox-http-static.js +103 -0
- package/dist/heart/mailbox/mailbox-http-transport.js +272 -0
- package/dist/heart/mailbox/mailbox-http.js +99 -0
- package/dist/heart/mailbox/mailbox-read.js +41 -0
- package/dist/heart/mailbox/mailbox-supervision.js +131 -0
- package/dist/heart/mailbox/mailbox-types.js +27 -0
- package/dist/heart/mailbox/mailbox-view.js +197 -0
- package/dist/heart/mailbox/readers/agent-machine.js +428 -0
- package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
- package/dist/heart/mailbox/readers/mail.js +375 -0
- package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
- package/dist/heart/mailbox/readers/sessions.js +231 -0
- package/dist/heart/mailbox/readers/shared.js +111 -0
- package/dist/heart/mcp/mcp-server.js +760 -0
- package/dist/heart/migrate-config.js +100 -0
- package/dist/heart/model-capabilities.js +83 -16
- package/dist/heart/orientation-frame.js +376 -0
- package/dist/heart/platform.js +81 -0
- package/dist/heart/primitives.js +1 -1
- package/dist/heart/private-runtime/decision-renderer.js +158 -0
- package/dist/heart/private-runtime/index.js +18 -0
- package/dist/heart/private-runtime/ledger.js +221 -0
- package/dist/heart/private-runtime/policy.js +260 -0
- package/dist/heart/private-runtime/types.js +2 -0
- package/dist/heart/progress-story.js +1 -1
- package/dist/heart/provider-attempt.js +137 -0
- package/dist/heart/provider-binding-resolver.js +273 -0
- package/dist/heart/provider-credentials.js +449 -0
- package/dist/heart/provider-failover.js +311 -0
- package/dist/heart/provider-models.js +96 -0
- package/dist/heart/provider-ping.js +266 -0
- package/dist/heart/provider-readiness-cache.js +119 -0
- package/dist/heart/provider-visibility.js +188 -0
- package/dist/heart/providers/anthropic-token.js +131 -0
- package/dist/heart/providers/anthropic.js +248 -67
- package/dist/heart/providers/azure.js +23 -11
- package/dist/heart/providers/error-classification.js +129 -0
- package/dist/heart/providers/github-copilot.js +38 -39
- package/dist/heart/providers/minimax-vlm.js +189 -0
- package/dist/heart/providers/minimax.js +26 -8
- package/dist/heart/providers/openai-codex-token.js +349 -0
- package/dist/heart/providers/openai-codex.js +55 -40
- package/dist/heart/providers/openai-compatible.js +177 -0
- package/dist/heart/reach-channel.js +85 -0
- package/dist/heart/reply-style.js +52 -0
- package/dist/heart/run-ledger.js +247 -0
- package/dist/heart/runtime-capability-check.js +170 -0
- package/dist/heart/runtime-credentials.js +608 -0
- package/dist/heart/runtime-cwd.js +87 -0
- package/dist/heart/sense-truth.js +24 -4
- package/dist/heart/session-activity.js +94 -24
- package/dist/heart/session-events.js +1521 -0
- package/dist/heart/session-playback-cli-main.js +5 -0
- package/dist/heart/session-playback-cli.js +36 -0
- package/dist/heart/session-playback.js +231 -0
- package/dist/heart/session-redaction-repair-cli-main.js +31 -0
- package/dist/heart/session-redaction-repair.js +552 -0
- package/dist/heart/session-stats-cli-main.js +5 -0
- package/dist/heart/session-stats.js +183 -0
- package/dist/heart/session-transcript.js +133 -0
- package/dist/heart/shelf-claims.js +78 -0
- package/dist/heart/shepherd/custody-types.js +2 -0
- package/dist/heart/shepherd/mandates.js +352 -0
- package/dist/heart/shepherd/operation-commands.js +19 -0
- package/dist/heart/shepherd/operations.js +135 -0
- package/dist/heart/shepherd/supervision.js +114 -0
- package/dist/heart/shepherd/types.js +2 -0
- package/dist/heart/shepherd-config.js +123 -0
- package/dist/heart/source-grounding.js +302 -0
- package/dist/heart/start-of-turn-packet.js +372 -0
- package/dist/heart/steward-policy.js +656 -0
- package/dist/heart/streaming.js +631 -207
- package/dist/heart/structured-output.js +196 -0
- package/dist/heart/sync-classification.js +176 -0
- package/dist/heart/sync-health.js +152 -0
- package/dist/heart/sync.js +726 -0
- package/dist/heart/target-resolution.js +11 -7
- package/dist/heart/tempo.js +93 -0
- package/dist/heart/temporal-view.js +41 -0
- package/dist/heart/timeouts.js +101 -0
- package/dist/heart/tool-activity-callbacks.js +59 -0
- package/dist/heart/tool-approval.js +382 -0
- package/dist/heart/tool-description.js +155 -0
- package/dist/heart/tool-friction.js +55 -0
- package/dist/heart/tool-loop.js +206 -0
- package/dist/heart/turn-context.js +496 -0
- package/dist/heart/turn-execution-lease.js +30 -0
- package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
- package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +3 -2
- package/dist/heart/versioning/ouro-path-installer.js +432 -0
- package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
- package/dist/heart/versioning/ouro-version-manager.js +432 -0
- package/dist/heart/versioning/release-sources.js +173 -0
- package/dist/heart/versioning/self-update-defaults.js +294 -0
- package/dist/heart/versioning/self-update.js +196 -0
- package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
- package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
- package/dist/heart/versioning/update-hooks.js +154 -0
- package/dist/heart/versioning/update-state.js +126 -0
- package/dist/heart/versioning/updater-launchd.js +150 -0
- package/dist/heart/versioning/version-intent.js +114 -0
- package/dist/heart/work-card.js +380 -0
- package/dist/mailbox-ui/assets/index-Dbska1tZ.js +1 -0
- package/dist/mailbox-ui/assets/index-DsiKaPyH.css +1 -0
- package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
- package/dist/mailbox-ui/index.html +16 -0
- package/dist/mailroom/attention.js +167 -0
- package/dist/mailroom/autonomy.js +209 -0
- package/dist/mailroom/blob-store.js +889 -0
- package/dist/mailroom/body-cache.js +61 -0
- package/dist/mailroom/cache-sync-cli.js +58 -0
- package/dist/mailroom/core.js +803 -0
- package/dist/mailroom/entry.js +160 -0
- package/dist/mailroom/file-store.js +568 -0
- package/dist/mailroom/hosted-cache-sync.js +384 -0
- package/dist/mailroom/mbox-import.js +393 -0
- package/dist/mailroom/migration.js +164 -0
- package/dist/mailroom/outbound.js +380 -0
- package/dist/mailroom/policy.js +263 -0
- package/dist/mailroom/reader.js +292 -0
- package/dist/mailroom/search-cache.js +513 -0
- package/dist/mailroom/search-relevance.js +319 -0
- package/dist/mailroom/smtp-ingress.js +176 -0
- package/dist/mailroom/source-state.js +176 -0
- package/dist/mailroom/thread.js +109 -0
- package/dist/mailroom/travel-extract.js +89 -0
- package/dist/mind/bundle-manifest.js +24 -2
- package/dist/mind/context.js +328 -139
- package/dist/mind/desk-section.js +362 -0
- package/dist/mind/diary-integrity.js +60 -0
- package/dist/mind/{memory.js → diary.js} +68 -77
- package/dist/mind/embedding-provider.js +60 -0
- package/dist/mind/file-state.js +179 -0
- package/dist/mind/friend-link-codes.js +209 -0
- package/dist/mind/friend-merge.js +336 -0
- package/dist/mind/{associative-recall.js → note-search.js} +47 -58
- package/dist/mind/obligation-steering.js +199 -3
- package/dist/mind/outbound-record.js +168 -0
- package/dist/mind/pending.js +36 -10
- package/dist/mind/prompt-budget.js +479 -0
- package/dist/mind/prompt-refresh.js +3 -2
- package/dist/mind/prompt.js +1130 -199
- package/dist/mind/provenance-trust.js +26 -0
- package/dist/mind/record-paths.js +312 -0
- package/dist/mind/scrutiny.js +173 -0
- package/dist/mind/session-transaction.js +622 -0
- package/dist/nerves/cli-logging.js +7 -1
- package/dist/nerves/coverage/audit-rules.js +15 -6
- package/dist/nerves/coverage/audit.js +28 -2
- package/dist/nerves/coverage/cli.js +1 -1
- package/dist/nerves/coverage/contract.js +5 -5
- package/dist/nerves/coverage/file-completeness.js +143 -5
- package/dist/nerves/coverage/run-artifacts.js +55 -35
- package/dist/nerves/coverage/source-scanner.js +4 -4
- package/dist/nerves/event-buffer.js +111 -0
- package/dist/nerves/index.js +293 -9
- package/dist/nerves/observation.js +20 -0
- package/dist/nerves/redact.js +79 -0
- package/dist/nerves/review/cli-main.js +5 -0
- package/dist/nerves/review/cli.js +156 -0
- package/dist/nerves/review/core.js +159 -0
- package/dist/nerves/runtime.js +17 -1
- package/dist/repertoire/ado-client.js +15 -56
- package/dist/repertoire/ado-semantic.js +16 -10
- package/dist/repertoire/api-client.js +97 -0
- package/dist/repertoire/bitwarden-store.js +1199 -0
- package/dist/repertoire/bundle-templates.js +71 -0
- package/dist/repertoire/bw-installer.js +231 -0
- package/dist/repertoire/coding/codex-jsonl.js +64 -0
- package/dist/repertoire/coding/context-pack.js +331 -0
- package/dist/repertoire/coding/feedback.js +146 -34
- package/dist/repertoire/coding/index.js +15 -3
- package/dist/repertoire/coding/manager.js +159 -10
- package/dist/repertoire/coding/spawner.js +40 -11
- package/dist/repertoire/coding/tools.js +182 -18
- package/dist/repertoire/coding/workbench-client.js +272 -0
- package/dist/repertoire/coding/workbench-manager.js +346 -0
- package/dist/repertoire/commerce-errors.js +109 -0
- package/dist/repertoire/commerce-self-test.js +156 -0
- package/dist/repertoire/credential-access.js +183 -0
- package/dist/repertoire/desk/classifier.js +362 -0
- package/dist/repertoire/duffel-client.js +185 -0
- package/dist/repertoire/github-client.js +14 -55
- package/dist/repertoire/graph-client.js +11 -52
- package/dist/repertoire/guardrails.js +971 -20
- package/dist/repertoire/house-sweep.js +471 -0
- package/dist/repertoire/mcp-client.js +58 -5
- package/dist/repertoire/mcp-manager.js +427 -139
- package/dist/repertoire/mcp-tools.js +132 -0
- package/dist/repertoire/mcp-write-guard.js +46 -0
- package/dist/repertoire/plugin-mcp.js +175 -0
- package/dist/repertoire/plugins.js +253 -0
- package/dist/repertoire/relationship-authorization.js +322 -0
- package/dist/repertoire/sanctuary-container-policy.js +50 -0
- package/dist/repertoire/shell-sessions.js +134 -0
- package/dist/repertoire/skills.js +48 -4
- package/dist/repertoire/stripe-client.js +131 -0
- package/dist/repertoire/tool-arguments.js +182 -0
- package/dist/repertoire/tool-results.js +29 -0
- package/dist/repertoire/tools-a2a.js +699 -0
- package/dist/repertoire/tools-attachments.js +322 -0
- package/dist/repertoire/tools-awaiting.js +897 -0
- package/dist/repertoire/tools-base.js +83 -1168
- package/dist/repertoire/tools-bluebubbles.js +2 -0
- package/dist/repertoire/tools-bridge.js +144 -0
- package/dist/repertoire/tools-bundle.js +995 -0
- package/dist/repertoire/tools-commerce.js +253 -0
- package/dist/repertoire/tools-config.js +186 -0
- package/dist/repertoire/tools-continuity.js +588 -0
- package/dist/repertoire/tools-credential.js +383 -0
- package/dist/repertoire/tools-escalation.js +84 -0
- package/dist/repertoire/tools-evolution.js +527 -0
- package/dist/repertoire/tools-files.js +344 -0
- package/dist/repertoire/tools-flight.js +290 -0
- package/dist/repertoire/tools-flow.js +119 -0
- package/dist/repertoire/tools-friend-link.js +57 -0
- package/dist/repertoire/tools-github.js +3 -8
- package/dist/repertoire/tools-habits.js +103 -0
- package/dist/repertoire/tools-house-care.js +174 -0
- package/dist/repertoire/tools-mail.js +1828 -0
- package/dist/repertoire/tools-notes.js +501 -0
- package/dist/repertoire/tools-obligations.js +182 -0
- package/dist/repertoire/tools-orientation.js +31 -0
- package/dist/repertoire/tools-record.js +482 -0
- package/dist/repertoire/tools-rsvp.js +139 -0
- package/dist/repertoire/tools-runtime.js +238 -0
- package/dist/repertoire/tools-sanctuary-host.js +202 -0
- package/dist/repertoire/tools-session.js +1141 -0
- package/dist/repertoire/tools-shell.js +154 -0
- package/dist/repertoire/tools-shepherd-guidance.js +171 -0
- package/dist/repertoire/tools-shepherd.js +325 -0
- package/dist/repertoire/tools-steward-policy.js +147 -0
- package/dist/repertoire/tools-stripe.js +224 -0
- package/dist/repertoire/tools-surface.js +369 -0
- package/dist/repertoire/tools-teams.js +50 -39
- package/dist/repertoire/tools-telegram-contacts.js +37 -0
- package/dist/repertoire/tools-travel.js +125 -0
- package/dist/repertoire/tools-trip.js +982 -0
- package/dist/repertoire/tools-unraid.js +556 -0
- package/dist/repertoire/tools-user-profile.js +146 -0
- package/dist/repertoire/tools-vault.js +40 -0
- package/dist/repertoire/tools-voice-local.js +198 -0
- package/dist/repertoire/tools-voice.js +145 -0
- package/dist/repertoire/tools.js +518 -156
- package/dist/repertoire/travel-api-client.js +360 -0
- package/dist/repertoire/unraid-client.js +155 -0
- package/dist/repertoire/unraid-restart.js +339 -0
- package/dist/repertoire/user-profile.js +131 -0
- package/dist/repertoire/vault-setup.js +246 -0
- package/dist/repertoire/vault-unlock.js +686 -0
- package/dist/rsvp/aisleplanner-client.js +354 -0
- package/dist/rsvp/cli.js +936 -0
- package/dist/rsvp/config.js +327 -0
- package/dist/rsvp/cutover.js +433 -0
- package/dist/rsvp/diagnostics.js +232 -0
- package/dist/rsvp/diff-renderer.js +176 -0
- package/dist/rsvp/habit-policy.js +110 -0
- package/dist/rsvp/habit-stage.js +123 -0
- package/dist/rsvp/incident-bundle.js +97 -0
- package/dist/rsvp/migration.js +204 -0
- package/dist/rsvp/native-habit-runner.js +630 -0
- package/dist/rsvp/outbound-state.js +628 -0
- package/dist/rsvp/query.js +118 -0
- package/dist/rsvp/replay.js +233 -0
- package/dist/rsvp/snapshot.js +232 -0
- package/dist/rsvp/spend-ledger.js +175 -0
- package/dist/scripts/claude-code-hook.js +41 -0
- package/dist/scripts/claude-code-stop-hook.js +47 -0
- package/dist/senses/a2a-entry.js +132 -0
- package/dist/senses/acp-server.js +386 -0
- package/dist/senses/attention-queue.js +186 -0
- package/dist/senses/await-turn-message.js +65 -0
- package/dist/senses/bluebubbles/active-turns.js +216 -0
- package/dist/senses/bluebubbles/attachment-cache.js +53 -0
- package/dist/senses/bluebubbles/attachment-download.js +137 -0
- package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +393 -43
- package/dist/senses/bluebubbles/context-packet.js +207 -0
- package/dist/senses/bluebubbles/context-smoke.js +144 -0
- package/dist/senses/bluebubbles/entry.js +90 -0
- package/dist/senses/bluebubbles/host-account-verifier.js +88 -0
- package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
- package/dist/senses/bluebubbles/index.js +4054 -0
- package/dist/senses/bluebubbles/latest-turn.js +311 -0
- package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
- package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
- package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
- package/dist/senses/bluebubbles/outbound-state.js +335 -0
- package/dist/senses/bluebubbles/processed-log.js +133 -0
- package/dist/senses/bluebubbles/reaction-policy.js +47 -0
- package/dist/senses/bluebubbles/replay.js +284 -0
- package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
- package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
- package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
- package/dist/senses/bluebubbles/webhook-registration.js +257 -0
- package/dist/senses/bluebubbles-meta-guard.js +39 -0
- package/dist/senses/cli/bracketed-paste.js +82 -0
- package/dist/senses/cli/image-paste.js +287 -0
- package/dist/senses/cli/image-ref-navigation.js +75 -0
- package/dist/senses/cli/ink-app.js +156 -0
- package/dist/senses/cli/inline-diff.js +64 -0
- package/dist/senses/cli/input-keys.js +174 -0
- package/dist/senses/cli/kill-ring.js +86 -0
- package/dist/senses/cli/message-list.js +51 -0
- package/dist/senses/cli/ouro-tui.js +607 -0
- package/dist/senses/cli/spinner-imperative.js +135 -0
- package/dist/senses/cli/spinner.js +101 -0
- package/dist/senses/cli/status-line.js +60 -0
- package/dist/senses/cli/streaming-markdown.js +526 -0
- package/dist/senses/cli/tool-display.js +85 -0
- package/dist/senses/cli/tool-render.js +85 -0
- package/dist/senses/cli/tui-store.js +241 -0
- package/dist/senses/cli/virtual-list.js +35 -0
- package/dist/senses/cli-entry.js +60 -8
- package/dist/senses/cli.js +570 -309
- package/dist/senses/commands.js +66 -3
- package/dist/senses/context-packet-ledger.js +371 -0
- package/dist/senses/context-packets.js +154 -0
- package/dist/senses/habit-lifecycle-guard.js +24 -0
- package/dist/senses/habit-turn-message.js +160 -0
- package/dist/senses/ingress-evidence.js +2 -0
- package/dist/senses/mail-entry.js +66 -0
- package/dist/senses/mail.js +524 -0
- package/dist/senses/pipeline.js +1158 -204
- package/dist/senses/private-runtime-worker.js +857 -0
- package/dist/senses/private-runtime.js +1627 -0
- package/dist/senses/proactive-content-guard.js +51 -0
- package/dist/senses/root-host-approval-port.js +345 -0
- package/dist/senses/root-host-approval-runtime.js +393 -0
- package/dist/senses/sanctuary-authority-resident.js +102 -0
- package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
- package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
- package/dist/senses/sanctuary-grounding.js +118 -0
- package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
- package/dist/senses/sanctuary-health-acceptance-probe.js +786 -0
- package/dist/senses/sanctuary-health-runner.js +106 -0
- package/dist/senses/sanctuary-health.js +442 -0
- package/dist/senses/sanctuary-house.js +97 -0
- package/dist/senses/sanctuary-install-state-contract.js +169 -0
- package/dist/senses/sanctuary-interactive-control.js +410 -0
- package/dist/senses/sanctuary-media-catalog-contract.js +268 -0
- package/dist/senses/sanctuary-media-optimization.js +514 -0
- package/dist/senses/sanctuary-runtime.js +371 -0
- package/dist/senses/sanctuary-sab.js +85 -0
- package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
- package/dist/senses/shared-turn.js +832 -0
- package/dist/senses/shepherd/agent-presentation.js +88 -0
- package/dist/senses/shepherd/attention-page.js +166 -0
- package/dist/senses/shepherd/attention-sidebar.js +76 -0
- package/dist/senses/shepherd/attention.js +295 -0
- package/dist/senses/shepherd/checkin-config.js +76 -0
- package/dist/senses/shepherd/checkin-store.js +386 -0
- package/dist/senses/shepherd/client.js +196 -0
- package/dist/senses/shepherd/cmux.js +483 -0
- package/dist/senses/shepherd/composer.js +336 -0
- package/dist/senses/shepherd/copilot-app.js +648 -0
- package/dist/senses/shepherd/feedback-reply.js +108 -0
- package/dist/senses/shepherd/feedback-source.js +20 -0
- package/dist/senses/shepherd/feedback-store.js +331 -0
- package/dist/senses/shepherd/feedback-submit.js +182 -0
- package/dist/senses/shepherd/feedback-worker.js +208 -0
- package/dist/senses/shepherd/guidance.js +273 -0
- package/dist/senses/shepherd/herdr.js +427 -0
- package/dist/senses/shepherd/host.js +17 -0
- package/dist/senses/shepherd/human-decision-guard.js +29 -0
- package/dist/senses/shepherd/judge-evaluation-command.js +183 -0
- package/dist/senses/shepherd/judge-evaluation-entry.js +13 -0
- package/dist/senses/shepherd/judge-evaluation.js +155 -0
- package/dist/senses/shepherd/judge.js +210 -0
- package/dist/senses/shepherd/notice-outbox.js +262 -0
- package/dist/senses/shepherd/observation-publisher.js +320 -0
- package/dist/senses/shepherd/operations-defaults.js +86 -0
- package/dist/senses/shepherd/operations.js +159 -0
- package/dist/senses/shepherd/owner-notice.js +489 -0
- package/dist/senses/shepherd/prompt-state.js +60 -0
- package/dist/senses/shepherd/recovery.js +543 -0
- package/dist/senses/shepherd/redact.js +66 -0
- package/dist/senses/shepherd/returns.js +79 -0
- package/dist/senses/shepherd/sense.js +849 -0
- package/dist/senses/shepherd/shepherd-judge-corpus-v1.json +170 -0
- package/dist/senses/shepherd/surface.js +123 -0
- package/dist/senses/shepherd/target-binding.js +13 -0
- package/dist/senses/shepherd/terminal-process.js +147 -0
- package/dist/senses/shepherd-entry.js +98 -0
- package/dist/senses/surface-tool.js +109 -0
- package/dist/senses/teams-entry.js +68 -8
- package/dist/senses/teams-image.js +119 -0
- package/dist/senses/teams.js +998 -337
- package/dist/senses/telegram-admission.js +718 -0
- package/dist/senses/telegram-approval-runtime.js +793 -0
- package/dist/senses/telegram-attachments.js +186 -0
- package/dist/senses/telegram-audit-ledger.js +220 -0
- package/dist/senses/telegram-authority-transport.js +231 -0
- package/dist/senses/telegram-client.js +1755 -0
- package/dist/senses/telegram-effect-adapter.js +904 -0
- package/dist/senses/telegram-entry.js +83 -0
- package/dist/senses/telegram-handoff.js +154 -0
- package/dist/senses/telegram.js +2474 -0
- package/dist/senses/trust-gate.js +104 -9
- package/dist/senses/voice/audio-playback.js +237 -0
- package/dist/senses/voice/audio-routing.js +119 -0
- package/dist/senses/voice/call-auth.js +250 -0
- package/dist/senses/voice/elevenlabs.js +202 -0
- package/dist/senses/voice/floor-control.js +431 -0
- package/dist/senses/voice/floor-controller.js +115 -0
- package/dist/senses/voice/golden-path.js +116 -0
- package/dist/senses/voice/index.js +29 -0
- package/dist/senses/voice/local-audio-control.js +344 -0
- package/dist/senses/voice/local-audio-devices.js +516 -0
- package/dist/senses/voice/local-audio-disclosure.js +174 -0
- package/dist/senses/voice/local-audio-identity.js +103 -0
- package/dist/senses/voice/local-audio-join.js +325 -0
- package/dist/senses/voice/local-audio-mute.js +199 -0
- package/dist/senses/voice/local-audio-notify.js +124 -0
- package/dist/senses/voice/local-audio-prompts.js +116 -0
- package/dist/senses/voice/local-audio-transport.js +427 -0
- package/dist/senses/voice/local-audio.js +281 -0
- package/dist/senses/voice/local-media-stream.js +145 -0
- package/dist/senses/voice/meeting.js +113 -0
- package/dist/senses/voice/outbound.js +190 -0
- package/dist/senses/voice/phone.js +33 -0
- package/dist/senses/voice/playback.js +139 -0
- package/dist/senses/voice/process-guards.js +51 -0
- package/dist/senses/voice/realtime-eval.js +496 -0
- package/dist/senses/voice/realtime-tool-schema.js +195 -0
- package/dist/senses/voice/realtime-trace.js +531 -0
- package/dist/senses/voice/transcript.js +70 -0
- package/dist/senses/voice/turn.js +191 -0
- package/dist/senses/voice/twilio-phone-runtime.js +836 -0
- package/dist/senses/voice/twilio-phone.js +5454 -0
- package/dist/senses/voice/types.js +2 -0
- package/dist/senses/voice/whisper.js +161 -0
- package/dist/senses/voice-entry.js +83 -0
- package/dist/senses/voice-realtime-eval-command.js +99 -0
- package/dist/senses/voice-realtime-eval-entry.js +21 -0
- package/dist/senses/voice-twilio-entry.js +87 -0
- package/dist/trips/core.js +138 -0
- package/dist/trips/store.js +265 -0
- package/dist/util/frontmatter.js +69 -0
- package/npm-shrinkwrap.json +8190 -0
- package/package.json +75 -13
- package/skills/agent-commerce.md +113 -0
- package/skills/browser-navigation.md +117 -0
- package/skills/commerce-setup-guide.md +116 -0
- package/skills/commerce-setup.md +84 -0
- package/skills/configure-dev-tools.md +99 -0
- package/skills/travel-planning.md +138 -0
- package/dist/heart/daemon/auth-flow.js +0 -430
- package/dist/heart/daemon/ouro-path-installer.js +0 -260
- package/dist/heart/daemon/ouro-version-manager.js +0 -171
- package/dist/heart/daemon/update-hooks.js +0 -138
- package/dist/heart/obligations.js +0 -191
- package/dist/heart/safe-workspace.js +0 -381
- package/dist/heart/session-recall.js +0 -116
- package/dist/mind/friends/channel.js +0 -84
- package/dist/mind/friends/group-context.js +0 -144
- package/dist/mind/friends/resolver.js +0 -84
- package/dist/mind/friends/store-file.js +0 -190
- package/dist/mind/friends/store.js +0 -4
- package/dist/mind/friends/tokens.js +0 -26
- package/dist/mind/friends/trust-explanation.js +0 -74
- package/dist/mind/friends/types.js +0 -29
- package/dist/repertoire/tasks/board.js +0 -134
- package/dist/repertoire/tasks/index.js +0 -224
- package/dist/repertoire/tasks/lifecycle.js +0 -80
- package/dist/repertoire/tasks/middleware.js +0 -65
- package/dist/repertoire/tasks/parser.js +0 -173
- package/dist/repertoire/tasks/scanner.js +0 -132
- package/dist/repertoire/tasks/transitions.js +0 -144
- package/dist/senses/bluebubbles-entry.js +0 -13
- package/dist/senses/bluebubbles.js +0 -1181
- package/dist/senses/debug-activity.js +0 -154
- package/dist/senses/inner-dialog-worker.js +0 -90
- package/dist/senses/inner-dialog.js +0 -525
- package/subagents/README.md +0 -7
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
- /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
- /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
- /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
- /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
- /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
const { TextDecoder } = require("node:util")
|
|
4
|
+
|
|
5
|
+
const DECLARATION = "<?xml version=\"1.0\"?>"
|
|
6
|
+
const ROOT_OPEN = "<Container version=\"2\">"
|
|
7
|
+
const ROOT_CLOSE = "</Container>"
|
|
8
|
+
const NAME_START = /^[A-Za-z_]$/u
|
|
9
|
+
const NAME_CHARACTER = /^[A-Za-z0-9_.:-]$/u
|
|
10
|
+
const XML_WHITESPACE = /^[\t\n\r ]$/u
|
|
11
|
+
const UTF8_DECODER = new TextDecoder("utf-8", { fatal: true })
|
|
12
|
+
|
|
13
|
+
function decodeUtf8(value) {
|
|
14
|
+
if (typeof value === "string") return value
|
|
15
|
+
if (!(value instanceof Uint8Array)) throw new TypeError("DockerMan template bytes are invalid")
|
|
16
|
+
return UTF8_DECODER.decode(value)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function skipWhitespace(value, start) {
|
|
20
|
+
let index = start
|
|
21
|
+
while (XML_WHITESPACE.test(value[index] ?? "")) index += 1
|
|
22
|
+
return index
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function readName(value, start) {
|
|
26
|
+
if (!NAME_START.test(value[start] ?? "")) return null
|
|
27
|
+
let index = start + 1
|
|
28
|
+
while (NAME_CHARACTER.test(value[index] ?? "")) index += 1
|
|
29
|
+
return { name: value.slice(start, index), index }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function readOpenTag(xml, start) {
|
|
33
|
+
if (xml[start] !== "<") return null
|
|
34
|
+
const parsedName = readName(xml, start + 1)
|
|
35
|
+
if (!parsedName) return null
|
|
36
|
+
const attributes = new Map()
|
|
37
|
+
let index = parsedName.index
|
|
38
|
+
while (index < xml.length) {
|
|
39
|
+
if (xml[index] === ">") return { name: parsedName.name, attributes: Object.fromEntries(attributes), form: "text", index: index + 1 }
|
|
40
|
+
if (xml.startsWith("/>", index)) return { name: parsedName.name, attributes: Object.fromEntries(attributes), form: "empty", index: index + 2 }
|
|
41
|
+
const whitespaceEnd = skipWhitespace(xml, index)
|
|
42
|
+
if (whitespaceEnd === index) return null
|
|
43
|
+
index = whitespaceEnd
|
|
44
|
+
if (xml[index] === ">" || xml.startsWith("/>", index)) continue
|
|
45
|
+
const attribute = readName(xml, index)
|
|
46
|
+
if (!attribute || attributes.has(attribute.name)) return null
|
|
47
|
+
index = skipWhitespace(xml, attribute.index)
|
|
48
|
+
if (xml[index] !== "=") return null
|
|
49
|
+
index = skipWhitespace(xml, index + 1)
|
|
50
|
+
if (xml[index] !== "\"") return null
|
|
51
|
+
const end = xml.indexOf("\"", index + 1)
|
|
52
|
+
if (end === -1) return null
|
|
53
|
+
const value = xml.slice(index + 1, end)
|
|
54
|
+
if (!/^[\x20-\x7E]*$/u.test(value) || value.includes("<") || value.includes("&")) return null
|
|
55
|
+
attributes.set(attribute.name, value)
|
|
56
|
+
index = end + 1
|
|
57
|
+
}
|
|
58
|
+
return null
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function hasValidXmlCharacters(value) {
|
|
62
|
+
for (const character of value) {
|
|
63
|
+
const codePoint = character.codePointAt(0)
|
|
64
|
+
if (!(codePoint === 0x9 || codePoint === 0xA || codePoint === 0xD
|
|
65
|
+
|| (codePoint >= 0x20 && codePoint <= 0xD7FF)
|
|
66
|
+
|| (codePoint >= 0xE000 && codePoint <= 0xFFFD)
|
|
67
|
+
|| (codePoint >= 0x10000 && codePoint <= 0x10FFFF))) return false
|
|
68
|
+
}
|
|
69
|
+
return true
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Canonical DockerMan dialect: exact declaration and Container root, flat leaf children, double-quoted ASCII attributes, and literal text without entities or auxiliary XML constructs.
|
|
73
|
+
function parseDockerManTemplateXml(input) {
|
|
74
|
+
let xml
|
|
75
|
+
try { xml = decodeUtf8(input) } catch { return null }
|
|
76
|
+
if (!hasValidXmlCharacters(xml) || !xml.startsWith(DECLARATION)) return null
|
|
77
|
+
let index = skipWhitespace(xml, DECLARATION.length)
|
|
78
|
+
if (!xml.startsWith(ROOT_OPEN, index)) return null
|
|
79
|
+
index += ROOT_OPEN.length
|
|
80
|
+
const children = []
|
|
81
|
+
while (index < xml.length) {
|
|
82
|
+
index = skipWhitespace(xml, index)
|
|
83
|
+
if (xml.startsWith(ROOT_CLOSE, index)) {
|
|
84
|
+
index = skipWhitespace(xml, index + ROOT_CLOSE.length)
|
|
85
|
+
return index === xml.length ? { root: { name: "Container", attributes: { version: "2" } }, children } : null
|
|
86
|
+
}
|
|
87
|
+
const child = readOpenTag(xml, index)
|
|
88
|
+
if (!child) return null
|
|
89
|
+
index = child.index
|
|
90
|
+
if (child.form === "empty") {
|
|
91
|
+
children.push({ name: child.name, attributes: child.attributes, form: child.form, text: "" })
|
|
92
|
+
continue
|
|
93
|
+
}
|
|
94
|
+
const close = `</${child.name}>`
|
|
95
|
+
const end = xml.indexOf("<", index)
|
|
96
|
+
if (end === -1 || !xml.startsWith(close, end)) return null
|
|
97
|
+
const text = xml.slice(index, end)
|
|
98
|
+
if (text.includes("&") || text.includes("]]>")) return null
|
|
99
|
+
children.push({ name: child.name, attributes: child.attributes, form: child.form, text })
|
|
100
|
+
index = end + close.length
|
|
101
|
+
}
|
|
102
|
+
return null
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = { decodeUtf8, parseDockerManTemplateXml }
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Ouro Butler installer for Unraid 7.2 or newer.
|
|
3
|
+
#
|
|
4
|
+
# Run it as root in the Unraid web terminal. Download it and read it first if you like:
|
|
5
|
+
# curl -fsSLo /tmp/ouro-butler-install.sh https://github.com/ourostack/ouroboros/releases/latest/download/install.sh
|
|
6
|
+
# bash /tmp/ouro-butler-install.sh
|
|
7
|
+
#
|
|
8
|
+
# What it does, in order (each step says what it is doing as it goes):
|
|
9
|
+
# 1. checks this is Unraid 7.2+, as root, with Docker running and no Butler installed yet
|
|
10
|
+
# 2. asks for your name, the Butler's name, a vault email, your Anthropic API key and your Telegram bot token
|
|
11
|
+
# (secrets are read with the terminal's echo off and never appear in a command line)
|
|
12
|
+
# 3. pulls the Butler image and seeds the Butler's files under /mnt/user/appdata/ouro-butler
|
|
13
|
+
# 4. creates the Butler's vault (you choose its unlock phrase) and stores the Anthropic key in it
|
|
14
|
+
# 5. creates two Unraid API keys for the Butler (read-only, and read plus Docker update) and stores them in the vault
|
|
15
|
+
# 6. finds your Telegram user id when you message the bot, then installs the root authority that holds the bot
|
|
16
|
+
# token and starts the Butler
|
|
17
|
+
#
|
|
18
|
+
# Options:
|
|
19
|
+
# --version <0.1.0-alpha.N> install this release instead of the newest one
|
|
20
|
+
# --vault-server <url> use your own Vaultwarden-compatible server instead of https://vault.ouro.bot
|
|
21
|
+
# --help print this header
|
|
22
|
+
set -euo pipefail
|
|
23
|
+
umask 077
|
|
24
|
+
|
|
25
|
+
IMAGE_REPO=ghcr.io/ourostack/ouroboros-butler
|
|
26
|
+
APPDATA=/mnt/user/appdata/ouro-butler
|
|
27
|
+
RUNTIME=$APPDATA/runtime/.ouro-cli
|
|
28
|
+
BUNDLE=$APPDATA/agent/sanctuary.ouro
|
|
29
|
+
STAGE=$APPDATA/installer
|
|
30
|
+
AUTHORITY=/mnt/user/appdata/ouro-authority
|
|
31
|
+
EVENTS=/boot/config/custom/ouro-events
|
|
32
|
+
CONTAINER=ouro-butler
|
|
33
|
+
AGENT=sanctuary
|
|
34
|
+
TTY=/dev/tty
|
|
35
|
+
VERSION=""
|
|
36
|
+
VAULT_SERVER=""
|
|
37
|
+
|
|
38
|
+
say() { printf '\n== %s\n' "$*"; }
|
|
39
|
+
ok() { printf ' ok %s\n' "$*"; }
|
|
40
|
+
die() { printf '\nSTOPPED: %s\n' "$*" >&2; exit 1; }
|
|
41
|
+
|
|
42
|
+
ask() { # ask <variable> <prompt> [default]
|
|
43
|
+
local answer
|
|
44
|
+
printf '%s%s: ' "$2" "${3:+ [$3]}" > "$TTY"
|
|
45
|
+
IFS= read -r answer < "$TTY" || die "no answer read from the terminal"
|
|
46
|
+
printf -v "$1" '%s' "${answer:-${3:-}}"
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
ask_secret() { # ask_secret <variable> <prompt>
|
|
50
|
+
local answer saved
|
|
51
|
+
saved=$(stty -g < "$TTY")
|
|
52
|
+
printf '%s (input is hidden): ' "$2" > "$TTY"
|
|
53
|
+
stty -echo < "$TTY"
|
|
54
|
+
IFS= read -r answer < "$TTY" || { stty "$saved" < "$TTY"; die "no answer read from the terminal"; }
|
|
55
|
+
stty "$saved" < "$TTY"
|
|
56
|
+
printf '\n' > "$TTY"
|
|
57
|
+
printf -v "$1" '%s' "$answer"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
confirm() { local reply; ask reply "$1 (y/n)" n; case "$reply" in y|Y|yes|YES) return 0 ;; *) return 1 ;; esac; }
|
|
61
|
+
|
|
62
|
+
while (($# > 0)); do
|
|
63
|
+
case "$1" in
|
|
64
|
+
--version) VERSION="${2:?--version needs a value, for example 0.1.0-alpha.970}"; shift 2 ;;
|
|
65
|
+
--vault-server) VAULT_SERVER="${2:?--vault-server needs a URL}"; shift 2 ;;
|
|
66
|
+
--help|-h) sed -n '2,/^set -euo/p' "$0" | sed '$d; s/^# \{0,1\}//'; exit 0 ;;
|
|
67
|
+
*) die "unknown option $1 (see --help)" ;;
|
|
68
|
+
esac
|
|
69
|
+
done
|
|
70
|
+
|
|
71
|
+
# The ouro CLI from the Butler image, run against the Butler's own files as the Butler's user.
|
|
72
|
+
ouro() {
|
|
73
|
+
docker run --rm --pull=never --network host --user 10001:10001 \
|
|
74
|
+
--mount "type=bind,src=$RUNTIME,dst=/home/ouro/.ouro-cli" \
|
|
75
|
+
--mount "type=bind,src=$BUNDLE,dst=/home/ouro/AgentBundles/$AGENT.ouro" \
|
|
76
|
+
--entrypoint node "$IMAGE" /opt/ouro/dist/heart/daemon/ouro-entry.js "$@"
|
|
77
|
+
}
|
|
78
|
+
ouro_stdin() {
|
|
79
|
+
docker run --rm -i --pull=never --network host --user 10001:10001 \
|
|
80
|
+
--mount "type=bind,src=$RUNTIME,dst=/home/ouro/.ouro-cli" \
|
|
81
|
+
--mount "type=bind,src=$BUNDLE,dst=/home/ouro/AgentBundles/$AGENT.ouro" \
|
|
82
|
+
--entrypoint node "$IMAGE" /opt/ouro/dist/heart/daemon/ouro-entry.js "$@"
|
|
83
|
+
}
|
|
84
|
+
ouro_interactive() {
|
|
85
|
+
docker run --rm -it --pull=never --network host --user 10001:10001 \
|
|
86
|
+
--mount "type=bind,src=$RUNTIME,dst=/home/ouro/.ouro-cli" \
|
|
87
|
+
--mount "type=bind,src=$BUNDLE,dst=/home/ouro/AgentBundles/$AGENT.ouro" \
|
|
88
|
+
--entrypoint node "$IMAGE" /opt/ouro/dist/heart/daemon/ouro-entry.js "$@" < "$TTY"
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# Write a private file owned by the Butler's user from stdin.
|
|
92
|
+
write_butler_file() {
|
|
93
|
+
local path=$1
|
|
94
|
+
cat > "$path.tmp.$$"
|
|
95
|
+
chown 10001:10001 "$path.tmp.$$"
|
|
96
|
+
chmod 0600 "$path.tmp.$$"
|
|
97
|
+
mv -f "$path.tmp.$$" "$path"
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# ---------------------------------------------------------------------------------------------------------------
|
|
101
|
+
say "1. checking this host"
|
|
102
|
+
test "$(id -u)" = 0 || die "run this as root (the Unraid web terminal is root)"
|
|
103
|
+
test -r "$TTY" || die "this installer needs a terminal for its questions; run it in the Unraid web terminal"
|
|
104
|
+
test -r /etc/unraid-version || die "this is not Unraid (no /etc/unraid-version)"
|
|
105
|
+
UNRAID_VERSION=$(sed -n 's/^version="\([0-9.]*\).*/\1/p' /etc/unraid-version)
|
|
106
|
+
IFS=. read -r UNRAID_MAJOR UNRAID_MINOR _ <<< "$UNRAID_VERSION"
|
|
107
|
+
if ((UNRAID_MAJOR < 7 || (UNRAID_MAJOR == 7 && UNRAID_MINOR < 2))); then die "Unraid $UNRAID_VERSION is too old; the Butler needs Unraid 7.2 or newer"; fi
|
|
108
|
+
ok "Unraid $UNRAID_VERSION"
|
|
109
|
+
command -v node >/dev/null || die "node is missing (Unraid 7.2 ships it at /usr/local/bin/node)"
|
|
110
|
+
command -v unraid-api >/dev/null || die "unraid-api is missing (Unraid 7.2 ships it)"
|
|
111
|
+
docker info >/dev/null 2>&1 || die "Docker is not running; start it in Settings > Docker"
|
|
112
|
+
ok "node, unraid-api and Docker are available"
|
|
113
|
+
! docker container inspect "$CONTAINER" >/dev/null 2>&1 || die "an $CONTAINER container already exists; this installer is for a first install (upgrades use the Butler's own upgrade path)"
|
|
114
|
+
test ! -e "$AUTHORITY/active.json" || die "a Butler authority is already installed on this host"
|
|
115
|
+
ok "no Butler installed yet"
|
|
116
|
+
|
|
117
|
+
if test -z "$VERSION"; then
|
|
118
|
+
VERSION=$(node -e 'fetch("https://registry.npmjs.org/-/package/@ouro.bot/cli/dist-tags").then(r => r.json()).then(t => process.stdout.write(t.latest)).catch(() => process.exit(1))') \
|
|
119
|
+
|| die "could not look up the newest Butler release; pass --version"
|
|
120
|
+
fi
|
|
121
|
+
[[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9.]+)?$ ]] || die "version $VERSION does not look like a release version"
|
|
122
|
+
IMAGE=$IMAGE_REPO:$VERSION
|
|
123
|
+
ok "installing Ouro Butler $VERSION"
|
|
124
|
+
|
|
125
|
+
# ---------------------------------------------------------------------------------------------------------------
|
|
126
|
+
say "2. a few questions"
|
|
127
|
+
printf 'The Butler lives on this server and talks to you on Telegram. You can change any name later in\n%s/house/house.json.\n\n' "$BUNDLE" > "$TTY"
|
|
128
|
+
ask OWNER_NAME "Your first name" ""
|
|
129
|
+
test -n "$OWNER_NAME" || die "a name is needed so the Butler knows who it works for"
|
|
130
|
+
ask BUTLER_NAME "What should the Butler call itself" "Butler"
|
|
131
|
+
ask HOUSEHOLD_NAME "A name for this household or server" "$(hostname)"
|
|
132
|
+
printf '\nThe Butler keeps its secrets in a Bitwarden-compatible vault. It gets its own vault account, so use an\nemail address no other Butler uses (for example you+butler@example.com). No mail is sent to it.\n' > "$TTY"
|
|
133
|
+
ask VAULT_EMAIL "Vault account email" ""
|
|
134
|
+
[[ "$VAULT_EMAIL" == *@*.* ]] || die "that does not look like an email address"
|
|
135
|
+
printf '\nThe Butler thinks with Anthropic models. Create an API key at https://console.anthropic.com/settings/keys\n' > "$TTY"
|
|
136
|
+
ask_secret ANTHROPIC_KEY "Anthropic API key"
|
|
137
|
+
[[ "$ANTHROPIC_KEY" == sk-ant-* ]] || die "Anthropic API keys start with sk-ant-"
|
|
138
|
+
printf '\nCreate a Telegram bot for the Butler: message @BotFather, send /newbot, and copy the token it gives you.\n' > "$TTY"
|
|
139
|
+
ask_secret BOT_TOKEN "Telegram bot token"
|
|
140
|
+
[[ "$BOT_TOKEN" =~ ^[0-9]+:[A-Za-z0-9_-]+$ ]] || die "that does not look like a Telegram bot token (digits, a colon, then letters)"
|
|
141
|
+
BOT_INFO=$(TOKEN="$BOT_TOKEN" node -e '
|
|
142
|
+
fetch(`https://api.telegram.org/bot${process.env.TOKEN}/getMe`).then(r => r.json()).then(b => {
|
|
143
|
+
if (!b.ok) process.exit(2)
|
|
144
|
+
process.stdout.write(`${b.result.id}\t${b.result.username}`)
|
|
145
|
+
}).catch(() => process.exit(1))') || die "Telegram did not accept that bot token"
|
|
146
|
+
BOT_USERNAME=${BOT_INFO#*$'\t'}
|
|
147
|
+
ok "Telegram knows the bot @$BOT_USERNAME"
|
|
148
|
+
|
|
149
|
+
# ---------------------------------------------------------------------------------------------------------------
|
|
150
|
+
say "3. Butler image and files"
|
|
151
|
+
docker pull "$IMAGE" >/dev/null || die "could not pull $IMAGE"
|
|
152
|
+
ok "pulled $IMAGE"
|
|
153
|
+
install -d -m 0700 -o 10001 -g 10001 "$APPDATA" "$APPDATA/runtime" "$APPDATA/agent" "$RUNTIME" "$BUNDLE"
|
|
154
|
+
install -d -m 0700 -o 0 -g 0 "$AUTHORITY" "$STAGE"
|
|
155
|
+
if test ! -f "$RUNTIME/machine.json"; then
|
|
156
|
+
NOW=$(date -u +%Y-%m-%dT%H:%M:%S.000Z)
|
|
157
|
+
printf '{\n "schemaVersion": 1,\n "machineId": "%s",\n "createdAt": "%s",\n "updatedAt": "%s",\n "hostnameAliases": []\n}\n' "$AGENT" "$NOW" "$NOW" | write_butler_file "$RUNTIME/machine.json"
|
|
158
|
+
fi
|
|
159
|
+
if test ! -f "$BUNDLE/agent.json"; then
|
|
160
|
+
test -z "$(find "$BUNDLE" -mindepth 1 -print -quit)" || die "$BUNDLE has files but no agent.json; move it aside and run the installer again"
|
|
161
|
+
docker run --rm --pull=never --network=none --user 10001:10001 \
|
|
162
|
+
--mount "type=bind,src=$BUNDLE,dst=/home/ouro/AgentBundles/$AGENT.ouro" \
|
|
163
|
+
--entrypoint /bin/sh "$IMAGE" -ceu '
|
|
164
|
+
cp -R /opt/ouro/deploy/unraid/sanctuary.ouro/. /home/ouro/AgentBundles/sanctuary.ouro/
|
|
165
|
+
find /home/ouro/AgentBundles/sanctuary.ouro -type d -exec chmod 0700 {} +
|
|
166
|
+
find /home/ouro/AgentBundles/sanctuary.ouro -type f -exec chmod 0600 {} +'
|
|
167
|
+
fi
|
|
168
|
+
ok "Butler files seeded in $BUNDLE"
|
|
169
|
+
install -d -m 0700 -o 10001 -g 10001 "$BUNDLE/house"
|
|
170
|
+
OWNER_NAME=$OWNER_NAME BUTLER_NAME=$BUTLER_NAME HOUSEHOLD_NAME=$HOUSEHOLD_NAME node -e '
|
|
171
|
+
const house = { ownerName: process.env.OWNER_NAME, butlerName: process.env.BUTLER_NAME, householdName: process.env.HOUSEHOLD_NAME, publicEndpoints: [], requiredContainers: [] }
|
|
172
|
+
process.stdout.write(`${JSON.stringify(house, null, 2)}\n`)' | write_butler_file "$BUNDLE/house/house.json"
|
|
173
|
+
if test ! -f "$BUNDLE/house/HOUSE.md"; then
|
|
174
|
+
printf '# %s\n\n%s owns this Unraid server and is the person %s works for.\n\nAdd anything the Butler should know about this household here: who lives here, what each container is for, what matters most. The Butler reads this file at the start of every conversation.\n' \
|
|
175
|
+
"$HOUSEHOLD_NAME" "$OWNER_NAME" "$BUTLER_NAME" | write_butler_file "$BUNDLE/house/HOUSE.md"
|
|
176
|
+
fi
|
|
177
|
+
ok "house description written to $BUNDLE/house"
|
|
178
|
+
|
|
179
|
+
ASSETS=ouro-butler-installer-assets
|
|
180
|
+
docker rm -f "$ASSETS" >/dev/null 2>&1 || true
|
|
181
|
+
docker create --name "$ASSETS" "$IMAGE" >/dev/null
|
|
182
|
+
docker cp "$ASSETS:/opt/ouro/deploy/unraid/sanctuary-butler-upgrade.mjs" "$STAGE/sanctuary-butler-upgrade.mjs" >/dev/null
|
|
183
|
+
docker cp "$ASSETS:/opt/ouro/deploy/unraid/ouro-events/bootstrap-spool.sh" "$STAGE/bootstrap-spool.sh" >/dev/null
|
|
184
|
+
docker rm -f "$ASSETS" >/dev/null
|
|
185
|
+
chown 0:0 "$STAGE"/*; chmod 0700 "$STAGE"/*
|
|
186
|
+
bash "$STAGE/bootstrap-spool.sh" --install-only
|
|
187
|
+
bash "$EVENTS/bootstrap-spool.sh" --mount
|
|
188
|
+
ok "event spool mounted and registered to mount at boot"
|
|
189
|
+
|
|
190
|
+
# ---------------------------------------------------------------------------------------------------------------
|
|
191
|
+
say "4. vault and model provider"
|
|
192
|
+
VAULT_STATUS=$(ouro vault status --agent "$AGENT" --store plaintext-file 2>&1 || true)
|
|
193
|
+
if [[ "$VAULT_STATUS" != *"local unlock: available"* ]]; then
|
|
194
|
+
printf 'Creating the vault. Choose an unlock phrase and keep it somewhere safe: it is the only way to recover\nthe Butler'"'"'s secrets if this server is lost.\n' > "$TTY"
|
|
195
|
+
ouro_interactive vault create --agent "$AGENT" --email "$VAULT_EMAIL" ${VAULT_SERVER:+--server "$VAULT_SERVER"} --store plaintext-file \
|
|
196
|
+
|| die "vault creation did not finish; run the installer again to retry"
|
|
197
|
+
fi
|
|
198
|
+
ok "vault ready"
|
|
199
|
+
printf '%s' "$ANTHROPIC_KEY" | ouro_stdin auth --agent "$AGENT" --provider anthropic --api-key-file /dev/stdin >/dev/null \
|
|
200
|
+
|| die "storing the Anthropic key failed"
|
|
201
|
+
unset ANTHROPIC_KEY
|
|
202
|
+
for LANE in outward inner; do
|
|
203
|
+
ouro check --agent "$AGENT" --lane "$LANE" >/dev/null 2>&1 || die "the $LANE model lane did not answer; check the Anthropic key and your account's credit"
|
|
204
|
+
done
|
|
205
|
+
ok "Anthropic key stored in the vault; both model lanes answer"
|
|
206
|
+
|
|
207
|
+
# ---------------------------------------------------------------------------------------------------------------
|
|
208
|
+
say "5. Unraid API access"
|
|
209
|
+
PORT=$(sed -n 's/^PORT="\{0,1\}\([0-9]*\)"\{0,1\}$/\1/p' /boot/config/ident.cfg 2>/dev/null | head -1)
|
|
210
|
+
GRAPHQL_URL="http://127.0.0.1${PORT:+$( [ "$PORT" = 80 ] || printf ':%s' "$PORT")}/graphql"
|
|
211
|
+
READ_PERMISSIONS="ARRAY:READ_ANY,DASHBOARD:READ_ANY,DISK:READ_ANY,DOCKER:READ_ANY,INFO:READ_ANY,LOGS:READ_ANY,NOTIFICATIONS:READ_ANY,SHARE:READ_ANY,VARS:READ_ANY"
|
|
212
|
+
STAMP=$(date +%Y%m%d%H%M%S)
|
|
213
|
+
create_unraid_key() { # create_unraid_key <name> <permissions> <vault field>
|
|
214
|
+
# Unraid 7.2's CLI refuses --permissions without a role ("Invalid data structure"); GUEST adds only own-profile access.
|
|
215
|
+
unraid-api apikey --create --name "$1" --roles GUEST --permissions "$2" --description "Ouro Butler $3" --json 2>/dev/null \
|
|
216
|
+
| node -e '
|
|
217
|
+
let text = ""; process.stdin.on("data", (c) => text += c).on("end", () => {
|
|
218
|
+
const start = text.indexOf("{"); if (start < 0) process.exit(1)
|
|
219
|
+
const key = JSON.parse(text.slice(start)).key; if (typeof key !== "string" || !key) process.exit(1)
|
|
220
|
+
process.stdout.write(key) })' \
|
|
221
|
+
| ouro_stdin vault config set --agent "$AGENT" --key "$3" --scope machine --value-file /dev/stdin >/dev/null \
|
|
222
|
+
|| die "creating the Unraid API key $1 failed"
|
|
223
|
+
}
|
|
224
|
+
create_unraid_key "Butler RO $STAMP" "$READ_PERMISSIONS" unraidReadApiKey
|
|
225
|
+
create_unraid_key "Butler RW $STAMP" "$READ_PERMISSIONS,DOCKER:UPDATE_ANY" unraidWriteApiKey
|
|
226
|
+
ouro vault config set --agent "$AGENT" --key unraidGraphqlUrl --scope machine --value "$GRAPHQL_URL" >/dev/null
|
|
227
|
+
ok "API keys \"Butler RO $STAMP\" and \"Butler RW $STAMP\" created (see Settings > Management Access > API Keys)"
|
|
228
|
+
|
|
229
|
+
# ---------------------------------------------------------------------------------------------------------------
|
|
230
|
+
say "6. Telegram and the root authority"
|
|
231
|
+
test ! -L "$AUTHORITY/incoming-token" || die "$AUTHORITY/incoming-token is a link; remove it and run again"
|
|
232
|
+
printf '%s' "$BOT_TOKEN" > "$AUTHORITY/incoming-token.tmp.$$"
|
|
233
|
+
chmod 0600 "$AUTHORITY/incoming-token.tmp.$$"
|
|
234
|
+
mv -f "$AUTHORITY/incoming-token.tmp.$$" "$AUTHORITY/incoming-token"
|
|
235
|
+
unset BOT_TOKEN
|
|
236
|
+
printf '\nOpen Telegram, find @%s and send it any message (for example "hello"). Waiting up to 3 minutes...\n' "$BOT_USERNAME" > "$TTY"
|
|
237
|
+
OWNER_INFO=$(node -e '
|
|
238
|
+
const token = require("node:fs").readFileSync(process.argv[1], "utf8").trim()
|
|
239
|
+
const api = (method, query) => fetch(`https://api.telegram.org/bot${token}/${method}?${query}`).then((r) => r.json())
|
|
240
|
+
const deadline = Date.now() + 180000
|
|
241
|
+
;(async () => {
|
|
242
|
+
while (Date.now() < deadline) {
|
|
243
|
+
const body = await api("getUpdates", "timeout=20&allowed_updates=%5B%22message%22%5D").catch(() => null)
|
|
244
|
+
const updates = body && body.ok ? body.result : []
|
|
245
|
+
const latest = updates.filter((u) => u.message && u.message.chat && u.message.chat.type === "private" && u.message.from).pop()
|
|
246
|
+
if (latest) {
|
|
247
|
+
await api("getUpdates", `offset=${latest.update_id + 1}&timeout=0`).catch(() => null)
|
|
248
|
+
const from = latest.message.from
|
|
249
|
+
process.stdout.write(`${from.id}\t${from.first_name || ""}${from.username ? ` (@${from.username})` : ""}`)
|
|
250
|
+
return
|
|
251
|
+
}
|
|
252
|
+
if (body && body.ok === false) { process.stderr.write(`Telegram: ${body.description}\n`); process.exit(2) }
|
|
253
|
+
}
|
|
254
|
+
process.exit(1)
|
|
255
|
+
})()' "$AUTHORITY/incoming-token") || die "no message reached the bot; run the installer again and message the bot when asked"
|
|
256
|
+
OWNER_ID=${OWNER_INFO%%$'\t'*}
|
|
257
|
+
confirm "The message came from ${OWNER_INFO#*$'\t'}. Is that you" || die "only the owner should message the bot during install; run the installer again"
|
|
258
|
+
ok "owner Telegram id found"
|
|
259
|
+
|
|
260
|
+
UPGRADE=(node "$STAGE/sanctuary-butler-upgrade.mjs")
|
|
261
|
+
"${UPGRADE[@]}" preflight "$VERSION" --fresh || die "preflight found a problem (above); nothing has been installed yet"
|
|
262
|
+
"${UPGRADE[@]}" prepare "$VERSION" --fresh --owner-id "$OWNER_ID" || die "prepare found a problem (above)"
|
|
263
|
+
LOG=/var/log/ouro-butler-install.log
|
|
264
|
+
printf 'Installing the authority and starting the Butler. This runs on even if this terminal closes; its log is %s.\n' "$LOG" > "$TTY"
|
|
265
|
+
setsid nohup "${UPGRADE[@]}" install "$VERSION" > "$LOG" 2>&1 < /dev/null &
|
|
266
|
+
INSTALL_PID=$!
|
|
267
|
+
tail -n +1 --pid="$INSTALL_PID" -f "$LOG"
|
|
268
|
+
wait "$INSTALL_PID" || die "install did not complete and was rolled back; the log is $LOG"
|
|
269
|
+
"${UPGRADE[@]}" verify || die "the Butler is installed but verify found a problem (above)"
|
|
270
|
+
|
|
271
|
+
say "done"
|
|
272
|
+
printf 'Ouro Butler %s is running. Say hello to @%s on Telegram.\n' "$VERSION" "$BOT_USERNAME"
|
|
273
|
+
printf 'Tell it about your household in %s/house/HOUSE.md.\n' "$BUNDLE"
|
|
274
|
+
printf 'Keep the vault unlock phrase you chose somewhere safe.\n'
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as path from "node:path"
|
|
3
|
+
import { pathToFileURL } from "node:url"
|
|
4
|
+
|
|
5
|
+
const USAGE = "Usage: migrate-sanctuary-bundle.mjs --package-root <path> --agent-root <path> --operation <migrate|seed|rollback|finalize-rollback|commit|status|inspect> [--rollback-image-id <sha256:id> --target-image-id <sha256:id>]"
|
|
6
|
+
const BASE_KEYS = ["--package-root", "--agent-root", "--operation"]
|
|
7
|
+
const MIGRATE_KEYS = [...BASE_KEYS, "--rollback-image-id", "--target-image-id"]
|
|
8
|
+
|
|
9
|
+
function parseArguments(args) {
|
|
10
|
+
if (args.length % 2 !== 0) throw new Error(USAGE)
|
|
11
|
+
const values = new Map()
|
|
12
|
+
for (let index = 0; index < args.length; index += 2) {
|
|
13
|
+
const key = args[index]
|
|
14
|
+
const value = args[index + 1]
|
|
15
|
+
if (values.has(key) || typeof value !== "string" || value.length === 0) throw new Error(USAGE)
|
|
16
|
+
values.set(key, value)
|
|
17
|
+
}
|
|
18
|
+
const operation = values.get("--operation")
|
|
19
|
+
if (!["migrate", "seed", "rollback", "finalize-rollback", "commit", "status", "inspect"].includes(operation)) throw new Error(USAGE)
|
|
20
|
+
const expectedKeys = operation === "migrate" ? MIGRATE_KEYS : BASE_KEYS
|
|
21
|
+
if (values.size !== expectedKeys.length || expectedKeys.some((key) => !values.has(key)) || [...values.keys()].some((key) => !expectedKeys.includes(key))) throw new Error(USAGE)
|
|
22
|
+
return values
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function runSanctuaryBundleOperation(args, dependencies) {
|
|
26
|
+
const values = parseArguments(args)
|
|
27
|
+
const packageRoot = values.get("--package-root")
|
|
28
|
+
const agentRoot = values.get("--agent-root")
|
|
29
|
+
const operation = values.get("--operation")
|
|
30
|
+
const result = operation === "migrate"
|
|
31
|
+
? dependencies.migrate({ packageRoot, agentRoot, retainRollback: true, rollbackImageId: values.get("--rollback-image-id"), targetImageId: values.get("--target-image-id") })
|
|
32
|
+
// A fresh install has no earlier image to roll back to, so it writes the packaged files without a rollback record.
|
|
33
|
+
: operation === "seed"
|
|
34
|
+
? dependencies.migrate({ packageRoot, agentRoot, retainRollback: false })
|
|
35
|
+
: operation === "rollback"
|
|
36
|
+
? { rolledBack: dependencies.rollback(agentRoot, { retainRecord: true }) }
|
|
37
|
+
// `rollback` keeps crash-retry evidence; the host uses `finalize-rollback` only after old production is audited, ready, and restored to autostart.
|
|
38
|
+
: operation === "finalize-rollback"
|
|
39
|
+
? { rolledBack: dependencies.rollback(agentRoot, { retainRecord: false }) }
|
|
40
|
+
: operation === "commit"
|
|
41
|
+
? { committed: dependencies.commit(agentRoot) }
|
|
42
|
+
: operation === "status"
|
|
43
|
+
? dependencies.status(agentRoot)
|
|
44
|
+
: dependencies.inspect({ packageRoot, agentRoot, runtimePackageVersion: dependencies.getPackageVersion() })
|
|
45
|
+
if (result === null || ("rolledBack" in result && !result.rolledBack) || ("committed" in result && !result.committed)) throw new Error(`${operation} found no pending Sanctuary bundle transaction`)
|
|
46
|
+
return result
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function runSanctuaryBundleCli(args = process.argv.slice(2), output = process.stdout) {
|
|
50
|
+
const migration = await import("../../dist/heart/daemon/sanctuary-bundle-migration.js")
|
|
51
|
+
const manifest = await import("../../dist/mind/bundle-manifest.js")
|
|
52
|
+
const result = runSanctuaryBundleOperation(args, {
|
|
53
|
+
commit: migration.commitSanctuaryPackageManagedBundle,
|
|
54
|
+
getPackageVersion: manifest.getPackageVersion,
|
|
55
|
+
inspect: migration.inspectSanctuaryPackageManagedBundle,
|
|
56
|
+
migrate: migration.migrateSanctuaryPackageManagedBundle,
|
|
57
|
+
rollback: migration.rollbackSanctuaryPackageManagedBundle,
|
|
58
|
+
status: migration.inspectSanctuaryPackageManagedBundleRollback,
|
|
59
|
+
})
|
|
60
|
+
output.write(`${JSON.stringify(result)}\n`)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) await runSanctuaryBundleCli()
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SPOOL_ROOT="/boot/config/custom/ouro-events/spool"
|
|
5
|
+
INSTALL_PATH="/boot/config/custom/ouro-events/bootstrap-spool.sh"
|
|
6
|
+
GO_FILE="/boot/config/go"
|
|
7
|
+
TMPFS_OPTIONS="size=4m,mode=0755,uid=0,gid=0,nodev,nosuid,noexec"
|
|
8
|
+
BOOT_HOOK="/bin/bash /boot/config/custom/ouro-events/bootstrap-spool.sh --mount"
|
|
9
|
+
ACTION="mount"
|
|
10
|
+
|
|
11
|
+
while (($# > 0)); do
|
|
12
|
+
case "$1" in
|
|
13
|
+
--mount|--install-only|--self-test) ACTION="${1#--}"; shift ;;
|
|
14
|
+
--go-file) GO_FILE="${2:?missing --go-file value}"; shift 2 ;;
|
|
15
|
+
--install-path) INSTALL_PATH="${2:?missing --install-path value}"; shift 2 ;;
|
|
16
|
+
*) echo "ouro event spool bootstrap: invalid argument: $1" >&2; exit 2 ;;
|
|
17
|
+
esac
|
|
18
|
+
done
|
|
19
|
+
|
|
20
|
+
mount_spool() {
|
|
21
|
+
local target="$1"
|
|
22
|
+
/bin/mkdir -p "$target"
|
|
23
|
+
/bin/chown 0:0 "$target"
|
|
24
|
+
/bin/chmod 0755 "$target"
|
|
25
|
+
if /bin/mountpoint -q "$target"; then
|
|
26
|
+
[[ "$(/bin/findmnt -n -o FSTYPE --target "$target")" == "tmpfs" ]] || { echo "ouro event spool bootstrap: canonical path is already a non-tmpfs mount" >&2; return 1; }
|
|
27
|
+
else
|
|
28
|
+
/bin/mount -t tmpfs -o "$TMPFS_OPTIONS" ouro-events-spool "$target"
|
|
29
|
+
fi
|
|
30
|
+
[[ "$(/bin/stat -c '%u:%g:%a' "$target")" == "0:0:755" ]] || { echo "ouro event spool bootstrap: tmpfs identity or mode is unsafe" >&2; return 1; }
|
|
31
|
+
local options
|
|
32
|
+
options="$(/bin/findmnt -n -o OPTIONS --target "$target")"
|
|
33
|
+
for required in nodev nosuid noexec; do
|
|
34
|
+
[[ ",$options," == *",$required,"* ]] || { echo "ouro event spool bootstrap: tmpfs is missing $required" >&2; return 1; }
|
|
35
|
+
done
|
|
36
|
+
local size_bytes
|
|
37
|
+
size_bytes="$(/bin/findmnt -bn -o SIZE --target "$target")"
|
|
38
|
+
[[ "$size_bytes" =~ ^[0-9]+$ && "$size_bytes" -le 4194304 ]] || { echo "ouro event spool bootstrap: tmpfs exceeds its 4 MiB bound" >&2; return 1; }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
install_boot_hook() {
|
|
42
|
+
local install_dir resolved_source resolved_install
|
|
43
|
+
install_dir="$(dirname "$INSTALL_PATH")"
|
|
44
|
+
/bin/mkdir -p "$install_dir"
|
|
45
|
+
resolved_source="$(cd "$(dirname "$0")" && pwd -P)/$(basename "$0")"
|
|
46
|
+
resolved_install="$(cd "$install_dir" && pwd -P)/$(basename "$INSTALL_PATH")"
|
|
47
|
+
if [[ "$resolved_source" != "$resolved_install" ]]; then
|
|
48
|
+
install -m 0700 "$0" "$INSTALL_PATH"
|
|
49
|
+
else
|
|
50
|
+
/bin/chmod 0700 "$INSTALL_PATH"
|
|
51
|
+
fi
|
|
52
|
+
[[ -f "$GO_FILE" ]] || printf '#!/bin/bash\n' > "$GO_FILE"
|
|
53
|
+
if ! grep -Fqx "$BOOT_HOOK" "$GO_FILE"; then
|
|
54
|
+
local temporary="${GO_FILE}.ouro-events.$$"
|
|
55
|
+
awk -v hook="$BOOT_HOOK" 'NR == 1 && /^#!/ { print; print hook; next } NR == 1 { print hook } { print }' "$GO_FILE" > "$temporary"
|
|
56
|
+
/bin/chmod 0700 "$temporary"
|
|
57
|
+
/bin/mv "$temporary" "$GO_FILE"
|
|
58
|
+
fi
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
self_test() {
|
|
62
|
+
[[ "$(/usr/bin/id -u)" == "0" ]] || { echo "ouro event spool bootstrap self-test requires root" >&2; return 1; }
|
|
63
|
+
local test_root target readonly_view
|
|
64
|
+
test_root="$(/usr/bin/mktemp -d /tmp/ouro-event-spool.XXXXXX)"
|
|
65
|
+
target="$test_root/spool"
|
|
66
|
+
readonly_view="$test_root/readonly"
|
|
67
|
+
/bin/chmod 0755 "$test_root"
|
|
68
|
+
/bin/mkdir "$target" "$readonly_view"
|
|
69
|
+
cleanup() {
|
|
70
|
+
/bin/umount "$readonly_view" 2>/dev/null || true
|
|
71
|
+
/bin/umount "$target" 2>/dev/null || true
|
|
72
|
+
/bin/rmdir "$readonly_view" "$target" "$test_root" 2>/dev/null || true
|
|
73
|
+
}
|
|
74
|
+
trap cleanup EXIT
|
|
75
|
+
mount_spool "$target"
|
|
76
|
+
/usr/bin/printf 'probe\n' > "$target/probe"
|
|
77
|
+
/bin/chown 0:0 "$target/probe"
|
|
78
|
+
/bin/chmod 0444 "$target/probe"
|
|
79
|
+
/bin/mount --bind "$target" "$readonly_view"
|
|
80
|
+
/bin/mount -o remount,bind,ro,nodev,nosuid,noexec "$readonly_view"
|
|
81
|
+
/usr/bin/setpriv --reuid=10001 --regid=10001 --clear-groups /usr/bin/test -r "$readonly_view/probe"
|
|
82
|
+
[[ ",$(/bin/findmnt -n -o OPTIONS --target "$readonly_view")," == *",ro,"* ]] || { echo "ouro event spool bootstrap: test bind is not read-only" >&2; return 1; }
|
|
83
|
+
echo "uid10001-ro-bind: pass"
|
|
84
|
+
cleanup
|
|
85
|
+
trap - EXIT
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
case "$ACTION" in
|
|
89
|
+
mount) mount_spool "$SPOOL_ROOT" ;;
|
|
90
|
+
install-only) install_boot_hook ;;
|
|
91
|
+
self-test) self_test ;;
|
|
92
|
+
esac
|