Repository navigation
Replies: 2 comments
|
Thanks for the very concrete report — the "phone can answer questions but never approvals" framing is exactly the right way to state it. I spent a round reading the current tree ( 1. How the approval waterfall is actually keyed
this.ctx.waterfall(
scopeTarget(req.agent, req.agent), 'approval/request', req,
() => Promise.resolve<ApprovalOutcome>('unavailable'),
)So the dispatch key is the asking agent's scope, not the service owner's and not the requester's. The admission rule is then in One more fact that matters for your option 2, and for #5236: the 2. "My listener never fires" has three distinct causes — please don't stop at the first(a) Filtered by scope. Your ctx is tagged below the asking agent (a preset child, a per-agent binding). Fix: register where the ctx is untagged or encloses the agents — (b) Admitted, but never reached. (c) A different process/plane. This is the one I'd check first on your machine. In 0.2 a session can run in a runtime carrier, and a listener in the shell process simply cannot see that waterfall; symmetrically, the web browser half is a separate process that receives host events through A one-line way to tell them apart in your own plugin: register a control listener on an event that provably fires in the same ctx ( I want to be explicit about what this evidence does not say: in a standalone cordis harness I measured an unscoped plugin ctx and 3. What you're asking for is achievable without a core changeYour option 2 — an explicit answerer registry with first-answer-wins — does not need a new core API to exist, because
That gives exactly the semantics you validated in your prototype: both surfaces are presented, the first answer wins, and the tool call receives the winner's real outcome. Two properties I would hold such a plugin to, both testable: with zero answerers registered it must be byte-identical to I am building this as If you can paste the registration matrix (which ctx each of the five variants was registered on) and whether your control event fired, I can name which of (a)/(b)/(c) it is in one pass — and if it turns out to be (c), that is a finding worth its own thread, because it would mean profile plugins and the runtime carrier disagree about which process owns the approval chain. |
|
The gap this thread describes now has a plugin form, so a third-party surface does not have to be written against the seam from scratch.
npm install @argszero/dsh-approval-bridgeMount it at the profile (root) level, then a surface plugin registers an answerer — that is the whole integration: ctx.inject(['approvalBridge'], (scoped) => {
scoped.effect(() => scoped.approvalBridge.register({
name: 'phone',
match: ask => ask.toolName === 'bash',
answer: async ask => (await promptOnThePhone(ask)) ?? undefined,
}))
})A claiming outcome ( The seam, measured rather than read.
The second-to-last row is the one worth repeating: a scope-tagged listener is skipped silently, which is why the plugin's untagged test is written against The report answers the question the harness does not. Honest boundaries. It cannot make a tagged listener admitted (that is the dispatcher's filter). Under the default Evidence: 41 test arms against a real cordis |
Uh oh!
There was an error while loading. Please reload this page.
[Ideas] 让
approval/request对插件 ctx 可达(与user-questions/request对齐)一句话
approval/request目前任何插件都观测不到、更无法应答,而user-questions/request可以。结果是:所有交互式审批 surface 只能活在宿主内部,第三方 surface(IM/手机、手表、语音、自定义 UI)在结构上就做不出来。我们希望有一个 seam 让插件参与审批 —— 具体场景是"在手机上审批",但同一堵墙挡住的是所有宿主之外的 surface。影响
用手机驾驶 dsh 会话的人能收到 round 卡、叙述和问询卡,唯独收不到审批卡。当某个工具调用需要提权而人不在电脑前时,回合只能等到审批超时、fail-closed 拒绝 —— 工作直接停住,而手机上没有任何办法把它放行。这是"用手机驾驶已有 dsh 会话"这条路上唯一缺的一块。
根因(dsh-desktop 0.2.0-rc.2 实测)
dsh-scope的准入把插件 ctx 排除在外:无 tag 的监听器全局准入,带 tag 的只对匹配/祖先 scope 准入(hook.global || !filter || filter.call(thisArg, hook.ctx))。插件的 ctx 是提问 agent 子树的兄弟,请求根本到不了它。我们试过五种注册方式,在大量真实审批上一次都没有触发(每一次都由宿主自带 UI 处理):插件 ctx、
{ global: true }、{ global: true, prepend: true }、ctx.root.on(...)、ctx.get('approval').ctx.on(...)。让这件事看起来像疏漏而非有意设计的,是这个对照:
user-questions/request能到达插件 —— 注册在已绑定 agent 的 ctx 上(ctx.on('user-questions/request', …))即可,而这正是我们希望审批也具备的形态。今天问询卡在手机上工作正常,审批卡则完全不可能。最小复现
approval/request(上述五种变体)和user-questions/request注册监听器,进入时打日志。ask_user_question→ ask 监听器触发。环境:dsh-desktop 0.2.0-rc.2(Electron 44 / node 24.18.1)、dsh-skill 0.2.0-rc.2。
期望的 seam(任一即可解开)
approval/request对"注册在提问 agent scope 上"的监听器可达,claim /next()语义与之一致。改动最小:插件想接就 claim,不想接就 delegate。落地后会做什么
@aiwayds/dsh-feishu(社区插件,用飞书/Lark 驱动 dsh 会话)会补上手机端审批卡。它的用户已经在手机上作答问询卡、steer 回合,唯一缺的就是审批。我们已经验证过期望的最终行为(两端同时在线、先答者胜、落败的一方被替换成胜者的真实结果、终态卡仍保留工具/理由上下文),插件作者也表示宿主 seam 一落地他就在插件里实现手机审批卡 —— 见 fan56/dsh-feishu#5 的评论。补充说明
感谢阅读 —— 也感谢"一切皆插件"的设计;这是我们在它边界上撞到的那一处。
All reactions