@sweny-ai/core 0.1.54 → 0.1.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/executor.test.js +2 -1
- package/dist/__tests__/integration/sources.integration.test.d.ts +1 -0
- package/dist/__tests__/integration/sources.integration.test.js +123 -0
- package/dist/__tests__/workflow-yaml.test.js +12 -5
- package/dist/cli/__tests__/report-cloud.test.d.ts +1 -0
- package/dist/cli/__tests__/report-cloud.test.js +165 -0
- package/dist/cli/cloud-report.d.ts +12 -0
- package/dist/cli/cloud-report.js +79 -0
- package/dist/cli/config-file.d.ts +3 -3
- package/dist/cli/config-file.js +18 -0
- package/dist/cli/config.d.ts +3 -0
- package/dist/cli/config.js +18 -2
- package/dist/cli/config.test.js +65 -1
- package/dist/cli/e2e.js +4 -2
- package/dist/cli/e2e.test.js +9 -2
- package/dist/cli/main.js +48 -3
- package/dist/cli/output.test.js +1 -0
- package/dist/cli/publish.test.d.ts +1 -0
- package/dist/cli/publish.test.js +610 -0
- package/dist/executor.d.ts +8 -0
- package/dist/executor.js +21 -3
- package/dist/executor.test.js +56 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/mermaid.test.js +2 -0
- package/dist/schema.d.ts +174 -46
- package/dist/schema.js +31 -2
- package/dist/sources.d.ts +70 -0
- package/dist/sources.js +194 -0
- package/dist/sources.test.d.ts +1 -0
- package/dist/sources.test.js +264 -0
- package/dist/sources.validation.test.d.ts +12 -0
- package/dist/sources.validation.test.js +360 -0
- package/dist/templates.d.ts +6 -2
- package/dist/templates.js +36 -46
- package/dist/testing.js +4 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.js +0 -5
- package/dist/workflows/browser.js +1 -1
- package/dist/workflows/triage.yml +1 -23
- package/package.json +1 -1
package/dist/cli/config.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { validateInputs } from "./config.js";
|
|
2
|
+
import { validateInputs, parseCliInputs } from "./config.js";
|
|
3
3
|
/**
|
|
4
4
|
* Focused tests for validateInputs() — specifically the notification-provider
|
|
5
5
|
* switch. Regressions here break every `swenyai/triage` action run because
|
|
@@ -65,6 +65,9 @@ function baseConfig(overrides = {}) {
|
|
|
65
65
|
workspaceTools: [],
|
|
66
66
|
rules: [],
|
|
67
67
|
context: [],
|
|
68
|
+
offline: false,
|
|
69
|
+
fetchAuth: {},
|
|
70
|
+
cloudToken: "",
|
|
68
71
|
...overrides,
|
|
69
72
|
};
|
|
70
73
|
}
|
|
@@ -109,3 +112,64 @@ describe("validateInputs — notification provider", () => {
|
|
|
109
112
|
expect(err).toContain("console");
|
|
110
113
|
});
|
|
111
114
|
});
|
|
115
|
+
describe("fetch.auth + offline parsing", () => {
|
|
116
|
+
it("parses offline flag", () => {
|
|
117
|
+
const config = parseCliInputs({ offline: true }, {});
|
|
118
|
+
expect(config.offline).toBe(true);
|
|
119
|
+
});
|
|
120
|
+
it("defaults fetchAuth to {} and offline to false", () => {
|
|
121
|
+
const config = parseCliInputs({}, {});
|
|
122
|
+
expect(config.offline).toBe(false);
|
|
123
|
+
expect(config.fetchAuth).toEqual({});
|
|
124
|
+
});
|
|
125
|
+
it("parses fetch.auth from file config", () => {
|
|
126
|
+
const config = parseCliInputs({}, { "fetch.auth": { "api.example.com": "MY_TOKEN" } });
|
|
127
|
+
expect(config.fetchAuth).toEqual({ "api.example.com": "MY_TOKEN" });
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
describe("parseCliInputs — cloud token", () => {
|
|
131
|
+
it("reads SWENY_CLOUD_TOKEN from env", () => {
|
|
132
|
+
const original = process.env.SWENY_CLOUD_TOKEN;
|
|
133
|
+
process.env.SWENY_CLOUD_TOKEN = "sweny_pk_test123";
|
|
134
|
+
try {
|
|
135
|
+
const config = parseCliInputs({});
|
|
136
|
+
expect(config.cloudToken).toBe("sweny_pk_test123");
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
if (original === undefined)
|
|
140
|
+
delete process.env.SWENY_CLOUD_TOKEN;
|
|
141
|
+
else
|
|
142
|
+
process.env.SWENY_CLOUD_TOKEN = original;
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
it("reads cloud-token from config file", () => {
|
|
146
|
+
const config = parseCliInputs({}, { "cloud-token": "sweny_pk_fromfile" });
|
|
147
|
+
expect(config.cloudToken).toBe("sweny_pk_fromfile");
|
|
148
|
+
});
|
|
149
|
+
it("env var overrides config file", () => {
|
|
150
|
+
const original = process.env.SWENY_CLOUD_TOKEN;
|
|
151
|
+
process.env.SWENY_CLOUD_TOKEN = "sweny_pk_env";
|
|
152
|
+
try {
|
|
153
|
+
const config = parseCliInputs({}, { "cloud-token": "sweny_pk_file" });
|
|
154
|
+
expect(config.cloudToken).toBe("sweny_pk_env");
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
if (original === undefined)
|
|
158
|
+
delete process.env.SWENY_CLOUD_TOKEN;
|
|
159
|
+
else
|
|
160
|
+
process.env.SWENY_CLOUD_TOKEN = original;
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
it("defaults to empty string", () => {
|
|
164
|
+
const original = process.env.SWENY_CLOUD_TOKEN;
|
|
165
|
+
delete process.env.SWENY_CLOUD_TOKEN;
|
|
166
|
+
try {
|
|
167
|
+
const config = parseCliInputs({});
|
|
168
|
+
expect(config.cloudToken).toBe("");
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
if (original !== undefined)
|
|
172
|
+
process.env.SWENY_CLOUD_TOKEN = original;
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
});
|
package/dist/cli/e2e.js
CHANGED
|
@@ -830,9 +830,11 @@ export async function runE2eRun(options) {
|
|
|
830
830
|
runResults.push({ file: fileName, passed: false });
|
|
831
831
|
continue;
|
|
832
832
|
}
|
|
833
|
-
// Replace template vars in node instructions
|
|
833
|
+
// Replace template vars in node instructions (e2e workflows always use string instructions)
|
|
834
834
|
for (const node of Object.values(workflow.nodes)) {
|
|
835
|
-
|
|
835
|
+
if (typeof node.instruction === "string") {
|
|
836
|
+
node.instruction = resolveTemplateVars(node.instruction, vars);
|
|
837
|
+
}
|
|
836
838
|
}
|
|
837
839
|
// Build skills + Claude client
|
|
838
840
|
const skills = createSkillMap(configuredSkills(process.env, cwd));
|
package/dist/cli/e2e.test.js
CHANGED
|
@@ -247,7 +247,13 @@ describe("buildFlowNodes", () => {
|
|
|
247
247
|
const { nodes } = buildFlowNodes(flow);
|
|
248
248
|
for (const [id, node] of Object.entries(nodes)) {
|
|
249
249
|
expect(node.name, `${id}.name`).toBeTruthy();
|
|
250
|
-
|
|
250
|
+
const instr = node.instruction;
|
|
251
|
+
if (typeof instr === "string") {
|
|
252
|
+
expect(instr.length, `${id}.instruction`).toBeGreaterThan(0);
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
expect(instr, `${id}.instruction`).toBeTruthy();
|
|
256
|
+
}
|
|
251
257
|
expect(Array.isArray(node.skills), `${id}.skills`).toBe(true);
|
|
252
258
|
}
|
|
253
259
|
});
|
|
@@ -607,7 +613,8 @@ describe("template variable completeness — all {vars} in instructions are reso
|
|
|
607
613
|
it(`${flow.type}: all template vars in instructions resolve to values`, () => {
|
|
608
614
|
const wf = buildFlowWorkflow(flow, "http://localhost:3000");
|
|
609
615
|
for (const [nodeId, node] of Object.entries(wf.nodes)) {
|
|
610
|
-
const
|
|
616
|
+
const instrText = typeof node.instruction === "string" ? node.instruction : "";
|
|
617
|
+
const resolved = resolveTemplateVars(instrText, vars);
|
|
611
618
|
// After resolution, no {word} placeholders should remain
|
|
612
619
|
// (except for agent-browser refs like @<ref> which are not {vars})
|
|
613
620
|
const unresolvedVars = resolved.match(/\{(\w+)\}/g) || [];
|
package/dist/cli/main.js
CHANGED
|
@@ -29,6 +29,7 @@ import { c, formatBanner, getStepDetails, formatStepLine, formatDagResultHuman,
|
|
|
29
29
|
import { checkProviderConnectivity } from "./check.js";
|
|
30
30
|
import { registerSetupCommand } from "./setup.js";
|
|
31
31
|
import { registerPublishCommand } from "./publish.js";
|
|
32
|
+
import { reportToCloud } from "./cloud-report.js";
|
|
32
33
|
// ── Stream observer (NDJSON) ────────────────────────────────────────
|
|
33
34
|
/**
|
|
34
35
|
* Create an observer that writes NDJSON ExecutionEvents to stdout.
|
|
@@ -324,10 +325,9 @@ triageCmd.action(async (options) => {
|
|
|
324
325
|
...(config.observabilityCredentials.tableName && {
|
|
325
326
|
betterstackTableName: config.observabilityCredentials.tableName,
|
|
326
327
|
}),
|
|
327
|
-
// Structured rules/context for executor
|
|
328
|
+
// Structured rules/context for executor (URLs resolved eagerly by loadAdditionalContext)
|
|
328
329
|
rules,
|
|
329
330
|
context: fullContext,
|
|
330
|
-
// URLs for the prepare node to fetch at runtime
|
|
331
331
|
rulesUrls,
|
|
332
332
|
contextUrls,
|
|
333
333
|
};
|
|
@@ -337,6 +337,10 @@ triageCmd.action(async (options) => {
|
|
|
337
337
|
claude,
|
|
338
338
|
observer,
|
|
339
339
|
logger: consoleLogger,
|
|
340
|
+
cwd: process.cwd(),
|
|
341
|
+
env: process.env,
|
|
342
|
+
fetchAuth: config.fetchAuth,
|
|
343
|
+
offline: config.offline,
|
|
340
344
|
});
|
|
341
345
|
const durationMs = Date.now() - runStart;
|
|
342
346
|
// Output
|
|
@@ -360,6 +364,13 @@ triageCmd.action(async (options) => {
|
|
|
360
364
|
console.error(c.subtle(` ⚠ could not write GITHUB_STEP_SUMMARY: ${err instanceof Error ? err.message : err}`));
|
|
361
365
|
}
|
|
362
366
|
}
|
|
367
|
+
// Report to SWEny Cloud (best-effort, never block the run)
|
|
368
|
+
try {
|
|
369
|
+
await reportToCloud(results, durationMs, config, "triage");
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
// silent — cloud reporting is optional
|
|
373
|
+
}
|
|
363
374
|
// Terminal bell
|
|
364
375
|
if (config.bell)
|
|
365
376
|
process.stderr.write("\x07");
|
|
@@ -420,6 +431,7 @@ implementCmd.action(async (issueId, options) => {
|
|
|
420
431
|
mcpServers,
|
|
421
432
|
});
|
|
422
433
|
console.log(chalk.cyan(`\n sweny implement ${issueId}\n`));
|
|
434
|
+
const implRunStart = Date.now();
|
|
423
435
|
const isTTY = process.stderr.isTTY ?? false;
|
|
424
436
|
const implProgressObserver = (event) => {
|
|
425
437
|
switch (event.type) {
|
|
@@ -477,6 +489,10 @@ implementCmd.action(async (issueId, options) => {
|
|
|
477
489
|
claude,
|
|
478
490
|
observer,
|
|
479
491
|
logger: consoleLogger,
|
|
492
|
+
cwd: process.cwd(),
|
|
493
|
+
env: process.env,
|
|
494
|
+
fetchAuth: config.fetchAuth,
|
|
495
|
+
offline: config.offline,
|
|
480
496
|
});
|
|
481
497
|
const hasFailed = [...results.values()].some((r) => r.status === "failed");
|
|
482
498
|
if (hasFailed) {
|
|
@@ -491,6 +507,13 @@ implementCmd.action(async (issueId, options) => {
|
|
|
491
507
|
else {
|
|
492
508
|
console.log(chalk.green(`\n Implement workflow completed\n`));
|
|
493
509
|
}
|
|
510
|
+
// Report to SWEny Cloud (best-effort)
|
|
511
|
+
try {
|
|
512
|
+
await reportToCloud(results, Date.now() - implRunStart, config, "implement");
|
|
513
|
+
}
|
|
514
|
+
catch {
|
|
515
|
+
// silent
|
|
516
|
+
}
|
|
494
517
|
process.exit(0);
|
|
495
518
|
}
|
|
496
519
|
catch (err) {
|
|
@@ -540,6 +563,7 @@ export async function workflowRunAction(file, options) {
|
|
|
540
563
|
}
|
|
541
564
|
process.exit(0);
|
|
542
565
|
}
|
|
566
|
+
const runStart = Date.now();
|
|
543
567
|
const fileConfig = loadConfigFile();
|
|
544
568
|
const config = parseCliInputs(options, fileConfig);
|
|
545
569
|
const isJson = Boolean(options.json);
|
|
@@ -659,6 +683,10 @@ export async function workflowRunAction(file, options) {
|
|
|
659
683
|
claude,
|
|
660
684
|
observer,
|
|
661
685
|
logger: consoleLogger,
|
|
686
|
+
cwd: process.cwd(),
|
|
687
|
+
env: process.env,
|
|
688
|
+
fetchAuth: config.fetchAuth,
|
|
689
|
+
offline: config.offline,
|
|
662
690
|
});
|
|
663
691
|
if (isJson) {
|
|
664
692
|
process.stdout.write(JSON.stringify(Object.fromEntries(results), null, 2) + "\n");
|
|
@@ -674,7 +702,21 @@ export async function workflowRunAction(file, options) {
|
|
|
674
702
|
}
|
|
675
703
|
process.stdout.write(toMermaidBlock(workflow, { state, trace, title: workflow.name }) + "\n");
|
|
676
704
|
}
|
|
705
|
+
// Report to SWEny Cloud (best-effort)
|
|
706
|
+
try {
|
|
707
|
+
await reportToCloud(results, Date.now() - runStart, config, workflow.id);
|
|
708
|
+
}
|
|
709
|
+
catch {
|
|
710
|
+
// silent
|
|
711
|
+
}
|
|
677
712
|
const hasFailed = [...results.values()].some((r) => r.status === "failed");
|
|
713
|
+
// Report to SWEny Cloud (best-effort)
|
|
714
|
+
try {
|
|
715
|
+
await reportToCloud(results, 0, config, workflow.id);
|
|
716
|
+
}
|
|
717
|
+
catch {
|
|
718
|
+
// silent
|
|
719
|
+
}
|
|
678
720
|
if (hasFailed) {
|
|
679
721
|
console.error(chalk.red(` Workflow failed\n`));
|
|
680
722
|
process.exit(1);
|
|
@@ -804,9 +846,12 @@ workflowCmd
|
|
|
804
846
|
.action(workflowExportAction);
|
|
805
847
|
workflowCmd
|
|
806
848
|
.command("create <description>")
|
|
807
|
-
.description("
|
|
849
|
+
.description("[DEPRECATED] Use `sweny new` and pick 'Describe your own'")
|
|
808
850
|
.option("--json", "Output workflow JSON to stdout (no interactive prompt)")
|
|
809
851
|
.action(async (description, options) => {
|
|
852
|
+
if (!options.json) {
|
|
853
|
+
console.warn("\x1B[33m ⚠ `sweny workflow create` is deprecated. Use `sweny new` instead.\x1B[0m\n");
|
|
854
|
+
}
|
|
810
855
|
const skills = configuredSkills();
|
|
811
856
|
const claude = new ClaudeClient({
|
|
812
857
|
maxTurns: 3,
|
package/dist/cli/output.test.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|