@pasko70/pibo 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -254
- package/context/codex-base-prompt.md +4 -0
- package/context/compute-worker.md +23 -0
- package/context/pibo-native-tooling.md +18 -0
- package/context/pibo-system-prompt.md +69 -8
- package/dist/api/simple-agent-api.js +136 -0
- package/dist/app-context.js +4 -0
- package/dist/apps/chat/agent-profiles.js +18 -3
- package/dist/apps/chat/agent-store.js +113 -16
- package/dist/apps/chat/chat-api-routes.js +311 -0
- package/dist/apps/chat/chat-capability-routes.js +90 -0
- package/dist/apps/chat/chat-files.js +178 -0
- package/dist/apps/chat/chat-request-normalizers.js +681 -0
- package/dist/apps/chat/chat-settings-routes.js +75 -0
- package/dist/apps/chat/chat-trace-helpers.js +94 -0
- package/dist/apps/chat/chat-user-skill-routes.js +149 -0
- package/dist/apps/chat/cron-api.js +213 -0
- package/dist/apps/chat/data/chat-data-mappers.js +74 -0
- package/dist/apps/chat/data/event-command-service.js +75 -0
- package/dist/apps/chat/data/navigation-query-service.js +11 -0
- package/dist/apps/chat/data/project-service.js +844 -0
- package/dist/apps/chat/data/read-state-service.js +42 -0
- package/dist/apps/chat/data/room-service.js +52 -0
- package/dist/apps/chat/data/session-query-service.js +63 -0
- package/dist/apps/chat/data/timeline-query-service.js +96 -0
- package/dist/apps/chat/event-log.js +1 -307
- package/dist/apps/chat/model-catalog.js +7 -2
- package/dist/apps/chat/output-compactor.js +126 -0
- package/dist/apps/chat/output-event-policy.js +17 -0
- package/dist/apps/chat/project-workflow-human-actions.js +347 -0
- package/dist/apps/chat/project-workflow-sessions.js +260 -0
- package/dist/apps/chat/provider-auth-actions.js +43 -0
- package/dist/apps/chat/ralph-api.js +156 -0
- package/dist/apps/chat/read-model.js +1 -218
- package/dist/apps/chat/rooms.js +1 -321
- package/dist/apps/chat/static-assets.js +996 -0
- package/dist/apps/chat/stream.js +29 -6
- package/dist/apps/chat/trace.js +179 -1003
- package/dist/apps/chat/types/event-store.js +1 -0
- package/dist/apps/chat/types/read-model.js +1 -0
- package/dist/apps/chat/types/rooms.js +36 -0
- package/dist/apps/chat/web-app.js +3131 -1959
- package/dist/apps/chat/workflow-catalog.js +572 -0
- package/dist/apps/chat/workflow-edge-compatibility.js +51 -0
- package/dist/apps/chat/workflow-json-schema-validation.js +335 -0
- package/dist/apps/chat/workflow-persistence-model.js +140 -0
- package/dist/apps/chat/workflow-persistence.js +633 -0
- package/dist/apps/chat/workflow-registered-ref-params.js +130 -0
- package/dist/apps/chat/workflow-registered-ref-pickers.js +179 -0
- package/dist/apps/chat/workflow-registered-ref-validation.js +210 -0
- package/dist/apps/chat/workflow-v2-security-validation.js +93 -0
- package/dist/apps/chat/workflow-validation-helpers.js +114 -0
- package/dist/apps/chat-ui/assets/{dist-CNLWH2qh.js → dist-B4lw9z4F.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-8e4L8ciw.js → dist-BbTaHWON.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CMZOa5ik.js → dist-BcT_c1EJ.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DNcnQRPF.js → dist-CGINd7XU.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CqqUC8Ce.js → dist-CrBzZkUp.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-D2N4-LIc.js → dist-CyyISotB.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CUqpST5w.js → dist-DFbnFNpX.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CspjOeBj.js → dist-DGLWQLX8.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-B7bbI3Qz.js → dist-DfcIkFSN.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-v4pjHlB7.js → dist-sKDHTwaT.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-D9L4MSRF.js → dist-y9D6la48.js} +1 -1
- package/dist/apps/chat-ui/assets/index-C25VYnyb.css +1 -0
- package/dist/apps/chat-ui/assets/index-CUkuvI3v.js +165 -0
- package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-144x144.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-192x192.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-48x48.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-512x512.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-72x72.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-96x96.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/100.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/1024.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/114.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/120.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/128.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/144.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/152.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/16.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/167.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/180.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/192.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/20.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/256.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/29.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/32.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/40.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/50.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/512.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/57.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/58.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/60.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/64.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/72.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/76.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/80.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/ios/87.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-100.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-125.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-150.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-200.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-400.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-100.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-125.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-150.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-200.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-400.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-100.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-125.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-150.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-200.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-400.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-100.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-125.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-150.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-200.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-400.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-16.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-20.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-24.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-256.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-30.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-32.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-36.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-40.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-44.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-48.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-60.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-64.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-72.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-80.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-96.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-16.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-20.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-24.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-256.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-30.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-32.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-36.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-40.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-44.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-48.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-60.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-64.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-72.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-80.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-96.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-100.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-125.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-150.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-200.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-400.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-16.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-20.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-24.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-256.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-30.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-32.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-36.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-40.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-44.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-48.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-60.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-64.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-72.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-80.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-96.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-100.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-125.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-150.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-200.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-400.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-100.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-125.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-150.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-200.png +0 -0
- package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-400.png +0 -0
- package/dist/apps/chat-ui/index.html +8 -3
- package/dist/apps/chat-ui/manifest.webmanifest +25 -0
- package/dist/apps/chat-ui/sw.js +41 -0
- package/dist/apps/cli-ui/InkSessionApp.js +1218 -0
- package/dist/apps/cli-ui/InkTerminalLine.js +53 -0
- package/dist/apps/cli-ui/InkTerminalRow.js +304 -0
- package/dist/apps/cli-ui/InkTerminalView.js +25 -0
- package/dist/apps/cli-ui/cliSessionsCommand.js +232 -0
- package/dist/apps/cli-ui/index.js +8 -0
- package/dist/apps/cli-ui/inkColors.js +67 -0
- package/dist/apps/cli-ui/inkJson.js +244 -0
- package/dist/apps/cli-ui/inkMarkdown.js +122 -0
- package/dist/apps/context-files-ui/assets/{dist-DFi2YGux.js → dist-BOiGdrG-.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-DyfSeBMu.js → dist-DK01b7x4.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-CwbH_3RN.js → dist-DPG9jOQ-.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-dTBsFYAl.js → dist-Dp5AH00p.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-CxRLRmMx.js → dist-DqYw0LH7.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-MyZgX9K2.js → dist-TF5iO5ML.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-DQXzt2Ng.js → dist-TbjAhles.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-YwR9dpb-.js → dist-ZsBbt0uY.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-CKQF1zEu.js → dist-kmsvtHkH.js} +1 -1
- package/dist/apps/context-files-ui/assets/{dist-BJW3917N.js → dist-vnd7PMu3.js} +1 -1
- package/dist/apps/context-files-ui/assets/{index-BwRDoHMC.css → index-B92tL3Pp.css} +1 -1
- package/dist/apps/context-files-ui/assets/{index-GwvjXytt.js → index-BhAWD3dv.js} +2 -2
- package/dist/apps/context-files-ui/index.html +2 -2
- package/dist/auth/better-auth.js +2 -1
- package/dist/auth/login-actions.js +251 -0
- package/dist/auth/openai-codex-usage.js +147 -0
- package/dist/bin/pibo.js +0 -0
- package/dist/bin/rg.js +15 -0
- package/dist/cli-session/fakeSessionSource.js +804 -0
- package/dist/cli-session/index.js +3 -0
- package/dist/cli-session/localSessionSource.js +1144 -0
- package/dist/cli-session/sessionSource.js +13 -0
- package/dist/cli.js +142 -14
- package/dist/compute/cli.js +415 -0
- package/dist/compute/docker.js +827 -0
- package/dist/compute/resource-health.js +333 -0
- package/dist/compute/resource-policy.js +98 -0
- package/dist/config/config.js +9 -5
- package/dist/core/context-build.js +677 -0
- package/dist/core/model-defaults.js +51 -9
- package/dist/core/pibo-home.js +8 -0
- package/dist/core/profiles.js +48 -0
- package/dist/core/provider-telemetry.js +222 -0
- package/dist/core/routed-session.js +441 -47
- package/dist/core/runtime-telemetry.js +853 -0
- package/dist/core/runtime.js +103 -15
- package/dist/core/session-errors.js +47 -0
- package/dist/core/session-model.js +39 -0
- package/dist/core/session-router.js +292 -62
- package/dist/core/shared-app.js +17 -0
- package/dist/core/skill-expansion.js +43 -0
- package/dist/core/system-prompt-template.js +9 -9
- package/dist/core/telemetry-staleness.js +128 -0
- package/dist/core/test-output-compaction.js +145 -0
- package/dist/core/user-settings.js +73 -0
- package/dist/cron/channel.js +28 -0
- package/dist/cron/cli.js +230 -0
- package/dist/cron/plugin.js +11 -0
- package/dist/cron/schedule.js +214 -0
- package/dist/cron/service.js +177 -0
- package/dist/cron/store.js +349 -0
- package/dist/cron/types.js +1 -0
- package/dist/data/cli.js +184 -0
- package/dist/data/event-log.js +106 -0
- package/dist/data/final-app-space-cutover-migration.js +728 -0
- package/dist/data/ingest-service.js +389 -0
- package/dist/data/message-store.js +62 -0
- package/dist/data/navigation-store.js +75 -0
- package/dist/data/observation-store.js +46 -0
- package/dist/data/payload-store.js +144 -0
- package/dist/data/pibo-store.js +59 -0
- package/dist/data/schema.js +434 -0
- package/dist/data/session-store.js +63 -0
- package/dist/data/shared-app-migration.js +757 -0
- package/dist/data/sqlite-schema.js +12 -0
- package/dist/data/telemetry-preview.js +65 -0
- package/dist/data/telemetry-queries.js +212 -0
- package/dist/data/telemetry-retention.js +50 -0
- package/dist/data/telemetry-rows.js +158 -0
- package/dist/data/telemetry.js +357 -0
- package/dist/debug/delta-compaction.js +99 -0
- package/dist/debug/detail-format.js +86 -0
- package/dist/debug/events.js +149 -29
- package/dist/debug/failures.js +162 -0
- package/dist/debug/index.js +655 -30
- package/dist/debug/messages.js +185 -0
- package/dist/debug/next-commands.js +6 -0
- package/dist/debug/payloads.js +123 -0
- package/dist/debug/pty.js +924 -0
- package/dist/debug/session.js +45 -15
- package/dist/debug/sql.js +1 -1
- package/dist/debug/stores.js +18 -13
- package/dist/debug/summary.js +72 -0
- package/dist/debug/telemetry.js +649 -0
- package/dist/debug/tools.js +168 -0
- package/dist/debug/trace-render-check.js +151 -0
- package/dist/debug/trace.js +152 -27
- package/dist/debug/web-artifacts.js +63 -0
- package/dist/debug/web-options.js +313 -0
- package/dist/debug/web-render-analysis.js +310 -0
- package/dist/debug/web-snapshot-browser-scripts.js +303 -0
- package/dist/debug/web-streaming-benchmark-analysis.js +605 -0
- package/dist/debug/web-streaming-browser-library.js +928 -0
- package/dist/debug/web-streaming-browser-scripts.js +242 -0
- package/dist/debug/web-streaming-provider-telemetry.js +194 -0
- package/dist/debug/web-streaming-report.js +493 -0
- package/dist/debug/web-streaming-types.js +1 -0
- package/dist/debug/web.js +574 -0
- package/dist/gateway/backup.js +83 -0
- package/dist/gateway/cli.js +511 -0
- package/dist/gateway/fallback.js +155 -0
- package/dist/gateway/pidfile.js +84 -0
- package/dist/gateway/protocol.js +16 -0
- package/dist/gateway/server.js +172 -17
- package/dist/gateway/tool.js +54 -51
- package/dist/gateway/web.js +74 -2
- package/dist/index.js +3 -1
- package/dist/local/client.js +3 -3
- package/dist/local/extension.js +8 -5
- package/dist/plugins/builtin.js +251 -49
- package/dist/plugins/chat-vscode-web.js +28 -0
- package/dist/plugins/codex-compat.js +0 -41
- package/dist/plugins/context-files.js +98 -18
- package/dist/plugins/dev-auth.js +124 -0
- package/dist/plugins/native-tooling.js +15 -0
- package/dist/plugins/registry.js +49 -1
- package/dist/plugins/web-annotations.js +27 -0
- package/dist/providers/minimax.js +70 -0
- package/dist/providers/openai-compat.js +48 -0
- package/dist/ralph/channel.js +8 -0
- package/dist/ralph/cli.js +152 -0
- package/dist/ralph/plugin.js +14 -0
- package/dist/ralph/service.js +271 -0
- package/dist/ralph/stopping.js +151 -0
- package/dist/ralph/store.js +450 -0
- package/dist/ralph/templates.js +200 -0
- package/dist/ralph/types.js +1 -0
- package/dist/reliability/store.js +42 -26
- package/dist/runs/registry.js +72 -35
- package/dist/session-ui/commandCatalog.js +193 -0
- package/dist/session-ui/commandResults.js +95 -0
- package/dist/session-ui/index.js +7 -0
- package/dist/session-ui/ownerViewModel.js +27 -0
- package/dist/session-ui/roomSessionViewModel.js +69 -0
- package/dist/session-ui/statusViewModel.js +127 -0
- package/dist/session-ui/terminalCards.js +210 -0
- package/dist/session-ui/terminalRows.js +937 -0
- package/dist/session-ui/terminalValue.js +45 -0
- package/dist/sessions/pibo-data-store.js +178 -0
- package/dist/sessions/sqlite-store.js +78 -12
- package/dist/sessions/store.js +11 -4
- package/dist/sessions/workflow-session-kind.js +20 -0
- package/dist/setup/cli.js +567 -0
- package/dist/shared/trace-async-agent-runs.js +127 -0
- package/dist/shared/trace-engine.js +96 -0
- package/dist/shared/trace-event-projection.js +679 -0
- package/dist/shared/trace-live-reducer.js +191 -0
- package/dist/shared/trace-nodes.js +76 -0
- package/dist/shared/trace-order.js +11 -10
- package/dist/shared/trace-patch-nodes.js +83 -0
- package/dist/shared/trace-run-notifications.js +69 -0
- package/dist/shared/trace-subagent-links.js +46 -0
- package/dist/shared/trace-transcript.js +303 -0
- package/dist/shared/trace-types.js +1 -0
- package/dist/shared-app.js +4 -0
- package/dist/signals/aggregate.js +65 -0
- package/dist/signals/events.js +1 -0
- package/dist/signals/projector.js +158 -0
- package/dist/signals/registry.js +513 -0
- package/dist/signals/store.js +1 -0
- package/dist/signals/types.js +1 -0
- package/dist/skills/cli.js +117 -0
- package/dist/tools/agent-browser-leases.js +219 -0
- package/dist/tools/agent-browser-wrapper.js +99 -0
- package/dist/tools/browser-pool.js +623 -0
- package/dist/tools/browser-use-cdp.js +56 -4
- package/dist/tools/browser-use-leases.js +215 -37
- package/dist/tools/browser-use-wrapper.js +508 -65
- package/dist/tools/cdp-client.js +189 -0
- package/dist/tools/guides.js +203 -4
- package/dist/tools/index.js +666 -16
- package/dist/tools/npm-runtime.js +136 -0
- package/dist/tools/registry.js +107 -8
- package/dist/tools/runtime/index.js +3 -0
- package/dist/tools/runtime/node-backend.js +225 -0
- package/dist/tools/runtime/node-worker-source.js +206 -0
- package/dist/tools/runtime/python-backend.js +227 -0
- package/dist/tools/runtime/python-worker-source.js +178 -0
- package/dist/tools/runtime/registry.js +255 -0
- package/dist/tools/runtime/tool.js +168 -0
- package/dist/tools/runtime/types.js +1 -0
- package/dist/tools/web-search.js +2 -1
- package/dist/user-skills/installer.js +39 -36
- package/dist/user-skills/store.js +50 -11
- package/dist/web/auth.js +5 -1
- package/dist/web/channel.js +86 -0
- package/dist/web/http.js +79 -14
- package/dist/web-annotations/api.js +348 -0
- package/dist/web-annotations/attachments.js +201 -0
- package/dist/web-annotations/cdp.js +1107 -0
- package/dist/web-annotations/index.js +7 -0
- package/dist/web-annotations/store.js +407 -0
- package/dist/web-annotations/tools.js +350 -0
- package/dist/web-annotations/types.js +34 -0
- package/dist/web-annotations/validation.js +288 -0
- package/docs/README.md +23 -0
- package/docs/ops/install-developer-host.md +112 -0
- package/docs/ops/install-user-host.md +76 -0
- package/docs/ops/upgrade-user-to-developer-host.md +69 -0
- package/package.json +24 -10
- package/skills/builtin/pi-agent-harness/SKILL.md +24 -24
- package/skills/builtin/pibo-docker-system/SKILL.md +170 -0
- package/skills/builtin/pibo-spec-writing/SKILL.md +330 -0
- package/skills/builtin/prd/SKILL.md +143 -0
- package/skills/builtin/ralph-loop/SKILL.md +359 -0
- package/skills/builtin/ralph-prd-json/SKILL.md +123 -0
- package/skills/builtin/skill-creator/LICENSE.txt +202 -0
- package/skills/builtin/skill-creator/SKILL.md +513 -0
- package/skills/builtin/skill-creator/agents/analyzer.md +274 -0
- package/skills/builtin/skill-creator/agents/comparator.md +202 -0
- package/skills/builtin/skill-creator/agents/grader.md +223 -0
- package/skills/builtin/skill-creator/assets/eval_review.html +146 -0
- package/skills/builtin/skill-creator/eval-viewer/generate_review.py +471 -0
- package/skills/builtin/skill-creator/eval-viewer/viewer.html +1325 -0
- package/skills/builtin/skill-creator/references/schemas.md +430 -0
- package/skills/builtin/skill-creator/scripts/__init__.py +0 -0
- package/skills/builtin/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/skills/builtin/skill-creator/scripts/generate_report.py +326 -0
- package/skills/builtin/skill-creator/scripts/improve_description.py +247 -0
- package/skills/builtin/skill-creator/scripts/package_skill.py +136 -0
- package/skills/builtin/skill-creator/scripts/quick_validate.py +103 -0
- package/skills/builtin/skill-creator/scripts/run_eval.py +310 -0
- package/skills/builtin/skill-creator/scripts/run_loop.py +328 -0
- package/skills/builtin/skill-creator/scripts/utils.py +47 -0
- package/skills/builtin/web-annotations/SKILL.md +93 -0
- package/dist/apps/chat-ui/assets/index-D2Qxambd.js +0 -151
- package/dist/apps/chat-ui/assets/index-DXx368XK.css +0 -1
- package/dist/env.js +0 -32
- package/dist/plugins/core-tools.js +0 -94
- package/dist/plugins/example.js +0 -67
- package/dist/plugins/remote-agent.js +0 -9
- package/dist/remote/channel.js +0 -176
- package/dist/remote/client.js +0 -92
- package/dist/remote/examples/tui-controller.js +0 -263
- package/dist/remote/protocol.js +0 -55
- package/dist/remote/session-client.js +0 -189
- package/dist/sessions/bindings.js +0 -41
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { resolve4 } from "node:dns/promises";
|
|
3
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { dirname, isAbsolute, join } from "node:path";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { getPiboConfigValue, loadPiboConfig } from "../config/config.js";
|
|
7
|
+
import { getPiboHome } from "../core/pibo-home.js";
|
|
8
|
+
function parsePort(value) {
|
|
9
|
+
const port = Number(value);
|
|
10
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535)
|
|
11
|
+
throw new Error("Port must be an integer between 1 and 65535");
|
|
12
|
+
return port;
|
|
13
|
+
}
|
|
14
|
+
function parseNonNegativeNumber(value) {
|
|
15
|
+
const parsed = Number(value);
|
|
16
|
+
if (!Number.isFinite(parsed) || parsed < 0)
|
|
17
|
+
throw new Error("Value must be a non-negative number");
|
|
18
|
+
return parsed;
|
|
19
|
+
}
|
|
20
|
+
function shellQuote(value) {
|
|
21
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
22
|
+
}
|
|
23
|
+
function serviceUnit(options) {
|
|
24
|
+
const gatewayPortEnv = options.serviceKind === "dev" ? `Environment=PIBO_GATEWAY_DEV_PORT=${options.webPort}\n` : `Environment=PIBO_GATEWAY_WEB_PORT=${options.webPort}\n`;
|
|
25
|
+
return `[Unit]
|
|
26
|
+
Description=${options.description}
|
|
27
|
+
After=network-online.target
|
|
28
|
+
Wants=network-online.target
|
|
29
|
+
|
|
30
|
+
[Service]
|
|
31
|
+
Type=simple
|
|
32
|
+
WorkingDirectory=${options.workingDirectory}
|
|
33
|
+
Environment=HOME=/root
|
|
34
|
+
Environment=PIBO_HOME=${options.piboHome}
|
|
35
|
+
Environment=NODE_ENV=production
|
|
36
|
+
${gatewayPortEnv}ExecStart=${options.execStart}
|
|
37
|
+
Restart=always
|
|
38
|
+
RestartSec=5
|
|
39
|
+
KillSignal=SIGTERM
|
|
40
|
+
TimeoutStopSec=30
|
|
41
|
+
|
|
42
|
+
[Install]
|
|
43
|
+
WantedBy=multi-user.target
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
function devStartWrapper(options) {
|
|
47
|
+
return `#!/usr/bin/env node
|
|
48
|
+
import { runWebGatewayServer } from ${JSON.stringify(`${options.repoDir}/dist/gateway/web.js`)};
|
|
49
|
+
|
|
50
|
+
await runWebGatewayServer({
|
|
51
|
+
host: "127.0.0.1",
|
|
52
|
+
port: ${options.gatewayPort},
|
|
53
|
+
web: {
|
|
54
|
+
host: "127.0.0.1",
|
|
55
|
+
port: ${options.webPort},
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
`;
|
|
59
|
+
}
|
|
60
|
+
function caddyfile(options) {
|
|
61
|
+
const blocks = [];
|
|
62
|
+
if (options.prodDomain) {
|
|
63
|
+
blocks.push(`${options.prodDomain} {
|
|
64
|
+
encode zstd gzip
|
|
65
|
+
reverse_proxy 127.0.0.1:${options.prodPort}
|
|
66
|
+
}`);
|
|
67
|
+
}
|
|
68
|
+
if (options.prodWwwDomain && options.prodDomain) {
|
|
69
|
+
blocks.push(`${options.prodWwwDomain} {
|
|
70
|
+
redir https://${options.prodDomain}{uri} permanent
|
|
71
|
+
}`);
|
|
72
|
+
}
|
|
73
|
+
if (options.devDomain && options.devPort) {
|
|
74
|
+
blocks.push(`${options.devDomain} {
|
|
75
|
+
encode zstd gzip
|
|
76
|
+
reverse_proxy 127.0.0.1:${options.devPort}
|
|
77
|
+
}`);
|
|
78
|
+
}
|
|
79
|
+
if (options.devWwwDomain && options.devDomain) {
|
|
80
|
+
blocks.push(`${options.devWwwDomain} {
|
|
81
|
+
redir https://${options.devDomain}{uri} permanent
|
|
82
|
+
}`);
|
|
83
|
+
}
|
|
84
|
+
return `${blocks.join("\n\n")}\n`;
|
|
85
|
+
}
|
|
86
|
+
function userEnvTemplate(options) {
|
|
87
|
+
return `# Pibo user-host setup
|
|
88
|
+
PIBO_HOME=${options.piboHome}
|
|
89
|
+
PIBO_AUTH_BASE_URL=${options.domain ? `https://${options.domain}` : "https://pibo.example.com"}
|
|
90
|
+
# Set through \`pibo config set\` or your secret manager:
|
|
91
|
+
# PIBO_AUTH_SECRET=<at-least-32-characters>
|
|
92
|
+
# PIBO_GOOGLE_CLIENT_ID=<google-client-id>
|
|
93
|
+
# PIBO_GOOGLE_CLIENT_SECRET=<google-client-secret>
|
|
94
|
+
# PIBO_ALLOWED_EMAILS=you@example.com
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
function developerEnvTemplate(options) {
|
|
98
|
+
return `# Pibo developer-host setup
|
|
99
|
+
PIBO_ORIGIN=${options.origin ?? "git@github.com:<your-fork>/pibo.git"}
|
|
100
|
+
PIBO_UPSTREAM=${options.upstream ?? "git@github.com:Pascapone/pibo.git"}
|
|
101
|
+
PIBO_REPO_DIR=${options.repoDir}
|
|
102
|
+
PIBO_PROD_HOME=${options.prodHome}
|
|
103
|
+
PIBO_DEV_HOME=${options.devHome}
|
|
104
|
+
PIBO_PROD_BASE_URL=${options.prodDomain ? `https://${options.prodDomain}` : "https://pibo.example.com"}
|
|
105
|
+
PIBO_DEV_BASE_URL=${options.devDomain ? `https://${options.devDomain}` : "https://dev.pibo.example.com"}
|
|
106
|
+
# Optional: override the dev deploy reachability probe. If omitted, deploy uses PIBO_DEV_BASE_URL/apps/chat.
|
|
107
|
+
# PIBO_DEV_PUBLIC_URL=${options.devDomain ? `https://${options.devDomain}/apps/chat` : "https://dev.pibo.example.com/apps/chat"}
|
|
108
|
+
`;
|
|
109
|
+
}
|
|
110
|
+
export function createUserHostSetupPlan(options = {}) {
|
|
111
|
+
const piboHome = options.piboHome ?? "/root/.pibo";
|
|
112
|
+
const workingDirectory = options.workingDirectory ?? "/root";
|
|
113
|
+
const webPort = options.webPort ?? 4788;
|
|
114
|
+
const serviceName = options.serviceName ?? "pibo-web";
|
|
115
|
+
const piboCommand = options.piboCommand ?? "/usr/bin/pibo";
|
|
116
|
+
const wwwDomain = options.wwwDomain ?? (options.domain ? `www.${options.domain}` : undefined);
|
|
117
|
+
const warnings = [];
|
|
118
|
+
if (!options.domain)
|
|
119
|
+
warnings.push("No production domain was provided; generated Caddy/Auth examples use placeholders.");
|
|
120
|
+
const generatedFiles = [
|
|
121
|
+
{
|
|
122
|
+
path: `/etc/systemd/system/${serviceName}.service`,
|
|
123
|
+
purpose: "Production web gateway systemd service",
|
|
124
|
+
content: serviceUnit({
|
|
125
|
+
description: "Pibo web gateway",
|
|
126
|
+
workingDirectory,
|
|
127
|
+
piboHome,
|
|
128
|
+
serviceKind: "prod",
|
|
129
|
+
webPort,
|
|
130
|
+
execStart: `${piboCommand} gateway:web --web-host 127.0.0.1 --web-port ${webPort}`,
|
|
131
|
+
}),
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
path: `${piboHome}/setup.env.example`,
|
|
135
|
+
purpose: "User-host environment template",
|
|
136
|
+
content: userEnvTemplate({ domain: options.domain, piboHome }),
|
|
137
|
+
},
|
|
138
|
+
];
|
|
139
|
+
if (options.includeCaddy !== false) {
|
|
140
|
+
generatedFiles.push({
|
|
141
|
+
path: "/etc/caddy/Caddyfile",
|
|
142
|
+
purpose: "HTTPS reverse proxy for the production gateway",
|
|
143
|
+
content: caddyfile({ prodDomain: options.domain, prodWwwDomain: wwwDomain, prodPort: webPort }),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
mode: "user-host",
|
|
148
|
+
summary: "Install one stable Pibo gateway for normal use. No developer gateway, Docker, GitHub App, or worktree setup is required.",
|
|
149
|
+
principles: [
|
|
150
|
+
"Keep first-run setup small enough that new users can succeed quickly.",
|
|
151
|
+
"Use one PIBO_HOME and one systemd service by default.",
|
|
152
|
+
"Make Docker and developer workflows explicit opt-ins.",
|
|
153
|
+
],
|
|
154
|
+
domains: { production: options.domain, productionWww: wwwDomain },
|
|
155
|
+
directories: { workingDirectory, piboHome },
|
|
156
|
+
services: { [serviceName]: { port: webPort, gatewayPort: 4789, home: piboHome } },
|
|
157
|
+
requiredHostPackages: ["node >=24", "npm"],
|
|
158
|
+
optionalHostPackages: ["caddy for HTTPS", "docker for compute workers only if the user opts in"],
|
|
159
|
+
warnings,
|
|
160
|
+
nextSteps: [
|
|
161
|
+
"Install Pibo through npm or build it from source.",
|
|
162
|
+
"Set auth.baseURL, auth.secret, OAuth client values, and allowed emails with `pibo config set`.",
|
|
163
|
+
`Install ${serviceName}.service, then run \`systemctl enable --now ${serviceName}\`.`,
|
|
164
|
+
"If Caddy is used, point DNS at the host before expecting Let's Encrypt certificates.",
|
|
165
|
+
"Run `pibo gateway web status` and open `/apps/chat` on the configured domain.",
|
|
166
|
+
],
|
|
167
|
+
generatedFiles,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
export function createDeveloperHostSetupPlan(options = {}) {
|
|
171
|
+
const repoDir = options.repoDir ?? "/root/code/pibo";
|
|
172
|
+
const prodBranch = options.prodBranch ?? "main";
|
|
173
|
+
const devBranch = options.devBranch ?? "dev";
|
|
174
|
+
const devWorktree = options.devWorktree ?? `${repoDir}/.worktrees/${devBranch}`;
|
|
175
|
+
const prodHome = options.prodHome ?? "/root/.pibo";
|
|
176
|
+
const devHome = options.devHome ?? "/root/.pibo-dev";
|
|
177
|
+
const prodWebPort = options.prodWebPort ?? 4788;
|
|
178
|
+
const prodGatewayPort = options.prodGatewayPort ?? 4789;
|
|
179
|
+
const devWebPort = options.devWebPort ?? 4808;
|
|
180
|
+
const devGatewayPort = options.devGatewayPort ?? 4809;
|
|
181
|
+
const nodeCommand = options.nodeCommand ?? "/usr/bin/node";
|
|
182
|
+
const prodEntrypoint = `${nodeCommand} ${repoDir}/dist/bin/pibo.js`;
|
|
183
|
+
const prodWwwDomain = options.prodWwwDomain ?? (options.prodDomain ? `www.${options.prodDomain}` : undefined);
|
|
184
|
+
const devWwwDomain = options.devWwwDomain ?? (options.devDomain ? `www.${options.devDomain}` : undefined);
|
|
185
|
+
const warnings = [];
|
|
186
|
+
if (!options.origin)
|
|
187
|
+
warnings.push("No origin fork was provided. Developer hosts should use a server-specific fork as origin.");
|
|
188
|
+
if (!options.prodDomain || !options.devDomain)
|
|
189
|
+
warnings.push("Production and dev domains should both be configured before requesting HTTPS certificates.");
|
|
190
|
+
const generatedFiles = [
|
|
191
|
+
{
|
|
192
|
+
path: "/etc/systemd/system/pibo-web.service",
|
|
193
|
+
purpose: "Production gateway pinned to the stable branch/home",
|
|
194
|
+
content: serviceUnit({
|
|
195
|
+
description: "Pibo production web gateway",
|
|
196
|
+
workingDirectory: repoDir,
|
|
197
|
+
piboHome: prodHome,
|
|
198
|
+
serviceKind: "prod",
|
|
199
|
+
webPort: prodWebPort,
|
|
200
|
+
execStart: `${prodEntrypoint} gateway:web --web-host 127.0.0.1 --web-port ${prodWebPort}`,
|
|
201
|
+
}),
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
path: "/usr/local/bin/pibo-web-dev-start.mjs",
|
|
205
|
+
purpose: "Dev gateway start wrapper; required so dev can use gateway port 4809 without colliding with production port 4789",
|
|
206
|
+
content: devStartWrapper({ repoDir: devWorktree, webPort: devWebPort, gatewayPort: devGatewayPort }),
|
|
207
|
+
mode: 0o755,
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
path: "/etc/systemd/system/pibo-web-dev.service",
|
|
211
|
+
purpose: "Development gateway pinned to the dev worktree and isolated PIBO_HOME",
|
|
212
|
+
content: serviceUnit({
|
|
213
|
+
description: "Pibo development web gateway",
|
|
214
|
+
workingDirectory: devWorktree,
|
|
215
|
+
piboHome: devHome,
|
|
216
|
+
serviceKind: "dev",
|
|
217
|
+
webPort: devWebPort,
|
|
218
|
+
execStart: `${nodeCommand} /usr/local/bin/pibo-web-dev-start.mjs`,
|
|
219
|
+
}),
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
path: `${repoDir}/.env.developer-host.example`,
|
|
223
|
+
purpose: "Developer-host environment template",
|
|
224
|
+
content: developerEnvTemplate({ origin: options.origin, upstream: options.upstream, prodDomain: options.prodDomain, devDomain: options.devDomain, repoDir, prodHome, devHome }),
|
|
225
|
+
},
|
|
226
|
+
];
|
|
227
|
+
if (options.includeCaddy !== false) {
|
|
228
|
+
generatedFiles.push({
|
|
229
|
+
path: "/etc/caddy/Caddyfile",
|
|
230
|
+
purpose: "HTTPS reverse proxy for production/dev gateways and www redirects",
|
|
231
|
+
content: caddyfile({ prodDomain: options.prodDomain, prodWwwDomain, devDomain: options.devDomain, devWwwDomain, prodPort: prodWebPort, devPort: devWebPort }),
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
mode: "developer-host",
|
|
236
|
+
summary: "Upgrade or install a Pibo host for core development with isolated production and dev gateways plus Docker compute workers.",
|
|
237
|
+
principles: [
|
|
238
|
+
"Production and development gateways must not share ports, PID files, service names, or PIBO_HOME directories.",
|
|
239
|
+
"Production follows the stable branch; development follows the dev branch in a separate worktree.",
|
|
240
|
+
"Docker compute workers are part of developer setup because each agent needs an isolated restartable gateway.",
|
|
241
|
+
"GitHub remotes stay explicit: origin is the server-specific fork, upstream is the canonical project.",
|
|
242
|
+
],
|
|
243
|
+
domains: { production: options.prodDomain, productionWww: prodWwwDomain, development: options.devDomain, developmentWww: devWwwDomain },
|
|
244
|
+
branches: { production: prodBranch, development: devBranch },
|
|
245
|
+
remotes: { origin: options.origin, upstream: options.upstream ?? "git@github.com:Pascapone/pibo.git" },
|
|
246
|
+
directories: { repoDir, devWorktree, prodHome, devHome },
|
|
247
|
+
services: {
|
|
248
|
+
"pibo-web": { port: prodWebPort, gatewayPort: prodGatewayPort, home: prodHome, branch: prodBranch },
|
|
249
|
+
"pibo-web-dev": { port: devWebPort, gatewayPort: devGatewayPort, home: devHome, branch: devBranch },
|
|
250
|
+
},
|
|
251
|
+
requiredHostPackages: ["node >=24", "npm", "git", "docker", "docker compose", "build-essential"],
|
|
252
|
+
optionalHostPackages: ["caddy for HTTPS", "ufw for explicit firewall rules"],
|
|
253
|
+
warnings,
|
|
254
|
+
nextSteps: [
|
|
255
|
+
`Clone ${options.origin ? shellQuote(options.origin) : "the server-specific fork"} into ${repoDir} and set upstream to ${options.upstream ?? "git@github.com:Pascapone/pibo.git"}.`,
|
|
256
|
+
`Check out ${prodBranch} in ${repoDir} and create ${devBranch} worktree at ${devWorktree}.`,
|
|
257
|
+
"Run `npm ci && npm run build` in each branch/worktree that has a service; do not globally install the dev worktree over production.",
|
|
258
|
+
"Restore or create production secrets under /root/.pibo; copy only non-production-safe config into /root/.pibo-dev.",
|
|
259
|
+
"Install the generated systemd units and dev start wrapper, then start pibo-web and pibo-web-dev.",
|
|
260
|
+
"Install Docker and validate `pibo compute spawn` so agent workers can restart their own gateways safely.",
|
|
261
|
+
"Point DNS at the host before expecting Caddy/Let's Encrypt to issue certificates.",
|
|
262
|
+
"Run `pibo gateway web status`, `PIBO_GATEWAY_DEV_PORT=4808 pibo gateway dev status`, and browser checks for both domains.",
|
|
263
|
+
],
|
|
264
|
+
generatedFiles,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function materializedPath(filePath, writeTo) {
|
|
268
|
+
if (!writeTo)
|
|
269
|
+
return filePath;
|
|
270
|
+
return isAbsolute(filePath) ? join(writeTo, filePath.replace(/^\/+/, "")) : join(writeTo, filePath);
|
|
271
|
+
}
|
|
272
|
+
function writeGeneratedFiles(plan, options) {
|
|
273
|
+
if (options.apply && options.writeTo)
|
|
274
|
+
throw new Error("Use either --apply or --write-to, not both");
|
|
275
|
+
if (options.apply && options.yes !== true)
|
|
276
|
+
throw new Error("Refusing to write system files without --yes");
|
|
277
|
+
if (!options.apply && !options.writeTo)
|
|
278
|
+
return [];
|
|
279
|
+
const written = [];
|
|
280
|
+
for (const file of plan.generatedFiles) {
|
|
281
|
+
const destinationPath = materializedPath(file.path, options.writeTo);
|
|
282
|
+
mkdirSync(dirname(destinationPath), { recursive: true });
|
|
283
|
+
writeFileSync(destinationPath, file.content.endsWith("\n") ? file.content : `${file.content}\n`);
|
|
284
|
+
if (file.mode !== undefined)
|
|
285
|
+
chmodSync(destinationPath, file.mode);
|
|
286
|
+
written.push({ sourcePath: file.path, destinationPath, mode: file.mode });
|
|
287
|
+
}
|
|
288
|
+
return written;
|
|
289
|
+
}
|
|
290
|
+
function printWrittenFiles(written) {
|
|
291
|
+
if (written.length === 0)
|
|
292
|
+
return;
|
|
293
|
+
console.log("\nWrote files:");
|
|
294
|
+
for (const file of written) {
|
|
295
|
+
const mode = file.mode !== undefined ? ` mode=${file.mode.toString(8)}` : "";
|
|
296
|
+
console.log(`- ${file.destinationPath} (from ${file.sourcePath})${mode}`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
function emitPlan(plan, options) {
|
|
300
|
+
if (options.json && (options.apply || options.writeTo))
|
|
301
|
+
throw new Error("--json cannot be combined with --apply or --write-to");
|
|
302
|
+
if (options.json) {
|
|
303
|
+
printJson(plan);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
printPlan(plan, options.printFiles === true);
|
|
307
|
+
printWrittenFiles(writeGeneratedFiles(plan, options));
|
|
308
|
+
}
|
|
309
|
+
function printPlan(plan, printFiles) {
|
|
310
|
+
console.log(`${plan.mode}: ${plan.summary}`);
|
|
311
|
+
console.log("\nPrinciples:");
|
|
312
|
+
for (const item of plan.principles)
|
|
313
|
+
console.log(`- ${item}`);
|
|
314
|
+
console.log("\nServices:");
|
|
315
|
+
for (const [name, service] of Object.entries(plan.services)) {
|
|
316
|
+
const gateway = service.gatewayPort ? ` gateway=${service.gatewayPort}` : "";
|
|
317
|
+
const branch = service.branch ? ` branch=${service.branch}` : "";
|
|
318
|
+
console.log(`- ${name}: web=${service.port}${gateway} home=${service.home}${branch}`);
|
|
319
|
+
}
|
|
320
|
+
if (plan.warnings.length > 0) {
|
|
321
|
+
console.log("\nWarnings:");
|
|
322
|
+
for (const warning of plan.warnings)
|
|
323
|
+
console.log(`- ${warning}`);
|
|
324
|
+
}
|
|
325
|
+
console.log("\nNext steps:");
|
|
326
|
+
for (const [index, step] of plan.nextSteps.entries())
|
|
327
|
+
console.log(`${index + 1}. ${step}`);
|
|
328
|
+
console.log("\nGenerated files:");
|
|
329
|
+
for (const file of plan.generatedFiles)
|
|
330
|
+
console.log(`- ${file.path}: ${file.purpose}`);
|
|
331
|
+
if (printFiles) {
|
|
332
|
+
for (const file of plan.generatedFiles) {
|
|
333
|
+
console.log(`\n--- ${file.path} ---`);
|
|
334
|
+
console.log(file.content.trimEnd());
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
function printJson(value) {
|
|
339
|
+
console.log(JSON.stringify(value, null, 2));
|
|
340
|
+
}
|
|
341
|
+
function commandExists(command) {
|
|
342
|
+
try {
|
|
343
|
+
execFileSync("sh", ["-lc", `command -v ${shellQuote(command)} >/dev/null 2>&1`], { stdio: "ignore" });
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
catch {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
function commandOutput(command, args) {
|
|
351
|
+
try {
|
|
352
|
+
return execFileSync(command, args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
return undefined;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
function addCommandCheck(checks, command, required) {
|
|
359
|
+
const installed = commandExists(command);
|
|
360
|
+
checks.push({
|
|
361
|
+
name: `command:${command}`,
|
|
362
|
+
status: installed ? "ok" : required ? "fail" : "warn",
|
|
363
|
+
detail: installed ? `${command} is installed` : `${command} is not installed`,
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
function authConfigChecks(piboHome) {
|
|
367
|
+
const configPath = join(piboHome, "config.json");
|
|
368
|
+
const notReady = "Pibo web will not start until Better Auth is configured. Set auth.baseURL, auth.secret, auth.googleClientId, auth.googleClientSecret, and auth.allowedEmails.";
|
|
369
|
+
if (!existsSync(configPath))
|
|
370
|
+
return [
|
|
371
|
+
{ name: "auth.ready", status: "fail", detail: notReady },
|
|
372
|
+
{ name: "auth.config", status: "fail", detail: `${configPath} does not exist yet` },
|
|
373
|
+
];
|
|
374
|
+
try {
|
|
375
|
+
const config = loadPiboConfig(configPath);
|
|
376
|
+
const checks = [];
|
|
377
|
+
const missing = [];
|
|
378
|
+
const requiredStrings = [
|
|
379
|
+
{ key: "auth.baseURL", detail: "Set with `pibo config set auth.baseURL https://your-domain.example`." },
|
|
380
|
+
{ key: "auth.secret", detail: "Set a random value with at least 32 characters." },
|
|
381
|
+
{ key: "auth.googleClientId", detail: "Create a Google OAuth web client and set its client id." },
|
|
382
|
+
{ key: "auth.googleClientSecret", detail: "Set the Google OAuth client secret." },
|
|
383
|
+
];
|
|
384
|
+
for (const item of requiredStrings) {
|
|
385
|
+
const value = getPiboConfigValue(config, item.key);
|
|
386
|
+
const ok = typeof value === "string" && value.length > 0 && (item.key !== "auth.secret" || value.length >= 32);
|
|
387
|
+
if (!ok)
|
|
388
|
+
missing.push(item.key);
|
|
389
|
+
checks.push({ name: item.key, status: ok ? "ok" : "fail", detail: ok ? `${item.key} is configured` : `${item.key} is missing or invalid. ${item.detail}` });
|
|
390
|
+
}
|
|
391
|
+
const allowedEmails = getPiboConfigValue(config, "auth.allowedEmails");
|
|
392
|
+
const allowedEmailsOk = Array.isArray(allowedEmails) && allowedEmails.length > 0;
|
|
393
|
+
if (!allowedEmailsOk)
|
|
394
|
+
missing.push("auth.allowedEmails");
|
|
395
|
+
checks.push({
|
|
396
|
+
name: "auth.allowedEmails",
|
|
397
|
+
status: allowedEmailsOk ? "ok" : "fail",
|
|
398
|
+
detail: allowedEmailsOk ? "auth.allowedEmails is configured" : "auth.allowedEmails is missing or empty. Set with `pibo config set auth.allowedEmails you@example.com`.",
|
|
399
|
+
});
|
|
400
|
+
checks.unshift({ name: "auth.ready", status: missing.length === 0 ? "ok" : "fail", detail: missing.length === 0 ? "Better Auth is configured" : `${notReady} Missing: ${missing.join(", ")}` });
|
|
401
|
+
return checks;
|
|
402
|
+
}
|
|
403
|
+
catch (error) {
|
|
404
|
+
return [{ name: "auth.config", status: "fail", detail: error instanceof Error ? error.message : String(error) }];
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function swapTotalGb() {
|
|
408
|
+
try {
|
|
409
|
+
const match = readFileSync("/proc/meminfo", "utf8").match(/^SwapTotal:\s+(\d+)\s+kB/m);
|
|
410
|
+
if (!match)
|
|
411
|
+
return undefined;
|
|
412
|
+
return Number(match[1]) / 1024 / 1024;
|
|
413
|
+
}
|
|
414
|
+
catch {
|
|
415
|
+
return undefined;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
function swapCheck(minSwapGb) {
|
|
419
|
+
if (!minSwapGb || minSwapGb <= 0)
|
|
420
|
+
return [];
|
|
421
|
+
const total = swapTotalGb();
|
|
422
|
+
if (total === undefined)
|
|
423
|
+
return [{ name: "swap", status: "warn", detail: "Could not inspect swap from /proc/meminfo" }];
|
|
424
|
+
const ok = total + 0.05 >= minSwapGb;
|
|
425
|
+
return [{
|
|
426
|
+
name: "swap",
|
|
427
|
+
status: ok ? "ok" : "fail",
|
|
428
|
+
detail: `Swap ${total.toFixed(1)} GiB; expected at least ${minSwapGb} GiB for this host profile`,
|
|
429
|
+
}];
|
|
430
|
+
}
|
|
431
|
+
async function dnsChecks(domain, expectedIp, label) {
|
|
432
|
+
if (!domain)
|
|
433
|
+
return [];
|
|
434
|
+
try {
|
|
435
|
+
const addresses = await resolve4(domain);
|
|
436
|
+
const matches = expectedIp ? addresses.includes(expectedIp) : true;
|
|
437
|
+
return [{
|
|
438
|
+
name: `dns:${label}`,
|
|
439
|
+
status: matches ? "ok" : "fail",
|
|
440
|
+
detail: expectedIp ? `${domain} A=${addresses.join(", ") || "<none>"}; expected ${expectedIp}` : `${domain} A=${addresses.join(", ") || "<none>"}`,
|
|
441
|
+
}];
|
|
442
|
+
}
|
|
443
|
+
catch (error) {
|
|
444
|
+
return [{ name: `dns:${label}`, status: "fail", detail: error instanceof Error ? error.message : String(error) }];
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
async function createDoctorStatus(options) {
|
|
448
|
+
const piboHome = options.piboHome ?? getPiboHome();
|
|
449
|
+
const checks = [];
|
|
450
|
+
const nodeMajorOk = Number(process.versions.node.split(".")[0]) >= 24;
|
|
451
|
+
checks.push({ name: "node", status: nodeMajorOk ? "ok" : "fail", detail: `Node ${process.versions.node}${nodeMajorOk ? "" : " requires >=24"}` });
|
|
452
|
+
addCommandCheck(checks, "npm", true);
|
|
453
|
+
addCommandCheck(checks, "git", false);
|
|
454
|
+
addCommandCheck(checks, "systemctl", false);
|
|
455
|
+
addCommandCheck(checks, "caddy", false);
|
|
456
|
+
addCommandCheck(checks, "docker", options.requireDocker === true);
|
|
457
|
+
if (commandExists("docker")) {
|
|
458
|
+
const dockerInfo = commandOutput("docker", ["info", "--format", "{{.ServerVersion}}"]);
|
|
459
|
+
checks.push({ name: "docker.daemon", status: dockerInfo ? "ok" : options.requireDocker ? "fail" : "warn", detail: dockerInfo ? `Docker daemon ${dockerInfo}` : "Docker daemon is not reachable" });
|
|
460
|
+
}
|
|
461
|
+
checks.push(...swapCheck(options.minSwapGb));
|
|
462
|
+
checks.push(...authConfigChecks(piboHome));
|
|
463
|
+
checks.push(...await dnsChecks(options.domain, options.expectedIp, "production"));
|
|
464
|
+
checks.push(...await dnsChecks(options.devDomain, options.expectedIp, "development"));
|
|
465
|
+
return {
|
|
466
|
+
node: process.versions.node,
|
|
467
|
+
nodeMajorOk,
|
|
468
|
+
platform: process.platform,
|
|
469
|
+
uid: typeof process.getuid === "function" ? process.getuid() : undefined,
|
|
470
|
+
piboHome,
|
|
471
|
+
checks,
|
|
472
|
+
recommendations: [
|
|
473
|
+
"Use user-host setup for normal npm installs.",
|
|
474
|
+
"Use developer-host setup only when you need prod/dev gateways, Docker compute workers, GitHub App PR flow, and branch worktrees.",
|
|
475
|
+
"Configure auth before starting pibo-web; Better Auth requires baseURL, secret, Google OAuth values, and allowed emails.",
|
|
476
|
+
"Docker is only required for developer-host compute workers; user-host installs can ignore Docker warnings.",
|
|
477
|
+
"Swap is not created automatically; for developer hosts, provision swap at the OS level and verify it with `--min-swap-gb`."
|
|
478
|
+
],
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
function printDoctorStatus(status) {
|
|
482
|
+
console.log(`Node: ${status.node} (${status.nodeMajorOk ? "ok" : "requires >=24"})`);
|
|
483
|
+
console.log(`Platform: ${status.platform}`);
|
|
484
|
+
console.log(`PIBO_HOME: ${status.piboHome}`);
|
|
485
|
+
console.log("Checks:");
|
|
486
|
+
for (const check of status.checks)
|
|
487
|
+
console.log(`- ${check.status.toUpperCase()} ${check.name}: ${check.detail}`);
|
|
488
|
+
console.log("Recommendations:");
|
|
489
|
+
for (const item of status.recommendations)
|
|
490
|
+
console.log(`- ${item}`);
|
|
491
|
+
}
|
|
492
|
+
export async function runSetupCli(argv = process.argv) {
|
|
493
|
+
const program = new Command();
|
|
494
|
+
program.name("pibo setup").description("Plan Pibo host installation and developer upgrades").helpOption("-h, --help", "Display help for command").showHelpAfterError();
|
|
495
|
+
program
|
|
496
|
+
.command("user-host")
|
|
497
|
+
.description("Plan a simple one-gateway Pibo host for normal users")
|
|
498
|
+
.option("--domain <domain>", "Production domain, for example pibo.example.com")
|
|
499
|
+
.option("--www-domain <domain>", "Optional www redirect domain")
|
|
500
|
+
.option("--pibo-home <path>", "PIBO_HOME for the user host", "/root/.pibo")
|
|
501
|
+
.option("--working-dir <path>", "systemd WorkingDirectory for npm-based installs", "/root")
|
|
502
|
+
.option("--web-port <port>", "Loopback web port", parsePort, 4788)
|
|
503
|
+
.option("--service-name <name>", "systemd service name", "pibo-web")
|
|
504
|
+
.option("--pibo-command <command>", "Command used by systemd to start pibo", "/usr/bin/pibo")
|
|
505
|
+
.option("--no-caddy", "Do not include a Caddyfile")
|
|
506
|
+
.option("--json", "Print JSON")
|
|
507
|
+
.option("--print-files", "Print generated file contents")
|
|
508
|
+
.option("--write-to <dir>", "Write generated files under a staging directory instead of system paths")
|
|
509
|
+
.option("--apply", "Write generated files to their target system paths")
|
|
510
|
+
.option("--yes", "Confirm --apply writes")
|
|
511
|
+
.action((options) => {
|
|
512
|
+
const plan = createUserHostSetupPlan({ ...options, workingDirectory: options.workingDir, includeCaddy: options.caddy });
|
|
513
|
+
emitPlan(plan, options);
|
|
514
|
+
});
|
|
515
|
+
program
|
|
516
|
+
.command("developer-host")
|
|
517
|
+
.description("Plan a two-gateway developer host with prod/dev separation and Docker compute workers")
|
|
518
|
+
.option("--prod-domain <domain>", "Production domain")
|
|
519
|
+
.option("--prod-www-domain <domain>", "Production www redirect domain")
|
|
520
|
+
.option("--dev-domain <domain>", "Development domain")
|
|
521
|
+
.option("--dev-www-domain <domain>", "Development www redirect domain")
|
|
522
|
+
.option("--origin <url>", "Server-specific fork remote")
|
|
523
|
+
.option("--upstream <url>", "Canonical upstream remote", "git@github.com:Pascapone/pibo.git")
|
|
524
|
+
.option("--repo-dir <path>", "Production source checkout", "/root/code/pibo")
|
|
525
|
+
.option("--dev-worktree <path>", "Development worktree path")
|
|
526
|
+
.option("--prod-branch <name>", "Production branch", "main")
|
|
527
|
+
.option("--dev-branch <name>", "Development branch", "dev")
|
|
528
|
+
.option("--prod-home <path>", "Production PIBO_HOME", "/root/.pibo")
|
|
529
|
+
.option("--dev-home <path>", "Development PIBO_HOME", "/root/.pibo-dev")
|
|
530
|
+
.option("--prod-web-port <port>", "Production web port", parsePort, 4788)
|
|
531
|
+
.option("--prod-gateway-port <port>", "Production internal gateway port", parsePort, 4789)
|
|
532
|
+
.option("--dev-web-port <port>", "Development web port", parsePort, 4808)
|
|
533
|
+
.option("--dev-gateway-port <port>", "Development internal gateway port", parsePort, 4809)
|
|
534
|
+
.option("--node-command <command>", "Node command used by generated source-pinned services", "/usr/bin/node")
|
|
535
|
+
.option("--no-caddy", "Do not include a Caddyfile")
|
|
536
|
+
.option("--json", "Print JSON")
|
|
537
|
+
.option("--print-files", "Print generated file contents")
|
|
538
|
+
.option("--write-to <dir>", "Write generated files under a staging directory instead of system paths")
|
|
539
|
+
.option("--apply", "Write generated files to their target system paths")
|
|
540
|
+
.option("--yes", "Confirm --apply writes")
|
|
541
|
+
.action((options) => {
|
|
542
|
+
const plan = createDeveloperHostSetupPlan({ ...options, includeCaddy: options.caddy });
|
|
543
|
+
emitPlan(plan, options);
|
|
544
|
+
});
|
|
545
|
+
program
|
|
546
|
+
.command("doctor")
|
|
547
|
+
.description("Inspect local host prerequisites without changing the system")
|
|
548
|
+
.option("--pibo-home <path>", "PIBO_HOME to inspect", getPiboHome())
|
|
549
|
+
.option("--domain <domain>", "Production domain to resolve")
|
|
550
|
+
.option("--dev-domain <domain>", "Development domain to resolve")
|
|
551
|
+
.option("--expected-ip <ip>", "Expected A record target for domain checks")
|
|
552
|
+
.option("--require-docker", "Treat missing Docker as a failure")
|
|
553
|
+
.option("--min-swap-gb <gb>", "Require at least this much configured swap", parseNonNegativeNumber)
|
|
554
|
+
.option("--json", "Print JSON")
|
|
555
|
+
.action(async (options) => {
|
|
556
|
+
const status = await createDoctorStatus(options);
|
|
557
|
+
if (options.json)
|
|
558
|
+
printJson(status);
|
|
559
|
+
else
|
|
560
|
+
printDoctorStatus(status);
|
|
561
|
+
});
|
|
562
|
+
if (argv.length <= 2 || argv[2] === "--help" || argv[2] === "-h") {
|
|
563
|
+
program.outputHelp();
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
await program.parseAsync(argv);
|
|
567
|
+
}
|