@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
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { mkdirSync } from "node:fs";
|
|
3
3
|
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { piboHomePath } from "../core/pibo-home.js";
|
|
5
|
+
import { sqliteTableColumns } from "../data/sqlite-schema.js";
|
|
4
6
|
import { DatabaseSync } from "node:sqlite";
|
|
5
7
|
function now() {
|
|
6
8
|
return new Date().toISOString();
|
|
@@ -17,9 +19,24 @@ function parseJson(value) {
|
|
|
17
19
|
function asDate(value) {
|
|
18
20
|
return value ?? new Date();
|
|
19
21
|
}
|
|
22
|
+
function migratePiboRunControllerColumn(db) {
|
|
23
|
+
const table = db.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'pibo_runs'").get();
|
|
24
|
+
if (!table)
|
|
25
|
+
return;
|
|
26
|
+
const legacyColumn = ["o", "wner_pibo_session_id"].join("");
|
|
27
|
+
const columns = sqliteTableColumns(db, "pibo_runs");
|
|
28
|
+
if (!columns.has(legacyColumn) || columns.has("controller_pibo_session_id"))
|
|
29
|
+
return;
|
|
30
|
+
db.exec("DROP INDEX IF EXISTS idx_pibo_runs_" + ["o", "wner_updated"].join(""));
|
|
31
|
+
db.exec(`ALTER TABLE pibo_runs RENAME COLUMN ${legacyColumn} TO controller_pibo_session_id`);
|
|
32
|
+
}
|
|
20
33
|
export class PiboReliabilityStore {
|
|
21
34
|
db;
|
|
22
|
-
|
|
35
|
+
appendEventStatement;
|
|
36
|
+
getEventByStreamIdStatement;
|
|
37
|
+
getEventByTopicEventIdStatement;
|
|
38
|
+
getEventByTopicIdempotencyKeyStatement;
|
|
39
|
+
constructor(path = piboHomePath("pibo-events.sqlite")) {
|
|
23
40
|
const resolvedPath = path === ":memory:" ? path : resolve(path);
|
|
24
41
|
if (resolvedPath !== ":memory:")
|
|
25
42
|
mkdirSync(dirname(resolvedPath), { recursive: true });
|
|
@@ -28,6 +45,7 @@ export class PiboReliabilityStore {
|
|
|
28
45
|
this.db.exec("PRAGMA foreign_keys = ON");
|
|
29
46
|
if (resolvedPath !== ":memory:")
|
|
30
47
|
this.db.exec("PRAGMA journal_mode = WAL");
|
|
48
|
+
migratePiboRunControllerColumn(this.db);
|
|
31
49
|
this.db.exec(`
|
|
32
50
|
CREATE TABLE IF NOT EXISTS pibo_event_stream (
|
|
33
51
|
stream_id INTEGER PRIMARY KEY,
|
|
@@ -102,7 +120,7 @@ export class PiboReliabilityStore {
|
|
|
102
120
|
CREATE TABLE IF NOT EXISTS pibo_runs (
|
|
103
121
|
run_id TEXT PRIMARY KEY,
|
|
104
122
|
kind TEXT NOT NULL,
|
|
105
|
-
|
|
123
|
+
controller_pibo_session_id TEXT NOT NULL,
|
|
106
124
|
status TEXT NOT NULL,
|
|
107
125
|
completion_policy TEXT NOT NULL,
|
|
108
126
|
consumed INTEGER NOT NULL DEFAULT 0,
|
|
@@ -119,21 +137,23 @@ export class PiboReliabilityStore {
|
|
|
119
137
|
retryable INTEGER NOT NULL DEFAULT 0,
|
|
120
138
|
max_attempts INTEGER NOT NULL DEFAULT 1
|
|
121
139
|
);
|
|
122
|
-
CREATE INDEX IF NOT EXISTS
|
|
123
|
-
ON pibo_runs(
|
|
140
|
+
CREATE INDEX IF NOT EXISTS idx_pibo_runs_controller_updated
|
|
141
|
+
ON pibo_runs(controller_pibo_session_id, updated_at);
|
|
124
142
|
CREATE INDEX IF NOT EXISTS idx_pibo_runs_status
|
|
125
143
|
ON pibo_runs(status);
|
|
126
144
|
`);
|
|
145
|
+
this.appendEventStatement = this.db.prepare(`
|
|
146
|
+
INSERT INTO pibo_event_stream (topic, key, event_id, idempotency_key, created_at, retention_class, payload_json)
|
|
147
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
148
|
+
`);
|
|
149
|
+
this.getEventByStreamIdStatement = this.db.prepare("SELECT * FROM pibo_event_stream WHERE stream_id = ?");
|
|
150
|
+
this.getEventByTopicEventIdStatement = this.db.prepare("SELECT * FROM pibo_event_stream WHERE topic = ? AND event_id = ?");
|
|
151
|
+
this.getEventByTopicIdempotencyKeyStatement = this.db.prepare("SELECT * FROM pibo_event_stream WHERE topic = ? AND idempotency_key = ?");
|
|
127
152
|
}
|
|
128
153
|
append(input) {
|
|
129
154
|
const eventId = input.eventId ?? `evt_${randomUUID()}`;
|
|
130
155
|
const createdAt = input.createdAt ?? now();
|
|
131
|
-
const result = this.
|
|
132
|
-
.prepare(`
|
|
133
|
-
INSERT INTO pibo_event_stream (topic, key, event_id, idempotency_key, created_at, retention_class, payload_json)
|
|
134
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
135
|
-
`)
|
|
136
|
-
.run(input.topic, input.key ?? null, eventId, input.idempotencyKey ?? null, createdAt, input.retentionClass ?? "audit_event", json(input.payload));
|
|
156
|
+
const result = this.appendEventStatement.run(input.topic, input.key ?? null, eventId, input.idempotencyKey ?? null, createdAt, input.retentionClass ?? "audit_event", json(input.payload));
|
|
137
157
|
return this.getEventByStreamId(Number(result.lastInsertRowid));
|
|
138
158
|
}
|
|
139
159
|
appendOnce(input) {
|
|
@@ -450,7 +470,7 @@ export class PiboReliabilityStore {
|
|
|
450
470
|
queue: "runs",
|
|
451
471
|
payload: {
|
|
452
472
|
runId,
|
|
453
|
-
|
|
473
|
+
controllerPiboSessionId: input.controllerPiboSessionId,
|
|
454
474
|
toolName: input.toolName,
|
|
455
475
|
params: input.params,
|
|
456
476
|
},
|
|
@@ -459,12 +479,12 @@ export class PiboReliabilityStore {
|
|
|
459
479
|
this.db
|
|
460
480
|
.prepare(`
|
|
461
481
|
INSERT INTO pibo_runs (
|
|
462
|
-
run_id, kind,
|
|
482
|
+
run_id, kind, controller_pibo_session_id, status, completion_policy, consumed, tool_name,
|
|
463
483
|
summary, result_json, error, notified_status, acknowledged_status, created_at, updated_at,
|
|
464
484
|
completed_at, job_id, retryable, max_attempts
|
|
465
485
|
) VALUES (?, 'tool', ?, 'running', ?, 0, ?, ?, NULL, NULL, NULL, NULL, ?, ?, NULL, ?, ?, ?)
|
|
466
486
|
`)
|
|
467
|
-
.run(runId, input.
|
|
487
|
+
.run(runId, input.controllerPiboSessionId, input.completionPolicy, input.toolName, `${input.toolName} run is running.`, timestamp, timestamp, job.jobId, input.retryable ? 1 : 0, maxAttempts);
|
|
468
488
|
this.claimJob(job.jobId, `run-registry:${process.pid}`, 24 * 60 * 60 * 1000);
|
|
469
489
|
return this.requireRun(runId);
|
|
470
490
|
}
|
|
@@ -501,9 +521,9 @@ export class PiboReliabilityStore {
|
|
|
501
521
|
listRuns(input = {}) {
|
|
502
522
|
const clauses = [];
|
|
503
523
|
const values = [];
|
|
504
|
-
if (input.
|
|
505
|
-
clauses.push("
|
|
506
|
-
values.push(input.
|
|
524
|
+
if (input.controllerPiboSessionId) {
|
|
525
|
+
clauses.push("controller_pibo_session_id = ?");
|
|
526
|
+
values.push(input.controllerPiboSessionId);
|
|
507
527
|
}
|
|
508
528
|
if (!input.includeConsumed)
|
|
509
529
|
clauses.push("consumed = 0");
|
|
@@ -566,21 +586,17 @@ export class PiboReliabilityStore {
|
|
|
566
586
|
this.db.close();
|
|
567
587
|
}
|
|
568
588
|
getEventByStreamId(streamId) {
|
|
569
|
-
const row = this.
|
|
589
|
+
const row = this.getEventByStreamIdStatement.get(streamId);
|
|
570
590
|
if (!row)
|
|
571
591
|
throw new Error(`Unknown pibo event stream id "${streamId}"`);
|
|
572
592
|
return eventFromRow(row);
|
|
573
593
|
}
|
|
574
594
|
getEventByTopicEventId(topic, eventId) {
|
|
575
|
-
const row = this.
|
|
576
|
-
.prepare("SELECT * FROM pibo_event_stream WHERE topic = ? AND event_id = ?")
|
|
577
|
-
.get(topic, eventId);
|
|
595
|
+
const row = this.getEventByTopicEventIdStatement.get(topic, eventId);
|
|
578
596
|
return row ? eventFromRow(row) : undefined;
|
|
579
597
|
}
|
|
580
598
|
getEventByTopicIdempotencyKey(topic, idempotencyKey) {
|
|
581
|
-
const row = this.
|
|
582
|
-
.prepare("SELECT * FROM pibo_event_stream WHERE topic = ? AND idempotency_key = ?")
|
|
583
|
-
.get(topic, idempotencyKey);
|
|
599
|
+
const row = this.getEventByTopicIdempotencyKeyStatement.get(topic, idempotencyKey);
|
|
584
600
|
return row ? eventFromRow(row) : undefined;
|
|
585
601
|
}
|
|
586
602
|
getConsumerOffset(topic, consumer) {
|
|
@@ -666,8 +682,8 @@ export class PiboReliabilityStore {
|
|
|
666
682
|
return run;
|
|
667
683
|
}
|
|
668
684
|
}
|
|
669
|
-
export function createDefaultPiboReliabilityStore(
|
|
670
|
-
return new PiboReliabilityStore(
|
|
685
|
+
export function createDefaultPiboReliabilityStore(_cwd) {
|
|
686
|
+
return new PiboReliabilityStore(piboHomePath("pibo-events.sqlite"));
|
|
671
687
|
}
|
|
672
688
|
function eventFromRow(row) {
|
|
673
689
|
return {
|
|
@@ -720,7 +736,7 @@ function runFromRow(row) {
|
|
|
720
736
|
const output = {
|
|
721
737
|
runId: row.run_id,
|
|
722
738
|
kind: row.kind,
|
|
723
|
-
|
|
739
|
+
controllerPiboSessionId: row.controller_pibo_session_id,
|
|
724
740
|
status: row.status,
|
|
725
741
|
completionPolicy: row.completion_policy,
|
|
726
742
|
consumed: row.consumed === 1,
|
package/dist/runs/registry.js
CHANGED
|
@@ -8,7 +8,7 @@ function snapshot(record) {
|
|
|
8
8
|
const output = {
|
|
9
9
|
runId: record.runId,
|
|
10
10
|
kind: record.kind,
|
|
11
|
-
|
|
11
|
+
controllerPiboSessionId: record.controllerPiboSessionId,
|
|
12
12
|
status: record.status,
|
|
13
13
|
completionPolicy: record.completionPolicy,
|
|
14
14
|
consumed: record.consumed,
|
|
@@ -29,6 +29,11 @@ export class PiboRunRegistry {
|
|
|
29
29
|
options;
|
|
30
30
|
runs = new Map();
|
|
31
31
|
waiters = new Map();
|
|
32
|
+
listeners = new Set();
|
|
33
|
+
subscribe(listener) {
|
|
34
|
+
this.listeners.add(listener);
|
|
35
|
+
return () => this.listeners.delete(listener);
|
|
36
|
+
}
|
|
32
37
|
constructor(options = {}) {
|
|
33
38
|
this.options = options;
|
|
34
39
|
if (this.options.store) {
|
|
@@ -42,7 +47,7 @@ export class PiboRunRegistry {
|
|
|
42
47
|
this.prune();
|
|
43
48
|
if (this.options.store) {
|
|
44
49
|
const stored = this.options.store.createRun({
|
|
45
|
-
|
|
50
|
+
controllerPiboSessionId: input.controllerPiboSessionId,
|
|
46
51
|
toolName: input.toolName,
|
|
47
52
|
completionPolicy: input.completionPolicy ?? "tracked",
|
|
48
53
|
params: input.params,
|
|
@@ -51,14 +56,16 @@ export class PiboRunRegistry {
|
|
|
51
56
|
});
|
|
52
57
|
const record = recordFromStored(stored);
|
|
53
58
|
this.runs.set(record.runId, record);
|
|
54
|
-
|
|
59
|
+
const output = snapshot(record);
|
|
60
|
+
this.notify({ type: "run_started", run: output });
|
|
61
|
+
return output;
|
|
55
62
|
}
|
|
56
63
|
const timestamp = now();
|
|
57
64
|
const runId = `run_${randomUUID()}`;
|
|
58
65
|
const record = {
|
|
59
66
|
runId,
|
|
60
67
|
kind: "tool",
|
|
61
|
-
|
|
68
|
+
controllerPiboSessionId: input.controllerPiboSessionId,
|
|
62
69
|
status: "running",
|
|
63
70
|
completionPolicy: input.completionPolicy ?? "tracked",
|
|
64
71
|
consumed: false,
|
|
@@ -70,12 +77,15 @@ export class PiboRunRegistry {
|
|
|
70
77
|
maxAttempts: Math.max(1, input.maxAttempts ?? 1),
|
|
71
78
|
};
|
|
72
79
|
this.runs.set(runId, record);
|
|
73
|
-
|
|
80
|
+
const output = snapshot(record);
|
|
81
|
+
this.notify({ type: "run_started", run: output });
|
|
82
|
+
return output;
|
|
74
83
|
}
|
|
75
84
|
complete(runId, result) {
|
|
76
85
|
const record = this.runs.get(runId);
|
|
77
86
|
if (!record || terminal(record.status))
|
|
78
87
|
return undefined;
|
|
88
|
+
const previousStatus = record.status;
|
|
79
89
|
record.status = "completed";
|
|
80
90
|
record.result = result;
|
|
81
91
|
record.summary = `${record.toolName} run completed.`;
|
|
@@ -83,12 +93,15 @@ export class PiboRunRegistry {
|
|
|
83
93
|
this.options.store?.updateRun(runId, record);
|
|
84
94
|
if (record.jobId)
|
|
85
95
|
this.options.store?.ack(record.jobId, `run-registry:${process.pid}`);
|
|
86
|
-
|
|
96
|
+
const output = snapshot(record);
|
|
97
|
+
this.notify({ type: "run_changed", run: output, previousStatus });
|
|
98
|
+
return output;
|
|
87
99
|
}
|
|
88
100
|
fail(runId, error) {
|
|
89
101
|
const record = this.runs.get(runId);
|
|
90
102
|
if (!record || terminal(record.status))
|
|
91
103
|
return undefined;
|
|
104
|
+
const previousStatus = record.status;
|
|
92
105
|
record.status = "failed";
|
|
93
106
|
record.error = error;
|
|
94
107
|
record.summary = `${record.toolName} run failed.`;
|
|
@@ -96,21 +109,30 @@ export class PiboRunRegistry {
|
|
|
96
109
|
this.options.store?.updateRun(runId, record);
|
|
97
110
|
if (record.jobId)
|
|
98
111
|
this.options.store?.fail(record.jobId, `run-registry:${process.pid}`, error);
|
|
99
|
-
|
|
112
|
+
const output = snapshot(record);
|
|
113
|
+
this.notify({ type: "run_changed", run: output, previousStatus, reason: error });
|
|
114
|
+
return output;
|
|
100
115
|
}
|
|
101
|
-
list(
|
|
116
|
+
list(controllerPiboSessionId, options = {}) {
|
|
102
117
|
this.prune();
|
|
103
118
|
return [...this.runs.values()]
|
|
104
|
-
.filter((record) => record.
|
|
119
|
+
.filter((record) => record.controllerPiboSessionId === controllerPiboSessionId)
|
|
105
120
|
.filter((record) => options.includeConsumed || !record.consumed)
|
|
106
121
|
.filter((record) => options.includeDetached || record.completionPolicy !== "detached")
|
|
107
122
|
.map(snapshot);
|
|
108
123
|
}
|
|
109
|
-
|
|
110
|
-
|
|
124
|
+
listAll(options = {}) {
|
|
125
|
+
this.prune();
|
|
126
|
+
return [...this.runs.values()]
|
|
127
|
+
.filter((record) => options.includeConsumed || !record.consumed)
|
|
128
|
+
.filter((record) => options.includeDetached || record.completionPolicy !== "detached")
|
|
129
|
+
.map(snapshot);
|
|
130
|
+
}
|
|
131
|
+
status(controllerPiboSessionId, runId) {
|
|
132
|
+
return snapshot(this.requireRunForController(controllerPiboSessionId, runId));
|
|
111
133
|
}
|
|
112
|
-
async wait(
|
|
113
|
-
const record = this.
|
|
134
|
+
async wait(controllerPiboSessionId, runId, timeoutMs) {
|
|
135
|
+
const record = this.requireRunForController(controllerPiboSessionId, runId);
|
|
114
136
|
if (terminal(record.status))
|
|
115
137
|
return { ...snapshot(record), timedOut: false };
|
|
116
138
|
const boundedTimeoutMs = Math.max(0, Math.min(timeoutMs, 300000));
|
|
@@ -143,12 +165,13 @@ export class PiboRunRegistry {
|
|
|
143
165
|
return { ...snapshot(record), timedOut: true };
|
|
144
166
|
return { ...snapshot(completed), timedOut: false };
|
|
145
167
|
}
|
|
146
|
-
read(
|
|
147
|
-
const record = this.
|
|
168
|
+
read(controllerPiboSessionId, runId) {
|
|
169
|
+
const record = this.requireRunForController(controllerPiboSessionId, runId);
|
|
148
170
|
if (terminal(record.status)) {
|
|
149
171
|
record.consumed = true;
|
|
150
172
|
record.updatedAt = now();
|
|
151
173
|
this.options.store?.updateRun(runId, record);
|
|
174
|
+
this.notify({ type: "run_consumed", run: snapshot(record) });
|
|
152
175
|
}
|
|
153
176
|
const output = { ...snapshot(record) };
|
|
154
177
|
if (record.result)
|
|
@@ -157,8 +180,9 @@ export class PiboRunRegistry {
|
|
|
157
180
|
output.error = record.error;
|
|
158
181
|
return output;
|
|
159
182
|
}
|
|
160
|
-
cancel(
|
|
161
|
-
const record = this.
|
|
183
|
+
cancel(controllerPiboSessionId, runId) {
|
|
184
|
+
const record = this.requireRunForController(controllerPiboSessionId, runId);
|
|
185
|
+
const previousStatus = record.status;
|
|
162
186
|
if (!terminal(record.status)) {
|
|
163
187
|
record.status = "cancelled";
|
|
164
188
|
record.summary = `${record.toolName} run cancelled.`;
|
|
@@ -169,19 +193,23 @@ export class PiboRunRegistry {
|
|
|
169
193
|
record.consumed = true;
|
|
170
194
|
record.updatedAt = now();
|
|
171
195
|
this.options.store?.updateRun(runId, record);
|
|
172
|
-
|
|
196
|
+
const output = snapshot(record);
|
|
197
|
+
this.notify({ type: "run_changed", run: output, previousStatus, reason: "Run was cancelled." });
|
|
198
|
+
return output;
|
|
173
199
|
}
|
|
174
|
-
ack(
|
|
175
|
-
const record = this.
|
|
200
|
+
ack(controllerPiboSessionId, runId) {
|
|
201
|
+
const record = this.requireRunForController(controllerPiboSessionId, runId);
|
|
176
202
|
record.acknowledgedStatus = record.status;
|
|
177
203
|
if (terminal(record.status))
|
|
178
204
|
record.consumed = true;
|
|
179
205
|
record.updatedAt = now();
|
|
180
206
|
this.options.store?.updateRun(runId, record);
|
|
181
|
-
|
|
207
|
+
const output = snapshot(record);
|
|
208
|
+
this.notify({ type: "run_acknowledged", run: output });
|
|
209
|
+
return output;
|
|
182
210
|
}
|
|
183
|
-
createNotification(
|
|
184
|
-
const records = [...this.runs.values()].filter((record) => this.needsNotification(record,
|
|
211
|
+
createNotification(controllerPiboSessionId, options = {}) {
|
|
212
|
+
const records = [...this.runs.values()].filter((record) => this.needsNotification(record, controllerPiboSessionId, options));
|
|
185
213
|
if (records.length === 0)
|
|
186
214
|
return undefined;
|
|
187
215
|
for (const record of records) {
|
|
@@ -207,13 +235,13 @@ export class PiboRunRegistry {
|
|
|
207
235
|
}
|
|
208
236
|
return notification;
|
|
209
237
|
}
|
|
210
|
-
hasPendingNotification(
|
|
211
|
-
return [...this.runs.values()].some((record) => this.needsNotification(record,
|
|
238
|
+
hasPendingNotification(controllerPiboSessionId, options = {}) {
|
|
239
|
+
return [...this.runs.values()].some((record) => this.needsNotification(record, controllerPiboSessionId, options));
|
|
212
240
|
}
|
|
213
|
-
|
|
241
|
+
cancelControllerRuns(controllerPiboSessionId, reason = "Controller Pibo session was disposed.") {
|
|
214
242
|
const cancelled = [];
|
|
215
243
|
for (const record of this.runs.values()) {
|
|
216
|
-
if (record.
|
|
244
|
+
if (record.controllerPiboSessionId !== controllerPiboSessionId || terminal(record.status))
|
|
217
245
|
continue;
|
|
218
246
|
record.status = "cancelled";
|
|
219
247
|
record.error = reason;
|
|
@@ -223,7 +251,9 @@ export class PiboRunRegistry {
|
|
|
223
251
|
this.options.store?.updateRun(record.runId, record);
|
|
224
252
|
if (record.jobId)
|
|
225
253
|
this.options.store?.fail(record.jobId, `run-registry:${process.pid}`, reason);
|
|
226
|
-
|
|
254
|
+
const output = snapshot(record);
|
|
255
|
+
this.notify({ type: "run_changed", run: output, previousStatus: "running", reason });
|
|
256
|
+
cancelled.push(output);
|
|
227
257
|
}
|
|
228
258
|
return cancelled;
|
|
229
259
|
}
|
|
@@ -240,7 +270,9 @@ export class PiboRunRegistry {
|
|
|
240
270
|
this.options.store?.updateRun(record.runId, record);
|
|
241
271
|
if (record.jobId)
|
|
242
272
|
this.options.store?.fail(record.jobId, `run-registry:${process.pid}`, reason);
|
|
243
|
-
|
|
273
|
+
const output = snapshot(record);
|
|
274
|
+
this.notify({ type: "run_changed", run: output, previousStatus: "running", reason });
|
|
275
|
+
cancelled.push(output);
|
|
244
276
|
}
|
|
245
277
|
return cancelled;
|
|
246
278
|
}
|
|
@@ -262,6 +294,7 @@ export class PiboRunRegistry {
|
|
|
262
294
|
if (!shouldPrune)
|
|
263
295
|
continue;
|
|
264
296
|
this.runs.delete(runId);
|
|
297
|
+
this.notify({ type: "run_removed", runId, controllerPiboSessionId: record.controllerPiboSessionId });
|
|
265
298
|
pruned += 1;
|
|
266
299
|
}
|
|
267
300
|
if (this.options.store) {
|
|
@@ -269,15 +302,15 @@ export class PiboRunRegistry {
|
|
|
269
302
|
}
|
|
270
303
|
return pruned;
|
|
271
304
|
}
|
|
272
|
-
|
|
305
|
+
requireRunForController(controllerPiboSessionId, runId) {
|
|
273
306
|
const record = this.runs.get(runId);
|
|
274
|
-
if (!record || record.
|
|
275
|
-
throw new Error(`Unknown run "${runId}" for session "${
|
|
307
|
+
if (!record || record.controllerPiboSessionId !== controllerPiboSessionId) {
|
|
308
|
+
throw new Error(`Unknown run "${runId}" for session "${controllerPiboSessionId}"`);
|
|
276
309
|
}
|
|
277
310
|
return record;
|
|
278
311
|
}
|
|
279
|
-
needsNotification(record,
|
|
280
|
-
return (record.
|
|
312
|
+
needsNotification(record, controllerPiboSessionId, options = {}) {
|
|
313
|
+
return (record.controllerPiboSessionId === controllerPiboSessionId &&
|
|
281
314
|
record.completionPolicy === "tracked" &&
|
|
282
315
|
!record.consumed &&
|
|
283
316
|
record.acknowledgedStatus !== record.status &&
|
|
@@ -298,12 +331,16 @@ export class PiboRunRegistry {
|
|
|
298
331
|
waiter.resolve(record);
|
|
299
332
|
}
|
|
300
333
|
}
|
|
334
|
+
notify(event) {
|
|
335
|
+
for (const listener of this.listeners)
|
|
336
|
+
listener(event);
|
|
337
|
+
}
|
|
301
338
|
}
|
|
302
339
|
function recordFromStored(record) {
|
|
303
340
|
return {
|
|
304
341
|
runId: record.runId,
|
|
305
342
|
kind: record.kind,
|
|
306
|
-
|
|
343
|
+
controllerPiboSessionId: record.controllerPiboSessionId,
|
|
307
344
|
status: record.status,
|
|
308
345
|
completionPolicy: record.completionPolicy,
|
|
309
346
|
consumed: record.consumed,
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { redactTerminalSecret } from "./statusViewModel.js";
|
|
2
|
+
export const CLI_ONLY_SLASH_COMMANDS = [
|
|
3
|
+
{ id: "help", slash: "/help", description: "Show command help and keyboard controls.", group: "cli", support: "supported" },
|
|
4
|
+
{ id: "new", slash: "/new", description: "Create a new session in the active or selected room.", group: "navigation", support: "supported" },
|
|
5
|
+
{ id: "room", slash: "/room", description: "Select the active room in the app context.", group: "navigation", support: "supported" },
|
|
6
|
+
{ id: "session", slash: "/session", description: "Select a room, then open or create a session.", group: "navigation", support: "supported" },
|
|
7
|
+
{ id: "agent", slash: "/agent", description: "Select an existing agent/profile for the session.", group: "navigation", support: "supported" },
|
|
8
|
+
{ id: "profile", slash: "/profile", description: "Select an existing agent/profile for the session.", group: "navigation", support: "supported" },
|
|
9
|
+
{ id: "repair-user-unknown", slash: "/repair-user-unknown", description: "Repair legacy CLI sessions stored under user:unknown.", group: "cli", support: "supported" },
|
|
10
|
+
{ id: "exit", slash: "/exit", description: "Exit the terminal UI.", group: "cli", support: "supported", aliases: ["/quit"] },
|
|
11
|
+
{ id: "quit", slash: "/quit", description: "Exit the terminal UI.", group: "cli", support: "supported" },
|
|
12
|
+
];
|
|
13
|
+
export const WEB_PARITY_SLASH_COMMANDS = [
|
|
14
|
+
{ id: "status", slash: "/status", actionName: "status", description: "Show session, runtime, model, queue, and usage status.", group: "session", support: "supported" },
|
|
15
|
+
{ id: "compact", slash: "/compact", actionName: "compact", description: "Run session compaction when the runtime supports it.", group: "runtime", support: "terminal-adapted" },
|
|
16
|
+
{ id: "clear", slash: "/clear", actionName: "clear_queue", description: "Clear queued messages that have not started yet; terminal currently also clears local display.", group: "runtime", support: "terminal-adapted" },
|
|
17
|
+
{ id: "abort", slash: "/abort", actionName: "abort", description: "Abort the active response.", group: "runtime", support: "terminal-adapted" },
|
|
18
|
+
{ id: "kill", slash: "/kill", actionName: "kill", description: "Dispose the active session runtime.", group: "runtime", support: "terminal-adapted" },
|
|
19
|
+
{ id: "kill-all", slash: "/kill-all", actionName: "kill-all", description: "Dispose all routed runtimes for the selected app context when supported.", group: "runtime", support: "terminal-adapted" },
|
|
20
|
+
{ id: "fast", slash: "/fast", actionName: "fast_mode", description: "Toggle fast mode for the active session.", argumentHint: "[on|off]", group: "runtime", support: "terminal-adapted" },
|
|
21
|
+
{ id: "thinking", slash: "/thinking", actionName: "thinking", description: "Show or set model thinking level.", argumentHint: "[off|minimal|low|medium|high|xhigh]", group: "runtime", support: "terminal-adapted", terminalAdaptation: "Without an argument, open a keyboard picker." },
|
|
22
|
+
{ id: "model", slash: "/model", actionName: "model", description: "Choose an authenticated provider model.", group: "runtime", support: "terminal-adapted", terminalAdaptation: "Open provider and model pickers." },
|
|
23
|
+
{ id: "login", slash: "/login", actionName: "login", description: "Authenticate a model provider.", group: "runtime", support: "terminal-adapted", terminalAdaptation: "Show provider/auth-method instructions in terminal." },
|
|
24
|
+
{ id: "session-current", slash: "/session-current", actionName: "session-current", description: "Show metadata for the active session.", group: "session", support: "terminal-adapted" },
|
|
25
|
+
{ id: "sessions", slash: "/sessions", actionName: "sessions", description: "List sessions for the selected shared room.", group: "session", support: "terminal-adapted" },
|
|
26
|
+
{ id: "clone", slash: "/clone", actionName: "clone", description: "Clone or derive the active session when supported.", group: "session", support: "terminal-adapted" },
|
|
27
|
+
{ id: "fork-candidates", slash: "/fork-candidates", actionName: "session.fork_candidates", description: "Inspect terminal-selectable fork candidates.", argumentHint: "[entry-id]", group: "session", support: "terminal-adapted", terminalAdaptation: "Without an argument, list candidates; selecting one attempts a routed fork." },
|
|
28
|
+
{ id: "download", slash: "/download", actionName: "download", description: "Show terminal-safe download instructions for a server path.", argumentHint: "<path>", group: "session", support: "terminal-adapted", terminalAdaptation: "Use shell/server paths instead of browser download APIs." },
|
|
29
|
+
{ id: "upload", slash: "/upload", actionName: "upload", description: "Show terminal-safe upload instructions for a local path.", argumentHint: "<path>", group: "session", support: "terminal-adapted", terminalAdaptation: "Use path-based terminal instructions instead of browser file picker APIs." },
|
|
30
|
+
{ id: "thinking-show", slash: "/thinking-show", actionName: "thinking", description: "Show thinking controls in Web.", group: "unsupported", support: "deferred", unsupportedReason: "Use /thinking in terminal." },
|
|
31
|
+
];
|
|
32
|
+
export function buildSlashCommandCatalog(capabilities = []) {
|
|
33
|
+
const bySlash = new Map();
|
|
34
|
+
for (const command of [...WEB_PARITY_SLASH_COMMANDS, ...CLI_ONLY_SLASH_COMMANDS])
|
|
35
|
+
bySlash.set(command.slash, command);
|
|
36
|
+
for (const capability of expandGatewayCommandCapabilities(capabilities)) {
|
|
37
|
+
if (capability.hidden)
|
|
38
|
+
continue;
|
|
39
|
+
const slash = normalizeSlash(capability.slash ?? capability.name);
|
|
40
|
+
if (!slash)
|
|
41
|
+
continue;
|
|
42
|
+
const existing = bySlash.get(slash);
|
|
43
|
+
if (existing && isCliOwnedCommand(existing) && capability.name !== undefined)
|
|
44
|
+
continue;
|
|
45
|
+
bySlash.set(slash, {
|
|
46
|
+
id: slash.slice(1),
|
|
47
|
+
slash,
|
|
48
|
+
actionName: capability.actionName ?? existing?.actionName ?? capability.name,
|
|
49
|
+
description: redactTerminalSecret(capability.description ?? existing?.description ?? `Run ${slash}.`),
|
|
50
|
+
argumentHint: capability.argumentHint ?? existing?.argumentHint,
|
|
51
|
+
group: capability.browserOnly || capability.productArea ? "unsupported" : existing?.group ?? "session",
|
|
52
|
+
support: supportForCapability(capability, existing),
|
|
53
|
+
unsupportedReason: redactTerminalSecret(capability.unsupportedReason ?? existing?.unsupportedReason ?? "") || undefined,
|
|
54
|
+
terminalAdaptation: existing?.terminalAdaptation,
|
|
55
|
+
aliases: existing?.aliases,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return [...bySlash.values()].sort((left, right) => left.slash.localeCompare(right.slash));
|
|
59
|
+
}
|
|
60
|
+
export function filterSlashCommands(catalog, input) {
|
|
61
|
+
const normalized = input.trim().split(/\s+/, 1)[0]?.toLowerCase() ?? "";
|
|
62
|
+
const prefix = normalized.startsWith("/") ? normalized : `/${normalized}`;
|
|
63
|
+
return catalog.filter((command) => command.slash.toLowerCase().startsWith(prefix) || command.aliases?.some((alias) => alias.toLowerCase().startsWith(prefix)));
|
|
64
|
+
}
|
|
65
|
+
export function formatSlashCommand(command) {
|
|
66
|
+
return `${command.slash}${command.argumentHint ? ` ${command.argumentHint}` : ""}`;
|
|
67
|
+
}
|
|
68
|
+
export function commandSupportLabel(command) {
|
|
69
|
+
if (command.support === "supported")
|
|
70
|
+
return "available";
|
|
71
|
+
if (command.support === "terminal-adapted")
|
|
72
|
+
return "terminal";
|
|
73
|
+
if (command.support === "browser-only")
|
|
74
|
+
return "browser-only";
|
|
75
|
+
if (command.support === "product-area")
|
|
76
|
+
return "product-area";
|
|
77
|
+
return "deferred";
|
|
78
|
+
}
|
|
79
|
+
export function groupSlashCommandsForHelp(catalog) {
|
|
80
|
+
return {
|
|
81
|
+
available: catalog.filter((command) => (command.group === "session" || command.group === "runtime") && (command.support === "supported" || command.support === "terminal-adapted")),
|
|
82
|
+
navigation: catalog.filter((command) => command.group === "navigation" || command.group === "cli"),
|
|
83
|
+
unsupported: catalog.filter((command) => command.group === "unsupported" || command.support === "browser-only" || command.support === "product-area" || command.support === "deferred"),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export function buildSlashCommandBehaviorMatrix(catalog = buildSlashCommandCatalog()) {
|
|
87
|
+
return catalog.map((command) => ({
|
|
88
|
+
id: command.id,
|
|
89
|
+
slash: command.slash,
|
|
90
|
+
aliases: command.aliases ?? [],
|
|
91
|
+
group: command.group,
|
|
92
|
+
support: command.support,
|
|
93
|
+
supportLabel: commandSupportLabel(command),
|
|
94
|
+
palette: "shown",
|
|
95
|
+
argumentBehavior: slashArgumentBehavior(command),
|
|
96
|
+
enterBehavior: slashEnterBehavior(command),
|
|
97
|
+
resultPlacement: slashResultPlacement(command),
|
|
98
|
+
contextRequirement: slashContextRequirement(command),
|
|
99
|
+
errorBehavior: slashErrorBehavior(command),
|
|
100
|
+
terminalAdaptation: command.terminalAdaptation,
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
function slashArgumentBehavior(command) {
|
|
104
|
+
if (command.argumentHint)
|
|
105
|
+
return command.argumentHint;
|
|
106
|
+
if (command.slash === "/model")
|
|
107
|
+
return "no argument opens provider/model picker; provider/model applies selection";
|
|
108
|
+
if (command.slash === "/login")
|
|
109
|
+
return "no argument opens provider/auth picker; provider/method applies selection";
|
|
110
|
+
if (command.slash === "/thinking")
|
|
111
|
+
return "no argument opens thinking picker; level applies selection";
|
|
112
|
+
return "none";
|
|
113
|
+
}
|
|
114
|
+
function slashEnterBehavior(command) {
|
|
115
|
+
if (command.slash === "/help")
|
|
116
|
+
return "append help text above transcript guidance";
|
|
117
|
+
if (command.slash === "/new")
|
|
118
|
+
return "create session in active or selected room";
|
|
119
|
+
if (["/room", "/session", "/profile", "/agent"].includes(command.slash))
|
|
120
|
+
return "open keyboard picker overlay";
|
|
121
|
+
if (["/exit", "/quit"].includes(command.slash))
|
|
122
|
+
return "exit terminal UI";
|
|
123
|
+
if (command.slash === "/repair-user-unknown")
|
|
124
|
+
return "append compact repair result";
|
|
125
|
+
if (["/model", "/login", "/thinking"].includes(command.slash))
|
|
126
|
+
return "open picker without arguments or append result with arguments";
|
|
127
|
+
if (command.slash === "/fork-candidates")
|
|
128
|
+
return "open candidate picker without entry id or dispatch fork with entry id";
|
|
129
|
+
if (command.support === "browser-only" || command.support === "product-area" || command.support === "deferred")
|
|
130
|
+
return "append unsupported/deferred transcript result";
|
|
131
|
+
return "append command and result rows to transcript";
|
|
132
|
+
}
|
|
133
|
+
function slashResultPlacement(command) {
|
|
134
|
+
if (["/exit", "/quit"].includes(command.slash))
|
|
135
|
+
return "exit";
|
|
136
|
+
if (["/room", "/session", "/profile", "/agent"].includes(command.slash))
|
|
137
|
+
return "overlay";
|
|
138
|
+
if (command.slash === "/new")
|
|
139
|
+
return "navigation";
|
|
140
|
+
if (["/model", "/login", "/thinking", "/fork-candidates"].includes(command.slash))
|
|
141
|
+
return "transcript-or-overlay";
|
|
142
|
+
return "transcript";
|
|
143
|
+
}
|
|
144
|
+
function slashContextRequirement(command) {
|
|
145
|
+
if (["/room", "/session", "/new", "/profile", "/repair-user-unknown"].includes(command.slash))
|
|
146
|
+
return "app room/session navigation";
|
|
147
|
+
if (["/status", "/sessions", "/session-current", "/clone", "/fork-candidates"].includes(command.slash))
|
|
148
|
+
return "active session when available; named room context preferred";
|
|
149
|
+
if (["/compact", "/clear", "/abort", "/kill", "/kill-all", "/fast", "/thinking", "/model", "/login"].includes(command.slash))
|
|
150
|
+
return "active routed session/runtime";
|
|
151
|
+
if (["/download", "/upload"].includes(command.slash))
|
|
152
|
+
return "terminal path argument";
|
|
153
|
+
return "none";
|
|
154
|
+
}
|
|
155
|
+
function slashErrorBehavior(command) {
|
|
156
|
+
if (command.support === "browser-only" || command.support === "product-area" || command.support === "deferred")
|
|
157
|
+
return "render compact unsupported result";
|
|
158
|
+
if (["/room", "/session", "/profile", "/agent", "/model", "/login", "/thinking", "/fork-candidates"].includes(command.slash))
|
|
159
|
+
return "keep overlay compact or append redacted error row after confirmed action";
|
|
160
|
+
return "append redacted command error row";
|
|
161
|
+
}
|
|
162
|
+
function expandGatewayCommandCapabilities(capabilities) {
|
|
163
|
+
const expanded = [];
|
|
164
|
+
for (const capability of capabilities) {
|
|
165
|
+
if (capability.slashCommands && capability.slashCommands.length > 0) {
|
|
166
|
+
for (const slash of capability.slashCommands)
|
|
167
|
+
expanded.push({ ...capability, slash, actionName: capability.actionName ?? capability.name });
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
expanded.push(capability);
|
|
171
|
+
}
|
|
172
|
+
return expanded;
|
|
173
|
+
}
|
|
174
|
+
function isCliOwnedCommand(command) {
|
|
175
|
+
return command.group === "cli" || command.slash === "/new" || command.slash === "/room" || command.slash === "/session" || command.slash === "/agent" || command.slash === "/profile";
|
|
176
|
+
}
|
|
177
|
+
function normalizeSlash(value) {
|
|
178
|
+
if (!value)
|
|
179
|
+
return undefined;
|
|
180
|
+
const trimmed = value.trim().toLowerCase();
|
|
181
|
+
if (!trimmed)
|
|
182
|
+
return undefined;
|
|
183
|
+
return (trimmed.startsWith("/") ? trimmed : `/${trimmed}`);
|
|
184
|
+
}
|
|
185
|
+
function supportForCapability(capability, existing) {
|
|
186
|
+
if (capability.browserOnly)
|
|
187
|
+
return "browser-only";
|
|
188
|
+
if (capability.productArea)
|
|
189
|
+
return "product-area";
|
|
190
|
+
if (capability.supported === false)
|
|
191
|
+
return "deferred";
|
|
192
|
+
return existing?.support ?? "terminal-adapted";
|
|
193
|
+
}
|