index.ts 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /**
  2. * Session feedback event plus the human-facing `/feedback` producer. Recording
  3. * appends one authoritative log-only event and does not start model work. The
  4. * append is eager but unflushed, so acknowledgement reports that the entry is
  5. * logged, not that it reached disk.
  6. * @module @deepseek-ai/dsh-command-feedback
  7. */
  8. import type { Context } from '@deepseek-ai/cordis'
  9. import type { CommandInvocation, CommandResult } from '@deepseek-ai/dsh-commands'
  10. import type { Session } from '@deepseek-ai/dsh-session'
  11. import { getOrCreateAnonymousUserId } from '@deepseek-ai/dsh-anonymous-user-id'
  12. export const name = 'command-feedback'
  13. export const inject = ['commands']
  14. const USAGE = 'Usage: /feedback <text>'
  15. declare module '@deepseek-ai/dsh-session/types' {
  16. interface SessionEventMap {
  17. /**
  18. * One recorded human remark about this session. Log-only and independent
  19. * of its trigger; it never enters model context or derived history.
  20. */
  21. 'feedback/record': { text: string }
  22. }
  23. }
  24. /**
  25. * Record feedback independently of any UI trigger.
  26. * @param session - session the feedback describes.
  27. * @param text - human-authored feedback; surrounding whitespace is discarded.
  28. * @throws {TypeError} when the normalized text is empty.
  29. */
  30. export function recordFeedback(session: Session, text: string): void {
  31. const normalized = text.trim()
  32. if (normalized.length === 0) throw new TypeError('feedback text must not be empty')
  33. session.append('feedback/record', { text: normalized })
  34. }
  35. /**
  36. * Validate, record, and acknowledge one feedback entry. Returning an error
  37. * leaves no `feedback/record` event.
  38. * @param invocation - receiving agent, raw command input, and UI cancellation.
  39. * @returns an acknowledgement containing the receiving session and anonymous
  40. * user ids, or a usage error when no feedback text was supplied.
  41. */
  42. function executeFeedbackCommand(invocation: CommandInvocation): CommandResult {
  43. if (invocation.rawInput.trim().length === 0) {
  44. return { kind: 'error', text: `Feedback text is required. ${USAGE}` }
  45. }
  46. recordFeedback(invocation.agent.session, invocation.rawInput)
  47. return {
  48. kind: 'success',
  49. text: `Feedback recorded for session ${invocation.agent.session.id}\nAnonymous user: ${getOrCreateAnonymousUserId()}.`,
  50. }
  51. }
  52. /** Register the global `/feedback` command for every composed command adapter. */
  53. export function apply(ctx: Context): void {
  54. ctx.commands.register({
  55. name: 'feedback',
  56. description: 'record feedback about this session',
  57. input: { hint: '<text>' },
  58. recordInput: false,
  59. handler: executeFeedbackCommand,
  60. })
  61. }