mcpField
E
ef-agent-panel

ef-agent-panel

github.com/editframe開発1973 回インストール2 週間前に更新
リポジトリ

ef-agent-panel について

EFAgentPanel 向けの開発スキルです。GUI のコンポジション編集を収集し、コピー可能なコーディングエージェント向けプロンプトにまとめます。イベント処理、重複排除、インスペクターのスキーマ、テストを扱います。

主な機能

  1. 01`ef-edit` コンポジションイベントの取得
  2. 02要素とプロパティ単位で編集を重複排除
  3. 03セレクター単位で編集をグループ化
  4. 04コピー可能なコーディングエージェント向けプロンプトを生成
  5. 05イベントとスキーマのテスト方法を説明

活用シーン

  1. 01GUI のコンポジション変更をエージェント向けプロンプトに変換
  2. 02Shadow DOM コンポーネント間の編集イベントを追跡
  3. 03編集イベントのヘルパーとブラウザー動作をテスト

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/editframe/skills --skill ef-agent-panel

インストール後、Claude Code で/ef-agent-panelを入力して読み込まれたか確認します。

詳細

エージェントパネル

EFAgentPanel は、GUI で意味のある編集操作が行われるたびにディスパッチされる ef-edit CustomEvents を取得し、キー付きレジストリを使って要素とプロパティの組み合わせごとに重複を排除します。さらに、セレクターごとにグループ化し、コピー可能なコーディングエージェント向けプロンプトを表示します。

イベントパイプライン

GUI interaction (canvas drag, inspector change, trim drag, loop toggle)
  └─ component.dispatchEvent(createEditCustomEvent(editEvent))
       └─ [bubbles: true, composed: true]
            └─ EFWorkbench listener → agentPanel.addEdit(event)
                 └─ Map<editChangeKey, EditEvent> registry (deduplicates)
                      └─ groupEditsBySelector() → buildAgentPrompt() → copy button

EFWorkbench は、自身に addEventListener('ef-edit', ...) を登録します。ef-edit はバブルアップし、composed であるため、特別なルーティングなしで、どのスロット内のコンポーネントからでも(タイムライン、階層、キャンバスなど)ディスパッチできます。

主要な型(editEvents.ts)

// EditEvent — what the panel accumulates
interface EditEvent {
  operation: EditOperation;
  description: string;   // human sentence
  selector: string;      // CSS path from composition root
  elementHtml: string;   // cleaned outerHTML snippet
  timestamp: number;
}

// Operation union — extend here when adding new interaction types
type EditOperation =
  | { type: "element-property-changed"; elementId; tagName; label; property; oldValue; newValue }
  | { type: "element-moved";   elementId; tagName; label; fromX; fromY; toX; toY }
  | { type: "element-resized"; elementId; tagName; label; x; y; width; height }
  | { type: "element-rotated"; elementId; tagName; label; rotation }

レジストリキーの形式 — 重複排除の方法を決定します。

  • プロパティ変更:selector::prop:propName
  • 移動/サイズ変更/回転:selector::move、selector::resize、selector::rotate

パターン:新しい ef-edit ディスパッチ箇所を追加する

import {
  createEditCustomEvent, buildSelectorPath, getElementHtml,
  buildEditDescription, type ElementPropertyChangedOperation,
} from "../../editEvents.js";

const oldValue = element.someProperty;
element.someProperty = newValue;

const op: ElementPropertyChangedOperation = {
  type: "element-property-changed",
  elementId: el.id,
  tagName: el.tagName.toLowerCase(),
  label: el.textContent?.trim().slice(0, 30) || el.id || el.tagName.toLowerCase(),
  property: "attr-name",   // attribute name as used in HTML source
  oldValue,
  newValue,
};
this.dispatchEvent(createEditCustomEvent({
  operation: op,
  description: buildEditDescription(op),
  selector: buildSelectorPath(el),
  elementHtml: getElementHtml(el),
  timestamp: Date.now(),
}));

EFInspector.ts の buildPropertyEditEvent(element, property, oldValue, newValue) は、単純なプロパティ編集に使う短縮形です。

現在のディスパッチ箇所を確認する

# Every call site that produces an ef-edit event
rg 'createEditCustomEvent' elements/packages/elements/src/

# Track subclasses that override render() — each must bind @trim-change-end
rg 'override render' elements/packages/elements/src/gui/timeline/tracks/

# Registered element schemas
rg 'SCHEMA_REGISTRY' elements/packages/elements/src/gui/elementPropertySchema.ts

配線されていないもの(意図的)

再生コントロール(再生/一時停止/シーク)、パンとズーム/ズームレベル、ツールバーの設定は表示専用の状態であり、ef-edit イベントを生成すべきではありません。階層の並べ替え(EFHierarchy の hierarchy-reorder)には、新しい ElementReorderedOperation 型が必要ですが、まだ実装されていません。

Shadow DOM のイベントルーティングに関する注意点

trim-change-end は EFTrimHandles から composed: true でバブルアップします。TrackItem.render() は ef-trim-handles 要素に @trim-change-end をバインドします。EFVideoTrack は render() を全面的にオーバーライドし、独自の ef-trim-handles バインディングを提供します。今後、render() をオーバーライドして ef-trim-handles を含めるトラックサブクラスでは、@trim-change と @trim-change-end の両方をバインドする必要があります。render() をオーバーライドすると、基底クラス TrackItem.render() のハンドラーは継承されません。

要素プロパティのスキーマ(elementPropertySchema.ts)

静的ディスクリプターがインスペクター UI を制御します。新しい要素型は、末尾の SCHEMA_REGISTRY に登録します。次のファクトリー関数を使用してください。

  • timeDescriptor(attr, label, opts) — 時間値(${ms}ms 属性として保存)
  • enumDescriptor(attr, label, options, condition?)
  • boolDescriptor(attr, label, condition?)
  • numberDescriptor(attr, label, opts)
  • stringDescriptor(attr, label)

レジストリー項目がない要素は、インスペクターに表示されません。テストのパターンは elementPropertySchema.test.ts を確認してください。

ef-edit イベントのテスト

ユニットテスト(Node/vitest):editEvents.ts のヘルパー(editChangeKey、rollUpEdits、groupEditsBySelector、buildAgentPrompt)に使用します。

ブラウザーテスト(Chromium/vitest):DOM イベントまたは Shadow DOM が関係するテストには必須です。

トリムの ef-edit をテストする場合は、ef-trim-handles のホスト要素で trim-change-end を直接ディスパッチしてください。テスト環境ではポインターキャプチャの動作が不安定なため、Shadow DOM のレイヤーを通してポインターイベント全体をシミュレートしようとしないでください。

const trimHandles = track.shadowRoot?.querySelector("ef-trim-handles");
trimHandles?.dispatchEvent(new CustomEvent("trim-change-end", {
  detail: { elementId: video.id, type: "start" },
  bubbles: true, composed: true,
}));

ループの ef-edit をテストする場合は、ループボタンをクリックします:shadowRoot.querySelector("button[title='Loop']").click()。

document レベルでリッスンしてください。ef-edit は bubbles: true, composed: true であるため、どのコンポーネントからでも document まで伝播します。

コメント