@kalphq/cli 0.0.0-dev-20260512233019 → 0.0.0-dev-20260513001643
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/chunk-63JREECU.js +742 -0
- package/dist/chunk-63JREECU.js.map +1 -0
- package/dist/{chunk-6WQW3UVW.js → chunk-PY6VAS54.js} +36 -56
- package/dist/chunk-PY6VAS54.js.map +1 -0
- package/dist/{deploy-ABYREUMX.js → deploy-Z2R7ER7U.js} +8 -5
- package/dist/deploy-Z2R7ER7U.js.map +1 -0
- package/dist/{dev-Q3UX3HY2.js → dev-PNRWXULV.js} +2 -2
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/{push-EXOBRO5V.js → push-SVABM7WN.js} +4 -3
- package/dist/push-SVABM7WN.js.map +1 -0
- package/dist/runtime-template/worker-entry.js +169 -3
- package/package.json +4 -4
- package/dist/chunk-6WQW3UVW.js.map +0 -1
- package/dist/chunk-WMQSBT64.js +0 -423
- package/dist/chunk-WMQSBT64.js.map +0 -1
- package/dist/deploy-ABYREUMX.js.map +0 -1
- package/dist/push-EXOBRO5V.js.map +0 -1
- /package/dist/{dev-Q3UX3HY2.js.map → dev-PNRWXULV.js.map} +0 -0
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { DurableObject } from "cloudflare:workers";
|
|
2
2
|
import { Hono } from "hono";
|
|
3
3
|
import { deleteCookie, getSignedCookie, setSignedCookie } from "hono/cookie";
|
|
4
|
+
import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
4
5
|
import agentsSnapshot from "./agents.snapshot.json";
|
|
6
|
+
import identityConfig from "./identity.config.json";
|
|
7
|
+
import mapIdentity from "./identity.map.mjs";
|
|
5
8
|
|
|
6
9
|
const SESSION_COOKIE_NAME = "kalp_studio_session";
|
|
7
10
|
const SESSION_MAX_AGE_SECONDS = 60 * 60 * 8;
|
|
@@ -10,6 +13,71 @@ const CORS_HEADERS = {
|
|
|
10
13
|
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
11
14
|
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
12
15
|
};
|
|
16
|
+
const JWKS_RESOLVER_CACHE = new Map();
|
|
17
|
+
|
|
18
|
+
function extractBearerToken(authorization) {
|
|
19
|
+
if (!authorization) return null;
|
|
20
|
+
const value = authorization.trim();
|
|
21
|
+
if (!value) return null;
|
|
22
|
+
const match = value.match(/^Bearer\s+(.+)$/i);
|
|
23
|
+
if (!match || !match[1]) return null;
|
|
24
|
+
const token = match[1].trim();
|
|
25
|
+
return token || null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function normalizeHeaderRecord(request) {
|
|
29
|
+
const headers = {};
|
|
30
|
+
for (const [key, value] of request.headers.entries()) {
|
|
31
|
+
headers[key.toLowerCase()] = value;
|
|
32
|
+
}
|
|
33
|
+
return headers;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function toMappedIdentity(payload, request) {
|
|
37
|
+
const rawHeaders = normalizeHeaderRecord(request);
|
|
38
|
+
try {
|
|
39
|
+
const mapped = mapIdentity(payload, rawHeaders);
|
|
40
|
+
if (
|
|
41
|
+
mapped &&
|
|
42
|
+
typeof mapped === "object" &&
|
|
43
|
+
typeof mapped.userId === "string" &&
|
|
44
|
+
mapped.userId.length > 0
|
|
45
|
+
) {
|
|
46
|
+
return {
|
|
47
|
+
userId: mapped.userId,
|
|
48
|
+
email: mapped.email,
|
|
49
|
+
name: mapped.name,
|
|
50
|
+
claims:
|
|
51
|
+
mapped.claims && typeof mapped.claims === "object" ? mapped.claims : {},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
} catch {}
|
|
55
|
+
|
|
56
|
+
const sub =
|
|
57
|
+
payload && typeof payload === "object" && typeof payload.sub === "string"
|
|
58
|
+
? payload.sub
|
|
59
|
+
: "anonymous";
|
|
60
|
+
return { userId: sub, claims: {} };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function resolveSymmetricSecret(env, secretEnvKey) {
|
|
64
|
+
const key = secretEnvKey && secretEnvKey.trim() ? secretEnvKey.trim() : "JWT_SIGNING_SECRET";
|
|
65
|
+
const selected = env[key];
|
|
66
|
+
if (typeof selected === "string" && selected.trim()) return selected.trim();
|
|
67
|
+
if (key !== "JWT_SIGNING_SECRET") {
|
|
68
|
+
const fallback = env.JWT_SIGNING_SECRET;
|
|
69
|
+
if (typeof fallback === "string" && fallback.trim()) return fallback.trim();
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getJwksResolver(jwksUrl) {
|
|
75
|
+
const cached = JWKS_RESOLVER_CACHE.get(jwksUrl);
|
|
76
|
+
if (cached) return cached;
|
|
77
|
+
const resolver = createRemoteJWKSet(new URL(jwksUrl));
|
|
78
|
+
JWKS_RESOLVER_CACHE.set(jwksUrl, resolver);
|
|
79
|
+
return resolver;
|
|
80
|
+
}
|
|
13
81
|
|
|
14
82
|
function withCors(response) {
|
|
15
83
|
if (response.status === 101) return response;
|
|
@@ -92,6 +160,78 @@ async function requireSession(c, next) {
|
|
|
92
160
|
return next();
|
|
93
161
|
}
|
|
94
162
|
|
|
163
|
+
async function verifyGatewayAuth(c) {
|
|
164
|
+
const enforce = identityConfig?.enforceGlobalAuth !== false;
|
|
165
|
+
if (!enforce) {
|
|
166
|
+
return { userId: "anonymous", claims: {}, providerId: "none" };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const token = extractBearerToken(c.req.header("Authorization"));
|
|
170
|
+
|
|
171
|
+
const serviceKey = c.env.KALP_SERVICE_KEY?.trim();
|
|
172
|
+
if (serviceKey && token && token === serviceKey) {
|
|
173
|
+
return {
|
|
174
|
+
userId: "service-admin",
|
|
175
|
+
providerId: "service-key",
|
|
176
|
+
claims: { role: "service_admin", service: true },
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const strategy = identityConfig?.strategy;
|
|
181
|
+
if (!strategy) return null;
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
if (strategy.type === "jwks") {
|
|
185
|
+
if (!token) return null;
|
|
186
|
+
if (!strategy.jwksUrl) return null;
|
|
187
|
+
const resolver = getJwksResolver(strategy.jwksUrl);
|
|
188
|
+
const options = {};
|
|
189
|
+
if (strategy.issuer) options.issuer = strategy.issuer;
|
|
190
|
+
if (strategy.audience) options.audience = strategy.audience;
|
|
191
|
+
const { payload } = await jwtVerify(token, resolver, options);
|
|
192
|
+
return {
|
|
193
|
+
...toMappedIdentity(payload, c.req.raw),
|
|
194
|
+
providerId: identityConfig.identityId ?? "identity",
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (strategy.type === "symmetric") {
|
|
199
|
+
if (!token) return null;
|
|
200
|
+
const secret = resolveSymmetricSecret(c.env, strategy.secretEnvKey);
|
|
201
|
+
if (!secret) return null;
|
|
202
|
+
const encoded = new TextEncoder().encode(secret);
|
|
203
|
+
const { payload } = await jwtVerify(token, encoded, {
|
|
204
|
+
algorithms: ["HS256"],
|
|
205
|
+
});
|
|
206
|
+
return {
|
|
207
|
+
...toMappedIdentity(payload, c.req.raw),
|
|
208
|
+
providerId: identityConfig.identityId ?? "identity",
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (strategy.type === "apiKey") {
|
|
213
|
+
const headerName = (strategy.headerName || "x-api-key").toLowerCase();
|
|
214
|
+
const envKey = strategy.envKey || "KALP_API_KEY";
|
|
215
|
+
const expected =
|
|
216
|
+
typeof c.env[envKey] === "string" ? c.env[envKey].trim() : "";
|
|
217
|
+
if (!expected) return null;
|
|
218
|
+
const provided =
|
|
219
|
+
c.req.header(headerName)?.trim() ??
|
|
220
|
+
(headerName === "authorization" ? token : null);
|
|
221
|
+
if (!provided || provided !== expected) return null;
|
|
222
|
+
return {
|
|
223
|
+
userId: "api-key-client",
|
|
224
|
+
providerId: identityConfig.identityId ?? "identity",
|
|
225
|
+
claims: { role: "api_key" },
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
} catch {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
|
|
95
235
|
function mapIndexToStudioAgents(entries) {
|
|
96
236
|
return entries.map((entry) => ({
|
|
97
237
|
name: entry.name,
|
|
@@ -124,6 +264,16 @@ async function readLatestManifest(env, agentName) {
|
|
|
124
264
|
}
|
|
125
265
|
}
|
|
126
266
|
|
|
267
|
+
async function resolveAgentAccess(env, agentName, routeKey) {
|
|
268
|
+
const manifest = await readLatestManifest(env, agentName);
|
|
269
|
+
const metadata = manifest?.metadata || {};
|
|
270
|
+
const routePublic = metadata.routesPublic
|
|
271
|
+
? metadata.routesPublic[routeKey]
|
|
272
|
+
: undefined;
|
|
273
|
+
const agentPublic = metadata.public ?? false;
|
|
274
|
+
return { isPublic: routePublic !== undefined ? routePublic : agentPublic };
|
|
275
|
+
}
|
|
276
|
+
|
|
127
277
|
export class AgentDurableObject extends DurableObject {
|
|
128
278
|
constructor(ctx, env) {
|
|
129
279
|
super(ctx, env);
|
|
@@ -216,9 +366,19 @@ function getAgentRouting(url) {
|
|
|
216
366
|
};
|
|
217
367
|
}
|
|
218
368
|
|
|
219
|
-
async function forwardToAgentDO(request, env) {
|
|
369
|
+
async function forwardToAgentDO(c, request, env) {
|
|
220
370
|
const url = new URL(request.url);
|
|
221
371
|
const { agentName, passthroughPath } = getAgentRouting(url);
|
|
372
|
+
const routeKey = `${request.method.toUpperCase()}:${passthroughPath === "/" ? "/" : passthroughPath}`;
|
|
373
|
+
const access = await resolveAgentAccess(env, agentName, routeKey);
|
|
374
|
+
let identity = null;
|
|
375
|
+
if (!access.isPublic) {
|
|
376
|
+
identity = await verifyGatewayAuth(c);
|
|
377
|
+
if (!identity) {
|
|
378
|
+
return c.json({ ok: false, error: "Unauthorized" }, 401);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
222
382
|
const id = env.KALP_RUNTIME_CLOUDFLARE.idFromName(agentName);
|
|
223
383
|
const stub = env.KALP_RUNTIME_CLOUDFLARE.get(id);
|
|
224
384
|
|
|
@@ -226,6 +386,12 @@ async function forwardToAgentDO(request, env) {
|
|
|
226
386
|
proxiedUrl.pathname = passthroughPath === "/" ? "/" : passthroughPath;
|
|
227
387
|
const headers = new Headers(request.headers);
|
|
228
388
|
headers.set("x-kalp-agent-name", agentName);
|
|
389
|
+
headers.set("x-kalp-route-public", String(access.isPublic));
|
|
390
|
+
if (identity && identity.userId) {
|
|
391
|
+
headers.set("x-kalp-auth-user-id", identity.userId);
|
|
392
|
+
headers.set("x-kalp-auth-provider-id", identity.providerId ?? "identity");
|
|
393
|
+
headers.set("x-kalp-auth-claims", JSON.stringify(identity.claims ?? {}));
|
|
394
|
+
}
|
|
229
395
|
|
|
230
396
|
const proxyRequest = new Request(proxiedUrl.toString(), {
|
|
231
397
|
method: request.method,
|
|
@@ -376,11 +542,11 @@ app.get("/api/internal/events/:executionId", (c) => {
|
|
|
376
542
|
});
|
|
377
543
|
|
|
378
544
|
app.all("/a/:agentName/*", async (c) => {
|
|
379
|
-
return forwardToAgentDO(c.req.raw, c.env);
|
|
545
|
+
return forwardToAgentDO(c, c.req.raw, c.env);
|
|
380
546
|
});
|
|
381
547
|
|
|
382
548
|
app.all("/a/:agentName", async (c) => {
|
|
383
|
-
return forwardToAgentDO(c.req.raw, c.env);
|
|
549
|
+
return forwardToAgentDO(c, c.req.raw, c.env);
|
|
384
550
|
});
|
|
385
551
|
|
|
386
552
|
app.get("/studio", (c) => c.redirect("/studio/", 308));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kalphq/cli",
|
|
3
|
-
"version": "0.0.0-dev-
|
|
3
|
+
"version": "0.0.0-dev-20260513001643",
|
|
4
4
|
"description": "Zero-config CLI for deploying Kalp agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"open": "^11.0.0",
|
|
28
28
|
"picocolors": "1.1.1",
|
|
29
29
|
"zod": "3.25.76",
|
|
30
|
-
"@kalphq/compiler": "0.0.0-dev-
|
|
31
|
-
"@kalphq/
|
|
32
|
-
"@kalphq/
|
|
30
|
+
"@kalphq/compiler": "0.0.0-dev-20260513001643",
|
|
31
|
+
"@kalphq/sdk": "0.0.0-dev-20260513001643",
|
|
32
|
+
"@kalphq/project": "0.0.0-dev-20260513001643"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/json-stable-stringify": "1.2.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/deploy.ts","../src/utils/ai.ts"],"sourcesContent":["import { readFile, writeFile } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport { execa } from \"execa\";\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 { resolveProvider } from \"@/utils/providers\";\n\nfunction findWorkersUrl(output: string): string | null {\n const match = output.match(/https:\\/\\/[^\\s]+\\.workers\\.dev/);\n return match?.[0] ?? null;\n}\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\nfunction parseKvListOutput(stdout: string): KvNamespaceInfo[] {\n const trimmed = stdout.trim();\n if (!trimmed) return [];\n\n try {\n const parsed = JSON.parse(trimmed);\n if (Array.isArray(parsed)) {\n return parsed\n .map((item) => ({\n id: String((item as { id?: string }).id ?? \"\"),\n title: String((item as { title?: string }).title ?? \"\"),\n }))\n .filter((item) => !!item.id && !!item.title);\n }\n } catch {\n // fallback to text parsing below\n }\n\n const matches = trimmed.match(/[a-f0-9]{32}\\s+[^\\r\\n]+/gi) ?? [];\n return matches\n .map((line) => {\n const [id, ...rest] = line.trim().split(/\\s+/g);\n return { id: id ?? \"\", title: rest.join(\" \") };\n })\n .filter((item) => !!item.id && !!item.title);\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\nasync function resolveWorkerUrl(\n configPath: string,\n deployOutput: string,\n): Promise<string> {\n const fromOutput = findWorkersUrl(deployOutput);\n if (fromOutput) return fromOutput;\n\n const configText = await readFile(configPath, \"utf-8\").catch(\n () => null as string | null,\n );\n const workerName = configText?.match(/\"name\"\\s*:\\s*\"([^\"]+)\"/)?.[1];\n\n if (workerName) {\n return `https://${workerName}.workers.dev`;\n }\n\n throw new Error(\"Could not resolve worker URL from wrangler deploy output.\");\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 credentialsChanged: boolean;\n}> {\n const auth = await requireAuth();\n const aiProvider = await resolveProviderFromConfig(cwd);\n const requiredProviderSecret = getRequiredSecretForProvider(aiProvider);\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 secrets = await ensureStudioSecrets(cwd);\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 [requiredProviderSecret, providerSecretValue],\n ] as const;\n\n for (const [name, value] of secretEntries) {\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 const deployArgs = secretSyncFailed\n ? [\n \"wrangler\",\n \"deploy\",\n \"--config\",\n runtime.wranglerConfigPath,\n \"--secrets-file\",\n \".env\",\n ]\n : [\"wrangler\", \"deploy\", \"--config\", runtime.wranglerConfigPath];\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\n await writeProjectState(cwd, {\n workerUrl,\n deployedAt: new Date().toISOString(),\n accountId: auth.accountId,\n studioCredentialsFingerprint: credentialsFingerprint,\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 credentialsChanged,\n };\n}\n","import { access, readFile } from \"node:fs/promises\";\nimport { constants } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createJiti } from \"jiti\";\n\nexport type AIProvider = \"openai\" | \"anthropic\" | \"openrouter\" | \"custom\";\n\nconst PROVIDER_SECRET_MAP: Record<AIProvider, string> = {\n openai: \"OPENAI_API_KEY\",\n anthropic: \"ANTHROPIC_API_KEY\",\n openrouter: \"OPENROUTER_API_KEY\",\n custom: \"CUSTOM_AI_API_KEY\",\n};\n\nfunction parseEnv(content: string): Record<string, string> {\n const env: Record<string, string> = {};\n for (const raw of content.split(/\\r?\\n/g)) {\n const line = raw.trim();\n if (!line || line.startsWith(\"#\")) continue;\n const idx = line.indexOf(\"=\");\n if (idx <= 0) continue;\n env[line.slice(0, idx).trim()] = line.slice(idx + 1);\n }\n return env;\n}\n\nexport async function resolveProviderFromConfig(cwd: string): Promise<AIProvider> {\n const configPath = join(cwd, \"kalp.config.ts\");\n await access(configPath, constants.F_OK);\n const jiti = createJiti(cwd, { interopDefault: true });\n const config = (await jiti.import(configPath)) as\n | { default?: { ai?: { provider?: AIProvider } }; ai?: { provider?: AIProvider } }\n | undefined;\n const provider = config?.default?.ai?.provider ?? config?.ai?.provider ?? \"openai\";\n return provider;\n}\n\nexport async function readDotEnv(cwd: string): Promise<Record<string, string>> {\n const envPath = join(cwd, \".env\");\n const content = await readFile(envPath, \"utf-8\").catch(() => \"\");\n return parseEnv(content);\n}\n\nexport function getRequiredSecretForProvider(provider: AIProvider): string {\n return PROVIDER_SECRET_MAP[provider];\n}\n"],"mappings":"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","names":["readFile","readFile"]}
|