qlogicagent 2.11.13 → 2.11.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -802,7 +802,7 @@ ${p}${m}`}],details:{type:"notebook_edit",edit_mode:o,cell_number:n,total_cells:
802
802
  `),parameters:P5,execute:async(e,r,n)=>{let o=Math.max(1,Math.min(3600,Math.round(r.duration))),i=o*1e3,s=new AbortController,a=()=>s.abort();n?.addEventListener("abort",a,{once:!0}),n?.aborted&&s.abort();try{let c=await t.sleep(i,s.signal),u=[];return c.interrupted?(u.push(`Sleep interrupted after ${c.sleptSeconds}s.`),c.interruptReason&&u.push(`Reason: ${c.interruptReason}`),u.push("Check for new messages or tasks.")):u.push(`Slept for ${c.sleptSeconds}s. Waking up.`),{content:[{type:"text",text:u.join(`
803
803
  `)}],details:{...c,requestedSeconds:o}}}finally{n?.removeEventListener("abort",a)}}}}var T5="tool_search",A5={type:"object",properties:{query:{type:"string",description:'Search query for tools. Use "select:toolName" to directly activate a deferred tool, or provide keywords to search tool names/descriptions. Prefix a term with "+" to mark it as required (all +terms must match).'},maxResults:{type:"number",description:"Maximum number of results to return (default: 5)."}},required:["query"]},I5=5;function W_(t){return{name:T5,label:"Tool Search",description:'Search for available tools that are not currently loaded. Many tools are deferred to save context tokens. Use "select:toolName" to directly activate a tool, or provide keywords to find relevant tools. Activated tools become available in subsequent messages.',parameters:A5,execute:async(e,r)=>{if(!r.query||r.query.trim().length===0)return{content:[{type:"text",text:"Error: query is required."}],details:{type:"tool_search",error:"empty_query"}};let n=r.query.trim(),o=r.maxResults??I5;if(n.startsWith("select:")){let s=n.slice(7).split(",").map(d=>d.trim()).filter(Boolean),a=[],c=[];if(t.activateTool)for(let d of s)await t.activateTool(d)?a.push(d):c.push(d);else{let d=await t.searchTools(n,{maxResults:o});return q_(d)}let u=[];return a.length>0&&u.push(`Activated: ${a.join(", ")}. These tools are now available.`),c.length>0&&u.push(`Not found: ${c.join(", ")}.`),{content:[{type:"text",text:u.join(`
804
804
  `)}],details:{type:"tool_search",activated:a,notFound:c,mode:"select"}}}let i=await t.searchTools(n,{maxResults:o});return q_(i)}}}function q_(t){if(t.matches.length===0)return{content:[{type:"text",text:`No tools found matching "${t.query}". Total deferred tools available: ${t.totalDeferred}.`}],details:{type:"tool_search",query:t.query,matchCount:0,totalDeferred:t.totalDeferred}};let e=[`Found ${t.matches.length} tool(s) matching "${t.query}" (${t.totalDeferred} total deferred):`,""];for(let r of t.matches)e.push(`- **${r.name}**: ${r.description}`);return e.push(""),e.push('Use "select:toolName" to activate a tool for use in subsequent messages.'),{content:[{type:"text",text:e.join(`
805
- `)}],details:{type:"tool_search",query:t.query,matchCount:t.matches.length,totalDeferred:t.totalDeferred,matches:t.matches.map(r=>r.name)}}}var gb="image_generate",C5={type:"object",properties:{prompt:{type:"string",description:"Image generation prompt. Enrich vague requests with style, lighting, composition, color, mood details."},purpose:{type:"string",description:"Intended use: 'social-media', 'short-video-cover', 'phone-wallpaper', 'avatar', 'poster', etc."},style:{type:"string",description:"Visual art style: 'photorealistic', 'anime', 'watercolor', 'oil-painting', '3d-render', etc."},size:{type:"string",description:"Dimensions: e.g. '1024x1792' (portrait), '1792x1024' (landscape), '1024x1024' (square). Default: '1024x1024'."},image_url:{type:"string",description:"Reference image URL for image-to-image generation (img2img). Character reference sheet or style transfer. MUST be a publicly accessible HTTP/HTTPS URL. Local file paths and data: URLs are NOT supported."},n:{type:"number",description:"Number of images to generate (1-4). Default: 1."},quality:{type:"string",description:"Image quality level: 'auto', 'high', 'low', 'hd'. Provider-specific."},seed:{type:"number",description:"Random seed for reproducible generation. Same seed + prompt = same result."}},required:["prompt"]};function G_(t){return{name:gb,label:"Image Generate",description:"Generate images from a text prompt. You MUST enrich vague prompts with details about style, lighting, composition, color, and mood before calling. Supports img2img via image_url reference. All generated images are saved locally and can be viewed immediately. IMPORTANT: For ordinary creative requests, infer reasonable defaults for purpose, style, and size and call this tool directly. Use ask_user only when a missing detail is critical or the request is genuinely ambiguous (e.g. the user asks for a production ad with unspecified brand constraints). Infer image size automatically from purpose (e.g. 1024x1792 for phone wallpaper, 1792x1024 for landscape poster, 1024x1024 for avatar/social). Do NOT expose size as a raw number to the user. Do NOT invent Markdown image URLs, placeholder attachment paths, or claim an image was generated without this tool returning mediaUrls. ALL reference image URLs MUST be publicly accessible HTTP/HTTPS URLs. Use file_upload tool first if the user provides a local file. Local file paths and data: URIs are NOT supported by the generation API.",parameters:C5,isEgress:!0,egressCarriesData:!0,execute:async(e,r)=>{let n=await t.generateImage({prompt:r.prompt,purpose:r.purpose,style:r.style,size:r.size,imageUrl:r.image_url,n:r.n,quality:r.quality,seed:r.seed}),o=n.mediaUrls.length;return{content:[{type:"text",text:`Generated ${o} image${o>1?"s":""}${n.model?` (model: ${n.model})`:""}`}],details:{type:"image_generate",model:n.model,size:n.size,durationMs:n.durationMs,mediaUrls:n.mediaUrls}}}}}var _5={type:"object",properties:{text:{type:"string",description:"Text to convert to speech."},channel:{type:"string",description:"Optional channel id to pick output format (e.g. telegram)."},voice:{type:"string",description:"Voice name for TTS. Available voices depend on the provider. Common options: alloy, ash, ballad, coral, echo, fable, nova, onyx, sage, shimmer."},speed:{type:"number",description:"Speech speed multiplier (0.25-4.0). Default is 1.0."}},required:["text"]};function K_(t){return{name:"tts",label:"TTS",description:"Convert text to speech (TTS) \u2014 read text aloud as spoken audio. Use for narration, voice messages, or any spoken-word output. DO NOT use for music, songs, or melodies \u2014 use music_generate instead.",parameters:_5,execute:async(e,r)=>{let n=await t.textToSpeech({text:r.text,channel:r.channel,voice:r.voice,speed:r.speed});return{content:[{type:"text",text:"\u5DF2\u6210\u529F\u751F\u6210\u8BED\u97F3\u3002"}],details:{type:"tts",audioPath:n.audioPath,provider:n.provider,voiceCompatible:n.voiceCompatible,mediaUrls:n.mediaUrls}}}}}var fb="video_generate",E5={type:"object",properties:{prompt:{type:"string",description:"Video generation prompt. MUST be in English. Include scene, movement, camera motion, lighting, style."},purpose:{type:"string",description:"Intended use: 'social-media', 'short-video', 'presentation', etc."},style:{type:"string",description:"Visual style: 'cinematic', 'anime', 'watercolor', etc."},image_url:{type:"string",description:"Reference image URL for image-to-video generation (first frame, style reference, or character reference). MUST be a publicly accessible HTTP/HTTPS URL. Local file paths and data: URLs are NOT supported. If the user provides a local file, use a file hosting service or the image_generate tool first."},reference_videos:{type:"array",items:{type:"string"},maxItems:3,description:"Reference video URLs for video-to-video or multimodal generation (Seedance 2.0). Max 3 videos, total duration \u226415s. Use for: (a) video-to-video: provide source video to restyle/transform with prompt guidance; (b) multimodal reference: combine with image_url and/or reference_audios for style/motion/audio-guided generation. Each URL MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},reference_audios:{type:"array",items:{type:"string"},maxItems:3,description:"Reference audio URLs for audio-guided video generation (Seedance 2.0). Max 3 audio clips, total duration \u226415s. CANNOT be used alone \u2014 must be combined with at least one image_url or reference_video. Each URL MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},generate_audio:{type:"boolean",description:"Generate synchronized audio track for the video (Seedance 2.0/1.5 pro). When true, the output video includes AI-generated sound effects matching the visual content."},aspect_ratio:{type:"string",description:"Video aspect ratio: '9:16' (vertical), '16:9' (horizontal), '1:1' (square). Default: '16:9'."},duration:{type:"number",minimum:3,maximum:15,description:"Video duration in seconds. Seedance 2.0: 4-15s per shot. Seedance 1.0/1.5: 3-10s. For longer videos (>15s), use multi-shot storyboard workflow (generate + extend/merge). Must be confirmed by user before generation."},resolution:{type:"string",description:"Output resolution: '480p', '720p', '1080p'. Default: '720p'."},fps:{type:"number",description:"Frame rate: 24 or 30 fps. Default: provider-specific."},seed:{type:"number",description:"Random seed for reproducible generation."},camera_fixed:{type:"boolean",description:"Lock camera position (Seedance 1.0/1.5 only, not supported for img2video)."},return_last_frame:{type:"boolean",description:"Return last frame URL for chaining continuous video segments."},draft:{type:"boolean",description:"Draft mode: low-cost preview (Seedance 1.5 pro only)."},service_tier:{type:"string",enum:["default","flex"],description:"'default' (online, fast) or 'flex' (offline, ~50% cost). Not all models support flex."},callback_url:{type:"string",description:"Webhook URL for async task completion notification."},safety_identifier:{type:"string",description:"End-user safety identifier for content moderation tracking."},execution_expires_after:{type:"number",description:"Task expiration in seconds (for offline/flex scheduling)."},video_tools:{type:"array",items:{type:"string"},description:"Video-level builtin tools, e.g. ['web_search'] (Seedance 2.0 online search)."}},required:["prompt"]};function V_(t){return{name:fb,label:"Video Generate",description:"Generate a short video clip from a text prompt, reference image, source video, or multimodal references. Prompt MUST be in English. Include scene, movement, camera motion, lighting details. Single-shot: 3\u201310s. For longer videos (>10s), use multi-shot storyboard workflow. MODES: (1) text-to-video: prompt only. (2) image-to-video: prompt + image_url. (3) video-to-video: prompt + reference_videos \u2014 restyle/transform an existing video with prompt guidance. (4) multimodal reference: prompt + any combination of image_url / reference_videos / reference_audios for style/motion/audio-guided generation. (5) generate_audio=true for synchronized sound effects. ALL image/video/audio URLs MUST be publicly accessible HTTP/HTTPS URLs. Local file paths and data: URIs are NOT supported by the generation API. If the user provides a local file, use the file_upload tool FIRST to get a public URL. IMPORTANT: If the user has not specified aspect ratio or duration, use ask_user to clarify (e.g. aspect: 16:9 for landscape / 9:16 for vertical / 1:1 for square; duration: 3-10s). Auto-set aspect_ratio based on stated purpose (e.g. 9:16 for short-video / Douyin, 16:9 for presentation).",parameters:E5,execute:async(e,r)=>{let n=await t.generateVideo({prompt:r.prompt,purpose:r.purpose,style:r.style,imageUrl:r.image_url,referenceVideos:r.reference_videos,referenceAudios:r.reference_audios,generateAudio:r.generate_audio,aspectRatio:r.aspect_ratio,duration:r.duration,resolution:r.resolution,fps:r.fps,seed:r.seed,cameraFixed:r.camera_fixed,returnLastFrame:r.return_last_frame,draft:r.draft,serviceTier:r.service_tier,callbackUrl:r.callback_url,safetyIdentifier:r.safety_identifier,executionExpiresAfterSeconds:r.execution_expires_after,videoTools:r.video_tools}),o=n.mediaUrls.length,i=[`Generated ${o} video${o>1?"s":""}`];return n.model&&i.push(`model: ${n.model}`),n.lastFrameUrl&&i.push(`last_frame: ${n.lastFrameUrl}`),n.taskId&&i.push(`task_id: ${n.taskId}`),{content:[{type:"text",text:i.length>1?`${i[0]} (${i.slice(1).join(", ")})`:i[0]}],details:{type:"video_generate",model:n.model,durationMs:n.durationMs,mediaUrls:n.mediaUrls,...n.taskId?{taskId:n.taskId}:{}}}}}}var hb="music_generate",M5={type:"object",properties:{prompt:{type:"string",description:"Music generation prompt. MUST be in English. Include genre, mood, tempo, instruments, and atmosphere details."},purpose:{type:"string",description:"Intended use: 'background-music', 'ringtone', 'short-video-bgm', 'full-song', 'notification-sound', etc."},style:{type:"string",description:"Musical style/genre: 'lo-fi', 'pop', 'rock', 'jazz', 'classical', 'electronic', 'ambient', etc."},lyrics:{type:"string",description:"Optional lyrics for vocal music. Structure with [verse], [chorus], [bridge] tags if desired."},duration:{type:"number",description:"Duration in seconds (5-300). Infer from purpose: ringtone 15-30s, BGM 30-60s, full song 120-180s."},is_instrumental:{type:"boolean",description:"Set true for pure instrumental music without vocals. Defaults to true when no lyrics are provided."},cover_audio_url:{type:"string",description:"URL of an existing audio track to use as base for cover/remix. When provided, generates a cover version. MUST be a publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},audio_format:{type:"string",enum:["mp3","wav","flac"],description:"Output audio format. Defaults to mp3."}},required:["prompt"]};function Z_(t){return{name:hb,label:"Music Generate",description:"Generate music, songs, or melodies from text descriptions. Prompt MUST be in English. Supports lyrics for vocal songs. DO NOT use for spoken-word audio or TTS \u2014 use tts tool instead. IMPORTANT: If the user has not specified genre/style or duration, use ask_user to clarify (e.g. style: lo-fi / pop / rock / jazz; duration inferred from purpose: 30s for ringtone, 60-90s for BGM, 180-240s for full song). Auto-infer duration from purpose when possible.",parameters:M5,isEgress:!0,egressCarriesData:!0,execute:async(e,r)=>{let n=r.lyrics;if(!n&&!r.is_instrumental&&t.generateLyrics)try{n=await t.generateLyrics(r.prompt)}catch{}let o=await t.generateMusic({prompt:r.prompt,purpose:r.purpose,style:r.style,lyrics:n,duration:r.duration,isInstrumental:r.is_instrumental,audioUrl:r.cover_audio_url,audioFormat:r.audio_format}),i=o.mediaUrls.length;return{content:[{type:"text",text:`Generated ${i} audio track${i>1?"s":""}${o.model?` (model: ${o.model})`:""}`}],details:{type:"music_generate",model:o.model,durationMs:o.durationMs,mediaUrls:o.mediaUrls}}}}}var D5="video_edit",N5={type:"object",properties:{prompt:{type:"string",description:"Edit instruction. Reference videos as \u89C6\u98911, \u89C6\u98912, \u89C6\u98913. Reference images as \u56FE\u72471, \u56FE\u72472. Operations: add/remove/modify elements, extend, track fill."},source_videos:{type:"array",items:{type:"string"},minItems:1,maxItems:3,description:"Video(s) to edit (1-3 URLs). Order: [0]=\u89C6\u98911, [1]=\u89C6\u98912, [2]=\u89C6\u98913. All URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},reference_images:{type:"array",items:{type:"string"},maxItems:9,description:"Optional reference images for element replacement (up to 9). All URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},duration:{type:"number",minimum:4,maximum:15,description:"Output duration in seconds (4-15s). Default: same as source."},aspect_ratio:{type:"string",description:"Output aspect ratio: 16:9, 9:16, 1:1, 4:3, 3:4, 21:9. Default: same as source."},resolution:{type:"string",description:"Output resolution: '480p' or '720p'. Default: '720p'."}},required:["prompt","source_videos"]};function J_(t){return{name:D5,label:"Video Edit",description:"Edit existing videos: add/remove/modify elements, extend, or bridge clips. Requires source_videos (max 3). Max 9 reference images for element replacement. Max 720p. All video/image URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file. For generating NEW videos from scratch, use video_generate instead.",parameters:N5,execute:async(e,r)=>{if(!r.source_videos?.length)return{content:[{type:"text",text:"Error: source_videos is required."}]};let n=await t.editVideo({prompt:r.prompt,sourceVideos:r.source_videos,referenceImages:r.reference_images,duration:r.duration,aspectRatio:r.aspect_ratio,resolution:r.resolution});return{content:[{type:"text",text:`Video edited successfully${n.model?` (model: ${n.model})`:""}`}],details:{type:"video_edit",model:n.model,durationMs:n.durationMs,mediaUrls:n.mediaUrls}}}}}var $5="video_merge",O5={type:"object",properties:{clips:{type:"array",items:{type:"object",properties:{video:{type:"string",description:"Video URL or file path. MUST be publicly accessible HTTP/HTTPS URL. Use file_upload tool first if local file."},audio:{type:"string",description:"Narration audio file path (from TTS)."},trimStart:{type:"number",description:"Trim start in seconds (default 0)."},trimEnd:{type:"number",description:"Trim end in seconds (default: full)."}},required:["video"]},minItems:2,description:"Array of video clips to merge, in order."},transition:{type:"string",description:"Transition effect: 'crossfade' (default), 'fade', 'wipeleft', 'cut', 'dissolve', etc."},transitionDuration:{type:"number",description:"Transition duration in seconds (0.1-2.0, default 0.5)."},subtitles:{type:"string",description:"Path to SRT subtitle file to burn-in."},bgm:{type:"string",description:"Background music file path."},bgmVolume:{type:"number",description:"BGM volume (0.0-1.0, default 0.15)."},outputResolution:{type:"string",description:"Output resolution: '1920x1080', '1080x1920', etc. Default: auto."},outputFps:{type:"number",description:"Output FPS (default 30)."}},required:["clips"]};function X_(t){return{name:$5,label:"Video Merge",description:"Merge multiple video clips into a single video with transitions, subtitles, and background music. Requires at least 2 clips. Supports crossfade, fade, wipe, dissolve, and cut transitions. All video/audio URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides local files. Audio per clip is preserved; BGM is mixed at adjustable volume.",parameters:O5,execute:async(e,r)=>{if(!r.clips||r.clips.length<2)return{content:[{type:"text",text:"Error: at least 2 clips are required for merging."}]};let n=await t.mergeVideos({clips:r.clips,transition:r.transition,transitionDuration:r.transitionDuration,subtitles:r.subtitles,bgm:r.bgm,bgmVolume:r.bgmVolume,outputResolution:r.outputResolution,outputFps:r.outputFps});return{content:[{type:"text",text:`Merged ${n.clipCount} clips \u2192 ${n.durationSec.toFixed(1)}s video`+(r.transition?` (transition: ${r.transition})`:"")}],details:{type:"video_merge",localPath:n.localPath,servePath:n.servePath,durationSec:n.durationSec,clipCount:n.clipCount,mediaUrls:n.mediaUrls}}}}}var j5="video_upscale",L5={type:"object",properties:{video:{type:"string",description:"Video URL to upscale. MUST be publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},targetResolution:{type:"string",description:"Target resolution: '1080p' (default, 1920x1080/1080x1920), '2k' (2560x1440/1440x2560)."},sharpness:{type:"string",description:"Sharpening intensity: 'light' (default), 'medium', 'strong'."}},required:["video"]};function Y_(t){return{name:j5,label:"Video Upscale",description:"Upscale a video to higher resolution with optional sharpening. Auto-detects orientation (landscape/portrait). Uses Lanczos interpolation + unsharp mask. Supports 1080p and 2K targets. Video URL MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file. Best used as post-processing after video_merge.",parameters:L5,execute:async(e,r)=>{let n=await t.upscaleVideo({video:r.video,targetResolution:r.targetResolution,sharpness:r.sharpness});return{content:[{type:"text",text:`Upscaled to ${n.resolution}${r.sharpness?` (sharpness: ${r.sharpness})`:""}`}],details:{type:"video_upscale",localPath:n.localPath,servePath:n.servePath,resolution:n.resolution,durationSec:n.durationSec,mediaUrls:n.mediaUrls}}}}}var U5="three_d_generate",F5={type:"object",properties:{prompt:{type:"string",description:"3D model generation prompt. Describe the object's shape, material, texture, color, and pose. For text-to-3D, provide a detailed description. For image-to-3D, also provide image_url."},image_url:{type:"string",description:"Reference image URL for image-to-3D generation. The image should show the object clearly from a single viewpoint with clean background for best results. MUST be a publicly accessible HTTP/HTTPS URL. Local file paths and data: URLs are NOT supported."},output_format:{type:"string",description:"3D model output format: 'glb' (default), 'obj', 'usd', 'usdz'."},seed:{type:"number",description:"Random seed for reproducible generation."}},required:["prompt"]};function Q_(t){return{name:U5,label:"3D Generate",description:"Generate a 3D model from a text prompt or reference image. Supports text-to-3D and image-to-3D workflows. Output formats include GLB, OBJ, USD. The generated model can be viewed in any 3D viewer or imported into game engines. IMPORTANT: Describe the object in detail \u2014 shape, size, material, texture, color, and pose.",parameters:F5,execute:async(e,r)=>{let n=await t.generate3D({prompt:r.prompt,imageUrl:r.image_url,outputFormat:r.output_format,seed:r.seed}),o=n.mediaUrls.length,i=`Generated ${o} 3D model${o>1?"s":""}${n.model?` (model: ${n.model})`:""}`;return o===0&&n.metadata?.debugResponseKeys&&(i+=` [debug: response keys=${JSON.stringify(n.metadata.debugResponseKeys)}, content=${n.metadata.debugContentSample??"null"}]`),{content:[{type:"text",text:i}],details:{type:"three_d_generate",model:n.model,durationMs:n.durationMs,mediaUrls:n.mediaUrls,...n.metadata??{}}}}}}var z5={type:"object",properties:{audio_url:{type:"string",description:"URL of the audio file to transcribe. Supports mp3, wav, m4a, ogg, flac formats. MUST be a publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},language:{type:"string",description:"Language hint for transcription: 'zh' (Chinese), 'en' (English), or auto-detect if omitted."}},required:["audio_url"]};function eE(t){return{name:"stt",label:"STT",description:"Transcribe audio to text (Speech-to-Text). Provide an audio file URL and receive the spoken content as text. Supports Chinese and English. Use for meeting transcription, voice message reading, subtitle generation, or any audio-to-text conversion.",parameters:z5,execute:async(e,r)=>{if(!r.audio_url)return{content:[{type:"text",text:"Error: audio_url parameter is required. Provide a publicly accessible HTTP/HTTPS URL to an audio file."}],details:{error:"audio_url parameter is required"}};let n=await t.speechToText({audioUrl:r.audio_url,language:r.language}),o=n.transcription.length>200?n.transcription.slice(0,200)+"\u2026":n.transcription;return{content:[{type:"text",text:n.transcription}],details:{type:"stt",model:n.model,durationMs:n.durationMs,transcriptionLength:n.transcription.length,preview:o}}}}}var H5="voice_clone",B5={type:"object",properties:{text:{type:"string",description:"Text to synthesize in the cloned voice."},sample_audio_url:{type:"string",description:"URL of an audio sample (5-30 seconds recommended) of the voice to clone. The sample should be clear speech with minimal background noise. MUST be a publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},speed:{type:"number",description:"Speech speed multiplier (0.5-2.0). Default is 1.0."}},required:["text","sample_audio_url"]};function tE(t){return{name:H5,label:"Voice Clone",description:"Clone a voice from an audio sample and synthesize new speech in that voice. Requires a clear audio sample (5-30s recommended) of the target voice. Use for personalized narration, character voices, or voice preservation. DO NOT use for impersonation or deception. For standard TTS with preset voices, use the tts tool instead.",parameters:B5,execute:async(e,r)=>{let n=await t.cloneVoice({text:r.text,sampleAudioUrl:r.sample_audio_url,speed:r.speed});return{content:[{type:"text",text:`Voice cloned and synthesized speech${n.model?` (model: ${n.model})`:""}`}],details:{type:"voice_clone",model:n.model,voiceId:n.voiceId,durationMs:n.durationMs,mediaUrls:n.mediaUrls}}}}}var q5="media_cancel",W5={type:"object",properties:{task_id:{type:"string",description:"The task ID of the media generation to cancel (returned in previous generation results)."},provider:{type:"string",description:"Provider name (e.g. 'doubao', 'zhipu'). If omitted, auto-detects from task context."}},required:["task_id"]};function rE(t){return{name:q5,label:"Media Cancel",description:"Cancel an in-progress media generation task (video, 3D, etc.). Provide the task_id from a previous generation result. Use this when a user wants to abort a long-running generation.",parameters:W5,execute:async(e,r)=>{if(!r.task_id)return{content:[{type:"text",text:"Error: task_id is required."}],details:{error:"task_id is required"}};let n=await t.cancelTask({taskId:r.task_id,provider:r.provider});return{content:[{type:"text",text:n.ok?`Task ${r.task_id} cancelled.`:`Cancel failed: ${n.message}`}],details:n.ok?void 0:{error:n.message}}}}}import ZJ from"node:fs";import JJ from"node:path";import le from"node:fs/promises";import fE from"node:os";import Y from"node:path";import{createCanvas as uu,loadImage as Rb}from"@napi-rs/canvas";import{randomUUID as G5}from"node:crypto";import dn from"node:fs";import pn from"node:path";import{fileURLToPath as K5}from"node:url";import{createCanvas as V5,loadImage as Z5}from"@napi-rs/canvas";async function yb(t){let e=await tJ(dn.readFileSync(t));for(let s of e.keys())if(wl(s))throw new Error(`unsafe path in Petdex package: ${s}`);if(e.has("manifest.json")||[...e.keys()].some(s=>s.toLowerCase().endsWith(".svg")))throw new Error("SVG .pet state packages are not supported by Petdex v1");let r=e.get("pet.json");if(!r)throw new Error("Petdex package missing pet.json");let n=e.get("spritesheet.webp");if(!n)throw new Error("Petdex package missing spritesheet.webp");let o=JSON.parse(r.toString("utf-8")),i=Vn(o,n);return{manifest:o,spritesheet:n,validation:i}}async function vb(t){let e=Vn(t.asset,t.spritesheet);dn.mkdirSync(t.outputDir,{recursive:!0});let r=eJ(t.fileName??`${t.asset.id}.petdex`),n=pn.join(t.outputDir,r.endsWith(".petdex")?r:`${r}.petdex`),o=[{name:"pet.json",data:Buffer.from(JSON.stringify(t.asset,null,2),"utf-8")},{name:"spritesheet.webp",data:t.spritesheet},{name:"validation.json",data:Buffer.from(JSON.stringify(e,null,2),"utf-8")},...t.productionRun?[{name:"production-run.json",data:Buffer.from(JSON.stringify(t.productionRun,null,2),"utf-8")}]:[]];return dn.writeFileSync(n,rJ(o)),n}async function bb(t){let e=t.now??new Date().toISOString(),r=t.id??`petdex-${G5()}`,n=await Q5(t.spritesheet),o=kv(n),i={schema:Fs,id:r,assetKind:"petdex",name:t.name,description:t.description,createdAt:e,updatedAt:e,source:{kind:t.sourceKind??"forge",prompt:t.prompt??null},sourcePrompt:t.prompt??void 0,atlas:{image:"spritesheet.webp",...X,sha256:o},animations:bv(),thumbnail:{frame:0}},s=Vn(i,n);return{asset:i,spritesheet:n,validation:s}}var J5=["builtin-anime-horse-girl"],iu=null;async function su(){return iu||(iu=Promise.all(J5.map(t=>X5(t))).catch(t=>{throw iu=null,t})),iu}async function X5(t){let e=Y5(),r=pn.join(e,`${t}.petdex`);if(dn.existsSync(r)){let u=await yb(r);return nE(t,u.manifest),{asset:u.manifest,spritesheet:u.spritesheet,validation:u.validation}}let n=pn.join(e,t),o=pn.join(n,"pet.json"),i=pn.join(n,"spritesheet.webp");if(!dn.existsSync(o)||!dn.existsSync(i))throw new Error(`Missing published builtin Petdex asset ${t} under ${e}`);let s=JSON.parse(dn.readFileSync(o,"utf-8")),a=dn.readFileSync(i),c=Vn(s,a);return nE(t,s),{asset:s,spritesheet:a,validation:c}}function Y5(){let t=process.env.QLOGICAGENT_BUILTIN_PETDEX_DIR?.trim();return t?pn.resolve(t):pn.resolve(pn.dirname(K5(import.meta.url)),"builtin-petdex")}function nE(t,e){if(e.id!==t)throw new Error(`Builtin Petdex asset id mismatch: expected ${t}, got ${e.id}`);if(e.source.kind!=="builtin")throw new Error(`Builtin Petdex asset ${t} must declare source.kind=builtin`)}async function Q5(t){let e=await Z5(t),r=V5(X.width,X.height),n=r.getContext("2d");return n.clearRect(0,0,X.width,X.height),n.imageSmoothingEnabled=!0,n.imageSmoothingQuality="high",n.drawImage(e,0,0,X.width,X.height),Buffer.from(await r.encode("webp"))}function eJ(t){return t.replace(/[^a-zA-Z0-9._-]/g,"_").replace(/^_+/,"")||"petdex-asset.petdex"}async function tJ(t){let e=new Map,r=0;for(;r<t.length-4&&t.readUInt32LE(r)===67324752;){let o=t.readUInt16LE(r+8),i=t.readUInt32LE(r+18),s=t.readUInt32LE(r+22),a=t.readUInt16LE(r+26),c=t.readUInt16LE(r+28),u=r+30,d=t.subarray(u,u+a).toString("utf-8"),p=u+a+c,m=t.subarray(p,p+i);if(o===0)e.set(d,t.subarray(p,p+s));else if(o===8){let{inflateRawSync:g}=await import("node:zlib");e.set(d,g(m))}r=p+i}return e}function rJ(t){let e=[],r=[],n=0,{time:o,date:i}=nJ();for(let u of t){if(wl(u.name))throw new Error(`unsafe path in Petdex package entry: ${u.name}`);let d=Buffer.from(u.name,"utf-8"),p=iJ(u.data),m=Buffer.alloc(30);m.writeUInt32LE(67324752,0),m.writeUInt16LE(20,4),m.writeUInt16LE(2048,6),m.writeUInt16LE(0,8),m.writeUInt16LE(o,10),m.writeUInt16LE(i,12),m.writeUInt32LE(p,14),m.writeUInt32LE(u.data.length,18),m.writeUInt32LE(u.data.length,22),m.writeUInt16LE(d.length,26),m.writeUInt16LE(0,28),e.push(m,d,u.data);let g=Buffer.alloc(46);g.writeUInt32LE(33639248,0),g.writeUInt16LE(20,4),g.writeUInt16LE(20,6),g.writeUInt16LE(2048,8),g.writeUInt16LE(0,10),g.writeUInt16LE(o,12),g.writeUInt16LE(i,14),g.writeUInt32LE(p,16),g.writeUInt32LE(u.data.length,20),g.writeUInt32LE(u.data.length,24),g.writeUInt16LE(d.length,28),g.writeUInt16LE(0,30),g.writeUInt16LE(0,32),g.writeUInt16LE(0,34),g.writeUInt16LE(0,36),g.writeUInt32LE(0,38),g.writeUInt32LE(n,42),r.push(g,d),n+=m.length+d.length+u.data.length}let s=n,a=Buffer.concat(r),c=Buffer.alloc(22);return c.writeUInt32LE(101010256,0),c.writeUInt16LE(0,4),c.writeUInt16LE(0,6),c.writeUInt16LE(t.length,8),c.writeUInt16LE(t.length,10),c.writeUInt32LE(a.length,12),c.writeUInt32LE(s,16),c.writeUInt16LE(0,20),Buffer.concat([...e,a,c])}function nJ(){let t=new Date,e=t.getHours()<<11|t.getMinutes()<<5|Math.floor(t.getSeconds()/2),r=t.getFullYear()-1980<<9|t.getMonth()+1<<5|t.getDate();return{time:e,date:r}}var oJ=new Uint32Array(256).map((t,e)=>{let r=e;for(let n=0;n<8;n++)r=r&1?3988292384^r>>>1:r>>>1;return r>>>0});function iJ(t){let e=4294967295;for(let r of t)e=oJ[(e^r)&255]^e>>>8;return(e^4294967295)>>>0}import{spawn as sJ}from"node:child_process";import{existsSync as oE}from"node:fs";import{dirname as iE,join as lu}from"node:path";import{fileURLToPath as aJ}from"node:url";var cJ=iE(aJ(import.meta.url)),au,cu;function sE(t,e,r){return new Promise(n=>{let o="",i="",s=!1,a=d=>{s||(s=!0,clearTimeout(u),n(d))},c=sJ(t,e,{windowsHide:!0}),u=setTimeout(()=>{c.kill("SIGKILL"),a({ok:!1,stdout:o,stderr:`${i}
805
+ `)}],details:{type:"tool_search",query:t.query,matchCount:t.matches.length,totalDeferred:t.totalDeferred,matches:t.matches.map(r=>r.name)}}}var gb="image_generate",C5={type:"object",properties:{prompt:{type:"string",description:"Image generation prompt. Enrich vague requests with style, lighting, composition, color, mood details."},purpose:{type:"string",description:"Intended use: 'social-media', 'short-video-cover', 'phone-wallpaper', 'avatar', 'poster', etc."},style:{type:"string",description:"Visual art style: 'photorealistic', 'anime', 'watercolor', 'oil-painting', '3d-render', etc."},size:{type:"string",description:"Dimensions: e.g. '1024x1792' (portrait), '1792x1024' (landscape), '1024x1024' (square). Default: '1024x1024'."},image_url:{type:"string",description:"Reference image URL for image-to-image generation (img2img). Character reference sheet or style transfer. MUST be a publicly accessible HTTP/HTTPS URL. Local file paths and data: URLs are NOT supported."},n:{type:"number",description:"Number of images to generate (1-4). Default: 1."},quality:{type:"string",description:"Image quality level: 'auto', 'high', 'low', 'hd'. Provider-specific."},seed:{type:"number",description:"Random seed for reproducible generation. Same seed + prompt = same result."}},required:["prompt"]};function G_(t){return{name:gb,label:"Image Generate",description:"Generate images from a text prompt. You MUST enrich vague prompts with details about style, lighting, composition, color, and mood before calling. Supports img2img via image_url reference. All generated images are saved locally and can be viewed immediately. IMPORTANT: For ordinary creative requests, infer reasonable defaults for purpose, style, and size and call this tool directly. Use ask_user only when a missing detail is critical or the request is genuinely ambiguous (e.g. the user asks for a production ad with unspecified brand constraints). Infer image size automatically from purpose (e.g. 1024x1792 for phone wallpaper, 1792x1024 for landscape poster, 1024x1024 for avatar/social). Do NOT expose size as a raw number to the user. Do NOT invent Markdown image URLs, placeholder attachment paths, or claim an image was generated without this tool returning mediaUrls. ALL reference image URLs MUST be publicly accessible HTTP/HTTPS URLs. Use file_upload tool first if the user provides a local file. Local file paths and data: URIs are NOT supported by the generation API.",parameters:C5,isEgress:!0,egressCarriesData:!1,execute:async(e,r)=>{let n=await t.generateImage({prompt:r.prompt,purpose:r.purpose,style:r.style,size:r.size,imageUrl:r.image_url,n:r.n,quality:r.quality,seed:r.seed}),o=n.mediaUrls.length;return{content:[{type:"text",text:`Generated ${o} image${o>1?"s":""}${n.model?` (model: ${n.model})`:""}`}],details:{type:"image_generate",model:n.model,size:n.size,durationMs:n.durationMs,mediaUrls:n.mediaUrls}}}}}var _5={type:"object",properties:{text:{type:"string",description:"Text to convert to speech."},channel:{type:"string",description:"Optional channel id to pick output format (e.g. telegram)."},voice:{type:"string",description:"Voice name for TTS. Available voices depend on the provider. Common options: alloy, ash, ballad, coral, echo, fable, nova, onyx, sage, shimmer."},speed:{type:"number",description:"Speech speed multiplier (0.25-4.0). Default is 1.0."}},required:["text"]};function K_(t){return{name:"tts",label:"TTS",description:"Convert text to speech (TTS) \u2014 read text aloud as spoken audio. Use for narration, voice messages, or any spoken-word output. DO NOT use for music, songs, or melodies \u2014 use music_generate instead.",parameters:_5,execute:async(e,r)=>{let n=await t.textToSpeech({text:r.text,channel:r.channel,voice:r.voice,speed:r.speed});return{content:[{type:"text",text:"\u5DF2\u6210\u529F\u751F\u6210\u8BED\u97F3\u3002"}],details:{type:"tts",audioPath:n.audioPath,provider:n.provider,voiceCompatible:n.voiceCompatible,mediaUrls:n.mediaUrls}}}}}var fb="video_generate",E5={type:"object",properties:{prompt:{type:"string",description:"Video generation prompt. MUST be in English. Include scene, movement, camera motion, lighting, style."},purpose:{type:"string",description:"Intended use: 'social-media', 'short-video', 'presentation', etc."},style:{type:"string",description:"Visual style: 'cinematic', 'anime', 'watercolor', etc."},image_url:{type:"string",description:"Reference image URL for image-to-video generation (first frame, style reference, or character reference). MUST be a publicly accessible HTTP/HTTPS URL. Local file paths and data: URLs are NOT supported. If the user provides a local file, use a file hosting service or the image_generate tool first."},reference_videos:{type:"array",items:{type:"string"},maxItems:3,description:"Reference video URLs for video-to-video or multimodal generation (Seedance 2.0). Max 3 videos, total duration \u226415s. Use for: (a) video-to-video: provide source video to restyle/transform with prompt guidance; (b) multimodal reference: combine with image_url and/or reference_audios for style/motion/audio-guided generation. Each URL MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},reference_audios:{type:"array",items:{type:"string"},maxItems:3,description:"Reference audio URLs for audio-guided video generation (Seedance 2.0). Max 3 audio clips, total duration \u226415s. CANNOT be used alone \u2014 must be combined with at least one image_url or reference_video. Each URL MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},generate_audio:{type:"boolean",description:"Generate synchronized audio track for the video (Seedance 2.0/1.5 pro). When true, the output video includes AI-generated sound effects matching the visual content."},aspect_ratio:{type:"string",description:"Video aspect ratio: '9:16' (vertical), '16:9' (horizontal), '1:1' (square). Default: '16:9'."},duration:{type:"number",minimum:3,maximum:15,description:"Video duration in seconds. Seedance 2.0: 4-15s per shot. Seedance 1.0/1.5: 3-10s. For longer videos (>15s), use multi-shot storyboard workflow (generate + extend/merge). Must be confirmed by user before generation."},resolution:{type:"string",description:"Output resolution: '480p', '720p', '1080p'. Default: '720p'."},fps:{type:"number",description:"Frame rate: 24 or 30 fps. Default: provider-specific."},seed:{type:"number",description:"Random seed for reproducible generation."},camera_fixed:{type:"boolean",description:"Lock camera position (Seedance 1.0/1.5 only, not supported for img2video)."},return_last_frame:{type:"boolean",description:"Return last frame URL for chaining continuous video segments."},draft:{type:"boolean",description:"Draft mode: low-cost preview (Seedance 1.5 pro only)."},service_tier:{type:"string",enum:["default","flex"],description:"'default' (online, fast) or 'flex' (offline, ~50% cost). Not all models support flex."},callback_url:{type:"string",description:"Webhook URL for async task completion notification."},safety_identifier:{type:"string",description:"End-user safety identifier for content moderation tracking."},execution_expires_after:{type:"number",description:"Task expiration in seconds (for offline/flex scheduling)."},video_tools:{type:"array",items:{type:"string"},description:"Video-level builtin tools, e.g. ['web_search'] (Seedance 2.0 online search)."}},required:["prompt"]};function V_(t){return{name:fb,label:"Video Generate",description:"Generate a short video clip from a text prompt, reference image, source video, or multimodal references. Prompt MUST be in English. Include scene, movement, camera motion, lighting details. Single-shot: 3\u201310s. For longer videos (>10s), use multi-shot storyboard workflow. MODES: (1) text-to-video: prompt only. (2) image-to-video: prompt + image_url. (3) video-to-video: prompt + reference_videos \u2014 restyle/transform an existing video with prompt guidance. (4) multimodal reference: prompt + any combination of image_url / reference_videos / reference_audios for style/motion/audio-guided generation. (5) generate_audio=true for synchronized sound effects. ALL image/video/audio URLs MUST be publicly accessible HTTP/HTTPS URLs. Local file paths and data: URIs are NOT supported by the generation API. If the user provides a local file, use the file_upload tool FIRST to get a public URL. IMPORTANT: If the user has not specified aspect ratio or duration, use ask_user to clarify (e.g. aspect: 16:9 for landscape / 9:16 for vertical / 1:1 for square; duration: 3-10s). Auto-set aspect_ratio based on stated purpose (e.g. 9:16 for short-video / Douyin, 16:9 for presentation).",parameters:E5,execute:async(e,r)=>{let n=await t.generateVideo({prompt:r.prompt,purpose:r.purpose,style:r.style,imageUrl:r.image_url,referenceVideos:r.reference_videos,referenceAudios:r.reference_audios,generateAudio:r.generate_audio,aspectRatio:r.aspect_ratio,duration:r.duration,resolution:r.resolution,fps:r.fps,seed:r.seed,cameraFixed:r.camera_fixed,returnLastFrame:r.return_last_frame,draft:r.draft,serviceTier:r.service_tier,callbackUrl:r.callback_url,safetyIdentifier:r.safety_identifier,executionExpiresAfterSeconds:r.execution_expires_after,videoTools:r.video_tools}),o=n.mediaUrls.length,i=[`Generated ${o} video${o>1?"s":""}`];return n.model&&i.push(`model: ${n.model}`),n.lastFrameUrl&&i.push(`last_frame: ${n.lastFrameUrl}`),n.taskId&&i.push(`task_id: ${n.taskId}`),{content:[{type:"text",text:i.length>1?`${i[0]} (${i.slice(1).join(", ")})`:i[0]}],details:{type:"video_generate",model:n.model,durationMs:n.durationMs,mediaUrls:n.mediaUrls,...n.taskId?{taskId:n.taskId}:{}}}}}}var hb="music_generate",M5={type:"object",properties:{prompt:{type:"string",description:"Music generation prompt. MUST be in English. Include genre, mood, tempo, instruments, and atmosphere details."},purpose:{type:"string",description:"Intended use: 'background-music', 'ringtone', 'short-video-bgm', 'full-song', 'notification-sound', etc."},style:{type:"string",description:"Musical style/genre: 'lo-fi', 'pop', 'rock', 'jazz', 'classical', 'electronic', 'ambient', etc."},lyrics:{type:"string",description:"Optional lyrics for vocal music. Structure with [verse], [chorus], [bridge] tags if desired."},duration:{type:"number",description:"Duration in seconds (5-300). Infer from purpose: ringtone 15-30s, BGM 30-60s, full song 120-180s."},is_instrumental:{type:"boolean",description:"Set true for pure instrumental music without vocals. Defaults to true when no lyrics are provided."},cover_audio_url:{type:"string",description:"URL of an existing audio track to use as base for cover/remix. When provided, generates a cover version. MUST be a publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},audio_format:{type:"string",enum:["mp3","wav","flac"],description:"Output audio format. Defaults to mp3."}},required:["prompt"]};function Z_(t){return{name:hb,label:"Music Generate",description:"Generate music, songs, or melodies from text descriptions. Prompt MUST be in English. Supports lyrics for vocal songs. DO NOT use for spoken-word audio or TTS \u2014 use tts tool instead. IMPORTANT: If the user has not specified genre/style or duration, use ask_user to clarify (e.g. style: lo-fi / pop / rock / jazz; duration inferred from purpose: 30s for ringtone, 60-90s for BGM, 180-240s for full song). Auto-infer duration from purpose when possible.",parameters:M5,isEgress:!0,egressCarriesData:!1,execute:async(e,r)=>{let n=r.lyrics;if(!n&&!r.is_instrumental&&t.generateLyrics)try{n=await t.generateLyrics(r.prompt)}catch{}let o=await t.generateMusic({prompt:r.prompt,purpose:r.purpose,style:r.style,lyrics:n,duration:r.duration,isInstrumental:r.is_instrumental,audioUrl:r.cover_audio_url,audioFormat:r.audio_format}),i=o.mediaUrls.length;return{content:[{type:"text",text:`Generated ${i} audio track${i>1?"s":""}${o.model?` (model: ${o.model})`:""}`}],details:{type:"music_generate",model:o.model,durationMs:o.durationMs,mediaUrls:o.mediaUrls}}}}}var D5="video_edit",N5={type:"object",properties:{prompt:{type:"string",description:"Edit instruction. Reference videos as \u89C6\u98911, \u89C6\u98912, \u89C6\u98913. Reference images as \u56FE\u72471, \u56FE\u72472. Operations: add/remove/modify elements, extend, track fill."},source_videos:{type:"array",items:{type:"string"},minItems:1,maxItems:3,description:"Video(s) to edit (1-3 URLs). Order: [0]=\u89C6\u98911, [1]=\u89C6\u98912, [2]=\u89C6\u98913. All URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},reference_images:{type:"array",items:{type:"string"},maxItems:9,description:"Optional reference images for element replacement (up to 9). All URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},duration:{type:"number",minimum:4,maximum:15,description:"Output duration in seconds (4-15s). Default: same as source."},aspect_ratio:{type:"string",description:"Output aspect ratio: 16:9, 9:16, 1:1, 4:3, 3:4, 21:9. Default: same as source."},resolution:{type:"string",description:"Output resolution: '480p' or '720p'. Default: '720p'."}},required:["prompt","source_videos"]};function J_(t){return{name:D5,label:"Video Edit",description:"Edit existing videos: add/remove/modify elements, extend, or bridge clips. Requires source_videos (max 3). Max 9 reference images for element replacement. Max 720p. All video/image URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file. For generating NEW videos from scratch, use video_generate instead.",parameters:N5,execute:async(e,r)=>{if(!r.source_videos?.length)return{content:[{type:"text",text:"Error: source_videos is required."}]};let n=await t.editVideo({prompt:r.prompt,sourceVideos:r.source_videos,referenceImages:r.reference_images,duration:r.duration,aspectRatio:r.aspect_ratio,resolution:r.resolution});return{content:[{type:"text",text:`Video edited successfully${n.model?` (model: ${n.model})`:""}`}],details:{type:"video_edit",model:n.model,durationMs:n.durationMs,mediaUrls:n.mediaUrls}}}}}var $5="video_merge",O5={type:"object",properties:{clips:{type:"array",items:{type:"object",properties:{video:{type:"string",description:"Video URL or file path. MUST be publicly accessible HTTP/HTTPS URL. Use file_upload tool first if local file."},audio:{type:"string",description:"Narration audio file path (from TTS)."},trimStart:{type:"number",description:"Trim start in seconds (default 0)."},trimEnd:{type:"number",description:"Trim end in seconds (default: full)."}},required:["video"]},minItems:2,description:"Array of video clips to merge, in order."},transition:{type:"string",description:"Transition effect: 'crossfade' (default), 'fade', 'wipeleft', 'cut', 'dissolve', etc."},transitionDuration:{type:"number",description:"Transition duration in seconds (0.1-2.0, default 0.5)."},subtitles:{type:"string",description:"Path to SRT subtitle file to burn-in."},bgm:{type:"string",description:"Background music file path."},bgmVolume:{type:"number",description:"BGM volume (0.0-1.0, default 0.15)."},outputResolution:{type:"string",description:"Output resolution: '1920x1080', '1080x1920', etc. Default: auto."},outputFps:{type:"number",description:"Output FPS (default 30)."}},required:["clips"]};function X_(t){return{name:$5,label:"Video Merge",description:"Merge multiple video clips into a single video with transitions, subtitles, and background music. Requires at least 2 clips. Supports crossfade, fade, wipe, dissolve, and cut transitions. All video/audio URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides local files. Audio per clip is preserved; BGM is mixed at adjustable volume.",parameters:O5,execute:async(e,r)=>{if(!r.clips||r.clips.length<2)return{content:[{type:"text",text:"Error: at least 2 clips are required for merging."}]};let n=await t.mergeVideos({clips:r.clips,transition:r.transition,transitionDuration:r.transitionDuration,subtitles:r.subtitles,bgm:r.bgm,bgmVolume:r.bgmVolume,outputResolution:r.outputResolution,outputFps:r.outputFps});return{content:[{type:"text",text:`Merged ${n.clipCount} clips \u2192 ${n.durationSec.toFixed(1)}s video`+(r.transition?` (transition: ${r.transition})`:"")}],details:{type:"video_merge",localPath:n.localPath,servePath:n.servePath,durationSec:n.durationSec,clipCount:n.clipCount,mediaUrls:n.mediaUrls}}}}}var j5="video_upscale",L5={type:"object",properties:{video:{type:"string",description:"Video URL to upscale. MUST be publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},targetResolution:{type:"string",description:"Target resolution: '1080p' (default, 1920x1080/1080x1920), '2k' (2560x1440/1440x2560)."},sharpness:{type:"string",description:"Sharpening intensity: 'light' (default), 'medium', 'strong'."}},required:["video"]};function Y_(t){return{name:j5,label:"Video Upscale",description:"Upscale a video to higher resolution with optional sharpening. Auto-detects orientation (landscape/portrait). Uses Lanczos interpolation + unsharp mask. Supports 1080p and 2K targets. Video URL MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file. Best used as post-processing after video_merge.",parameters:L5,execute:async(e,r)=>{let n=await t.upscaleVideo({video:r.video,targetResolution:r.targetResolution,sharpness:r.sharpness});return{content:[{type:"text",text:`Upscaled to ${n.resolution}${r.sharpness?` (sharpness: ${r.sharpness})`:""}`}],details:{type:"video_upscale",localPath:n.localPath,servePath:n.servePath,resolution:n.resolution,durationSec:n.durationSec,mediaUrls:n.mediaUrls}}}}}var U5="three_d_generate",F5={type:"object",properties:{prompt:{type:"string",description:"3D model generation prompt. Describe the object's shape, material, texture, color, and pose. For text-to-3D, provide a detailed description. For image-to-3D, also provide image_url."},image_url:{type:"string",description:"Reference image URL for image-to-3D generation. The image should show the object clearly from a single viewpoint with clean background for best results. MUST be a publicly accessible HTTP/HTTPS URL. Local file paths and data: URLs are NOT supported."},output_format:{type:"string",description:"3D model output format: 'glb' (default), 'obj', 'usd', 'usdz'."},seed:{type:"number",description:"Random seed for reproducible generation."}},required:["prompt"]};function Q_(t){return{name:U5,label:"3D Generate",description:"Generate a 3D model from a text prompt or reference image. Supports text-to-3D and image-to-3D workflows. Output formats include GLB, OBJ, USD. The generated model can be viewed in any 3D viewer or imported into game engines. IMPORTANT: Describe the object in detail \u2014 shape, size, material, texture, color, and pose.",parameters:F5,execute:async(e,r)=>{let n=await t.generate3D({prompt:r.prompt,imageUrl:r.image_url,outputFormat:r.output_format,seed:r.seed}),o=n.mediaUrls.length,i=`Generated ${o} 3D model${o>1?"s":""}${n.model?` (model: ${n.model})`:""}`;return o===0&&n.metadata?.debugResponseKeys&&(i+=` [debug: response keys=${JSON.stringify(n.metadata.debugResponseKeys)}, content=${n.metadata.debugContentSample??"null"}]`),{content:[{type:"text",text:i}],details:{type:"three_d_generate",model:n.model,durationMs:n.durationMs,mediaUrls:n.mediaUrls,...n.metadata??{}}}}}}var z5={type:"object",properties:{audio_url:{type:"string",description:"URL of the audio file to transcribe. Supports mp3, wav, m4a, ogg, flac formats. MUST be a publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},language:{type:"string",description:"Language hint for transcription: 'zh' (Chinese), 'en' (English), or auto-detect if omitted."}},required:["audio_url"]};function eE(t){return{name:"stt",label:"STT",description:"Transcribe audio to text (Speech-to-Text). Provide an audio file URL and receive the spoken content as text. Supports Chinese and English. Use for meeting transcription, voice message reading, subtitle generation, or any audio-to-text conversion.",parameters:z5,execute:async(e,r)=>{if(!r.audio_url)return{content:[{type:"text",text:"Error: audio_url parameter is required. Provide a publicly accessible HTTP/HTTPS URL to an audio file."}],details:{error:"audio_url parameter is required"}};let n=await t.speechToText({audioUrl:r.audio_url,language:r.language}),o=n.transcription.length>200?n.transcription.slice(0,200)+"\u2026":n.transcription;return{content:[{type:"text",text:n.transcription}],details:{type:"stt",model:n.model,durationMs:n.durationMs,transcriptionLength:n.transcription.length,preview:o}}}}}var H5="voice_clone",B5={type:"object",properties:{text:{type:"string",description:"Text to synthesize in the cloned voice."},sample_audio_url:{type:"string",description:"URL of an audio sample (5-30 seconds recommended) of the voice to clone. The sample should be clear speech with minimal background noise. MUST be a publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},speed:{type:"number",description:"Speech speed multiplier (0.5-2.0). Default is 1.0."}},required:["text","sample_audio_url"]};function tE(t){return{name:H5,label:"Voice Clone",description:"Clone a voice from an audio sample and synthesize new speech in that voice. Requires a clear audio sample (5-30s recommended) of the target voice. Use for personalized narration, character voices, or voice preservation. DO NOT use for impersonation or deception. For standard TTS with preset voices, use the tts tool instead.",parameters:B5,execute:async(e,r)=>{let n=await t.cloneVoice({text:r.text,sampleAudioUrl:r.sample_audio_url,speed:r.speed});return{content:[{type:"text",text:`Voice cloned and synthesized speech${n.model?` (model: ${n.model})`:""}`}],details:{type:"voice_clone",model:n.model,voiceId:n.voiceId,durationMs:n.durationMs,mediaUrls:n.mediaUrls}}}}}var q5="media_cancel",W5={type:"object",properties:{task_id:{type:"string",description:"The task ID of the media generation to cancel (returned in previous generation results)."},provider:{type:"string",description:"Provider name (e.g. 'doubao', 'zhipu'). If omitted, auto-detects from task context."}},required:["task_id"]};function rE(t){return{name:q5,label:"Media Cancel",description:"Cancel an in-progress media generation task (video, 3D, etc.). Provide the task_id from a previous generation result. Use this when a user wants to abort a long-running generation.",parameters:W5,execute:async(e,r)=>{if(!r.task_id)return{content:[{type:"text",text:"Error: task_id is required."}],details:{error:"task_id is required"}};let n=await t.cancelTask({taskId:r.task_id,provider:r.provider});return{content:[{type:"text",text:n.ok?`Task ${r.task_id} cancelled.`:`Cancel failed: ${n.message}`}],details:n.ok?void 0:{error:n.message}}}}}import ZJ from"node:fs";import JJ from"node:path";import le from"node:fs/promises";import fE from"node:os";import Y from"node:path";import{createCanvas as uu,loadImage as Rb}from"@napi-rs/canvas";import{randomUUID as G5}from"node:crypto";import dn from"node:fs";import pn from"node:path";import{fileURLToPath as K5}from"node:url";import{createCanvas as V5,loadImage as Z5}from"@napi-rs/canvas";async function yb(t){let e=await tJ(dn.readFileSync(t));for(let s of e.keys())if(wl(s))throw new Error(`unsafe path in Petdex package: ${s}`);if(e.has("manifest.json")||[...e.keys()].some(s=>s.toLowerCase().endsWith(".svg")))throw new Error("SVG .pet state packages are not supported by Petdex v1");let r=e.get("pet.json");if(!r)throw new Error("Petdex package missing pet.json");let n=e.get("spritesheet.webp");if(!n)throw new Error("Petdex package missing spritesheet.webp");let o=JSON.parse(r.toString("utf-8")),i=Vn(o,n);return{manifest:o,spritesheet:n,validation:i}}async function vb(t){let e=Vn(t.asset,t.spritesheet);dn.mkdirSync(t.outputDir,{recursive:!0});let r=eJ(t.fileName??`${t.asset.id}.petdex`),n=pn.join(t.outputDir,r.endsWith(".petdex")?r:`${r}.petdex`),o=[{name:"pet.json",data:Buffer.from(JSON.stringify(t.asset,null,2),"utf-8")},{name:"spritesheet.webp",data:t.spritesheet},{name:"validation.json",data:Buffer.from(JSON.stringify(e,null,2),"utf-8")},...t.productionRun?[{name:"production-run.json",data:Buffer.from(JSON.stringify(t.productionRun,null,2),"utf-8")}]:[]];return dn.writeFileSync(n,rJ(o)),n}async function bb(t){let e=t.now??new Date().toISOString(),r=t.id??`petdex-${G5()}`,n=await Q5(t.spritesheet),o=kv(n),i={schema:Fs,id:r,assetKind:"petdex",name:t.name,description:t.description,createdAt:e,updatedAt:e,source:{kind:t.sourceKind??"forge",prompt:t.prompt??null},sourcePrompt:t.prompt??void 0,atlas:{image:"spritesheet.webp",...X,sha256:o},animations:bv(),thumbnail:{frame:0}},s=Vn(i,n);return{asset:i,spritesheet:n,validation:s}}var J5=["builtin-anime-horse-girl"],iu=null;async function su(){return iu||(iu=Promise.all(J5.map(t=>X5(t))).catch(t=>{throw iu=null,t})),iu}async function X5(t){let e=Y5(),r=pn.join(e,`${t}.petdex`);if(dn.existsSync(r)){let u=await yb(r);return nE(t,u.manifest),{asset:u.manifest,spritesheet:u.spritesheet,validation:u.validation}}let n=pn.join(e,t),o=pn.join(n,"pet.json"),i=pn.join(n,"spritesheet.webp");if(!dn.existsSync(o)||!dn.existsSync(i))throw new Error(`Missing published builtin Petdex asset ${t} under ${e}`);let s=JSON.parse(dn.readFileSync(o,"utf-8")),a=dn.readFileSync(i),c=Vn(s,a);return nE(t,s),{asset:s,spritesheet:a,validation:c}}function Y5(){let t=process.env.QLOGICAGENT_BUILTIN_PETDEX_DIR?.trim();return t?pn.resolve(t):pn.resolve(pn.dirname(K5(import.meta.url)),"builtin-petdex")}function nE(t,e){if(e.id!==t)throw new Error(`Builtin Petdex asset id mismatch: expected ${t}, got ${e.id}`);if(e.source.kind!=="builtin")throw new Error(`Builtin Petdex asset ${t} must declare source.kind=builtin`)}async function Q5(t){let e=await Z5(t),r=V5(X.width,X.height),n=r.getContext("2d");return n.clearRect(0,0,X.width,X.height),n.imageSmoothingEnabled=!0,n.imageSmoothingQuality="high",n.drawImage(e,0,0,X.width,X.height),Buffer.from(await r.encode("webp"))}function eJ(t){return t.replace(/[^a-zA-Z0-9._-]/g,"_").replace(/^_+/,"")||"petdex-asset.petdex"}async function tJ(t){let e=new Map,r=0;for(;r<t.length-4&&t.readUInt32LE(r)===67324752;){let o=t.readUInt16LE(r+8),i=t.readUInt32LE(r+18),s=t.readUInt32LE(r+22),a=t.readUInt16LE(r+26),c=t.readUInt16LE(r+28),u=r+30,d=t.subarray(u,u+a).toString("utf-8"),p=u+a+c,m=t.subarray(p,p+i);if(o===0)e.set(d,t.subarray(p,p+s));else if(o===8){let{inflateRawSync:g}=await import("node:zlib");e.set(d,g(m))}r=p+i}return e}function rJ(t){let e=[],r=[],n=0,{time:o,date:i}=nJ();for(let u of t){if(wl(u.name))throw new Error(`unsafe path in Petdex package entry: ${u.name}`);let d=Buffer.from(u.name,"utf-8"),p=iJ(u.data),m=Buffer.alloc(30);m.writeUInt32LE(67324752,0),m.writeUInt16LE(20,4),m.writeUInt16LE(2048,6),m.writeUInt16LE(0,8),m.writeUInt16LE(o,10),m.writeUInt16LE(i,12),m.writeUInt32LE(p,14),m.writeUInt32LE(u.data.length,18),m.writeUInt32LE(u.data.length,22),m.writeUInt16LE(d.length,26),m.writeUInt16LE(0,28),e.push(m,d,u.data);let g=Buffer.alloc(46);g.writeUInt32LE(33639248,0),g.writeUInt16LE(20,4),g.writeUInt16LE(20,6),g.writeUInt16LE(2048,8),g.writeUInt16LE(0,10),g.writeUInt16LE(o,12),g.writeUInt16LE(i,14),g.writeUInt32LE(p,16),g.writeUInt32LE(u.data.length,20),g.writeUInt32LE(u.data.length,24),g.writeUInt16LE(d.length,28),g.writeUInt16LE(0,30),g.writeUInt16LE(0,32),g.writeUInt16LE(0,34),g.writeUInt16LE(0,36),g.writeUInt32LE(0,38),g.writeUInt32LE(n,42),r.push(g,d),n+=m.length+d.length+u.data.length}let s=n,a=Buffer.concat(r),c=Buffer.alloc(22);return c.writeUInt32LE(101010256,0),c.writeUInt16LE(0,4),c.writeUInt16LE(0,6),c.writeUInt16LE(t.length,8),c.writeUInt16LE(t.length,10),c.writeUInt32LE(a.length,12),c.writeUInt32LE(s,16),c.writeUInt16LE(0,20),Buffer.concat([...e,a,c])}function nJ(){let t=new Date,e=t.getHours()<<11|t.getMinutes()<<5|Math.floor(t.getSeconds()/2),r=t.getFullYear()-1980<<9|t.getMonth()+1<<5|t.getDate();return{time:e,date:r}}var oJ=new Uint32Array(256).map((t,e)=>{let r=e;for(let n=0;n<8;n++)r=r&1?3988292384^r>>>1:r>>>1;return r>>>0});function iJ(t){let e=4294967295;for(let r of t)e=oJ[(e^r)&255]^e>>>8;return(e^4294967295)>>>0}import{spawn as sJ}from"node:child_process";import{existsSync as oE}from"node:fs";import{dirname as iE,join as lu}from"node:path";import{fileURLToPath as aJ}from"node:url";var cJ=iE(aJ(import.meta.url)),au,cu;function sE(t,e,r){return new Promise(n=>{let o="",i="",s=!1,a=d=>{s||(s=!0,clearTimeout(u),n(d))},c=sJ(t,e,{windowsHide:!0}),u=setTimeout(()=>{c.kill("SIGKILL"),a({ok:!1,stdout:o,stderr:`${i}
806
806
  [hatch-pet] timed out after ${r}ms`,code:null})},r);u.unref?.(),c.stdout?.on("data",d=>{o+=d.toString()}),c.stderr?.on("data",d=>{i+=d.toString()}),c.on("error",d=>a({ok:!1,stdout:o,stderr:`${i}${d instanceof Error?d.message:String(d)}`,code:null})),c.on("close",d=>a({ok:d===0,stdout:o,stderr:i,code:d}))})}function lJ(){let t=[],e=process.env.QLOGICAGENT_PYTHON?.trim();return e&&t.push(e),t.push("python3","python","py"),t}async function uJ(t){let e=await sE(t,["-c","import PIL; import sys; sys.stdout.write('hatchpet-ok')"],1e4);return e.code===0&&e.stdout.includes("hatchpet-ok")}async function aE(){if(au!==void 0)return au;for(let t of lJ())if(await uJ(t))return au=t,t;return au=null,null}function cE(){if(cu!==void 0)return cu;let t=[],e=process.env.QLOGICAGENT_HATCHPET_DIR?.trim();e&&t.push(lu(e,"scripts"),e);let r=cJ;for(let n=0;n<7;n++){t.push(lu(r,"vendor","hatch-pet","scripts"));let o=iE(r);if(o===r)break;r=o}for(let n of t)if(oE(lu(n,"compose_atlas.py")))return cu=n,n;return cu=null,null}async function lE(){return await aE()!==null&&cE()!==null}async function kb(t,e,r={}){let n=await aE();if(!n)throw new Error("Petdex generation requires Python with Pillow; none found (set QLOGICAGENT_PYTHON to a python that can `import PIL`)");let o=cE();if(!o)throw new Error("Vendored hatch-pet scripts not found (set QLOGICAGENT_HATCHPET_DIR)");let i=lu(o,t);if(!oE(i))throw new Error(`Unknown hatch-pet script: ${t}`);return sE(n,[i,...e],r.timeoutMs??12e4)}var uE="references/canonical-base.png",dJ="single centered full-body desktop pet character on a flat chroma-key background, readable at pet size",pJ="one horizontal animation row strip with evenly spaced full-body frames sharing a single consistent character identity",mJ="4096x1024",Sb="#FF00FF",hE="110",yE="stable-slots",gJ="90",vE=["STRICT BACKGROUND: render one single continuous flat background of the same solid color filling the entire image edge to edge.","Do NOT draw any picture frame, framed panel, border, mat, outline, box, gallery frame, white or light margin, or divider around or between the poses.","The poses sit directly on the one seamless flat background, evenly spaced, with nothing separating them.","IDENTITY LOCK: every frame is the EXACT same character \u2014 identical species, body shape, proportions, colors, palette, face, and markings. Do not redesign, restyle, recolor, or resize the character between frames; only its pose changes.","Each pose is ONE connected solid silhouette at a consistent size. No detached parts, sweat drops, tears, dust, puffs, sparkles, speed lines, motion blur, floating effects, or drop shadows."].join(" "),fJ="Leftward gait is the framewise horizontal mirror of the approved rightward row, preserving frame order and timing semantics.",hJ=2,yJ=2;async function du(t,e,r={}){if(!await lE())throw new Error("Petdex forge requires the vendored Hatch-Pet pipeline (Python with Pillow). Install Python + Pillow or set QLOGICAGENT_PYTHON to a python that can `import PIL`.");let n={billingQuantity:0,durationMs:0},o=[],i=[],s=GA(t),a=await WJ(),c=await qJ(t);try{await ni("prepare_pet_run.py",["--pet-name",t.name,"--display-name",t.name,"--description",t.description,"--pet-notes",t.prompt?.trim()||t.description,"--pet-id",VJ(t.id??t.name),"--output-dir",a,"--chroma-key","auto",...c.flatMap(I=>["--reference",I])]);let u=Y.join(a,"imagegen-jobs.json"),d=await xE(u),p=r.inspectImage,m=Math.max(1,r.candidates??hJ),g=[],f=Sb,h;for(let I of d.jobs){if(!!(I.derivation_policy?.may_derive&&I.derivation_policy.may_derive_from)&&!p){await bE(a),o.push({id:`row-${I.id}`,kind:"row-strip",status:"complete",animationId:I.id,prompt:`derived: framewise-horizontal-mirror of ${I.derivation_policy.may_derive_from}`,inputImages:[],outputUrl:I.output_path});continue}let G=await le.readFile(Y.join(a,I.prompt_file),"utf-8"),x=I.retry_prompt_file?await le.readFile(Y.join(a,I.retry_prompt_file),"utf-8").catch(()=>{}):void 0;i.push(G);let z=I.kind==="base-pet",{mediaUrl:be,inputImages:H}=await kE({runDir:a,job:I,prompt:G,retryPrompt:x,generateImage:e,inspectImage:p,candidates:m,usage:n,upload:r.uploadReferenceImage,baseDataUrl:h});z&&(await le.copyFile(Y.join(a,I.output_path),Y.join(a,uE)),f=await KJ(Y.join(a,I.output_path)),h=await wJ(Y.join(a,uE))),I.status="complete",await le.writeFile(u,JSON.stringify(d,null,2),"utf-8"),o.push({id:z?"base-reference":`row-${I.id}`,kind:z?"reference":"row-strip",status:"complete",...z?{}:{animationId:I.id},prompt:G,inputImages:H,outputUrl:be}),z||g.push(I)}let y=Y.join(a,"decoded"),b=Y.join(a,"frames"),v=Y.join(a,"atlas.png"),w=Y.join(a,"atlas.webp");await ni("extract_strip_frames.py",["--decoded-dir",y,"--output-dir",b,"--chroma-key",f,"--key-threshold",hE,"--method",yE]),await xJ({runDir:a,decodedDir:y,framesDir:b,generatedRows:g,chromaHex:f,generateImage:e,inspectImage:p,candidates:m,baseDataUrl:h,usage:n,upload:r.uploadReferenceImage,productionJobs:o});let S=Y.join(a,"qa","contact-sheet.png");await SE(a,b,v,w,S),h&&await NJ({runDir:a,framesDir:b,atlasPng:v,atlasWebp:w,contactSheet:S,generatedRows:g,generateImage:e,inspectImage:p,candidates:m,usage:n,upload:r.uploadReferenceImage,baseDataUrl:h}),await Tb("render_animation_previews.py",["--frames-root",b,"--output-dir",Y.join(a,"qa","previews")]);let P=await le.readFile(w);return{...await bb({id:t.id,name:t.name,description:t.description,prompt:t.prompt,spritesheet:P,sourceKind:"forge"}),prompt:i.join(`
807
807
 
808
808
  ---
package/dist/index.js CHANGED
@@ -801,7 +801,7 @@ ${p}${m}`}],details:{type:"notebook_edit",edit_mode:o,cell_number:n,total_cells:
801
801
  `),parameters:g5,execute:async(e,r,n)=>{let o=Math.max(1,Math.min(3600,Math.round(r.duration))),i=o*1e3,s=new AbortController,a=()=>s.abort();n?.addEventListener("abort",a,{once:!0}),n?.aborted&&s.abort();try{let c=await t.sleep(i,s.signal),u=[];return c.interrupted?(u.push(`Sleep interrupted after ${c.sleptSeconds}s.`),c.interruptReason&&u.push(`Reason: ${c.interruptReason}`),u.push("Check for new messages or tasks.")):u.push(`Slept for ${c.sleptSeconds}s. Waking up.`),{content:[{type:"text",text:u.join(`
802
802
  `)}],details:{...c,requestedSeconds:o}}}finally{n?.removeEventListener("abort",a)}}}}var f5="tool_search",h5={type:"object",properties:{query:{type:"string",description:'Search query for tools. Use "select:toolName" to directly activate a deferred tool, or provide keywords to search tool names/descriptions. Prefix a term with "+" to mark it as required (all +terms must match).'},maxResults:{type:"number",description:"Maximum number of results to return (default: 5)."}},required:["query"]},y5=5;function z_(t){return{name:f5,label:"Tool Search",description:'Search for available tools that are not currently loaded. Many tools are deferred to save context tokens. Use "select:toolName" to directly activate a tool, or provide keywords to find relevant tools. Activated tools become available in subsequent messages.',parameters:h5,execute:async(e,r)=>{if(!r.query||r.query.trim().length===0)return{content:[{type:"text",text:"Error: query is required."}],details:{type:"tool_search",error:"empty_query"}};let n=r.query.trim(),o=r.maxResults??y5;if(n.startsWith("select:")){let s=n.slice(7).split(",").map(d=>d.trim()).filter(Boolean),a=[],c=[];if(t.activateTool)for(let d of s)await t.activateTool(d)?a.push(d):c.push(d);else{let d=await t.searchTools(n,{maxResults:o});return F_(d)}let u=[];return a.length>0&&u.push(`Activated: ${a.join(", ")}. These tools are now available.`),c.length>0&&u.push(`Not found: ${c.join(", ")}.`),{content:[{type:"text",text:u.join(`
803
803
  `)}],details:{type:"tool_search",activated:a,notFound:c,mode:"select"}}}let i=await t.searchTools(n,{maxResults:o});return F_(i)}}}function F_(t){if(t.matches.length===0)return{content:[{type:"text",text:`No tools found matching "${t.query}". Total deferred tools available: ${t.totalDeferred}.`}],details:{type:"tool_search",query:t.query,matchCount:0,totalDeferred:t.totalDeferred}};let e=[`Found ${t.matches.length} tool(s) matching "${t.query}" (${t.totalDeferred} total deferred):`,""];for(let r of t.matches)e.push(`- **${r.name}**: ${r.description}`);return e.push(""),e.push('Use "select:toolName" to activate a tool for use in subsequent messages.'),{content:[{type:"text",text:e.join(`
804
- `)}],details:{type:"tool_search",query:t.query,matchCount:t.matches.length,totalDeferred:t.totalDeferred,matches:t.matches.map(r=>r.name)}}}var pb="image_generate",v5={type:"object",properties:{prompt:{type:"string",description:"Image generation prompt. Enrich vague requests with style, lighting, composition, color, mood details."},purpose:{type:"string",description:"Intended use: 'social-media', 'short-video-cover', 'phone-wallpaper', 'avatar', 'poster', etc."},style:{type:"string",description:"Visual art style: 'photorealistic', 'anime', 'watercolor', 'oil-painting', '3d-render', etc."},size:{type:"string",description:"Dimensions: e.g. '1024x1792' (portrait), '1792x1024' (landscape), '1024x1024' (square). Default: '1024x1024'."},image_url:{type:"string",description:"Reference image URL for image-to-image generation (img2img). Character reference sheet or style transfer. MUST be a publicly accessible HTTP/HTTPS URL. Local file paths and data: URLs are NOT supported."},n:{type:"number",description:"Number of images to generate (1-4). Default: 1."},quality:{type:"string",description:"Image quality level: 'auto', 'high', 'low', 'hd'. Provider-specific."},seed:{type:"number",description:"Random seed for reproducible generation. Same seed + prompt = same result."}},required:["prompt"]};function H_(t){return{name:pb,label:"Image Generate",description:"Generate images from a text prompt. You MUST enrich vague prompts with details about style, lighting, composition, color, and mood before calling. Supports img2img via image_url reference. All generated images are saved locally and can be viewed immediately. IMPORTANT: For ordinary creative requests, infer reasonable defaults for purpose, style, and size and call this tool directly. Use ask_user only when a missing detail is critical or the request is genuinely ambiguous (e.g. the user asks for a production ad with unspecified brand constraints). Infer image size automatically from purpose (e.g. 1024x1792 for phone wallpaper, 1792x1024 for landscape poster, 1024x1024 for avatar/social). Do NOT expose size as a raw number to the user. Do NOT invent Markdown image URLs, placeholder attachment paths, or claim an image was generated without this tool returning mediaUrls. ALL reference image URLs MUST be publicly accessible HTTP/HTTPS URLs. Use file_upload tool first if the user provides a local file. Local file paths and data: URIs are NOT supported by the generation API.",parameters:v5,isEgress:!0,egressCarriesData:!0,execute:async(e,r)=>{let n=await t.generateImage({prompt:r.prompt,purpose:r.purpose,style:r.style,size:r.size,imageUrl:r.image_url,n:r.n,quality:r.quality,seed:r.seed}),o=n.mediaUrls.length;return{content:[{type:"text",text:`Generated ${o} image${o>1?"s":""}${n.model?` (model: ${n.model})`:""}`}],details:{type:"image_generate",model:n.model,size:n.size,durationMs:n.durationMs,mediaUrls:n.mediaUrls}}}}}var b5={type:"object",properties:{text:{type:"string",description:"Text to convert to speech."},channel:{type:"string",description:"Optional channel id to pick output format (e.g. telegram)."},voice:{type:"string",description:"Voice name for TTS. Available voices depend on the provider. Common options: alloy, ash, ballad, coral, echo, fable, nova, onyx, sage, shimmer."},speed:{type:"number",description:"Speech speed multiplier (0.25-4.0). Default is 1.0."}},required:["text"]};function B_(t){return{name:"tts",label:"TTS",description:"Convert text to speech (TTS) \u2014 read text aloud as spoken audio. Use for narration, voice messages, or any spoken-word output. DO NOT use for music, songs, or melodies \u2014 use music_generate instead.",parameters:b5,execute:async(e,r)=>{let n=await t.textToSpeech({text:r.text,channel:r.channel,voice:r.voice,speed:r.speed});return{content:[{type:"text",text:"\u5DF2\u6210\u529F\u751F\u6210\u8BED\u97F3\u3002"}],details:{type:"tts",audioPath:n.audioPath,provider:n.provider,voiceCompatible:n.voiceCompatible,mediaUrls:n.mediaUrls}}}}}var mb="video_generate",k5={type:"object",properties:{prompt:{type:"string",description:"Video generation prompt. MUST be in English. Include scene, movement, camera motion, lighting, style."},purpose:{type:"string",description:"Intended use: 'social-media', 'short-video', 'presentation', etc."},style:{type:"string",description:"Visual style: 'cinematic', 'anime', 'watercolor', etc."},image_url:{type:"string",description:"Reference image URL for image-to-video generation (first frame, style reference, or character reference). MUST be a publicly accessible HTTP/HTTPS URL. Local file paths and data: URLs are NOT supported. If the user provides a local file, use a file hosting service or the image_generate tool first."},reference_videos:{type:"array",items:{type:"string"},maxItems:3,description:"Reference video URLs for video-to-video or multimodal generation (Seedance 2.0). Max 3 videos, total duration \u226415s. Use for: (a) video-to-video: provide source video to restyle/transform with prompt guidance; (b) multimodal reference: combine with image_url and/or reference_audios for style/motion/audio-guided generation. Each URL MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},reference_audios:{type:"array",items:{type:"string"},maxItems:3,description:"Reference audio URLs for audio-guided video generation (Seedance 2.0). Max 3 audio clips, total duration \u226415s. CANNOT be used alone \u2014 must be combined with at least one image_url or reference_video. Each URL MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},generate_audio:{type:"boolean",description:"Generate synchronized audio track for the video (Seedance 2.0/1.5 pro). When true, the output video includes AI-generated sound effects matching the visual content."},aspect_ratio:{type:"string",description:"Video aspect ratio: '9:16' (vertical), '16:9' (horizontal), '1:1' (square). Default: '16:9'."},duration:{type:"number",minimum:3,maximum:15,description:"Video duration in seconds. Seedance 2.0: 4-15s per shot. Seedance 1.0/1.5: 3-10s. For longer videos (>15s), use multi-shot storyboard workflow (generate + extend/merge). Must be confirmed by user before generation."},resolution:{type:"string",description:"Output resolution: '480p', '720p', '1080p'. Default: '720p'."},fps:{type:"number",description:"Frame rate: 24 or 30 fps. Default: provider-specific."},seed:{type:"number",description:"Random seed for reproducible generation."},camera_fixed:{type:"boolean",description:"Lock camera position (Seedance 1.0/1.5 only, not supported for img2video)."},return_last_frame:{type:"boolean",description:"Return last frame URL for chaining continuous video segments."},draft:{type:"boolean",description:"Draft mode: low-cost preview (Seedance 1.5 pro only)."},service_tier:{type:"string",enum:["default","flex"],description:"'default' (online, fast) or 'flex' (offline, ~50% cost). Not all models support flex."},callback_url:{type:"string",description:"Webhook URL for async task completion notification."},safety_identifier:{type:"string",description:"End-user safety identifier for content moderation tracking."},execution_expires_after:{type:"number",description:"Task expiration in seconds (for offline/flex scheduling)."},video_tools:{type:"array",items:{type:"string"},description:"Video-level builtin tools, e.g. ['web_search'] (Seedance 2.0 online search)."}},required:["prompt"]};function q_(t){return{name:mb,label:"Video Generate",description:"Generate a short video clip from a text prompt, reference image, source video, or multimodal references. Prompt MUST be in English. Include scene, movement, camera motion, lighting details. Single-shot: 3\u201310s. For longer videos (>10s), use multi-shot storyboard workflow. MODES: (1) text-to-video: prompt only. (2) image-to-video: prompt + image_url. (3) video-to-video: prompt + reference_videos \u2014 restyle/transform an existing video with prompt guidance. (4) multimodal reference: prompt + any combination of image_url / reference_videos / reference_audios for style/motion/audio-guided generation. (5) generate_audio=true for synchronized sound effects. ALL image/video/audio URLs MUST be publicly accessible HTTP/HTTPS URLs. Local file paths and data: URIs are NOT supported by the generation API. If the user provides a local file, use the file_upload tool FIRST to get a public URL. IMPORTANT: If the user has not specified aspect ratio or duration, use ask_user to clarify (e.g. aspect: 16:9 for landscape / 9:16 for vertical / 1:1 for square; duration: 3-10s). Auto-set aspect_ratio based on stated purpose (e.g. 9:16 for short-video / Douyin, 16:9 for presentation).",parameters:k5,execute:async(e,r)=>{let n=await t.generateVideo({prompt:r.prompt,purpose:r.purpose,style:r.style,imageUrl:r.image_url,referenceVideos:r.reference_videos,referenceAudios:r.reference_audios,generateAudio:r.generate_audio,aspectRatio:r.aspect_ratio,duration:r.duration,resolution:r.resolution,fps:r.fps,seed:r.seed,cameraFixed:r.camera_fixed,returnLastFrame:r.return_last_frame,draft:r.draft,serviceTier:r.service_tier,callbackUrl:r.callback_url,safetyIdentifier:r.safety_identifier,executionExpiresAfterSeconds:r.execution_expires_after,videoTools:r.video_tools}),o=n.mediaUrls.length,i=[`Generated ${o} video${o>1?"s":""}`];return n.model&&i.push(`model: ${n.model}`),n.lastFrameUrl&&i.push(`last_frame: ${n.lastFrameUrl}`),n.taskId&&i.push(`task_id: ${n.taskId}`),{content:[{type:"text",text:i.length>1?`${i[0]} (${i.slice(1).join(", ")})`:i[0]}],details:{type:"video_generate",model:n.model,durationMs:n.durationMs,mediaUrls:n.mediaUrls,...n.taskId?{taskId:n.taskId}:{}}}}}}var gb="music_generate",w5={type:"object",properties:{prompt:{type:"string",description:"Music generation prompt. MUST be in English. Include genre, mood, tempo, instruments, and atmosphere details."},purpose:{type:"string",description:"Intended use: 'background-music', 'ringtone', 'short-video-bgm', 'full-song', 'notification-sound', etc."},style:{type:"string",description:"Musical style/genre: 'lo-fi', 'pop', 'rock', 'jazz', 'classical', 'electronic', 'ambient', etc."},lyrics:{type:"string",description:"Optional lyrics for vocal music. Structure with [verse], [chorus], [bridge] tags if desired."},duration:{type:"number",description:"Duration in seconds (5-300). Infer from purpose: ringtone 15-30s, BGM 30-60s, full song 120-180s."},is_instrumental:{type:"boolean",description:"Set true for pure instrumental music without vocals. Defaults to true when no lyrics are provided."},cover_audio_url:{type:"string",description:"URL of an existing audio track to use as base for cover/remix. When provided, generates a cover version. MUST be a publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},audio_format:{type:"string",enum:["mp3","wav","flac"],description:"Output audio format. Defaults to mp3."}},required:["prompt"]};function W_(t){return{name:gb,label:"Music Generate",description:"Generate music, songs, or melodies from text descriptions. Prompt MUST be in English. Supports lyrics for vocal songs. DO NOT use for spoken-word audio or TTS \u2014 use tts tool instead. IMPORTANT: If the user has not specified genre/style or duration, use ask_user to clarify (e.g. style: lo-fi / pop / rock / jazz; duration inferred from purpose: 30s for ringtone, 60-90s for BGM, 180-240s for full song). Auto-infer duration from purpose when possible.",parameters:w5,isEgress:!0,egressCarriesData:!0,execute:async(e,r)=>{let n=r.lyrics;if(!n&&!r.is_instrumental&&t.generateLyrics)try{n=await t.generateLyrics(r.prompt)}catch{}let o=await t.generateMusic({prompt:r.prompt,purpose:r.purpose,style:r.style,lyrics:n,duration:r.duration,isInstrumental:r.is_instrumental,audioUrl:r.cover_audio_url,audioFormat:r.audio_format}),i=o.mediaUrls.length;return{content:[{type:"text",text:`Generated ${i} audio track${i>1?"s":""}${o.model?` (model: ${o.model})`:""}`}],details:{type:"music_generate",model:o.model,durationMs:o.durationMs,mediaUrls:o.mediaUrls}}}}}var S5="video_edit",x5={type:"object",properties:{prompt:{type:"string",description:"Edit instruction. Reference videos as \u89C6\u98911, \u89C6\u98912, \u89C6\u98913. Reference images as \u56FE\u72471, \u56FE\u72472. Operations: add/remove/modify elements, extend, track fill."},source_videos:{type:"array",items:{type:"string"},minItems:1,maxItems:3,description:"Video(s) to edit (1-3 URLs). Order: [0]=\u89C6\u98911, [1]=\u89C6\u98912, [2]=\u89C6\u98913. All URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},reference_images:{type:"array",items:{type:"string"},maxItems:9,description:"Optional reference images for element replacement (up to 9). All URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},duration:{type:"number",minimum:4,maximum:15,description:"Output duration in seconds (4-15s). Default: same as source."},aspect_ratio:{type:"string",description:"Output aspect ratio: 16:9, 9:16, 1:1, 4:3, 3:4, 21:9. Default: same as source."},resolution:{type:"string",description:"Output resolution: '480p' or '720p'. Default: '720p'."}},required:["prompt","source_videos"]};function G_(t){return{name:S5,label:"Video Edit",description:"Edit existing videos: add/remove/modify elements, extend, or bridge clips. Requires source_videos (max 3). Max 9 reference images for element replacement. Max 720p. All video/image URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file. For generating NEW videos from scratch, use video_generate instead.",parameters:x5,execute:async(e,r)=>{if(!r.source_videos?.length)return{content:[{type:"text",text:"Error: source_videos is required."}]};let n=await t.editVideo({prompt:r.prompt,sourceVideos:r.source_videos,referenceImages:r.reference_images,duration:r.duration,aspectRatio:r.aspect_ratio,resolution:r.resolution});return{content:[{type:"text",text:`Video edited successfully${n.model?` (model: ${n.model})`:""}`}],details:{type:"video_edit",model:n.model,durationMs:n.durationMs,mediaUrls:n.mediaUrls}}}}}var R5="video_merge",P5={type:"object",properties:{clips:{type:"array",items:{type:"object",properties:{video:{type:"string",description:"Video URL or file path. MUST be publicly accessible HTTP/HTTPS URL. Use file_upload tool first if local file."},audio:{type:"string",description:"Narration audio file path (from TTS)."},trimStart:{type:"number",description:"Trim start in seconds (default 0)."},trimEnd:{type:"number",description:"Trim end in seconds (default: full)."}},required:["video"]},minItems:2,description:"Array of video clips to merge, in order."},transition:{type:"string",description:"Transition effect: 'crossfade' (default), 'fade', 'wipeleft', 'cut', 'dissolve', etc."},transitionDuration:{type:"number",description:"Transition duration in seconds (0.1-2.0, default 0.5)."},subtitles:{type:"string",description:"Path to SRT subtitle file to burn-in."},bgm:{type:"string",description:"Background music file path."},bgmVolume:{type:"number",description:"BGM volume (0.0-1.0, default 0.15)."},outputResolution:{type:"string",description:"Output resolution: '1920x1080', '1080x1920', etc. Default: auto."},outputFps:{type:"number",description:"Output FPS (default 30)."}},required:["clips"]};function K_(t){return{name:R5,label:"Video Merge",description:"Merge multiple video clips into a single video with transitions, subtitles, and background music. Requires at least 2 clips. Supports crossfade, fade, wipe, dissolve, and cut transitions. All video/audio URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides local files. Audio per clip is preserved; BGM is mixed at adjustable volume.",parameters:P5,execute:async(e,r)=>{if(!r.clips||r.clips.length<2)return{content:[{type:"text",text:"Error: at least 2 clips are required for merging."}]};let n=await t.mergeVideos({clips:r.clips,transition:r.transition,transitionDuration:r.transitionDuration,subtitles:r.subtitles,bgm:r.bgm,bgmVolume:r.bgmVolume,outputResolution:r.outputResolution,outputFps:r.outputFps});return{content:[{type:"text",text:`Merged ${n.clipCount} clips \u2192 ${n.durationSec.toFixed(1)}s video`+(r.transition?` (transition: ${r.transition})`:"")}],details:{type:"video_merge",localPath:n.localPath,servePath:n.servePath,durationSec:n.durationSec,clipCount:n.clipCount,mediaUrls:n.mediaUrls}}}}}var T5="video_upscale",A5={type:"object",properties:{video:{type:"string",description:"Video URL to upscale. MUST be publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},targetResolution:{type:"string",description:"Target resolution: '1080p' (default, 1920x1080/1080x1920), '2k' (2560x1440/1440x2560)."},sharpness:{type:"string",description:"Sharpening intensity: 'light' (default), 'medium', 'strong'."}},required:["video"]};function V_(t){return{name:T5,label:"Video Upscale",description:"Upscale a video to higher resolution with optional sharpening. Auto-detects orientation (landscape/portrait). Uses Lanczos interpolation + unsharp mask. Supports 1080p and 2K targets. Video URL MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file. Best used as post-processing after video_merge.",parameters:A5,execute:async(e,r)=>{let n=await t.upscaleVideo({video:r.video,targetResolution:r.targetResolution,sharpness:r.sharpness});return{content:[{type:"text",text:`Upscaled to ${n.resolution}${r.sharpness?` (sharpness: ${r.sharpness})`:""}`}],details:{type:"video_upscale",localPath:n.localPath,servePath:n.servePath,resolution:n.resolution,durationSec:n.durationSec,mediaUrls:n.mediaUrls}}}}}var I5="three_d_generate",C5={type:"object",properties:{prompt:{type:"string",description:"3D model generation prompt. Describe the object's shape, material, texture, color, and pose. For text-to-3D, provide a detailed description. For image-to-3D, also provide image_url."},image_url:{type:"string",description:"Reference image URL for image-to-3D generation. The image should show the object clearly from a single viewpoint with clean background for best results. MUST be a publicly accessible HTTP/HTTPS URL. Local file paths and data: URLs are NOT supported."},output_format:{type:"string",description:"3D model output format: 'glb' (default), 'obj', 'usd', 'usdz'."},seed:{type:"number",description:"Random seed for reproducible generation."}},required:["prompt"]};function Z_(t){return{name:I5,label:"3D Generate",description:"Generate a 3D model from a text prompt or reference image. Supports text-to-3D and image-to-3D workflows. Output formats include GLB, OBJ, USD. The generated model can be viewed in any 3D viewer or imported into game engines. IMPORTANT: Describe the object in detail \u2014 shape, size, material, texture, color, and pose.",parameters:C5,execute:async(e,r)=>{let n=await t.generate3D({prompt:r.prompt,imageUrl:r.image_url,outputFormat:r.output_format,seed:r.seed}),o=n.mediaUrls.length,i=`Generated ${o} 3D model${o>1?"s":""}${n.model?` (model: ${n.model})`:""}`;return o===0&&n.metadata?.debugResponseKeys&&(i+=` [debug: response keys=${JSON.stringify(n.metadata.debugResponseKeys)}, content=${n.metadata.debugContentSample??"null"}]`),{content:[{type:"text",text:i}],details:{type:"three_d_generate",model:n.model,durationMs:n.durationMs,mediaUrls:n.mediaUrls,...n.metadata??{}}}}}}var _5={type:"object",properties:{audio_url:{type:"string",description:"URL of the audio file to transcribe. Supports mp3, wav, m4a, ogg, flac formats. MUST be a publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},language:{type:"string",description:"Language hint for transcription: 'zh' (Chinese), 'en' (English), or auto-detect if omitted."}},required:["audio_url"]};function J_(t){return{name:"stt",label:"STT",description:"Transcribe audio to text (Speech-to-Text). Provide an audio file URL and receive the spoken content as text. Supports Chinese and English. Use for meeting transcription, voice message reading, subtitle generation, or any audio-to-text conversion.",parameters:_5,execute:async(e,r)=>{if(!r.audio_url)return{content:[{type:"text",text:"Error: audio_url parameter is required. Provide a publicly accessible HTTP/HTTPS URL to an audio file."}],details:{error:"audio_url parameter is required"}};let n=await t.speechToText({audioUrl:r.audio_url,language:r.language}),o=n.transcription.length>200?n.transcription.slice(0,200)+"\u2026":n.transcription;return{content:[{type:"text",text:n.transcription}],details:{type:"stt",model:n.model,durationMs:n.durationMs,transcriptionLength:n.transcription.length,preview:o}}}}}var E5="voice_clone",M5={type:"object",properties:{text:{type:"string",description:"Text to synthesize in the cloned voice."},sample_audio_url:{type:"string",description:"URL of an audio sample (5-30 seconds recommended) of the voice to clone. The sample should be clear speech with minimal background noise. MUST be a publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},speed:{type:"number",description:"Speech speed multiplier (0.5-2.0). Default is 1.0."}},required:["text","sample_audio_url"]};function X_(t){return{name:E5,label:"Voice Clone",description:"Clone a voice from an audio sample and synthesize new speech in that voice. Requires a clear audio sample (5-30s recommended) of the target voice. Use for personalized narration, character voices, or voice preservation. DO NOT use for impersonation or deception. For standard TTS with preset voices, use the tts tool instead.",parameters:M5,execute:async(e,r)=>{let n=await t.cloneVoice({text:r.text,sampleAudioUrl:r.sample_audio_url,speed:r.speed});return{content:[{type:"text",text:`Voice cloned and synthesized speech${n.model?` (model: ${n.model})`:""}`}],details:{type:"voice_clone",model:n.model,voiceId:n.voiceId,durationMs:n.durationMs,mediaUrls:n.mediaUrls}}}}}var D5="media_cancel",N5={type:"object",properties:{task_id:{type:"string",description:"The task ID of the media generation to cancel (returned in previous generation results)."},provider:{type:"string",description:"Provider name (e.g. 'doubao', 'zhipu'). If omitted, auto-detects from task context."}},required:["task_id"]};function Y_(t){return{name:D5,label:"Media Cancel",description:"Cancel an in-progress media generation task (video, 3D, etc.). Provide the task_id from a previous generation result. Use this when a user wants to abort a long-running generation.",parameters:N5,execute:async(e,r)=>{if(!r.task_id)return{content:[{type:"text",text:"Error: task_id is required."}],details:{error:"task_id is required"}};let n=await t.cancelTask({taskId:r.task_id,provider:r.provider});return{content:[{type:"text",text:n.ok?`Task ${r.task_id} cancelled.`:`Cancel failed: ${n.message}`}],details:n.ok?void 0:{error:n.message}}}}}import LJ from"node:fs";import UJ from"node:path";import le from"node:fs/promises";import dE from"node:os";import Y from"node:path";import{createCanvas as lu,loadImage as Sb}from"@napi-rs/canvas";import{randomUUID as $5}from"node:crypto";import un from"node:fs";import dn from"node:path";import{fileURLToPath as O5}from"node:url";import{createCanvas as j5,loadImage as L5}from"@napi-rs/canvas";async function fb(t){let e=await q5(un.readFileSync(t));for(let s of e.keys())if(kl(s))throw new Error(`unsafe path in Petdex package: ${s}`);if(e.has("manifest.json")||[...e.keys()].some(s=>s.toLowerCase().endsWith(".svg")))throw new Error("SVG .pet state packages are not supported by Petdex v1");let r=e.get("pet.json");if(!r)throw new Error("Petdex package missing pet.json");let n=e.get("spritesheet.webp");if(!n)throw new Error("Petdex package missing spritesheet.webp");let o=JSON.parse(r.toString("utf-8")),i=Kn(o,n);return{manifest:o,spritesheet:n,validation:i}}async function hb(t){let e=Kn(t.asset,t.spritesheet);un.mkdirSync(t.outputDir,{recursive:!0});let r=B5(t.fileName??`${t.asset.id}.petdex`),n=dn.join(t.outputDir,r.endsWith(".petdex")?r:`${r}.petdex`),o=[{name:"pet.json",data:Buffer.from(JSON.stringify(t.asset,null,2),"utf-8")},{name:"spritesheet.webp",data:t.spritesheet},{name:"validation.json",data:Buffer.from(JSON.stringify(e,null,2),"utf-8")},...t.productionRun?[{name:"production-run.json",data:Buffer.from(JSON.stringify(t.productionRun,null,2),"utf-8")}]:[]];return un.writeFileSync(n,W5(o)),n}async function yb(t){let e=t.now??new Date().toISOString(),r=t.id??`petdex-${$5()}`,n=await H5(t.spritesheet),o=vv(n),i={schema:Ls,id:r,assetKind:"petdex",name:t.name,description:t.description,createdAt:e,updatedAt:e,source:{kind:t.sourceKind??"forge",prompt:t.prompt??null},sourcePrompt:t.prompt??void 0,atlas:{image:"spritesheet.webp",...X,sha256:o},animations:yv(),thumbnail:{frame:0}},s=Kn(i,n);return{asset:i,spritesheet:n,validation:s}}var U5=["builtin-anime-horse-girl"],ou=null;async function iu(){return ou||(ou=Promise.all(U5.map(t=>F5(t))).catch(t=>{throw ou=null,t})),ou}async function F5(t){let e=z5(),r=dn.join(e,`${t}.petdex`);if(un.existsSync(r)){let u=await fb(r);return Q_(t,u.manifest),{asset:u.manifest,spritesheet:u.spritesheet,validation:u.validation}}let n=dn.join(e,t),o=dn.join(n,"pet.json"),i=dn.join(n,"spritesheet.webp");if(!un.existsSync(o)||!un.existsSync(i))throw new Error(`Missing published builtin Petdex asset ${t} under ${e}`);let s=JSON.parse(un.readFileSync(o,"utf-8")),a=un.readFileSync(i),c=Kn(s,a);return Q_(t,s),{asset:s,spritesheet:a,validation:c}}function z5(){let t=process.env.QLOGICAGENT_BUILTIN_PETDEX_DIR?.trim();return t?dn.resolve(t):dn.resolve(dn.dirname(O5(import.meta.url)),"builtin-petdex")}function Q_(t,e){if(e.id!==t)throw new Error(`Builtin Petdex asset id mismatch: expected ${t}, got ${e.id}`);if(e.source.kind!=="builtin")throw new Error(`Builtin Petdex asset ${t} must declare source.kind=builtin`)}async function H5(t){let e=await L5(t),r=j5(X.width,X.height),n=r.getContext("2d");return n.clearRect(0,0,X.width,X.height),n.imageSmoothingEnabled=!0,n.imageSmoothingQuality="high",n.drawImage(e,0,0,X.width,X.height),Buffer.from(await r.encode("webp"))}function B5(t){return t.replace(/[^a-zA-Z0-9._-]/g,"_").replace(/^_+/,"")||"petdex-asset.petdex"}async function q5(t){let e=new Map,r=0;for(;r<t.length-4&&t.readUInt32LE(r)===67324752;){let o=t.readUInt16LE(r+8),i=t.readUInt32LE(r+18),s=t.readUInt32LE(r+22),a=t.readUInt16LE(r+26),c=t.readUInt16LE(r+28),u=r+30,d=t.subarray(u,u+a).toString("utf-8"),p=u+a+c,m=t.subarray(p,p+i);if(o===0)e.set(d,t.subarray(p,p+s));else if(o===8){let{inflateRawSync:g}=await import("node:zlib");e.set(d,g(m))}r=p+i}return e}function W5(t){let e=[],r=[],n=0,{time:o,date:i}=G5();for(let u of t){if(kl(u.name))throw new Error(`unsafe path in Petdex package entry: ${u.name}`);let d=Buffer.from(u.name,"utf-8"),p=V5(u.data),m=Buffer.alloc(30);m.writeUInt32LE(67324752,0),m.writeUInt16LE(20,4),m.writeUInt16LE(2048,6),m.writeUInt16LE(0,8),m.writeUInt16LE(o,10),m.writeUInt16LE(i,12),m.writeUInt32LE(p,14),m.writeUInt32LE(u.data.length,18),m.writeUInt32LE(u.data.length,22),m.writeUInt16LE(d.length,26),m.writeUInt16LE(0,28),e.push(m,d,u.data);let g=Buffer.alloc(46);g.writeUInt32LE(33639248,0),g.writeUInt16LE(20,4),g.writeUInt16LE(20,6),g.writeUInt16LE(2048,8),g.writeUInt16LE(0,10),g.writeUInt16LE(o,12),g.writeUInt16LE(i,14),g.writeUInt32LE(p,16),g.writeUInt32LE(u.data.length,20),g.writeUInt32LE(u.data.length,24),g.writeUInt16LE(d.length,28),g.writeUInt16LE(0,30),g.writeUInt16LE(0,32),g.writeUInt16LE(0,34),g.writeUInt16LE(0,36),g.writeUInt32LE(0,38),g.writeUInt32LE(n,42),r.push(g,d),n+=m.length+d.length+u.data.length}let s=n,a=Buffer.concat(r),c=Buffer.alloc(22);return c.writeUInt32LE(101010256,0),c.writeUInt16LE(0,4),c.writeUInt16LE(0,6),c.writeUInt16LE(t.length,8),c.writeUInt16LE(t.length,10),c.writeUInt32LE(a.length,12),c.writeUInt32LE(s,16),c.writeUInt16LE(0,20),Buffer.concat([...e,a,c])}function G5(){let t=new Date,e=t.getHours()<<11|t.getMinutes()<<5|Math.floor(t.getSeconds()/2),r=t.getFullYear()-1980<<9|t.getMonth()+1<<5|t.getDate();return{time:e,date:r}}var K5=new Uint32Array(256).map((t,e)=>{let r=e;for(let n=0;n<8;n++)r=r&1?3988292384^r>>>1:r>>>1;return r>>>0});function V5(t){let e=4294967295;for(let r of t)e=K5[(e^r)&255]^e>>>8;return(e^4294967295)>>>0}import{spawn as Z5}from"node:child_process";import{existsSync as eE}from"node:fs";import{dirname as tE,join as cu}from"node:path";import{fileURLToPath as J5}from"node:url";var X5=tE(J5(import.meta.url)),su,au;function rE(t,e,r){return new Promise(n=>{let o="",i="",s=!1,a=d=>{s||(s=!0,clearTimeout(u),n(d))},c=Z5(t,e,{windowsHide:!0}),u=setTimeout(()=>{c.kill("SIGKILL"),a({ok:!1,stdout:o,stderr:`${i}
804
+ `)}],details:{type:"tool_search",query:t.query,matchCount:t.matches.length,totalDeferred:t.totalDeferred,matches:t.matches.map(r=>r.name)}}}var pb="image_generate",v5={type:"object",properties:{prompt:{type:"string",description:"Image generation prompt. Enrich vague requests with style, lighting, composition, color, mood details."},purpose:{type:"string",description:"Intended use: 'social-media', 'short-video-cover', 'phone-wallpaper', 'avatar', 'poster', etc."},style:{type:"string",description:"Visual art style: 'photorealistic', 'anime', 'watercolor', 'oil-painting', '3d-render', etc."},size:{type:"string",description:"Dimensions: e.g. '1024x1792' (portrait), '1792x1024' (landscape), '1024x1024' (square). Default: '1024x1024'."},image_url:{type:"string",description:"Reference image URL for image-to-image generation (img2img). Character reference sheet or style transfer. MUST be a publicly accessible HTTP/HTTPS URL. Local file paths and data: URLs are NOT supported."},n:{type:"number",description:"Number of images to generate (1-4). Default: 1."},quality:{type:"string",description:"Image quality level: 'auto', 'high', 'low', 'hd'. Provider-specific."},seed:{type:"number",description:"Random seed for reproducible generation. Same seed + prompt = same result."}},required:["prompt"]};function H_(t){return{name:pb,label:"Image Generate",description:"Generate images from a text prompt. You MUST enrich vague prompts with details about style, lighting, composition, color, and mood before calling. Supports img2img via image_url reference. All generated images are saved locally and can be viewed immediately. IMPORTANT: For ordinary creative requests, infer reasonable defaults for purpose, style, and size and call this tool directly. Use ask_user only when a missing detail is critical or the request is genuinely ambiguous (e.g. the user asks for a production ad with unspecified brand constraints). Infer image size automatically from purpose (e.g. 1024x1792 for phone wallpaper, 1792x1024 for landscape poster, 1024x1024 for avatar/social). Do NOT expose size as a raw number to the user. Do NOT invent Markdown image URLs, placeholder attachment paths, or claim an image was generated without this tool returning mediaUrls. ALL reference image URLs MUST be publicly accessible HTTP/HTTPS URLs. Use file_upload tool first if the user provides a local file. Local file paths and data: URIs are NOT supported by the generation API.",parameters:v5,isEgress:!0,egressCarriesData:!1,execute:async(e,r)=>{let n=await t.generateImage({prompt:r.prompt,purpose:r.purpose,style:r.style,size:r.size,imageUrl:r.image_url,n:r.n,quality:r.quality,seed:r.seed}),o=n.mediaUrls.length;return{content:[{type:"text",text:`Generated ${o} image${o>1?"s":""}${n.model?` (model: ${n.model})`:""}`}],details:{type:"image_generate",model:n.model,size:n.size,durationMs:n.durationMs,mediaUrls:n.mediaUrls}}}}}var b5={type:"object",properties:{text:{type:"string",description:"Text to convert to speech."},channel:{type:"string",description:"Optional channel id to pick output format (e.g. telegram)."},voice:{type:"string",description:"Voice name for TTS. Available voices depend on the provider. Common options: alloy, ash, ballad, coral, echo, fable, nova, onyx, sage, shimmer."},speed:{type:"number",description:"Speech speed multiplier (0.25-4.0). Default is 1.0."}},required:["text"]};function B_(t){return{name:"tts",label:"TTS",description:"Convert text to speech (TTS) \u2014 read text aloud as spoken audio. Use for narration, voice messages, or any spoken-word output. DO NOT use for music, songs, or melodies \u2014 use music_generate instead.",parameters:b5,execute:async(e,r)=>{let n=await t.textToSpeech({text:r.text,channel:r.channel,voice:r.voice,speed:r.speed});return{content:[{type:"text",text:"\u5DF2\u6210\u529F\u751F\u6210\u8BED\u97F3\u3002"}],details:{type:"tts",audioPath:n.audioPath,provider:n.provider,voiceCompatible:n.voiceCompatible,mediaUrls:n.mediaUrls}}}}}var mb="video_generate",k5={type:"object",properties:{prompt:{type:"string",description:"Video generation prompt. MUST be in English. Include scene, movement, camera motion, lighting, style."},purpose:{type:"string",description:"Intended use: 'social-media', 'short-video', 'presentation', etc."},style:{type:"string",description:"Visual style: 'cinematic', 'anime', 'watercolor', etc."},image_url:{type:"string",description:"Reference image URL for image-to-video generation (first frame, style reference, or character reference). MUST be a publicly accessible HTTP/HTTPS URL. Local file paths and data: URLs are NOT supported. If the user provides a local file, use a file hosting service or the image_generate tool first."},reference_videos:{type:"array",items:{type:"string"},maxItems:3,description:"Reference video URLs for video-to-video or multimodal generation (Seedance 2.0). Max 3 videos, total duration \u226415s. Use for: (a) video-to-video: provide source video to restyle/transform with prompt guidance; (b) multimodal reference: combine with image_url and/or reference_audios for style/motion/audio-guided generation. Each URL MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},reference_audios:{type:"array",items:{type:"string"},maxItems:3,description:"Reference audio URLs for audio-guided video generation (Seedance 2.0). Max 3 audio clips, total duration \u226415s. CANNOT be used alone \u2014 must be combined with at least one image_url or reference_video. Each URL MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},generate_audio:{type:"boolean",description:"Generate synchronized audio track for the video (Seedance 2.0/1.5 pro). When true, the output video includes AI-generated sound effects matching the visual content."},aspect_ratio:{type:"string",description:"Video aspect ratio: '9:16' (vertical), '16:9' (horizontal), '1:1' (square). Default: '16:9'."},duration:{type:"number",minimum:3,maximum:15,description:"Video duration in seconds. Seedance 2.0: 4-15s per shot. Seedance 1.0/1.5: 3-10s. For longer videos (>15s), use multi-shot storyboard workflow (generate + extend/merge). Must be confirmed by user before generation."},resolution:{type:"string",description:"Output resolution: '480p', '720p', '1080p'. Default: '720p'."},fps:{type:"number",description:"Frame rate: 24 or 30 fps. Default: provider-specific."},seed:{type:"number",description:"Random seed for reproducible generation."},camera_fixed:{type:"boolean",description:"Lock camera position (Seedance 1.0/1.5 only, not supported for img2video)."},return_last_frame:{type:"boolean",description:"Return last frame URL for chaining continuous video segments."},draft:{type:"boolean",description:"Draft mode: low-cost preview (Seedance 1.5 pro only)."},service_tier:{type:"string",enum:["default","flex"],description:"'default' (online, fast) or 'flex' (offline, ~50% cost). Not all models support flex."},callback_url:{type:"string",description:"Webhook URL for async task completion notification."},safety_identifier:{type:"string",description:"End-user safety identifier for content moderation tracking."},execution_expires_after:{type:"number",description:"Task expiration in seconds (for offline/flex scheduling)."},video_tools:{type:"array",items:{type:"string"},description:"Video-level builtin tools, e.g. ['web_search'] (Seedance 2.0 online search)."}},required:["prompt"]};function q_(t){return{name:mb,label:"Video Generate",description:"Generate a short video clip from a text prompt, reference image, source video, or multimodal references. Prompt MUST be in English. Include scene, movement, camera motion, lighting details. Single-shot: 3\u201310s. For longer videos (>10s), use multi-shot storyboard workflow. MODES: (1) text-to-video: prompt only. (2) image-to-video: prompt + image_url. (3) video-to-video: prompt + reference_videos \u2014 restyle/transform an existing video with prompt guidance. (4) multimodal reference: prompt + any combination of image_url / reference_videos / reference_audios for style/motion/audio-guided generation. (5) generate_audio=true for synchronized sound effects. ALL image/video/audio URLs MUST be publicly accessible HTTP/HTTPS URLs. Local file paths and data: URIs are NOT supported by the generation API. If the user provides a local file, use the file_upload tool FIRST to get a public URL. IMPORTANT: If the user has not specified aspect ratio or duration, use ask_user to clarify (e.g. aspect: 16:9 for landscape / 9:16 for vertical / 1:1 for square; duration: 3-10s). Auto-set aspect_ratio based on stated purpose (e.g. 9:16 for short-video / Douyin, 16:9 for presentation).",parameters:k5,execute:async(e,r)=>{let n=await t.generateVideo({prompt:r.prompt,purpose:r.purpose,style:r.style,imageUrl:r.image_url,referenceVideos:r.reference_videos,referenceAudios:r.reference_audios,generateAudio:r.generate_audio,aspectRatio:r.aspect_ratio,duration:r.duration,resolution:r.resolution,fps:r.fps,seed:r.seed,cameraFixed:r.camera_fixed,returnLastFrame:r.return_last_frame,draft:r.draft,serviceTier:r.service_tier,callbackUrl:r.callback_url,safetyIdentifier:r.safety_identifier,executionExpiresAfterSeconds:r.execution_expires_after,videoTools:r.video_tools}),o=n.mediaUrls.length,i=[`Generated ${o} video${o>1?"s":""}`];return n.model&&i.push(`model: ${n.model}`),n.lastFrameUrl&&i.push(`last_frame: ${n.lastFrameUrl}`),n.taskId&&i.push(`task_id: ${n.taskId}`),{content:[{type:"text",text:i.length>1?`${i[0]} (${i.slice(1).join(", ")})`:i[0]}],details:{type:"video_generate",model:n.model,durationMs:n.durationMs,mediaUrls:n.mediaUrls,...n.taskId?{taskId:n.taskId}:{}}}}}}var gb="music_generate",w5={type:"object",properties:{prompt:{type:"string",description:"Music generation prompt. MUST be in English. Include genre, mood, tempo, instruments, and atmosphere details."},purpose:{type:"string",description:"Intended use: 'background-music', 'ringtone', 'short-video-bgm', 'full-song', 'notification-sound', etc."},style:{type:"string",description:"Musical style/genre: 'lo-fi', 'pop', 'rock', 'jazz', 'classical', 'electronic', 'ambient', etc."},lyrics:{type:"string",description:"Optional lyrics for vocal music. Structure with [verse], [chorus], [bridge] tags if desired."},duration:{type:"number",description:"Duration in seconds (5-300). Infer from purpose: ringtone 15-30s, BGM 30-60s, full song 120-180s."},is_instrumental:{type:"boolean",description:"Set true for pure instrumental music without vocals. Defaults to true when no lyrics are provided."},cover_audio_url:{type:"string",description:"URL of an existing audio track to use as base for cover/remix. When provided, generates a cover version. MUST be a publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},audio_format:{type:"string",enum:["mp3","wav","flac"],description:"Output audio format. Defaults to mp3."}},required:["prompt"]};function W_(t){return{name:gb,label:"Music Generate",description:"Generate music, songs, or melodies from text descriptions. Prompt MUST be in English. Supports lyrics for vocal songs. DO NOT use for spoken-word audio or TTS \u2014 use tts tool instead. IMPORTANT: If the user has not specified genre/style or duration, use ask_user to clarify (e.g. style: lo-fi / pop / rock / jazz; duration inferred from purpose: 30s for ringtone, 60-90s for BGM, 180-240s for full song). Auto-infer duration from purpose when possible.",parameters:w5,isEgress:!0,egressCarriesData:!1,execute:async(e,r)=>{let n=r.lyrics;if(!n&&!r.is_instrumental&&t.generateLyrics)try{n=await t.generateLyrics(r.prompt)}catch{}let o=await t.generateMusic({prompt:r.prompt,purpose:r.purpose,style:r.style,lyrics:n,duration:r.duration,isInstrumental:r.is_instrumental,audioUrl:r.cover_audio_url,audioFormat:r.audio_format}),i=o.mediaUrls.length;return{content:[{type:"text",text:`Generated ${i} audio track${i>1?"s":""}${o.model?` (model: ${o.model})`:""}`}],details:{type:"music_generate",model:o.model,durationMs:o.durationMs,mediaUrls:o.mediaUrls}}}}}var S5="video_edit",x5={type:"object",properties:{prompt:{type:"string",description:"Edit instruction. Reference videos as \u89C6\u98911, \u89C6\u98912, \u89C6\u98913. Reference images as \u56FE\u72471, \u56FE\u72472. Operations: add/remove/modify elements, extend, track fill."},source_videos:{type:"array",items:{type:"string"},minItems:1,maxItems:3,description:"Video(s) to edit (1-3 URLs). Order: [0]=\u89C6\u98911, [1]=\u89C6\u98912, [2]=\u89C6\u98913. All URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},reference_images:{type:"array",items:{type:"string"},maxItems:9,description:"Optional reference images for element replacement (up to 9). All URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file."},duration:{type:"number",minimum:4,maximum:15,description:"Output duration in seconds (4-15s). Default: same as source."},aspect_ratio:{type:"string",description:"Output aspect ratio: 16:9, 9:16, 1:1, 4:3, 3:4, 21:9. Default: same as source."},resolution:{type:"string",description:"Output resolution: '480p' or '720p'. Default: '720p'."}},required:["prompt","source_videos"]};function G_(t){return{name:S5,label:"Video Edit",description:"Edit existing videos: add/remove/modify elements, extend, or bridge clips. Requires source_videos (max 3). Max 9 reference images for element replacement. Max 720p. All video/image URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file. For generating NEW videos from scratch, use video_generate instead.",parameters:x5,execute:async(e,r)=>{if(!r.source_videos?.length)return{content:[{type:"text",text:"Error: source_videos is required."}]};let n=await t.editVideo({prompt:r.prompt,sourceVideos:r.source_videos,referenceImages:r.reference_images,duration:r.duration,aspectRatio:r.aspect_ratio,resolution:r.resolution});return{content:[{type:"text",text:`Video edited successfully${n.model?` (model: ${n.model})`:""}`}],details:{type:"video_edit",model:n.model,durationMs:n.durationMs,mediaUrls:n.mediaUrls}}}}}var R5="video_merge",P5={type:"object",properties:{clips:{type:"array",items:{type:"object",properties:{video:{type:"string",description:"Video URL or file path. MUST be publicly accessible HTTP/HTTPS URL. Use file_upload tool first if local file."},audio:{type:"string",description:"Narration audio file path (from TTS)."},trimStart:{type:"number",description:"Trim start in seconds (default 0)."},trimEnd:{type:"number",description:"Trim end in seconds (default: full)."}},required:["video"]},minItems:2,description:"Array of video clips to merge, in order."},transition:{type:"string",description:"Transition effect: 'crossfade' (default), 'fade', 'wipeleft', 'cut', 'dissolve', etc."},transitionDuration:{type:"number",description:"Transition duration in seconds (0.1-2.0, default 0.5)."},subtitles:{type:"string",description:"Path to SRT subtitle file to burn-in."},bgm:{type:"string",description:"Background music file path."},bgmVolume:{type:"number",description:"BGM volume (0.0-1.0, default 0.15)."},outputResolution:{type:"string",description:"Output resolution: '1920x1080', '1080x1920', etc. Default: auto."},outputFps:{type:"number",description:"Output FPS (default 30)."}},required:["clips"]};function K_(t){return{name:R5,label:"Video Merge",description:"Merge multiple video clips into a single video with transitions, subtitles, and background music. Requires at least 2 clips. Supports crossfade, fade, wipe, dissolve, and cut transitions. All video/audio URLs MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides local files. Audio per clip is preserved; BGM is mixed at adjustable volume.",parameters:P5,execute:async(e,r)=>{if(!r.clips||r.clips.length<2)return{content:[{type:"text",text:"Error: at least 2 clips are required for merging."}]};let n=await t.mergeVideos({clips:r.clips,transition:r.transition,transitionDuration:r.transitionDuration,subtitles:r.subtitles,bgm:r.bgm,bgmVolume:r.bgmVolume,outputResolution:r.outputResolution,outputFps:r.outputFps});return{content:[{type:"text",text:`Merged ${n.clipCount} clips \u2192 ${n.durationSec.toFixed(1)}s video`+(r.transition?` (transition: ${r.transition})`:"")}],details:{type:"video_merge",localPath:n.localPath,servePath:n.servePath,durationSec:n.durationSec,clipCount:n.clipCount,mediaUrls:n.mediaUrls}}}}}var T5="video_upscale",A5={type:"object",properties:{video:{type:"string",description:"Video URL to upscale. MUST be publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},targetResolution:{type:"string",description:"Target resolution: '1080p' (default, 1920x1080/1080x1920), '2k' (2560x1440/1440x2560)."},sharpness:{type:"string",description:"Sharpening intensity: 'light' (default), 'medium', 'strong'."}},required:["video"]};function V_(t){return{name:T5,label:"Video Upscale",description:"Upscale a video to higher resolution with optional sharpening. Auto-detects orientation (landscape/portrait). Uses Lanczos interpolation + unsharp mask. Supports 1080p and 2K targets. Video URL MUST be publicly accessible HTTP/HTTPS. Use file_upload tool first if the user provides a local file. Best used as post-processing after video_merge.",parameters:A5,execute:async(e,r)=>{let n=await t.upscaleVideo({video:r.video,targetResolution:r.targetResolution,sharpness:r.sharpness});return{content:[{type:"text",text:`Upscaled to ${n.resolution}${r.sharpness?` (sharpness: ${r.sharpness})`:""}`}],details:{type:"video_upscale",localPath:n.localPath,servePath:n.servePath,resolution:n.resolution,durationSec:n.durationSec,mediaUrls:n.mediaUrls}}}}}var I5="three_d_generate",C5={type:"object",properties:{prompt:{type:"string",description:"3D model generation prompt. Describe the object's shape, material, texture, color, and pose. For text-to-3D, provide a detailed description. For image-to-3D, also provide image_url."},image_url:{type:"string",description:"Reference image URL for image-to-3D generation. The image should show the object clearly from a single viewpoint with clean background for best results. MUST be a publicly accessible HTTP/HTTPS URL. Local file paths and data: URLs are NOT supported."},output_format:{type:"string",description:"3D model output format: 'glb' (default), 'obj', 'usd', 'usdz'."},seed:{type:"number",description:"Random seed for reproducible generation."}},required:["prompt"]};function Z_(t){return{name:I5,label:"3D Generate",description:"Generate a 3D model from a text prompt or reference image. Supports text-to-3D and image-to-3D workflows. Output formats include GLB, OBJ, USD. The generated model can be viewed in any 3D viewer or imported into game engines. IMPORTANT: Describe the object in detail \u2014 shape, size, material, texture, color, and pose.",parameters:C5,execute:async(e,r)=>{let n=await t.generate3D({prompt:r.prompt,imageUrl:r.image_url,outputFormat:r.output_format,seed:r.seed}),o=n.mediaUrls.length,i=`Generated ${o} 3D model${o>1?"s":""}${n.model?` (model: ${n.model})`:""}`;return o===0&&n.metadata?.debugResponseKeys&&(i+=` [debug: response keys=${JSON.stringify(n.metadata.debugResponseKeys)}, content=${n.metadata.debugContentSample??"null"}]`),{content:[{type:"text",text:i}],details:{type:"three_d_generate",model:n.model,durationMs:n.durationMs,mediaUrls:n.mediaUrls,...n.metadata??{}}}}}}var _5={type:"object",properties:{audio_url:{type:"string",description:"URL of the audio file to transcribe. Supports mp3, wav, m4a, ogg, flac formats. MUST be a publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},language:{type:"string",description:"Language hint for transcription: 'zh' (Chinese), 'en' (English), or auto-detect if omitted."}},required:["audio_url"]};function J_(t){return{name:"stt",label:"STT",description:"Transcribe audio to text (Speech-to-Text). Provide an audio file URL and receive the spoken content as text. Supports Chinese and English. Use for meeting transcription, voice message reading, subtitle generation, or any audio-to-text conversion.",parameters:_5,execute:async(e,r)=>{if(!r.audio_url)return{content:[{type:"text",text:"Error: audio_url parameter is required. Provide a publicly accessible HTTP/HTTPS URL to an audio file."}],details:{error:"audio_url parameter is required"}};let n=await t.speechToText({audioUrl:r.audio_url,language:r.language}),o=n.transcription.length>200?n.transcription.slice(0,200)+"\u2026":n.transcription;return{content:[{type:"text",text:n.transcription}],details:{type:"stt",model:n.model,durationMs:n.durationMs,transcriptionLength:n.transcription.length,preview:o}}}}}var E5="voice_clone",M5={type:"object",properties:{text:{type:"string",description:"Text to synthesize in the cloned voice."},sample_audio_url:{type:"string",description:"URL of an audio sample (5-30 seconds recommended) of the voice to clone. The sample should be clear speech with minimal background noise. MUST be a publicly accessible HTTP/HTTPS URL. Use file_upload tool first if the user provides a local file."},speed:{type:"number",description:"Speech speed multiplier (0.5-2.0). Default is 1.0."}},required:["text","sample_audio_url"]};function X_(t){return{name:E5,label:"Voice Clone",description:"Clone a voice from an audio sample and synthesize new speech in that voice. Requires a clear audio sample (5-30s recommended) of the target voice. Use for personalized narration, character voices, or voice preservation. DO NOT use for impersonation or deception. For standard TTS with preset voices, use the tts tool instead.",parameters:M5,execute:async(e,r)=>{let n=await t.cloneVoice({text:r.text,sampleAudioUrl:r.sample_audio_url,speed:r.speed});return{content:[{type:"text",text:`Voice cloned and synthesized speech${n.model?` (model: ${n.model})`:""}`}],details:{type:"voice_clone",model:n.model,voiceId:n.voiceId,durationMs:n.durationMs,mediaUrls:n.mediaUrls}}}}}var D5="media_cancel",N5={type:"object",properties:{task_id:{type:"string",description:"The task ID of the media generation to cancel (returned in previous generation results)."},provider:{type:"string",description:"Provider name (e.g. 'doubao', 'zhipu'). If omitted, auto-detects from task context."}},required:["task_id"]};function Y_(t){return{name:D5,label:"Media Cancel",description:"Cancel an in-progress media generation task (video, 3D, etc.). Provide the task_id from a previous generation result. Use this when a user wants to abort a long-running generation.",parameters:N5,execute:async(e,r)=>{if(!r.task_id)return{content:[{type:"text",text:"Error: task_id is required."}],details:{error:"task_id is required"}};let n=await t.cancelTask({taskId:r.task_id,provider:r.provider});return{content:[{type:"text",text:n.ok?`Task ${r.task_id} cancelled.`:`Cancel failed: ${n.message}`}],details:n.ok?void 0:{error:n.message}}}}}import LJ from"node:fs";import UJ from"node:path";import le from"node:fs/promises";import dE from"node:os";import Y from"node:path";import{createCanvas as lu,loadImage as Sb}from"@napi-rs/canvas";import{randomUUID as $5}from"node:crypto";import un from"node:fs";import dn from"node:path";import{fileURLToPath as O5}from"node:url";import{createCanvas as j5,loadImage as L5}from"@napi-rs/canvas";async function fb(t){let e=await q5(un.readFileSync(t));for(let s of e.keys())if(kl(s))throw new Error(`unsafe path in Petdex package: ${s}`);if(e.has("manifest.json")||[...e.keys()].some(s=>s.toLowerCase().endsWith(".svg")))throw new Error("SVG .pet state packages are not supported by Petdex v1");let r=e.get("pet.json");if(!r)throw new Error("Petdex package missing pet.json");let n=e.get("spritesheet.webp");if(!n)throw new Error("Petdex package missing spritesheet.webp");let o=JSON.parse(r.toString("utf-8")),i=Kn(o,n);return{manifest:o,spritesheet:n,validation:i}}async function hb(t){let e=Kn(t.asset,t.spritesheet);un.mkdirSync(t.outputDir,{recursive:!0});let r=B5(t.fileName??`${t.asset.id}.petdex`),n=dn.join(t.outputDir,r.endsWith(".petdex")?r:`${r}.petdex`),o=[{name:"pet.json",data:Buffer.from(JSON.stringify(t.asset,null,2),"utf-8")},{name:"spritesheet.webp",data:t.spritesheet},{name:"validation.json",data:Buffer.from(JSON.stringify(e,null,2),"utf-8")},...t.productionRun?[{name:"production-run.json",data:Buffer.from(JSON.stringify(t.productionRun,null,2),"utf-8")}]:[]];return un.writeFileSync(n,W5(o)),n}async function yb(t){let e=t.now??new Date().toISOString(),r=t.id??`petdex-${$5()}`,n=await H5(t.spritesheet),o=vv(n),i={schema:Ls,id:r,assetKind:"petdex",name:t.name,description:t.description,createdAt:e,updatedAt:e,source:{kind:t.sourceKind??"forge",prompt:t.prompt??null},sourcePrompt:t.prompt??void 0,atlas:{image:"spritesheet.webp",...X,sha256:o},animations:yv(),thumbnail:{frame:0}},s=Kn(i,n);return{asset:i,spritesheet:n,validation:s}}var U5=["builtin-anime-horse-girl"],ou=null;async function iu(){return ou||(ou=Promise.all(U5.map(t=>F5(t))).catch(t=>{throw ou=null,t})),ou}async function F5(t){let e=z5(),r=dn.join(e,`${t}.petdex`);if(un.existsSync(r)){let u=await fb(r);return Q_(t,u.manifest),{asset:u.manifest,spritesheet:u.spritesheet,validation:u.validation}}let n=dn.join(e,t),o=dn.join(n,"pet.json"),i=dn.join(n,"spritesheet.webp");if(!un.existsSync(o)||!un.existsSync(i))throw new Error(`Missing published builtin Petdex asset ${t} under ${e}`);let s=JSON.parse(un.readFileSync(o,"utf-8")),a=un.readFileSync(i),c=Kn(s,a);return Q_(t,s),{asset:s,spritesheet:a,validation:c}}function z5(){let t=process.env.QLOGICAGENT_BUILTIN_PETDEX_DIR?.trim();return t?dn.resolve(t):dn.resolve(dn.dirname(O5(import.meta.url)),"builtin-petdex")}function Q_(t,e){if(e.id!==t)throw new Error(`Builtin Petdex asset id mismatch: expected ${t}, got ${e.id}`);if(e.source.kind!=="builtin")throw new Error(`Builtin Petdex asset ${t} must declare source.kind=builtin`)}async function H5(t){let e=await L5(t),r=j5(X.width,X.height),n=r.getContext("2d");return n.clearRect(0,0,X.width,X.height),n.imageSmoothingEnabled=!0,n.imageSmoothingQuality="high",n.drawImage(e,0,0,X.width,X.height),Buffer.from(await r.encode("webp"))}function B5(t){return t.replace(/[^a-zA-Z0-9._-]/g,"_").replace(/^_+/,"")||"petdex-asset.petdex"}async function q5(t){let e=new Map,r=0;for(;r<t.length-4&&t.readUInt32LE(r)===67324752;){let o=t.readUInt16LE(r+8),i=t.readUInt32LE(r+18),s=t.readUInt32LE(r+22),a=t.readUInt16LE(r+26),c=t.readUInt16LE(r+28),u=r+30,d=t.subarray(u,u+a).toString("utf-8"),p=u+a+c,m=t.subarray(p,p+i);if(o===0)e.set(d,t.subarray(p,p+s));else if(o===8){let{inflateRawSync:g}=await import("node:zlib");e.set(d,g(m))}r=p+i}return e}function W5(t){let e=[],r=[],n=0,{time:o,date:i}=G5();for(let u of t){if(kl(u.name))throw new Error(`unsafe path in Petdex package entry: ${u.name}`);let d=Buffer.from(u.name,"utf-8"),p=V5(u.data),m=Buffer.alloc(30);m.writeUInt32LE(67324752,0),m.writeUInt16LE(20,4),m.writeUInt16LE(2048,6),m.writeUInt16LE(0,8),m.writeUInt16LE(o,10),m.writeUInt16LE(i,12),m.writeUInt32LE(p,14),m.writeUInt32LE(u.data.length,18),m.writeUInt32LE(u.data.length,22),m.writeUInt16LE(d.length,26),m.writeUInt16LE(0,28),e.push(m,d,u.data);let g=Buffer.alloc(46);g.writeUInt32LE(33639248,0),g.writeUInt16LE(20,4),g.writeUInt16LE(20,6),g.writeUInt16LE(2048,8),g.writeUInt16LE(0,10),g.writeUInt16LE(o,12),g.writeUInt16LE(i,14),g.writeUInt32LE(p,16),g.writeUInt32LE(u.data.length,20),g.writeUInt32LE(u.data.length,24),g.writeUInt16LE(d.length,28),g.writeUInt16LE(0,30),g.writeUInt16LE(0,32),g.writeUInt16LE(0,34),g.writeUInt16LE(0,36),g.writeUInt32LE(0,38),g.writeUInt32LE(n,42),r.push(g,d),n+=m.length+d.length+u.data.length}let s=n,a=Buffer.concat(r),c=Buffer.alloc(22);return c.writeUInt32LE(101010256,0),c.writeUInt16LE(0,4),c.writeUInt16LE(0,6),c.writeUInt16LE(t.length,8),c.writeUInt16LE(t.length,10),c.writeUInt32LE(a.length,12),c.writeUInt32LE(s,16),c.writeUInt16LE(0,20),Buffer.concat([...e,a,c])}function G5(){let t=new Date,e=t.getHours()<<11|t.getMinutes()<<5|Math.floor(t.getSeconds()/2),r=t.getFullYear()-1980<<9|t.getMonth()+1<<5|t.getDate();return{time:e,date:r}}var K5=new Uint32Array(256).map((t,e)=>{let r=e;for(let n=0;n<8;n++)r=r&1?3988292384^r>>>1:r>>>1;return r>>>0});function V5(t){let e=4294967295;for(let r of t)e=K5[(e^r)&255]^e>>>8;return(e^4294967295)>>>0}import{spawn as Z5}from"node:child_process";import{existsSync as eE}from"node:fs";import{dirname as tE,join as cu}from"node:path";import{fileURLToPath as J5}from"node:url";var X5=tE(J5(import.meta.url)),su,au;function rE(t,e,r){return new Promise(n=>{let o="",i="",s=!1,a=d=>{s||(s=!0,clearTimeout(u),n(d))},c=Z5(t,e,{windowsHide:!0}),u=setTimeout(()=>{c.kill("SIGKILL"),a({ok:!1,stdout:o,stderr:`${i}
805
805
  [hatch-pet] timed out after ${r}ms`,code:null})},r);u.unref?.(),c.stdout?.on("data",d=>{o+=d.toString()}),c.stderr?.on("data",d=>{i+=d.toString()}),c.on("error",d=>a({ok:!1,stdout:o,stderr:`${i}${d instanceof Error?d.message:String(d)}`,code:null})),c.on("close",d=>a({ok:d===0,stdout:o,stderr:i,code:d}))})}function Y5(){let t=[],e=process.env.QLOGICAGENT_PYTHON?.trim();return e&&t.push(e),t.push("python3","python","py"),t}async function Q5(t){let e=await rE(t,["-c","import PIL; import sys; sys.stdout.write('hatchpet-ok')"],1e4);return e.code===0&&e.stdout.includes("hatchpet-ok")}async function nE(){if(su!==void 0)return su;for(let t of Y5())if(await Q5(t))return su=t,t;return su=null,null}function oE(){if(au!==void 0)return au;let t=[],e=process.env.QLOGICAGENT_HATCHPET_DIR?.trim();e&&t.push(cu(e,"scripts"),e);let r=X5;for(let n=0;n<7;n++){t.push(cu(r,"vendor","hatch-pet","scripts"));let o=tE(r);if(o===r)break;r=o}for(let n of t)if(eE(cu(n,"compose_atlas.py")))return au=n,n;return au=null,null}async function iE(){return await nE()!==null&&oE()!==null}async function vb(t,e,r={}){let n=await nE();if(!n)throw new Error("Petdex generation requires Python with Pillow; none found (set QLOGICAGENT_PYTHON to a python that can `import PIL`)");let o=oE();if(!o)throw new Error("Vendored hatch-pet scripts not found (set QLOGICAGENT_HATCHPET_DIR)");let i=cu(o,t);if(!eE(i))throw new Error(`Unknown hatch-pet script: ${t}`);return rE(n,[i,...e],r.timeoutMs??12e4)}var sE="references/canonical-base.png",eJ="single centered full-body desktop pet character on a flat chroma-key background, readable at pet size",tJ="one horizontal animation row strip with evenly spaced full-body frames sharing a single consistent character identity",rJ="4096x1024",kb="#FF00FF",pE="110",mE="stable-slots",nJ="90",gE=["STRICT BACKGROUND: render one single continuous flat background of the same solid color filling the entire image edge to edge.","Do NOT draw any picture frame, framed panel, border, mat, outline, box, gallery frame, white or light margin, or divider around or between the poses.","The poses sit directly on the one seamless flat background, evenly spaced, with nothing separating them.","IDENTITY LOCK: every frame is the EXACT same character \u2014 identical species, body shape, proportions, colors, palette, face, and markings. Do not redesign, restyle, recolor, or resize the character between frames; only its pose changes.","Each pose is ONE connected solid silhouette at a consistent size. No detached parts, sweat drops, tears, dust, puffs, sparkles, speed lines, motion blur, floating effects, or drop shadows."].join(" "),oJ="Leftward gait is the framewise horizontal mirror of the approved rightward row, preserving frame order and timing semantics.",iJ=2,sJ=2;async function uu(t,e,r={}){if(!await iE())throw new Error("Petdex forge requires the vendored Hatch-Pet pipeline (Python with Pillow). Install Python + Pillow or set QLOGICAGENT_PYTHON to a python that can `import PIL`.");let n={billingQuantity:0,durationMs:0},o=[],i=[],s=HA(t),a=await NJ(),c=await DJ(t);try{await ei("prepare_pet_run.py",["--pet-name",t.name,"--display-name",t.name,"--description",t.description,"--pet-notes",t.prompt?.trim()||t.description,"--pet-id",jJ(t.id??t.name),"--output-dir",a,"--chroma-key","auto",...c.flatMap(I=>["--reference",I])]);let u=Y.join(a,"imagegen-jobs.json"),d=await bE(u),p=r.inspectImage,m=Math.max(1,r.candidates??iJ),g=[],f=kb,h;for(let I of d.jobs){if(!!(I.derivation_policy?.may_derive&&I.derivation_policy.may_derive_from)&&!p){await fE(a),o.push({id:`row-${I.id}`,kind:"row-strip",status:"complete",animationId:I.id,prompt:`derived: framewise-horizontal-mirror of ${I.derivation_policy.may_derive_from}`,inputImages:[],outputUrl:I.output_path});continue}let G=await le.readFile(Y.join(a,I.prompt_file),"utf-8"),x=I.retry_prompt_file?await le.readFile(Y.join(a,I.retry_prompt_file),"utf-8").catch(()=>{}):void 0;i.push(G);let z=I.kind==="base-pet",{mediaUrl:be,inputImages:H}=await hE({runDir:a,job:I,prompt:G,retryPrompt:x,generateImage:e,inspectImage:p,candidates:m,usage:n,upload:r.uploadReferenceImage,baseDataUrl:h});z&&(await le.copyFile(Y.join(a,I.output_path),Y.join(a,sE)),f=await OJ(Y.join(a,I.output_path)),h=await uJ(Y.join(a,sE))),I.status="complete",await le.writeFile(u,JSON.stringify(d,null,2),"utf-8"),o.push({id:z?"base-reference":`row-${I.id}`,kind:z?"reference":"row-strip",status:"complete",...z?{}:{animationId:I.id},prompt:G,inputImages:H,outputUrl:be}),z||g.push(I)}let y=Y.join(a,"decoded"),b=Y.join(a,"frames"),v=Y.join(a,"atlas.png"),w=Y.join(a,"atlas.webp");await ei("extract_strip_frames.py",["--decoded-dir",y,"--output-dir",b,"--chroma-key",f,"--key-threshold",pE,"--method",mE]),await pJ({runDir:a,decodedDir:y,framesDir:b,generatedRows:g,chromaHex:f,generateImage:e,inspectImage:p,candidates:m,baseDataUrl:h,usage:n,upload:r.uploadReferenceImage,productionJobs:o});let S=Y.join(a,"qa","contact-sheet.png");await vE(a,b,v,w,S),h&&await xJ({runDir:a,framesDir:b,atlasPng:v,atlasWebp:w,contactSheet:S,generatedRows:g,generateImage:e,inspectImage:p,candidates:m,usage:n,upload:r.uploadReferenceImage,baseDataUrl:h}),await Rb("render_animation_previews.py",["--frames-root",b,"--output-dir",Y.join(a,"qa","previews")]);let P=await le.readFile(w);return{...await yb({id:t.id,name:t.name,description:t.description,prompt:t.prompt,spritesheet:P,sourceKind:"forge"}),prompt:i.join(`
806
806
 
807
807
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qlogicagent",
3
- "version": "2.11.13",
3
+ "version": "2.11.14",
4
4
  "description": "XiaozhiClaw Agent CLI — subprocess architecture (JSON-RPC over stdio)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",