@refrainai/cli 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/ai-model-FM6GWCID.js +37 -0
  2. package/dist/ai-model-FM6GWCID.js.map +1 -0
  3. package/dist/chunk-2BVDAJZT.js +236 -0
  4. package/dist/chunk-2BVDAJZT.js.map +1 -0
  5. package/dist/chunk-2H7UOFLK.js +11 -0
  6. package/dist/chunk-2H7UOFLK.js.map +1 -0
  7. package/dist/chunk-7UCVPKD4.js +902 -0
  8. package/dist/chunk-7UCVPKD4.js.map +1 -0
  9. package/dist/chunk-AG3CFMYU.js +36 -0
  10. package/dist/chunk-AG3CFMYU.js.map +1 -0
  11. package/dist/chunk-CLYJHKPY.js +1131 -0
  12. package/dist/chunk-CLYJHKPY.js.map +1 -0
  13. package/dist/chunk-D5SI2PHK.js +74 -0
  14. package/dist/chunk-D5SI2PHK.js.map +1 -0
  15. package/dist/chunk-DJVUITRB.js +9084 -0
  16. package/dist/chunk-DJVUITRB.js.map +1 -0
  17. package/dist/chunk-H47NWH7N.js +4427 -0
  18. package/dist/chunk-H47NWH7N.js.map +1 -0
  19. package/dist/chunk-HQDXLWAY.js +109 -0
  20. package/dist/chunk-HQDXLWAY.js.map +1 -0
  21. package/dist/chunk-IGFCYKHC.js +1974 -0
  22. package/dist/chunk-IGFCYKHC.js.map +1 -0
  23. package/dist/chunk-RT664YIO.js +245 -0
  24. package/dist/chunk-RT664YIO.js.map +1 -0
  25. package/dist/chunk-RYIJPYM3.js +164 -0
  26. package/dist/chunk-RYIJPYM3.js.map +1 -0
  27. package/dist/chunk-TDSM3UXI.js +40 -0
  28. package/dist/chunk-TDSM3UXI.js.map +1 -0
  29. package/dist/chunk-UGPXCQY3.js +778 -0
  30. package/dist/chunk-UGPXCQY3.js.map +1 -0
  31. package/dist/chunk-VPK2MQAZ.js +589 -0
  32. package/dist/chunk-VPK2MQAZ.js.map +1 -0
  33. package/dist/chunk-WEYR56ZN.js +953 -0
  34. package/dist/chunk-WEYR56ZN.js.map +1 -0
  35. package/dist/chunk-XMFCXPYU.js +275 -0
  36. package/dist/chunk-XMFCXPYU.js.map +1 -0
  37. package/dist/chunk-Z33FCOTZ.js +251 -0
  38. package/dist/chunk-Z33FCOTZ.js.map +1 -0
  39. package/dist/cli.js +59 -0
  40. package/dist/cli.js.map +1 -0
  41. package/dist/compose-MTSIJY5D.js +547 -0
  42. package/dist/compose-MTSIJY5D.js.map +1 -0
  43. package/dist/config-ZSUNCFXR.js +9 -0
  44. package/dist/config-ZSUNCFXR.js.map +1 -0
  45. package/dist/fix-runbook-ZSBOTLC2.js +294 -0
  46. package/dist/fix-runbook-ZSBOTLC2.js.map +1 -0
  47. package/dist/google-sheets-DRWIVEVC.js +482 -0
  48. package/dist/google-sheets-DRWIVEVC.js.map +1 -0
  49. package/dist/registry-LZLYTNDJ.js +17 -0
  50. package/dist/registry-LZLYTNDJ.js.map +1 -0
  51. package/dist/runbook-data-helpers-KRR2SH76.js +16 -0
  52. package/dist/runbook-data-helpers-KRR2SH76.js.map +1 -0
  53. package/dist/runbook-executor-K7T6RJWJ.js +1480 -0
  54. package/dist/runbook-executor-K7T6RJWJ.js.map +1 -0
  55. package/dist/runbook-generator-MPXJBQ5N.js +800 -0
  56. package/dist/runbook-generator-MPXJBQ5N.js.map +1 -0
  57. package/dist/runbook-schema-3T6TP3JJ.js +35 -0
  58. package/dist/runbook-schema-3T6TP3JJ.js.map +1 -0
  59. package/dist/runbook-store-G5GUOWRR.js +11 -0
  60. package/dist/runbook-store-G5GUOWRR.js.map +1 -0
  61. package/dist/schema-5G6UQSPT.js +91 -0
  62. package/dist/schema-5G6UQSPT.js.map +1 -0
  63. package/dist/server-AG3LXQBI.js +8778 -0
  64. package/dist/server-AG3LXQBI.js.map +1 -0
  65. package/dist/tenant-ai-config-QPFEJUVJ.js +14 -0
  66. package/dist/tenant-ai-config-QPFEJUVJ.js.map +1 -0
  67. package/dist/yaml-patcher-VGUS2JGH.js +15 -0
  68. package/dist/yaml-patcher-VGUS2JGH.js.map +1 -0
  69. package/package.json +37 -0
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ tenantModelOverrides,
4
+ tenantModelProviders
5
+ } from "./chunk-CLYJHKPY.js";
6
+
7
+ // src/server/inngest/helpers/tenant-ai-config.ts
8
+ import { eq } from "drizzle-orm";
9
+
10
+ // src/server/crypto.ts
11
+ import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
12
+ var ALGORITHM = "aes-256-gcm";
13
+ var IV_LENGTH = 12;
14
+ var AUTH_TAG_LENGTH = 16;
15
+ function encrypt(plaintext, key) {
16
+ const keyBuffer = Buffer.from(key, "hex");
17
+ if (keyBuffer.length !== 32) {
18
+ throw new Error("Encryption key must be 32 bytes (64 hex characters)");
19
+ }
20
+ const iv = randomBytes(IV_LENGTH);
21
+ const cipher = createCipheriv(ALGORITHM, keyBuffer, iv, {
22
+ authTagLength: AUTH_TAG_LENGTH
23
+ });
24
+ const encrypted = Buffer.concat([
25
+ cipher.update(plaintext, "utf8"),
26
+ cipher.final()
27
+ ]);
28
+ const authTag = cipher.getAuthTag();
29
+ return `${iv.toString("hex")}:${authTag.toString("hex")}:${encrypted.toString("hex")}`;
30
+ }
31
+ function decrypt(encrypted, key) {
32
+ const keyBuffer = Buffer.from(key, "hex");
33
+ if (keyBuffer.length !== 32) {
34
+ throw new Error("Encryption key must be 32 bytes (64 hex characters)");
35
+ }
36
+ const [ivHex, authTagHex, ciphertextHex] = encrypted.split(":");
37
+ if (!ivHex || !authTagHex || !ciphertextHex) {
38
+ throw new Error("Invalid encrypted format: expected iv:authTag:ciphertext");
39
+ }
40
+ const iv = Buffer.from(ivHex, "hex");
41
+ const authTag = Buffer.from(authTagHex, "hex");
42
+ const ciphertext = Buffer.from(ciphertextHex, "hex");
43
+ const decipher = createDecipheriv(ALGORITHM, keyBuffer, iv, {
44
+ authTagLength: AUTH_TAG_LENGTH
45
+ });
46
+ decipher.setAuthTag(authTag);
47
+ return Buffer.concat([
48
+ decipher.update(ciphertext),
49
+ decipher.final()
50
+ ]).toString("utf8");
51
+ }
52
+ function maskSensitiveValue(value) {
53
+ if (value.length <= 8) return "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
54
+ return `${value.slice(0, 4)}\u2022\u2022\u2022\u2022${value.slice(-4)}`;
55
+ }
56
+ function isMaskedValue(value) {
57
+ return value.includes("\u2022\u2022\u2022\u2022") || /^\*+$/.test(value);
58
+ }
59
+
60
+ // src/server/inngest/helpers/tenant-ai-config.ts
61
+ var ENCRYPTED_CONFIG_FIELDS = ["apiKey", "bedrockSecretAccessKey"];
62
+ async function resolveTenantAIConfig(db, tenantId, encryptionKey) {
63
+ const [provider] = await db.select().from(tenantModelProviders).where(eq(tenantModelProviders.tenantId, tenantId)).limit(1);
64
+ if (!provider) {
65
+ throw new Error(
66
+ `AI provider not configured for tenant ${tenantId}. Please configure an AI provider in Settings > AI Models.`
67
+ );
68
+ }
69
+ const overrides = await db.select().from(tenantModelOverrides).where(eq(tenantModelOverrides.tenantId, tenantId));
70
+ const modelOverrides = {};
71
+ for (const o of overrides) {
72
+ modelOverrides[o.purpose] = o.modelId;
73
+ }
74
+ const rawConfig = provider.config ?? {};
75
+ const config = { ...rawConfig };
76
+ for (const field of ENCRYPTED_CONFIG_FIELDS) {
77
+ const value = config[field];
78
+ if (value) {
79
+ try {
80
+ config[field] = decrypt(value, encryptionKey);
81
+ } catch {
82
+ }
83
+ }
84
+ }
85
+ return {
86
+ modelId: provider.modelId,
87
+ provider: provider.providerId,
88
+ apiKey: config.apiKey,
89
+ baseURL: config.baseURL,
90
+ bedrockRegion: config.bedrockRegion,
91
+ bedrockAccessKeyId: config.bedrockAccessKeyId,
92
+ bedrockSecretAccessKey: config.bedrockSecretAccessKey,
93
+ bedrockSessionToken: config.bedrockSessionToken,
94
+ vertexProject: config.vertexProject,
95
+ vertexLocation: config.vertexLocation,
96
+ azureResourceName: config.azureResourceName,
97
+ azureApiVersion: config.azureApiVersion,
98
+ modelOverrides: Object.keys(modelOverrides).length > 0 ? modelOverrides : void 0
99
+ };
100
+ }
101
+
102
+ export {
103
+ encrypt,
104
+ decrypt,
105
+ maskSensitiveValue,
106
+ isMaskedValue,
107
+ resolveTenantAIConfig
108
+ };
109
+ //# sourceMappingURL=chunk-HQDXLWAY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/inngest/helpers/tenant-ai-config.ts","../../../src/server/crypto.ts"],"sourcesContent":["/**\n * テナント別 AI モデル設定解決\n *\n * tenantModelProviders + tenantModelOverrides → AIModelConfig 構築。\n * 暗号化フィールドは decrypt() で復号。\n * プロバイダー未設定時はエラーをスロー(サイレントフォールバックしない)。\n */\n\nimport { eq } from \"drizzle-orm\";\nimport type { getDb } from \"../../db/client.js\";\nimport { tenantModelProviders, tenantModelOverrides } from \"../../db/schema.js\";\nimport { decrypt } from \"../../crypto.js\";\nimport type { AIModelConfig, ModelProvider, ModelPurpose } from \"../../../harness/ai-model.js\";\nimport { buildModelFactory } from \"../../../harness/ai-model.js\";\n\nexport { buildModelFactory };\n\ntype Db = ReturnType<typeof getDb>;\n\n/** 暗号化された provider config のフィールド */\nconst ENCRYPTED_CONFIG_FIELDS = [\"apiKey\", \"bedrockSecretAccessKey\"];\n\ninterface ProviderConfig {\n apiKey?: string;\n baseURL?: string;\n bedrockRegion?: string;\n bedrockAccessKeyId?: string;\n bedrockSecretAccessKey?: string;\n bedrockSessionToken?: string;\n vertexProject?: string;\n vertexLocation?: string;\n azureResourceName?: string;\n azureApiVersion?: string;\n}\n\n/**\n * DB からプロバイダーとオーバーライドを読み込み、AIModelConfig を構築する。\n * プロバイダー未設定時はエラーをスロー(サイレントフォールバックしない)。\n */\nexport async function resolveTenantAIConfig(\n db: Db,\n tenantId: string,\n encryptionKey: string,\n): Promise<AIModelConfig> {\n // プロバイダーを取得(connected 状態に関係なく使用)\n const [provider] = await db\n .select()\n .from(tenantModelProviders)\n .where(eq(tenantModelProviders.tenantId, tenantId))\n .limit(1);\n\n if (!provider) {\n throw new Error(\n `AI provider not configured for tenant ${tenantId}. Please configure an AI provider in Settings > AI Models.`,\n );\n }\n\n // オーバーライドを取得\n const overrides = await db\n .select()\n .from(tenantModelOverrides)\n .where(eq(tenantModelOverrides.tenantId, tenantId));\n\n const modelOverrides: Partial<Record<ModelPurpose, string>> = {};\n for (const o of overrides) {\n modelOverrides[o.purpose as ModelPurpose] = o.modelId;\n }\n\n // provider.config の暗号化フィールドを復号\n const rawConfig = (provider.config ?? {}) as ProviderConfig;\n const config: ProviderConfig = { ...rawConfig };\n for (const field of ENCRYPTED_CONFIG_FIELDS) {\n const value = config[field as keyof ProviderConfig] as string | undefined;\n if (value) {\n try {\n (config as Record<string, unknown>)[field] = decrypt(value, encryptionKey);\n } catch {\n // 復号失敗は無視(平文の可能性あり)\n }\n }\n }\n\n return {\n modelId: provider.modelId,\n provider: provider.providerId as ModelProvider,\n apiKey: config.apiKey,\n baseURL: config.baseURL,\n bedrockRegion: config.bedrockRegion,\n bedrockAccessKeyId: config.bedrockAccessKeyId,\n bedrockSecretAccessKey: config.bedrockSecretAccessKey,\n bedrockSessionToken: config.bedrockSessionToken,\n vertexProject: config.vertexProject,\n vertexLocation: config.vertexLocation,\n azureResourceName: config.azureResourceName,\n azureApiVersion: config.azureApiVersion,\n modelOverrides: Object.keys(modelOverrides).length > 0 ? modelOverrides : undefined,\n };\n}\n\n","/**\n * AES-256-GCM 暗号化/復号ユーティリティ\n */\n\nimport { createCipheriv, createDecipheriv, randomBytes } from \"node:crypto\";\n\nconst ALGORITHM = \"aes-256-gcm\";\nconst IV_LENGTH = 12;\nconst AUTH_TAG_LENGTH = 16;\n\n/**\n * AES-256-GCM で暗号化し、`iv:authTag:ciphertext` 形式の hex 文字列を返す\n */\nexport function encrypt(plaintext: string, key: string): string {\n const keyBuffer = Buffer.from(key, \"hex\");\n if (keyBuffer.length !== 32) {\n throw new Error(\"Encryption key must be 32 bytes (64 hex characters)\");\n }\n\n const iv = randomBytes(IV_LENGTH);\n const cipher = createCipheriv(ALGORITHM, keyBuffer, iv, {\n authTagLength: AUTH_TAG_LENGTH,\n });\n\n const encrypted = Buffer.concat([\n cipher.update(plaintext, \"utf8\"),\n cipher.final(),\n ]);\n const authTag = cipher.getAuthTag();\n\n return `${iv.toString(\"hex\")}:${authTag.toString(\"hex\")}:${encrypted.toString(\"hex\")}`;\n}\n\n/**\n * `iv:authTag:ciphertext` 形式の hex 文字列を復号\n */\nexport function decrypt(encrypted: string, key: string): string {\n const keyBuffer = Buffer.from(key, \"hex\");\n if (keyBuffer.length !== 32) {\n throw new Error(\"Encryption key must be 32 bytes (64 hex characters)\");\n }\n\n const [ivHex, authTagHex, ciphertextHex] = encrypted.split(\":\");\n if (!ivHex || !authTagHex || !ciphertextHex) {\n throw new Error(\"Invalid encrypted format: expected iv:authTag:ciphertext\");\n }\n\n const iv = Buffer.from(ivHex, \"hex\");\n const authTag = Buffer.from(authTagHex, \"hex\");\n const ciphertext = Buffer.from(ciphertextHex, \"hex\");\n\n const decipher = createDecipheriv(ALGORITHM, keyBuffer, iv, {\n authTagLength: AUTH_TAG_LENGTH,\n });\n decipher.setAuthTag(authTag);\n\n return Buffer.concat([\n decipher.update(ciphertext),\n decipher.final(),\n ]).toString(\"utf8\");\n}\n\n/**\n * 表示用マスク: 先頭4文字 + `••••` + 末尾4文字\n */\nexport function maskSensitiveValue(value: string): string {\n if (value.length <= 8) return \"••••••••\";\n return `${value.slice(0, 4)}••••${value.slice(-4)}`;\n}\n\n/**\n * マスク値かどうかを判定。\n * Web UI は `***`、CLI/将来実装は `••••` 系を返しうるため両方を受け入れる。\n */\nexport function isMaskedValue(value: string): boolean {\n return value.includes(\"••••\") || /^\\*+$/.test(value);\n}\n"],"mappings":"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","names":[]}