| 349 | |
| 350 | // ── event plumbing ─────────────────────────────────────────────────────── |
| 351 | private controlQuery(subtype: string, params: Record<string, unknown>): Promise<unknown> { |
| 352 | const requestId = `q${++this.reqId}` |
| 353 | return new Promise(resolve => { |
| 354 | this.pending.set(requestId, { reject: () => resolve(null), resolve }) |
| 355 | this.send({ request: { subtype, ...params }, request_id: requestId, type: 'control_request' }) |
| 356 | setTimeout(() => { |
| 357 | if (this.pending.has(requestId)) { |
| 358 | this.pending.delete(requestId) |
| 359 | resolve(null) |
| 360 | } |
| 361 | }, RPC_TIMEOUT_MS) |
| 362 | }) |
| 363 | } |
| 364 | |
| 365 | // Map a slash command (name + optional arg) to a clawcodex control_request |
| 366 | // and return a CommandDispatchResponse (`type:'exec'` + human-readable output |