@desplega.ai/agent-swarm 1.113.0 → 1.115.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.
- package/README.md +2 -2
- package/dist/{actions-q4n7cz6e.js → actions-17ya5wde.js} +8 -9
- package/dist/{app-es4nzc71.js → app-4f718yk0.js} +6 -6
- package/dist/{assistant-0x8ey0vs.js → assistant-ah7csnjz.js} +19 -18
- package/dist/{boot-reembed-69agkhv6.js → boot-reembed-4jpxhb25.js} +6 -6
- package/dist/{boot-reembed-p0ny05t8.js → boot-reembed-qata34xa.js} +5 -5
- package/dist/{boot-scrub-logs-yybrkmvr.js → boot-scrub-logs-tv48nn3z.js} +4 -4
- package/dist/{claude-adapter-mma9a1yr.js → claude-adapter-3csn5bks.js} +3 -3
- package/dist/{claude-managed-adapter-pv2nbqy4.js → claude-managed-adapter-kysmkz89.js} +2 -2
- package/dist/cli-0pygq9r1.js +429 -0
- package/dist/{cli-hsetkkd3.js → cli-12vb0xg6.js} +33 -9
- package/dist/{cli-ncfgsqbd.js → cli-15y7qhzp.js} +262 -33
- package/dist/{cli-7ga43spr.js → cli-1yjrbg1f.js} +1 -1
- package/dist/{cli-36ymmpmp.js → cli-3samkyap.js} +2 -2
- package/dist/cli-52fg7s7x.js +269 -0
- package/dist/{cli-hjhvekf4.js → cli-65ekje01.js} +11 -8
- package/dist/{cli-h3k622d0.js → cli-6aq8xhvm.js} +90 -3
- package/dist/{cli-f3qa069v.js → cli-7xje5amz.js} +1 -1
- package/dist/cli-86fdnerz.js +405 -0
- package/dist/{cli-9cy6nc5m.js → cli-8fjwym53.js} +1 -1
- package/dist/{cli-c3frqf65.js → cli-b23axgz4.js} +3 -3
- package/dist/{cli-a0t7vapf.js → cli-bc89my0z.js} +1 -1
- package/dist/{cli-bnzbn8j8.js → cli-beea4a3y.js} +73 -24
- package/dist/{cli-q21d49ac.js → cli-bw80ck94.js} +1 -1
- package/dist/{cli-pwc5e83c.js → cli-cchksf5q.js} +12 -7
- package/dist/{cli-30bbaveh.js → cli-cmw9rzy5.js} +2 -2
- package/dist/{cli-y6mrptcn.js → cli-cnwssmsr.js} +1 -1
- package/dist/{cli-r5g6ngtn.js → cli-dcca6j8m.js} +46 -5
- package/dist/{cli-tkmm5nf9.js → cli-e61fs2hp.js} +59 -2
- package/dist/{cli-6wscj9z0.js → cli-e7306swv.js} +14 -14
- package/dist/{cli-dcfyyh3t.js → cli-ftyf58xj.js} +2 -2
- package/dist/{cli-4xyj9jtq.js → cli-hrhye2rm.js} +1062 -478
- package/dist/cli-jkhwmmgg.js +136 -0
- package/dist/{cli-y4ycrnjc.js → cli-k3y4z3h5.js} +1 -1
- package/dist/{cli-6xd0bvf8.js → cli-ma04faw5.js} +1 -1
- package/dist/{cli-2fc97xm5.js → cli-mnbgv3w7.js} +4 -4
- package/dist/{cli-trmapn9k.js → cli-pet3aev6.js} +95 -10
- package/dist/{cli-z46pnksz.js → cli-q1rx7g0d.js} +175 -28
- package/dist/{cli-qwgtacd6.js → cli-r9f6ngrf.js} +1244 -336
- package/dist/{cli-gtkqc144.js → cli-shvaxw27.js} +13 -7
- package/dist/{cli-ywez6yps.js → cli-sq7f72d6.js} +1 -1
- package/dist/cli-t0vqevnm.js +393 -0
- package/dist/{cli-tbw13sx8.js → cli-tece6zgm.js} +1 -1
- package/dist/{cli-bgvskydy.js → cli-tffvrh6j.js} +1 -1
- package/dist/cli-wh91zby6.js +187222 -0
- package/dist/{cli-anrj584m.js → cli-xz9aq0rf.js} +1 -1
- package/dist/{cli-mq580e06.js → cli-zsrdty74.js} +18 -18
- package/dist/cli.js +32 -15
- package/dist/{codex-adapter-5cmy858w.js → codex-adapter-de3w0nch.js} +10 -10
- package/dist/{codex-session-runner-46q8mrba.js → codex-session-runner-bnw8cysk.js} +10 -10
- package/dist/{commands-z5dbwta3.js → commands-hch4e2k1.js} +4 -4
- package/dist/{db-bbgahh4z.js → db-p3h2j06x.js} +14 -4
- package/dist/{handlers-6b44317z.js → handlers-9er4zx9q.js} +17 -31
- package/dist/{hook-sbp5fmps.js → hook-4axs756z.js} +7 -7
- package/dist/{http-2xz43gz3.js → http-809fvtz2.js} +1934 -886
- package/dist/{index-wz1ea15p.js → index-2dgfj9av.js} +3 -3
- package/dist/{index-nhat35em.js → index-47em3d2n.js} +14 -11
- package/dist/{index-5ghxn8s6.js → index-9fqaktjr.js} +12 -9
- package/dist/{index-0gzmqj4k.js → index-9ht8gr56.js} +13 -10
- package/dist/{index-vfedgdw6.js → index-rm85cfdx.js} +368 -40
- package/dist/{index-ykvs43z4.js → index-t2snazez.js} +4 -4
- package/dist/{keepalive-62gfj91d.js → keepalive-3cps6e3e.js} +7 -6
- package/dist/{lead-ag0akn0v.js → lead-fkk95wgq.js} +36 -32
- package/dist/{maintenance-xxrrzk5x.js → maintenance-fweqh0yj.js} +6 -6
- package/dist/{mistral-conversations-26yrnbf1.js → mistral-conversations-7gqnz2wt.js} +7 -7
- package/dist/oauth-refresh-sweep-sycqtbph.js +114 -0
- package/dist/{onboard-64zyfcbs.js → onboard-cy0rkgvx.js} +2 -2
- package/dist/{opencode-adapter-mqsxr170.js → opencode-adapter-p6bxnbm4.js} +2 -2
- package/dist/{otel-zjd9zaxs.js → otel-g299k41b.js} +2 -2
- package/dist/{otel-impl-b86qseaa.js → otel-impl-wbns8hf7.js} +1 -1
- package/dist/{pi-mono-adapter-kxjxpfgy.js → pi-mono-adapter-05sck1ds.js} +17 -109
- package/dist/{pricing-refresh-cgtkffpa.js → pricing-refresh-0hvazmkf.js} +6 -6
- package/dist/rbac-roles-kfesjy9y.js +28 -0
- package/dist/rbac-roles-mwcwhbxc.js +283 -0
- package/dist/{seed-pricing-1r1y1xkq.js → seed-pricing-h2kdq4cq.js} +5 -5
- package/dist/{setup-mkcgkjf7.js → setup-8506q97w.js} +2 -2
- package/dist/{worker-351sze63.js → worker-4r5c6zyb.js} +36 -32
- package/openapi.json +1327 -20
- package/package.json +3 -3
- package/src/agentmail/handlers.ts +16 -6
- package/src/agentmail/templates.ts +25 -5
- package/src/be/audit-user.ts +28 -4
- package/src/be/db-queries/oauth.ts +42 -0
- package/src/be/db.ts +314 -28
- package/src/be/identity.ts +79 -0
- package/src/be/mcp-proxy.ts +132 -0
- package/src/be/migrations/109_rbac_roles.sql +79 -0
- package/src/be/migrations/111_oauth_credential_bindings.sql +6 -0
- package/src/be/migrations/112_script_connections_graphql.sql +96 -0
- package/src/be/migrations/113_task_routing_affinity.sql +9 -0
- package/src/be/migrations/114_backfill_gpt_5_6_pricing.sql +15 -0
- package/src/be/modelsdev-cache.json +135 -0
- package/src/be/oauth-credential-bindings.ts +35 -0
- package/src/be/oauth-refresh-sweep.ts +159 -0
- package/src/be/rbac-audit.ts +52 -13
- package/src/be/rbac-roles.ts +424 -0
- package/src/be/script-connections.ts +459 -40
- package/src/be/script-credential-broker.ts +29 -3
- package/src/be/scripts/typecheck.ts +51 -7
- package/src/be/seed-scripts/catalog/catalog-report.inline.ts +325 -24
- package/src/be/seed-scripts/catalog/catalog-report.ts +325 -24
- package/src/be/users.ts +24 -0
- package/src/cli.tsx +17 -0
- package/src/github/handlers.ts +10 -9
- package/src/github/templates.ts +45 -9
- package/src/gitlab/handlers.ts +20 -8
- package/src/gitlab/templates.ts +18 -6
- package/src/heartbeat/heartbeat.ts +143 -21
- package/src/http/all-routes.ts +3 -0
- package/src/http/approval-requests.ts +12 -0
- package/src/http/config.ts +44 -10
- package/src/http/core.ts +30 -3
- package/src/http/favorites.ts +1 -5
- package/src/http/index.ts +25 -1
- package/src/http/mcp-oauth.ts +2 -0
- package/src/http/mcp-servers.ts +44 -3
- package/src/http/oauth-generic.ts +105 -0
- package/src/http/poll.ts +20 -3
- package/src/http/script-connection-proxy.ts +116 -0
- package/src/http/script-connections.ts +1657 -0
- package/src/http/scripts.ts +27 -7
- package/src/http/skills.ts +11 -0
- package/src/http/tasks.ts +27 -13
- package/src/http/x.ts +6 -2
- package/src/integrations/kapso/inbound.ts +23 -6
- package/src/jira/sync.ts +111 -17
- package/src/jira/templates.ts +10 -2
- package/src/mcp-client/http-client.ts +194 -0
- package/src/oauth/app-validation.ts +16 -0
- package/src/oauth/ensure-token.ts +69 -14
- package/src/oauth/mcp-wrapper.ts +15 -0
- package/src/oauth/wrapper.ts +48 -20
- package/src/prompts/session-templates.ts +3 -3
- package/src/providers/codex-models.ts +100 -30
- package/src/providers/modelsdev-reasoning.json +51 -0
- package/src/providers/pi-mono-mcp-client.ts +2 -133
- package/src/providers/reasoning-effort.ts +11 -5
- package/src/rbac/admission.ts +68 -0
- package/src/rbac/index.ts +2 -0
- package/src/rbac/legacy-policy.ts +12 -0
- package/src/rbac/permissions.ts +48 -0
- package/src/scheduler/scheduler.ts +9 -1
- package/src/scripts-runtime/api-client.ts +151 -19
- package/src/scripts-runtime/api-types.ts +38 -6
- package/src/scripts-runtime/credential-broker/default-bindings.ts +1 -0
- package/src/scripts-runtime/credential-broker/types.ts +8 -0
- package/src/scripts-runtime/ctx.ts +11 -1
- package/src/scripts-runtime/eval-harness.ts +5 -1
- package/src/scripts-runtime/executors/types.ts +2 -1
- package/src/scripts-runtime/loader.ts +3 -1
- package/src/scripts-runtime/mcp-client.ts +87 -0
- package/src/scripts-runtime/sdk-allowlist.ts +1 -0
- package/src/scripts-runtime/types/stdlib.d.ts +6 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +19 -0
- package/src/server-user.ts +114 -59
- package/src/server.ts +12 -0
- package/src/slack/assistant.ts +14 -6
- package/src/slack/enrich.ts +17 -0
- package/src/slack/handlers.ts +8 -22
- package/src/slack/responses.ts +91 -1
- package/src/slack/thread-buffer.ts +6 -3
- package/src/slack/watcher.ts +9 -6
- package/src/tasks/worker-follow-up.ts +100 -3
- package/src/tests/agentmail-handlers.test.ts +32 -3
- package/src/tests/approval-requests.test.ts +61 -0
- package/src/tests/audit-user.test.ts +47 -1
- package/src/tests/codex-adapter.test.ts +46 -23
- package/src/tests/credential-broker.test.ts +5 -2
- package/src/tests/delete-page-tool.test.ts +197 -0
- package/src/tests/github-handlers.test.ts +28 -2
- package/src/tests/gitlab-handlers.test.ts +125 -0
- package/src/tests/heartbeat.test.ts +48 -3
- package/src/tests/identity.test.ts +117 -0
- package/src/tests/jira-sync.test.ts +99 -1
- package/src/tests/kapso-inbound.test.ts +7 -0
- package/src/tests/mcp-tools-user.test.ts +60 -6
- package/src/tests/model-control.test.ts +8 -2
- package/src/tests/oauth-credential-bindings.test.ts +490 -0
- package/src/tests/oauth-refresh-sweep.test.ts +160 -0
- package/src/tests/pool-affinity.test.ts +401 -0
- package/src/tests/prompt-template-remaining.test.ts +2 -2
- package/src/tests/rbac-admission-e2e.test.ts +386 -0
- package/src/tests/rbac-admission.test.ts +492 -0
- package/src/tests/rbac-e2e-helpers.ts +3 -0
- package/src/tests/rbac-engine.test.ts +50 -0
- package/src/tests/rbac-mcp-admission-e2e.test.ts +362 -0
- package/src/tests/rbac-roles.test.ts +328 -0
- package/src/tests/reasoning-effort.test.ts +15 -2
- package/src/tests/schedule-target-type.test.ts +50 -0
- package/src/tests/scheduled-tasks.test.ts +40 -0
- package/src/tests/script-apis-mcp.test.ts +37 -13
- package/src/tests/script-connections-http.test.ts +1158 -0
- package/src/tests/script-connections-mcp.test.ts +894 -0
- package/src/tests/script-connections.test.ts +754 -6
- package/src/tests/scripts-external-api.test.ts +49 -1
- package/src/tests/scripts-runtime-secret-egress.test.ts +1 -0
- package/src/tests/scripts-runtime.test.ts +291 -0
- package/src/tests/seed-scripts.test.ts +36 -0
- package/src/tests/slack-identity-resolution.test.ts +37 -3
- package/src/tests/slack-inline-output.test.ts +65 -0
- package/src/tests/slack-thread-buffer.test.ts +28 -0
- package/src/tests/tool-annotations.test.ts +1 -0
- package/src/tests/user-token-rest-auth.test.ts +140 -1
- package/src/tests/workflow-swarm-script.test.ts +44 -0
- package/src/tests/workflow-triggers-v2.test.ts +300 -1
- package/src/tools/credential-bindings/tool.ts +277 -18
- package/src/tools/delete-page.ts +145 -0
- package/src/tools/mcp-servers/mcp-server-delete.ts +7 -4
- package/src/tools/request-human-input.ts +2 -0
- package/src/tools/resolve-user.ts +77 -27
- package/src/tools/script-apis.ts +62 -3
- package/src/tools/script-connections/tool.ts +275 -31
- package/src/tools/send-task.ts +15 -1
- package/src/tools/task-action.ts +34 -2
- package/src/tools/templates.ts +53 -1
- package/src/tools/tool-config.ts +2 -1
- package/src/tools/utils.ts +2 -0
- package/src/tools/workflows/create-workflow.ts +8 -1
- package/src/tools/workflows/update-workflow.ts +11 -2
- package/src/types.ts +90 -11
- package/src/utils/scoped-resource.ts +25 -0
- package/src/workflows/executors/human-in-the-loop.ts +1 -0
- package/src/workflows/executors/swarm-script.ts +7 -1
- package/src/workflows/triggers.ts +146 -18
- package/templates/skills/swarm-scripts/content.md +33 -8
- package/dist/cli-bgef578c.js +0 -771
- package/dist/cli-c9mtm09b.js +0 -43
- package/dist/cli-ceewqajw.js +0 -1698
- package/dist/{anthropic-messages-8nc6r2dw.js → anthropic-messages-kq3pjhbp.js} +6 -6
- package/dist/{azure-openai-responses-6yfzw3qw.js → azure-openai-responses-gm1ejtmn.js} +7 -7
- package/dist/{cli-vbraamxr.js → cli-6b4wwmm8.js} +9 -9
- package/dist/{cli-2r7s8jhp.js → cli-sznberje.js} +3 -3
- package/dist/{google-generative-ai-vfq6ymz9.js → google-generative-ai-hyrra2jm.js} +3 -3
- package/dist/{google-vertex-mj5y5rfj.js → google-vertex-8bs2pzgn.js} +3 -3
- package/dist/{openai-codex-responses-8h6kvfv8.js → openai-codex-responses-3nkvje79.js} +4 -4
- package/dist/{openai-completions-x6kjnqjd.js → openai-completions-0asftkwg.js} +11 -11
- package/dist/{openai-responses-7jwyz3ds.js → openai-responses-pmatek45.js} +10 -10
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
ScriptApiConnectionDescriptor,
|
|
3
|
+
ScriptApiCredentialDescriptor,
|
|
3
4
|
ScriptApiOperationDescriptor,
|
|
4
5
|
ScriptApiRegistryClient,
|
|
5
6
|
} from "./api-types";
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
type FetchResponse = Awaited<ReturnType<typeof fetch>>;
|
|
9
|
+
type TextResponse = {
|
|
10
|
+
headers: { get(name: string): string | null };
|
|
11
|
+
text(): Promise<string>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type ScriptApiRawResult = {
|
|
15
|
+
ok: boolean;
|
|
16
|
+
status: number;
|
|
17
|
+
statusText: string;
|
|
18
|
+
headers: Record<string, string>;
|
|
19
|
+
url: string;
|
|
20
|
+
response: FetchResponse;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type ScriptApiError = Error & {
|
|
24
|
+
status?: number;
|
|
25
|
+
statusText?: string;
|
|
26
|
+
body?: unknown;
|
|
27
|
+
response?: FetchResponse;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function applyTemplate(template: string): [string, string] | null {
|
|
8
31
|
const idx = template.indexOf("=");
|
|
9
32
|
if (idx >= 0) return [template.slice(0, idx), template.slice(idx + 1)];
|
|
10
33
|
const colon = template.indexOf(":");
|
|
@@ -12,6 +35,22 @@ function applyTemplate(template: string, _placeholder: string): [string, string]
|
|
|
12
35
|
return null;
|
|
13
36
|
}
|
|
14
37
|
|
|
38
|
+
function applyCredential(
|
|
39
|
+
credential: ScriptApiCredentialDescriptor | null,
|
|
40
|
+
url: URL,
|
|
41
|
+
headers: Headers,
|
|
42
|
+
) {
|
|
43
|
+
if (!credential) return;
|
|
44
|
+
if (credential.headerTemplate) {
|
|
45
|
+
const parsed = applyTemplate(credential.headerTemplate);
|
|
46
|
+
if (parsed) headers.set(parsed[0], parsed[1]);
|
|
47
|
+
}
|
|
48
|
+
if (credential.queryTemplate) {
|
|
49
|
+
const parsed = applyTemplate(credential.queryTemplate);
|
|
50
|
+
if (parsed) url.searchParams.set(parsed[0], parsed[1]);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
15
54
|
function operationUrl(
|
|
16
55
|
baseUrl: string,
|
|
17
56
|
operation: ScriptApiOperationDescriptor,
|
|
@@ -28,7 +67,9 @@ function operationUrl(
|
|
|
28
67
|
throw new Error(`Missing path parameter ${param.name}`);
|
|
29
68
|
path = path.replace(`{${param.name}}`, encodeURIComponent(String(value ?? "")));
|
|
30
69
|
}
|
|
31
|
-
|
|
70
|
+
// Spec paths are absolute ("/store/inventory"); resolve them relative to the
|
|
71
|
+
// base URL so a base path prefix like "/api/v3" is preserved.
|
|
72
|
+
const url = new URL(path.replace(/^\/+/, ""), baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
|
|
32
73
|
const queryArgs = (args.query && typeof args.query === "object" ? args.query : {}) as Record<
|
|
33
74
|
string,
|
|
34
75
|
unknown
|
|
@@ -44,14 +85,113 @@ function operationUrl(
|
|
|
44
85
|
return url;
|
|
45
86
|
}
|
|
46
87
|
|
|
88
|
+
function graphqlErrorMessage(errors: unknown): string {
|
|
89
|
+
if (!Array.isArray(errors)) return JSON.stringify(errors);
|
|
90
|
+
return errors
|
|
91
|
+
.map((error) => {
|
|
92
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
93
|
+
return String((error as { message: unknown }).message);
|
|
94
|
+
}
|
|
95
|
+
return JSON.stringify(error);
|
|
96
|
+
})
|
|
97
|
+
.join("; ");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function isRawOptions(value: unknown): value is { raw: true } {
|
|
101
|
+
return Boolean(value && typeof value === "object" && (value as { raw?: unknown }).raw === true);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function headersRecord(headers: Headers): Record<string, string> {
|
|
105
|
+
return Object.fromEntries(headers.entries());
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function rawResult(response: FetchResponse): ScriptApiRawResult {
|
|
109
|
+
return {
|
|
110
|
+
ok: response.ok,
|
|
111
|
+
status: response.status,
|
|
112
|
+
statusText: response.statusText,
|
|
113
|
+
headers: headersRecord(response.headers),
|
|
114
|
+
url: response.url,
|
|
115
|
+
response,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function parseResponseBody(response: TextResponse): Promise<unknown> {
|
|
120
|
+
const text = await response.text();
|
|
121
|
+
if (!text) return "";
|
|
122
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
123
|
+
if (contentType.includes("application/json")) {
|
|
124
|
+
try {
|
|
125
|
+
return JSON.parse(text);
|
|
126
|
+
} catch {
|
|
127
|
+
return text;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return text;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function throwApiResponseError(
|
|
134
|
+
slug: string,
|
|
135
|
+
operationName: string,
|
|
136
|
+
response: FetchResponse,
|
|
137
|
+
): Promise<never> {
|
|
138
|
+
const error = new Error(
|
|
139
|
+
`ctx.api.${slug}.${operationName} failed with ${response.status}`,
|
|
140
|
+
) as ScriptApiError;
|
|
141
|
+
error.status = response.status;
|
|
142
|
+
error.statusText = response.statusText;
|
|
143
|
+
error.response = response;
|
|
144
|
+
try {
|
|
145
|
+
error.body = await parseResponseBody(response.clone());
|
|
146
|
+
} catch {
|
|
147
|
+
error.body = undefined;
|
|
148
|
+
}
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
|
|
47
152
|
export function createApiRegistryClient(
|
|
48
153
|
descriptors: ScriptApiConnectionDescriptor[] = [],
|
|
154
|
+
options: { fetch?: typeof fetch } = {},
|
|
49
155
|
): ScriptApiRegistryClient {
|
|
156
|
+
const fetchImpl = options.fetch ?? fetch;
|
|
50
157
|
const registry: ScriptApiRegistryClient = {};
|
|
51
158
|
for (const descriptor of descriptors) {
|
|
52
159
|
const client: ScriptApiRegistryClient[string] = {};
|
|
160
|
+
if (descriptor.kind === "graphql") {
|
|
161
|
+
client.graphql = async (query, variables) => {
|
|
162
|
+
if (typeof query !== "string") {
|
|
163
|
+
throw new Error(`ctx.api.${descriptor.slug}.graphql query must be a string`);
|
|
164
|
+
}
|
|
165
|
+
const url = new URL(descriptor.baseUrl);
|
|
166
|
+
const headers = new Headers({ "content-type": "application/json" });
|
|
167
|
+
applyCredential(descriptor.credential, url, headers);
|
|
168
|
+
const response = await fetchImpl(url, {
|
|
169
|
+
method: "POST",
|
|
170
|
+
headers,
|
|
171
|
+
body: JSON.stringify({ query, variables }),
|
|
172
|
+
});
|
|
173
|
+
if (!response.ok) {
|
|
174
|
+
throw new Error(`ctx.api.${descriptor.slug}.graphql failed with ${response.status}`);
|
|
175
|
+
}
|
|
176
|
+
const body = (await response.json()) as unknown;
|
|
177
|
+
if (body && typeof body === "object") {
|
|
178
|
+
const record = body as { data?: unknown; errors?: unknown };
|
|
179
|
+
if (Array.isArray(record.errors) && !("data" in record)) {
|
|
180
|
+
throw new Error(
|
|
181
|
+
`ctx.api.${descriptor.slug}.graphql failed: ${graphqlErrorMessage(record.errors)}`,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
if ("data" in record) return record.data;
|
|
185
|
+
}
|
|
186
|
+
return body;
|
|
187
|
+
};
|
|
188
|
+
registry[descriptor.slug] = client;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
|
|
53
192
|
for (const operation of descriptor.operations) {
|
|
54
|
-
client[operation.name] = async (rawArgs = {}) => {
|
|
193
|
+
client[operation.name] = async (rawArgs = {}, options?: unknown) => {
|
|
194
|
+
const raw = isRawOptions(options);
|
|
55
195
|
const args = rawArgs as Record<string, unknown>;
|
|
56
196
|
const url = operationUrl(descriptor.baseUrl, operation, args);
|
|
57
197
|
const headers = new Headers();
|
|
@@ -67,28 +207,20 @@ export function createApiRegistryClient(
|
|
|
67
207
|
headers.set(param.name, String(value));
|
|
68
208
|
}
|
|
69
209
|
|
|
70
|
-
|
|
71
|
-
? `[REDACTED:${descriptor.credential.configKey}]`
|
|
72
|
-
: null;
|
|
73
|
-
if (placeholder && descriptor.credential?.headerTemplate) {
|
|
74
|
-
const parsed = applyTemplate(descriptor.credential.headerTemplate, placeholder);
|
|
75
|
-
if (parsed) headers.set(parsed[0], parsed[1]);
|
|
76
|
-
}
|
|
77
|
-
if (placeholder && descriptor.credential?.queryTemplate) {
|
|
78
|
-
const parsed = applyTemplate(descriptor.credential.queryTemplate, placeholder);
|
|
79
|
-
if (parsed) url.searchParams.set(parsed[0], parsed[1]);
|
|
80
|
-
}
|
|
210
|
+
applyCredential(descriptor.credential, url, headers);
|
|
81
211
|
|
|
82
212
|
const init: RequestInit = { method: operation.method, headers };
|
|
83
|
-
|
|
213
|
+
// Guard against stored runtimes generated before hasBody excluded
|
|
214
|
+
// GET/HEAD — fetch() throws on GET/HEAD requests with a body.
|
|
215
|
+
const methodAllowsBody = !["GET", "HEAD"].includes(operation.method.toUpperCase());
|
|
216
|
+
if (operation.hasBody && methodAllowsBody) {
|
|
84
217
|
headers.set("content-type", headers.get("content-type") ?? "application/json");
|
|
85
218
|
init.body = JSON.stringify(args.body ?? null);
|
|
86
219
|
}
|
|
87
|
-
const response = await
|
|
220
|
+
const response = await fetchImpl(url, init);
|
|
221
|
+
if (raw) return rawResult(response);
|
|
88
222
|
if (!response.ok) {
|
|
89
|
-
|
|
90
|
-
`ctx.api.${descriptor.slug}.${operation.name} failed with ${response.status}`,
|
|
91
|
-
);
|
|
223
|
+
await throwApiResponseError(descriptor.slug, operation.name, response);
|
|
92
224
|
}
|
|
93
225
|
const contentType = response.headers.get("content-type") ?? "";
|
|
94
226
|
return contentType.includes("application/json") ? response.json() : response.text();
|
|
@@ -28,18 +28,50 @@ export type ScriptApiOperationDescriptor = {
|
|
|
28
28
|
responseType: string;
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
export type
|
|
31
|
+
export type ScriptApiCredentialDescriptor = {
|
|
32
|
+
configKey: string;
|
|
33
|
+
headerTemplate?: string;
|
|
34
|
+
queryTemplate?: string;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type ScriptOpenApiConnectionDescriptor = {
|
|
32
38
|
slug: string;
|
|
39
|
+
kind?: "openapi";
|
|
33
40
|
baseUrl: string;
|
|
34
|
-
credential:
|
|
35
|
-
configKey: string;
|
|
36
|
-
headerTemplate?: string;
|
|
37
|
-
queryTemplate?: string;
|
|
38
|
-
} | null;
|
|
41
|
+
credential: ScriptApiCredentialDescriptor | null;
|
|
39
42
|
operations: ScriptApiOperationDescriptor[];
|
|
40
43
|
};
|
|
41
44
|
|
|
45
|
+
export type ScriptGraphqlConnectionDescriptor = {
|
|
46
|
+
slug: string;
|
|
47
|
+
kind: "graphql";
|
|
48
|
+
baseUrl: string;
|
|
49
|
+
credential: ScriptApiCredentialDescriptor | null;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type ScriptApiConnectionDescriptor =
|
|
53
|
+
| ScriptOpenApiConnectionDescriptor
|
|
54
|
+
| ScriptGraphqlConnectionDescriptor;
|
|
55
|
+
|
|
56
|
+
export type ScriptMcpToolDescriptor = {
|
|
57
|
+
name: string;
|
|
58
|
+
description?: string;
|
|
59
|
+
inputSchema: ScriptApiJsonSchema;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export type ScriptMcpConnectionDescriptor = {
|
|
63
|
+
slug: string;
|
|
64
|
+
kind: "mcp";
|
|
65
|
+
connectionId: string;
|
|
66
|
+
tools: ScriptMcpToolDescriptor[];
|
|
67
|
+
};
|
|
68
|
+
|
|
42
69
|
export type ScriptApiRegistryClient = Record<
|
|
70
|
+
string,
|
|
71
|
+
Record<string, (...args: unknown[]) => Promise<unknown>>
|
|
72
|
+
>;
|
|
73
|
+
|
|
74
|
+
export type ScriptMcpRegistryClient = Record<
|
|
43
75
|
string,
|
|
44
76
|
Record<string, (args?: Record<string, unknown>) => Promise<unknown>>
|
|
45
77
|
>;
|
|
@@ -5,6 +5,7 @@ export const CREDENTIAL_BINDINGS_CONFIG_KEY = "SCRIPT_CREDENTIAL_BINDINGS";
|
|
|
5
5
|
export const REDACTED_PLACEHOLDER_PREFIX = "[REDACTED:";
|
|
6
6
|
|
|
7
7
|
export const CredentialBindingScopeSchema = z.enum(["global", "agent", "repo"]);
|
|
8
|
+
export const CredentialBindingAuthKindSchema = z.enum(["config", "oauth"]);
|
|
8
9
|
|
|
9
10
|
export const CredentialBindingSchema = z
|
|
10
11
|
.object({
|
|
@@ -15,9 +16,15 @@ export const CredentialBindingSchema = z
|
|
|
15
16
|
scope: CredentialBindingScopeSchema.default("global"),
|
|
16
17
|
scopeId: z.string().nullable().optional(),
|
|
17
18
|
active: z.boolean().default(true),
|
|
19
|
+
authKind: CredentialBindingAuthKindSchema.default("config"),
|
|
20
|
+
oauthProvider: z.string().min(1).max(255).optional(),
|
|
18
21
|
})
|
|
19
22
|
.refine((binding) => binding.headerTemplate || binding.queryTemplate, {
|
|
20
23
|
message: "At least one of headerTemplate or queryTemplate is required.",
|
|
24
|
+
})
|
|
25
|
+
.refine((binding) => binding.authKind !== "oauth" || !!binding.oauthProvider, {
|
|
26
|
+
message: "oauthProvider is required when authKind is oauth.",
|
|
27
|
+
path: ["oauthProvider"],
|
|
21
28
|
});
|
|
22
29
|
|
|
23
30
|
export const CredentialBindingsDocumentSchema = z.union([
|
|
@@ -26,6 +33,7 @@ export const CredentialBindingsDocumentSchema = z.union([
|
|
|
26
33
|
]);
|
|
27
34
|
|
|
28
35
|
export type CredentialBindingScope = z.infer<typeof CredentialBindingScopeSchema>;
|
|
36
|
+
export type CredentialBindingAuthKind = z.infer<typeof CredentialBindingAuthKindSchema>;
|
|
29
37
|
export type CredentialBinding = z.infer<typeof CredentialBindingSchema>;
|
|
30
38
|
|
|
31
39
|
export type ResolvedCredentialBinding = CredentialBinding & {
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { createApiRegistryClient } from "./api-client";
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
ScriptApiConnectionDescriptor,
|
|
4
|
+
ScriptApiRegistryClient,
|
|
5
|
+
ScriptMcpConnectionDescriptor,
|
|
6
|
+
ScriptMcpRegistryClient,
|
|
7
|
+
} from "./api-types";
|
|
8
|
+
import { createMcpRegistryClient } from "./mcp-client";
|
|
3
9
|
import { stdlib } from "./stdlib";
|
|
4
10
|
import type { SwarmConfig } from "./swarm-config";
|
|
5
11
|
import { createSwarmSdk } from "./swarm-sdk";
|
|
@@ -7,6 +13,7 @@ import { createSwarmSdk } from "./swarm-sdk";
|
|
|
7
13
|
export type RuntimeCtx = {
|
|
8
14
|
swarm: Record<string, unknown> & { config: SwarmConfig };
|
|
9
15
|
api: ScriptApiRegistryClient;
|
|
16
|
+
mcp: ScriptMcpRegistryClient;
|
|
10
17
|
stdlib: typeof stdlib;
|
|
11
18
|
logger: {
|
|
12
19
|
log: (...args: unknown[]) => void;
|
|
@@ -18,15 +25,18 @@ export type RuntimeCtx = {
|
|
|
18
25
|
export function buildCtx({
|
|
19
26
|
swarmConfig,
|
|
20
27
|
apiConnections,
|
|
28
|
+
mcpConnections,
|
|
21
29
|
}: {
|
|
22
30
|
swarmConfig: SwarmConfig;
|
|
23
31
|
apiConnections?: ScriptApiConnectionDescriptor[];
|
|
32
|
+
mcpConnections?: ScriptMcpConnectionDescriptor[];
|
|
24
33
|
}): RuntimeCtx {
|
|
25
34
|
const swarm = createSwarmSdk(swarmConfig) as Record<string, unknown> & { config: SwarmConfig };
|
|
26
35
|
swarm.config = swarmConfig;
|
|
27
36
|
return {
|
|
28
37
|
swarm,
|
|
29
38
|
api: createApiRegistryClient(apiConnections),
|
|
39
|
+
mcp: createMcpRegistryClient(mcpConnections, swarmConfig),
|
|
30
40
|
stdlib,
|
|
31
41
|
logger: console,
|
|
32
42
|
};
|
|
@@ -92,7 +92,11 @@ try {
|
|
|
92
92
|
const rawArgs = JSON.parse(await Bun.file(requiredEnv("SWARM_SCRIPT_ARGS_FILE")).text());
|
|
93
93
|
// Accept both shapes: callers may pass an already-serialized JSON string.
|
|
94
94
|
const parsedArgs = typeof rawArgs === "string" ? JSON.parse(rawArgs) : rawArgs;
|
|
95
|
-
const ctx = buildCtx({
|
|
95
|
+
const ctx = buildCtx({
|
|
96
|
+
swarmConfig,
|
|
97
|
+
apiConnections: payload.apiConnections,
|
|
98
|
+
mcpConnections: payload.mcpConnections,
|
|
99
|
+
});
|
|
96
100
|
|
|
97
101
|
const sourceText = await Bun.file(requiredEnv("SWARM_SCRIPT_SOURCE_FILE")).text();
|
|
98
102
|
await Bun.write(userModulePath, sourceText);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ScriptApiConnectionDescriptor } from "../api-types";
|
|
1
|
+
import type { ScriptApiConnectionDescriptor, ScriptMcpConnectionDescriptor } from "../api-types";
|
|
2
2
|
import type { ResolvedCredentialBinding } from "../credential-broker";
|
|
3
3
|
|
|
4
4
|
export type ScriptFsMode = "none" | "workspace-rw";
|
|
@@ -14,6 +14,7 @@ export type SwarmConfigPayload = {
|
|
|
14
14
|
user: Record<string, { value: string; isSecret: boolean }>;
|
|
15
15
|
egressSecrets?: EgressSecretEntry[];
|
|
16
16
|
apiConnections?: ScriptApiConnectionDescriptor[];
|
|
17
|
+
mcpConnections?: ScriptMcpConnectionDescriptor[];
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
export type ScriptResourcePolicy = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getApiKey } from "../utils/api-key";
|
|
2
2
|
import { scrubObject, scrubSecrets } from "../utils/secret-scrubber";
|
|
3
|
-
import type { ScriptApiConnectionDescriptor } from "./api-types";
|
|
3
|
+
import type { ScriptApiConnectionDescriptor, ScriptMcpConnectionDescriptor } from "./api-types";
|
|
4
4
|
import { buildEgressSecrets } from "./egress-secrets";
|
|
5
5
|
import { getScriptExecutor } from "./executors/registry";
|
|
6
6
|
import {
|
|
@@ -25,6 +25,7 @@ export type RunScriptInput = {
|
|
|
25
25
|
userConfig?: Record<string, { value: string; isSecret: boolean }>;
|
|
26
26
|
egressSecrets?: EgressSecretEntry[];
|
|
27
27
|
apiConnections?: ScriptApiConnectionDescriptor[];
|
|
28
|
+
mcpConnections?: ScriptMcpConnectionDescriptor[];
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
export type RunScriptOutput = Omit<ExecutorOutput, "result" | "stdout" | "stderr"> & {
|
|
@@ -51,6 +52,7 @@ function buildConfigPayload(input: RunScriptInput): SwarmConfigPayload {
|
|
|
51
52
|
user: input.userConfig ?? {},
|
|
52
53
|
egressSecrets: input.egressSecrets ?? buildEgressSecrets(),
|
|
53
54
|
apiConnections: input.apiConnections ?? [],
|
|
55
|
+
mcpConnections: input.mcpConnections ?? [],
|
|
54
56
|
};
|
|
55
57
|
}
|
|
56
58
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { ScriptMcpConnectionDescriptor, ScriptMcpRegistryClient } from "./api-types";
|
|
2
|
+
import { Redacted } from "./redacted";
|
|
3
|
+
import type { SwarmConfig } from "./swarm-config";
|
|
4
|
+
|
|
5
|
+
function methodName(name: string): string {
|
|
6
|
+
const cleaned = name
|
|
7
|
+
.trim()
|
|
8
|
+
.replace(/[^A-Za-z0-9]+(.)/g, (_m, chr: string) => chr.toUpperCase())
|
|
9
|
+
.replace(/^[^A-Za-z_]+/, "")
|
|
10
|
+
.replace(/[^A-Za-z0-9_]/g, "");
|
|
11
|
+
if (!cleaned) throw new Error("MCP tool name must contain at least one letter");
|
|
12
|
+
return `${cleaned[0]?.toLowerCase()}${cleaned.slice(1)}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function methodNames(
|
|
16
|
+
tools: Array<{ name: string }>,
|
|
17
|
+
): Array<{ tool: { name: string }; methodName: string }> {
|
|
18
|
+
const used = new Set<string>();
|
|
19
|
+
const baseCounts = new Map<string, number>();
|
|
20
|
+
return tools.map((tool) => {
|
|
21
|
+
const base = methodName(tool.name);
|
|
22
|
+
const count = baseCounts.get(base) ?? 0;
|
|
23
|
+
baseCounts.set(base, count + 1);
|
|
24
|
+
let toolMethod = count === 0 ? base : `${base}${count + 1}`;
|
|
25
|
+
let suffix = count + 2;
|
|
26
|
+
while (used.has(toolMethod)) {
|
|
27
|
+
toolMethod = `${base}${suffix}`;
|
|
28
|
+
suffix += 1;
|
|
29
|
+
}
|
|
30
|
+
used.add(toolMethod);
|
|
31
|
+
return { tool, methodName: toolMethod };
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function headers(config: SwarmConfig): Record<string, string> {
|
|
36
|
+
return {
|
|
37
|
+
Authorization: `Bearer ${Redacted.value(config.apiKey)}`,
|
|
38
|
+
"X-Agent-ID": Redacted.value(config.agentId),
|
|
39
|
+
"Content-Type": "application/json",
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function errorMessage(data: unknown): string {
|
|
44
|
+
if (data && typeof data === "object") {
|
|
45
|
+
if ("error" in data) return JSON.stringify((data as { error: unknown }).error);
|
|
46
|
+
if ("message" in data) return String((data as { message: unknown }).message);
|
|
47
|
+
}
|
|
48
|
+
return "unknown MCP proxy error";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function createMcpRegistryClient(
|
|
52
|
+
descriptors: ScriptMcpConnectionDescriptor[] = [],
|
|
53
|
+
config: SwarmConfig,
|
|
54
|
+
): ScriptMcpRegistryClient {
|
|
55
|
+
const registry: ScriptMcpRegistryClient = {};
|
|
56
|
+
const baseUrl = Redacted.value(config.mcpBaseUrl).replace(/\/$/, "");
|
|
57
|
+
|
|
58
|
+
for (const descriptor of descriptors) {
|
|
59
|
+
const client: ScriptMcpRegistryClient[string] = {};
|
|
60
|
+
for (const { tool, methodName: toolMethod } of methodNames(descriptor.tools)) {
|
|
61
|
+
client[toolMethod] = async (rawArgs = {}) => {
|
|
62
|
+
const response = await fetch(
|
|
63
|
+
`${baseUrl}/api/script-connections/${encodeURIComponent(descriptor.connectionId)}/mcp-call`,
|
|
64
|
+
{
|
|
65
|
+
method: "POST",
|
|
66
|
+
headers: headers(config),
|
|
67
|
+
body: JSON.stringify({ tool: tool.name, arguments: rawArgs ?? {} }),
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
const text = await response.text();
|
|
71
|
+
const data = text ? JSON.parse(text) : {};
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`ctx.mcp.${descriptor.slug}.${toolMethod} failed with ${response.status}: ${errorMessage(data)}`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
if (!data || typeof data !== "object" || (data as { ok?: unknown }).ok !== true) {
|
|
78
|
+
throw new Error(`ctx.mcp.${descriptor.slug}.${toolMethod} failed: ${errorMessage(data)}`);
|
|
79
|
+
}
|
|
80
|
+
return (data as { result: unknown }).result;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
registry[descriptor.slug] = client;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return registry;
|
|
87
|
+
}
|
|
@@ -108,6 +108,7 @@ declare module "swarm-sdk" {
|
|
|
108
108
|
externalId?: string;
|
|
109
109
|
email?: string;
|
|
110
110
|
userId?: string;
|
|
111
|
+
name?: string;
|
|
111
112
|
}): Promise<unknown>;
|
|
112
113
|
db_query(args: { sql: string; params?: unknown[] }): Promise<unknown>;
|
|
113
114
|
// --- config ---
|
|
@@ -242,6 +243,8 @@ declare module "swarm-sdk" {
|
|
|
242
243
|
slack_startThread(args: { channelId: string; message: string }): Promise<unknown>;
|
|
243
244
|
slack_uploadFile(args: Record<string, unknown>): Promise<unknown>;
|
|
244
245
|
slack_downloadFile(args: { url: string }): Promise<unknown>;
|
|
246
|
+
slack_delete(args: { channelId: string; messageTs: string }): Promise<unknown>;
|
|
247
|
+
slack_update(args: { channelId: string; messageTs: string; message: string }): Promise<unknown>;
|
|
245
248
|
|
|
246
249
|
// --- write: messaging (internal) ---
|
|
247
250
|
message_post(args: { channel?: string; content: string; to?: string }): Promise<unknown>;
|
|
@@ -346,6 +349,7 @@ declare module "swarm-sdk" {
|
|
|
346
349
|
|
|
347
350
|
// --- pages & metrics ---
|
|
348
351
|
page_create(args: Record<string, unknown>): Promise<unknown>;
|
|
352
|
+
page_delete(args: { pageId?: string; slug?: string }): Promise<unknown>;
|
|
349
353
|
metric_create(args: Record<string, unknown>): Promise<unknown>;
|
|
350
354
|
|
|
351
355
|
// --- human input ---
|
|
@@ -411,6 +415,8 @@ declare module "swarm-sdk" {
|
|
|
411
415
|
run?: ScriptRunContext;
|
|
412
416
|
step?: ScriptWorkflowSteps;
|
|
413
417
|
swarm: SwarmSdk & { config: SwarmConfig };
|
|
418
|
+
api: ScriptApiRegistry;
|
|
419
|
+
mcp: ScriptMcpRegistry;
|
|
414
420
|
stdlib: ScriptStdlib;
|
|
415
421
|
logger: ScriptLogger;
|
|
416
422
|
}
|
|
@@ -8,6 +8,17 @@ declare module "swarm-sdk" {
|
|
|
8
8
|
| { [key: string]: JsonValue };
|
|
9
9
|
export type ScriptScope = "agent" | "global";
|
|
10
10
|
export type ScriptFsMode = "none" | "workspace-rw";
|
|
11
|
+
export type ScriptApiRawOptions = { raw: true };
|
|
12
|
+
export type ScriptApiDefaultOptions = { raw?: false };
|
|
13
|
+
|
|
14
|
+
export interface ScriptApiRawResult {
|
|
15
|
+
ok: boolean;
|
|
16
|
+
status: number;
|
|
17
|
+
statusText: string;
|
|
18
|
+
headers: Record<string, string>;
|
|
19
|
+
url: string;
|
|
20
|
+
response: Response;
|
|
21
|
+
}
|
|
11
22
|
|
|
12
23
|
export interface Redacted<T> {
|
|
13
24
|
readonly __redactedBrand?: T;
|
|
@@ -90,6 +101,7 @@ declare module "swarm-sdk" {
|
|
|
90
101
|
externalId?: string;
|
|
91
102
|
email?: string;
|
|
92
103
|
userId?: string;
|
|
104
|
+
name?: string;
|
|
93
105
|
}): Promise<unknown>;
|
|
94
106
|
db_query(args: { sql: string; params?: unknown[] }): Promise<unknown>;
|
|
95
107
|
// --- config ---
|
|
@@ -330,6 +342,7 @@ declare module "swarm-sdk" {
|
|
|
330
342
|
|
|
331
343
|
// --- pages & metrics ---
|
|
332
344
|
page_create(args: Record<string, unknown>): Promise<unknown>;
|
|
345
|
+
page_delete(args: { pageId?: string; slug?: string }): Promise<unknown>;
|
|
333
346
|
metric_create(args: Record<string, unknown>): Promise<unknown>;
|
|
334
347
|
|
|
335
348
|
// --- human input ---
|
|
@@ -395,10 +408,16 @@ declare module "swarm-sdk" {
|
|
|
395
408
|
run?: ScriptRunContext;
|
|
396
409
|
step?: ScriptWorkflowSteps;
|
|
397
410
|
swarm: SwarmSdk & { config: SwarmConfig };
|
|
411
|
+
api: ScriptApiRegistry;
|
|
412
|
+
mcp: ScriptMcpRegistry;
|
|
398
413
|
stdlib: ScriptStdlib;
|
|
399
414
|
logger: ScriptLogger;
|
|
400
415
|
}
|
|
401
416
|
|
|
402
417
|
// biome-ignore lint/suspicious/noExplicitAny: scripts may narrow their args type at the entrypoint.
|
|
403
418
|
export type ScriptMain = (args: any, ctx: ScriptContext) => unknown | Promise<unknown>;
|
|
419
|
+
|
|
420
|
+
export interface ScriptApiRegistry {}
|
|
421
|
+
|
|
422
|
+
export interface ScriptMcpRegistry {}
|
|
404
423
|
}
|