{"version":3,"file":"trigger-commands.mjs","names":[],"sources":["../../../src/commands/trigger-commands.ts"],"sourcesContent":["/**\n * /triggers — view and manage active triggers (price watches, cron schedules).\n *\n * Commands:\n *   /triggers         — list all active triggers with plan info\n *   /triggers_price   — list active price watches\n *   /triggers_cron    — list active cron-scheduled plans\n *   /dead_letter      — view terminal failures from the dead-letter log\n */\n\nimport { getScheduler } from '../services/plan-scheduler.js';\nimport type { Plan } from '../services/plan-types.js';\n\nfunction triggerType(plan: Plan): string {\n  if (!plan.trigger) return 'immediate';\n  return plan.trigger.type;\n}\n\nfunction formatTriggerDetail(plan: Plan): string {\n  const t = plan.trigger;\n  if (!t) return 'Trigger: immediate';\n\n  switch (t.type) {\n    case 'price':\n      return `${t.token} ${t.condition} $${t.threshold}${t.recurring ? ' (recurring)' : ' (once)'}`;\n    case 'cron':\n      return `cron: \\`${t.expression}\\`${t.timezone ? ` (${t.timezone})` : ''}${t.maxRuns ? ` max ${t.maxRuns} runs` : ''}`;\n    case 'interval':\n      return `every ${formatMs(t.everyMs)}${t.maxRuns ? ` (max ${t.maxRuns})` : ''}`;\n    case 'condition':\n      return `condition-based (poll every ${formatMs(t.pollIntervalMs ?? 60_000)})`;\n    case 'time':\n      return `at ${new Date(t.at).toLocaleString()}`;\n    case 'immediate':\n      return 'immediate';\n    case 'onchain_event':\n      return `on-chain: ${t.eventSignature} on ${t.contractAddress.slice(0, 10)}...${t.recurring ? ' (recurring)' : ' (once)'}`;\n    case 'balance':\n      return `${t.token} balance ${t.condition} ${t.threshold}${t.recurring ? ' (recurring)' : ' (once)'}`;\n    default:\n      return `unknown trigger type`;\n  }\n}\n\nfunction formatMs(ms: number): string {\n  if (ms >= 86_400_000) return `${Math.round(ms / 86_400_000)}d`;\n  if (ms >= 3_600_000) return `${Math.round(ms / 3_600_000)}h`;\n  if (ms >= 60_000) return `${Math.round(ms / 60_000)}m`;\n  return `${Math.round(ms / 1000)}s`;\n}\n\nfunction statusBadge(status: string): string {\n  switch (status) {\n    case 'scheduled': return 'ACTIVE';\n    case 'running': return 'RUNNING';\n    case 'paused': return 'PAUSED';\n    default: return status.toUpperCase();\n  }\n}\n\nexport const triggersCommand = {\n  name: 'triggers',\n  description: 'List all active triggers',\n  acceptsArgs: false,\n  requireAuth: true,\n\n  handler: async () => {\n    const scheduler = getScheduler();\n    const plans = scheduler.listPlans().filter(p =>\n      ['scheduled', 'running', 'paused'].includes(p.status) &&\n      p.trigger && p.trigger.type !== 'immediate',\n    );\n\n    if (plans.length === 0) {\n      return {\n        text: 'No active triggers.\\n\\nSet one up: \"when ETH hits $4000, sell half\" or \"every day at 9am, check my portfolio\"',\n      };\n    }\n\n    const lines = [`**Active Triggers** (${plans.length})`, ''];\n\n    for (const plan of plans) {\n      lines.push(`[${statusBadge(plan.status)}] **${plan.name}**`);\n      lines.push(`  Type: ${triggerType(plan)}`);\n      lines.push(`  ${formatTriggerDetail(plan)}`);\n      lines.push(`  ID: \\`${plan.id}\\``);\n      lines.push('');\n    }\n\n    lines.push('/triggers_price | /triggers_cron | /plans_cancel');\n\n    return { text: lines.join('\\n') };\n  },\n};\n\nexport const triggersPriceCommand = {\n  name: 'triggers_price',\n  description: 'List active price triggers',\n  acceptsArgs: false,\n  requireAuth: true,\n\n  handler: async () => {\n    const scheduler = getScheduler();\n    const plans = scheduler.listPlans().filter(p =>\n      ['scheduled', 'running', 'paused'].includes(p.status) &&\n      p.trigger?.type === 'price',\n    );\n\n    if (plans.length === 0) {\n      return {\n        text: 'No active price triggers.\\n\\nSet one: \"when BTC drops below $50k, buy 0.1 BTC\"',\n      };\n    }\n\n    const lines = [`**Price Triggers** (${plans.length})`, ''];\n\n    for (const plan of plans) {\n      const t = plan.trigger;\n      if (t?.type !== 'price') continue;\n      lines.push(`[${statusBadge(plan.status)}] **${plan.name}**`);\n      lines.push(`  ${t.token} ${t.condition} $${t.threshold}`);\n      if (t.recurring) lines.push('  Recurring: yes');\n      if (t.hysteresisPercent && t.hysteresisPercent !== 1) {\n        lines.push(`  Hysteresis: ${t.hysteresisPercent}%`);\n      }\n      lines.push(`  ID: \\`${plan.id}\\``);\n      lines.push('');\n    }\n\n    return { text: lines.join('\\n') };\n  },\n};\n\nexport const triggersCronCommand = {\n  name: 'triggers_cron',\n  description: 'List active cron triggers',\n  acceptsArgs: false,\n  requireAuth: true,\n\n  handler: async () => {\n    const scheduler = getScheduler();\n    const plans = scheduler.listPlans().filter(p =>\n      ['scheduled', 'running', 'paused'].includes(p.status) &&\n      p.trigger?.type === 'cron',\n    );\n\n    if (plans.length === 0) {\n      return {\n        text: 'No active cron triggers.\\n\\nSet one: \"every Monday at 9am, rebalance my portfolio\"',\n      };\n    }\n\n    const lines = [`**Cron Triggers** (${plans.length})`, ''];\n\n    for (const plan of plans) {\n      const t = plan.trigger;\n      if (t?.type !== 'cron') continue;\n      lines.push(`[${statusBadge(plan.status)}] **${plan.name}**`);\n      lines.push(`  Expression: \\`${t.expression}\\``);\n      if (t.timezone) lines.push(`  Timezone: ${t.timezone}`);\n      if (t.maxRuns) lines.push(`  Max runs: ${t.maxRuns}`);\n      lines.push(`  ID: \\`${plan.id}\\``);\n      lines.push('');\n    }\n\n    return { text: lines.join('\\n') };\n  },\n};\n\nexport const deadLetterCommand = {\n  name: 'dead_letter',\n  description: 'View terminal plan failures',\n  acceptsArgs: false,\n  requireAuth: true,\n\n  handler: async () => {\n    const scheduler = getScheduler();\n    const entries = scheduler.loadDeadLetters();\n\n    if (entries.length === 0) {\n      return {\n        text: 'No dead-letter entries. All plans have completed successfully or are still running.',\n      };\n    }\n\n    const lines = [`**Dead-Letter Log** (${entries.length} failures)`, ''];\n\n    for (const entry of entries.slice(0, 10)) {\n      const age = Date.now() - entry.timestamp;\n      lines.push(`**Plan:** \\`${entry.planId}\\` | **Node:** \\`${entry.nodeId}\\``);\n      if (entry.tool) lines.push(`  Tool: ${entry.tool}`);\n      lines.push(`  Error: ${entry.error}`);\n      lines.push(`  Retries: ${entry.retryCount} | ${formatMs(age)} ago`);\n      lines.push('');\n    }\n\n    if (entries.length > 10) {\n      lines.push(`...and ${entries.length - 10} more`);\n    }\n\n    lines.push('Use compound_action with action=\"dead_letter\" clear=true to purge.');\n\n    return { text: lines.join('\\n') };\n  },\n};\n"],"mappings":"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"}