import fs from 'node:fs' import path from 'node:path' import os from 'node:os' import crypto from 'node:crypto' import { CommandDefinitionId } from '@deepseek-ai/dsh-commands' export const name = 'dsh-queue-steer' export const inject = { commands: { required: true }, webServer: { required: true }, connection: { required: true } } const file = path.join(process.env.DSH_PROFILE_DIR || path.join(process.env.DSH_HOME || path.join(os.homedir(), '.dsh'), 'profiles', 'web'), 'dsh-queue-steer', 'settings.json') const defaults = { defaultMode: 'queue', defaultQueueList: 'batch', batchHeaderTemplate: 'Queued messages batch ({count}):\n\n{messages}' } let settings = { ...defaults } try { settings = { ...defaults, ...JSON.parse(fs.readFileSync(file, 'utf8')) } } catch {} const save = (next) => { settings = { ...settings, ...next }; fs.mkdirSync(path.dirname(file), { recursive: true }); fs.writeFileSync(file, JSON.stringify(settings, null, 2)) } const message = (value, via) => ({ id: crypto.randomUUID(), role: 'user', content: [{ type: 'text', text: value }], source: { kind: 'user', via } }) export function apply(ctx) { const add = (name, mode) => ctx.commands.register({ definitionId: CommandDefinitionId(`@local/dsh-queue-steer#${name}`), name, description: mode === 'steer' ? 'Steer the running agent with a message' : 'Queue a message for the agent', input: { hint: '[message]' }, handler: ({ rawInput, agent }) => { const value = rawInput.trim() if (!value) return { kind: 'error', text: `Usage: /${name} ` } const m = message(value, `command-${name}`) if (mode === 'steer' && agent.status === 'running') agent.steer(m) else if (mode === 'steer') agent.followup(m) else agent.inbox.append('next-turn', m) return { kind: 'success', text: `${mode === 'steer' ? 'Sent' : 'Queued'}: ${value.slice(0, 120)}` } }, }) add('queue', 'queue'); add('steer', 'steer') ctx.inject(['webServer', 'connection'], (wctx) => wctx.effect(() => wctx.webServer.register({ kind: 'exact', path: '/dsh-queue-steer/settings', handler: async (req, res) => { const denied = wctx.connection.requestRejection(req) res.setHeader('content-type', 'application/json; charset=utf-8'); res.setHeader('cache-control', 'no-store') if (denied !== undefined) { res.statusCode = denied; return res.end(JSON.stringify({ error: 'rejected' })) } if (req.method === 'GET') { res.statusCode = 200; return res.end(JSON.stringify(settings)) } if (req.method !== 'POST') { res.statusCode = 405; return res.end() } let body = ''; for await (const chunk of req) body += chunk try { save(JSON.parse(body || '{}')); res.statusCode = 200; res.end(JSON.stringify(settings)) } catch (e) { res.statusCode = 400; res.end(JSON.stringify({ error: String(e.message || e) })) } }, }), 'dsh-queue-steer: settings')) }