@sweny-ai/core 0.1.76 → 0.1.78

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 (123) hide show
  1. package/dist/browser.d.ts +11 -5
  2. package/dist/browser.js +11 -11
  3. package/dist/claude.d.ts +20 -0
  4. package/dist/claude.js +139 -9
  5. package/dist/cli/config.d.ts +22 -0
  6. package/dist/cli/config.js +56 -9
  7. package/dist/cli/main.d.ts +1 -1
  8. package/dist/cli/main.js +56 -57
  9. package/dist/cli/marketplace.js +35 -9
  10. package/dist/cli/publish.d.ts +10 -0
  11. package/dist/cli/publish.js +22 -14
  12. package/dist/executor.js +104 -43
  13. package/dist/loader.d.ts +40 -0
  14. package/dist/loader.js +73 -0
  15. package/dist/mcp-catalog.d.ts +47 -0
  16. package/dist/mcp-catalog.js +304 -0
  17. package/dist/mcp.d.ts +6 -9
  18. package/dist/mcp.js +24 -314
  19. package/dist/requires.d.ts +7 -0
  20. package/dist/requires.js +34 -0
  21. package/dist/retry.d.ts +23 -0
  22. package/dist/retry.js +72 -0
  23. package/dist/schema.d.ts +667 -80
  24. package/dist/schema.js +144 -5
  25. package/dist/skills/custom-loader.d.ts +40 -0
  26. package/dist/skills/custom-loader.js +107 -32
  27. package/dist/skills/index.d.ts +13 -1
  28. package/dist/skills/index.js +12 -3
  29. package/dist/studio.js +4 -1
  30. package/dist/templates.d.ts +29 -8
  31. package/dist/templates.js +30 -20
  32. package/dist/testing.d.ts +7 -0
  33. package/dist/testing.js +7 -0
  34. package/dist/types.d.ts +76 -0
  35. package/dist/verify.d.ts +1 -0
  36. package/dist/verify.js +43 -5
  37. package/package.json +8 -4
  38. package/dist/__tests__/cascade.test.d.ts +0 -11
  39. package/dist/__tests__/cascade.test.js +0 -449
  40. package/dist/__tests__/claude.test.d.ts +0 -1
  41. package/dist/__tests__/claude.test.js +0 -427
  42. package/dist/__tests__/custom-loader.test.d.ts +0 -1
  43. package/dist/__tests__/custom-loader.test.js +0 -116
  44. package/dist/__tests__/executor.test.d.ts +0 -1
  45. package/dist/__tests__/executor.test.js +0 -736
  46. package/dist/__tests__/integration/datadog.integration.test.d.ts +0 -1
  47. package/dist/__tests__/integration/datadog.integration.test.js +0 -23
  48. package/dist/__tests__/integration/e2e-workflow.integration.test.d.ts +0 -1
  49. package/dist/__tests__/integration/e2e-workflow.integration.test.js +0 -75
  50. package/dist/__tests__/integration/github.integration.test.d.ts +0 -1
  51. package/dist/__tests__/integration/github.integration.test.js +0 -37
  52. package/dist/__tests__/integration/harness.d.ts +0 -24
  53. package/dist/__tests__/integration/harness.js +0 -34
  54. package/dist/__tests__/integration/linear.integration.test.d.ts +0 -1
  55. package/dist/__tests__/integration/linear.integration.test.js +0 -15
  56. package/dist/__tests__/integration/sentry.integration.test.d.ts +0 -1
  57. package/dist/__tests__/integration/sentry.integration.test.js +0 -20
  58. package/dist/__tests__/integration/slack.integration.test.d.ts +0 -1
  59. package/dist/__tests__/integration/slack.integration.test.js +0 -22
  60. package/dist/__tests__/integration/sources.integration.test.d.ts +0 -1
  61. package/dist/__tests__/integration/sources.integration.test.js +0 -123
  62. package/dist/__tests__/publish.test.d.ts +0 -1
  63. package/dist/__tests__/publish.test.js +0 -180
  64. package/dist/__tests__/schema.test.d.ts +0 -1
  65. package/dist/__tests__/schema.test.js +0 -526
  66. package/dist/__tests__/skill-config-integration.test.d.ts +0 -1
  67. package/dist/__tests__/skill-config-integration.test.js +0 -204
  68. package/dist/__tests__/skills-index.test.d.ts +0 -1
  69. package/dist/__tests__/skills-index.test.js +0 -119
  70. package/dist/__tests__/skills.test.d.ts +0 -1
  71. package/dist/__tests__/skills.test.js +0 -565
  72. package/dist/__tests__/spec-conformance.test.d.ts +0 -18
  73. package/dist/__tests__/spec-conformance.test.js +0 -1074
  74. package/dist/__tests__/studio.test.d.ts +0 -1
  75. package/dist/__tests__/studio.test.js +0 -403
  76. package/dist/__tests__/templates.test.d.ts +0 -1
  77. package/dist/__tests__/templates.test.js +0 -49
  78. package/dist/__tests__/testing.test.d.ts +0 -1
  79. package/dist/__tests__/testing.test.js +0 -224
  80. package/dist/__tests__/verify.test.d.ts +0 -1
  81. package/dist/__tests__/verify.test.js +0 -517
  82. package/dist/__tests__/version-consistency.test.d.ts +0 -1
  83. package/dist/__tests__/version-consistency.test.js +0 -312
  84. package/dist/__tests__/workflow-builder.test.d.ts +0 -1
  85. package/dist/__tests__/workflow-builder.test.js +0 -110
  86. package/dist/__tests__/workflow-yaml.test.d.ts +0 -1
  87. package/dist/__tests__/workflow-yaml.test.js +0 -201
  88. package/dist/cli/__tests__/diagram.test.d.ts +0 -1
  89. package/dist/cli/__tests__/diagram.test.js +0 -225
  90. package/dist/cli/__tests__/report-cloud.test.d.ts +0 -1
  91. package/dist/cli/__tests__/report-cloud.test.js +0 -165
  92. package/dist/cli/__tests__/upgrade.test.d.ts +0 -1
  93. package/dist/cli/__tests__/upgrade.test.js +0 -317
  94. package/dist/cli/__tests__/version-check.test.d.ts +0 -1
  95. package/dist/cli/__tests__/version-check.test.js +0 -209
  96. package/dist/cli/config.test.d.ts +0 -1
  97. package/dist/cli/config.test.js +0 -200
  98. package/dist/cli/credentials.test.d.ts +0 -1
  99. package/dist/cli/credentials.test.js +0 -172
  100. package/dist/cli/e2e.test.d.ts +0 -1
  101. package/dist/cli/e2e.test.js +0 -690
  102. package/dist/cli/marketplace.test.d.ts +0 -1
  103. package/dist/cli/marketplace.test.js +0 -355
  104. package/dist/cli/new.test.d.ts +0 -1
  105. package/dist/cli/new.test.js +0 -1043
  106. package/dist/cli/output.test.d.ts +0 -1
  107. package/dist/cli/output.test.js +0 -180
  108. package/dist/cli/publish.test.d.ts +0 -1
  109. package/dist/cli/publish.test.js +0 -610
  110. package/dist/cli/renderer.test.d.ts +0 -1
  111. package/dist/cli/renderer.test.js +0 -302
  112. package/dist/executor.test.d.ts +0 -1
  113. package/dist/executor.test.js +0 -603
  114. package/dist/mcp.test.d.ts +0 -1
  115. package/dist/mcp.test.js +0 -735
  116. package/dist/mermaid.test.d.ts +0 -1
  117. package/dist/mermaid.test.js +0 -256
  118. package/dist/sources.test.d.ts +0 -1
  119. package/dist/sources.test.js +0 -265
  120. package/dist/sources.validation.test.d.ts +0 -12
  121. package/dist/sources.validation.test.js +0 -380
  122. package/dist/workflow-builder.test.d.ts +0 -1
  123. package/dist/workflow-builder.test.js +0 -117
@@ -1,302 +0,0 @@
1
- import { describe, it, expect, beforeEach } from "vitest";
2
- import { DagRenderer, stripAnsi } from "./renderer.js";
3
- const testWorkflow = {
4
- id: "test",
5
- name: "Test Workflow",
6
- description: "A simple test workflow",
7
- nodes: {
8
- gather: { name: "Gather Context", instruction: "Gather", skills: [] },
9
- investigate: { name: "Investigate", instruction: "Investigate", skills: [] },
10
- report: { name: "Report", instruction: "Report", skills: [] },
11
- },
12
- edges: [
13
- { from: "gather", to: "investigate" },
14
- { from: "investigate", to: "report" },
15
- ],
16
- entry: "gather",
17
- };
18
- describe("DagRenderer", () => {
19
- let renderer;
20
- beforeEach(() => {
21
- renderer = new DagRenderer(testWorkflow, { animate: false });
22
- });
23
- it("starts all nodes in pending state", () => {
24
- expect(renderer.getNodeState("gather")).toBe("pending");
25
- expect(renderer.getNodeState("investigate")).toBe("pending");
26
- expect(renderer.getNodeState("report")).toBe("pending");
27
- });
28
- it("tracks node state: pending → running on node:enter", () => {
29
- const event = { type: "node:enter", node: "gather", instruction: "Gather" };
30
- renderer.update(event);
31
- expect(renderer.getNodeState("gather")).toBe("running");
32
- expect(renderer.getNodeState("investigate")).toBe("pending");
33
- });
34
- it("tracks node state: running → completed on node:exit success", () => {
35
- renderer.update({ type: "node:enter", node: "gather", instruction: "Gather" });
36
- renderer.update({
37
- type: "node:exit",
38
- node: "gather",
39
- result: { status: "success", data: {}, toolCalls: [] },
40
- });
41
- expect(renderer.getNodeState("gather")).toBe("completed");
42
- });
43
- it("tracks node state: running → failed on node:exit failed", () => {
44
- renderer.update({ type: "node:enter", node: "gather", instruction: "Gather" });
45
- renderer.update({
46
- type: "node:exit",
47
- node: "gather",
48
- result: { status: "failed", data: {}, toolCalls: [] },
49
- });
50
- expect(renderer.getNodeState("gather")).toBe("failed");
51
- });
52
- it("tracks failed nodes", () => {
53
- renderer.update({ type: "node:enter", node: "investigate", instruction: "Investigate" });
54
- renderer.update({
55
- type: "node:exit",
56
- node: "investigate",
57
- result: { status: "failed", data: { error: "timeout" }, toolCalls: [] },
58
- });
59
- expect(renderer.getNodeState("investigate")).toBe("failed");
60
- });
61
- it("counts tool calls per node", () => {
62
- expect(renderer.getToolCallCount("gather")).toBe(0);
63
- renderer.update({ type: "node:enter", node: "gather", instruction: "Gather" });
64
- renderer.update({ type: "tool:call", node: "gather", tool: "search", input: {} });
65
- renderer.update({ type: "tool:call", node: "gather", tool: "fetch", input: {} });
66
- expect(renderer.getToolCallCount("gather")).toBe(2);
67
- expect(renderer.getToolCallCount("investigate")).toBe(0);
68
- });
69
- it("counts tool calls across multiple nodes independently", () => {
70
- renderer.update({ type: "node:enter", node: "gather", instruction: "Gather" });
71
- renderer.update({ type: "tool:call", node: "gather", tool: "search", input: {} });
72
- renderer.update({ type: "node:exit", node: "gather", result: { status: "success", data: {}, toolCalls: [] } });
73
- renderer.update({ type: "node:enter", node: "investigate", instruction: "Investigate" });
74
- renderer.update({ type: "tool:call", node: "investigate", tool: "read", input: {} });
75
- renderer.update({ type: "tool:call", node: "investigate", tool: "write", input: {} });
76
- renderer.update({ type: "tool:call", node: "investigate", tool: "run", input: {} });
77
- expect(renderer.getToolCallCount("gather")).toBe(1);
78
- expect(renderer.getToolCallCount("investigate")).toBe(3);
79
- });
80
- it("renders to string without crashing", () => {
81
- const output = renderer.renderToString();
82
- expect(typeof output).toBe("string");
83
- expect(output.length).toBeGreaterThan(0);
84
- });
85
- it("output contains all node names", () => {
86
- const output = renderer.renderToString();
87
- expect(output).toContain("Gather Context");
88
- expect(output).toContain("Investigate");
89
- expect(output).toContain("Report");
90
- });
91
- it("topological order starts from entry node", () => {
92
- const output = renderer.renderToString();
93
- const gatherIdx = output.indexOf("Gather Context");
94
- const investigateIdx = output.indexOf("Investigate");
95
- const reportIdx = output.indexOf("Report");
96
- expect(gatherIdx).toBeLessThan(investigateIdx);
97
- expect(investigateIdx).toBeLessThan(reportIdx);
98
- });
99
- it("shows running status icon for active node", () => {
100
- renderer.update({ type: "node:enter", node: "gather", instruction: "Gather" });
101
- const output = renderer.renderToString();
102
- // ◉ is the running icon
103
- expect(output).toContain("◉");
104
- });
105
- it("shows completed status icon for finished node", () => {
106
- renderer.update({ type: "node:enter", node: "gather", instruction: "Gather" });
107
- renderer.update({
108
- type: "node:exit",
109
- node: "gather",
110
- result: { status: "success", data: {}, toolCalls: [] },
111
- });
112
- const output = renderer.renderToString();
113
- // ● is the completed icon
114
- expect(output).toContain("●");
115
- });
116
- it("shows failed status icon for failed node", () => {
117
- renderer.update({ type: "node:enter", node: "gather", instruction: "Gather" });
118
- renderer.update({
119
- type: "node:exit",
120
- node: "gather",
121
- result: { status: "failed", data: {}, toolCalls: [] },
122
- });
123
- const output = renderer.renderToString();
124
- // ✕ is the failed icon
125
- expect(output).toContain("✕");
126
- });
127
- it("returns pending state for unknown node id", () => {
128
- expect(renderer.getNodeState("nonexistent")).toBe("pending");
129
- });
130
- it("returns 0 tool calls for unknown node id", () => {
131
- expect(renderer.getToolCallCount("nonexistent")).toBe(0);
132
- });
133
- it("includes a legend in the output", () => {
134
- const output = renderer.renderToString();
135
- // Legend should mention at least pending and completed
136
- expect(output).toContain("○");
137
- expect(output).toContain("●");
138
- });
139
- it("handles workflow:start event without crashing", () => {
140
- const event = { type: "workflow:start", workflow: "test" };
141
- expect(() => renderer.update(event)).not.toThrow();
142
- });
143
- it("handles workflow:end event without crashing", () => {
144
- const event = {
145
- type: "workflow:end",
146
- results: {
147
- gather: { status: "success", data: {}, toolCalls: [] },
148
- },
149
- };
150
- expect(() => renderer.update(event)).not.toThrow();
151
- });
152
- it("handles route event without crashing", () => {
153
- const event = { type: "route", from: "gather", to: "investigate", reason: "next" };
154
- expect(() => renderer.update(event)).not.toThrow();
155
- });
156
- describe("uniform box widths", () => {
157
- const mixedWidthWorkflow = {
158
- id: "mixed",
159
- name: "Mixed Width Workflow",
160
- description: "Nodes with varying name lengths",
161
- nodes: {
162
- a: { name: "A", instruction: "Short", skills: [] },
163
- b: { name: "Gather Context and Analyze", instruction: "Long name", skills: [] },
164
- c: { name: "Report", instruction: "Medium", skills: [] },
165
- },
166
- edges: [
167
- { from: "a", to: "b" },
168
- { from: "b", to: "c" },
169
- ],
170
- entry: "a",
171
- };
172
- it("all top-border lines have the same width", () => {
173
- const r = new DagRenderer(mixedWidthWorkflow, { animate: false });
174
- const output = stripAnsi(r.renderToString());
175
- const topLines = output.split("\n").filter((l) => l.includes("┌") && l.includes("┐"));
176
- expect(topLines.length).toBe(3);
177
- const widths = topLines.map((l) => l.trim().length);
178
- expect(new Set(widths).size).toBe(1); // all same width
179
- });
180
- it("output contains ▼ arrowhead on non-first boxes", () => {
181
- const r = new DagRenderer(mixedWidthWorkflow, { animate: false });
182
- const output = stripAnsi(r.renderToString());
183
- expect(output).toContain("▼");
184
- });
185
- it("▼ is positioned between box borders", () => {
186
- const r = new DagRenderer(mixedWidthWorkflow, { animate: false });
187
- const output = stripAnsi(r.renderToString());
188
- const arrowLines = output.split("\n").filter((l) => l.includes("▼"));
189
- for (const line of arrowLines) {
190
- // ▼ should be inside a top border: ┌───▼───┐
191
- expect(line).toMatch(/┌─*▼─*┐/);
192
- }
193
- });
194
- it("bottom of non-terminal boxes has centered ┬", () => {
195
- const r = new DagRenderer(mixedWidthWorkflow, { animate: false });
196
- const output = stripAnsi(r.renderToString());
197
- const bottomLinesWithT = output.split("\n").filter((l) => l.includes("┬"));
198
- // A and B are non-terminal, so 2 lines with ┬
199
- expect(bottomLinesWithT.length).toBe(2);
200
- for (const line of bottomLinesWithT) {
201
- expect(line).toMatch(/└─*┬─*┘/);
202
- }
203
- });
204
- it("vertical connector uses centered │", () => {
205
- const r = new DagRenderer(mixedWidthWorkflow, { animate: false });
206
- const output = stripAnsi(r.renderToString());
207
- // Find lines that are purely vertical connectors (between boxes)
208
- const lines = output.split("\n");
209
- const connectorLines = lines.filter((l) => l.trim() === "│");
210
- expect(connectorLines.length).toBeGreaterThan(0);
211
- // The │ should be centered relative to the box width
212
- const topLine = lines.find((l) => l.includes("┌") && l.includes("┐"));
213
- const tIdx = topLine.indexOf("┌");
214
- const boxWidth = topLine.lastIndexOf("┐") - tIdx + 1;
215
- const expectedCol = tIdx + Math.floor(boxWidth / 2);
216
- for (const cl of connectorLines) {
217
- expect(cl.indexOf("│")).toBe(expectedCol);
218
- }
219
- });
220
- });
221
- describe("branching layout", () => {
222
- const branchingWorkflow = {
223
- id: "triage",
224
- name: "Triage Test",
225
- description: "A branching workflow",
226
- nodes: {
227
- gather: { name: "Gather Context", instruction: "Gather", skills: [] },
228
- investigate: { name: "Investigate", instruction: "Investigate", skills: [] },
229
- create_ticket: { name: "Create Ticket", instruction: "Create", skills: [] },
230
- skip: { name: "Skip", instruction: "Skip", skills: [] },
231
- notify: { name: "Notify", instruction: "Notify", skills: [] },
232
- },
233
- edges: [
234
- { from: "gather", to: "investigate" },
235
- { from: "investigate", to: "create_ticket" },
236
- { from: "investigate", to: "skip" },
237
- { from: "create_ticket", to: "notify" },
238
- ],
239
- entry: "gather",
240
- };
241
- it("output contains both branch children", () => {
242
- const r = new DagRenderer(branchingWorkflow, { animate: false });
243
- const output = stripAnsi(r.renderToString());
244
- expect(output).toContain("Create Ticket");
245
- expect(output).toContain("Skip");
246
- });
247
- it("output contains ┴ fork character", () => {
248
- const r = new DagRenderer(branchingWorkflow, { animate: false });
249
- const output = stripAnsi(r.renderToString());
250
- expect(output).toContain("┴");
251
- });
252
- it("state tracking works through branches", () => {
253
- const r = new DagRenderer(branchingWorkflow, { animate: false });
254
- r.update({ type: "node:enter", node: "gather", instruction: "Gather" });
255
- r.update({ type: "node:exit", node: "gather", result: { status: "success", data: {}, toolCalls: [] } });
256
- r.update({ type: "node:enter", node: "investigate", instruction: "Investigate" });
257
- r.update({ type: "node:exit", node: "investigate", result: { status: "success", data: {}, toolCalls: [] } });
258
- r.update({ type: "node:enter", node: "create_ticket", instruction: "Create" });
259
- expect(r.getNodeState("gather")).toBe("completed");
260
- expect(r.getNodeState("investigate")).toBe("completed");
261
- expect(r.getNodeState("create_ticket")).toBe("running");
262
- expect(r.getNodeState("skip")).toBe("pending");
263
- expect(r.getNodeState("notify")).toBe("pending");
264
- });
265
- it("topological order: Gather before Investigate before Notify", () => {
266
- const r = new DagRenderer(branchingWorkflow, { animate: false });
267
- const output = stripAnsi(r.renderToString());
268
- const gatherIdx = output.indexOf("Gather Context");
269
- const investigateIdx = output.indexOf("Investigate");
270
- const notifyIdx = output.indexOf("Notify");
271
- expect(gatherIdx).toBeLessThan(investigateIdx);
272
- expect(investigateIdx).toBeLessThan(notifyIdx);
273
- });
274
- it("falls back to sequential for 3+ children", () => {
275
- const tripleWorkflow = {
276
- id: "triple",
277
- name: "Triple Branch",
278
- description: "Three-way branch",
279
- nodes: {
280
- start: { name: "Start", instruction: "Start", skills: [] },
281
- a: { name: "Branch A", instruction: "A", skills: [] },
282
- b: { name: "Branch B", instruction: "B", skills: [] },
283
- c: { name: "Branch C", instruction: "C", skills: [] },
284
- },
285
- edges: [
286
- { from: "start", to: "a" },
287
- { from: "start", to: "b" },
288
- { from: "start", to: "c" },
289
- ],
290
- entry: "start",
291
- };
292
- const r = new DagRenderer(tripleWorkflow, { animate: false });
293
- const output = stripAnsi(r.renderToString());
294
- // Should NOT have ┴ fork — sequential fallback
295
- expect(output).not.toContain("┴");
296
- // But all branches are present
297
- expect(output).toContain("Branch A");
298
- expect(output).toContain("Branch B");
299
- expect(output).toContain("Branch C");
300
- });
301
- });
302
- });
@@ -1 +0,0 @@
1
- export {};