@skaleagents/swarm 0.6.0 → 0.6.1

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/README.md CHANGED
@@ -127,6 +127,11 @@ to your AI client. The package stores the OAuth refresh credential locally and
127
127
  refreshes access automatically. You do not need to create or paste an API key.
128
128
  Active connections can be revoked from the web app's MCP settings page.
129
129
 
130
+ Local `review_architecture` calls validate the account and fetch public bot
131
+ hints concurrently. The public directory request carries no credential. Every
132
+ review still requires successful account validation. An anonymous directory
133
+ request may already be in flight when validation rejects a connection.
134
+
130
135
  ## Local development
131
136
 
132
137
  ```bash
@@ -182,7 +187,7 @@ Dev without build:
182
187
  "mcpServers": {
183
188
  "skaleagents": {
184
189
  "command": "npx",
185
- "args": ["-y", "@skaleagents/swarm@0.6.0"]
190
+ "args": ["-y", "@skaleagents/swarm@0.6.1"]
186
191
  }
187
192
  }
188
193
  }
@@ -205,6 +210,35 @@ Use the published package configuration above in `.mcp.json`. OAuth starts on th
205
210
  | `SKALEAGENTS_OAUTH_ENABLED` | No | Set to `false` only to disable browser OAuth. |
206
211
  | `MCP_RESOURCE_URL` | No | Hosted transport audience. Defaults to `https://skaleagents.com/mcp`; must match the API OAuth configuration. |
207
212
 
213
+ ## Steady-state tool latency probe
214
+
215
+ With an existing, authorized `SKALEAGENTS_API_TOKEN` in the environment, run
216
+ `npm run benchmark:tool`. The script builds this checkout, starts its stdio MCP
217
+ server, makes five warmup calls, then times 50 `review_architecture` calls on a
218
+ fixed synthetic application snippet. Set `BENCHMARK_WARMUP` from 0 to 20 and
219
+ `BENCHMARK_SAMPLES` from 1 to 200 to change those counts. It refuses to start
220
+ without the token and never opens an OAuth browser flow.
221
+ Set `BENCHMARK_INPUT_FILE` to an existing, non-secret application source file to
222
+ measure that source instead of the fixed snippet. Run separate samples for
223
+ different file sizes or code patterns. The output reports only the input byte
224
+ count and SHA-256 digest, not its path or contents. The supplied source must be
225
+ nonempty and at most 500,000 characters. Use the same local file and pinned
226
+ package commit when comparing runs.
227
+
228
+ Each timed call includes JSON-RPC transport, hosted API account validation,
229
+ static review, and the API bot-hint lookup. Process startup, the MCP handshake,
230
+ OAuth login or refresh, and a hosted MCP runtime are outside the timer. The
231
+ output contains aggregate p50/p95/p99/max latency, the API origin, and counts.
232
+ It also reports response-header timing for the `/api/user` and `/api/bots`
233
+ fetches, their overlap, and the remaining tool-call time after subtracting the
234
+ union of those intervals. Overlapping time is counted once.
235
+ That remainder includes response bodies, local work, and stdio overhead; it is
236
+ not a single server or network measurement. Output omits the credential,
237
+ account, and source text. A failed or unauthorized
238
+ call aborts instead of being counted as a successful sample. This short,
239
+ single-client diagnostic does not establish the platform's sub-second p95 or
240
+ monthly availability target.
241
+
208
242
  ## Auth behavior
209
243
 
210
244
  - Missing bearer override → browser OAuth starts automatically.
package/dist/review.d.ts CHANGED
@@ -16,4 +16,4 @@ export type Finding = {
16
16
  export declare function architectureFindings(content: string, focus: string): Finding[];
17
17
  export declare function literalCredential(value: string): boolean;
18
18
  export declare function externalHttp(value: string): boolean;
19
- export declare function fetchPublicBotHints(token?: string): Promise<string[]>;
19
+ export declare function fetchPublicBotHints(): Promise<string[]>;
package/dist/review.js CHANGED
@@ -168,13 +168,12 @@ export function externalHttp(value) {
168
168
  return false;
169
169
  }
170
170
  }
171
- export async function fetchPublicBotHints(token) {
171
+ export async function fetchPublicBotHints() {
172
172
  try {
173
173
  const res = await fetch(`${getApiUrl()}/api/bots`, {
174
174
  signal: AbortSignal.timeout(10_000),
175
175
  headers: {
176
176
  Accept: "application/json",
177
- ...(token ? { Authorization: `Bearer ${token}` } : {}),
178
177
  },
179
178
  });
180
179
  if (!res.ok)
package/dist/server.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { z } from "zod";
3
- import { getApiAccessToken, requireApiAuth, unauthorizedContent, } from "./auth.js";
3
+ import { requireApiAuth, unauthorizedContent } from "./auth.js";
4
4
  import { architectureFindings, fetchPublicBotHints } from "./review.js";
5
5
  import { looksLikeIac, ScanInputError } from "./iac/parse.js";
6
6
  import { filterFindings, scanIac, summarize } from "./iac/scan.js";
@@ -79,14 +79,11 @@ export function createServer(remote = false) {
79
79
  .describe("Content format: terraform, cloudformation, kubernetes, application, auto"),
80
80
  },
81
81
  }, async ({ content, focus, format, minSeverity, maxFindings }) => {
82
- let token;
82
+ const botHints = fetchPublicBotHints();
83
83
  if (!remote) {
84
84
  const auth = await requireApiAuth();
85
85
  if (!auth.ok)
86
86
  return unauthorizedContent(auth);
87
- token = (await getApiAccessToken()) ?? undefined;
88
- if (!token)
89
- return unauthorizedContent({ ok: false, reason: "oauth_failed" });
90
87
  }
91
88
  try {
92
89
  const options = { focus, minSeverity, maxFindings };
@@ -94,7 +91,7 @@ export function createServer(remote = false) {
94
91
  (format !== "auto" || looksLikeIac(content))) {
95
92
  return result({
96
93
  ...scanIac(content, { ...options, format }),
97
- botHints: await fetchPublicBotHints(token),
94
+ botHints: await botHints,
98
95
  });
99
96
  }
100
97
  const findings = filterFindings(architectureFindings(content, focus).slice(1), options);
@@ -111,7 +108,7 @@ export function createServer(remote = false) {
111
108
  limitations: [
112
109
  "Application checks are text patterns, not a language-aware or runtime analysis. Findings do not establish that code is safe.",
113
110
  ],
114
- botHints: await fetchPublicBotHints(token),
111
+ botHints: await botHints,
115
112
  });
116
113
  }
117
114
  catch (error) {
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "0.6.0";
1
+ export declare const VERSION = "0.6.1";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = "0.6.0";
1
+ export const VERSION = "0.6.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skaleagents/swarm",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -24,7 +24,8 @@
24
24
  "start": "node dist/index.js",
25
25
  "dev": "tsx src/index.ts",
26
26
  "typecheck": "tsc --noEmit",
27
- "test": "tsx --test src/*.test.ts src/iac/*.test.ts src/application/*.test.ts",
27
+ "test": "tsx --test src/*.test.ts src/iac/*.test.ts src/application/*.test.ts && npm run build && node --test scripts/*.test.mjs",
28
+ "benchmark:tool": "npm run build && node scripts/benchmark-tool-latency.mjs",
28
29
  "smoke": "tsx scripts/smoke-tools.mjs"
29
30
  },
30
31
  "engines": {