Skip to content

エージェント状態

ドキュメント作成中

一部の内容はまだ不完全な場合があります。

長いタスクを実行している Thread は現在の状態を持ちます。おかげで、一つずつ見に行かなくても、どのセッションが自分を必要としているか一目で分かります。見ていない Thread が終わったとき、あるいは判断を待ち始めたときには、短い音が鳴ります。

状態は working(作業中)、blocked(ユーザーの判断待ち)、idle(待機中)です。ThinkTerm が分類できないセッションには何も付きません。

検出は既定で無効です。設定から有効にします。

状態はどう決まるか

3 つの根拠を、契約として強い順に参照します。

1. THINKTERM_AGENT 変数。 プログラム自身が身元・セッション・状態を報告します。以下で説明する公開プロトコルであり、プログラムの画面がどう作り直されても生き残る唯一の手段です。

2. 画面ルール。 ペインの可視出力とターミナルタイトルに対して照合される TOML マニフェストです。同梱のルールは herdr プロジェクト由来です。

3. ネイティブのエスケープシーケンス。 OSC 9;4 の進捗報告と、タイトル先頭のスピナー表示です。機能を無効にしているときに使われるのもこれだけです。

重要な調停規則が 2 つあり、意図的に逆を向いています。

  • 生きているプロセスが「身元」で勝ちます。 マニフェストに一致する前景プロセスは「いま何が動いているか」の事実そのものです。報告された変数は過去からのメッセージであり、これを覆すことはありません。終了したプログラムが残した変数が、そのペインで次に動くものに誤ったラベルを付けることはない、ということです。
  • 画面が「状態」で勝ちます。 プログラムは「ユーザーが Esc を押した」「プロンプトが取り消された」という遷移をしばしば取りこぼし、そのどちらも画面上は明らかに待機状態で終わります。したがって一致した画面ルールは、報告された状態より優先されます。

画面から推定された遷移 — blocked からの離脱、および working から idle への変化 — にはおよそ 450 ミリ秒のデバウンスがかかります。描画途中のフレームが通知を再生してしまってはならないからです。プロトコルで報告された状態はデバウンスを通りません。明示的な報告は推測ではないからです。

自分のプログラムから状態を報告する

状態が変わるたび、ターミナルへエスケープシーケンスを 1 つ書き出します。

ESC ] 1337 ; SetUserVar=THINKTERM_AGENT=<base64(value)> BEL

シェルからなら:

sh
v="v1;agent=my-agent;state=working;session=$SESSION_ID;ts=$(date +%s)"
printf '\033]1337;SetUserVar=THINKTERM_AGENT=%s\007' \
  "$(printf %s "$v" | base64 | tr -d '\n')"

このシーケンスは何も描画せずカーソルも動かさないため、全画面出力の合間に挟んでも安全です。SSH 越しでも ThinkTerm のマルチプレクサドメイン上でも機能します。その pty を持つターミナルが解釈し、値は mux 接続をまたいで自動的に複製されます。

値の文法、バージョン 1

v1;agent=<id>;state=<working|idle|blocked>[;session=<id>][;pid=<n>][;ts=<unix-seconds>][;ended=1]
フィールド意味
v1文法バージョン。未知のメジャーバージョンは完全に無視されます
agent必須。短く安定した識別子
state必須。workingidleblocked のいずれか。それ以外は不明として扱われ、何も駆動しません
session自分のセッション ID。セッション復元のための予約。空でも構いません
pid前方互換のために受理されますが、現在は無視されます
ts送信時刻(unix 秒)。下記参照
ended=1セッションが終了した

未知のキーは無視されるため、古い読み手を壊さずに文法を拡張できます。

ts について。 6 時間より古い非 idle の報告は権威を失います — サーバー上のペインは、それに書き込んだセッションより長く生き残りうるからです。現在より 5 分以上先のタイムスタンプも同様に扱われ、進んだ時計によって報告が永久に新鮮なままになることを防ぎます。プロセスを観測しえないペイン(SSH、tmux、シリアル)では、この同じ 6 時間の窓が報告された身元も失効させます。プログラムが別れを告げずに落ちた可能性を示す、唯一残された信号だからです。承認プロンプトを一晩放置するなど、正当に長く非 idle でいられるセッションなら、現在の状態を定期的に再送してください。再送はこの窓をリセットします。idle の報告、および ts のない報告は無期限に信頼されます。

ended=1 について。 自分のプロセスがそのペインの前景リーダーである間、このフラグは無視されます。生きているプロセスは自らの別れの挨拶より優先されるからです。プロセスが終了すると、そのペインは分類の対象から外れます。

いつ何を送るか。 ターンの開始時に working、入力を受け付けられる状態になったら idle、答えを要するプロンプトを表示したその瞬間に blocked、そのプロンプトが解決したら再び適切な状態を — ユーザーが取り消したり中断したりした場合も含めて。これらの遷移をすべて自分で観測できる実装であれば、画面ルールは一切不要です。

画面ルールを上書きする

同梱のマニフェストは、自分のものを次のディレクトリへ置くことで置き換えられます。

~/.config/thinkterm/agent-detection/

どの同梱マニフェストを置き換えるかを決めるのはファイル内部id であり、ファイル名は無視されます。配置後、エージェントパネルからルールを再読み込みしてください。

ルールを書くうえで知っておくべきことが一つあります。タイトルと進捗の領域は、プログラムが実際に送出したものしか見えません。タイトルや進捗の報告が届くまで両者は空であり、ペインのプログラムが変わると消去されます。表示上のフォールバック — プロセス名から導かれたタブタイトル、進捗が無いという想定 — がルールに届くことはありません。そのため、タイトルに対する regex = ['\S'] のようなルールは、プログラムが一度も発言していないペインには一致しません。

関連