Replies: 3 comments 1 reply
|
The waterfall analysis here is right and worth keeping: One correction before anyone writes the patch, though: Which leaves a question worth answering before the fix is designed: where is the Either way the underlying issue stands on its own and is worth stating without the missing method: a plugin cannot make itself heard on an agent-scoped ask through 中文 这里的 waterfall 分析是对的,值得保留: 不过在有人动手写补丁之前,需要更正一点:本仓库中并不存在 由此产生一个在设计修复前值得先回答的问题:您所修补的 无论如何,底层问题独立成立,且值得在不提及那个缺失方法的前提下重述:插件仅凭 |
|
Thanks for the careful review — you found the exact missing piece, and the answer to your question is: registerProvider is not upstream, it's an uncommitted local addition in my checkout. My working tree carries unpublished compat work (a legacy single-slot provider seam, alongside resolveSessionPreset composition) that exists so the published plugin — which calls userQuestions.registerProvider(...) — can run against the current dev tree. I patched that local seam and then wrongly presented it as an upstream contract. You're right on both counts: it isn't in this repository at d347e70, and the fix I sketched has no upstream method to land in. That leaves the seam-free statements, which I think stand on their own: The trap: a plugin cannot make itself heard on an agent-scoped ask through plain ctx.on alone, and nothing in the event's documentation says so. It is self-serve today — a plugin registering its own {global: true, prepend: true} listener works (that variant is also validated here, end-to-end Telegram inline buttons) — but I only learned the filter requirement after a full debug session, and the failure is completely silent: the ask falls through to whichever global listener exists (the web UI), with no diagnostic anywhere. The design call is real: first-class registration seam for non-host answerers, documenting the global requirement on scoped waterfall events, or an unscoped fallback pass when no scoped listener answers — all three would have turned a three-layer debug into a one-line fix. For the regression angle: @wsz987/dsh-channels shipped IM questions in v0.4.2 (Aug 21) and they demonstrably presented as Telegram buttons against the harness of that time; the current tree's scoped dispatch orphans that implementation. Whichever option is chosen, the published-plugin ecosystem will keep hitting this until it's settled or documented. Happy to provide the exact local diff of the seam I'm running if it's useful as a reference for the design discussion. |
|
Accepted on both counts — the tarball work settled it cleanly, and I retract the regression framing from my original post and the wsz987#2 addendum: registerProvider was upstream (verified here against 049170c), 0.4.2 never used it, and 0.5.0's direct backend shipped ~46 h after the removal. Two public surfaces removed inside a week, without compat paths, is the accurate story. One new data point, found while re-checking the published side: the removal is staged but not yet shipped to consumers. channel-harness@0.5.0 pins @deepseek-ai/dsh-user-questions at exactly 0.1.1-rc.2 — published 2026-08-21T12:33Z, ~25 h before the removal commit — and its published lib/index.js still contains the full registerProvider (docstring, DUPLICATE_PROVIDER guard, disposer; verified on unpkg). dist-tags.latest for that package still points at a pre-removal build; post-removal code has only shipped under next/alpha. So the pinned published pairs (0.4.x + apiproxy, 0.5.0 + rc.2) are self-consistent, and the breakage is strictly plugin-vs-HEAD — how we run the harness, which is why it broke here and not for most users. Practical consequence for the maintainers: the deprecation-or-compat question is still cheap to act on. No consumer has received the removal through a default-tagged release yet — a compat shim, a documented migration, or a changelog note in the next release train lands before anyone feels it, rather than after. And the seam-free finding stands on its own: a plugin cannot be heard on an agent-scoped ask through plain ctx.on, nothing documents the global requirement, and the failure is silent. |
Uh oh!
There was an error while loading. Please reload this page.
Posting here as a discussion since this repo doesn't use issues — this is a finding with a validated fix proposal; happy to move it wherever the team prefers.
Environment
d347e70390), web profile@wsz987/dsh-channels0.5.0 (the published plugin this seam exists for)Symptom
ask_user_questionin a channel-initiated turn never reaches the channel's registered provider. The question falls through to the web UI's remote listener, so it appears only in the web GUI. The provider is never consulted — no log output, no presentation attempt, nothing.Root cause
The service dispatches agent-owned asks as scoped waterfalls:
Cordis
dispatchfilters listeners for scoped events: onlyhook.globallisteners (or listeners mounted inside the target's subtree) are consulted.UserQuestionService.registerProvider— the documented compat seam that published plugins use — registers a plain listener:No
globalflag → filtered out of every agent-scoped ask. Any UI/remote listener that is global wins by default. The seam is structurally inaudible in the waterfall architecture it is supposed to serve.Suggested fix (in
registerProvider)The seam should mount legacy providers where they can actually hear scoped asks — published plugins cannot be expected to know cordis filter semantics:
Two details that matter:
{ global: true }— audibility in scoped waterfalls.{ prepend: true }— the provider presents what it can; its decline falls through to the remaining answerers unchanged (preserves the GUI fallback for non-channel sessions).restoreUserQuestionErrorbefore theASK_ABORTEDcheck — when the host runs from a dev checkout, a published plugin importsUserQuestionErrorfrom its own installed copy, so a cross-copyinstanceoffails and a decline would rethrow instead of delegating. Duck-typing through the existing restore helper makes the seam robust against module duplication.Verification (2026-09-05, Telegram,
@wsz987/dsh-channels0.5.0)With this exact change: questions asked from Telegram present in the chat as inline buttons (option buttons + Other + Skip), button taps complete the turn, custom typed answers work — and web-initiated asks still fall through to the GUI. Four consecutive rounds verified, including a custom answer.
This resolves the IM-questions feature request from the plugin side: wsz987/dsh-channels#2.
All reactions