Skip to main content

工具注册

所有 tool 在 createTools(resourceId, threadId, model?, taskId?)(src/ai/tools/index.ts)里注册,每个都用 withTracking 包一层 —— 自动绑定 OTel kira.tool.name、记 ai.tool.duration{tool,success,error_type}、发 PostHog tool_usage,并把不安全的 provider 报错替换成对用户友好的兜底文案(原始错误经 cause 仍进 Dash0)。 当前注册 25 个 tool:
统计口径以 createTools 实际返回的对象为准(src/ai/tools/index.ts)。没有任何 music / audio 工具 —— 音频特性已退役,无法生成、上传或读取。

图像生成 / 编辑(共 11)

Tool用途
generateImageWithAI从文本 prompt 生成全新图(可带最多 9 张参考图)
imageEdit编辑已有图(改内容 / 风格迁移 / 合图 / 改比例 / 保身份);对话里的 inpaint 也走它
removeBackground抠除背景
replaceBackgroundWithPrompt用 prompt 换背景
replaceBackgroundWithImage用参考图换背景
inpaintWithPrompt按 mask + prompt 局部重绘
inpaintWithImage按 mask + 参考图局部重绘
expand外扩画布(outpaint)
eraser擦除指定区域(保持 FAL fal-ai/bria/eraser)
upscale超分放大
redux图像变体 / 风格再创作

generateImageWithAI 的 NSFW provider 路由

文生图按”是否 NSFW + 是否带参考图”选 provider(src/ai/tools/generateImageWithAI.ts):
NSFW prompt 且无参考图  → BytePlus Seedream 4.5(NSFW t2i)
其余(SFW,或任意带参考图) → DashScope WAN 2.7 image
  • NSFW 判定由 utility 模型(gemini-3.1-flash-lite)做,fail-safe 到 NSFW(判定失败时全部走 Seedream)。
  • 带参考图时跳过 NSFW 判定,直接走 WAN 2.7。

imageEdit 的多 provider 路由

imageEdit 一个工具按 “anime 与否 + 是否 ultra plan” fallback 到 3 个 provider(src/ai/tools/imageEdit.ts):
输入特征路由
anime + ultragpt-image-2 → 失败 fallback seedream-4.5
anime + 非 ultraseedream-4.5
写实 + ultragpt-image-2 → 失败 fallback wan2.7-image
写实 + 非 ultrawan2.7-image
anime 判定同样由 utility 模型做(fail-soft 到非 anime)。credit:ultra 路径 gpt-image-2 扣 15,其余扣 5。

视频(共 5)

Tool用途
generateVideo文生视频 / 图生视频(异步,worker 完成后通知)
videoEdit视频局部编辑(WAN 2.7 VideoEdit)
videoExtend视频续帧延长
motionControl运动控制(TencentCloud VOD + Kling)
trimVideo裁剪

generateVideo 的 provider 路由

generateVideomodel tier 选 provider(src/ai/tools/generateVideo.ts),不是按 NSFW:
switch (model) {
  case "nova":
  case "ultra": provider = "dashscope-wan27"; break; // WAN 2.7(model: wan2.7-video)
  case "lite":
  default:      provider = "seedance";        break; // Seedance(model: seedance-1.5-pro)
}
tierprovider上报 model 名
lite(及默认)seedanceseedance-1.5-pro
nova / ultradashscope-wan27wan2.7-video
视频工具不在 agent 进程里直接调 provider,而是返回一个 pending task,由 onFinish 通过 Trigger.dev 触发 worker 上的 task(见下)。status 可能是 pending / insufficient_credits / insufficient_plan,后两者要求 agent 停手并提示用户。

交互式工具(共 6)

这些 tool 不直接产出资产,而是向前端发出”需要用户操作”的信号(选 mask、选滤镜、确认裁剪等),由前端 UI 接管:
Tool用途
initializeWithImage用一张图初始化画布
initializeWithVideo用一段视频初始化画布(也是上传视频的路由目标)
getMaskImageFromUser请用户绘制 inpaint mask
getExpandMaskImageFromUser请用户指定外扩区域
getFilterChoiceFromUser请用户选滤镜 / 调色预设
getAutoCropResultFromUser请用户确认自动裁剪结果

工具类(共 3)

Tool用途
googleSearch实时检索(时事 / 事实核查 / 真实主体的视觉参考)
readImage读取/理解一张图(用户上传图的路由目标)
readVideo读取/理解一段视频
本类共 3 项(googleSearch / readImage / readVideo)。图像 11 + 视频 5 + 交互 6 + 工具 3 = 25 个注册 tool。

视频工具 → Trigger.dev

会产出视频的 tool(generateVideo / videoEdit / videoExtend / motionControl / trimVideo)不在 agent 进程里同步生成。run 的 onFinishpending 视频从 responseMessage.parts 收集出来,落 thread_version,然后通过 kira-agent/src/lib/tasks.tspublishVideoTask 触发 Trigger.dev Cloud 上的 task(由 kira-video-worker 执行):
// kira-agent/src/lib/tasks.ts —— 用 @trigger.dev/sdk/v3 触发任务
import { tasks } from "@trigger.dev/sdk/v3";

// SDK 从环境读 TRIGGER_SECRET_KEY(env-scoped:DEV key 路由到本地
// `trigger.dev dev` worker,PROD key 路由到已部署 worker)。
await tasks.trigger(
  triggerTaskId,                         // toolName[:provider] -> task id(见下表)
  { ...task, priority: getPriority(userPlan) },
  {
    tags: [`videoTask:${task.taskId}`],  // 供 purgeVideoTasks 按业务 taskId 找到本次 run 取消
    priority: getPriority(userPlan),     // Pro/Max plan = 100,free = 0,用于插队
  },
);
task id 按 toolName[:provider] 路由(替代旧的 Inngest 事件名 video/{action}-{provider}.requested):
toolName[:provider]task id
generateVideo:seedancevideo-generation-seedance
generateVideo:dashscope-wan27video-generation-dashscope-wan27
videoEdit:dashscope-wan27video-edit-dashscope-wan27
videoExtend:dashscope-wan27video-extend-dashscope-wan27
motionControlvideo-motion-control-tencentcloud-vod-kling
trimVideovideo-trim-kira
upload(由 kira-cdn 触发,非 kira-agent)video-upload-kira
每次 trigger 都给 run 打 videoTask:<businessTaskId> 标签。kira-be 不是 publisher,它只负责取消在途的 run(kira-be/src/lib/tasks.tspurgeVideoTasks):按 tag 列出 run(runs.list({ tag }))再对仍可取消的调 runs.cancel() —— 已经没有 video/task.cancelled 事件了。
鉴权只需一个 env:TRIGGER_SECRET_KEY(每个 publisher / canceller 服务各一份,environment-scoped)。它替代了旧的 INNGEST_EVENT_KEY + INNGEST_SIGNING_KEY(以及 INNGEST_BASE_URL / INNGEST_API_BASE_URL / INNGEST_SERVE_ORIGIN / INNGEST_DEV)。本地开发跑 Trigger.dev CLI dev 会话 bunx trigger.dev@latest dev(在 kira-video-worker 里);已没有 localhost:8288 本地事件服务器,也没有 /api/inngest webhook。
并发由 worker 侧的 per-provider 全局 queue 控制(kira-video-worker/src/trigger/_shared.tsqueue({ name, concurrencyLimit })):seedance 200、dashscope-wan27 200(gen + edit + extend 共享同一上游配额)、motion-control 50。publisher 不传 concurrencyKey,所以这些上限是真正的全局上限。Trigger.dev 用 CRIU 在 wait.for 处对 run 做 checkpoint,没有 replay(不像 Inngest 的 step replay):task 的 run() 就是一段普通 async 函数,无 step.run 包裹;配合 retry.maxAttempts=1,credit 恰好扣一次。
worker 侧处理详见 Kira Video Worker

参考