@kairos-sdk/core 0.5.0 → 0.6.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.
Files changed (44) hide show
  1. package/README.md +131 -16
  2. package/dist/{chunk-KIFT5LA7.js → chunk-2ZHNO37N.js} +49 -5
  3. package/dist/chunk-2ZHNO37N.js.map +1 -0
  4. package/dist/chunk-GG4B4TYG.js +153 -0
  5. package/dist/chunk-GG4B4TYG.js.map +1 -0
  6. package/dist/{chunk-5GAY7CSJ.js → chunk-PCNW5ZUD.js} +2 -2
  7. package/dist/chunk-SC6CLQZB.js +144 -0
  8. package/dist/chunk-SC6CLQZB.js.map +1 -0
  9. package/dist/chunk-SQS4QHDH.js +44 -0
  10. package/dist/chunk-SQS4QHDH.js.map +1 -0
  11. package/dist/{chunk-EVOAYH2K.js → chunk-STG7Z2SS.js} +2 -2
  12. package/dist/{chunk-HBGZTUUZ.js → chunk-YOQTEVDB.js} +5 -7
  13. package/dist/chunk-YOQTEVDB.js.map +1 -0
  14. package/dist/cli.cjs +702 -40
  15. package/dist/cli.cjs.map +1 -1
  16. package/dist/cli.js +262 -7
  17. package/dist/cli.js.map +1 -1
  18. package/dist/index.cjs +417 -39
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +86 -4
  21. package/dist/index.d.ts +86 -4
  22. package/dist/index.js +19 -5
  23. package/dist/mcp-server.cjs +139 -24
  24. package/dist/mcp-server.cjs.map +1 -1
  25. package/dist/mcp-server.js +90 -19
  26. package/dist/mcp-server.js.map +1 -1
  27. package/dist/pack-builder-RTQWXGIS.js +9 -0
  28. package/dist/pack-builder-RTQWXGIS.js.map +1 -0
  29. package/dist/pack-exporter-KFNLSP5V.js +7 -0
  30. package/dist/pack-exporter-KFNLSP5V.js.map +1 -0
  31. package/dist/pack-validator-HZPB2XJ3.js +7 -0
  32. package/dist/pack-validator-HZPB2XJ3.js.map +1 -0
  33. package/dist/{reader-B5mV20H6.d.ts → reader-CfWGpL4V.d.cts} +2 -1
  34. package/dist/{reader-B5mV20H6.d.cts → reader-CfWGpL4V.d.ts} +2 -1
  35. package/dist/standalone.cjs +44 -4
  36. package/dist/standalone.cjs.map +1 -1
  37. package/dist/standalone.d.cts +1 -1
  38. package/dist/standalone.d.ts +1 -1
  39. package/dist/standalone.js +2 -2
  40. package/package.json +12 -5
  41. package/dist/chunk-HBGZTUUZ.js.map +0 -1
  42. package/dist/chunk-KIFT5LA7.js.map +0 -1
  43. /package/dist/{chunk-5GAY7CSJ.js.map → chunk-PCNW5ZUD.js.map} +0 -0
  44. /package/dist/{chunk-EVOAYH2K.js.map → chunk-STG7Z2SS.js.map} +0 -0
@@ -0,0 +1,153 @@
1
+ // src/pack/pack-builder.ts
2
+ import Anthropic from "@anthropic-ai/sdk";
3
+ function derivePackStatus(pack) {
4
+ const hasBlocking = pack.assumptions.some((a) => a.type === "blocking");
5
+ const hasFailures = pack.workflows.some((w) => w.error);
6
+ const allDeployed = pack.workflows.length > 0 && pack.workflows.every((w) => w.deployed);
7
+ const hasNeedsConfirmation = pack.assumptions.some((a) => a.type === "needs_confirmation");
8
+ if (pack.status === "active" && !hasBlocking && !hasFailures && allDeployed) return "active";
9
+ if (pack.workflows.length === 0 || !allDeployed && !hasFailures) return "draft";
10
+ if (hasBlocking) return "blocked";
11
+ if (hasFailures) return "needs_attention";
12
+ if (hasNeedsConfirmation) return "ready_for_test";
13
+ return "ready_for_activation";
14
+ }
15
+ var PLAN_PROMPT = `You are planning an n8n workflow automation pack for a business.
16
+
17
+ Business context: {CONTEXT}
18
+
19
+ Generate a list of 4-8 n8n workflows that would meaningfully automate this business's operations. Focus on workflows that save time on repetitive tasks, improve customer communication, prevent things falling through the cracks, and are realistic to implement with n8n nodes.
20
+
21
+ For each workflow, write a detailed build description (2-4 sentences) suitable for passing directly to an n8n workflow generator. Be specific: name the trigger type, data sources (Google Sheets columns if applicable), actions, and outputs.
22
+
23
+ For assumptions, classify each one:
24
+ - "safe": a clearly reasonable default the business likely expects (e.g. "Schedule runs Monday 9 AM")
25
+ - "needs_confirmation": should be confirmed before going live but won't break things immediately (e.g. "Assumed professional email tone \u2014 confirm brand voice")
26
+ - "blocking": MUST be resolved before activation or the workflow will fail, send duplicates, or surprise customers (e.g. "Google Sheet ID not provided", "emails auto-send without approval gate \u2014 add confirmation step")
27
+
28
+ Treat any open question that would block safe deployment as a blocking assumption.
29
+
30
+ Return ONLY valid JSON with no markdown or extra text:
31
+ {
32
+ "workflows": [
33
+ {
34
+ "name": "Short descriptive name",
35
+ "description": "Detailed generator-ready description specifying trigger, data sources, actions, outputs",
36
+ "purpose": "One sentence explaining the business value"
37
+ }
38
+ ],
39
+ "assumptions": [
40
+ { "type": "safe" | "needs_confirmation" | "blocking", "text": "Description of the assumption" }
41
+ ],
42
+ "sheetsColumns": [
43
+ { "sheet": "Sheet name", "columns": ["col1", "col2"] }
44
+ ],
45
+ "testChecklist": [
46
+ { "workflow": "Workflow name", "steps": ["How to manually test this workflow"] }
47
+ ]
48
+ }`;
49
+ function normalizeAssumptions(raw) {
50
+ const validTypes = /* @__PURE__ */ new Set(["safe", "needs_confirmation", "blocking"]);
51
+ return raw.map((a) => {
52
+ if (typeof a === "string") {
53
+ return { type: "needs_confirmation", text: a };
54
+ }
55
+ if (typeof a === "object" && a !== null) {
56
+ const obj = a;
57
+ const type = typeof obj["type"] === "string" && validTypes.has(obj["type"]) ? obj["type"] : "needs_confirmation";
58
+ const text = typeof obj["text"] === "string" ? obj["text"] : JSON.stringify(obj);
59
+ return { type, text };
60
+ }
61
+ return { type: "needs_confirmation", text: String(a) };
62
+ });
63
+ }
64
+ var PackBuilder = class {
65
+ client;
66
+ kairos;
67
+ model;
68
+ constructor(options) {
69
+ this.client = new Anthropic({ apiKey: options.anthropicApiKey });
70
+ this.kairos = options.kairos;
71
+ this.model = options.model ?? "claude-sonnet-4-6";
72
+ }
73
+ async plan(businessContext) {
74
+ const prompt = PLAN_PROMPT.replace("{CONTEXT}", businessContext);
75
+ const response = await this.client.messages.create({
76
+ model: this.model,
77
+ max_tokens: 4096,
78
+ messages: [{ role: "user", content: prompt }]
79
+ });
80
+ const text = response.content[0]?.type === "text" ? response.content[0].text.trim() : "";
81
+ const cleaned = text.replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "").trim();
82
+ const parsed = JSON.parse(cleaned);
83
+ const rawAssumptions = Array.isArray(parsed["assumptions"]) ? parsed["assumptions"] : [];
84
+ const rawOpenQuestions = Array.isArray(parsed["openQuestions"]) ? parsed["openQuestions"] : [];
85
+ const assumptions = normalizeAssumptions([...rawAssumptions, ...rawOpenQuestions.map(
86
+ (q) => typeof q === "string" ? { type: "needs_confirmation", text: q } : q
87
+ )]);
88
+ return {
89
+ businessContext,
90
+ workflows: Array.isArray(parsed["workflows"]) ? parsed["workflows"] : [],
91
+ assumptions,
92
+ sheetsColumns: Array.isArray(parsed["sheetsColumns"]) ? parsed["sheetsColumns"] : [],
93
+ testChecklist: Array.isArray(parsed["testChecklist"]) ? parsed["testChecklist"] : []
94
+ };
95
+ }
96
+ async build(plan, options = {}) {
97
+ const hasBlockingAssumptions = plan.assumptions.some((a) => a.type === "blocking");
98
+ const effectiveActivate = hasBlockingAssumptions ? false : options.activate ?? false;
99
+ const results = [];
100
+ const credentialMap = /* @__PURE__ */ new Map();
101
+ for (let i = 0; i < plan.workflows.length; i++) {
102
+ const wf = plan.workflows[i];
103
+ options.onProgress?.(wf, i, plan.workflows.length);
104
+ try {
105
+ const result = await this.kairos.build(wf.description, {
106
+ name: wf.name,
107
+ dryRun: options.dryRun ?? false,
108
+ activate: effectiveActivate
109
+ });
110
+ for (const cred of result.credentialsNeeded) {
111
+ credentialMap.set(cred.service, { service: cred.service, credentialType: cred.credentialType });
112
+ }
113
+ results.push({
114
+ name: wf.name,
115
+ purpose: wf.purpose,
116
+ workflowId: result.workflowId,
117
+ deployed: !result.dryRun,
118
+ generationAttempts: result.generationAttempts,
119
+ credentialsNeeded: result.credentialsNeeded
120
+ });
121
+ } catch (err) {
122
+ results.push({
123
+ name: wf.name,
124
+ purpose: wf.purpose,
125
+ workflowId: null,
126
+ deployed: false,
127
+ generationAttempts: 0,
128
+ credentialsNeeded: [],
129
+ error: err instanceof Error ? err.message : String(err)
130
+ });
131
+ }
132
+ }
133
+ const packName = plan.businessContext.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
134
+ const partial = {
135
+ businessContext: plan.businessContext,
136
+ packName,
137
+ status: "draft",
138
+ workflows: results,
139
+ allCredentials: Array.from(credentialMap.values()),
140
+ sheetsColumns: plan.sheetsColumns,
141
+ assumptions: plan.assumptions,
142
+ testChecklist: plan.testChecklist,
143
+ builtAt: (/* @__PURE__ */ new Date()).toISOString()
144
+ };
145
+ return { ...partial, status: derivePackStatus(partial) };
146
+ }
147
+ };
148
+
149
+ export {
150
+ derivePackStatus,
151
+ PackBuilder
152
+ };
153
+ //# sourceMappingURL=chunk-GG4B4TYG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pack/pack-builder.ts"],"sourcesContent":["import Anthropic from '@anthropic-ai/sdk'\nimport type { Kairos } from '../client.js'\nimport type { CredentialRequirement } from '../types/result.js'\n\nexport type AssumptionType = 'safe' | 'needs_confirmation' | 'blocking'\nexport type PackStatus = 'draft' | 'blocked' | 'ready_for_test' | 'ready_for_activation' | 'active' | 'needs_attention'\n\nexport interface TypedAssumption {\n type: AssumptionType\n text: string\n}\n\nexport interface WorkflowPlan {\n name: string\n description: string\n purpose: string\n}\n\nexport interface PackPlan {\n businessContext: string\n workflows: WorkflowPlan[]\n assumptions: TypedAssumption[]\n sheetsColumns: Array<{ sheet: string; columns: string[] }>\n testChecklist: Array<{ workflow: string; steps: string[] }>\n}\n\nexport interface PackWorkflowResult {\n name: string\n purpose: string\n workflowId: string | null\n deployed: boolean\n generationAttempts: number\n credentialsNeeded: CredentialRequirement[]\n error?: string\n}\n\nexport interface WorkflowPackResult {\n businessContext: string\n packName: string\n status: PackStatus\n workflows: PackWorkflowResult[]\n allCredentials: Array<{ service: string; credentialType: string }>\n sheetsColumns: Array<{ sheet: string; columns: string[] }>\n assumptions: TypedAssumption[]\n testChecklist: Array<{ workflow: string; steps: string[] }>\n builtAt: string\n}\n\nexport function derivePackStatus(\n pack: Pick<WorkflowPackResult, 'assumptions' | 'workflows'> & { status?: PackStatus }\n): PackStatus {\n const hasBlocking = pack.assumptions.some(a => a.type === 'blocking')\n const hasFailures = pack.workflows.some(w => w.error)\n const allDeployed = pack.workflows.length > 0 && pack.workflows.every(w => w.deployed)\n const hasNeedsConfirmation = pack.assumptions.some(a => a.type === 'needs_confirmation')\n\n // Preserve active status if the pack is still in a healthy deployed state\n if (pack.status === 'active' && !hasBlocking && !hasFailures && allDeployed) return 'active'\n\n if (pack.workflows.length === 0 || (!allDeployed && !hasFailures)) return 'draft'\n if (hasBlocking) return 'blocked'\n if (hasFailures) return 'needs_attention'\n if (hasNeedsConfirmation) return 'ready_for_test'\n return 'ready_for_activation'\n}\n\nconst PLAN_PROMPT = `You are planning an n8n workflow automation pack for a business.\n\nBusiness context: {CONTEXT}\n\nGenerate a list of 4-8 n8n workflows that would meaningfully automate this business's operations. Focus on workflows that save time on repetitive tasks, improve customer communication, prevent things falling through the cracks, and are realistic to implement with n8n nodes.\n\nFor each workflow, write a detailed build description (2-4 sentences) suitable for passing directly to an n8n workflow generator. Be specific: name the trigger type, data sources (Google Sheets columns if applicable), actions, and outputs.\n\nFor assumptions, classify each one:\n- \"safe\": a clearly reasonable default the business likely expects (e.g. \"Schedule runs Monday 9 AM\")\n- \"needs_confirmation\": should be confirmed before going live but won't break things immediately (e.g. \"Assumed professional email tone — confirm brand voice\")\n- \"blocking\": MUST be resolved before activation or the workflow will fail, send duplicates, or surprise customers (e.g. \"Google Sheet ID not provided\", \"emails auto-send without approval gate — add confirmation step\")\n\nTreat any open question that would block safe deployment as a blocking assumption.\n\nReturn ONLY valid JSON with no markdown or extra text:\n{\n \"workflows\": [\n {\n \"name\": \"Short descriptive name\",\n \"description\": \"Detailed generator-ready description specifying trigger, data sources, actions, outputs\",\n \"purpose\": \"One sentence explaining the business value\"\n }\n ],\n \"assumptions\": [\n { \"type\": \"safe\" | \"needs_confirmation\" | \"blocking\", \"text\": \"Description of the assumption\" }\n ],\n \"sheetsColumns\": [\n { \"sheet\": \"Sheet name\", \"columns\": [\"col1\", \"col2\"] }\n ],\n \"testChecklist\": [\n { \"workflow\": \"Workflow name\", \"steps\": [\"How to manually test this workflow\"] }\n ]\n}`\n\nfunction normalizeAssumptions(raw: unknown[]): TypedAssumption[] {\n const validTypes = new Set<string>(['safe', 'needs_confirmation', 'blocking'])\n return raw.map((a): TypedAssumption => {\n if (typeof a === 'string') {\n return { type: 'needs_confirmation', text: a }\n }\n if (typeof a === 'object' && a !== null) {\n const obj = a as Record<string, unknown>\n const type = typeof obj['type'] === 'string' && validTypes.has(obj['type'])\n ? (obj['type'] as AssumptionType)\n : 'needs_confirmation'\n const text = typeof obj['text'] === 'string' ? obj['text'] : JSON.stringify(obj)\n return { type, text }\n }\n return { type: 'needs_confirmation', text: String(a) }\n })\n}\n\nexport class PackBuilder {\n private client: Anthropic\n private kairos: Kairos\n private model: string\n\n constructor(options: { anthropicApiKey: string; kairos: Kairos; model?: string }) {\n this.client = new Anthropic({ apiKey: options.anthropicApiKey })\n this.kairos = options.kairos\n this.model = options.model ?? 'claude-sonnet-4-6'\n }\n\n async plan(businessContext: string): Promise<PackPlan> {\n const prompt = PLAN_PROMPT.replace('{CONTEXT}', businessContext)\n const response = await this.client.messages.create({\n model: this.model,\n max_tokens: 4096,\n messages: [{ role: 'user', content: prompt }],\n })\n\n const text = response.content[0]?.type === 'text' ? response.content[0].text.trim() : ''\n\n // Strip markdown code fences if present\n const cleaned = text.replace(/^```(?:json)?\\s*/i, '').replace(/\\s*```$/, '').trim()\n const parsed = JSON.parse(cleaned) as Record<string, unknown>\n\n const rawAssumptions = Array.isArray(parsed['assumptions']) ? parsed['assumptions'] : []\n // Fold legacy openQuestions into needs_confirmation assumptions\n const rawOpenQuestions = Array.isArray(parsed['openQuestions']) ? parsed['openQuestions'] : []\n\n const assumptions = normalizeAssumptions([...rawAssumptions, ...rawOpenQuestions.map((q: unknown) =>\n typeof q === 'string' ? { type: 'needs_confirmation', text: q } : q\n )])\n\n return {\n businessContext,\n workflows: Array.isArray(parsed['workflows']) ? (parsed['workflows'] as WorkflowPlan[]) : [],\n assumptions,\n sheetsColumns: Array.isArray(parsed['sheetsColumns'])\n ? (parsed['sheetsColumns'] as PackPlan['sheetsColumns'])\n : [],\n testChecklist: Array.isArray(parsed['testChecklist'])\n ? (parsed['testChecklist'] as PackPlan['testChecklist'])\n : [],\n }\n }\n\n async build(\n plan: PackPlan,\n options: {\n dryRun?: boolean\n activate?: boolean\n onProgress?: (workflow: WorkflowPlan, index: number, total: number) => void\n } = {}\n ): Promise<WorkflowPackResult> {\n const hasBlockingAssumptions = plan.assumptions.some(a => a.type === 'blocking')\n // Never activate when blocking assumptions exist — safety gate\n const effectiveActivate = hasBlockingAssumptions ? false : (options.activate ?? false)\n\n const results: PackWorkflowResult[] = []\n const credentialMap = new Map<string, { service: string; credentialType: string }>()\n\n for (let i = 0; i < plan.workflows.length; i++) {\n const wf = plan.workflows[i]!\n options.onProgress?.(wf, i, plan.workflows.length)\n\n try {\n const result = await this.kairos.build(wf.description, {\n name: wf.name,\n dryRun: options.dryRun ?? false,\n activate: effectiveActivate,\n })\n\n for (const cred of result.credentialsNeeded) {\n credentialMap.set(cred.service, { service: cred.service, credentialType: cred.credentialType })\n }\n\n results.push({\n name: wf.name,\n purpose: wf.purpose,\n workflowId: result.workflowId,\n deployed: !result.dryRun,\n generationAttempts: result.generationAttempts,\n credentialsNeeded: result.credentialsNeeded,\n })\n } catch (err) {\n results.push({\n name: wf.name,\n purpose: wf.purpose,\n workflowId: null,\n deployed: false,\n generationAttempts: 0,\n credentialsNeeded: [],\n error: err instanceof Error ? err.message : String(err),\n })\n }\n }\n\n const packName = plan.businessContext\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n\n const partial = {\n businessContext: plan.businessContext,\n packName,\n status: 'draft' as PackStatus,\n workflows: results,\n allCredentials: Array.from(credentialMap.values()),\n sheetsColumns: plan.sheetsColumns,\n assumptions: plan.assumptions,\n testChecklist: plan.testChecklist,\n builtAt: new Date().toISOString(),\n }\n\n return { ...partial, status: derivePackStatus(partial) }\n }\n}\n"],"mappings":"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","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  N8nValidator,
5
5
  ProviderError,
6
6
  generateUUID
7
- } from "./chunk-KIFT5LA7.js";
7
+ } from "./chunk-2ZHNO37N.js";
8
8
 
9
9
  // src/library/null-library.ts
10
10
  var NullLibrary = class {
@@ -408,4 +408,4 @@ export {
408
408
  ValidationError,
409
409
  TemplateSyncer
410
410
  };
411
- //# sourceMappingURL=chunk-5GAY7CSJ.js.map
411
+ //# sourceMappingURL=chunk-PCNW5ZUD.js.map
@@ -0,0 +1,144 @@
1
+ // src/pack/pack-exporter.ts
2
+ var STATUS_LABELS = {
3
+ draft: "Draft",
4
+ blocked: "Blocked \u2014 resolve issues before activation",
5
+ ready_for_test: "Ready for Testing",
6
+ ready_for_activation: "Ready for Activation",
7
+ active: "Active",
8
+ needs_attention: "Needs Attention"
9
+ };
10
+ function generateHandoff(pack) {
11
+ const lines = [];
12
+ const line = () => lines.push("");
13
+ lines.push(`# ${pack.businessContext} \u2014 Workflow Pack`);
14
+ line();
15
+ lines.push(`**Status:** ${STATUS_LABELS[pack.status] ?? pack.status}`);
16
+ lines.push(`**Generated:** ${new Date(pack.builtAt).toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric" })}`);
17
+ lines.push(`**Workflows:** ${pack.workflows.length} (${pack.workflows.filter((w) => w.deployed).length} deployed)`);
18
+ line();
19
+ lines.push(`## Overview`);
20
+ line();
21
+ lines.push(
22
+ `This workflow pack automates operations for **${pack.businessContext}**. It was built with Kairos and requires credential setup before workflows can be activated in n8n.`
23
+ );
24
+ line();
25
+ const blocking = pack.assumptions.filter((a) => a.type === "blocking");
26
+ if (blocking.length > 0) {
27
+ lines.push(`## Blocking Issues`);
28
+ line();
29
+ lines.push(`> These must be resolved before any workflows are activated.`);
30
+ line();
31
+ for (const a of blocking) {
32
+ lines.push(`- [ ] ${a.text}`);
33
+ }
34
+ line();
35
+ }
36
+ lines.push(`## Workflows`);
37
+ line();
38
+ for (const wf of pack.workflows) {
39
+ const icon = wf.error ? "\u2717" : "\u2713";
40
+ lines.push(`### ${icon} ${wf.name}`);
41
+ line();
42
+ lines.push(`**Purpose:** ${wf.purpose}`);
43
+ if (wf.workflowId) lines.push(`**n8n ID:** \`${wf.workflowId}\``);
44
+ if (!wf.deployed && !wf.error) lines.push(`**Status:** Not deployed (dry run)`);
45
+ if (wf.error) lines.push(`**Error:** ${wf.error}`);
46
+ line();
47
+ }
48
+ if (pack.allCredentials.length > 0) {
49
+ lines.push(`## Required Credentials`);
50
+ line();
51
+ lines.push(`Connect these in n8n before activating workflows:`);
52
+ line();
53
+ for (const cred of pack.allCredentials) {
54
+ lines.push(`- [ ] **${cred.service}** (${cred.credentialType})`);
55
+ }
56
+ line();
57
+ }
58
+ if (pack.sheetsColumns.length > 0) {
59
+ lines.push(`## Required Google Sheets`);
60
+ line();
61
+ for (const sheet of pack.sheetsColumns) {
62
+ lines.push(`### ${sheet.sheet}`);
63
+ line();
64
+ lines.push(`Columns: ${sheet.columns.map((c) => `\`${c}\``).join(", ")}`);
65
+ line();
66
+ }
67
+ }
68
+ const needsConfirmation = pack.assumptions.filter((a) => a.type === "needs_confirmation");
69
+ if (needsConfirmation.length > 0) {
70
+ lines.push(`## Needs Confirmation`);
71
+ line();
72
+ lines.push(`Verify these with the client before going live:`);
73
+ line();
74
+ for (const a of needsConfirmation) {
75
+ lines.push(`- [ ] ${a.text}`);
76
+ }
77
+ line();
78
+ }
79
+ const safe = pack.assumptions.filter((a) => a.type === "safe");
80
+ if (safe.length > 0) {
81
+ lines.push(`## Safe Assumptions`);
82
+ line();
83
+ lines.push(`These defaults were used during generation \u2014 no action needed:`);
84
+ line();
85
+ for (const a of safe) {
86
+ lines.push(`- ${a.text}`);
87
+ }
88
+ line();
89
+ }
90
+ lines.push(`## Setup Checklist`);
91
+ line();
92
+ lines.push(`Complete before testing:`);
93
+ line();
94
+ for (const cred of pack.allCredentials) {
95
+ lines.push(`- [ ] Connect **${cred.service}** credential in n8n Settings \u2192 Credentials`);
96
+ }
97
+ for (const sheet of pack.sheetsColumns) {
98
+ lines.push(`- [ ] Create Google Sheet: "${sheet.sheet}" with columns: ${sheet.columns.join(", ")}`);
99
+ }
100
+ for (const a of blocking) {
101
+ lines.push(`- [ ] Resolve: ${a.text}`);
102
+ }
103
+ for (const a of needsConfirmation) {
104
+ lines.push(`- [ ] Confirm: ${a.text}`);
105
+ }
106
+ line();
107
+ if (pack.testChecklist.length > 0) {
108
+ lines.push(`## Testing Checklist`);
109
+ line();
110
+ for (const item of pack.testChecklist) {
111
+ lines.push(`### ${item.workflow}`);
112
+ line();
113
+ for (const step of item.steps) {
114
+ lines.push(`- [ ] ${step}`);
115
+ }
116
+ line();
117
+ }
118
+ }
119
+ const deployedWorkflows = pack.workflows.filter((w) => w.deployed && !w.error);
120
+ if (deployedWorkflows.length > 0) {
121
+ lines.push(`## Activation Checklist`);
122
+ line();
123
+ lines.push(`Activate in n8n after testing is complete:`);
124
+ line();
125
+ for (const wf of deployedWorkflows) {
126
+ const idSuffix = wf.workflowId ? ` (n8n ID: \`${wf.workflowId}\`)` : "";
127
+ lines.push(`- [ ] Activate: **${wf.name}**${idSuffix}`);
128
+ }
129
+ line();
130
+ }
131
+ lines.push(`## Maintenance Notes`);
132
+ line();
133
+ lines.push(`- Monitor n8n executions weekly \u2014 check the Executions tab for failures`);
134
+ lines.push(`- Re-run \`kairos build-pack\` to regenerate workflows if business needs change`);
135
+ lines.push(`- Update Google Sheets data as business information changes`);
136
+ lines.push(`- Rotate API credentials before expiration (n8n Settings \u2192 Credentials)`);
137
+ lines.push(`- Run \`kairos validate-pack <name>\` before activating after any changes`);
138
+ return lines.join("\n");
139
+ }
140
+
141
+ export {
142
+ generateHandoff
143
+ };
144
+ //# sourceMappingURL=chunk-SC6CLQZB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pack/pack-exporter.ts"],"sourcesContent":["import type { WorkflowPackResult } from './pack-builder.js'\n\nconst STATUS_LABELS: Record<string, string> = {\n draft: 'Draft',\n blocked: 'Blocked — resolve issues before activation',\n ready_for_test: 'Ready for Testing',\n ready_for_activation: 'Ready for Activation',\n active: 'Active',\n needs_attention: 'Needs Attention',\n}\n\nexport function generateHandoff(pack: WorkflowPackResult): string {\n const lines: string[] = []\n const line = () => lines.push('')\n\n lines.push(`# ${pack.businessContext} — Workflow Pack`)\n line()\n lines.push(`**Status:** ${STATUS_LABELS[pack.status] ?? pack.status}`)\n lines.push(`**Generated:** ${new Date(pack.builtAt).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}`)\n lines.push(`**Workflows:** ${pack.workflows.length} (${pack.workflows.filter(w => w.deployed).length} deployed)`)\n line()\n\n // Overview\n lines.push(`## Overview`)\n line()\n lines.push(\n `This workflow pack automates operations for **${pack.businessContext}**. ` +\n `It was built with Kairos and requires credential setup before workflows can be activated in n8n.`\n )\n line()\n\n // Blocking items (elevated to top if present)\n const blocking = pack.assumptions.filter(a => a.type === 'blocking')\n if (blocking.length > 0) {\n lines.push(`## Blocking Issues`)\n line()\n lines.push(`> These must be resolved before any workflows are activated.`)\n line()\n for (const a of blocking) {\n lines.push(`- [ ] ${a.text}`)\n }\n line()\n }\n\n // Workflows\n lines.push(`## Workflows`)\n line()\n for (const wf of pack.workflows) {\n const icon = wf.error ? '✗' : '✓'\n lines.push(`### ${icon} ${wf.name}`)\n line()\n lines.push(`**Purpose:** ${wf.purpose}`)\n if (wf.workflowId) lines.push(`**n8n ID:** \\`${wf.workflowId}\\``)\n if (!wf.deployed && !wf.error) lines.push(`**Status:** Not deployed (dry run)`)\n if (wf.error) lines.push(`**Error:** ${wf.error}`)\n line()\n }\n\n // Required credentials\n if (pack.allCredentials.length > 0) {\n lines.push(`## Required Credentials`)\n line()\n lines.push(`Connect these in n8n before activating workflows:`)\n line()\n for (const cred of pack.allCredentials) {\n lines.push(`- [ ] **${cred.service}** (${cred.credentialType})`)\n }\n line()\n }\n\n // Required Google Sheets\n if (pack.sheetsColumns.length > 0) {\n lines.push(`## Required Google Sheets`)\n line()\n for (const sheet of pack.sheetsColumns) {\n lines.push(`### ${sheet.sheet}`)\n line()\n lines.push(`Columns: ${sheet.columns.map(c => `\\`${c}\\``).join(', ')}`)\n line()\n }\n }\n\n // Needs confirmation\n const needsConfirmation = pack.assumptions.filter(a => a.type === 'needs_confirmation')\n if (needsConfirmation.length > 0) {\n lines.push(`## Needs Confirmation`)\n line()\n lines.push(`Verify these with the client before going live:`)\n line()\n for (const a of needsConfirmation) {\n lines.push(`- [ ] ${a.text}`)\n }\n line()\n }\n\n // Safe assumptions\n const safe = pack.assumptions.filter(a => a.type === 'safe')\n if (safe.length > 0) {\n lines.push(`## Safe Assumptions`)\n line()\n lines.push(`These defaults were used during generation — no action needed:`)\n line()\n for (const a of safe) {\n lines.push(`- ${a.text}`)\n }\n line()\n }\n\n // Setup checklist\n lines.push(`## Setup Checklist`)\n line()\n lines.push(`Complete before testing:`)\n line()\n for (const cred of pack.allCredentials) {\n lines.push(`- [ ] Connect **${cred.service}** credential in n8n Settings → Credentials`)\n }\n for (const sheet of pack.sheetsColumns) {\n lines.push(`- [ ] Create Google Sheet: \"${sheet.sheet}\" with columns: ${sheet.columns.join(', ')}`)\n }\n for (const a of blocking) {\n lines.push(`- [ ] Resolve: ${a.text}`)\n }\n for (const a of needsConfirmation) {\n lines.push(`- [ ] Confirm: ${a.text}`)\n }\n line()\n\n // Testing checklist\n if (pack.testChecklist.length > 0) {\n lines.push(`## Testing Checklist`)\n line()\n for (const item of pack.testChecklist) {\n lines.push(`### ${item.workflow}`)\n line()\n for (const step of item.steps) {\n lines.push(`- [ ] ${step}`)\n }\n line()\n }\n }\n\n // Activation checklist\n const deployedWorkflows = pack.workflows.filter(w => w.deployed && !w.error)\n if (deployedWorkflows.length > 0) {\n lines.push(`## Activation Checklist`)\n line()\n lines.push(`Activate in n8n after testing is complete:`)\n line()\n for (const wf of deployedWorkflows) {\n const idSuffix = wf.workflowId ? ` (n8n ID: \\`${wf.workflowId}\\`)` : ''\n lines.push(`- [ ] Activate: **${wf.name}**${idSuffix}`)\n }\n line()\n }\n\n // Maintenance notes\n lines.push(`## Maintenance Notes`)\n line()\n lines.push(`- Monitor n8n executions weekly — check the Executions tab for failures`)\n lines.push(`- Re-run \\`kairos build-pack\\` to regenerate workflows if business needs change`)\n lines.push(`- Update Google Sheets data as business information changes`)\n lines.push(`- Rotate API credentials before expiration (n8n Settings → Credentials)`)\n lines.push(`- Run \\`kairos validate-pack <name>\\` before activating after any changes`)\n\n return lines.join('\\n')\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,44 @@
1
+ // src/pack/pack-validator.ts
2
+ function validatePack(pack) {
3
+ const issues = [];
4
+ const names = pack.workflows.map((w) => w.name);
5
+ const seen = /* @__PURE__ */ new Set();
6
+ const duplicates = /* @__PURE__ */ new Set();
7
+ for (const name of names) {
8
+ if (seen.has(name)) duplicates.add(name);
9
+ seen.add(name);
10
+ }
11
+ if (duplicates.size > 0) {
12
+ issues.push({
13
+ type: "duplicate_name",
14
+ severity: "error",
15
+ message: `Duplicate workflow names: ${[...duplicates].join(", ")} \u2014 n8n may overwrite existing workflows on deploy`,
16
+ workflows: [...duplicates]
17
+ });
18
+ }
19
+ const blocking = pack.assumptions.filter((a) => a.type === "blocking");
20
+ if (blocking.length > 0) {
21
+ const plural = blocking.length === 1 ? "assumption" : "assumptions";
22
+ issues.push({
23
+ type: "blocking_assumption",
24
+ severity: "error",
25
+ message: `${blocking.length} blocking ${plural} must be resolved before activation:
26
+ ${blocking.map((a) => `\u2022 ${a.text}`).join("\n ")}`
27
+ });
28
+ }
29
+ const failed = pack.workflows.filter((w) => w.error);
30
+ for (const wf of failed) {
31
+ issues.push({
32
+ type: "unsafe_activation",
33
+ severity: "error",
34
+ message: `Workflow "${wf.name}" failed to deploy: ${wf.error ?? "unknown error"}`,
35
+ workflows: [wf.name]
36
+ });
37
+ }
38
+ return issues;
39
+ }
40
+
41
+ export {
42
+ validatePack
43
+ };
44
+ //# sourceMappingURL=chunk-SQS4QHDH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pack/pack-validator.ts"],"sourcesContent":["import type { WorkflowPackResult } from './pack-builder.js'\n\nexport interface PackValidationIssue {\n type: 'duplicate_name' | 'blocking_assumption' | 'unsafe_activation' | 'schedule_conflict'\n severity: 'error' | 'warning'\n message: string\n workflows?: string[]\n}\n\nexport function validatePack(pack: WorkflowPackResult): PackValidationIssue[] {\n const issues: PackValidationIssue[] = []\n\n // Duplicate workflow names\n const names = pack.workflows.map(w => w.name)\n const seen = new Set<string>()\n const duplicates = new Set<string>()\n for (const name of names) {\n if (seen.has(name)) duplicates.add(name)\n seen.add(name)\n }\n if (duplicates.size > 0) {\n issues.push({\n type: 'duplicate_name',\n severity: 'error',\n message: `Duplicate workflow names: ${[...duplicates].join(', ')} — n8n may overwrite existing workflows on deploy`,\n workflows: [...duplicates],\n })\n }\n\n // Unresolved blocking assumptions\n const blocking = pack.assumptions.filter(a => a.type === 'blocking')\n if (blocking.length > 0) {\n const plural = blocking.length === 1 ? 'assumption' : 'assumptions'\n issues.push({\n type: 'blocking_assumption',\n severity: 'error',\n message: `${blocking.length} blocking ${plural} must be resolved before activation:\\n ${blocking.map(a => `• ${a.text}`).join('\\n ')}`,\n })\n }\n\n // Workflows that failed to deploy\n const failed = pack.workflows.filter(w => w.error)\n for (const wf of failed) {\n issues.push({\n type: 'unsafe_activation',\n severity: 'error',\n message: `Workflow \"${wf.name}\" failed to deploy: ${wf.error ?? 'unknown error'}`,\n workflows: [wf.name],\n })\n }\n\n return issues\n}\n"],"mappings":";AASO,SAAS,aAAa,MAAiD;AAC5E,QAAM,SAAgC,CAAC;AAGvC,QAAM,QAAQ,KAAK,UAAU,IAAI,OAAK,EAAE,IAAI;AAC5C,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,IAAI,IAAI,EAAG,YAAW,IAAI,IAAI;AACvC,SAAK,IAAI,IAAI;AAAA,EACf;AACA,MAAI,WAAW,OAAO,GAAG;AACvB,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,6BAA6B,CAAC,GAAG,UAAU,EAAE,KAAK,IAAI,CAAC;AAAA,MAChE,WAAW,CAAC,GAAG,UAAU;AAAA,IAC3B,CAAC;AAAA,EACH;AAGA,QAAM,WAAW,KAAK,YAAY,OAAO,OAAK,EAAE,SAAS,UAAU;AACnE,MAAI,SAAS,SAAS,GAAG;AACvB,UAAM,SAAS,SAAS,WAAW,IAAI,eAAe;AACtD,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,GAAG,SAAS,MAAM,aAAa,MAAM;AAAA,IAA2C,SAAS,IAAI,OAAK,UAAK,EAAE,IAAI,EAAE,EAAE,KAAK,MAAM,CAAC;AAAA,IACxI,CAAC;AAAA,EACH;AAGA,QAAM,SAAS,KAAK,UAAU,OAAO,OAAK,EAAE,KAAK;AACjD,aAAW,MAAM,QAAQ;AACvB,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,aAAa,GAAG,IAAI,uBAAuB,GAAG,SAAS,eAAe;AAAA,MAC/E,WAAW,CAAC,GAAG,IAAI;AAAA,IACrB,CAAC;AAAA,EACH;AAEA,SAAO;AACT;","names":[]}
@@ -2,7 +2,7 @@ import {
2
2
  RULE_EXAMPLES,
3
3
  RULE_MITIGATIONS,
4
4
  scoreToMode
5
- } from "./chunk-KIFT5LA7.js";
5
+ } from "./chunk-2ZHNO37N.js";
6
6
 
7
7
  // src/generation/prompt-builder.ts
8
8
  import { readFileSync } from "fs";
@@ -566,4 +566,4 @@ export {
566
566
  PromptBuilder,
567
567
  inferWorkflowType
568
568
  };
569
- //# sourceMappingURL=chunk-EVOAYH2K.js.map
569
+ //# sourceMappingURL=chunk-STG7Z2SS.js.map
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  PromptBuilder,
3
3
  inferWorkflowType
4
- } from "./chunk-EVOAYH2K.js";
4
+ } from "./chunk-STG7Z2SS.js";
5
5
  import {
6
6
  GenerationError,
7
7
  N8nProvider,
8
8
  NullLibrary,
9
9
  ResponseParseError,
10
10
  ValidationError
11
- } from "./chunk-5GAY7CSJ.js";
11
+ } from "./chunk-PCNW5ZUD.js";
12
12
  import {
13
13
  GuardError,
14
14
  N8nApiClient,
@@ -20,7 +20,7 @@ import {
20
20
  generateUUID,
21
21
  nullLogger,
22
22
  scoreToMode
23
- } from "./chunk-KIFT5LA7.js";
23
+ } from "./chunk-2ZHNO37N.js";
24
24
 
25
25
  // src/client.ts
26
26
  import Anthropic from "@anthropic-ai/sdk";
@@ -195,7 +195,6 @@ var DEFAULT_MODEL = process.env["KAIROS_MODEL"] ?? "claude-sonnet-4-6";
195
195
  var Kairos = class {
196
196
  provider;
197
197
  designer;
198
- validator;
199
198
  library;
200
199
  logger;
201
200
  telemetry;
@@ -221,7 +220,6 @@ var Kairos = class {
221
220
  const anthropic = new Anthropic({ apiKey: options.anthropicApiKey });
222
221
  const patternsPath = typeof options.telemetry === "string" ? join(options.telemetry, "..", "patterns.json") : join(homedir(), ".kairos", "patterns.json");
223
222
  this.designer = new WorkflowDesigner(anthropic, this.model, logger, patternsPath);
224
- this.validator = new N8nValidator();
225
223
  this.library = options.library ?? new NullLibrary();
226
224
  this.logger = logger;
227
225
  if (options.telemetry === true) {
@@ -318,7 +316,6 @@ var Kairos = class {
318
316
  }
319
317
  await this.emitAttemptTelemetry(description, designResult, workflowType, runId);
320
318
  const workflow = options?.name ? { ...designResult.workflow, name: options.name } : designResult.workflow;
321
- this.saveToLibrary(workflow, description, designResult, matches);
322
319
  if (options?.dryRun) {
323
320
  const totalTokensInput2 = designResult.attemptMetadata.reduce((s, m) => s + m.tokensInput, 0);
324
321
  const totalTokensOutput2 = designResult.attemptMetadata.reduce((s, m) => s + m.tokensOutput, 0);
@@ -354,6 +351,7 @@ var Kairos = class {
354
351
  if (options?.activate) {
355
352
  await provider.activate(deployed.workflowId);
356
353
  }
354
+ this.saveToLibrary(workflow, description, designResult, matches, deployed.workflowId);
357
355
  let smokeTestResult;
358
356
  if (options?.smokeTest) {
359
357
  smokeTestResult = await provider.smokeTest(deployed.workflowId, workflow).catch((err) => {
@@ -599,4 +597,4 @@ var Kairos = class {
599
597
  export {
600
598
  Kairos
601
599
  };
602
- //# sourceMappingURL=chunk-HBGZTUUZ.js.map
600
+ //# sourceMappingURL=chunk-YOQTEVDB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts","../src/generation/designer.ts"],"sourcesContent":["import Anthropic from '@anthropic-ai/sdk'\nimport type { N8nWorkflow, Tag } from './types/workflow.js'\nimport type { BuildResult, WorkflowListItem, ExecutionSummary, ExecutionDetail, SmokeTestResult } from './types/result.js'\nimport type { ClientOptions, BuildOptions, DeleteOptions, ExecutionFilter } from './types/options.js'\nimport type { IWorkflowLibrary, WorkflowMatch, WorkflowMetadataInput } from './library/types.js'\nimport { NullLibrary } from './library/null-library.js'\nimport { N8nApiClient } from './providers/n8n/api-client.js'\nimport { N8nFieldStripper } from './providers/n8n/stripper.js'\nimport { N8nProvider } from './providers/n8n/provider.js'\nimport { WorkflowDesigner } from './generation/designer.js'\nimport type { DesignResult } from './generation/types.js'\nimport { TelemetryCollector } from './telemetry/collector.js'\nimport { TelemetryReader } from './telemetry/reader.js'\nimport { PatternAnalyzer } from './telemetry/pattern-analyzer.js'\nimport { nullLogger } from './utils/logger.js'\nimport type { ILogger } from './utils/logger.js'\nimport { scoreToMode } from './utils/thresholds.js'\nimport { GuardError } from './errors/guard-error.js'\nimport { ValidationError } from './errors/validation-error.js'\nimport { inferWorkflowType } from './utils/workflow-type.js'\nimport { generateUUID } from './utils/uuid.js'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nconst DEFAULT_MODEL = process.env['KAIROS_MODEL'] ?? 'claude-sonnet-4-6'\n\nexport class Kairos {\n private readonly provider: N8nProvider | null\n private readonly designer: WorkflowDesigner\n private readonly library: IWorkflowLibrary\n private readonly logger: ILogger\n private readonly telemetry: TelemetryCollector | null\n private readonly telemetryReader: TelemetryReader | null\n private readonly patternAnalyzer: PatternAnalyzer | null\n private readonly model: string\n private saveQueue: Promise<string | null> = Promise.resolve(null)\n\n constructor(options: ClientOptions) {\n const logger = options.logger ?? nullLogger\n this.model = options.model ?? DEFAULT_MODEL\n\n if (options.n8nBaseUrl && options.n8nApiKey) {\n try {\n new URL(options.n8nBaseUrl)\n } catch {\n throw new GuardError(`Invalid n8nBaseUrl: \"${options.n8nBaseUrl}\" — must be a valid URL`)\n }\n const apiClient = new N8nApiClient(options.n8nBaseUrl, options.n8nApiKey, logger)\n const stripper = new N8nFieldStripper()\n this.provider = new N8nProvider(apiClient, stripper)\n } else {\n this.provider = null\n }\n\n const anthropic = new Anthropic({ apiKey: options.anthropicApiKey })\n const patternsPath = typeof options.telemetry === 'string'\n ? join(options.telemetry, '..', 'patterns.json')\n : join(homedir(), '.kairos', 'patterns.json')\n this.designer = new WorkflowDesigner(anthropic, this.model, logger, patternsPath)\n this.library = options.library ?? new NullLibrary()\n this.logger = logger\n\n if (options.telemetry === true) {\n this.telemetry = new TelemetryCollector()\n this.telemetryReader = new TelemetryReader()\n this.patternAnalyzer = new PatternAnalyzer()\n } else if (typeof options.telemetry === 'string') {\n this.telemetry = new TelemetryCollector(options.telemetry)\n this.telemetryReader = new TelemetryReader(options.telemetry)\n this.patternAnalyzer = new PatternAnalyzer(options.telemetry)\n } else {\n this.telemetry = null\n this.telemetryReader = null\n this.patternAnalyzer = null\n }\n }\n\n private requireProvider(): N8nProvider {\n if (!this.provider) {\n throw new GuardError('n8nBaseUrl and n8nApiKey are required for this operation — set them in the Kairos constructor, or use { dryRun: true } for generation-only mode')\n }\n return this.provider\n }\n\n private validateDescription(description: string): void {\n if (!description || description.trim().length === 0) {\n throw new GuardError('Description is required and must be non-empty')\n }\n }\n\n async build(description: string, options?: BuildOptions): Promise<BuildResult> {\n this.validateDescription(description)\n this.logger.info('Kairos.build', { description, dryRun: options?.dryRun })\n const buildStart = Date.now()\n const runId = generateUUID()\n const workflowType = inferWorkflowType(description)\n\n await this.telemetry?.emit('build_start', {\n description,\n model: this.model,\n dryRun: options?.dryRun ?? false,\n }, runId)\n\n await this.library.initialize()\n const matches = await this.library.search(description)\n\n if (matches.length > 0) {\n const top = matches[0]!\n this.logger.info(`Library: ${matches.length} match(es), top=\"${top.workflow.description.slice(0, 50)}\" score=${top.score.toFixed(2)} mode=${top.mode}`)\n } else {\n this.logger.info('Library: no matches (scratch mode)')\n }\n\n const globalFailureRates = await this.telemetryReader?.getFailureRates() ?? []\n\n if (globalFailureRates.length > 0) {\n const highFreq = globalFailureRates.filter((r) => r.rate >= 0.15)\n if (highFreq.length > 0) {\n this.logger.info(`Telemetry: ${highFreq.length} high-frequency failure rule(s) will be warned about`)\n }\n }\n\n let designResult: DesignResult\n try {\n designResult = await this.designer.design(\n { description, ...(options?.name ? { name: options.name } : {}) },\n matches,\n globalFailureRates,\n )\n } catch (err) {\n if (err instanceof ValidationError && err.attemptMetadata) {\n for (const meta of err.attemptMetadata) {\n await this.telemetry?.emit('generation_attempt', {\n description,\n attempt: meta.attempt,\n temperature: meta.temperature,\n durationMs: meta.durationMs,\n tokensInput: meta.tokensInput,\n tokensOutput: meta.tokensOutput,\n validationPassed: meta.validationPassed,\n issueCount: meta.issues.length,\n issues: meta.issues.map((i) => ({ rule: i.rule, severity: i.severity, message: i.message, nodeId: i.nodeId ?? null, nodeType: i.nodeType ?? null })),\n workflowType,\n }, runId)\n }\n await this.telemetry?.emit('build_complete', {\n description,\n success: false,\n totalAttempts: err.attemptMetadata.length,\n totalDurationMs: Date.now() - buildStart,\n totalTokensInput: err.attemptMetadata.reduce((s, m) => s + m.tokensInput, 0),\n totalTokensOutput: err.attemptMetadata.reduce((s, m) => s + m.tokensOutput, 0),\n workflowName: null,\n workflowId: null,\n dryRun: options?.dryRun ?? false,\n credentialsNeeded: 0,\n warnedRules: err.warnedRules ?? [],\n workflowType,\n }, runId)\n this.updatePatterns()\n }\n throw err\n }\n\n await this.emitAttemptTelemetry(description, designResult, workflowType, runId)\n\n const workflow = options?.name\n ? { ...designResult.workflow, name: options.name }\n : designResult.workflow\n\n if (options?.dryRun) {\n const totalTokensInput = designResult.attemptMetadata.reduce((s, m) => s + m.tokensInput, 0)\n const totalTokensOutput = designResult.attemptMetadata.reduce((s, m) => s + m.tokensOutput, 0)\n\n await this.telemetry?.emit('build_complete', {\n description,\n success: true,\n totalAttempts: designResult.attempts,\n totalDurationMs: Date.now() - buildStart,\n totalTokensInput,\n totalTokensOutput,\n workflowName: workflow.name,\n workflowId: null,\n dryRun: true,\n credentialsNeeded: designResult.credentialsNeeded.length,\n warnedRules: designResult.warnedRules,\n workflowType,\n }, runId)\n\n this.updatePatterns()\n\n return {\n workflowId: null,\n name: workflow.name,\n workflow,\n credentialsNeeded: designResult.credentialsNeeded,\n activationRequired: true,\n generationAttempts: designResult.attempts,\n dryRun: true,\n }\n }\n\n const provider = this.requireProvider()\n const deployed = await provider.deploy(workflow)\n // Log the workflow ID immediately — if any post-deploy step fails, this ID\n // lets the user manually locate and clean up the orphaned workflow in n8n.\n this.logger.info('Workflow deployed to n8n', { workflowId: deployed.workflowId, name: deployed.name })\n this.recordDeploy(deployed.workflowId)\n\n if (options?.activate) {\n await provider.activate(deployed.workflowId)\n }\n\n this.saveToLibrary(workflow, description, designResult, matches, deployed.workflowId)\n\n let smokeTestResult: SmokeTestResult | undefined\n if (options?.smokeTest) {\n smokeTestResult = await provider.smokeTest(deployed.workflowId, workflow).catch((err: unknown): SmokeTestResult => {\n this.logger.warn('Smoke test threw unexpectedly', { err: String(err) })\n return { status: 'error', triggerType: 'manual', error: String(err) }\n })\n this.logger.info('Smoke test complete', { status: smokeTestResult.status, triggerType: smokeTestResult.triggerType })\n }\n\n const totalTokensInput = designResult.attemptMetadata.reduce((s, m) => s + m.tokensInput, 0)\n const totalTokensOutput = designResult.attemptMetadata.reduce((s, m) => s + m.tokensOutput, 0)\n\n await this.telemetry?.emit('build_complete', {\n description,\n success: true,\n totalAttempts: designResult.attempts,\n totalDurationMs: Date.now() - buildStart,\n totalTokensInput,\n totalTokensOutput,\n workflowName: deployed.name,\n workflowId: deployed.workflowId,\n dryRun: false,\n credentialsNeeded: designResult.credentialsNeeded.length,\n warnedRules: designResult.warnedRules,\n workflowType,\n }, runId)\n\n this.updatePatterns()\n\n return {\n workflowId: deployed.workflowId,\n name: deployed.name,\n workflow,\n credentialsNeeded: designResult.credentialsNeeded,\n activationRequired: !options?.activate,\n generationAttempts: designResult.attempts,\n dryRun: false,\n ...(smokeTestResult !== undefined ? { smokeTest: smokeTestResult } : {}),\n }\n }\n\n async replace(id: string, description: string): Promise<BuildResult> {\n this.validateDescription(description)\n this.logger.info('Kairos.update', { id, description })\n const buildStart = Date.now()\n const runId = generateUUID()\n const workflowType = inferWorkflowType(description)\n\n await this.telemetry?.emit('build_start', {\n description,\n model: this.model,\n dryRun: false,\n }, runId)\n\n await this.library.initialize()\n const matches = await this.library.search(description)\n const globalFailureRates = await this.telemetryReader?.getFailureRates() ?? []\n\n let designResult: DesignResult\n try {\n designResult = await this.designer.design({ description }, matches, globalFailureRates)\n } catch (err) {\n if (err instanceof ValidationError && err.attemptMetadata) {\n for (const meta of err.attemptMetadata) {\n await this.telemetry?.emit('generation_attempt', {\n description,\n attempt: meta.attempt,\n temperature: meta.temperature,\n durationMs: meta.durationMs,\n tokensInput: meta.tokensInput,\n tokensOutput: meta.tokensOutput,\n validationPassed: meta.validationPassed,\n issueCount: meta.issues.length,\n issues: meta.issues.map((i) => ({ rule: i.rule, severity: i.severity, message: i.message, nodeId: i.nodeId ?? null, nodeType: i.nodeType ?? null })),\n workflowType,\n }, runId)\n }\n await this.telemetry?.emit('build_complete', {\n description,\n success: false,\n totalAttempts: err.attemptMetadata.length,\n totalDurationMs: Date.now() - buildStart,\n totalTokensInput: err.attemptMetadata.reduce((s, m) => s + m.tokensInput, 0),\n totalTokensOutput: err.attemptMetadata.reduce((s, m) => s + m.tokensOutput, 0),\n workflowName: null,\n workflowId: null,\n dryRun: false,\n credentialsNeeded: 0,\n warnedRules: err.warnedRules ?? [],\n workflowType,\n }, runId)\n this.updatePatterns()\n }\n throw err\n }\n\n await this.emitAttemptTelemetry(description, designResult, workflowType, runId)\n\n const provider = this.requireProvider()\n const deployed = await provider.update(id, designResult.workflow)\n this.logger.info('Workflow updated in n8n', { workflowId: deployed.workflowId, name: deployed.name })\n\n this.saveToLibrary(designResult.workflow, description, designResult, matches, deployed.workflowId)\n this.recordDeploy()\n\n const totalTokensInput = designResult.attemptMetadata.reduce((s, m) => s + m.tokensInput, 0)\n const totalTokensOutput = designResult.attemptMetadata.reduce((s, m) => s + m.tokensOutput, 0)\n\n await this.telemetry?.emit('build_complete', {\n description,\n success: true,\n totalAttempts: designResult.attempts,\n totalDurationMs: Date.now() - buildStart,\n totalTokensInput,\n totalTokensOutput,\n workflowName: deployed.name,\n workflowId: deployed.workflowId,\n dryRun: false,\n credentialsNeeded: designResult.credentialsNeeded.length,\n warnedRules: designResult.warnedRules,\n workflowType,\n }, runId)\n\n this.updatePatterns()\n\n return {\n workflowId: deployed.workflowId,\n name: deployed.name,\n workflow: designResult.workflow,\n credentialsNeeded: designResult.credentialsNeeded,\n activationRequired: true,\n generationAttempts: designResult.attempts,\n dryRun: false,\n }\n }\n\n async drain(): Promise<void> {\n await this.saveQueue.catch(() => {})\n }\n\n private updatePatterns(): void {\n if (!this.patternAnalyzer) return\n this.saveQueue = this.saveQueue\n .then(() => this.patternAnalyzer!.analyzeAndSave())\n .then(() => null)\n .catch((err: unknown) => {\n this.logger.warn('Pattern analysis failed (non-fatal)', { err: String(err) })\n return null\n })\n }\n\n private async emitAttemptTelemetry(description: string, designResult: DesignResult, workflowType: string | null, runId: string): Promise<void> {\n for (const meta of designResult.attemptMetadata) {\n await this.telemetry?.emit('generation_attempt', {\n description,\n attempt: meta.attempt,\n temperature: meta.temperature,\n durationMs: meta.durationMs,\n tokensInput: meta.tokensInput,\n tokensOutput: meta.tokensOutput,\n validationPassed: meta.validationPassed,\n issueCount: meta.issues.length,\n issues: meta.issues.map((i) => ({ rule: i.rule, severity: i.severity, message: i.message, nodeId: i.nodeId ?? null, nodeType: i.nodeType ?? null })),\n workflowType,\n }, runId)\n }\n }\n\n private recordDeploy(n8nWorkflowId?: string): void {\n this.saveQueue = this.saveQueue\n .then(async (savedId) => {\n if (savedId) {\n await this.library.recordDeployment(savedId, n8nWorkflowId)\n }\n return savedId\n })\n .catch((err: unknown) => {\n this.logger.warn('Failed to record deployment (non-fatal)', { err: String(err) })\n return null\n })\n }\n\n private saveToLibrary(\n workflow: N8nWorkflow,\n description: string,\n designResult: DesignResult,\n matches: WorkflowMatch[],\n n8nWorkflowId?: string,\n ): void {\n const failedAttempts = designResult.attemptMetadata.filter((m) => !m.validationPassed)\n const failurePatterns = failedAttempts.flatMap((m) =>\n m.issues.map((i) => ({ rule: i.rule, message: i.message })),\n )\n const topMatch = matches[0]\n const generationMode = topMatch ? scoreToMode(topMatch.score) : 'scratch' as const\n\n const autoTags = Array.from(new Set(\n workflow.nodes.flatMap((n) => {\n const bare = n.type.split('.').pop() ?? ''\n const tags = [bare]\n if (n.type.includes('Trigger') || n.type.includes('trigger')) tags.push(`trigger:${bare}`)\n if (n.type.includes('langchain')) tags.push('ai')\n return tags\n }),\n ))\n\n const metadata: WorkflowMetadataInput = {\n description,\n generationMode,\n generationAttempts: designResult.attempts,\n }\n if (autoTags.length > 0) metadata.tags = autoTags\n if (failurePatterns.length > 0) metadata.failurePatterns = failurePatterns\n if (matches.length > 0) metadata.sourceWorkflowIds = matches.map((m) => m.workflow.id)\n if (topMatch) metadata.topMatchScore = topMatch.score\n if (designResult.credentialsNeeded.length > 0) metadata.credentialsNeeded = designResult.credentialsNeeded\n if (n8nWorkflowId) metadata.n8nWorkflowId = n8nWorkflowId\n\n const firstTryPass = designResult.attemptMetadata.length > 0\n && designResult.attemptMetadata[0]!.validationPassed\n const failedRules = Array.from(new Set(\n designResult.attemptMetadata\n .filter((m) => !m.validationPassed)\n .flatMap((m) => m.issues.map((i) => i.rule)),\n ))\n\n this.saveQueue = this.saveQueue\n .then(async () => {\n const savedId = await this.library.save(workflow, metadata)\n\n for (const match of matches) {\n if (match.mode === 'direct' || match.mode === 'reference') {\n await this.library.recordOutcome(match.workflow.id, {\n attempts: designResult.attempts,\n firstTryPass,\n failedRules,\n mode: match.mode,\n })\n }\n }\n\n return savedId\n })\n .catch((err: unknown) => {\n this.logger.warn('Failed to save workflow to library (non-fatal)', { err: String(err) })\n return null\n })\n }\n\n async get(id: string): Promise<N8nWorkflow> {\n return this.requireProvider().get(id)\n }\n\n async list(): Promise<WorkflowListItem[]> {\n return this.requireProvider().list()\n }\n\n async activate(id: string): Promise<void> {\n await this.requireProvider().activate(id)\n }\n\n async deactivate(id: string): Promise<void> {\n await this.requireProvider().deactivate(id)\n }\n\n async delete(id: string, options: DeleteOptions): Promise<void> {\n await this.requireProvider().delete(id, options)\n }\n\n async executions(workflowId?: string, filter?: ExecutionFilter): Promise<ExecutionSummary[]> {\n return this.requireProvider().executions(workflowId, filter)\n }\n\n async execution(id: string): Promise<ExecutionDetail> {\n return this.requireProvider().execution(id)\n }\n\n async listTags(): Promise<Tag[]> {\n return this.requireProvider().listTags()\n }\n\n async createTag(name: string): Promise<Tag> {\n return this.requireProvider().createTag(name)\n }\n\n async tag(workflowId: string, tagIds: string[]): Promise<void> {\n await this.requireProvider().tag(workflowId, tagIds)\n }\n\n async untag(workflowId: string, tagIds: string[]): Promise<void> {\n await this.requireProvider().untag(workflowId, tagIds)\n }\n}\n","import Anthropic from '@anthropic-ai/sdk'\nimport type { WorkflowMatch } from '../library/types.js'\nimport type { N8nWorkflow } from '../types/workflow.js'\nimport type { CredentialRequirement } from '../types/result.js'\nimport type { ILogger } from '../utils/logger.js'\nimport { GenerationError } from '../errors/generation-error.js'\nimport { ResponseParseError } from '../errors/response-parse-error.js'\nimport { ValidationError } from '../errors/validation-error.js'\nimport type { ValidationIssue } from '../errors/validation-error.js'\nimport { N8nValidator } from '../validation/validator.js'\nimport { PromptBuilder } from './prompt-builder.js'\nimport type { AttemptMetadata } from '../telemetry/types.js'\nimport type { RuleFailureRate } from '../telemetry/reader.js'\nimport type { DesignRequest, DesignResult, SystemPromptBlock } from './types.js'\n\nconst MAX_ATTEMPTS = 3\nconst BASE_TEMPERATURE = 0.2\nconst FINAL_TEMPERATURE = 0.1\n\nconst GENERATE_WORKFLOW_TOOL: Anthropic.Tool = {\n name: 'generate_workflow',\n description: 'Generate a valid n8n workflow JSON object',\n input_schema: {\n type: 'object',\n properties: {\n workflow: {\n type: 'object',\n description: 'The complete n8n workflow object',\n properties: {\n name: { type: 'string' },\n nodes: { type: 'array' },\n connections: { type: 'object' },\n settings: { type: 'object' },\n },\n required: ['name', 'nodes', 'connections'],\n },\n credentialsNeeded: {\n type: 'array',\n description: 'List of credentials the user must configure before activating',\n items: {\n type: 'object',\n properties: {\n service: { type: 'string' },\n credentialType: { type: 'string' },\n description: { type: 'string' },\n },\n required: ['service', 'credentialType', 'description'],\n },\n },\n error: {\n type: 'string',\n description: 'Set this if the request cannot be fulfilled — explain why',\n },\n },\n required: [],\n },\n}\n\ninterface ToolUseResult {\n workflow: N8nWorkflow\n credentialsNeeded: CredentialRequirement[]\n error?: string\n}\n\nexport class WorkflowDesigner {\n private readonly validator: N8nValidator\n private readonly promptBuilder: PromptBuilder\n\n constructor(\n private readonly anthropic: Anthropic,\n private readonly model: string,\n private readonly logger: ILogger,\n patternsPath?: string,\n ) {\n this.validator = new N8nValidator()\n this.promptBuilder = new PromptBuilder(patternsPath)\n }\n\n async design(request: DesignRequest, matches: WorkflowMatch[], globalFailureRates: RuleFailureRate[] = []): Promise<DesignResult> {\n const attemptMetadata: AttemptMetadata[] = []\n let lastErrors: ValidationIssue[] = []\n let attempts = 0\n const built = this.promptBuilder.build(request, matches, globalFailureRates)\n\n for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {\n attempts = attempt\n const temperature = attempt === MAX_ATTEMPTS ? FINAL_TEMPERATURE : BASE_TEMPERATURE\n\n let userMessage: string\n if (attempt === 1) {\n userMessage = built.userMessage\n this.logger.debug('WorkflowDesigner: attempt 1', { description: request.description })\n } else {\n const issueLines = lastErrors.map(\n (i) => `- [Rule ${i.rule}] ${i.message}${i.nodeId ? ` (node: ${i.nodeId})` : ''}`,\n )\n const failingRuleIds = lastErrors.map((i) => i.rule)\n userMessage = this.promptBuilder.buildCorrectionMessage(request, matches, issueLines, attempt - 1, failingRuleIds)\n this.logger.debug(`WorkflowDesigner: correction attempt ${attempt}`, { issueCount: lastErrors.length })\n }\n\n const start = Date.now()\n const message = await this.callClaude(built.system, userMessage, temperature)\n const durationMs = Date.now() - start\n const parsed = this.extractToolUse(message)\n\n if (parsed.error) {\n throw new GenerationError(`Claude declined to generate workflow: ${parsed.error}`)\n }\n\n const validation = this.validator.validate(parsed.workflow)\n const errors = validation.issues.filter((i) => i.severity === 'error')\n\n attemptMetadata.push({\n attempt,\n temperature,\n durationMs,\n tokensInput: message.usage.input_tokens,\n tokensOutput: message.usage.output_tokens,\n validationPassed: validation.valid,\n issues: validation.issues,\n })\n\n if (validation.valid) {\n return { workflow: parsed.workflow, credentialsNeeded: parsed.credentialsNeeded, attempts, attemptMetadata, warnedRules: this.promptBuilder.getWarnedRules() }\n }\n\n lastErrors = errors\n this.logger.warn(`WorkflowDesigner: validation failed on attempt ${attempt}`, {\n errorCount: errors.length,\n })\n }\n\n const finalIssues = attemptMetadata.at(-1)?.issues ?? lastErrors\n throw new ValidationError(\n `Workflow failed validation after ${MAX_ATTEMPTS} attempts`,\n finalIssues,\n attemptMetadata,\n this.promptBuilder.getWarnedRules(),\n )\n }\n\n private async callClaude(\n system: SystemPromptBlock[],\n userMessage: string,\n temperature: number,\n ): Promise<Anthropic.Message> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), 120_000)\n try {\n return await this.anthropic.messages.create(\n {\n model: this.model,\n max_tokens: 8192,\n temperature,\n system: system.map((b) => ({ type: b.type, text: b.text, ...(b.cache_control ? { cache_control: b.cache_control } : {}) })),\n messages: [{ role: 'user', content: userMessage }],\n tools: [GENERATE_WORKFLOW_TOOL],\n tool_choice: { type: 'tool', name: 'generate_workflow' },\n },\n { signal: controller.signal },\n )\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err)\n throw new GenerationError(`Anthropic API call failed: ${detail}`, err)\n } finally {\n clearTimeout(timer)\n }\n }\n\n private extractToolUse(message: Anthropic.Message): ToolUseResult {\n if (message.stop_reason === 'max_tokens') {\n throw new GenerationError(\n 'Claude response was truncated (max_tokens reached) — the workflow may be too large. Try a simpler description or break it into smaller workflows.',\n )\n }\n\n const toolUseBlock = message.content.find(\n (block): block is Anthropic.ToolUseBlock => block.type === 'tool_use',\n )\n if (!toolUseBlock) {\n throw new ResponseParseError(\n 'Claude response contained no tool_use block — forced tool_choice failed unexpectedly',\n )\n }\n\n const input = toolUseBlock.input as Record<string, unknown>\n\n if (typeof input['error'] === 'string') {\n return {\n workflow: { name: '', nodes: [], connections: {} },\n credentialsNeeded: [],\n error: input['error'],\n }\n }\n\n if (!input['workflow'] || typeof input['workflow'] !== 'object') {\n throw new ResponseParseError('generate_workflow tool call missing workflow field')\n }\n\n const workflow = input['workflow'] as N8nWorkflow\n const credentialsNeeded = (input['credentialsNeeded'] as CredentialRequirement[] | undefined) ?? []\n\n return { workflow, credentialsNeeded }\n }\n}\n"],"mappings":"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","names":["totalTokensInput","totalTokensOutput"]}