@sweny-ai/core 0.1.78 → 0.1.79

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 (2) hide show
  1. package/dist/verify.js +54 -3
  2. package/package.json +1 -1
package/dist/verify.js CHANGED
@@ -105,22 +105,73 @@ function succeededTools(toolCalls) {
105
105
  function calledList(toolCalls) {
106
106
  return toolCalls.map((c) => c.tool).join(", ") || "none";
107
107
  }
108
+ // Tool aliases: first-party SWEny skill tool names ↔ their MCP-server equivalents.
109
+ //
110
+ // When an external MCP server is wired for the same provider a skill covers
111
+ // (e.g. the Linear HTTP MCP server alongside the `linear` skill), both sets of
112
+ // tools are presented to the agent and the agent may pick either. The calls
113
+ // are functionally equivalent — same backend, same effect — but the names
114
+ // differ, so a verify rule that lists one will fail when the agent picked the
115
+ // other. These aliases let either call satisfy the rule.
116
+ //
117
+ // Only unambiguous MCP tool names are aliased. Names that collide across
118
+ // providers (e.g. `get_issue` exists on both Linear and GitHub MCP servers)
119
+ // are deliberately omitted so a call to one provider cannot spuriously
120
+ // satisfy a rule about the other.
121
+ const TOOL_ALIAS_GROUPS = [
122
+ // Linear (official remote MCP at mcp.linear.app — upsert naming)
123
+ ["linear_search_issues", "list_issues"],
124
+ ["linear_create_issue", "save_issue"],
125
+ ["linear_update_issue", "save_issue"],
126
+ ["linear_add_comment", "save_comment"],
127
+ ["linear_list_teams", "list_teams"],
128
+ // GitHub (github.com/github/github-mcp-server)
129
+ ["github_create_issue", "create_issue"],
130
+ ["github_search_issues", "search_issues"],
131
+ ["github_add_comment", "add_issue_comment"],
132
+ ["github_create_pr", "create_pull_request"],
133
+ ];
134
+ const TOOL_ALIASES = (() => {
135
+ const map = new Map();
136
+ for (const group of TOOL_ALIAS_GROUPS) {
137
+ for (const name of group) {
138
+ let set = map.get(name);
139
+ if (!set) {
140
+ set = new Set();
141
+ map.set(name, set);
142
+ }
143
+ for (const other of group)
144
+ set.add(other);
145
+ }
146
+ }
147
+ return map;
148
+ })();
149
+ function expandAliases(name) {
150
+ return TOOL_ALIASES.get(name) ?? new Set([name]);
151
+ }
152
+ function anyAliasIn(name, set) {
153
+ for (const alias of expandAliases(name)) {
154
+ if (set.has(alias))
155
+ return true;
156
+ }
157
+ return false;
158
+ }
108
159
  export function checkAnyToolCalled(required, toolCalls) {
109
160
  const succeeded = succeededTools(toolCalls);
110
- if (required.some((t) => succeeded.has(t)))
161
+ if (required.some((t) => anyAliasIn(t, succeeded)))
111
162
  return null;
112
163
  return `any_tool_called: required one of [${required.join(", ")}] to succeed, called: [${calledList(toolCalls)}]`;
113
164
  }
114
165
  export function checkAllToolsCalled(required, toolCalls) {
115
166
  const succeeded = succeededTools(toolCalls);
116
- const missing = required.filter((t) => !succeeded.has(t));
167
+ const missing = required.filter((t) => !anyAliasIn(t, succeeded));
117
168
  if (missing.length === 0)
118
169
  return null;
119
170
  return `all_tools_called: missing successful calls to [${missing.join(", ")}], called: [${calledList(toolCalls)}]`;
120
171
  }
121
172
  export function checkNoToolCalled(forbidden, toolCalls) {
122
173
  const calledNames = new Set(toolCalls.map((c) => c.tool));
123
- const violated = forbidden.filter((t) => calledNames.has(t));
174
+ const violated = forbidden.filter((t) => anyAliasIn(t, calledNames));
124
175
  if (violated.length === 0)
125
176
  return null;
126
177
  return `no_tool_called: forbidden tools were invoked: [${violated.join(", ")}], called: [${calledList(toolCalls)}]`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sweny-ai/core",
3
- "version": "0.1.78",
3
+ "version": "0.1.79",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "sweny": "./dist/cli/main.js"