@kalphq/cli 0.0.0-dev-20260420023403 → 0.1.0
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-5NOYFTJV.js → add-UCN5EAL3.js} +37 -5
- package/dist/add-UCN5EAL3.js.map +1 -0
- package/dist/{chunk-CJCIZDCF.js → chunk-EAMMDUE3.js} +24 -24
- package/dist/chunk-EAMMDUE3.js.map +1 -0
- package/dist/{chunk-HD5FT7T6.js → chunk-MECZEYSU.js} +165 -78
- package/dist/chunk-MECZEYSU.js.map +1 -0
- package/dist/{chunk-Q455HC3P.js → chunk-TPTPZH2W.js} +6 -10
- package/dist/chunk-TPTPZH2W.js.map +1 -0
- package/dist/{create-RSQEKCI6.js → create-PENWHZ26.js} +4 -8
- package/dist/create-PENWHZ26.js.map +1 -0
- package/dist/{delete-ZJB2JGAL.js → delete-6MKUQ3XK.js} +26 -1
- package/dist/delete-6MKUQ3XK.js.map +1 -0
- package/dist/index.js +9 -9
- package/dist/index.js.map +1 -1
- package/dist/{init-CUBJEWPE.js → init-WOEW2QED.js} +3 -3
- package/dist/link-YCIA4JJ3.js +37 -0
- package/dist/link-YCIA4JJ3.js.map +1 -0
- package/dist/login-22HHVS52.js +39 -0
- package/dist/login-22HHVS52.js.map +1 -0
- package/dist/logout-OJM3VAOF.js +32 -0
- package/dist/logout-OJM3VAOF.js.map +1 -0
- package/dist/{build-SUIPVJO6.js → migrate-GA7EHSDG.js} +14 -14
- package/dist/migrate-GA7EHSDG.js.map +1 -0
- package/dist/{push-L3BXB6OC.js → push-2B4NWFGC.js} +10 -8
- package/dist/push-2B4NWFGC.js.map +1 -0
- package/dist/secrets-SIK6J5AF.js +46 -0
- package/dist/secrets-SIK6J5AF.js.map +1 -0
- package/package.json +2 -2
- package/dist/add-5NOYFTJV.js.map +0 -1
- package/dist/build-SUIPVJO6.js.map +0 -1
- package/dist/chunk-CJCIZDCF.js.map +0 -1
- package/dist/chunk-HD5FT7T6.js.map +0 -1
- package/dist/chunk-Q455HC3P.js.map +0 -1
- package/dist/create-RSQEKCI6.js.map +0 -1
- package/dist/delete-ZJB2JGAL.js.map +0 -1
- package/dist/link-YKDZ7Y6K.js +0 -23
- package/dist/link-YKDZ7Y6K.js.map +0 -1
- package/dist/login-LBEXP7ET.js +0 -27
- package/dist/login-LBEXP7ET.js.map +0 -1
- package/dist/logout-S3PV4WE7.js +0 -27
- package/dist/logout-S3PV4WE7.js.map +0 -1
- package/dist/push-L3BXB6OC.js.map +0 -1
- package/dist/secrets-3SKCSAGD.js +0 -33
- package/dist/secrets-3SKCSAGD.js.map +0 -1
- /package/dist/{init-CUBJEWPE.js.map → init-WOEW2QED.js.map} +0 -0
- /package/templates/project/meta/{manifest-registry.json → snapshot.json} +0 -0
|
@@ -30,15 +30,46 @@ async function addSecretToLocalConfig(cwd, key) {
|
|
|
30
30
|
if (!match) {
|
|
31
31
|
throw new Error("Could not find secrets array in kalp.config.ts");
|
|
32
32
|
}
|
|
33
|
-
const currentArray = match[1]?.trim();
|
|
34
|
-
if (!currentArray) {
|
|
35
|
-
throw new Error("Secrets array is empty in kalp.config.ts");
|
|
36
|
-
}
|
|
33
|
+
const currentArray = match[1]?.trim() ?? "";
|
|
37
34
|
const newSecret = currentArray.length > 0 ? `, "${key}"` : `"${key}"`;
|
|
38
35
|
const newArray = `secrets: [${currentArray}${newSecret}]`;
|
|
39
36
|
content = content.replace(/secrets:\s*\[([^\]]*)\]/, newArray);
|
|
40
37
|
await writeFile(configPath, content, "utf-8");
|
|
41
38
|
}
|
|
39
|
+
async function addSecretToTypes(cwd, key) {
|
|
40
|
+
const dtsPath = join(cwd, "kalp.d.ts");
|
|
41
|
+
let content;
|
|
42
|
+
try {
|
|
43
|
+
content = await readFile(dtsPath, "utf-8");
|
|
44
|
+
} catch {
|
|
45
|
+
content = `import "@kalphq/sdk";
|
|
46
|
+
|
|
47
|
+
declare module "@kalphq/sdk" {
|
|
48
|
+
interface SecretsRegistry {
|
|
49
|
+
keys: [];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
}
|
|
54
|
+
if (content.includes(`"${key}"`)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const match = content.match(/keys:\s*\[([^\]]*)\]/);
|
|
58
|
+
if (!match) {
|
|
59
|
+
throw new Error("Could not find keys array in kalp.d.ts");
|
|
60
|
+
}
|
|
61
|
+
const currentArray = match[1]?.trim();
|
|
62
|
+
if (!currentArray || currentArray.length === 0) {
|
|
63
|
+
content = content.replace(/keys:\s*\[\s*\]/, `keys: ["${key}"]`);
|
|
64
|
+
} else {
|
|
65
|
+
const newKey = `, "${key}"`;
|
|
66
|
+
content = content.replace(
|
|
67
|
+
/keys:\s*\[([^\]]*)\]/,
|
|
68
|
+
`keys: [${currentArray}${newKey}]`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
await writeFile(dtsPath, content, "utf-8");
|
|
72
|
+
}
|
|
42
73
|
var add_default = defineCommand({
|
|
43
74
|
meta: {
|
|
44
75
|
name: "add",
|
|
@@ -113,6 +144,7 @@ var add_default = defineCommand({
|
|
|
113
144
|
try {
|
|
114
145
|
await addSecretToCloud(key, value);
|
|
115
146
|
await addSecretToLocalConfig(cwd, key);
|
|
147
|
+
await addSecretToTypes(cwd, key);
|
|
116
148
|
s.stop(`Secret ${pc.cyan(key)} added successfully`);
|
|
117
149
|
p.outro("Done");
|
|
118
150
|
} catch (error) {
|
|
@@ -130,4 +162,4 @@ var add_default = defineCommand({
|
|
|
130
162
|
export {
|
|
131
163
|
add_default as default
|
|
132
164
|
};
|
|
133
|
-
//# sourceMappingURL=add-
|
|
165
|
+
//# sourceMappingURL=add-UCN5EAL3.js.map
|
|
@@ -0,0 +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 { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { getAuthToken } from \"../../utils/auth.js\";\n\nconst LOGO = \"🦋\";\n\nasync function addSecretToCloud(key: string, value: string): Promise<void> {\n // TODO: Implement real API call to Kalp Cloud\n console.log(pc.dim(`[Simulated] Adding secret ${key} to Kalp Cloud...`));\n}\n\nasync function addSecretToLocalConfig(cwd: string, key: string): Promise<void> {\n const configPath = join(cwd, \"kalp.config.ts\");\n let content: string;\n\n try {\n content = await readFile(configPath, \"utf-8\");\n } catch {\n throw new Error(\"kalp.config.ts not found. Run `kalp init` first.\");\n }\n\n // Check if key already exists\n const regex = new RegExp(`[\"']${key}[\"']`);\n if (regex.test(content)) {\n throw new Error(`Secret ${key} already exists in kalp.config.ts`);\n }\n\n // Add secret to array\n const match = content.match(/secrets:\\s*\\[([^\\]]*)\\]/);\n if (!match) {\n throw new Error(\"Could not find secrets array in kalp.config.ts\");\n }\n\n const currentArray = match[1]?.trim() ?? \"\";\n\n const newSecret = currentArray.length > 0 ? `, \"${key}\"` : `\"${key}\"`;\n const newArray = `secrets: [${currentArray}${newSecret}]`;\n\n content = content.replace(/secrets:\\s*\\[([^\\]]*)\\]/, newArray);\n\n await writeFile(configPath, content, \"utf-8\");\n}\n\nasync function addSecretToTypes(cwd: string, key: string): Promise<void> {\n const dtsPath = join(cwd, \"kalp.d.ts\");\n let content: string;\n\n try {\n content = await readFile(dtsPath, \"utf-8\");\n } catch {\n // If file doesn't exist, create it\n content = `import \"@kalphq/sdk\";\n\n declare module \"@kalphq/sdk\" {\n interface SecretsRegistry {\n keys: [];\n }\n }\n `;\n }\n\n // Check if key already exists in types\n if (content.includes(`\"${key}\"`)) {\n return; // Already there, skip\n }\n\n // Add key to the keys tuple\n const match = content.match(/keys:\\s*\\[([^\\]]*)\\]/);\n if (!match) {\n throw new Error(\"Could not find keys array in kalp.d.ts\");\n }\n\n const currentArray = match[1]?.trim();\n\n if (!currentArray || currentArray.length === 0) {\n // Empty array, add first element\n content = content.replace(/keys:\\s*\\[\\s*\\]/, `keys: [\"${key}\"]`);\n } else {\n // Add to existing array\n const newKey = `, \"${key}\"`;\n content = content.replace(\n /keys:\\s*\\[([^\\]]*)\\]/,\n `keys: [${currentArray}${newKey}]`,\n );\n }\n\n await writeFile(dtsPath, content, \"utf-8\");\n}\n\nexport default defineCommand({\n meta: {\n name: \"add\",\n description: \"Add a secret to Kalp Cloud and local config\",\n },\n args: {\n key: {\n type: \"string\",\n alias: \"k\",\n description: \"Secret key name (e.g., STRIPE_SECRET_KEY)\",\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 p.log.info(\n pc.dim(\"Example: kalp secrets add -k STRIPE_SECRET_KEY -v sk_test_...\"),\n );\n return;\n }\n\n p.intro(`${LOGO} ${pc.bold(\"kalp secrets add\")}`);\n\n const token = await getAuthToken();\n if (!token) {\n p.log.warn(pc.yellow(\"Not logged in. Run `kalp login` first.\"));\n p.outro(\"Authentication required\");\n return;\n }\n\n let key = args.key;\n let value = args.value;\n\n // Interactive prompts if not provided\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 = input;\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 = input;\n }\n\n const s = p.spinner();\n s.start(`Adding ${pc.cyan(key)}...`);\n\n try {\n // Add to cloud (simulated)\n await addSecretToCloud(key, value);\n\n // Add to local config\n await addSecretToLocalConfig(cwd, key);\n\n // Add to types\n await addSecretToTypes(cwd, key);\n\n s.stop(`Secret ${pc.cyan(key)} added successfully`);\n p.outro(\"Done\");\n } catch (error) {\n s.stop(\"Failed to add secret\");\n p.log.error(\n pc.red(\n `Error: ${error instanceof Error ? error.message : String(error)}`,\n ),\n );\n p.outro(\"Failed\");\n process.exit(1);\n }\n },\n});\n"],"mappings":";;;;;;;AAAA,SAAS,qBAAqB;AAC9B,YAAY,OAAO;AACnB,OAAO,QAAQ;AACf,SAAS,UAAU,iBAAiB;AACpC,SAAS,YAAY;AAGrB,IAAM,OAAO;AAEb,eAAe,iBAAiB,KAAa,OAA8B;AAEzE,UAAQ,IAAI,GAAG,IAAI,6BAA6B,GAAG,mBAAmB,CAAC;AACzE;AAEA,eAAe,uBAAuB,KAAa,KAA4B;AAC7E,QAAM,aAAa,KAAK,KAAK,gBAAgB;AAC7C,MAAI;AAEJ,MAAI;AACF,cAAU,MAAM,SAAS,YAAY,OAAO;AAAA,EAC9C,QAAQ;AACN,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AAGA,QAAM,QAAQ,IAAI,OAAO,OAAO,GAAG,MAAM;AACzC,MAAI,MAAM,KAAK,OAAO,GAAG;AACvB,UAAM,IAAI,MAAM,UAAU,GAAG,mCAAmC;AAAA,EAClE;AAGA,QAAM,QAAQ,QAAQ,MAAM,yBAAyB;AACrD,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,QAAM,eAAe,MAAM,CAAC,GAAG,KAAK,KAAK;AAEzC,QAAM,YAAY,aAAa,SAAS,IAAI,MAAM,GAAG,MAAM,IAAI,GAAG;AAClE,QAAM,WAAW,aAAa,YAAY,GAAG,SAAS;AAEtD,YAAU,QAAQ,QAAQ,2BAA2B,QAAQ;AAE7D,QAAM,UAAU,YAAY,SAAS,OAAO;AAC9C;AAEA,eAAe,iBAAiB,KAAa,KAA4B;AACvE,QAAM,UAAU,KAAK,KAAK,WAAW;AACrC,MAAI;AAEJ,MAAI;AACF,cAAU,MAAM,SAAS,SAAS,OAAO;AAAA,EAC3C,QAAQ;AAEN,cAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQZ;AAGA,MAAI,QAAQ,SAAS,IAAI,GAAG,GAAG,GAAG;AAChC;AAAA,EACF;AAGA,QAAM,QAAQ,QAAQ,MAAM,sBAAsB;AAClD,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AAEA,QAAM,eAAe,MAAM,CAAC,GAAG,KAAK;AAEpC,MAAI,CAAC,gBAAgB,aAAa,WAAW,GAAG;AAE9C,cAAU,QAAQ,QAAQ,mBAAmB,WAAW,GAAG,IAAI;AAAA,EACjE,OAAO;AAEL,UAAM,SAAS,MAAM,GAAG;AACxB,cAAU,QAAQ;AAAA,MAChB;AAAA,MACA,UAAU,YAAY,GAAG,MAAM;AAAA,IACjC;AAAA,EACF;AAEA,QAAM,UAAU,SAAS,SAAS,OAAO;AAC3C;AAEA,IAAO,cAAQ,cAAc;AAAA,EAC3B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,MAAM;AAAA,IACJ,KAAK;AAAA,MACH,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACf;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACf;AAAA,IACA,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,MAAM,IAAI,EAAE,KAAK,GAAG;AAClB,UAAM,MAAM,QAAQ,IAAI;AAExB,QAAI,KAAK,MAAM;AACb,MAAE,MAAI,KAAK,GAAG,GAAG,KAAK,OAAO,CAAC,wCAAwC;AACtE,MAAE,MAAI;AAAA,QACJ,GAAG,IAAI,+DAA+D;AAAA,MACxE;AACA;AAAA,IACF;AAEA,IAAE,QAAM,GAAG,IAAI,IAAI,GAAG,KAAK,kBAAkB,CAAC,EAAE;AAEhD,UAAM,QAAQ,MAAM,aAAa;AACjC,QAAI,CAAC,OAAO;AACV,MAAE,MAAI,KAAK,GAAG,OAAO,wCAAwC,CAAC;AAC9D,MAAE,QAAM,yBAAyB;AACjC;AAAA,IACF;AAEA,QAAI,MAAM,KAAK;AACf,QAAI,QAAQ,KAAK;AAGjB,QAAI,CAAC,KAAK;AACR,YAAM,QAAQ,MAAQ,OAAK;AAAA,QACzB,SAAS;AAAA,QACT,aAAa;AAAA,QACb,UAAU,CAAC,MAAM;AACf,cAAI,CAAC,EAAG,QAAO;AACf,cAAI,CAAC,qBAAqB,KAAK,CAAC,GAAG;AACjC,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF,CAAC;AACD,UAAM,WAAS,KAAK,GAAG;AACrB,QAAE,QAAM,WAAW;AACnB;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAEA,QAAI,CAAC,OAAO;AACV,YAAM,QAAQ,MAAQ,WAAS;AAAA,QAC7B,SAAS,mBAAmB,GAAG;AAAA,QAC/B,MAAM;AAAA,MACR,CAAC;AACD,UAAM,WAAS,KAAK,GAAG;AACrB,QAAE,QAAM,WAAW;AACnB;AAAA,MACF;AACA,cAAQ;AAAA,IACV;AAEA,UAAM,IAAM,UAAQ;AACpB,MAAE,MAAM,UAAU,GAAG,KAAK,GAAG,CAAC,KAAK;AAEnC,QAAI;AAEF,YAAM,iBAAiB,KAAK,KAAK;AAGjC,YAAM,uBAAuB,KAAK,GAAG;AAGrC,YAAM,iBAAiB,KAAK,GAAG;AAE/B,QAAE,KAAK,UAAU,GAAG,KAAK,GAAG,CAAC,qBAAqB;AAClD,MAAE,QAAM,MAAM;AAAA,IAChB,SAAS,OAAO;AACd,QAAE,KAAK,sBAAsB;AAC7B,MAAE,MAAI;AAAA,QACJ,GAAG;AAAA,UACD,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAClE;AAAA,MACF;AACA,MAAE,QAAM,QAAQ;AAChB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF,CAAC;","names":[]}
|
|
@@ -195,7 +195,7 @@ function getHash(payload) {
|
|
|
195
195
|
return createHash("sha256").update(payload).digest("hex");
|
|
196
196
|
}
|
|
197
197
|
function isManifestVersionFile(fileName) {
|
|
198
|
-
return fileName.endsWith(".json")
|
|
198
|
+
return fileName.endsWith(".json");
|
|
199
199
|
}
|
|
200
200
|
function createVersionId(payload, generatedAt) {
|
|
201
201
|
return createHash("sha256").update(payload).update(generatedAt).digest("hex").slice(0, 8);
|
|
@@ -210,7 +210,7 @@ async function readManifestVersionFile(filePath) {
|
|
|
210
210
|
}
|
|
211
211
|
async function writeVersionedManifest(params) {
|
|
212
212
|
const { cwd, agentName, manifest } = params;
|
|
213
|
-
const agentMetaDir = join(cwd, "meta", "
|
|
213
|
+
const agentMetaDir = join(cwd, "meta", "migrations", agentName);
|
|
214
214
|
await mkdir(agentMetaDir, { recursive: true });
|
|
215
215
|
const files = await readdir(agentMetaDir);
|
|
216
216
|
const versionFiles = files.filter(isManifestVersionFile);
|
|
@@ -234,19 +234,14 @@ async function writeVersionedManifest(params) {
|
|
|
234
234
|
};
|
|
235
235
|
const versionFile = join(agentMetaDir, `${versionId}.json`);
|
|
236
236
|
await writeFile(versionFile, JSON.stringify(record, null, 2) + "\n", "utf-8");
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
"utf-8"
|
|
241
|
-
);
|
|
242
|
-
const registryPath = join(cwd, "meta", "manifest-registry.json");
|
|
243
|
-
const registry = await readManifestRegistry(registryPath);
|
|
244
|
-
const prev = registry[agentName] ?? { latest: "", versions: [] };
|
|
237
|
+
const snapshotPath = join(cwd, "meta", "snapshot.json");
|
|
238
|
+
const snapshot = await readSnapshot(snapshotPath);
|
|
239
|
+
const prev = snapshot[agentName] ?? { latest: "", versions: [] };
|
|
245
240
|
const versions = prev.versions.includes(versionId) ? prev.versions : [...prev.versions, versionId];
|
|
246
|
-
|
|
241
|
+
snapshot[agentName] = { latest: versionId, versions };
|
|
247
242
|
await writeFile(
|
|
248
|
-
|
|
249
|
-
JSON.stringify(
|
|
243
|
+
snapshotPath,
|
|
244
|
+
JSON.stringify(snapshot, null, 2) + "\n",
|
|
250
245
|
"utf-8"
|
|
251
246
|
);
|
|
252
247
|
return {
|
|
@@ -256,14 +251,19 @@ async function writeVersionedManifest(params) {
|
|
|
256
251
|
}
|
|
257
252
|
async function readLatestVersionedManifest(params) {
|
|
258
253
|
const { cwd, agentName } = params;
|
|
259
|
-
const agentMetaDir = join(cwd, "meta", "
|
|
260
|
-
const
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
254
|
+
const agentMetaDir = join(cwd, "meta", "migrations", agentName);
|
|
255
|
+
const snapshotPath = join(cwd, "meta", "snapshot.json");
|
|
256
|
+
const snapshot = await readSnapshot(snapshotPath);
|
|
257
|
+
const agentEntry = snapshot[agentName];
|
|
258
|
+
if (agentEntry?.latest) {
|
|
259
|
+
const latestFile = join(agentMetaDir, `${agentEntry.latest}.json`);
|
|
260
|
+
const latest = await readManifestVersionFile(latestFile);
|
|
261
|
+
if (latest) {
|
|
262
|
+
return {
|
|
263
|
+
...latest,
|
|
264
|
+
outputPath: latestFile
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
267
|
}
|
|
268
268
|
const files = await readdir(agentMetaDir).catch(() => []);
|
|
269
269
|
const records = (await Promise.all(
|
|
@@ -281,9 +281,9 @@ async function readLatestVersionedManifest(params) {
|
|
|
281
281
|
outputPath: join(agentMetaDir, `${newest.versionId}.json`)
|
|
282
282
|
};
|
|
283
283
|
}
|
|
284
|
-
async function
|
|
284
|
+
async function readSnapshot(snapshotPath) {
|
|
285
285
|
try {
|
|
286
|
-
const src = await readFile(
|
|
286
|
+
const src = await readFile(snapshotPath, "utf-8");
|
|
287
287
|
return JSON.parse(src);
|
|
288
288
|
} catch {
|
|
289
289
|
return {};
|
|
@@ -295,4 +295,4 @@ export {
|
|
|
295
295
|
writeVersionedManifest,
|
|
296
296
|
readLatestVersionedManifest
|
|
297
297
|
};
|
|
298
|
-
//# sourceMappingURL=chunk-
|
|
298
|
+
//# sourceMappingURL=chunk-EAMMDUE3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/manifest.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport {\n access,\n mkdtemp,\n mkdir,\n readFile,\n readdir,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { build } from \"esbuild\";\nimport type { ZodTypeAny } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nexport interface AgentManifestV1 {\n format: \"kalp-agent-manifest\";\n schemaVersion: 1;\n generatedAt: string;\n agent: {\n id?: string;\n name: string;\n description: string;\n systemPrompt:\n | { type: \"static\"; value: string }\n | { type: \"dynamic\" }\n | { type: \"none\" };\n lifecycle: {\n onInit: boolean;\n onMessage: boolean;\n onTick: boolean;\n };\n actions: {\n ai: boolean;\n wait: boolean;\n fetch: boolean;\n runStep: boolean;\n callTool: boolean;\n runFlow: boolean;\n };\n steps: Array<{\n id: string;\n order: number;\n description: string;\n inputSchema: Record<string, unknown> | null;\n outputSchema: Record<string, unknown> | null;\n }>;\n tools: Array<{\n id: string;\n order: number;\n description: string;\n inputSchema: Record<string, unknown> | null;\n }>;\n routes: Array<{\n id: string;\n order: number;\n method: string;\n path: string;\n inputSchema: Record<string, unknown> | null;\n }>;\n flows: Array<{\n id: string;\n order: number;\n description: string;\n steps: Array<{\n order: number;\n stepId: string;\n existsInAgentSteps: boolean;\n }>;\n }>;\n execution: {\n stepOrder: string[];\n toolOrder: string[];\n routeOrder: string[];\n flowOrder: string[];\n };\n };\n}\n\nexport interface ManifestVersionRecord {\n version: number;\n versionId: string;\n hash: string;\n generatedAt: string;\n immutable: true;\n manifest: AgentManifestV1;\n}\n\ninterface ManifestRegistryEntry {\n latest: string;\n versions: string[];\n}\n\ninterface LoadedAgentModule {\n agent: unknown;\n tempDir: string;\n}\n\ninterface AgentItemWithInput {\n id?: unknown;\n description?: unknown;\n input?: unknown;\n}\n\ninterface AgentStepItem extends AgentItemWithInput {\n output?: unknown;\n}\n\ninterface AgentRouteItem extends AgentItemWithInput {\n method?: unknown;\n path?: unknown;\n}\n\ninterface AgentFlowItem {\n id?: unknown;\n description?: unknown;\n steps?: unknown;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return typeof value === \"object\" && value !== null\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction asArray(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nfunction toJsonSchema(\n schema: unknown,\n name: string,\n): Record<string, unknown> | null {\n try {\n return zodToJsonSchema(schema as ZodTypeAny, name) as Record<\n string,\n unknown\n >;\n } catch {\n return null;\n }\n}\n\nfunction serializeSystemPrompt(\n systemPrompt: unknown,\n): AgentManifestV1[\"agent\"][\"systemPrompt\"] {\n if (typeof systemPrompt === \"string\") {\n return { type: \"static\", value: systemPrompt };\n }\n\n if (typeof systemPrompt === \"function\") {\n return { type: \"dynamic\" };\n }\n\n return { type: \"none\" };\n}\n\nfunction serializeSteps(steps: unknown[]): AgentManifestV1[\"agent\"][\"steps\"] {\n return steps.map((step, index) => {\n const item = asRecord(step) as AgentStepItem;\n return {\n id: asString(item.id) ?? `step_${index + 1}`,\n order: index + 1,\n description: asString(item.description) ?? \"\",\n inputSchema: toJsonSchema(item.input, `step_${index + 1}_input`),\n outputSchema: toJsonSchema(item.output, `step_${index + 1}_output`),\n };\n });\n}\n\nfunction serializeTools(tools: unknown[]): AgentManifestV1[\"agent\"][\"tools\"] {\n return tools.map((tool, index) => {\n const item = asRecord(tool) as AgentItemWithInput;\n return {\n id: asString(item.id) ?? `tool_${index + 1}`,\n order: index + 1,\n description: asString(item.description) ?? \"\",\n inputSchema: toJsonSchema(item.input, `tool_${index + 1}_input`),\n };\n });\n}\n\nfunction serializeRoutes(\n routes: unknown[],\n): AgentManifestV1[\"agent\"][\"routes\"] {\n return routes.map((route, index) => {\n const item = asRecord(route) as AgentRouteItem;\n return {\n id: asString(item.id) ?? `route_${index + 1}`,\n order: index + 1,\n method: asString(item.method) ?? \"GET\",\n path: asString(item.path) ?? \"/\",\n inputSchema: toJsonSchema(item.input, `route_${index + 1}_input`),\n };\n });\n}\n\nfunction serializeFlows(\n flows: unknown[],\n stepIds: Set<string>,\n): AgentManifestV1[\"agent\"][\"flows\"] {\n return flows.map((flow, index) => {\n const item = asRecord(flow) as AgentFlowItem;\n const steps = asArray(item.steps).map((s, stepIndex) => {\n const step = asRecord(s);\n const stepId = asString(step.id) ?? `step_${stepIndex + 1}`;\n return {\n order: stepIndex + 1,\n stepId,\n existsInAgentSteps: stepIds.has(stepId),\n };\n });\n\n return {\n id: asString(item.id) ?? `flow_${index + 1}`,\n order: index + 1,\n description: asString(item.description) ?? \"\",\n steps,\n };\n });\n}\n\nasync function loadAgentModule(\n agentPath: string,\n cwd: string,\n): Promise<LoadedAgentModule> {\n const tempDir = await mkdtemp(join(cwd, \".kalp-manifest-\"));\n const outFile = join(tempDir, \"agent.manifest.mjs\");\n\n await build({\n entryPoints: [agentPath],\n outfile: outFile,\n bundle: true,\n format: \"esm\",\n platform: \"node\",\n target: \"node18\",\n logLevel: \"silent\",\n packages: \"external\",\n plugins: [\n {\n name: \"relative-js-to-ts\",\n setup(buildCtx) {\n buildCtx.onResolve({ filter: /^\\.+\\/.*\\.js$/ }, (args) => {\n const resolved = resolve(args.resolveDir, args.path);\n if (existsSync(resolved)) {\n return { path: resolved };\n }\n\n const tsPath = resolved.replace(/\\.js$/, \".ts\");\n if (existsSync(tsPath)) {\n return { path: tsPath };\n }\n\n const tsxPath = resolved.replace(/\\.js$/, \".tsx\");\n if (existsSync(tsxPath)) {\n return { path: tsxPath };\n }\n\n return null;\n });\n },\n },\n ],\n });\n\n const loaded = (await import(\n `${pathToFileURL(outFile).href}?t=${Date.now()}`\n )) as { default?: unknown };\n\n return {\n agent: loaded.default,\n tempDir,\n };\n}\n\nexport async function readAgentManifest(params: {\n cwd: string;\n agentName: string;\n}): Promise<AgentManifestV1> {\n const { cwd, agentName } = params;\n const agentPath = join(cwd, \"agents\", agentName, \"index.ts\");\n await access(agentPath);\n\n let tempDir: string | undefined;\n\n try {\n const loaded = await loadAgentModule(agentPath, cwd);\n tempDir = loaded.tempDir;\n const agent = asRecord(loaded.agent);\n const steps = serializeSteps(asArray(agent.steps));\n const tools = serializeTools(asArray(agent.tools));\n const routes = serializeRoutes(asArray(agent.routes));\n const stepIds = new Set(steps.map((step) => step.id));\n const flows = serializeFlows(asArray(agent.flows), stepIds);\n\n return {\n format: \"kalp-agent-manifest\",\n schemaVersion: 1,\n generatedAt: new Date().toISOString(),\n agent: {\n id: asString(agent.id),\n name: asString(agent.name) ?? agentName,\n description: asString(agent.description) ?? \"\",\n systemPrompt: serializeSystemPrompt(agent.systemPrompt),\n lifecycle: {\n onInit: typeof agent.onInit === \"function\",\n onMessage: typeof agent.onMessage === \"function\",\n onTick: typeof agent.onTick === \"function\",\n },\n actions: {\n ai: true,\n wait: true,\n fetch: true,\n runStep: true,\n callTool: true,\n runFlow: true,\n },\n steps,\n tools,\n routes,\n flows,\n execution: {\n stepOrder: steps.map((step) => step.id),\n toolOrder: tools.map((tool) => tool.id),\n routeOrder: routes.map((route) => route.id),\n flowOrder: flows.map((flow) => flow.id),\n },\n },\n };\n } finally {\n if (tempDir) {\n await rm(tempDir, { recursive: true, force: true });\n }\n }\n}\n\nfunction getHash(payload: string): string {\n return createHash(\"sha256\").update(payload).digest(\"hex\");\n}\n\nfunction isManifestVersionFile(fileName: string): boolean {\n return fileName.endsWith(\".json\");\n}\n\nfunction createVersionId(payload: string, generatedAt: string): string {\n return createHash(\"sha256\")\n .update(payload)\n .update(generatedAt)\n .digest(\"hex\")\n .slice(0, 8);\n}\n\nasync function readManifestVersionFile(\n filePath: string,\n): Promise<ManifestVersionRecord | null> {\n try {\n const src = await readFile(filePath, \"utf-8\");\n return JSON.parse(src) as ManifestVersionRecord;\n } catch {\n return null;\n }\n}\n\nexport async function writeVersionedManifest(params: {\n cwd: string;\n agentName: string;\n manifest: AgentManifestV1;\n}): Promise<ManifestVersionRecord & { outputPath: string }> {\n const { cwd, agentName, manifest } = params;\n const agentMetaDir = join(cwd, \"meta\", \"migrations\", agentName);\n await mkdir(agentMetaDir, { recursive: true });\n\n const files = await readdir(agentMetaDir);\n const versionFiles = files.filter(isManifestVersionFile);\n const existingRecords = (\n await Promise.all(\n versionFiles.map((file) =>\n readManifestVersionFile(join(agentMetaDir, file)),\n ),\n )\n ).filter((record): record is ManifestVersionRecord => record !== null);\n\n const latestVersion =\n existingRecords\n .map((record) => record.version)\n .sort((a, b) => a - b)\n .at(-1) ?? 0;\n const nextVersion = latestVersion + 1;\n\n const payload = JSON.stringify(manifest);\n const generatedAt = new Date().toISOString();\n const versionId = createVersionId(payload, generatedAt);\n const record: ManifestVersionRecord = {\n version: nextVersion,\n versionId,\n hash: getHash(payload),\n generatedAt,\n immutable: true,\n manifest,\n };\n\n const versionFile = join(agentMetaDir, `${versionId}.json`);\n await writeFile(versionFile, JSON.stringify(record, null, 2) + \"\\n\", \"utf-8\");\n\n const snapshotPath = join(cwd, \"meta\", \"snapshot.json\");\n const snapshot = await readSnapshot(snapshotPath);\n const prev = snapshot[agentName] ?? { latest: \"\", versions: [] };\n const versions = prev.versions.includes(versionId)\n ? prev.versions\n : [...prev.versions, versionId];\n snapshot[agentName] = { latest: versionId, versions };\n await writeFile(\n snapshotPath,\n JSON.stringify(snapshot, null, 2) + \"\\n\",\n \"utf-8\",\n );\n\n return {\n ...record,\n outputPath: versionFile,\n };\n}\n\nexport async function readLatestVersionedManifest(params: {\n cwd: string;\n agentName: string;\n}): Promise<(ManifestVersionRecord & { outputPath: string }) | null> {\n const { cwd, agentName } = params;\n const agentMetaDir = join(cwd, \"meta\", \"migrations\", agentName);\n const snapshotPath = join(cwd, \"meta\", \"snapshot.json\");\n\n // Try to read from snapshot first\n const snapshot = await readSnapshot(snapshotPath);\n const agentEntry = snapshot[agentName];\n\n if (agentEntry?.latest) {\n const latestFile = join(agentMetaDir, `${agentEntry.latest}.json`);\n const latest = await readManifestVersionFile(latestFile);\n if (latest) {\n return {\n ...latest,\n outputPath: latestFile,\n };\n }\n }\n\n // Fallback: scan directory and find latest by version number\n const files = await readdir(agentMetaDir).catch(() => [] as string[]);\n const records = (\n await Promise.all(\n files\n .filter(isManifestVersionFile)\n .map((file) => readManifestVersionFile(join(agentMetaDir, file))),\n )\n ).filter((record): record is ManifestVersionRecord => record !== null);\n\n if (records.length === 0) {\n return null;\n }\n\n const newest = records.sort((a, b) => b.version - a.version)[0] ?? null;\n if (!newest) {\n return null;\n }\n\n return {\n ...newest,\n outputPath: join(agentMetaDir, `${newest.versionId}.json`),\n };\n}\n\nasync function readSnapshot(\n snapshotPath: string,\n): Promise<Record<string, ManifestRegistryEntry>> {\n try {\n const src = await readFile(snapshotPath, \"utf-8\");\n return JSON.parse(src) as Record<string, ManifestRegistryEntry>;\n } catch {\n return {};\n }\n}\n"],"mappings":";;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,MAAM,eAAe;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,aAAa;AAEtB,SAAS,uBAAuB;AA0GhC,SAAS,SAAS,OAAyC;AACzD,SAAO,OAAO,UAAU,YAAY,UAAU,OACzC,QACD,CAAC;AACP;AAEA,SAAS,SAAS,OAAoC;AACpD,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAEA,SAAS,QAAQ,OAA2B;AAC1C,SAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC;AACzC;AAEA,SAAS,aACP,QACA,MACgC;AAChC,MAAI;AACF,WAAO,gBAAgB,QAAsB,IAAI;AAAA,EAInD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,sBACP,cAC0C;AAC1C,MAAI,OAAO,iBAAiB,UAAU;AACpC,WAAO,EAAE,MAAM,UAAU,OAAO,aAAa;AAAA,EAC/C;AAEA,MAAI,OAAO,iBAAiB,YAAY;AACtC,WAAO,EAAE,MAAM,UAAU;AAAA,EAC3B;AAEA,SAAO,EAAE,MAAM,OAAO;AACxB;AAEA,SAAS,eAAe,OAAqD;AAC3E,SAAO,MAAM,IAAI,CAAC,MAAM,UAAU;AAChC,UAAM,OAAO,SAAS,IAAI;AAC1B,WAAO;AAAA,MACL,IAAI,SAAS,KAAK,EAAE,KAAK,QAAQ,QAAQ,CAAC;AAAA,MAC1C,OAAO,QAAQ;AAAA,MACf,aAAa,SAAS,KAAK,WAAW,KAAK;AAAA,MAC3C,aAAa,aAAa,KAAK,OAAO,QAAQ,QAAQ,CAAC,QAAQ;AAAA,MAC/D,cAAc,aAAa,KAAK,QAAQ,QAAQ,QAAQ,CAAC,SAAS;AAAA,IACpE;AAAA,EACF,CAAC;AACH;AAEA,SAAS,eAAe,OAAqD;AAC3E,SAAO,MAAM,IAAI,CAAC,MAAM,UAAU;AAChC,UAAM,OAAO,SAAS,IAAI;AAC1B,WAAO;AAAA,MACL,IAAI,SAAS,KAAK,EAAE,KAAK,QAAQ,QAAQ,CAAC;AAAA,MAC1C,OAAO,QAAQ;AAAA,MACf,aAAa,SAAS,KAAK,WAAW,KAAK;AAAA,MAC3C,aAAa,aAAa,KAAK,OAAO,QAAQ,QAAQ,CAAC,QAAQ;AAAA,IACjE;AAAA,EACF,CAAC;AACH;AAEA,SAAS,gBACP,QACoC;AACpC,SAAO,OAAO,IAAI,CAAC,OAAO,UAAU;AAClC,UAAM,OAAO,SAAS,KAAK;AAC3B,WAAO;AAAA,MACL,IAAI,SAAS,KAAK,EAAE,KAAK,SAAS,QAAQ,CAAC;AAAA,MAC3C,OAAO,QAAQ;AAAA,MACf,QAAQ,SAAS,KAAK,MAAM,KAAK;AAAA,MACjC,MAAM,SAAS,KAAK,IAAI,KAAK;AAAA,MAC7B,aAAa,aAAa,KAAK,OAAO,SAAS,QAAQ,CAAC,QAAQ;AAAA,IAClE;AAAA,EACF,CAAC;AACH;AAEA,SAAS,eACP,OACA,SACmC;AACnC,SAAO,MAAM,IAAI,CAAC,MAAM,UAAU;AAChC,UAAM,OAAO,SAAS,IAAI;AAC1B,UAAM,QAAQ,QAAQ,KAAK,KAAK,EAAE,IAAI,CAAC,GAAG,cAAc;AACtD,YAAM,OAAO,SAAS,CAAC;AACvB,YAAM,SAAS,SAAS,KAAK,EAAE,KAAK,QAAQ,YAAY,CAAC;AACzD,aAAO;AAAA,QACL,OAAO,YAAY;AAAA,QACnB;AAAA,QACA,oBAAoB,QAAQ,IAAI,MAAM;AAAA,MACxC;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,IAAI,SAAS,KAAK,EAAE,KAAK,QAAQ,QAAQ,CAAC;AAAA,MAC1C,OAAO,QAAQ;AAAA,MACf,aAAa,SAAS,KAAK,WAAW,KAAK;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,eAAe,gBACb,WACA,KAC4B;AAC5B,QAAM,UAAU,MAAM,QAAQ,KAAK,KAAK,iBAAiB,CAAC;AAC1D,QAAM,UAAU,KAAK,SAAS,oBAAoB;AAElD,QAAM,MAAM;AAAA,IACV,aAAa,CAAC,SAAS;AAAA,IACvB,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,MAAM,UAAU;AACd,mBAAS,UAAU,EAAE,QAAQ,gBAAgB,GAAG,CAAC,SAAS;AACxD,kBAAM,WAAW,QAAQ,KAAK,YAAY,KAAK,IAAI;AACnD,gBAAI,WAAW,QAAQ,GAAG;AACxB,qBAAO,EAAE,MAAM,SAAS;AAAA,YAC1B;AAEA,kBAAM,SAAS,SAAS,QAAQ,SAAS,KAAK;AAC9C,gBAAI,WAAW,MAAM,GAAG;AACtB,qBAAO,EAAE,MAAM,OAAO;AAAA,YACxB;AAEA,kBAAM,UAAU,SAAS,QAAQ,SAAS,MAAM;AAChD,gBAAI,WAAW,OAAO,GAAG;AACvB,qBAAO,EAAE,MAAM,QAAQ;AAAA,YACzB;AAEA,mBAAO;AAAA,UACT,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,SAAU,MAAM,OACpB,GAAG,cAAc,OAAO,EAAE,IAAI,MAAM,KAAK,IAAI,CAAC;AAGhD,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd;AAAA,EACF;AACF;AAEA,eAAsB,kBAAkB,QAGX;AAC3B,QAAM,EAAE,KAAK,UAAU,IAAI;AAC3B,QAAM,YAAY,KAAK,KAAK,UAAU,WAAW,UAAU;AAC3D,QAAM,OAAO,SAAS;AAEtB,MAAI;AAEJ,MAAI;AACF,UAAM,SAAS,MAAM,gBAAgB,WAAW,GAAG;AACnD,cAAU,OAAO;AACjB,UAAM,QAAQ,SAAS,OAAO,KAAK;AACnC,UAAM,QAAQ,eAAe,QAAQ,MAAM,KAAK,CAAC;AACjD,UAAM,QAAQ,eAAe,QAAQ,MAAM,KAAK,CAAC;AACjD,UAAM,SAAS,gBAAgB,QAAQ,MAAM,MAAM,CAAC;AACpD,UAAM,UAAU,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AACpD,UAAM,QAAQ,eAAe,QAAQ,MAAM,KAAK,GAAG,OAAO;AAE1D,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,eAAe;AAAA,MACf,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC,OAAO;AAAA,QACL,IAAI,SAAS,MAAM,EAAE;AAAA,QACrB,MAAM,SAAS,MAAM,IAAI,KAAK;AAAA,QAC9B,aAAa,SAAS,MAAM,WAAW,KAAK;AAAA,QAC5C,cAAc,sBAAsB,MAAM,YAAY;AAAA,QACtD,WAAW;AAAA,UACT,QAAQ,OAAO,MAAM,WAAW;AAAA,UAChC,WAAW,OAAO,MAAM,cAAc;AAAA,UACtC,QAAQ,OAAO,MAAM,WAAW;AAAA,QAClC;AAAA,QACA,SAAS;AAAA,UACP,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,OAAO;AAAA,UACP,SAAS;AAAA,UACT,UAAU;AAAA,UACV,SAAS;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW;AAAA,UACT,WAAW,MAAM,IAAI,CAAC,SAAS,KAAK,EAAE;AAAA,UACtC,WAAW,MAAM,IAAI,CAAC,SAAS,KAAK,EAAE;AAAA,UACtC,YAAY,OAAO,IAAI,CAAC,UAAU,MAAM,EAAE;AAAA,UAC1C,WAAW,MAAM,IAAI,CAAC,SAAS,KAAK,EAAE;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AAAA,EACF,UAAE;AACA,QAAI,SAAS;AACX,YAAM,GAAG,SAAS,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACpD;AAAA,EACF;AACF;AAEA,SAAS,QAAQ,SAAyB;AACxC,SAAO,WAAW,QAAQ,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AAC1D;AAEA,SAAS,sBAAsB,UAA2B;AACxD,SAAO,SAAS,SAAS,OAAO;AAClC;AAEA,SAAS,gBAAgB,SAAiB,aAA6B;AACrE,SAAO,WAAW,QAAQ,EACvB,OAAO,OAAO,EACd,OAAO,WAAW,EAClB,OAAO,KAAK,EACZ,MAAM,GAAG,CAAC;AACf;AAEA,eAAe,wBACb,UACuC;AACvC,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,UAAU,OAAO;AAC5C,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,uBAAuB,QAIe;AAC1D,QAAM,EAAE,KAAK,WAAW,SAAS,IAAI;AACrC,QAAM,eAAe,KAAK,KAAK,QAAQ,cAAc,SAAS;AAC9D,QAAM,MAAM,cAAc,EAAE,WAAW,KAAK,CAAC;AAE7C,QAAM,QAAQ,MAAM,QAAQ,YAAY;AACxC,QAAM,eAAe,MAAM,OAAO,qBAAqB;AACvD,QAAM,mBACJ,MAAM,QAAQ;AAAA,IACZ,aAAa;AAAA,MAAI,CAAC,SAChB,wBAAwB,KAAK,cAAc,IAAI,CAAC;AAAA,IAClD;AAAA,EACF,GACA,OAAO,CAACA,YAA4CA,YAAW,IAAI;AAErE,QAAM,gBACJ,gBACG,IAAI,CAACA,YAAWA,QAAO,OAAO,EAC9B,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,EACpB,GAAG,EAAE,KAAK;AACf,QAAM,cAAc,gBAAgB;AAEpC,QAAM,UAAU,KAAK,UAAU,QAAQ;AACvC,QAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC3C,QAAM,YAAY,gBAAgB,SAAS,WAAW;AACtD,QAAM,SAAgC;AAAA,IACpC,SAAS;AAAA,IACT;AAAA,IACA,MAAM,QAAQ,OAAO;AAAA,IACrB;AAAA,IACA,WAAW;AAAA,IACX;AAAA,EACF;AAEA,QAAM,cAAc,KAAK,cAAc,GAAG,SAAS,OAAO;AAC1D,QAAM,UAAU,aAAa,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,OAAO;AAE5E,QAAM,eAAe,KAAK,KAAK,QAAQ,eAAe;AACtD,QAAM,WAAW,MAAM,aAAa,YAAY;AAChD,QAAM,OAAO,SAAS,SAAS,KAAK,EAAE,QAAQ,IAAI,UAAU,CAAC,EAAE;AAC/D,QAAM,WAAW,KAAK,SAAS,SAAS,SAAS,IAC7C,KAAK,WACL,CAAC,GAAG,KAAK,UAAU,SAAS;AAChC,WAAS,SAAS,IAAI,EAAE,QAAQ,WAAW,SAAS;AACpD,QAAM;AAAA,IACJ;AAAA,IACA,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI;AAAA,IACpC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,YAAY;AAAA,EACd;AACF;AAEA,eAAsB,4BAA4B,QAGmB;AACnE,QAAM,EAAE,KAAK,UAAU,IAAI;AAC3B,QAAM,eAAe,KAAK,KAAK,QAAQ,cAAc,SAAS;AAC9D,QAAM,eAAe,KAAK,KAAK,QAAQ,eAAe;AAGtD,QAAM,WAAW,MAAM,aAAa,YAAY;AAChD,QAAM,aAAa,SAAS,SAAS;AAErC,MAAI,YAAY,QAAQ;AACtB,UAAM,aAAa,KAAK,cAAc,GAAG,WAAW,MAAM,OAAO;AACjE,UAAM,SAAS,MAAM,wBAAwB,UAAU;AACvD,QAAI,QAAQ;AACV,aAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAGA,QAAM,QAAQ,MAAM,QAAQ,YAAY,EAAE,MAAM,MAAM,CAAC,CAAa;AACpE,QAAM,WACJ,MAAM,QAAQ;AAAA,IACZ,MACG,OAAO,qBAAqB,EAC5B,IAAI,CAAC,SAAS,wBAAwB,KAAK,cAAc,IAAI,CAAC,CAAC;AAAA,EACpE,GACA,OAAO,CAAC,WAA4C,WAAW,IAAI;AAErE,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,QAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,KAAK;AACnE,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,YAAY,KAAK,cAAc,GAAG,OAAO,SAAS,OAAO;AAAA,EAC3D;AACF;AAEA,eAAe,aACb,cACgD;AAChD,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,cAAc,OAAO;AAChD,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;","names":["record"]}
|
|
@@ -4,7 +4,14 @@ import {
|
|
|
4
4
|
} from "./chunk-2H7UOFLK.js";
|
|
5
5
|
|
|
6
6
|
// src/scaffold.ts
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
writeFile,
|
|
9
|
+
readFile as readFile2,
|
|
10
|
+
readdir,
|
|
11
|
+
cp,
|
|
12
|
+
mkdir,
|
|
13
|
+
access
|
|
14
|
+
} from "fs/promises";
|
|
8
15
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
9
16
|
import { join as join4, dirname as dirname3 } from "path";
|
|
10
17
|
|
|
@@ -19709,13 +19716,44 @@ async function scaffoldProject(opts) {
|
|
|
19709
19716
|
recursive: true,
|
|
19710
19717
|
force: true
|
|
19711
19718
|
});
|
|
19719
|
+
const gitignorePath = join4(targetDir, ".gitignore");
|
|
19720
|
+
try {
|
|
19721
|
+
await access(gitignorePath);
|
|
19722
|
+
} catch {
|
|
19723
|
+
await writeFile(
|
|
19724
|
+
gitignorePath,
|
|
19725
|
+
"node_modules/\ndist/\n.env\n*.log\n.turbo/\n.temp/\n",
|
|
19726
|
+
"utf-8"
|
|
19727
|
+
);
|
|
19728
|
+
}
|
|
19729
|
+
const tempDir = join4(targetDir, ".temp");
|
|
19730
|
+
await mkdir(tempDir, { recursive: true });
|
|
19731
|
+
const versionInfo = {
|
|
19732
|
+
cliVersion: "0.0.2",
|
|
19733
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19734
|
+
projectName
|
|
19735
|
+
};
|
|
19736
|
+
await writeFile(
|
|
19737
|
+
join4(tempDir, "version.json"),
|
|
19738
|
+
JSON.stringify(versionInfo, null, 2),
|
|
19739
|
+
"utf-8"
|
|
19740
|
+
);
|
|
19712
19741
|
const kalpConfig = `import { defineConfig } from "@kalphq/sdk";
|
|
19713
19742
|
|
|
19714
|
-
export default defineConfig({
|
|
19715
|
-
|
|
19716
|
-
});
|
|
19743
|
+
export default defineConfig({
|
|
19744
|
+
secrets: [],
|
|
19745
|
+
});
|
|
19717
19746
|
`;
|
|
19718
19747
|
await writeFile(join4(targetDir, "kalp.config.ts"), kalpConfig, "utf-8");
|
|
19748
|
+
const kalpDts = `import "@kalphq/sdk";
|
|
19749
|
+
|
|
19750
|
+
declare module "@kalphq/sdk" {
|
|
19751
|
+
interface SecretsRegistry {
|
|
19752
|
+
keys: [];
|
|
19753
|
+
}
|
|
19754
|
+
}
|
|
19755
|
+
`;
|
|
19756
|
+
await writeFile(join4(targetDir, "kalp.d.ts"), kalpDts, "utf-8");
|
|
19719
19757
|
await replacePlaceholders(targetDir, { __PROJECT_NAME__: projectName });
|
|
19720
19758
|
}
|
|
19721
19759
|
async function scaffoldAgent(opts) {
|
|
@@ -19726,95 +19764,144 @@ async function scaffoldAgent(opts) {
|
|
|
19726
19764
|
await mkdir(join4(agentDir, "routes"), { recursive: true });
|
|
19727
19765
|
await mkdir(join4(agentDir, "flows"), { recursive: true });
|
|
19728
19766
|
const agentIndex = `import { asAgentId, defineAgent } from "@kalphq/sdk";
|
|
19729
|
-
import {
|
|
19730
|
-
import {
|
|
19731
|
-
import {
|
|
19732
|
-
import {
|
|
19767
|
+
import { processQuery } from "./steps/process-query.js";
|
|
19768
|
+
import { formatResponse } from "./steps/format-response.js";
|
|
19769
|
+
import { searchTool } from "./tools/search.js";
|
|
19770
|
+
import { healthRoute } from "./routes/health.js";
|
|
19771
|
+
import { chatFlow } from "./flows/chat-flow.js";
|
|
19733
19772
|
|
|
19734
|
-
export default defineAgent({
|
|
19735
|
-
|
|
19736
|
-
|
|
19737
|
-
|
|
19738
|
-
|
|
19739
|
-
|
|
19740
|
-
|
|
19773
|
+
export default defineAgent({
|
|
19774
|
+
id: asAgentId("${agentName}"),
|
|
19775
|
+
name: "${agentName}",
|
|
19776
|
+
description: "A helpful AI assistant",
|
|
19777
|
+
steps: [processQuery, formatResponse],
|
|
19778
|
+
tools: [searchTool],
|
|
19779
|
+
routes: [healthRoute],
|
|
19780
|
+
flows: [chatFlow],
|
|
19741
19781
|
|
|
19742
|
-
|
|
19743
|
-
|
|
19744
|
-
|
|
19745
|
-
|
|
19746
|
-
|
|
19747
|
-
|
|
19748
|
-
|
|
19749
|
-
|
|
19750
|
-
|
|
19751
|
-
});
|
|
19752
|
-
`;
|
|
19753
|
-
const stepFile = `import { createStep } from "@kalphq/sdk";
|
|
19754
|
-
import { z } from "zod";
|
|
19782
|
+
async onMessage({ message, ctx, actions }) {
|
|
19783
|
+
// Stream AI response
|
|
19784
|
+
const stream = await actions.ai.stream({
|
|
19785
|
+
model: "openai/gpt-4o-mini",
|
|
19786
|
+
system: "You are a helpful assistant.",
|
|
19787
|
+
messages: [
|
|
19788
|
+
{ role: "user", content: message.text },
|
|
19789
|
+
],
|
|
19790
|
+
});
|
|
19755
19791
|
|
|
19756
|
-
|
|
19757
|
-
|
|
19758
|
-
|
|
19759
|
-
|
|
19760
|
-
|
|
19761
|
-
|
|
19762
|
-
|
|
19763
|
-
|
|
19764
|
-
|
|
19765
|
-
|
|
19792
|
+
return stream;
|
|
19793
|
+
},
|
|
19794
|
+
});`;
|
|
19795
|
+
const stepProcessFile = `import { createStep } from "@kalphq/sdk";
|
|
19796
|
+
import { z } from "zod";
|
|
19797
|
+
|
|
19798
|
+
export const processQuery = createStep({
|
|
19799
|
+
id: "process_query",
|
|
19800
|
+
description: "Analyze and enhance user query",
|
|
19801
|
+
input: z.object({ query: z.string() }),
|
|
19802
|
+
output: z.object({
|
|
19803
|
+
enhanced: z.string(),
|
|
19804
|
+
intent: z.string(),
|
|
19805
|
+
needsSearch: z.boolean(),
|
|
19806
|
+
}),
|
|
19807
|
+
async run({ query }) {
|
|
19808
|
+
// Simple intent detection
|
|
19809
|
+
const intent = query.includes("?") ? "question" : "statement";
|
|
19810
|
+
const needsSearch = query.toLowerCase().includes("search") || query.includes("?");
|
|
19811
|
+
|
|
19812
|
+
return {
|
|
19813
|
+
enhanced: query.trim(),
|
|
19814
|
+
intent,
|
|
19815
|
+
needsSearch,
|
|
19816
|
+
};
|
|
19817
|
+
},
|
|
19818
|
+
});`;
|
|
19819
|
+
const stepFormatFile = `import { createStep } from "@kalphq/sdk";
|
|
19820
|
+
import { z } from "zod";
|
|
19821
|
+
|
|
19822
|
+
export const formatResponse = createStep({
|
|
19823
|
+
id: "format_response",
|
|
19824
|
+
description: "Format final response with metadata",
|
|
19825
|
+
input: z.object({
|
|
19826
|
+
text: z.string(),
|
|
19827
|
+
sources: z.array(z.string()).optional(),
|
|
19828
|
+
}),
|
|
19829
|
+
output: z.object({
|
|
19830
|
+
formatted: z.string(),
|
|
19831
|
+
meta: z.object({ timestamp: z.number(), version: z.string() }),
|
|
19832
|
+
}),
|
|
19833
|
+
async run({ text, sources }) {
|
|
19834
|
+
const formatted = sources?.length
|
|
19835
|
+
? \`\${text}\\n\\nSources: \${sources.join(", ")}\`
|
|
19836
|
+
: text;
|
|
19837
|
+
|
|
19838
|
+
return {
|
|
19839
|
+
formatted,
|
|
19840
|
+
meta: {
|
|
19841
|
+
timestamp: Date.now(),
|
|
19842
|
+
version: "1.0.0",
|
|
19843
|
+
},
|
|
19844
|
+
};
|
|
19845
|
+
},
|
|
19846
|
+
});`;
|
|
19766
19847
|
const toolFile = `import { createTool } from "@kalphq/sdk";
|
|
19767
|
-
import { z } from "zod";
|
|
19848
|
+
import { z } from "zod";
|
|
19768
19849
|
|
|
19769
|
-
export const
|
|
19770
|
-
|
|
19771
|
-
|
|
19772
|
-
|
|
19773
|
-
|
|
19774
|
-
|
|
19775
|
-
|
|
19776
|
-
})
|
|
19777
|
-
|
|
19850
|
+
export const searchTool = createTool({
|
|
19851
|
+
id: "search",
|
|
19852
|
+
description: "Search for relevant information",
|
|
19853
|
+
input: z.object({ query: z.string(), limit: z.number().default(3) }),
|
|
19854
|
+
output: z.object({
|
|
19855
|
+
results: z.array(z.object({ title: z.string(), snippet: z.string() })),
|
|
19856
|
+
total: z.number(),
|
|
19857
|
+
}),
|
|
19858
|
+
async execute({ query, limit }) {
|
|
19859
|
+
// Simulated search - replace with real API call
|
|
19860
|
+
const results = [
|
|
19861
|
+
{ title: "Result 1", snippet: \`Info about: \${query}\` },
|
|
19862
|
+
{ title: "Result 2", snippet: "More relevant content..." },
|
|
19863
|
+
].slice(0, limit);
|
|
19864
|
+
|
|
19865
|
+
return { results, total: results.length };
|
|
19866
|
+
},
|
|
19867
|
+
});`;
|
|
19778
19868
|
const routeFile = `import { defineRoute } from "@kalphq/sdk";
|
|
19779
19869
|
|
|
19780
|
-
export const
|
|
19781
|
-
|
|
19782
|
-
|
|
19783
|
-
|
|
19784
|
-
|
|
19785
|
-
|
|
19786
|
-
|
|
19787
|
-
}
|
|
19788
|
-
|
|
19870
|
+
export const healthRoute = defineRoute({
|
|
19871
|
+
id: "health",
|
|
19872
|
+
method: "GET",
|
|
19873
|
+
path: "/health",
|
|
19874
|
+
handler: async (_req, res, { ctx }) => {
|
|
19875
|
+
res.json({
|
|
19876
|
+
status: "ok",
|
|
19877
|
+
agent: "${agentName}",
|
|
19878
|
+
timestamp: new Date().toISOString(),
|
|
19879
|
+
});
|
|
19880
|
+
},
|
|
19881
|
+
});`;
|
|
19789
19882
|
const flowFile = `import { defineFlow } from "@kalphq/sdk";
|
|
19883
|
+
import { processQuery } from "../steps/process-query.js";
|
|
19884
|
+
import { formatResponse } from "../steps/format-response.js";
|
|
19790
19885
|
|
|
19791
|
-
export const
|
|
19792
|
-
|
|
19793
|
-
|
|
19794
|
-
|
|
19795
|
-
})
|
|
19796
|
-
`;
|
|
19886
|
+
export const chatFlow = defineFlow({
|
|
19887
|
+
id: "chat_flow",
|
|
19888
|
+
description: "Process user message through query analysis and formatting",
|
|
19889
|
+
steps: [processQuery, formatResponse],
|
|
19890
|
+
});`;
|
|
19797
19891
|
await writeFile(join4(agentDir, "index.ts"), agentIndex, "utf-8");
|
|
19798
19892
|
await writeFile(
|
|
19799
|
-
join4(agentDir, "steps", "
|
|
19800
|
-
|
|
19801
|
-
"utf-8"
|
|
19802
|
-
);
|
|
19803
|
-
await writeFile(
|
|
19804
|
-
join4(agentDir, "tools", "example-tool.ts"),
|
|
19805
|
-
toolFile,
|
|
19806
|
-
"utf-8"
|
|
19807
|
-
);
|
|
19808
|
-
await writeFile(
|
|
19809
|
-
join4(agentDir, "routes", "example-route.ts"),
|
|
19810
|
-
routeFile,
|
|
19893
|
+
join4(agentDir, "steps", "process-query.ts"),
|
|
19894
|
+
stepProcessFile,
|
|
19811
19895
|
"utf-8"
|
|
19812
19896
|
);
|
|
19813
19897
|
await writeFile(
|
|
19814
|
-
join4(agentDir, "
|
|
19815
|
-
|
|
19898
|
+
join4(agentDir, "steps", "format-response.ts"),
|
|
19899
|
+
stepFormatFile,
|
|
19816
19900
|
"utf-8"
|
|
19817
19901
|
);
|
|
19902
|
+
await writeFile(join4(agentDir, "tools", "search.ts"), toolFile, "utf-8");
|
|
19903
|
+
await writeFile(join4(agentDir, "routes", "health.ts"), routeFile, "utf-8");
|
|
19904
|
+
await writeFile(join4(agentDir, "flows", "chat-flow.ts"), flowFile, "utf-8");
|
|
19818
19905
|
}
|
|
19819
19906
|
|
|
19820
19907
|
// src/utils/ui.ts
|
|
@@ -19873,4 +19960,4 @@ export {
|
|
|
19873
19960
|
promptProjectName,
|
|
19874
19961
|
promptAgentDetails
|
|
19875
19962
|
};
|
|
19876
|
-
//# sourceMappingURL=chunk-
|
|
19963
|
+
//# sourceMappingURL=chunk-MECZEYSU.js.map
|