Appearance
EP-029 paid_article_ai_chat_send(有料記事 AI 相談送信)
← EP-一覧 · EP-030 履歴消去 · 設計概要
概要
有料記事(月刊まっく / paid_article)の編集画面から、考察欄(target_field)を 1 つ以上指定して AI に相談する。ハンドラは返信文と欄別下書きを JSON で返す。考察欄の post meta へは自動保存しない(画面上のエディタ末尾への追記はフロントが paidArticleCommentEditorAppendContent で行う)。会話履歴は db_paid_article_ai_chat_message に記事単位(post_id)で保存する。
LLM のプロバイダ・モデル・API キー・欄別指針は ADM-028(PaidArticleAiOptions)を再利用する。システムプロンプトは ADM-028 の有料記事 AI 相談用 option(mycustom_paid_article_ai_chat_system_prompt)を参照する。空のときは PaidArticleAiChatServiceCopy::DEFAULT_SYSTEM_PROMPT にフォールバックする(一括生成用システムプロンプト mycustom_paid_article_ai_system_prompt は使わない)。ツールは 有料記事 AI データ取得ツール の管理画面カタログ(PaidArticleAiToolDispatcherInterface / AiToolDispatcher)のみを使う。日別記事専用 Tool カタログは使わない。
POST パラメータ
| フィールド | 必須 | 型・制約 | 説明 |
|---|---|---|---|
action | ○ | 文字列 | paid_article_ai_chat_send |
_wpnonce | ○ | 文字列 | paid_article_ai_chat で発行した nonce。nonce でも受け付ける |
post_id | ○ | 正整数 | 対象の paid_article 投稿 ID |
message | ○ | 非空文字列 | ユーザーの相談文 |
halls | ○ | 文字列配列、または JSON 配列文字列 | 日別記事対象ホール(HallEnum::get_available_halls_for_daily_article())を 1 つ以上。空は拒否(全日別扱いしない) |
target_fields | ○ | 文字列配列、または JSON 配列文字列 | PaidArticleAiTargetField 許可リストの target_field を 1 つ以上 |
field_contents | − | JSON オブジェクト文字列(target_field → HTML) | 画面上の現行考察本文。省略時は空マップ |
成功時 data
| 論理名 | 物理名 | 型 | 説明 |
|---|---|---|---|
| 返信文 | reply | string | チャットに表示する説明文 |
| 下書き | drafts | object | 選択された target_field キー → 段落 HTML(空オブジェクト可) |
| 履歴 | messages | array | 保存後の全メッセージ(下記) |
messages[]
| 論理名 | 物理名 | 型 | 説明 |
|---|---|---|---|
| ID | id | number | 行 ID |
| 役割 | role | string | user / assistant |
| 本文 | body | string | ユーザー文または reply |
| 対象欄 | target_fields | string[] | 送信時点の選択 target_field |
| 下書き | drafts | object|null | assistant のみ。user は null |
| 作成日時 | created_at | string | MySQL datetime |
失敗・ブロック(success: false)
| 条件 | message の内容 |
|---|---|
| AJAX コンテキスト外・nonce 不正 | Messages::AUTH_FAILED |
post_id が不正、または投稿タイプが paid_article でない | PaidArticleAiChatAjaxCopy::INVALID_POST |
edit_post 権限なし | Messages::PERMISSION_DENIED |
message が空 | PaidArticleAiChatAjaxCopy::MESSAGE_REQUIRED |
halls が空 | PaidArticleAiChatAjaxCopy::HALLS_REQUIRED |
halls に許可外のみが含まれる | PaidArticleAiChatAjaxCopy::HALLS_INVALID |
target_fields が空 | PaidArticleAiChatAjaxCopy::TARGET_FIELDS_REQUIRED |
target_fields に許可外のみが含まれる | PaidArticleAiChatAjaxCopy::TARGET_FIELDS_INVALID |
| Claude / Gemini 両方の API キー未設定(Service 例外) | PaidArticleAiChatServiceCopy::API_KEY_MISSING または GEMINI_API_KEY_MISSING(保存済みプロバイダ側の文言。詳細は error_log にも記録) |
| 対象月(YYYY-MM)未設定(Service 例外) | PaidArticleAiChatServiceCopy::TARGET_MONTH_MISSING |
| HTTP 429 / quota(Service 例外) | CLAUDE_RATE_LIMITED / GEMINI_RATE_LIMITED(値は Messages::AI_LLM_*)(応答から取れた待ち秒が 1〜120 なら「(約 N 秒後)」を付与。生レスポンスは出さない) |
| HTTP 401 / 403(Service 例外) | CLAUDE_AUTH_FAILED / GEMINI_AUTH_FAILED(値は Messages::AI_LLM_*) |
| HTTP タイムアウト・経過上限(Service 例外) | CLAUDE_TIMEOUT / GEMINI_TIMEOUT(値は Messages::AI_LLM_*) |
| 接続失敗(WP_Error、タイムアウト以外)(Service 例外) | CLAUDE_CONNECTION_FAILED / GEMINI_CONNECTION_FAILED(値は Messages::AI_LLM_*) |
| その他の HTTP 非 200(Service 例外) | CLAUDE_HTTP_ERROR / GEMINI_HTTP_ERROR(値は Messages::AI_LLM_*)(ステータスコードのみ。例: …(HTTP 500)。) |
| 応答切れ・履歴保存失敗・形式不正・ループ上限など | 対応する PaidArticleAiChatServiceCopy の固定文言(詳細は error_log) |
| 上記以外の未知の Service 例外 | PaidArticleAiChatAjaxCopy::NOTICE_GENERIC_ERROR(詳細は error_log) |
権限
- ログイン必須(
wp_ajax_のみ。noprivは付けない) - capability:
edit_post(対象post_id)
関連
- 履歴消去: EP-030
- 一括生成: EP-021 / EP-022
- LLM キー・プロバイダ: ADM-028
- Tool 契約: paid-article-ai-tools-design.md
- 履歴テーブル:
db_paid_article_ai_chat_message