maestro/docs/tools/xsearch.md
oss-sync 77ee3bc426
Some checks are pending
CI / build-and-test (push) Waiting to run
sync: update from private repo (ddadfd71)
2026-07-08 23:35:00 +00:00

207 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# X / Twitter ツールXSearch / XUserPosts / XPostDetail / XTimeline / XFetchCardMedia
twitter-cli を内部で呼び出して X (旧 Twitter) のデータを取得する read-only ツール群。
## 認証設定(必須)
X ツールは `tools.x_cli_command` で指定した外部 CLI を呼び出す。どちらの CLI でも
Cookie 認証が必要。Settings UI の "Tools" セクションで設定:
- **X Auth Token**: ブラウザの `auth_token` cookie の値
- **X ct0**: ブラウザの `ct0` cookie の値
任意:
- **X Proxy**: `http://proxy:port` 形式
- **X Chrome Profile**: cookie 抽出元のプロファイルパス
設定が無いと「認証エラー」で失敗する。
## バックエンド CLIx-adapter / twitter-cli
2026 年に X.com が Web クライアントを新バンドルx-web / `sign.o*.js`)へ移行し、
従来の twitter-cli が依存する `x_client_transaction` の transaction-id 生成が壊れた
`Failed to init ClientTransaction` → 全リクエストが HTTP 404 → `exited with code 1`)。
復旧のため、新バンドルに追従している **twscrape**transaction-id 生成 `XClIdGen` +
検索/ユーザー投稿/詳細)と **twikit**(ホームタイムラインの GraphQL endpoint 定義)を
使う twitter-cli 互換アダプタ `x-adapter` を導入した。x.ts は無改修で、`x_cli_command`
を切り替えるだけ。
セットアップ:
```bash
./scripts/install-x-adapter.sh # 隔離 venv に twscrape/twikit を入れ ~/.local/bin/x-adapter を作る
# config.yaml:
# tools:
# x_cli_command: [x-adapter]
```
X が再び取得を壊した場合(おおむね 2〜4 週ごと)の修復レバー:
```bash
./scripts/install-x-adapter.sh --upgrade # twscrape / twikit を最新へ
```
`x-adapter` のサブコマンドは twitter-cli と同じ(`search` / `user-posts` / `tweet` /
`feed`)で、同じ YAML を stdout に吐く。実装は `scripts/x-adapter/x_adapter.py`
pure マッピング関数の単体テストは `scripts/x-adapter/test_x_adapter.py`
## XSearch — 投稿検索
```js
XSearch({
query: "ローカル LLM",
limit: 20,
tab: "Latest", // Top / Latest / Photos / Videos
full_text: true, // 長文の省略を避ける
compact: false, // true で token 節約
output_path: "x/local-llm.txt" // 任意: output/x/ 配下に保存
})
```
## XUserPosts — ユーザー投稿一覧
```js
XUserPosts({
username: "elonmusk", // @ なし
limit: 50,
full_text: true
})
```
## XTimeline — ホームタイムライン(ログイン中アカウント)
```js
XTimeline({
tab: "for_you", // for_you (デフォルト) / following
limit: 20, // デフォルト 20, 最大 50
full_text: true,
compact: false,
output_path: "x/timeline.txt" // 任意
})
```
設定済みの `auth_token` / `ct0` cookie に紐づくアカウントの**ホームタイムライン**を返す。
`tab: "for_you"`(おすすめ)と `tab: "following"`(フォロー中)を切り替えられる。
内部的には `twitter feed [-t following]` を呼ぶ。検索ではなく「ログイン中ユーザーが
普段見るフィード」を取得したいときに使う。出力・メディア DL の扱いは XSearch と共通。
## XPostDetail — 投稿の詳細+リプライ
```js
XPostDetail({
tweet: "https://x.com/.../status/1234567890",
// tweet ID だけでも、長文記事 URL (https://x.com/.../article/1234567890) でも可
})
```
返り値にはリプライツリーが含まれる。議論の流れを追いたいときに使う。
### X 長文記事X Articles
対象が長文記事ポストの場合、`text` は記事への t.co リンク 1 本だけになる。
記事の中身は `article` キーに入る:
```yaml
data:
- id: '1234567890'
text: https://t.co/xxxx # 記事ポストの本文はリンクのみ
article:
title: 記事タイトル
previewText: 冒頭のプレビュー文
plainText: 記事本文の全文(プレーンテキスト)
publishedAtISO: '2026-07-02T00:04:51+00:00'
coverImageUrl: https://pbs.twimg.com/media/XXXX.jpg
```
- `plainText` はデフォルトで 12,000 文字で切り詰め、`plainTextTruncated: true` が付く。
全文が必要なら `full_text: true` を渡す
- **記事内の埋め込み画像・動画は `media[]` に合流する**(先頭 20 件まで)。通常の
投稿メディアと同じく自動ダウンロードされ `localPath` が付くので、そのまま
ReadImage / AnnotateImage に渡せる。動画の扱いは `tools.x_download_video` に従う
- カバー画像(`coverImageUrl`)は自動ダウンロード対象外。必要なら DownloadFile に渡す
- 記事ページ(`x.com/{user}/article/{id}`)を WebFetch で読むことはできない
(ログイン壁で失敗する)。記事は必ずこのツールで取得する
## 出力フォーマット
- デフォルト: 構造化テキスト(投稿者・本文・いいね数等)
- `compact: true`: token 節約版(簡潔表記)
- `output_path` 指定時: ファイルにも保存(パスは output/x/ 相対)
## メディアの自動ダウンロード
X / Twitter ツールは取得した投稿に紐付く画像 / 動画 (poster) を**自動的に
ワークスペースにダウンロード**して `localPath` を返す。LLM はそのパスを
ReadImage / AnnotateImage / Bash 等に直接渡せる。
```yaml
# 出力例 (XPostDetail / XUserPosts / XSearch 共通)
data:
- id: '1234567890'
media:
- type: photo
url: https://pbs.twimg.com/media/AAA.jpg?name=large
localPath: logs/x-media/1234567890/0.jpg # ← 自動付与
bytes: 384172
```
保存先は `{workspace}/logs/x-media/{tweet_id}/{N}.{ext}`。同じ tweet を再取得しても
既存ファイルは上書きしない (idempotent)。
### 動画の扱い
設定で挙動を切り替える (`tools.x_download_video`):
| モード | 挙動 |
| --- | --- |
| `thumbnail` (default) | poster (静止画 jpg) のみ DL。内容把握に十分で軽量 |
| `full` | variants から最高 bitrate の mp4 を DL。サイズ大なので明示的に有効化 |
| `never` | 動画系は完全にスキップ |
### サイズ上限
`tools.x_media_max_mb` (default 25) を超えるメディアはスキップしてログに記録。
content-length ヘッダで判定し、ボディが膨張した場合も DL 後に再度チェックする。
### 完全に無効化したいとき
```yaml
tools:
x_download_media: never # 全 X ツールでメディア DL を無効化
```
## XFetchCardMedia — quiz / poll / link card の画像取得
XSearch / XPostDetail で `media: []` が返るが、tweet が quiz / poll / link card
形式で card 画像があるはずだと LLM が判断した時のみ呼ぶ専用 tool。
```js
XFetchCardMedia({
tweet: "https://x.com/someuser/status/1234567890"
// または tweet: "1234567890" (この場合 screen_name 任意)
})
```
挙動:
- Playwright で X.com を開き、GraphQL response + 対象 article の DOM から
`pbs.twimg.com/(media|card_img)/...` URL を抽出
- 抽出した URL を `logs/x-media/{tweetId}/` に DL
- 成功すれば保存パスを返す
- 0 件なら "no card media found" を返す (LLM は plain text と判断)
**重要**: 1 回の呼び出しに Playwright 起動 + ページ遷移で約 14 秒かかる。
**XSearch / XUserPosts / XPostDetail からは自動発動しない**。LLM が以下の
状況でのみ明示的に呼ぶこと:
- XPostDetail が `media: []` を返した
- かつ tweet 本文が画像クイズ / 投票 / link preview を示唆する
- かつその画像の中身が次の判断に必要
text-only tweet には呼ばないこと (14 秒を無駄にする)。
## トラブルシューティング
- **認証エラー**: cookie の有効期限切れ。ブラウザで取得し直して Settings に再投入
- **rate limit**: しばらく待ってから再実行。検索回数を絞る
- **twitter-cli not found**: `scripts/install-twitter-cli.sh` で導入が必要
- **`media: []` のままで画像が取れない**: card / quiz 形式の投稿は X API 自体に
メディアが乗らない。XFetchCardMedia を呼んで Playwright 経由で取得する