@kairos-sdk/core 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -1
- package/dist/{chunk-HBGZTUUZ.js → chunk-GVZKMS53.js} +5 -7
- package/dist/chunk-GVZKMS53.js.map +1 -0
- package/dist/{chunk-5GAY7CSJ.js → chunk-MYAGTDQ2.js} +2 -2
- package/dist/{chunk-EVOAYH2K.js → chunk-V2IZBZGB.js} +2 -2
- package/dist/{chunk-KIFT5LA7.js → chunk-VPPWTMRJ.js} +2 -2
- package/dist/chunk-VPPWTMRJ.js.map +1 -0
- package/dist/cli.cjs +55 -37
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +27 -7
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +32 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +4 -4
- package/dist/mcp-server.cjs +92 -21
- package/dist/mcp-server.cjs.map +1 -1
- package/dist/mcp-server.js +90 -19
- package/dist/mcp-server.js.map +1 -1
- package/dist/standalone.cjs +1 -1
- package/dist/standalone.cjs.map +1 -1
- package/dist/standalone.js +2 -2
- package/package.json +12 -5
- package/dist/chunk-HBGZTUUZ.js.map +0 -1
- package/dist/chunk-KIFT5LA7.js.map +0 -1
- /package/dist/{chunk-5GAY7CSJ.js.map → chunk-MYAGTDQ2.js.map} +0 -0
- /package/dist/{chunk-EVOAYH2K.js.map → chunk-V2IZBZGB.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -4,7 +4,6 @@ export { A as ApiError, d as AttemptMetadata, e as CredentialRequirement, f as D
|
|
|
4
4
|
declare class Kairos {
|
|
5
5
|
private readonly provider;
|
|
6
6
|
private readonly designer;
|
|
7
|
-
private readonly validator;
|
|
8
7
|
private readonly library;
|
|
9
8
|
private readonly logger;
|
|
10
9
|
private readonly telemetry;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ export { A as ApiError, d as AttemptMetadata, e as CredentialRequirement, f as D
|
|
|
4
4
|
declare class Kairos {
|
|
5
5
|
private readonly provider;
|
|
6
6
|
private readonly designer;
|
|
7
|
-
private readonly validator;
|
|
8
7
|
private readonly library;
|
|
9
8
|
private readonly logger;
|
|
10
9
|
private readonly telemetry;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Kairos
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-GVZKMS53.js";
|
|
4
|
+
import "./chunk-V2IZBZGB.js";
|
|
5
5
|
import "./chunk-6FOFWVMG.js";
|
|
6
6
|
import {
|
|
7
7
|
GenerationError,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
ResponseParseError,
|
|
11
11
|
TemplateSyncer,
|
|
12
12
|
ValidationError
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-MYAGTDQ2.js";
|
|
14
14
|
import {
|
|
15
15
|
ApiError,
|
|
16
16
|
DEFAULT_REGISTRY,
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
nullLogger,
|
|
31
31
|
rerank,
|
|
32
32
|
tokenize
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-VPPWTMRJ.js";
|
|
34
34
|
export {
|
|
35
35
|
ApiError,
|
|
36
36
|
DEFAULT_REGISTRY,
|
package/dist/mcp-server.cjs
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
// src/mcp-server.ts
|
|
5
5
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
6
6
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
7
|
+
var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
8
|
+
var import_node_http = require("http");
|
|
7
9
|
var import_zod = require("zod");
|
|
8
10
|
|
|
9
11
|
// src/library/file-library.ts
|
|
@@ -2594,7 +2596,7 @@ var PatternAnalyzer = class _PatternAnalyzer {
|
|
|
2594
2596
|
this._cachedEvents = events;
|
|
2595
2597
|
const starts = events.filter((e) => e.eventType === "build_start");
|
|
2596
2598
|
const attempts = events.filter((e) => e.eventType === "generation_attempt");
|
|
2597
|
-
const
|
|
2599
|
+
const _passed = attempts.filter(
|
|
2598
2600
|
(a) => a.data.validationPassed === true
|
|
2599
2601
|
);
|
|
2600
2602
|
const failed = attempts.filter(
|
|
@@ -3177,12 +3179,37 @@ function inferWorkflowType(description) {
|
|
|
3177
3179
|
|
|
3178
3180
|
// src/mcp-server.ts
|
|
3179
3181
|
var import_node_fs3 = require("fs");
|
|
3180
|
-
var
|
|
3182
|
+
var import_node_path8 = require("path");
|
|
3181
3183
|
var import_node_os6 = require("os");
|
|
3182
3184
|
var import_node_url = require("url");
|
|
3185
|
+
|
|
3186
|
+
// src/utils/node-catalog-cache.ts
|
|
3187
|
+
var import_promises5 = require("fs/promises");
|
|
3188
|
+
var import_node_path7 = require("path");
|
|
3189
|
+
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
3190
|
+
async function readCatalogCache(cachePath) {
|
|
3191
|
+
try {
|
|
3192
|
+
const raw = await (0, import_promises5.readFile)(cachePath, "utf-8");
|
|
3193
|
+
const cached = JSON.parse(raw);
|
|
3194
|
+
if (Date.now() - cached.cachedAt > CACHE_TTL_MS) return null;
|
|
3195
|
+
return cached.syncResult;
|
|
3196
|
+
} catch {
|
|
3197
|
+
return null;
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
async function writeCatalogCache(cachePath, syncResult) {
|
|
3201
|
+
try {
|
|
3202
|
+
await (0, import_promises5.mkdir)((0, import_node_path7.dirname)(cachePath), { recursive: true });
|
|
3203
|
+
const payload = { cachedAt: Date.now(), syncResult };
|
|
3204
|
+
await (0, import_promises5.writeFile)(cachePath, JSON.stringify(payload), "utf-8");
|
|
3205
|
+
} catch {
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3209
|
+
// src/mcp-server.ts
|
|
3183
3210
|
var import_meta = {};
|
|
3184
|
-
var __dirname = (0,
|
|
3185
|
-
var pkg = JSON.parse((0, import_node_fs3.readFileSync)((0,
|
|
3211
|
+
var __dirname = (0, import_node_path8.dirname)((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
3212
|
+
var pkg = JSON.parse((0, import_node_fs3.readFileSync)((0, import_node_path8.join)(__dirname, "..", "package.json"), "utf-8"));
|
|
3186
3213
|
var library = new FileLibrary();
|
|
3187
3214
|
var _validator = new N8nValidator();
|
|
3188
3215
|
function getValidator() {
|
|
@@ -3201,9 +3228,9 @@ function getMcpTelemetry() {
|
|
|
3201
3228
|
function getMcpPatternsPath() {
|
|
3202
3229
|
const val = process.env["KAIROS_TELEMETRY"];
|
|
3203
3230
|
if (val && val !== "false" && val !== "true") {
|
|
3204
|
-
return (0,
|
|
3231
|
+
return (0, import_node_path8.join)(val, "..", "patterns.json");
|
|
3205
3232
|
}
|
|
3206
|
-
return (0,
|
|
3233
|
+
return (0, import_node_path8.join)((0, import_node_os6.homedir)(), ".kairos", "patterns.json");
|
|
3207
3234
|
}
|
|
3208
3235
|
var mcpTelemetry = getMcpTelemetry();
|
|
3209
3236
|
var mcpSessions = /* @__PURE__ */ new Map();
|
|
@@ -3221,7 +3248,14 @@ function getTelemetryReader() {
|
|
|
3221
3248
|
return null;
|
|
3222
3249
|
}
|
|
3223
3250
|
}
|
|
3251
|
+
function getMcpMode() {
|
|
3252
|
+
const mode = process.env["KAIROS_MCP_MODE"]?.toLowerCase();
|
|
3253
|
+
if (mode === "readonly" || mode === "validate") return mode;
|
|
3254
|
+
return "deploy";
|
|
3255
|
+
}
|
|
3224
3256
|
function isAllowed(action) {
|
|
3257
|
+
const mode = getMcpMode();
|
|
3258
|
+
if (mode === "readonly" || mode === "validate") return false;
|
|
3225
3259
|
const key = `KAIROS_MCP_ALLOW_${action.toUpperCase()}`;
|
|
3226
3260
|
return process.env[key] === "true";
|
|
3227
3261
|
}
|
|
@@ -3245,8 +3279,20 @@ function getApiClient() {
|
|
|
3245
3279
|
}
|
|
3246
3280
|
return new N8nApiClient(baseUrl, apiKey, nullLogger);
|
|
3247
3281
|
}
|
|
3282
|
+
function getCatalogCachePath() {
|
|
3283
|
+
const telemetry = process.env["KAIROS_TELEMETRY"];
|
|
3284
|
+
const base = telemetry ? (0, import_node_path8.join)(telemetry, "..") : (0, import_node_path8.join)((0, import_node_os6.homedir)(), ".kairos");
|
|
3285
|
+
return (0, import_node_path8.join)(base, "node-catalog-cache.json");
|
|
3286
|
+
}
|
|
3248
3287
|
async function autoSync() {
|
|
3249
3288
|
if (lastSync) return lastSync;
|
|
3289
|
+
const cachePath = getCatalogCachePath();
|
|
3290
|
+
const cached = await readCatalogCache(cachePath);
|
|
3291
|
+
if (cached) {
|
|
3292
|
+
lastSync = cached;
|
|
3293
|
+
_validator = new N8nValidator(lastSync.registry);
|
|
3294
|
+
return lastSync;
|
|
3295
|
+
}
|
|
3250
3296
|
const baseUrl = process.env["N8N_BASE_URL"];
|
|
3251
3297
|
const apiKey = process.env["N8N_API_KEY"];
|
|
3252
3298
|
if (!baseUrl || !apiKey) return null;
|
|
@@ -3256,6 +3302,8 @@ async function autoSync() {
|
|
|
3256
3302
|
if (nodeTypes.length === 0) return null;
|
|
3257
3303
|
lastSync = nodeSyncer.sync(nodeTypes);
|
|
3258
3304
|
_validator = new N8nValidator(lastSync.registry);
|
|
3305
|
+
writeCatalogCache(cachePath, lastSync).catch(() => {
|
|
3306
|
+
});
|
|
3259
3307
|
return lastSync;
|
|
3260
3308
|
} catch {
|
|
3261
3309
|
return null;
|
|
@@ -3274,13 +3322,9 @@ server.tool(
|
|
|
3274
3322
|
},
|
|
3275
3323
|
async ({ description, name }) => {
|
|
3276
3324
|
evictStaleSessions();
|
|
3277
|
-
const baseUrl = process.env["N8N_BASE_URL"];
|
|
3278
|
-
const apiKey = process.env["N8N_API_KEY"];
|
|
3279
|
-
if (!baseUrl || !apiKey) {
|
|
3280
|
-
return mcpError(JSON.stringify({ error: "N8N_BASE_URL and N8N_API_KEY are required. Kairos needs to sync your n8n instance's node types to generate accurate workflows." }));
|
|
3281
|
-
}
|
|
3282
3325
|
const runId = generateUUID();
|
|
3283
3326
|
const workflowType = inferWorkflowType(description);
|
|
3327
|
+
const hasN8nCreds = !!(process.env["N8N_BASE_URL"] && process.env["N8N_API_KEY"]);
|
|
3284
3328
|
const syncPromise = autoSync();
|
|
3285
3329
|
const syncTimeout = new Promise((resolve) => setTimeout(() => resolve(null), AUTO_SYNC_TIMEOUT_MS));
|
|
3286
3330
|
await library.initialize();
|
|
@@ -3300,7 +3344,8 @@ server.tool(
|
|
|
3300
3344
|
startTime: Date.now(),
|
|
3301
3345
|
validateAttempts: 0,
|
|
3302
3346
|
warnedRules: promptBuilder.getWarnedRules(),
|
|
3303
|
-
workflowType
|
|
3347
|
+
workflowType,
|
|
3348
|
+
matchCount: matches.length
|
|
3304
3349
|
});
|
|
3305
3350
|
await mcpTelemetry.emit("build_start", { description, model: "mcp-decomposed", dryRun: false }, runId);
|
|
3306
3351
|
}
|
|
@@ -3312,7 +3357,9 @@ server.tool(
|
|
|
3312
3357
|
topMatchScore: matches[0]?.score ?? null,
|
|
3313
3358
|
nodeCatalog: syncResult ? "synced" : "static",
|
|
3314
3359
|
nodeCount: syncResult?.nodeCount ?? null,
|
|
3315
|
-
...syncResult ? {} : {
|
|
3360
|
+
...syncResult ? {} : {
|
|
3361
|
+
syncWarning: hasN8nCreds ? "Could not sync node types from your n8n instance. Using static fallback catalog \u2014 generated workflows may not match your exact n8n setup." : "N8N_BASE_URL and N8N_API_KEY are not set. Using static fallback catalog \u2014 node types may not match your n8n instance. Set these env vars to enable accurate generation and deployment."
|
|
3362
|
+
},
|
|
3316
3363
|
systemPrompt: systemText,
|
|
3317
3364
|
userMessage: built.userMessage,
|
|
3318
3365
|
outputFormat: {
|
|
@@ -3385,10 +3432,11 @@ server.tool(
|
|
|
3385
3432
|
{
|
|
3386
3433
|
workflow: import_zod.z.string().describe("The validated workflow JSON string to deploy"),
|
|
3387
3434
|
activate: import_zod.z.boolean().default(false).describe("Activate the workflow immediately after deployment"),
|
|
3435
|
+
description: import_zod.z.string().optional().describe("The original user intent / description for this workflow \u2014 used to improve library search quality over time"),
|
|
3388
3436
|
kairos_run_id: import_zod.z.string().optional().describe("Run ID from kairos_prompt \u2014 enables telemetry correlation"),
|
|
3389
3437
|
kairos_secret: import_zod.z.string().optional().describe("Required when KAIROS_MCP_SECRET env var is set")
|
|
3390
3438
|
},
|
|
3391
|
-
async ({ workflow: workflowStr, activate, kairos_run_id, kairos_secret }) => {
|
|
3439
|
+
async ({ workflow: workflowStr, activate, description: userDescription, kairos_run_id, kairos_secret }) => {
|
|
3392
3440
|
const authError = checkMcpAuth(kairos_secret);
|
|
3393
3441
|
if (authError) return authError;
|
|
3394
3442
|
if (!isAllowed("deploy")) {
|
|
@@ -3429,8 +3477,8 @@ server.tool(
|
|
|
3429
3477
|
Note: kairos_run_id "${kairos_run_id}" was provided but no active session was found. This usually means kairos_deploy was called without a prior kairos_prompt call, or the session expired. Telemetry and pattern learning for this build were skipped.` : "";
|
|
3430
3478
|
await library.initialize();
|
|
3431
3479
|
await library.save(parsed, {
|
|
3432
|
-
description: session?.description ?? parsed.name,
|
|
3433
|
-
generationMode: "scratch",
|
|
3480
|
+
description: session?.description ?? userDescription ?? parsed.name,
|
|
3481
|
+
generationMode: session && session.matchCount > 0 ? "reference" : "scratch",
|
|
3434
3482
|
generationAttempts: session?.validateAttempts ?? 1,
|
|
3435
3483
|
n8nWorkflowId: response.id
|
|
3436
3484
|
});
|
|
@@ -3467,12 +3515,16 @@ server.tool(
|
|
|
3467
3515
|
{
|
|
3468
3516
|
workflow_id: import_zod.z.string().describe("The n8n workflow ID to replace"),
|
|
3469
3517
|
workflow: import_zod.z.string().describe("The validated workflow JSON string"),
|
|
3518
|
+
description: import_zod.z.string().optional().describe("The original user intent / description for this workflow \u2014 used to improve library search quality over time"),
|
|
3470
3519
|
kairos_run_id: import_zod.z.string().optional().describe("Run ID from kairos_prompt \u2014 enables telemetry correlation"),
|
|
3471
3520
|
kairos_secret: import_zod.z.string().optional().describe("Required when KAIROS_MCP_SECRET env var is set")
|
|
3472
3521
|
},
|
|
3473
|
-
async ({ workflow_id, workflow: workflowStr, kairos_run_id, kairos_secret }) => {
|
|
3522
|
+
async ({ workflow_id, workflow: workflowStr, description: userDescription, kairos_run_id, kairos_secret }) => {
|
|
3474
3523
|
const authError = checkMcpAuth(kairos_secret);
|
|
3475
3524
|
if (authError) return authError;
|
|
3525
|
+
if (!isAllowed("deploy")) {
|
|
3526
|
+
return mcpError(JSON.stringify({ error: "Replace is disabled. Set KAIROS_MCP_ALLOW_DEPLOY=true or KAIROS_MCP_MODE=deploy to enable." }));
|
|
3527
|
+
}
|
|
3476
3528
|
let parsed;
|
|
3477
3529
|
try {
|
|
3478
3530
|
parsed = JSON.parse(workflowStr);
|
|
@@ -3496,8 +3548,8 @@ server.tool(
|
|
|
3496
3548
|
Note: kairos_run_id "${kairos_run_id}" was provided but no active session was found.` : "";
|
|
3497
3549
|
await library.initialize();
|
|
3498
3550
|
await library.save(parsed, {
|
|
3499
|
-
description: session?.description ?? parsed.name,
|
|
3500
|
-
generationMode: "scratch",
|
|
3551
|
+
description: session?.description ?? userDescription ?? parsed.name,
|
|
3552
|
+
generationMode: session && session.matchCount > 0 ? "reference" : "scratch",
|
|
3501
3553
|
generationAttempts: session?.validateAttempts ?? 1,
|
|
3502
3554
|
n8nWorkflowId: workflow_id
|
|
3503
3555
|
});
|
|
@@ -3743,8 +3795,27 @@ async function main() {
|
|
|
3743
3795
|
"[kairos-mcp] WARNING: ANTHROPIC_API_KEY is not set \u2014 kairos_prompt will fail. Set it before using workflow generation tools.\n"
|
|
3744
3796
|
);
|
|
3745
3797
|
}
|
|
3746
|
-
const
|
|
3747
|
-
|
|
3798
|
+
const useHttp = process.argv.includes("--http");
|
|
3799
|
+
if (useHttp) {
|
|
3800
|
+
const port = parseInt(process.env["KAIROS_MCP_PORT"] ?? "3000", 10);
|
|
3801
|
+
const transport = new import_streamableHttp.StreamableHTTPServerTransport();
|
|
3802
|
+
await server.connect(transport);
|
|
3803
|
+
const httpServer = (0, import_node_http.createServer)(async (req, res) => {
|
|
3804
|
+
if (req.method === "GET" || req.method === "POST" || req.method === "DELETE") {
|
|
3805
|
+
await transport.handleRequest(req, res);
|
|
3806
|
+
} else {
|
|
3807
|
+
res.writeHead(405, { "Content-Type": "application/json" });
|
|
3808
|
+
res.end(JSON.stringify({ error: "Method not allowed" }));
|
|
3809
|
+
}
|
|
3810
|
+
});
|
|
3811
|
+
httpServer.listen(port, () => {
|
|
3812
|
+
process.stderr.write(`[kairos-mcp] HTTP transport listening on port ${port}
|
|
3813
|
+
`);
|
|
3814
|
+
});
|
|
3815
|
+
} else {
|
|
3816
|
+
const transport = new import_stdio.StdioServerTransport();
|
|
3817
|
+
await server.connect(transport);
|
|
3818
|
+
}
|
|
3748
3819
|
}
|
|
3749
3820
|
main().catch((err) => {
|
|
3750
3821
|
console.error("Kairos MCP server failed to start:", err);
|