@refrainai/cli 0.4.1 → 0.4.2
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-2BVDAJZT.js → chunk-65CTEK2K.js} +9 -6
- package/dist/chunk-65CTEK2K.js.map +1 -0
- package/dist/chunk-BGC75OVR.js +30 -0
- package/dist/chunk-BGC75OVR.js.map +1 -0
- package/dist/{chunk-H47NWH7N.js → chunk-CJM3IU5Q.js} +611 -73
- package/dist/chunk-CJM3IU5Q.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-IGFCYKHC.js → chunk-CNJ5KCDN.js} +252 -295
- package/dist/chunk-CNJ5KCDN.js.map +1 -0
- package/dist/{chunk-DJVUITRB.js → chunk-ELQ23L4Z.js} +898 -1135
- package/dist/chunk-ELQ23L4Z.js.map +1 -0
- package/dist/chunk-EMAYENG4.js +1146 -0
- package/dist/chunk-EMAYENG4.js.map +1 -0
- package/dist/{chunk-7UCVPKD4.js → chunk-F7WTOQIQ.js} +12 -72
- package/dist/chunk-F7WTOQIQ.js.map +1 -0
- package/dist/{chunk-WEYR56ZN.js → chunk-HHRHHFSK.js} +4 -4
- 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-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-XIVS7N3V.js +74 -0
- package/dist/chunk-XIVS7N3V.js.map +1 -0
- package/dist/chunk-YTVEYQGA.js +64 -0
- package/dist/chunk-YTVEYQGA.js.map +1 -0
- package/dist/{chunk-RYIJPYM3.js → chunk-YW46VP57.js} +25 -8
- package/dist/chunk-YW46VP57.js.map +1 -0
- package/dist/cli.js +5 -5
- package/dist/{compose-MTSIJY5D.js → compose-B2IAO7YW.js} +9 -7
- package/dist/{compose-MTSIJY5D.js.map → compose-B2IAO7YW.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-JJN4HVIP.js} +12 -10
- package/dist/{fix-runbook-ZSBOTLC2.js.map → fix-runbook-JJN4HVIP.js.map} +1 -1
- package/dist/prompts-XMJXIITW.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-TVV5EG6Q.js} +41 -444
- package/dist/runbook-executor-TVV5EG6Q.js.map +1 -0
- package/dist/{runbook-generator-MPXJBQ5N.js → runbook-generator-4XKNV2B7.js} +61 -136
- package/dist/runbook-generator-4XKNV2B7.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-5XARL5N7.js} +1176 -128
- package/dist/server-5XARL5N7.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-32QBPXT2.js +18 -0
- package/dist/yaml-patcher-32QBPXT2.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-XMJXIITW.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
|
@@ -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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/store/runbook-data-helpers.ts","../../../src/server/store/version-lifecycle.ts"],"sourcesContent":["/**\n * Runbook データ操作の純粋ヘルパー関数\n *\n * RunbookStore / VersionStore の private メソッドを抽出したもの。\n * DB トランザクション内で使用する。\n */\n\nimport { eq } from \"drizzle-orm\";\nimport {\n runbookSettings,\n runbookVariables,\n runbookSecrets,\n runbookSteps,\n jobs,\n} from \"../db/schema.js\";\nimport type { getDb } from \"../db/client.js\";\nimport type { ParsedStep } from \"../../runbook-executor/types.js\";\nimport { resolveDisplayStatus } from \"./version-lifecycle.js\";\n\ntype Db = ReturnType<typeof getDb>;\ntype Tx = Parameters<Parameters<Db[\"transaction\"]>[0]>[0];\n\n/**\n * バージョンデータ(settings, variables, secrets, steps)をコピーする。\n */\nexport async function copyVersionData(\n tx: Tx,\n sourceVersionId: string,\n targetVersionId: string,\n options?: { skipSteps?: boolean },\n) {\n // Settings\n const srcSettings = await tx.query.runbookSettings.findFirst({\n where: eq(runbookSettings.versionId, sourceVersionId),\n });\n if (srcSettings) {\n await tx.insert(runbookSettings).values({\n versionId: targetVersionId,\n defaultTimeout: srcSettings.defaultTimeout,\n pauseBetweenSteps: srcSettings.pauseBetweenSteps,\n stopOnError: srcSettings.stopOnError,\n stepDelay: srcSettings.stepDelay,\n enableSelectorCache: srcSettings.enableSelectorCache,\n enableAgentFallback: srcSettings.enableAgentFallback,\n enableVisionFallback: srcSettings.enableVisionFallback,\n modelId: srcSettings.modelId,\n modelProvider: srcSettings.modelProvider,\n });\n }\n\n // Variables\n const srcVars = await tx.query.runbookVariables.findMany({\n where: eq(runbookVariables.versionId, sourceVersionId),\n });\n if (srcVars.length > 0) {\n await tx.insert(runbookVariables).values(\n srcVars.map((v) => ({\n versionId: targetVersionId,\n name: v.name,\n source: v.source,\n description: v.description,\n required: v.required,\n sensitive: v.sensitive,\n value: v.value,\n })),\n );\n }\n\n // Secrets\n const srcSecrets = await tx.query.runbookSecrets.findMany({\n where: eq(runbookSecrets.versionId, sourceVersionId),\n });\n if (srcSecrets.length > 0) {\n await tx.insert(runbookSecrets).values(\n srcSecrets.map((s) => ({\n versionId: targetVersionId,\n key: s.key,\n encryptedValue: s.encryptedValue,\n })),\n );\n }\n\n // Steps(skipSteps 時はスキップ — 新バージョンでは AI が再生成する)\n if (options?.skipSteps) return;\n\n // Steps(再帰構造をコピー)\n const srcSteps = await tx.query.runbookSteps.findMany({\n where: eq(runbookSteps.versionId, sourceVersionId),\n orderBy: [runbookSteps.ordinal],\n });\n if (srcSteps.length > 0) {\n // ID マッピングを構築\n const idMap = new Map<string, string>();\n for (const s of srcSteps) {\n const [newStep] = await tx.insert(runbookSteps).values({\n versionId: targetVersionId,\n parentStepId: s.parentStepId ? idMap.get(s.parentStepId) ?? null : null,\n ordinal: s.ordinal,\n description: s.description,\n actionType: s.actionType,\n url: s.url,\n riskLevel: s.riskLevel,\n requiresConfirmation: s.requiresConfirmation,\n value: s.value,\n optionText: s.optionText,\n script: s.script,\n extractPrompt: s.extractPrompt,\n keys: s.keys,\n downloadPath: s.downloadPath,\n exportCollection: s.exportCollection,\n exportFormat: s.exportFormat,\n exportPath: s.exportPath,\n selector: s.selector,\n condition: s.condition,\n captures: s.captures,\n memoryOperations: s.memoryOperations,\n loopCondition: s.loopCondition,\n loopForEach: s.loopForEach,\n loopItemVariable: s.loopItemVariable,\n loopIndexVariable: s.loopIndexVariable,\n loopMaxIterations: s.loopMaxIterations,\n loopCounterVariable: s.loopCounterVariable,\n branchValue: s.branchValue,\n branchCaseMatch: s.branchCaseMatch,\n branchIsDefault: s.branchIsDefault,\n }).returning();\n idMap.set(s.id, newStep.id);\n }\n }\n}\n\n/**\n * ステップツリーを再帰的に DB に挿入する。\n */\nexport async function insertSteps(\n tx: Tx,\n versionId: string,\n steps: ParsedStep[],\n parentStepId: string | null,\n branchCaseMatch?: string,\n branchIsDefault?: boolean,\n) {\n for (const step of steps) {\n const [inserted] = await tx\n .insert(runbookSteps)\n .values({\n versionId,\n parentStepId,\n ordinal: step.ordinal,\n description: step.description,\n actionType: step.action.type,\n url: step.url || null,\n riskLevel: step.riskLevel,\n requiresConfirmation: step.requiresConfirmation,\n value: step.action.value ?? null,\n optionText: step.action.optionText ?? null,\n script: step.action.script ?? null,\n extractPrompt: step.action.extractPrompt ?? null,\n keys: step.action.keys ?? null,\n downloadPath: step.action.downloadPath ?? null,\n exportCollection: step.action.exportCollection ?? null,\n exportFormat: step.action.exportFormat ?? null,\n exportPath: step.action.exportPath ?? null,\n selector: step.action.selector ?? null,\n condition: step.condition ?? null,\n captures: step.captures ?? null,\n memoryOperations: step.memoryOperations ?? null,\n loopCondition: step.loop?.condition ?? null,\n loopForEach: step.loop?.forEach ?? null,\n loopItemVariable: step.loop?.itemVariable ?? null,\n loopIndexVariable: step.loop?.indexVariable ?? null,\n loopMaxIterations: step.loop?.maxIterations ?? null,\n loopCounterVariable: step.loop?.counterVariable ?? null,\n branchValue: step.branches?.value ?? null,\n branchCaseMatch: branchCaseMatch ?? null,\n branchIsDefault: branchIsDefault ?? false,\n })\n .returning();\n\n // サブステップ (loop)\n if (step.steps && step.steps.length > 0) {\n await insertSteps(tx, versionId, step.steps, inserted.id);\n }\n\n // ブランチ (cases + default)\n if (step.branches) {\n for (const branchCase of step.branches.cases) {\n await insertSteps(\n tx,\n versionId,\n branchCase.steps,\n inserted.id,\n branchCase.match,\n );\n }\n if (step.branches.default) {\n await insertSteps(\n tx,\n versionId,\n step.branches.default.steps,\n inserted.id,\n undefined,\n true,\n );\n }\n }\n }\n}\n\n/**\n * バージョン詳細(settings, variables, secrets, steps)を読み込む。\n */\nexport async function loadVersionDetail(db: Db, versionId: string) {\n const [settingsRow, variables, secretRows, steps] = await Promise.all([\n db.query.runbookSettings.findFirst({\n where: eq(runbookSettings.versionId, versionId),\n }),\n db.query.runbookVariables.findMany({\n where: eq(runbookVariables.versionId, versionId),\n }),\n db.query.runbookSecrets.findMany({\n where: eq(runbookSecrets.versionId, versionId),\n }),\n db.query.runbookSteps.findMany({\n where: eq(runbookSteps.versionId, versionId),\n orderBy: [runbookSteps.ordinal],\n }),\n ]);\n\n return {\n settings: settingsRow ?? null,\n variables,\n secrets: secretRows,\n steps,\n };\n}\n\n/**\n * DB のバージョン + 子テーブルからフラット構造を構築する(旧 API 互換)。\n */\nexport async function buildFlatRunbook(\n db: Db,\n rb: { id: string; title: string; disabled: boolean; activeVersionId: string | null; createdAt: Date; updatedAt: Date; tenantId: string; createdBy: string | null },\n ver: { id: string; status: string; goal: string; startUrl: string | null; context: string | null; generatedAt: string | null; verificationJobId: string | null; versionNumber: number },\n) {\n const detail = await loadVersionDetail(db, ver.id);\n\n // 検証ジョブのステータスを取得\n let verificationJobStatus: string | null = null;\n if (ver.verificationJobId) {\n const [job] = await db.select({ status: jobs.status }).from(jobs).where(eq(jobs.id, ver.verificationJobId));\n verificationJobStatus = job?.status ?? null;\n }\n\n // ステータスの計算: disabled フラグが true なら \"disabled\"、それ以外はバージョンステータス\n const status = rb.disabled\n ? \"disabled\" as const\n : ver.status === \"active\"\n ? \"active\" as const\n : ver.status === \"pending_verification\"\n ? \"pending_verification\" as const\n : ver.status === \"pending_approval\"\n ? \"pending_verification\" as const // 旧 API 互換\n : \"draft\" as const;\n\n return {\n ...rb,\n // フラット構造互換フィールド(バージョンからコピー)\n goal: ver.goal,\n startUrl: ver.startUrl,\n context: ver.context,\n generatedAt: ver.generatedAt,\n status,\n verificationJobId: ver.verificationJobId,\n verificationJobStatus,\n displayStatus: resolveDisplayStatus(\n rb.disabled ? \"disabled\" : ver.status,\n ver.verificationJobId,\n verificationJobStatus,\n ),\n // 子データ\n ...detail,\n // バージョン情報\n activeVersionId: rb.activeVersionId,\n currentVersionId: ver.id,\n versionNumber: ver.versionNumber,\n versionStatus: ver.status,\n };\n}\n","/**\n * バージョン状態遷移マシン\n *\n * 全てのバージョンステータス遷移ルールを一元管理する。\n * store/handler はここを参照して遷移の妥当性を検証する。\n */\n\nexport type VersionStatus = \"draft\" | \"pending_verification\" | \"pending_approval\" | \"active\" | \"archived\";\n\n/** 許可された状態遷移マップ */\nconst TRANSITIONS: Record<VersionStatus, VersionStatus[]> = {\n draft: [\"pending_verification\"],\n pending_verification: [\"pending_approval\", \"active\"],\n pending_approval: [\"pending_verification\", \"active\"],\n active: [\"archived\"],\n archived: [\"active\"],\n};\n\n/** 遷移が許可されているか */\nexport function canTransition(from: VersionStatus, to: VersionStatus): boolean {\n return TRANSITIONS[from]?.includes(to) ?? false;\n}\n\n/** 遷移を検証し、不正な場合は例外を投げる */\nexport function assertTransition(from: VersionStatus, to: VersionStatus): void {\n if (!canTransition(from, to)) {\n throw new Error(`Invalid transition: ${from} → ${to}`);\n }\n}\n\n/** 編集可能なステータスか(draft | pending_verification) */\nexport function isEditable(status: VersionStatus): boolean {\n return status === \"draft\" || status === \"pending_verification\";\n}\n\n/** 削除可能なステータスか(draft | pending_verification) */\nexport function isDeletable(status: VersionStatus): boolean {\n return status === \"draft\" || status === \"pending_verification\";\n}\n\n/** 検証可能なステータスか(pending_verification) */\nexport function isVerifiable(status: VersionStatus): boolean {\n return status === \"pending_verification\";\n}\n\n// ── 表示ステータス ──\n\nexport type DisplayStatus =\n | \"draft\"\n | \"pendingVerification\"\n | \"verifying\"\n | \"readyToActivate\"\n | \"pendingApproval\"\n | \"active\"\n | \"archived\"\n | \"disabled\";\n\n/**\n * DB ステータス + 検証ジョブ状態から表示用ステータスを解決する。\n * サーバーで計算して返し、フロントエンドはそのまま使う。\n */\nexport function resolveDisplayStatus(\n status: string,\n verificationJobId: string | null,\n verificationJobStatus: string | null,\n): DisplayStatus {\n if (status === \"disabled\") return \"disabled\";\n if (status === \"pending_verification\") {\n if (verificationJobId && verificationJobStatus === \"completed\") return \"readyToActivate\";\n if (\n verificationJobId &&\n verificationJobStatus &&\n ![\"completed\", \"failed\", \"cancelled\"].includes(verificationJobStatus)\n ) return \"verifying\";\n return \"pendingVerification\";\n }\n if (status === \"pending_approval\") return \"pendingApproval\";\n if (status === \"active\") return \"active\";\n if (status === \"archived\") return \"archived\";\n return \"draft\";\n}\n\n/**\n * 公開可能なステータスか\n * requireApproval=true の場合: pending_approval のみ\n * requireApproval=false の場合: pending_verification | pending_approval\n */\nexport function isPublishable(status: VersionStatus, requireApproval: boolean): boolean {\n if (requireApproval) {\n return status === \"pending_approval\";\n }\n return status === \"pending_verification\" || status === \"pending_approval\";\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
t
|
|
4
|
+
} from "./chunk-F7WTOQIQ.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-XIVS7N3V.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,64 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/browser/snapshot-parser.ts
|
|
4
|
+
function parseSnapshotLine(line) {
|
|
5
|
+
const refMatch = line.match(/\[ref=(e\d+)\]/);
|
|
6
|
+
if (!refMatch) return null;
|
|
7
|
+
const ref = refMatch[1];
|
|
8
|
+
const refIndex = line.indexOf(refMatch[0]);
|
|
9
|
+
const beforeRef = line.slice(0, refIndex).trim();
|
|
10
|
+
const afterRef = line.slice(refIndex + refMatch[0].length).trim();
|
|
11
|
+
const cleanBefore = beforeRef.replace(/^-\s+/, "");
|
|
12
|
+
let role;
|
|
13
|
+
let name;
|
|
14
|
+
const roleNameMatch = cleanBefore.match(/^(\S+)\s+"([^"]*)"$/);
|
|
15
|
+
const roleOnlyMatch = cleanBefore.match(/^(\S+)$/);
|
|
16
|
+
if (roleNameMatch) {
|
|
17
|
+
role = roleNameMatch[1];
|
|
18
|
+
name = roleNameMatch[2];
|
|
19
|
+
} else if (roleOnlyMatch && !roleOnlyMatch[1].startsWith("[")) {
|
|
20
|
+
role = roleOnlyMatch[1];
|
|
21
|
+
name = "";
|
|
22
|
+
} else {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const attrSource = afterRef.replace(/:$/, "").trim();
|
|
26
|
+
const attributes = {};
|
|
27
|
+
const attrRegex = /\[(\w+)(?:=([^\]]*))?\]/g;
|
|
28
|
+
let attrMatch;
|
|
29
|
+
while ((attrMatch = attrRegex.exec(attrSource)) !== null) {
|
|
30
|
+
const key = attrMatch[1];
|
|
31
|
+
if (key === "ref") continue;
|
|
32
|
+
const value = attrMatch[2] ?? "true";
|
|
33
|
+
attributes[key] = value;
|
|
34
|
+
}
|
|
35
|
+
return { ref, role, name, attributes };
|
|
36
|
+
}
|
|
37
|
+
function findElementInSnapshot(snapshot, ref) {
|
|
38
|
+
const lines = snapshot.split("\n");
|
|
39
|
+
for (const line of lines) {
|
|
40
|
+
if (!line.includes(`[ref=${ref}]`)) continue;
|
|
41
|
+
const parsed = parseSnapshotLine(line);
|
|
42
|
+
if (parsed && parsed.ref === ref) return parsed;
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
function parseAllElements(snapshot) {
|
|
47
|
+
const lines = snapshot.split("\n");
|
|
48
|
+
const elements = [];
|
|
49
|
+
for (const line of lines) {
|
|
50
|
+
const parsed = parseSnapshotLine(line);
|
|
51
|
+
if (parsed) elements.push(parsed);
|
|
52
|
+
}
|
|
53
|
+
return elements;
|
|
54
|
+
}
|
|
55
|
+
function countElements(snapshot) {
|
|
56
|
+
return parseAllElements(snapshot).length;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export {
|
|
60
|
+
findElementInSnapshot,
|
|
61
|
+
parseAllElements,
|
|
62
|
+
countElements
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=chunk-YTVEYQGA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/browser/snapshot-parser.ts"],"sourcesContent":["/**\n * snapshot-parser — アクセシビリティスナップショット行パース\n *\n * Playwright のアクセシビリティスナップショット出力形式:\n * role \"name\" [ref=eN] [attrs]\n *\n * から構造化データを抽出する純粋関数群\n */\n\nexport interface ParsedSnapshotElement {\n /** 参照ID(例: \"e3\") */\n ref: string;\n /** ロール(例: \"textbox\", \"button\", \"link\") */\n role: string;\n /** 名前(例: \"Email\", \"ログイン\") */\n name: string;\n /** 追加属性 */\n attributes: Record<string, string>;\n}\n\n/**\n * スナップショットの1行をパースして構造化データに変換\n *\n * 入力例:\n * textbox \"Email\" [ref=e3] [required] [focused]\n * - button \"ログイン\" [ref=e5]\n * heading \"Title\" [ref=e1] [level=2]\n * textbox \"サブドメイン\" [ref=e3]:\n * img [ref=e10]\n *\n * @returns パースされた要素、またはマッチしない場合 null\n */\nexport function parseSnapshotLine(\n line: string,\n): ParsedSnapshotElement | null {\n // [ref=eN] を抽出\n const refMatch = line.match(/\\[ref=(e\\d+)\\]/);\n if (!refMatch) return null;\n\n const ref = refMatch[1];\n const refIndex = line.indexOf(refMatch[0]);\n\n // ref より前のテキスト(role \"name\" が先頭にある)\n const beforeRef = line.slice(0, refIndex).trim();\n // ref より後のテキスト(属性のみ)\n const afterRef = line.slice(refIndex + refMatch[0].length).trim();\n\n // 先頭の \"- \" (Playwright リストbullet) を除去\n const cleanBefore = beforeRef.replace(/^-\\s+/, \"\");\n\n let role: string;\n let name: string;\n\n // role \"name\" パターン\n const roleNameMatch = cleanBefore.match(/^(\\S+)\\s+\"([^\"]*)\"$/);\n const roleOnlyMatch = cleanBefore.match(/^(\\S+)$/);\n\n if (roleNameMatch) {\n role = roleNameMatch[1];\n name = roleNameMatch[2];\n } else if (roleOnlyMatch && !roleOnlyMatch[1].startsWith(\"[\")) {\n role = roleOnlyMatch[1];\n name = \"\";\n } else {\n return null;\n }\n\n // 末尾 \":\" (子要素インジケータ) を除去して属性を抽出\n const attrSource = afterRef.replace(/:$/, \"\").trim();\n\n // 属性を抽出([key=value] または [key] 形式、[ref=...] はスキップ)\n const attributes: Record<string, string> = {};\n const attrRegex = /\\[(\\w+)(?:=([^\\]]*))?\\]/g;\n let attrMatch: RegExpExecArray | null;\n while ((attrMatch = attrRegex.exec(attrSource)) !== null) {\n const key = attrMatch[1];\n if (key === \"ref\") continue;\n const value = attrMatch[2] ?? \"true\";\n attributes[key] = value;\n }\n\n return { ref, role, name, attributes };\n}\n\n/**\n * スナップショット全体から指定refの要素を検索\n */\nexport function findElementInSnapshot(\n snapshot: string,\n ref: string,\n): ParsedSnapshotElement | null {\n const lines = snapshot.split(\"\\n\");\n for (const line of lines) {\n if (!line.includes(`[ref=${ref}]`)) continue;\n const parsed = parseSnapshotLine(line);\n if (parsed && parsed.ref === ref) return parsed;\n }\n return null;\n}\n\n/**\n * スナップショットからインタラクティブ要素一覧を抽出\n */\nexport function parseAllElements(\n snapshot: string,\n): ParsedSnapshotElement[] {\n const lines = snapshot.split(\"\\n\");\n const elements: ParsedSnapshotElement[] = [];\n for (const line of lines) {\n const parsed = parseSnapshotLine(line);\n if (parsed) elements.push(parsed);\n }\n return elements;\n}\n\n/**\n * スナップショット内の [ref=eN] 要素の総数を返す。\n */\nexport function countElements(snapshot: string): number {\n return parseAllElements(snapshot).length;\n}\n"],"mappings":";;;AAgCO,SAAS,kBACd,MAC8B;AAE9B,QAAM,WAAW,KAAK,MAAM,gBAAgB;AAC5C,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,MAAM,SAAS,CAAC;AACtB,QAAM,WAAW,KAAK,QAAQ,SAAS,CAAC,CAAC;AAGzC,QAAM,YAAY,KAAK,MAAM,GAAG,QAAQ,EAAE,KAAK;AAE/C,QAAM,WAAW,KAAK,MAAM,WAAW,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK;AAGhE,QAAM,cAAc,UAAU,QAAQ,SAAS,EAAE;AAEjD,MAAI;AACJ,MAAI;AAGJ,QAAM,gBAAgB,YAAY,MAAM,qBAAqB;AAC7D,QAAM,gBAAgB,YAAY,MAAM,SAAS;AAEjD,MAAI,eAAe;AACjB,WAAO,cAAc,CAAC;AACtB,WAAO,cAAc,CAAC;AAAA,EACxB,WAAW,iBAAiB,CAAC,cAAc,CAAC,EAAE,WAAW,GAAG,GAAG;AAC7D,WAAO,cAAc,CAAC;AACtB,WAAO;AAAA,EACT,OAAO;AACL,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,SAAS,QAAQ,MAAM,EAAE,EAAE,KAAK;AAGnD,QAAM,aAAqC,CAAC;AAC5C,QAAM,YAAY;AAClB,MAAI;AACJ,UAAQ,YAAY,UAAU,KAAK,UAAU,OAAO,MAAM;AACxD,UAAM,MAAM,UAAU,CAAC;AACvB,QAAI,QAAQ,MAAO;AACnB,UAAM,QAAQ,UAAU,CAAC,KAAK;AAC9B,eAAW,GAAG,IAAI;AAAA,EACpB;AAEA,SAAO,EAAE,KAAK,MAAM,MAAM,WAAW;AACvC;AAKO,SAAS,sBACd,UACA,KAC8B;AAC9B,QAAM,QAAQ,SAAS,MAAM,IAAI;AACjC,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,KAAK,SAAS,QAAQ,GAAG,GAAG,EAAG;AACpC,UAAM,SAAS,kBAAkB,IAAI;AACrC,QAAI,UAAU,OAAO,QAAQ,IAAK,QAAO;AAAA,EAC3C;AACA,SAAO;AACT;AAKO,SAAS,iBACd,UACyB;AACzB,QAAM,QAAQ,SAAS,MAAM,IAAI;AACjC,QAAM,WAAoC,CAAC;AAC3C,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,kBAAkB,IAAI;AACrC,QAAI,OAAQ,UAAS,KAAK,MAAM;AAAA,EAClC;AACA,SAAO;AACT;AAKO,SAAS,cAAc,UAA0B;AACtD,SAAO,iBAAiB,QAAQ,EAAE;AACpC;","names":[]}
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
} from "./chunk-D5SI2PHK.js";
|
|
5
5
|
import {
|
|
6
6
|
log
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-XIVS7N3V.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-YW46VP57.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":"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","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -5,19 +5,19 @@ var command = process.argv[2];
|
|
|
5
5
|
process.argv = [process.argv[0], process.argv[1], ...process.argv.slice(3)];
|
|
6
6
|
switch (command) {
|
|
7
7
|
case "generate":
|
|
8
|
-
await import("./runbook-generator-
|
|
8
|
+
await import("./runbook-generator-4XKNV2B7.js");
|
|
9
9
|
break;
|
|
10
10
|
case "execute":
|
|
11
|
-
await import("./runbook-executor-
|
|
11
|
+
await import("./runbook-executor-TVV5EG6Q.js");
|
|
12
12
|
break;
|
|
13
13
|
case "fix-runbook":
|
|
14
|
-
await import("./fix-runbook-
|
|
14
|
+
await import("./fix-runbook-JJN4HVIP.js");
|
|
15
15
|
break;
|
|
16
16
|
case "compose":
|
|
17
|
-
await import("./compose-
|
|
17
|
+
await import("./compose-B2IAO7YW.js");
|
|
18
18
|
break;
|
|
19
19
|
case "serve":
|
|
20
|
-
await import("./server-
|
|
20
|
+
await import("./server-5XARL5N7.js");
|
|
21
21
|
break;
|
|
22
22
|
case "--version":
|
|
23
23
|
case "-v": {
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
initLocale,
|
|
4
3
|
intro,
|
|
5
4
|
log,
|
|
6
5
|
note,
|
|
7
6
|
outro,
|
|
8
7
|
promptConfirm,
|
|
9
8
|
promptSelect,
|
|
10
|
-
promptText
|
|
11
|
-
|
|
12
|
-
tf
|
|
13
|
-
} from "./chunk-7UCVPKD4.js";
|
|
9
|
+
promptText
|
|
10
|
+
} from "./chunk-XIVS7N3V.js";
|
|
14
11
|
import {
|
|
15
12
|
ParsedRunbookSchema
|
|
16
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-LZDZGI4M.js";
|
|
14
|
+
import {
|
|
15
|
+
initLocale,
|
|
16
|
+
t,
|
|
17
|
+
tf
|
|
18
|
+
} from "./chunk-F7WTOQIQ.js";
|
|
17
19
|
import "./chunk-2H7UOFLK.js";
|
|
18
20
|
|
|
19
21
|
// src/compose/config.ts
|
|
@@ -544,4 +546,4 @@ try {
|
|
|
544
546
|
console.error(`\u5408\u6210\u5931\u6557: ${msg}`);
|
|
545
547
|
process.exit(1);
|
|
546
548
|
}
|
|
547
|
-
//# sourceMappingURL=compose-
|
|
549
|
+
//# sourceMappingURL=compose-B2IAO7YW.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/compose/config.ts","../../../src/compose/composer.ts","../../../src/compose/interactive.ts","../../../src/compose/index.ts"],"sourcesContent":["/**\n * compose CLI 引数パース\n *\n * 対話式フローでは全引数を optional に。--output のみ必須。\n * CLI 引数はプリフィルとして使用し、未指定分はプロンプトで収集。\n */\n\nimport { parseArgs } from \"node:util\";\n\nexport interface ComposeConfig {\n /** 分岐条件の変数名(未指定時はプロンプトで収集) */\n branchOn?: string;\n /** \"match:yamlPath\" のペア(未指定時はプロンプトで収集) */\n cases: { match: string; yamlPath: string }[];\n /** 合成後のゴール */\n goal?: string;\n /** 出力先 YAML パス */\n output: string;\n /** ロケール */\n locale?: string;\n}\n\nexport function parseComposeArgs(): ComposeConfig {\n const { values } = parseArgs({\n options: {\n \"branch-on\": { type: \"string\" },\n case: { type: \"string\", multiple: true },\n goal: { type: \"string\" },\n output: { type: \"string\" },\n locale: { type: \"string\" },\n },\n strict: false,\n });\n\n const output = values[\"output\"] as string | undefined;\n if (!output) {\n console.error(\"--output is required\");\n process.exit(1);\n }\n\n const caseArgs = (values[\"case\"] as string[] | undefined) ?? [];\n const cases = caseArgs.map((c) => {\n const colonIdx = c.indexOf(\":\");\n if (colonIdx === -1) {\n console.error(`Invalid --case format: \"${c}\" (expected match:yamlPath)`);\n process.exit(1);\n }\n return {\n match: c.slice(0, colonIdx),\n yamlPath: c.slice(colonIdx + 1),\n };\n });\n\n return {\n branchOn: values[\"branch-on\"] as string | undefined,\n cases,\n goal: values[\"goal\"] as string | undefined,\n output,\n locale: values[\"locale\"] as string | undefined,\n };\n}\n","/**\n * composer — 複数の手順書 YAML を1つの分岐付き手順書に合成する純粋関数群\n */\n\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { parse, stringify } from \"yaml\";\nimport { ParsedRunbookSchema, VariableDefinitionSchema } from \"../schemas/runbook-schema\";\nimport type { z } from \"zod\";\n\n// ── 型定義 ──\n\nexport type ParsedRunbook = z.infer<typeof ParsedRunbookSchema>;\nexport type VariableDefinition = z.infer<typeof VariableDefinitionSchema>;\n\nexport interface LoadedCase {\n match: string;\n yamlPath: string;\n runbook: ParsedRunbook;\n}\n\nexport interface VariableConflict {\n name: string;\n definitions: { caseName: string; def: VariableDefinition }[];\n}\n\nexport interface VariableMergeResult {\n /** 全ケースで定義一致の変数 */\n shared: Record<string, VariableDefinition>;\n /** ケース間で定義が異なる変数 */\n conflicts: VariableConflict[];\n /** 特定ケースにのみ存在する変数 */\n caseSpecific: { caseName: string; name: string; def: VariableDefinition }[];\n}\n\nexport interface SettingsDiff {\n key: string;\n values: { caseName: string; value: unknown }[];\n}\n\nexport interface CompositionState {\n branchOn: string;\n cases: LoadedCase[];\n goal?: string;\n output: string;\n mergedVariables: Record<string, VariableDefinition>;\n settings: ParsedRunbook[\"settings\"];\n metadata: ParsedRunbook[\"metadata\"];\n title: string;\n}\n\n// ── 純粋関数 ──\n\n/**\n * 単一ケースの読み込み・バリデーション\n */\nexport async function loadCase(match: string, yamlPath: string): Promise<LoadedCase> {\n const raw = await readFile(yamlPath, \"utf-8\");\n const doc = parse(raw);\n const runbook = ParsedRunbookSchema.parse(doc);\n return { match, yamlPath, runbook };\n}\n\n/**\n * VariableDefinition を正規化して比較用にする。\n * Zod のデフォルト値(required: true, sensitive: false)を埋めた上でフィールド単位比較。\n */\nfunction normalizeVarDef(def: VariableDefinition): VariableDefinition {\n return {\n source: def.source,\n required: def.required ?? true,\n sensitive: def.sensitive ?? false,\n ...(def.description !== undefined ? { description: def.description } : {}),\n ...(def.value !== undefined ? { value: def.value } : {}),\n ...(def.expression !== undefined ? { expression: def.expression } : {}),\n ...(def.envKey !== undefined ? { envKey: def.envKey } : {}),\n };\n}\n\nfunction varDefsEqual(a: VariableDefinition, b: VariableDefinition): boolean {\n const na = normalizeVarDef(a);\n const nb = normalizeVarDef(b);\n return (\n na.source === nb.source &&\n na.required === nb.required &&\n na.sensitive === nb.sensitive &&\n na.description === nb.description &&\n na.value === nb.value &&\n na.expression === nb.expression &&\n na.envKey === nb.envKey\n );\n}\n\n/**\n * 変数を分析(共通/競合/ケース固有に分類)\n */\nexport function analyzeVariables(cases: LoadedCase[]): VariableMergeResult {\n // 各変数名がどのケースに定義されているか収集\n const varMap = new Map<string, { caseName: string; def: VariableDefinition }[]>();\n for (const lc of cases) {\n if (!lc.runbook.variables) continue;\n for (const [name, def] of Object.entries(lc.runbook.variables)) {\n const existing = varMap.get(name) ?? [];\n existing.push({ caseName: lc.match, def });\n varMap.set(name, existing);\n }\n }\n\n const shared: Record<string, VariableDefinition> = {};\n const conflicts: VariableConflict[] = [];\n const caseSpecific: { caseName: string; name: string; def: VariableDefinition }[] = [];\n\n for (const [name, entries] of varMap) {\n if (entries.length === 1) {\n // 1つのケースにのみ存在\n caseSpecific.push({ caseName: entries[0].caseName, name, def: entries[0].def });\n } else if (entries.length === cases.length) {\n // 全ケースに存在 → 定義が一致するか確認\n const allEqual = entries.every((e) => varDefsEqual(e.def, entries[0].def));\n if (allEqual) {\n shared[name] = entries[0].def;\n } else {\n conflicts.push({ name, definitions: entries });\n }\n } else {\n // 一部のケースにのみ存在(2ケース以上だが全ケースではない)\n // これも競合として扱う\n conflicts.push({ name, definitions: entries });\n }\n }\n\n return { shared, conflicts, caseSpecific };\n}\n\n/**\n * 競合解決マップ付きで変数をマージ。\n * resolutions: 競合変数名 → 採用する定義のマップ\n */\nexport function mergeVariables(\n analysis: VariableMergeResult,\n resolutions: Map<string, VariableDefinition>,\n branchOn: string,\n caseMatches: string[],\n): Record<string, VariableDefinition> {\n const merged: Record<string, VariableDefinition> = {};\n\n // 共通変数\n for (const [name, def] of Object.entries(analysis.shared)) {\n merged[name] = def;\n }\n\n // 競合変数(解決マップから採用)\n for (const conflict of analysis.conflicts) {\n const resolved = resolutions.get(conflict.name);\n if (resolved) {\n merged[conflict.name] = resolved;\n } else {\n // 解決がない場合は最初のケースの定義を使用\n merged[conflict.name] = conflict.definitions[0].def;\n }\n }\n\n // ケース固有変数\n for (const cs of analysis.caseSpecific) {\n merged[cs.name] = cs.def;\n }\n\n // 分岐変数を追加(まだ含まれていなければ)\n if (!(branchOn in merged)) {\n merged[branchOn] = {\n source: \"prompt\",\n description: `分岐条件 (${caseMatches.join(\", \")})`,\n required: true,\n sensitive: false,\n };\n }\n\n return merged;\n}\n\n/**\n * Settings の差分検出。全ケースで同じ値なら空配列。\n */\nexport function diffSettings(cases: LoadedCase[]): SettingsDiff[] {\n if (cases.length <= 1) return [];\n\n const diffs: SettingsDiff[] = [];\n const keys = [\"baseUrl\", \"defaultTimeout\", \"pauseBetweenSteps\", \"stopOnError\"] as const;\n\n for (const key of keys) {\n const values = cases.map((lc) => ({\n caseName: lc.match,\n value: lc.runbook.settings[key],\n }));\n\n const allSame = values.every((v) => v.value === values[0].value);\n if (!allSame) {\n diffs.push({ key, values });\n }\n }\n\n return diffs;\n}\n\n/**\n * 合成済み runbook オブジェクト構築(I/O なし)\n */\nexport function buildComposedRunbook(state: CompositionState): Record<string, unknown> {\n const base = state.cases[0].runbook;\n\n const branchStep = {\n ordinal: 0,\n description: state.goal ?? `${state.branchOn} に応じた分岐`,\n action: { type: \"memory\" },\n url: state.metadata.startUrl,\n riskLevel: \"low\",\n requiresConfirmation: false,\n branches: {\n value: `{{${state.branchOn}}}`,\n cases: state.cases.map((lc) => ({\n match: lc.match,\n steps: lc.runbook.steps.map((s, i) => ({\n ...s,\n ordinal: i,\n })),\n })),\n },\n };\n\n return {\n title: state.title,\n ...(base.naturalLanguageSummary ? { naturalLanguageSummary: base.naturalLanguageSummary } : {}),\n settings: state.settings,\n metadata: {\n ...state.metadata,\n totalSteps: 1,\n generatedAt: new Date().toISOString(),\n },\n steps: [branchStep],\n context: base.context ?? \"\",\n variables: state.mergedVariables,\n };\n}\n\n/**\n * Zod バリデーション + YAML 書き出し\n */\nexport async function validateAndWriteYaml(\n composed: Record<string, unknown>,\n outputPath: string,\n): Promise<string> {\n ParsedRunbookSchema.parse(composed);\n const yamlContent = stringify(composed, { lineWidth: 120 });\n await writeFile(outputPath, yamlContent, \"utf-8\");\n return outputPath;\n}\n\n/**\n * 変数定義の表示文字列を生成\n */\nexport function formatVariableDef(def: VariableDefinition): string {\n const parts = [`source: ${def.source}`];\n if (def.value !== undefined) parts.push(`value: \"${def.value}\"`);\n if (def.envKey !== undefined) parts.push(`envKey: ${def.envKey}`);\n if (def.expression !== undefined) parts.push(`expression: ${def.expression}`);\n return parts.join(\", \");\n}\n","/**\n * compose/interactive — 対話ロジック(収集・競合解決・プレビュー・編集ループ)\n *\n * composer.ts の純粋関数を呼び出しつつ、@clack/prompts でユーザーと対話する。\n */\n\nimport { t, tf } from \"../i18n\";\nimport { log, note, promptConfirm, promptSelect, promptText } from \"../cli/prompts\";\nimport type {\n CompositionState,\n LoadedCase,\n VariableConflict,\n VariableDefinition,\n VariableMergeResult,\n SettingsDiff,\n ParsedRunbook,\n} from \"./composer\";\nimport { loadCase, formatVariableDef, analyzeVariables, mergeVariables, diffSettings } from \"./composer\";\n\n// ── Phase 1: 入力収集 ──\n\n/**\n * 分岐変数名をプロンプトで取得\n */\nexport async function gatherBranchVariable(): Promise<string> {\n return promptText(t(\"compose.branchVarPrompt\"), {\n validate: (v) => (!v?.trim() ? t(\"compose.branchVarPrompt\") : undefined),\n });\n}\n\n/**\n * 対話的にケースを1つずつ追加\n */\nexport async function gatherCasesInteractively(): Promise<LoadedCase[]> {\n const cases: LoadedCase[] = [];\n\n // 最低2ケース必要\n while (cases.length < 2 || (await promptConfirm(t(\"compose.addAnotherCase\"), false))) {\n const yamlPath = await promptText(t(\"compose.yamlPathPrompt\"), {\n validate: (v) => (!v?.trim() ? t(\"compose.yamlPathPrompt\") : undefined),\n });\n const match = await promptText(t(\"compose.matchValuePrompt\"), {\n validate: (v) => (!v?.trim() ? t(\"compose.matchValuePrompt\") : undefined),\n });\n\n const loaded = await loadCase(match, yamlPath);\n const varCount = loaded.runbook.variables\n ? Object.keys(loaded.runbook.variables).length\n : 0;\n log.success(\n tf(\"compose.caseLoaded\", {\n title: loaded.runbook.title,\n steps: loaded.runbook.steps.length,\n vars: varCount,\n }),\n );\n cases.push(loaded);\n }\n\n return cases;\n}\n\n/**\n * CLI 引数で指定されたケースを一括ロード\n */\nexport async function loadProvidedCases(\n caseDefs: { match: string; yamlPath: string }[],\n): Promise<LoadedCase[]> {\n const cases: LoadedCase[] = [];\n for (const c of caseDefs) {\n const loaded = await loadCase(c.match, c.yamlPath);\n const varCount = loaded.runbook.variables\n ? Object.keys(loaded.runbook.variables).length\n : 0;\n log.success(\n tf(\"compose.caseLoaded\", {\n title: loaded.runbook.title,\n steps: loaded.runbook.steps.length,\n vars: varCount,\n }),\n );\n cases.push(loaded);\n }\n return cases;\n}\n\n/**\n * ゴールをプロンプトで取得\n */\nexport async function gatherGoal(defaultGoal?: string): Promise<string | undefined> {\n const goal = await promptText(t(\"compose.goalPrompt\"), {\n initialValue: defaultGoal,\n placeholder: defaultGoal,\n });\n return goal.trim() || undefined;\n}\n\n// ── Phase 2: 変数競合解決 ──\n\n/**\n * 変数マージプレビューを表示\n */\nexport function displayVariableMergePreview(\n analysis: VariableMergeResult,\n branchOn: string,\n): void {\n const lines: string[] = [];\n\n // 共通変数\n const sharedEntries = Object.entries(analysis.shared);\n if (sharedEntries.length > 0) {\n lines.push(t(\"compose.sharedVariables\"));\n for (const [name, def] of sharedEntries) {\n lines.push(` ${name} → ${formatVariableDef(def)}`);\n }\n lines.push(\"\");\n }\n\n // 競合変数\n if (analysis.conflicts.length > 0) {\n lines.push(t(\"compose.conflictingVariables\"));\n for (const conflict of analysis.conflicts) {\n lines.push(` ${conflict.name}`);\n for (const d of conflict.definitions) {\n lines.push(` [${d.caseName}] ${formatVariableDef(d.def)}`);\n }\n }\n lines.push(\"\");\n }\n\n // ケース固有変数\n if (analysis.caseSpecific.length > 0) {\n lines.push(t(\"compose.caseSpecificVariables\"));\n for (const cs of analysis.caseSpecific) {\n lines.push(` [${cs.caseName}] ${cs.name} → ${formatVariableDef(cs.def)}`);\n }\n lines.push(\"\");\n }\n\n // 分岐変数\n lines.push(t(\"compose.branchVariable\"));\n lines.push(` ${branchOn} → source: prompt`);\n\n note(lines.join(\"\\n\"), t(\"compose.variableMergePreview\"));\n}\n\n/**\n * 競合変数の解決をユーザーに問う\n */\nexport async function resolveVariableConflicts(\n analysis: VariableMergeResult,\n): Promise<Map<string, VariableDefinition>> {\n const resolutions = new Map<string, VariableDefinition>();\n\n for (const conflict of analysis.conflicts) {\n const options = conflict.definitions.map((d) => ({\n value: d.caseName,\n label: tf(\"compose.useFromCase\", { case: d.caseName }),\n hint: formatVariableDef(d.def),\n }));\n\n const chosen = await promptSelect(\n tf(\"compose.conflictPrompt\", { name: conflict.name }),\n options,\n );\n\n const selected = conflict.definitions.find((d) => d.caseName === chosen);\n if (selected) {\n resolutions.set(conflict.name, selected.def);\n }\n }\n\n return resolutions;\n}\n\n// ── Phase 3: Settings 解決 ──\n\n/**\n * Settings の差分をユーザーに問う\n */\nexport async function resolveSettings(\n diffs: SettingsDiff[],\n cases: LoadedCase[],\n baseSettings: ParsedRunbook[\"settings\"],\n): Promise<ParsedRunbook[\"settings\"]> {\n const settings = { ...baseSettings };\n\n for (const diff of diffs) {\n const options = diff.values.map((v) => ({\n value: v.caseName,\n label: tf(\"compose.useFromCase\", { case: v.caseName }),\n hint: `${diff.key} = ${JSON.stringify(v.value)}`,\n }));\n\n const chosen = await promptSelect(\n tf(\"compose.settingsDiffPrompt\", { key: diff.key }),\n options,\n );\n\n const selectedCase = cases.find((c) => c.match === chosen);\n if (selectedCase) {\n (settings as Record<string, unknown>)[diff.key] =\n selectedCase.runbook.settings[diff.key as keyof typeof settings];\n }\n }\n\n return settings;\n}\n\n// ── Phase 4: プレビュー + 編集ループ ──\n\n/**\n * 合成結果のプレビューを表示\n */\nfunction displayPreview(state: CompositionState): void {\n const lines: string[] = [];\n lines.push(`Title: ${state.title}`);\n lines.push(`Branch: {{${state.branchOn}}}`);\n lines.push(\n `Cases: ${state.cases.map((c) => `${c.match} (${c.runbook.steps.length} steps)`).join(\", \")}`,\n );\n lines.push(\"\");\n\n const varEntries = Object.entries(state.mergedVariables);\n lines.push(`Variables (${varEntries.length}):`);\n for (const [name, def] of varEntries) {\n const isBranch = name === state.branchOn ? \" (branch)\" : \"\";\n lines.push(` ${name} → ${formatVariableDef(def)}${isBranch}`);\n }\n lines.push(\"\");\n\n lines.push(\"Settings:\");\n lines.push(` baseUrl: ${state.settings.baseUrl}`);\n lines.push(` defaultTimeout: ${state.settings.defaultTimeout}`);\n\n note(lines.join(\"\\n\"), t(\"compose.composedPreview\"));\n}\n\ntype EditAction = \"confirm\" | \"editBranch\" | \"editMatches\" | \"editVariables\" | \"editTitle\";\n\n/**\n * 編集ループ — ユーザーが「確定」を選ぶまで繰り返す\n */\nexport async function editLoop(state: CompositionState): Promise<void> {\n while (true) {\n displayPreview(state);\n\n const action = await promptSelect<EditAction>(t(\"compose.selectAction\"), [\n { value: \"confirm\", label: t(\"compose.confirm\"), hint: t(\"compose.confirmHint\") },\n { value: \"editBranch\", label: t(\"compose.editBranch\") },\n { value: \"editMatches\", label: t(\"compose.editMatches\") },\n { value: \"editVariables\", label: t(\"compose.editVariables\") },\n { value: \"editTitle\", label: t(\"compose.editTitle\") },\n ]);\n\n if (action === \"confirm\") break;\n\n switch (action) {\n case \"editBranch\":\n await handleEditBranch(state);\n break;\n case \"editMatches\":\n await handleEditMatches(state);\n break;\n case \"editVariables\":\n await handleEditVariables(state);\n break;\n case \"editTitle\":\n await handleEditTitle(state);\n break;\n }\n }\n}\n\nasync function handleEditBranch(state: CompositionState): Promise<void> {\n const oldBranch = state.branchOn;\n const newBranch = await promptText(t(\"compose.newBranchVar\"), {\n initialValue: oldBranch,\n validate: (v) => (!v?.trim() ? t(\"compose.branchVarPrompt\") : undefined),\n });\n\n if (newBranch !== oldBranch) {\n // mergedVariables のキーを付け替え\n const branchDef = state.mergedVariables[oldBranch];\n if (branchDef) {\n delete state.mergedVariables[oldBranch];\n state.mergedVariables[newBranch] = branchDef;\n }\n state.branchOn = newBranch;\n }\n}\n\nasync function handleEditMatches(state: CompositionState): Promise<void> {\n const options = state.cases.map((c) => ({\n value: c.match,\n label: c.match,\n hint: c.runbook.title,\n }));\n\n const selected = await promptSelect(t(\"compose.selectCase\"), options);\n const caseObj = state.cases.find((c) => c.match === selected);\n if (!caseObj) return;\n\n const newMatch = await promptText(t(\"compose.newMatchValue\"), {\n initialValue: caseObj.match,\n validate: (v) => (!v?.trim() ? t(\"compose.matchValuePrompt\") : undefined),\n });\n caseObj.match = newMatch;\n\n // 分岐変数の description を更新\n const branchDef = state.mergedVariables[state.branchOn];\n if (branchDef) {\n branchDef.description = `分岐条件 (${state.cases.map((c) => c.match).join(\", \")})`;\n }\n}\n\ntype VarAction = \"delete\" | \"add\" | \"edit\";\n\nasync function handleEditVariables(state: CompositionState): Promise<void> {\n const action = await promptSelect<VarAction>(t(\"compose.editVarAction\"), [\n { value: \"delete\", label: t(\"compose.deleteVar\") },\n { value: \"add\", label: t(\"compose.addVar\") },\n { value: \"edit\", label: t(\"compose.editVarDef\") },\n ]);\n\n const varNames = Object.keys(state.mergedVariables).filter((n) => n !== state.branchOn);\n\n switch (action) {\n case \"delete\": {\n if (varNames.length === 0) return;\n const toDelete = await promptSelect(\n t(\"compose.selectVar\"),\n varNames.map((n) => ({\n value: n,\n label: n,\n hint: formatVariableDef(state.mergedVariables[n]),\n })),\n );\n delete state.mergedVariables[toDelete];\n log.success(tf(\"compose.varDeleted\", { name: toDelete }));\n break;\n }\n case \"add\": {\n const name = await promptText(t(\"compose.newVarName\"), {\n validate: (v) => {\n if (!v?.trim()) return t(\"compose.newVarName\");\n if (v.trim() === state.branchOn)\n return tf(\"compose.branchVarConflict\", { name: v.trim() });\n return undefined;\n },\n });\n const source = await promptSelect(t(\"compose.newVarSource\"), [\n { value: \"prompt\", label: \"prompt\" },\n { value: \"fixed\", label: \"fixed\" },\n { value: \"env\", label: \"env\" },\n { value: \"context\", label: \"context\" },\n { value: \"expression\", label: \"expression\" },\n { value: \"data\", label: \"data\" },\n ]);\n const value = await promptText(t(\"compose.newVarValue\"));\n const description = await promptText(t(\"compose.newVarDescription\"));\n state.mergedVariables[name] = {\n source: source as VariableDefinition[\"source\"],\n required: true,\n sensitive: false,\n ...(value.trim() ? { value: value.trim() } : {}),\n ...(description.trim() ? { description: description.trim() } : {}),\n };\n log.success(tf(\"compose.varAdded\", { name }));\n break;\n }\n case \"edit\": {\n if (varNames.length === 0) return;\n const toEdit = await promptSelect(\n t(\"compose.selectVar\"),\n varNames.map((n) => ({\n value: n,\n label: n,\n hint: formatVariableDef(state.mergedVariables[n]),\n })),\n );\n const currentDef = state.mergedVariables[toEdit];\n const newSource = await promptSelect(t(\"compose.newVarSource\"), [\n { value: \"prompt\", label: \"prompt\" },\n { value: \"fixed\", label: \"fixed\" },\n { value: \"env\", label: \"env\" },\n { value: \"context\", label: \"context\" },\n { value: \"expression\", label: \"expression\" },\n { value: \"data\", label: \"data\" },\n ]);\n const newValue = await promptText(t(\"compose.newVarValue\"), {\n initialValue: currentDef.value ?? \"\",\n });\n const newDesc = await promptText(t(\"compose.newVarDescription\"), {\n initialValue: currentDef.description ?? \"\",\n });\n state.mergedVariables[toEdit] = {\n source: newSource as VariableDefinition[\"source\"],\n required: currentDef.required,\n sensitive: currentDef.sensitive,\n ...(newValue.trim() ? { value: newValue.trim() } : {}),\n ...(newDesc.trim() ? { description: newDesc.trim() } : {}),\n };\n log.success(tf(\"compose.varUpdated\", { name: toEdit }));\n break;\n }\n }\n}\n\nasync function handleEditTitle(state: CompositionState): Promise<void> {\n const newTitle = await promptText(t(\"compose.newTitle\"), {\n initialValue: state.title,\n validate: (v) => (!v?.trim() ? t(\"compose.newTitle\") : undefined),\n });\n state.title = newTitle;\n state.goal = newTitle;\n state.metadata = { ...state.metadata, goal: newTitle };\n}\n\n// ── ヘルパー: 状態構築の再利用 ──\n\n/**\n * 変数分析・競合解決・Settings 解決を経て CompositionState を構築する\n */\nexport async function buildState(opts: {\n branchOn: string;\n cases: LoadedCase[];\n goal?: string;\n output: string;\n}): Promise<CompositionState> {\n const { branchOn, cases, goal, output } = opts;\n\n // 変数分析\n const varAnalysis = analyzeVariables(cases);\n displayVariableMergePreview(varAnalysis, branchOn);\n const resolutions = await resolveVariableConflicts(varAnalysis);\n\n // Settings 解決\n const settingsDiffs = diffSettings(cases);\n const settings = await resolveSettings(settingsDiffs, cases, cases[0].runbook.settings);\n\n const mergedVars = mergeVariables(\n varAnalysis,\n resolutions,\n branchOn,\n cases.map((c) => c.match),\n );\n\n const title = goal ?? cases[0].runbook.title;\n\n return {\n branchOn,\n cases,\n goal,\n output,\n mergedVariables: mergedVars,\n settings,\n metadata: {\n ...cases[0].runbook.metadata,\n goal: goal ?? cases[0].runbook.metadata.goal,\n },\n title,\n };\n}\n","/**\n * compose CLI エントリポイント\n *\n * 複数の生成済み手順書を1つの分岐付き手順書に対話的に合成する。\n * CLI 引数はプリフィルとして使用し、未指定分はプロンプトで収集。\n */\n\nimport { initLocale, t, tf } from \"../i18n\";\nimport { intro, outro } from \"../cli/prompts\";\nimport { parseComposeArgs } from \"./config\";\nimport { buildComposedRunbook, validateAndWriteYaml } from \"./composer\";\nimport {\n gatherBranchVariable,\n gatherCasesInteractively,\n loadProvidedCases,\n gatherGoal,\n buildState,\n editLoop,\n} from \"./interactive\";\n\nconst config = parseComposeArgs();\ninitLocale(config.locale);\nintro(t(\"compose.title\"));\n\ntry {\n // Phase 1: 入力収集(CLI 引数はプリフィル)\n const branchOn = config.branchOn ?? (await gatherBranchVariable());\n const cases =\n config.cases.length > 0\n ? await loadProvidedCases(config.cases)\n : await gatherCasesInteractively();\n const goal = config.goal ?? (await gatherGoal(cases[0]?.runbook.title));\n\n // Phase 2 & 3: 変数競合解決 + Settings 解決\n const state = await buildState({ branchOn, cases, goal, output: config.output });\n\n // Phase 4: プレビュー + 編集ループ\n await editLoop(state);\n\n // Phase 5: 書き出し\n const composed = buildComposedRunbook(state);\n const outputPath = await validateAndWriteYaml(composed, config.output);\n outro(tf(\"compose.complete\", { path: outputPath }));\n} catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(`合成失敗: ${msg}`);\n process.exit(1);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/compose/config.ts","../../../src/compose/composer.ts","../../../src/compose/interactive.ts","../../../src/compose/index.ts"],"sourcesContent":["/**\n * compose CLI 引数パース\n *\n * 対話式フローでは全引数を optional に。--output のみ必須。\n * CLI 引数はプリフィルとして使用し、未指定分はプロンプトで収集。\n */\n\nimport { parseArgs } from \"node:util\";\n\nexport interface ComposeConfig {\n /** 分岐条件の変数名(未指定時はプロンプトで収集) */\n branchOn?: string;\n /** \"match:yamlPath\" のペア(未指定時はプロンプトで収集) */\n cases: { match: string; yamlPath: string }[];\n /** 合成後のゴール */\n goal?: string;\n /** 出力先 YAML パス */\n output: string;\n /** ロケール */\n locale?: string;\n}\n\nexport function parseComposeArgs(): ComposeConfig {\n const { values } = parseArgs({\n options: {\n \"branch-on\": { type: \"string\" },\n case: { type: \"string\", multiple: true },\n goal: { type: \"string\" },\n output: { type: \"string\" },\n locale: { type: \"string\" },\n },\n strict: false,\n });\n\n const output = values[\"output\"] as string | undefined;\n if (!output) {\n console.error(\"--output is required\");\n process.exit(1);\n }\n\n const caseArgs = (values[\"case\"] as string[] | undefined) ?? [];\n const cases = caseArgs.map((c) => {\n const colonIdx = c.indexOf(\":\");\n if (colonIdx === -1) {\n console.error(`Invalid --case format: \"${c}\" (expected match:yamlPath)`);\n process.exit(1);\n }\n return {\n match: c.slice(0, colonIdx),\n yamlPath: c.slice(colonIdx + 1),\n };\n });\n\n return {\n branchOn: values[\"branch-on\"] as string | undefined,\n cases,\n goal: values[\"goal\"] as string | undefined,\n output,\n locale: values[\"locale\"] as string | undefined,\n };\n}\n","/**\n * composer — 複数の手順書 YAML を1つの分岐付き手順書に合成する純粋関数群\n */\n\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { parse, stringify } from \"yaml\";\nimport { ParsedRunbookSchema, VariableDefinitionSchema } from \"../schemas/runbook-schema\";\nimport type { z } from \"zod\";\n\n// ── 型定義 ──\n\nexport type ParsedRunbook = z.infer<typeof ParsedRunbookSchema>;\nexport type VariableDefinition = z.infer<typeof VariableDefinitionSchema>;\n\nexport interface LoadedCase {\n match: string;\n yamlPath: string;\n runbook: ParsedRunbook;\n}\n\nexport interface VariableConflict {\n name: string;\n definitions: { caseName: string; def: VariableDefinition }[];\n}\n\nexport interface VariableMergeResult {\n /** 全ケースで定義一致の変数 */\n shared: Record<string, VariableDefinition>;\n /** ケース間で定義が異なる変数 */\n conflicts: VariableConflict[];\n /** 特定ケースにのみ存在する変数 */\n caseSpecific: { caseName: string; name: string; def: VariableDefinition }[];\n}\n\nexport interface SettingsDiff {\n key: string;\n values: { caseName: string; value: unknown }[];\n}\n\nexport interface CompositionState {\n branchOn: string;\n cases: LoadedCase[];\n goal?: string;\n output: string;\n mergedVariables: Record<string, VariableDefinition>;\n settings: ParsedRunbook[\"settings\"];\n metadata: ParsedRunbook[\"metadata\"];\n title: string;\n}\n\n// ── 純粋関数 ──\n\n/**\n * 単一ケースの読み込み・バリデーション\n */\nexport async function loadCase(match: string, yamlPath: string): Promise<LoadedCase> {\n const raw = await readFile(yamlPath, \"utf-8\");\n const doc = parse(raw);\n const runbook = ParsedRunbookSchema.parse(doc);\n return { match, yamlPath, runbook };\n}\n\n/**\n * VariableDefinition を正規化して比較用にする。\n * Zod のデフォルト値(required: true, sensitive: false)を埋めた上でフィールド単位比較。\n */\nfunction normalizeVarDef(def: VariableDefinition): VariableDefinition {\n return {\n source: def.source,\n required: def.required ?? true,\n sensitive: def.sensitive ?? false,\n ...(def.description !== undefined ? { description: def.description } : {}),\n ...(def.value !== undefined ? { value: def.value } : {}),\n ...(def.expression !== undefined ? { expression: def.expression } : {}),\n ...(def.envKey !== undefined ? { envKey: def.envKey } : {}),\n };\n}\n\nfunction varDefsEqual(a: VariableDefinition, b: VariableDefinition): boolean {\n const na = normalizeVarDef(a);\n const nb = normalizeVarDef(b);\n return (\n na.source === nb.source &&\n na.required === nb.required &&\n na.sensitive === nb.sensitive &&\n na.description === nb.description &&\n na.value === nb.value &&\n na.expression === nb.expression &&\n na.envKey === nb.envKey\n );\n}\n\n/**\n * 変数を分析(共通/競合/ケース固有に分類)\n */\nexport function analyzeVariables(cases: LoadedCase[]): VariableMergeResult {\n // 各変数名がどのケースに定義されているか収集\n const varMap = new Map<string, { caseName: string; def: VariableDefinition }[]>();\n for (const lc of cases) {\n if (!lc.runbook.variables) continue;\n for (const [name, def] of Object.entries(lc.runbook.variables)) {\n const existing = varMap.get(name) ?? [];\n existing.push({ caseName: lc.match, def });\n varMap.set(name, existing);\n }\n }\n\n const shared: Record<string, VariableDefinition> = {};\n const conflicts: VariableConflict[] = [];\n const caseSpecific: { caseName: string; name: string; def: VariableDefinition }[] = [];\n\n for (const [name, entries] of varMap) {\n if (entries.length === 1) {\n // 1つのケースにのみ存在\n caseSpecific.push({ caseName: entries[0].caseName, name, def: entries[0].def });\n } else if (entries.length === cases.length) {\n // 全ケースに存在 → 定義が一致するか確認\n const allEqual = entries.every((e) => varDefsEqual(e.def, entries[0].def));\n if (allEqual) {\n shared[name] = entries[0].def;\n } else {\n conflicts.push({ name, definitions: entries });\n }\n } else {\n // 一部のケースにのみ存在(2ケース以上だが全ケースではない)\n // これも競合として扱う\n conflicts.push({ name, definitions: entries });\n }\n }\n\n return { shared, conflicts, caseSpecific };\n}\n\n/**\n * 競合解決マップ付きで変数をマージ。\n * resolutions: 競合変数名 → 採用する定義のマップ\n */\nexport function mergeVariables(\n analysis: VariableMergeResult,\n resolutions: Map<string, VariableDefinition>,\n branchOn: string,\n caseMatches: string[],\n): Record<string, VariableDefinition> {\n const merged: Record<string, VariableDefinition> = {};\n\n // 共通変数\n for (const [name, def] of Object.entries(analysis.shared)) {\n merged[name] = def;\n }\n\n // 競合変数(解決マップから採用)\n for (const conflict of analysis.conflicts) {\n const resolved = resolutions.get(conflict.name);\n if (resolved) {\n merged[conflict.name] = resolved;\n } else {\n // 解決がない場合は最初のケースの定義を使用\n merged[conflict.name] = conflict.definitions[0].def;\n }\n }\n\n // ケース固有変数\n for (const cs of analysis.caseSpecific) {\n merged[cs.name] = cs.def;\n }\n\n // 分岐変数を追加(まだ含まれていなければ)\n if (!(branchOn in merged)) {\n merged[branchOn] = {\n source: \"prompt\",\n description: `分岐条件 (${caseMatches.join(\", \")})`,\n required: true,\n sensitive: false,\n };\n }\n\n return merged;\n}\n\n/**\n * Settings の差分検出。全ケースで同じ値なら空配列。\n */\nexport function diffSettings(cases: LoadedCase[]): SettingsDiff[] {\n if (cases.length <= 1) return [];\n\n const diffs: SettingsDiff[] = [];\n const keys = [\"baseUrl\", \"defaultTimeout\", \"pauseBetweenSteps\", \"stopOnError\"] as const;\n\n for (const key of keys) {\n const values = cases.map((lc) => ({\n caseName: lc.match,\n value: lc.runbook.settings[key],\n }));\n\n const allSame = values.every((v) => v.value === values[0].value);\n if (!allSame) {\n diffs.push({ key, values });\n }\n }\n\n return diffs;\n}\n\n/**\n * 合成済み runbook オブジェクト構築(I/O なし)\n */\nexport function buildComposedRunbook(state: CompositionState): Record<string, unknown> {\n const base = state.cases[0].runbook;\n\n const branchStep = {\n ordinal: 0,\n description: state.goal ?? `${state.branchOn} に応じた分岐`,\n action: { type: \"memory\" },\n url: state.metadata.startUrl,\n riskLevel: \"low\",\n requiresConfirmation: false,\n branches: {\n value: `{{${state.branchOn}}}`,\n cases: state.cases.map((lc) => ({\n match: lc.match,\n steps: lc.runbook.steps.map((s, i) => ({\n ...s,\n ordinal: i,\n })),\n })),\n },\n };\n\n return {\n title: state.title,\n ...(base.naturalLanguageSummary ? { naturalLanguageSummary: base.naturalLanguageSummary } : {}),\n settings: state.settings,\n metadata: {\n ...state.metadata,\n totalSteps: 1,\n generatedAt: new Date().toISOString(),\n },\n steps: [branchStep],\n context: base.context ?? \"\",\n variables: state.mergedVariables,\n };\n}\n\n/**\n * Zod バリデーション + YAML 書き出し\n */\nexport async function validateAndWriteYaml(\n composed: Record<string, unknown>,\n outputPath: string,\n): Promise<string> {\n ParsedRunbookSchema.parse(composed);\n const yamlContent = stringify(composed, { lineWidth: 120 });\n await writeFile(outputPath, yamlContent, \"utf-8\");\n return outputPath;\n}\n\n/**\n * 変数定義の表示文字列を生成\n */\nexport function formatVariableDef(def: VariableDefinition): string {\n const parts = [`source: ${def.source}`];\n if (def.value !== undefined) parts.push(`value: \"${def.value}\"`);\n if (def.envKey !== undefined) parts.push(`envKey: ${def.envKey}`);\n if (def.expression !== undefined) parts.push(`expression: ${def.expression}`);\n return parts.join(\", \");\n}\n","/**\n * compose/interactive — 対話ロジック(収集・競合解決・プレビュー・編集ループ)\n *\n * composer.ts の純粋関数を呼び出しつつ、@clack/prompts でユーザーと対話する。\n */\n\nimport { t, tf } from \"../i18n\";\nimport { log, note, promptConfirm, promptSelect, promptText } from \"../cli/prompts\";\nimport type {\n CompositionState,\n LoadedCase,\n VariableConflict,\n VariableDefinition,\n VariableMergeResult,\n SettingsDiff,\n ParsedRunbook,\n} from \"./composer\";\nimport { loadCase, formatVariableDef, analyzeVariables, mergeVariables, diffSettings } from \"./composer\";\n\n// ── Phase 1: 入力収集 ──\n\n/**\n * 分岐変数名をプロンプトで取得\n */\nexport async function gatherBranchVariable(): Promise<string> {\n return promptText(t(\"compose.branchVarPrompt\"), {\n validate: (v) => (!v?.trim() ? t(\"compose.branchVarPrompt\") : undefined),\n });\n}\n\n/**\n * 対話的にケースを1つずつ追加\n */\nexport async function gatherCasesInteractively(): Promise<LoadedCase[]> {\n const cases: LoadedCase[] = [];\n\n // 最低2ケース必要\n while (cases.length < 2 || (await promptConfirm(t(\"compose.addAnotherCase\"), false))) {\n const yamlPath = await promptText(t(\"compose.yamlPathPrompt\"), {\n validate: (v) => (!v?.trim() ? t(\"compose.yamlPathPrompt\") : undefined),\n });\n const match = await promptText(t(\"compose.matchValuePrompt\"), {\n validate: (v) => (!v?.trim() ? t(\"compose.matchValuePrompt\") : undefined),\n });\n\n const loaded = await loadCase(match, yamlPath);\n const varCount = loaded.runbook.variables\n ? Object.keys(loaded.runbook.variables).length\n : 0;\n log.success(\n tf(\"compose.caseLoaded\", {\n title: loaded.runbook.title,\n steps: loaded.runbook.steps.length,\n vars: varCount,\n }),\n );\n cases.push(loaded);\n }\n\n return cases;\n}\n\n/**\n * CLI 引数で指定されたケースを一括ロード\n */\nexport async function loadProvidedCases(\n caseDefs: { match: string; yamlPath: string }[],\n): Promise<LoadedCase[]> {\n const cases: LoadedCase[] = [];\n for (const c of caseDefs) {\n const loaded = await loadCase(c.match, c.yamlPath);\n const varCount = loaded.runbook.variables\n ? Object.keys(loaded.runbook.variables).length\n : 0;\n log.success(\n tf(\"compose.caseLoaded\", {\n title: loaded.runbook.title,\n steps: loaded.runbook.steps.length,\n vars: varCount,\n }),\n );\n cases.push(loaded);\n }\n return cases;\n}\n\n/**\n * ゴールをプロンプトで取得\n */\nexport async function gatherGoal(defaultGoal?: string): Promise<string | undefined> {\n const goal = await promptText(t(\"compose.goalPrompt\"), {\n initialValue: defaultGoal,\n placeholder: defaultGoal,\n });\n return goal.trim() || undefined;\n}\n\n// ── Phase 2: 変数競合解決 ──\n\n/**\n * 変数マージプレビューを表示\n */\nexport function displayVariableMergePreview(\n analysis: VariableMergeResult,\n branchOn: string,\n): void {\n const lines: string[] = [];\n\n // 共通変数\n const sharedEntries = Object.entries(analysis.shared);\n if (sharedEntries.length > 0) {\n lines.push(t(\"compose.sharedVariables\"));\n for (const [name, def] of sharedEntries) {\n lines.push(` ${name} → ${formatVariableDef(def)}`);\n }\n lines.push(\"\");\n }\n\n // 競合変数\n if (analysis.conflicts.length > 0) {\n lines.push(t(\"compose.conflictingVariables\"));\n for (const conflict of analysis.conflicts) {\n lines.push(` ${conflict.name}`);\n for (const d of conflict.definitions) {\n lines.push(` [${d.caseName}] ${formatVariableDef(d.def)}`);\n }\n }\n lines.push(\"\");\n }\n\n // ケース固有変数\n if (analysis.caseSpecific.length > 0) {\n lines.push(t(\"compose.caseSpecificVariables\"));\n for (const cs of analysis.caseSpecific) {\n lines.push(` [${cs.caseName}] ${cs.name} → ${formatVariableDef(cs.def)}`);\n }\n lines.push(\"\");\n }\n\n // 分岐変数\n lines.push(t(\"compose.branchVariable\"));\n lines.push(` ${branchOn} → source: prompt`);\n\n note(lines.join(\"\\n\"), t(\"compose.variableMergePreview\"));\n}\n\n/**\n * 競合変数の解決をユーザーに問う\n */\nexport async function resolveVariableConflicts(\n analysis: VariableMergeResult,\n): Promise<Map<string, VariableDefinition>> {\n const resolutions = new Map<string, VariableDefinition>();\n\n for (const conflict of analysis.conflicts) {\n const options = conflict.definitions.map((d) => ({\n value: d.caseName,\n label: tf(\"compose.useFromCase\", { case: d.caseName }),\n hint: formatVariableDef(d.def),\n }));\n\n const chosen = await promptSelect(\n tf(\"compose.conflictPrompt\", { name: conflict.name }),\n options,\n );\n\n const selected = conflict.definitions.find((d) => d.caseName === chosen);\n if (selected) {\n resolutions.set(conflict.name, selected.def);\n }\n }\n\n return resolutions;\n}\n\n// ── Phase 3: Settings 解決 ──\n\n/**\n * Settings の差分をユーザーに問う\n */\nexport async function resolveSettings(\n diffs: SettingsDiff[],\n cases: LoadedCase[],\n baseSettings: ParsedRunbook[\"settings\"],\n): Promise<ParsedRunbook[\"settings\"]> {\n const settings = { ...baseSettings };\n\n for (const diff of diffs) {\n const options = diff.values.map((v) => ({\n value: v.caseName,\n label: tf(\"compose.useFromCase\", { case: v.caseName }),\n hint: `${diff.key} = ${JSON.stringify(v.value)}`,\n }));\n\n const chosen = await promptSelect(\n tf(\"compose.settingsDiffPrompt\", { key: diff.key }),\n options,\n );\n\n const selectedCase = cases.find((c) => c.match === chosen);\n if (selectedCase) {\n (settings as Record<string, unknown>)[diff.key] =\n selectedCase.runbook.settings[diff.key as keyof typeof settings];\n }\n }\n\n return settings;\n}\n\n// ── Phase 4: プレビュー + 編集ループ ──\n\n/**\n * 合成結果のプレビューを表示\n */\nfunction displayPreview(state: CompositionState): void {\n const lines: string[] = [];\n lines.push(`Title: ${state.title}`);\n lines.push(`Branch: {{${state.branchOn}}}`);\n lines.push(\n `Cases: ${state.cases.map((c) => `${c.match} (${c.runbook.steps.length} steps)`).join(\", \")}`,\n );\n lines.push(\"\");\n\n const varEntries = Object.entries(state.mergedVariables);\n lines.push(`Variables (${varEntries.length}):`);\n for (const [name, def] of varEntries) {\n const isBranch = name === state.branchOn ? \" (branch)\" : \"\";\n lines.push(` ${name} → ${formatVariableDef(def)}${isBranch}`);\n }\n lines.push(\"\");\n\n lines.push(\"Settings:\");\n lines.push(` baseUrl: ${state.settings.baseUrl}`);\n lines.push(` defaultTimeout: ${state.settings.defaultTimeout}`);\n\n note(lines.join(\"\\n\"), t(\"compose.composedPreview\"));\n}\n\ntype EditAction = \"confirm\" | \"editBranch\" | \"editMatches\" | \"editVariables\" | \"editTitle\";\n\n/**\n * 編集ループ — ユーザーが「確定」を選ぶまで繰り返す\n */\nexport async function editLoop(state: CompositionState): Promise<void> {\n while (true) {\n displayPreview(state);\n\n const action = await promptSelect<EditAction>(t(\"compose.selectAction\"), [\n { value: \"confirm\", label: t(\"compose.confirm\"), hint: t(\"compose.confirmHint\") },\n { value: \"editBranch\", label: t(\"compose.editBranch\") },\n { value: \"editMatches\", label: t(\"compose.editMatches\") },\n { value: \"editVariables\", label: t(\"compose.editVariables\") },\n { value: \"editTitle\", label: t(\"compose.editTitle\") },\n ]);\n\n if (action === \"confirm\") break;\n\n switch (action) {\n case \"editBranch\":\n await handleEditBranch(state);\n break;\n case \"editMatches\":\n await handleEditMatches(state);\n break;\n case \"editVariables\":\n await handleEditVariables(state);\n break;\n case \"editTitle\":\n await handleEditTitle(state);\n break;\n }\n }\n}\n\nasync function handleEditBranch(state: CompositionState): Promise<void> {\n const oldBranch = state.branchOn;\n const newBranch = await promptText(t(\"compose.newBranchVar\"), {\n initialValue: oldBranch,\n validate: (v) => (!v?.trim() ? t(\"compose.branchVarPrompt\") : undefined),\n });\n\n if (newBranch !== oldBranch) {\n // mergedVariables のキーを付け替え\n const branchDef = state.mergedVariables[oldBranch];\n if (branchDef) {\n delete state.mergedVariables[oldBranch];\n state.mergedVariables[newBranch] = branchDef;\n }\n state.branchOn = newBranch;\n }\n}\n\nasync function handleEditMatches(state: CompositionState): Promise<void> {\n const options = state.cases.map((c) => ({\n value: c.match,\n label: c.match,\n hint: c.runbook.title,\n }));\n\n const selected = await promptSelect(t(\"compose.selectCase\"), options);\n const caseObj = state.cases.find((c) => c.match === selected);\n if (!caseObj) return;\n\n const newMatch = await promptText(t(\"compose.newMatchValue\"), {\n initialValue: caseObj.match,\n validate: (v) => (!v?.trim() ? t(\"compose.matchValuePrompt\") : undefined),\n });\n caseObj.match = newMatch;\n\n // 分岐変数の description を更新\n const branchDef = state.mergedVariables[state.branchOn];\n if (branchDef) {\n branchDef.description = `分岐条件 (${state.cases.map((c) => c.match).join(\", \")})`;\n }\n}\n\ntype VarAction = \"delete\" | \"add\" | \"edit\";\n\nasync function handleEditVariables(state: CompositionState): Promise<void> {\n const action = await promptSelect<VarAction>(t(\"compose.editVarAction\"), [\n { value: \"delete\", label: t(\"compose.deleteVar\") },\n { value: \"add\", label: t(\"compose.addVar\") },\n { value: \"edit\", label: t(\"compose.editVarDef\") },\n ]);\n\n const varNames = Object.keys(state.mergedVariables).filter((n) => n !== state.branchOn);\n\n switch (action) {\n case \"delete\": {\n if (varNames.length === 0) return;\n const toDelete = await promptSelect(\n t(\"compose.selectVar\"),\n varNames.map((n) => ({\n value: n,\n label: n,\n hint: formatVariableDef(state.mergedVariables[n]),\n })),\n );\n delete state.mergedVariables[toDelete];\n log.success(tf(\"compose.varDeleted\", { name: toDelete }));\n break;\n }\n case \"add\": {\n const name = await promptText(t(\"compose.newVarName\"), {\n validate: (v) => {\n if (!v?.trim()) return t(\"compose.newVarName\");\n if (v.trim() === state.branchOn)\n return tf(\"compose.branchVarConflict\", { name: v.trim() });\n return undefined;\n },\n });\n const source = await promptSelect(t(\"compose.newVarSource\"), [\n { value: \"prompt\", label: \"prompt\" },\n { value: \"fixed\", label: \"fixed\" },\n { value: \"env\", label: \"env\" },\n { value: \"context\", label: \"context\" },\n { value: \"expression\", label: \"expression\" },\n { value: \"data\", label: \"data\" },\n ]);\n const value = await promptText(t(\"compose.newVarValue\"));\n const description = await promptText(t(\"compose.newVarDescription\"));\n state.mergedVariables[name] = {\n source: source as VariableDefinition[\"source\"],\n required: true,\n sensitive: false,\n ...(value.trim() ? { value: value.trim() } : {}),\n ...(description.trim() ? { description: description.trim() } : {}),\n };\n log.success(tf(\"compose.varAdded\", { name }));\n break;\n }\n case \"edit\": {\n if (varNames.length === 0) return;\n const toEdit = await promptSelect(\n t(\"compose.selectVar\"),\n varNames.map((n) => ({\n value: n,\n label: n,\n hint: formatVariableDef(state.mergedVariables[n]),\n })),\n );\n const currentDef = state.mergedVariables[toEdit];\n const newSource = await promptSelect(t(\"compose.newVarSource\"), [\n { value: \"prompt\", label: \"prompt\" },\n { value: \"fixed\", label: \"fixed\" },\n { value: \"env\", label: \"env\" },\n { value: \"context\", label: \"context\" },\n { value: \"expression\", label: \"expression\" },\n { value: \"data\", label: \"data\" },\n ]);\n const newValue = await promptText(t(\"compose.newVarValue\"), {\n initialValue: currentDef.value ?? \"\",\n });\n const newDesc = await promptText(t(\"compose.newVarDescription\"), {\n initialValue: currentDef.description ?? \"\",\n });\n state.mergedVariables[toEdit] = {\n source: newSource as VariableDefinition[\"source\"],\n required: currentDef.required,\n sensitive: currentDef.sensitive,\n ...(newValue.trim() ? { value: newValue.trim() } : {}),\n ...(newDesc.trim() ? { description: newDesc.trim() } : {}),\n };\n log.success(tf(\"compose.varUpdated\", { name: toEdit }));\n break;\n }\n }\n}\n\nasync function handleEditTitle(state: CompositionState): Promise<void> {\n const newTitle = await promptText(t(\"compose.newTitle\"), {\n initialValue: state.title,\n validate: (v) => (!v?.trim() ? t(\"compose.newTitle\") : undefined),\n });\n state.title = newTitle;\n state.goal = newTitle;\n state.metadata = { ...state.metadata, goal: newTitle };\n}\n\n// ── ヘルパー: 状態構築の再利用 ──\n\n/**\n * 変数分析・競合解決・Settings 解決を経て CompositionState を構築する\n */\nexport async function buildState(opts: {\n branchOn: string;\n cases: LoadedCase[];\n goal?: string;\n output: string;\n}): Promise<CompositionState> {\n const { branchOn, cases, goal, output } = opts;\n\n // 変数分析\n const varAnalysis = analyzeVariables(cases);\n displayVariableMergePreview(varAnalysis, branchOn);\n const resolutions = await resolveVariableConflicts(varAnalysis);\n\n // Settings 解決\n const settingsDiffs = diffSettings(cases);\n const settings = await resolveSettings(settingsDiffs, cases, cases[0].runbook.settings);\n\n const mergedVars = mergeVariables(\n varAnalysis,\n resolutions,\n branchOn,\n cases.map((c) => c.match),\n );\n\n const title = goal ?? cases[0].runbook.title;\n\n return {\n branchOn,\n cases,\n goal,\n output,\n mergedVariables: mergedVars,\n settings,\n metadata: {\n ...cases[0].runbook.metadata,\n goal: goal ?? cases[0].runbook.metadata.goal,\n },\n title,\n };\n}\n","/**\n * compose CLI エントリポイント\n *\n * 複数の生成済み手順書を1つの分岐付き手順書に対話的に合成する。\n * CLI 引数はプリフィルとして使用し、未指定分はプロンプトで収集。\n */\n\nimport { initLocale, t, tf } from \"../i18n\";\nimport { intro, outro } from \"../cli/prompts\";\nimport { parseComposeArgs } from \"./config\";\nimport { buildComposedRunbook, validateAndWriteYaml } from \"./composer\";\nimport {\n gatherBranchVariable,\n gatherCasesInteractively,\n loadProvidedCases,\n gatherGoal,\n buildState,\n editLoop,\n} from \"./interactive\";\n\nconst config = parseComposeArgs();\ninitLocale(config.locale);\nintro(t(\"compose.title\"));\n\ntry {\n // Phase 1: 入力収集(CLI 引数はプリフィル)\n const branchOn = config.branchOn ?? (await gatherBranchVariable());\n const cases =\n config.cases.length > 0\n ? await loadProvidedCases(config.cases)\n : await gatherCasesInteractively();\n const goal = config.goal ?? (await gatherGoal(cases[0]?.runbook.title));\n\n // Phase 2 & 3: 変数競合解決 + Settings 解決\n const state = await buildState({ branchOn, cases, goal, output: config.output });\n\n // Phase 4: プレビュー + 編集ループ\n await editLoop(state);\n\n // Phase 5: 書き出し\n const composed = buildComposedRunbook(state);\n const outputPath = await validateAndWriteYaml(composed, config.output);\n outro(tf(\"compose.complete\", { path: outputPath }));\n} catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(`合成失敗: ${msg}`);\n process.exit(1);\n}\n"],"mappings":"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","names":[]}
|