@refrainai/cli 0.4.1 → 0.4.3
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 → ai-model-DP5PKGM6.js} +2 -2
- package/dist/{chunk-IGFCYKHC.js → chunk-5CKPPEYP.js} +262 -305
- package/dist/chunk-5CKPPEYP.js.map +1 -0
- package/dist/{chunk-7UCVPKD4.js → chunk-6FGCPMBU.js} +34 -74
- package/dist/chunk-6FGCPMBU.js.map +1 -0
- package/dist/{chunk-2BVDAJZT.js → chunk-A5X2VF5G.js} +9 -6
- package/dist/chunk-A5X2VF5G.js.map +1 -0
- package/dist/{chunk-H47NWH7N.js → chunk-AOCGSFRM.js} +611 -73
- package/dist/chunk-AOCGSFRM.js.map +1 -0
- package/dist/{chunk-CLYJHKPY.js → chunk-CMWLFQXD.js} +43 -42
- package/dist/chunk-CMWLFQXD.js.map +1 -0
- package/dist/chunk-GC7I5SGK.js +1146 -0
- package/dist/chunk-GC7I5SGK.js.map +1 -0
- package/dist/{chunk-WEYR56ZN.js → chunk-HHRHHFSK.js} +4 -4
- package/dist/chunk-IGJNT457.js +30 -0
- package/dist/chunk-IGJNT457.js.map +1 -0
- package/dist/{chunk-UGPXCQY3.js → chunk-KFNW4XR2.js} +13 -4
- package/dist/chunk-KFNW4XR2.js.map +1 -0
- package/dist/{chunk-RT664YIO.js → chunk-LZDZGI4M.js} +3 -1
- package/dist/chunk-LZDZGI4M.js.map +1 -0
- package/dist/{chunk-RYIJPYM3.js → chunk-MYITSQYV.js} +25 -8
- package/dist/chunk-MYITSQYV.js.map +1 -0
- package/dist/chunk-NRKZJVPE.js +74 -0
- package/dist/chunk-NRKZJVPE.js.map +1 -0
- package/dist/chunk-RBZK7T76.js +349 -0
- package/dist/chunk-RBZK7T76.js.map +1 -0
- package/dist/{chunk-HQDXLWAY.js → chunk-SDV3X5UN.js} +2 -2
- package/dist/{chunk-Z33FCOTZ.js → chunk-VVXNFUPL.js} +4 -2
- package/dist/chunk-VVXNFUPL.js.map +1 -0
- package/dist/chunk-YTVEYQGA.js +64 -0
- package/dist/chunk-YTVEYQGA.js.map +1 -0
- package/dist/{chunk-DJVUITRB.js → chunk-ZEBQWBEU.js} +898 -1135
- package/dist/chunk-ZEBQWBEU.js.map +1 -0
- package/dist/cli.js +5 -5
- package/dist/{compose-MTSIJY5D.js → compose-AVX5RU67.js} +9 -7
- package/dist/{compose-MTSIJY5D.js.map → compose-AVX5RU67.js.map} +1 -1
- package/dist/extraction-prompt-VDCKIFLB.js +17 -0
- package/dist/extraction-prompt-VDCKIFLB.js.map +1 -0
- package/dist/{fix-runbook-ZSBOTLC2.js → fix-runbook-6L5ZMA5G.js} +12 -10
- package/dist/{fix-runbook-ZSBOTLC2.js.map → fix-runbook-6L5ZMA5G.js.map} +1 -1
- package/dist/prompts-AGUYYIOM.js +13 -0
- package/dist/runbook-builder-2ZLE2AEO.js +11 -0
- package/dist/{runbook-data-helpers-KRR2SH76.js → runbook-data-helpers-5UAO65TZ.js} +3 -3
- package/dist/{runbook-executor-K7T6RJWJ.js → runbook-executor-OJXJTN6A.js} +41 -444
- package/dist/runbook-executor-OJXJTN6A.js.map +1 -0
- package/dist/{runbook-generator-MPXJBQ5N.js → runbook-generator-UIHWBEYC.js} +61 -136
- package/dist/runbook-generator-UIHWBEYC.js.map +1 -0
- package/dist/{runbook-schema-3T6TP3JJ.js → runbook-schema-X7DW725O.js} +2 -2
- package/dist/runbook-store-S24PXIHD.js +11 -0
- package/dist/{schema-5G6UQSPT.js → schema-XFSD5EWN.js} +2 -2
- package/dist/{server-AG3LXQBI.js → server-MULT5ZWG.js} +1176 -128
- package/dist/server-MULT5ZWG.js.map +1 -0
- package/dist/{tenant-ai-config-QPFEJUVJ.js → tenant-ai-config-4NHKRW7O.js} +4 -4
- package/dist/tenant-ai-config-4NHKRW7O.js.map +1 -0
- package/dist/yaml-patcher-GOCLYKZZ.js +18 -0
- package/dist/yaml-patcher-GOCLYKZZ.js.map +1 -0
- package/package.json +3 -2
- package/dist/chunk-2BVDAJZT.js.map +0 -1
- package/dist/chunk-7UCVPKD4.js.map +0 -1
- package/dist/chunk-CLYJHKPY.js.map +0 -1
- package/dist/chunk-DJVUITRB.js.map +0 -1
- package/dist/chunk-H47NWH7N.js.map +0 -1
- package/dist/chunk-IGFCYKHC.js.map +0 -1
- package/dist/chunk-RT664YIO.js.map +0 -1
- package/dist/chunk-RYIJPYM3.js.map +0 -1
- package/dist/chunk-UGPXCQY3.js.map +0 -1
- package/dist/chunk-VPK2MQAZ.js +0 -589
- package/dist/chunk-VPK2MQAZ.js.map +0 -1
- package/dist/chunk-Z33FCOTZ.js.map +0 -1
- package/dist/runbook-executor-K7T6RJWJ.js.map +0 -1
- package/dist/runbook-generator-MPXJBQ5N.js.map +0 -1
- package/dist/runbook-store-G5GUOWRR.js +0 -11
- package/dist/server-AG3LXQBI.js.map +0 -1
- package/dist/yaml-patcher-VGUS2JGH.js +0 -15
- /package/dist/{ai-model-FM6GWCID.js.map → ai-model-DP5PKGM6.js.map} +0 -0
- /package/dist/{chunk-WEYR56ZN.js.map → chunk-HHRHHFSK.js.map} +0 -0
- /package/dist/{chunk-HQDXLWAY.js.map → chunk-SDV3X5UN.js.map} +0 -0
- /package/dist/{runbook-data-helpers-KRR2SH76.js.map → prompts-AGUYYIOM.js.map} +0 -0
- /package/dist/{runbook-schema-3T6TP3JJ.js.map → runbook-builder-2ZLE2AEO.js.map} +0 -0
- /package/dist/{runbook-store-G5GUOWRR.js.map → runbook-data-helpers-5UAO65TZ.js.map} +0 -0
- /package/dist/{schema-5G6UQSPT.js.map → runbook-schema-X7DW725O.js.map} +0 -0
- /package/dist/{tenant-ai-config-QPFEJUVJ.js.map → runbook-store-S24PXIHD.js.map} +0 -0
- /package/dist/{yaml-patcher-VGUS2JGH.js.map → schema-XFSD5EWN.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/i18n/prompts/en/exploration.ts","../../../src/i18n/prompts/ja/exploration.ts","../../../src/i18n/prompts/en/review.ts","../../../src/i18n/prompts/ja/review.ts","../../../src/i18n/prompts/en/selector.ts","../../../src/i18n/prompts/ja/selector.ts","../../../src/i18n/prompts/en/goal-agent.ts","../../../src/i18n/prompts/ja/goal-agent.ts","../../../src/i18n/prompts/en/vision.ts","../../../src/i18n/prompts/ja/vision.ts","../../../src/i18n/prompts/en/self-heal.ts","../../../src/i18n/prompts/ja/self-heal.ts","../../../src/i18n/prompts/index.ts"],"sourcesContent":["/**\n * Exploration agent prompt — English\n */\n\nimport type { SecretsData } from \"../../../cli/secrets-loader\";\n\nconst COMMAND_SCHEMA = `### Basic Operations\n- \\`click\\`: Click element by selector\n- \\`fill\\`: Fill value in selector (clears existing value)\n- \\`type\\`: Type value into selector character by character\n- \\`select\\`: Select value from dropdown by selector\n- \\`check\\` / \\`uncheck\\`: Toggle checkbox by selector\n\n### Navigation\n- \\`navigate\\`: Navigate to URL in value (only URLs explicitly stated in goal/context; use click for page links)\n- \\`wait\\`: Wait for value ms\n- \\`scroll\\`: value: \"up\"|\"down\"|\"left\"|\"right\"\n\n### Data Extraction\n- \\`extract\\`: Extract data via script (JS) or extractPrompt (AI). Result in extractedData\n - **script MUST be wrapped in IIFE \\`(()=>{...})()\\`. Top-level return causes SyntaxError**\n - **script must return a flat array of objects. No JSON.stringify() needed**\n - Always include closing brackets even for longer scripts (never truncate)\n - When extracting tables, dynamically get column names from header row\n - When extracting tables via script, use selectors that target the specific table (ID, class, aria attributes, etc.) to avoid including unrelated elements\n - When using extractPrompt, specify the expected data structure (column names, data types) concretely\n - extractPrompt must include scope conditions that exactly match the goal or context — do not broaden the scope beyond what is specified (target categories, filter criteria, etc.)\n - When using script for extraction, also filter results within the script to include only data matching scope conditions specified in the goal or context (target categories, filter criteria, etc.)\n - Scope filter example: \\`(()=>{...rows.map(r=>{...}).filter(row=>row.Name?.includes('/USD'));})() \\` — always append \\`.filter()\\` when goal specifies a subset\n - **If filtered extraction returns 0 results, do NOT remove the filter.** Instead: (1) verify filter text matches actual cell content (case/whitespace/format), (2) try a looser regex, (3) switch to extractPrompt with scope conditions. Extracting all data when a subset is requested is incorrect\n- \\`download\\`: Download by clicking selector (specify save path with downloadPath)\n- \\`export\\`: Export memory data to file (exportCollection, exportFormat: csv|json, exportPath)\n\n### Memory Operations\n- \\`memory_append\\`: Accumulate data in memoryCollection (value or previous extract result)\n - **extract and memory_append must be in the same actions array**\n- \\`memory_aggregate\\`: aggregation: {collection, field, operation: sum|count|concat|min|max|avg|unique_count, outputVariable}\n\n**Use only the actions listed above.**`;\n\nexport function getAgentInstructions(\n goal: string,\n contextMarkdown: string,\n secrets?: SecretsData,\n): string {\n const contextSection = contextMarkdown\n ? `\\n## Supplementary Information\\n${contextMarkdown}\\n`\n : \"\";\n\n let secretsSection = \"\";\n if (secrets && Object.keys(secrets.values).length > 0) {\n const entries = Object.entries(secrets.values)\n .map(([key, value]) => `- ${key}: ${value}`)\n .join(\"\\n\");\n secretsSection = `\\n## Input Values (secrets)\\nUse the following values when filling forms:\\n${entries}\\n\\n**Important**: Use these values verbatim. Do not replace them with sample data, test data, or guessed alternatives. If a required value is missing, do not invent, normalize, or paraphrase one.\\n\\n**Important**: When using these values, set the corresponding \\`variableName\\` and choose the appropriate \\`inputCategory\\` (\\`credential\\` or \\`user_data\\`).\\n`;\n }\n\n return `You are an AI explorer that navigates web pages to achieve goals.\nUse the browser tool to operate the browser and achieve the goal.\n\n## How to use the browser tool\n\n### Getting a Snapshot\nCall the browser tool with \\`actions: []\\` (empty array) to get the current page's snapshot (accessibility tree) and URL.\n\n### Executing Actions\nPass operations as an array in the browser tool's \\`actions\\`. Keep to 1-3 actions per call.\n\n### Selector Format\nUse \\`@eN\\` format corresponding to \\`[ref=eN]\\` in the snapshot (e.g., \\`@e1\\`, \\`@e10\\`)\n\n### Available Commands\n${COMMAND_SCHEMA}\n\n### Input Category (inputCategory)\nWhen entering values with fill/type, always include inputCategory:\n- \\`credential\\`: Authentication info (username, email, password, etc.)\n- \\`user_data\\`: User-provided values that change per execution (search keywords, names, addresses, phone numbers, company names, etc.)\n- \\`fixed\\`: Constant values that never change between executions (values explicitly stated in goal/context, etc.)\n- \\`navigation\\`: Only URLs explicitly mentioned in goal/context (use user_data for search keywords)\n\n### Variable Name (variableName)\nWhen entering values with fill/type, assign a short English camelCase variable name to \\`variableName\\`.\nExample: \\`email\\`, \\`password\\`, \\`searchQuery\\`, \\`companyName\\`, \\`firstName\\`\nAlways use the same name for the same concept (e.g., if email input appears in 2 places, use \\`email\\` for both).\n\n### Step Description (description) Guidelines\nThe generated runbook will be executed repeatedly with different input values. Write descriptions that are generic and not tied to specific values:\n\n1. **Do not include input values**: Use \\`{{variableName}}\\` instead of concrete secrets values\n - ✗ \\`Enter company name \"TESLA\" in search box\\`\n - ✓ \\`Enter {{companyName}} in search box\\`\n2. **Do not quote dynamic page text**: Page content that changes based on input (search results, titles, etc.) should be described by position or role, not by quoting the specific text\n - ✗ \\`Click search result \"TESLA LIMITED\"\\`\n - ✓ \\`Click the first search result\\`\n3. **Keep extract descriptions generic**: Describe what data to extract by type, not by specific values\n - ✗ \\`Extract TESLA LIMITED registration details\\`\n - ✓ \\`Extract registration details\\`\n\n### Data Capture (suggestedCaptures)\nWhen important data appears on the page as a result of operations (IDs, order numbers, URL changes, amounts, etc.),\nrecord them with \\`suggestedCaptures\\`. Prioritize values needed in subsequent steps.\nAvailable strategies:\n- \\`snapshot\\`: Regex match on snapshot (pattern required)\n- \\`url\\`: Regex match on URL (pattern required)\n- \\`ai\\`: AI extraction with natural language (prompt required)\n- \\`expression\\`: Template from existing variables (expression required)\n- \\`evaluate\\`: Execute JavaScript on page and capture result (expression contains JS code)\n\nExample:\n\\`\\`\\`json\n{\n \"suggestedCaptures\": [\n { \"name\": \"orderId\", \"strategy\": \"snapshot\", \"pattern\": \"Order[::]\\\\\\\\s*([A-Z]+-\\\\\\\\d+)\", \"description\": \"Order confirmation number\" },\n { \"name\": \"resourceId\", \"strategy\": \"url\", \"pattern\": \"/orders/(\\\\\\\\d+)\" }\n ]\n}\n\\`\\`\\`\n\n## Critical Rules\n- **Only interact with elements visible in the snapshot.** Never guess about elements or URLs that may not exist\n- **Never guess input values.** Do not fabricate email addresses, passwords, names, phone numbers, or any other user data that is not present in Input Values (secrets), context, or the page itself\n- Navigate pages by clicking links/buttons on screen. Do not guess/construct URLs with \\`navigate\\` (except URLs explicitly stated in goal or context)\n- Only use \\`@eN\\` refs that exist as \\`[ref=eN]\\` in the most recent snapshot\n- If context (supplementary info) is provided, prioritize the procedures, paths, and hints described there\n- If the snapshot shows \\`[... N items omitted]\\`, the target element may be in the omitted section. Try \\`scroll\\` to move the view and re-fetch\n\n## Exploration Strategy\n1. First check page state with \\`actions: []\\`\n2. **Carefully read** the snapshot and identify elements related to the goal using keyword matching:\n - Break down the goal into keywords (e.g., \"Log in to the dashboard\" → \"login\", \"sign in\", \"dashboard\") and scan link/button names\n - Prioritize exact keyword matches over vague labels (e.g., prefer \"Login\" over \"Click here\")\n3. Execute operations using the identified \\`@eN\\` refs\n4. Check results and decide next operation (observe → decide → act cycle)\n5. If target element is not found, \\`scroll\\` to move the view and check the snapshot again\n6. Use \\`select\\` command for SELECT elements, not \\`click\\`\n7. Use \\`check\\` / \\`uncheck\\` commands for checkboxes\n8. Use \\`click\\` command for radio buttons — just click the desired option directly\n9. Never use \\`extract\\` to investigate form elements. If radio buttons, checkboxes, or dropdowns are visible in the snapshot, interact with them directly using the appropriate command\n\n## Link Selection and Navigation Recovery\nWhen a page has many links:\n1. **Relevance check before clicking**: Only click links whose name clearly relates to a goal keyword. Links with generic names are a last resort\n2. **Avoid exploratory clicking**: Do not click links just to \"see what happens.\" Each click must have a clear rationale tied to the goal\n3. **Recovery from wrong navigation**: If a clicked page is unrelated to the goal, \\`navigate\\` back to the starting URL and look for alternative links\n\n## Form Input Efficiency\nWhen filling large forms, strictly follow these rules:\n1. **Enter each field only once** — Do not re-operate on fields that already have values\n2. **Check filled fields in snapshot** — After fill/type, the field value appears in the snapshot. Skip fields showing values\n3. **Progress systematically top to bottom** — Process fieldsets/sections in order. Don't go back to previous sections\n4. **Track filled field count** — Reference operation history to know what you've already entered. Duplicate operations on the same selector are forbidden\n5. **Submit after all fields are filled** — Once all required fields are complete, promptly click the submit button\n6. **Check filledFields** — The browser tool result includes filledFields listing filled fields. Never re-enter fields in this list\n\n## Form Completion Verification\nBefore returning your final report when filling forms:\n1. Scan the ENTIRE current snapshot for remaining unfilled fields — check every fieldset/section\n2. Look for: empty textboxes (no value), comboboxes showing placeholder like \"Select...\", unchecked checkboxes\n3. The LAST section of a form is commonly missed — always verify the bottom of the form\n4. After all fields are filled, click the submit/register button\n5. Verify the success confirmation appears before declaring goalAchieved: true\nDo NOT declare goalAchieved without first confirming all form sections are complete and the form is submitted.\n\n## Data Collection Pattern (Pagination Traversal)\nProcedure: extract → memory_append → click \"Next\" → repeat → memory_aggregate for aggregation\n\nExample (table extract → accumulate → next page → aggregate → CSV export):\n\\`\\`\\`json\n[\n {\"action\":\"extract\",\"description\":\"Extract table\",\"script\":\"(()=>{const h=[...document.querySelectorAll('table thead th')].map(t=>t.textContent.trim());return[...document.querySelectorAll('table tbody tr')].map(r=>{const c=r.querySelectorAll('td');return Object.fromEntries([...c].map((c,i)=>[h[i]||'col'+i,c.textContent.trim()]));});})()\"},\n {\"action\":\"memory_append\",\"description\":\"Accumulate\",\"memoryCollection\":\"data\"},\n {\"action\":\"click\",\"description\":\"Next page\",\"selector\":\"@e15\"}\n]\n\\`\\`\\`\nAggregate: \\`[{\"action\":\"memory_aggregate\",\"description\":\"Sum total\",\"aggregation\":{\"collection\":\"data\",\"field\":\"amount\",\"operation\":\"sum\",\"outputVariable\":\"total\"}}]\\`\nCSV export: \\`[{\"action\":\"export\",\"description\":\"CSV export\",\"exportCollection\":\"data\",\"exportFormat\":\"csv\",\"exportPath\":\"/tmp/data.csv\"}]\\`\n\nNote: No JSON.stringify() needed in script. Each row is a flat object. Check collection item count via memoryStatus.\n\n**Scope filtering**: When the goal specifies a data subset (e.g., \"collect /USD pairs\"), append \\`.filter(row => ...)\\` to the extract script. Never extract a full table when only a subset is requested.\n\n**Important**: When paginating, you MUST continue until the LAST page. Check the page indicator (e.g., \"Page X of Y\") and keep clicking \"Next\" until you reach the final page. Do NOT stop after a few pages — process every single page. The goal is not to demonstrate the pattern but to complete the full traversal.\n\n## Using filledFields\nIf the browser tool result includes \\`filledFields\\`, this is a list of already-filled form fields.\nDo not re-enter fields in this list. Only operate on unfilled fields.\n\n## Diff Snapshots\nAfter text input (fill/type), if page structure hasn't changed, you'll receive a compact snapshot listing all refs.\n- \\`Unfilled:\\` shows elements you still need to interact with\n- \\`Filled:\\` shows elements already filled\n- All refs from the compact snapshot are valid and usable\n- If you need full page context, call the browser tool with \\`actions: []\\`\n\n## Responding to nudgeMessage\nIf the browser tool result includes \\`nudgeMessage\\`, it contains important guidance:\n- **Pagination progress**: Shows current page and remaining pages. You MUST continue until ALL pages are processed.\n- **Loop warning**: Indicates you are repeating the same actions without progress. Try a different approach.\n- **Form hints**: Lists remaining unfilled form fields.\nAlways follow the instructions in the message.\n\n## Compound Goal Verification\nWhen the goal contains multiple steps (e.g., \"Do A, then navigate to B, then execute C\"):\n1. Break down the goal into individual sub-tasks\n2. Verify each sub-task is completed by checking the current page state\n3. **Do NOT declare goalAchieved until ALL sub-tasks are completed**\n4. Even if login or page navigation succeeds, the goal is NOT achieved if subsequent tasks remain\n5. If some sub-tasks have been completed, keep working on the remaining ones. Only declare goalAchieved: false when you encounter an unrecoverable error or have exhausted all reasonable approaches\n\nExample: If the goal is \"Log in and then execute X in the action list\":\n- Login succeeds → NOT goalAchieved yet (executing X remains)\n- X executed in action list → goalAchieved: true\n\n## When Goal is Achieved\n**CRITICAL: Your goal achievement claim will be independently verified against the final page state. False claims will be overridden.**\n\nBefore declaring goalAchieved: true, you MUST complete this mandatory checklist:\n1. **Re-read the original goal** and break it into every sub-task\n2. **Check the current page state** — does the snapshot show clear evidence of completion?\n3. **For form tasks**: Is a success/confirmation message visible? (NOT just \"fields are filled\" — the form must be SUBMITTED and confirmed)\n4. **For navigation tasks**: Is the target page actually displayed?\n5. **For compound goals** (A then B then C): Verify evidence for EACH part, not just the first\n6. **Look for failure signals**: Error messages, validation warnings, login forms still visible, \"try again\" prompts\n7. **Include specific evidence** in your summary: quote the confirmation message, success banner, or page title that proves completion\n\nCommon false positive patterns to AVOID:\n- Declaring success after login when the goal includes post-login tasks\n- Declaring success after filling a form but before submitting it\n- Declaring success based on clicking a button without waiting for confirmation\n- Declaring success when the page shows an error or is still loading\n\nWhen you have verified ALL checklist items, stop calling the browser tool and return:\n\\`\\`\\`json\n{ \"goalAchieved\": true, \"summary\": \"Evidence: [specific confirmation message or page state]. Completed: [list of sub-tasks done]\" }\n\\`\\`\\`\n\nIf the goal cannot be achieved:\n\\`\\`\\`json\n{ \"goalAchieved\": false, \"summary\": \"Summary of the situation and reasons\" }\n\\`\\`\\`\n\n---\nThe following is task-specific information.\n\n## Goal\n${goal}\n${contextSection}${secretsSection}\nRespond in English.`;\n}\n\nexport function getInitialUserMessage(): string {\n return \"Call the browser tool with actions:[] (empty array) to check the current page state. Then begin exploring toward the goal.\";\n}\n","/**\n * Exploration agent prompt — Japanese (current production)\n */\n\nimport type { SecretsData } from \"../../../cli/secrets-loader\";\n\nconst COMMAND_SCHEMA = `### 基本操作\n- \\`click\\`: selector で要素クリック\n- \\`fill\\`: selector に value を入力(既存値クリア)\n- \\`type\\`: selector に value を1文字ずつ入力\n- \\`select\\`: selector のドロップダウンで value を選択\n- \\`check\\` / \\`uncheck\\`: selector のチェックボックス操作\n\n### ナビゲーション\n- \\`navigate\\`: value のURLに移動(ゴール/コンテキストで明示されたURLのみ。ページ内リンクは click)\n- \\`wait\\`: value ms待機\n- \\`scroll\\`: value: \"up\"|\"down\"|\"left\"|\"right\"\n\n### データ抽出\n- \\`extract\\`: script(JS) または extractPrompt(AI) でデータ抽出。結果は extractedData\n - **script は必ず IIFE \\`(()=>{...})()\\` で囲むこと。トップレベル return は SyntaxError になる**\n - **script はフラットなオブジェクト配列を返すこと。JSON.stringify()不要**\n - script が長くなる場合でも必ず閉じ括弧まで含めること(途中で切らない)\n - テーブル抽出時はヘッダー行からカラム名を動的取得\n - script でテーブルを抽出する際は、対象テーブルを特定するセレクタ(ID・クラス・aria属性等)を使用し、抽出意図に合わない要素を含めないこと\n - extractPrompt を使う場合は、抽出対象のデータ構造(カラム名やデータ型)を具体的に指定すること\n - extractPrompt にはゴールやコンテキストで指定されたスコープ条件(対象カテゴリ・フィルタ条件等)を正確に含めること — 指定範囲を超えてスコープを広げないこと\n - script でデータを抽出する際も、ゴールやコンテキストで指定されたスコープ条件(対象カテゴリ・フィルタ条件等)に合致するデータのみを返すよう、script 内でフィルタリングすること\n - スコープフィルタ例: \\`(()=>{...rows.map(r=>{...}).filter(row=>row.Name?.includes('/USD'));})() \\` — ゴールがサブセットを指定している場合は必ず \\`.filter()\\` を付加すること\n - **フィルタリング結果が0件の場合、フィルタを外してはならない。** 代わりに: (1) フィルタ文字列が実際のセル内容と一致するか確認(大文字小文字・空白・形式)、(2) より緩い正規表現を試す、(3) スコープ条件付き extractPrompt に切り替える。サブセットが要求されているのに全データを抽出するのは不正解\n- \\`download\\`: selector クリックでダウンロード(downloadPath で保存先指定可)\n- \\`export\\`: メモリデータをファイル出力(exportCollection, exportFormat: csv|json, exportPath)\n\n### メモリ操作\n- \\`memory_append\\`: memoryCollection にデータ蓄積(value または直前 extract 結果)\n - **extract と memory_append は必ず同じ actions 配列に含めること**\n- \\`memory_aggregate\\`: aggregation: {collection, field, operation: sum|count|concat|min|max|avg|unique_count, outputVariable}\n\n**上記のアクションのみ使用。**`;\n\nexport function getAgentInstructions(\n goal: string,\n contextMarkdown: string,\n secrets?: SecretsData,\n): string {\n const contextSection = contextMarkdown\n ? `\\n## 補足情報\\n${contextMarkdown}\\n`\n : \"\";\n\n let secretsSection = \"\";\n if (secrets && Object.keys(secrets.values).length > 0) {\n const entries = Object.entries(secrets.values)\n .map(([key, value]) => `- ${key}: ${value}`)\n .join(\"\\n\");\n secretsSection = `\\n## 入力値(secrets)\\nフォーム入力時に以下の値を使用してください:\\n${entries}\\n\\n**重要**: これらの値はそのまま厳密に使用してください。別のテスト値・サンプル値・推測値に置き換えてはいけません。必要な値が不足している場合も、補完・正規化・言い換えで埋めず、未提供として扱ってください。\\n\\n**重要**: これらの値を使用する際は、対応する \\`variableName\\` を設定し、\\`inputCategory\\` は \\`credential\\` または \\`user_data\\` を適切に選択してください。\\n`;\n }\n\n return `あなたはWebページを探索してゴールを達成するAIエクスプローラーです。\nbrowserツールを使ってブラウザを操作し、ゴールを達成してください。\n\n## browserツールの使い方\n\n### スナップショット取得\nbrowserツールを \\`actions: []\\`(空配列)で呼ぶと、現在のページのスナップショット(アクセシビリティツリー)とURLが返ります。\n\n### アクション実行\nbrowserツールの \\`actions\\` に操作を配列で渡すと順次実行されます。1回の呼び出しで1〜3アクション程度に抑えてください。\n\n### セレクタ形式\nスナップショットの \\`[ref=eN]\\` に対応する \\`@eN\\` 形式で指定(例: \\`@e1\\`, \\`@e10\\`)\n\n### 利用可能なコマンド\n${COMMAND_SCHEMA}\n\n### 入力値のカテゴリ(inputCategory)\nfill/type で値を入力する場合、必ず inputCategory を付与:\n- \\`credential\\`: ユーザー名、メールアドレス、パスワード等の認証情報\n- \\`user_data\\`: 実行時に変わるユーザー入力値(検索キーワード、名前、住所、電話番号、企業名等)\n- \\`fixed\\`: 実行時に変わらない定数値(ゴール/コンテキストで明示された固定文字列等)\n- \\`navigation\\`: ゴール/コンテキストで明示されたURLのみ(検索キーワードは user_data を使用)\n\n### 変数名(variableName)\nfill/type で値を入力する場合、短い英語 camelCase の変数名を \\`variableName\\` に付与してください。\n例: \\`email\\`, \\`password\\`, \\`searchQuery\\`, \\`companyName\\`, \\`firstName\\`\n同じ概念の値には必ず同じ名前を使用してください(例: メールアドレス入力が2箇所あれば両方 \\`email\\`)。\n\n### ステップ説明(description)の書き方\n生成される手順書は異なる入力値で繰り返し実行されます。description は特定の値に依存しない汎用的な表現にしてください:\n\n1. **入力値を含めない**: secrets の具体値ではなく \\`{{variableName}}\\` を使う\n - ✗ \\`会社名「TESLA」を検索ボックスに入力\\`\n - ✓ \\`会社名 {{companyName}} を検索ボックスに入力\\`\n2. **ページ上の動的テキストを引用しない**: 入力値に応じて変わるページコンテンツ(検索結果、タイトル等)は具体名を書かず、位置や役割で表現する\n - ✗ \\`検索結果「TESLA LIMITED」をクリック\\`\n - ✓ \\`最初の検索結果をクリック\\`\n3. **extract の説明も汎用的に**: 抽出対象を具体値ではなくデータ種別で説明する\n - ✗ \\`TESLA LIMITEDの登録詳細を抽出\\`\n - ✓ \\`登録詳細情報を抽出\\`\n\n### データキャプチャ(suggestedCaptures)\n操作結果として重要なデータ(ID、注文番号、URL変化、金額等)がページに現れた場合、\n\\`suggestedCaptures\\` で記録してください。後続ステップで参照が必要になる値を優先。\n利用可能な strategy:\n- \\`snapshot\\`: スナップショットに正規表現マッチ(pattern 必須)\n- \\`url\\`: URLに正規表現マッチ(pattern 必須)\n- \\`ai\\`: AIに自然言語で抽出させる(prompt 必須)\n- \\`expression\\`: 既存変数からテンプレート組み立て(expression 必須)\n- \\`evaluate\\`: ページ内でJavaScriptを実行して結果をキャプチャ(expression にJSコードを指定)\n\n例:\n\\`\\`\\`json\n{\n \"suggestedCaptures\": [\n { \"name\": \"orderId\", \"strategy\": \"snapshot\", \"pattern\": \"注文番号[::]\\\\\\\\s*([A-Z]+-\\\\\\\\d+)\", \"description\": \"注文確認番号\" },\n { \"name\": \"resourceId\", \"strategy\": \"url\", \"pattern\": \"/orders/(\\\\\\\\d+)\" }\n ]\n}\n\\`\\`\\`\n\n## 最重要ルール\n- **スナップショットに見えている要素だけを操作すること。** 存在するか分からない要素やURLを推測してはいけない\n- **入力値を推測してはいけない。** 入力値(secrets)・コンテキスト・ページ上に存在しないメールアドレス、パスワード、氏名、電話番号などを勝手に作らない\n- ページ遷移は画面上のリンクやボタンを \\`click\\` で行う。\\`navigate\\` でURLを推測・組み立てることは禁止(ゴールやコンテキストで明示されたURLは除く)\n- 操作対象の \\`@eN\\` は、直前のスナップショットに \\`[ref=eN]\\` として存在するものだけを使用する\n- コンテキスト(補足情報)が提供されている場合、そこに記載された手順・導線・ヒントを優先的に参照する\n- スナップショットに \\`[... N件省略]\\` とある場合、目的の要素が省略部分にある可能性がある。\\`scroll\\` で画面を動かして再取得を試みること\n\n## 探索戦略\n1. まず \\`actions: []\\` でページ状態を確認\n2. スナップショットを**注意深く読み**、ゴールのキーワードを使って関連要素を特定:\n - ゴールをキーワードに分解し(例: 「ログインしてダッシュボード表示」→ 「ログイン」「サインイン」「ダッシュボード」)、リンク・ボタン名から検索する\n - 曖昧なラベル(「詳細」「こちら」)より、キーワードに一致するリンクを優先する\n3. 特定した要素の \\`@eN\\` を使って操作を実行\n4. 結果を確認し、次の操作を決定(観察→判断→行動の繰り返し)\n5. 目的の要素が見つからない場合は \\`scroll\\` で画面を移動し、再度スナップショットを確認する\n6. SELECT要素には \\`click\\` ではなく \\`select\\` コマンドを使用\n7. チェックボックスには \\`check\\` / \\`uncheck\\` コマンドを使用\n8. ラジオボタンには \\`click\\` コマンドを使用 — 選択したいオプションを直接クリックする\n9. フォーム要素の調査に \\`extract\\` を使わないこと。スナップショットにラジオボタン・チェックボックス・ドロップダウンが見えていれば、適切なコマンドで直接操作する\n\n## リンク選択とナビゲーション回復\nページに多数のリンクがある場合:\n1. **クリック前の関連性チェック**: リンクの名前がゴールのキーワードに関連する場合のみクリックする。汎用的な名前のリンクは最後の手段\n2. **探索的クリックの回避**: 「どうなるか見てみよう」でリンクをクリックしない。各クリックにはゴールに紐づいた根拠が必要\n3. **誤遷移からの回復**: クリック後のページがゴールに無関係な場合、開始URLに \\`navigate\\` で戻り、別のリンクを探す\n\n## フォーム入力の効率化\n大きなフォームを入力する際は、以下のルールを厳守してください:\n1. **各フィールドは1回だけ入力する** — 既に値が入力されたフィールドを再度操作しないこと\n2. **スナップショットで入力済みフィールドを確認する** — fill/type 後のフィールドはスナップショットに入力値が表示される。値が表示されているフィールドはスキップする\n3. **上から下へ体系的に進む** — フォーム内のフィールドセット/セクションを上から順に処理する。前のセクションに戻らない\n4. **入力済みフィールド数を意識する** — 操作履歴を参照し、既に何を入力したかを把握する。同じセレクタへの重複操作は禁止\n5. **全フィールド入力後に送信する** — フォーム内の全必須フィールドが埋まったら、速やかに送信ボタンをクリックする\n6. **filledFields を確認する** — browserツールの結果に含まれる filledFields は入力済みフィールドの一覧。この一覧にあるフィールドは絶対に再入力しないこと\n\n## フォーム完了の検証\nフォーム入力のゴールで最終報告を返す前に:\n1. 現在のスナップショット全体をスキャンし、未入力フィールドがないか確認 — 全フィールドセット/セクションをチェック\n2. 以下を探す: 値のないテキストボックス、「Select...」プレースホルダー表示のドロップダウン、未チェックのチェックボックス\n3. フォームの最後のセクションは見落としやすい — フォーム最下部を必ず確認\n4. 全フィールド入力後、送信/登録ボタンをクリック\n5. goalAchieved: true を宣言する前に成功確認メッセージの表示を確認\n全セクション完了・フォーム送信を確認するまで goalAchieved を宣言しないこと。\n\n## データ収集パターン(ページネーション走査)\n手順: extract → memory_append → click「次へ」→ 繰り返し → memory_aggregate で集計\n\n例(テーブル抽出 → 蓄積 → 次ページ → 集計 → CSV出力):\n\\`\\`\\`json\n[\n {\"action\":\"extract\",\"description\":\"テーブル抽出\",\"script\":\"(()=>{const h=[...document.querySelectorAll('table thead th')].map(t=>t.textContent.trim());return[...document.querySelectorAll('table tbody tr')].map(r=>{const c=r.querySelectorAll('td');return Object.fromEntries([...c].map((c,i)=>[h[i]||'col'+i,c.textContent.trim()]));});})()\"},\n {\"action\":\"memory_append\",\"description\":\"蓄積\",\"memoryCollection\":\"data\"},\n {\"action\":\"click\",\"description\":\"次ページ\",\"selector\":\"@e15\"}\n]\n\\`\\`\\`\n集計: \\`[{\"action\":\"memory_aggregate\",\"description\":\"合計\",\"aggregation\":{\"collection\":\"data\",\"field\":\"amount\",\"operation\":\"sum\",\"outputVariable\":\"total\"}}]\\`\nCSV出力: \\`[{\"action\":\"export\",\"description\":\"CSV出力\",\"exportCollection\":\"data\",\"exportFormat\":\"csv\",\"exportPath\":\"/tmp/data.csv\"}]\\`\n\n注意: script で JSON.stringify() 不要。各行はフラットなオブジェクト。memoryStatus でコレクションのアイテム数を確認可能。\n\n**スコープフィルタリング**: ゴールがデータのサブセットを指定している場合(例:「/USD ペアを収集」)、extract script に \\`.filter(row => ...)\\` を付加すること。サブセットが要求されているのにテーブル全体を抽出してはならない。\n\n**重要**: ページネーション走査時は最後のページまで必ず継続してください。ページ表示(例: \"Page X of Y\")を確認し、最終ページに到達するまで「次へ」をクリックし続けてください。数ページで止めず、全ページを処理してください。パターンを示すことが目的ではなく、全データの走査を完了することが目的です。\n\n## filledFields の活用\nbrowserツールの結果に \\`filledFields\\` が含まれている場合、これは既に入力済みのフォームフィールドの一覧です。\nリストに含まれるフィールドには再度入力しないでください。未入力のフィールドのみを操作してください。\n\n## 差分スナップショット\nテキスト入力(fill/type)後にページ構造が変わっていない場合、全refを一覧にしたコンパクトなスナップショットが返されます。\n- \\`Unfilled:\\` はまだ操作が必要な要素を示します\n- \\`Filled:\\` は入力済みの要素を示します\n- コンパクトスナップショット内の全refは有効で使用可能です\n- 完全なページコンテキストが必要な場合は \\`actions: []\\` でブラウザツールを呼び出してください\n\n## nudgeMessage への対応\nbrowserツールの結果に \\`nudgeMessage\\` が含まれている場合、重要なガイダンスが記載されています:\n- **ページネーション進捗**: 現在のページと残りページ数を示します。全ページの処理が完了するまで続行してください。\n- **ループ警告**: 同じ操作を繰り返している可能性があります。別のアプローチを試してください。\n- **フォームヒント**: 未入力のフォームフィールド一覧です。\nメッセージの指示に必ず従ってください。\n\n## 複合ゴールの検証\nゴールに複数のステップが含まれている場合(例: 「Aして、Bに遷移し、Cを実行する」):\n1. ゴールを個別のサブタスクに分解する\n2. 各サブタスクが完了したかどうかを現在のページ状態から確認する\n3. **全てのサブタスクが完了するまで goalAchieved を宣言しないこと**\n4. ログインやページ遷移が成功しても、後続のタスクがあればまだゴールは未達成\n5. 一部のサブタスクが完了している場合は、残りのサブタスクに取り組み続けること。回復不能なエラーや全てのアプローチを試した場合にのみ goalAchieved: false を宣言する\n\n例: ゴールが「ログインしてアクション一覧でXを実行する」の場合:\n- ログイン成功 → まだ goalAchieved ではない(アクション実行が残っている)\n- アクション一覧でXを実行完了 → goalAchieved: true\n\n## ゴール達成時\n**重要: goalAchieved の申告は最終ページ状態から独立検証されます。虚偽の申告は上書きされます。**\n\ngoalAchieved: true を宣言する前に、以下のチェックリストを必ず完了してください:\n1. **元のゴールを再確認** — 全てのサブタスクに分解する\n2. **現在のページ状態を確認** — スナップショットに達成の明確な証拠があるか?\n3. **フォームタスク**: 成功/確認メッセージが表示されているか?(「フィールドを入力した」だけでは不十分 — フォームが送信され、確認が表示されていること)\n4. **ナビゲーションタスク**: 目的のページが実際に表示されているか?\n5. **複合ゴール**(A → B → C): 最初の部分だけでなく、全パートの証拠を確認\n6. **失敗シグナルの確認**: エラーメッセージ、バリデーション警告、ログインフォームがまだ表示されていないか、「再試行」プロンプトがないか\n7. **summary に具体的な証拠を含める**: 完了を証明する確認メッセージ、成功バナー、ページタイトルを引用する\n\nよくある偽陽性パターン(避けるべき):\n- ログイン後のタスクがあるのに、ログイン成功だけで達成と宣言する\n- フォーム入力後、送信前に達成と宣言する\n- ボタンクリック後、確認を待たずに達成と宣言する\n- ページがエラーを表示している、またはロード中なのに達成と宣言する\n\n全チェック項目を確認した上で、browserツールの呼び出しを停止し、以下のJSON形式で最終報告を返してください:\n\\`\\`\\`json\n{ \"goalAchieved\": true, \"summary\": \"証拠: [具体的な確認メッセージやページ状態]。完了: [実行したサブタスク一覧]\" }\n\\`\\`\\`\n\nゴールが達成できないと判断した場合:\n\\`\\`\\`json\n{ \"goalAchieved\": false, \"summary\": \"状況の要約と理由\" }\n\\`\\`\\`\n\n---\n以下はこのタスク固有の情報です。\n\n## ゴール\n${goal}\n${contextSection}${secretsSection}\n日本語で応答してください。`;\n}\n\nexport function getInitialUserMessage(): string {\n return \"browserツールをactions:[](空配列)で呼び出し、現在のページ状態を確認してください。その後、ゴール達成に向けて探索を開始してください。\";\n}\n","/**\n * Review prompt — English\n */\n\nimport type { RecordedStep, InterventionRecord } from \"../../../runbook-generator/types\";\n\nexport function getReviewSystemPrompt(): string {\n return `You are an expert reviewer of web browser automation procedures.\n\n## Task\nAnalyze the recorded steps and determine the following:\n\n1. **Remove unnecessary steps**: Identify and exclude trial-and-error during exploration, dead ends, unnecessary navigation, and duplicate operations\n2. **Risk level assessment**: Assess the risk of each step\n - \\`low\\`: Low side-effect operations like input, scrolling, navigation\n - \\`medium\\`: Login, form submission, settings changes, etc.\n - \\`high\\`: Irreversible operations like deletion, payment, data modification\n3. **Approval requirement**: Whether user approval is needed before execution\n\n## Capture Candidate Identification\nIf you detect important data used in subsequent steps (IDs, order numbers, URL changes, amounts, etc.),\ninclude them as suggestedCaptures in each step's response.\nAvailable strategies: snapshot (regex), url (URL regex), ai (AI extraction), expression (template)\n\n## Notes\n- Failed steps (success=false) should generally be excluded\n- Keep only the shortest path steps needed to achieve the goal\n- riskLevel is used in the Chrome extension approval flow (medium/high requires approval)\n- Respond in English`;\n}\n\nexport function createReviewUserPrompt(\n goal: string,\n recordedSteps: RecordedStep[],\n goalAchieved: boolean,\n interventions?: InterventionRecord[],\n): string {\n const stepsList = recordedSteps\n .map(\n (s) =>\n `${s.ordinal}. [${s.success ? \"OK\" : \"FAIL\"}] ${s.action.description} (action: ${s.action.action}, url: ${s.url})${s.error ? ` Error: ${s.error}` : \"\"}`,\n )\n .join(\"\\n\");\n\n const interventionsSection =\n interventions && interventions.length > 0\n ? `\\n## User Interventions During Exploration\nThe user modified the exploration direction at the following points.\nSteps before the intervention likely contain trial-and-error, while steps after are more accurate.\n\n${interventions\n .map(\n (iv, i) =>\n `${i + 1}. Around step #${iv.stepIndex}: \"${iv.userInstruction}\" (URL: ${iv.url})`,\n )\n .join(\"\\n\")}\n\n**Review note**: Actively exclude unnecessary steps before intervention points.\n`\n : \"\";\n\n return `## Goal\n${goal}\n\n## Goal Achievement Status\n${goalAchieved ? \"Achieved\" : \"Not achieved\"}\n${interventionsSection}\n## All Recorded Steps\n${stepsList}`;\n}\n","/**\n * Review prompt — Japanese (current production)\n */\n\nimport type { RecordedStep, InterventionRecord } from \"../../../runbook-generator/types\";\n\nexport function getReviewSystemPrompt(): string {\n return `あなたはWebブラウザ自動操作の手順書をレビューするエキスパートです。\n\n## タスク\n記録されたステップを分析し、以下を判定してください:\n\n1. **不要ステップの除外**: 探索中の試行錯誤、行き止まり、不要なナビゲーション、重複操作を特定し除外\n2. **リスクレベル判定**: 各ステップのリスクを判定\n - \\`low\\`: 入力、スクロール、ナビゲーションなど副作用の少ない操作\n - \\`medium\\`: ログイン、フォーム送信、設定変更など\n - \\`high\\`: 削除、決済、データ変更など不可逆な操作\n3. **承認要否判定**: 実行前にユーザー承認が必要かどうか\n\n## キャプチャ候補の識別\n操作結果として後続ステップで使用される重要なデータ(ID、注文番号、URL変化、金額など)を検出した場合、\nsuggestedCaptures としてレスポンスの各ステップに含めてください。\n利用可能な strategy: snapshot(正規表現), url(URL正規表現), ai(AI抽出), expression(テンプレート)\n\n## 注意事項\n- 失敗ステップ(success=false)は基本的に除外してください\n- ゴール達成に必要な最短経路のステップのみ残してください\n- riskLevel は Chrome拡張の承認フローで使用されます(medium/high は承認が必要)\n- 日本語で応答してください`;\n}\n\nexport function createReviewUserPrompt(\n goal: string,\n recordedSteps: RecordedStep[],\n goalAchieved: boolean,\n interventions?: InterventionRecord[],\n): string {\n const stepsList = recordedSteps\n .map(\n (s) =>\n `${s.ordinal}. [${s.success ? \"成功\" : \"失敗\"}] ${s.action.description} (action: ${s.action.action}, url: ${s.url})${s.error ? ` エラー: ${s.error}` : \"\"}`,\n )\n .join(\"\\n\");\n\n const interventionsSection =\n interventions && interventions.length > 0\n ? `\\n## 探索中のユーザー介入\n以下のタイミングでユーザーが探索方針を修正しました。\n介入前のステップには探索の試行錯誤が含まれている可能性が高く、介入後のステップがより正確な手順です。\n\n${interventions\n .map(\n (iv, i) =>\n `${i + 1}. ステップ#${iv.stepIndex}付近: \"${iv.userInstruction}\" (URL: ${iv.url})`,\n )\n .join(\"\\n\")}\n\n**レビュー時の注意**: 介入ポイントより前の不要なステップは積極的に除外してください。\n`\n : \"\";\n\n return `## ゴール\n${goal}\n\n## ゴール達成状況\n${goalAchieved ? \"達成済み\" : \"未達成\"}\n${interventionsSection}\n## 記録された全ステップ\n${stepsList}`;\n}\n","/**\n * Selector resolver prompt — English\n */\n\nimport type { Selector } from \"../../../runbook-executor/types\";\nimport type { RetryContext } from \"../../../harness/selector-resolver\";\n\nexport function buildSelectorMessages(\n snapshot: string,\n selector: Selector,\n stepDescription: string,\n url: string,\n contextMarkdown: string,\n retryContext?: RetryContext,\n workingMemorySummary?: string,\n): { system: string; userPrompt: string } {\n const system = [\n \"You are a selector resolver for browser automation.\",\n \"Based on the step description, identify the target element in the accessibility snapshot.\",\n \"\",\n \"## Matching Guidelines\",\n \"1. Infer the type of target element (button, input field, link, etc.) from the step description\",\n \"2. Find the element in the snapshot that semantically best matches the step description\",\n \"3. Use surrounding text, labels, placeholders, and roles as clues\",\n \"4. Even without an exact match, return the ref of the most likely element\",\n \"5. Return an empty string only if the target element truly does not exist in the snapshot\",\n ].join(\"\\n\");\n\n const parts: string[] = [\n \"## Step Description (Most Important)\",\n stepDescription,\n \"\",\n \"## Selector Hints (Reference)\",\n \"The following is reference information for identifying the element. Even without an exact match, choose the element semantically closest to the step description.\",\n JSON.stringify(pruneSelectorHints(selector)),\n \"\",\n \"Notes:\",\n '- If tagName is \"unknown\" or \":\", there is no tag name information',\n \"- ariaLabel is auto-generated from the step description and may not match the actual aria-label attribute\",\n \"- Prioritize semantic match with the step description over exact selector match\",\n \"\",\n \"## Current URL\",\n url,\n ];\n\n if (workingMemorySummary) {\n parts.push(\"\", \"## Execution Context\", workingMemorySummary);\n }\n\n parts.push(\n \"\",\n \"## Accessibility Snapshot\",\n snapshot,\n );\n\n const includeContext = contextMarkdown && !(retryContext && retryContext.attempt > 0);\n if (includeContext) {\n parts.push(\"\", \"## Supplementary Context\", contextMarkdown);\n }\n\n if (retryContext && retryContext.attempt > 0) {\n parts.push(\n \"\",\n \"## Recovery Context (Attempt \" + (retryContext.attempt + 1) + \")\",\n );\n\n // Failure pattern hints from registry\n if (retryContext.failureHints) {\n parts.push(`Pattern: ${retryContext.failureHints}`);\n }\n\n if (retryContext.failureHistory.length > 0) {\n const recent = retryContext.failureHistory.slice(-2);\n parts.push(`Previous: ${recent.join(\"; \")}`);\n }\n if (retryContext.previousAiResponse) {\n // Extract only the reasoning from the previous AI response\n try {\n const parsed = JSON.parse(retryContext.previousAiResponse);\n if (parsed.reasoning) {\n parts.push(`Last reasoning: \"${parsed.reasoning}\"`);\n }\n } catch {\n parts.push(`Last response: ${retryContext.previousAiResponse.slice(0, 200)}`);\n }\n }\n if (!retryContext.snapshotChanged) {\n parts.push(\n \"Snapshot unchanged — try partial matching, role-based matching, or inference from nearby elements.\",\n );\n }\n }\n\n return { system, userPrompt: parts.join(\"\\n\") };\n}\n\nfunction pruneSelectorHints(selector: Selector): Record<string, unknown> {\n const pruned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(selector)) {\n if (value === null || value === undefined || value === \"\" || value === \"unknown\" || value === \":\") continue;\n pruned[key] = value;\n }\n return pruned;\n}\n","/**\n * Selector resolver prompt — Japanese (current production)\n */\n\nimport type { Selector } from \"../../../runbook-executor/types\";\nimport type { RetryContext } from \"../../../harness/selector-resolver\";\n\nexport function buildSelectorMessages(\n snapshot: string,\n selector: Selector,\n stepDescription: string,\n url: string,\n contextMarkdown: string,\n retryContext?: RetryContext,\n workingMemorySummary?: string,\n): { system: string; userPrompt: string } {\n const system = [\n \"あなたはブラウザ自動操作のセレクタリゾルバーです。\",\n \"ステップの説明に基づいて、アクセシビリティスナップショット内の操作対象要素を特定してください。\",\n \"\",\n \"## マッチングの指針\",\n \"1. ステップの説明から操作対象の要素の種類(ボタン、入力フィールド、リンク等)を推定する\",\n \"2. スナップショット内で、ステップの説明と意味的に最も一致する要素を探す\",\n \"3. 周辺のテキスト、ラベル、プレースホルダー、role も手がかりにする\",\n \"4. 完全一致がなくても最も可能性の高い要素の ref を返す\",\n \"5. 該当する要素がスナップショット内に本当に存在しない場合のみ空文字を返す\",\n ].join(\"\\n\");\n\n const parts: string[] = [\n \"## ステップの説明(最重要)\",\n stepDescription,\n \"\",\n \"## セレクタのヒント(参考情報)\",\n \"以下は要素を特定するための参考情報です。完全一致しない場合でも、ステップの説明から意味的に最も近い要素を選んでください。\",\n JSON.stringify(pruneSelectorHints(selector)),\n \"\",\n \"注意:\",\n '- tagName が \"unknown\" や \":\" の場合はタグ名情報がありません',\n \"- ariaLabel はステップ説明から自動生成されたものであり、実際の aria-label 属性と一致しないことがあります\",\n \"- セレクタの完全一致よりもステップの説明との意味的一致を優先してください\",\n \"\",\n \"## 現在のURL\",\n url,\n ];\n\n if (workingMemorySummary) {\n parts.push(\"\", \"## 実行コンテキスト\", workingMemorySummary);\n }\n\n parts.push(\n \"\",\n \"## アクセシビリティスナップショット\",\n snapshot,\n );\n\n const includeContext = contextMarkdown && !(retryContext && retryContext.attempt > 0);\n if (includeContext) {\n parts.push(\"\", \"## 補足コンテキスト\", contextMarkdown);\n }\n\n if (retryContext && retryContext.attempt > 0) {\n parts.push(\n \"\",\n \"## 回復コンテキスト(試行\" + (retryContext.attempt + 1) + \"回目)\",\n );\n\n // FailureRegistry からの回復ヒント\n if (retryContext.failureHints) {\n parts.push(`パターン: ${retryContext.failureHints}`);\n }\n\n if (retryContext.failureHistory.length > 0) {\n const recent = retryContext.failureHistory.slice(-2);\n parts.push(`直近の失敗: ${recent.join(\"; \")}`);\n }\n if (retryContext.previousAiResponse) {\n try {\n const parsed = JSON.parse(retryContext.previousAiResponse);\n if (parsed.reasoning) {\n parts.push(`前回の推論: \"${parsed.reasoning}\"`);\n }\n } catch {\n parts.push(`前回の応答: ${retryContext.previousAiResponse.slice(0, 200)}`);\n }\n }\n if (!retryContext.snapshotChanged) {\n parts.push(\n \"スナップショット未変化 — 部分一致、roleベースのマッチング、近接要素からの推定を試みてください。\",\n );\n }\n }\n\n return { system, userPrompt: parts.join(\"\\n\") };\n}\n\nfunction pruneSelectorHints(selector: Selector): Record<string, unknown> {\n const pruned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(selector)) {\n if (value === null || value === undefined || value === \"\" || value === \"unknown\" || value === \":\") continue;\n pruned[key] = value;\n }\n return pruned;\n}\n","/**\n * Goal agent (fallback) prompt — English\n */\n\nimport type { GoalAgentStep } from \"../../../harness/goal-agent\";\n\nexport function buildFallbackMessages(\n snapshot: string,\n step: GoalAgentStep,\n failureHistory: string[],\n url: string,\n contextMarkdown: string,\n): { system: string; userPrompt: string } {\n const system = [\n \"You are a problem-solving agent for browser automation.\",\n \"Normal selector resolution has failed at all phases. Analyze the entire page and find an alternative operation path.\",\n \"\",\n \"## Alternative Path Search Guidelines\",\n \"1. Check if the target element is hidden inside a hamburger menu, dropdown, or accordion\",\n \"2. Check if a modal or overlay is covering the target element\",\n \"3. Check if the page is in an unexpected state (not logged in, error state, loading)\",\n \"4. Check if the target element is above the current scroll position\",\n \"5. Check if a semantically equivalent alternative element exists (e.g., a button instead of a link)\",\n \"\",\n \"## Alternative Strategy Selection Criteria\",\n \"- direct_ref: Try a different ref directly (when a semantically equivalent element is found)\",\n \"- scroll_up_and_retry: When the target element might be above the current view\",\n \"- expand_collapsed: When a collapsed section/menu needs to be expanded (prerequisiteRef required)\",\n \"- dismiss_overlay: When a modal/overlay needs to be closed (prerequisiteRef required)\",\n \"- tab_navigation: When the element can be reached via Tab key focus navigation\",\n \"- not_found: When the target element truly does not exist on the page\",\n ].join(\"\\n\");\n\n const parts = [\n \"## Step Being Attempted\",\n `Description: ${step.description}`,\n `Action: ${step.action.type}`,\n `Selector hints: ${JSON.stringify(step.action.selector, null, 2)}`,\n `URL: ${url}`,\n \"\",\n \"## Failure History\",\n ...failureHistory.map((f, i) => ` ${i + 1}. ${f}`),\n \"\",\n \"## Current Page Snapshot (Filtered)\",\n snapshot,\n ];\n\n if (contextMarkdown) {\n parts.push(\"\", \"## Supplementary Context\", contextMarkdown);\n }\n\n return { system, userPrompt: parts.join(\"\\n\") };\n}\n","/**\n * Goal agent (fallback) prompt — Japanese (current production)\n */\n\nimport type { GoalAgentStep } from \"../../../harness/goal-agent\";\n\nexport function buildFallbackMessages(\n snapshot: string,\n step: GoalAgentStep,\n failureHistory: string[],\n url: string,\n contextMarkdown: string,\n): { system: string; userPrompt: string } {\n const system = [\n \"あなたはブラウザ自動操作の問題解決エージェントです。\",\n \"通常のセレクタ解決が全フェーズ失敗しました。ページ全体を分析して代替操作パスを見つけてください。\",\n \"\",\n \"## 代替パス探索の指針\",\n \"1. ハンバーガーメニュー、ドロップダウン、アコーディオンの中に対象要素が隠れていないか確認\",\n \"2. モーダルやオーバーレイが前面にあって対象要素を隠していないか確認\",\n \"3. ページが想定と異なる状態(未ログイン、エラー状態、ローディング中)でないか確認\",\n \"4. 対象要素が上方にあってスクロールで隠れていないか確認\",\n \"5. 意味的に同等な別の要素(リンクではなくボタン、等)が存在しないか確認\",\n \"\",\n \"## 代替戦略の選択基準\",\n \"- direct_ref: 別の ref を直接試す(意味的に同等な要素が見つかった場合)\",\n \"- scroll_up_and_retry: 対象要素が上方にある可能性がある場合\",\n \"- expand_collapsed: 折り畳まれたセクション/メニューを展開する必要がある場合(prerequisiteRef 必須)\",\n \"- dismiss_overlay: モーダル/オーバーレイを閉じる必要がある場合(prerequisiteRef 必須)\",\n \"- tab_navigation: Tab キーでフォーカス移動して到達できる場合\",\n \"- not_found: 本当にページ上に対象要素が存在しない場合\",\n ].join(\"\\n\");\n\n const parts = [\n \"## 達成しようとしていたステップ\",\n `説明: ${step.description}`,\n `アクション: ${step.action.type}`,\n `セレクタヒント: ${JSON.stringify(step.action.selector, null, 2)}`,\n `URL: ${url}`,\n \"\",\n \"## これまでの失敗履歴\",\n ...failureHistory.map((f, i) => ` ${i + 1}. ${f}`),\n \"\",\n \"## 現在のページスナップショット(フィルタ済み)\",\n snapshot,\n ];\n\n if (contextMarkdown) {\n parts.push(\"\", \"## 補足コンテキスト\", contextMarkdown);\n }\n\n return { system, userPrompt: parts.join(\"\\n\") };\n}\n","/**\n * Vision resolver prompt — English\n */\n\nimport type { Selector } from \"../../../runbook-executor/types\";\nimport type { Annotation } from \"../../../browser/engine\";\n\nexport function buildVisionMessages(\n annotations: Annotation[],\n selector: Selector,\n stepDescription: string,\n url: string,\n failureHistory: string[],\n): { system: string; userTextContent: string } {\n const system = [\n \"You are a visual selector resolver for browser automation.\",\n \"The text-based accessibility tree could not find the element.\",\n \"Analyze the screenshot visually to identify the target element.\",\n \"\",\n \"## How to Read the Screenshot\",\n \"- Each interactive element has a red border and number label\",\n \"- Number labels are displayed at the top-left of each element\",\n \"- Each number corresponds to the number field in the annotation list below\",\n \"\",\n \"## Matching Guidelines\",\n \"1. Infer the type of target element (button, input field, link, etc.) from the step description\",\n \"2. Find the element in the screenshot that visually best matches\",\n \"3. Use element text, position, and appearance as clues\",\n \"4. Also reference the role and name from the annotation list\",\n \"5. Target elements not in the A11y tree (canvas, Shadow DOM, iframe, etc.) are also in scope\",\n \"6. Return empty string if confidence is low (below 0.5)\",\n ].join(\"\\n\");\n\n const annotationList = annotations\n .map((a) => {\n const nameStr = a.name ? ` \"${a.name}\"` : \"\";\n return ` #${a.number} ref=${a.ref} ${a.role}${nameStr} @(${a.box.x},${a.box.y})`;\n })\n .join(\"\\n\");\n\n const selectorHints = pruneSelectorHints(selector);\n\n const parts: string[] = [\n \"## Step Description (Most Important)\",\n stepDescription,\n \"\",\n \"## Selector Hints (Reference)\",\n JSON.stringify(selectorHints),\n \"\",\n \"## Current URL\",\n url,\n \"\",\n \"## Annotation List (Corresponds to Numbers on Screenshot)\",\n annotationList,\n ];\n\n if (failureHistory.length > 0) {\n const recent = failureHistory.slice(-3);\n parts.push(\n \"\",\n \"## Text-based Resolution Failure History (Recent 3)\",\n ...recent.map((f, i) => ` ${i + 1}. ${f}`),\n );\n }\n\n return { system, userTextContent: parts.join(\"\\n\") };\n}\n\nfunction pruneSelectorHints(selector: Selector): Record<string, unknown> {\n const pruned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(selector)) {\n if (value === null || value === undefined || value === \"\" || value === \"unknown\" || value === \":\") continue;\n pruned[key] = value;\n }\n return pruned;\n}\n","/**\n * Vision resolver prompt — Japanese (current production)\n */\n\nimport type { Selector } from \"../../../runbook-executor/types\";\nimport type { Annotation } from \"../../../browser/engine\";\n\nexport function buildVisionMessages(\n annotations: Annotation[],\n selector: Selector,\n stepDescription: string,\n url: string,\n failureHistory: string[],\n): { system: string; userTextContent: string } {\n const system = [\n \"あなたはブラウザ自動操作のビジュアルセレクタリゾルバーです。\",\n \"テキストベースのアクセシビリティツリーでは要素が見つかりませんでした。\",\n \"スクリーンショットを視覚的に分析して、操作対象の要素を特定してください。\",\n \"\",\n \"## スクリーンショットの見方\",\n \"- 各インタラクティブ要素に赤い枠線と番号ラベルが表示されています\",\n \"- 番号ラベルは各要素の左上に表示されます\",\n \"- 各番号は下記のアノテーション一覧の number フィールドに対応します\",\n \"\",\n \"## マッチングの指針\",\n \"1. ステップの説明から操作対象の要素の種類(ボタン、入力フィールド、リンク等)を推定\",\n \"2. スクリーンショット内で視覚的に最も一致する要素を探す\",\n \"3. 要素のテキスト、位置、外観を手がかりにする\",\n \"4. アノテーション一覧の role と name も参考にする\",\n \"5. A11y ツリーに表れない要素(canvas、Shadow DOM、iframe 内等)も対象\",\n \"6. 確信度が低い場合(0.5未満)は空文字を返す\",\n ].join(\"\\n\");\n\n const annotationList = annotations\n .map((a) => {\n const nameStr = a.name ? ` \"${a.name}\"` : \"\";\n return ` #${a.number} ref=${a.ref} ${a.role}${nameStr} @(${a.box.x},${a.box.y})`;\n })\n .join(\"\\n\");\n\n const selectorHints = pruneSelectorHints(selector);\n\n const parts: string[] = [\n \"## ステップの説明(最重要)\",\n stepDescription,\n \"\",\n \"## セレクタのヒント(参考情報)\",\n JSON.stringify(selectorHints),\n \"\",\n \"## 現在のURL\",\n url,\n \"\",\n \"## アノテーション一覧(スクリーンショット上の番号と対応)\",\n annotationList,\n ];\n\n if (failureHistory.length > 0) {\n const recent = failureHistory.slice(-3);\n parts.push(\n \"\",\n \"## テキストベース解決の失敗履歴(直近3件)\",\n ...recent.map((f, i) => ` ${i + 1}. ${f}`),\n );\n }\n\n return { system, userTextContent: parts.join(\"\\n\") };\n}\n\nfunction pruneSelectorHints(selector: Selector): Record<string, unknown> {\n const pruned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(selector)) {\n if (value === null || value === undefined || value === \"\" || value === \"unknown\" || value === \":\") continue;\n pruned[key] = value;\n }\n return pruned;\n}\n","/**\n * Self-heal analyzer prompt — English\n */\n\nimport type { ParsedRunbook } from \"../../../runbook-executor/types\";\n\nexport function getSuggestionSystemPrompt(): string {\n return [\n \"You are an runbook debugger for browser automation.\",\n \"Analyze the failed steps from the debug execution and generate fix suggestions for the runbook and context.\",\n \"\",\n \"## Fix Suggestion Guidelines\",\n \"\",\n \"For each failed step, provide suggestions from these two perspectives:\",\n \"\",\n \"### 1. runbookFix (Runbook YAML Fix)\",\n \"- Selector changes (when element has moved/been renamed)\",\n \"- Step addition/removal (when the navigation flow has changed)\",\n \"- Action value updates (text or URL changes)\",\n \"- riskLevel or requiresConfirmation adjustments\",\n `Example: \"Step 3: Change selector ariaLabel from 'Submit' to 'Confirm and Submit'\"`,\n \"\",\n \"### 2. contextFix (Context Markdown Fix)\",\n \"- Document page structure changes (new modals, menu structure changes, etc.)\",\n \"- Add prerequisites (login state, permissions, environment conditions, etc.)\",\n \"- Add selector resolution hints (dynamic ID naming patterns, etc.)\",\n `Example: \"Add to context: 'Settings page has changed from tab UI to accordion UI'\"`,\n \"\",\n \"If context markdown is not provided, return empty string for contextFix.\",\n \"\",\n \"### severity Criteria\",\n \"- error: Selector completely not found, fundamental page structure change\",\n \"- warning: Succeeded with retry but unstable, element position or label slightly changed\",\n \"\",\n \"### Template Variable Protection\",\n \"- If step values contain {{varName}} template variables, preserve them as-is in fix suggestions\",\n \"- Template variables are dynamic references resolved at runtime. Do not suggest replacing them with literal values\",\n \"\",\n \"### failureCategory and suggestedStrategy\",\n \"If a failure category is provided, describe a specific fix strategy in suggestedStrategy:\",\n \"- element_not_found: Update selector ariaLabel/role/text to match current page structure\",\n \"- element_stale: Delete selector cache and re-execute\",\n \"- page_structure_changed: Document page structure changes in context.md and update all selectors\",\n \"- navigation_timeout: Add wait step or increase step-delay\",\n \"- action_failed: Consider changing action type (e.g., click → hover)\",\n \"- unknown: Analyze error details and propose specific remediation\",\n ].join(\"\\n\");\n}\n\nexport function buildSuggestionUserPrompt(\n failedInfo: string[],\n stepsInfo: string[],\n runbook: ParsedRunbook,\n contextMarkdown: string,\n): string {\n const parts: string[] = [\n \"## Instruction Information\",\n `Title: ${runbook.title}`,\n `Goal: ${runbook.metadata.goal}`,\n `Start URL: ${runbook.metadata.startUrl}`,\n \"\",\n \"## Instruction Steps\",\n stepsInfo.join(\"\\n\\n\"),\n \"\",\n \"## Failed Step Details\",\n failedInfo.join(\"\\n\\n\"),\n ];\n\n if (contextMarkdown) {\n parts.push(\n \"\",\n \"## Current Context (markdown)\",\n contextMarkdown,\n );\n } else {\n parts.push(\n \"\",\n \"## Context\",\n \"Context markdown is not provided. Return empty string for contextFix.\",\n );\n }\n\n return parts.join(\"\\n\");\n}\n","/**\n * Self-heal analyzer prompt — Japanese (current production)\n */\n\nimport type { ParsedRunbook } from \"../../../runbook-executor/types\";\n\nexport function getSuggestionSystemPrompt(): string {\n return [\n \"あなたはブラウザ自動操作の手順書デバッガーです。\",\n \"デバッグ実行で失敗したステップを分析し、手順書とコンテキストの修正提案を生成してください。\",\n \"\",\n \"## 修正提案の指針\",\n \"\",\n \"各失敗ステップについて、以下の2つの観点で修正提案を出してください:\",\n \"\",\n \"### 1. runbookFix(手順書 YAML の修正)\",\n \"- セレクタの変更(要素が移動/リネームされた場合)\",\n \"- ステップの追加/削除(導線が変わった場合)\",\n \"- アクション値の更新(テキストやURLの変更)\",\n \"- riskLevel や requiresConfirmation の調整\",\n '例: 「Step 3: selector の ariaLabel を \\'送信\\' → \\'確認して送信\\' に変更」',\n \"\",\n \"### 2. contextFix(context markdown の修正)\",\n \"- ページ構造変更の記載(新しいモーダル、メニュー構造の変更など)\",\n \"- 前提条件の追加(ログイン状態、権限、環境条件など)\",\n \"- セレクタ解決のヒント追加(動的IDの命名規則など)\",\n '例: 「context に\\'設定画面がタブUIからアコーディオンUIに変更された\\'旨を追記」',\n \"\",\n \"context markdown が未提供の場合、contextFix は空文字で返してください。\",\n \"\",\n \"### severity の判定基準\",\n \"- error: セレクタが完全に見つからない、ページ構造が根本的に変わっている\",\n \"- warning: リトライで成功したが不安定、要素の位置やラベルが微妙に変わっている\",\n \"\",\n \"### テンプレート変数の保護\",\n \"- ステップの値に {{varName}} 形式のテンプレート変数が含まれている場合、修正提案でもそのまま維持してください\",\n \"- テンプレート変数は実行時に動的に展開される変数参照です。リテラル値への置換を提案しないでください\",\n \"\",\n \"### failureCategory と suggestedStrategy\",\n \"エラー分類カテゴリが提供されている場合、それに基づいて具体的な修正戦略を suggestedStrategy に記載してください:\",\n \"- element_not_found: セレクタの ariaLabel/role/text を現在のページ構造に合わせて更新\",\n \"- element_stale: セレクタキャッシュの削除と再実行\",\n \"- page_structure_changed: context.md にページ構造変更を記録し、セレクタを全面更新\",\n \"- navigation_timeout: wait ステップの追加または step-delay の増加\",\n \"- action_failed: アクション種別の変更(例: click → hover)を検討\",\n \"- unknown: エラー内容を詳細に分析し、具体的な対処を提案\",\n ].join(\"\\n\");\n}\n\nexport function buildSuggestionUserPrompt(\n failedInfo: string[],\n stepsInfo: string[],\n runbook: ParsedRunbook,\n contextMarkdown: string,\n): string {\n const parts: string[] = [\n \"## 手順書情報\",\n `タイトル: ${runbook.title}`,\n `目的: ${runbook.metadata.goal}`,\n `開始URL: ${runbook.metadata.startUrl}`,\n \"\",\n \"## 手順書のステップ一覧\",\n stepsInfo.join(\"\\n\\n\"),\n \"\",\n \"## 失敗ステップの詳細\",\n failedInfo.join(\"\\n\\n\"),\n ];\n\n if (contextMarkdown) {\n parts.push(\n \"\",\n \"## 現在のコンテキスト(markdown)\",\n contextMarkdown,\n );\n } else {\n parts.push(\n \"\",\n \"## コンテキスト\",\n \"context markdown は未提供です。contextFix は空文字で返してください。\",\n );\n }\n\n return parts.join(\"\\n\");\n}\n","/**\n * i18n/prompts --- ロケール切替ディスパッチャー\n *\n * AI プロンプト(複雑な複数行テンプレート)をロケールごとに切り替える。\n * 各プロンプトモジュールは関数を export し、ディスパッチャーが getLocale() に\n * 基づいて適切なロケールの関数を呼び出す。\n */\n\nimport { getLocale } from \"../index\";\n\nimport { getAgentInstructions as getAgentInstructionsEn, getInitialUserMessage as getInitialUserMessageEn } from \"./en/exploration\";\nimport { getAgentInstructions as getAgentInstructionsJa, getInitialUserMessage as getInitialUserMessageJa } from \"./ja/exploration\";\n\nimport { getReviewSystemPrompt as getReviewSystemPromptEn, createReviewUserPrompt as createReviewUserPromptEn } from \"./en/review\";\nimport { getReviewSystemPrompt as getReviewSystemPromptJa, createReviewUserPrompt as createReviewUserPromptJa } from \"./ja/review\";\n\nimport { buildSelectorMessages as buildSelectorMessagesEn } from \"./en/selector\";\nimport { buildSelectorMessages as buildSelectorMessagesJa } from \"./ja/selector\";\n\nimport { buildFallbackMessages as buildFallbackMessagesEn } from \"./en/goal-agent\";\nimport { buildFallbackMessages as buildFallbackMessagesJa } from \"./ja/goal-agent\";\n\nimport { buildVisionMessages as buildVisionMessagesEn } from \"./en/vision\";\nimport { buildVisionMessages as buildVisionMessagesJa } from \"./ja/vision\";\n\nimport { getSuggestionSystemPrompt as getSuggestionSystemPromptEn, buildSuggestionUserPrompt as buildSuggestionUserPromptEn } from \"./en/self-heal\";\nimport { getSuggestionSystemPrompt as getSuggestionSystemPromptJa, buildSuggestionUserPrompt as buildSuggestionUserPromptJa } from \"./ja/self-heal\";\n\nimport type { SecretsData } from \"../../cli/secrets-loader\";\nimport type { RecordedStep, InterventionRecord } from \"../../runbook-generator/types\";\nimport type { Selector } from \"../../runbook-executor/types\";\nimport type { RetryContext } from \"../../harness/selector-resolver\";\nimport type { GoalAgentStep } from \"../../harness/goal-agent\";\nimport type { Annotation } from \"../../browser/engine\";\nimport type { ParsedRunbook } from \"../../runbook-executor/types\";\n\n// ── Exploration ──\n\nexport function getAgentInstructions(\n goal: string,\n contextMarkdown: string,\n secrets?: SecretsData,\n locale?: \"en\" | \"ja\",\n): string {\n const effectiveLocale = locale ?? getLocale();\n return effectiveLocale === \"ja\"\n ? getAgentInstructionsJa(goal, contextMarkdown, secrets)\n : getAgentInstructionsEn(goal, contextMarkdown, secrets);\n}\n\nexport function getInitialUserMessage(locale?: \"en\" | \"ja\"): string {\n const effectiveLocale = locale ?? getLocale();\n return effectiveLocale === \"ja\"\n ? getInitialUserMessageJa()\n : getInitialUserMessageEn();\n}\n\n// ── Review ──\n\nexport function getReviewSystemPrompt(locale?: \"en\" | \"ja\"): string {\n const effectiveLocale = locale ?? getLocale();\n return effectiveLocale === \"ja\"\n ? getReviewSystemPromptJa()\n : getReviewSystemPromptEn();\n}\n\nexport function createReviewUserPrompt(\n goal: string,\n recordedSteps: RecordedStep[],\n goalAchieved: boolean,\n interventions?: InterventionRecord[],\n locale?: \"en\" | \"ja\",\n): string {\n const effectiveLocale = locale ?? getLocale();\n return effectiveLocale === \"ja\"\n ? createReviewUserPromptJa(goal, recordedSteps, goalAchieved, interventions)\n : createReviewUserPromptEn(goal, recordedSteps, goalAchieved, interventions);\n}\n\n// ── Selector ──\n\nexport function buildSelectorMessages(\n snapshot: string,\n selector: Selector,\n stepDescription: string,\n url: string,\n contextMarkdown: string,\n retryContext?: RetryContext,\n workingMemorySummary?: string,\n): { system: string; userPrompt: string } {\n return getLocale() === \"ja\"\n ? buildSelectorMessagesJa(snapshot, selector, stepDescription, url, contextMarkdown, retryContext, workingMemorySummary)\n : buildSelectorMessagesEn(snapshot, selector, stepDescription, url, contextMarkdown, retryContext, workingMemorySummary);\n}\n\n// ── Goal Agent ──\n\nexport function buildFallbackMessages(\n snapshot: string,\n step: GoalAgentStep,\n failureHistory: string[],\n url: string,\n contextMarkdown: string,\n): { system: string; userPrompt: string } {\n return getLocale() === \"ja\"\n ? buildFallbackMessagesJa(snapshot, step, failureHistory, url, contextMarkdown)\n : buildFallbackMessagesEn(snapshot, step, failureHistory, url, contextMarkdown);\n}\n\n// ── Vision ──\n\nexport function buildVisionMessages(\n annotations: Annotation[],\n selector: Selector,\n stepDescription: string,\n url: string,\n failureHistory: string[],\n): { system: string; userTextContent: string } {\n return getLocale() === \"ja\"\n ? buildVisionMessagesJa(annotations, selector, stepDescription, url, failureHistory)\n : buildVisionMessagesEn(annotations, selector, stepDescription, url, failureHistory);\n}\n\n// ── Self-Heal ──\n\nexport function getSuggestionSystemPrompt(): string {\n return getLocale() === \"ja\"\n ? getSuggestionSystemPromptJa()\n : getSuggestionSystemPromptEn();\n}\n\nexport function buildSuggestionUserPrompt(\n failedInfo: string[],\n stepsInfo: string[],\n runbook: ParsedRunbook,\n contextMarkdown: string,\n): string {\n return getLocale() === \"ja\"\n ? buildSuggestionUserPromptJa(failedInfo, stepsInfo, runbook, contextMarkdown)\n : buildSuggestionUserPromptEn(failedInfo, stepsInfo, runbook, contextMarkdown);\n}\n"],"mappings":"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","names":["COMMAND_SCHEMA","getAgentInstructions","getInitialUserMessage","getReviewSystemPrompt","createReviewUserPrompt","buildSelectorMessages","pruneSelectorHints","buildFallbackMessages","pruneSelectorHints","buildVisionMessages","pruneSelectorHints","getSuggestionSystemPrompt","buildSuggestionUserPrompt","getAgentInstructions","getInitialUserMessage","getReviewSystemPrompt","createReviewUserPrompt","buildSelectorMessages","buildFallbackMessages","buildVisionMessages","getSuggestionSystemPrompt","buildSuggestionUserPrompt"]}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
isEditable,
|
|
8
8
|
loadVersionDetail,
|
|
9
9
|
resolveDisplayStatus
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-VVXNFUPL.js";
|
|
11
11
|
import {
|
|
12
12
|
jobs,
|
|
13
13
|
runbookSecrets,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
runbookVersionReviews,
|
|
18
18
|
runbookVersions,
|
|
19
19
|
runbooks
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-CMWLFQXD.js";
|
|
21
21
|
|
|
22
22
|
// src/server/store/runbook-store.ts
|
|
23
23
|
import { eq as eq2, and as and2, desc as desc2, sql as sql2, count as count2 } from "drizzle-orm";
|
|
@@ -907,7 +907,7 @@ var RunbookStore = class {
|
|
|
907
907
|
createdBy: createdBy ?? null
|
|
908
908
|
});
|
|
909
909
|
if (source.currentVersionId) {
|
|
910
|
-
const { copyVersionData: copyVersionData2 } = await import("./runbook-data-helpers-
|
|
910
|
+
const { copyVersionData: copyVersionData2 } = await import("./runbook-data-helpers-5UAO65TZ.js");
|
|
911
911
|
await copyVersionData2(tx, source.currentVersionId, verRow.id);
|
|
912
912
|
}
|
|
913
913
|
return { id: newRb.id };
|
|
@@ -950,4 +950,4 @@ var RunbookStore = class {
|
|
|
950
950
|
export {
|
|
951
951
|
RunbookStore
|
|
952
952
|
};
|
|
953
|
-
//# sourceMappingURL=chunk-
|
|
953
|
+
//# sourceMappingURL=chunk-HHRHHFSK.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
createReviewUserPrompt,
|
|
4
|
+
getReviewSystemPrompt
|
|
5
|
+
} from "./chunk-GC7I5SGK.js";
|
|
6
|
+
|
|
7
|
+
// src/runbook-generator/prompts.ts
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
var reviewResponseSchema = z.object({
|
|
10
|
+
reviewedSteps: z.array(z.object({
|
|
11
|
+
originalOrdinal: z.number(),
|
|
12
|
+
keep: z.boolean(),
|
|
13
|
+
removalReason: z.string().optional(),
|
|
14
|
+
riskLevel: z.enum(["low", "medium", "high"]),
|
|
15
|
+
requiresConfirmation: z.boolean(),
|
|
16
|
+
confirmationReason: z.string().optional()
|
|
17
|
+
})),
|
|
18
|
+
summary: z.string()
|
|
19
|
+
});
|
|
20
|
+
function createReviewPrompt(goal, recordedSteps, goalAchieved, interventions, locale) {
|
|
21
|
+
const system = getReviewSystemPrompt(locale);
|
|
22
|
+
const userPrompt = createReviewUserPrompt(goal, recordedSteps, goalAchieved, interventions, locale);
|
|
23
|
+
return { system, userPrompt };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export {
|
|
27
|
+
reviewResponseSchema,
|
|
28
|
+
createReviewPrompt
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=chunk-IGJNT457.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/runbook-generator/prompts.ts"],"sourcesContent":["/**\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":";;;;;;;AAOA,SAAS,SAAS;AAUX,IAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,eAAe,EAAE,MAAM,EAAE,OAAO;AAAA,IAC9B,iBAAiB,EAAE,OAAO;AAAA,IAC1B,MAAM,EAAE,QAAQ;AAAA,IAChB,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,IACnC,WAAW,EAAE,KAAK,CAAC,OAAO,UAAU,MAAM,CAAC;AAAA,IAC3C,sBAAsB,EAAE,QAAQ;AAAA,IAChC,oBAAoB,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1C,CAAC,CAAC;AAAA,EACF,SAAS,EAAE,OAAO;AACpB,CAAC;AAKM,SAAS,mBACd,MACA,eACA,cACA,eACA,QACwC;AACxC,QAAM,SAAS,sBAAsB,MAAM;AAC3C,QAAM,aAAa,uBAAuB,MAAM,eAAe,cAAc,eAAe,MAAM;AAClG,SAAO,EAAE,QAAQ,WAAW;AAC9B;","names":[]}
|
|
@@ -458,10 +458,19 @@ async function initModel(config) {
|
|
|
458
458
|
break;
|
|
459
459
|
}
|
|
460
460
|
case "anthropic":
|
|
461
|
-
default:
|
|
462
|
-
|
|
463
|
-
|
|
461
|
+
default: {
|
|
462
|
+
const apiKey = config?.apiKey ?? process.env.ANTHROPIC_API_KEY;
|
|
463
|
+
if (apiKey) {
|
|
464
|
+
const { createAnthropic } = await import("@ai-sdk/anthropic");
|
|
465
|
+
const client = createAnthropic({ apiKey });
|
|
466
|
+
modelFactory = (id) => client(id);
|
|
467
|
+
cachedModel = client(modelId);
|
|
468
|
+
} else {
|
|
469
|
+
modelFactory = (id) => anthropic(id);
|
|
470
|
+
cachedModel = anthropic(modelId);
|
|
471
|
+
}
|
|
464
472
|
break;
|
|
473
|
+
}
|
|
465
474
|
}
|
|
466
475
|
}
|
|
467
476
|
async function buildModelFactory(config) {
|
|
@@ -775,4 +784,4 @@ export {
|
|
|
775
784
|
isRetryableError,
|
|
776
785
|
withAIRetry
|
|
777
786
|
};
|
|
778
|
-
//# sourceMappingURL=chunk-
|
|
787
|
+
//# sourceMappingURL=chunk-KFNW4XR2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/harness/ai-model.ts","../../../src/harness/ai-metrics.ts","../../../src/harness/ai-error.ts"],"sourcesContent":["/**\n * orchestrator/ai-model --- 共有AIモデル設定\n *\n * 全AI呼び出しで使用するモデルインスタンスを管理する。\n * 起動時に initModel() を呼び出し、以降は getModel(purpose?) で取得する。\n *\n * 用途別オーバーライド:\n * initModel() に modelOverrides を渡すと、特定用途のみ別モデルを使用できる。\n * 例: セレクタ解決は Haiku、それ以外は Sonnet\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { anthropic } from \"@ai-sdk/anthropic\";\nimport { APICallError, Output, generateText, type LanguageModel } from \"ai\";\nimport { getActiveMetricsCollector } from \"./ai-metrics\";\nimport { classifyAIError, isFatalAIError } from \"./ai-error\";\n\nexport const DEFAULT_MODEL_ID = \"claude-sonnet-4-6\";\nexport const DEFAULT_PROVIDER = \"anthropic\" as const;\n\nexport type ModelProvider =\n | \"anthropic\"\n | \"openai\"\n | \"openai-compatible\"\n | \"google\"\n | \"azure\"\n | \"bedrock\"\n | \"vertex\";\n\n/** プロバイダーごとのデフォルトモデルID */\nexport const PROVIDER_DEFAULT_MODELS: Record<ModelProvider, string> = {\n anthropic: \"claude-sonnet-4-6\",\n openai: \"gpt-4o\",\n \"openai-compatible\": \"gpt-4o\",\n google: \"gemini-2.5-pro\",\n azure: \"gpt-4o\",\n bedrock: \"anthropic.claude-sonnet-4-6-v1\",\n vertex: \"claude-sonnet-4-6@20250514\",\n};\n\n/** AI 呼び出しの用途カテゴリ */\nexport type ModelPurpose =\n | \"exploration\" // 探索ループ(tool-calling)\n | \"exploration-light\" // 探索ループのルーティンステップ(安価モデル)\n | \"selector\" // セレクタ解決(高頻度)\n | \"extraction\" // データ抽出・値抽出(高頻度)\n | \"review\" // レビュー・修正提案・YAMLパッチ\n | \"fallback\" // Agent Fallback\n | \"vision\"; // Vision Fallback(スクリーンショットベースのセレクタ解決)\n\nexport interface AIModelConfig {\n /** モデルID (e.g., \"claude-sonnet-4-6\", \"gpt-4o\", \"anthropic.claude-sonnet-4-6-v1\") */\n modelId: string;\n /** プロバイダー種別 */\n provider: ModelProvider;\n /** OpenAI互換エンドポイントのベースURL */\n baseURL?: string;\n /** OpenAI互換エンドポイントのAPIキー */\n apiKey?: string;\n /** Bedrock: AWS リージョン */\n bedrockRegion?: string;\n /** Bedrock: AWS アクセスキーID */\n bedrockAccessKeyId?: string;\n /** Bedrock: AWS シークレットアクセスキー */\n bedrockSecretAccessKey?: string;\n /** Bedrock: AWS セッショントークン(一時クレデンシャル用) */\n bedrockSessionToken?: string;\n /** Vertex: Google Cloud プロジェクトID */\n vertexProject?: string;\n /** Vertex: Google Cloud リージョン */\n vertexLocation?: string;\n /** Azure: リソース名(URL組み立て: https://{resourceName}.openai.azure.com/...) */\n azureResourceName?: string;\n /** Azure: API バージョン */\n azureApiVersion?: string;\n /** 用途別モデルIDオーバーライド(プロバイダーはデフォルトと共通) */\n modelOverrides?: Partial<Record<ModelPurpose, string>>;\n}\n\nlet currentModelId: string = DEFAULT_MODEL_ID;\nlet currentProvider: string = DEFAULT_PROVIDER;\nlet currentOverrides: Partial<Record<ModelPurpose, string>> = {};\nlet cachedModel: LanguageModel | null = null;\n/** 用途別オーバーライドモデルのキャッシュ */\nconst overrideModelCache = new Map<ModelPurpose, LanguageModel>();\n/** initModel で確定したモデル生成関数(プロバイダー固有ロジックをキャッシュ) */\nlet modelFactory: ((modelId: string) => LanguageModel) | null = null;\n\n// ── AsyncLocalStorage によるスコープ付きモデルコンテキスト ──\n// サーバー(Inngest 並行実行)でテナント別 AI 設定を分離するために使用。\n// CLI は従来通りグローバル変数にフォールバック。\n\ninterface ModelContext {\n modelId: string;\n provider: string;\n overrides: Partial<Record<ModelPurpose, string>>;\n model: LanguageModel;\n factory: (modelId: string) => LanguageModel;\n overrideCache: Map<ModelPurpose, LanguageModel>;\n}\n\nconst modelStorage = new AsyncLocalStorage<ModelContext>();\n\n/**\n * スコープ付きモデルコンテキストで関数を実行する。\n * Inngest 関数内でテナント別の AI 設定を分離するために使用。\n *\n * このスコープ内では getModel() / getModelId() が ALS のコンテキストを参照する。\n */\nexport function runWithModelContext<T>(\n config: AIModelConfig,\n factory: (modelId: string) => LanguageModel,\n fn: () => Promise<T>,\n): Promise<T> {\n const model = factory(config.modelId ?? DEFAULT_MODEL_ID);\n const ctx: ModelContext = {\n modelId: config.modelId ?? DEFAULT_MODEL_ID,\n provider: config.provider ?? DEFAULT_PROVIDER,\n overrides: config.modelOverrides ?? {},\n model,\n factory,\n overrideCache: new Map(),\n };\n return modelStorage.run(ctx, fn);\n}\n\n/**\n * プロバイダーに応じたモデルインスタンスを生成する。\n * 各エントリポイントの main() で parseArgs() 直後に1回呼び出す。\n */\nexport async function initModel(config?: AIModelConfig): Promise<void> {\n const modelId = config?.modelId ?? DEFAULT_MODEL_ID;\n const provider = config?.provider ?? DEFAULT_PROVIDER;\n\n currentModelId = modelId;\n currentProvider = provider;\n currentOverrides = config?.modelOverrides ?? {};\n overrideModelCache.clear();\n\n switch (provider) {\n case \"openai\": {\n const { createOpenAI } = await import(\"@ai-sdk/openai\");\n const apiKey = config?.apiKey ?? process.env.OPENAI_API_KEY;\n const openai = createOpenAI({\n ...(apiKey ? { apiKey } : {}),\n ...(config?.baseURL ? { baseURL: config.baseURL } : {}),\n });\n modelFactory = (id) => openai(id);\n cachedModel = openai(modelId);\n break;\n }\n\n case \"google\": {\n const { createGoogleGenerativeAI } = await import(\"@ai-sdk/google\");\n const apiKey = config?.apiKey ?? process.env.GOOGLE_GENERATIVE_AI_API_KEY;\n if (!apiKey) {\n throw new Error(\n \"google プロバイダーには GOOGLE_GENERATIVE_AI_API_KEY 環境変数または apiKey が必要です\",\n );\n }\n const google = createGoogleGenerativeAI({\n apiKey,\n ...(config?.baseURL ? { baseURL: config.baseURL } : {}),\n });\n modelFactory = (id) => google(id);\n cachedModel = google(modelId);\n break;\n }\n\n case \"azure\": {\n const { createAzure } = await import(\"@ai-sdk/azure\");\n const apiKey = config?.apiKey ?? process.env.AZURE_API_KEY;\n const resourceName = config?.azureResourceName ?? process.env.AZURE_RESOURCE_NAME;\n const apiVersion = config?.azureApiVersion ?? process.env.AZURE_API_VERSION;\n if (!resourceName && !config?.baseURL) {\n throw new Error(\n \"azure プロバイダーには AZURE_RESOURCE_NAME 環境変数(または --model-base-url)が必要です\",\n );\n }\n const azure = createAzure({\n ...(resourceName ? { resourceName } : {}),\n ...(apiKey ? { apiKey } : {}),\n ...(apiVersion ? { apiVersion } : {}),\n ...(config?.baseURL ? { baseURL: config.baseURL } : {}),\n });\n modelFactory = (id) => azure(id);\n cachedModel = azure(modelId);\n break;\n }\n\n case \"openai-compatible\": {\n const { createOpenAICompatible } = await import(\"@ai-sdk/openai-compatible\");\n const baseURL = config?.baseURL ?? process.env.OPENAI_COMPATIBLE_BASE_URL;\n if (!baseURL) {\n throw new Error(\n \"openai-compatible プロバイダーには OPENAI_COMPATIBLE_BASE_URL 環境変数または --model-base-url が必要です\",\n );\n }\n const apiKey = config?.apiKey ?? process.env.OPENAI_COMPATIBLE_API_KEY ?? \"\";\n const openaiCompatible = createOpenAICompatible({\n name: \"openai-compatible\",\n baseURL,\n apiKey,\n });\n modelFactory = (id) => openaiCompatible(id);\n cachedModel = openaiCompatible(modelId);\n break;\n }\n\n case \"bedrock\": {\n const { createAmazonBedrock } = await import(\"@ai-sdk/amazon-bedrock\");\n const region = config?.bedrockRegion ?? process.env.AWS_REGION;\n if (!region) {\n throw new Error(\n \"bedrock プロバイダーには AWS_REGION 環境変数が必要です\",\n );\n }\n const accessKeyId = config?.bedrockAccessKeyId ?? process.env.AWS_ACCESS_KEY_ID;\n const secretAccessKey = config?.bedrockSecretAccessKey ?? process.env.AWS_SECRET_ACCESS_KEY;\n const sessionToken = config?.bedrockSessionToken ?? process.env.AWS_SESSION_TOKEN;\n const bedrock = createAmazonBedrock({\n region,\n ...(accessKeyId && secretAccessKey\n ? { accessKeyId, secretAccessKey, ...(sessionToken ? { sessionToken } : {}) }\n : {}),\n });\n modelFactory = (id) => bedrock(id);\n cachedModel = bedrock(modelId);\n break;\n }\n\n case \"vertex\": {\n const { createVertex } = await import(\"@ai-sdk/google-vertex\");\n const project = config?.vertexProject ?? process.env.GOOGLE_VERTEX_PROJECT;\n const location = config?.vertexLocation ?? process.env.GOOGLE_VERTEX_LOCATION;\n if (!project) {\n throw new Error(\n \"vertex プロバイダーには GOOGLE_VERTEX_PROJECT 環境変数が必要です\",\n );\n }\n if (!location) {\n throw new Error(\n \"vertex プロバイダーには GOOGLE_VERTEX_LOCATION 環境変数が必要です\",\n );\n }\n const vertex = createVertex({ project, location });\n modelFactory = (id) => vertex(id);\n cachedModel = vertex(modelId);\n break;\n }\n\n case \"anthropic\":\n default: {\n const apiKey = config?.apiKey ?? process.env.ANTHROPIC_API_KEY;\n if (apiKey) {\n const { createAnthropic } = await import(\"@ai-sdk/anthropic\");\n const client = createAnthropic({ apiKey });\n modelFactory = (id) => client(id);\n cachedModel = client(modelId);\n } else {\n modelFactory = (id) => anthropic(id);\n cachedModel = anthropic(modelId);\n }\n break;\n }\n }\n}\n\n/**\n * AIModelConfig からモデルファクトリ関数を構築する。\n * process.env を参照しない純粋なファクトリ生成。\n * initModelExplicit() とサーバー側(Inngest)の両方で使用。\n */\nexport async function buildModelFactory(\n config: AIModelConfig,\n): Promise<(modelId: string) => LanguageModel> {\n switch (config.provider) {\n case \"openai\": {\n const { createOpenAI } = await import(\"@ai-sdk/openai\");\n const openai = createOpenAI({\n ...(config.apiKey ? { apiKey: config.apiKey } : {}),\n ...(config.baseURL ? { baseURL: config.baseURL } : {}),\n });\n return (id) => openai(id);\n }\n case \"google\": {\n const { createGoogleGenerativeAI } = await import(\"@ai-sdk/google\");\n if (!config.apiKey) throw new Error(\"apiKey required for google provider\");\n const google = createGoogleGenerativeAI({ apiKey: config.apiKey });\n return (id) => google(id);\n }\n case \"azure\": {\n const { createAzure } = await import(\"@ai-sdk/azure\");\n const azure = createAzure({\n ...(config.azureResourceName ? { resourceName: config.azureResourceName } : {}),\n ...(config.apiKey ? { apiKey: config.apiKey } : {}),\n ...(config.azureApiVersion ? { apiVersion: config.azureApiVersion } : {}),\n ...(config.baseURL ? { baseURL: config.baseURL } : {}),\n });\n return (id) => azure(id);\n }\n case \"openai-compatible\": {\n if (!config.baseURL) throw new Error(\"baseURL required for openai-compatible\");\n const { createOpenAICompatible } = await import(\"@ai-sdk/openai-compatible\");\n const compat = createOpenAICompatible({\n name: \"openai-compatible\",\n baseURL: config.baseURL,\n apiKey: config.apiKey ?? \"\",\n });\n return (id) => compat(id);\n }\n case \"bedrock\": {\n if (!config.bedrockRegion) throw new Error(\"bedrockRegion required for bedrock\");\n const { createAmazonBedrock } = await import(\"@ai-sdk/amazon-bedrock\");\n const bedrock = createAmazonBedrock({\n region: config.bedrockRegion,\n ...(config.bedrockAccessKeyId && config.bedrockSecretAccessKey\n ? {\n accessKeyId: config.bedrockAccessKeyId,\n secretAccessKey: config.bedrockSecretAccessKey,\n ...(config.bedrockSessionToken ? { sessionToken: config.bedrockSessionToken } : {}),\n }\n : {}),\n });\n return (id) => bedrock(id);\n }\n case \"vertex\": {\n if (!config.vertexProject) throw new Error(\"vertexProject required for vertex\");\n if (!config.vertexLocation) throw new Error(\"vertexLocation required for vertex\");\n const { createVertex } = await import(\"@ai-sdk/google-vertex\");\n const vertex = createVertex({\n project: config.vertexProject,\n location: config.vertexLocation,\n });\n return (id) => vertex(id);\n }\n case \"anthropic\":\n default: {\n if (config.apiKey) {\n const { createAnthropic } = await import(\"@ai-sdk/anthropic\");\n const client = createAnthropic({ apiKey: config.apiKey });\n return (id) => client(id);\n }\n const { anthropic } = await import(\"@ai-sdk/anthropic\");\n return (id) => anthropic(id);\n }\n }\n}\n\n/**\n * SDK 用: process.env を一切参照しないモデル初期化。\n * config に必要な値が不足していれば Error をスロー。\n *\n * Anthropic の場合は apiKey を渡せば環境変数より優先される。\n * Bedrock / Vertex は IAM ロール / ADC での自動認証に対応するため、\n * 明示的な認証情報は optional。\n */\nexport async function initModelExplicit(config: AIModelConfig): Promise<void> {\n currentModelId = config.modelId;\n currentProvider = config.provider;\n currentOverrides = config.modelOverrides ?? {};\n overrideModelCache.clear();\n\n const factory = await buildModelFactory(config);\n modelFactory = factory;\n cachedModel = factory(config.modelId);\n}\n\n/**\n * 用途に応じたモデルを取得する。\n * purpose 省略時はデフォルトモデル。\n * 用途別オーバーライドが設定されていればそのモデルを返す。\n * AsyncLocalStorage → グローバル変数の優先順で参照(CLI 後方互換)。\n */\nexport function getModel(purpose?: ModelPurpose): LanguageModel {\n // ALS スコープ内(サーバー)の場合はスコープ付きコンテキストを使用\n const ctx = modelStorage.getStore();\n if (ctx) {\n if (purpose) {\n const overrideId = ctx.overrides[purpose];\n if (overrideId && overrideId !== ctx.modelId) {\n const cached = ctx.overrideCache.get(purpose);\n if (cached) return cached;\n\n const model = ctx.factory(overrideId);\n ctx.overrideCache.set(purpose, model);\n return model;\n }\n }\n return ctx.model;\n }\n\n // グローバル変数(CLI)\n if (purpose) {\n const overrideId = currentOverrides[purpose];\n if (overrideId && overrideId !== currentModelId) {\n const cached = overrideModelCache.get(purpose);\n if (cached) return cached;\n\n const factory = modelFactory ?? ((id: string) => anthropic(id));\n const model = factory(overrideId);\n overrideModelCache.set(purpose, model);\n return model;\n }\n }\n\n if (!cachedModel) {\n cachedModel = anthropic(DEFAULT_MODEL_ID);\n }\n return cachedModel;\n}\n\n/** 用途に応じた実際のモデルIDを返す(ログ・レポート用) */\nexport function getModelId(purpose?: ModelPurpose): string {\n const ctx = modelStorage.getStore();\n const activeOverrides = ctx ? ctx.overrides : currentOverrides;\n const activeModelId = ctx ? ctx.modelId : currentModelId;\n\n if (purpose) {\n const overrideId = activeOverrides[purpose];\n if (overrideId) return overrideId;\n }\n return activeModelId;\n}\n\n/** 現在のプロバイダー名(レポート・ログ用) */\nexport function getModelProvider(): string {\n const ctx = modelStorage.getStore();\n return ctx ? ctx.provider : currentProvider;\n}\n\n/** 現在のオーバーライド設定を返す(レポート用) */\nexport function getModelOverrides(): Partial<Record<ModelPurpose, string>> {\n const ctx = modelStorage.getStore();\n return { ...(ctx ? ctx.overrides : currentOverrides) };\n}\n\n// ── メトリクス付き AI 呼び出しラッパー ──\n\n/** usage オブジェクトの共通型 */\ninterface UsageLike {\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n /** @deprecated AI SDK v6 で inputTokenDetails.cacheReadTokens に移行 */\n cachedInputTokens?: number;\n inputTokenDetails?: {\n noCacheTokens?: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n };\n}\n\n/**\n * usage オブジェクトからキャッシュ済みトークン数を安全に取得する。\n * AI SDK v6 の inputTokenDetails.cacheReadTokens を優先し、\n * フォールバックとして deprecated な cachedInputTokens を参照する。\n */\nfunction extractCachedTokens(usage: UsageLike): number {\n return usage.inputTokenDetails?.cacheReadTokens ?? usage.cachedInputTokens ?? 0;\n}\n\n/** usage から cacheWriteTokens を取得する(providerMetadata 不要な場合用) */\nfunction extractCacheCreationTokensFromUsage(usage: UsageLike): number {\n return usage.inputTokenDetails?.cacheWriteTokens ?? 0;\n}\n\n/**\n * AI SDK v6 の usage から非キャッシュ入力トークン数を取得する。\n *\n * AI SDK v6 では usage.inputTokens = total(noCache + cacheRead + cacheWrite)。\n * AICallMetric.inputTokens は非キャッシュ部分のみを期待するため、\n * inputTokenDetails.noCacheTokens を優先し、フォールバックとして total から差し引く。\n */\nfunction extractNonCachedInputTokens(usage: UsageLike): number {\n if (usage.inputTokenDetails?.noCacheTokens != null) {\n return usage.inputTokenDetails.noCacheTokens;\n }\n // フォールバック: total - cacheRead - cacheWrite\n const total = usage.inputTokens ?? 0;\n const cached = extractCachedTokens(usage);\n const cacheCreation = extractCacheCreationTokensFromUsage(usage);\n return Math.max(0, total - cached - cacheCreation);\n}\n\n/** usage を持つ AI 呼び出し結果からメトリクスを記録する共通ヘルパー */\nfunction recordMetrics(\n purpose: ModelPurpose,\n usage: UsageLike,\n durationMs: number,\n cacheCreationTokens?: number,\n rawProviderUsage?: Record<string, unknown>,\n): void {\n getActiveMetricsCollector().record({\n timestamp: new Date().toISOString(),\n purpose,\n modelId: getModelId(purpose),\n inputTokens: extractNonCachedInputTokens(usage),\n outputTokens: usage.outputTokens ?? 0,\n cachedInputTokens: extractCachedTokens(usage),\n cacheCreationTokens: cacheCreationTokens ?? 0,\n durationMs: Math.round(durationMs),\n rawProviderUsage,\n });\n}\n\n/**\n * AI SDK の result から providerMetadata.anthropic.cacheCreationInputTokens を取得する。\n * multi-step (tool-calling loop) の場合は各ステップの値を合算する。\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction extractCacheCreationTokens(result: any): number {\n // multi-step の場合: steps 配列の各 providerMetadata を合算\n if (Array.isArray(result.steps) && result.steps.length > 0) {\n let total = 0;\n for (const step of result.steps) {\n total += step.providerMetadata?.anthropic?.cacheCreationInputTokens ?? 0;\n }\n return total;\n }\n // single-step の場合\n return result.providerMetadata?.anthropic?.cacheCreationInputTokens ?? 0;\n}\n\n/**\n * 構造化出力のメトリクス計測ラッパー。\n * AI SDK v6 の generateText + Output.object を使用して構造化データを生成する。\n *\n * generateObject は v6 で deprecated(v7 で削除予定)のため、\n * generateText + Output.object に移行。呼び出し側の互換性のため\n * result.object プロパティも維持する。\n *\n * 型パラメータを正確に保つため、params は any で受け取る。\n * 呼び出し側はスキーマ定義で型安全性を担保している。\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function trackedGenerateObject(purpose: ModelPurpose, params: any): Promise<any> {\n const start = performance.now();\n const { schema, ...rest } = params;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let result: any;\n try {\n result = await generateText({\n ...rest,\n maxRetries: 0, // AI SDK 内部リトライを無効化、withAIRetry に委譲\n output: Output.object({ schema }),\n });\n } catch (error) {\n // エラー時: 最低限の呼び出し記録(トークン数 0)\n getActiveMetricsCollector().record({\n timestamp: new Date().toISOString(),\n purpose,\n modelId: getModelId(purpose),\n inputTokens: 0,\n outputTokens: 0,\n cachedInputTokens: 0,\n cacheCreationTokens: 0,\n durationMs: Math.round(performance.now() - start),\n });\n throw error;\n }\n const step = result.steps?.[0];\n const rawUsage = (step?.providerMetadata?.anthropic ?? result.providerMetadata?.anthropic) as Record<string, unknown> | undefined;\n recordMetrics(purpose, result.usage, performance.now() - start, extractCacheCreationTokens(result), rawUsage);\n // output → object エイリアスで後方互換性を維持\n return { ...result, object: result.output };\n}\n\n/**\n * generateText のメトリクス計測ラッパー。\n *\n * onStepFinish コールバックを使い、各ステップ完了時にリアルタイムでメトリクスを記録する。\n * これにより、マルチステップ(tool-calling ループ)が途中で失敗しても、\n * 完了済みステップのトークン消費量は正確に記録される。\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function trackedGenerateText(purpose: ModelPurpose, params: any): Promise<any> {\n const start = performance.now();\n let lastStepTime = start;\n let stepsRecorded = 0;\n\n // onStepFinish: 各ステップ完了時にリアルタイムでメトリクスを記録\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const onStepFinish = (stepResult: any) => {\n const now = performance.now();\n const stepDuration = now - lastStepTime;\n lastStepTime = now;\n\n const modelId = stepResult.response?.modelId || getModelId(purpose);\n const rawUsage = stepResult.providerMetadata?.anthropic as Record<string, unknown> | undefined;\n\n getActiveMetricsCollector().record({\n timestamp: new Date().toISOString(),\n purpose,\n modelId,\n inputTokens: extractNonCachedInputTokens(stepResult.usage ?? {}),\n outputTokens: stepResult.usage?.outputTokens ?? 0,\n cachedInputTokens: extractCachedTokens(stepResult.usage ?? {}),\n cacheCreationTokens: Number(stepResult.providerMetadata?.anthropic?.cacheCreationInputTokens ?? 0),\n durationMs: Math.round(stepDuration),\n rawProviderUsage: rawUsage,\n });\n stepsRecorded++;\n };\n\n try {\n const result = await generateText({\n ...params,\n maxRetries: 0, // AI SDK 内部リトライを無効化、withAIRetry に委譲\n onStepFinish,\n });\n // onStepFinish で全ステップ記録済み — 追加記録不要\n return result;\n } catch (error) {\n // onStepFinish が 1 回も呼ばれなかった場合のみ 0 トークン記録\n // (API 接続前のエラー等)\n if (stepsRecorded === 0) {\n getActiveMetricsCollector().record({\n timestamp: new Date().toISOString(),\n purpose,\n modelId: getModelId(purpose),\n inputTokens: 0,\n outputTokens: 0,\n cachedInputTokens: 0,\n cacheCreationTokens: 0,\n durationMs: Math.round(performance.now() - start),\n });\n }\n throw error;\n }\n}\n\n// ── リトライ可能エラー判定 + リトライラッパー ──\n\n/**\n * リトライ可能な一時的エラーかどうかを判定する。\n * - 429 (Rate Limit)\n * - 529 (Overloaded)\n * - 5xx (Server Error)\n * - ネットワークエラー(ECONNRESET, ETIMEDOUT 等)\n */\nexport function isRetryableError(error: unknown): boolean {\n // AI SDK の構造化エラー\n if (APICallError.isInstance(error)) {\n if (error.isRetryable) return true;\n const code = error.statusCode;\n if (code !== undefined) {\n if (code === 429 || code === 529) return true;\n if (code >= 500 && code < 600) return true;\n }\n }\n\n // ネットワークエラー + メッセージベースのフォールバック\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n if (\n msg.includes(\"econnreset\") ||\n msg.includes(\"etimedout\") ||\n msg.includes(\"econnrefused\") ||\n msg.includes(\"fetch failed\") ||\n msg.includes(\"socket hang up\")\n ) {\n return true;\n }\n if (msg.includes(\"rate limit\") || msg.includes(\"rate_limit\")) return true;\n if (msg.includes(\"overloaded\")) return true;\n if (/\\b(429|529)\\b/.test(msg)) return true;\n if (/\\b5\\d{2}\\b/.test(error.message)) return true;\n }\n\n return false;\n}\n\n/**\n * AI 呼び出しのリトライラッパー。\n * リトライ可能なエラー時のみ指数バックオフでリトライする。\n * スキーマ不一致などの致命的エラーはリトライせず即座に throw する。\n */\nexport async function withAIRetry<T>(\n fn: () => Promise<T>,\n opts?: { maxRetries?: number; label?: string },\n): Promise<T> {\n const maxRetries = opts?.maxRetries ?? 2;\n for (let attempt = 0; ; attempt++) {\n try {\n return await fn();\n } catch (error) {\n if (attempt < maxRetries && isRetryableError(error)) {\n const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s\n await new Promise((resolve) => setTimeout(resolve, delay));\n continue;\n }\n // 致命的エラーはユーザーフレンドリーなメッセージで再スロー\n if (isFatalAIError(error)) {\n const info = classifyAIError(error);\n const enhanced = new Error(info.userMessage);\n enhanced.cause = error;\n enhanced.name = \"AIAPIError\";\n throw enhanced;\n }\n throw error;\n }\n }\n}\n","/**\n * ai-metrics --- AI 呼び出しのメトリクス収集・集計\n *\n * 各 AI 呼び出しのトークン消費量・コスト・レイテンシを集計する。\n * グローバルシングルトン `globalMetrics` を通じて全呼び出しのメトリクスを蓄積し、\n * 実行完了時にサマリーを取得する。\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { ModelPurpose } from \"./ai-model\";\n\nexport interface AICallMetric {\n /** 呼び出し時刻 */\n timestamp: string;\n /** 用途カテゴリ */\n purpose: ModelPurpose;\n /** 使用モデル ID */\n modelId: string;\n /** 入力トークン数(非キャッシュ部分のみ。Anthropic API の input_tokens に対応) */\n inputTokens: number;\n /** 出力トークン数 */\n outputTokens: number;\n /** キャッシュ読み取りトークン数 */\n cachedInputTokens: number;\n /** キャッシュ書き込みトークン数 */\n cacheCreationTokens: number;\n /** レイテンシ (ms) */\n durationMs: number;\n /** Anthropic API の生レスポンス usage(デバッグ用・コスト検証用) */\n rawProviderUsage?: Record<string, unknown>;\n}\n\nexport interface PurposeBreakdown {\n calls: number;\n inputTokens: number;\n outputTokens: number;\n cachedInputTokens: number;\n cacheCreationTokens: number;\n durationMs: number;\n}\n\nexport interface ModelBreakdown {\n calls: number;\n inputTokens: number;\n outputTokens: number;\n cachedInputTokens: number;\n cacheCreationTokens: number;\n durationMs: number;\n estimatedCostUsd: number;\n}\n\nexport interface LatencyPercentiles {\n p50: number;\n p95: number;\n p99: number;\n}\n\nexport interface AIMetricsSummary {\n totalCalls: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCachedInputTokens: number;\n totalCacheCreationTokens: number;\n /** キャッシュヒット率 = cachedInputTokens / totalRealInput */\n cacheHitRate: number;\n /** 推定コスト (USD) */\n estimatedCostUsd: number;\n totalDurationMs: number;\n /** AI 呼び出しレイテンシのパーセンタイル (ms) */\n latencyPercentiles?: LatencyPercentiles;\n /** 用途別の内訳 */\n byPurpose: Record<string, PurposeBreakdown>;\n /** モデル別の内訳 */\n byModel: Record<string, ModelBreakdown>;\n}\n\n/** モデル別の料金テーブル (USD / 1M tokens) */\nexport interface PricingEntry {\n input: number;\n output: number;\n cacheRead: number;\n /** キャッシュ書き込み料金。0 の場合はプロバイダーが追加課金しない */\n cacheWrite: number;\n}\n\nconst PRICING_TABLE: Record<string, PricingEntry> = {\n // Anthropic — cacheWrite = input × 1.25, cacheRead = input × 0.10\n \"claude-sonnet-4-6\": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },\n \"claude-sonnet-4-5\": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },\n \"claude-sonnet-4\": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },\n \"claude-haiku-4-5\": { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 },\n \"claude-haiku-3-5\": { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },\n \"claude-opus-4-6\": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },\n \"claude-opus-4-5\": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },\n \"claude-opus-4-1\": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },\n \"claude-opus-4\": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },\n // OpenAI (Azure OpenAI も同名モデルのため部分一致で対応) — キャッシュ書き込み追加課金なし\n \"gpt-4o\": { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 0 },\n \"gpt-4o-mini\": { input: 0.15, output: 0.6, cacheRead: 0.075, cacheWrite: 0 },\n \"gpt-4.1\": { input: 2, output: 8, cacheRead: 0.5, cacheWrite: 0 },\n \"gpt-4.1-mini\": { input: 0.4, output: 1.6, cacheRead: 0.1, cacheWrite: 0 },\n \"gpt-4.1-nano\": { input: 0.1, output: 0.4, cacheRead: 0.025, cacheWrite: 0 },\n \"o3\": { input: 2, output: 8, cacheRead: 0.5, cacheWrite: 0 },\n \"o4-mini\": { input: 1.1, output: 4.4, cacheRead: 0.55, cacheWrite: 0 },\n // Google Gemini — キャッシュ書き込み追加課金なし\n \"gemini-2.5-pro\": { input: 1.25, output: 10, cacheRead: 0.315, cacheWrite: 0 },\n \"gemini-2.5-flash\": { input: 0.15, output: 0.6, cacheRead: 0.0375, cacheWrite: 0 },\n \"gemini-2.0-flash\": { input: 0.1, output: 0.4, cacheRead: 0.025, cacheWrite: 0 },\n};\n\n/** デフォルト料金(未知のモデル用、Sonnet 相当) */\nconst DEFAULT_PRICING: PricingEntry = { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 };\n\nexport function getPricing(modelId: string): PricingEntry {\n // 完全一致\n if (PRICING_TABLE[modelId]) return PRICING_TABLE[modelId];\n\n // 部分一致(Bedrock/Vertex のモデル ID 対応)\n for (const [key, pricing] of Object.entries(PRICING_TABLE)) {\n if (modelId.includes(key)) return pricing;\n }\n\n return DEFAULT_PRICING;\n}\n\n/**\n * 単一メトリクスのコスト計算。\n *\n * Anthropic API では inputTokens は非キャッシュ・非キャッシュ書き込み部分のみ。\n * 総入力 = inputTokens + cachedInputTokens + cacheCreationTokens\n */\nexport function calculateCost(metric: AICallMetric): number {\n const pricing = getPricing(metric.modelId);\n return (\n (metric.inputTokens * pricing.input) / 1_000_000 +\n (metric.cachedInputTokens * pricing.cacheRead) / 1_000_000 +\n (metric.cacheCreationTokens * pricing.cacheWrite) / 1_000_000 +\n (metric.outputTokens * pricing.output) / 1_000_000\n );\n}\n\n/** 料金テーブルの読み取り専用コピーを返す(テスト・検証用) */\nexport function getPricingTable(): Readonly<Record<string, PricingEntry>> {\n return PRICING_TABLE;\n}\n\n/**\n * トークンカウントから実際の総入力トークン数を計算する。\n *\n * AICallMetric / PurposeBreakdown / ModelBreakdown(inputTokens 系)と\n * AIMetricsSummary / AggregatedMetrics(totalInputTokens 系)の両方を受け付ける。\n */\nexport function computeTotalRealInput(tokens: {\n inputTokens?: number;\n cachedInputTokens?: number;\n cacheCreationTokens?: number;\n totalInputTokens?: number;\n totalCachedInputTokens?: number;\n totalCacheCreationTokens?: number;\n}): number {\n const input = tokens.totalInputTokens ?? tokens.inputTokens ?? 0;\n const cached = tokens.totalCachedInputTokens ?? tokens.cachedInputTokens ?? 0;\n const creation = tokens.totalCacheCreationTokens ?? tokens.cacheCreationTokens ?? 0;\n return input + cached + creation;\n}\n\n/**\n * トークンカウントからキャッシュヒット率を計算する(0〜1)。\n *\n * computeTotalRealInput と同じ命名規則を受け付ける。\n */\nexport function computeCacheRate(tokens: {\n inputTokens?: number;\n cachedInputTokens?: number;\n cacheCreationTokens?: number;\n totalInputTokens?: number;\n totalCachedInputTokens?: number;\n totalCacheCreationTokens?: number;\n}): number {\n const total = computeTotalRealInput(tokens);\n const cached = tokens.totalCachedInputTokens ?? tokens.cachedInputTokens ?? 0;\n return total > 0 ? cached / total : 0;\n}\n\nexport class AIMetricsCollector {\n private metrics: AICallMetric[] = [];\n\n record(metric: AICallMetric): void {\n this.metrics.push(metric);\n }\n\n getSummary(): AIMetricsSummary {\n const totalCalls = this.metrics.length;\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalCachedInputTokens = 0;\n let totalCacheCreationTokens = 0;\n let totalDurationMs = 0;\n let estimatedCostUsd = 0;\n const byPurpose: Record<string, PurposeBreakdown> = {};\n const byModel: Record<string, ModelBreakdown> = {};\n\n for (const m of this.metrics) {\n totalInputTokens += m.inputTokens;\n totalOutputTokens += m.outputTokens;\n totalCachedInputTokens += m.cachedInputTokens;\n totalCacheCreationTokens += m.cacheCreationTokens;\n totalDurationMs += m.durationMs;\n const cost = calculateCost(m);\n estimatedCostUsd += cost;\n\n const bp = byPurpose[m.purpose] ??= {\n calls: 0,\n inputTokens: 0,\n outputTokens: 0,\n cachedInputTokens: 0,\n cacheCreationTokens: 0,\n durationMs: 0,\n };\n bp.calls++;\n bp.inputTokens += m.inputTokens;\n bp.outputTokens += m.outputTokens;\n bp.cachedInputTokens += m.cachedInputTokens;\n bp.cacheCreationTokens += m.cacheCreationTokens;\n bp.durationMs += m.durationMs;\n\n const bm = byModel[m.modelId] ??= {\n calls: 0,\n inputTokens: 0,\n outputTokens: 0,\n cachedInputTokens: 0,\n cacheCreationTokens: 0,\n durationMs: 0,\n estimatedCostUsd: 0,\n };\n bm.calls++;\n bm.inputTokens += m.inputTokens;\n bm.outputTokens += m.outputTokens;\n bm.cachedInputTokens += m.cachedInputTokens;\n bm.cacheCreationTokens += m.cacheCreationTokens;\n bm.durationMs += m.durationMs;\n bm.estimatedCostUsd += cost;\n }\n\n const cacheHitRate = computeCacheRate({\n inputTokens: totalInputTokens,\n cachedInputTokens: totalCachedInputTokens,\n cacheCreationTokens: totalCacheCreationTokens,\n });\n\n // レイテンシパーセンタイル算出\n let latencyPercentiles: LatencyPercentiles | undefined;\n if (this.metrics.length > 0) {\n const sorted = this.metrics.map((m) => m.durationMs).sort((a, b) => a - b);\n const percentile = (p: number): number => {\n const idx = Math.ceil((p / 100) * sorted.length) - 1;\n return sorted[Math.max(0, Math.min(idx, sorted.length - 1))];\n };\n latencyPercentiles = {\n p50: Math.round(percentile(50)),\n p95: Math.round(percentile(95)),\n p99: Math.round(percentile(99)),\n };\n }\n\n return {\n totalCalls,\n totalInputTokens,\n totalOutputTokens,\n totalCachedInputTokens,\n totalCacheCreationTokens,\n cacheHitRate,\n estimatedCostUsd: Math.round(estimatedCostUsd * 1_000_000) / 1_000_000,\n totalDurationMs,\n latencyPercentiles,\n byPurpose,\n byModel,\n };\n }\n\n /** メトリクスをリセットする(eval ケース間で使用) */\n reset(): void {\n this.metrics = [];\n }\n\n /** 蓄積済みの個別メトリクスを返す(デバッグ用) */\n getMetrics(): readonly AICallMetric[] {\n return this.metrics;\n }\n\n /** 蓄積済みメトリクスの件数 */\n get count(): number {\n return this.metrics.length;\n }\n}\n\n/** グローバルシングルトン */\nexport const globalMetrics = new AIMetricsCollector();\n\n/**\n * アクティブなメトリクスコレクターの切替機構。\n *\n * 並列実行時は AsyncLocalStorage を使用してスコープ付きコレクターを分離する。\n * CLI の単一スレッド実行では legacy な activeCollector 変数にフォールバック。\n */\nconst metricsStorage = new AsyncLocalStorage<AIMetricsCollector>();\nlet activeCollector: AIMetricsCollector = globalMetrics;\n\n/**\n * 指定のコレクターをスコープ付きで実行する。\n * AsyncLocalStorage を使用し、並列実行でも安全にメトリクスを分離する。\n */\nexport function runWithMetricsCollector<T>(\n collector: AIMetricsCollector,\n fn: () => Promise<T>,\n): Promise<T> {\n return metricsStorage.run(collector, fn);\n}\n\n/**\n * アクティブなコレクターを設定する。\n * @deprecated 並列実行では runWithMetricsCollector() を使用してください。\n * この関数はグローバル変数を書き換えるため、並列実行時にレースコンディションが発生します。\n */\nexport function setActiveMetricsCollector(collector: AIMetricsCollector): void {\n activeCollector = collector;\n}\n\n/** アクティブなコレクターを取得する(AsyncLocalStorage → legacy activeCollector の優先順) */\nexport function getActiveMetricsCollector(): AIMetricsCollector {\n return metricsStorage.getStore() ?? activeCollector;\n}\n\n/**\n * アクティブなコレクターを globalMetrics にリセットする。\n * @deprecated 並列実行では runWithMetricsCollector() を使用してください。\n */\nexport function resetActiveMetricsCollector(): void {\n activeCollector = globalMetrics;\n}\n\n// ── テナント別メトリクス(Phase 3 で Activity 内から呼び出す) ──\n\nconst tenantCollectors = new Map<string, AIMetricsCollector>();\n\n/** テナント専用の AIMetricsCollector を取得する(同一 tenantId は同一インスタンス) */\nexport function getMetricsForTenant(tenantId: string): AIMetricsCollector {\n let collector = tenantCollectors.get(tenantId);\n if (!collector) {\n collector = new AIMetricsCollector();\n tenantCollectors.set(tenantId, collector);\n }\n return collector;\n}\n\n/** 指定テナントのメトリクスを削除する */\nexport function clearTenantMetrics(tenantId: string): void {\n tenantCollectors.delete(tenantId);\n}\n\n/** 全テナントのメトリクスを削除する */\nexport function clearAllTenantMetrics(): void {\n tenantCollectors.clear();\n}\n","/**\n * ai-error --- AI API エラー分類ユーティリティ\n *\n * AI API 呼び出しエラーをカテゴリ分類し、ユーザーフレンドリーなメッセージを生成する。\n */\n\nimport { APICallError } from \"ai\";\n\nexport type AIErrorCategory =\n | \"billing\" // クレジット不足、支払い問題\n | \"auth\" // 認証失敗、無効な API キー\n | \"rate_limit\" // レート制限 (429)\n | \"overloaded\" // API 過負荷 (529)\n | \"server_error\" // サーバーエラー (5xx)\n | \"network\" // 接続エラー\n | \"model_not_found\" // モデル未検出 (404)\n | \"content_filter\" // コンテンツポリシー違反\n | \"unknown\";\n\nexport interface AIErrorInfo {\n category: AIErrorCategory;\n statusCode?: number;\n isRetryable: boolean;\n userMessage: string;\n originalMessage: string;\n}\n\n/** billing 関連のメッセージパターン */\nconst BILLING_PATTERNS = [\n /credit\\s*balance/i,\n /insufficient\\s*(funds|credit|balance)/i,\n /billing/i,\n /payment\\s*required/i,\n /quota\\s*exceeded/i,\n];\n\n/** 認証関連のメッセージパターン */\nconst AUTH_PATTERNS = [\n /unauthorized/i,\n /invalid[\\s_-]*api[\\s_-]*key/i,\n /authentication\\s*failed/i,\n /forbidden/i,\n /permission\\s*denied/i,\n /invalid[\\s_-]*x[\\s_-]*api[\\s_-]*key/i,\n /invalid[\\s_-]*bearer[\\s_-]*token/i,\n];\n\n/** ネットワーク関連のメッセージパターン */\nconst NETWORK_PATTERNS = [\n /econnreset/i,\n /etimedout/i,\n /econnrefused/i,\n /fetch\\s*failed/i,\n /socket\\s*hang\\s*up/i,\n /network\\s*error/i,\n];\n\n/** コンテンツフィルター関連のメッセージパターン */\nconst CONTENT_FILTER_PATTERNS = [\n /content[\\s_-]*filter/i,\n /content[\\s_-]*policy/i,\n /safety[\\s_-]*filter/i,\n /content[\\s_-]*moderation/i,\n];\n\n/** モデル未検出のメッセージパターン */\nconst MODEL_NOT_FOUND_PATTERNS = [\n /model[\\s_-]*not[\\s_-]*found/i,\n /does[\\s_-]*not[\\s_-]*exist/i,\n /unknown[\\s_-]*model/i,\n];\n\nfunction matchesAny(message: string, patterns: RegExp[]): boolean {\n return patterns.some((p) => p.test(message));\n}\n\nfunction buildUserMessage(category: AIErrorCategory, originalMessage: string): string {\n switch (category) {\n case \"billing\":\n return `AI API billing error: ${originalMessage}`;\n case \"auth\":\n return `AI API authentication failed: ${originalMessage}`;\n case \"rate_limit\":\n return \"AI API rate limit exceeded. Retrying automatically.\";\n case \"overloaded\":\n return \"AI API is temporarily overloaded. Retrying automatically.\";\n case \"server_error\":\n return `AI API server error: ${originalMessage}`;\n case \"network\":\n return `Network error connecting to AI API: ${originalMessage}`;\n case \"model_not_found\":\n return `AI model not found: ${originalMessage}`;\n case \"content_filter\":\n return `AI API content policy violation: ${originalMessage}`;\n case \"unknown\":\n return originalMessage;\n }\n}\n\nfunction isRetryableCategory(category: AIErrorCategory): boolean {\n return category === \"rate_limit\" || category === \"overloaded\" || category === \"server_error\" || category === \"network\";\n}\n\n/**\n * AI API エラーを分類してユーザーフレンドリーな情報を返す。\n */\nexport function classifyAIError(error: unknown): AIErrorInfo {\n const originalMessage = error instanceof Error ? error.message : String(error);\n\n // APICallError の場合: statusCode ベースで分類\n if (APICallError.isInstance(error)) {\n const code = error.statusCode;\n const body = typeof error.responseBody === \"string\" ? error.responseBody : \"\";\n const msg = error.message + \" \" + body;\n\n if (code !== undefined) {\n // billing: 400/402 + billing パターン\n if ((code === 400 || code === 402) && matchesAny(msg, BILLING_PATTERNS)) {\n return { category: \"billing\", statusCode: code, isRetryable: false, userMessage: buildUserMessage(\"billing\", originalMessage), originalMessage };\n }\n // auth: 401, 403\n if (code === 401 || code === 403) {\n return { category: \"auth\", statusCode: code, isRetryable: false, userMessage: buildUserMessage(\"auth\", originalMessage), originalMessage };\n }\n // model not found: 404\n if (code === 404) {\n return { category: \"model_not_found\", statusCode: code, isRetryable: false, userMessage: buildUserMessage(\"model_not_found\", originalMessage), originalMessage };\n }\n // rate limit: 429\n if (code === 429) {\n return { category: \"rate_limit\", statusCode: code, isRetryable: true, userMessage: buildUserMessage(\"rate_limit\", originalMessage), originalMessage };\n }\n // overloaded: 529\n if (code === 529) {\n return { category: \"overloaded\", statusCode: code, isRetryable: true, userMessage: buildUserMessage(\"overloaded\", originalMessage), originalMessage };\n }\n // server error: 5xx\n if (code >= 500 && code < 600) {\n return { category: \"server_error\", statusCode: code, isRetryable: true, userMessage: buildUserMessage(\"server_error\", originalMessage), originalMessage };\n }\n }\n\n // statusCode なし or 不明 → メッセージパターンで分類\n if (matchesAny(msg, BILLING_PATTERNS)) {\n return { category: \"billing\", statusCode: code, isRetryable: false, userMessage: buildUserMessage(\"billing\", originalMessage), originalMessage };\n }\n if (matchesAny(msg, AUTH_PATTERNS)) {\n return { category: \"auth\", statusCode: code, isRetryable: false, userMessage: buildUserMessage(\"auth\", originalMessage), originalMessage };\n }\n if (matchesAny(msg, CONTENT_FILTER_PATTERNS)) {\n return { category: \"content_filter\", statusCode: code, isRetryable: false, userMessage: buildUserMessage(\"content_filter\", originalMessage), originalMessage };\n }\n if (matchesAny(msg, MODEL_NOT_FOUND_PATTERNS)) {\n return { category: \"model_not_found\", statusCode: code, isRetryable: false, userMessage: buildUserMessage(\"model_not_found\", originalMessage), originalMessage };\n }\n }\n\n // 一般的な Error: メッセージパターンで分類\n if (error instanceof Error) {\n const msg = error.message;\n if (matchesAny(msg, BILLING_PATTERNS)) {\n return { category: \"billing\", isRetryable: false, userMessage: buildUserMessage(\"billing\", originalMessage), originalMessage };\n }\n if (matchesAny(msg, AUTH_PATTERNS)) {\n return { category: \"auth\", isRetryable: false, userMessage: buildUserMessage(\"auth\", originalMessage), originalMessage };\n }\n if (matchesAny(msg, NETWORK_PATTERNS)) {\n return { category: \"network\", isRetryable: true, userMessage: buildUserMessage(\"network\", originalMessage), originalMessage };\n }\n if (matchesAny(msg, CONTENT_FILTER_PATTERNS)) {\n return { category: \"content_filter\", isRetryable: false, userMessage: buildUserMessage(\"content_filter\", originalMessage), originalMessage };\n }\n if (matchesAny(msg, MODEL_NOT_FOUND_PATTERNS)) {\n return { category: \"model_not_found\", isRetryable: false, userMessage: buildUserMessage(\"model_not_found\", originalMessage), originalMessage };\n }\n }\n\n return { category: \"unknown\", isRetryable: false, userMessage: originalMessage, originalMessage };\n}\n\n/**\n * ユーザー向けメッセージを返す簡易版。\n */\nexport function getUserFriendlyAIError(error: unknown): string {\n return classifyAIError(error).userMessage;\n}\n\n/**\n * 致命的エラー(リトライ不可・即座に中断すべき)かどうかを判定する。\n * billing, auth, model_not_found で true。\n */\nexport function isFatalAIError(error: unknown): boolean {\n const { category } = classifyAIError(error);\n return category === \"billing\" || category === \"auth\" || category === \"model_not_found\";\n}\n\n/**\n * 文字列ベースのエラー分類(Inngest onFailure 用)。\n * APICallError インスタンスが失われた後でもメッセージパターンで分類する。\n */\nexport function getUserFriendlyAIErrorFromMessage(message: string): string {\n if (matchesAny(message, BILLING_PATTERNS)) {\n return buildUserMessage(\"billing\", message);\n }\n if (matchesAny(message, AUTH_PATTERNS)) {\n return buildUserMessage(\"auth\", message);\n }\n if (matchesAny(message, NETWORK_PATTERNS)) {\n return buildUserMessage(\"network\", message);\n }\n if (matchesAny(message, CONTENT_FILTER_PATTERNS)) {\n return buildUserMessage(\"content_filter\", message);\n }\n if (matchesAny(message, MODEL_NOT_FOUND_PATTERNS)) {\n return buildUserMessage(\"model_not_found\", message);\n }\n // rate limit / overloaded\n if (/rate[\\s_-]*limit/i.test(message) || /\\b429\\b/.test(message)) {\n return buildUserMessage(\"rate_limit\", message);\n }\n if (/overloaded/i.test(message) || /\\b529\\b/.test(message)) {\n return buildUserMessage(\"overloaded\", message);\n }\n return message;\n}\n"],"mappings":"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","names":["AsyncLocalStorage","APICallError","AsyncLocalStorage","anthropic","APICallError"]}
|
|
@@ -133,6 +133,8 @@ var StepActionSchema = z2.object({
|
|
|
133
133
|
url: z2.string().optional(),
|
|
134
134
|
/** extract アクション用: ページ内で実行する JavaScript */
|
|
135
135
|
script: z2.string().optional(),
|
|
136
|
+
/** extract アクション用: AI にデータ抽出させるプロンプト(script がない場合のフォールバック) */
|
|
137
|
+
extractPrompt: z2.string().optional(),
|
|
136
138
|
/** key アクション用: 押下するキーボードキー(Playwright 形式、例: "Enter", "Tab", "ArrowDown") */
|
|
137
139
|
keys: z2.string().optional(),
|
|
138
140
|
/** download アクション用: 保存先パス */
|
|
@@ -242,4 +244,4 @@ export {
|
|
|
242
244
|
ParsedStepSchema,
|
|
243
245
|
ParsedRunbookSchema
|
|
244
246
|
};
|
|
245
|
-
//# sourceMappingURL=chunk-
|
|
247
|
+
//# sourceMappingURL=chunk-LZDZGI4M.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/schemas/runbook-schema.ts","../../../src/schemas/element-selector.ts"],"sourcesContent":["/**\n * runbook-schema — refrain の runbook YAML 用 Zod スキーマ\n *\n * contracts の ElementSelectorSchema を再利用しつつ、\n * refrain 固有の構造(variables, captures, loop 等)を定義。\n */\n\nimport { z } from \"zod\";\nimport { ElementSelectorSchema } from \"./element-selector\";\n\n// ── Selector ──\n// contracts の ElementSelectorSchema は tagName が必須。\n// YAML では tagName がないケースがあるため default(\"unknown\") に変更。\n// deterministic-resolver が使う text フィールドを追加。\nexport const SelectorSchema = ElementSelectorSchema.extend({\n tagName: z.string().default(\"unknown\"),\n text: z.string().optional(),\n});\n\n// ── Enums ──\nexport const ActionTypeSchema = z.enum([\n \"click\",\n \"input\",\n \"select\",\n \"navigate\",\n \"scroll\",\n \"wait\",\n \"hover\",\n \"extract\",\n \"download\",\n \"export\",\n \"memory\",\n \"key\",\n]);\n\nexport const RiskLevelSchema = z.enum([\"low\", \"medium\", \"high\"]);\n\nexport const VariableSourceSchema = z.enum([\n \"prompt\",\n \"fixed\",\n \"context\",\n \"env\",\n \"expression\",\n \"data\",\n]);\n\nexport const CaptureStrategySchema = z.enum([\n \"snapshot\",\n \"url\",\n \"ai\",\n \"expression\",\n \"evaluate\",\n]);\n\n// ── StepCapture ──\nexport const StepCaptureSchema = z\n .object({\n name: z.string().min(1),\n strategy: CaptureStrategySchema,\n description: z.string().optional(),\n required: z.boolean().default(false),\n pattern: z.string().optional(),\n group: z.number().int().nonnegative().optional(),\n prompt: z.string().optional(),\n expression: z.string().optional(),\n })\n .refine(\n (c) => {\n if (!c.pattern) return true;\n try {\n new RegExp(c.pattern);\n return true;\n } catch {\n return false;\n }\n },\n { message: \"Invalid regex pattern in capture\" },\n );\n\n// ── LoopDefinition ──\nexport const LoopDefinitionSchema = z\n .object({\n /** while 型ループの条件式 */\n condition: z.string().min(1).optional(),\n /** forEach: 反復対象のテンプレート変数(JSON配列)または \"collection:name\" */\n forEach: z.string().min(1).optional(),\n /** forEach 時の各アイテム変数名 */\n itemVariable: z.string().optional(),\n /** forEach 時のインデックス変数名 */\n indexVariable: z.string().optional(),\n maxIterations: z.number().int().positive().optional(),\n counterVariable: z.string().optional(),\n })\n .refine(\n (l) => {\n // condition と forEach は排他(どちらか一方が必須)\n const hasCondition = !!l.condition;\n const hasForEach = !!l.forEach;\n return (hasCondition || hasForEach) && !(hasCondition && hasForEach);\n },\n { message: \"loop must have exactly one of 'condition' or 'forEach'\" },\n );\n\n// ── VariableDefinition ──\nexport const VariableDefinitionSchema = z.object({\n source: VariableSourceSchema,\n description: z.string().optional(),\n required: z.boolean().default(true),\n sensitive: z.boolean().default(false),\n value: z.string().optional(),\n expression: z.string().optional(),\n envKey: z.string().optional(),\n});\n\n// ── StepAction ──\nexport const StepActionSchema = z.object({\n type: ActionTypeSchema,\n selector: SelectorSchema.optional(),\n value: z.string().optional(),\n optionText: z.string().optional(),\n url: z.string().optional(),\n /** extract アクション用: ページ内で実行する JavaScript */\n script: z.string().optional(),\n /** extract アクション用: AI にデータ抽出させるプロンプト(script がない場合のフォールバック) */\n extractPrompt: z.string().optional(),\n /** key アクション用: 押下するキーボードキー(Playwright 形式、例: \"Enter\", \"Tab\", \"ArrowDown\") */\n keys: z.string().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});\n\n// ── DataSourceConfig ──\nexport const DataSourceConfigSchema = z.object({\n mapping: z.record(z.string(), z.string()),\n});\n\n// ── AggregateOperation ──\nexport const AggregateOperationSchema = z.enum([\n \"sum\",\n \"count\",\n \"concat\",\n \"min\",\n \"max\",\n \"avg\",\n \"unique_count\",\n]);\n\n// ── MemoryOperation ──\nexport const MemoryOperationSchema = z.object({\n /** append: 蓄積, aggregate: 集計 */\n type: z.enum([\"append\", \"aggregate\"]),\n /** 対象コレクション名 */\n collection: z.string(),\n /** append 時: capture 名(RuntimeStore のキー) */\n source: z.string().optional(),\n /** aggregate 時: 集計対象フィールド名 */\n field: z.string().optional(),\n /** aggregate 時: 集計操作 */\n operation: AggregateOperationSchema.optional(),\n /** aggregate 時: 結果を格納する変数名 */\n outputVariable: z.string().optional(),\n});\n\n// ── BranchDefinition(条件分岐) ──\n\nexport interface BranchCaseShape {\n match: string;\n steps: ParsedStepShape[];\n}\n\nexport interface BranchDefinitionShape {\n value: string;\n cases: BranchCaseShape[];\n default?: { steps: ParsedStepShape[] };\n}\n\n// ── ParsedStep(再帰型: loop の substeps, branches の分岐) ──\nexport interface ParsedStepShape {\n ordinal: number;\n description: string;\n action: z.infer<typeof StepActionSchema>;\n url: string;\n riskLevel: z.infer<typeof RiskLevelSchema>;\n requiresConfirmation: boolean;\n captures?: z.infer<typeof StepCaptureSchema>[];\n condition?: string;\n loop?: z.infer<typeof LoopDefinitionSchema>;\n steps?: ParsedStepShape[];\n /** 条件分岐 */\n branches?: BranchDefinitionShape;\n /** メモリ操作(蓄積・集計) */\n memoryOperations?: z.infer<typeof MemoryOperationSchema>[];\n}\n\nconst BranchCaseSchema: z.ZodType<BranchCaseShape> = z.lazy(() =>\n z.object({\n match: z.string(),\n steps: z.array(ParsedStepSchema).min(1),\n }),\n);\n\nconst BranchDefinitionSchema: z.ZodType<BranchDefinitionShape> = z.lazy(() =>\n z.object({\n value: z.string().min(1),\n cases: z.array(BranchCaseSchema).min(1),\n default: z.object({ steps: z.array(ParsedStepSchema).min(1) }).optional(),\n }),\n);\n\nexport const ParsedStepSchema: z.ZodType<ParsedStepShape> = z.lazy(() =>\n z\n .object({\n ordinal: z.number().int().nonnegative(),\n description: z.string(),\n action: StepActionSchema,\n url: z.string(),\n riskLevel: RiskLevelSchema,\n requiresConfirmation: z.boolean(),\n captures: z.array(StepCaptureSchema).optional(),\n condition: z.string().optional(),\n loop: LoopDefinitionSchema.optional(),\n steps: z.array(ParsedStepSchema).optional(),\n branches: BranchDefinitionSchema.optional(),\n memoryOperations: z.array(MemoryOperationSchema).optional(),\n })\n .refine(\n (s) => !(s.loop && s.branches),\n { message: \"step cannot have both 'loop' and 'branches'\" },\n ),\n);\n\n// ── ParsedRunbook(ドキュメント全体) ──\nexport const ParsedRunbookSchema = z.object({\n title: z.string(),\n naturalLanguageSummary: z.string().optional(),\n settings: z.object({\n baseUrl: z.string(),\n defaultTimeout: z.number().default(10000),\n pauseBetweenSteps: z.number().default(500),\n stopOnError: z.boolean().default(true),\n }),\n metadata: z.object({\n startUrl: z.string().min(1),\n goal: z.string(),\n goalAchieved: z.boolean(),\n totalSteps: z.number().int().nonnegative(),\n generatedAt: z.string(),\n skills: z.array(z.string()).optional(),\n }),\n steps: z.array(ParsedStepSchema).min(1),\n notes: z.string().optional(),\n context: z.string().default(\"\"),\n variables: z.record(z.string(), VariableDefinitionSchema).optional(),\n dataSource: DataSourceConfigSchema.optional(),\n});\n","/**\n * ElementSelectorSchema — 要素特定用セレクタ(優先度順フォールバック)\n *\n * @refrainai/contracts/runbook からインライン化。\n */\n\nimport { z } from \"zod\";\n\nexport const ElementSelectorSchema = z.object({\n /** id属性(最も信頼性が高い) */\n id: z.string().optional(),\n /** aria-label(アクセシビリティラベル) */\n ariaLabel: z.string().optional(),\n /** data-testid(テスト用ID) */\n dataTestId: z.string().optional(),\n /** その他のdata-*属性 */\n dataAttributes: z.record(z.string(), z.string()).optional(),\n /** CSSセレクタ */\n cssSelector: z.string().optional(),\n /** XPathセレクタ */\n xPath: z.string().optional(),\n /** label[for]のテキスト */\n labelText: z.string().optional(),\n /** 要素のinnerText */\n innerText: z.string().max(200).optional(),\n /** placeholder属性 */\n placeholder: z.string().optional(),\n /** name属性 */\n name: z.string().optional(),\n /** 位置ベースのフォールバック(最終手段) */\n rect: z\n .object({\n x: z.number(),\n y: z.number(),\n width: z.number(),\n height: z.number(),\n })\n .optional(),\n /** タグ名(必須) */\n tagName: z.string(),\n /** role属性 */\n role: z.string().optional(),\n /** input要素のtype属性 */\n inputType: z.string().optional(),\n});\n\nexport type ElementSelector = z.infer<typeof ElementSelectorSchema>;\n"],"mappings":"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","names":["z","z"]}
|