owner-clone-ai-mcp 1.83.0 → 1.85.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/domains/video.js +28 -4
  2. package/package.json +1 -1
package/domains/video.js CHANGED
@@ -173,11 +173,11 @@ const tools = [
173
173
  },
174
174
  {
175
175
  name: 'patch_video_track',
176
- description: '1つのトラックだけを差し替えます(タイムライン全体を送り直さなくて済むので安全・軽量)。テロップだけ直す・BGMだけ足す、といった部分更新に使ってください。',
176
+ description: '1つのトラックだけを差し替えます(タイムライン全体を送り直さなくて済むので安全・軽量)。テロップだけ直す・BGMだけ足す・コーナー見出し(banner)を置く、といった部分更新に使ってください。コーナー見出し=ニュース番組の隅にあるテーマ表示で、テーマごとに start/duration を切って出しっぱなしにします(既定の位置は left 最優先の top-left)。形式は get_video_timeline_spec を参照。',
177
177
  annotations: { destructiveHint: false },
178
178
  inputSchema: { type: 'object', properties: {
179
179
  id: { type: 'string', description: 'プロジェクトID' },
180
- type: { type: 'string', enum: ['slides', 'audio', 'video', 'image', 'telop'], description: '対象トラックの種類' },
180
+ type: { type: 'string', enum: ['slides', 'audio', 'video', 'image', 'telop', 'banner'], description: "対象トラックの種類。banner=コーナー見出し(画面の隅に出しっぱなしの見出し。テロップとは別物)" },
181
181
  role: { type: 'string', description: '同じ種類が複数あるときの絞り込み(audio の voice / bgm)' },
182
182
  media_id: { type: 'string', description: '同じ種類が複数あるときの絞り込み(mediaId)' },
183
183
  clips: { type: 'array', items: { type: 'object' }, description: 'そのトラックのクリップ配列(全置換)。形式は get_video_timeline_spec' },
@@ -219,7 +219,7 @@ const tools = [
219
219
  },
220
220
  {
221
221
  name: 'list_video_notes',
222
- description: 'タイムラインに書き込まれた「修正指示」を取得します。利用者が動画編集画面のタイムライン上に、時刻を指して書いたメモです。各メモには context(その時刻に映っているスライドの枚数目・見出し・クリップ内の経過秒・出現済み要素・表示中のテロップ本文)が付いているので、**どこの話かを推測せずに**直せます。「修正指示を書き込みました」と言われたら、まずこれを読んでください。',
222
+ description: 'タイムラインに書き込まれた「修正指示」を取得します。利用者が動画編集画面で対象を指して書いたメモです。各メモの scope=対象の説明(一文)/target_items=指された対象そのもの(種類・trackIdx・index・テロップ本文・開始秒)/context=その時刻に映っているもの。⚠️ **直す対象は target_items** です(context は対象ではありません)。利用者はテロップ3件などを**まとめて1つの指示**として指せるため、context だけを見ると1件しか直りません。「修正指示を書き込みました」と言われたら、まずこれを読んでください。',
223
223
  inputSchema: { type: 'object', properties: {
224
224
  id: { type: 'string', description: 'プロジェクトID' },
225
225
  include_done: { type: 'boolean', description: 'true=対応済みも含める(省略=未対応のみ)' },
@@ -360,6 +360,21 @@ const handlers = {
360
360
  list_video_notes: async ({ id, include_done }) => {
361
361
  const d = await callApi(`/video/${id}/notes${include_done ? '?include_done=1' : ''}`);
362
362
  if (!d.notes || d.notes.length === 0) return '未対応の修正指示はありません。';
363
+ // ⚠️⚠️ 2026-10-04 の是正: ここで scope と target_items を落としていた。
364
+ // 落とすと「この時刻に映っているもの」しか残らず、**まとめて指された指示**で
365
+ // AIが1件しか直せない(利用者が3件選んでも、文章にはそのうち1件しか出ない)。
366
+ // 対象(target_items)を必ず機械可読な形で出すこと。
367
+ const label = { telop: 'テロップ', audio: '音声', video: '映像', image: '画像' };
368
+ const itemLine = (it) => {
369
+ const head = `- ${label[it.kind] || it.kind}: trackIdx=${it.trackIdx} index=${it.index}`;
370
+ if (it.missing) return `${head} ⚠️ すでに削除されています(指示を書いた後に消された)`;
371
+ const body = [
372
+ it.text != null ? `本文「${it.text}」` : null,
373
+ it.start != null ? `${it.start}秒〜` : null,
374
+ it.mediaId ? `mediaId=${it.mediaId}` : null,
375
+ ].filter(Boolean).join(' / ');
376
+ return `${head} ${body}`;
377
+ };
363
378
  return d.notes.map(n => {
364
379
  const c = n.context || {};
365
380
  const where = [
@@ -367,7 +382,16 @@ const handlers = {
367
382
  c.telops && c.telops.length ? `表示中のテロップ: ${c.telops.map(t => `「${t.text}」`).join(' ')}` : null,
368
383
  c.slide && c.slide.revealedPaths && c.slide.revealedPaths.length ? `出現済み: ${c.slide.revealedPaths.join(', ')}` : null,
369
384
  ].filter(Boolean).join(' / ');
370
- return `${n.done ? '✅' : '📝'} [${n.id}] ${n.at}秒 — ${n.text}\n ↳ ${where || '(この時刻に映っているものはありません)'}`;
385
+ const lines = [`${n.done ? '✅' : '📝'} [${n.id}] ${n.at}秒 — ${n.text}`];
386
+ if (n.scope) lines.push(` ↳ 対象: ${n.scope}`);
387
+ if (n.target_items && n.target_items.length) {
388
+ lines.push(` ↳ ⚠️ 直すのはこの${n.target_items.length}件(まとめて1つの指示):`);
389
+ n.target_items.forEach(it => lines.push(` ${itemLine(it)}`));
390
+ } else if (n.target) {
391
+ lines.push(` ↳ 対象の指定: ${JSON.stringify(n.target)}`);
392
+ }
393
+ lines.push(` ↳ 参考(この時刻に映っているもの・対象ではない): ${where || 'なし'}`);
394
+ return lines.join('\n');
371
395
  }).join('\n');
372
396
  },
373
397
  resolve_video_note: async ({ id, note_id, done }) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "owner-clone-ai-mcp",
3
- "version": "1.83.0",
3
+ "version": "1.85.0",
4
4
  "description": "MCP server for Owner Clone AI — exposes knowledge and agent presets to Claude Code",
5
5
  "main": "index.js",
6
6
  "bin": {