@kalphq/cli 0.0.0-dev-20260513014949 → 0.0.0-dev-20260513152102
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/{add-CTF5QIGY.js → add-YZSIMRPC.js} +6 -5
- package/dist/{add-CTF5QIGY.js.map → add-YZSIMRPC.js.map} +1 -1
- package/dist/{agents-NN2FLBZM.js → agents-WYK6WNQP.js} +3 -3
- package/dist/{chunk-TPG7QMXB.js → chunk-4CEJYSJY.js} +11 -9
- package/dist/{chunk-TPG7QMXB.js.map → chunk-4CEJYSJY.js.map} +1 -1
- package/dist/chunk-EXXTCGKR.js +77 -0
- package/dist/chunk-EXXTCGKR.js.map +1 -0
- package/dist/{chunk-FP3ZLBYT.js → chunk-IZXCZ3IA.js} +2 -2
- package/dist/chunk-LPEV4QH2.js +208 -0
- package/dist/chunk-LPEV4QH2.js.map +1 -0
- package/dist/{chunk-DHCCSWJN.js → chunk-XVD3FFOJ.js} +37 -104
- package/dist/chunk-XVD3FFOJ.js.map +1 -0
- package/dist/{chunk-EHNC6ITP.js → chunk-YE2SFYAJ.js} +10 -1
- package/dist/chunk-YE2SFYAJ.js.map +1 -0
- package/dist/{create-XC55BUCS.js → create-UCJ77P62.js} +6 -1
- package/dist/create-UCJ77P62.js.map +1 -0
- package/dist/{delete-BQFFYYWZ.js → delete-FIXMFFNZ.js} +6 -5
- package/dist/{delete-BQFFYYWZ.js.map → delete-FIXMFFNZ.js.map} +1 -1
- package/dist/{delete-LW2G4GCN.js → delete-QPYVL4OU.js} +7 -6
- package/dist/{delete-LW2G4GCN.js.map → delete-QPYVL4OU.js.map} +1 -1
- package/dist/{deploy-2JMOUTWG.js → deploy-DRZZ3YRB.js} +8 -3
- package/dist/deploy-DRZZ3YRB.js.map +1 -0
- package/dist/{dev-X43HHIYV.js → dev-5YY6W4WM.js} +7 -2
- package/dist/dev-5YY6W4WM.js.map +1 -0
- package/dist/generate-JW2DMJ3W.js +391 -0
- package/dist/generate-JW2DMJ3W.js.map +1 -0
- package/dist/index.js +10 -7
- package/dist/index.js.map +1 -1
- package/dist/{list-5RQZ3JVG.js → list-FKH4DWCF.js} +4 -3
- package/dist/{list-5RQZ3JVG.js.map → list-FKH4DWCF.js.map} +1 -1
- package/dist/{list-JXR4IULK.js → list-GZBBOFX5.js} +29 -9
- package/dist/list-GZBBOFX5.js.map +1 -0
- package/dist/mcp-DRMQYA7E.js +39 -0
- package/dist/mcp-DRMQYA7E.js.map +1 -0
- package/dist/pull-V7QJBVNZ.js +83 -0
- package/dist/pull-V7QJBVNZ.js.map +1 -0
- package/dist/{push-WHPQXAY7.js → push-P6CKRYT7.js} +13 -8
- package/dist/push-P6CKRYT7.js.map +1 -0
- package/dist/{secrets-Z53FLH56.js → secrets-M43LLCTB.js} +9 -5
- package/dist/secrets-M43LLCTB.js.map +1 -0
- package/dist/{sync-RPXLLOTK.js → sync-LTBH6DI5.js} +19 -7
- package/dist/sync-LTBH6DI5.js.map +1 -0
- package/package.json +5 -4
- package/dist/chunk-DHCCSWJN.js.map +0 -1
- package/dist/chunk-EHNC6ITP.js.map +0 -1
- package/dist/chunk-MMS3GWBG.js +0 -50
- package/dist/chunk-MMS3GWBG.js.map +0 -1
- package/dist/create-XC55BUCS.js.map +0 -1
- package/dist/deploy-2JMOUTWG.js.map +0 -1
- package/dist/dev-X43HHIYV.js.map +0 -1
- package/dist/list-JXR4IULK.js.map +0 -1
- package/dist/push-WHPQXAY7.js.map +0 -1
- package/dist/secrets-Z53FLH56.js.map +0 -1
- package/dist/sync-RPXLLOTK.js.map +0 -1
- /package/dist/{agents-NN2FLBZM.js.map → agents-WYK6WNQP.js.map} +0 -0
- /package/dist/{chunk-FP3ZLBYT.js.map → chunk-IZXCZ3IA.js.map} +0 -0
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
generateTypes
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LPEV4QH2.js";
|
|
5
5
|
import {
|
|
6
6
|
mergeSecrets,
|
|
7
7
|
readLocalSecretsFromConfig,
|
|
8
8
|
writeLocalSecretsToConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-YE2SFYAJ.js";
|
|
10
10
|
import {
|
|
11
11
|
resolveSecretsRuntimeConfigPath
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-IZXCZ3IA.js";
|
|
13
13
|
import "./chunk-INB3LG6O.js";
|
|
14
|
+
import "./chunk-XVD3FFOJ.js";
|
|
14
15
|
import {
|
|
15
16
|
requireAuth,
|
|
16
17
|
resolveProvider
|
|
17
18
|
} from "./chunk-S3KAVLVM.js";
|
|
18
19
|
import "./chunk-FO24J6XL.js";
|
|
19
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-EXXTCGKR.js";
|
|
20
21
|
|
|
21
22
|
// src/commands/secrets/add.ts
|
|
22
23
|
import { defineCommand } from "citty";
|
|
@@ -123,4 +124,4 @@ var add_default = defineCommand({
|
|
|
123
124
|
export {
|
|
124
125
|
add_default as default
|
|
125
126
|
};
|
|
126
|
-
//# sourceMappingURL=add-
|
|
127
|
+
//# sourceMappingURL=add-YZSIMRPC.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/secrets/add.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { requireAuth } from \"@/utils/auth\";\nimport { generateTypes } from \"@/utils/codegen\";\nimport { resolveProvider } from \"@/utils/providers\";\nimport {\n mergeSecrets,\n readLocalSecretsFromConfig,\n writeLocalSecretsToConfig,\n} from \"@/utils/secrets-config\";\nimport { resolveSecretsRuntimeConfigPath } from \"@/utils/secrets-runtime\";\n\nconst LOGO = \"🦋\";\n\nexport default defineCommand({\n meta: {\n name: \"add\",\n description: \"Add a secret to remote runtime and local config\",\n },\n args: {\n key: {\n type: \"string\",\n alias: \"k\",\n description: \"Secret key (UPPER_SNAKE_CASE)\",\n },\n value: {\n type: \"string\",\n alias: \"v\",\n description: \"Secret value\",\n },\n help: {\n type: \"boolean\",\n alias: \"h\",\n description: \"Show help\",\n default: false,\n },\n },\n async run({ args }) {\n const cwd = process.cwd();\n\n if (args.help) {\n p.log.info(`${pc.bold(\"Usage\")}: kalp secrets add -k <KEY> -v <VALUE>`);\n return;\n }\n\n p.intro(`${LOGO} ${pc.bold(\"kalp secrets add\")}`);\n\n await requireAuth().catch(() => {\n p.log.error(\"Not authenticated. Run `kalp login` first.\");\n process.exit(1);\n });\n\n let key = args.key?.trim();\n let value = args.value;\n\n if (!key) {\n const input = await p.text({\n message: \"Secret key name\",\n placeholder: \"STRIPE_SECRET_KEY\",\n validate: (v) => {\n if (!v) return \"Key is required\";\n if (!/^[A-Z_][A-Z0-9_]*$/.test(v)) {\n return \"Key must be UPPER_SNAKE_CASE\";\n }\n },\n });\n if (p.isCancel(input)) {\n p.outro(\"Cancelled\");\n return;\n }\n key = String(input).trim();\n }\n\n if (!/^[A-Z_][A-Z0-9_]*$/.test(key)) {\n p.log.error(\"Invalid key. Use UPPER_SNAKE_CASE.\");\n process.exit(1);\n }\n\n if (!value) {\n const input = await p.password({\n message: `Enter value for ${key}`,\n mask: \"*\",\n });\n if (p.isCancel(input)) {\n p.outro(\"Cancelled\");\n return;\n }\n value = String(input);\n }\n\n const trimmedValue = value.trim();\n if (!trimmedValue) {\n p.log.error(\"Secret value cannot be empty.\");\n process.exit(1);\n }\n\n const spinner = p.spinner();\n spinner.start(`Adding ${pc.cyan(key)} to remote runtime`);\n\n try {\n const configPath = await resolveSecretsRuntimeConfigPath(cwd);\n const provider = resolveProvider();\n await provider.putSecret({\n cwd,\n configPath,\n name: key,\n value: trimmedValue,\n });\n\n const localSecrets = await readLocalSecretsFromConfig(cwd);\n const merged = mergeSecrets(localSecrets, [key]);\n await writeLocalSecretsToConfig(cwd, merged);\n await generateTypes(cwd);\n\n spinner.stop(`Secret ${pc.cyan(key)} added`);\n p.outro(\"Done\");\n } catch (error) {\n spinner.stop(\"Failed to add secret\");\n p.log.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n },\n});\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/commands/secrets/add.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { requireAuth } from \"@/utils/auth\";\nimport { generateTypes } from \"@/utils/codegen\";\nimport { resolveProvider } from \"@/utils/providers\";\nimport {\n mergeSecrets,\n readLocalSecretsFromConfig,\n writeLocalSecretsToConfig,\n} from \"@/utils/secrets-config\";\nimport { resolveSecretsRuntimeConfigPath } from \"@/utils/secrets-runtime\";\n\nconst LOGO = \"🦋\";\n\nexport default defineCommand({\n meta: {\n name: \"add\",\n description: \"Add a secret to remote runtime and local config\",\n },\n args: {\n key: {\n type: \"string\",\n alias: \"k\",\n description: \"Secret key (UPPER_SNAKE_CASE)\",\n },\n value: {\n type: \"string\",\n alias: \"v\",\n description: \"Secret value\",\n },\n help: {\n type: \"boolean\",\n alias: \"h\",\n description: \"Show help\",\n default: false,\n },\n },\n async run({ args }) {\n const cwd = process.cwd();\n\n if (args.help) {\n p.log.info(`${pc.bold(\"Usage\")}: kalp secrets add -k <KEY> -v <VALUE>`);\n return;\n }\n\n p.intro(`${LOGO} ${pc.bold(\"kalp secrets add\")}`);\n\n await requireAuth().catch(() => {\n p.log.error(\"Not authenticated. Run `kalp login` first.\");\n process.exit(1);\n });\n\n let key = args.key?.trim();\n let value = args.value;\n\n if (!key) {\n const input = await p.text({\n message: \"Secret key name\",\n placeholder: \"STRIPE_SECRET_KEY\",\n validate: (v) => {\n if (!v) return \"Key is required\";\n if (!/^[A-Z_][A-Z0-9_]*$/.test(v)) {\n return \"Key must be UPPER_SNAKE_CASE\";\n }\n },\n });\n if (p.isCancel(input)) {\n p.outro(\"Cancelled\");\n return;\n }\n key = String(input).trim();\n }\n\n if (!/^[A-Z_][A-Z0-9_]*$/.test(key)) {\n p.log.error(\"Invalid key. Use UPPER_SNAKE_CASE.\");\n process.exit(1);\n }\n\n if (!value) {\n const input = await p.password({\n message: `Enter value for ${key}`,\n mask: \"*\",\n });\n if (p.isCancel(input)) {\n p.outro(\"Cancelled\");\n return;\n }\n value = String(input);\n }\n\n const trimmedValue = value.trim();\n if (!trimmedValue) {\n p.log.error(\"Secret value cannot be empty.\");\n process.exit(1);\n }\n\n const spinner = p.spinner();\n spinner.start(`Adding ${pc.cyan(key)} to remote runtime`);\n\n try {\n const configPath = await resolveSecretsRuntimeConfigPath(cwd);\n const provider = resolveProvider();\n await provider.putSecret({\n cwd,\n configPath,\n name: key,\n value: trimmedValue,\n });\n\n const localSecrets = await readLocalSecretsFromConfig(cwd);\n const merged = mergeSecrets(localSecrets, [key]);\n await writeLocalSecretsToConfig(cwd, merged);\n await generateTypes(cwd);\n\n spinner.stop(`Secret ${pc.cyan(key)} added`);\n p.outro(\"Done\");\n } catch (error) {\n spinner.stop(\"Failed to add secret\");\n p.log.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n },\n});\n"],"mappings":"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","names":["spinner"]}
|
|
@@ -19,8 +19,8 @@ var agents_default = defineCommand({
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
subCommands: {
|
|
22
|
-
list: () => import("./list-
|
|
23
|
-
delete: () => import("./delete-
|
|
22
|
+
list: () => import("./list-FKH4DWCF.js").then((r) => r.default),
|
|
23
|
+
delete: () => import("./delete-QPYVL4OU.js").then((r) => r.default)
|
|
24
24
|
},
|
|
25
25
|
run({ args }) {
|
|
26
26
|
const subcommand = process.argv[3];
|
|
@@ -40,4 +40,4 @@ var agents_default = defineCommand({
|
|
|
40
40
|
export {
|
|
41
41
|
agents_default as default
|
|
42
42
|
};
|
|
43
|
-
//# sourceMappingURL=agents-
|
|
43
|
+
//# sourceMappingURL=agents-WYK6WNQP.js.map
|
|
@@ -2,21 +2,23 @@
|
|
|
2
2
|
import {
|
|
3
3
|
ensureStudioSecrets
|
|
4
4
|
} from "./chunk-NV2IZ4XM.js";
|
|
5
|
-
import {
|
|
6
|
-
requireAuth,
|
|
7
|
-
resolveProvider
|
|
8
|
-
} from "./chunk-S3KAVLVM.js";
|
|
9
5
|
import {
|
|
10
6
|
getRequiredSecretForProvider,
|
|
11
|
-
loadProjectConfig,
|
|
12
7
|
materializeRuntime,
|
|
13
8
|
readDotEnv,
|
|
14
9
|
readProjectState,
|
|
15
|
-
resolveIdentityAuthRequirements,
|
|
16
10
|
resolveProviderFromConfig,
|
|
17
|
-
resolveRuntimeIdentityConfig,
|
|
18
11
|
writeProjectState
|
|
19
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-XVD3FFOJ.js";
|
|
13
|
+
import {
|
|
14
|
+
requireAuth,
|
|
15
|
+
resolveProvider
|
|
16
|
+
} from "./chunk-S3KAVLVM.js";
|
|
17
|
+
import {
|
|
18
|
+
loadProjectConfig,
|
|
19
|
+
resolveIdentityAuthRequirements,
|
|
20
|
+
resolveRuntimeIdentityConfig
|
|
21
|
+
} from "./chunk-EXXTCGKR.js";
|
|
20
22
|
|
|
21
23
|
// src/utils/deploy.ts
|
|
22
24
|
import { readFile, writeFile } from "fs/promises";
|
|
@@ -196,4 +198,4 @@ export {
|
|
|
196
198
|
promptDeployTarget,
|
|
197
199
|
showKalpCloudWaitlist
|
|
198
200
|
};
|
|
199
|
-
//# sourceMappingURL=chunk-
|
|
201
|
+
//# sourceMappingURL=chunk-4CEJYSJY.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/deploy.ts","../src/utils/deploy-target.ts"],"sourcesContent":["import { readFile, writeFile } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport { requireAuth } from \"@/utils/auth\";\nimport { ensureStudioSecrets } from \"@/utils/secret\";\nimport { readProjectState, writeProjectState } from \"@/utils/project-state\";\nimport { materializeRuntime } from \"@/utils/runtime\";\nimport {\n getRequiredSecretForProvider,\n readDotEnv,\n resolveProviderFromConfig,\n} from \"@/utils/ai\";\nimport {\n loadProjectConfig,\n resolveIdentityAuthRequirements,\n resolveRuntimeIdentityConfig,\n} from \"@/utils/project-config\";\nimport { resolveProvider } from \"@/utils/providers\";\n\ninterface RuntimeWranglerConfig {\n name?: string;\n kv_namespaces?: Array<{ binding: string; id?: string }>;\n}\n\ninterface KvNamespaceInfo {\n id: string;\n title: string;\n}\n\nasync function readWranglerConfig(\n configPath: string,\n): Promise<RuntimeWranglerConfig> {\n const text = await readFile(configPath, \"utf-8\");\n return JSON.parse(text) as RuntimeWranglerConfig;\n}\n\nasync function writeWranglerConfig(\n configPath: string,\n config: RuntimeWranglerConfig,\n): Promise<void> {\n await writeFile(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n}\n\nfunction deriveKvNamespaceTitle(workerName: string, binding: string): string {\n return `${workerName}-${binding.toLowerCase().replace(/_/g, \"-\")}`;\n}\n\nasync function listKvNamespaces(\n cwd: string,\n configPath: string,\n): Promise<KvNamespaceInfo[]> {\n const provider = resolveProvider();\n const namespaces = await provider.listNamespaces({ cwd, configPath });\n return namespaces.map((item) => ({\n id: item.id,\n title: item.title,\n }));\n}\n\nasync function ensureKvNamespaceBindingId(\n cwd: string,\n configPath: string,\n): Promise<string | null> {\n const config = await readWranglerConfig(configPath);\n const binding = config.kv_namespaces?.find(\n (item) => item.binding === \"KALP_MANIFESTS\",\n );\n\n if (!binding || !config.name) return null;\n if (binding.id) return binding.id;\n\n const expectedTitle = deriveKvNamespaceTitle(config.name, binding.binding);\n const namespaces = await listKvNamespaces(cwd, configPath);\n const existing = namespaces.find((item) => item.title === expectedTitle);\n if (!existing) return null;\n\n binding.id = existing.id;\n await writeWranglerConfig(configPath, config);\n return existing.id;\n}\n\nfunction isNamespaceAlreadyExistsError(output: string): boolean {\n return output.includes(\"[code: 10014]\") && output.includes(\"already exists\");\n}\n\nexport async function runInitialDeploy(cwd: string): Promise<{\n workerUrl: string;\n customDomains: string[];\n accountId: string;\n studioAdminUser: string;\n studioPassword: string;\n serviceKey: string;\n credentialsChanged: boolean;\n serviceKeyChanged: boolean;\n}> {\n const auth = await requireAuth();\n const loadedConfig = await loadProjectConfig(cwd);\n const identityConfig = resolveRuntimeIdentityConfig(loadedConfig.raw);\n const identitySecretRequirements = resolveIdentityAuthRequirements(identityConfig);\n const aiProvider = await resolveProviderFromConfig(cwd);\n const requiredProviderSecret = getRequiredSecretForProvider(aiProvider);\n const secrets = await ensureStudioSecrets(cwd);\n const envMap = await readDotEnv(cwd);\n const providerSecretValue = envMap[requiredProviderSecret]?.trim();\n if (!providerSecretValue) {\n throw new Error(\n `Missing required secret ${requiredProviderSecret} for provider \"${aiProvider}\". Add it to .env before deploy.`,\n );\n }\n\n const resolvedIdentitySecrets = identitySecretRequirements.map((requirement) => {\n const value = envMap[requirement.envKey]?.trim();\n if (!value) {\n throw new Error(\n `Missing required secret ${requirement.envKey} for ${requirement.reason}. Add it to .env before deploy.`,\n );\n }\n return { name: requirement.envKey, value };\n });\n\n const runtimeProvider = resolveProvider();\n const runtime = await materializeRuntime(cwd);\n let secretSyncFailed = false;\n const secretEntries = [\n [\"KALP_SECRET_KEY\", secrets.key],\n [\"KALP_STUDIO_PASSWORD\", secrets.studioPassword],\n [\"KALP_STUDIO_ADMIN_USER\", secrets.studioAdminUser],\n [\"KALP_SERVICE_KEY\", secrets.serviceKey],\n [requiredProviderSecret, providerSecretValue],\n ...resolvedIdentitySecrets.map((item) => [item.name, item.value] as const),\n ];\n const dedupedSecrets = new Map<string, string>();\n for (const [name, value] of secretEntries) {\n dedupedSecrets.set(name, value);\n }\n\n for (const [name, value] of dedupedSecrets.entries()) {\n try {\n await runtimeProvider.putSecret({\n cwd,\n configPath: runtime.wranglerConfigPath,\n name,\n value,\n });\n } catch {\n secretSyncFailed = true;\n break;\n }\n }\n\n await ensureKvNamespaceBindingId(cwd, runtime.wranglerConfigPath).catch(\n () => null,\n );\n\n let deploy = await runtimeProvider\n .deployRuntime({\n cwd,\n configPath: runtime.wranglerConfigPath,\n useSecretsFile: secretSyncFailed,\n })\n .catch((error) => error);\n if (deploy instanceof Error) {\n const combined = deploy.message;\n if (isNamespaceAlreadyExistsError(combined)) {\n await ensureKvNamespaceBindingId(cwd, runtime.wranglerConfigPath);\n deploy = await runtimeProvider.deployRuntime({\n cwd,\n configPath: runtime.wranglerConfigPath,\n useSecretsFile: secretSyncFailed,\n });\n } else {\n throw deploy;\n }\n }\n\n const workerUrl = deploy.workerUrl;\n const customDomains = deploy.customDomains ?? [];\n\n const existingState = await readProjectState(cwd);\n\n const credentialsFingerprint = createHash(\"sha256\")\n .update(`${secrets.studioAdminUser}:${secrets.studioPassword}`)\n .digest(\"hex\");\n const credentialsChanged =\n existingState?.studioCredentialsFingerprint !== credentialsFingerprint;\n const serviceKeyFingerprint = createHash(\"sha256\")\n .update(secrets.serviceKey)\n .digest(\"hex\");\n const serviceKeyChanged =\n existingState?.serviceKeyFingerprint !== serviceKeyFingerprint;\n\n await writeProjectState(cwd, {\n workerUrl,\n deployedAt: new Date().toISOString(),\n accountId: auth.accountId,\n studioCredentialsFingerprint: credentialsFingerprint,\n serviceKeyFingerprint,\n agents: existingState?.agents ?? {},\n });\n\n return {\n workerUrl,\n customDomains,\n accountId: auth.accountId,\n studioAdminUser: secrets.studioAdminUser,\n studioPassword: secrets.studioPassword,\n serviceKey: secrets.serviceKey,\n credentialsChanged,\n serviceKeyChanged,\n };\n}\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\n\nexport type DeployTarget = \"cloudflare\" | \"kalp-cloud\";\n\nexport async function promptDeployTarget(message: string): Promise<DeployTarget | null> {\n const selected = await p.select({\n message,\n options: [\n {\n value: \"cloudflare\",\n label: \"Cloudflare\",\n hint: \"Available now\",\n },\n {\n value: \"kalp-cloud\",\n label: \"Kalp Cloud\",\n hint: \"Coming soon\",\n },\n ],\n });\n\n if (p.isCancel(selected)) return null;\n return selected as DeployTarget;\n}\n\nexport function showKalpCloudWaitlist(): void {\n p.note(\n [\n `${pc.bold(\"Kalp Cloud is coming soon 🚀\")}`,\n pc.dim(\"Join the waitlist for early access:\"),\n pc.cyan(\"https://usekalp.com/waitlist\"),\n ].join(\"\\n\"),\n \"Kalp Cloud\",\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/deploy.ts","../src/utils/deploy-target.ts"],"sourcesContent":["import { readFile, writeFile } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport { requireAuth } from \"@/utils/auth\";\nimport { ensureStudioSecrets } from \"@/utils/secret\";\nimport { readProjectState, writeProjectState } from \"@/utils/project-state\";\nimport { materializeRuntime } from \"@/utils/runtime\";\nimport {\n getRequiredSecretForProvider,\n readDotEnv,\n resolveProviderFromConfig,\n} from \"@/utils/ai\";\nimport {\n loadProjectConfig,\n resolveIdentityAuthRequirements,\n resolveRuntimeIdentityConfig,\n} from \"@/utils/project-config\";\nimport { resolveProvider } from \"@/utils/providers\";\n\ninterface RuntimeWranglerConfig {\n name?: string;\n kv_namespaces?: Array<{ binding: string; id?: string }>;\n}\n\ninterface KvNamespaceInfo {\n id: string;\n title: string;\n}\n\nasync function readWranglerConfig(\n configPath: string,\n): Promise<RuntimeWranglerConfig> {\n const text = await readFile(configPath, \"utf-8\");\n return JSON.parse(text) as RuntimeWranglerConfig;\n}\n\nasync function writeWranglerConfig(\n configPath: string,\n config: RuntimeWranglerConfig,\n): Promise<void> {\n await writeFile(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n}\n\nfunction deriveKvNamespaceTitle(workerName: string, binding: string): string {\n return `${workerName}-${binding.toLowerCase().replace(/_/g, \"-\")}`;\n}\n\nasync function listKvNamespaces(\n cwd: string,\n configPath: string,\n): Promise<KvNamespaceInfo[]> {\n const provider = resolveProvider();\n const namespaces = await provider.listNamespaces({ cwd, configPath });\n return namespaces.map((item) => ({\n id: item.id,\n title: item.title,\n }));\n}\n\nasync function ensureKvNamespaceBindingId(\n cwd: string,\n configPath: string,\n): Promise<string | null> {\n const config = await readWranglerConfig(configPath);\n const binding = config.kv_namespaces?.find(\n (item) => item.binding === \"KALP_MANIFESTS\",\n );\n\n if (!binding || !config.name) return null;\n if (binding.id) return binding.id;\n\n const expectedTitle = deriveKvNamespaceTitle(config.name, binding.binding);\n const namespaces = await listKvNamespaces(cwd, configPath);\n const existing = namespaces.find((item) => item.title === expectedTitle);\n if (!existing) return null;\n\n binding.id = existing.id;\n await writeWranglerConfig(configPath, config);\n return existing.id;\n}\n\nfunction isNamespaceAlreadyExistsError(output: string): boolean {\n return output.includes(\"[code: 10014]\") && output.includes(\"already exists\");\n}\n\nexport async function runInitialDeploy(cwd: string): Promise<{\n workerUrl: string;\n customDomains: string[];\n accountId: string;\n studioAdminUser: string;\n studioPassword: string;\n serviceKey: string;\n credentialsChanged: boolean;\n serviceKeyChanged: boolean;\n}> {\n const auth = await requireAuth();\n const loadedConfig = await loadProjectConfig(cwd);\n const identityConfig = resolveRuntimeIdentityConfig(loadedConfig.raw);\n const identitySecretRequirements = resolveIdentityAuthRequirements(identityConfig);\n const aiProvider = await resolveProviderFromConfig(cwd);\n const requiredProviderSecret = getRequiredSecretForProvider(aiProvider);\n const secrets = await ensureStudioSecrets(cwd);\n const envMap = await readDotEnv(cwd);\n const providerSecretValue = envMap[requiredProviderSecret]?.trim();\n if (!providerSecretValue) {\n throw new Error(\n `Missing required secret ${requiredProviderSecret} for provider \"${aiProvider}\". Add it to .env before deploy.`,\n );\n }\n\n const resolvedIdentitySecrets = identitySecretRequirements.map((requirement) => {\n const value = envMap[requirement.envKey]?.trim();\n if (!value) {\n throw new Error(\n `Missing required secret ${requirement.envKey} for ${requirement.reason}. Add it to .env before deploy.`,\n );\n }\n return { name: requirement.envKey, value };\n });\n\n const runtimeProvider = resolveProvider();\n const runtime = await materializeRuntime(cwd);\n let secretSyncFailed = false;\n const secretEntries = [\n [\"KALP_SECRET_KEY\", secrets.key],\n [\"KALP_STUDIO_PASSWORD\", secrets.studioPassword],\n [\"KALP_STUDIO_ADMIN_USER\", secrets.studioAdminUser],\n [\"KALP_SERVICE_KEY\", secrets.serviceKey],\n [requiredProviderSecret, providerSecretValue],\n ...resolvedIdentitySecrets.map((item) => [item.name, item.value] as const),\n ];\n const dedupedSecrets = new Map<string, string>();\n for (const [name, value] of secretEntries) {\n dedupedSecrets.set(name, value);\n }\n\n for (const [name, value] of dedupedSecrets.entries()) {\n try {\n await runtimeProvider.putSecret({\n cwd,\n configPath: runtime.wranglerConfigPath,\n name,\n value,\n });\n } catch {\n secretSyncFailed = true;\n break;\n }\n }\n\n await ensureKvNamespaceBindingId(cwd, runtime.wranglerConfigPath).catch(\n () => null,\n );\n\n let deploy = await runtimeProvider\n .deployRuntime({\n cwd,\n configPath: runtime.wranglerConfigPath,\n useSecretsFile: secretSyncFailed,\n })\n .catch((error) => error);\n if (deploy instanceof Error) {\n const combined = deploy.message;\n if (isNamespaceAlreadyExistsError(combined)) {\n await ensureKvNamespaceBindingId(cwd, runtime.wranglerConfigPath);\n deploy = await runtimeProvider.deployRuntime({\n cwd,\n configPath: runtime.wranglerConfigPath,\n useSecretsFile: secretSyncFailed,\n });\n } else {\n throw deploy;\n }\n }\n\n const workerUrl = deploy.workerUrl;\n const customDomains = deploy.customDomains ?? [];\n\n const existingState = await readProjectState(cwd);\n\n const credentialsFingerprint = createHash(\"sha256\")\n .update(`${secrets.studioAdminUser}:${secrets.studioPassword}`)\n .digest(\"hex\");\n const credentialsChanged =\n existingState?.studioCredentialsFingerprint !== credentialsFingerprint;\n const serviceKeyFingerprint = createHash(\"sha256\")\n .update(secrets.serviceKey)\n .digest(\"hex\");\n const serviceKeyChanged =\n existingState?.serviceKeyFingerprint !== serviceKeyFingerprint;\n\n await writeProjectState(cwd, {\n workerUrl,\n deployedAt: new Date().toISOString(),\n accountId: auth.accountId,\n studioCredentialsFingerprint: credentialsFingerprint,\n serviceKeyFingerprint,\n agents: existingState?.agents ?? {},\n });\n\n return {\n workerUrl,\n customDomains,\n accountId: auth.accountId,\n studioAdminUser: secrets.studioAdminUser,\n studioPassword: secrets.studioPassword,\n serviceKey: secrets.serviceKey,\n credentialsChanged,\n serviceKeyChanged,\n };\n}\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\n\nexport type DeployTarget = \"cloudflare\" | \"kalp-cloud\";\n\nexport async function promptDeployTarget(message: string): Promise<DeployTarget | null> {\n const selected = await p.select({\n message,\n options: [\n {\n value: \"cloudflare\",\n label: \"Cloudflare\",\n hint: \"Available now\",\n },\n {\n value: \"kalp-cloud\",\n label: \"Kalp Cloud\",\n hint: \"Coming soon\",\n },\n ],\n });\n\n if (p.isCancel(selected)) return null;\n return selected as DeployTarget;\n}\n\nexport function showKalpCloudWaitlist(): void {\n p.note(\n [\n `${pc.bold(\"Kalp Cloud is coming soon 🚀\")}`,\n pc.dim(\"Join the waitlist for early access:\"),\n pc.cyan(\"https://usekalp.com/waitlist\"),\n ].join(\"\\n\"),\n \"Kalp Cloud\",\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,UAAU,iBAAiB;AACpC,SAAS,kBAAkB;AA2B3B,eAAe,mBACb,YACgC;AAChC,QAAM,OAAO,MAAM,SAAS,YAAY,OAAO;AAC/C,SAAO,KAAK,MAAM,IAAI;AACxB;AAEA,eAAe,oBACb,YACA,QACe;AACf,QAAM,UAAU,YAAY,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,GAAM,OAAO;AAC7E;AAEA,SAAS,uBAAuB,YAAoB,SAAyB;AAC3E,SAAO,GAAG,UAAU,IAAI,QAAQ,YAAY,EAAE,QAAQ,MAAM,GAAG,CAAC;AAClE;AAEA,eAAe,iBACb,KACA,YAC4B;AAC5B,QAAM,WAAW,gBAAgB;AACjC,QAAM,aAAa,MAAM,SAAS,eAAe,EAAE,KAAK,WAAW,CAAC;AACpE,SAAO,WAAW,IAAI,CAAC,UAAU;AAAA,IAC/B,IAAI,KAAK;AAAA,IACT,OAAO,KAAK;AAAA,EACd,EAAE;AACJ;AAEA,eAAe,2BACb,KACA,YACwB;AACxB,QAAM,SAAS,MAAM,mBAAmB,UAAU;AAClD,QAAM,UAAU,OAAO,eAAe;AAAA,IACpC,CAAC,SAAS,KAAK,YAAY;AAAA,EAC7B;AAEA,MAAI,CAAC,WAAW,CAAC,OAAO,KAAM,QAAO;AACrC,MAAI,QAAQ,GAAI,QAAO,QAAQ;AAE/B,QAAM,gBAAgB,uBAAuB,OAAO,MAAM,QAAQ,OAAO;AACzE,QAAM,aAAa,MAAM,iBAAiB,KAAK,UAAU;AACzD,QAAM,WAAW,WAAW,KAAK,CAAC,SAAS,KAAK,UAAU,aAAa;AACvE,MAAI,CAAC,SAAU,QAAO;AAEtB,UAAQ,KAAK,SAAS;AACtB,QAAM,oBAAoB,YAAY,MAAM;AAC5C,SAAO,SAAS;AAClB;AAEA,SAAS,8BAA8B,QAAyB;AAC9D,SAAO,OAAO,SAAS,eAAe,KAAK,OAAO,SAAS,gBAAgB;AAC7E;AAEA,eAAsB,iBAAiB,KASpC;AACD,QAAM,OAAO,MAAM,YAAY;AAC/B,QAAM,eAAe,MAAM,kBAAkB,GAAG;AAChD,QAAM,iBAAiB,6BAA6B,aAAa,GAAG;AACpE,QAAM,6BAA6B,gCAAgC,cAAc;AACjF,QAAM,aAAa,MAAM,0BAA0B,GAAG;AACtD,QAAM,yBAAyB,6BAA6B,UAAU;AACtE,QAAM,UAAU,MAAM,oBAAoB,GAAG;AAC7C,QAAM,SAAS,MAAM,WAAW,GAAG;AACnC,QAAM,sBAAsB,OAAO,sBAAsB,GAAG,KAAK;AACjE,MAAI,CAAC,qBAAqB;AACxB,UAAM,IAAI;AAAA,MACR,2BAA2B,sBAAsB,kBAAkB,UAAU;AAAA,IAC/E;AAAA,EACF;AAEA,QAAM,0BAA0B,2BAA2B,IAAI,CAAC,gBAAgB;AAC9E,UAAM,QAAQ,OAAO,YAAY,MAAM,GAAG,KAAK;AAC/C,QAAI,CAAC,OAAO;AACV,YAAM,IAAI;AAAA,QACR,2BAA2B,YAAY,MAAM,QAAQ,YAAY,MAAM;AAAA,MACzE;AAAA,IACF;AACA,WAAO,EAAE,MAAM,YAAY,QAAQ,MAAM;AAAA,EAC3C,CAAC;AAED,QAAM,kBAAkB,gBAAgB;AACxC,QAAM,UAAU,MAAM,mBAAmB,GAAG;AAC5C,MAAI,mBAAmB;AACvB,QAAM,gBAAgB;AAAA,IACpB,CAAC,mBAAmB,QAAQ,GAAG;AAAA,IAC/B,CAAC,wBAAwB,QAAQ,cAAc;AAAA,IAC/C,CAAC,0BAA0B,QAAQ,eAAe;AAAA,IAClD,CAAC,oBAAoB,QAAQ,UAAU;AAAA,IACvC,CAAC,wBAAwB,mBAAmB;AAAA,IAC5C,GAAG,wBAAwB,IAAI,CAAC,SAAS,CAAC,KAAK,MAAM,KAAK,KAAK,CAAU;AAAA,EAC3E;AACA,QAAM,iBAAiB,oBAAI,IAAoB;AAC/C,aAAW,CAAC,MAAM,KAAK,KAAK,eAAe;AACzC,mBAAe,IAAI,MAAM,KAAK;AAAA,EAChC;AAEA,aAAW,CAAC,MAAM,KAAK,KAAK,eAAe,QAAQ,GAAG;AACpD,QAAI;AACF,YAAM,gBAAgB,UAAU;AAAA,QAC9B;AAAA,QACA,YAAY,QAAQ;AAAA,QACpB;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,QAAQ;AACN,yBAAmB;AACnB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,2BAA2B,KAAK,QAAQ,kBAAkB,EAAE;AAAA,IAChE,MAAM;AAAA,EACR;AAEA,MAAI,SAAS,MAAM,gBAChB,cAAc;AAAA,IACb;AAAA,IACA,YAAY,QAAQ;AAAA,IACpB,gBAAgB;AAAA,EAClB,CAAC,EACA,MAAM,CAAC,UAAU,KAAK;AACzB,MAAI,kBAAkB,OAAO;AAC3B,UAAM,WAAW,OAAO;AACxB,QAAI,8BAA8B,QAAQ,GAAG;AAC3C,YAAM,2BAA2B,KAAK,QAAQ,kBAAkB;AAChE,eAAS,MAAM,gBAAgB,cAAc;AAAA,QAC3C;AAAA,QACA,YAAY,QAAQ;AAAA,QACpB,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,YAAY,OAAO;AACzB,QAAM,gBAAgB,OAAO,iBAAiB,CAAC;AAE/C,QAAM,gBAAgB,MAAM,iBAAiB,GAAG;AAEhD,QAAM,yBAAyB,WAAW,QAAQ,EAC/C,OAAO,GAAG,QAAQ,eAAe,IAAI,QAAQ,cAAc,EAAE,EAC7D,OAAO,KAAK;AACf,QAAM,qBACJ,eAAe,iCAAiC;AAClD,QAAM,wBAAwB,WAAW,QAAQ,EAC9C,OAAO,QAAQ,UAAU,EACzB,OAAO,KAAK;AACf,QAAM,oBACJ,eAAe,0BAA0B;AAE3C,QAAM,kBAAkB,KAAK;AAAA,IAC3B;AAAA,IACA,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,IACnC,WAAW,KAAK;AAAA,IAChB,8BAA8B;AAAA,IAC9B;AAAA,IACA,QAAQ,eAAe,UAAU,CAAC;AAAA,EACpC,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,WAAW,KAAK;AAAA,IAChB,iBAAiB,QAAQ;AAAA,IACzB,gBAAgB,QAAQ;AAAA,IACxB,YAAY,QAAQ;AAAA,IACpB;AAAA,IACA;AAAA,EACF;AACF;;;ACjNA,YAAY,OAAO;AACnB,OAAO,QAAQ;AAIf,eAAsB,mBAAmB,SAA+C;AACtF,QAAM,WAAW,MAAQ,SAAO;AAAA,IAC9B;AAAA,IACA,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAM,WAAS,QAAQ,EAAG,QAAO;AACjC,SAAO;AACT;AAEO,SAAS,wBAA8B;AAC5C,EAAE;AAAA,IACA;AAAA,MACE,GAAG,GAAG,KAAK,qCAA8B,CAAC;AAAA,MAC1C,GAAG,IAAI,qCAAqC;AAAA,MAC5C,GAAG,KAAK,8BAA8B;AAAA,IACxC,EAAE,KAAK,IAAI;AAAA,IACX;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/utils/project-config.ts
|
|
4
|
+
import { createJiti } from "jiti";
|
|
5
|
+
import { access } from "fs/promises";
|
|
6
|
+
import { constants } from "fs";
|
|
7
|
+
import { join, resolve } from "path";
|
|
8
|
+
function normalizeStrategy(strategy) {
|
|
9
|
+
if (!strategy) return null;
|
|
10
|
+
if (strategy.type === "jwks") {
|
|
11
|
+
return {
|
|
12
|
+
type: "jwks",
|
|
13
|
+
jwksUrl: strategy.jwksUrl,
|
|
14
|
+
issuer: strategy.issuer,
|
|
15
|
+
audience: strategy.audience
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (strategy.type === "symmetric") {
|
|
19
|
+
return {
|
|
20
|
+
type: "symmetric",
|
|
21
|
+
secretEnvKey: strategy.secretEnvKey
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
type: "apiKey",
|
|
26
|
+
headerName: strategy.headerName,
|
|
27
|
+
envKey: strategy.envKey
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async function loadProjectConfig(cwd) {
|
|
31
|
+
const configPath = resolve(join(cwd, "kalp.config.ts"));
|
|
32
|
+
await access(configPath, constants.F_OK);
|
|
33
|
+
const jiti = createJiti(cwd, { interopDefault: true });
|
|
34
|
+
const moduleValue = await jiti.import(configPath);
|
|
35
|
+
const raw = moduleValue && typeof moduleValue === "object" && "default" in moduleValue ? moduleValue.default ?? moduleValue : moduleValue;
|
|
36
|
+
return { path: configPath, raw };
|
|
37
|
+
}
|
|
38
|
+
function resolveRuntimeIdentityConfig(rawConfig) {
|
|
39
|
+
const identity = rawConfig.identity && typeof rawConfig.identity === "object" ? rawConfig.identity : void 0;
|
|
40
|
+
const enforceGlobalAuth = typeof rawConfig.enforceGlobalAuth === "boolean" ? rawConfig.enforceGlobalAuth : true;
|
|
41
|
+
return {
|
|
42
|
+
enforceGlobalAuth,
|
|
43
|
+
identityId: identity && typeof identity.id === "string" && identity.id.length > 0 ? identity.id : null,
|
|
44
|
+
strategy: normalizeStrategy(identity?.strategy)
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function resolveIdentityAuthRequirements(identity) {
|
|
48
|
+
if (!identity.strategy) return [];
|
|
49
|
+
if (identity.strategy.type === "symmetric") {
|
|
50
|
+
return [
|
|
51
|
+
{
|
|
52
|
+
envKey: identity.strategy.secretEnvKey?.trim() || "JWT_SIGNING_SECRET",
|
|
53
|
+
reason: "symmetric JWT validation"
|
|
54
|
+
}
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
if (identity.strategy.type === "apiKey") {
|
|
58
|
+
const envKey = identity.strategy.envKey?.trim();
|
|
59
|
+
if (!envKey) {
|
|
60
|
+
return [
|
|
61
|
+
{
|
|
62
|
+
envKey: "KALP_API_KEY",
|
|
63
|
+
reason: "apiKey strategy (default env key)"
|
|
64
|
+
}
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
return [{ envKey, reason: "apiKey strategy" }];
|
|
68
|
+
}
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export {
|
|
73
|
+
loadProjectConfig,
|
|
74
|
+
resolveRuntimeIdentityConfig,
|
|
75
|
+
resolveIdentityAuthRequirements
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=chunk-EXXTCGKR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/project-config.ts"],"sourcesContent":["import { createJiti } from \"jiti\";\nimport { access } from \"node:fs/promises\";\nimport { constants } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport type { AuthStrategy, IdentityConfig } from \"@kalphq/sdk\";\n\nexport interface LoadedProjectConfig {\n path: string;\n raw: Record<string, unknown>;\n}\n\nexport interface RuntimeIdentityStrategyConfig {\n type: \"jwks\" | \"symmetric\" | \"apiKey\";\n jwksUrl?: string;\n issuer?: string;\n audience?: string;\n secretEnvKey?: string;\n headerName?: string;\n envKey?: string;\n}\n\nexport interface RuntimeIdentityConfig {\n enforceGlobalAuth: boolean;\n identityId: string | null;\n strategy: RuntimeIdentityStrategyConfig | null;\n}\n\nexport interface ProjectConfigAuthRequirement {\n envKey: string;\n reason: string;\n}\n\nfunction normalizeStrategy(\n strategy: AuthStrategy | undefined,\n): RuntimeIdentityStrategyConfig | null {\n if (!strategy) return null;\n if (strategy.type === \"jwks\") {\n return {\n type: \"jwks\",\n jwksUrl: strategy.jwksUrl,\n issuer: strategy.issuer,\n audience: strategy.audience,\n };\n }\n if (strategy.type === \"symmetric\") {\n return {\n type: \"symmetric\",\n secretEnvKey: strategy.secretEnvKey,\n };\n }\n return {\n type: \"apiKey\",\n headerName: strategy.headerName,\n envKey: strategy.envKey,\n };\n}\n\nexport async function loadProjectConfig(cwd: string): Promise<LoadedProjectConfig> {\n const configPath = resolve(join(cwd, \"kalp.config.ts\"));\n await access(configPath, constants.F_OK);\n const jiti = createJiti(cwd, { interopDefault: true });\n const moduleValue = (await jiti.import(configPath)) as\n | { default?: Record<string, unknown> }\n | Record<string, unknown>;\n const raw =\n moduleValue && typeof moduleValue === \"object\" && \"default\" in moduleValue\n ? ((moduleValue.default ?? moduleValue) as Record<string, unknown>)\n : (moduleValue as Record<string, unknown>);\n return { path: configPath, raw };\n}\n\nexport function resolveRuntimeIdentityConfig(\n rawConfig: Record<string, unknown>,\n): RuntimeIdentityConfig {\n const identity =\n rawConfig.identity && typeof rawConfig.identity === \"object\"\n ? (rawConfig.identity as IdentityConfig)\n : undefined;\n const enforceGlobalAuth =\n typeof rawConfig.enforceGlobalAuth === \"boolean\"\n ? rawConfig.enforceGlobalAuth\n : true;\n\n return {\n enforceGlobalAuth,\n identityId:\n identity && typeof identity.id === \"string\" && identity.id.length > 0\n ? identity.id\n : null,\n strategy: normalizeStrategy(identity?.strategy),\n };\n}\n\nexport function resolveIdentityAuthRequirements(\n identity: RuntimeIdentityConfig,\n): ProjectConfigAuthRequirement[] {\n if (!identity.strategy) return [];\n\n if (identity.strategy.type === \"symmetric\") {\n return [\n {\n envKey: identity.strategy.secretEnvKey?.trim() || \"JWT_SIGNING_SECRET\",\n reason: \"symmetric JWT validation\",\n },\n ];\n }\n\n if (identity.strategy.type === \"apiKey\") {\n const envKey = identity.strategy.envKey?.trim();\n if (!envKey) {\n return [\n {\n envKey: \"KALP_API_KEY\",\n reason: \"apiKey strategy (default env key)\",\n },\n ];\n }\n return [{ envKey, reason: \"apiKey strategy\" }];\n }\n\n return [];\n}\n"],"mappings":";;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAC1B,SAAS,MAAM,eAAe;AA6B9B,SAAS,kBACP,UACsC;AACtC,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI,SAAS,SAAS,QAAQ;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,SAAS;AAAA,MAClB,QAAQ,SAAS;AAAA,MACjB,UAAU,SAAS;AAAA,IACrB;AAAA,EACF;AACA,MAAI,SAAS,SAAS,aAAa;AACjC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,cAAc,SAAS;AAAA,IACzB;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY,SAAS;AAAA,IACrB,QAAQ,SAAS;AAAA,EACnB;AACF;AAEA,eAAsB,kBAAkB,KAA2C;AACjF,QAAM,aAAa,QAAQ,KAAK,KAAK,gBAAgB,CAAC;AACtD,QAAM,OAAO,YAAY,UAAU,IAAI;AACvC,QAAM,OAAO,WAAW,KAAK,EAAE,gBAAgB,KAAK,CAAC;AACrD,QAAM,cAAe,MAAM,KAAK,OAAO,UAAU;AAGjD,QAAM,MACJ,eAAe,OAAO,gBAAgB,YAAY,aAAa,cACzD,YAAY,WAAW,cACxB;AACP,SAAO,EAAE,MAAM,YAAY,IAAI;AACjC;AAEO,SAAS,6BACd,WACuB;AACvB,QAAM,WACJ,UAAU,YAAY,OAAO,UAAU,aAAa,WAC/C,UAAU,WACX;AACN,QAAM,oBACJ,OAAO,UAAU,sBAAsB,YACnC,UAAU,oBACV;AAEN,SAAO;AAAA,IACL;AAAA,IACA,YACE,YAAY,OAAO,SAAS,OAAO,YAAY,SAAS,GAAG,SAAS,IAChE,SAAS,KACT;AAAA,IACN,UAAU,kBAAkB,UAAU,QAAQ;AAAA,EAChD;AACF;AAEO,SAAS,gCACd,UACgC;AAChC,MAAI,CAAC,SAAS,SAAU,QAAO,CAAC;AAEhC,MAAI,SAAS,SAAS,SAAS,aAAa;AAC1C,WAAO;AAAA,MACL;AAAA,QACE,QAAQ,SAAS,SAAS,cAAc,KAAK,KAAK;AAAA,QAClD,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,SAAS,SAAS,UAAU;AACvC,UAAM,SAAS,SAAS,SAAS,QAAQ,KAAK;AAC9C,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,QACL;AAAA,UACE,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AACA,WAAO,CAAC,EAAE,QAAQ,QAAQ,kBAAkB,CAAC;AAAA,EAC/C;AAEA,SAAO,CAAC;AACV;","names":[]}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
materializeRuntime,
|
|
7
7
|
readProjectState
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-XVD3FFOJ.js";
|
|
9
9
|
|
|
10
10
|
// src/utils/secrets-runtime.ts
|
|
11
11
|
async function resolveSecretsRuntimeConfigPath(cwd) {
|
|
@@ -25,4 +25,4 @@ async function resolveSecretsRuntimeConfigPath(cwd) {
|
|
|
25
25
|
export {
|
|
26
26
|
resolveSecretsRuntimeConfigPath
|
|
27
27
|
};
|
|
28
|
-
//# sourceMappingURL=chunk-
|
|
28
|
+
//# sourceMappingURL=chunk-IZXCZ3IA.js.map
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
loadProjectConfig
|
|
4
|
+
} from "./chunk-EXXTCGKR.js";
|
|
5
|
+
|
|
6
|
+
// src/utils/codegen.ts
|
|
7
|
+
import { access, mkdir, readFile, writeFile } from "fs/promises";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
var GENERATED_HEADER = `// \u{1F98B} Kalp Generated Types
|
|
10
|
+
// This file is auto-generated. Do not edit manually.
|
|
11
|
+
`;
|
|
12
|
+
var GENERATED_MCP_HEADER = `// \u{1F98B} Kalp Generated MCP Types
|
|
13
|
+
// This file is auto-generated by \`kalp mcp generate\`.
|
|
14
|
+
// Do not edit manually.
|
|
15
|
+
`;
|
|
16
|
+
var DEFAULT_PROVIDER = "openai";
|
|
17
|
+
function sanitizeSecrets(input) {
|
|
18
|
+
if (!Array.isArray(input)) return [];
|
|
19
|
+
return input.filter((value) => typeof value === "string").map((value) => value.trim()).filter(Boolean).sort((a, b) => a.localeCompare(b));
|
|
20
|
+
}
|
|
21
|
+
function sanitizeCustomModels(input) {
|
|
22
|
+
if (!Array.isArray(input)) return [];
|
|
23
|
+
return input.filter((value) => typeof value === "string").map((value) => value.trim()).filter(Boolean).sort((a, b) => a.localeCompare(b));
|
|
24
|
+
}
|
|
25
|
+
function sanitizeProvider(input) {
|
|
26
|
+
if (input === "openai" || input === "anthropic" || input === "openrouter" || input === "custom") {
|
|
27
|
+
return input;
|
|
28
|
+
}
|
|
29
|
+
return DEFAULT_PROVIDER;
|
|
30
|
+
}
|
|
31
|
+
function parseSecretsFromConfigText(configContent) {
|
|
32
|
+
const secretsMatch = configContent.match(/secrets:\s*\[([^\]]*)\]/);
|
|
33
|
+
if (!secretsMatch) return [];
|
|
34
|
+
const secretsArray = secretsMatch[1] ?? "";
|
|
35
|
+
const secretMatches = secretsArray.match(/"([^"]+)"/g);
|
|
36
|
+
if (!secretMatches) return [];
|
|
37
|
+
return secretMatches.map((match) => match.replace(/"/g, "").trim()).filter(Boolean).sort((a, b) => a.localeCompare(b));
|
|
38
|
+
}
|
|
39
|
+
function parseProviderFromConfigText(configContent) {
|
|
40
|
+
const providerMatch = configContent.match(
|
|
41
|
+
/provider:\s*"(openai|anthropic|openrouter|custom)"/
|
|
42
|
+
);
|
|
43
|
+
return sanitizeProvider(providerMatch?.[1]);
|
|
44
|
+
}
|
|
45
|
+
function parseCustomModelsFromConfigText(configContent) {
|
|
46
|
+
const modelsMatch = configContent.match(/customModels:\s*\[([^\]]*)\]/);
|
|
47
|
+
if (!modelsMatch) return [];
|
|
48
|
+
const modelsArray = modelsMatch[1] ?? "";
|
|
49
|
+
const modelMatches = modelsArray.match(/"([^"]+)"/g);
|
|
50
|
+
if (!modelMatches) return [];
|
|
51
|
+
return modelMatches.map((match) => match.replace(/"/g, "").trim()).filter(Boolean).sort((a, b) => a.localeCompare(b));
|
|
52
|
+
}
|
|
53
|
+
async function readConfigForTypes(cwd) {
|
|
54
|
+
try {
|
|
55
|
+
const { raw } = await loadProjectConfig(cwd);
|
|
56
|
+
const aiConfig = raw.ai && typeof raw.ai === "object" ? raw.ai : {};
|
|
57
|
+
return {
|
|
58
|
+
secrets: sanitizeSecrets(raw.secrets),
|
|
59
|
+
provider: sanitizeProvider(aiConfig.provider),
|
|
60
|
+
customModels: sanitizeCustomModels(aiConfig.customModels)
|
|
61
|
+
};
|
|
62
|
+
} catch {
|
|
63
|
+
const configPath = join(cwd, "kalp.config.ts");
|
|
64
|
+
const configContent = await readFile(configPath, "utf-8").catch(() => "");
|
|
65
|
+
return {
|
|
66
|
+
secrets: parseSecretsFromConfigText(configContent),
|
|
67
|
+
provider: parseProviderFromConfigText(configContent),
|
|
68
|
+
customModels: parseCustomModelsFromConfigText(configContent)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function toStringTuple(values) {
|
|
73
|
+
if (values.length === 0) return "readonly []";
|
|
74
|
+
return `readonly [${values.map((value) => JSON.stringify(value)).join(", ")}]`;
|
|
75
|
+
}
|
|
76
|
+
function buildKalpDtsContent() {
|
|
77
|
+
return `import "@kalphq/sdk";
|
|
78
|
+
import "./.kalp/mcp.types";
|
|
79
|
+
import type {
|
|
80
|
+
RegisteredSecretKeys,
|
|
81
|
+
ConfiguredAIProvider,
|
|
82
|
+
ConfiguredAICustomModels,
|
|
83
|
+
} from "./.kalp/types";
|
|
84
|
+
|
|
85
|
+
declare module "@kalphq/sdk" {
|
|
86
|
+
interface SecretsRegistry {
|
|
87
|
+
keys: RegisteredSecretKeys;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
interface KalpAIEnvironment {
|
|
91
|
+
provider: ConfiguredAIProvider;
|
|
92
|
+
customModels: ConfiguredAICustomModels;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function parseTsconfigJson(content: string): { include?: string[] } | null {
|
|
97
|
+
try {
|
|
98
|
+
return JSON.parse(content) as { include?: string[] };
|
|
99
|
+
} catch {
|
|
100
|
+
const withoutComments = content
|
|
101
|
+
.replace(//*[sS]*?*//g, "")
|
|
102
|
+
.replace(/^s*//.*$/gm, "");
|
|
103
|
+
const withoutTrailingCommas = withoutComments
|
|
104
|
+
.replace(/,s*}/g, "}")
|
|
105
|
+
.replace(/,s*]/g, "]");
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
return JSON.parse(withoutTrailingCommas) as { include?: string[] };
|
|
109
|
+
} catch {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
`;
|
|
115
|
+
}
|
|
116
|
+
function buildEmptyMcpTypesContent() {
|
|
117
|
+
return `${GENERATED_MCP_HEADER}import "@kalphq/sdk";
|
|
118
|
+
|
|
119
|
+
declare module "@kalphq/sdk" {
|
|
120
|
+
interface McpRegistry {}
|
|
121
|
+
}
|
|
122
|
+
`;
|
|
123
|
+
}
|
|
124
|
+
async function writeMcpTypes(cwd, content) {
|
|
125
|
+
const kalpDir = join(cwd, ".kalp");
|
|
126
|
+
const mcpTypesPath = join(kalpDir, "mcp.types.d.ts");
|
|
127
|
+
await mkdir(kalpDir, { recursive: true });
|
|
128
|
+
await writeFile(mcpTypesPath, content, "utf-8");
|
|
129
|
+
await updateKalpDts(cwd);
|
|
130
|
+
await updateTsconfig(cwd);
|
|
131
|
+
return mcpTypesPath;
|
|
132
|
+
}
|
|
133
|
+
async function ensureMcpTypesFile(cwd) {
|
|
134
|
+
const kalpDir = join(cwd, ".kalp");
|
|
135
|
+
const mcpTypesPath = join(kalpDir, "mcp.types.d.ts");
|
|
136
|
+
try {
|
|
137
|
+
await access(mcpTypesPath);
|
|
138
|
+
return;
|
|
139
|
+
} catch {
|
|
140
|
+
await writeMcpTypes(cwd, buildEmptyMcpTypesContent());
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async function generateTypes(cwd) {
|
|
144
|
+
const kalpDir = join(cwd, ".kalp");
|
|
145
|
+
const typesPath = join(kalpDir, "types.d.ts");
|
|
146
|
+
const config = await readConfigForTypes(cwd);
|
|
147
|
+
await mkdir(kalpDir, { recursive: true });
|
|
148
|
+
const typesContent = `${GENERATED_HEADER}/**
|
|
149
|
+
* Registered secrets from kalp.config.ts
|
|
150
|
+
* @generated
|
|
151
|
+
*/
|
|
152
|
+
export type RegisteredSecretKeys = ${toStringTuple(config.secrets)};
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* AI provider resolved from kalp.config.ts
|
|
156
|
+
* @generated
|
|
157
|
+
*/
|
|
158
|
+
export type ConfiguredAIProvider = ${JSON.stringify(config.provider)};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Custom model suggestions resolved from kalp.config.ts
|
|
162
|
+
* @generated
|
|
163
|
+
*/
|
|
164
|
+
export type ConfiguredAICustomModels = ${toStringTuple(config.customModels)};
|
|
165
|
+
`;
|
|
166
|
+
await writeFile(typesPath, typesContent, "utf-8");
|
|
167
|
+
await ensureMcpTypesFile(cwd);
|
|
168
|
+
await updateKalpDts(cwd);
|
|
169
|
+
await updateTsconfig(cwd);
|
|
170
|
+
}
|
|
171
|
+
async function updateKalpDts(cwd) {
|
|
172
|
+
const kalpDtsPath = join(cwd, "kalp.d.ts");
|
|
173
|
+
const content = buildKalpDtsContent();
|
|
174
|
+
try {
|
|
175
|
+
await access(kalpDtsPath);
|
|
176
|
+
const current = await readFile(kalpDtsPath, "utf-8");
|
|
177
|
+
if (current.trim() === content.trim()) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
} catch {
|
|
181
|
+
}
|
|
182
|
+
await writeFile(kalpDtsPath, content, "utf-8");
|
|
183
|
+
}
|
|
184
|
+
async function updateTsconfig(cwd) {
|
|
185
|
+
const tsconfigPath = join(cwd, "tsconfig.json");
|
|
186
|
+
try {
|
|
187
|
+
const content = await readFile(tsconfigPath, "utf-8");
|
|
188
|
+
const config = parseTsconfigJson(content);
|
|
189
|
+
if (!config) return;
|
|
190
|
+
if (!Array.isArray(config.include)) {
|
|
191
|
+
config.include = [];
|
|
192
|
+
}
|
|
193
|
+
const required = ["kalp.d.ts", ".kalp/types.d.ts", ".kalp/mcp.types.d.ts"];
|
|
194
|
+
for (const includePath of required) {
|
|
195
|
+
if (!config.include.includes(includePath)) {
|
|
196
|
+
config.include.push(includePath);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
await writeFile(tsconfigPath, JSON.stringify(config, null, 2), "utf-8");
|
|
200
|
+
} catch {
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export {
|
|
205
|
+
writeMcpTypes,
|
|
206
|
+
generateTypes
|
|
207
|
+
};
|
|
208
|
+
//# sourceMappingURL=chunk-LPEV4QH2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/codegen.ts"],"sourcesContent":["import { access, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { loadProjectConfig } from \"@/utils/project-config\";\n\nconst GENERATED_HEADER = `// 🦋 Kalp Generated Types\n// This file is auto-generated. Do not edit manually.\n`;\n\nconst GENERATED_MCP_HEADER = `// 🦋 Kalp Generated MCP Types\n// This file is auto-generated by \\`kalp mcp generate\\`.\n// Do not edit manually.\n`;\n\ntype AIProvider = \"openai\" | \"anthropic\" | \"openrouter\" | \"custom\";\n\ninterface GeneratedTypeConfig {\n secrets: string[];\n provider: AIProvider;\n customModels: string[];\n}\n\nconst DEFAULT_PROVIDER: AIProvider = \"openai\";\n\nfunction sanitizeSecrets(input: unknown): string[] {\n if (!Array.isArray(input)) return [];\n return input\n .filter((value): value is string => typeof value === \"string\")\n .map((value) => value.trim())\n .filter(Boolean)\n .sort((a, b) => a.localeCompare(b));\n}\n\nfunction sanitizeCustomModels(input: unknown): string[] {\n if (!Array.isArray(input)) return [];\n return input\n .filter((value): value is string => typeof value === \"string\")\n .map((value) => value.trim())\n .filter(Boolean)\n .sort((a, b) => a.localeCompare(b));\n}\n\nfunction sanitizeProvider(input: unknown): AIProvider {\n if (\n input === \"openai\" ||\n input === \"anthropic\" ||\n input === \"openrouter\" ||\n input === \"custom\"\n ) {\n return input;\n }\n return DEFAULT_PROVIDER;\n}\n\nfunction parseSecretsFromConfigText(configContent: string): string[] {\n const secretsMatch = configContent.match(/secrets:\\s*\\[([^\\]]*)\\]/);\n if (!secretsMatch) return [];\n const secretsArray = secretsMatch[1] ?? \"\";\n const secretMatches = secretsArray.match(/\"([^\"]+)\"/g);\n if (!secretMatches) return [];\n return secretMatches\n .map((match) => match.replace(/\"/g, \"\").trim())\n .filter(Boolean)\n .sort((a, b) => a.localeCompare(b));\n}\n\nfunction parseProviderFromConfigText(configContent: string): AIProvider {\n const providerMatch = configContent.match(\n /provider:\\s*\"(openai|anthropic|openrouter|custom)\"/,\n );\n return sanitizeProvider(providerMatch?.[1]);\n}\n\nfunction parseCustomModelsFromConfigText(configContent: string): string[] {\n const modelsMatch = configContent.match(/customModels:\\s*\\[([^\\]]*)\\]/);\n if (!modelsMatch) return [];\n const modelsArray = modelsMatch[1] ?? \"\";\n const modelMatches = modelsArray.match(/\"([^\"]+)\"/g);\n if (!modelMatches) return [];\n return modelMatches\n .map((match) => match.replace(/\"/g, \"\").trim())\n .filter(Boolean)\n .sort((a, b) => a.localeCompare(b));\n}\n\nasync function readConfigForTypes(cwd: string): Promise<GeneratedTypeConfig> {\n try {\n const { raw } = await loadProjectConfig(cwd);\n const aiConfig =\n raw.ai && typeof raw.ai === \"object\" ? (raw.ai as Record<string, unknown>) : {};\n\n return {\n secrets: sanitizeSecrets(raw.secrets),\n provider: sanitizeProvider(aiConfig.provider),\n customModels: sanitizeCustomModels(aiConfig.customModels),\n };\n } catch {\n const configPath = join(cwd, \"kalp.config.ts\");\n const configContent = await readFile(configPath, \"utf-8\").catch(() => \"\");\n return {\n secrets: parseSecretsFromConfigText(configContent),\n provider: parseProviderFromConfigText(configContent),\n customModels: parseCustomModelsFromConfigText(configContent),\n };\n }\n}\n\nfunction toStringTuple(values: string[]): string {\n if (values.length === 0) return \"readonly []\";\n return `readonly [${values.map((value) => JSON.stringify(value)).join(\", \")}]`;\n}\n\nfunction buildKalpDtsContent(): string {\n return `import \"@kalphq/sdk\";\nimport \"./.kalp/mcp.types\";\nimport type {\n RegisteredSecretKeys,\n ConfiguredAIProvider,\n ConfiguredAICustomModels,\n} from \"./.kalp/types\";\n\ndeclare module \"@kalphq/sdk\" {\n interface SecretsRegistry {\n keys: RegisteredSecretKeys;\n }\n\n interface KalpAIEnvironment {\n provider: ConfiguredAIProvider;\n customModels: ConfiguredAICustomModels;\n }\n}\n\nfunction parseTsconfigJson(content: string): { include?: string[] } | null {\n try {\n return JSON.parse(content) as { include?: string[] };\n } catch {\n const withoutComments = content\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .replace(/^\\s*\\/\\/.*$/gm, \"\");\n const withoutTrailingCommas = withoutComments\n .replace(/,\\s*}/g, \"}\")\n .replace(/,\\s*]/g, \"]\");\n\n try {\n return JSON.parse(withoutTrailingCommas) as { include?: string[] };\n } catch {\n return null;\n }\n }\n}\n`;\n}\n\nfunction buildEmptyMcpTypesContent(): string {\n return `${GENERATED_MCP_HEADER}import \"@kalphq/sdk\";\n\ndeclare module \"@kalphq/sdk\" {\n interface McpRegistry {}\n}\n`;\n}\n\nexport async function writeMcpTypes(cwd: string, content: string): Promise<string> {\n const kalpDir = join(cwd, \".kalp\");\n const mcpTypesPath = join(kalpDir, \"mcp.types.d.ts\");\n await mkdir(kalpDir, { recursive: true });\n await writeFile(mcpTypesPath, content, \"utf-8\");\n await updateKalpDts(cwd);\n await updateTsconfig(cwd);\n return mcpTypesPath;\n}\n\nasync function ensureMcpTypesFile(cwd: string): Promise<void> {\n const kalpDir = join(cwd, \".kalp\");\n const mcpTypesPath = join(kalpDir, \"mcp.types.d.ts\");\n\n try {\n await access(mcpTypesPath);\n return;\n } catch {\n await writeMcpTypes(cwd, buildEmptyMcpTypesContent());\n }\n}\n\n/**\n * Generate .kalp/types.d.ts and ensure local module augmentations are wired.\n */\nexport async function generateTypes(cwd: string): Promise<void> {\n const kalpDir = join(cwd, \".kalp\");\n const typesPath = join(kalpDir, \"types.d.ts\");\n const config = await readConfigForTypes(cwd);\n\n await mkdir(kalpDir, { recursive: true });\n\n const typesContent = `${GENERATED_HEADER}/**\n * Registered secrets from kalp.config.ts\n * @generated\n */\nexport type RegisteredSecretKeys = ${toStringTuple(config.secrets)};\n\n/**\n * AI provider resolved from kalp.config.ts\n * @generated\n */\nexport type ConfiguredAIProvider = ${JSON.stringify(config.provider)};\n\n/**\n * Custom model suggestions resolved from kalp.config.ts\n * @generated\n */\nexport type ConfiguredAICustomModels = ${toStringTuple(config.customModels)};\n`;\n\n await writeFile(typesPath, typesContent, \"utf-8\");\n await ensureMcpTypesFile(cwd);\n await updateKalpDts(cwd);\n await updateTsconfig(cwd);\n}\n\n/**\n * Ensure kalp.d.ts exists and contains SDK module augmentations.\n */\nexport async function updateKalpDts(cwd: string): Promise<void> {\n const kalpDtsPath = join(cwd, \"kalp.d.ts\");\n const content = buildKalpDtsContent();\n\n try {\n await access(kalpDtsPath);\n const current = await readFile(kalpDtsPath, \"utf-8\");\n if (current.trim() === content.trim()) {\n return;\n }\n } catch {\n // file does not exist yet\n }\n\n await writeFile(kalpDtsPath, content, \"utf-8\");\n}\n\n/**\n * Ensure tsconfig includes kalp.d.ts and generated .kalp types.\n */\nexport async function updateTsconfig(cwd: string): Promise<void> {\n const tsconfigPath = join(cwd, \"tsconfig.json\");\n\n try {\n const content = await readFile(tsconfigPath, \"utf-8\");\n const config = parseTsconfigJson(content);\n if (!config) return;\n\n if (!Array.isArray(config.include)) {\n config.include = [];\n }\n\n const required = [\"kalp.d.ts\", \".kalp/types.d.ts\", \".kalp/mcp.types.d.ts\"];\n for (const includePath of required) {\n if (!config.include.includes(includePath)) {\n config.include.push(includePath);\n }\n }\n\n await writeFile(tsconfigPath, JSON.stringify(config, null, 2), \"utf-8\");\n } catch {\n // no-op\n }\n}\n"],"mappings":"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","names":[]}
|