@refrainai/cli 0.4.1
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.
- package/dist/ai-model-FM6GWCID.js +37 -0
- package/dist/ai-model-FM6GWCID.js.map +1 -0
- package/dist/chunk-2BVDAJZT.js +236 -0
- package/dist/chunk-2BVDAJZT.js.map +1 -0
- package/dist/chunk-2H7UOFLK.js +11 -0
- package/dist/chunk-2H7UOFLK.js.map +1 -0
- package/dist/chunk-7UCVPKD4.js +902 -0
- package/dist/chunk-7UCVPKD4.js.map +1 -0
- package/dist/chunk-AG3CFMYU.js +36 -0
- package/dist/chunk-AG3CFMYU.js.map +1 -0
- package/dist/chunk-CLYJHKPY.js +1131 -0
- package/dist/chunk-CLYJHKPY.js.map +1 -0
- package/dist/chunk-D5SI2PHK.js +74 -0
- package/dist/chunk-D5SI2PHK.js.map +1 -0
- package/dist/chunk-DJVUITRB.js +9084 -0
- package/dist/chunk-DJVUITRB.js.map +1 -0
- package/dist/chunk-H47NWH7N.js +4427 -0
- package/dist/chunk-H47NWH7N.js.map +1 -0
- package/dist/chunk-HQDXLWAY.js +109 -0
- package/dist/chunk-HQDXLWAY.js.map +1 -0
- package/dist/chunk-IGFCYKHC.js +1974 -0
- package/dist/chunk-IGFCYKHC.js.map +1 -0
- package/dist/chunk-RT664YIO.js +245 -0
- package/dist/chunk-RT664YIO.js.map +1 -0
- package/dist/chunk-RYIJPYM3.js +164 -0
- package/dist/chunk-RYIJPYM3.js.map +1 -0
- package/dist/chunk-TDSM3UXI.js +40 -0
- package/dist/chunk-TDSM3UXI.js.map +1 -0
- package/dist/chunk-UGPXCQY3.js +778 -0
- package/dist/chunk-UGPXCQY3.js.map +1 -0
- package/dist/chunk-VPK2MQAZ.js +589 -0
- package/dist/chunk-VPK2MQAZ.js.map +1 -0
- package/dist/chunk-WEYR56ZN.js +953 -0
- package/dist/chunk-WEYR56ZN.js.map +1 -0
- package/dist/chunk-XMFCXPYU.js +275 -0
- package/dist/chunk-XMFCXPYU.js.map +1 -0
- package/dist/chunk-Z33FCOTZ.js +251 -0
- package/dist/chunk-Z33FCOTZ.js.map +1 -0
- package/dist/cli.js +59 -0
- package/dist/cli.js.map +1 -0
- package/dist/compose-MTSIJY5D.js +547 -0
- package/dist/compose-MTSIJY5D.js.map +1 -0
- package/dist/config-ZSUNCFXR.js +9 -0
- package/dist/config-ZSUNCFXR.js.map +1 -0
- package/dist/fix-runbook-ZSBOTLC2.js +294 -0
- package/dist/fix-runbook-ZSBOTLC2.js.map +1 -0
- package/dist/google-sheets-DRWIVEVC.js +482 -0
- package/dist/google-sheets-DRWIVEVC.js.map +1 -0
- package/dist/registry-LZLYTNDJ.js +17 -0
- package/dist/registry-LZLYTNDJ.js.map +1 -0
- package/dist/runbook-data-helpers-KRR2SH76.js +16 -0
- package/dist/runbook-data-helpers-KRR2SH76.js.map +1 -0
- package/dist/runbook-executor-K7T6RJWJ.js +1480 -0
- package/dist/runbook-executor-K7T6RJWJ.js.map +1 -0
- package/dist/runbook-generator-MPXJBQ5N.js +800 -0
- package/dist/runbook-generator-MPXJBQ5N.js.map +1 -0
- package/dist/runbook-schema-3T6TP3JJ.js +35 -0
- package/dist/runbook-schema-3T6TP3JJ.js.map +1 -0
- package/dist/runbook-store-G5GUOWRR.js +11 -0
- package/dist/runbook-store-G5GUOWRR.js.map +1 -0
- package/dist/schema-5G6UQSPT.js +91 -0
- package/dist/schema-5G6UQSPT.js.map +1 -0
- package/dist/server-AG3LXQBI.js +8778 -0
- package/dist/server-AG3LXQBI.js.map +1 -0
- package/dist/tenant-ai-config-QPFEJUVJ.js +14 -0
- package/dist/tenant-ai-config-QPFEJUVJ.js.map +1 -0
- package/dist/yaml-patcher-VGUS2JGH.js +15 -0
- package/dist/yaml-patcher-VGUS2JGH.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/runbook-generator/exploration-agent.ts","../../../src/runbook-generator/browser-tool.ts","../../../src/browser/selector-builder.ts","../../../src/harness/loop-detector.ts","../../../src/runbook-generator/intervention-controller.ts","../../../src/runbook-generator/explorer.ts","../../../src/runbook-generator/runbook-builder.ts","../../../src/runbook-generator/prompts.ts"],"sourcesContent":["/**\n * exploration-agent — AI SDK generateText による探索ループ\n *\n * browser tool を使って AI がゴール達成まで自律的に探索する。\n * prepareStep で古いスナップショットを刈り取り、トークン消費を抑制する。\n */\n\nimport { stepCountIs, type ModelMessage } from \"ai\";\nimport { z } from \"zod\";\nimport { getModel, trackedGenerateText, trackedGenerateObject, type ModelPurpose } from \"../harness/ai-model\";\nimport type { AIModelProvider } from \"../harness/ai-service\";\nimport { createBrowserTool, type BrowserToolConfig, type PaginationTracker } from \"./browser-tool\";\nimport {\n getAgentInstructions,\n getInitialUserMessage,\n} from \"../i18n/prompts\";\nimport type { AgentBrowser } from \"../browser/browser-client\";\nimport type { DebugLogger } from \"../cli/debug-logger\";\nimport type { SecretsData } from \"../cli/secrets-loader\";\nimport type { DataStore, DataAggregator } from \"../context/data-store\";\nimport type { DownloadManager } from \"../context/download-manager\";\nimport type { RecordedStep } from \"./types\";\nimport type { IInterventionController } from \"./intervention-controller\";\nimport type { Skill } from \"../skills/types\";\nimport { getLocale } from \"../i18n\";\n\nexport interface ExplorationAgentConfig {\n goal: string;\n locale?: \"en\" | \"ja\";\n contextMarkdown: string;\n secrets?: SecretsData;\n maxIterations: number;\n stepDelay: number;\n snapshotFilter: boolean;\n screenshotDir?: string;\n debugLogger?: DebugLogger;\n interventionController?: IInterventionController;\n /** Maximum number of tool call turns to keep in message history (default: 10) */\n historyWindow: number;\n /** Enable multi-model routing: route routine steps to cheaper model (default: false) */\n enableMultiModel?: boolean;\n /** ブラウザツール実行開始時に呼ばれるコールバック(spinner停止 + ステップ表示) */\n onToolCallStart?: (stepCount: number) => void;\n /** ブラウザツール実行完了時に呼ばれるコールバック(spinner再開) */\n onToolCallEnd?: () => void;\n /** ドメイン特化スキルリスト */\n skills?: Skill[];\n /** AI モデル提供(DI) */\n aiProvider?: AIModelProvider;\n}\n\n// getAgentInstructions is now dispatched via i18n/prompts\nexport { getAgentInstructions } from \"../i18n/prompts\";\n\nexport interface ExploreWithAIResult {\n /** 構造化されたゴール達成判定 */\n goalResult: { goalAchieved: boolean; summary: string };\n totalTokens: {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n };\n}\n\n// ── Multi-model routing ──\n\nexport interface RoutingDecision {\n purpose: \"exploration\" | \"exploration-light\";\n reason: string;\n}\n\n/**\n * 探索ステップごとにモデルをルーティングする。\n *\n * ルーティンなターン(フォーム入力、データ収集、安定操作)は安価なモデルへ、\n * 複雑なターン(初回観測、エラー回復、ページ遷移直後)は高性能モデルへ振り分ける。\n */\nexport function routeExplorationModel(\n stepNumber: number,\n messages: ModelMessage[],\n recordedSteps: RecordedStep[],\n): RoutingDecision {\n // 1. 初回 2 ステップは精度最優先(初回観測 + 最初のアクション)\n if (stepNumber <= 2) {\n return { purpose: \"exploration\", reason: \"initial_observation\" };\n }\n\n // tool メッセージのインデックスを収集(フェーズ検出・直前ステップ解析用)\n const toolIndices: number[] = [];\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role === \"tool\") toolIndices.push(i);\n }\n\n // 直前のツール結果を解析\n if (toolIndices.length > 0) {\n const lastToolMsg = messages[toolIndices[toolIndices.length - 1]];\n const lastVal = extractToolOutputValue(lastToolMsg);\n\n if (lastVal) {\n // 2. 直前ステップにエラーがあれば Sonnet(エラー回復に高度な推論が必要)\n const results = lastVal.results as Array<{ success: boolean }> | undefined;\n if (results?.some(r => !r.success)) {\n return { purpose: \"exploration\", reason: \"previous_step_failed\" };\n }\n\n // 3. nudgeMessage があれば Sonnet(ループ検出/ページネーション警告)\n if (lastVal.nudgeMessage) {\n return { purpose: \"exploration\", reason: \"nudge_active\" };\n }\n }\n }\n\n // 4. URL が直前ステップと異なれば Sonnet(新ページの構造理解が必要)\n if (recordedSteps.length >= 2) {\n const last = recordedSteps[recordedSteps.length - 1];\n const prev = recordedSteps[recordedSteps.length - 2];\n if (last.url !== prev.url) {\n return { purpose: \"exploration\", reason: \"page_changed\" };\n }\n }\n\n // 5. フェーズベースのルーティング: form_filling / data_collection は安価モデルへ\n if (toolIndices.length > 0) {\n const phase = detectExplorationPhase(messages, toolIndices);\n if (phase === \"form_filling\") {\n return { purpose: \"exploration-light\", reason: \"routine_form_fill\" };\n }\n if (phase === \"data_collection\") {\n return { purpose: \"exploration-light\", reason: \"routine_data_collection\" };\n }\n }\n\n // 6. 同一 URL 上で 3+ 連続成功なら安価モデル(安定した操作フロー)\n if (recordedSteps.length >= 3) {\n const recent = recordedSteps.slice(-3);\n const allSucceeded = recent.every(s => s.success);\n const sameUrl = recent.every(s => s.url === recent[0].url);\n if (allSucceeded && sameUrl) {\n return { purpose: \"exploration-light\", reason: \"stable_operation\" };\n }\n }\n\n // デフォルト: 高性能モデル\n return { purpose: \"exploration\", reason: \"default\" };\n}\n\n/**\n * AI SDK generateText で探索を実行する。\n * prepareStep で古い tool result のスナップショットを刈り取り、トークン消費を抑制。\n */\nexport async function exploreWithAI(\n browser: AgentBrowser,\n recordedSteps: RecordedStep[],\n config: ExplorationAgentConfig,\n dataStore?: DataStore & DataAggregator,\n downloadManager?: DownloadManager,\n): Promise<ExploreWithAIResult> {\n const paginationTracker: PaginationTracker = { currentPage: 0, totalPages: 0 };\n const toolConfig: BrowserToolConfig = {\n stepDelay: config.stepDelay,\n screenshotDir: config.screenshotDir,\n snapshotFilter: config.snapshotFilter,\n debugLogger: config.debugLogger,\n interventionController: config.interventionController,\n paginationTracker,\n onToolCallStart: config.onToolCallStart,\n onToolCallEnd: config.onToolCallEnd,\n skills: config.skills,\n };\n\n const browserTool = createBrowserTool(browser, recordedSteps, toolConfig, dataStore, downloadManager);\n const totalMaxSteps = config.maxIterations * 3;\n\n // システムプロンプト構築(スキルの augmentation を含む)\n const promptLocale = config.locale ?? getLocale();\n let systemContent = getAgentInstructions(\n config.goal,\n config.contextMarkdown,\n config.secrets,\n promptLocale,\n );\n if (config.skills && config.skills.length > 0) {\n const currentUrl = await browser.url();\n for (const skill of config.skills) {\n const augmentation = skill.getPromptAugmentation({\n url: currentUrl,\n locale: promptLocale,\n });\n if (augmentation) {\n systemContent += augmentation;\n }\n }\n }\n\n const systemMessage = {\n role: \"system\" as const,\n content: systemContent,\n providerOptions: {\n anthropic: { cacheControl: { type: \"ephemeral\" } },\n },\n };\n\n // ── ページネーション停滞検出 ──\n // toolChoice: \"required\" でモデルが非生産的なツール呼び出しを繰り返す場合に制約を解除する\n const STALL_THRESHOLD = 6; // 約2ページ分のバッファ(ページごとに2-3ツール呼び出し)\n let lastProgressPage = 0;\n let stepsWithoutProgress = 0;\n\n const prepareStep = ({ messages, stepNumber }: { messages: ModelMessage[]; stepNumber: number }) => {\n if (stepNumber <= 1) return undefined;\n // 古い tool result から snapshot と extractedData を除去してトークンを節約\n const pruned = pruneOldToolResults(messages, config.historyWindow);\n\n // ページネーション停滞カウンタ更新\n if (paginationTracker.currentPage > lastProgressPage) {\n lastProgressPage = paginationTracker.currentPage;\n stepsWithoutProgress = 0;\n } else {\n stepsWithoutProgress++;\n }\n\n // ページネーション進行中かつ停滞していない場合、ツール呼び出しを強制して\n // モデルが構造化出力を返して探索を打ち切ることを防ぐ\n const paginationInProgress =\n paginationTracker.totalPages > 0 &&\n paginationTracker.currentPage < paginationTracker.totalPages;\n const notStalled = stepsWithoutProgress < STALL_THRESHOLD;\n\n // マルチモデルルーティング: ルーティンステップは安価モデルへ\n if (config.enableMultiModel) {\n const decision = routeExplorationModel(stepNumber, messages, recordedSteps);\n const model = config.aiProvider\n ? config.aiProvider.getModel(decision.purpose as ModelPurpose)\n : getModel(decision.purpose as ModelPurpose);\n if (paginationInProgress && notStalled) {\n return { messages: pruned, toolChoice: \"required\" as const, model };\n }\n return { messages: pruned, model };\n }\n\n if (paginationInProgress && notStalled) {\n return { messages: pruned, toolChoice: \"required\" as const };\n }\n\n return { messages: pruned };\n };\n\n const explorationModel = config.aiProvider\n ? config.aiProvider.getModel(\"exploration\")\n : getModel(\"exploration\");\n const result = await trackedGenerateText(\"exploration\", {\n model: explorationModel,\n messages: [\n systemMessage,\n { role: \"user\" as const, content: getInitialUserMessage(promptLocale) },\n ],\n tools: { browser: browserTool },\n // output: Output.object 削除 — responseFormat の干渉を排除\n stopWhen: [stepCountIs(totalMaxSteps + 1)],\n prepareStep,\n });\n\n const goalResult = parseAgentResultFallback(result.text);\n const usageInfo = {\n promptTokens: result.usage.inputTokens ?? 0,\n completionTokens: result.usage.outputTokens ?? 0,\n totalTokens: (result.usage.inputTokens ?? 0) + (result.usage.outputTokens ?? 0),\n };\n\n // ゴール達成を主張している場合、最終ページ状態で独立検証を実施\n if (goalResult.goalAchieved) {\n const verification = await verifyGoalAchievement(\n browser,\n config.goal,\n goalResult.summary,\n recordedSteps,\n config.aiProvider,\n );\n if (!verification.achieved) {\n goalResult.goalAchieved = false;\n goalResult.summary = `[Verification failed: ${verification.reason}] ${goalResult.summary}`;\n }\n } else if (!goalResult.parsed) {\n // テキストから JSON を抽出できなかった場合、ページ状態で正方向の検証\n const verification = await verifyGoalAchievement(\n browser,\n config.goal,\n goalResult.summary,\n recordedSteps,\n config.aiProvider,\n );\n if (verification.achieved) {\n goalResult.goalAchieved = true;\n goalResult.summary = verification.reason;\n }\n }\n\n return {\n goalResult,\n totalTokens: usageInfo,\n };\n}\n\n/**\n * 古い tool result メッセージを 3 段階で圧縮してトークンを節約する。\n *\n * - 直近 2 ターン: Raw(完全保持)\n * - 3〜4 ターン前: Compact(snapshot 除去 + extractedData 削除)\n * - 5 ターン以上前: Summary(Compact + 成功 results を 1 行に集約)\n *\n * 失敗情報(success: false)、nudgeMessage、scratchpad は全ゾーンで保持する。\n *\n * 適応的圧縮:\n * - フォーム入力フェーズではRawゾーンを拡張(+2ターン)\n * - トークン圧迫時はSummaryゾーンを拡張\n */\nexport function pruneOldToolResults(messages: ModelMessage[], historyWindow = 10): ModelMessage[] {\n let toolIndices: number[] = [];\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role === \"tool\") toolIndices.push(i);\n }\n\n if (toolIndices.length <= 2) return messages;\n\n // フェーズ検出: 直近ツール結果から入力フェーズかどうかを推定\n const phase = detectExplorationPhase(messages, toolIndices);\n // フォーム入力フェーズではRawゾーンを拡張\n const rawSize = phase === \"form_filling\" ? 4 : 2;\n const compactSize = phase === \"form_filling\" ? 4 : 2;\n\n // historyWindow を超えるターンを一括ドロップ\n if (toolIndices.length > historyWindow) {\n const cutoffIndex = toolIndices[toolIndices.length - historyWindow];\n // tool メッセージの直前にある assistant メッセージ(tool_use ブロック)を含めないと\n // orphaned tool_result エラーになるため、assistant メッセージから切る\n let startIndex = cutoffIndex;\n if (startIndex > 0 && messages[startIndex - 1].role === \"assistant\") {\n startIndex = startIndex - 1;\n }\n // システムメッセージと初期ユーザーメッセージを保持\n const preamble = messages.filter((m, i) =>\n i < startIndex && (m.role === \"system\" || (m.role === \"user\" && i < 3)),\n );\n const droppedCount = toolIndices.length - historyWindow;\n const summaryMsg: ModelMessage = {\n role: \"user\" as const,\n content: `[${droppedCount} earlier tool turns omitted for context efficiency]`,\n } as ModelMessage;\n messages = [...preamble, summaryMsg, ...messages.slice(startIndex)];\n\n // toolIndices を再計算\n toolIndices = [];\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role === \"tool\") toolIndices.push(i);\n }\n if (toolIndices.length <= 2) return messages;\n }\n\n // トークン圧迫推定: メッセージ総文字数ベースの簡易推定\n const estimatedChars = estimateMessageChars(messages);\n const HIGH_PRESSURE_CHARS = 400_000; // ~100K tokens\n const isHighPressure = estimatedChars > HIGH_PRESSURE_CHARS;\n\n // 高圧迫時はRaw/Compactゾーンを縮小\n const effectiveRawSize = isHighPressure ? Math.max(1, rawSize - 1) : rawSize;\n const effectiveCompactSize = isHighPressure ? Math.max(1, compactSize - 1) : compactSize;\n\n const recentThreshold = toolIndices[Math.max(0, toolIndices.length - effectiveRawSize)];\n const compactThreshold = toolIndices.length > effectiveRawSize + effectiveCompactSize\n ? toolIndices[toolIndices.length - effectiveRawSize - effectiveCompactSize]\n : 0;\n\n return messages.map((msg, i) => {\n if (msg.role !== \"tool\") return msg;\n\n // Raw ゾーン\n if (i >= recentThreshold) return msg;\n\n // Compact ゾーン\n if (i >= compactThreshold) return compactToolResult(msg);\n\n // Summary ゾーン\n return summarizeToolResult(msg);\n });\n}\n\n/**\n * 直近のツール結果から探索フェーズを推定する。\n * AI 呼び出し不要のヒューリスティック。\n * ツール結果の filledFields / extractedData / memoryStatus フィールドの存在で判定。\n */\nfunction detectExplorationPhase(\n messages: ModelMessage[],\n toolIndices: number[],\n): \"form_filling\" | \"data_collection\" | \"exploring\" {\n const recentTools = toolIndices.slice(-3);\n let fillCount = 0;\n let extractCount = 0;\n\n for (const idx of recentTools) {\n const msg = messages[idx];\n const val = extractToolOutputValue(msg);\n if (val) {\n if (\"filledFields\" in val && val.filledFields) fillCount++;\n if (\"extractedData\" in val && val.extractedData) extractCount++;\n if (\"memoryStatus\" in val && val.memoryStatus) extractCount++;\n }\n }\n\n if (fillCount >= 2) return \"form_filling\";\n if (extractCount >= 2) return \"data_collection\";\n return \"exploring\";\n}\n\n/** ツール結果メッセージから output.value を取得 */\nfunction extractToolOutputValue(msg: ModelMessage): Record<string, unknown> | null {\n if (!Array.isArray(msg.content)) return null;\n const parts = msg.content as unknown as Array<{ type: string; output: unknown }>;\n for (const part of parts) {\n if (part.type !== \"tool-result\") continue;\n const output = part.output as { type?: string; value?: unknown } | null;\n if (output?.type === \"json\" && typeof output.value === \"object\" && output.value !== null) {\n return output.value as Record<string, unknown>;\n }\n }\n return null;\n}\n\n/** メッセージ全体の文字数を簡易推定 */\nfunction estimateMessageChars(messages: ModelMessage[]): number {\n let total = 0;\n for (const msg of messages) {\n if (typeof msg.content === \"string\") {\n total += msg.content.length;\n } else if (Array.isArray(msg.content)) {\n total += JSON.stringify(msg.content).length;\n }\n }\n return total;\n}\n\n/** tool-result part の JSON value を変換するユーティリティ */\nfunction mapToolResultValue(\n msg: ModelMessage,\n transform: (val: Record<string, unknown>) => Record<string, unknown>,\n): ModelMessage {\n if (!Array.isArray(msg.content)) return msg;\n\n // ToolModelMessage.content は ToolContent (= Array<ToolResultPart>) だが、\n // ModelMessage の union 型のため直接 .map() すると型が合わない。unknown 経由でキャスト。\n const parts = msg.content as unknown as Array<{ type: string; output: unknown; [k: string]: unknown }>;\n\n const prunedContent = parts.map((part) => {\n if (part.type !== \"tool-result\") return part;\n const output = part.output;\n if (typeof output !== \"object\" || output === null) return part;\n\n const out = output as { type?: string; value?: unknown };\n if (out.type === \"json\" && typeof out.value === \"object\" && out.value !== null) {\n const val = { ...(out.value as Record<string, unknown>) };\n const transformed = transform(val);\n return { ...part, output: { ...out, value: transformed } };\n }\n\n return part;\n });\n\n return { ...msg, content: prunedContent as unknown as ModelMessage[\"content\"] } as ModelMessage;\n}\n\n/** Compact: snapshot を \"[省略]\" に置換、extractedData を削除。他は保持。 */\nfunction compactToolResult(msg: ModelMessage): ModelMessage {\n return mapToolResultValue(msg, (val) => {\n if (\"snapshot\" in val) { val.snapshot = \"[省略]\"; }\n if (\"extractedData\" in val) { delete val.extractedData; }\n return val;\n });\n}\n\n/** Summary: snapshot キー削除 + 成功 results を 1 行に集約。失敗は個別保持。 */\nfunction summarizeToolResult(msg: ModelMessage): ModelMessage {\n return mapToolResultValue(msg, (val) => {\n // snapshot キー自体を削除\n if (\"snapshot\" in val) { delete val.snapshot; }\n if (\"extractedData\" in val) { delete val.extractedData; }\n\n // results を圧縮: 失敗は個別保持、成功は 1 行に集約\n if (\"results\" in val && Array.isArray(val.results)) {\n const results = val.results as Array<{ description: string; success: boolean; error?: string }>;\n const failures = results.filter((r) => !r.success);\n const successes = results.filter((r) => r.success);\n\n const compressed: Array<{ description: string; success: boolean; error?: string }> = [...failures];\n if (successes.length > 0) {\n compressed.push({ description: `${successes.length}件成功`, success: true });\n }\n val.results = compressed;\n }\n\n return val;\n });\n}\n\n/** ゴール達成判定の構造化スキーマ。parseAgentResultFallback で使用。 */\nconst agentResultSchema = z.object({\n goalAchieved: z.boolean(),\n summary: z.string().default(\"\"),\n});\n\n/** ゴール検証結果のスキーマ */\nconst goalVerificationSchema = z.object({\n achieved: z.boolean(),\n reason: z.string(),\n});\n\n/** 副作用アクション(ページスナップショットでは確認できない操作) */\nconst SIDE_EFFECT_ACTIONS = new Set([\"download\", \"export\", \"memory_append\", \"memory_aggregate\", \"extract\"]);\n\n/**\n * 記録済みステップから検証用のエビデンスサマリーを構築する。\n * 副作用アクション(download, export, memory 操作等)を明示して、\n * ページスナップショットだけでは判断できないゴール達成の証拠を提供する。\n */\nfunction buildExecutionEvidence(recordedSteps: RecordedStep[]): string {\n const totalSteps = recordedSteps.length;\n const succeededSteps = recordedSteps.filter(s => s.success).length;\n\n const lines: string[] = [];\n lines.push(`Completed Actions (${totalSteps} steps, ${succeededSteps} succeeded):`);\n\n for (const step of recordedSteps) {\n const status = step.success ? \"success\" : \"FAILED\";\n const errorSuffix = step.error ? ` — ${step.error}` : \"\";\n lines.push(`- Step ${step.ordinal}: ${step.action.action} — ${step.action.description} (${status}${errorSuffix})`);\n }\n\n // 副作用アクションの集計\n const sideEffectCounts = new Map<string, number>();\n for (const step of recordedSteps) {\n if (step.success && SIDE_EFFECT_ACTIONS.has(step.action.action)) {\n sideEffectCounts.set(step.action.action, (sideEffectCounts.get(step.action.action) ?? 0) + 1);\n }\n }\n\n if (sideEffectCounts.size > 0) {\n const parts = Array.from(sideEffectCounts.entries()).map(\n ([action, count]) => `${count} ${action}`,\n );\n lines.push(`\\nSide effects (not visible in page snapshot): ${parts.join(\", \")}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * AI がゴール達成を主張した後に、最終ページ状態から独立検証を行う。\n * 探索 AI のコンテキスト刈り込みや思い込みによる偽陽性を防ぐ。\n */\nasync function verifyGoalAchievement(\n browser: AgentBrowser,\n goal: string,\n declaredSummary: string,\n recordedSteps: RecordedStep[],\n aiProvider?: AIModelProvider,\n): Promise<{ achieved: boolean; reason: string }> {\n try {\n const snapshot = await browser.snapshot();\n const currentUrl = await browser.url();\n // スナップショットを適度に切り詰め(トークン節約)\n const truncatedSnapshot = snapshot.length > 8000\n ? `${snapshot.slice(0, 8000)}\\n[... truncated]`\n : snapshot;\n\n // 実行済みステップのエビデンスサマリーを構築\n const executionEvidence = buildExecutionEvidence(recordedSteps);\n\n const prompt = `You are an independent verifier. Your task is to check whether a browser automation goal has ACTUALLY been achieved based on the current page state and execution evidence.\n\n## Goal\n${goal}\n\n## Current State\nURL: ${currentUrl}\nPage snapshot (accessibility tree):\n${truncatedSnapshot}\n\n## Agent's Claim\n\"${declaredSummary}\"\n\n## Execution Evidence\n${executionEvidence}\n\n## Verification Checklist\nCheck ALL of the following:\n1. Does the current page clearly show the expected outcome of the goal?\n2. Are there any error messages, validation warnings, or \"try again\" prompts?\n3. For login/auth goals: Is a login form still visible? Are there auth error messages?\n4. For form submission goals: Is there a clear success confirmation? Or is the form still displayed?\n5. For navigation goals: Does the URL and page content match the intended destination?\n6. For compound goals (A then B then C): Can you see evidence that ALL parts were completed, not just the first part?\n7. For goals involving file downloads, data export, or memory operations: These side effects are confirmed by the Execution Evidence above, NOT by the page snapshot. If the execution log shows all download/export/aggregate steps succeeded, consider this as valid evidence of completion.\n\nBe CONSERVATIVE: if the page state is ambiguous or doesn't clearly confirm ALL parts of the goal were achieved, set achieved to false.\nDo NOT trust the agent's claim — verify independently from the page state and execution evidence.`;\n\n const verificationModel = aiProvider ? aiProvider.getModel(\"exploration\") : getModel(\"exploration\");\n const verificationResult = await trackedGenerateObject(\"exploration\", {\n model: verificationModel,\n prompt,\n schema: goalVerificationSchema,\n temperature: 0,\n });\n\n return verificationResult.object ?? { achieved: true, reason: \"verification_returned_null\" };\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n console.warn(`[exploration-agent] Goal verification failed: ${msg}`);\n // 検証自体が失敗した場合は元の結果を信頼\n return { achieved: true, reason: \"verification_error\" };\n }\n}\n\n/**\n * テキストから JSON を抽出してゴール達成判定を行う。\n * JSON が見つからない場合は保守的に goalAchieved: false, parsed: false を返す。\n *\n * parsed フラグ: JSON パースに成功した場合は true、テキストから抽出できなかった場合は false。\n * 呼び出し元は parsed: false の場合にページ状態ベースの独立検証を行える。\n */\nexport function parseAgentResultFallback(text: string): {\n goalAchieved: boolean;\n summary: string;\n parsed: boolean;\n} {\n // 1. 全体が JSON なら直接パース\n try {\n const result = agentResultSchema.parse(JSON.parse(text.trim()));\n return { ...result, parsed: true };\n } catch {\n // fallthrough\n }\n\n // 2. テキスト中の JSON オブジェクトを抽出\n const jsonMatch = text.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch) {\n try {\n const result = agentResultSchema.parse(JSON.parse(jsonMatch[0]));\n return { ...result, parsed: true };\n } catch {\n // fallthrough\n }\n }\n\n // 3. JSON 解析できない場合は保守的に false を返す\n // 正規表現ヒューリスティックは否定文で偽陽性を生むため使用しない\n return { goalAchieved: false, summary: text.slice(0, 200), parsed: false };\n}\n","/**\n * browser-tool — AgentBrowser を AI SDK tool としてラップ\n *\n * AI SDK generateText の tool-calling ループから呼ばれ、\n * ブラウザ操作の実行 + スナップショット返却 + RecordedStep 記録を行う。\n */\n\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\nimport type { AgentBrowser } from \"../browser/browser-client\";\nimport { filterSnapshot } from \"../browser/snapshot-filter\";\nimport { findElementInSnapshot, parseAllElements } from \"../browser/snapshot-parser\";\nimport { buildSelector } from \"../browser/selector-builder\";\nimport { detectLoop } from \"../harness/loop-detector\";\nimport { classifyFailure, sanitizeBrowserError } from \"../harness/error-classifier\";\nimport { log } from \"../cli/prompts\";\nimport { tf } from \"../i18n\";\nimport type { DebugLogger } from \"../cli/debug-logger\";\nimport { noopLogger } from \"../cli/debug-logger\";\nimport type { DataStore, DataAggregator } from \"../context/data-store\";\nimport type { DownloadManager } from \"../context/download-manager\";\nimport { parseAndAppendToMemory } from \"../context/memory-operations\";\nimport { sleep } from \"../harness/sleep\";\nimport type { ExplorationAction, RecordedStep } from \"./types\";\nimport type { IInterventionController } from \"./intervention-controller\";\nimport type { Skill } from \"../skills/types\";\nimport { getLocale } from \"../i18n\";\n\nconst suggestedCaptureSchema = z.object({\n name: z.string(),\n strategy: z.enum([\"snapshot\", \"url\", \"ai\", \"expression\", \"evaluate\"]),\n description: z.string().optional(),\n pattern: z.string().optional(),\n group: z.number().optional(),\n prompt: z.string().optional(),\n expression: z.string().optional(),\n});\n\nconst aggregationSchema = z.object({\n collection: z.string(),\n field: z.string(),\n operation: z.enum([\"sum\", \"count\", \"concat\", \"min\", \"max\", \"avg\", \"unique_count\"]),\n outputVariable: z.string(),\n});\n\nconst actionSchema = z.object({\n action: z.enum([\n \"click\",\n \"fill\",\n \"type\",\n \"select\",\n \"check\",\n \"uncheck\",\n \"navigate\",\n \"wait\",\n \"scroll\",\n \"extract\",\n \"download\",\n \"export\",\n \"memory_append\",\n \"memory_aggregate\",\n \"key\",\n ]),\n selector: z.string().optional(),\n value: z.string().optional(),\n description: z.string(),\n inputCategory: z\n .enum([\"credential\", \"user_data\", \"fixed\", \"navigation\"])\n .optional(),\n variableName: z.string().optional(),\n suggestedCaptures: z.array(suggestedCaptureSchema).optional(),\n /** extract 用: ページ内で実行する JavaScript */\n script: z.string().optional(),\n /** extract 用: AI にデータを抽出させるプロンプト */\n extractPrompt: z.string().optional(),\n /** memory_append 用: 蓄積先コレクション名 */\n memoryCollection: z.string().optional(),\n /** memory_aggregate 用: 集計設定 */\n aggregation: aggregationSchema.optional(),\n /** download 用: 保存先パス */\n downloadPath: z.string().optional(),\n /** export 用: 出力対象コレクション名 */\n exportCollection: z.string().optional(),\n /** export 用: 出力フォーマット */\n exportFormat: z.enum([\"csv\", \"json\"]).optional(),\n /** export 用: 出力先パス */\n exportPath: z.string().optional(),\n /** key 用: 押下するキーボードキー(Playwright 形式、例: \"Enter\", \"Tab\") */\n keys: z.string().optional(),\n});\n\nconst browserInputSchema = z.object({\n actions: z\n .array(actionSchema)\n .describe(\n \"実行するブラウザ操作の配列。空配列なら現在のページスナップショットのみ返す。\",\n ),\n});\n\n/** tool の戻り値の型 */\nexport interface BrowserToolResult {\n results: Array<{ description: string; success: boolean; error?: string }>;\n snapshot: string;\n url: string;\n nudgeMessage?: string;\n stepCount: number;\n memoryStatus?: Record<string, number>;\n extractedData?: string;\n filledFields?: string;\n /** 探索スクラッチパッド: 重要イベントの要約(会話圧縮で失われない知見を保持) */\n scratchpad?: string;\n}\n\n/**\n * 抽出データをプレビュー用に圧縮する。\n * JSON配列の場合は先頭3件 + 合計件数のサマリーに変換。\n */\nfunction truncateExtractedData(data: string, maxLength: number): string {\n try {\n const parsed = JSON.parse(data);\n if (Array.isArray(parsed)) {\n const total = parsed.length;\n const preview = parsed.slice(0, 3);\n if (total <= 3) return JSON.stringify(preview);\n return `${JSON.stringify(preview).slice(0, maxLength)} ... (全${total}件)`;\n }\n } catch {\n // JSON でなければそのまま truncate\n }\n if (data.length <= maxLength) return data;\n return `${data.slice(0, maxLength)}... (${data.length}文字)`;\n}\n\nfunction getActionDelay(action: string, baseDelay: number): number {\n switch (action) {\n case \"navigate\":\n return Math.max(baseDelay, 1000);\n case \"click\":\n return Math.round(baseDelay * 0.6);\n case \"fill\":\n case \"type\":\n return Math.round(baseDelay * 0.2);\n case \"select\":\n return Math.round(baseDelay * 0.4);\n default:\n return baseDelay;\n }\n}\n\nfunction cancellableSleep(\n ms: number,\n ic?: IInterventionController,\n): Promise<void> {\n if (!ic) return sleep(ms);\n return new Promise((resolve) => {\n const interval = 50;\n let elapsed = 0;\n const timer = setInterval(() => {\n elapsed += interval;\n if (elapsed >= ms || ic.isCancelRequested() || ic.isPauseRequested()) {\n clearInterval(timer);\n resolve();\n }\n }, interval);\n });\n}\n\nexport interface PaginationTracker {\n currentPage: number;\n totalPages: number;\n}\n\nexport interface BrowserToolConfig {\n stepDelay: number;\n screenshotDir?: string;\n snapshotFilter: boolean;\n debugLogger?: DebugLogger;\n interventionController?: IInterventionController;\n paginationTracker?: PaginationTracker;\n /** ブラウザツール実行開始時に呼ばれるコールバック(spinner停止 + ステップ表示) */\n onToolCallStart?: (stepCount: number) => void;\n /** ブラウザツール実行完了時に呼ばれるコールバック(spinner再開) */\n onToolCallEnd?: () => void;\n /** ドメイン特化スキルリスト(スナップショット変換 + extractedData 提供) */\n skills?: Skill[];\n}\n\nexport function createBrowserTool(\n browser: AgentBrowser,\n recordedSteps: RecordedStep[],\n config: BrowserToolConfig,\n dataStore?: DataStore & DataAggregator,\n downloadManager?: DownloadManager,\n) {\n let ordinal = 0;\n let nudgeCount = 0;\n let lastSnapshot: string | null = null;\n let lastExtractedData: string | undefined;\n const dl = config.debugLogger;\n /** 入力済みフィールドを追跡(selector → description) */\n const filledFieldsMap = new Map<string, string>();\n const inputActionTypes = new Set([\"fill\", \"type\", \"select\", \"check\", \"uncheck\"]);\n /** 探索スクラッチパッド: 重要イベントの ring buffer */\n const scratchpadEntries: string[] = [];\n const MAX_SCRATCHPAD = 10;\n let lastUrl = \"\";\n\n /**\n * スナップショット変換: スキルが有効ならスキルの transformSnapshot を使用、\n * そうでなければ標準の filterSnapshot を適用する。\n * extractedData が返された場合は lastExtractedData にセットされる。\n */\n const applySnapshotTransform = async (\n raw: string,\n url: string,\n filterOptions?: { filledSelectors?: Set<string> },\n ): Promise<{ snapshot: string; extractedData?: string }> => {\n if (config.skills) {\n for (const skill of config.skills) {\n if (skill.shouldActivate(url)) {\n try {\n const result = await skill.transformSnapshot(browser, raw, {\n url,\n locale: getLocale() as \"en\" | \"ja\",\n });\n if (result.extractedData) {\n lastExtractedData = result.extractedData;\n }\n return result;\n } catch {\n // スキル変換失敗時は次のスキルまたは標準フィルタにフォールバック\n }\n }\n }\n }\n const filtered = config.snapshotFilter\n ? filterSnapshot(raw, filterOptions)\n : raw;\n return { snapshot: filtered };\n };\n\n return tool({\n description:\n \"ブラウザ操作を実行し、操作後のページスナップショットを返す。actionsが空なら現在のページ状態のみ返す。\",\n inputSchema: browserInputSchema,\n execute: async (inputData) => {\n config.onToolCallStart?.(recordedSteps.length);\n try {\n const ic = config.interventionController;\n let interventionNudge: string | undefined;\n\n // ── キャンセルチェック ──\n if (ic?.isCancelRequested()) {\n const snapshot = lastSnapshot ?? (await browser.snapshot());\n const finalSnapshot = config.snapshotFilter\n ? filterSnapshot(snapshot)\n : snapshot;\n return {\n results: [],\n snapshot: finalSnapshot,\n url: await browser.url(),\n nudgeMessage:\n \"ユーザーが探索のキャンセルを要求しました。goalAchieved: false で最終報告を作成してください。\",\n stepCount: recordedSteps.length,\n };\n }\n\n // ── 介入チェック: ユーザーが一時停止を要求していたら対話を行う ──\n if (ic?.isPauseRequested()) {\n const currentUrl = await browser.url();\n const interventionResult = await ic.collectIntervention(\n recordedSteps.length,\n currentUrl,\n );\n\n if (interventionResult.action === \"abort\") {\n const snapshot = lastSnapshot ?? (await browser.snapshot());\n const finalSnapshot = config.snapshotFilter\n ? filterSnapshot(snapshot)\n : snapshot;\n return {\n results: [],\n snapshot: finalSnapshot,\n url: currentUrl,\n nudgeMessage:\n \"ユーザーが探索の中止を要求しました。goalAchieved: false で最終報告を作成してください。\",\n stepCount: recordedSteps.length,\n };\n }\n\n if (interventionResult.guidanceText) {\n interventionNudge = tf(\"browserTool.interventionGuidance\", { text: interventionResult.guidanceText });\n }\n\n dl?.log({\n phase: \"generator\",\n event: \"user_intervention\",\n step: recordedSteps.length,\n data: {\n action: interventionResult.action,\n guidanceText: interventionResult.guidanceText,\n url: currentUrl,\n },\n });\n }\n\n const results: Array<{\n description: string;\n success: boolean;\n error?: string;\n }> = [];\n\n // 空アクション → 観測のみ(初回呼出 or 現在状態確認)\n // snapshot()を呼んでもrefを使う操作がないので安全\n if (inputData.actions.length === 0) {\n const snapshot = await browser.snapshot();\n lastSnapshot = snapshot;\n const currentUrl = await browser.url();\n const transformResult = await applySnapshotTransform(snapshot, currentUrl);\n let finalSnapshot = transformResult.snapshot;\n\n // ページネーション進行中なら nudge + バナーを追加\n let emptyNudge: string | undefined;\n const dataCollectionActionSet = new Set([\"download\", \"extract\", \"memory_append\", \"memory_aggregate\"]);\n const hasDataCollectionHistory = recordedSteps.some(\n s => s.success && dataCollectionActionSet.has(s.action.action),\n );\n if (hasDataCollectionHistory) {\n const pageMatch = snapshot.match(/Page\\s+(\\d+)\\s+(?:of|\\/)\\s+(\\d+)/i);\n if (pageMatch) {\n const cp = Number(pageMatch[1]);\n const tp = Number(pageMatch[2]);\n if (cp < tp) {\n const pp = recordedSteps.filter(\n s => s.success && (s.action.action === \"download\" || s.action.action === \"extract\"),\n ).length;\n emptyNudge = `Pagination progress: Page ${cp} of ${tp} (${pp} pages processed, ${tp - pp} remaining). You MUST continue processing ALL remaining pages — do NOT stop early.`;\n const banner = `[PAGINATION INCOMPLETE: ${pp}/${tp} pages processed. ${tp - pp} pages remaining. You MUST continue — do NOT return goalAchieved yet.]`;\n finalSnapshot = `${banner}\\n${finalSnapshot}`;\n if (config.paginationTracker) {\n config.paginationTracker.currentPage = cp;\n config.paginationTracker.totalPages = tp;\n }\n }\n }\n }\n\n dl?.log({\n phase: \"generator\",\n event: \"snapshot\",\n step: recordedSteps.length,\n data: { url: currentUrl, snapshot, filteredSnapshot: finalSnapshot },\n });\n // スキルが extractedData を返した場合、プレビューを含める\n const skillExtractedPreview = transformResult.extractedData\n ? truncateExtractedData(transformResult.extractedData, 500)\n : undefined;\n\n return {\n results: [],\n snapshot: finalSnapshot,\n url: currentUrl,\n nudgeMessage: emptyNudge,\n stepCount: recordedSteps.length,\n ...(skillExtractedPreview ? { extractedData: skillExtractedPreview } : {}),\n };\n }\n\n // アクションあり → snapshot()を呼ばない(前回のrefマッピングを保持)\n // browser.snapshot()を呼ぶとagent-browser内部の@eNマッピングが再生成され、\n // エージェントが前回のスナップショットで参照した@eNが無効化されてしまう\n const snapshotBefore = lastSnapshot ?? \"\";\n\n for (const action of inputData.actions) {\n // ── アクション間キャンセルチェック ──\n if (ic?.isCancelRequested()) {\n const snapshot = lastSnapshot ?? (await browser.snapshot());\n const finalSnapshot = config.snapshotFilter\n ? filterSnapshot(snapshot)\n : snapshot;\n return {\n results,\n snapshot: finalSnapshot,\n url: await browser.url(),\n nudgeMessage:\n \"ユーザーが探索のキャンセルを要求しました。goalAchieved: false で最終報告を作成してください。\",\n stepCount: recordedSteps.length,\n };\n }\n\n // ── アクション間一時停止チェック ──\n if (ic?.isPauseRequested()) {\n const currentUrl = await browser.url();\n const interventionResult = await ic.collectIntervention(\n recordedSteps.length,\n currentUrl,\n );\n\n if (interventionResult.action === \"abort\") {\n const snapshot = lastSnapshot ?? (await browser.snapshot());\n const finalSnapshot = config.snapshotFilter\n ? filterSnapshot(snapshot)\n : snapshot;\n return {\n results,\n snapshot: finalSnapshot,\n url: currentUrl,\n nudgeMessage:\n \"ユーザーが探索の中止を要求しました。goalAchieved: false で最終報告を作成してください。\",\n stepCount: recordedSteps.length,\n };\n }\n\n if (interventionResult.guidanceText) {\n interventionNudge = tf(\"browserTool.interventionGuidance\", { text: interventionResult.guidanceText });\n }\n\n dl?.log({\n phase: \"generator\",\n event: \"user_intervention\",\n step: recordedSteps.length,\n data: {\n action: interventionResult.action,\n guidanceText: interventionResult.guidanceText,\n url: currentUrl,\n },\n });\n }\n\n log.step(`${action.description} (${action.action} ${action.selector ?? \"\"})`);\n\n // ── メモリ操作(ブラウザ操作不要) ──\n if (action.action === \"memory_append\" && dataStore) {\n const actionStart = performance.now();\n const collection = action.memoryCollection ?? \"default\";\n const rawValue = lastExtractedData ?? action.value ?? \"\";\n const success = true;\n const error: string | undefined = undefined;\n\n parseAndAppendToMemory(rawValue, {\n dataStore,\n debugLogger: dl ?? noopLogger,\n phase: \"generator\",\n step: ordinal,\n collection,\n });\n\n const explorationAction: ExplorationAction = {\n action: action.action,\n value: rawValue,\n description: action.description,\n memoryCollection: collection,\n };\n recordedSteps.push({\n ordinal, action: explorationAction, snapshotBefore,\n url: await browser.url(), success, error,\n durationMs: Math.round(performance.now() - actionStart),\n });\n ordinal++;\n results.push({ description: action.description, success, error });\n // Scratchpad: メモリ蓄積マイルストーン\n const collectionCount = dataStore.count(collection);\n if (collectionCount % 50 === 0 || collectionCount <= 5) {\n addScratchpadEntry(scratchpadEntries, MAX_SCRATCHPAD, `Memory: ${collection} now has ${collectionCount} items`);\n }\n continue;\n }\n\n if (action.action === \"memory_aggregate\" && dataStore && action.aggregation) {\n const actionStart = performance.now();\n const agg = action.aggregation;\n let success = true;\n let error: string | undefined;\n let aggregateResult = \"\";\n\n try {\n aggregateResult = dataStore.aggregate({\n collection: agg.collection,\n field: agg.field,\n operation: agg.operation,\n });\n log.success(`Memory: ${agg.operation}(${agg.collection}.${agg.field}) = \"${aggregateResult}\"`);\n lastExtractedData = aggregateResult;\n } catch (e) {\n success = false;\n error = sanitizeBrowserError(e instanceof Error ? e.message : String(e));\n log.error(`Memory aggregate failed: ${error}`);\n }\n\n const explorationAction: ExplorationAction = {\n action: action.action,\n description: action.description,\n aggregation: agg,\n };\n recordedSteps.push({\n ordinal, action: explorationAction, snapshotBefore,\n url: await browser.url(), success, error,\n durationMs: Math.round(performance.now() - actionStart),\n });\n ordinal++;\n results.push({ description: action.description, success, error });\n continue;\n }\n\n // ── extract(JavaScript実行またはAI抽出) ──\n if (action.action === \"extract\") {\n const actionStart = performance.now();\n let success = true;\n let error: string | undefined;\n let extractResult = \"\";\n\n try {\n if (action.script) {\n dl?.log({\n phase: \"generator\",\n event: \"extract\",\n step: ordinal,\n data: { script: action.script.slice(0, 200) },\n });\n const result = await browser.evaluate(action.script);\n const isArray = Array.isArray(result);\n const stringifyApplied = typeof result !== \"string\" && result !== null && result !== undefined;\n extractResult = result === null || result === undefined\n ? \"\"\n : typeof result === \"string\" ? result : JSON.stringify(result);\n dl?.log({\n phase: \"generator\",\n event: \"extract_result\",\n step: ordinal,\n data: {\n resultType: result === null ? \"null\" : typeof result,\n isArray,\n arrayLength: isArray ? (result as unknown[]).length : undefined,\n resultPreview: extractResult.slice(0, 200),\n storedLength: extractResult.length,\n stringifyApplied,\n },\n });\n } else if (action.extractPrompt) {\n dl?.log({\n phase: \"generator\",\n event: \"extract\",\n step: ordinal,\n data: { extractPrompt: action.extractPrompt.slice(0, 200) },\n });\n const snapshot = await browser.snapshot();\n const { getModel, trackedGenerateObject } = await import(\"../harness/ai-model\");\n const extractSchema = z.object({ data: z.string() });\n const aiResult = await trackedGenerateObject(\"extraction\", {\n model: getModel(\"extraction\"),\n prompt: `${action.extractPrompt}\\n\\nスナップショット:\\n${snapshot}`,\n schema: extractSchema,\n temperature: 0,\n });\n extractResult = aiResult.object?.data ?? \"\";\n dl?.log({\n phase: \"generator\",\n event: \"extract_result\",\n step: ordinal,\n data: {\n resultType: \"string (AI)\",\n resultPreview: extractResult.slice(0, 200),\n storedLength: extractResult.length,\n },\n });\n }\n lastExtractedData = extractResult;\n log.success(`Extracted: ${extractResult.slice(0, 100)}${extractResult.length > 100 ? \"...\" : \"\"}`);\n // Scratchpad: 抽出マイルストーン\n const extractLen = extractResult.length;\n addScratchpadEntry(scratchpadEntries, MAX_SCRATCHPAD, `Extracted ${extractLen > 200 ? `${extractLen} chars` : \"data\"} via ${action.script ? \"script\" : \"AI prompt\"}`);\n\n } catch (e) {\n success = false;\n error = sanitizeBrowserError(e instanceof Error ? e.message : String(e));\n log.error(`Extract failed: ${error}`);\n }\n\n const explorationAction: ExplorationAction = {\n action: action.action,\n description: action.description,\n script: action.script,\n extractPrompt: action.extractPrompt,\n };\n recordedSteps.push({\n ordinal, action: explorationAction, snapshotBefore,\n url: await browser.url(), success, error,\n durationMs: Math.round(performance.now() - actionStart),\n });\n ordinal++;\n results.push({ description: action.description, success, error });\n continue;\n }\n\n // ── download(ファイルダウンロード) ──\n if (action.action === \"download\") {\n const actionStart = performance.now();\n let success = true;\n let error: string | undefined;\n const downloadPath = action.downloadPath ?? `/tmp/download-${Date.now()}.bin`;\n\n try {\n if (action.selector) {\n await browser.download(action.selector, downloadPath);\n } else {\n await browser.waitForDownload(downloadPath);\n }\n log.success(`Downloaded: ${downloadPath}`);\n\n if (downloadManager) {\n downloadManager.addDownload({\n path: downloadPath,\n filename: downloadPath.split(\"/\").pop() ?? \"unknown\",\n stepOrdinal: ordinal,\n timestamp: new Date().toISOString(),\n });\n }\n } catch (e) {\n success = false;\n error = sanitizeBrowserError(e instanceof Error ? e.message : String(e));\n log.error(`Download failed: ${error}`);\n }\n\n const explorationAction: ExplorationAction = {\n action: action.action,\n selector: action.selector,\n description: action.description,\n downloadPath,\n };\n recordedSteps.push({\n ordinal, action: explorationAction, snapshotBefore,\n url: await browser.url(), success, error,\n durationMs: Math.round(performance.now() - actionStart),\n });\n ordinal++;\n results.push({ description: action.description, success, error });\n continue;\n }\n\n // ── export(メモリコレクションをファイルに書き出し) ──\n if (action.action === \"export\" && dataStore) {\n const actionStart = performance.now();\n const collection = action.exportCollection ?? \"default\";\n const format = (action.exportFormat ?? \"csv\") as \"csv\" | \"json\";\n const exportPath = action.exportPath ?? `/tmp/${collection}.${format}`;\n let success = true;\n let error: string | undefined;\n\n try {\n const exportItems = dataStore.getAll(collection);\n const sampleKeys = exportItems.length > 0\n ? JSON.stringify(Object.keys(exportItems[0]))\n : \"N/A\";\n dl?.log({\n phase: \"generator\",\n event: \"export\",\n step: ordinal,\n data: {\n collection,\n itemCount: exportItems.length,\n format,\n path: exportPath,\n sampleKeys,\n },\n });\n await dataStore.writeToFile(collection, exportPath, format);\n log.success(`Exported: ${collection} → ${exportPath} (${format})`);\n lastExtractedData = exportPath;\n\n if (downloadManager) {\n downloadManager.addDownload({\n path: exportPath,\n filename: exportPath.split(\"/\").pop() ?? \"unknown\",\n stepOrdinal: ordinal,\n timestamp: new Date().toISOString(),\n });\n }\n } catch (e) {\n success = false;\n error = sanitizeBrowserError(e instanceof Error ? e.message : String(e));\n log.error(`Export failed: ${error}`);\n }\n\n const explorationAction: ExplorationAction = {\n action: action.action,\n description: action.description,\n exportCollection: collection,\n exportFormat: format,\n exportPath,\n };\n recordedSteps.push({\n ordinal, action: explorationAction, snapshotBefore,\n url: await browser.url(), success, error,\n durationMs: Math.round(performance.now() - actionStart),\n });\n ordinal++;\n results.push({ description: action.description, success, error });\n continue;\n }\n\n // ── key(キーボードキー押下) ──\n if (action.action === \"key\") {\n const actionStart = performance.now();\n const keys = action.keys ?? action.value ?? \"\";\n let success = true;\n let error: string | undefined;\n\n try {\n await browser.pressKeys(keys);\n log.success(`Key: ${keys}`);\n } catch (e) {\n success = false;\n error = sanitizeBrowserError(e instanceof Error ? e.message : String(e));\n log.error(`Key failed: ${error}`);\n }\n\n const explorationAction: ExplorationAction = {\n action: \"key\",\n description: action.description,\n keys,\n };\n recordedSteps.push({\n ordinal, action: explorationAction, snapshotBefore,\n url: await browser.url(), success, error,\n durationMs: Math.round(performance.now() - actionStart),\n });\n ordinal++;\n results.push({ description: action.description, success, error });\n continue;\n }\n\n // ── 通常のブラウザ操作 ──\n const explorationAction: ExplorationAction = {\n action: action.action as ExplorationAction[\"action\"],\n selector: action.selector,\n value: action.value,\n description: action.description,\n inputCategory: action.inputCategory,\n variableName: action.variableName,\n suggestedCaptures: action.suggestedCaptures,\n };\n\n const navigatingActions = new Set([\"click\", \"navigate\"]);\n const mayNavigate = navigatingActions.has(action.action);\n\n const urlBeforeAction = mayNavigate ? await browser.url() : \"\";\n const pageCountBefore = mayNavigate ? await browser.pageCount() : 0;\n const result = await browser.executeStep(explorationAction);\n\n if (mayNavigate) {\n await browser.waitForPossibleNavigation(\n urlBeforeAction,\n pageCountBefore,\n );\n }\n\n const stepUrl = await browser.url();\n\n // RecordedStep に記録(失敗時はエラー分類を付与)\n const recorded: RecordedStep = {\n ordinal,\n action: explorationAction,\n snapshotBefore,\n url: stepUrl,\n success: result.success,\n error: result.error,\n durationMs: result.durationMs,\n failureCategory: result.success ? undefined : classifyFailure({\n error: result.error ?? \"unknown error\",\n selectorResolved: !!action.selector,\n actionExecuted: true,\n }),\n };\n recordedSteps.push(recorded);\n ordinal++;\n\n results.push({\n description: action.description,\n success: result.success,\n error: result.error,\n });\n\n dl?.log({\n phase: \"generator\",\n event: \"action\",\n step: ordinal - 1,\n data: {\n action: action.action,\n selector: action.selector,\n value: action.value,\n description: action.description,\n result: {\n success: result.success,\n error: result.error,\n durationMs: result.durationMs,\n },\n url: stepUrl,\n failureCategory: recorded.failureCategory,\n },\n });\n\n if (result.success) {\n log.success(`OK (${result.durationMs}ms)`);\n // 入力操作の成功を追跡(filledFields として AI に提供)\n if (inputActionTypes.has(action.action) && action.selector) {\n filledFieldsMap.set(action.selector, action.description);\n }\n // Scratchpad: URL 遷移を記録\n if (mayNavigate && stepUrl !== urlBeforeAction) {\n addScratchpadEntry(scratchpadEntries, MAX_SCRATCHPAD, `Navigated ${shortenUrl(urlBeforeAction)} → ${shortenUrl(stepUrl)}`);\n lastUrl = stepUrl;\n // ページ遷移時にゴールリマインダー\n addScratchpadEntry(scratchpadEntries, MAX_SCRATCHPAD, `GOAL CHECK: Verify ALL parts of the goal are completed before declaring goalAchieved. Your claim will be independently verified.`);\n }\n // 定期的なゴールリマインダー(5ステップごと)\n if (ordinal > 0 && ordinal % 5 === 0) {\n addScratchpadEntry(scratchpadEntries, MAX_SCRATCHPAD, `REMINDER (step ${ordinal}): Before declaring goalAchieved, re-read the original goal and confirm ALL sub-tasks are done. Include evidence in your summary.`);\n }\n } else {\n log.error(`FAILED: ${result.error}`);\n // Scratchpad: 失敗を記録\n addScratchpadEntry(scratchpadEntries, MAX_SCRATCHPAD, `${action.action} ${action.selector ?? \"\"} failed: ${(result.error ?? \"unknown\").slice(0, 60)}`);\n }\n\n await cancellableSleep(getActionDelay(action.action, config.stepDelay), ic);\n }\n\n // navigate 使用時の警告: ページ上にリンクがあるなら click を使うべき\n let navigateNudge: string | undefined;\n if (inputData.actions.some(a => a.action === \"navigate\") && lastSnapshot) {\n const linkCount = parseAllElements(lastSnapshot).filter(e => e.role === \"link\").length;\n if (linkCount > 0) {\n navigateNudge = `注意: ページ上に ${linkCount} 個のリンクがあります。navigate でURLを組み立てるのではなく、ページ上のリンクを click で辿ってください。`;\n }\n }\n\n // ループ検出\n let nudgeMessage: string | undefined = navigateNudge;\n if (recordedSteps.length >= 2) {\n const loopResult = detectLoop(recordedSteps, nudgeCount);\n if (loopResult.isLoop) {\n nudgeCount = loopResult.nudgeCount;\n const loopNudge = loopResult.nudgeMessage ?? undefined;\n nudgeMessage = nudgeMessage && loopNudge\n ? `${nudgeMessage}\\n${loopNudge}`\n : loopNudge ?? nudgeMessage;\n log.warn(`Loop detected: ${loopResult.loopType}`);\n dl?.log({\n phase: \"generator\",\n event: \"loop_detection\",\n step: recordedSteps.length - 1,\n data: loopResult as unknown as Record<string, unknown>,\n });\n }\n }\n\n const postSnapshot = await browser.snapshot();\n const currentUrl = await browser.url();\n\n // テキスト入力のみ(fill/type)かつ全成功なら差分スナップショットを試行\n // fill/type はページ構造を変えないため、構造シグネチャが同一なら\n // コンパクトな ref 一覧を返してトークンを節約する。\n const textOnlyActions = new Set([\"fill\", \"type\"]);\n const allTextOnly = inputData.actions.length > 0\n && inputData.actions.every(a => textOnlyActions.has(a.action))\n && results.every(r => r.success);\n\n let finalSnapshot: string;\n\n if (allTextOnly && lastSnapshot) {\n const oldSig = extractStructuralSignature(lastSnapshot);\n const newSig = extractStructuralSignature(postSnapshot);\n\n if (oldSig === newSig) {\n finalSnapshot = buildDiffSnapshot(postSnapshot, filledFieldsMap);\n dl?.log({\n phase: \"generator\",\n event: \"snapshot_diff\",\n step: recordedSteps.length - 1,\n data: { url: currentUrl, reason: \"structure_unchanged\", elementCount: newSig.split(\"\\n\").length },\n });\n } else {\n const filledSelectors = filledFieldsMap.size > 0\n ? new Set(filledFieldsMap.keys()) : undefined;\n const tr = await applySnapshotTransform(postSnapshot, currentUrl, { filledSelectors });\n finalSnapshot = tr.snapshot;\n dl?.log({\n phase: \"generator\",\n event: \"snapshot\",\n step: recordedSteps.length - 1,\n data: { url: currentUrl, snapshot: postSnapshot, filteredSnapshot: finalSnapshot },\n });\n }\n } else {\n const filledSelectors = filledFieldsMap.size > 0\n ? new Set(filledFieldsMap.keys()) : undefined;\n const tr = await applySnapshotTransform(postSnapshot, currentUrl, { filledSelectors });\n finalSnapshot = tr.snapshot;\n dl?.log({\n phase: \"generator\",\n event: \"snapshot\",\n step: recordedSteps.length - 1,\n data: { url: currentUrl, snapshot: postSnapshot, filteredSnapshot: finalSnapshot },\n });\n }\n\n lastSnapshot = postSnapshot;\n\n // 介入ガイダンスを nudgeMessage に合成\n if (interventionNudge) {\n nudgeMessage = nudgeMessage\n ? `${interventionNudge}\\n${nudgeMessage}`\n : interventionNudge;\n }\n\n // メモリコレクション状態を収集\n const memoryStatus = dataStore\n ? Object.fromEntries(\n dataStore.listCollections().map((c) => [c, dataStore.count(c)]),\n )\n : undefined;\n\n // extractedData は extract/memory_aggregate アクションまたはスキル抽出を含む場合に返す\n // AI に渡す際はプレビューに圧縮(生データは lastExtractedData に保持)\n const hasExtractAction = inputData.actions.some(\n a => a.action === \"extract\" || a.action === \"memory_aggregate\",\n );\n const skillProvidedData = config.skills?.some(s => s.shouldActivate(currentUrl)) && lastExtractedData;\n const extractedDataPreview = (hasExtractAction || skillProvidedData) && lastExtractedData\n ? truncateExtractedData(lastExtractedData, 500)\n : undefined;\n\n // 古い recordedSteps の snapshotBefore をクリア(メモリ節約)\n // 破棄前に要素メタデータを保存(runbook-builder で正しいセレクタ生成に必要)\n const keepRecent = 5;\n if (recordedSteps.length > keepRecent) {\n const stepToPrune = recordedSteps[recordedSteps.length - keepRecent - 1];\n if (stepToPrune.snapshotBefore && stepToPrune.action.selector) {\n const ref = stepToPrune.action.selector.replace(\"@\", \"\");\n const element = findElementInSnapshot(stepToPrune.snapshotBefore, ref);\n if (element) {\n stepToPrune.resolvedElement = buildSelector(element);\n }\n }\n stepToPrune.snapshotBefore = \"\";\n }\n\n // 入力済みフィールドのサマリーを構築\n const filledFieldsSummary = filledFieldsMap.size > 0\n ? [...filledFieldsMap.entries()]\n .map(([sel, desc]) => `${sel}: ${desc}`)\n .join(\", \")\n : undefined;\n\n // ── ページネーション進捗ナッジ ──\n // 過去にデータ収集アクションが1回でも成功していれば、以降の全ツールコールで\n // ページネーション進捗を返す(click のみのコールでも発火させる)\n let paginationCurrentPage = 0;\n let paginationTotalPages = 0;\n let paginationPagesProcessed = 0;\n const dataCollectionActionSet = new Set([\"download\", \"extract\", \"memory_append\", \"memory_aggregate\"]);\n const hasDataCollectionHistory = recordedSteps.some(\n s => s.success && dataCollectionActionSet.has(s.action.action),\n );\n if (hasDataCollectionHistory) {\n const pageMatch = postSnapshot.match(/Page\\s+(\\d+)\\s+(?:of|\\/)\\s+(\\d+)/i);\n if (pageMatch) {\n paginationCurrentPage = Number(pageMatch[1]);\n paginationTotalPages = Number(pageMatch[2]);\n if (paginationCurrentPage < paginationTotalPages) {\n paginationPagesProcessed = recordedSteps.filter(\n s => s.success && (s.action.action === \"download\" || s.action.action === \"extract\"),\n ).length;\n const paginationNudge = `Pagination progress: Page ${paginationCurrentPage} of ${paginationTotalPages} (${paginationPagesProcessed} pages processed, ${paginationTotalPages - paginationPagesProcessed} remaining). You MUST continue processing ALL remaining pages — do NOT stop early.`;\n nudgeMessage = nudgeMessage ? `${nudgeMessage}\\n${paginationNudge}` : paginationNudge;\n // paginationTracker を更新(prepareStep で参照)\n if (config.paginationTracker) {\n config.paginationTracker.currentPage = paginationCurrentPage;\n config.paginationTracker.totalPages = paginationTotalPages;\n }\n }\n }\n }\n\n // 未入力フォームフィールドの検出: フォーム入力が進行中(3件以上入力済み)の場合、\n // まだ未操作のフォーム要素があれば AI にヒントを返す\n if (filledFieldsMap.size >= 3) {\n const formRoles = new Set([\"textbox\", \"combobox\", \"checkbox\", \"spinbutton\"]);\n const filledRefs = new Set(\n [...filledFieldsMap.keys()].map(s => s.replace(\"@\", \"\")),\n );\n const allElements = parseAllElements(postSnapshot);\n const remainingFormElements = allElements.filter(\n e => formRoles.has(e.role) && !filledRefs.has(e.ref),\n );\n\n if (remainingFormElements.length > 0) {\n const names = remainingFormElements\n .map(e => e.name ? `\"${e.name}\"` : `@${e.ref}`)\n .join(\", \");\n const formHint = `Note: ${remainingFormElements.length} form fields not yet filled: ${names}. Fill all remaining fields before submitting.`;\n nudgeMessage = nudgeMessage ? `${nudgeMessage}\\n${formHint}` : formHint;\n }\n }\n\n // ページネーション進捗バナーをスナップショット先頭に埋め込む\n // nudgeMessage とは別に、スナップショット本文の先頭に配置して AI が無視できないようにする\n if (paginationCurrentPage > 0 && paginationCurrentPage < paginationTotalPages) {\n const banner = `[PAGINATION INCOMPLETE: ${paginationPagesProcessed}/${paginationTotalPages} pages processed. ${paginationTotalPages - paginationPagesProcessed} pages remaining. You MUST continue — do NOT return goalAchieved yet.]`;\n finalSnapshot = `${banner}\\n${finalSnapshot}`;\n }\n\n // Build scratchpad string from entries\n const scratchpad = scratchpadEntries.length > 0\n ? scratchpadEntries.join(\"\\n\")\n : undefined;\n\n return {\n results,\n snapshot: finalSnapshot,\n url: currentUrl,\n nudgeMessage,\n stepCount: recordedSteps.length,\n ...(memoryStatus && Object.keys(memoryStatus).length > 0 ? { memoryStatus } : {}),\n ...(extractedDataPreview ? { extractedData: extractedDataPreview } : {}),\n ...(filledFieldsSummary ? { filledFields: filledFieldsSummary } : {}),\n ...(scratchpad ? { scratchpad } : {}),\n };\n } finally {\n config.onToolCallEnd?.();\n }\n },\n });\n}\n\n/** Ring buffer に探索スクラッチパッドエントリを追加 */\nfunction addScratchpadEntry(entries: string[], max: number, entry: string): void {\n entries.push(entry);\n if (entries.length > max) {\n entries.shift();\n }\n}\n\n/** URL をパス部分のみに短縮(ホスト名省略) */\nfunction shortenUrl(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.pathname + (parsed.search ? parsed.search.slice(0, 30) : \"\");\n } catch {\n return url.slice(0, 50);\n }\n}\n\n/**\n * スナップショットから構造シグネチャを抽出。\n * 各行の indent:role:ref を連結した文字列。名前・属性値は無視。\n * fill/type は値のみ変更するため、シグネチャが同一なら構造変化なし。\n */\nfunction extractStructuralSignature(snapshot: string): string {\n return snapshot.split(\"\\n\")\n .map(line => {\n const indent = line.length - line.trimStart().length;\n const trimmed = line.trimStart().replace(/^-\\s+/, \"\");\n const roleMatch = trimmed.match(/^(\\S+)/);\n const refMatch = line.match(/\\[ref=(e\\d+)\\]/);\n return `${indent}:${roleMatch?.[1] ?? \"\"}:${refMatch?.[1] ?? \"\"}`;\n })\n .join(\"\\n\");\n}\n\n/**\n * 構造変化なし時のコンパクトスナップショットを構築。\n * 未入力フィールドを優先表示し、AI が次のアクションを判断しやすくする。\n */\nfunction buildDiffSnapshot(\n snapshot: string,\n filledFieldsMap: Map<string, string>,\n): string {\n const elements = parseAllElements(snapshot);\n const filledRefs = new Set(\n [...filledFieldsMap.keys()].map(sel => sel.replace(\"@\", \"\")),\n );\n\n const unfilled: string[] = [];\n const filled: string[] = [];\n\n for (const el of elements) {\n const label = `@${el.ref} ${el.role}${el.name ? ` \"${el.name}\"` : \"\"}`;\n if (filledRefs.has(el.ref)) {\n filled.push(label);\n } else {\n unfilled.push(label);\n }\n }\n\n const lines = [\n `[Structure unchanged after text input. ${elements.length} interactive elements, all refs valid.]`,\n ];\n if (unfilled.length > 0) {\n lines.push(`Unfilled: ${unfilled.join(\", \")}`);\n }\n if (filled.length > 0) {\n lines.push(`Filled (${filled.length}): ${filled.join(\", \")}`);\n }\n return lines.join(\"\\n\");\n}\n","/**\n * selector-builder — ParsedSnapshotElement → ElementSelector 変換\n *\n * スナップショットのロール/名前からcontractsのElementSelectorへ近似変換。\n * 正確なロケーターではなく、ヒントとしての変換。\n */\n\nimport type { ElementSelector } from \"../schemas/element-selector\";\nimport type { ParsedSnapshotElement } from \"./snapshot-parser\";\n\n/** role → tagName マッピング */\nexport const ROLE_TAG_MAP: Record<\n string,\n { tagName: string; inputType?: string; role?: string }\n> = {\n textbox: { tagName: \"input\", inputType: \"text\" },\n button: { tagName: \"button\", role: \"button\" },\n link: { tagName: \"a\", role: \"link\" },\n checkbox: { tagName: \"input\", inputType: \"checkbox\" },\n radio: { tagName: \"input\", inputType: \"radio\" },\n combobox: { tagName: \"select\", role: \"combobox\" },\n searchbox: { tagName: \"input\", inputType: \"search\" },\n slider: { tagName: \"input\", inputType: \"range\" },\n spinbutton: { tagName: \"input\", inputType: \"number\" },\n switch: { tagName: \"input\", inputType: \"checkbox\", role: \"switch\" },\n tab: { tagName: \"button\", role: \"tab\" },\n menuitem: { tagName: \"button\", role: \"menuitem\" },\n option: { tagName: \"option\", role: \"option\" },\n heading: { tagName: \"h2\", role: \"heading\" },\n img: { tagName: \"img\", role: \"img\" },\n navigation: { tagName: \"nav\", role: \"navigation\" },\n listitem: { tagName: \"li\", role: \"listitem\" },\n};\n\n/**\n * ParsedSnapshotElement を ElementSelector に変換\n */\nexport function buildSelector(\n element: ParsedSnapshotElement,\n): ElementSelector {\n const mapping = ROLE_TAG_MAP[element.role];\n const tagName = mapping?.tagName ?? element.role;\n\n const selector: ElementSelector = { tagName };\n\n // role\n if (mapping?.role) {\n selector.role = mapping.role;\n } else if (element.role !== tagName) {\n selector.role = element.role;\n }\n\n // inputType\n if (mapping?.inputType) {\n selector.inputType = mapping.inputType;\n }\n\n // name → ariaLabel(共通)\n if (element.name) {\n selector.ariaLabel = element.name;\n\n // button/link は innerText も設定\n if (element.role === \"button\" || element.role === \"link\") {\n selector.innerText = element.name.slice(0, 200);\n }\n }\n\n // 属性から追加情報を取得\n if (element.attributes.placeholder) {\n selector.placeholder = element.attributes.placeholder;\n }\n if (element.attributes.name) {\n selector.name = element.attributes.name;\n }\n\n return selector;\n}\n","/**\n * loop-detector — ハッシュベースのループ検出\n *\n * BrowserUse の ActionLoopDetector パターンを参考に、\n * AI stall check の前に高速・無料な決定的ループ検出を行う。\n */\n\nimport type { RecordedStep } from \"../runbook-generator/types\";\n\nexport interface LoopDetectionResult {\n isLoop: boolean;\n loopType: \"exact_repeat\" | \"action_cycle\" | \"url_bounce\" | \"selector_refill\" | null;\n nudgeMessage: string | null;\n nudgeCount: number;\n shouldPromptHuman: boolean;\n}\n\n/**\n * RecordedStep からハッシュ文字列を生成\n * action|selector|urlPath の組み合わせ\n */\nfunction stepHash(step: RecordedStep): string {\n const urlPath = extractPath(step.url);\n return `${step.action.action}|${step.action.selector ?? \"\"}|${urlPath}`;\n}\n\nfunction extractPath(url: string): string {\n try {\n return new URL(url).pathname;\n } catch {\n return url;\n }\n}\n\n/**\n * ループを検出してナッジメッセージを返す\n *\n * @param recordedSteps - これまでの全ステップ\n * @param previousNudgeCount - これまでのナッジ回数\n * @param windowSize - 検出ウィンドウサイズ (default: 4)\n */\nexport function detectLoop(\n recordedSteps: RecordedStep[],\n previousNudgeCount: number,\n windowSize = 4,\n): LoopDetectionResult {\n const noLoop: LoopDetectionResult = {\n isLoop: false,\n loopType: null,\n nudgeMessage: null,\n nudgeCount: previousNudgeCount,\n shouldPromptHuman: false,\n };\n\n if (recordedSteps.length < 2) return noLoop;\n\n // 1. Exact repeat: 直近2アクションのハッシュが同一\n const last = stepHash(recordedSteps[recordedSteps.length - 1]);\n const secondLast = stepHash(recordedSteps[recordedSteps.length - 2]);\n if (last === secondLast) {\n return buildResult(\"exact_repeat\", previousNudgeCount);\n }\n\n // 2. Action cycle: ウィンドウ内のハッシュ列が繰り返し ([A,B,A,B] パターン)\n // ただしデータ収集アクション(download/extract/memory系/export)を含む場合はスキップ\n // → ページネーション走査(download→click→download→click)はループではない\n if (recordedSteps.length >= windowSize) {\n const recentSteps = recordedSteps.slice(-windowSize);\n const dataCollectionActions = new Set([\"download\", \"extract\", \"memory_append\", \"memory_aggregate\", \"export\"]);\n const hasDataCollection = recentSteps.some(s => dataCollectionActions.has(s.action.action));\n\n if (!hasDataCollection) {\n const recentHashes = recentSteps.map(stepHash);\n const halfLen = Math.floor(windowSize / 2);\n const firstHalf = recentHashes.slice(0, halfLen).join(\",\");\n const secondHalf = recentHashes.slice(halfLen, halfLen * 2).join(\",\");\n if (firstHalf === secondHalf) {\n return buildResult(\"action_cycle\", previousNudgeCount);\n }\n }\n }\n\n // 3. URL bounce: 直近4ステップで2URLが交互\n if (recordedSteps.length >= 4) {\n const recentUrls = recordedSteps.slice(-4).map((s) => extractPath(s.url));\n if (\n recentUrls[0] === recentUrls[2] &&\n recentUrls[1] === recentUrls[3] &&\n recentUrls[0] !== recentUrls[1]\n ) {\n return buildResult(\"url_bounce\", previousNudgeCount);\n }\n }\n\n // 4. Selector refill: 同一セレクタへの入力操作が3回以上(大フォームでの再入力ループ検出)\n const inputActions = new Set([\"fill\", \"type\", \"select\", \"check\", \"uncheck\"]);\n const selectorCounts = new Map<string, { count: number; description: string }>();\n for (const step of recordedSteps) {\n if (!step.success) continue;\n if (!inputActions.has(step.action.action)) continue;\n if (!step.action.selector) continue;\n const key = `${step.action.action}|${step.action.selector}`;\n const existing = selectorCounts.get(key);\n if (existing) {\n existing.count++;\n } else {\n selectorCounts.set(key, { count: 1, description: step.action.description });\n }\n }\n\n const refills = [...selectorCounts.entries()]\n .filter(([, v]) => v.count >= 3)\n .map(([k, v]) => ({ selector: k.split(\"|\")[1], count: v.count, description: v.description }));\n\n if (refills.length > 0) {\n const details = refills\n .map((r) => `${r.selector} \"${r.description}\" (${r.count}回)`)\n .join(\", \");\n return buildRefillResult(details, previousNudgeCount);\n }\n\n return noLoop;\n}\n\nfunction buildResult(\n loopType: \"exact_repeat\" | \"action_cycle\" | \"url_bounce\",\n previousNudgeCount: number,\n): LoopDetectionResult {\n const nudgeCount = previousNudgeCount + 1;\n const messages: Record<string, string> = {\n exact_repeat:\n \"同じ操作を繰り返しています。別のアプローチを試してください。\",\n action_cycle:\n \"操作がループしています。異なる戦略を検討してください。\",\n url_bounce:\n \"同じURL間を行き来しています。目的のページに留まって操作を進めてください。\",\n };\n\n return {\n isLoop: true,\n loopType,\n nudgeMessage: messages[loopType],\n nudgeCount,\n // 1回目はナッジのみ、2回目以降は人間に確認\n shouldPromptHuman: nudgeCount >= 2,\n };\n}\n\nfunction buildRefillResult(\n details: string,\n previousNudgeCount: number,\n): LoopDetectionResult {\n const nudgeCount = previousNudgeCount + 1;\n return {\n isLoop: true,\n loopType: \"selector_refill\",\n nudgeMessage: `同じフォームフィールドを繰り返し入力しています。以下は既に入力済みです: ${details}。入力済みフィールドをスキップし、未入力フィールドに進んでください。`,\n nudgeCount,\n shouldPromptHuman: nudgeCount >= 2,\n };\n}\n","/**\n * intervention-controller — 探索中のユーザー介入管理\n *\n * stdin キー押下で一時停止フラグをセットし、\n * browser-tool の execute から呼ばれて介入テキストを収集する。\n */\n\nimport { promptSelect, promptText, log } from \"../cli/prompts\";\nimport type { InterventionRecord } from \"./types\";\n\nexport type InterventionAction = \"guidance\" | \"abort\";\n\nexport interface InterventionResult {\n action: InterventionAction;\n guidanceText?: string;\n}\n\nexport interface InterventionControllerOptions {\n onPause?: () => void;\n onResume?: () => void;\n onCancel?: () => void;\n}\n\n/** CLI / Server 共通の介入コントローラーインターフェース */\nexport interface IInterventionController {\n readonly interventions: InterventionRecord[];\n setCallbacks(options: InterventionControllerOptions): void;\n startListening(): void | Promise<void>;\n isPauseRequested(): boolean;\n isCancelRequested(): boolean;\n collectIntervention(currentStepIndex: number, currentUrl: string): Promise<InterventionResult>;\n dispose(): void;\n}\n\nexport class InterventionController implements IInterventionController {\n private pauseRequested = false;\n private cancelRequested = false;\n private stdinCleanup: (() => void) | null = null;\n private options: InterventionControllerOptions = {};\n readonly interventions: InterventionRecord[] = [];\n\n /**\n * spinner コールバックを後から設定する\n */\n setCallbacks(options: InterventionControllerOptions): void {\n this.options = options;\n }\n\n /**\n * stdin の raw mode キーリスナーを開始。\n * Enter キーまたは p キーで pauseRequested フラグをセット。\n */\n startListening(): void {\n if (!process.stdin.isTTY) return;\n\n const onData = (data: Buffer) => {\n // 'q' key (0x71) or Ctrl+C (0x03) → cancel\n if (data[0] === 0x71 || data[0] === 0x03) {\n if (!this.cancelRequested) {\n this.cancelRequested = true;\n log.warn(\"⏹ キャンセルを要求しました...\");\n this.options.onCancel?.();\n }\n return;\n }\n // Enter key (0x0d) or 'p' key (0x70) → pause\n if (data[0] === 0x0d || data[0] === 0x70) {\n if (!this.pauseRequested) {\n this.pauseRequested = true;\n log.warn(\"⏸ 一時停止を要求しました。次のツール呼び出しで停止します...\");\n }\n }\n };\n\n process.stdin.setRawMode(true);\n process.stdin.resume();\n process.stdin.on(\"data\", onData);\n\n this.stdinCleanup = () => {\n process.stdin.off(\"data\", onData);\n try {\n process.stdin.setRawMode(false);\n } catch {\n // setRawMode failure is non-critical\n }\n process.stdin.pause();\n };\n }\n\n /**\n * 一時停止が要求されているか確認\n */\n isPauseRequested(): boolean {\n return this.pauseRequested;\n }\n\n /**\n * キャンセルが要求されているか確認\n */\n isCancelRequested(): boolean {\n return this.cancelRequested;\n }\n\n /**\n * 一時停止中にユーザーから介入指示を収集。\n * stdin raw mode を一時的に解除して @clack/prompts を使う。\n */\n async collectIntervention(\n currentStepIndex: number,\n currentUrl: string,\n ): Promise<InterventionResult> {\n this.suspendRawMode();\n this.options.onPause?.();\n\n try {\n log.info(\n `--- 一時停止 (ステップ #${currentStepIndex}, URL: ${currentUrl}) ---`,\n );\n\n const action = await promptSelect<InterventionAction>(\n \"操作を選択してください\",\n [\n {\n value: \"guidance\",\n label: \"ガイダンスを入力して続行\",\n hint: \"AIの探索方針を修正\",\n },\n { value: \"abort\", label: \"探索を中止\" },\n ],\n );\n\n if (action === \"abort\") {\n return { action: \"abort\" };\n }\n\n const guidanceText = await promptText(\"ガイダンス (AIへの指示)\", {\n validate: (v) =>\n !v?.trim() ? \"ガイダンスを入力してください\" : undefined,\n });\n\n const record: InterventionRecord = {\n stepIndex: currentStepIndex,\n userInstruction: guidanceText.trim(),\n url: currentUrl,\n timestamp: new Date().toISOString(),\n };\n this.interventions.push(record);\n\n log.success(`ガイダンスを記録しました: \"${guidanceText.trim()}\"`);\n\n return { action: \"guidance\", guidanceText: guidanceText.trim() };\n } finally {\n this.pauseRequested = false;\n this.resumeRawMode();\n this.options.onResume?.();\n }\n }\n\n /**\n * リスナーを停止しリソースを解放\n */\n dispose(): void {\n if (this.stdinCleanup) {\n this.stdinCleanup();\n this.stdinCleanup = null;\n }\n }\n\n private suspendRawMode(): void {\n if (this.stdinCleanup) {\n try {\n process.stdin.setRawMode(false);\n } catch {\n // non-critical\n }\n process.stdin.pause();\n }\n }\n\n private resumeRawMode(): void {\n if (this.stdinCleanup) {\n try {\n process.stdin.setRawMode(true);\n } catch {\n // non-critical\n }\n process.stdin.resume();\n }\n }\n}\n","/**\n * explorer — AI SDK generateText による探索ループ\n *\n * AgentBrowser を AI SDK tool 化し、generateText の tool-calling ループで\n * ゴール達成まで自律的に探索する。\n * prepareStep で古いスナップショットを刈り取り、トークン消費を抑制。\n */\n\nimport { AgentBrowser } from \"../browser/browser-client\";\nimport { exploreWithAI } from \"./exploration-agent\";\nimport type { AIModelProvider } from \"../harness/ai-service\";\nimport { InMemoryDataStore } from \"../context/data-store\";\nimport { DownloadManager } from \"../context/download-manager\";\nimport type { DownloadRecord } from \"../context/download-manager\";\nimport { log } from \"../cli/prompts\";\nimport { formatDuration } from \"../cli/format\";\nimport { createDebugLogger } from \"../cli/debug-logger\";\nimport { InterventionController } from \"./intervention-controller\";\nimport type { IInterventionController } from \"./intervention-controller\";\nimport type { GeneratorConfig, RecordedStep, InterventionRecord } from \"./types\";\nimport { t, tf } from \"../i18n\";\nimport { sleep } from \"../harness/sleep\";\nimport { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { initBuiltinSkills, createSkills } from \"../skills/registry\";\nimport type { Skill } from \"../skills/types\";\n\n/** 探索オプション: サーバー用に外部注入可能なパラメータ */\nexport interface ExploreOptions {\n /** 外部から注入する InterventionController(サーバー用 RemoteInterventionController) */\n interventionController?: IInterventionController;\n /** 外部から注入する AgentBrowser インスタンス(テスト・サーバー用) */\n browser?: AgentBrowser;\n /** Logger インスタンス(サーバー用にカスタム可能) */\n logger?: import(\"../logger\").Logger;\n /** AI モデル提供(DI) */\n aiProvider?: AIModelProvider;\n /** 外部から注入する DownloadManager(サーバー用) */\n downloadManager?: DownloadManager;\n /** 探索ステップ完了コールバック(SSE 発行 + DB 更新用) */\n onExplorerStep?: (stepNumber: number, description: string, step: RecordedStep) => Promise<void>;\n}\n\nexport async function explore(config: GeneratorConfig, options?: ExploreOptions): Promise<{\n recordedSteps: RecordedStep[];\n goalAchieved: boolean;\n additionalGuidance: string[];\n interventions: InterventionRecord[];\n cancelled: boolean;\n downloads: DownloadRecord[];\n error?: Error;\n}> {\n const browser = options?.browser ?? new AgentBrowser();\n const ownsBrowser = !options?.browser;\n const recordedSteps: RecordedStep[] = [];\n const debugLogger = createDebugLogger({\n filePath: config.debugLogPath,\n console: config.debugConsole,\n });\n const interventionController = options?.interventionController ?? new InterventionController();\n const downloadManager = options?.downloadManager\n ?? (config.screenshotDir ? new DownloadManager(join(config.screenshotDir, \"..\")) : undefined);\n\n // スクリーンショットディレクトリの準備\n if (config.screenshotDir) {\n await mkdir(config.screenshotDir, { recursive: true });\n }\n\n try {\n // 初期ページを開く\n log.step(tf(\"generator.openingUrl\", { url: config.url }));\n await browser.open(config.url, {\n headless: config.headless,\n stealth: config.stealth,\n proxy: config.proxy,\n });\n await sleep(1000); // ページロード待ち\n log.info(t(\"generator.pageLoaded\"));\n\n // 動画録画開始\n if (config.videoDir) {\n try {\n await browser.startRecording(config.videoDir);\n log.info(tf(\"generator.recordingStarted\", { path: config.videoDir }));\n } catch (e) {\n log.warn(tf(\"generator.recordingStartFailed\", { error: e instanceof Error ? e.message : String(e) }));\n }\n }\n\n // 初期画面のスクリーンショット保存\n if (config.screenshotDir) {\n try {\n const initialPath = join(config.screenshotDir, \"initial.png\");\n await browser.screenshot(initialPath);\n log.step(tf(\"generator.screenshotSaved\", { path: initialPath }));\n } catch {\n // スクリーンショット失敗は無視\n }\n }\n\n // 介入コントローラーにコールバックを設定\n interventionController.setCallbacks({\n onPause: () => log.info(t(\"generator.paused\")),\n onResume: () => log.step(t(\"generator.waitingForAI\")),\n onCancel: () => log.info(t(\"generator.cancelledByUser\")),\n });\n\n // DataStore 生成\n const dataStore = new InMemoryDataStore();\n\n // スキル解決\n let skills: Skill[] = [];\n if (config.skills && config.skills.length > 0) {\n await initBuiltinSkills();\n skills = createSkills(config.skills);\n log.info(`Skills: ${skills.map(s => s.name).join(\", \")}`);\n }\n\n const maxSteps = config.maxIterations * 3;\n\n log.step(t(\"generator.waitingForAI\"));\n interventionController.startListening();\n\n const agentStart = performance.now();\n const result = await exploreWithAI(browser, recordedSteps, {\n goal: config.goal,\n locale: config.locale,\n contextMarkdown: config.contextMarkdown,\n secrets: config.secrets,\n maxIterations: config.maxIterations,\n stepDelay: config.stepDelay,\n snapshotFilter: config.snapshotFilter,\n screenshotDir: config.screenshotDir,\n debugLogger,\n interventionController,\n historyWindow: config.historyWindow,\n enableMultiModel: config.enableMultiModel,\n skills: skills.length > 0 ? skills : undefined,\n aiProvider: options?.aiProvider,\n onToolCallStart: (stepCount) => {\n log.step(tf(\"generator.exploringStep\", { current: stepCount + 1, total: maxSteps }));\n },\n onToolCallEnd: () => {\n const lastStep = recordedSteps[recordedSteps.length - 1];\n if (lastStep && options?.onExplorerStep) {\n options.onExplorerStep(\n recordedSteps.length,\n lastStep.action.description ?? lastStep.action.action,\n lastStep,\n ).catch(() => {});\n }\n },\n }, dataStore, downloadManager);\n interventionController.dispose();\n log.info(tf(\"generator.explorationComplete\", { duration: formatDuration(performance.now() - agentStart) }));\n\n // 構造化出力からゴール達成を判定\n const { goalResult } = result;\n log.info(`Goal achieved: ${goalResult.goalAchieved}`);\n log.info(`Summary: ${goalResult.summary}`);\n log.info(`Tokens: prompt=${result.totalTokens.promptTokens}, completion=${result.totalTokens.completionTokens}, total=${result.totalTokens.totalTokens}`);\n\n // メモリデータ出力\n if (dataStore.listCollections().length > 0) {\n log.info(`Memory collections: ${dataStore.listCollections().join(\", \")}`);\n const memoryOutputDir = config.screenshotDir ? join(config.screenshotDir, \"..\") : undefined;\n if (memoryOutputDir) {\n for (const collection of dataStore.listCollections()) {\n const filePath = join(memoryOutputDir, `${collection}.json`);\n await dataStore.writeToFile(collection, filePath, \"json\");\n log.info(`Memory data exported: ${filePath}`);\n }\n }\n }\n\n // ダウンロードファイル一覧\n if (downloadManager && downloadManager.getDownloads().length > 0) {\n log.info(`Downloaded files: ${downloadManager.getDownloads().length}`);\n for (const dl of downloadManager.getDownloads()) {\n log.info(` - ${dl.filename} (${dl.path})`);\n }\n }\n\n await debugLogger.flush();\n\n const interventions = interventionController.interventions;\n const additionalGuidance = interventions.map((iv) => iv.userInstruction);\n\n return {\n recordedSteps,\n goalAchieved: goalResult.goalAchieved,\n additionalGuidance,\n interventions,\n cancelled: interventionController.isCancelRequested(),\n downloads: downloadManager?.getDownloads() ?? [],\n };\n } catch (err) {\n const interventions = interventionController.interventions;\n return {\n recordedSteps,\n goalAchieved: false,\n additionalGuidance: interventions.map((iv) => iv.userInstruction),\n interventions,\n cancelled: interventionController.isCancelRequested(),\n downloads: downloadManager?.getDownloads() ?? [],\n error: err instanceof Error ? err : new Error(String(err)),\n };\n } finally {\n try {\n interventionController.dispose();\n } catch {\n // dispose失敗は無視\n }\n // 動画録画停止\n if (browser.isRecording()) {\n try {\n const result = await browser.stopRecording();\n for (const p of result.paths) {\n log.info(tf(\"generator.recordingComplete\", { path: p }));\n }\n } catch (e) {\n log.warn(tf(\"generator.recordingStopFailed\", { error: e instanceof Error ? e.message : String(e) }));\n }\n }\n // 外部注入ブラウザの場合は呼び出し側が close する\n if (ownsBrowser) {\n try {\n await browser.close();\n } catch {\n // close失敗は無視\n }\n }\n }\n}\n","/**\n * runbook-builder — RecordedStep[] → YAML手順書変換\n *\n * ブラウザ/AI非依存の純粋関数。\n */\n\nimport { stringify } from \"yaml\";\nimport type { RecordedStep, ReviewResult, SuggestedCapture, InterventionRecord } from \"./types\";\nimport { findElementInSnapshot } from \"../browser/snapshot-parser\";\nimport { buildSelector } from \"../browser/selector-builder\";\nimport type { Selector, VariableSource, StepCapture } from \"../runbook-executor/types\";\nimport { ParsedRunbookSchema } from \"../schemas/runbook-schema\";\n\ninterface RunbookInput {\n goal: string;\n startUrl: string;\n recordedSteps: RecordedStep[];\n goalAchieved: boolean;\n stepDelay: number;\n contextMarkdown: string;\n reviewResult?: ReviewResult;\n humanGuidance?: string[];\n interventions?: InterventionRecord[];\n /** Skill 名リスト(YAML metadata に記録) */\n skills?: string[];\n}\n\n/** ExplorationAction.action → YAML action.type マッピング */\nfunction toActionType(\n action: string,\n): \"click\" | \"input\" | \"select\" | \"navigate\" | \"scroll\" | \"wait\" | \"hover\" | \"extract\" | \"download\" | \"export\" | \"memory\" | \"key\" {\n switch (action) {\n case \"fill\":\n case \"type\":\n return \"input\";\n case \"check\":\n case \"uncheck\":\n case \"click\":\n return \"click\";\n case \"select\":\n return \"select\";\n case \"navigate\":\n return \"navigate\";\n case \"scroll\":\n return \"scroll\";\n case \"wait\":\n return \"wait\";\n case \"extract\":\n return \"extract\";\n case \"download\":\n return \"download\";\n case \"export\":\n return \"export\";\n case \"memory_append\":\n case \"memory_aggregate\":\n return \"memory\";\n case \"key\":\n return \"key\";\n default:\n return \"click\";\n }\n}\n\n/** inputCategory → VariableSource マッピング */\nfunction categoryToSource(\n category: \"credential\" | \"user_data\" | \"fixed\" | \"navigation\" | undefined,\n): VariableSource {\n switch (category) {\n case \"credential\":\n return \"prompt\";\n case \"user_data\":\n return \"prompt\";\n case \"fixed\":\n return \"fixed\";\n case \"navigation\":\n return \"fixed\";\n default:\n return \"prompt\";\n }\n}\n\n/**\n * RecordedStep配列からYAML手順書文字列を生成\n */\nexport function buildRunbookYaml(input: RunbookInput): string {\n const { goal, startUrl, recordedSteps, goalAchieved, stepDelay, reviewResult, humanGuidance, interventions } = input;\n\n const successfulSteps = recordedSteps.filter((s) => s.success);\n\n // reviewResult がある場合、keep=true のステップのみ残す\n const reviewMap = new Map(\n reviewResult?.reviewedSteps.map((r) => [r.originalOrdinal, r]),\n );\n const filteredSteps = reviewResult\n ? successfulSteps.filter((s) => reviewMap.get(s.ordinal)?.keep !== false)\n : successfulSteps;\n\n // ── 変数定義の構築 ──\n const variables: Record<string, {\n source: VariableSource;\n description?: string;\n required?: boolean;\n sensitive?: boolean;\n value?: string;\n }> = {};\n\n // 変数名の重複管理(同じ名前の変数は1つだけ定義)\n const usedVariableNames = new Set<string>();\n\n filteredSteps.forEach((recorded) => {\n const { action } = recorded;\n const actionType = toActionType(action.action);\n\n if (actionType === \"input\" && action.value !== undefined) {\n const varName = action.variableName ?? `input_${recorded.ordinal}`;\n if (!usedVariableNames.has(varName)) {\n usedVariableNames.add(varName);\n const source = categoryToSource(action.inputCategory);\n variables[varName] = {\n source,\n description: action.description,\n ...(source === \"prompt\" && {\n required: true,\n sensitive: action.inputCategory === \"credential\",\n }),\n ...(source === \"fixed\" && { value: action.value }),\n };\n }\n }\n });\n\n // ── steps構築 ──\n const steps = filteredSteps.map((recorded, index) => {\n const actionType = toActionType(recorded.action.action);\n const review = reviewMap.get(recorded.ordinal);\n\n // スナップショットから要素を特定してSelectorを構築\n let selector: Selector | undefined;\n if (recorded.action.selector) {\n const ref = recorded.action.selector.replace(\"@\", \"\");\n const element = findElementInSnapshot(recorded.snapshotBefore, ref);\n if (element) {\n selector = buildSelector(element);\n } else if (recorded.resolvedElement) {\n // スナップショット破棄前に保存した要素メタデータを使用\n selector = recorded.resolvedElement;\n } else {\n // description をセレクタの ariaLabel に入れない。\n // AI セレクタ解決は stepDescription パラメータから description を受け取るため、\n // セレクタに重複した description テキストを入れると\n // 決定論的リゾルバが無関係な要素にマッチする原因になる。\n selector = { tagName: \"unknown\" };\n }\n }\n\n // input値を {{varName}} テンプレートに置換\n let value: string | undefined;\n if (actionType === \"input\" && recorded.action.value !== undefined) {\n const varName = recorded.action.variableName ?? `input_${recorded.ordinal}`;\n value = `{{${varName}}}`;\n }\n\n const step: Record<string, unknown> = {\n ordinal: index,\n description: recorded.action.description,\n action: {\n type: actionType,\n ...(selector && { selector }),\n ...(actionType === \"input\" && value !== undefined && { value }),\n ...(actionType === \"select\" && recorded.action.value !== undefined && {\n optionText: recorded.action.value,\n }),\n ...(actionType === \"navigate\" && recorded.action.value && {\n url: recorded.action.value,\n }),\n ...(actionType === \"extract\" && recorded.action.script && {\n script: recorded.action.script,\n }),\n ...(actionType === \"download\" && recorded.action.downloadPath && {\n downloadPath: recorded.action.downloadPath,\n }),\n ...(actionType === \"export\" && recorded.action.exportCollection && {\n exportCollection: recorded.action.exportCollection,\n }),\n ...(actionType === \"export\" && recorded.action.exportFormat && {\n exportFormat: recorded.action.exportFormat,\n }),\n ...(actionType === \"export\" && recorded.action.exportPath && {\n exportPath: recorded.action.exportPath,\n }),\n ...(actionType === \"key\" && {\n keys: recorded.action.keys ?? recorded.action.value,\n }),\n },\n url: recorded.url,\n riskLevel: review?.riskLevel ?? \"low\",\n requiresConfirmation: review?.requiresConfirmation ?? false,\n };\n\n // キャプチャ定義\n const captures = buildCaptures(recorded.action.suggestedCaptures);\n if (captures.length > 0) {\n step.captures = captures;\n }\n\n // メモリオペレーション定義\n if (recorded.action.action === \"memory_append\" && recorded.action.memoryCollection) {\n step.memoryOperations = [{\n type: \"append\" as const,\n collection: recorded.action.memoryCollection,\n source: recorded.action.variableName ?? \"extractedData\",\n }];\n } else if (recorded.action.action === \"memory_aggregate\" && recorded.action.aggregation) {\n const agg = recorded.action.aggregation;\n step.memoryOperations = [{\n type: \"aggregate\" as const,\n collection: agg.collection,\n field: agg.field,\n operation: agg.operation,\n outputVariable: agg.outputVariable,\n }];\n }\n\n return step;\n });\n\n // ── YAML構造構築 ──\n const baseUrl = new URL(startUrl).origin;\n\n const runbook: Record<string, unknown> = {\n title: goal,\n settings: {\n baseUrl,\n defaultTimeout: 10000,\n pauseBetweenSteps: stepDelay,\n stopOnError: true,\n },\n metadata: {\n startUrl,\n goal,\n goalAchieved,\n totalSteps: filteredSteps.length,\n generatedAt: new Date().toISOString(),\n ...(input.skills && input.skills.length > 0 && { skills: input.skills }),\n },\n context: input.contextMarkdown,\n };\n\n if (Object.keys(variables).length > 0) {\n runbook.variables = variables;\n }\n\n runbook.steps = steps;\n\n const allNotes: string[] = [];\n if (humanGuidance && humanGuidance.length > 0) {\n allNotes.push(\n ...humanGuidance.map((g, i) => `[方針修正 ${i + 1}] ${g}`),\n );\n }\n if (interventions && interventions.length > 0) {\n allNotes.push(\n ...interventions.map(\n (iv) => `[探索中介入 ステップ#${iv.stepIndex}] ${iv.userInstruction}`,\n ),\n );\n }\n if (allNotes.length > 0) {\n runbook.notes = allNotes.join(\"\\n\");\n }\n\n // ラウンドトリップ検証: 生成した構造が Zod スキーマに適合するか確認\n ParsedRunbookSchema.parse(runbook);\n\n return stringify(runbook, { lineWidth: 120 });\n}\n\n/**\n * SuggestedCapture[] → YAML用キャプチャ定義に変換\n */\nfunction buildCaptures(\n suggested: SuggestedCapture[] | undefined,\n): StepCapture[] {\n if (!suggested || suggested.length === 0) return [];\n\n return suggested.map((c) => ({\n name: c.name,\n strategy: c.strategy,\n required: false,\n ...(c.description && { description: c.description }),\n ...(c.pattern && { pattern: c.pattern }),\n ...(c.group !== undefined && c.group !== 1 && { group: c.group }),\n ...(c.prompt && { prompt: c.prompt }),\n ...(c.expression && { expression: c.expression }),\n }));\n}\n","/**\n * AI プロンプト\n *\n * 探索後のレビュー用プロンプトを提供。\n * 探索ループ自体は Mastra Agent (exploration-agent.ts) が担当。\n */\n\nimport { z } from \"zod\";\nimport {\n getReviewSystemPrompt,\n createReviewUserPrompt,\n} from \"../i18n/prompts\";\nimport type {\n RecordedStep,\n InterventionRecord,\n} from \"./types\";\n\nexport const reviewResponseSchema = z.object({\n reviewedSteps: z.array(z.object({\n originalOrdinal: z.number(),\n keep: z.boolean(),\n removalReason: z.string().optional(),\n riskLevel: z.enum([\"low\", \"medium\", \"high\"]),\n requiresConfirmation: z.boolean(),\n confirmationReason: z.string().optional(),\n })),\n summary: z.string(),\n});\n\n/**\n * ステップレビュー用プロンプトを生成(system / userPrompt 分離)\n */\nexport function createReviewPrompt(\n goal: string,\n recordedSteps: RecordedStep[],\n goalAchieved: boolean,\n interventions?: InterventionRecord[],\n locale?: \"en\" | \"ja\",\n): { system: string; userPrompt: string } {\n const system = getReviewSystemPrompt(locale);\n const userPrompt = createReviewUserPrompt(goal, recordedSteps, goalAchieved, interventions, locale);\n return { system, userPrompt };\n}\n"],"mappings":"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","names":["z","finalSnapshot","currentUrl","dataCollectionActionSet","hasDataCollectionHistory","explorationAction","result","getModel","trackedGenerateObject","z","z","z"]}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/schemas/runbook-schema.ts
|
|
4
|
+
import { z as z2 } from "zod";
|
|
5
|
+
|
|
6
|
+
// src/schemas/element-selector.ts
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
var ElementSelectorSchema = z.object({
|
|
9
|
+
/** id属性(最も信頼性が高い) */
|
|
10
|
+
id: z.string().optional(),
|
|
11
|
+
/** aria-label(アクセシビリティラベル) */
|
|
12
|
+
ariaLabel: z.string().optional(),
|
|
13
|
+
/** data-testid(テスト用ID) */
|
|
14
|
+
dataTestId: z.string().optional(),
|
|
15
|
+
/** その他のdata-*属性 */
|
|
16
|
+
dataAttributes: z.record(z.string(), z.string()).optional(),
|
|
17
|
+
/** CSSセレクタ */
|
|
18
|
+
cssSelector: z.string().optional(),
|
|
19
|
+
/** XPathセレクタ */
|
|
20
|
+
xPath: z.string().optional(),
|
|
21
|
+
/** label[for]のテキスト */
|
|
22
|
+
labelText: z.string().optional(),
|
|
23
|
+
/** 要素のinnerText */
|
|
24
|
+
innerText: z.string().max(200).optional(),
|
|
25
|
+
/** placeholder属性 */
|
|
26
|
+
placeholder: z.string().optional(),
|
|
27
|
+
/** name属性 */
|
|
28
|
+
name: z.string().optional(),
|
|
29
|
+
/** 位置ベースのフォールバック(最終手段) */
|
|
30
|
+
rect: z.object({
|
|
31
|
+
x: z.number(),
|
|
32
|
+
y: z.number(),
|
|
33
|
+
width: z.number(),
|
|
34
|
+
height: z.number()
|
|
35
|
+
}).optional(),
|
|
36
|
+
/** タグ名(必須) */
|
|
37
|
+
tagName: z.string(),
|
|
38
|
+
/** role属性 */
|
|
39
|
+
role: z.string().optional(),
|
|
40
|
+
/** input要素のtype属性 */
|
|
41
|
+
inputType: z.string().optional()
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// src/schemas/runbook-schema.ts
|
|
45
|
+
var SelectorSchema = ElementSelectorSchema.extend({
|
|
46
|
+
tagName: z2.string().default("unknown"),
|
|
47
|
+
text: z2.string().optional()
|
|
48
|
+
});
|
|
49
|
+
var ActionTypeSchema = z2.enum([
|
|
50
|
+
"click",
|
|
51
|
+
"input",
|
|
52
|
+
"select",
|
|
53
|
+
"navigate",
|
|
54
|
+
"scroll",
|
|
55
|
+
"wait",
|
|
56
|
+
"hover",
|
|
57
|
+
"extract",
|
|
58
|
+
"download",
|
|
59
|
+
"export",
|
|
60
|
+
"memory",
|
|
61
|
+
"key"
|
|
62
|
+
]);
|
|
63
|
+
var RiskLevelSchema = z2.enum(["low", "medium", "high"]);
|
|
64
|
+
var VariableSourceSchema = z2.enum([
|
|
65
|
+
"prompt",
|
|
66
|
+
"fixed",
|
|
67
|
+
"context",
|
|
68
|
+
"env",
|
|
69
|
+
"expression",
|
|
70
|
+
"data"
|
|
71
|
+
]);
|
|
72
|
+
var CaptureStrategySchema = z2.enum([
|
|
73
|
+
"snapshot",
|
|
74
|
+
"url",
|
|
75
|
+
"ai",
|
|
76
|
+
"expression",
|
|
77
|
+
"evaluate"
|
|
78
|
+
]);
|
|
79
|
+
var StepCaptureSchema = z2.object({
|
|
80
|
+
name: z2.string().min(1),
|
|
81
|
+
strategy: CaptureStrategySchema,
|
|
82
|
+
description: z2.string().optional(),
|
|
83
|
+
required: z2.boolean().default(false),
|
|
84
|
+
pattern: z2.string().optional(),
|
|
85
|
+
group: z2.number().int().nonnegative().optional(),
|
|
86
|
+
prompt: z2.string().optional(),
|
|
87
|
+
expression: z2.string().optional()
|
|
88
|
+
}).refine(
|
|
89
|
+
(c) => {
|
|
90
|
+
if (!c.pattern) return true;
|
|
91
|
+
try {
|
|
92
|
+
new RegExp(c.pattern);
|
|
93
|
+
return true;
|
|
94
|
+
} catch {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
{ message: "Invalid regex pattern in capture" }
|
|
99
|
+
);
|
|
100
|
+
var LoopDefinitionSchema = z2.object({
|
|
101
|
+
/** while 型ループの条件式 */
|
|
102
|
+
condition: z2.string().min(1).optional(),
|
|
103
|
+
/** forEach: 反復対象のテンプレート変数(JSON配列)または "collection:name" */
|
|
104
|
+
forEach: z2.string().min(1).optional(),
|
|
105
|
+
/** forEach 時の各アイテム変数名 */
|
|
106
|
+
itemVariable: z2.string().optional(),
|
|
107
|
+
/** forEach 時のインデックス変数名 */
|
|
108
|
+
indexVariable: z2.string().optional(),
|
|
109
|
+
maxIterations: z2.number().int().positive().optional(),
|
|
110
|
+
counterVariable: z2.string().optional()
|
|
111
|
+
}).refine(
|
|
112
|
+
(l) => {
|
|
113
|
+
const hasCondition = !!l.condition;
|
|
114
|
+
const hasForEach = !!l.forEach;
|
|
115
|
+
return (hasCondition || hasForEach) && !(hasCondition && hasForEach);
|
|
116
|
+
},
|
|
117
|
+
{ message: "loop must have exactly one of 'condition' or 'forEach'" }
|
|
118
|
+
);
|
|
119
|
+
var VariableDefinitionSchema = z2.object({
|
|
120
|
+
source: VariableSourceSchema,
|
|
121
|
+
description: z2.string().optional(),
|
|
122
|
+
required: z2.boolean().default(true),
|
|
123
|
+
sensitive: z2.boolean().default(false),
|
|
124
|
+
value: z2.string().optional(),
|
|
125
|
+
expression: z2.string().optional(),
|
|
126
|
+
envKey: z2.string().optional()
|
|
127
|
+
});
|
|
128
|
+
var StepActionSchema = z2.object({
|
|
129
|
+
type: ActionTypeSchema,
|
|
130
|
+
selector: SelectorSchema.optional(),
|
|
131
|
+
value: z2.string().optional(),
|
|
132
|
+
optionText: z2.string().optional(),
|
|
133
|
+
url: z2.string().optional(),
|
|
134
|
+
/** extract アクション用: ページ内で実行する JavaScript */
|
|
135
|
+
script: z2.string().optional(),
|
|
136
|
+
/** key アクション用: 押下するキーボードキー(Playwright 形式、例: "Enter", "Tab", "ArrowDown") */
|
|
137
|
+
keys: z2.string().optional(),
|
|
138
|
+
/** download アクション用: 保存先パス */
|
|
139
|
+
downloadPath: z2.string().optional(),
|
|
140
|
+
/** export アクション用: 出力対象コレクション名 */
|
|
141
|
+
exportCollection: z2.string().optional(),
|
|
142
|
+
/** export アクション用: 出力フォーマット */
|
|
143
|
+
exportFormat: z2.enum(["csv", "json"]).optional(),
|
|
144
|
+
/** export アクション用: 出力先パス */
|
|
145
|
+
exportPath: z2.string().optional()
|
|
146
|
+
});
|
|
147
|
+
var DataSourceConfigSchema = z2.object({
|
|
148
|
+
mapping: z2.record(z2.string(), z2.string())
|
|
149
|
+
});
|
|
150
|
+
var AggregateOperationSchema = z2.enum([
|
|
151
|
+
"sum",
|
|
152
|
+
"count",
|
|
153
|
+
"concat",
|
|
154
|
+
"min",
|
|
155
|
+
"max",
|
|
156
|
+
"avg",
|
|
157
|
+
"unique_count"
|
|
158
|
+
]);
|
|
159
|
+
var MemoryOperationSchema = z2.object({
|
|
160
|
+
/** append: 蓄積, aggregate: 集計 */
|
|
161
|
+
type: z2.enum(["append", "aggregate"]),
|
|
162
|
+
/** 対象コレクション名 */
|
|
163
|
+
collection: z2.string(),
|
|
164
|
+
/** append 時: capture 名(RuntimeStore のキー) */
|
|
165
|
+
source: z2.string().optional(),
|
|
166
|
+
/** aggregate 時: 集計対象フィールド名 */
|
|
167
|
+
field: z2.string().optional(),
|
|
168
|
+
/** aggregate 時: 集計操作 */
|
|
169
|
+
operation: AggregateOperationSchema.optional(),
|
|
170
|
+
/** aggregate 時: 結果を格納する変数名 */
|
|
171
|
+
outputVariable: z2.string().optional()
|
|
172
|
+
});
|
|
173
|
+
var BranchCaseSchema = z2.lazy(
|
|
174
|
+
() => z2.object({
|
|
175
|
+
match: z2.string(),
|
|
176
|
+
steps: z2.array(ParsedStepSchema).min(1)
|
|
177
|
+
})
|
|
178
|
+
);
|
|
179
|
+
var BranchDefinitionSchema = z2.lazy(
|
|
180
|
+
() => z2.object({
|
|
181
|
+
value: z2.string().min(1),
|
|
182
|
+
cases: z2.array(BranchCaseSchema).min(1),
|
|
183
|
+
default: z2.object({ steps: z2.array(ParsedStepSchema).min(1) }).optional()
|
|
184
|
+
})
|
|
185
|
+
);
|
|
186
|
+
var ParsedStepSchema = z2.lazy(
|
|
187
|
+
() => z2.object({
|
|
188
|
+
ordinal: z2.number().int().nonnegative(),
|
|
189
|
+
description: z2.string(),
|
|
190
|
+
action: StepActionSchema,
|
|
191
|
+
url: z2.string(),
|
|
192
|
+
riskLevel: RiskLevelSchema,
|
|
193
|
+
requiresConfirmation: z2.boolean(),
|
|
194
|
+
captures: z2.array(StepCaptureSchema).optional(),
|
|
195
|
+
condition: z2.string().optional(),
|
|
196
|
+
loop: LoopDefinitionSchema.optional(),
|
|
197
|
+
steps: z2.array(ParsedStepSchema).optional(),
|
|
198
|
+
branches: BranchDefinitionSchema.optional(),
|
|
199
|
+
memoryOperations: z2.array(MemoryOperationSchema).optional()
|
|
200
|
+
}).refine(
|
|
201
|
+
(s) => !(s.loop && s.branches),
|
|
202
|
+
{ message: "step cannot have both 'loop' and 'branches'" }
|
|
203
|
+
)
|
|
204
|
+
);
|
|
205
|
+
var ParsedRunbookSchema = z2.object({
|
|
206
|
+
title: z2.string(),
|
|
207
|
+
naturalLanguageSummary: z2.string().optional(),
|
|
208
|
+
settings: z2.object({
|
|
209
|
+
baseUrl: z2.string(),
|
|
210
|
+
defaultTimeout: z2.number().default(1e4),
|
|
211
|
+
pauseBetweenSteps: z2.number().default(500),
|
|
212
|
+
stopOnError: z2.boolean().default(true)
|
|
213
|
+
}),
|
|
214
|
+
metadata: z2.object({
|
|
215
|
+
startUrl: z2.string().min(1),
|
|
216
|
+
goal: z2.string(),
|
|
217
|
+
goalAchieved: z2.boolean(),
|
|
218
|
+
totalSteps: z2.number().int().nonnegative(),
|
|
219
|
+
generatedAt: z2.string(),
|
|
220
|
+
skills: z2.array(z2.string()).optional()
|
|
221
|
+
}),
|
|
222
|
+
steps: z2.array(ParsedStepSchema).min(1),
|
|
223
|
+
notes: z2.string().optional(),
|
|
224
|
+
context: z2.string().default(""),
|
|
225
|
+
variables: z2.record(z2.string(), VariableDefinitionSchema).optional(),
|
|
226
|
+
dataSource: DataSourceConfigSchema.optional()
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
export {
|
|
230
|
+
SelectorSchema,
|
|
231
|
+
ActionTypeSchema,
|
|
232
|
+
RiskLevelSchema,
|
|
233
|
+
VariableSourceSchema,
|
|
234
|
+
CaptureStrategySchema,
|
|
235
|
+
StepCaptureSchema,
|
|
236
|
+
LoopDefinitionSchema,
|
|
237
|
+
VariableDefinitionSchema,
|
|
238
|
+
StepActionSchema,
|
|
239
|
+
DataSourceConfigSchema,
|
|
240
|
+
AggregateOperationSchema,
|
|
241
|
+
MemoryOperationSchema,
|
|
242
|
+
ParsedStepSchema,
|
|
243
|
+
ParsedRunbookSchema
|
|
244
|
+
};
|
|
245
|
+
//# sourceMappingURL=chunk-RT664YIO.js.map
|