@desplega.ai/agent-swarm 1.94.0 → 1.96.0

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 (38) hide show
  1. package/README.md +3 -3
  2. package/openapi.json +46 -1
  3. package/package.json +4 -3
  4. package/src/be/boot-scrub-logs.ts +76 -0
  5. package/src/be/db.ts +22 -10
  6. package/src/be/migrations/094_mcp_extra_authorize_params.sql +4 -0
  7. package/src/be/modelsdev-cache.json +89422 -85636
  8. package/src/be/skill-sync.ts +4 -4
  9. package/src/be/swarm-config-guard.ts +8 -0
  10. package/src/commands/provider-credentials.ts +37 -9
  11. package/src/commands/runner.ts +28 -0
  12. package/src/http/agents.ts +1 -0
  13. package/src/http/config.ts +24 -4
  14. package/src/http/index.ts +9 -0
  15. package/src/http/mcp-oauth.ts +14 -0
  16. package/src/oauth/mcp-wrapper.ts +14 -0
  17. package/src/prompts/session-templates.ts +21 -0
  18. package/src/providers/codex-skill-resolver.ts +22 -8
  19. package/src/providers/opencode-adapter.ts +20 -2
  20. package/src/providers/pi-mono-adapter.ts +160 -21
  21. package/src/providers/types.ts +33 -0
  22. package/src/tests/bedrock-model-groups.test.ts +135 -0
  23. package/src/tests/credential-check.test.ts +538 -50
  24. package/src/tests/harness-provider-resolution.test.ts +23 -0
  25. package/src/tests/mcp-oauth-queries.test.ts +71 -1
  26. package/src/tests/mcp-oauth-wrapper.test.ts +109 -0
  27. package/src/tests/opencode-adapter.test.ts +29 -1
  28. package/src/tests/provider-command-format.test.ts +12 -0
  29. package/src/tests/secret-scrubber.test.ts +73 -1
  30. package/src/tests/skill-fs-writer.test.ts +7 -1
  31. package/src/tests/skill-sync.test.ts +15 -3
  32. package/src/tools/mcp-servers/mcp-server-create.ts +7 -0
  33. package/src/tools/mcp-servers/mcp-server-update.ts +8 -0
  34. package/src/tools/swarm-config/get-config.ts +9 -1
  35. package/src/tools/swarm-config/list-config.ts +8 -0
  36. package/src/types.ts +22 -0
  37. package/src/utils/secret-scrubber.ts +33 -12
  38. package/src/utils/skill-fs-writer.ts +11 -3
@@ -93,42 +93,63 @@ const MIN_VALUE_LENGTH = 12;
93
93
  * Order matters when one pattern is a prefix of another (e.g. `sk-ant-` must
94
94
  * match before the more general `sk-`).
95
95
  */
96
+
97
+ // Leading word boundary that also matches after JSON escape sequences (\n, \t,
98
+ // \r, etc.) where the trailing char is alphanumeric and defeats standard \b.
99
+ const TB = String.raw`(?:(?<=\\[nrtbfu0])|(?<!\w))`;
100
+
96
101
  const TOKEN_REGEXES: ReadonlyArray<{ name: string; re: RegExp }> = [
97
102
  // GitHub fine-grained PATs
98
103
  { name: "github_pat", re: /github_pat_[A-Za-z0-9_]{20,}/g },
99
104
  // GitHub classic/OAuth tokens (ghp_, gho_, ghu_, ghs_, ghr_)
100
- { name: "github_token", re: /\bgh[pousr]_[A-Za-z0-9]{20,}\b/g },
105
+ { name: "github_token", re: new RegExp(String.raw`${TB}gh[pousr]_[A-Za-z0-9]{20,}\b`, "g") },
101
106
  // GitLab personal access tokens
102
- { name: "gitlab_pat", re: /\bglpat-[A-Za-z0-9_-]{20,}\b/g },
107
+ { name: "gitlab_pat", re: new RegExp(String.raw`${TB}glpat-[A-Za-z0-9_-]{20,}\b`, "g") },
103
108
  // Anthropic API keys (must match before the generic sk- rule below)
104
- { name: "anthropic_key", re: /\bsk-ant-[A-Za-z0-9_-]{20,}\b/g },
109
+ { name: "anthropic_key", re: new RegExp(String.raw`${TB}sk-ant-[A-Za-z0-9_-]{20,}\b`, "g") },
105
110
  // OpenAI project keys
106
- { name: "openai_proj_key", re: /\bsk-proj-[A-Za-z0-9_-]{20,}\b/g },
111
+ { name: "openai_proj_key", re: new RegExp(String.raw`${TB}sk-proj-[A-Za-z0-9_-]{20,}\b`, "g") },
107
112
  // OpenRouter keys
108
- { name: "openrouter_key", re: /\bsk-or-(?:v1-)?[A-Za-z0-9_-]{20,}\b/g },
113
+ {
114
+ name: "openrouter_key",
115
+ re: new RegExp(String.raw`${TB}sk-or-(?:v1-)?[A-Za-z0-9_-]{20,}\b`, "g"),
116
+ },
109
117
  // Generic sk- legacy OpenAI keys (must come AFTER the ant/proj/or variants)
110
- { name: "sk_key", re: /\bsk-[A-Za-z0-9]{20,}\b/g },
118
+ { name: "sk_key", re: new RegExp(String.raw`${TB}sk-[A-Za-z0-9]{20,}\b`, "g") },
111
119
  // Slack tokens
112
- { name: "slack_token", re: /\bxox[baprseo]-[A-Za-z0-9-]{10,}\b/g },
120
+ { name: "slack_token", re: new RegExp(String.raw`${TB}xox[baprseo]-[A-Za-z0-9-]{10,}\b`, "g") },
113
121
  // AWS access key IDs
114
- { name: "aws_access_key", re: /\bAKIA[0-9A-Z]{16}\b/g },
122
+ { name: "aws_access_key", re: new RegExp(String.raw`${TB}AKIA[0-9A-Z]{16}\b`, "g") },
115
123
  // Google API keys
116
- { name: "google_api_key", re: /\bAIza[A-Za-z0-9_-]{35}\b/g },
124
+ { name: "google_api_key", re: new RegExp(String.raw`${TB}AIza[A-Za-z0-9_-]{35}\b`, "g") },
117
125
  // JWTs (3 dot-separated base64url segments)
118
126
  {
119
127
  name: "jwt",
120
- re: /\beyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g,
128
+ re: new RegExp(
129
+ String.raw`${TB}eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b`,
130
+ "g",
131
+ ),
121
132
  },
122
133
  // SigNoz Cloud OTLP auth header values.
123
134
  {
124
135
  name: "signoz_ingestion_key",
125
- re: /\bsignoz-ingestion-key=[A-Za-z0-9._~+/-]{20,}={0,2}\b/g,
136
+ re: new RegExp(String.raw`${TB}signoz-ingestion-key=[A-Za-z0-9._~+/-]{20,}={0,2}\b`, "g"),
137
+ },
138
+ // Linear OAuth tokens and API keys
139
+ { name: "linear_oauth", re: new RegExp(String.raw`${TB}lin_oauth_[A-Za-z0-9_-]{10,}\b`, "g") },
140
+ { name: "linear_api", re: new RegExp(String.raw`${TB}lin_api_[A-Za-z0-9_-]{10,}\b`, "g") },
141
+ // npm tokens
142
+ { name: "npm_token", re: new RegExp(String.raw`${TB}npm_[A-Za-z0-9_-]{20,}\b`, "g") },
143
+ // Jira API tokens (Atlassian cloud)
144
+ {
145
+ name: "atlassian_token",
146
+ re: new RegExp(String.raw`${TB}ATATT[A-Za-z0-9_-]{20,}\b`, "g"),
126
147
  },
127
148
  // Agent-swarm MCP user tokens (`aswt_<base62-20+>`). Schema lands in
128
149
  // migration 064; mint/revoke endpoints ship with the MCP-token plan.
129
150
  // Rule lives here now so plaintexts never leak into logs once endpoints
130
151
  // come online.
131
- { name: "mcp_token", re: /\baswt_[A-Za-z0-9]{20,}\b/g },
152
+ { name: "mcp_token", re: new RegExp(String.raw`${TB}aswt_[A-Za-z0-9]{20,}\b`, "g") },
132
153
  ];
133
154
 
134
155
  interface EnvValueEntry {
@@ -8,8 +8,8 @@
8
8
  * SkillFsEntry data from the DB then delegates here.
9
9
  * - Worker-side: refreshSkillsIfChanged (src/utils/skills-refresh.ts) which
10
10
  * fetches SkillFsEntry data over HTTP then calls writeSkillsToFilesystem
11
- * with the worker's own homedir(), writing SKILL.md files to the correct
12
- * machine instead of the API box.
11
+ * with the worker's own homedir(), writing SKILL.md files to every local
12
+ * harness tree instead of the API box.
13
13
  */
14
14
 
15
15
  import type { Dirent } from "node:fs";
@@ -32,6 +32,8 @@ export interface SkillFsEntry {
32
32
  files: { path: string; content: string; isBinary: boolean }[];
33
33
  }
34
34
 
35
+ export type SkillHarnessTarget = "claude" | "pi" | "codex" | "opencode" | "agents" | "all";
36
+
35
37
  /**
36
38
  * Marker file written into every swarm-managed skill directory. Cleanup
37
39
  * only ever removes directories that contain this marker, so unrelated
@@ -109,7 +111,7 @@ function reconcileManagedSkillFiles(skillDir: string, currentRelativeFiles: Set<
109
111
  */
110
112
  export function writeSkillsToFilesystem(
111
113
  entries: SkillFsEntry[],
112
- harnessType: "claude" | "pi" | "codex" | "all" = "all",
114
+ harnessType: SkillHarnessTarget = "all",
113
115
  home: string,
114
116
  ): SkillSyncResult {
115
117
  const errors: string[] = [];
@@ -127,6 +129,12 @@ export function writeSkillsToFilesystem(
127
129
  if (harnessType === "codex" || harnessType === "all") {
128
130
  skillDirs.push(join(home, ".codex", "skills"));
129
131
  }
132
+ if (harnessType === "opencode" || harnessType === "all") {
133
+ skillDirs.push(join(home, ".opencode", "skills"));
134
+ }
135
+ if (harnessType === "agents" || harnessType === "all") {
136
+ skillDirs.push(join(home, ".agents", "skills"));
137
+ }
130
138
 
131
139
  // Ensure base dirs exist
132
140
  for (const dir of skillDirs) {