@sweny-ai/core 0.1.77 → 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 (119) hide show
  1. package/dist/browser.d.ts +11 -5
  2. package/dist/browser.js +11 -11
  3. package/dist/claude.d.ts +16 -0
  4. package/dist/claude.js +98 -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/loader.d.ts +40 -0
  13. package/dist/loader.js +73 -0
  14. package/dist/mcp-catalog.d.ts +47 -0
  15. package/dist/mcp-catalog.js +304 -0
  16. package/dist/mcp.d.ts +6 -9
  17. package/dist/mcp.js +24 -314
  18. package/dist/schema.d.ts +183 -151
  19. package/dist/schema.js +49 -7
  20. package/dist/skills/custom-loader.d.ts +40 -0
  21. package/dist/skills/custom-loader.js +107 -32
  22. package/dist/skills/index.d.ts +13 -1
  23. package/dist/skills/index.js +12 -3
  24. package/dist/studio.js +4 -1
  25. package/dist/templates.d.ts +29 -8
  26. package/dist/templates.js +30 -20
  27. package/dist/types.d.ts +12 -0
  28. package/dist/verify.js +42 -4
  29. package/package.json +8 -4
  30. package/dist/__tests__/cascade.test.d.ts +0 -11
  31. package/dist/__tests__/cascade.test.js +0 -452
  32. package/dist/__tests__/claude.test.d.ts +0 -1
  33. package/dist/__tests__/claude.test.js +0 -427
  34. package/dist/__tests__/custom-loader.test.d.ts +0 -1
  35. package/dist/__tests__/custom-loader.test.js +0 -116
  36. package/dist/__tests__/executor.test.d.ts +0 -1
  37. package/dist/__tests__/executor.test.js +0 -1635
  38. package/dist/__tests__/integration/datadog.integration.test.d.ts +0 -1
  39. package/dist/__tests__/integration/datadog.integration.test.js +0 -23
  40. package/dist/__tests__/integration/e2e-workflow.integration.test.d.ts +0 -1
  41. package/dist/__tests__/integration/e2e-workflow.integration.test.js +0 -75
  42. package/dist/__tests__/integration/github.integration.test.d.ts +0 -1
  43. package/dist/__tests__/integration/github.integration.test.js +0 -37
  44. package/dist/__tests__/integration/harness.d.ts +0 -24
  45. package/dist/__tests__/integration/harness.js +0 -34
  46. package/dist/__tests__/integration/linear.integration.test.d.ts +0 -1
  47. package/dist/__tests__/integration/linear.integration.test.js +0 -15
  48. package/dist/__tests__/integration/sentry.integration.test.d.ts +0 -1
  49. package/dist/__tests__/integration/sentry.integration.test.js +0 -20
  50. package/dist/__tests__/integration/slack.integration.test.d.ts +0 -1
  51. package/dist/__tests__/integration/slack.integration.test.js +0 -22
  52. package/dist/__tests__/integration/sources.integration.test.d.ts +0 -1
  53. package/dist/__tests__/integration/sources.integration.test.js +0 -123
  54. package/dist/__tests__/publish.test.d.ts +0 -1
  55. package/dist/__tests__/publish.test.js +0 -180
  56. package/dist/__tests__/requires.test.d.ts +0 -1
  57. package/dist/__tests__/requires.test.js +0 -82
  58. package/dist/__tests__/retry.test.d.ts +0 -1
  59. package/dist/__tests__/retry.test.js +0 -213
  60. package/dist/__tests__/schema.test.d.ts +0 -1
  61. package/dist/__tests__/schema.test.js +0 -600
  62. package/dist/__tests__/skill-config-integration.test.d.ts +0 -1
  63. package/dist/__tests__/skill-config-integration.test.js +0 -204
  64. package/dist/__tests__/skills-index.test.d.ts +0 -1
  65. package/dist/__tests__/skills-index.test.js +0 -119
  66. package/dist/__tests__/skills.test.d.ts +0 -1
  67. package/dist/__tests__/skills.test.js +0 -565
  68. package/dist/__tests__/spec-conformance.test.d.ts +0 -18
  69. package/dist/__tests__/spec-conformance.test.js +0 -1084
  70. package/dist/__tests__/studio.test.d.ts +0 -1
  71. package/dist/__tests__/studio.test.js +0 -403
  72. package/dist/__tests__/templates.test.d.ts +0 -1
  73. package/dist/__tests__/templates.test.js +0 -49
  74. package/dist/__tests__/testing.test.d.ts +0 -1
  75. package/dist/__tests__/testing.test.js +0 -242
  76. package/dist/__tests__/verify.test.d.ts +0 -1
  77. package/dist/__tests__/verify.test.js +0 -517
  78. package/dist/__tests__/version-consistency.test.d.ts +0 -1
  79. package/dist/__tests__/version-consistency.test.js +0 -312
  80. package/dist/__tests__/workflow-builder.test.d.ts +0 -1
  81. package/dist/__tests__/workflow-builder.test.js +0 -110
  82. package/dist/__tests__/workflow-yaml.test.d.ts +0 -1
  83. package/dist/__tests__/workflow-yaml.test.js +0 -201
  84. package/dist/cli/__tests__/diagram.test.d.ts +0 -1
  85. package/dist/cli/__tests__/diagram.test.js +0 -225
  86. package/dist/cli/__tests__/report-cloud.test.d.ts +0 -1
  87. package/dist/cli/__tests__/report-cloud.test.js +0 -165
  88. package/dist/cli/__tests__/upgrade.test.d.ts +0 -1
  89. package/dist/cli/__tests__/upgrade.test.js +0 -317
  90. package/dist/cli/__tests__/version-check.test.d.ts +0 -1
  91. package/dist/cli/__tests__/version-check.test.js +0 -209
  92. package/dist/cli/config.test.d.ts +0 -1
  93. package/dist/cli/config.test.js +0 -200
  94. package/dist/cli/credentials.test.d.ts +0 -1
  95. package/dist/cli/credentials.test.js +0 -172
  96. package/dist/cli/e2e.test.d.ts +0 -1
  97. package/dist/cli/e2e.test.js +0 -690
  98. package/dist/cli/marketplace.test.d.ts +0 -1
  99. package/dist/cli/marketplace.test.js +0 -355
  100. package/dist/cli/new.test.d.ts +0 -1
  101. package/dist/cli/new.test.js +0 -1043
  102. package/dist/cli/output.test.d.ts +0 -1
  103. package/dist/cli/output.test.js +0 -180
  104. package/dist/cli/publish.test.d.ts +0 -1
  105. package/dist/cli/publish.test.js +0 -610
  106. package/dist/cli/renderer.test.d.ts +0 -1
  107. package/dist/cli/renderer.test.js +0 -302
  108. package/dist/executor.test.d.ts +0 -1
  109. package/dist/executor.test.js +0 -618
  110. package/dist/mcp.test.d.ts +0 -1
  111. package/dist/mcp.test.js +0 -735
  112. package/dist/mermaid.test.d.ts +0 -1
  113. package/dist/mermaid.test.js +0 -256
  114. package/dist/sources.test.d.ts +0 -1
  115. package/dist/sources.test.js +0 -265
  116. package/dist/sources.validation.test.d.ts +0 -12
  117. package/dist/sources.validation.test.js +0 -380
  118. package/dist/workflow-builder.test.d.ts +0 -1
  119. package/dist/workflow-builder.test.js +0 -123
@@ -1,200 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { validateInputs, parseCliInputs } from "./config.js";
3
- /**
4
- * Focused tests for validateInputs() — specifically the notification-provider
5
- * switch. Regressions here break every `swenyai/triage` action run because
6
- * that action passes --notification-provider github-summary by default.
7
- */
8
- function baseConfig(overrides = {}) {
9
- return {
10
- codingAgentProvider: "claude",
11
- anthropicApiKey: "sk-ant-test",
12
- claudeOauthToken: "",
13
- openaiApiKey: "",
14
- geminiApiKey: "",
15
- observabilityProviders: ["file"],
16
- observabilityCredentials: { file: {} },
17
- issueTrackerProvider: "file",
18
- linearApiKey: "",
19
- linearTeamId: "",
20
- linearBugLabelId: "",
21
- linearTriageLabelId: "",
22
- linearStateBacklog: "",
23
- linearStateInProgress: "",
24
- linearStatePeerReview: "",
25
- timeRange: "24h",
26
- severityFocus: "errors",
27
- serviceFilter: "*",
28
- investigationDepth: "standard",
29
- maxInvestigateTurns: 50,
30
- maxImplementTurns: 30,
31
- baseBranch: "main",
32
- prLabels: ["agent"],
33
- issueLabels: [],
34
- dryRun: false,
35
- reviewMode: "review",
36
- noveltyMode: true,
37
- issueOverride: "",
38
- additionalInstructions: "",
39
- serviceMapPath: ".github/service-map.yml",
40
- githubToken: "ghp_test",
41
- botToken: "",
42
- sourceControlProvider: "github",
43
- jiraBaseUrl: "",
44
- jiraEmail: "",
45
- jiraApiToken: "",
46
- gitlabToken: "",
47
- gitlabProjectId: "",
48
- gitlabBaseUrl: "https://gitlab.com",
49
- notificationProvider: "console",
50
- notificationWebhookUrl: "",
51
- sendgridApiKey: "",
52
- emailFrom: "",
53
- emailTo: "",
54
- webhookSigningSecret: "",
55
- repository: "acme/app",
56
- repositoryOwner: "",
57
- json: false,
58
- stream: false,
59
- bell: false,
60
- cacheDir: ".sweny/cache",
61
- cacheTtl: 86400,
62
- noCache: false,
63
- outputDir: ".sweny/output",
64
- mcpServers: {},
65
- workspaceTools: [],
66
- rules: [],
67
- context: [],
68
- offline: false,
69
- fetchAuth: {},
70
- cloudToken: "",
71
- ...overrides,
72
- };
73
- }
74
- describe("validateInputs — notification provider", () => {
75
- it("accepts console (no credentials required)", () => {
76
- const errors = validateInputs(baseConfig({ notificationProvider: "console" }));
77
- expect(errors.filter((e) => e.includes("notification-provider"))).toEqual([]);
78
- });
79
- it("accepts github-summary (no credentials required)", () => {
80
- // Regression guard: the `swenyai/triage` composite action passes this as
81
- // its default. If the validator stops accepting it every scheduled run
82
- // across every consumer immediately breaks.
83
- const errors = validateInputs(baseConfig({ notificationProvider: "github-summary" }));
84
- expect(errors.filter((e) => e.includes("notification-provider"))).toEqual([]);
85
- });
86
- it("accepts file (no credentials required)", () => {
87
- const errors = validateInputs(baseConfig({ notificationProvider: "file" }));
88
- expect(errors.filter((e) => e.includes("notification-provider"))).toEqual([]);
89
- });
90
- it("requires NOTIFICATION_WEBHOOK_URL for slack", () => {
91
- const errors = validateInputs(baseConfig({ notificationProvider: "slack", notificationWebhookUrl: "" }));
92
- expect(errors.some((e) => e.includes("NOTIFICATION_WEBHOOK_URL"))).toBe(true);
93
- });
94
- it("accepts slack when NOTIFICATION_WEBHOOK_URL is set", () => {
95
- const errors = validateInputs(baseConfig({
96
- notificationProvider: "slack",
97
- notificationWebhookUrl: "https://hooks.slack.com/services/T/B/X",
98
- }));
99
- expect(errors.filter((e) => e.includes("notification"))).toEqual([]);
100
- });
101
- it("requires sendgrid credentials for email", () => {
102
- const errors = validateInputs(baseConfig({ notificationProvider: "email" }));
103
- expect(errors.some((e) => e.includes("SENDGRID_API_KEY"))).toBe(true);
104
- expect(errors.some((e) => e.includes("EMAIL_FROM"))).toBe(true);
105
- expect(errors.some((e) => e.includes("EMAIL_TO"))).toBe(true);
106
- });
107
- it("rejects unknown providers and lists github-summary in the error", () => {
108
- const errors = validateInputs(baseConfig({ notificationProvider: "bogus" }));
109
- const err = errors.find((e) => e.includes("Unknown --notification-provider"));
110
- expect(err).toBeDefined();
111
- expect(err).toContain("github-summary");
112
- expect(err).toContain("console");
113
- });
114
- });
115
- describe("validateInputs — observability provider", () => {
116
- it("accepts 'none' without requiring any credentials", () => {
117
- const errors = validateInputs(baseConfig({ observabilityProviders: [], observabilityCredentials: {} }));
118
- expect(errors.filter((e) => e.includes("DD_") || e.includes("observability"))).toEqual([]);
119
- });
120
- it("requires DD keys when explicitly set to datadog", () => {
121
- const errors = validateInputs(baseConfig({ observabilityProviders: ["datadog"], observabilityCredentials: {} }));
122
- expect(errors.some((e) => e.includes("DD_API_KEY"))).toBe(true);
123
- expect(errors.some((e) => e.includes("DD_APP_KEY"))).toBe(true);
124
- });
125
- });
126
- describe("parseCliInputs — observability provider default", () => {
127
- it("defaults to empty array when no provider is configured", () => {
128
- const config = parseCliInputs({}, {});
129
- expect(config.observabilityProviders).toEqual([]);
130
- });
131
- it("respects explicit datadog provider", () => {
132
- const config = parseCliInputs({ observabilityProvider: "datadog" }, {});
133
- expect(config.observabilityProviders).toEqual(["datadog"]);
134
- });
135
- it("supports comma-separated multiple providers", () => {
136
- const config = parseCliInputs({ observabilityProvider: "loki,sentry" }, {});
137
- expect(config.observabilityProviders).toEqual(["loki", "sentry"]);
138
- });
139
- });
140
- describe("fetch.auth + offline parsing", () => {
141
- it("parses offline flag", () => {
142
- const config = parseCliInputs({ offline: true }, {});
143
- expect(config.offline).toBe(true);
144
- });
145
- it("defaults fetchAuth to {} and offline to false", () => {
146
- const config = parseCliInputs({}, {});
147
- expect(config.offline).toBe(false);
148
- expect(config.fetchAuth).toEqual({});
149
- });
150
- it("parses fetch.auth from file config", () => {
151
- const config = parseCliInputs({}, { "fetch.auth": { "api.example.com": "MY_TOKEN" } });
152
- expect(config.fetchAuth).toEqual({ "api.example.com": "MY_TOKEN" });
153
- });
154
- });
155
- describe("parseCliInputs — cloud token", () => {
156
- it("reads SWENY_CLOUD_TOKEN from env", () => {
157
- const original = process.env.SWENY_CLOUD_TOKEN;
158
- process.env.SWENY_CLOUD_TOKEN = "sweny_pk_test123";
159
- try {
160
- const config = parseCliInputs({});
161
- expect(config.cloudToken).toBe("sweny_pk_test123");
162
- }
163
- finally {
164
- if (original === undefined)
165
- delete process.env.SWENY_CLOUD_TOKEN;
166
- else
167
- process.env.SWENY_CLOUD_TOKEN = original;
168
- }
169
- });
170
- it("reads cloud-token from config file", () => {
171
- const config = parseCliInputs({}, { "cloud-token": "sweny_pk_fromfile" });
172
- expect(config.cloudToken).toBe("sweny_pk_fromfile");
173
- });
174
- it("env var overrides config file", () => {
175
- const original = process.env.SWENY_CLOUD_TOKEN;
176
- process.env.SWENY_CLOUD_TOKEN = "sweny_pk_env";
177
- try {
178
- const config = parseCliInputs({}, { "cloud-token": "sweny_pk_file" });
179
- expect(config.cloudToken).toBe("sweny_pk_env");
180
- }
181
- finally {
182
- if (original === undefined)
183
- delete process.env.SWENY_CLOUD_TOKEN;
184
- else
185
- process.env.SWENY_CLOUD_TOKEN = original;
186
- }
187
- });
188
- it("defaults to empty string", () => {
189
- const original = process.env.SWENY_CLOUD_TOKEN;
190
- delete process.env.SWENY_CLOUD_TOKEN;
191
- try {
192
- const config = parseCliInputs({});
193
- expect(config.cloudToken).toBe("");
194
- }
195
- finally {
196
- if (original !== undefined)
197
- process.env.SWENY_CLOUD_TOKEN = original;
198
- }
199
- });
200
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,172 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { buildCredentialMap } from "./credentials.js";
3
- import { buildSkillMcpServers } from "../mcp.js";
4
- // ─────────────────────────────────────────────────────────────────────
5
- // Integration tests: env vars → buildCredentialMap → buildSkillMcpServers
6
- // ─────────────────────────────────────────────────────────────────────
7
- //
8
- // These tests catch env-var name drift between:
9
- // - the user-facing env var name (what docs / new.ts / config.ts read)
10
- // - the canonical key the MCP wiring functions look up
11
- //
12
- // Unit tests in mcp.test.ts inject the credentials map directly. That
13
- // validates each MCP wiring path but cannot catch a buildCredentialMap
14
- // that puts the value under the wrong key. THESE tests close that gap
15
- // by going through the real env-var → canonical-key translation.
16
- //
17
- // If a future contributor renames an env var and forgets to update both
18
- // sides, one of these will fail loudly.
19
- describe("buildCredentialMap ↔ buildSkillMcpServers integration", () => {
20
- // ── New Relic: NR_API_KEY user-facing → NEW_RELIC_API_KEY canonical ──
21
- it("user setting NR_API_KEY auto-wires the New Relic MCP", () => {
22
- const creds = buildCredentialMap({ NR_API_KEY: "NRAK-abc" });
23
- expect(creds.NEW_RELIC_API_KEY).toBe("NRAK-abc");
24
- const mcps = buildSkillMcpServers({
25
- referencedSkills: new Set(["newrelic"]),
26
- credentials: creds,
27
- });
28
- expect(mcps.newrelic).toBeDefined();
29
- expect(mcps.newrelic?.url).toBe("https://mcp.newrelic.com/mcp/");
30
- });
31
- it("user setting NR_REGION=eu picks the EU New Relic endpoint", () => {
32
- const creds = buildCredentialMap({ NR_API_KEY: "NRAK-abc", NR_REGION: "eu" });
33
- const mcps = buildSkillMcpServers({
34
- referencedSkills: new Set(["newrelic"]),
35
- credentials: creds,
36
- });
37
- expect(mcps.newrelic?.url).toBe("https://mcp.eu.newrelic.com/mcp/");
38
- });
39
- it("user setting NEW_RELIC_API_KEY (canonical name) also works", () => {
40
- const creds = buildCredentialMap({ NEW_RELIC_API_KEY: "NRAK-xyz" });
41
- expect(creds.NEW_RELIC_API_KEY).toBe("NRAK-xyz");
42
- });
43
- // ── Sentry: SENTRY_BASE_URL user-facing → SENTRY_URL canonical ──
44
- it("user setting SENTRY_BASE_URL for self-hosted reaches the MCP layer", () => {
45
- const creds = buildCredentialMap({
46
- SENTRY_AUTH_TOKEN: "sntrys_abc",
47
- SENTRY_BASE_URL: "https://sentry.acme.com",
48
- });
49
- expect(creds.SENTRY_URL).toBe("https://sentry.acme.com");
50
- const mcps = buildSkillMcpServers({
51
- referencedSkills: new Set(["sentry"]),
52
- credentials: creds,
53
- });
54
- expect(mcps.sentry).toBeDefined();
55
- expect(mcps.sentry?.env?.SENTRY_HOST).toBe("sentry.acme.com");
56
- });
57
- it("user setting SENTRY_URL (canonical name) also reaches MCP layer", () => {
58
- const creds = buildCredentialMap({
59
- SENTRY_AUTH_TOKEN: "sntrys_abc",
60
- SENTRY_URL: "https://sentry.acme.com",
61
- });
62
- expect(creds.SENTRY_URL).toBe("https://sentry.acme.com");
63
- });
64
- it("default sentry.io URL does not set SENTRY_HOST", () => {
65
- const creds = buildCredentialMap({ SENTRY_AUTH_TOKEN: "sntrys_abc" });
66
- const mcps = buildSkillMcpServers({
67
- referencedSkills: new Set(["sentry"]),
68
- credentials: creds,
69
- });
70
- expect(mcps.sentry).toBeDefined();
71
- expect(mcps.sentry?.env?.SENTRY_HOST).toBeUndefined();
72
- });
73
- // ── Jira: JIRA_BASE_URL user-facing → JIRA_URL canonical ──
74
- it("user setting JIRA_BASE_URL auto-wires the Jira MCP", () => {
75
- const creds = buildCredentialMap({
76
- JIRA_BASE_URL: "https://acme.atlassian.net",
77
- JIRA_EMAIL: "alice@acme.com",
78
- JIRA_API_TOKEN: "tok_abc",
79
- });
80
- expect(creds.JIRA_URL).toBe("https://acme.atlassian.net");
81
- const mcps = buildSkillMcpServers({
82
- referencedSkills: new Set(["jira"]),
83
- credentials: creds,
84
- });
85
- expect(mcps.jira).toBeDefined();
86
- expect(mcps.jira?.env?.JIRA_URL).toBe("https://acme.atlassian.net");
87
- });
88
- it("user setting JIRA_URL (canonical name) also auto-wires Jira", () => {
89
- const creds = buildCredentialMap({
90
- JIRA_URL: "https://acme.atlassian.net",
91
- JIRA_EMAIL: "alice@acme.com",
92
- JIRA_API_TOKEN: "tok_abc",
93
- });
94
- const mcps = buildSkillMcpServers({
95
- referencedSkills: new Set(["jira"]),
96
- credentials: creds,
97
- });
98
- expect(mcps.jira).toBeDefined();
99
- });
100
- it("Jira MCP is NOT wired without all 3 creds", () => {
101
- const creds = buildCredentialMap({
102
- JIRA_BASE_URL: "https://acme.atlassian.net",
103
- JIRA_EMAIL: "alice@acme.com",
104
- // missing JIRA_API_TOKEN
105
- });
106
- const mcps = buildSkillMcpServers({
107
- referencedSkills: new Set(["jira"]),
108
- credentials: creds,
109
- });
110
- expect(mcps.jira).toBeUndefined();
111
- });
112
- // ── Notion: both env-var spellings ──
113
- it("user setting NOTION_API_KEY (official Notion name) auto-wires Notion MCP", () => {
114
- const creds = buildCredentialMap({ NOTION_API_KEY: "secret_abc" });
115
- expect(creds.NOTION_API_KEY).toBe("secret_abc");
116
- const mcps = buildSkillMcpServers({
117
- referencedSkills: new Set(["notion"]),
118
- credentials: creds,
119
- });
120
- expect(mcps.notion).toBeDefined();
121
- expect(mcps.notion?.env?.NOTION_TOKEN).toBe("secret_abc");
122
- });
123
- it("user setting NOTION_TOKEN auto-wires Notion MCP", () => {
124
- const creds = buildCredentialMap({ NOTION_TOKEN: "secret_xyz" });
125
- const mcps = buildSkillMcpServers({
126
- referencedSkills: new Set(["notion"]),
127
- credentials: creds,
128
- });
129
- expect(mcps.notion?.env?.NOTION_TOKEN).toBe("secret_xyz");
130
- });
131
- // ── BetterStack token fallbacks ──
132
- it("user setting BETTERSTACK_API_TOKEN auto-wires BetterStack MCP", () => {
133
- const creds = buildCredentialMap({ BETTERSTACK_API_TOKEN: "bs_abc" });
134
- const mcps = buildSkillMcpServers({
135
- referencedSkills: new Set(["betterstack"]),
136
- credentials: creds,
137
- });
138
- expect(mcps.betterstack).toBeDefined();
139
- expect(mcps.betterstack?.headers?.Authorization).toBe("Bearer bs_abc");
140
- });
141
- it("user setting BETTERSTACK_TELEMETRY_TOKEN reaches the MCP layer", () => {
142
- const creds = buildCredentialMap({ BETTERSTACK_TELEMETRY_TOKEN: "bs_tel_abc" });
143
- const mcps = buildSkillMcpServers({
144
- referencedSkills: new Set(["betterstack"]),
145
- credentials: creds,
146
- });
147
- expect(mcps.betterstack?.headers?.Authorization).toBe("Bearer bs_tel_abc");
148
- });
149
- // ── Happy-path: all the common providers at once ──
150
- it("end-to-end: a typical SRE triage env wires every expected MCP", () => {
151
- const creds = buildCredentialMap({
152
- GITHUB_TOKEN: "ghp_abc",
153
- LINEAR_API_KEY: "lin_abc",
154
- DD_API_KEY: "dd_api",
155
- DD_APP_KEY: "dd_app",
156
- SLACK_BOT_TOKEN: "xoxb-abc",
157
- });
158
- const mcps = buildSkillMcpServers({
159
- referencedSkills: new Set(["github", "linear", "datadog", "slack"]),
160
- credentials: creds,
161
- });
162
- expect(Object.keys(mcps).sort()).toEqual(["datadog", "github", "linear", "slack"]);
163
- });
164
- it("returns empty creds for an empty env", () => {
165
- expect(buildCredentialMap({})).toEqual({});
166
- });
167
- it("ignores empty-string env values (treats them as unset)", () => {
168
- const creds = buildCredentialMap({ GITHUB_TOKEN: "", LINEAR_API_KEY: "lin_abc" });
169
- expect(creds.GITHUB_TOKEN).toBeUndefined();
170
- expect(creds.LINEAR_API_KEY).toBe("lin_abc");
171
- });
172
- });
@@ -1 +0,0 @@
1
- export {};