@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,348 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { PiboWebHttpError, readJsonBody, responseJson } from "../web/http.js";
|
|
3
|
+
import { buildWebAnnotationOverlayScript, createWebAnnotationCdpService } from "./cdp.js";
|
|
4
|
+
import { serializeWebAnnotationAttachment } from "./attachments.js";
|
|
5
|
+
import { createDefaultWebAnnotationStore } from "./store.js";
|
|
6
|
+
import { isWebAnnotationStatus, isWebAnnotationTargetKind } from "./types.js";
|
|
7
|
+
import { assertWebAnnotationStatusTransition, normalizeWebAnnotationLimit, normalizeWebAnnotationScreenshotRef, normalizeWebAnnotationTarget, normalizeWebAnnotationViewport, requireWebAnnotationText, sanitizeWebAnnotationText, WEB_ANNOTATION_LIMITS, } from "./validation.js";
|
|
8
|
+
export const WEB_ANNOTATIONS_API_PREFIX = "/api/web-annotations";
|
|
9
|
+
export const WEB_ANNOTATIONS_APP_MOUNT = "/apps/web-annotations";
|
|
10
|
+
let defaultStore;
|
|
11
|
+
function getDefaultStore() {
|
|
12
|
+
defaultStore ??= createDefaultWebAnnotationStore();
|
|
13
|
+
return defaultStore;
|
|
14
|
+
}
|
|
15
|
+
function createSameOriginBinding(store, request, context, body) {
|
|
16
|
+
const bindingToken = randomBytes(24).toString("base64url");
|
|
17
|
+
const binding = store.createBinding({
|
|
18
|
+
...context,
|
|
19
|
+
url: normalizeSameOriginBindingUrl(request, body.url),
|
|
20
|
+
title: optionalBodyString(body.title, WEB_ANNOTATION_LIMITS.title),
|
|
21
|
+
state: "active",
|
|
22
|
+
metadata: { source: "same-origin", overlaySubmissionToken: bindingToken },
|
|
23
|
+
});
|
|
24
|
+
return {
|
|
25
|
+
binding,
|
|
26
|
+
overlay: {
|
|
27
|
+
bindingId: binding.id,
|
|
28
|
+
bindingToken,
|
|
29
|
+
piboSessionId: binding.piboSessionId,
|
|
30
|
+
annotationShortcut: optionalBodyString(body.annotationShortcut, 80, false),
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function createWebAnnotationsWebApp(options = {}) {
|
|
35
|
+
const store = options.store ?? getDefaultStore();
|
|
36
|
+
const baseService = options.cdpService ?? createWebAnnotationCdpService({ store });
|
|
37
|
+
return {
|
|
38
|
+
name: "web-annotations",
|
|
39
|
+
mountPath: WEB_ANNOTATIONS_APP_MOUNT,
|
|
40
|
+
apiPrefix: WEB_ANNOTATIONS_API_PREFIX,
|
|
41
|
+
async handleRequest(request, context) {
|
|
42
|
+
const url = new URL(request.url);
|
|
43
|
+
if (url.pathname === `${WEB_ANNOTATIONS_APP_MOUNT}/overlay.js` && request.method === "GET") {
|
|
44
|
+
return responseJavaScript(buildWebAnnotationOverlayScript(), { headers: { "cache-control": "no-store" } });
|
|
45
|
+
}
|
|
46
|
+
if (url.pathname === WEB_ANNOTATIONS_APP_MOUNT && request.method === "GET") {
|
|
47
|
+
return responseJson({ ok: true, apiPrefix: WEB_ANNOTATIONS_API_PREFIX });
|
|
48
|
+
}
|
|
49
|
+
if (!url.pathname.startsWith(WEB_ANNOTATIONS_API_PREFIX))
|
|
50
|
+
return undefined;
|
|
51
|
+
try {
|
|
52
|
+
if (url.pathname === `${WEB_ANNOTATIONS_API_PREFIX}/submissions` && request.method === "OPTIONS") {
|
|
53
|
+
return corsResponse(null, { status: 204 });
|
|
54
|
+
}
|
|
55
|
+
if (url.pathname === `${WEB_ANNOTATIONS_API_PREFIX}/submissions` && request.method === "POST") {
|
|
56
|
+
const annotation = await handleOverlaySubmission(store, request);
|
|
57
|
+
return corsJson({ ok: true, annotation }, { status: 201 });
|
|
58
|
+
}
|
|
59
|
+
const webSession = await context.requireSession({ request });
|
|
60
|
+
if (url.pathname === `${WEB_ANNOTATIONS_API_PREFIX}/targets` && request.method === "GET") {
|
|
61
|
+
const service = serviceForRequest(baseService, url.searchParams.get("cdpUrl") ?? undefined, request, store, options);
|
|
62
|
+
const targets = await service.listTargets();
|
|
63
|
+
return responseJson({ ok: true, targets });
|
|
64
|
+
}
|
|
65
|
+
if (url.pathname === `${WEB_ANNOTATIONS_API_PREFIX}/bindings` && request.method === "GET") {
|
|
66
|
+
const piboSessionId = requireQueryParam(url, "piboSessionId");
|
|
67
|
+
const bindingContext = resolveBindingContext(context, webSession, { piboSessionId });
|
|
68
|
+
const bindings = baseService.listBindings(bindingContext, parseLimit(url.searchParams.get("limit")));
|
|
69
|
+
return responseJson({ ok: true, bindings });
|
|
70
|
+
}
|
|
71
|
+
if (url.pathname === `${WEB_ANNOTATIONS_API_PREFIX}/bindings` && request.method === "POST") {
|
|
72
|
+
requireSameOriginJsonRequest(request);
|
|
73
|
+
const body = await readJsonBody(request);
|
|
74
|
+
const bindingContext = resolveBindingContext(context, webSession, body);
|
|
75
|
+
const service = serviceForRequest(baseService, body.cdpUrl, request, store, options);
|
|
76
|
+
if (body.url) {
|
|
77
|
+
if (body.sameOrigin) {
|
|
78
|
+
const result = createSameOriginBinding(store, request, bindingContext, body);
|
|
79
|
+
return responseJson({ ok: true, ...result }, { status: 201 });
|
|
80
|
+
}
|
|
81
|
+
const result = await service.createUrlBinding({ ...bindingContext, url: body.url });
|
|
82
|
+
return responseJson({ ok: true, ...result }, { status: 201 });
|
|
83
|
+
}
|
|
84
|
+
if (body.targetId) {
|
|
85
|
+
const result = await service.createTargetBinding({ ...bindingContext, targetId: body.targetId });
|
|
86
|
+
return responseJson({ ok: true, ...result }, { status: 201 });
|
|
87
|
+
}
|
|
88
|
+
throw new PiboWebHttpError("url or targetId is required", 400);
|
|
89
|
+
}
|
|
90
|
+
if (url.pathname === WEB_ANNOTATIONS_API_PREFIX && request.method === "GET") {
|
|
91
|
+
const piboSessionId = requireQueryParam(url, "piboSessionId", "sessionId");
|
|
92
|
+
const bindingContext = resolveBindingContext(context, webSession, { piboSessionId });
|
|
93
|
+
const status = optionalStatus(url.searchParams.get("status"));
|
|
94
|
+
const scope = url.searchParams.get("scope") === "app" || url.searchParams.get("allSessions") === "true" ? "app" : "session";
|
|
95
|
+
const annotations = store.listAnnotations({
|
|
96
|
+
...(scope === "session" ? { piboSessionId: bindingContext.piboSessionId } : {}),
|
|
97
|
+
status,
|
|
98
|
+
limit: parseLimit(url.searchParams.get("limit")),
|
|
99
|
+
}).map(serializeWebAnnotationAttachment);
|
|
100
|
+
return responseJson({ ok: true, annotations, scope });
|
|
101
|
+
}
|
|
102
|
+
const annotationResource = matchAnnotationResource(url.pathname);
|
|
103
|
+
if (annotationResource) {
|
|
104
|
+
if (request.method === "GET") {
|
|
105
|
+
const piboSessionId = requireQueryParam(url, "piboSessionId", "sessionId");
|
|
106
|
+
const bindingContext = resolveBindingContext(context, webSession, { piboSessionId });
|
|
107
|
+
const annotation = store.getAnnotation(bindingContext.piboSessionId, annotationResource.id);
|
|
108
|
+
if (!annotation)
|
|
109
|
+
throw new PiboWebHttpError("Web Annotation was not found", 404);
|
|
110
|
+
return responseJson({ ok: true, annotation });
|
|
111
|
+
}
|
|
112
|
+
if (request.method === "PATCH") {
|
|
113
|
+
requireSameOriginJsonRequest(request);
|
|
114
|
+
const body = await readJsonBody(request);
|
|
115
|
+
const bindingContext = resolveBindingContext(context, webSession, body);
|
|
116
|
+
const status = optionalStatus(body.status);
|
|
117
|
+
const existing = store.getAnnotation(bindingContext.piboSessionId, annotationResource.id);
|
|
118
|
+
if (!existing)
|
|
119
|
+
throw new PiboWebHttpError("Web Annotation was not found", 404);
|
|
120
|
+
try {
|
|
121
|
+
assertWebAnnotationStatusTransition(existing.status, status);
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
throw new PiboWebHttpError(error instanceof Error ? error.message : String(error), 400);
|
|
125
|
+
}
|
|
126
|
+
const annotation = store.patchAnnotation(bindingContext.piboSessionId, annotationResource.id, {
|
|
127
|
+
...(status ? { status } : {}),
|
|
128
|
+
...(body.summary !== undefined ? { summary: body.summary } : {}),
|
|
129
|
+
});
|
|
130
|
+
if (!annotation)
|
|
131
|
+
throw new PiboWebHttpError("Web Annotation was not found", 404);
|
|
132
|
+
return responseJson({ ok: true, annotation: serializeWebAnnotationAttachment(annotation) });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const bindingResource = matchBindingResource(url.pathname);
|
|
136
|
+
if (bindingResource) {
|
|
137
|
+
if (request.method === "POST" && (bindingResource.action === "inject" || bindingResource.action === "reinject")) {
|
|
138
|
+
requireSameOriginJsonRequest(request);
|
|
139
|
+
const body = await readJsonBody(request);
|
|
140
|
+
const bindingContext = resolveBindingContext(context, webSession, body);
|
|
141
|
+
const service = serviceForRequest(baseService, body.cdpUrl, request, store, options);
|
|
142
|
+
const result = await service.injectBinding(bindingContext, bindingResource.id, { annotationShortcut: optionalBodyString(body.annotationShortcut, 80, false) });
|
|
143
|
+
return responseJson({ ok: true, ...result });
|
|
144
|
+
}
|
|
145
|
+
if (request.method === "POST" && bindingResource.action === "stop") {
|
|
146
|
+
requireSameOriginJsonRequest(request);
|
|
147
|
+
const body = await readJsonBody(request);
|
|
148
|
+
const bindingContext = resolveBindingContext(context, webSession, body);
|
|
149
|
+
const service = serviceForRequest(baseService, body.cdpUrl, request, store, options);
|
|
150
|
+
const result = await service.stopBinding(bindingContext, bindingResource.id);
|
|
151
|
+
return responseJson({ ok: true, ...result });
|
|
152
|
+
}
|
|
153
|
+
if (request.method === "DELETE" && !bindingResource.action) {
|
|
154
|
+
requireSameOriginRequest(request);
|
|
155
|
+
const piboSessionId = requireQueryParam(url, "piboSessionId");
|
|
156
|
+
const bindingContext = resolveBindingContext(context, webSession, { piboSessionId });
|
|
157
|
+
return responseJson({ ok: true, removed: baseService.removeBinding(bindingContext, bindingResource.id) });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
if (error instanceof PiboWebHttpError)
|
|
164
|
+
throw error;
|
|
165
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
166
|
+
throw new PiboWebHttpError(message, 400);
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
async function handleOverlaySubmission(store, request) {
|
|
172
|
+
const contentType = request.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase();
|
|
173
|
+
if (contentType !== "application/json")
|
|
174
|
+
throw new PiboWebHttpError("Content-Type must be application/json", 415);
|
|
175
|
+
const body = await readJsonBody(request);
|
|
176
|
+
const bindingId = requireBodyString(body.bindingId, "bindingId", WEB_ANNOTATION_LIMITS.id, false);
|
|
177
|
+
const bindingToken = requireBodyString(body.bindingToken, "bindingToken", WEB_ANNOTATION_LIMITS.bindingToken, false);
|
|
178
|
+
const binding = store.getBindingById(bindingId);
|
|
179
|
+
if (!binding)
|
|
180
|
+
throw new PiboWebHttpError("Web Annotation binding was not found", 404);
|
|
181
|
+
if (binding.state === "removed")
|
|
182
|
+
throw new PiboWebHttpError("Web Annotation binding was removed", 404);
|
|
183
|
+
if (binding.metadata?.overlaySubmissionToken !== bindingToken)
|
|
184
|
+
throw new PiboWebHttpError("Invalid Web Annotation binding token", 403);
|
|
185
|
+
const note = requireBodyString(body.note, "note", WEB_ANNOTATION_LIMITS.note);
|
|
186
|
+
const targetKind = requireTargetKind(body.targetKind);
|
|
187
|
+
const viewport = normalizeViewport(body.viewport);
|
|
188
|
+
return store.createAnnotation({
|
|
189
|
+
piboSessionId: binding.piboSessionId,
|
|
190
|
+
piboRoomId: binding.piboRoomId,
|
|
191
|
+
bindingId: binding.id,
|
|
192
|
+
note,
|
|
193
|
+
url: optionalBodyString(body.url, WEB_ANNOTATION_LIMITS.url, false) ?? binding.url,
|
|
194
|
+
title: optionalBodyString(body.title, WEB_ANNOTATION_LIMITS.title) ?? binding.title,
|
|
195
|
+
targetId: binding.targetId,
|
|
196
|
+
targetKind,
|
|
197
|
+
viewport,
|
|
198
|
+
target: normalizeTarget(body.target, targetKind),
|
|
199
|
+
screenshotRef: normalizeWebAnnotationScreenshotRef(body.screenshotRef),
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
function requireBodyString(value, field, max, redactSecrets = true) {
|
|
203
|
+
try {
|
|
204
|
+
return requireWebAnnotationText(value, { field, max, redactSecrets });
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
throw new PiboWebHttpError(error instanceof Error ? error.message : String(error), 400);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function optionalBodyString(value, max, redactSecrets = true) {
|
|
211
|
+
try {
|
|
212
|
+
return sanitizeWebAnnotationText(value, { field: "field", max, redactSecrets });
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
throw new PiboWebHttpError(error instanceof Error ? error.message : String(error), 400);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function normalizeSameOriginBindingUrl(request, value) {
|
|
219
|
+
const raw = requireBodyString(value, "url", WEB_ANNOTATION_LIMITS.url, false);
|
|
220
|
+
const requestOrigin = new URL(request.url).origin;
|
|
221
|
+
let parsed;
|
|
222
|
+
try {
|
|
223
|
+
parsed = new URL(raw, requestOrigin);
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
throw new PiboWebHttpError("url must be a valid URL", 400);
|
|
227
|
+
}
|
|
228
|
+
if (parsed.origin !== requestOrigin)
|
|
229
|
+
throw new PiboWebHttpError("same-origin annotations require a URL on this Pibo web origin", 400);
|
|
230
|
+
return parsed.href;
|
|
231
|
+
}
|
|
232
|
+
function requireTargetKind(value) {
|
|
233
|
+
if (!value || !isWebAnnotationTargetKind(value))
|
|
234
|
+
throw new PiboWebHttpError("Invalid annotation target kind", 400);
|
|
235
|
+
return value;
|
|
236
|
+
}
|
|
237
|
+
function normalizeViewport(value) {
|
|
238
|
+
if (!value || typeof value.width !== "number" || typeof value.height !== "number")
|
|
239
|
+
throw new PiboWebHttpError("viewport width and height are required", 400);
|
|
240
|
+
try {
|
|
241
|
+
return normalizeWebAnnotationViewport(value);
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
throw new PiboWebHttpError(error instanceof Error ? error.message : String(error), 400);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function normalizeTarget(value, targetKind) {
|
|
248
|
+
if (value === undefined)
|
|
249
|
+
return { kind: targetKind };
|
|
250
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
251
|
+
throw new PiboWebHttpError("target must be an object", 400);
|
|
252
|
+
try {
|
|
253
|
+
return normalizeWebAnnotationTarget({ ...value, kind: targetKind }, targetKind);
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
throw new PiboWebHttpError(error instanceof Error ? error.message : String(error), 400);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function responseJavaScript(source, init = {}) {
|
|
260
|
+
return new Response(source, {
|
|
261
|
+
...init,
|
|
262
|
+
headers: {
|
|
263
|
+
"content-type": "text/javascript; charset=utf-8",
|
|
264
|
+
...init.headers,
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
function corsJson(payload, init = {}) {
|
|
269
|
+
return responseJson(payload, { ...init, headers: corsHeaders(init.headers) });
|
|
270
|
+
}
|
|
271
|
+
function corsResponse(body, init = {}) {
|
|
272
|
+
return new Response(body, { ...init, headers: corsHeaders(init.headers) });
|
|
273
|
+
}
|
|
274
|
+
function corsHeaders(existing) {
|
|
275
|
+
return {
|
|
276
|
+
"access-control-allow-origin": "*",
|
|
277
|
+
"access-control-allow-methods": "POST, OPTIONS",
|
|
278
|
+
"access-control-allow-headers": "content-type",
|
|
279
|
+
...Object.fromEntries(new Headers(existing).entries()),
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function requireSameOriginJsonRequest(request) {
|
|
283
|
+
const contentType = request.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase();
|
|
284
|
+
if (contentType !== "application/json")
|
|
285
|
+
throw new PiboWebHttpError("Content-Type must be application/json", 415);
|
|
286
|
+
requireSameOriginRequest(request);
|
|
287
|
+
}
|
|
288
|
+
function requireSameOriginRequest(request) {
|
|
289
|
+
const origin = request.headers.get("origin");
|
|
290
|
+
if (!origin)
|
|
291
|
+
throw new PiboWebHttpError("Origin header is required", 403);
|
|
292
|
+
if (origin !== new URL(request.url).origin)
|
|
293
|
+
throw new PiboWebHttpError("Origin is not allowed", 403);
|
|
294
|
+
}
|
|
295
|
+
function serviceForRequest(baseService, cdpUrl, request, store, options) {
|
|
296
|
+
if (options.cdpService)
|
|
297
|
+
return baseService;
|
|
298
|
+
return createWebAnnotationCdpService({ store, cdpUrl, apiBaseUrl: new URL(request.url).origin });
|
|
299
|
+
}
|
|
300
|
+
function resolveBindingContext(context, _webSession, input) {
|
|
301
|
+
const piboSessionId = input.piboSessionId?.trim();
|
|
302
|
+
if (!piboSessionId)
|
|
303
|
+
throw new PiboWebHttpError("piboSessionId is required", 400);
|
|
304
|
+
const session = context.channelContext.getSession(piboSessionId);
|
|
305
|
+
if (!session)
|
|
306
|
+
throw new PiboWebHttpError("Pibo session not found", 404);
|
|
307
|
+
return {
|
|
308
|
+
piboSessionId,
|
|
309
|
+
piboRoomId: input.piboRoomId?.trim() || undefined,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function requireQueryParam(url, name, fallbackName) {
|
|
313
|
+
const value = (url.searchParams.get(name) ?? (fallbackName ? url.searchParams.get(fallbackName) : undefined))?.trim();
|
|
314
|
+
if (!value)
|
|
315
|
+
throw new PiboWebHttpError(`${name} is required`, 400);
|
|
316
|
+
return value;
|
|
317
|
+
}
|
|
318
|
+
function optionalStatus(value) {
|
|
319
|
+
if (!value)
|
|
320
|
+
return undefined;
|
|
321
|
+
if (!isWebAnnotationStatus(value))
|
|
322
|
+
throw new PiboWebHttpError("Invalid annotation status", 400);
|
|
323
|
+
return value;
|
|
324
|
+
}
|
|
325
|
+
function parseLimit(value) {
|
|
326
|
+
if (!value)
|
|
327
|
+
return undefined;
|
|
328
|
+
const parsed = Number.parseInt(value, 10);
|
|
329
|
+
return Number.isFinite(parsed) ? normalizeWebAnnotationLimit(parsed, 100, 500) : undefined;
|
|
330
|
+
}
|
|
331
|
+
function matchBindingResource(pathname) {
|
|
332
|
+
const prefix = `${WEB_ANNOTATIONS_API_PREFIX}/bindings/`;
|
|
333
|
+
if (!pathname.startsWith(prefix))
|
|
334
|
+
return undefined;
|
|
335
|
+
const parts = pathname.slice(prefix.length).split("/").filter(Boolean).map(decodeURIComponent);
|
|
336
|
+
if (parts.length === 0 || parts.length > 2)
|
|
337
|
+
return undefined;
|
|
338
|
+
return { id: parts[0], action: parts[1] };
|
|
339
|
+
}
|
|
340
|
+
function matchAnnotationResource(pathname) {
|
|
341
|
+
const prefix = `${WEB_ANNOTATIONS_API_PREFIX}/`;
|
|
342
|
+
if (!pathname.startsWith(prefix) || pathname.startsWith(`${WEB_ANNOTATIONS_API_PREFIX}/bindings/`))
|
|
343
|
+
return undefined;
|
|
344
|
+
const parts = pathname.slice(prefix.length).split("/").filter(Boolean).map(decodeURIComponent);
|
|
345
|
+
if (parts.length !== 1 || parts[0] === "targets" || parts[0] === "submissions" || parts[0] === "bindings")
|
|
346
|
+
return undefined;
|
|
347
|
+
return { id: parts[0] };
|
|
348
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { sanitizeWebAnnotationText, WEB_ANNOTATION_LIMITS } from "./validation.js";
|
|
2
|
+
export const WEB_ANNOTATION_MESSAGE_ATTACHMENT_LIMIT = WEB_ANNOTATION_LIMITS.attachments;
|
|
3
|
+
export function normalizeWebAnnotationAttachmentIds(value) {
|
|
4
|
+
if (value === undefined || value === null)
|
|
5
|
+
return [];
|
|
6
|
+
if (!Array.isArray(value))
|
|
7
|
+
throw new Error("webAnnotationIds must be an array");
|
|
8
|
+
if (value.length > WEB_ANNOTATION_MESSAGE_ATTACHMENT_LIMIT)
|
|
9
|
+
throw new Error(`At most ${WEB_ANNOTATION_MESSAGE_ATTACHMENT_LIMIT} web annotations can be attached`);
|
|
10
|
+
const ids = [];
|
|
11
|
+
const seen = new Set();
|
|
12
|
+
for (const item of value) {
|
|
13
|
+
if (typeof item !== "string")
|
|
14
|
+
throw new Error("webAnnotationIds entries must be strings");
|
|
15
|
+
const id = item.trim();
|
|
16
|
+
if (!id)
|
|
17
|
+
throw new Error("webAnnotationIds entries must be non-empty strings");
|
|
18
|
+
if (id.length > 160)
|
|
19
|
+
throw new Error("web annotation id is too long");
|
|
20
|
+
if (!seen.has(id)) {
|
|
21
|
+
seen.add(id);
|
|
22
|
+
ids.push(id);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return ids;
|
|
26
|
+
}
|
|
27
|
+
export function serializeWebAnnotationAttachment(annotation) {
|
|
28
|
+
const attachment = {
|
|
29
|
+
id: annotation.id,
|
|
30
|
+
status: annotation.status,
|
|
31
|
+
targetKind: annotation.targetKind,
|
|
32
|
+
piboSessionId: annotation.piboSessionId,
|
|
33
|
+
piboRoomId: annotation.piboRoomId,
|
|
34
|
+
url: truncateInline(annotation.url, 240) ?? annotation.url,
|
|
35
|
+
note: truncateInline(annotation.note, 400) ?? "",
|
|
36
|
+
createdAt: annotation.createdAt,
|
|
37
|
+
};
|
|
38
|
+
const label = truncateInline(annotation.target?.label, 160);
|
|
39
|
+
const selector = truncateInline(annotation.target?.selector ?? annotation.target?.domPath ?? annotation.target?.stableId, 220);
|
|
40
|
+
const sourceHint = truncateInline(sourceHintSummary(annotation.target?.sourceHints?.[0]), 220);
|
|
41
|
+
const sourceHints = sourceHintSummaries(annotation.target?.sourceHints).map((hint) => truncateInline(hint, 220)).filter((hint) => Boolean(hint));
|
|
42
|
+
const primaryTarget = truncateInline(primaryTargetSummary(annotation.target?.sourceHints), 220);
|
|
43
|
+
const piboContext = truncateInline(piboContextSummary(annotation.target?.sourceHints), 260);
|
|
44
|
+
const position = positionSummary(annotation);
|
|
45
|
+
const text = truncateInline(annotation.target?.selectedText ?? annotation.target?.text, 220);
|
|
46
|
+
if (label)
|
|
47
|
+
attachment.label = label;
|
|
48
|
+
if (selector)
|
|
49
|
+
attachment.selector = selector;
|
|
50
|
+
if (primaryTarget)
|
|
51
|
+
attachment.primaryTarget = primaryTarget;
|
|
52
|
+
if (piboContext)
|
|
53
|
+
attachment.piboContext = piboContext;
|
|
54
|
+
if (sourceHint)
|
|
55
|
+
attachment.sourceHint = sourceHint;
|
|
56
|
+
if (sourceHints.length)
|
|
57
|
+
attachment.sourceHints = sourceHints;
|
|
58
|
+
if (position)
|
|
59
|
+
attachment.position = position;
|
|
60
|
+
if (text)
|
|
61
|
+
attachment.text = text;
|
|
62
|
+
return attachment;
|
|
63
|
+
}
|
|
64
|
+
export function prepareWebAnnotationMessageAttachments(input) {
|
|
65
|
+
const ids = normalizeWebAnnotationAttachmentIds(input.attachmentIds);
|
|
66
|
+
if (!ids.length) {
|
|
67
|
+
return { ids: [], annotations: [], attachments: [], modelContext: "", messageText: input.messageText };
|
|
68
|
+
}
|
|
69
|
+
const annotations = ids.map((id) => {
|
|
70
|
+
const annotation = input.store.getAnnotationById(id);
|
|
71
|
+
if (!annotation)
|
|
72
|
+
throw new Error(`Web Annotation ${id} is not available in this app`);
|
|
73
|
+
if (annotation.status === "resolved" || annotation.status === "dismissed") {
|
|
74
|
+
throw new Error(`Web Annotation ${id} cannot be attached because it is ${annotation.status}`);
|
|
75
|
+
}
|
|
76
|
+
return annotation;
|
|
77
|
+
});
|
|
78
|
+
const modelContext = renderAttachedWebAnnotations(annotations);
|
|
79
|
+
return {
|
|
80
|
+
ids,
|
|
81
|
+
annotations,
|
|
82
|
+
attachments: annotations.map(serializeWebAnnotationAttachment),
|
|
83
|
+
modelContext,
|
|
84
|
+
messageText: modelContext ? `${input.messageText.trimEnd()}\n\n${modelContext}` : input.messageText,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export function renderAttachedWebAnnotations(annotations) {
|
|
88
|
+
const bounded = annotations.slice(0, WEB_ANNOTATION_MESSAGE_ATTACHMENT_LIMIT);
|
|
89
|
+
if (!bounded.length)
|
|
90
|
+
return "";
|
|
91
|
+
const lines = ["<attached-web-annotations>"];
|
|
92
|
+
bounded.forEach((annotation, index) => {
|
|
93
|
+
const target = annotation.target;
|
|
94
|
+
const sourceHint = sourceHintSummary(target?.sourceHints?.[0]);
|
|
95
|
+
const sourceHints = sourceHintSummaries(target?.sourceHints);
|
|
96
|
+
const primaryTarget = primaryTargetSummary(target?.sourceHints);
|
|
97
|
+
const piboContext = piboContextSummary(target?.sourceHints);
|
|
98
|
+
const position = positionSummary(annotation);
|
|
99
|
+
lines.push(`${index + 1}. ${escapeBlockValue(annotation.id)}`);
|
|
100
|
+
lines.push(`targetKind: ${escapeBlockValue(annotation.targetKind)}`);
|
|
101
|
+
lines.push(`sourceSession: ${escapeBlockValue(annotation.piboSessionId)}`);
|
|
102
|
+
if (annotation.piboRoomId)
|
|
103
|
+
lines.push(`sourceRoom: ${escapeBlockValue(annotation.piboRoomId)}`);
|
|
104
|
+
lines.push(`url: ${escapeBlockValue(truncateInline(annotation.url, 240) ?? "")}`);
|
|
105
|
+
if (target?.label)
|
|
106
|
+
lines.push(`label: ${escapeBlockValue(truncateInline(target.label, 160) ?? "")}`);
|
|
107
|
+
if (primaryTarget)
|
|
108
|
+
lines.push(`primaryTarget: ${escapeBlockValue(truncateInline(primaryTarget, 220) ?? "")}`);
|
|
109
|
+
if (piboContext)
|
|
110
|
+
lines.push(`piboContext: ${escapeBlockValue(truncateInline(piboContext, 260) ?? "")}`);
|
|
111
|
+
const selector = target?.selector ?? target?.domPath ?? target?.stableId;
|
|
112
|
+
if (selector)
|
|
113
|
+
lines.push(`selector: ${escapeBlockValue(truncateInline(selector, 220) ?? "")}`);
|
|
114
|
+
if (sourceHint)
|
|
115
|
+
lines.push(`sourceHint: ${escapeBlockValue(truncateInline(sourceHint, 220) ?? "")}`);
|
|
116
|
+
if (sourceHints.length > 1)
|
|
117
|
+
lines.push(`sourceHints: ${escapeBlockValue(truncateInline(sourceHints.slice(0, 5).join(" | "), 500) ?? "")}`);
|
|
118
|
+
if (position)
|
|
119
|
+
lines.push(`position: ${escapeBlockValue(position)}`);
|
|
120
|
+
const text = target?.selectedText ?? target?.text;
|
|
121
|
+
if (text)
|
|
122
|
+
lines.push(`text: ${escapeBlockValue(truncateInline(text, 220) ?? "")}`);
|
|
123
|
+
if (target?.htmlHint)
|
|
124
|
+
lines.push(`htmlHint: ${escapeBlockValue(truncateInline(target.htmlHint, 180) ?? "")}`);
|
|
125
|
+
lines.push(`comment: ${escapeBlockValue(truncateInline(annotation.note, 400) ?? "")}`);
|
|
126
|
+
});
|
|
127
|
+
lines.push("</attached-web-annotations>");
|
|
128
|
+
return lines.join("\n");
|
|
129
|
+
}
|
|
130
|
+
function primaryTargetSummary(hints) {
|
|
131
|
+
const hint = hints?.find((candidate) => candidate.kind === "pibo-shared-card")
|
|
132
|
+
?? hints?.find((candidate) => candidate.kind === "pibo-markdown")
|
|
133
|
+
?? hints?.find((candidate) => candidate.kind === "pibo-terminal-row")
|
|
134
|
+
?? hints?.find((candidate) => candidate.kind === "pibo-component")
|
|
135
|
+
?? hints?.[0];
|
|
136
|
+
if (!hint)
|
|
137
|
+
return undefined;
|
|
138
|
+
if (hint.kind === "pibo-shared-card")
|
|
139
|
+
return [hint.component, hint.id === "status" ? "status card" : hint.id].filter(Boolean).join(" ");
|
|
140
|
+
if (hint.kind === "pibo-terminal-row")
|
|
141
|
+
return [hint.component ?? "TerminalRow", rawString(hint, "rowKind") ?? hint.id].filter(Boolean).join(" ");
|
|
142
|
+
if (hint.kind === "pibo-markdown")
|
|
143
|
+
return [hint.component ?? "MarkdownRenderer", hint.id].filter(Boolean).join(" ");
|
|
144
|
+
return hint.component ?? hint.id;
|
|
145
|
+
}
|
|
146
|
+
function piboContextSummary(hints) {
|
|
147
|
+
if (!hints?.length)
|
|
148
|
+
return undefined;
|
|
149
|
+
const parts = [];
|
|
150
|
+
for (const hint of hints) {
|
|
151
|
+
if (!hint.kind.startsWith("pibo-"))
|
|
152
|
+
continue;
|
|
153
|
+
const values = [
|
|
154
|
+
hint.component ? `component=${hint.component}` : undefined,
|
|
155
|
+
hint.id ? `${hint.kind.replace(/^pibo-/, "")}=${hint.id}` : undefined,
|
|
156
|
+
rawString(hint, "rowKind") ? `rowKind=${rawString(hint, "rowKind")}` : undefined,
|
|
157
|
+
rawString(hint, "rowStatus") ? `rowStatus=${rawString(hint, "rowStatus")}` : undefined,
|
|
158
|
+
rawString(hint, "eventId") ? `eventId=${rawString(hint, "eventId")}` : undefined,
|
|
159
|
+
rawString(hint, "traceNodeId") ? `traceNodeId=${rawString(hint, "traceNodeId")}` : undefined,
|
|
160
|
+
rawString(hint, "runId") ? `runId=${rawString(hint, "runId")}` : undefined,
|
|
161
|
+
rawString(hint, "piboSessionId") ? `piboSessionId=${rawString(hint, "piboSessionId")}` : undefined,
|
|
162
|
+
].filter(Boolean).join(", ");
|
|
163
|
+
if (values && !parts.includes(values))
|
|
164
|
+
parts.push(values);
|
|
165
|
+
if (parts.length >= 3)
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
return parts.length ? parts.join(" | ") : undefined;
|
|
169
|
+
}
|
|
170
|
+
function sourceHintSummaries(hints) {
|
|
171
|
+
return hints?.map(sourceHintSummary).filter((summary) => Boolean(summary)).slice(0, 6) ?? [];
|
|
172
|
+
}
|
|
173
|
+
function sourceHintSummary(hint) {
|
|
174
|
+
if (!hint)
|
|
175
|
+
return undefined;
|
|
176
|
+
const location = hint.file
|
|
177
|
+
? `${hint.file}${hint.line !== undefined ? `:${hint.line}` : ""}${hint.column !== undefined ? `:${hint.column}` : ""}`
|
|
178
|
+
: [hint.component, hint.id].filter(Boolean).join(" ") || undefined;
|
|
179
|
+
const rawBits = [rawString(hint, "rowKind"), rawString(hint, "eventId"), rawString(hint, "traceNodeId")].filter(Boolean).join(" · ");
|
|
180
|
+
return [location, hint.confidence, hint.kind, rawBits].filter(Boolean).join(" · ");
|
|
181
|
+
}
|
|
182
|
+
function rawString(hint, key) {
|
|
183
|
+
const value = hint.raw?.[key];
|
|
184
|
+
return typeof value === "string" && value ? value : undefined;
|
|
185
|
+
}
|
|
186
|
+
function positionSummary(annotation) {
|
|
187
|
+
const box = annotation.target?.boundingBox;
|
|
188
|
+
if (box)
|
|
189
|
+
return `x${formatNumber(box.x)} y${formatNumber(box.y)} ${formatNumber(box.width)}x${formatNumber(box.height)}`;
|
|
190
|
+
const position = annotation.target?.position;
|
|
191
|
+
return position ? `x${formatNumber(position.x)} y${formatNumber(position.y)}` : undefined;
|
|
192
|
+
}
|
|
193
|
+
function formatNumber(value) {
|
|
194
|
+
return Number.isInteger(value) ? String(value) : value.toFixed(1);
|
|
195
|
+
}
|
|
196
|
+
function truncateInline(value, max) {
|
|
197
|
+
return sanitizeWebAnnotationText(value, { max, field: "web annotation attachment" });
|
|
198
|
+
}
|
|
199
|
+
function escapeBlockValue(value) {
|
|
200
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
201
|
+
}
|