@kairos-sdk/core 0.5.1 → 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 (42) hide show
  1. package/README.md +121 -15
  2. package/dist/{chunk-VPPWTMRJ.js → chunk-2ZHNO37N.js} +48 -4
  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-MYAGTDQ2.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-V2IZBZGB.js → chunk-STG7Z2SS.js} +2 -2
  12. package/dist/{chunk-GVZKMS53.js → chunk-YOQTEVDB.js} +4 -4
  13. package/dist/cli.cjs +647 -3
  14. package/dist/cli.cjs.map +1 -1
  15. package/dist/cli.js +239 -4
  16. package/dist/cli.js.map +1 -1
  17. package/dist/index.cjs +385 -5
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.cts +86 -3
  20. package/dist/index.d.ts +86 -3
  21. package/dist/index.js +19 -5
  22. package/dist/mcp-server.cjs +47 -3
  23. package/dist/mcp-server.cjs.map +1 -1
  24. package/dist/mcp-server.js +2 -2
  25. package/dist/pack-builder-RTQWXGIS.js +9 -0
  26. package/dist/pack-builder-RTQWXGIS.js.map +1 -0
  27. package/dist/pack-exporter-KFNLSP5V.js +7 -0
  28. package/dist/pack-exporter-KFNLSP5V.js.map +1 -0
  29. package/dist/pack-validator-HZPB2XJ3.js +7 -0
  30. package/dist/pack-validator-HZPB2XJ3.js.map +1 -0
  31. package/dist/{reader-B5mV20H6.d.ts → reader-CfWGpL4V.d.cts} +2 -1
  32. package/dist/{reader-B5mV20H6.d.cts → reader-CfWGpL4V.d.ts} +2 -1
  33. package/dist/standalone.cjs +43 -3
  34. package/dist/standalone.cjs.map +1 -1
  35. package/dist/standalone.d.cts +1 -1
  36. package/dist/standalone.d.ts +1 -1
  37. package/dist/standalone.js +2 -2
  38. package/package.json +1 -1
  39. package/dist/chunk-VPPWTMRJ.js.map +0 -1
  40. /package/dist/{chunk-MYAGTDQ2.js.map → chunk-PCNW5ZUD.js.map} +0 -0
  41. /package/dist/{chunk-V2IZBZGB.js.map → chunk-STG7Z2SS.js.map} +0 -0
  42. /package/dist/{chunk-GVZKMS53.js.map → chunk-YOQTEVDB.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-VPPWTMRJ.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-MYAGTDQ2.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-VPPWTMRJ.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-V2IZBZGB.js.map
569
+ //# sourceMappingURL=chunk-STG7Z2SS.js.map
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  PromptBuilder,
3
3
  inferWorkflowType
4
- } from "./chunk-V2IZBZGB.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-MYAGTDQ2.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-VPPWTMRJ.js";
23
+ } from "./chunk-2ZHNO37N.js";
24
24
 
25
25
  // src/client.ts
26
26
  import Anthropic from "@anthropic-ai/sdk";
@@ -597,4 +597,4 @@ var Kairos = class {
597
597
  export {
598
598
  Kairos
599
599
  };
600
- //# sourceMappingURL=chunk-GVZKMS53.js.map
600
+ //# sourceMappingURL=chunk-YOQTEVDB.js.map