waterplane 0.1.6 → 0.1.11
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/CHANGELOG.md +92 -1
- package/README.md +1 -1
- package/SECURITY.md +11 -3
- package/deploy/node-version +1 -1
- package/node_modules/@waterplane/shared/dist/agentfiles.d.ts +17 -0
- package/node_modules/@waterplane/shared/dist/agentfiles.js +58 -4
- package/node_modules/@waterplane/shared/dist/agentfiles.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/alwaysonwords.d.ts +83 -0
- package/node_modules/@waterplane/shared/dist/alwaysonwords.js +209 -0
- package/node_modules/@waterplane/shared/dist/alwaysonwords.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/autocompact.js +1 -1
- package/node_modules/@waterplane/shared/dist/autocompact.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/backendsources.d.ts +11 -1
- package/node_modules/@waterplane/shared/dist/backendsources.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/branchmode.d.ts +27 -0
- package/node_modules/@waterplane/shared/dist/branchmode.js +80 -0
- package/node_modules/@waterplane/shared/dist/branchmode.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/buildstamp.d.ts +37 -0
- package/node_modules/@waterplane/shared/dist/buildstamp.js +95 -0
- package/node_modules/@waterplane/shared/dist/buildstamp.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/burn.d.ts +16 -1
- package/node_modules/@waterplane/shared/dist/burn.js +30 -0
- package/node_modules/@waterplane/shared/dist/burn.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/changebrief.d.ts +61 -0
- package/node_modules/@waterplane/shared/dist/changebrief.js +70 -0
- package/node_modules/@waterplane/shared/dist/changebrief.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/desktopfiles.d.ts +100 -0
- package/node_modules/@waterplane/shared/dist/desktopfiles.js +192 -0
- package/node_modules/@waterplane/shared/dist/desktopfiles.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/exposure.d.ts +175 -0
- package/node_modules/@waterplane/shared/dist/exposure.js +357 -0
- package/node_modules/@waterplane/shared/dist/exposure.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/exposurepush.d.ts +60 -0
- package/node_modules/@waterplane/shared/dist/exposurepush.js +103 -0
- package/node_modules/@waterplane/shared/dist/exposurepush.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/healthindex/commits.d.ts +26 -0
- package/node_modules/@waterplane/shared/dist/healthindex/commits.js +57 -0
- package/node_modules/@waterplane/shared/dist/healthindex/commits.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/healthindex/move.d.ts +25 -0
- package/node_modules/@waterplane/shared/dist/healthindex/move.js +79 -0
- package/node_modules/@waterplane/shared/dist/healthindex/move.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/healthindex/readings.d.ts +53 -0
- package/node_modules/@waterplane/shared/dist/healthindex/readings.js +154 -0
- package/node_modules/@waterplane/shared/dist/healthindex/readings.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/healthindex/repoindex.d.ts +41 -0
- package/node_modules/@waterplane/shared/dist/healthindex/repoindex.js +19 -0
- package/node_modules/@waterplane/shared/dist/healthindex/repoindex.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/healthindex/score.d.ts +26 -0
- package/node_modules/@waterplane/shared/dist/healthindex/score.js +154 -0
- package/node_modules/@waterplane/shared/dist/healthindex/score.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/healthindex/types.d.ts +206 -0
- package/node_modules/@waterplane/shared/dist/healthindex/types.js +58 -0
- package/node_modules/@waterplane/shared/dist/healthindex/types.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/healthindex/vs.d.ts +26 -0
- package/node_modules/@waterplane/shared/dist/healthindex/vs.js +38 -0
- package/node_modules/@waterplane/shared/dist/healthindex/vs.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/healthindex/words.d.ts +28 -0
- package/node_modules/@waterplane/shared/dist/healthindex/words.js +69 -0
- package/node_modules/@waterplane/shared/dist/healthindex/words.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/healthindex.d.ts +15 -411
- package/node_modules/@waterplane/shared/dist/healthindex.js +8 -602
- package/node_modules/@waterplane/shared/dist/healthindex.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/hints.js +5 -0
- package/node_modules/@waterplane/shared/dist/hints.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/index.d.ts +29 -0
- package/node_modules/@waterplane/shared/dist/index.js +29 -0
- package/node_modules/@waterplane/shared/dist/index.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/intent/kind.d.ts +31 -1
- package/node_modules/@waterplane/shared/dist/intent/kind.js +27 -3
- package/node_modules/@waterplane/shared/dist/intent/kind.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/intent.d.ts +1 -1
- package/node_modules/@waterplane/shared/dist/intent.js +1 -1
- package/node_modules/@waterplane/shared/dist/intent.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/launchmodes.d.ts +2 -0
- package/node_modules/@waterplane/shared/dist/launchmodes.js +12 -0
- package/node_modules/@waterplane/shared/dist/launchmodes.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/ledgerspan.d.ts +59 -0
- package/node_modules/@waterplane/shared/dist/ledgerspan.js +99 -0
- package/node_modules/@waterplane/shared/dist/ledgerspan.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/netretry.d.ts +38 -0
- package/node_modules/@waterplane/shared/dist/netretry.js +31 -0
- package/node_modules/@waterplane/shared/dist/netretry.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/netretrycfg.d.ts +12 -0
- package/node_modules/@waterplane/shared/dist/netretrycfg.js +27 -0
- package/node_modules/@waterplane/shared/dist/netretrycfg.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/nodemin.d.ts +6 -4
- package/node_modules/@waterplane/shared/dist/nodemin.js +6 -4
- package/node_modules/@waterplane/shared/dist/nodemin.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/optins.d.ts +35 -1
- package/node_modules/@waterplane/shared/dist/optins.js +39 -1
- package/node_modules/@waterplane/shared/dist/optins.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/plugin/api.d.ts +364 -0
- package/node_modules/@waterplane/shared/dist/plugin/api.js +2 -0
- package/node_modules/@waterplane/shared/dist/plugin/api.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/plugin/backend.d.ts +197 -0
- package/node_modules/@waterplane/shared/dist/plugin/backend.js +9 -0
- package/node_modules/@waterplane/shared/dist/plugin/backend.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/plugin/manifest.d.ts +160 -0
- package/node_modules/@waterplane/shared/dist/plugin/manifest.js +98 -0
- package/node_modules/@waterplane/shared/dist/plugin/manifest.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/plugin/module.d.ts +98 -0
- package/node_modules/@waterplane/shared/dist/plugin/module.js +13 -0
- package/node_modules/@waterplane/shared/dist/plugin/module.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/plugin/version.d.ts +64 -0
- package/node_modules/@waterplane/shared/dist/plugin/version.js +84 -0
- package/node_modules/@waterplane/shared/dist/plugin/version.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/plugin.d.ts +5 -867
- package/node_modules/@waterplane/shared/dist/plugin.js +27 -186
- package/node_modules/@waterplane/shared/dist/plugin.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/pluginlaunch.d.ts +7 -0
- package/node_modules/@waterplane/shared/dist/prview.d.ts +23 -0
- package/node_modules/@waterplane/shared/dist/prview.js +107 -0
- package/node_modules/@waterplane/shared/dist/prview.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/repohealth.d.ts +4 -0
- package/node_modules/@waterplane/shared/dist/repohealth.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/schedule/schedaction.d.ts +29 -0
- package/node_modules/@waterplane/shared/dist/schedule/schedaction.js +22 -0
- package/node_modules/@waterplane/shared/dist/schedule/schedaction.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/schedule/schedclean.js +26 -0
- package/node_modules/@waterplane/shared/dist/schedule/schedclean.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/schedule.d.ts +1 -1
- package/node_modules/@waterplane/shared/dist/schedule.js +1 -1
- package/node_modules/@waterplane/shared/dist/schedule.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/sessionbudget.d.ts +20 -5
- package/node_modules/@waterplane/shared/dist/sessionbudget.js +42 -16
- package/node_modules/@waterplane/shared/dist/sessionbudget.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/weekburn.d.ts +114 -0
- package/node_modules/@waterplane/shared/dist/weekburn.js +205 -0
- package/node_modules/@waterplane/shared/dist/weekburn.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/wire/alwayson.d.ts +64 -0
- package/node_modules/@waterplane/shared/dist/wire/alwayson.js +7 -0
- package/node_modules/@waterplane/shared/dist/wire/alwayson.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/wire/backend.d.ts +4 -0
- package/node_modules/@waterplane/shared/dist/wire/backendtokens.d.ts +6 -0
- package/node_modules/@waterplane/shared/dist/wire/backendtokens.js +0 -9
- package/node_modules/@waterplane/shared/dist/wire/backendtokens.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/wire/costwindow.d.ts +20 -0
- package/node_modules/@waterplane/shared/dist/wire/messages/clienthost.d.ts +15 -1
- package/node_modules/@waterplane/shared/dist/wire/messages/clientsession.d.ts +10 -0
- package/node_modules/@waterplane/shared/dist/wire/messages/hosttools.d.ts +12 -2
- package/node_modules/@waterplane/shared/dist/wire/notify.d.ts +129 -1
- package/node_modules/@waterplane/shared/dist/wire/notify.js +79 -1
- package/node_modules/@waterplane/shared/dist/wire/notify.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/wire/pullrequest.d.ts +42 -0
- package/node_modules/@waterplane/shared/dist/wire/pullrequest.js +2 -0
- package/node_modules/@waterplane/shared/dist/wire/pullrequest.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/wire/repo.d.ts +119 -0
- package/node_modules/@waterplane/shared/dist/wire/repo.js +8 -3
- package/node_modules/@waterplane/shared/dist/wire/repo.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/wire/sent.d.ts +3 -1
- package/node_modules/@waterplane/shared/dist/wire/session/contextspark.d.ts +7 -0
- package/node_modules/@waterplane/shared/dist/wire/session/info.d.ts +4 -1
- package/node_modules/@waterplane/shared/dist/wire/session/launch.d.ts +25 -0
- package/node_modules/@waterplane/shared/dist/wire/session.d.ts +1 -1
- package/node_modules/@waterplane/shared/dist/wire/telemetry.d.ts +4 -0
- package/node_modules/@waterplane/shared/dist/wire/work.d.ts +13 -0
- package/node_modules/@waterplane/shared/dist/wire/work.js.map +1 -1
- package/npm-shrinkwrap.json +3 -3
- package/package.json +2 -2
- package/packages/extensions/scorecard/waterplane-plugin.json +10 -0
- package/packages/host/dist/agentexposure.d.ts +13 -0
- package/packages/host/dist/agentexposure.js +90 -0
- package/packages/host/dist/agentexposure.js.map +1 -0
- package/packages/host/dist/agentintents.js +2 -2
- package/packages/host/dist/agentintents.js.map +1 -1
- package/packages/host/dist/agentwatch.d.ts +3 -7
- package/packages/host/dist/agentwatch.js.map +1 -1
- package/packages/host/dist/alwayson.d.ts +18 -0
- package/packages/host/dist/alwayson.js +159 -0
- package/packages/host/dist/alwayson.js.map +1 -0
- package/packages/host/dist/answergate.d.ts +3 -7
- package/packages/host/dist/answergate.js.map +1 -1
- package/packages/host/dist/attentionstore.d.ts +61 -0
- package/packages/host/dist/attentionstore.js +162 -0
- package/packages/host/dist/attentionstore.js.map +1 -0
- package/packages/host/dist/backends/claude.js +1 -1
- package/packages/host/dist/backends/claude.js.map +1 -1
- package/packages/host/dist/backends/derive.js +1 -0
- package/packages/host/dist/backends/derive.js.map +1 -1
- package/packages/host/dist/backends/registry.js +4 -1
- package/packages/host/dist/backends/registry.js.map +1 -1
- package/packages/host/dist/backends/types.d.ts +2 -0
- package/packages/host/dist/besidespend.d.ts +22 -0
- package/packages/host/dist/besidespend.js +65 -0
- package/packages/host/dist/besidespend.js.map +1 -0
- package/packages/host/dist/boxkit.d.ts +19 -0
- package/packages/host/dist/boxkit.js +38 -0
- package/packages/host/dist/boxkit.js.map +1 -0
- package/packages/host/dist/branchrules.d.ts +14 -0
- package/packages/host/dist/branchrules.js +47 -0
- package/packages/host/dist/branchrules.js.map +1 -0
- package/packages/host/dist/builds.d.ts +31 -1
- package/packages/host/dist/builds.js +55 -3
- package/packages/host/dist/builds.js.map +1 -1
- package/packages/host/dist/buildversions.d.ts +2 -0
- package/packages/host/dist/buildversions.js +36 -0
- package/packages/host/dist/buildversions.js.map +1 -0
- package/packages/host/dist/burnwatch.d.ts +23 -11
- package/packages/host/dist/burnwatch.js +51 -2
- package/packages/host/dist/burnwatch.js.map +1 -1
- package/packages/host/dist/changebrief.d.ts +37 -0
- package/packages/host/dist/changebrief.js +157 -0
- package/packages/host/dist/changebrief.js.map +1 -0
- package/packages/host/dist/cli/index.js +1 -1
- package/packages/host/dist/cli/index.js.map +1 -1
- package/packages/host/dist/clihealth.d.ts +2 -0
- package/packages/host/dist/clihealth.js +11 -2
- package/packages/host/dist/clihealth.js.map +1 -1
- package/packages/host/dist/compliance.d.ts +5 -1
- package/packages/host/dist/compliance.js +70 -31
- package/packages/host/dist/compliance.js.map +1 -1
- package/packages/host/dist/composer.d.ts +3 -1
- package/packages/host/dist/composer.js +3 -1
- package/packages/host/dist/composer.js.map +1 -1
- package/packages/host/dist/ctxlog/ctxcursor.d.ts +36 -1
- package/packages/host/dist/ctxlog/ctxcursor.js +96 -2
- package/packages/host/dist/ctxlog/ctxcursor.js.map +1 -1
- package/packages/host/dist/ctxlog/ctxproject.js +2 -1
- package/packages/host/dist/ctxlog/ctxproject.js.map +1 -1
- package/packages/host/dist/ctxlog/ctxupdate.js +13 -2
- package/packages/host/dist/ctxlog/ctxupdate.js.map +1 -1
- package/packages/host/dist/diskwatch.d.ts +4 -6
- package/packages/host/dist/diskwatch.js +3 -1
- package/packages/host/dist/diskwatch.js.map +1 -1
- package/packages/host/dist/eraseen.d.ts +6 -0
- package/packages/host/dist/eraseen.js +100 -0
- package/packages/host/dist/eraseen.js.map +1 -0
- package/packages/host/dist/exposure.d.ts +56 -0
- package/packages/host/dist/exposure.js +371 -0
- package/packages/host/dist/exposure.js.map +1 -0
- package/packages/host/dist/exposurepush.d.ts +28 -0
- package/packages/host/dist/exposurepush.js +136 -0
- package/packages/host/dist/exposurepush.js.map +1 -0
- package/packages/host/dist/exposurerun.d.ts +18 -0
- package/packages/host/dist/exposurerun.js +126 -0
- package/packages/host/dist/exposurerun.js.map +1 -0
- package/packages/host/dist/exposurewatch.d.ts +29 -0
- package/packages/host/dist/exposurewatch.js +127 -0
- package/packages/host/dist/exposurewatch.js.map +1 -0
- package/packages/host/dist/extensions/scorecard/host/engine.d.mts +54 -0
- package/packages/host/dist/extensions/scorecard/host/engine.mjs +303 -0
- package/packages/host/dist/extensions/scorecard/host/engine.mjs.map +1 -0
- package/packages/host/dist/extensions/scorecard/host/gitslug.d.mts +5 -0
- package/packages/host/dist/extensions/scorecard/host/gitslug.mjs +45 -0
- package/packages/host/dist/extensions/scorecard/host/gitslug.mjs.map +1 -0
- package/packages/host/dist/extensions/scorecard/host/index.d.mts +15 -0
- package/packages/host/dist/extensions/scorecard/host/index.mjs +47 -0
- package/packages/host/dist/extensions/scorecard/host/index.mjs.map +1 -0
- package/packages/host/dist/extensions/scorecard/host/store.d.mts +12 -0
- package/packages/host/dist/extensions/scorecard/host/store.mjs +91 -0
- package/packages/host/dist/extensions/scorecard/host/store.mjs.map +1 -0
- package/packages/host/dist/extensions/scorecard/shared/logic.d.mts +42 -0
- package/packages/host/dist/extensions/scorecard/shared/logic.mjs +170 -0
- package/packages/host/dist/extensions/scorecard/shared/logic.mjs.map +1 -0
- package/packages/host/dist/extensions/scorecard/shared/wire.d.mts +140 -0
- package/packages/host/dist/extensions/scorecard/shared/wire.mjs +29 -0
- package/packages/host/dist/extensions/scorecard/shared/wire.mjs.map +1 -0
- package/packages/host/dist/forge/github.d.ts +3 -0
- package/packages/host/dist/forge/github.js +82 -0
- package/packages/host/dist/forge/github.js.map +1 -0
- package/packages/host/dist/forge/index.d.ts +14 -0
- package/packages/host/dist/forge/index.js +32 -0
- package/packages/host/dist/forge/index.js.map +1 -0
- package/packages/host/dist/forge/types.d.ts +52 -0
- package/packages/host/dist/forge/types.js +2 -0
- package/packages/host/dist/forge/types.js.map +1 -0
- package/packages/host/dist/git.d.ts +36 -3
- package/packages/host/dist/git.js +119 -41
- package/packages/host/dist/git.js.map +1 -1
- package/packages/host/dist/gitnotify.d.ts +24 -0
- package/packages/host/dist/gitnotify.js +60 -0
- package/packages/host/dist/gitnotify.js.map +1 -0
- package/packages/host/dist/healthwatch.d.ts +2 -1
- package/packages/host/dist/healthwatch.js +4 -2
- package/packages/host/dist/healthwatch.js.map +1 -1
- package/packages/host/dist/intents/adapters.js +45 -14
- package/packages/host/dist/intents/adapters.js.map +1 -1
- package/packages/host/dist/intents/contract.d.ts +4 -0
- package/packages/host/dist/intents/contract.js.map +1 -1
- package/packages/host/dist/intents/fire.js +7 -1
- package/packages/host/dist/intents/fire.js.map +1 -1
- package/packages/host/dist/intents/manager.d.ts +3 -3
- package/packages/host/dist/intents/manager.js +2 -2
- package/packages/host/dist/intents/manager.js.map +1 -1
- package/packages/host/dist/intents/watch.d.ts +10 -2
- package/packages/host/dist/intents/watch.js +27 -2
- package/packages/host/dist/intents/watch.js.map +1 -1
- package/packages/host/dist/localcistatus.d.ts +22 -0
- package/packages/host/dist/localcistatus.js +105 -0
- package/packages/host/dist/localcistatus.js.map +1 -0
- package/packages/host/dist/main.js +40 -10
- package/packages/host/dist/main.js.map +1 -1
- package/packages/host/dist/net.d.ts +2 -0
- package/packages/host/dist/net.js +11 -2
- package/packages/host/dist/net.js.map +1 -1
- package/packages/host/dist/netlog.d.ts +40 -0
- package/packages/host/dist/netlog.js +165 -0
- package/packages/host/dist/netlog.js.map +1 -0
- package/packages/host/dist/netretrycfg.d.ts +7 -0
- package/packages/host/dist/netretrycfg.js +51 -0
- package/packages/host/dist/netretrycfg.js.map +1 -0
- package/packages/host/dist/notifyprefs.d.ts +6 -2
- package/packages/host/dist/notifyprefs.js +20 -5
- package/packages/host/dist/notifyprefs.js.map +1 -1
- package/packages/host/dist/notifytypes.d.ts +58 -0
- package/packages/host/dist/notifytypes.js +2 -0
- package/packages/host/dist/notifytypes.js.map +1 -0
- package/packages/host/dist/opendeliveries.js +24 -0
- package/packages/host/dist/opendeliveries.js.map +1 -1
- package/packages/host/dist/optins.d.ts +28 -1
- package/packages/host/dist/optins.js +96 -4
- package/packages/host/dist/optins.js.map +1 -1
- package/packages/host/dist/peers/agentpeer.js +1 -1
- package/packages/host/dist/peers/agentpeer.js.map +1 -1
- package/packages/host/dist/peers/jobs.d.ts +2 -4
- package/packages/host/dist/peers/jobs.js +6 -1
- package/packages/host/dist/peers/jobs.js.map +1 -1
- package/packages/host/dist/plugins/pluginapi.js +2 -0
- package/packages/host/dist/plugins/pluginapi.js.map +1 -1
- package/packages/host/dist/plugins/pluginregistry.d.ts +3 -8
- package/packages/host/dist/plugins/pluginregistry.js +1 -1
- package/packages/host/dist/plugins/pluginregistry.js.map +1 -1
- package/packages/host/dist/protectmain.d.ts +35 -0
- package/packages/host/dist/protectmain.js +73 -0
- package/packages/host/dist/protectmain.js.map +1 -0
- package/packages/host/dist/prpush.d.ts +30 -0
- package/packages/host/dist/prpush.js +171 -0
- package/packages/host/dist/prpush.js.map +1 -0
- package/packages/host/dist/prs.d.ts +70 -0
- package/packages/host/dist/prs.js +328 -0
- package/packages/host/dist/prs.js.map +1 -0
- package/packages/host/dist/push.d.ts +19 -0
- package/packages/host/dist/push.js.map +1 -1
- package/packages/host/dist/render.d.ts +57 -0
- package/packages/host/dist/render.js +57 -39
- package/packages/host/dist/render.js.map +1 -1
- package/packages/host/dist/repohealth.js +5 -2
- package/packages/host/dist/repohealth.js.map +1 -1
- package/packages/host/dist/repohealthapproval.d.ts +3 -0
- package/packages/host/dist/repohealthapproval.js +92 -2
- package/packages/host/dist/repohealthapproval.js.map +1 -1
- package/packages/host/dist/repos.js +7 -1
- package/packages/host/dist/repos.js.map +1 -1
- package/packages/host/dist/reposkill.d.ts +8 -5
- package/packages/host/dist/reposkill.js +16 -11
- package/packages/host/dist/reposkill.js.map +1 -1
- package/packages/host/dist/reposkilltext.d.ts +8 -1
- package/packages/host/dist/reposkilltext.js +72 -3
- package/packages/host/dist/reposkilltext.js.map +1 -1
- package/packages/host/dist/routes/apihost.js +26 -2
- package/packages/host/dist/routes/apihost.js.map +1 -1
- package/packages/host/dist/routes/apiprs.d.ts +2 -0
- package/packages/host/dist/routes/apiprs.js +45 -0
- package/packages/host/dist/routes/apiprs.js.map +1 -0
- package/packages/host/dist/routes/apirepofiles.js +12 -1
- package/packages/host/dist/routes/apirepofiles.js.map +1 -1
- package/packages/host/dist/routes/apirepowork.js +48 -24
- package/packages/host/dist/routes/apirepowork.js.map +1 -1
- package/packages/host/dist/routes/apiroutes.js +2 -1
- package/packages/host/dist/routes/apiroutes.js.map +1 -1
- package/packages/host/dist/routes/apisession.js +24 -0
- package/packages/host/dist/routes/apisession.js.map +1 -1
- package/packages/host/dist/routes/apistats.js +12 -7
- package/packages/host/dist/routes/apistats.js.map +1 -1
- package/packages/host/dist/routes/apisystem.js +23 -1
- package/packages/host/dist/routes/apisystem.js.map +1 -1
- package/packages/host/dist/routes/apitable.d.ts +10 -0
- package/packages/host/dist/routes/apitable.js.map +1 -1
- package/packages/host/dist/routes/apiweekburn.d.ts +2 -0
- package/packages/host/dist/routes/apiweekburn.js +30 -0
- package/packages/host/dist/routes/apiweekburn.js.map +1 -0
- package/packages/host/dist/routes/session.js +4 -0
- package/packages/host/dist/routes/session.js.map +1 -1
- package/packages/host/dist/routes/system.js +33 -6
- package/packages/host/dist/routes/system.js.map +1 -1
- package/packages/host/dist/routes/types.d.ts +29 -21
- package/packages/host/dist/routes/work/workbuild.js +3 -2
- package/packages/host/dist/routes/work/workbuild.js.map +1 -1
- package/packages/host/dist/routes/work/workschedule.js +33 -3
- package/packages/host/dist/routes/work/workschedule.js.map +1 -1
- package/packages/host/dist/screenlog.d.ts +20 -0
- package/packages/host/dist/screenlog.js +40 -0
- package/packages/host/dist/screenlog.js.map +1 -1
- package/packages/host/dist/server/clients.d.ts +14 -24
- package/packages/host/dist/server/clients.js +77 -11
- package/packages/host/dist/server/clients.js.map +1 -1
- package/packages/host/dist/server/ctx.d.ts +2 -0
- package/packages/host/dist/server/ctxseal.d.ts +1 -1
- package/packages/host/dist/server/ctxseal.js +6 -6
- package/packages/host/dist/server/ctxseal.js.map +1 -1
- package/packages/host/dist/server/deliveries.js +4 -2
- package/packages/host/dist/server/deliveries.js.map +1 -1
- package/packages/host/dist/server/http.js +2 -2
- package/packages/host/dist/server/http.js.map +1 -1
- package/packages/host/dist/server/intentDeps.js +4 -1
- package/packages/host/dist/server/intentDeps.js.map +1 -1
- package/packages/host/dist/server/intentEvents.js +9 -4
- package/packages/host/dist/server/intentEvents.js.map +1 -1
- package/packages/host/dist/server/scan.js +23 -1
- package/packages/host/dist/server/scan.js.map +1 -1
- package/packages/host/dist/server/sessionEvents.js +37 -10
- package/packages/host/dist/server/sessionEvents.js.map +1 -1
- package/packages/host/dist/sessions/agentpoll.d.ts +31 -0
- package/packages/host/dist/sessions/agentpoll.js +176 -0
- package/packages/host/dist/sessions/agentpoll.js.map +1 -0
- package/packages/host/dist/sessions/apiretry.d.ts +59 -0
- package/packages/host/dist/sessions/apiretry.js +240 -0
- package/packages/host/dist/sessions/apiretry.js.map +1 -0
- package/packages/host/dist/sessions/askwatch.d.ts +62 -0
- package/packages/host/dist/sessions/askwatch.js +169 -0
- package/packages/host/dist/sessions/askwatch.js.map +1 -0
- package/packages/host/dist/sessions/boxes.d.ts +2 -23
- package/packages/host/dist/sessions/boxes.js +10 -664
- package/packages/host/dist/sessions/boxes.js.map +1 -1
- package/packages/host/dist/sessions/boxread.d.ts +47 -0
- package/packages/host/dist/sessions/boxread.js +628 -0
- package/packages/host/dist/sessions/boxread.js.map +1 -0
- package/packages/host/dist/sessions/core.d.ts +16 -1
- package/packages/host/dist/sessions/ctxseries.js +3 -0
- package/packages/host/dist/sessions/ctxseries.js.map +1 -1
- package/packages/host/dist/sessions/drive.d.ts +20 -6
- package/packages/host/dist/sessions/drive.js +43 -8
- package/packages/host/dist/sessions/drive.js.map +1 -1
- package/packages/host/dist/sessions/knobs.d.ts +8 -0
- package/packages/host/dist/sessions/knobs.js +9 -0
- package/packages/host/dist/sessions/knobs.js.map +1 -1
- package/packages/host/dist/sessions/record.js +7 -2
- package/packages/host/dist/sessions/record.js.map +1 -1
- package/packages/host/dist/sessions/resume.d.ts +17 -0
- package/packages/host/dist/sessions/resume.js +65 -11
- package/packages/host/dist/sessions/resume.js.map +1 -1
- package/packages/host/dist/sessions/roster.js +3 -0
- package/packages/host/dist/sessions/roster.js.map +1 -1
- package/packages/host/dist/sessions/sidechannel.d.ts +1 -1
- package/packages/host/dist/sessions/sidechannel.js +2 -2
- package/packages/host/dist/sessions/turn.d.ts +15 -58
- package/packages/host/dist/sessions/turn.js +17 -356
- package/packages/host/dist/sessions/turn.js.map +1 -1
- package/packages/host/dist/sessions.d.ts +7 -1
- package/packages/host/dist/sessions.js +22 -13
- package/packages/host/dist/sessions.js.map +1 -1
- package/packages/host/dist/settle.d.ts +6 -0
- package/packages/host/dist/settle.js +26 -21
- package/packages/host/dist/settle.js.map +1 -1
- package/packages/host/dist/setupprefs.d.ts +26 -1
- package/packages/host/dist/setupprefs.js +49 -1
- package/packages/host/dist/setupprefs.js.map +1 -1
- package/packages/host/dist/sidecar/sidecarname.d.ts +2 -0
- package/packages/host/dist/sidecar/sidecarname.js +5 -1
- package/packages/host/dist/sidecar/sidecarname.js.map +1 -1
- package/packages/host/dist/sidecar/sidecarroute.d.ts +1 -1
- package/packages/host/dist/sidecar/sidecarroute.js +5 -0
- package/packages/host/dist/sidecar/sidecarroute.js.map +1 -1
- package/packages/host/dist/sidecar.d.ts +1 -1
- package/packages/host/dist/sidecar.js +1 -1
- package/packages/host/dist/sidecar.js.map +1 -1
- package/packages/host/dist/tokenscan.d.ts +4 -0
- package/packages/host/dist/tokenscan.js +6 -1
- package/packages/host/dist/tokenscan.js.map +1 -1
- package/packages/host/dist/tokenstats.js +3 -1
- package/packages/host/dist/tokenstats.js.map +1 -1
- package/packages/host/dist/transcript/transcriptparse.js +6 -1
- package/packages/host/dist/transcript/transcriptparse.js.map +1 -1
- package/packages/host/dist/transcript/transcriptturns.d.ts +29 -0
- package/packages/host/dist/transcript/transcriptturns.js +27 -0
- package/packages/host/dist/transcript/transcriptturns.js.map +1 -1
- package/packages/host/dist/transcript.d.ts +1 -1
- package/packages/host/dist/transcript.js +1 -1
- package/packages/host/dist/transcript.js.map +1 -1
- package/packages/host/dist/usagesources.d.ts +1 -1
- package/packages/host/dist/usagesources.js +7 -2
- package/packages/host/dist/usagesources.js.map +1 -1
- package/packages/host/dist/weekburn.d.ts +75 -0
- package/packages/host/dist/weekburn.js +251 -0
- package/packages/host/dist/weekburn.js.map +1 -0
- package/packages/host/dist/worktreeleftover.d.ts +9 -0
- package/packages/host/dist/worktreeleftover.js +17 -1
- package/packages/host/dist/worktreeleftover.js.map +1 -1
- package/packages/web/dist/assets/demo-C1GHaeTv.js +23 -0
- package/packages/web/dist/assets/icons-DlcvcZoo.js +1 -0
- package/packages/web/dist/assets/index-BBc6xwDA.css +1 -0
- package/packages/web/dist/assets/index-DzQKnksZ.js +169 -0
- package/packages/web/dist/assets/shared-Cl34umPA.js +47 -0
- package/packages/web/dist/assets/{sheets-Bjv2L-cG.css → sheets-DoUhPGK0.css} +1 -1
- package/packages/web/dist/assets/sheets-_3_SvXAx.js +220 -0
- package/packages/web/dist/build-id.txt +1 -1
- package/packages/web/dist/buildstamp.json +1 -0
- package/packages/web/dist/index.html +7 -7
- package/packages/web/dist/sw.js +14 -3
- package/release.json +7 -4
- package/packages/web/dist/assets/demo-CXlqlYE4.js +0 -23
- package/packages/web/dist/assets/icons-BbqDBVjw.js +0 -1
- package/packages/web/dist/assets/index-CgPoyb3Y.css +0 -1
- package/packages/web/dist/assets/index-D5JKj8DK.js +0 -169
- package/packages/web/dist/assets/shared-eyaskl5l.js +0 -47
- package/packages/web/dist/assets/sheets-BzzL2re1.js +0 -204
|
@@ -1,403 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The choice box:
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Reasoning: `waterplane-heuristics` (`prompt.ts`, `ocprompt.ts`, `askbox.ts`,
|
|
8
|
-
* `login.ts`) and docs/notes/host-architecture.md.
|
|
2
|
+
* The choice box, ANSWERED: the one answer dispatcher (`answerBox`), the two
|
|
3
|
+
* walks that place a selection before pressing Return (`choosePromptBox`,
|
|
4
|
+
* `chooseClaudeNavBox`) and the checkbox Submit row (`submitPromptBox`).
|
|
5
|
+
* Reading and publishing the box is `boxread.ts`. Stateless — every per-session
|
|
6
|
+
* fact lives on the `Session` record.
|
|
9
7
|
*/
|
|
10
8
|
import { answerTextProblem } from "@waterplane/shared";
|
|
11
9
|
import { answerSourcePlan, applySourceReply } from "../sourceanswer.js";
|
|
12
|
-
export { sourceKeysProblem } from "../sourceanswer.js";
|
|
13
10
|
import { screenReaderFor } from "../backends/readers.js";
|
|
14
11
|
import { derive } from "../backends/derive.js";
|
|
15
|
-
import {
|
|
16
|
-
import { asksFromCall, descFor, pendingAskQuestions, pendingAskRecord, pickAsk, recoverHead } from "../askbox.js";
|
|
17
|
-
import { isPlanBox, planPathFor, readPlan } from "../planbox.js";
|
|
18
|
-
import { detectLimitText, STOP_WAIT_RE } from "../limit.js";
|
|
19
|
-
import { detectLogin, loginCandidate, sameLogin } from "../login.js";
|
|
20
|
-
import { logMtime, transcriptPath } from "../transcript.js";
|
|
21
|
-
import { recordSent } from "../sentlog.js";
|
|
12
|
+
import { navToSubmit, readNavBox } from "../prompt.js";
|
|
22
13
|
import { rememberRule, sessionAskRules } from "../answergate.js";
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
* The tail of a screen ending at the row a matcher was looking for.
|
|
26
|
-
*
|
|
27
|
-
* Anchored on the MATCHED row rather than sliced off the bottom, for the same
|
|
28
|
-
* reason `deliver.ts` places its echo instead of taking the last N rows: the
|
|
29
|
-
* bottom of a claude screen is the composer and the working line, and a sample
|
|
30
|
-
* that shows those says nothing about the box above them.
|
|
31
|
-
*/
|
|
32
|
-
/** How long the `askbox.enrich` fixture waits for the log to write the call: 2 min. */
|
|
33
|
-
const ASK_RECORD_POLLS = 60;
|
|
34
|
-
const ASK_RECORD_POLL_MS = 2_000;
|
|
35
|
-
function healthTail(screen, anchor) {
|
|
36
|
-
const rows = screen.split("\n");
|
|
37
|
-
let hit = -1;
|
|
38
|
-
for (let i = rows.length - 1; i >= 0; i--)
|
|
39
|
-
if (anchor(rows[i])) {
|
|
40
|
-
hit = i;
|
|
41
|
-
break;
|
|
42
|
-
}
|
|
43
|
-
if (hit < 0)
|
|
44
|
-
hit = rows.length - 1;
|
|
45
|
-
return rows.slice(Math.max(0, hit - HEALTH_SAMPLE_ROWS + 1), hit + 1).join("\n");
|
|
46
|
-
}
|
|
47
|
-
export function scheduleChecks(core, s) {
|
|
48
|
-
if (s.idleTimer)
|
|
49
|
-
clearTimeout(s.idleTimer);
|
|
50
|
-
s.idleTimer = setTimeout(() => core.checkIdle(s), IDLE_PING_MS);
|
|
51
|
-
// Output on a hooked session with no turn in flight: the hooks say nothing
|
|
52
|
-
// is running, and the CLI may be working anyway (`/compact` announces
|
|
53
|
-
// nothing, and a `Stop` a hook blocked leaves the turn going). One armed
|
|
54
|
-
// timer, never restarted while a pass is already pending, and it costs a
|
|
55
|
-
// regex over ONE repaint — see `checkTurnWatch`. A session with a turn the
|
|
56
|
-
// hooks DO own is left to them.
|
|
57
|
-
// Not while a backend's own channel reports EXACT turns: those boundaries are
|
|
58
|
-
// exact by definition, and `workingLine` is claude's working line — pointed
|
|
59
|
-
// at another TUI it could only ever match something else. A channel whose
|
|
60
|
-
// ends are requests (`verifyEnds`: claude's hook pipe) keeps the watch.
|
|
61
|
-
const exactTurns = !!s.channel?.turnsLive && !s.backend.sources?.turns?.verifyEnds;
|
|
62
|
-
if (s.hooksActive && !exactTurns && !s.stopVerifyTimer && !s.turnActive)
|
|
63
|
-
core.armTurnWatch(s);
|
|
64
|
-
// The prompt check is a debounce with a CEILING. A pure debounce never fires
|
|
65
|
-
// while a box is up — the TUI repaints its working line every second or so,
|
|
66
|
-
// and each repaint pushed the check out again — which is exactly the state
|
|
67
|
-
// that needs publishing. `PROMPT_MAX_STALE_MS` since the last check that
|
|
68
|
-
// actually ran wins over the quiet window, so a repaint storm delays
|
|
69
|
-
// verification by a bounded amount instead of for ever.
|
|
70
|
-
// Measured from the start of THIS burst when the last check is older than the
|
|
71
|
-
// ceiling itself: after a quiet spell the ceiling has long expired, and taking
|
|
72
|
-
// it at face value fired the check at 0 ms on the burst's FIRST chunk — the
|
|
73
|
-
// first chunk of a box tmux is still painting. (`readTwice` is what keeps a
|
|
74
|
-
// half-painted read from being published; this only stops buying it.)
|
|
75
|
-
const now = Date.now();
|
|
76
|
-
const since = s.promptTimer || now - s.lastPromptCheckAt < PROMPT_MAX_STALE_MS ? s.lastPromptCheckAt : now;
|
|
77
|
-
const ceiling = since + PROMPT_MAX_STALE_MS - now;
|
|
78
|
-
armPromptCheck(core, s, Math.max(0, Math.min(PROMPT_CHECK_MS, ceiling)));
|
|
79
|
-
// A shell's links and codes (`shelllinks.ts`) on the same quiet tick; a
|
|
80
|
-
// session with turns never pays for that read.
|
|
81
|
-
if (s.backend.caps.turns === false)
|
|
82
|
-
core.armLinksCheck(s);
|
|
83
|
-
}
|
|
84
|
-
/** Arm the prompt check, EARLIEST-wins: a later caller may pull the check
|
|
85
|
-
* forward but never push a pending one back (that is what made the debounce
|
|
86
|
-
* starve under constant output). */
|
|
87
|
-
export function armPromptCheck(core, s, delayMs) {
|
|
88
|
-
const due = Date.now() + delayMs;
|
|
89
|
-
if (s.promptTimer && s.promptDueAt <= due)
|
|
90
|
-
return;
|
|
91
|
-
if (s.promptTimer)
|
|
92
|
-
clearTimeout(s.promptTimer);
|
|
93
|
-
s.promptDueAt = due;
|
|
94
|
-
s.promptTimer = setTimeout(() => { s.promptTimer = null; checkPrompt(core, s); }, delayMs);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Prompt detection runs in two stages. The cheap stage scans an ANSI-stripped
|
|
98
|
-
* byte window — fast enough for a per-quiet-period check, but a repaint-based
|
|
99
|
-
* TUI makes that window a shuffled, hole-punched approximation of the screen
|
|
100
|
-
* (fragments joined across cursor jumps, words missing letters). So a hit is
|
|
101
|
-
* only a CANDIDATE: it is re-detected against the RENDERED screen (headless VT
|
|
102
|
-
* replay, what a user actually sees) and that result is what we publish. The
|
|
103
|
-
* render is the expensive part, hence the gate — no candidate, no replay.
|
|
104
|
-
*
|
|
105
|
-
* Before this, garbled repaint fragments were surfaced verbatim as one-tap
|
|
106
|
-
* option labels, and phantom prompts flickered in and out mid-answer.
|
|
107
|
-
*/
|
|
108
|
-
function checkPrompt(core, s) {
|
|
109
|
-
if (!s.info.running)
|
|
110
|
-
return;
|
|
111
|
-
// A backend whose TUI draws no box this detector can read is a backend this
|
|
112
|
-
// check has nothing to say about. Not armed at all, rather than armed and
|
|
113
|
-
// publishing null: the strict stage costs a full VT replay per quiet period,
|
|
114
|
-
// and — the part that matters more — the only way a claude-shaped rule can
|
|
115
|
-
// "match" a screen it was never written for is by matching something else.
|
|
116
|
-
// The sign-in link rides on this same render, which is the right place for
|
|
117
|
-
// it too: a claude account's sign-in screen is not a fact about a binary
|
|
118
|
-
// that has no claude account.
|
|
119
|
-
const reader = derive(s.backend).screen("dialogs");
|
|
120
|
-
if (!reader)
|
|
121
|
-
return;
|
|
122
|
-
// The CLI's own channel is posing the dialogs: the screen reader stands down,
|
|
123
|
-
// because two readers on one box re-key its fingerprint (a card re-opened, a
|
|
124
|
-
// queued answer stale, a push). It comes back the moment the channel goes
|
|
125
|
-
// down (`sidechannel.ts`), and it also stays off for a box the channel
|
|
126
|
-
// published before it finished reconciling.
|
|
127
|
-
if (screenReaderOff(s))
|
|
128
|
-
return;
|
|
129
|
-
// Named readers, not a boolean: `prompt.ts`'s rules are claude's screen and
|
|
130
|
-
// nothing else, so a second TUI gets its own reader rather than a looser
|
|
131
|
-
// version of this one. See `backends/types.ts`.
|
|
132
|
-
// A reader a plugin contributed (`backends/readers.ts`) — opencode's, for one.
|
|
133
|
-
const nav = screenReaderFor(s.backend);
|
|
134
|
-
if (nav) {
|
|
135
|
-
checkNavBox(core, s, nav);
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
if (reader !== "claude-numbered")
|
|
139
|
-
return; // a contributed name whose plugin left: no reader, no box
|
|
140
|
-
// A pane in copy-mode is showing HISTORY, not the live screen: the rendered
|
|
141
|
-
// grid is wherever the user panned to, so an answered box scrolled back into
|
|
142
|
-
// view would be re-detected as live — an approve bar over a dialog that no
|
|
143
|
-
// longer exists, and an `awaitingInput` interlock on a session that is fine.
|
|
144
|
-
// The pane is unchanged underneath; the next check after the pan back down
|
|
145
|
-
// reads it. (`tmuxscroll.ts`.)
|
|
146
|
-
if (s.copyMode)
|
|
147
|
-
return;
|
|
148
|
-
s.lastPromptCheckAt = Date.now();
|
|
149
|
-
// Cheap stage runs LENIENT: the "❯" cursor and the Enter/Esc footer each sit
|
|
150
|
-
// on their own row, and a repaint can leave them outside the byte window while
|
|
151
|
-
// the option rows sit inside it. Demanding them here would drop a real prompt
|
|
152
|
-
// before it ever reached the render — no approve bar, no push. Strictness
|
|
153
|
-
// belongs on the rendered screen below, which is what gets published.
|
|
154
|
-
// A dialog we could NOT parse is still a blocked session, and the reader view
|
|
155
|
-
// has no terminal to notice it in — so the render is also paid for when the
|
|
156
|
-
// tail merely carries a box FOOTER, and an unparsable box publishes the
|
|
157
|
-
// weaker `awaitingInput` signal ("open the CLI") instead of nothing at all.
|
|
158
|
-
// "esc to interrupt" is deliberately not in DIALOG_FOOTER_RE: that is the
|
|
159
|
-
// TUI's working line, i.e. every busy session, i.e. a render per check.
|
|
160
|
-
// The window is a few repaints wide, not one: this TUI redraws a full screen
|
|
161
|
-
// in ~3 KB, and the footer is not the LAST thing it draws — a box whose
|
|
162
|
-
// preview pane was painted after it fell outside a one-frame window entirely.
|
|
163
|
-
// A regex over 12 KB every 600 ms of quiet costs nothing; missing the gate
|
|
164
|
-
// costs the whole feature. Stale bytes here only buy a render whose STRICT
|
|
165
|
-
// pass then publishes null, so a wide gate can't invent a phantom prompt.
|
|
166
|
-
const rawTail = s.scrollback.slice(-PROMPT_GATE_BYTES);
|
|
167
|
-
const tail = stripAnsi(rawTail);
|
|
168
|
-
const candidate = !!detectPrompt(rawTail, { lenient: true });
|
|
169
|
-
// A gate miss retires a prompt only when there is no PUBLISHED box to lose.
|
|
170
|
-
//
|
|
171
|
-
// "Only the strict verifier clears it" is the rule the miss counter below
|
|
172
|
-
// exists to enforce, and this exit sat outside it. The gate reads a fixed
|
|
173
|
-
// byte WINDOW, so a box whose own frame is a large fraction of that window —
|
|
174
|
-
// six options with a wrapped description each — plus the repaints that follow
|
|
175
|
-
// can push the footer out of view while the box is plainly still on screen,
|
|
176
|
-
// and the panel vanished with no misses spent. With a box published we fall
|
|
177
|
-
// through to the render and let the strict pass decide instead; a box that is
|
|
178
|
-
// genuinely gone leaves a screen carrying no dialog footer, which clears it on
|
|
179
|
-
// that same pass with no added latency.
|
|
180
|
-
// A sign-in link opens the gate on its own shape: claude 2.1.293's sign-in
|
|
181
|
-
// screen draws no dialog footer (`login.ts`'s `loginCandidate`).
|
|
182
|
-
if (!candidate && !hasDialogFooter(tail) && !s.info.prompt && !s.info.login && !loginCandidate(rawTail, tail)) {
|
|
183
|
-
s.promptGen++; // invalidates any render still in flight — the box is gone
|
|
184
|
-
s.promptMisses = 0;
|
|
185
|
-
s.promptPending = null;
|
|
186
|
-
applyPrompt(core, s, null);
|
|
187
|
-
setAwaiting(core, s, false);
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
if (s.promptRendering)
|
|
191
|
-
return;
|
|
192
|
-
s.promptRendering = true;
|
|
193
|
-
const gen = s.promptGen;
|
|
194
|
-
void core.screenText(s.info.id, 60)
|
|
195
|
-
.then((screen) => {
|
|
196
|
-
if (!s.info.running || s.promptGen !== gen)
|
|
197
|
-
return;
|
|
198
|
-
// The sign-in link rides on THIS render rather than paying for one of
|
|
199
|
-
// its own: the gate above opens on the link's shape (`loginCandidate`),
|
|
200
|
-
// so the replay is bought every time there is a link to find.
|
|
201
|
-
applyLogin(core, s, detectLogin(screen, s.scrollback));
|
|
202
|
-
const parsed = detectPrompt(screen);
|
|
203
|
-
if (parsed) {
|
|
204
|
-
s.promptMisses = 0;
|
|
205
|
-
// One box stays ONE box while the TUI repaints under it. The strict
|
|
206
|
-
// pass runs about twice a second and reads whatever is legible right
|
|
207
|
-
// now — which the console refreshing itself, a pan, or a box taller
|
|
208
|
-
// than the terminal all change — so a live question was re-published
|
|
209
|
-
// several times a minute under a new fingerprint. That re-opened a
|
|
210
|
-
// card the user had collapsed or hidden to answer at the desk, made
|
|
211
|
-
// queued answers stale and fired a push per repaint. `sameBox` /
|
|
212
|
-
// `mergeBox` in `prompt.ts` carry the reasoning; a box that is
|
|
213
|
-
// genuinely different is published as itself.
|
|
214
|
-
// The commit row's own word, off this same render — "Submit" on the
|
|
215
|
-
// last question of an ask, "Next" on every one before it.
|
|
216
|
-
const commit = parsed.multi ? navToSubmit(screen) : null;
|
|
217
|
-
const read = commit ? { ...parsed, submitLabel: commit.label } : parsed;
|
|
218
|
-
// Enriched BEFORE the comparison, not after: the enrichment is what
|
|
219
|
-
// carries `askId`, and that is the only handle `sameBox` can trust on
|
|
220
|
-
// the boxes that actually move.
|
|
221
|
-
const fresh = enrichPrompt(s, read);
|
|
222
|
-
const live = s.info.prompt;
|
|
223
|
-
const next = live && sameBox(live, fresh) ? mergeBox(live, fresh) : fresh;
|
|
224
|
-
// A box that is NEW, or that would change the published one, waits for
|
|
225
|
-
// a second read that agrees — see `readTwice`. The published box (if
|
|
226
|
-
// any) stays as it is meanwhile.
|
|
227
|
-
if (samePrompt(next, live ?? null))
|
|
228
|
-
s.promptPending = null;
|
|
229
|
-
else if (!readTwice(s, read)) {
|
|
230
|
-
armPromptCheck(core, s, PROMPT_SETTLE_MS);
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
applyPrompt(core, s, next);
|
|
234
|
-
setAwaiting(core, s, false);
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
// Nothing parsed — but a capture taken mid-repaint is a HALF-DRAWN box:
|
|
238
|
-
// the option rows are there and the cursor row (or a label, or the
|
|
239
|
-
// footer) is not yet redrawn. Publishing null on that is what made a
|
|
240
|
-
// live dialog blink: the panel unmounted, the next capture parsed it
|
|
241
|
-
// again, and around it went, about once a second. So while the screen
|
|
242
|
-
// still carries a dialog footer, keep the box we already published and
|
|
243
|
-
// count the miss; a box that is genuinely gone runs the counter out (or
|
|
244
|
-
// takes the cheap gate's exit above, which needs no misses at all).
|
|
245
|
-
// `dialogStillUp`, not merely "a footer is somewhere on this screen".
|
|
246
|
-
// This CLI scrolls rather than repainting an alt screen, so an answered
|
|
247
|
-
// box stays in the rendered tail for as long as the conversation takes
|
|
248
|
-
// to push it out — and the loose test read that corpse as a live
|
|
249
|
-
// question, which both kept the retired box published for its full miss
|
|
250
|
-
// budget and raised `awaitingInput` on a session sitting at an idle
|
|
251
|
-
// composer.
|
|
252
|
-
s.promptPending = null; // agreement is between CONSECUTIVE reads
|
|
253
|
-
const dialog = dialogStillUp(screen);
|
|
254
|
-
/**
|
|
255
|
-
* **A repaint WE asked for is not evidence the box is gone.**
|
|
256
|
-
*
|
|
257
|
-
* The phone's answer panel takes its space from the terminal, so
|
|
258
|
-
* publishing a box shrinks the grid, which reports new rows, which is a
|
|
259
|
-
* SIGWINCH, which makes this TUI clear and redraw everything. The
|
|
260
|
-
* captures taken across that redraw are half-drawn — and they were being
|
|
261
|
-
* counted as misses, three of them at `PROMPT_CHECK_MS` apart retired the
|
|
262
|
-
* box, the panel unmounted, the grid grew back, another SIGWINCH, the box
|
|
263
|
-
* parsed again, and the panel came back. A ~2 Hz blink that made a live
|
|
264
|
-
* question unanswerable, and every part of it correct in isolation.
|
|
265
|
-
*
|
|
266
|
-
* The miss budget is for a screen we happened to catch mid-repaint. This
|
|
267
|
-
* is a screen we KNOW is mid-repaint, because we are the ones who asked
|
|
268
|
-
* for it — so it costs nothing and we simply look again. `dialogStillUp`
|
|
269
|
-
* still gates it: a box genuinely gone during a resize leaves a screen
|
|
270
|
-
* with no footer and is retired on this same pass, exactly as before.
|
|
271
|
-
*/
|
|
272
|
-
if (s.info.prompt && dialog && Date.now() - s.lastResizeAt < RESIZE_REPAINT_MS) {
|
|
273
|
-
armPromptCheck(core, s, PROMPT_CHECK_MS);
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
if (s.info.prompt && dialog && s.promptMisses < PROMPT_MISS_MAX) {
|
|
277
|
-
s.promptMisses++;
|
|
278
|
-
// Re-arm ourselves: checks are otherwise driven by output, and a box
|
|
279
|
-
// that was answered at the DESK leaves a quiet screen behind — the
|
|
280
|
-
// retained prompt would then never be re-verified at all.
|
|
281
|
-
armPromptCheck(core, s, PROMPT_CHECK_MS);
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
s.promptMisses = 0;
|
|
285
|
-
applyPrompt(core, s, null);
|
|
286
|
-
setAwaiting(core, s, dialog, screen);
|
|
287
|
-
})
|
|
288
|
-
.catch(() => { })
|
|
289
|
-
.finally(() => { s.promptRendering = false; });
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* Has the screen read this box TWICE IN A ROW? A box is published only then.
|
|
293
|
-
*
|
|
294
|
-
* tmux hands its client a screen in CHUNKS, so a render taken between two of
|
|
295
|
-
* them is a box painted down to some row and no further: options missing, the
|
|
296
|
-
* last label cut mid-word ("Yes, and don't a"), the question short. With a
|
|
297
|
-
* selection cursor on row 1 that half PARSES — strictly, correctly, as what is
|
|
298
|
-
* legible — and publishing it is publishing a wrong box: the cut label is a
|
|
299
|
-
* one-tap button, it is in `promptFingerprint`, and `mergeBox` never rewrites a
|
|
300
|
-
* published label, so the cut stayed for the life of the box. Measured on the
|
|
301
|
-
* first box of a session, where the paint follows a quiet spell and the check
|
|
302
|
-
* fired on its first chunk (`scheduleChecks`'s ceiling), but nothing about it
|
|
303
|
-
* is specific to the first.
|
|
304
|
-
*
|
|
305
|
-
* Nothing on a half-painted screen says it is half-painted, so completeness is
|
|
306
|
-
* asked of TIME instead: two consecutive strict reads, `PROMPT_SETTLE_MS`
|
|
307
|
-
* apart, that agree field for field (`samePrompt`, on the screen's own read
|
|
308
|
-
* BEFORE enrichment — the log is not what is being proved). A read that
|
|
309
|
-
* disagrees becomes the new candidate; any pass that reads no box clears it.
|
|
310
|
-
* Costs one extra render and ~`PROMPT_SETTLE_MS` on a box's first appearance,
|
|
311
|
-
* and nothing while it sits unchanged. Degrades to publishing nothing yet,
|
|
312
|
-
* never to a box nobody drew.
|
|
313
|
-
*/
|
|
314
|
-
function readTwice(s, read) {
|
|
315
|
-
const agreed = !!s.promptPending && samePrompt(s.promptPending, read);
|
|
316
|
-
s.promptPending = agreed ? null : read;
|
|
317
|
-
return agreed;
|
|
318
|
-
}
|
|
319
|
-
/** A settle between a walk's keystroke and its re-read — the box walks' one wait. */
|
|
320
|
-
const pause = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
321
|
-
/** A contributed reader's answer, or `fallback` when it threw: a throw reads as "no box". */
|
|
322
|
-
function safe(fn, fallback) {
|
|
323
|
-
try {
|
|
324
|
-
return fn();
|
|
325
|
-
}
|
|
326
|
-
catch {
|
|
327
|
-
return fallback;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* The same two-stage check, for a TUI that draws its dialog a different way.
|
|
332
|
-
*
|
|
333
|
-
* Separate from `checkPrompt()` rather than a branch inside it, because the
|
|
334
|
-
* two share the SHAPE (cheap byte gate → expensive replay → publish, with a
|
|
335
|
-
* miss budget so a half-drawn repaint cannot retire a live box) and not one
|
|
336
|
-
* single rule: opencode (the first such TUI) has no numbered rows, no `❯`, no
|
|
337
|
-
* "Enter to confirm" footer and no scrollback, and every one of `prompt.ts`'s defences is written
|
|
338
|
-
* against one of those. Folding them together would mean loosening rules that
|
|
339
|
-
* exist because of a measured failure on the other screen.
|
|
340
|
-
*
|
|
341
|
-
* What it keeps, deliberately, is the blink fix: a box that stops parsing
|
|
342
|
-
* while the anchor is still on screen costs a MISS, not a retirement, and a
|
|
343
|
-
* repaint the host itself caused by publishing the box (the answer panel takes
|
|
344
|
-
* its space from the terminal, which resizes the PTY, which makes the TUI
|
|
345
|
-
* redraw) costs nothing at all.
|
|
346
|
-
*/
|
|
347
|
-
function checkNavBox(core, s, reader) {
|
|
348
|
-
if (s.copyMode)
|
|
349
|
-
return;
|
|
350
|
-
s.lastPromptCheckAt = Date.now();
|
|
351
|
-
const tail = stripAnsi(s.scrollback.slice(-PROMPT_GATE_BYTES));
|
|
352
|
-
if (!safe(() => reader.candidate(tail), false)) {
|
|
353
|
-
// Nothing that could be a dialog in the window: retire whatever was
|
|
354
|
-
// published with no misses spent, exactly as the claude gate does.
|
|
355
|
-
s.promptGen++;
|
|
356
|
-
s.promptMisses = 0;
|
|
357
|
-
applyPrompt(core, s, null);
|
|
358
|
-
setAwaiting(core, s, false);
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
361
|
-
if (s.promptRendering)
|
|
362
|
-
return;
|
|
363
|
-
s.promptRendering = true;
|
|
364
|
-
const gen = s.promptGen;
|
|
365
|
-
void core.screenCells(s.info.id, PROMPT_CELL_ROWS)
|
|
366
|
-
.then((rows) => {
|
|
367
|
-
if (!s.info.running || s.promptGen !== gen)
|
|
368
|
-
return;
|
|
369
|
-
const box = safe(() => reader.read(rows), null);
|
|
370
|
-
const prompt = box ? safe(() => reader.prompt(box), null) : null;
|
|
371
|
-
if (prompt) {
|
|
372
|
-
s.promptMisses = 0;
|
|
373
|
-
applyPrompt(core, s, prompt);
|
|
374
|
-
setAwaiting(core, s, false);
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
// Unparsed. "Is the dialog still up" is the reader's own question about
|
|
378
|
-
// its own TUI; a dialog still drawn spends a miss rather than retiring the box.
|
|
379
|
-
const dialog = safe(() => reader.stillUp(rows), false);
|
|
380
|
-
if (s.info.prompt && dialog && Date.now() - s.lastResizeAt < RESIZE_REPAINT_MS) {
|
|
381
|
-
armPromptCheck(core, s, PROMPT_CHECK_MS);
|
|
382
|
-
return;
|
|
383
|
-
}
|
|
384
|
-
if (s.info.prompt && dialog && s.promptMisses < PROMPT_MISS_MAX) {
|
|
385
|
-
s.promptMisses++;
|
|
386
|
-
armPromptCheck(core, s, PROMPT_CHECK_MS);
|
|
387
|
-
return;
|
|
388
|
-
}
|
|
389
|
-
s.promptMisses = 0;
|
|
390
|
-
applyPrompt(core, s, null);
|
|
391
|
-
// A dialog whose ARMED option could not be read is still a blocked
|
|
392
|
-
// session, and the phone has no terminal open in the reader view to
|
|
393
|
-
// notice it in. `awaitingInput` is the honest signal for it — "something
|
|
394
|
-
// is asking; open the CLI" — and it is what the phone renders the
|
|
395
|
-
// sentence from rather than greying out a control nobody can explain.
|
|
396
|
-
setAwaiting(core, s, dialog);
|
|
397
|
-
})
|
|
398
|
-
.catch(() => { })
|
|
399
|
-
.finally(() => { s.promptRendering = false; });
|
|
400
|
-
}
|
|
14
|
+
import { healthTail, pause, safe } from "../boxkit.js";
|
|
15
|
+
import { SUBMIT_NAV_TRIES, SUBMIT_NAV_MAX_KEYS, SUBMIT_NAV_LINES, SUBMIT_NAV_SETTLE_MS, CHOOSE_NAV_TRIES, CHOOSE_NAV_SETTLE_MS, PROMPT_CELL_ROWS, HEALTH_SAMPLE_ROWS } from "./knobs.js";
|
|
401
16
|
/**
|
|
402
17
|
* Answer an unnumbered box by placing the selection on the option the user
|
|
403
18
|
* named, and only then pressing Return.
|
|
@@ -500,19 +115,6 @@ async function chooseClaudeNavBox(core, id, choice) {
|
|
|
500
115
|
}
|
|
501
116
|
return core.input(id, "\r") ? { ok: true } : { ok: false, reason: "session not available" };
|
|
502
117
|
}
|
|
503
|
-
/** Is the published box the side channel's, or is the channel reconciled and
|
|
504
|
-
* owning every box? Either way the screen has nothing to add. */
|
|
505
|
-
export function screenReaderOff(s) {
|
|
506
|
-
const ch = s.channel;
|
|
507
|
-
if (!ch || ch.closed)
|
|
508
|
-
return false;
|
|
509
|
-
if (!!ch.published && s.info.prompt?.askId === ch.published)
|
|
510
|
-
return true;
|
|
511
|
-
// A dialog the channel can see but cannot pose (opencode's `question` tool, whose answer
|
|
512
|
-
// route nobody measured) reaches the phone through the screen or not at all: the reader
|
|
513
|
-
// keeps its duty — and so does `awaitingInput` behind it — while one is open.
|
|
514
|
-
return ch.dialogsLive && !ch.unposed;
|
|
515
|
-
}
|
|
516
118
|
/**
|
|
517
119
|
* **The one answer dispatcher** — every answer to a choice box goes through
|
|
518
120
|
* here: the phone's tap (`routes/session.ts`, a digit, a `promptChoice`, typed
|
|
@@ -641,263 +243,6 @@ async function answerQuestion(q, choice, text, reply) {
|
|
|
641
243
|
}
|
|
642
244
|
return applySourceReply(r, reply);
|
|
643
245
|
}
|
|
644
|
-
/**
|
|
645
|
-
* Put the CLI's OWN words on the box we scraped.
|
|
646
|
-
*
|
|
647
|
-
* `AskUserQuestion` writes its question and every option's full description
|
|
648
|
-
* into the conversation log before anyone answers, and the screen is where
|
|
649
|
-
* that text goes to die: descriptions are cut at the right edge and again by
|
|
650
|
-
* the preview pane, and a box with six of them is taller than a phone's
|
|
651
|
-
* terminal, so the question row is not on screen at all. A one-tap button
|
|
652
|
-
* reading "A + B + C" with the paragraph explaining it nowhere on the device
|
|
653
|
-
* is a button you cannot honestly press — which is the actual complaint
|
|
654
|
-
* behind "I need to see the question".
|
|
655
|
-
*
|
|
656
|
-
* Enrichment is additive and identity-neutral: `desc`/`ask`/`truncated` are
|
|
657
|
-
* outside `promptFingerprint` on purpose, so a description that arrives one
|
|
658
|
-
* check late cannot invalidate an answer already queued against the box.
|
|
659
|
-
* Matching is by LABEL, never by index — the TUI appends its own rows ("Type
|
|
660
|
-
* something.", "Chat about this") after the tool's, and on a truncated box the
|
|
661
|
-
* visible run starts above 1.
|
|
662
|
-
*
|
|
663
|
-
* Cached on the log's mtime: the strict pass runs about twice a second while a
|
|
664
|
-
* box is up and the log does not move in that time, so this costs one `stat`
|
|
665
|
-
* per check and a tail read per turn.
|
|
666
|
-
*/
|
|
667
|
-
function enrichPrompt(s, p) {
|
|
668
|
-
// The health verdict is STASHED, not recorded: this runs on every strict
|
|
669
|
-
// pass, about twice a second while a box is up, and `applyPrompt` owns the
|
|
670
|
-
// one edge where a box genuinely becomes published. Cleared first, so a
|
|
671
|
-
// path that returns early below leaves no stale answer behind for that edge
|
|
672
|
-
// to record — "the log could not be asked" is not an observation about the
|
|
673
|
-
// matcher.
|
|
674
|
-
s.enrich = null;
|
|
675
|
-
const cid = s.info.claudeSessionId;
|
|
676
|
-
if (!cid)
|
|
677
|
-
return p;
|
|
678
|
-
// A plan approval is never an `AskUserQuestion`, so it is done and returned
|
|
679
|
-
// here: the card gets the plan it is asking about, or nothing extra.
|
|
680
|
-
if (isPlanBox(p.ask ?? p.question)) {
|
|
681
|
-
const plan = pendingPlanFor(s, cid);
|
|
682
|
-
return plan ? { ...p, plan } : p;
|
|
683
|
-
}
|
|
684
|
-
let asks;
|
|
685
|
-
try {
|
|
686
|
-
const mtime = logMtime(transcriptPath(s.info.cwd, cid)) ?? 0;
|
|
687
|
-
if (s.askCache && s.askCache.mtime === mtime)
|
|
688
|
-
asks = s.askCache.asks;
|
|
689
|
-
else {
|
|
690
|
-
asks = pendingAskQuestions(s.info.cwd, cid);
|
|
691
|
-
s.askCache = { mtime, asks };
|
|
692
|
-
}
|
|
693
|
-
// The log does not hold the call while its box is up on 2.1.304 (it is
|
|
694
|
-
// written once answered); the `PreToolUse` hook carried it before the box.
|
|
695
|
-
if (!asks.length && s.askHook)
|
|
696
|
-
asks = asksFromCall(s.info.cwd, cid, s.askHook);
|
|
697
|
-
}
|
|
698
|
-
catch {
|
|
699
|
-
return p;
|
|
700
|
-
}
|
|
701
|
-
const labels = p.options.map((o) => o.label);
|
|
702
|
-
// The UNIQUE best match, never the first that overlaps: one
|
|
703
|
-
// `AskUserQuestion` may carry several questions and two of them sharing a
|
|
704
|
-
// pair of labels ("Yes"/"No") is ordinary, so `find` handed back question 1
|
|
705
|
-
// for a screen showing question 2 — and with it question 1's `askId`, its
|
|
706
|
-
// descriptions and its first options as a "recovered" head a digit would
|
|
707
|
-
// select. A tie now enriches nothing. See `pickAsk`.
|
|
708
|
-
const ask = pickAsk(asks, labels);
|
|
709
|
-
// Only a box the log HAS a pending question for can say anything about this
|
|
710
|
-
// matcher. A tool approval or a trust dialog carries no `AskUserQuestion` at
|
|
711
|
-
// all, so `asks` is legitimately empty and counting that as a miss would
|
|
712
|
-
// report the commonest box in the app as a broken parse.
|
|
713
|
-
s.enrich = { asks: asks.length, matched: !!ask, labels: labels.join("\n") };
|
|
714
|
-
if (!ask)
|
|
715
|
-
return p;
|
|
716
|
-
const options = p.options.map((o) => {
|
|
717
|
-
const desc = descFor(ask, o.label);
|
|
718
|
-
return desc ? { ...o, desc } : o;
|
|
719
|
-
});
|
|
720
|
-
// A box taller than the terminal scrolled its own first options away. The
|
|
721
|
-
// log has them, and their indices are the TUI's own — see `recoverHead`,
|
|
722
|
-
// which refuses unless the two lists can be proved to line up. Recovered,
|
|
723
|
-
// the card is no longer missing buttons, so `truncated` (which SAYS options
|
|
724
|
-
// are unreachable from here) goes with them.
|
|
725
|
-
const head = recoverHead(ask, p.options);
|
|
726
|
-
if (head) {
|
|
727
|
-
const recovered = head.map((o, i) => ({ index: i + 1, label: o.label, ...(o.desc ? { desc: o.desc } : {}) }));
|
|
728
|
-
const { truncated: _cut, ...rest } = p;
|
|
729
|
-
// Capped like the merge, and from the same end: the recovered head is the
|
|
730
|
-
// part nobody can see on the terminal, so the tail is what gives way.
|
|
731
|
-
const all = [...recovered, ...options].slice(0, MAX_BOX_OPTIONS);
|
|
732
|
-
return { ...rest, options: all, ask: ask.question, askId: ask.id };
|
|
733
|
-
}
|
|
734
|
-
return { ...p, options, ask: ask.question, askId: ask.id };
|
|
735
|
-
}
|
|
736
|
-
/**
|
|
737
|
-
* The plan file behind a plan-approval box (`planbox.ts`), cached on the log's
|
|
738
|
-
* mtime and the file's: the strict pass runs about twice a second while the box
|
|
739
|
-
* is up, and neither moves in that time unless somebody edits the plan.
|
|
740
|
-
*/
|
|
741
|
-
function pendingPlanFor(s, cid) {
|
|
742
|
-
try {
|
|
743
|
-
const logM = logMtime(transcriptPath(s.info.cwd, cid)) ?? 0;
|
|
744
|
-
const c = s.planCache;
|
|
745
|
-
const path = c && c.logMtime === logM ? c.path : planPathFor(s.info.cwd, cid);
|
|
746
|
-
const fileM = path ? logMtime(path) ?? 0 : 0;
|
|
747
|
-
if (c && c.logMtime === logM && c.path === path && c.fileMtime === fileM)
|
|
748
|
-
return c.plan ?? undefined;
|
|
749
|
-
const plan = path && fileM ? readPlan(path) : null;
|
|
750
|
-
s.planCache = { logMtime: logM, path, fileMtime: fileM, plan };
|
|
751
|
-
return plan ?? undefined;
|
|
752
|
-
}
|
|
753
|
-
catch {
|
|
754
|
-
return undefined;
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
/** Publish the "unparsable dialog on screen" fallback flag. */
|
|
758
|
-
export function setAwaiting(core, s, on, screen) {
|
|
759
|
-
if (!!s.info.awaitingInput === on)
|
|
760
|
-
return;
|
|
761
|
-
s.info.awaitingInput = on || undefined;
|
|
762
|
-
core.emit("updated", s.info);
|
|
763
|
-
// Same reason the parsed prompt notifies: a blocked session is silent, so
|
|
764
|
-
// nothing else would ever tell you. Fires on the ON transition only.
|
|
765
|
-
if (on)
|
|
766
|
-
core.emit("awaiting", s.info.id);
|
|
767
|
-
// …which is nearly the edge the health record wants, and the "nearly" is
|
|
768
|
-
// the whole correction. Raising this flag means "a dialog footer is on that
|
|
769
|
-
// screen and no box parsed above it" — but the flag is an INTERLOCK, and its
|
|
770
|
-
// rule is deliberately loose because a false wait is cheap and typing into a
|
|
771
|
-
// live question box is not. A CLAIM ABOUT THE DETECTOR has the opposite
|
|
772
|
-
// error cost, so it needs the stricter question: was a box actually up?
|
|
773
|
-
//
|
|
774
|
-
// On the live host it was not. A claude session displaying our own prose
|
|
775
|
-
// about this very detector put "Esc to cancel" on screen inside a sentence,
|
|
776
|
-
// the cheap gate fired, the strict pass correctly refused to read a
|
|
777
|
-
// paragraph as a box — and that CORRECT REFUSAL was filed as a miss. Four in
|
|
778
|
-
// nine, i.e. a working detector reporting 44% failure, which is how a board
|
|
779
|
-
// teaches the person reading it to stop reading it.
|
|
780
|
-
//
|
|
781
|
-
// So: an observation is only a miss if the primary rule was the RIGHT RULE
|
|
782
|
-
// and failed. `dialogEvidence` is what says it was — a footer row the CLI
|
|
783
|
-
// painted, plus a cursor or option rows above it. No box, no observation:
|
|
784
|
-
// not a `good` either, because nothing here has been seen to work, and a
|
|
785
|
-
// `good` per correct refusal would fill the twenty-slot window with
|
|
786
|
-
// successes and bury the misses that matter.
|
|
787
|
-
if (on && screen) {
|
|
788
|
-
const ev = dialogEvidence(screen);
|
|
789
|
-
if (ev.box) {
|
|
790
|
-
core.noteFor(s, "prompt.box", "fallback", {
|
|
791
|
-
via: "the weaker “something is asking you something” flag",
|
|
792
|
-
raw: healthTail(screen, (l) => isDialogFooterRow(l)),
|
|
793
|
-
});
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
/**
|
|
798
|
-
* Publish (or retire) the sign-in link this session is showing.
|
|
799
|
-
*
|
|
800
|
-
* Same shape as `applyPrompt` and for the same reason: this runs about twice
|
|
801
|
-
* a second while the login screen is up, and a `session.list` broadcast per
|
|
802
|
-
* repaint would be one per repaint. `at` is stamped when the URL first
|
|
803
|
-
* appears and kept while it is the same URL, because a login link expires and
|
|
804
|
-
* "how old is this" is the difference between a page that signs you in and a
|
|
805
|
-
* page that refuses.
|
|
806
|
-
*/
|
|
807
|
-
function applyLogin(core, s, login) {
|
|
808
|
-
const had = s.info.login ?? null;
|
|
809
|
-
if (sameLogin(had, login))
|
|
810
|
-
return;
|
|
811
|
-
if (!login) {
|
|
812
|
-
s.info.login = null;
|
|
813
|
-
}
|
|
814
|
-
else {
|
|
815
|
-
s.info.login = { ...login, at: had && had.url === login.url ? had.at : Date.now() };
|
|
816
|
-
}
|
|
817
|
-
core.emit("updated", s.info);
|
|
818
|
-
}
|
|
819
|
-
export function applyPrompt(core, s, prompt) {
|
|
820
|
-
// The usage-limit menu is owned by auto-continue, not the normal prompt
|
|
821
|
-
// flow: take its stop-and-wait option ourselves and never surface it (no
|
|
822
|
-
// push, no plugin event) — the scheduled continue does the rest. With
|
|
823
|
-
// auto-continue off it stays a normal prompt (the badge still shows).
|
|
824
|
-
const stopWait = prompt?.options.find((o) => STOP_WAIT_RE.test(o.label));
|
|
825
|
-
if (prompt && stopWait) {
|
|
826
|
-
const scan = stripAnsi(s.scrollback.slice(-6000));
|
|
827
|
-
const det = detectLimitText(scan);
|
|
828
|
-
core.markLimitBlocked(s, det.resetAt, det.weekly, scan.slice(-600));
|
|
829
|
-
if (core.limitAuto(s)) {
|
|
830
|
-
if (s.info.prompt) {
|
|
831
|
-
s.info.prompt = null;
|
|
832
|
-
core.emit("updated", s.info);
|
|
833
|
-
}
|
|
834
|
-
s.proc.write(String(stopWait.index) + "\r");
|
|
835
|
-
// This menu is answered on the user's behalf and then never shown, so
|
|
836
|
-
// the audit log is the ONLY place it is visible at all.
|
|
837
|
-
recordSent({
|
|
838
|
-
sessionId: s.info.id, actor: "auto", source: "limit", kind: "answer",
|
|
839
|
-
text: String(stopWait.index), result: "written",
|
|
840
|
-
detail: `took the usage-limit menu's "${stopWait.label}"`,
|
|
841
|
-
});
|
|
842
|
-
return;
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
// A box IS the question, with buttons. Publishing both would put the same
|
|
846
|
-
// ask on the row twice and in two different wordings.
|
|
847
|
-
if (prompt)
|
|
848
|
-
core.setAsking(s, null);
|
|
849
|
-
// Field by field (`samePrompt`), never `JSON.stringify`: that also compares
|
|
850
|
-
// KEY ORDER, and `mergeBox` builds its object in its own order, so the pass
|
|
851
|
-
// after every merge reported a change for a card that had not moved — one
|
|
852
|
-
// broadcast, one push and one plugin event per box, bought with nothing.
|
|
853
|
-
const changed = !samePrompt(prompt, s.info.prompt ?? null);
|
|
854
|
-
// A tick toggled on a checkbox box is the box being answered, not a new
|
|
855
|
-
// question: the phone redraws it, nobody is pushed "needs you" per tap.
|
|
856
|
-
const ticked = changed && samePrompt(prompt, s.info.prompt ?? null, "ignore");
|
|
857
|
-
const had = !!s.info.prompt;
|
|
858
|
-
if (changed) {
|
|
859
|
-
s.info.prompt = prompt;
|
|
860
|
-
// A numbered-choice suggestion answers THIS box; when the box goes, so
|
|
861
|
-
// does it. (Output alone no longer clears either — see the data handler.)
|
|
862
|
-
const sug = s.info.suggestion;
|
|
863
|
-
if (!prompt && sug && sug.choice != null)
|
|
864
|
-
s.info.suggestion = null;
|
|
865
|
-
core.emit("updated", s.info);
|
|
866
|
-
if (prompt && !ticked)
|
|
867
|
-
core.emit("prompt", s.info.id, prompt);
|
|
868
|
-
// A box became published where none was — the one edge on which the
|
|
869
|
-
// choice-box detector has provably worked. Not on every `changed`: a box
|
|
870
|
-
// whose cursor moves republishes several times while it is up, and the
|
|
871
|
-
// question is "can this app still read a question box", asked once per
|
|
872
|
-
// box. Not on every strict pass either, for the reason `enrichPrompt`
|
|
873
|
-
// states.
|
|
874
|
-
if (prompt && !had) {
|
|
875
|
-
// The fixture is the screen the box was published off (`clifixtures.ts`).
|
|
876
|
-
core.noteFor(s, "prompt.box", "good", { fixture: () => core.screenText(s.info.id) });
|
|
877
|
-
// The enrichment rides on the same edge, from what the poll stashed.
|
|
878
|
-
// `asks: 0` is not a miss (see `enrichPrompt`); the fallback is that the
|
|
879
|
-
// phone shows the labels as the terminal cut them, with the paragraph
|
|
880
|
-
// that explains them nowhere on the device.
|
|
881
|
-
const e = s.enrich;
|
|
882
|
-
if (e && e.asks > 0) {
|
|
883
|
-
// The fixture is the LOG's record of the call, which 2.1.304 writes only
|
|
884
|
-
// once the box is answered — so it is waited for (once per CLI version).
|
|
885
|
-
if (e.matched)
|
|
886
|
-
core.noteFor(s, "askbox.enrich", "good", { fixture: async () => {
|
|
887
|
-
for (let i = 0; i < ASK_RECORD_POLLS; i++) {
|
|
888
|
-
const rec = pendingAskRecord(s.info.cwd, s.info.claudeSessionId);
|
|
889
|
-
if (rec)
|
|
890
|
-
return rec;
|
|
891
|
-
await pause(ASK_RECORD_POLL_MS);
|
|
892
|
-
}
|
|
893
|
-
return null;
|
|
894
|
-
} });
|
|
895
|
-
else
|
|
896
|
-
core.noteFor(s, "askbox.enrich", "fallback", { via: "the labels as the terminal cut them", raw: e.labels });
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
246
|
/**
|
|
902
247
|
* Press Return on a checkbox box's **Submit row**, walking the selection
|
|
903
248
|
* cursor there first.
|
|
@@ -956,7 +301,7 @@ export async function submitPromptBox(core, id) {
|
|
|
956
301
|
// which is the bug this whole method exists to fix.
|
|
957
302
|
// Both words the commit row is drawn with — see `prompt.ts`'s
|
|
958
303
|
// `SUBMIT_ROW_RE`. Anchored, so a sentence containing "next" is not a row.
|
|
959
|
-
const tail = healthTail(seen, (l) => /^\s*\S?\s*(Submit|Next)\s*$/.test(l));
|
|
304
|
+
const tail = healthTail(seen, (l) => /^\s*\S?\s*(Submit|Next)\s*$/.test(l), HEALTH_SAMPLE_ROWS);
|
|
960
305
|
if (placed)
|
|
961
306
|
core.noteFor(s, "prompt.submit", "good", { fixture: () => seen });
|
|
962
307
|
else if (readable)
|
|
@@ -965,4 +310,5 @@ export async function submitPromptBox(core, id) {
|
|
|
965
310
|
core.noteFor(s, "prompt.submit", "fallback", { via: "a bare Return", raw: tail });
|
|
966
311
|
return { ok: core.input(id, "\r"), placed };
|
|
967
312
|
}
|
|
313
|
+
export { sourceKeysProblem } from "../sourceanswer.js";
|
|
968
314
|
//# sourceMappingURL=boxes.js.map
|