@sweny-ai/core 0.1.29 → 0.1.30

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.
@@ -65,11 +65,11 @@ describe("skills registry", () => {
65
65
  expect(validCategories).toContain(skill.category);
66
66
  }
67
67
  });
68
- it("isSkillConfigured checks env vars", () => {
68
+ it("isSkillConfigured checks required env vars", () => {
69
69
  expect(isSkillConfigured(github, { GITHUB_TOKEN: "ghp_xxx" })).toBe(true);
70
- expect(isSkillConfigured(github, {})).toBe(false);
71
- // Slack has all-optional config — needs at least one to be usable
72
- expect(isSkillConfigured(slack, {})).toBe(false);
70
+ expect(isSkillConfigured(github, {})).toBe(false); // GITHUB_TOKEN is required
71
+ // Slack has all-optional config — always configured, tools validate at call time
72
+ expect(isSkillConfigured(slack, {})).toBe(true);
73
73
  expect(isSkillConfigured(slack, { SLACK_WEBHOOK_URL: "https://hooks.slack.com/..." })).toBe(true);
74
74
  expect(isSkillConfigured(slack, { SLACK_BOT_TOKEN: "xoxb-..." })).toBe(true);
75
75
  });
@@ -391,16 +391,16 @@ describe("configuredSkills with custom skills", () => {
391
391
  }
392
392
  it("includes custom skills alongside configured built-ins", () => {
393
393
  writeSkill("my-custom", `---\nname: my-custom\ndescription: Custom\n---\nBody`);
394
- // Provide a notification webhook so at least one built-in is configured
395
- const skills = configuredSkills({ NOTIFICATION_WEBHOOK_URL: "https://example.com" }, tmpDir);
394
+ const skills = configuredSkills({}, tmpDir);
396
395
  const ids = skills.map((s) => s.id);
397
396
  expect(ids).toContain("my-custom");
397
+ // Skills with only optional config are always configured
398
398
  expect(ids).toContain("notification");
399
+ expect(ids).toContain("slack");
399
400
  });
400
401
  it("built-in skills take precedence over custom skills with same ID", () => {
401
- // notification is configured when a webhook URL is set
402
402
  writeSkill("notification", `---\nname: notification\ndescription: Custom override attempt\n---\nBody`);
403
- const skills = configuredSkills({ NOTIFICATION_WEBHOOK_URL: "https://example.com" }, tmpDir);
403
+ const skills = configuredSkills({}, tmpDir);
404
404
  const notif = skills.filter((s) => s.id === "notification");
405
405
  expect(notif).toHaveLength(1);
406
406
  // Should be the built-in (has tools), not the custom one (tools: [])
@@ -41,10 +41,9 @@ export declare function allSkills(): Map<string, Skill>;
41
41
  /**
42
42
  * Check if a skill is usable given the available environment.
43
43
  *
44
- * - All required config fields must have values.
45
- * - If a skill has env-backed config fields (even optional ones),
46
- * at least one must be set — otherwise the skill has zero credentials.
47
- * - Skills with no env-backed config are always considered configured.
44
+ * A skill is configured when all its *required* config fields are set.
45
+ * Optional fields are validated by individual tool handlers at call time,
46
+ * so missing optional config never disqualifies the skill.
48
47
  */
49
48
  export declare function isSkillConfigured(skill: Skill, env?: Record<string, string | undefined>): boolean;
50
49
  /**
@@ -106,22 +106,16 @@ export function allSkills() {
106
106
  /**
107
107
  * Check if a skill is usable given the available environment.
108
108
  *
109
- * - All required config fields must have values.
110
- * - If a skill has env-backed config fields (even optional ones),
111
- * at least one must be set — otherwise the skill has zero credentials.
112
- * - Skills with no env-backed config are always considered configured.
109
+ * A skill is configured when all its *required* config fields are set.
110
+ * Optional fields are validated by individual tool handlers at call time,
111
+ * so missing optional config never disqualifies the skill.
113
112
  */
114
113
  export function isSkillConfigured(skill, env = process.env) {
115
- const envFields = Object.values(skill.config).filter((f) => f.env);
116
- if (envFields.length === 0)
117
- return true; // no env needed
118
- // All required fields must be set
119
- for (const field of envFields) {
120
- if (field.required && !env[field.env])
114
+ for (const field of Object.values(skill.config)) {
115
+ if (field.required && field.env && !env[field.env])
121
116
  return false;
122
117
  }
123
- // At least one env-backed field must be set (handles all-optional skills like slack)
124
- return envFields.some((f) => env[f.env]);
118
+ return true;
125
119
  }
126
120
  /**
127
121
  * From all builtins + custom repo skills, return only the skills that are usable.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sweny-ai/core",
3
- "version": "0.1.29",
3
+ "version": "0.1.30",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "sweny": "./dist/cli/main.js"