@pasko70/pibo 1.0.5 → 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 -250
- 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 +42 -5
- 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 +47 -0
- 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 +3168 -1811
- 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-CI0Xj2Cp.js → dist-B4lw9z4F.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-aMr2VYOu.js → dist-BbTaHWON.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-u2OzzOTm.js → dist-BcT_c1EJ.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Di1ScJ22.js → dist-CGINd7XU.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-wiRpAHIv.js → dist-CrBzZkUp.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CaNOvqMY.js → dist-CyyISotB.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-zgYUl2B-.js → dist-DFbnFNpX.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CNlhGq5i.js → dist-DGLWQLX8.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BGxHKHPX.js → dist-DfcIkFSN.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DrM-H3e1.js → dist-sKDHTwaT.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DpmEro5R.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 +174 -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 +252 -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 +66 -2
- 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 +214 -0
- package/dist/user-skills/manager.js +35 -0
- package/dist/user-skills/store.js +267 -0
- package/dist/user-skills/types.js +1 -0
- 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/{.codex/skills → 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-B_E935fP.js +0 -151
- package/dist/apps/chat-ui/assets/index-Dk-opWl3.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
- /package/{.codex/skills → skills/builtin}/pi-agent-harness/agents/openai.yaml +0 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { DEFAULT_TOOL_BYTES, formatTruncationFooter, sliceTextByBytes } from "./detail-format.js";
|
|
2
|
+
import { formatNextCommands } from "./next-commands.js";
|
|
3
|
+
import { eventAttributes, eventPayload, stringifyPayloadValue } from "./payloads.js";
|
|
4
|
+
import { openReadOnlyDebugDatabase, withStorePath } from "./sql.js";
|
|
5
|
+
export function inspectDebugTool(piboSessionId, store, selector, options = {}) {
|
|
6
|
+
if (!store.exists)
|
|
7
|
+
throw new Error(`Debug store "chat" not found at ${store.path}`);
|
|
8
|
+
const db = openReadOnlyDebugDatabase(store);
|
|
9
|
+
try {
|
|
10
|
+
if (!tableExists(db, "event_log"))
|
|
11
|
+
return emptyTool(piboSessionId, selector);
|
|
12
|
+
const rows = db.prepare(`
|
|
13
|
+
SELECT stream_id, session_id, session_sequence, event_id, type, created_at, preview_text, attributes_json
|
|
14
|
+
FROM event_log
|
|
15
|
+
WHERE session_id = ? AND type IN ('tool_call', 'tool_execution_started', 'tool_execution_updated', 'tool_execution_finished')
|
|
16
|
+
ORDER BY stream_id ASC
|
|
17
|
+
`).all(piboSessionId);
|
|
18
|
+
const matching = rows.filter((row) => toolCallIdFromRow(row)?.includes(selector) || row.event_id === selector);
|
|
19
|
+
if (matching.length === 0)
|
|
20
|
+
return emptyTool(piboSessionId, selector);
|
|
21
|
+
const toolCallId = toolCallIdFromRow(matching[0]) ?? selector;
|
|
22
|
+
const toolName = firstString(matching.map(toolNameFromRow));
|
|
23
|
+
const started = matching.find((row) => row.type === "tool_execution_started") ?? matching.find((row) => row.type === "tool_call");
|
|
24
|
+
const finished = [...matching].reverse().find((row) => row.type === "tool_execution_finished");
|
|
25
|
+
const args = firstDefined(matching.map(argsFromRow));
|
|
26
|
+
const output = finished ? outputFromRow(finished) : firstDefined([...matching].reverse().map(outputFromRow));
|
|
27
|
+
const error = finished ? errorFromRow(finished) : undefined;
|
|
28
|
+
const status = statusFromRows(matching, finished);
|
|
29
|
+
const argsSlice = args !== undefined ? sliceTextByBytes(stringifyPayloadValue(args), options, DEFAULT_TOOL_BYTES) : undefined;
|
|
30
|
+
const outputSlice = output !== undefined ? sliceTextByBytes(stringifyPayloadValue(options.error ? (error ?? output) : output), options, DEFAULT_TOOL_BYTES) : undefined;
|
|
31
|
+
return {
|
|
32
|
+
piboSessionId,
|
|
33
|
+
resultType: "debug.tool",
|
|
34
|
+
selector,
|
|
35
|
+
toolCallId,
|
|
36
|
+
toolName,
|
|
37
|
+
status,
|
|
38
|
+
startedAt: started?.created_at,
|
|
39
|
+
completedAt: finished?.created_at,
|
|
40
|
+
args,
|
|
41
|
+
output,
|
|
42
|
+
error,
|
|
43
|
+
argsText: argsSlice?.text,
|
|
44
|
+
outputText: outputSlice?.text,
|
|
45
|
+
argsTruncation: argsSlice,
|
|
46
|
+
outputTruncation: outputSlice,
|
|
47
|
+
events: matching.map((row) => ({ streamId: row.stream_id, type: row.type, eventId: row.event_id ?? undefined, createdAt: row.created_at })),
|
|
48
|
+
nextCommands: [
|
|
49
|
+
`pibo debug tool ${piboSessionId} ${toolCallId} --output --no-truncate`,
|
|
50
|
+
`pibo debug tool ${piboSessionId} ${toolCallId} --args --no-truncate`,
|
|
51
|
+
finished ? `pibo debug events ${piboSessionId} show ${finished.stream_id} --payload` : undefined,
|
|
52
|
+
].filter((command) => Boolean(command)),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
throw withStorePath(error, store);
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
db.close();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export function formatDebugTool(result, options = {}) {
|
|
63
|
+
if (!result.toolCallId)
|
|
64
|
+
return [`tool: not found`, ...formatNextCommands(result.nextCommands)].join("\n");
|
|
65
|
+
const lines = [];
|
|
66
|
+
lines.push(`toolCallId: ${result.toolCallId}`);
|
|
67
|
+
if (result.toolName)
|
|
68
|
+
lines.push(`toolName: ${result.toolName}`);
|
|
69
|
+
if (result.status)
|
|
70
|
+
lines.push(`status: ${result.status}`);
|
|
71
|
+
if (result.startedAt)
|
|
72
|
+
lines.push(`startedAt: ${result.startedAt}`);
|
|
73
|
+
if (result.completedAt)
|
|
74
|
+
lines.push(`completedAt: ${result.completedAt}`);
|
|
75
|
+
lines.push("");
|
|
76
|
+
lines.push("Events:");
|
|
77
|
+
for (const event of result.events)
|
|
78
|
+
lines.push(` ${event.streamId}\t${event.type}\t${event.eventId ?? ""}\t${event.createdAt}`);
|
|
79
|
+
if ((options.args || !options.output) && result.argsText !== undefined) {
|
|
80
|
+
lines.push("");
|
|
81
|
+
lines.push("Args:");
|
|
82
|
+
lines.push(result.argsText);
|
|
83
|
+
if (result.argsTruncation)
|
|
84
|
+
lines.push(...formatTruncationFooter(result.argsTruncation, {
|
|
85
|
+
full: `pibo debug tool ${result.piboSessionId} ${result.toolCallId} --args --no-truncate`,
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
if ((options.output || options.error || !options.args) && result.outputText !== undefined) {
|
|
89
|
+
lines.push("");
|
|
90
|
+
lines.push(options.error ? "Error / output:" : "Output preview:");
|
|
91
|
+
lines.push(result.outputText);
|
|
92
|
+
if (result.outputTruncation)
|
|
93
|
+
lines.push(...formatTruncationFooter(result.outputTruncation, {
|
|
94
|
+
full: `pibo debug tool ${result.piboSessionId} ${result.toolCallId} --output --no-truncate`,
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
lines.push(...formatNextCommands(result.nextCommands));
|
|
98
|
+
return lines.join("\n");
|
|
99
|
+
}
|
|
100
|
+
function emptyTool(piboSessionId, selector) {
|
|
101
|
+
return { piboSessionId, resultType: "debug.tool", selector, events: [], nextCommands: [`pibo debug events ${piboSessionId} --type tool_execution_finished --limit 20`] };
|
|
102
|
+
}
|
|
103
|
+
function toolCallIdFromRow(row) {
|
|
104
|
+
const payload = eventPayload(row);
|
|
105
|
+
const attributes = eventAttributes(row);
|
|
106
|
+
return typeof payload.toolCallId === "string" ? payload.toolCallId : typeof attributes.toolCallId === "string" ? attributes.toolCallId : undefined;
|
|
107
|
+
}
|
|
108
|
+
function toolNameFromRow(row) {
|
|
109
|
+
const payload = eventPayload(row);
|
|
110
|
+
const attributes = eventAttributes(row);
|
|
111
|
+
return typeof payload.toolName === "string" ? payload.toolName : typeof attributes.toolName === "string" ? attributes.toolName : row.preview_text ?? undefined;
|
|
112
|
+
}
|
|
113
|
+
function argsFromRow(row) {
|
|
114
|
+
const payload = eventPayload(row);
|
|
115
|
+
if ("args" in payload)
|
|
116
|
+
return payload.args;
|
|
117
|
+
if (row.type === "tool_call" || row.type === "tool_execution_started")
|
|
118
|
+
return eventAttributes(row).inlinePayload;
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
function outputFromRow(row) {
|
|
122
|
+
const payload = eventPayload(row);
|
|
123
|
+
if ("result" in payload)
|
|
124
|
+
return payload.result;
|
|
125
|
+
if ("partialResult" in payload)
|
|
126
|
+
return payload.partialResult;
|
|
127
|
+
if (row.type === "tool_execution_finished" || row.type === "tool_execution_updated")
|
|
128
|
+
return eventAttributes(row).inlinePayload;
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
function errorFromRow(row) {
|
|
132
|
+
const payload = eventPayload(row);
|
|
133
|
+
if (typeof payload.error === "string")
|
|
134
|
+
return payload.error;
|
|
135
|
+
const result = payload.result;
|
|
136
|
+
if (result && typeof result === "object" && !Array.isArray(result)) {
|
|
137
|
+
const record = result;
|
|
138
|
+
if (typeof record.error === "string")
|
|
139
|
+
return record.error;
|
|
140
|
+
}
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
function statusFromRows(rows, finished) {
|
|
144
|
+
if (!finished)
|
|
145
|
+
return rows.some((row) => row.type === "tool_execution_started") ? "running" : "started";
|
|
146
|
+
const payload = eventPayload(finished);
|
|
147
|
+
if (payload.isError === true)
|
|
148
|
+
return "error";
|
|
149
|
+
const result = payload.result;
|
|
150
|
+
if (result && typeof result === "object" && !Array.isArray(result)) {
|
|
151
|
+
const details = result.details;
|
|
152
|
+
if (details && typeof details === "object" && !Array.isArray(details) && typeof details.status === "string")
|
|
153
|
+
return String(details.status);
|
|
154
|
+
if (typeof result.status === "string")
|
|
155
|
+
return String(result.status);
|
|
156
|
+
}
|
|
157
|
+
return "completed";
|
|
158
|
+
}
|
|
159
|
+
function firstDefined(values) {
|
|
160
|
+
return values.find((value) => value !== undefined && value !== null);
|
|
161
|
+
}
|
|
162
|
+
function firstString(values) {
|
|
163
|
+
return values.find((value) => Boolean(value));
|
|
164
|
+
}
|
|
165
|
+
function tableExists(db, table) {
|
|
166
|
+
const row = db.prepare("SELECT name FROM sqlite_schema WHERE type = 'table' AND name = ?").get(table);
|
|
167
|
+
return row !== undefined;
|
|
168
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Trace Render Consistency Check
|
|
4
|
+
*
|
|
5
|
+
* Loads frontend snapshots, calls the backend replay API, applies the
|
|
6
|
+
* frontend transformations, and compares the visible row ids.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* npx tsx src/debug/trace-render-check.ts --snapshots snapshots.json --api http://localhost:3000/api/chat/debug/trace-at-sequence
|
|
10
|
+
*/
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
import { adaptTrace } from "../apps/chat-ui/src/tracing/adapt.js";
|
|
13
|
+
import { processSpanTree } from "../apps/chat-ui/src/tracing/traceTree.js";
|
|
14
|
+
function parseArgs() {
|
|
15
|
+
const args = process.argv.slice(2);
|
|
16
|
+
let snapshotsPath = "trace-snapshots.json";
|
|
17
|
+
let apiBaseUrl = "http://localhost:3000/api/chat/debug/trace-at-sequence";
|
|
18
|
+
let piboSessionId;
|
|
19
|
+
for (let i = 0; i < args.length; i++) {
|
|
20
|
+
if (args[i] === "--snapshots" && args[i + 1])
|
|
21
|
+
snapshotsPath = args[i + 1];
|
|
22
|
+
if (args[i] === "--api" && args[i + 1])
|
|
23
|
+
apiBaseUrl = args[i + 1];
|
|
24
|
+
if (args[i] === "--session" && args[i + 1])
|
|
25
|
+
piboSessionId = args[i + 1];
|
|
26
|
+
}
|
|
27
|
+
return { snapshotsPath, apiBaseUrl, piboSessionId };
|
|
28
|
+
}
|
|
29
|
+
function loadSnapshots(path) {
|
|
30
|
+
const raw = readFileSync(path, "utf8");
|
|
31
|
+
const parsed = JSON.parse(raw);
|
|
32
|
+
if (typeof parsed.piboSessionId === "string" && Array.isArray(parsed.snapshots)) {
|
|
33
|
+
return { [parsed.piboSessionId]: parsed.snapshots };
|
|
34
|
+
}
|
|
35
|
+
return parsed;
|
|
36
|
+
}
|
|
37
|
+
async function replayTraceAtSequence(apiBaseUrl, piboSessionId, eventSequence) {
|
|
38
|
+
const response = await fetch(apiBaseUrl, {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: { "Content-Type": "application/json" },
|
|
41
|
+
body: JSON.stringify({ piboSessionId, eventSequence }),
|
|
42
|
+
});
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
throw new Error(`Replay API error: ${response.status} ${await response.text()}`);
|
|
45
|
+
}
|
|
46
|
+
return response.json();
|
|
47
|
+
}
|
|
48
|
+
function filterThinking(spans, showThinking) {
|
|
49
|
+
if (showThinking)
|
|
50
|
+
return spans;
|
|
51
|
+
return spans.filter((span) => span.spanType !== "model.reasoning");
|
|
52
|
+
}
|
|
53
|
+
function isExpandedAtDepth(depth, expansionDepth) {
|
|
54
|
+
if (expansionDepth === "all")
|
|
55
|
+
return true;
|
|
56
|
+
return depth < expansionDepth;
|
|
57
|
+
}
|
|
58
|
+
function flattenVisibleSpans(spans, expansionDepth, expandThinking, expansionOverrides, depth = 0) {
|
|
59
|
+
const rows = [];
|
|
60
|
+
for (const span of spans) {
|
|
61
|
+
const defaultExpanded = isExpandedAtDepth(depth, expansionDepth);
|
|
62
|
+
const override = expansionOverrides[span.id];
|
|
63
|
+
const contentExpanded = override?.contentExpanded ?? (span.spanType === "model.reasoning" ? expandThinking : defaultExpanded);
|
|
64
|
+
const childrenExpanded = override?.childrenExpanded ?? defaultExpanded;
|
|
65
|
+
rows.push({ id: span.id, span, depth });
|
|
66
|
+
if (span.children?.length && contentExpanded && childrenExpanded) {
|
|
67
|
+
rows.push(...flattenVisibleSpans(span.children, expansionDepth, expandThinking, expansionOverrides, depth + 1));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return rows;
|
|
71
|
+
}
|
|
72
|
+
function simulateFrontend(view, expandThinking = true) {
|
|
73
|
+
const trace = adaptTrace(view.piboSessionId, view.title, view.nodes);
|
|
74
|
+
const tree = processSpanTree(filterThinking(trace.spans, expandThinking));
|
|
75
|
+
const rows = flattenVisibleSpans(tree, "all", expandThinking, {});
|
|
76
|
+
return rows.map((r) => r.id);
|
|
77
|
+
}
|
|
78
|
+
function findFirstMismatch(actual, expected) {
|
|
79
|
+
const len = Math.max(actual.length, expected.length);
|
|
80
|
+
for (let i = 0; i < len; i++) {
|
|
81
|
+
if (actual[i] !== expected[i]) {
|
|
82
|
+
return { index: i, actual: actual[i] ?? "<missing>", expected: expected[i] ?? "<missing>" };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
async function checkSession(apiBaseUrl, piboSessionId, snapshots) {
|
|
88
|
+
let checked = 0;
|
|
89
|
+
let mismatches = 0;
|
|
90
|
+
let errors = 0;
|
|
91
|
+
for (const snapshot of snapshots) {
|
|
92
|
+
const visibleLayer = snapshot.layers.find((l) => l.kind === "visibleRows");
|
|
93
|
+
if (!visibleLayer)
|
|
94
|
+
continue;
|
|
95
|
+
const backendLayer = snapshot.layers.find((l) => l.kind === "backendNodes");
|
|
96
|
+
const frontendIds = visibleLayer.ids;
|
|
97
|
+
// Use the available snapshot size as a coarse replay point. This keeps
|
|
98
|
+
// the checker useful even when a snapshot trigger has no explicit
|
|
99
|
+
// event sequence.
|
|
100
|
+
try {
|
|
101
|
+
const lastEventSequence = backendLayer ? backendLayer.ids.length : frontendIds.length;
|
|
102
|
+
const replayed = await replayTraceAtSequence(apiBaseUrl, piboSessionId, lastEventSequence);
|
|
103
|
+
const simulatedIds = simulateFrontend(replayed);
|
|
104
|
+
const mismatch = findFirstMismatch(frontendIds, simulatedIds);
|
|
105
|
+
if (mismatch) {
|
|
106
|
+
mismatches++;
|
|
107
|
+
console.error(`\n[MISMATCH] ${piboSessionId} @ ${new Date(snapshot.timestamp).toISOString()}`);
|
|
108
|
+
console.error(` Trigger: ${snapshot.trigger}`);
|
|
109
|
+
console.error(` First diff at index ${mismatch.index}:`);
|
|
110
|
+
console.error(` Frontend: ${mismatch.actual}`);
|
|
111
|
+
console.error(` Backend+Sim: ${mismatch.expected}`);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
checked++;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (caught) {
|
|
118
|
+
errors++;
|
|
119
|
+
console.error(`\n[ERROR] ${piboSessionId} @ ${new Date(snapshot.timestamp).toISOString()}: ${caught}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return { checked, mismatches, errors };
|
|
123
|
+
}
|
|
124
|
+
async function main() {
|
|
125
|
+
const options = parseArgs();
|
|
126
|
+
const allSnapshots = loadSnapshots(options.snapshotsPath);
|
|
127
|
+
const sessions = options.piboSessionId ? { [options.piboSessionId]: allSnapshots[options.piboSessionId] ?? [] } : allSnapshots;
|
|
128
|
+
console.log(`Trace Render Consistency Check`);
|
|
129
|
+
console.log(`Snapshots: ${options.snapshotsPath}`);
|
|
130
|
+
console.log(`API: ${options.apiBaseUrl}`);
|
|
131
|
+
console.log(`Sessions: ${Object.keys(sessions).length}\n`);
|
|
132
|
+
let totalChecked = 0;
|
|
133
|
+
let totalMismatches = 0;
|
|
134
|
+
let totalErrors = 0;
|
|
135
|
+
for (const [piboSessionId, snapshots] of Object.entries(sessions)) {
|
|
136
|
+
if (!snapshots.length)
|
|
137
|
+
continue;
|
|
138
|
+
console.log(`Checking session ${piboSessionId} (${snapshots.length} snapshots)...`);
|
|
139
|
+
const result = await checkSession(options.apiBaseUrl, piboSessionId, snapshots);
|
|
140
|
+
totalChecked += result.checked;
|
|
141
|
+
totalMismatches += result.mismatches;
|
|
142
|
+
totalErrors += result.errors;
|
|
143
|
+
console.log(` OK: ${result.checked}, Mismatch: ${result.mismatches}, Error: ${result.errors}`);
|
|
144
|
+
}
|
|
145
|
+
console.log(`\nTotal: ${totalChecked} OK, ${totalMismatches} mismatches, ${totalErrors} errors`);
|
|
146
|
+
process.exit(totalMismatches > 0 || totalErrors > 0 ? 1 : 0);
|
|
147
|
+
}
|
|
148
|
+
main().catch((err) => {
|
|
149
|
+
console.error(err);
|
|
150
|
+
process.exit(1);
|
|
151
|
+
});
|
package/dist/debug/trace.js
CHANGED
|
@@ -1,32 +1,31 @@
|
|
|
1
1
|
import { buildTraceView } from "../apps/chat/trace.js";
|
|
2
|
+
import { normalizeSessionErrorDetails } from "../core/session-errors.js";
|
|
2
3
|
import { compareTraceOrder } from "../shared/trace-order.js";
|
|
3
4
|
import { openReadOnlyDebugDatabase, withStorePath } from "./sql.js";
|
|
5
|
+
import { formatNextCommands } from "./next-commands.js";
|
|
4
6
|
export async function inspectDebugTrace(piboSessionId, stores, options = {}) {
|
|
5
7
|
if (!stores.sessions.exists)
|
|
6
|
-
throw new Error(`Debug store "sessions" not found at ${stores.sessions.
|
|
8
|
+
throw new Error(`Debug store "sessions" not found at ${stores.sessions.path}`);
|
|
7
9
|
if (!stores.chat.exists)
|
|
8
|
-
throw new Error(`Debug store "chat" not found at ${stores.chat.
|
|
10
|
+
throw new Error(`Debug store "chat" not found at ${stores.chat.path}`);
|
|
9
11
|
const sessionsDb = openReadOnlyDebugDatabase(stores.sessions);
|
|
10
|
-
const chatDb = openReadOnlyDebugDatabase(stores.chat);
|
|
12
|
+
const chatDb = stores.chat.path === stores.sessions.path ? sessionsDb : openReadOnlyDebugDatabase(stores.chat);
|
|
11
13
|
try {
|
|
12
|
-
const sessionRow = sessionsDb.prepare("SELECT * FROM
|
|
14
|
+
const sessionRow = sessionsDb.prepare("SELECT * FROM sessions WHERE id = ?").get(piboSessionId);
|
|
13
15
|
if (!sessionRow)
|
|
14
16
|
throw new Error(`Pibo session "${piboSessionId}" not found`);
|
|
15
17
|
const session = sessionFromRow(sessionRow);
|
|
16
|
-
const sessions = sessionsDb.prepare("SELECT * FROM
|
|
17
|
-
const
|
|
18
|
-
? chatDb.prepare("SELECT status FROM web_chat_sessions WHERE pibo_session_id = ?").get(piboSessionId)
|
|
19
|
-
: undefined;
|
|
20
|
-
const events = tableExists(chatDb, "web_chat_events")
|
|
18
|
+
const sessions = sessionsDb.prepare("SELECT * FROM sessions").all().map(sessionFromRow);
|
|
19
|
+
const events = tableExists(chatDb, "event_log")
|
|
21
20
|
? chatDb
|
|
22
|
-
.prepare("SELECT
|
|
23
|
-
.all(piboSessionId).map(eventFromRow)
|
|
21
|
+
.prepare("SELECT stream_id, session_id, session_sequence, event_id, type, created_at, preview_text, attributes_json FROM event_log WHERE session_id = ? ORDER BY stream_id ASC")
|
|
22
|
+
.all(piboSessionId).map(eventFromRow).filter((event) => event !== undefined)
|
|
24
23
|
: [];
|
|
25
24
|
const view = await buildTraceView({
|
|
26
25
|
session,
|
|
27
26
|
sessions,
|
|
28
27
|
events,
|
|
29
|
-
status:
|
|
28
|
+
status: sessionRow.status === "running" || sessionRow.status === "error" ? sessionRow.status : "idle",
|
|
30
29
|
});
|
|
31
30
|
const rows = flattenTraceNodes(view.nodes);
|
|
32
31
|
const filtered = options.runningOnly ? rows.filter((node) => node.status === "running") : rows;
|
|
@@ -38,6 +37,7 @@ export async function inspectDebugTrace(piboSessionId, stores, options = {}) {
|
|
|
38
37
|
nodes: filtered,
|
|
39
38
|
rawNodeCount: rows.length,
|
|
40
39
|
...(options.check ? { checks: checkTraceView(view) } : {}),
|
|
40
|
+
nextCommands: buildTraceNextCommands(view.piboSessionId, filtered),
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
catch (error) {
|
|
@@ -45,10 +45,24 @@ export async function inspectDebugTrace(piboSessionId, stores, options = {}) {
|
|
|
45
45
|
}
|
|
46
46
|
finally {
|
|
47
47
|
sessionsDb.close();
|
|
48
|
-
chatDb
|
|
48
|
+
if (chatDb !== sessionsDb)
|
|
49
|
+
chatDb.close();
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
|
-
export function
|
|
52
|
+
export async function inspectDebugTraceNode(piboSessionId, stores, nodeId) {
|
|
53
|
+
const trace = await inspectDebugTrace(piboSessionId, stores, {});
|
|
54
|
+
const node = trace.nodes.find((item) => item.id === nodeId);
|
|
55
|
+
const children = trace.nodes.filter((item) => item.parentId === nodeId);
|
|
56
|
+
return {
|
|
57
|
+
piboSessionId,
|
|
58
|
+
resultType: "debug.trace.show",
|
|
59
|
+
nodeId,
|
|
60
|
+
node,
|
|
61
|
+
children,
|
|
62
|
+
nextCommands: node ? buildNodeNextCommands(piboSessionId, node) : [`pibo debug trace ${piboSessionId}`],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export function formatDebugTrace(result, options = {}) {
|
|
52
66
|
const lines = [
|
|
53
67
|
`piboSessionId: ${result.piboSessionId}`,
|
|
54
68
|
`piSessionId: ${result.piSessionId}`,
|
|
@@ -60,17 +74,25 @@ export function formatDebugTrace(result) {
|
|
|
60
74
|
lines.push("nodes: 0");
|
|
61
75
|
return lines.join("\n");
|
|
62
76
|
}
|
|
63
|
-
|
|
77
|
+
const columns = options.medium
|
|
78
|
+
? ["status", "type", "title", "id", "runId", "toolCallId", "linkedPiboSessionId", "source", "stableKey", "order"]
|
|
79
|
+
: ["status", "type", "title", "id", "runId", "linkedPiboSessionId"];
|
|
80
|
+
lines.push(columns.join("\t"));
|
|
64
81
|
for (const node of result.nodes) {
|
|
65
82
|
const title = `${" ".repeat(node.depth)}${node.title}`;
|
|
66
|
-
|
|
67
|
-
node.status,
|
|
68
|
-
node.type,
|
|
83
|
+
const values = {
|
|
84
|
+
status: node.status,
|
|
85
|
+
type: node.type,
|
|
69
86
|
title,
|
|
70
|
-
node.id,
|
|
71
|
-
node.runId
|
|
72
|
-
node.
|
|
73
|
-
|
|
87
|
+
id: node.id,
|
|
88
|
+
runId: node.runId,
|
|
89
|
+
toolCallId: node.toolCallId,
|
|
90
|
+
linkedPiboSessionId: node.linkedPiboSessionId,
|
|
91
|
+
source: node.source,
|
|
92
|
+
stableKey: node.stableKey,
|
|
93
|
+
order: node.order,
|
|
94
|
+
};
|
|
95
|
+
lines.push(columns.map((column) => values[column] ?? "").join("\t"));
|
|
74
96
|
}
|
|
75
97
|
lines.push(`nodes: ${result.nodes.length}${result.nodes.length !== result.rawNodeCount ? ` of ${result.rawNodeCount}` : ""}`);
|
|
76
98
|
if (result.checks) {
|
|
@@ -82,6 +104,38 @@ export function formatDebugTrace(result) {
|
|
|
82
104
|
if (result.checks.issues.length === 0)
|
|
83
105
|
lines.push("issues: 0");
|
|
84
106
|
}
|
|
107
|
+
lines.push(...formatNextCommands(result.nextCommands ?? []));
|
|
108
|
+
return lines.join("\n");
|
|
109
|
+
}
|
|
110
|
+
export function formatDebugTraceNode(result) {
|
|
111
|
+
if (!result.node)
|
|
112
|
+
return [`node: not found`, ...formatNextCommands(result.nextCommands)].join("\n");
|
|
113
|
+
const node = result.node;
|
|
114
|
+
const lines = [];
|
|
115
|
+
lines.push(`nodeId: ${node.id}`);
|
|
116
|
+
lines.push(`type: ${node.type}`);
|
|
117
|
+
lines.push(`title: ${node.title}`);
|
|
118
|
+
lines.push(`status: ${node.status}`);
|
|
119
|
+
if (node.parentId)
|
|
120
|
+
lines.push(`parentId: ${node.parentId}`);
|
|
121
|
+
if (node.startedAt)
|
|
122
|
+
lines.push(`startedAt: ${node.startedAt}`);
|
|
123
|
+
if (node.completedAt)
|
|
124
|
+
lines.push(`completedAt: ${node.completedAt}`);
|
|
125
|
+
if (node.source)
|
|
126
|
+
lines.push(`source: ${node.source}`);
|
|
127
|
+
if (node.stableKey)
|
|
128
|
+
lines.push(`stableKey: ${node.stableKey}`);
|
|
129
|
+
if (node.order)
|
|
130
|
+
lines.push(`order: ${node.order}`);
|
|
131
|
+
lines.push(`children: ${result.children.length}`);
|
|
132
|
+
if (node.linkedPiboSessionId)
|
|
133
|
+
lines.push(`linkedPiboSessionId: ${node.linkedPiboSessionId}`);
|
|
134
|
+
if (node.runId)
|
|
135
|
+
lines.push(`runId: ${node.runId}`);
|
|
136
|
+
if (node.toolCallId)
|
|
137
|
+
lines.push(`toolCallId: ${node.toolCallId}`);
|
|
138
|
+
lines.push(...formatNextCommands(result.nextCommands));
|
|
85
139
|
return lines.join("\n");
|
|
86
140
|
}
|
|
87
141
|
function flattenTraceNodes(nodes, depth = 0) {
|
|
@@ -91,6 +145,7 @@ function flattenTraceNodes(nodes, depth = 0) {
|
|
|
91
145
|
type: node.type,
|
|
92
146
|
title: node.title,
|
|
93
147
|
id: node.id,
|
|
148
|
+
parentId: node.parentId,
|
|
94
149
|
runId: node.runId,
|
|
95
150
|
toolCallId: node.toolCallId,
|
|
96
151
|
linkedPiboSessionId: node.linkedPiboSessionId,
|
|
@@ -99,6 +154,7 @@ function flattenTraceNodes(nodes, depth = 0) {
|
|
|
99
154
|
order: formatOrderKey(node),
|
|
100
155
|
startedAt: node.startedAt,
|
|
101
156
|
completedAt: node.completedAt,
|
|
157
|
+
childrenCount: node.children.length,
|
|
102
158
|
depth,
|
|
103
159
|
},
|
|
104
160
|
...flattenTraceNodes(node.children, depth + 1),
|
|
@@ -184,6 +240,24 @@ function compareOrder(left, right) {
|
|
|
184
240
|
function flattenPiboTraceNodes(nodes) {
|
|
185
241
|
return nodes.flatMap((node) => [node, ...flattenPiboTraceNodes(node.children)]);
|
|
186
242
|
}
|
|
243
|
+
function buildTraceNextCommands(piboSessionId, nodes) {
|
|
244
|
+
const errorNode = nodes.find((node) => node.status === "error");
|
|
245
|
+
const firstNode = nodes[0];
|
|
246
|
+
return [
|
|
247
|
+
errorNode ? `pibo debug trace ${piboSessionId} show ${errorNode.id}` : firstNode ? `pibo debug trace ${piboSessionId} show ${firstNode.id}` : undefined,
|
|
248
|
+
nodes.some((node) => node.status === "error") ? `pibo debug failures ${piboSessionId}` : undefined,
|
|
249
|
+
`pibo debug messages ${piboSessionId} list`,
|
|
250
|
+
].filter((command) => Boolean(command));
|
|
251
|
+
}
|
|
252
|
+
function buildNodeNextCommands(piboSessionId, node) {
|
|
253
|
+
return [
|
|
254
|
+
node.toolCallId ? `pibo debug tool ${piboSessionId} ${node.toolCallId}` : undefined,
|
|
255
|
+
node.linkedPiboSessionId ? `pibo debug session ${node.linkedPiboSessionId}` : undefined,
|
|
256
|
+
node.linkedPiboSessionId ? `pibo debug trace ${node.linkedPiboSessionId}` : undefined,
|
|
257
|
+
`pibo debug trace ${piboSessionId} --medium`,
|
|
258
|
+
`pibo debug events ${piboSessionId} --limit 20`,
|
|
259
|
+
].filter((command) => Boolean(command));
|
|
260
|
+
}
|
|
187
261
|
function formatOrderKey(node) {
|
|
188
262
|
const order = node.orderKey;
|
|
189
263
|
if (!order)
|
|
@@ -205,7 +279,6 @@ function sessionFromRow(row) {
|
|
|
205
279
|
channel: row.channel,
|
|
206
280
|
kind: row.kind,
|
|
207
281
|
profile: row.profile,
|
|
208
|
-
ownerScope: row.owner_scope ?? undefined,
|
|
209
282
|
parentId: row.parent_id ?? undefined,
|
|
210
283
|
originId: row.origin_id ?? undefined,
|
|
211
284
|
workspace: row.workspace ?? undefined,
|
|
@@ -216,16 +289,68 @@ function sessionFromRow(row) {
|
|
|
216
289
|
};
|
|
217
290
|
}
|
|
218
291
|
function eventFromRow(row) {
|
|
292
|
+
const payload = outputPayloadFromV2Row(row);
|
|
293
|
+
if (!payload)
|
|
294
|
+
return undefined;
|
|
219
295
|
return {
|
|
220
|
-
id: row.
|
|
221
|
-
piboSessionId: row.
|
|
222
|
-
eventSequence: row.
|
|
296
|
+
id: String(row.stream_id),
|
|
297
|
+
piboSessionId: row.session_id ?? undefined,
|
|
298
|
+
eventSequence: row.session_sequence ?? undefined,
|
|
223
299
|
eventId: row.event_id ?? undefined,
|
|
300
|
+
streamId: row.stream_id,
|
|
224
301
|
type: row.type,
|
|
225
302
|
createdAt: row.created_at,
|
|
226
|
-
payload
|
|
303
|
+
payload,
|
|
227
304
|
};
|
|
228
305
|
}
|
|
306
|
+
function outputPayloadFromV2Row(row) {
|
|
307
|
+
const attributes = parseObject(row.attributes_json);
|
|
308
|
+
const inlinePayload = attributes.inlinePayload;
|
|
309
|
+
if (inlinePayload && typeof inlinePayload === "object" && !Array.isArray(inlinePayload) && typeof inlinePayload.type === "string") {
|
|
310
|
+
return inlinePayload;
|
|
311
|
+
}
|
|
312
|
+
const piboSessionId = row.session_id;
|
|
313
|
+
if (!piboSessionId)
|
|
314
|
+
return undefined;
|
|
315
|
+
const base = { piboSessionId, eventId: row.event_id ?? undefined };
|
|
316
|
+
if (row.type === "assistant_message")
|
|
317
|
+
return compactObject({ ...base, type: "assistant_message", text: row.preview_text ?? "" });
|
|
318
|
+
if (row.type === "message_started")
|
|
319
|
+
return compactObject({ ...base, type: "message_started", text: row.preview_text ?? "" });
|
|
320
|
+
if (row.type === "message_finished")
|
|
321
|
+
return compactObject({ ...base, type: "message_finished" });
|
|
322
|
+
if (row.type === "thinking_started")
|
|
323
|
+
return compactObject({ ...base, type: "thinking_started" });
|
|
324
|
+
if (row.type === "thinking_finished")
|
|
325
|
+
return compactObject({ ...base, type: "thinking_finished", text: row.preview_text ?? "" });
|
|
326
|
+
if (row.type === "tool_call")
|
|
327
|
+
return compactObject({ ...base, type: "tool_call", toolCallId: stringAttribute(attributes, "toolCallId") ?? row.event_id ?? `tool_${row.stream_id}`, toolName: row.preview_text ?? stringAttribute(attributes, "toolName") ?? "tool", args: inlinePayload ?? null, argsComplete: booleanAttribute(attributes, "argsComplete") ?? true });
|
|
328
|
+
if (row.type === "tool_execution_started")
|
|
329
|
+
return compactObject({ ...base, type: "tool_execution_started", toolCallId: stringAttribute(attributes, "toolCallId") ?? row.event_id ?? `tool_${row.stream_id}`, toolName: row.preview_text ?? stringAttribute(attributes, "toolName") ?? "tool", args: inlinePayload ?? null });
|
|
330
|
+
if (row.type === "tool_execution_updated")
|
|
331
|
+
return compactObject({ ...base, type: "tool_execution_updated", toolCallId: stringAttribute(attributes, "toolCallId") ?? row.event_id ?? `tool_${row.stream_id}`, toolName: row.preview_text ?? stringAttribute(attributes, "toolName") ?? "tool", args: null, partialResult: inlinePayload ?? null });
|
|
332
|
+
if (row.type === "tool_execution_finished")
|
|
333
|
+
return compactObject({ ...base, type: "tool_execution_finished", toolCallId: stringAttribute(attributes, "toolCallId") ?? row.event_id ?? `tool_${row.stream_id}`, toolName: row.preview_text ?? stringAttribute(attributes, "toolName") ?? "tool", result: inlinePayload ?? null, isError: booleanAttribute(attributes, "isError") ?? false });
|
|
334
|
+
if (row.type === "session_error") {
|
|
335
|
+
const error = stringAttribute(attributes, "error") ?? row.preview_text ?? "Error";
|
|
336
|
+
return compactObject({ ...base, type: "session_error", error, errorDetails: normalizeSessionErrorDetails(error, isRecord(attributes.errorDetails) ? attributes.errorDetails : undefined) });
|
|
337
|
+
}
|
|
338
|
+
return compactObject({ ...base, type: row.type });
|
|
339
|
+
}
|
|
340
|
+
function stringAttribute(attributes, key) {
|
|
341
|
+
const value = attributes[key];
|
|
342
|
+
return typeof value === "string" ? value : undefined;
|
|
343
|
+
}
|
|
344
|
+
function booleanAttribute(attributes, key) {
|
|
345
|
+
const value = attributes[key];
|
|
346
|
+
return typeof value === "boolean" ? value : undefined;
|
|
347
|
+
}
|
|
348
|
+
function isRecord(value) {
|
|
349
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
350
|
+
}
|
|
351
|
+
function compactObject(value) {
|
|
352
|
+
return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
|
|
353
|
+
}
|
|
229
354
|
function tableExists(db, table) {
|
|
230
355
|
const row = db.prepare("SELECT name FROM sqlite_schema WHERE type = 'table' AND name = ?").get(table);
|
|
231
356
|
return row !== undefined;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { getPiboHome } from "../core/pibo-home.js";
|
|
4
|
+
const STDOUT_BUDGET = 12_000;
|
|
5
|
+
export async function writeLastSnapshot(snapshot) {
|
|
6
|
+
if (!snapshot)
|
|
7
|
+
return;
|
|
8
|
+
const file = lastSnapshotPath();
|
|
9
|
+
await mkdir(path.dirname(file), { recursive: true });
|
|
10
|
+
await writeFile(file, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
11
|
+
}
|
|
12
|
+
export async function readBaselineSnapshot(file) {
|
|
13
|
+
const target = file ?? lastSnapshotPath();
|
|
14
|
+
let text;
|
|
15
|
+
try {
|
|
16
|
+
text = await readFile(target, "utf-8");
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
throw new Error(`Baseline snapshot not found at ${target}. Run pibo debug web snapshot first or pass --from <artifact>.`);
|
|
20
|
+
}
|
|
21
|
+
const parsed = JSON.parse(text);
|
|
22
|
+
if (isSnapshot(parsed))
|
|
23
|
+
return parsed;
|
|
24
|
+
if (isRecord(parsed) && isSnapshot(parsed.snapshot))
|
|
25
|
+
return parsed.snapshot;
|
|
26
|
+
if (isRecord(parsed) && isSnapshot(parsed.current))
|
|
27
|
+
return parsed.current;
|
|
28
|
+
throw new Error(`File is not a web render snapshot: ${target}`);
|
|
29
|
+
}
|
|
30
|
+
export async function writeArtifact(kind, payload) {
|
|
31
|
+
return writeTextArtifact(kind, "json", JSON.stringify(payload, null, 2));
|
|
32
|
+
}
|
|
33
|
+
export async function writeTextArtifact(kind, extension, content) {
|
|
34
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
35
|
+
const dir = path.join(getPiboHome(), "debug", "web-render", stamp);
|
|
36
|
+
await mkdir(dir, { recursive: true });
|
|
37
|
+
const file = path.join(dir, `${kind}.${extension}`);
|
|
38
|
+
await writeFile(file, content, "utf-8");
|
|
39
|
+
return file;
|
|
40
|
+
}
|
|
41
|
+
export async function writeReportOutput(outputPath, content) {
|
|
42
|
+
const file = path.resolve(outputPath);
|
|
43
|
+
await mkdir(path.dirname(file), { recursive: true });
|
|
44
|
+
await writeFile(file, content, "utf-8");
|
|
45
|
+
return file;
|
|
46
|
+
}
|
|
47
|
+
export function compactTarget(target) {
|
|
48
|
+
return { id: target.id, url: target.url, title: target.title, webSocketDebuggerUrl: target.webSocketDebuggerUrl };
|
|
49
|
+
}
|
|
50
|
+
export function limitStdout(value) {
|
|
51
|
+
if (value.length <= STDOUT_BUDGET)
|
|
52
|
+
return value;
|
|
53
|
+
return `${value.slice(0, STDOUT_BUDGET)}\n... truncated ${value.length - STDOUT_BUDGET} chars by stdout budget ...`;
|
|
54
|
+
}
|
|
55
|
+
function lastSnapshotPath() {
|
|
56
|
+
return path.join(getPiboHome(), "debug", "web-render", "last-snapshot.json");
|
|
57
|
+
}
|
|
58
|
+
function isSnapshot(value) {
|
|
59
|
+
return isRecord(value) && value.kind === "snapshot" && typeof value.scope === "string" && Array.isArray(value.nodes);
|
|
60
|
+
}
|
|
61
|
+
function isRecord(value) {
|
|
62
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
63
|
+
}
|