syntax = "v1" // M4 Studio: personas / plays / outbox / compose / own-posts / mentions type ( PersonaDraftPublic { Identity string `json:"identity"` Tone string `json:"tone"` Audience string `json:"audience"` Hooks string `json:"hooks"` LanguageFingerprint string `json:"language_fingerprint"` Rhythm string `json:"rhythm"` Punctuation string `json:"punctuation"` ContentPatterns string `json:"content_patterns"` KnowledgeTranslation string `json:"knowledge_translation"` CtaStyle string `json:"cta_style"` Examples string `json:"examples"` Avoid string `json:"avoid"` } StyleDimensionPublic { Summary string `json:"summary"` Evidence []string `json:"evidence,optional"` } PersonaStylePublic { Draft PersonaDraftPublic `json:"draft"` DraftText string `json:"draft_text"` Source string `json:"source"` BenchmarkUsername string `json:"benchmark_username,optional"` SourceLabel string `json:"source_label,optional"` SampleCount int `json:"sample_count"` AnalyzedAt int64 `json:"analyzed_at,optional"` SamplePreviews []string `json:"sample_previews,optional"` // 8D:d1Tone…d8Risk → { summary, evidence } Dimensions map[string]StyleDimensionPublic `json:"dimensions,optional"` } PersonaGuardPublic { Avoid []string `json:"avoid"` MaxChars int `json:"max_chars"` BanAiTone bool `json:"ban_ai_tone"` } PersonaPublic { Id string `json:"id"` Name string `json:"name"` Brief string `json:"brief"` Status string `json:"status"` Style PersonaStylePublic `json:"style"` Guard PersonaGuardPublic `json:"guard"` Voice string `json:"voice,optional"` Notes string `json:"notes,optional"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` } PersonaListData { List []PersonaPublic `json:"list"` } PersonaSaveReq { Id string `json:"id,optional"` Name string `json:"name"` Brief string `json:"brief,optional"` Status string `json:"status,optional"` Style PersonaStylePublic `json:"style,optional"` Guard PersonaGuardPublic `json:"guard,optional"` Voice string `json:"voice,optional"` Notes string `json:"notes,optional"` } PersonaIdPath { Id string `path:"id"` } PersonaActiveData { Id string `json:"id"` } PersonaSetActiveReq { Id string `json:"id"` } PersonaAnalyzeTextReq { Id string `path:"id"` RawText string `json:"raw_text"` SourceLabel string `json:"source_label,optional"` } PersonaAnalyzeAccountReq { Id string `path:"id"` Username string `json:"username"` } // --- Plays --- ExternalTargetPublic { Url string `json:"url"` RawUrl string `json:"raw_url,optional"` Shortcode string `json:"shortcode,optional"` AuthorUsername string `json:"author_username,optional"` TextPreview string `json:"text_preview,optional"` MediaId string `json:"media_id,optional"` ResolvedAt int64 `json:"resolved_at,optional"` } PlayStepPublic { Id string `json:"id"` SortOrder int `json:"sort_order"` Kind string `json:"kind"` AccountId string `json:"account_id"` Text string `json:"text"` DelayFromPreviousSec int `json:"delay_from_previous_sec"` PersonaId string `json:"persona_id,optional"` BrandId string `json:"brand_id,optional"` ImageUrls []string `json:"image_urls,optional"` } PlayPublic { Id string `json:"id"` Title string `json:"title"` Topic string `json:"topic"` Status string `json:"status"` LeadAccountId string `json:"lead_account_id"` CastAccountIds []string `json:"cast_account_ids"` TargetOwnPostId string `json:"target_own_post_id,optional"` TargetExternal ExternalTargetPublic `json:"target_external,optional"` Steps []PlayStepPublic `json:"steps"` ScheduleStartAt int64 `json:"schedule_start_at"` IntervalMinutes int `json:"interval_minutes,optional"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` } PlayListData { List []PlayPublic `json:"list"` } PlaySaveReq { Id string `json:"id,optional"` Title string `json:"title"` Topic string `json:"topic,optional"` Status string `json:"status,optional"` LeadAccountId string `json:"lead_account_id"` CastAccountIds []string `json:"cast_account_ids,optional"` TargetOwnPostId string `json:"target_own_post_id,optional"` TargetExternal ExternalTargetPublic `json:"target_external,optional"` Steps []PlayStepPublic `json:"steps"` ScheduleStartAt int64 `json:"schedule_start_at,optional"` IntervalMinutes int `json:"interval_minutes,optional"` } PlayIdPath { Id string `path:"id"` } PlayByPostReq { OwnPostId string `form:"own_post_id"` } PlayByExternalReq { Url string `form:"url"` } PlayResolveReq { Url string `json:"url"` } // AI 產劇本一步(真 LLM;互回/串場共用) PlayGenerateStepReq { PersonaId string `json:"persona_id,optional"` Context string `json:"context"` // 主貼/上一則/目標文 Topic string `json:"topic,optional"` SpeakerLabel string `json:"speaker_label,optional"` IsLead bool `json:"is_lead,optional"` // mode: reply(預設)| root(串場主貼) Mode string `json:"mode,optional"` } PlayGenerateStepData { Text string `json:"text"` } // 一次產完整劇本(背景 job) PlayGenerateScriptData { JobId string `json:"job_id"` Async bool `json:"async"` } // --- Outbox --- OutboxStepPublic { Id string `json:"id"` StepId string `json:"step_id"` SortOrder int `json:"sort_order"` Kind string `json:"kind"` AccountId string `json:"account_id"` Text string `json:"text"` Status string `json:"status"` Error string `json:"error,optional"` ScheduledAt int64 `json:"scheduled_at,optional"` PublishedAt int64 `json:"published_at,optional"` } OutboxPublic { Id string `json:"id"` PlayId string `json:"play_id"` Title string `json:"title"` Status string `json:"status"` Steps []OutboxStepPublic `json:"steps"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` } OutboxListData { List []OutboxPublic `json:"list"` } OutboxIdPath { Id string `path:"id"` } OutboxRetryPath { Id string `path:"id"` StepId string `path:"stepId"` } // --- Compose --- ComposeMimicReq { SourceText string `json:"source_text"` PersonaId string `json:"persona_id,optional"` // 可選:從「我的貼文」結構分析帶過來的備註(鉤子/結構/可複製點) StructureNotes string `json:"structure_notes,optional"` } // 仿寫改背景 Job:立刻回 job_id;完成後從 job.payload.result_text 取文 ComposeMimicData { // 相容:同步路徑才有;Job 路徑為空 Text string `json:"text,optional"` JobId string `json:"job_id,optional"` Async bool `json:"async,optional"` } // 人設試產:依指紋真 LLM 產主貼 + 回文(可帶新聞話題) ComposePersonaPreviewReq { PersonaId string `json:"persona_id"` // 手動話題;空則嘗試上網取新聞靈感 Topic string `json:"topic,optional"` // 預設 true:無 topic 時抓即時新聞標題當靈感 UseNews bool `json:"use_news,optional"` } ComposePersonaPreviewData { Topic string `json:"topic"` TopicSource string `json:"topic_source"` // news | manual | fallback PostText string `json:"post_text"` ReplyText string `json:"reply_text"` Notes string `json:"notes,optional"` } ComposeViralReq { Text string `json:"text"` } ViralAnalysisPublic { Hooks string `json:"hooks"` Structure string `json:"structure"` Emotion string `json:"emotion"` Summary string `json:"summary"` Cta string `json:"cta,optional"` Copyable string `json:"copyable,optional"` Risks string `json:"risks,optional"` } ComposePublishReq { AccountId string `json:"account_id"` Text string `json:"text"` Title string `json:"title,optional"` ImageUrls []string `json:"image_urls,optional"` ScheduleStartAt int64 `json:"schedule_start_at,optional"` // Threads 話題標籤(topic_tag,1~50 字,可不加 #) TopicTag string `json:"topic_tag,optional"` } // --- Own posts --- OwnPostReplyPublic { Id string `json:"id"` Username string `json:"username"` Text string `json:"text"` CreatedAt int64 `json:"created_at"` LikeCount int `json:"like_count,optional"` ReplyStatus string `json:"reply_status,optional"` RepliedBy string `json:"replied_by,optional"` RepliedAt int64 `json:"replied_at,optional"` ParentReplyId string `json:"parent_reply_id,optional"` IsMine bool `json:"is_mine,optional"` } OwnPostPublic { Id string `json:"id"` AccountId string `json:"account_id"` MediaId string `json:"media_id,optional"` Text string `json:"text"` MediaType string `json:"media_type"` MediaUrl string `json:"media_url,optional"` ThumbnailUrl string `json:"thumbnail_url,optional"` Permalink string `json:"permalink,optional"` Shortcode string `json:"shortcode,optional"` TopicTag string `json:"topic_tag,optional"` LikeCount int `json:"like_count"` ReplyCount int `json:"reply_count"` RepostCount int `json:"repost_count"` QuoteCount int `json:"quote_count"` ViewCount int `json:"view_count"` ShareCount int `json:"share_count"` InsightsStatus string `json:"insights_status,optional"` FormulaSummary string `json:"formula_summary,optional"` Insight string `json:"insight,optional"` FormulaDetail string `json:"formula_detail,optional"` Replies []OwnPostReplyPublic `json:"replies"` PublishedAt int64 `json:"published_at"` } OwnPostListData { List []OwnPostPublic `json:"list"` } OwnPostListReq { AccountId string `form:"account_id,optional"` } OwnPostSyncReq { AccountId string `json:"account_id"` } OwnPostLastSyncedData { LastSyncedAt int64 `json:"last_synced_at"` } OwnPostGenerateReplyReq { PostId string `json:"post_id"` ReplyId string `json:"reply_id,optional"` PersonaId string `json:"persona_id,optional"` } OwnPostGenerateReplyData { Text string `json:"text"` } OwnPostSendReplyReq { PostId string `json:"post_id"` ReplyId string `json:"reply_id,optional"` Text string `json:"text"` AccountId string `json:"account_id,optional"` ImageUrls []string `json:"image_urls,optional"` } OwnPostAnalyzeReq { PostId string `json:"post_id"` } // 點開貼文後再載留言(避免 sync 一次打爆 conversation API) OwnPostLoadRepliesReq { PostId string `json:"post_id"` } // --- Mentions --- MentionPublic { Id string `json:"id"` AccountId string `json:"account_id"` MediaId string `json:"media_id,optional"` FromUsername string `json:"from_username"` Text string `json:"text"` ContextSnippet string `json:"context_snippet"` Permalink string `json:"permalink,optional"` Status string `json:"status"` DraftText string `json:"draft_text,optional"` CreatedAt int64 `json:"created_at"` } MentionListData { List []MentionPublic `json:"list"` } MentionListReq { AccountId string `form:"account_id,optional"` } MentionSyncReq { AccountId string `json:"account_id"` } MentionIdPath { Id string `path:"id"` } MentionGenerateReq { Id string `path:"id"` PersonaId string `json:"persona_id,optional"` } MentionMarkRepliedReq { Id string `path:"id"` Text string `json:"text,optional"` ImageUrls []string `json:"image_urls,optional"` } ) @server ( jwt: Auth group: personas prefix: /api/v1/personas middleware: AuthJWT ) service gateway { @handler ListPersonas get / returns (PersonaListData) @handler GetActivePersona get /active returns (PersonaActiveData) @handler SetActivePersona post /active (PersonaSetActiveReq) returns (PersonaActiveData) @handler GetPersona get /:id (PersonaIdPath) returns (PersonaPublic) @handler SavePersona post / (PersonaSaveReq) returns (PersonaPublic) @handler RemovePersona delete /:id (PersonaIdPath) returns (OkData) @handler AnalyzePersonaText post /:id/analyze-text (PersonaAnalyzeTextReq) returns (PersonaPublic) @handler AnalyzePersonaAccount post /:id/analyze-account (PersonaAnalyzeAccountReq) returns (PersonaPublic) } @server ( jwt: Auth group: plays prefix: /api/v1/plays middleware: AuthJWT ) service gateway { @handler ListPlays get / returns (PlayListData) @handler ListPlaysByPost get /by-post (PlayByPostReq) returns (PlayListData) @handler ListPlaysByExternal get /by-external (PlayByExternalReq) returns (PlayListData) @handler ResolveExternalLink post /resolve-external (PlayResolveReq) returns (ExternalTargetPublic) @handler GetPlay get /:id (PlayIdPath) returns (PlayPublic) @handler SavePlay post / (PlaySaveReq) returns (PlayPublic) @handler RemovePlay delete /:id (PlayIdPath) returns (OkData) @handler SubmitPlay post /:id/submit (PlayIdPath) returns (OutboxPublic) @handler GeneratePlayStep post /generate-step (PlayGenerateStepReq) returns (PlayGenerateStepData) @handler GeneratePlayScript post /:id/generate-script (PlayIdPath) returns (PlayGenerateScriptData) } @server ( jwt: Auth group: outbox prefix: /api/v1/outbox middleware: AuthJWT ) service gateway { @handler ListOutbox get / returns (OutboxListData) @handler GetOutbox get /:id (OutboxIdPath) returns (OutboxPublic) @handler RemoveOutbox delete /:id (OutboxIdPath) returns (OkData) @handler RetryOutboxStep post /:id/steps/:stepId/retry (OutboxRetryPath) returns (OutboxPublic) } @server ( jwt: Auth group: compose prefix: /api/v1/compose middleware: AuthJWT ) service gateway { @handler ComposeMimic post /mimic (ComposeMimicReq) returns (ComposeMimicData) @handler ComposePersonaPreview post /persona-preview (ComposePersonaPreviewReq) returns (ComposePersonaPreviewData) @handler ComposeAnalyzeViral post /analyze-viral (ComposeViralReq) returns (ViralAnalysisPublic) @handler ComposePublishSingle post /publish-single (ComposePublishReq) returns (OutboxPublic) } @server ( jwt: Auth group: ownposts prefix: /api/v1/own-posts middleware: AuthJWT ) service gateway { @handler ListOwnPosts get / (OwnPostListReq) returns (OwnPostListData) @handler OwnPostsLastSynced get /last-synced-at returns (OwnPostLastSyncedData) @handler SyncOwnPosts post /sync (OwnPostSyncReq) returns (OwnPostListData) @handler OwnPostGenerateReply post /generate-reply (OwnPostGenerateReplyReq) returns (OwnPostGenerateReplyData) @handler OwnPostSendReply post /send-reply (OwnPostSendReplyReq) returns (OwnPostPublic) @handler OwnPostAnalyze post /analyze (OwnPostAnalyzeReq) returns (OwnPostPublic) @handler OwnPostLoadReplies post /load-replies (OwnPostLoadRepliesReq) returns (OwnPostPublic) } @server ( jwt: Auth group: mentions prefix: /api/v1/mentions middleware: AuthJWT ) service gateway { @handler ListMentions get / (MentionListReq) returns (MentionListData) @handler SyncMentions post /sync (MentionSyncReq) returns (MentionListData) @handler MentionGenerateReply post /:id/generate-reply (MentionGenerateReq) returns (MentionPublic) @handler MentionMarkReplied post /:id/mark-replied (MentionMarkRepliedReq) returns (MentionPublic) @handler MentionSkip post /:id/skip (MentionIdPath) returns (MentionPublic) }