@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
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
} from "./chunk-D5SI2PHK.js";
|
|
5
5
|
import {
|
|
6
6
|
log
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NRKZJVPE.js";
|
|
8
8
|
import {
|
|
9
9
|
getModel,
|
|
10
10
|
trackedGenerateText
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-KFNW4XR2.js";
|
|
12
12
|
import {
|
|
13
13
|
ParsedRunbookSchema
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-LZDZGI4M.js";
|
|
15
15
|
|
|
16
16
|
// src/fix-runbook/yaml-patcher.ts
|
|
17
17
|
import { parse } from "yaml";
|
|
@@ -25,10 +25,10 @@ var noopLogger = {
|
|
|
25
25
|
info: () => {
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
|
-
async function generatePatchCore(originalYaml, suggestion, logger = noopLogger) {
|
|
28
|
+
async function generatePatchCore(originalYaml, suggestion, logger = noopLogger, additionalPrompt) {
|
|
29
29
|
logger.step(`Step #${suggestion.stepOrdinal} \u306E\u30D1\u30C3\u30C1\u3092\u751F\u6210\u4E2D...`);
|
|
30
30
|
try {
|
|
31
|
-
const { system, userPrompt } = buildPatchMessages(originalYaml, suggestion);
|
|
31
|
+
const { system, userPrompt } = buildPatchMessages(originalYaml, suggestion, additionalPrompt);
|
|
32
32
|
const { text } = await trackedGenerateText("review", {
|
|
33
33
|
model: getModel("review"),
|
|
34
34
|
messages: [
|
|
@@ -99,7 +99,18 @@ var PATCH_SYSTEM_PROMPT = [
|
|
|
99
99
|
"- \u51FA\u529B\u306F YAML \u306E\u307F\uFF08```yaml ... ``` \u3067\u56F2\u3093\u3067\u304F\u3060\u3055\u3044\uFF09",
|
|
100
100
|
"- \u8AAC\u660E\u3084\u30B3\u30E1\u30F3\u30C8\u306F\u4E0D\u8981\u3067\u3059"
|
|
101
101
|
].join("\n");
|
|
102
|
-
function
|
|
102
|
+
async function generatePatchPipeline(originalYaml, suggestions, logger = noopLogger, additionalPrompt) {
|
|
103
|
+
let currentYaml = originalYaml;
|
|
104
|
+
for (const suggestion of suggestions) {
|
|
105
|
+
const result = await generatePatchCore(currentYaml, suggestion, logger, additionalPrompt);
|
|
106
|
+
if (!result.success) {
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
currentYaml = result.patchedYaml;
|
|
110
|
+
}
|
|
111
|
+
return { success: true, patchedYaml: currentYaml };
|
|
112
|
+
}
|
|
113
|
+
function buildPatchMessages(originalYaml, suggestion, additionalPrompt) {
|
|
103
114
|
const parts = [
|
|
104
115
|
"## \u4FEE\u6B63\u5BFE\u8C61",
|
|
105
116
|
`- \u30B9\u30C6\u30C3\u30D7\u756A\u53F7: ${suggestion.stepOrdinal}`,
|
|
@@ -125,6 +136,11 @@ function buildPatchMessages(originalYaml, suggestion) {
|
|
|
125
136
|
parts.push(suggestion.lastSnapshotPreview);
|
|
126
137
|
parts.push("```");
|
|
127
138
|
}
|
|
139
|
+
if (additionalPrompt) {
|
|
140
|
+
parts.push("");
|
|
141
|
+
parts.push("## \u8FFD\u52A0\u306E\u6307\u793A");
|
|
142
|
+
parts.push(additionalPrompt);
|
|
143
|
+
}
|
|
128
144
|
parts.push("");
|
|
129
145
|
parts.push("## \u73FE\u5728\u306E YAML");
|
|
130
146
|
parts.push("```yaml");
|
|
@@ -159,6 +175,7 @@ function validateYaml(yamlContent) {
|
|
|
159
175
|
|
|
160
176
|
export {
|
|
161
177
|
generatePatchCore,
|
|
162
|
-
generatePatch
|
|
178
|
+
generatePatch,
|
|
179
|
+
generatePatchPipeline
|
|
163
180
|
};
|
|
164
|
-
//# sourceMappingURL=chunk-
|
|
181
|
+
//# sourceMappingURL=chunk-MYITSQYV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/fix-runbook/yaml-patcher.ts"],"sourcesContent":["/**\n * yaml-patcher — AI を使って runbook YAML を修正する\n *\n * 修正提案と現在の YAML を AI に渡し、パッチ済み YAML を生成する。\n * yaml パッケージの Document API でパースしバリデーションを行う。\n */\n\nimport { parse, stringify } from \"yaml\";\nimport { getModel, trackedGenerateText } from \"../harness/ai-model\";\nimport { ParsedRunbookSchema } from \"../schemas/runbook-schema\";\nimport { extractVariableNames } from \"../context/template-resolver\";\nimport { log } from \"../cli/prompts\";\nimport type { ExtractedSuggestion } from \"./report-parser\";\n\nexport interface PatchResult {\n success: boolean;\n patchedYaml: string;\n error?: string;\n}\n\n/** ロガーインターフェース(CLI / サーバーで差し替え可能) */\nexport interface PatchLogger {\n step(msg: string): void;\n info(msg: string): void;\n}\n\nconst cliLogger: PatchLogger = {\n step: (msg) => log.step(msg),\n info: (msg) => log.info(msg),\n};\n\nconst noopLogger: PatchLogger = {\n step: () => {},\n info: () => {},\n};\n\n/**\n * AI を使って YAML を修正する(コア関数)。\n * ロガーを引数で受け取り、CLI / サーバーの両方で使用可能。\n */\nexport async function generatePatchCore(\n originalYaml: string,\n suggestion: ExtractedSuggestion,\n logger: PatchLogger = noopLogger,\n additionalPrompt?: string,\n): Promise<PatchResult> {\n logger.step(`Step #${suggestion.stepOrdinal} のパッチを生成中...`);\n\n try {\n const { system, userPrompt } = buildPatchMessages(originalYaml, suggestion, additionalPrompt);\n\n const { text } = await trackedGenerateText(\"review\", {\n model: getModel(\"review\"),\n messages: [\n {\n role: \"system\",\n content: system,\n providerOptions: {\n anthropic: { cacheControl: { type: \"ephemeral\" } },\n },\n },\n { role: \"user\", content: userPrompt },\n ],\n temperature: 0,\n });\n\n // AI のレスポンスから YAML 部分を抽出\n const patchedYaml = extractYamlFromResponse(text);\n if (!patchedYaml) {\n logger.info(\"パッチ生成失敗\");\n return {\n success: false,\n patchedYaml: originalYaml,\n error: \"AI レスポンスから YAML を抽出できませんでした\",\n };\n }\n\n // バリデーション\n const validationError = validateYaml(patchedYaml);\n if (validationError) {\n logger.info(\"バリデーション失敗\");\n return {\n success: false,\n patchedYaml: originalYaml,\n error: `バリデーションエラー: ${validationError}`,\n };\n }\n\n // テンプレート変数の保全チェック\n const originalRefs = extractVariableNames(originalYaml);\n const patchedRefs = extractVariableNames(patchedYaml);\n const lostRefs = originalRefs.filter((r) => !patchedRefs.includes(r));\n if (lostRefs.length > 0) {\n logger.info(`テンプレート変数が失われました: ${lostRefs.join(\", \")}`);\n return {\n success: false,\n patchedYaml: originalYaml,\n error: `テンプレート変数が失われました: ${lostRefs.join(\", \")}`,\n };\n }\n\n logger.info(\"パッチ生成完了\");\n return { success: true, patchedYaml };\n } catch (error) {\n logger.info(\"パッチ生成失敗\");\n return {\n success: false,\n patchedYaml: originalYaml,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * AI を使って YAML を修正する(CLI 互換ラッパー)。\n * 修正後の YAML が ParsedRunbookSchema でバリデーションを通ることを確認。\n */\nexport async function generatePatch(\n originalYaml: string,\n suggestion: ExtractedSuggestion,\n): Promise<PatchResult> {\n return generatePatchCore(originalYaml, suggestion, cliLogger);\n}\n\n/** 静的な YAML パッチ用システムプロンプト(キャッシュ対象) */\nconst PATCH_SYSTEM_PROMPT = [\n \"あなたは runbook YAML のパッチ生成ツールです。\",\n \"以下の修正提案に基づいて、YAML を修正してください。\",\n \"\",\n \"## ルール\",\n \"- 修正対象ステップ以外は一切変更しないでください\",\n \"- YAML のフォーマット(インデント、引用符スタイル、コメント位置)をできる限り維持してください\",\n \"- 修正は最小限にしてください\",\n \"- {{varName}} 形式のテンプレート変数は絶対に変更・削除・エスケープしないでください。これらは実行時に動的に展開される変数参照です\",\n \"- テンプレート変数をリテラル値(例: test@example.com)に置き換えないでください\",\n \"- 出力は YAML のみ(```yaml ... ``` で囲んでください)\",\n \"- 説明やコメントは不要です\",\n].join(\"\\n\");\n\n/**\n * 複数の suggestion を順番に適用する。\n * 各パッチの出力 YAML を次のパッチの入力として使用する。\n */\nexport async function generatePatchPipeline(\n originalYaml: string,\n suggestions: ExtractedSuggestion[],\n logger: PatchLogger = noopLogger,\n additionalPrompt?: string,\n): Promise<PatchResult> {\n let currentYaml = originalYaml;\n\n for (const suggestion of suggestions) {\n const result = await generatePatchCore(currentYaml, suggestion, logger, additionalPrompt);\n if (!result.success) {\n return result;\n }\n currentYaml = result.patchedYaml;\n }\n\n return { success: true, patchedYaml: currentYaml };\n}\n\nfunction buildPatchMessages(originalYaml: string, suggestion: ExtractedSuggestion, additionalPrompt?: string): { system: string; userPrompt: string } {\n const parts: string[] = [\n \"## 修正対象\",\n `- ステップ番号: ${suggestion.stepOrdinal}`,\n `- 説明: ${suggestion.description}`,\n `- エラー: ${suggestion.error}`,\n ];\n\n if (suggestion.category) {\n parts.push(`- エラー分類: ${suggestion.category}`);\n }\n if (suggestion.recoveryHint) {\n parts.push(`- 推奨対応: ${suggestion.recoveryHint}`);\n }\n if (suggestion.yamlFix) {\n parts.push(`- 修正提案: ${suggestion.yamlFix}`);\n }\n if (suggestion.currentSelector) {\n parts.push(`- 現在のセレクタ: ${suggestion.currentSelector}`);\n }\n if (suggestion.lastSnapshotPreview) {\n parts.push(\"\");\n parts.push(\"## 最終スナップショット(ページの現在の状態)\");\n parts.push(\"```\");\n parts.push(suggestion.lastSnapshotPreview);\n parts.push(\"```\");\n }\n\n if (additionalPrompt) {\n parts.push(\"\");\n parts.push(\"## 追加の指示\");\n parts.push(additionalPrompt);\n }\n\n parts.push(\"\");\n parts.push(\"## 現在の YAML\");\n parts.push(\"```yaml\");\n parts.push(originalYaml);\n parts.push(\"```\");\n\n return { system: PATCH_SYSTEM_PROMPT, userPrompt: parts.join(\"\\n\") };\n}\n\n/**\n * AI レスポンスから YAML コードブロックを抽出する。\n */\nfunction extractYamlFromResponse(response: string): string | null {\n // ```yaml ... ``` パターン\n const yamlMatch = response.match(/```ya?ml\\n([\\s\\S]*?)```/);\n if (yamlMatch) return yamlMatch[1].trim();\n\n // ``` ... ``` パターン(言語指定なし)\n const codeMatch = response.match(/```\\n([\\s\\S]*?)```/);\n if (codeMatch) return codeMatch[1].trim();\n\n // コードブロックなし — レスポンス全体が YAML の可能性\n try {\n parse(response);\n return response.trim();\n } catch {\n return null;\n }\n}\n\n/**\n * パッチ済み YAML が有効な runbook かバリデーションする。\n */\nfunction validateYaml(yamlContent: string): string | null {\n try {\n const doc = parse(yamlContent);\n ParsedRunbookSchema.parse(doc);\n return null;\n } catch (error) {\n if (error instanceof Error) {\n return error.message.slice(0, 200);\n }\n return String(error);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAOA,SAAS,aAAwB;AAmBjC,IAAM,YAAyB;AAAA,EAC7B,MAAM,CAAC,QAAQ,IAAI,KAAK,GAAG;AAAA,EAC3B,MAAM,CAAC,QAAQ,IAAI,KAAK,GAAG;AAC7B;AAEA,IAAM,aAA0B;AAAA,EAC9B,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,MAAM,MAAM;AAAA,EAAC;AACf;AAMA,eAAsB,kBACpB,cACA,YACA,SAAsB,YACtB,kBACsB;AACtB,SAAO,KAAK,SAAS,WAAW,WAAW,sDAAc;AAEzD,MAAI;AACF,UAAM,EAAE,QAAQ,WAAW,IAAI,mBAAmB,cAAc,YAAY,gBAAgB;AAE5F,UAAM,EAAE,KAAK,IAAI,MAAM,oBAAoB,UAAU;AAAA,MACnD,OAAO,SAAS,QAAQ;AAAA,MACxB,UAAU;AAAA,QACR;AAAA,UACE,MAAM;AAAA,UACN,SAAS;AAAA,UACT,iBAAiB;AAAA,YACf,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,EAAE;AAAA,UACnD;AAAA,QACF;AAAA,QACA,EAAE,MAAM,QAAQ,SAAS,WAAW;AAAA,MACtC;AAAA,MACA,aAAa;AAAA,IACf,CAAC;AAGD,UAAM,cAAc,wBAAwB,IAAI;AAChD,QAAI,CAAC,aAAa;AAChB,aAAO,KAAK,4CAAS;AACrB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa;AAAA,QACb,OAAO;AAAA,MACT;AAAA,IACF;AAGA,UAAM,kBAAkB,aAAa,WAAW;AAChD,QAAI,iBAAiB;AACnB,aAAO,KAAK,wDAAW;AACvB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa;AAAA,QACb,OAAO,iEAAe,eAAe;AAAA,MACvC;AAAA,IACF;AAGA,UAAM,eAAe,qBAAqB,YAAY;AACtD,UAAM,cAAc,qBAAqB,WAAW;AACpD,UAAM,WAAW,aAAa,OAAO,CAAC,MAAM,CAAC,YAAY,SAAS,CAAC,CAAC;AACpE,QAAI,SAAS,SAAS,GAAG;AACvB,aAAO,KAAK,+FAAoB,SAAS,KAAK,IAAI,CAAC,EAAE;AACrD,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa;AAAA,QACb,OAAO,+FAAoB,SAAS,KAAK,IAAI,CAAC;AAAA,MAChD;AAAA,IACF;AAEA,WAAO,KAAK,4CAAS;AACrB,WAAO,EAAE,SAAS,MAAM,YAAY;AAAA,EACtC,SAAS,OAAO;AACd,WAAO,KAAK,4CAAS;AACrB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa;AAAA,MACb,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D;AAAA,EACF;AACF;AAMA,eAAsB,cACpB,cACA,YACsB;AACtB,SAAO,kBAAkB,cAAc,YAAY,SAAS;AAC9D;AAGA,IAAM,sBAAsB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AAMX,eAAsB,sBACpB,cACA,aACA,SAAsB,YACtB,kBACsB;AACtB,MAAI,cAAc;AAElB,aAAW,cAAc,aAAa;AACpC,UAAM,SAAS,MAAM,kBAAkB,aAAa,YAAY,QAAQ,gBAAgB;AACxF,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO;AAAA,IACT;AACA,kBAAc,OAAO;AAAA,EACvB;AAEA,SAAO,EAAE,SAAS,MAAM,aAAa,YAAY;AACnD;AAEA,SAAS,mBAAmB,cAAsB,YAAiC,kBAAmE;AACpJ,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA,2CAAa,WAAW,WAAW;AAAA,IACnC,mBAAS,WAAW,WAAW;AAAA,IAC/B,yBAAU,WAAW,KAAK;AAAA,EAC5B;AAEA,MAAI,WAAW,UAAU;AACvB,UAAM,KAAK,qCAAY,WAAW,QAAQ,EAAE;AAAA,EAC9C;AACA,MAAI,WAAW,cAAc;AAC3B,UAAM,KAAK,+BAAW,WAAW,YAAY,EAAE;AAAA,EACjD;AACA,MAAI,WAAW,SAAS;AACtB,UAAM,KAAK,+BAAW,WAAW,OAAO,EAAE;AAAA,EAC5C;AACA,MAAI,WAAW,iBAAiB;AAC9B,UAAM,KAAK,iDAAc,WAAW,eAAe,EAAE;AAAA,EACvD;AACA,MAAI,WAAW,qBAAqB;AAClC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,mIAA0B;AACrC,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,WAAW,mBAAmB;AACzC,UAAM,KAAK,KAAK;AAAA,EAClB;AAEA,MAAI,kBAAkB;AACpB,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,mCAAU;AACrB,UAAM,KAAK,gBAAgB;AAAA,EAC7B;AAEA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,4BAAa;AACxB,QAAM,KAAK,SAAS;AACpB,QAAM,KAAK,YAAY;AACvB,QAAM,KAAK,KAAK;AAEhB,SAAO,EAAE,QAAQ,qBAAqB,YAAY,MAAM,KAAK,IAAI,EAAE;AACrE;AAKA,SAAS,wBAAwB,UAAiC;AAEhE,QAAM,YAAY,SAAS,MAAM,yBAAyB;AAC1D,MAAI,UAAW,QAAO,UAAU,CAAC,EAAE,KAAK;AAGxC,QAAM,YAAY,SAAS,MAAM,oBAAoB;AACrD,MAAI,UAAW,QAAO,UAAU,CAAC,EAAE,KAAK;AAGxC,MAAI;AACF,UAAM,QAAQ;AACd,WAAO,SAAS,KAAK;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,SAAS,aAAa,aAAoC;AACxD,MAAI;AACF,UAAM,MAAM,MAAM,WAAW;AAC7B,wBAAoB,MAAM,GAAG;AAC7B,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAC1B,aAAO,MAAM,QAAQ,MAAM,GAAG,GAAG;AAAA,IACnC;AACA,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;","names":[]}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
t
|
|
4
|
+
} from "./chunk-6FGCPMBU.js";
|
|
5
|
+
|
|
6
|
+
// src/cli/prompts.ts
|
|
7
|
+
import * as p from "@clack/prompts";
|
|
8
|
+
function exitIfCancelled(value) {
|
|
9
|
+
if (p.isCancel(value)) {
|
|
10
|
+
p.cancel(t("cli.cancelledMessage"));
|
|
11
|
+
process.exit(0);
|
|
12
|
+
}
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
function formatRiskHint(level) {
|
|
16
|
+
const keyMap = {
|
|
17
|
+
low: "risk.low",
|
|
18
|
+
medium: "risk.medium",
|
|
19
|
+
high: "risk.high"
|
|
20
|
+
};
|
|
21
|
+
return t(keyMap[level]);
|
|
22
|
+
}
|
|
23
|
+
async function promptSelect(message, options) {
|
|
24
|
+
const result = await p.select({
|
|
25
|
+
message,
|
|
26
|
+
options
|
|
27
|
+
});
|
|
28
|
+
return exitIfCancelled(result);
|
|
29
|
+
}
|
|
30
|
+
async function promptMultiselect(message, options, opts) {
|
|
31
|
+
const result = await p.multiselect({
|
|
32
|
+
message,
|
|
33
|
+
options,
|
|
34
|
+
initialValues: opts?.initialValues,
|
|
35
|
+
required: opts?.required ?? false
|
|
36
|
+
});
|
|
37
|
+
return exitIfCancelled(result);
|
|
38
|
+
}
|
|
39
|
+
async function promptText(message, opts) {
|
|
40
|
+
const result = await p.text({
|
|
41
|
+
message,
|
|
42
|
+
initialValue: opts?.initialValue,
|
|
43
|
+
placeholder: opts?.placeholder,
|
|
44
|
+
validate: opts?.validate
|
|
45
|
+
});
|
|
46
|
+
return exitIfCancelled(result);
|
|
47
|
+
}
|
|
48
|
+
async function promptConfirm(message, initialValue) {
|
|
49
|
+
const result = await p.confirm({
|
|
50
|
+
message,
|
|
51
|
+
initialValue
|
|
52
|
+
});
|
|
53
|
+
return exitIfCancelled(result);
|
|
54
|
+
}
|
|
55
|
+
var intro2 = p.intro;
|
|
56
|
+
var outro2 = p.outro;
|
|
57
|
+
var note2 = p.note;
|
|
58
|
+
var cancel2 = p.cancel;
|
|
59
|
+
var log2 = p.log;
|
|
60
|
+
var isDebug = process.env.DEBUG === "1" || process.env.DEBUG === "true";
|
|
61
|
+
|
|
62
|
+
export {
|
|
63
|
+
formatRiskHint,
|
|
64
|
+
promptSelect,
|
|
65
|
+
promptMultiselect,
|
|
66
|
+
promptText,
|
|
67
|
+
promptConfirm,
|
|
68
|
+
intro2 as intro,
|
|
69
|
+
outro2 as outro,
|
|
70
|
+
note2 as note,
|
|
71
|
+
cancel2 as cancel,
|
|
72
|
+
log2 as log
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=chunk-NRKZJVPE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/prompts.ts"],"sourcesContent":["/**\n * cli/prompts — @clack/prompts のラッパー\n *\n * 全プロンプトで共通のキャンセル処理・リスクレベル表示・型安全な選択を提供。\n */\n\nimport * as p from \"@clack/prompts\";\nimport type { Option } from \"@clack/prompts\";\nimport type { RiskLevel } from \"../runbook-generator/types\";\nimport { t } from \"../i18n\";\n\n/**\n * キャンセル検出 + 統一終了\n */\nexport function exitIfCancelled<T>(value: T | symbol): T {\n if (p.isCancel(value)) {\n p.cancel(t(\"cli.cancelledMessage\"));\n process.exit(0);\n }\n return value;\n}\n\n/**\n * リスクレベルの説明テキスト\n */\nexport function formatRiskHint(level: RiskLevel): string {\n const keyMap: Record<RiskLevel, \"risk.low\" | \"risk.medium\" | \"risk.high\"> = {\n low: \"risk.low\",\n medium: \"risk.medium\",\n high: \"risk.high\",\n };\n return t(keyMap[level]);\n}\n\n/**\n * select ラッパー(exitIfCancelled 内蔵)\n */\nexport async function promptSelect<Value extends string>(\n message: string,\n options: Option<Value>[],\n): Promise<Value> {\n const result = await p.select<Value>({\n message,\n options,\n });\n return exitIfCancelled(result);\n}\n\n/**\n * multiselect ラッパー(exitIfCancelled 内蔵)\n */\nexport async function promptMultiselect<Value>(\n message: string,\n options: Option<Value>[],\n opts?: { initialValues?: Value[]; required?: boolean },\n): Promise<Value[]> {\n const result = await p.multiselect<Value>({\n message,\n options,\n initialValues: opts?.initialValues,\n required: opts?.required ?? false,\n });\n return exitIfCancelled(result);\n}\n\n/**\n * text ラッパー(exitIfCancelled 内蔵)\n */\nexport async function promptText(\n message: string,\n opts?: {\n initialValue?: string;\n placeholder?: string;\n validate?: (value: string | undefined) => string | undefined;\n },\n): Promise<string> {\n const result = await p.text({\n message,\n initialValue: opts?.initialValue,\n placeholder: opts?.placeholder,\n validate: opts?.validate,\n });\n return exitIfCancelled(result);\n}\n\n/**\n * confirm ラッパー(exitIfCancelled 内蔵)\n */\nexport async function promptConfirm(\n message: string,\n initialValue?: boolean,\n): Promise<boolean> {\n const result = await p.confirm({\n message,\n initialValue,\n });\n return exitIfCancelled(result);\n}\n\n// 表示ヘルパー re-export\nexport const intro = p.intro;\nexport const outro = p.outro;\nexport const note = p.note;\nexport const spinner = p.spinner;\nexport const cancel = p.cancel;\nexport const log = p.log;\n\n/**\n * DEBUG=1 のときのみ出力するデバッグログ\n */\nconst isDebug = process.env.DEBUG === \"1\" || process.env.DEBUG === \"true\";\nexport function debug(message: string): void {\n if (isDebug) p.log.info(`[debug] ${message}`);\n}\n"],"mappings":";;;;;;AAMA,YAAY,OAAO;AAQZ,SAAS,gBAAmB,OAAsB;AACvD,MAAM,WAAS,KAAK,GAAG;AACrB,IAAE,SAAO,EAAE,sBAAsB,CAAC;AAClC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAKO,SAAS,eAAe,OAA0B;AACvD,QAAM,SAAsE;AAAA,IAC1E,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,MAAM;AAAA,EACR;AACA,SAAO,EAAE,OAAO,KAAK,CAAC;AACxB;AAKA,eAAsB,aACpB,SACA,SACgB;AAChB,QAAM,SAAS,MAAQ,SAAc;AAAA,IACnC;AAAA,IACA;AAAA,EACF,CAAC;AACD,SAAO,gBAAgB,MAAM;AAC/B;AAKA,eAAsB,kBACpB,SACA,SACA,MACkB;AAClB,QAAM,SAAS,MAAQ,cAAmB;AAAA,IACxC;AAAA,IACA;AAAA,IACA,eAAe,MAAM;AAAA,IACrB,UAAU,MAAM,YAAY;AAAA,EAC9B,CAAC;AACD,SAAO,gBAAgB,MAAM;AAC/B;AAKA,eAAsB,WACpB,SACA,MAKiB;AACjB,QAAM,SAAS,MAAQ,OAAK;AAAA,IAC1B;AAAA,IACA,cAAc,MAAM;AAAA,IACpB,aAAa,MAAM;AAAA,IACnB,UAAU,MAAM;AAAA,EAClB,CAAC;AACD,SAAO,gBAAgB,MAAM;AAC/B;AAKA,eAAsB,cACpB,SACA,cACkB;AAClB,QAAM,SAAS,MAAQ,UAAQ;AAAA,IAC7B;AAAA,IACA;AAAA,EACF,CAAC;AACD,SAAO,gBAAgB,MAAM;AAC/B;AAGO,IAAMA,SAAU;AAChB,IAAMC,SAAU;AAChB,IAAMC,QAAS;AAEf,IAAMC,UAAW;AACjB,IAAMC,OAAQ;AAKrB,IAAM,UAAU,QAAQ,IAAI,UAAU,OAAO,QAAQ,IAAI,UAAU;","names":["intro","outro","note","cancel","log"]}
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
findElementInSnapshot
|
|
4
|
+
} from "./chunk-YTVEYQGA.js";
|
|
5
|
+
import {
|
|
6
|
+
ParsedRunbookSchema
|
|
7
|
+
} from "./chunk-LZDZGI4M.js";
|
|
8
|
+
|
|
9
|
+
// src/runbook-generator/runbook-builder.ts
|
|
10
|
+
import { stringify } from "yaml";
|
|
11
|
+
|
|
12
|
+
// src/browser/selector-builder.ts
|
|
13
|
+
var ROLE_TAG_MAP = {
|
|
14
|
+
textbox: { tagName: "input", inputType: "text" },
|
|
15
|
+
button: { tagName: "button", role: "button" },
|
|
16
|
+
link: { tagName: "a", role: "link" },
|
|
17
|
+
checkbox: { tagName: "input", inputType: "checkbox" },
|
|
18
|
+
radio: { tagName: "input", inputType: "radio" },
|
|
19
|
+
combobox: { tagName: "select", role: "combobox" },
|
|
20
|
+
searchbox: { tagName: "input", inputType: "search" },
|
|
21
|
+
slider: { tagName: "input", inputType: "range" },
|
|
22
|
+
spinbutton: { tagName: "input", inputType: "number" },
|
|
23
|
+
switch: { tagName: "input", inputType: "checkbox", role: "switch" },
|
|
24
|
+
tab: { tagName: "button", role: "tab" },
|
|
25
|
+
menuitem: { tagName: "button", role: "menuitem" },
|
|
26
|
+
option: { tagName: "option", role: "option" },
|
|
27
|
+
heading: { tagName: "h2", role: "heading" },
|
|
28
|
+
img: { tagName: "img", role: "img" },
|
|
29
|
+
navigation: { tagName: "nav", role: "navigation" },
|
|
30
|
+
listitem: { tagName: "li", role: "listitem" }
|
|
31
|
+
};
|
|
32
|
+
function buildSelector(element) {
|
|
33
|
+
const mapping = ROLE_TAG_MAP[element.role];
|
|
34
|
+
const tagName = mapping?.tagName ?? element.role;
|
|
35
|
+
const selector = { tagName };
|
|
36
|
+
if (mapping?.role) {
|
|
37
|
+
selector.role = mapping.role;
|
|
38
|
+
} else if (element.role !== tagName) {
|
|
39
|
+
selector.role = element.role;
|
|
40
|
+
}
|
|
41
|
+
if (mapping?.inputType) {
|
|
42
|
+
selector.inputType = mapping.inputType;
|
|
43
|
+
}
|
|
44
|
+
if (element.name) {
|
|
45
|
+
selector.ariaLabel = element.name;
|
|
46
|
+
if (element.role === "button" || element.role === "link") {
|
|
47
|
+
selector.innerText = element.name.slice(0, 200);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (element.attributes.placeholder) {
|
|
51
|
+
selector.placeholder = element.attributes.placeholder;
|
|
52
|
+
}
|
|
53
|
+
if (element.attributes.name) {
|
|
54
|
+
selector.name = element.attributes.name;
|
|
55
|
+
}
|
|
56
|
+
return selector;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/runbook-generator/runbook-builder.ts
|
|
60
|
+
function toActionType(action) {
|
|
61
|
+
switch (action) {
|
|
62
|
+
case "fill":
|
|
63
|
+
case "type":
|
|
64
|
+
return "input";
|
|
65
|
+
case "check":
|
|
66
|
+
case "uncheck":
|
|
67
|
+
case "click":
|
|
68
|
+
return "click";
|
|
69
|
+
case "select":
|
|
70
|
+
return "select";
|
|
71
|
+
case "navigate":
|
|
72
|
+
return "navigate";
|
|
73
|
+
case "scroll":
|
|
74
|
+
return "scroll";
|
|
75
|
+
case "wait":
|
|
76
|
+
return "wait";
|
|
77
|
+
case "extract":
|
|
78
|
+
return "extract";
|
|
79
|
+
case "download":
|
|
80
|
+
return "download";
|
|
81
|
+
case "export":
|
|
82
|
+
return "export";
|
|
83
|
+
case "memory_append":
|
|
84
|
+
case "memory_aggregate":
|
|
85
|
+
return "memory";
|
|
86
|
+
case "key":
|
|
87
|
+
return "key";
|
|
88
|
+
default:
|
|
89
|
+
return "click";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function categoryToSource(category, context) {
|
|
93
|
+
switch (category) {
|
|
94
|
+
case "credential":
|
|
95
|
+
case "user_data":
|
|
96
|
+
return "prompt";
|
|
97
|
+
case "fixed":
|
|
98
|
+
return "fixed";
|
|
99
|
+
case "navigation": {
|
|
100
|
+
if (context) {
|
|
101
|
+
const signal = `${context.description ?? ""} ${context.variableName ?? ""}`.toLowerCase();
|
|
102
|
+
if (/search|query|keyword|filter|検索|フィルタ|絞り込み/.test(signal)) {
|
|
103
|
+
return "prompt";
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return "fixed";
|
|
107
|
+
}
|
|
108
|
+
default:
|
|
109
|
+
return "prompt";
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function buildRunbookYaml(input) {
|
|
113
|
+
const { goal, startUrl, recordedSteps, goalAchieved, stepDelay, reviewResult, humanGuidance, interventions } = input;
|
|
114
|
+
const successfulSteps = recordedSteps.filter((s) => s.success);
|
|
115
|
+
const reviewMap = new Map(
|
|
116
|
+
reviewResult?.reviewedSteps.map((r) => [r.originalOrdinal, r])
|
|
117
|
+
);
|
|
118
|
+
const filteredSteps = reviewResult ? successfulSteps.filter((s) => reviewMap.get(s.ordinal)?.keep !== false) : successfulSteps;
|
|
119
|
+
const variables = {};
|
|
120
|
+
const usedVariableNames = /* @__PURE__ */ new Set();
|
|
121
|
+
filteredSteps.forEach((recorded) => {
|
|
122
|
+
const { action } = recorded;
|
|
123
|
+
const actionType = toActionType(action.action);
|
|
124
|
+
if (actionType === "input" && action.value !== void 0) {
|
|
125
|
+
const varName = action.variableName ?? `input_${recorded.ordinal}`;
|
|
126
|
+
if (!usedVariableNames.has(varName)) {
|
|
127
|
+
usedVariableNames.add(varName);
|
|
128
|
+
const source = categoryToSource(action.inputCategory, {
|
|
129
|
+
description: action.description,
|
|
130
|
+
variableName: action.variableName ?? varName
|
|
131
|
+
});
|
|
132
|
+
variables[varName] = {
|
|
133
|
+
source,
|
|
134
|
+
description: action.description,
|
|
135
|
+
...source === "prompt" && {
|
|
136
|
+
required: true,
|
|
137
|
+
sensitive: action.inputCategory === "credential",
|
|
138
|
+
value: action.value
|
|
139
|
+
},
|
|
140
|
+
...source === "fixed" && { value: action.value }
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
const steps = filteredSteps.map((recorded, index) => {
|
|
146
|
+
const actionType = toActionType(recorded.action.action);
|
|
147
|
+
const review = reviewMap.get(recorded.ordinal);
|
|
148
|
+
let selector;
|
|
149
|
+
if (recorded.action.selector) {
|
|
150
|
+
const ref = recorded.action.selector.replace("@", "");
|
|
151
|
+
const element = findElementInSnapshot(recorded.snapshotBefore, ref);
|
|
152
|
+
if (element) {
|
|
153
|
+
selector = buildSelector(element);
|
|
154
|
+
} else if (recorded.resolvedElement) {
|
|
155
|
+
selector = recorded.resolvedElement;
|
|
156
|
+
} else {
|
|
157
|
+
selector = { tagName: "unknown" };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
let value;
|
|
161
|
+
if (actionType === "input" && recorded.action.value !== void 0) {
|
|
162
|
+
const varName = recorded.action.variableName ?? `input_${recorded.ordinal}`;
|
|
163
|
+
value = `{{${varName}}}`;
|
|
164
|
+
}
|
|
165
|
+
const step = {
|
|
166
|
+
ordinal: index,
|
|
167
|
+
description: recorded.action.description,
|
|
168
|
+
action: {
|
|
169
|
+
type: actionType,
|
|
170
|
+
...selector && { selector },
|
|
171
|
+
...actionType === "input" && value !== void 0 && { value },
|
|
172
|
+
...actionType === "select" && recorded.action.value !== void 0 && {
|
|
173
|
+
optionText: recorded.action.value
|
|
174
|
+
},
|
|
175
|
+
...actionType === "navigate" && recorded.action.value && {
|
|
176
|
+
url: recorded.action.value
|
|
177
|
+
},
|
|
178
|
+
...actionType === "extract" && recorded.action.script && {
|
|
179
|
+
script: recorded.action.script
|
|
180
|
+
},
|
|
181
|
+
...actionType === "extract" && !recorded.action.script && recorded.action.extractPrompt && {
|
|
182
|
+
extractPrompt: recorded.action.extractPrompt
|
|
183
|
+
},
|
|
184
|
+
...actionType === "download" && recorded.action.downloadPath && {
|
|
185
|
+
downloadPath: recorded.action.downloadPath
|
|
186
|
+
},
|
|
187
|
+
...actionType === "export" && recorded.action.exportCollection && {
|
|
188
|
+
exportCollection: recorded.action.exportCollection
|
|
189
|
+
},
|
|
190
|
+
...actionType === "export" && recorded.action.exportFormat && {
|
|
191
|
+
exportFormat: recorded.action.exportFormat
|
|
192
|
+
},
|
|
193
|
+
...actionType === "export" && recorded.action.exportPath && {
|
|
194
|
+
exportPath: recorded.action.exportPath
|
|
195
|
+
},
|
|
196
|
+
...actionType === "key" && {
|
|
197
|
+
keys: recorded.action.keys ?? recorded.action.value
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
url: recorded.url,
|
|
201
|
+
riskLevel: review?.riskLevel ?? "low",
|
|
202
|
+
requiresConfirmation: review?.requiresConfirmation ?? false
|
|
203
|
+
};
|
|
204
|
+
const captures = buildCaptures(recorded.action.suggestedCaptures);
|
|
205
|
+
if (captures.length > 0) {
|
|
206
|
+
step.captures = captures;
|
|
207
|
+
}
|
|
208
|
+
if (recorded.action.action === "memory_append" && recorded.action.memoryCollection) {
|
|
209
|
+
step.memoryOperations = [{
|
|
210
|
+
type: "append",
|
|
211
|
+
collection: recorded.action.memoryCollection,
|
|
212
|
+
source: recorded.action.variableName ?? "extractedData"
|
|
213
|
+
}];
|
|
214
|
+
} else if (recorded.action.action === "memory_aggregate" && recorded.action.aggregation) {
|
|
215
|
+
const agg = recorded.action.aggregation;
|
|
216
|
+
step.memoryOperations = [{
|
|
217
|
+
type: "aggregate",
|
|
218
|
+
collection: agg.collection,
|
|
219
|
+
field: agg.field,
|
|
220
|
+
operation: agg.operation,
|
|
221
|
+
outputVariable: agg.outputVariable
|
|
222
|
+
}];
|
|
223
|
+
}
|
|
224
|
+
return step;
|
|
225
|
+
});
|
|
226
|
+
const baseUrl = new URL(startUrl).origin;
|
|
227
|
+
const runbook = {
|
|
228
|
+
title: input.title ?? goal,
|
|
229
|
+
settings: {
|
|
230
|
+
baseUrl,
|
|
231
|
+
defaultTimeout: 1e4,
|
|
232
|
+
pauseBetweenSteps: stepDelay,
|
|
233
|
+
stopOnError: true
|
|
234
|
+
},
|
|
235
|
+
metadata: {
|
|
236
|
+
startUrl,
|
|
237
|
+
goal,
|
|
238
|
+
goalAchieved,
|
|
239
|
+
totalSteps: filteredSteps.length,
|
|
240
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
241
|
+
...input.skills && input.skills.length > 0 && { skills: input.skills }
|
|
242
|
+
},
|
|
243
|
+
context: input.contextMarkdown
|
|
244
|
+
};
|
|
245
|
+
if (Object.keys(variables).length > 0) {
|
|
246
|
+
runbook.variables = variables;
|
|
247
|
+
}
|
|
248
|
+
parameterizeSteps(steps, variables);
|
|
249
|
+
runbook.steps = steps;
|
|
250
|
+
const allNotes = [];
|
|
251
|
+
if (humanGuidance && humanGuidance.length > 0) {
|
|
252
|
+
allNotes.push(
|
|
253
|
+
...humanGuidance.map((g, i) => `[\u65B9\u91DD\u4FEE\u6B63 ${i + 1}] ${g}`)
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
if (interventions && interventions.length > 0) {
|
|
257
|
+
allNotes.push(
|
|
258
|
+
...interventions.map(
|
|
259
|
+
(iv) => `[\u63A2\u7D22\u4E2D\u4ECB\u5165 \u30B9\u30C6\u30C3\u30D7#${iv.stepIndex}] ${iv.userInstruction}`
|
|
260
|
+
)
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
if (allNotes.length > 0) {
|
|
264
|
+
runbook.notes = allNotes.join("\n");
|
|
265
|
+
}
|
|
266
|
+
ParsedRunbookSchema.parse(runbook);
|
|
267
|
+
return stringify(runbook, { lineWidth: 120 });
|
|
268
|
+
}
|
|
269
|
+
function parameterizeSteps(steps, variables) {
|
|
270
|
+
const varReplacements = [];
|
|
271
|
+
for (const [name, def] of Object.entries(variables)) {
|
|
272
|
+
if (def.value) {
|
|
273
|
+
varReplacements.push({ value: def.value, varName: name, lowerValue: def.value.toLowerCase() });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (varReplacements.length === 0) return;
|
|
277
|
+
for (const step of steps) {
|
|
278
|
+
const action = step.action;
|
|
279
|
+
if (action.selector && typeof action.selector === "object") {
|
|
280
|
+
const selector = action.selector;
|
|
281
|
+
for (const { lowerValue } of varReplacements) {
|
|
282
|
+
if (typeof selector.ariaLabel === "string" && selector.ariaLabel.toLowerCase().includes(lowerValue)) {
|
|
283
|
+
delete selector.ariaLabel;
|
|
284
|
+
}
|
|
285
|
+
if (typeof selector.innerText === "string" && selector.innerText.toLowerCase().includes(lowerValue)) {
|
|
286
|
+
delete selector.innerText;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (typeof step.description === "string") {
|
|
291
|
+
for (const { value, varName } of varReplacements) {
|
|
292
|
+
const regex = new RegExp(escapeRegExp(value), "gi");
|
|
293
|
+
step.description = step.description.replace(regex, `{{${varName}}}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (typeof step.description === "string") {
|
|
297
|
+
step.description = step.description.replace(/「[^」]*\{\{(\w+)\}\}[^」]*」/g, "\u300C{{$1}}\u300D").replace(/"[^"]*\{\{(\w+)\}\}[^"]*"/g, '"{{$1}}"');
|
|
298
|
+
}
|
|
299
|
+
if (step.memoryOperations && Array.isArray(step.memoryOperations)) {
|
|
300
|
+
for (const op of step.memoryOperations) {
|
|
301
|
+
if (typeof op.collection === "string") {
|
|
302
|
+
const col = op.collection;
|
|
303
|
+
for (const { lowerValue } of varReplacements) {
|
|
304
|
+
if (col.toLowerCase().includes(lowerValue)) {
|
|
305
|
+
op.collection = "data";
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (typeof action.exportCollection === "string") {
|
|
313
|
+
for (const { lowerValue } of varReplacements) {
|
|
314
|
+
if (action.exportCollection.toLowerCase().includes(lowerValue)) {
|
|
315
|
+
action.exportCollection = "data";
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (typeof action.exportPath === "string") {
|
|
320
|
+
for (const { lowerValue } of varReplacements) {
|
|
321
|
+
if (action.exportPath.toLowerCase().includes(lowerValue)) {
|
|
322
|
+
action.exportPath = `/tmp/data.${action.exportFormat ?? "csv"}`;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
function escapeRegExp(s) {
|
|
329
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
330
|
+
}
|
|
331
|
+
function buildCaptures(suggested) {
|
|
332
|
+
if (!suggested || suggested.length === 0) return [];
|
|
333
|
+
return suggested.map((c) => ({
|
|
334
|
+
name: c.name,
|
|
335
|
+
strategy: c.strategy,
|
|
336
|
+
required: false,
|
|
337
|
+
...c.description && { description: c.description },
|
|
338
|
+
...c.pattern && { pattern: c.pattern },
|
|
339
|
+
...c.group !== void 0 && c.group !== 1 && { group: c.group },
|
|
340
|
+
...c.prompt && { prompt: c.prompt },
|
|
341
|
+
...c.expression && { expression: c.expression }
|
|
342
|
+
}));
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export {
|
|
346
|
+
buildSelector,
|
|
347
|
+
buildRunbookYaml
|
|
348
|
+
};
|
|
349
|
+
//# sourceMappingURL=chunk-RBZK7T76.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/runbook-generator/runbook-builder.ts","../../../src/browser/selector-builder.ts"],"sourcesContent":["/**\n * runbook-builder — RecordedStep[] → YAML手順書変換\n *\n * ブラウザ/AI非依存の純粋関数。\n */\n\nimport { stringify } from \"yaml\";\nimport type { RecordedStep, ReviewResult, SuggestedCapture, InterventionRecord } from \"./types\";\nimport { findElementInSnapshot } from \"../browser/snapshot-parser\";\nimport { buildSelector } from \"../browser/selector-builder\";\nimport type { Selector, VariableSource, StepCapture } from \"../runbook-executor/types\";\nimport { ParsedRunbookSchema } from \"../schemas/runbook-schema\";\n\ninterface RunbookInput {\n title?: string;\n goal: string;\n startUrl: string;\n recordedSteps: RecordedStep[];\n goalAchieved: boolean;\n stepDelay: number;\n contextMarkdown: string;\n reviewResult?: ReviewResult;\n humanGuidance?: string[];\n interventions?: InterventionRecord[];\n /** Skill 名リスト(YAML metadata に記録) */\n skills?: string[];\n}\n\n/** ExplorationAction.action → YAML action.type マッピング */\nfunction toActionType(\n action: string,\n): \"click\" | \"input\" | \"select\" | \"navigate\" | \"scroll\" | \"wait\" | \"hover\" | \"extract\" | \"download\" | \"export\" | \"memory\" | \"key\" {\n switch (action) {\n case \"fill\":\n case \"type\":\n return \"input\";\n case \"check\":\n case \"uncheck\":\n case \"click\":\n return \"click\";\n case \"select\":\n return \"select\";\n case \"navigate\":\n return \"navigate\";\n case \"scroll\":\n return \"scroll\";\n case \"wait\":\n return \"wait\";\n case \"extract\":\n return \"extract\";\n case \"download\":\n return \"download\";\n case \"export\":\n return \"export\";\n case \"memory_append\":\n case \"memory_aggregate\":\n return \"memory\";\n case \"key\":\n return \"key\";\n default:\n return \"click\";\n }\n}\n\n/** inputCategory → VariableSource マッピング */\nfunction categoryToSource(\n category: \"credential\" | \"user_data\" | \"fixed\" | \"navigation\" | undefined,\n context?: { description?: string; variableName?: string },\n): VariableSource {\n switch (category) {\n case \"credential\":\n case \"user_data\":\n return \"prompt\";\n case \"fixed\":\n return \"fixed\";\n case \"navigation\": {\n // URL → fixed, 検索キーワード → prompt\n // description/variableName から検索意図を推定\n if (context) {\n const signal = `${context.description ?? \"\"} ${context.variableName ?? \"\"}`.toLowerCase();\n if (/search|query|keyword|filter|検索|フィルタ|絞り込み/.test(signal)) {\n return \"prompt\";\n }\n }\n return \"fixed\";\n }\n default:\n return \"prompt\";\n }\n}\n\n/**\n * RecordedStep配列からYAML手順書文字列を生成\n */\nexport function buildRunbookYaml(input: RunbookInput): string {\n const { goal, startUrl, recordedSteps, goalAchieved, stepDelay, reviewResult, humanGuidance, interventions } = input;\n\n const successfulSteps = recordedSteps.filter((s) => s.success);\n\n // reviewResult がある場合、keep=true のステップのみ残す\n const reviewMap = new Map(\n reviewResult?.reviewedSteps.map((r) => [r.originalOrdinal, r]),\n );\n const filteredSteps = reviewResult\n ? successfulSteps.filter((s) => reviewMap.get(s.ordinal)?.keep !== false)\n : successfulSteps;\n\n // ── 変数定義の構築 ──\n const variables: Record<string, {\n source: VariableSource;\n description?: string;\n required?: boolean;\n sensitive?: boolean;\n value?: string;\n }> = {};\n\n // 変数名の重複管理(同じ名前の変数は1つだけ定義)\n const usedVariableNames = new Set<string>();\n\n filteredSteps.forEach((recorded) => {\n const { action } = recorded;\n const actionType = toActionType(action.action);\n\n if (actionType === \"input\" && action.value !== undefined) {\n const varName = action.variableName ?? `input_${recorded.ordinal}`;\n if (!usedVariableNames.has(varName)) {\n usedVariableNames.add(varName);\n const source = categoryToSource(action.inputCategory, {\n description: action.description,\n variableName: action.variableName ?? varName,\n });\n variables[varName] = {\n source,\n description: action.description,\n ...(source === \"prompt\" && {\n required: true,\n sensitive: action.inputCategory === \"credential\",\n value: action.value,\n }),\n ...(source === \"fixed\" && { value: action.value }),\n };\n }\n }\n });\n\n // ── steps構築 ──\n const steps = filteredSteps.map((recorded, index) => {\n const actionType = toActionType(recorded.action.action);\n const review = reviewMap.get(recorded.ordinal);\n\n // スナップショットから要素を特定してSelectorを構築\n let selector: Selector | undefined;\n if (recorded.action.selector) {\n const ref = recorded.action.selector.replace(\"@\", \"\");\n const element = findElementInSnapshot(recorded.snapshotBefore, ref);\n if (element) {\n selector = buildSelector(element);\n } else if (recorded.resolvedElement) {\n // スナップショット破棄前に保存した要素メタデータを使用\n selector = recorded.resolvedElement;\n } else {\n // description をセレクタの ariaLabel に入れない。\n // AI セレクタ解決は stepDescription パラメータから description を受け取るため、\n // セレクタに重複した description テキストを入れると\n // 決定論的リゾルバが無関係な要素にマッチする原因になる。\n selector = { tagName: \"unknown\" };\n }\n }\n\n // input値を {{varName}} テンプレートに置換\n let value: string | undefined;\n if (actionType === \"input\" && recorded.action.value !== undefined) {\n const varName = recorded.action.variableName ?? `input_${recorded.ordinal}`;\n value = `{{${varName}}}`;\n }\n\n const step: Record<string, unknown> = {\n ordinal: index,\n description: recorded.action.description,\n action: {\n type: actionType,\n ...(selector && { selector }),\n ...(actionType === \"input\" && value !== undefined && { value }),\n ...(actionType === \"select\" && recorded.action.value !== undefined && {\n optionText: recorded.action.value,\n }),\n ...(actionType === \"navigate\" && recorded.action.value && {\n url: recorded.action.value,\n }),\n ...(actionType === \"extract\" && recorded.action.script && {\n script: recorded.action.script,\n }),\n ...(actionType === \"extract\" && !recorded.action.script && recorded.action.extractPrompt && {\n extractPrompt: recorded.action.extractPrompt,\n }),\n ...(actionType === \"download\" && recorded.action.downloadPath && {\n downloadPath: recorded.action.downloadPath,\n }),\n ...(actionType === \"export\" && recorded.action.exportCollection && {\n exportCollection: recorded.action.exportCollection,\n }),\n ...(actionType === \"export\" && recorded.action.exportFormat && {\n exportFormat: recorded.action.exportFormat,\n }),\n ...(actionType === \"export\" && recorded.action.exportPath && {\n exportPath: recorded.action.exportPath,\n }),\n ...(actionType === \"key\" && {\n keys: recorded.action.keys ?? recorded.action.value,\n }),\n },\n url: recorded.url,\n riskLevel: review?.riskLevel ?? \"low\",\n requiresConfirmation: review?.requiresConfirmation ?? false,\n };\n\n // キャプチャ定義\n const captures = buildCaptures(recorded.action.suggestedCaptures);\n if (captures.length > 0) {\n step.captures = captures;\n }\n\n // メモリオペレーション定義\n if (recorded.action.action === \"memory_append\" && recorded.action.memoryCollection) {\n step.memoryOperations = [{\n type: \"append\" as const,\n collection: recorded.action.memoryCollection,\n source: recorded.action.variableName ?? \"extractedData\",\n }];\n } else if (recorded.action.action === \"memory_aggregate\" && recorded.action.aggregation) {\n const agg = recorded.action.aggregation;\n step.memoryOperations = [{\n type: \"aggregate\" as const,\n collection: agg.collection,\n field: agg.field,\n operation: agg.operation,\n outputVariable: agg.outputVariable,\n }];\n }\n\n return step;\n });\n\n // ── YAML構造構築 ──\n const baseUrl = new URL(startUrl).origin;\n\n const runbook: Record<string, unknown> = {\n title: input.title ?? goal,\n settings: {\n baseUrl,\n defaultTimeout: 10000,\n pauseBetweenSteps: stepDelay,\n stopOnError: true,\n },\n metadata: {\n startUrl,\n goal,\n goalAchieved,\n totalSteps: filteredSteps.length,\n generatedAt: new Date().toISOString(),\n ...(input.skills && input.skills.length > 0 && { skills: input.skills }),\n },\n context: input.contextMarkdown,\n };\n\n if (Object.keys(variables).length > 0) {\n runbook.variables = variables;\n }\n\n parameterizeSteps(steps, variables);\n runbook.steps = steps;\n\n const allNotes: string[] = [];\n if (humanGuidance && humanGuidance.length > 0) {\n allNotes.push(\n ...humanGuidance.map((g, i) => `[方針修正 ${i + 1}] ${g}`),\n );\n }\n if (interventions && interventions.length > 0) {\n allNotes.push(\n ...interventions.map(\n (iv) => `[探索中介入 ステップ#${iv.stepIndex}] ${iv.userInstruction}`,\n ),\n );\n }\n if (allNotes.length > 0) {\n runbook.notes = allNotes.join(\"\\n\");\n }\n\n // ラウンドトリップ検証: 生成した構造が Zod スキーマに適合するか確認\n ParsedRunbookSchema.parse(runbook);\n\n return stringify(runbook, { lineWidth: 120 });\n}\n\n/**\n * 変数値がハードコードされたセレクタ・説明・パスを汎用化する。\n *\n * 1. セレクタ: ariaLabel/innerText が変数値を含む場合、そのプロパティを削除\n * → AI セレクタ解決が description ベースで適切な要素を見つける\n * 2. 説明: 変数値を {{varName}} に置換\n * 3. コレクション名/エクスポートパス: 変数値に基づく名前を汎用化\n */\nfunction parameterizeSteps(\n steps: Array<Record<string, unknown>>,\n variables: Record<string, { value?: string; source?: string }>,\n): void {\n // 全変数の値を収集(source を問わない。大文字小文字不問でマッチ)\n const varReplacements: Array<{ value: string; varName: string; lowerValue: string }> = [];\n for (const [name, def] of Object.entries(variables)) {\n if (def.value) {\n varReplacements.push({ value: def.value, varName: name, lowerValue: def.value.toLowerCase() });\n }\n }\n if (varReplacements.length === 0) return;\n\n for (const step of steps) {\n const action = step.action as Record<string, unknown>;\n\n // 1. セレクタから変数値を含む ariaLabel/innerText を除去\n if (action.selector && typeof action.selector === \"object\") {\n const selector = action.selector as Record<string, unknown>;\n for (const { lowerValue } of varReplacements) {\n if (typeof selector.ariaLabel === \"string\"\n && selector.ariaLabel.toLowerCase().includes(lowerValue)) {\n delete selector.ariaLabel;\n }\n if (typeof selector.innerText === \"string\"\n && selector.innerText.toLowerCase().includes(lowerValue)) {\n delete selector.innerText;\n }\n }\n }\n\n // 2a. 大文字小文字不問で変数値を {{varName}} に置換\n if (typeof step.description === \"string\") {\n for (const { value, varName } of varReplacements) {\n const regex = new RegExp(escapeRegExp(value), \"gi\");\n step.description = (step.description as string).replace(regex, `{{${varName}}}`);\n }\n }\n\n // 2b. {{varName}} を含む引用テキスト(「...」 / \"...\")を {{varName}} のみに縮約\n // 例: 「{{companyName}} LIMITED」→「{{companyName}}」\n if (typeof step.description === \"string\") {\n step.description = (step.description as string)\n .replace(/「[^」]*\\{\\{(\\w+)\\}\\}[^」]*」/g, \"「{{$1}}」\")\n .replace(/\"[^\"]*\\{\\{(\\w+)\\}\\}[^\"]*\"/g, '\"{{$1}}\"');\n }\n\n // 3. コレクション名の汎用化(変数値を含む場合)\n if (step.memoryOperations && Array.isArray(step.memoryOperations)) {\n for (const op of step.memoryOperations as Array<Record<string, unknown>>) {\n if (typeof op.collection === \"string\") {\n const col = op.collection as string;\n for (const { lowerValue } of varReplacements) {\n if (col.toLowerCase().includes(lowerValue)) {\n op.collection = \"data\";\n break;\n }\n }\n }\n }\n }\n\n // 4. export コレクション名・パスの汎用化\n if (typeof action.exportCollection === \"string\") {\n for (const { lowerValue } of varReplacements) {\n if ((action.exportCollection as string).toLowerCase().includes(lowerValue)) {\n action.exportCollection = \"data\";\n }\n }\n }\n if (typeof action.exportPath === \"string\") {\n for (const { lowerValue } of varReplacements) {\n if ((action.exportPath as string).toLowerCase().includes(lowerValue)) {\n action.exportPath = `/tmp/data.${action.exportFormat ?? \"csv\"}`;\n }\n }\n }\n }\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * SuggestedCapture[] → YAML用キャプチャ定義に変換\n */\nfunction buildCaptures(\n suggested: SuggestedCapture[] | undefined,\n): StepCapture[] {\n if (!suggested || suggested.length === 0) return [];\n\n return suggested.map((c) => ({\n name: c.name,\n strategy: c.strategy,\n required: false,\n ...(c.description && { description: c.description }),\n ...(c.pattern && { pattern: c.pattern }),\n ...(c.group !== undefined && c.group !== 1 && { group: c.group }),\n ...(c.prompt && { prompt: c.prompt }),\n ...(c.expression && { expression: c.expression }),\n }));\n}\n","/**\n * selector-builder — ParsedSnapshotElement → ElementSelector 変換\n *\n * スナップショットのロール/名前からcontractsのElementSelectorへ近似変換。\n * 正確なロケーターではなく、ヒントとしての変換。\n */\n\nimport type { ElementSelector } from \"../schemas/element-selector\";\nimport type { ParsedSnapshotElement } from \"./snapshot-parser\";\n\n/** role → tagName マッピング */\nexport const ROLE_TAG_MAP: Record<\n string,\n { tagName: string; inputType?: string; role?: string }\n> = {\n textbox: { tagName: \"input\", inputType: \"text\" },\n button: { tagName: \"button\", role: \"button\" },\n link: { tagName: \"a\", role: \"link\" },\n checkbox: { tagName: \"input\", inputType: \"checkbox\" },\n radio: { tagName: \"input\", inputType: \"radio\" },\n combobox: { tagName: \"select\", role: \"combobox\" },\n searchbox: { tagName: \"input\", inputType: \"search\" },\n slider: { tagName: \"input\", inputType: \"range\" },\n spinbutton: { tagName: \"input\", inputType: \"number\" },\n switch: { tagName: \"input\", inputType: \"checkbox\", role: \"switch\" },\n tab: { tagName: \"button\", role: \"tab\" },\n menuitem: { tagName: \"button\", role: \"menuitem\" },\n option: { tagName: \"option\", role: \"option\" },\n heading: { tagName: \"h2\", role: \"heading\" },\n img: { tagName: \"img\", role: \"img\" },\n navigation: { tagName: \"nav\", role: \"navigation\" },\n listitem: { tagName: \"li\", role: \"listitem\" },\n};\n\n/**\n * ParsedSnapshotElement を ElementSelector に変換\n */\nexport function buildSelector(\n element: ParsedSnapshotElement,\n): ElementSelector {\n const mapping = ROLE_TAG_MAP[element.role];\n const tagName = mapping?.tagName ?? element.role;\n\n const selector: ElementSelector = { tagName };\n\n // role\n if (mapping?.role) {\n selector.role = mapping.role;\n } else if (element.role !== tagName) {\n selector.role = element.role;\n }\n\n // inputType\n if (mapping?.inputType) {\n selector.inputType = mapping.inputType;\n }\n\n // name → ariaLabel(共通)\n if (element.name) {\n selector.ariaLabel = element.name;\n\n // button/link は innerText も設定\n if (element.role === \"button\" || element.role === \"link\") {\n selector.innerText = element.name.slice(0, 200);\n }\n }\n\n // 属性から追加情報を取得\n if (element.attributes.placeholder) {\n selector.placeholder = element.attributes.placeholder;\n }\n if (element.attributes.name) {\n selector.name = element.attributes.name;\n }\n\n return selector;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
tenantModelOverrides,
|
|
4
4
|
tenantModelProviders
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-CMWLFQXD.js";
|
|
6
6
|
|
|
7
7
|
// src/server/inngest/helpers/tenant-ai-config.ts
|
|
8
8
|
import { eq } from "drizzle-orm";
|
|
@@ -106,4 +106,4 @@ export {
|
|
|
106
106
|
isMaskedValue,
|
|
107
107
|
resolveTenantAIConfig
|
|
108
108
|
};
|
|
109
|
-
//# sourceMappingURL=chunk-
|
|
109
|
+
//# sourceMappingURL=chunk-SDV3X5UN.js.map
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
runbookSettings,
|
|
6
6
|
runbookSteps,
|
|
7
7
|
runbookVariables
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-CMWLFQXD.js";
|
|
9
9
|
|
|
10
10
|
// src/server/store/runbook-data-helpers.ts
|
|
11
11
|
import { eq } from "drizzle-orm";
|
|
@@ -100,6 +100,7 @@ async function copyVersionData(tx, sourceVersionId, targetVersionId, options) {
|
|
|
100
100
|
value: s.value,
|
|
101
101
|
optionText: s.optionText,
|
|
102
102
|
script: s.script,
|
|
103
|
+
extractPrompt: s.extractPrompt,
|
|
103
104
|
keys: s.keys,
|
|
104
105
|
downloadPath: s.downloadPath,
|
|
105
106
|
exportCollection: s.exportCollection,
|
|
@@ -137,6 +138,7 @@ async function insertSteps(tx, versionId, steps, parentStepId, branchCaseMatch,
|
|
|
137
138
|
value: step.action.value ?? null,
|
|
138
139
|
optionText: step.action.optionText ?? null,
|
|
139
140
|
script: step.action.script ?? null,
|
|
141
|
+
extractPrompt: step.action.extractPrompt ?? null,
|
|
140
142
|
keys: step.action.keys ?? null,
|
|
141
143
|
downloadPath: step.action.downloadPath ?? null,
|
|
142
144
|
exportCollection: step.action.exportCollection ?? null,
|
|
@@ -248,4 +250,4 @@ export {
|
|
|
248
250
|
loadVersionDetail,
|
|
249
251
|
buildFlatRunbook
|
|
250
252
|
};
|
|
251
|
-
//# sourceMappingURL=chunk-
|
|
253
|
+
//# sourceMappingURL=chunk-VVXNFUPL.js.map
|