Files
dsh-context/src/client/command.ts
T
bowenliang123 0eea57067a chore(client): strip comment noise in the client half
Apply the full-repo comment audit to client logic and components: drop
narration-style JSDoc and duplicated cross-file comments, keep only
non-obvious contracts (module-table require, projection keys, hooks
rules, no-white-screen guarantees). Fix stale claims: locale fallback
chain (en, not zh), unfounded 'harness block vocabulary' mirror, kind-chip
tint mapping, stats tooltip z-index, onToolFocus parenthetical.
2026-08-24 17:16:31 +08:00

54 lines
2.3 KiB
TypeScript

/**
* `/context` — a client-owned slash command that opens the context modal
* (current composition + recent trend) in the center of the page.
*
* Implemented as the plugin's own '/' trigger source instead of a host
* command: nothing is dispatched to the host, no session log records are
* written, and nothing becomes model-visible — the invocation never enters
* the message history. Both paths answer `'handled'` and open the modal,
* leaving the `/context` token in the composer while it is open; the modal's
* close path consumes the token then (see modalStore.ts).
*/
import { modalStoreOf, setPendingConsume } from './modalStore'
import type { ClientCtx, InputTriggersFace } from './services'
import type { ViewKit } from './viewkit'
const COMMAND = 'context'
const LINE = '/' + COMMAND
export function registerContextCommand(ctx: ClientCtx, kit: ViewKit): void {
ctx.effect(() => {
// Soft dependency (ctx.get, not the inject list): a harness without the
// input-trigger service keeps the tab working and only the command
// absent.
const inputTriggers = ctx.get('inputTriggers') as InputTriggersFace | undefined
if (inputTriggers === undefined) return () => {}
return inputTriggers.registerSource({
trigger: '/',
name: COMMAND,
order: 1,
candidates: (_session, req) => {
if (req.position !== 'leading') return Promise.resolve([])
const query = req.query.trim().toLowerCase()
if (query !== '' && !COMMAND.startsWith(query)) return Promise.resolve([])
return Promise.resolve([{ name: COMMAND, description: kit.t('cmd.desc') }])
},
onPick: (pick) => {
// Open and remember the token span: the modal's close path consumes
// it (span CAS — a draft changed meanwhile is left untouched).
setPendingConsume(pick.session.sessionId, { kind: 'span', span: pick.span })
modalStoreOf(pick.session.sessionId).set(true)
return 'handled'
},
matchEnter: (session, line) => {
if (line !== LINE) return Promise.resolve(undefined)
setPendingConsume(session.sessionId, { kind: 'bare-token', token: LINE })
modalStoreOf(session.sessionId).set(true)
return Promise.resolve<'handled'>('handled')
},
})
}, 'dsh-context: /context command')
}