{"version":3,"file":"policy-manage.mjs","names":[],"sources":["../../../src/tools/policy-manage.ts"],"sourcesContent":["/**\n * policy_manage — LLM-facing tool for creating and managing spending policies.\n *\n * Creation flow (multi-turn with explicit confirmation):\n * 1. User says something like \"don't spend more than $500/day on swaps\"\n * 2. LLM calls `propose` with structured interpretation\n * 3. Tool saves as DRAFT and returns the exact rules for user to verify\n * 4. User says \"yes\" / adjusts → LLM calls `confirm` to activate\n *\n * The LLM MUST NOT call `confirm` without the user explicitly approving.\n * If the user's intent is ambiguous, the LLM should ask follow-up questions\n * BEFORE calling `propose`.\n */\n\nimport { Type } from '@sinclair/typebox';\nimport { randomUUID } from 'node:crypto';\nimport { stringEnum, jsonResult, errorResult } from '../lib/tool-helpers.js';\nimport { getPolicyStore } from '../services/policy-store.js';\nimport {\n  evaluatePolicies,\n  buildPolicyDisplay,\n  renderPolicyDisplay,\n  extractPolicyUserId,\n} from '../services/policy-evaluator.js';\nimport {\n  type Policy,\n  type PolicyRule,\n  type PolicyScope,\n  type ActionContext,\n  describeRule,\n  describeScope,\n  TOOL_CATEGORIES,\n  CATEGORY_LABELS,\n} from '../services/policy-types.js';\n\n// ─── Schema ─────────────────────────────────────────────────────────────\n\nconst ACTIONS = [\n  'propose',       // create a draft policy from structured rules (needs user confirm)\n  'confirm',       // activate a draft after user approval\n  'revise',        // update a draft's rules before confirming\n  'list',          // list all policies\n  'get',           // get details of one policy\n  'disable',       // pause enforcement\n  'enable',        // resume enforcement\n  'delete',        // remove a policy\n  'evaluate',      // dry-run: check if an action would be allowed\n  'usage',         // show usage stats for a policy\n  'categories',    // list available tool categories\n] as const;\n\nconst RULE_TYPES = [\n  'spending_limit', 'rate_limit', 'allowlist', 'blocklist',\n  'time_window', 'approval_threshold', 'max_amount',\n] as const;\n\nconst PERIODS = ['hourly', 'daily', 'weekly', 'monthly'] as const;\nconst FIELDS = ['tokens', 'chains', 'addresses', 'contracts'] as const;\nconst SCOPE_TYPES = ['all_write', 'tools', 'categories'] as const;\n\nconst PolicyManageSchema = Type.Object({\n  action: stringEnum(ACTIONS, {\n    description: 'Action to perform. IMPORTANT: \"propose\" creates a DRAFT — you MUST show the user the exact rules and get explicit approval before calling \"confirm\".',\n  }),\n  // For propose / revise\n  name: Type.Optional(Type.String({\n    description: 'Short policy name (e.g., \"daily DeFi limit\")',\n  })),\n  description: Type.Optional(Type.String({\n    description: 'The user\\'s EXACT original words that define this policy. Do not paraphrase.',\n  })),\n  rules: Type.Optional(Type.Array(Type.Object({\n    type: stringEnum(RULE_TYPES, { description: 'Rule type' }),\n    maxAmountUsd: Type.Optional(Type.Number({ description: 'USD limit (spending_limit, max_amount)' })),\n    period: Type.Optional(stringEnum(PERIODS, { description: 'Period (spending_limit)' })),\n    maxCalls: Type.Optional(Type.Number({ description: 'Max calls (rate_limit)' })),\n    periodMs: Type.Optional(Type.Number({ description: 'Window in ms (rate_limit)' })),\n    field: Type.Optional(stringEnum(FIELDS, { description: 'Field (allowlist, blocklist)' })),\n    values: Type.Optional(Type.Array(Type.String(), { description: 'Values (allowlist, blocklist)' })),\n    allowedHours: Type.Optional(Type.Object({\n      start: Type.Number({ description: 'Start hour 0-23' }),\n      end: Type.Number({ description: 'End hour 0-23' }),\n    })),\n    allowedDays: Type.Optional(Type.Array(Type.Number(), { description: 'Days 0=Sun..6=Sat' })),\n    timezone: Type.Optional(Type.String({ description: 'IANA timezone' })),\n    amountUsd: Type.Optional(Type.Number({ description: 'USD threshold (approval_threshold)' })),\n  }), { description: 'Policy rules. Each is independently evaluated.' })),\n  scope: Type.Optional(Type.Object({\n    type: stringEnum(SCOPE_TYPES, { description: 'Scope type' }),\n    tools: Type.Optional(Type.Array(Type.String(), { description: 'Tool names (scope=tools)' })),\n    categories: Type.Optional(Type.Array(Type.String(), { description: 'Category names (scope=categories)' })),\n  })),\n  // For confirm, revise, get, disable, enable, delete, usage\n  policyId: Type.Optional(Type.String({ description: 'Policy ID' })),\n  // For evaluate (dry-run)\n  toolName: Type.Optional(Type.String({ description: 'Tool to check (evaluate)' })),\n  amountUsd: Type.Optional(Type.Number({ description: 'USD amount to check (evaluate)' })),\n  token: Type.Optional(Type.String({ description: 'Token to check (evaluate)' })),\n});\n\n// ─── Tool ───────────────────────────────────────────────────────────────\n\nexport function createPolicyManageTool() {\n  return {\n    name: 'policy_manage',\n    label: 'Policy Manager',\n    ownerOnly: true,\n    description: [\n      'Create and manage spending policies that limit what the agent can do autonomously.',\n      '',\n      'CRITICAL WORKFLOW for creating policies:',\n      '1. If the user\\'s request is ambiguous, ASK CLARIFYING QUESTIONS first.',\n      '2. Call \"propose\" with your structured interpretation — this creates a DRAFT.',\n      '3. Show the user EXACTLY what will be enforced (the tool returns this).',\n      '4. WAIT for the user to explicitly approve.',\n      '5. Only then call \"confirm\" to activate.',\n      '',\n      'NEVER skip step 3-4. NEVER call \"confirm\" without user approval.',\n      'NEVER guess what the user means — ask if unclear.',\n      '',\n      'Actions: propose, confirm, revise, list, get, disable, enable, delete, evaluate, usage, categories',\n    ].join('\\n'),\n    parameters: PolicyManageSchema,\n\n    execute: async (_toolCallId: string, args: unknown, ctx?: any) => {\n      const params = args as Record<string, unknown>;\n      const action = params.action as string;\n      const userId = extractPolicyUserId(ctx);\n\n      switch (action) {\n        case 'propose':   return handlePropose(params, userId);\n        case 'confirm':   return handleConfirm(params, userId);\n        case 'revise':    return handleRevise(params, userId);\n        case 'list':      return handleList(userId);\n        case 'get':       return handleGet(params, userId);\n        case 'disable':   return handleDisable(params, userId);\n        case 'enable':    return handleEnable(params, userId);\n        case 'delete':    return handleDelete(params, userId);\n        case 'evaluate':  return handleEvaluate(params, userId);\n        case 'usage':     return handleUsage(params, userId);\n        case 'categories': return handleCategories();\n        default:\n          return errorResult(`Unknown action: ${action}`);\n      }\n    },\n  };\n}\n\n// ─── Handlers ───────────────────────────────────────────────────────────\n\nfunction handlePropose(params: Record<string, unknown>, userId: string) {\n  const name = params.name as string | undefined;\n  const description = params.description as string | undefined;\n  const rawRules = params.rules as any[] | undefined;\n  const rawScope = params.scope as any | undefined;\n\n  if (!name) return errorResult('Policy name is required.');\n  if (!description) return errorResult('Description is required — use the user\\'s exact words.');\n  if (!rawRules || rawRules.length === 0) return errorResult('At least one rule is required.');\n  if (!rawScope) return errorResult('Scope is required (all_write, tools, or categories).');\n\n  // Check for duplicate name\n  const store = getPolicyStore();\n  const existing = store.getPolicyByName(userId, name);\n  if (existing) return errorResult(`A policy named \"${name}\" already exists (id: ${existing.id}).`);\n\n  let rules: PolicyRule[];\n  try {\n    rules = rawRules.map(parseRule);\n  } catch (err) {\n    return errorResult(`Invalid rule: ${err instanceof Error ? err.message : String(err)}`);\n  }\n  const scope = parseScope(rawScope);\n\n  const policy: Policy = {\n    id: randomUUID(),\n    name,\n    description,\n    rules,\n    scope,\n    status: 'draft',\n    createdAt: Date.now(),\n    updatedAt: Date.now(),\n    userId,\n  };\n\n  try {\n    store.savePolicy(policy);\n  } catch (err) {\n    return errorResult(err instanceof Error ? err.message : String(err));\n  }\n\n  // Render for user verification\n  const display = buildPolicyDisplay(policy, userId);\n  const rendered = renderPolicyDisplay(display);\n\n  return jsonResult({\n    status: 'draft_created',\n    policyId: policy.id,\n    message: [\n      'DRAFT policy created. Show the user this exact interpretation and ask them to confirm:',\n      '',\n      rendered,\n      '',\n      'Ask the user: \"Does this match what you want? Say yes to activate, or tell me what to change.\"',\n      'Call \"confirm\" ONLY after the user explicitly approves.',\n    ].join('\\n'),\n  });\n}\n\nfunction handleConfirm(params: Record<string, unknown>, userId: string) {\n  const policyId = params.policyId as string | undefined;\n  if (!policyId) return errorResult('policyId is required.');\n\n  const store = getPolicyStore();\n  const policy = store.getPolicy(userId, policyId);\n  if (!policy) return errorResult(`Policy ${policyId} not found.`);\n  if (policy.status === 'active') return errorResult('Policy is already active.');\n\n  policy.status = 'active';\n  policy.confirmedAt = Date.now();\n  policy.updatedAt = Date.now();\n  store.savePolicy(policy);\n\n  const display = buildPolicyDisplay(policy, userId);\n  const rendered = renderPolicyDisplay(display);\n\n  return jsonResult({\n    status: 'activated',\n    policyId: policy.id,\n    message: `Policy \"${policy.name}\" is now ACTIVE.\\n\\n${rendered}`,\n  });\n}\n\nfunction handleRevise(params: Record<string, unknown>, userId: string) {\n  const policyId = params.policyId as string | undefined;\n  if (!policyId) return errorResult('policyId is required.');\n\n  const store = getPolicyStore();\n  const policy = store.getPolicy(userId, policyId);\n  if (!policy) return errorResult(`Policy ${policyId} not found.`);\n  if (policy.status === 'active') {\n    return errorResult('Cannot revise an active policy. Disable it first, or delete and re-propose.');\n  }\n\n  // Update fields that are provided\n  if (params.name) {\n    const newName = params.name as string;\n    // Check duplicate name (skip if same policy)\n    const dup = store.getPolicyByName(userId, newName);\n    if (dup && dup.id !== policy.id) {\n      return errorResult(`A policy named \"${newName}\" already exists (id: ${dup.id}).`);\n    }\n    policy.name = newName;\n  }\n  if (params.description) policy.description = params.description as string;\n  if (params.rules && Array.isArray(params.rules) && (params.rules as any[]).length > 0) {\n    try {\n      policy.rules = (params.rules as any[]).map(parseRule);\n    } catch (err) {\n      return errorResult(`Invalid rule: ${err instanceof Error ? err.message : String(err)}`);\n    }\n  }\n  if (params.scope) policy.scope = parseScope(params.scope);\n\n  policy.updatedAt = Date.now();\n  store.savePolicy(policy);\n\n  const display = buildPolicyDisplay(policy, userId);\n  const rendered = renderPolicyDisplay(display);\n\n  return jsonResult({\n    status: 'draft_revised',\n    policyId: policy.id,\n    message: [\n      'Draft revised. Show the user this updated interpretation:',\n      '',\n      rendered,\n      '',\n      'Ask: \"Does this look right now?\"',\n    ].join('\\n'),\n  });\n}\n\nfunction handleList(userId: string) {\n  const store = getPolicyStore();\n  const policies = store.listPolicies(userId);\n\n  if (policies.length === 0) {\n    return jsonResult({\n      policies: [],\n      message: 'No policies set. The user can say something like \"don\\'t let me spend more than $500 a day\" to create one.',\n    });\n  }\n\n  const summaries = policies.map(p => {\n    const display = buildPolicyDisplay(p, userId);\n    return renderPolicyDisplay(display);\n  });\n\n  return jsonResult({\n    count: policies.length,\n    policies: policies.map(p => ({\n      id: p.id,\n      name: p.name,\n      status: p.status,\n      ruleCount: p.rules.length,\n    })),\n    rendered: summaries.join('\\n\\n---\\n\\n'),\n  });\n}\n\nfunction handleGet(params: Record<string, unknown>, userId: string) {\n  const policyId = params.policyId as string | undefined;\n  if (!policyId) return errorResult('policyId is required.');\n\n  const store = getPolicyStore();\n  const policy = store.getPolicy(userId, policyId);\n  if (!policy) return errorResult(`Policy ${policyId} not found.`);\n\n  const display = buildPolicyDisplay(policy, userId);\n  return jsonResult({\n    policy: {\n      id: policy.id,\n      name: policy.name,\n      status: policy.status,\n      description: policy.description,\n      rules: policy.rules,\n      scope: policy.scope,\n      createdAt: new Date(policy.createdAt).toISOString(),\n      updatedAt: new Date(policy.updatedAt).toISOString(),\n    },\n    rendered: renderPolicyDisplay(display),\n  });\n}\n\nfunction handleDisable(params: Record<string, unknown>, userId: string) {\n  const policyId = params.policyId as string | undefined;\n  if (!policyId) return errorResult('policyId is required.');\n\n  const store = getPolicyStore();\n  const policy = store.getPolicy(userId, policyId);\n  if (!policy) return errorResult(`Policy ${policyId} not found.`);\n\n  policy.status = 'disabled';\n  policy.updatedAt = Date.now();\n  store.savePolicy(policy);\n\n  return jsonResult({\n    status: 'disabled',\n    message: `Policy \"${policy.name}\" is now disabled. It will not be enforced until re-enabled.`,\n  });\n}\n\nfunction handleEnable(params: Record<string, unknown>, userId: string) {\n  const policyId = params.policyId as string | undefined;\n  if (!policyId) return errorResult('policyId is required.');\n\n  const store = getPolicyStore();\n  const policy = store.getPolicy(userId, policyId);\n  if (!policy) return errorResult(`Policy ${policyId} not found.`);\n\n  // Policies created via /policies create or via direct tool call\n  // may not have confirmedAt. Accept any policy for re-enabling.\n\n  policy.status = 'active';\n  policy.updatedAt = Date.now();\n  store.savePolicy(policy);\n\n  return jsonResult({\n    status: 'active',\n    message: `Policy \"${policy.name}\" is now active and being enforced.`,\n  });\n}\n\nfunction handleDelete(params: Record<string, unknown>, userId: string) {\n  const policyId = params.policyId as string | undefined;\n  if (!policyId) return errorResult('policyId is required.');\n\n  const store = getPolicyStore();\n  const policy = store.getPolicy(userId, policyId);\n  if (!policy) return errorResult(`Policy ${policyId} not found.`);\n\n  store.deletePolicy(userId, policyId);\n\n  return jsonResult({\n    status: 'deleted',\n    message: `Policy \"${policy.name}\" has been deleted.`,\n  });\n}\n\nfunction handleEvaluate(params: Record<string, unknown>, userId: string) {\n  const toolName = params.toolName as string | undefined;\n  if (!toolName) return errorResult('toolName is required for evaluate.');\n\n  const actionCtx: ActionContext = {\n    toolName,\n    userId,\n    amountUsd: params.amountUsd as number | undefined,\n    token: params.token as string | undefined,\n  };\n\n  const decision = evaluatePolicies(actionCtx);\n\n  return jsonResult({\n    decision: decision.action,\n    reason: decision.reason ?? 'No policy violations.',\n    policyName: decision.policyName,\n    ruleSummary: decision.ruleSummary,\n  });\n}\n\nfunction handleUsage(params: Record<string, unknown>, userId: string) {\n  const policyId = params.policyId as string | undefined;\n  if (!policyId) return errorResult('policyId is required.');\n\n  const store = getPolicyStore();\n  const policy = store.getPolicy(userId, policyId);\n  if (!policy) return errorResult(`Policy ${policyId} not found.`);\n\n  const usage = store.getUsage(userId, policyId);\n  const display = buildPolicyDisplay(policy, userId);\n\n  return jsonResult({\n    policyName: policy.name,\n    usageSummary: display.usageSummary ?? 'No usage tracked (no spending/rate limits).',\n    recentEntries: (usage?.entries ?? []).slice(-20).map(e => ({\n      time: new Date(e.timestamp).toISOString(),\n      tool: e.toolName,\n      action: e.action,\n      amountUsd: e.amountUsd,\n    })),\n  });\n}\n\nfunction handleCategories() {\n  const cats = Object.entries(CATEGORY_LABELS).map(([key, label]) => ({\n    key,\n    label,\n    tools: TOOL_CATEGORIES[key] ?? [],\n  }));\n\n  return jsonResult({\n    categories: cats,\n    message: 'Available tool categories for policy scopes. Use category keys in scope.categories.',\n  });\n}\n\n// ─── Parsing Helpers ────────────────────────────────────────────────────\n\n/**\n * Parse and validate a raw rule from the LLM.\n * Throws on missing required fields or unknown types instead of silently\n * defaulting (which could create zero-limit policies that block everything\n * or miss enforcement entirely).\n */\nfunction parseRule(raw: any): PolicyRule {\n  const type = raw.type as string;\n  switch (type) {\n    case 'spending_limit': {\n      if (raw.maxAmountUsd == null || typeof raw.maxAmountUsd !== 'number') {\n        throw new Error('spending_limit rule requires maxAmountUsd (number).');\n      }\n      if (raw.period == null) {\n        throw new Error('spending_limit rule requires period (hourly|daily|weekly|monthly).');\n      }\n      const validPeriods = ['hourly', 'daily', 'weekly', 'monthly'];\n      if (!validPeriods.includes(raw.period)) {\n        throw new Error(`spending_limit period must be one of: ${validPeriods.join(', ')}. Got: \"${raw.period}\".`);\n      }\n      return {\n        type: 'spending_limit',\n        maxAmountUsd: raw.maxAmountUsd,\n        period: raw.period,\n      };\n    }\n    case 'rate_limit': {\n      if (raw.maxCalls == null || typeof raw.maxCalls !== 'number') {\n        throw new Error('rate_limit rule requires maxCalls (number).');\n      }\n      if (raw.periodMs == null || typeof raw.periodMs !== 'number') {\n        throw new Error('rate_limit rule requires periodMs (number, milliseconds).');\n      }\n      return {\n        type: 'rate_limit',\n        maxCalls: raw.maxCalls,\n        periodMs: raw.periodMs,\n      };\n    }\n    case 'allowlist': {\n      if (!raw.field) {\n        throw new Error('allowlist rule requires field (tokens|chains|addresses|contracts).');\n      }\n      if (!raw.values || !Array.isArray(raw.values) || raw.values.length === 0) {\n        throw new Error('allowlist rule requires values (non-empty array).');\n      }\n      return {\n        type: 'allowlist',\n        field: raw.field,\n        values: raw.values.map((v: string) => v.toLowerCase()),\n      };\n    }\n    case 'blocklist': {\n      if (!raw.field) {\n        throw new Error('blocklist rule requires field (tokens|chains|addresses|contracts).');\n      }\n      if (!raw.values || !Array.isArray(raw.values) || raw.values.length === 0) {\n        throw new Error('blocklist rule requires values (non-empty array).');\n      }\n      return {\n        type: 'blocklist',\n        field: raw.field,\n        values: raw.values.map((v: string) => v.toLowerCase()),\n      };\n    }\n    case 'time_window': {\n      // Validate allowedHours range\n      if (raw.allowedHours) {\n        const { start, end } = raw.allowedHours;\n        if (typeof start !== 'number' || typeof end !== 'number' || start < 0 || start > 23 || end < 0 || end > 23) {\n          throw new Error('time_window allowedHours start/end must be 0-23.');\n        }\n      }\n      // Validate allowedDays range\n      if (raw.allowedDays && Array.isArray(raw.allowedDays)) {\n        for (const d of raw.allowedDays) {\n          if (typeof d !== 'number' || d < 0 || d > 6) {\n            throw new Error('time_window allowedDays must be numbers 0 (Sun) - 6 (Sat).');\n          }\n        }\n      }\n      if (!raw.allowedHours && !raw.allowedDays) {\n        throw new Error('time_window rule requires at least allowedHours or allowedDays.');\n      }\n      return {\n        type: 'time_window',\n        allowedHours: raw.allowedHours,\n        allowedDays: raw.allowedDays,\n        timezone: raw.timezone,\n      };\n    }\n    case 'approval_threshold': {\n      if (raw.amountUsd == null || typeof raw.amountUsd !== 'number') {\n        throw new Error('approval_threshold rule requires amountUsd (number).');\n      }\n      return {\n        type: 'approval_threshold',\n        amountUsd: raw.amountUsd,\n      };\n    }\n    case 'max_amount': {\n      if (raw.maxAmountUsd == null || typeof raw.maxAmountUsd !== 'number') {\n        throw new Error('max_amount rule requires maxAmountUsd (number).');\n      }\n      return {\n        type: 'max_amount',\n        maxAmountUsd: raw.maxAmountUsd,\n      };\n    }\n    default:\n      throw new Error(`Unknown rule type: \"${type}\". Valid types: spending_limit, rate_limit, allowlist, blocklist, time_window, approval_threshold, max_amount.`);\n  }\n}\n\nfunction parseScope(raw: any): PolicyScope {\n  return {\n    type: raw.type ?? 'all_write',\n    tools: raw.tools,\n    categories: raw.categories,\n  };\n}\n"],"mappings":"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"}