@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.
Files changed (56) hide show
  1. package/dist/{add-CTF5QIGY.js → add-YZSIMRPC.js} +6 -5
  2. package/dist/{add-CTF5QIGY.js.map → add-YZSIMRPC.js.map} +1 -1
  3. package/dist/{agents-NN2FLBZM.js → agents-WYK6WNQP.js} +3 -3
  4. package/dist/{chunk-TPG7QMXB.js → chunk-4CEJYSJY.js} +11 -9
  5. package/dist/{chunk-TPG7QMXB.js.map → chunk-4CEJYSJY.js.map} +1 -1
  6. package/dist/chunk-EXXTCGKR.js +77 -0
  7. package/dist/chunk-EXXTCGKR.js.map +1 -0
  8. package/dist/{chunk-FP3ZLBYT.js → chunk-IZXCZ3IA.js} +2 -2
  9. package/dist/chunk-LPEV4QH2.js +208 -0
  10. package/dist/chunk-LPEV4QH2.js.map +1 -0
  11. package/dist/{chunk-DHCCSWJN.js → chunk-XVD3FFOJ.js} +37 -104
  12. package/dist/chunk-XVD3FFOJ.js.map +1 -0
  13. package/dist/{chunk-EHNC6ITP.js → chunk-YE2SFYAJ.js} +10 -1
  14. package/dist/chunk-YE2SFYAJ.js.map +1 -0
  15. package/dist/{create-XC55BUCS.js → create-UCJ77P62.js} +6 -1
  16. package/dist/create-UCJ77P62.js.map +1 -0
  17. package/dist/{delete-BQFFYYWZ.js → delete-FIXMFFNZ.js} +6 -5
  18. package/dist/{delete-BQFFYYWZ.js.map → delete-FIXMFFNZ.js.map} +1 -1
  19. package/dist/{delete-LW2G4GCN.js → delete-QPYVL4OU.js} +7 -6
  20. package/dist/{delete-LW2G4GCN.js.map → delete-QPYVL4OU.js.map} +1 -1
  21. package/dist/{deploy-2JMOUTWG.js → deploy-DRZZ3YRB.js} +8 -3
  22. package/dist/deploy-DRZZ3YRB.js.map +1 -0
  23. package/dist/{dev-X43HHIYV.js → dev-5YY6W4WM.js} +7 -2
  24. package/dist/dev-5YY6W4WM.js.map +1 -0
  25. package/dist/generate-JW2DMJ3W.js +391 -0
  26. package/dist/generate-JW2DMJ3W.js.map +1 -0
  27. package/dist/index.js +10 -7
  28. package/dist/index.js.map +1 -1
  29. package/dist/{list-5RQZ3JVG.js → list-FKH4DWCF.js} +4 -3
  30. package/dist/{list-5RQZ3JVG.js.map → list-FKH4DWCF.js.map} +1 -1
  31. package/dist/{list-JXR4IULK.js → list-GZBBOFX5.js} +29 -9
  32. package/dist/list-GZBBOFX5.js.map +1 -0
  33. package/dist/mcp-DRMQYA7E.js +39 -0
  34. package/dist/mcp-DRMQYA7E.js.map +1 -0
  35. package/dist/pull-V7QJBVNZ.js +83 -0
  36. package/dist/pull-V7QJBVNZ.js.map +1 -0
  37. package/dist/{push-WHPQXAY7.js → push-P6CKRYT7.js} +13 -8
  38. package/dist/push-P6CKRYT7.js.map +1 -0
  39. package/dist/{secrets-Z53FLH56.js → secrets-M43LLCTB.js} +9 -5
  40. package/dist/secrets-M43LLCTB.js.map +1 -0
  41. package/dist/{sync-RPXLLOTK.js → sync-LTBH6DI5.js} +19 -7
  42. package/dist/sync-LTBH6DI5.js.map +1 -0
  43. package/package.json +5 -4
  44. package/dist/chunk-DHCCSWJN.js.map +0 -1
  45. package/dist/chunk-EHNC6ITP.js.map +0 -1
  46. package/dist/chunk-MMS3GWBG.js +0 -50
  47. package/dist/chunk-MMS3GWBG.js.map +0 -1
  48. package/dist/create-XC55BUCS.js.map +0 -1
  49. package/dist/deploy-2JMOUTWG.js.map +0 -1
  50. package/dist/dev-X43HHIYV.js.map +0 -1
  51. package/dist/list-JXR4IULK.js.map +0 -1
  52. package/dist/push-WHPQXAY7.js.map +0 -1
  53. package/dist/secrets-Z53FLH56.js.map +0 -1
  54. package/dist/sync-RPXLLOTK.js.map +0 -1
  55. /package/dist/{agents-NN2FLBZM.js.map → agents-WYK6WNQP.js.map} +0 -0
  56. /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-MMS3GWBG.js";
4
+ } from "./chunk-LPEV4QH2.js";
5
5
  import {
6
6
  mergeSecrets,
7
7
  readLocalSecretsFromConfig,
8
8
  writeLocalSecretsToConfig
9
- } from "./chunk-EHNC6ITP.js";
9
+ } from "./chunk-YE2SFYAJ.js";
10
10
  import {
11
11
  resolveSecretsRuntimeConfigPath
12
- } from "./chunk-FP3ZLBYT.js";
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-DHCCSWJN.js";
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-CTF5QIGY.js.map
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":"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","names":["spinner"]}
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-5RQZ3JVG.js").then((r) => r.default),
23
- delete: () => import("./delete-LW2G4GCN.js").then((r) => r.default)
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-NN2FLBZM.js.map
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-DHCCSWJN.js";
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-TPG7QMXB.js.map
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":"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","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-DHCCSWJN.js";
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-FP3ZLBYT.js.map
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":[]}