@desplega.ai/agent-swarm 1.119.3 → 1.119.4
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/dist/{actions-kd321p1j.js → actions-cvcf510b.js} +5 -5
- package/dist/{app-p1gqacgd.js → app-05ksvyna.js} +3 -3
- package/dist/{assistant-6w0zb089.js → assistant-wqr7nmqv.js} +8 -8
- package/dist/{boot-reembed-zktmj8zt.js → boot-reembed-dx3zweeh.js} +4 -4
- package/dist/{boot-reembed-7gy85nnp.js → boot-reembed-v0q84hej.js} +3 -3
- package/dist/{boot-scrub-logs-d8n8pcgr.js → boot-scrub-logs-3am4xegg.js} +2 -2
- package/dist/{cli-gzng1fst.js → cli-0y66mw72.js} +9 -7
- package/dist/{cli-527y7yzc.js → cli-1c5zhw9z.js} +3 -3
- package/dist/{cli-eb3s7zwh.js → cli-4xtzqzv4.js} +18 -18
- package/dist/{cli-yzxg93ma.js → cli-67e8g7bj.js} +4 -4
- package/dist/{cli-td2x0s9b.js → cli-758zm6xy.js} +1 -1
- package/dist/{cli-y82m27mq.js → cli-7mvmqemc.js} +1 -1
- package/dist/{cli-6expbmb3.js → cli-8jjrc3ww.js} +1 -1
- package/dist/{cli-p4yn675m.js → cli-bzjncaf6.js} +1 -1
- package/dist/{cli-8y1kmyn7.js → cli-chfh8r6f.js} +2 -2
- package/dist/{cli-3sew4a9j.js → cli-cs5g429e.js} +1 -1
- package/dist/{cli-j5da6jb2.js → cli-fhmhjjh4.js} +17 -29
- package/dist/{cli-e5hdn9nx.js → cli-h1bffz9b.js} +1 -1
- package/dist/{cli-9y4z25ke.js → cli-jfc1jm13.js} +1 -1
- package/dist/{cli-emgzr4ja.js → cli-k0x0fvh5.js} +5 -5
- package/dist/{cli-xgefj1nz.js → cli-kmtp1rg9.js} +2 -2
- package/dist/{cli-7yfmb4ne.js → cli-pc276yqz.js} +1 -1
- package/dist/{cli-j6n9at34.js → cli-pyagab0x.js} +2 -2
- package/dist/{cli-g5a31r9y.js → cli-qe43w9a5.js} +2 -2
- package/dist/{cli-z612d1nc.js → cli-qfp17rw8.js} +1 -1
- package/dist/{cli-9aqtt1dn.js → cli-rk6fkhkk.js} +5 -5
- package/dist/{cli-j2vpt4hd.js → cli-ttb3pty1.js} +4 -4
- package/dist/{cli-cx30v78p.js → cli-zm2jjaq6.js} +1 -1
- package/dist/{cli-get7n46a.js → cli-zrxpz200.js} +1 -1
- package/dist/cli.js +9 -9
- package/dist/{commands-14gkjns3.js → commands-3ke60h4e.js} +2 -2
- package/dist/{db-c9wx8pbf.js → db-a1e1nj43.js} +2 -2
- package/dist/{handlers-m9jxp50r.js → handlers-d86a4ypy.js} +8 -8
- package/dist/{hook-mm8mj3cp.js → hook-teegt6h5.js} +1 -1
- package/dist/{http-hhmh7m51.js → http-64jvxqnz.js} +33 -33
- package/dist/{index-vmcp507g.js → index-a95n0ay5.js} +8 -8
- package/dist/{index-basky7qw.js → index-bndzxk11.js} +10 -10
- package/dist/{index-9h6qre5v.js → index-hb9j1aqr.js} +6 -6
- package/dist/{index-ep25fyer.js → index-z39ch6n5.js} +9 -9
- package/dist/{keepalive-70mwsyhb.js → keepalive-ab1qpqrm.js} +4 -4
- package/dist/{lead-pshn5w58.js → lead-852gtrsa.js} +18 -18
- package/dist/{maintenance-rbjav7ey.js → maintenance-fke93wqq.js} +4 -4
- package/dist/{oauth-refresh-sweep-dfbd7yw0.js → oauth-refresh-sweep-a139pm5w.js} +3 -3
- package/dist/{onboard-g8911158.js → onboard-vcd22m9e.js} +2 -2
- package/dist/{otel-impl-qw4pakj6.js → otel-impl-88egk5hc.js} +1 -1
- package/dist/{pricing-refresh-7ra0g3az.js → pricing-refresh-bbg7s7qs.js} +4 -4
- package/dist/{rbac-roles-ksnmkjzf.js → rbac-roles-e169ndy2.js} +2 -2
- package/dist/{rbac-roles-s0esm5k6.js → rbac-roles-kc9t08gp.js} +3 -3
- package/dist/{seed-pricing-jd8zj8k7.js → seed-pricing-3zhtw483.js} +3 -3
- package/dist/{setup-z2s4vqf3.js → setup-6m99ne8y.js} +2 -2
- package/dist/{worker-xse3rpzd.js → worker-pwg46aav.js} +18 -18
- package/openapi.json +1 -1
- package/package.json +1 -1
- package/src/be/script-credential-broker.ts +12 -26
- package/src/scripts-runtime/credential-broker/broker.ts +15 -4
- package/src/scripts-runtime/credential-broker/index.ts +1 -0
- package/src/scripts-runtime/credential-broker/types.ts +1 -0
- package/src/scripts-runtime/egress-secrets.ts +2 -2
- package/src/scripts-runtime/loader.ts +3 -3
- package/src/tests/credential-broker.test.ts +130 -3
- package/src/tests/scripts-runtime-secret-egress.test.ts +4 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runAgent
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-ttb3pty1.js";
|
|
4
4
|
import"./cli-sznberje.js";
|
|
5
5
|
import"./cli-tyfxrrdd.js";
|
|
6
6
|
import"./cli-bc89my0z.js";
|
|
@@ -14,7 +14,7 @@ import"./cli-yv9dttkh.js";
|
|
|
14
14
|
import"./cli-hx1dcevq.js";
|
|
15
15
|
import {
|
|
16
16
|
getEnabledCapabilities
|
|
17
|
-
} from "./cli-
|
|
17
|
+
} from "./cli-4xtzqzv4.js";
|
|
18
18
|
import"./cli-1z7048dy.js";
|
|
19
19
|
import"./cli-gz9sbyk3.js";
|
|
20
20
|
import"./cli-ftyf58xj.js";
|
|
@@ -25,36 +25,36 @@ import"./cli-psrqtw2m.js";
|
|
|
25
25
|
import"./cli-zm7njwzd.js";
|
|
26
26
|
import"./cli-tghre7g6.js";
|
|
27
27
|
import"./cli-e61fs2hp.js";
|
|
28
|
-
import"./cli-
|
|
29
|
-
import"./cli-
|
|
30
|
-
import"./cli-
|
|
31
|
-
import"./cli-
|
|
28
|
+
import"./cli-67e8g7bj.js";
|
|
29
|
+
import"./cli-chfh8r6f.js";
|
|
30
|
+
import"./cli-h1bffz9b.js";
|
|
31
|
+
import"./cli-pc276yqz.js";
|
|
32
32
|
import"./cli-86fdnerz.js";
|
|
33
|
-
import"./cli-
|
|
34
|
-
import"./cli-
|
|
33
|
+
import"./cli-qfp17rw8.js";
|
|
34
|
+
import"./cli-fhmhjjh4.js";
|
|
35
35
|
import"./cli-f14fvzag.js";
|
|
36
|
-
import"./cli-
|
|
37
|
-
import"./cli-
|
|
36
|
+
import"./cli-bzjncaf6.js";
|
|
37
|
+
import"./cli-0y66mw72.js";
|
|
38
38
|
import"./cli-jkhwmmgg.js";
|
|
39
|
-
import"./cli-
|
|
40
|
-
import"./cli-
|
|
39
|
+
import"./cli-kmtp1rg9.js";
|
|
40
|
+
import"./cli-8jjrc3ww.js";
|
|
41
41
|
import"./cli-q25ejbyn.js";
|
|
42
42
|
import"./cli-0pygq9r1.js";
|
|
43
43
|
import"./cli-fad8m16k.js";
|
|
44
|
-
import"./cli-
|
|
45
|
-
import"./cli-
|
|
44
|
+
import"./cli-jfc1jm13.js";
|
|
45
|
+
import"./cli-k0x0fvh5.js";
|
|
46
46
|
import"./cli-rkndnn90.js";
|
|
47
47
|
import"./cli-b0p7rfnd.js";
|
|
48
|
-
import"./cli-
|
|
49
|
-
import"./cli-
|
|
48
|
+
import"./cli-cs5g429e.js";
|
|
49
|
+
import"./cli-758zm6xy.js";
|
|
50
50
|
import"./cli-ma04faw5.js";
|
|
51
51
|
import"./cli-wspgs9bt.js";
|
|
52
52
|
import"./cli-dh55d5fg.js";
|
|
53
|
-
import"./cli-
|
|
53
|
+
import"./cli-7mvmqemc.js";
|
|
54
54
|
import"./cli-z2zcxes1.js";
|
|
55
55
|
import"./cli-bw80ck94.js";
|
|
56
56
|
import"./cli-xz9aq0rf.js";
|
|
57
|
-
import"./cli-
|
|
57
|
+
import"./cli-zm2jjaq6.js";
|
|
58
58
|
import"./cli-4j2mrzag.js";
|
|
59
59
|
import"./cli-e15jhafb.js";
|
|
60
60
|
import"./cli-9aryf9tv.js";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
reembedAllScripts
|
|
3
|
-
} from "./cli-
|
|
4
|
-
import"./cli-
|
|
3
|
+
} from "./cli-kmtp1rg9.js";
|
|
4
|
+
import"./cli-8jjrc3ww.js";
|
|
5
5
|
import"./cli-q25ejbyn.js";
|
|
6
|
-
import"./cli-
|
|
6
|
+
import"./cli-7mvmqemc.js";
|
|
7
7
|
import"./cli-z2zcxes1.js";
|
|
8
8
|
import"./cli-bw80ck94.js";
|
|
9
9
|
import"./cli-xz9aq0rf.js";
|
|
10
|
-
import"./cli-
|
|
10
|
+
import"./cli-zm2jjaq6.js";
|
|
11
11
|
import"./cli-4j2mrzag.js";
|
|
12
12
|
import"./cli-p9swy5t3.js";
|
|
13
13
|
|
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
forceRefreshTokenOrThrow,
|
|
3
3
|
getOAuthTokens,
|
|
4
4
|
listOAuthTokenSweepRows
|
|
5
|
-
} from "./cli-
|
|
5
|
+
} from "./cli-bzjncaf6.js";
|
|
6
6
|
import"./cli-0pygq9r1.js";
|
|
7
|
-
import"./cli-
|
|
7
|
+
import"./cli-7mvmqemc.js";
|
|
8
8
|
import"./cli-z2zcxes1.js";
|
|
9
9
|
import"./cli-bw80ck94.js";
|
|
10
10
|
import"./cli-xz9aq0rf.js";
|
|
11
|
-
import"./cli-
|
|
11
|
+
import"./cli-zm2jjaq6.js";
|
|
12
12
|
import {
|
|
13
13
|
init_secret_scrubber,
|
|
14
14
|
scrubSecrets
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
createDefaultMcpJson,
|
|
4
4
|
createDefaultSettingsLocal,
|
|
5
5
|
createHooksConfig
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-zrxpz200.js";
|
|
7
7
|
import {
|
|
8
8
|
require_jsx_dev_runtime
|
|
9
9
|
} from "./cli-wx82tw1k.js";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
init_package,
|
|
15
15
|
package_default
|
|
16
|
-
} from "./cli-
|
|
16
|
+
} from "./cli-zm2jjaq6.js";
|
|
17
17
|
import {
|
|
18
18
|
Box_default,
|
|
19
19
|
Select,
|
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
PRICING_REFRESH_INTERVAL_MS,
|
|
3
3
|
refreshPricingFromModelsDev,
|
|
4
4
|
startPricingRefreshLoop
|
|
5
|
-
} from "./cli-
|
|
6
|
-
import"./cli-
|
|
7
|
-
import"./cli-
|
|
5
|
+
} from "./cli-chfh8r6f.js";
|
|
6
|
+
import"./cli-h1bffz9b.js";
|
|
7
|
+
import"./cli-7mvmqemc.js";
|
|
8
8
|
import"./cli-z2zcxes1.js";
|
|
9
9
|
import"./cli-bw80ck94.js";
|
|
10
10
|
import"./cli-xz9aq0rf.js";
|
|
11
|
-
import"./cli-
|
|
11
|
+
import"./cli-zm2jjaq6.js";
|
|
12
12
|
import"./cli-4j2mrzag.js";
|
|
13
13
|
import"./cli-p9swy5t3.js";
|
|
14
14
|
export {
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
getDb,
|
|
6
6
|
init_db
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-7mvmqemc.js";
|
|
8
8
|
import"./cli-z2zcxes1.js";
|
|
9
9
|
import"./cli-bw80ck94.js";
|
|
10
10
|
import"./cli-xz9aq0rf.js";
|
|
11
|
-
import"./cli-
|
|
11
|
+
import"./cli-zm2jjaq6.js";
|
|
12
12
|
import"./cli-4j2mrzag.js";
|
|
13
13
|
import"./cli-p9swy5t3.js";
|
|
14
14
|
|
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
getUserGrant,
|
|
8
8
|
listUserRoles,
|
|
9
9
|
runRbacCliCommand
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-pc276yqz.js";
|
|
11
11
|
import"./cli-86fdnerz.js";
|
|
12
|
-
import"./cli-
|
|
12
|
+
import"./cli-7mvmqemc.js";
|
|
13
13
|
import"./cli-z2zcxes1.js";
|
|
14
14
|
import"./cli-bw80ck94.js";
|
|
15
15
|
import"./cli-xz9aq0rf.js";
|
|
16
|
-
import"./cli-
|
|
16
|
+
import"./cli-zm2jjaq6.js";
|
|
17
17
|
import"./cli-4j2mrzag.js";
|
|
18
18
|
import"./cli-p9swy5t3.js";
|
|
19
19
|
export {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildModelsDevSeedRows,
|
|
3
3
|
seedPricingFromModelsDev
|
|
4
|
-
} from "./cli-
|
|
5
|
-
import"./cli-
|
|
4
|
+
} from "./cli-h1bffz9b.js";
|
|
5
|
+
import"./cli-7mvmqemc.js";
|
|
6
6
|
import"./cli-z2zcxes1.js";
|
|
7
7
|
import"./cli-bw80ck94.js";
|
|
8
8
|
import"./cli-xz9aq0rf.js";
|
|
9
|
-
import"./cli-
|
|
9
|
+
import"./cli-zm2jjaq6.js";
|
|
10
10
|
import"./cli-4j2mrzag.js";
|
|
11
11
|
import"./cli-p9swy5t3.js";
|
|
12
12
|
export {
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
createDefaultMcpJson,
|
|
5
5
|
createDefaultSettingsLocal,
|
|
6
6
|
createHooksConfig
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-zrxpz200.js";
|
|
8
8
|
import {
|
|
9
9
|
require_jsx_dev_runtime
|
|
10
10
|
} from "./cli-wx82tw1k.js";
|
|
11
11
|
import {
|
|
12
12
|
getApiKey
|
|
13
13
|
} from "./cli-f14fvzag.js";
|
|
14
|
-
import"./cli-
|
|
14
|
+
import"./cli-zm2jjaq6.js";
|
|
15
15
|
import {
|
|
16
16
|
Box_default,
|
|
17
17
|
Spinner,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runAgent
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-ttb3pty1.js";
|
|
4
4
|
import"./cli-sznberje.js";
|
|
5
5
|
import"./cli-tyfxrrdd.js";
|
|
6
6
|
import"./cli-bc89my0z.js";
|
|
@@ -14,7 +14,7 @@ import"./cli-yv9dttkh.js";
|
|
|
14
14
|
import"./cli-hx1dcevq.js";
|
|
15
15
|
import {
|
|
16
16
|
getEnabledCapabilities
|
|
17
|
-
} from "./cli-
|
|
17
|
+
} from "./cli-4xtzqzv4.js";
|
|
18
18
|
import"./cli-1z7048dy.js";
|
|
19
19
|
import"./cli-gz9sbyk3.js";
|
|
20
20
|
import"./cli-ftyf58xj.js";
|
|
@@ -25,36 +25,36 @@ import"./cli-psrqtw2m.js";
|
|
|
25
25
|
import"./cli-zm7njwzd.js";
|
|
26
26
|
import"./cli-tghre7g6.js";
|
|
27
27
|
import"./cli-e61fs2hp.js";
|
|
28
|
-
import"./cli-
|
|
29
|
-
import"./cli-
|
|
30
|
-
import"./cli-
|
|
31
|
-
import"./cli-
|
|
28
|
+
import"./cli-67e8g7bj.js";
|
|
29
|
+
import"./cli-chfh8r6f.js";
|
|
30
|
+
import"./cli-h1bffz9b.js";
|
|
31
|
+
import"./cli-pc276yqz.js";
|
|
32
32
|
import"./cli-86fdnerz.js";
|
|
33
|
-
import"./cli-
|
|
34
|
-
import"./cli-
|
|
33
|
+
import"./cli-qfp17rw8.js";
|
|
34
|
+
import"./cli-fhmhjjh4.js";
|
|
35
35
|
import"./cli-f14fvzag.js";
|
|
36
|
-
import"./cli-
|
|
37
|
-
import"./cli-
|
|
36
|
+
import"./cli-bzjncaf6.js";
|
|
37
|
+
import"./cli-0y66mw72.js";
|
|
38
38
|
import"./cli-jkhwmmgg.js";
|
|
39
|
-
import"./cli-
|
|
40
|
-
import"./cli-
|
|
39
|
+
import"./cli-kmtp1rg9.js";
|
|
40
|
+
import"./cli-8jjrc3ww.js";
|
|
41
41
|
import"./cli-q25ejbyn.js";
|
|
42
42
|
import"./cli-0pygq9r1.js";
|
|
43
43
|
import"./cli-fad8m16k.js";
|
|
44
|
-
import"./cli-
|
|
45
|
-
import"./cli-
|
|
44
|
+
import"./cli-jfc1jm13.js";
|
|
45
|
+
import"./cli-k0x0fvh5.js";
|
|
46
46
|
import"./cli-rkndnn90.js";
|
|
47
47
|
import"./cli-b0p7rfnd.js";
|
|
48
|
-
import"./cli-
|
|
49
|
-
import"./cli-
|
|
48
|
+
import"./cli-cs5g429e.js";
|
|
49
|
+
import"./cli-758zm6xy.js";
|
|
50
50
|
import"./cli-ma04faw5.js";
|
|
51
51
|
import"./cli-wspgs9bt.js";
|
|
52
52
|
import"./cli-dh55d5fg.js";
|
|
53
|
-
import"./cli-
|
|
53
|
+
import"./cli-7mvmqemc.js";
|
|
54
54
|
import"./cli-z2zcxes1.js";
|
|
55
55
|
import"./cli-bw80ck94.js";
|
|
56
56
|
import"./cli-xz9aq0rf.js";
|
|
57
|
-
import"./cli-
|
|
57
|
+
import"./cli-zm2jjaq6.js";
|
|
58
58
|
import"./cli-4j2mrzag.js";
|
|
59
59
|
import"./cli-e15jhafb.js";
|
|
60
60
|
import"./cli-9aryf9tv.js";
|
package/openapi.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.1.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Agent Swarm API",
|
|
5
|
-
"version": "1.119.
|
|
5
|
+
"version": "1.119.4",
|
|
6
6
|
"description": "Multi-agent orchestration API for Claude Code, Codex, and Gemini CLI. Enables task distribution, agent communication, and service discovery.\n\nMCP tools are documented separately in [MCP.md](./MCP.md)."
|
|
7
7
|
},
|
|
8
8
|
"servers": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@desplega.ai/agent-swarm",
|
|
3
|
-
"version": "1.119.
|
|
3
|
+
"version": "1.119.4",
|
|
4
4
|
"description": "Multi-agent orchestration for Claude Code, Codex, Gemini CLI, and other AI coding assistants",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "desplega.sh <contact@desplega.sh>",
|
|
@@ -25,38 +25,24 @@ export async function buildScriptCredentialBindings(input: {
|
|
|
25
25
|
}): Promise<EgressSecretEntry[]> {
|
|
26
26
|
const resolvedConfigs = getResolvedConfig(input.agentId, input.repoId);
|
|
27
27
|
const configMap = new Map(resolvedConfigs.map((config) => [config.key, config.value]));
|
|
28
|
-
const relationalBindings = listRelationalCredentialBindings(input);
|
|
29
|
-
for (const binding of relationalBindings) {
|
|
30
|
-
if (binding.authKind !== "oauth") continue;
|
|
31
|
-
configMap.set(binding.configKey, "");
|
|
32
|
-
if (!binding.oauthProvider) continue;
|
|
33
|
-
|
|
34
|
-
let accessToken: string | undefined;
|
|
35
|
-
try {
|
|
36
|
-
accessToken = await resolveOAuthBindingToken(binding.oauthProvider);
|
|
37
|
-
} catch (err) {
|
|
38
|
-
// A stale/broken provider must not take down unrelated script runs —
|
|
39
|
-
// skip just this binding (the "" shadow above keeps the placeholder
|
|
40
|
-
// unresolved instead of falling through to a same-named config value).
|
|
41
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
42
|
-
console.warn(
|
|
43
|
-
`[script-credential-broker] skipping OAuth binding ${binding.configKey}: token refresh for provider ${binding.oauthProvider} failed: ${scrubSecrets(message)}`,
|
|
44
|
-
);
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
if (!accessToken) continue;
|
|
48
|
-
|
|
49
|
-
configMap.set(binding.configKey, accessToken);
|
|
50
|
-
registerVolatileSecret(accessToken, binding.configKey);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
28
|
const broker = new CredentialBroker(
|
|
54
29
|
new RelationalCredentialBindingStore((filters) => getSwarmConfigs(filters)),
|
|
55
30
|
(configKey) => configMap.get(configKey) ?? process.env[configKey],
|
|
56
31
|
DEFAULT_CREDENTIAL_BINDINGS,
|
|
32
|
+
async (provider) => {
|
|
33
|
+
try {
|
|
34
|
+
return await resolveOAuthBindingToken(provider);
|
|
35
|
+
} catch (err) {
|
|
36
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
37
|
+
console.warn(
|
|
38
|
+
`[script-credential-broker] skipping OAuth provider ${provider}: ${scrubSecrets(message)}`,
|
|
39
|
+
);
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
},
|
|
57
43
|
);
|
|
58
44
|
|
|
59
|
-
const bindings = broker.resolveBindings({ agentId: input.agentId, repoId: input.repoId });
|
|
45
|
+
const bindings = await broker.resolveBindings({ agentId: input.agentId, repoId: input.repoId });
|
|
60
46
|
for (const binding of bindings) {
|
|
61
47
|
registerVolatileSecret(binding.value, binding.configKey);
|
|
62
48
|
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
CredentialBinding,
|
|
3
|
+
CredentialBindingStore,
|
|
4
|
+
CredentialResolver,
|
|
5
|
+
OAuthCredentialResolver,
|
|
6
|
+
} from "./types";
|
|
2
7
|
import { placeholderForConfigKey, type ResolvedCredentialBinding } from "./types";
|
|
3
8
|
|
|
4
9
|
function bindingHasPlaceholder(binding: CredentialBinding) {
|
|
@@ -12,11 +17,12 @@ function bindingHasPlaceholder(binding: CredentialBinding) {
|
|
|
12
17
|
export class CredentialBroker {
|
|
13
18
|
constructor(
|
|
14
19
|
private readonly store: CredentialBindingStore,
|
|
15
|
-
private readonly
|
|
20
|
+
private readonly resolveConfigCredential: CredentialResolver,
|
|
16
21
|
private readonly defaults: CredentialBinding[] = [],
|
|
22
|
+
private readonly resolveOAuthCredential?: OAuthCredentialResolver,
|
|
17
23
|
) {}
|
|
18
24
|
|
|
19
|
-
resolveBindings(context: Parameters<CredentialBindingStore["listActiveBindings"]>[0]) {
|
|
25
|
+
async resolveBindings(context: Parameters<CredentialBindingStore["listActiveBindings"]>[0]) {
|
|
20
26
|
const merged = [...this.defaults, ...this.store.listActiveBindings(context)];
|
|
21
27
|
const resolved: ResolvedCredentialBinding[] = [];
|
|
22
28
|
const seen = new Set<string>();
|
|
@@ -25,7 +31,12 @@ export class CredentialBroker {
|
|
|
25
31
|
if (binding.active === false) continue;
|
|
26
32
|
if (!bindingHasPlaceholder(binding)) continue;
|
|
27
33
|
|
|
28
|
-
const value =
|
|
34
|
+
const value =
|
|
35
|
+
binding.authKind === "oauth"
|
|
36
|
+
? binding.oauthProvider
|
|
37
|
+
? await this.resolveOAuthCredential?.(binding.oauthProvider)
|
|
38
|
+
: undefined
|
|
39
|
+
: this.resolveConfigCredential(binding.configKey);
|
|
29
40
|
if (!value) continue;
|
|
30
41
|
|
|
31
42
|
const dedupeKey = [
|
|
@@ -51,6 +51,7 @@ export interface CredentialBindingStore {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export type CredentialResolver = (configKey: string) => string | undefined;
|
|
54
|
+
export type OAuthCredentialResolver = (oauthProvider: string) => Promise<string | undefined>;
|
|
54
55
|
|
|
55
56
|
export function placeholderForConfigKey(configKey: string): string {
|
|
56
57
|
return `${REDACTED_PLACEHOLDER_PREFIX}${configKey}]`;
|
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
|
|
8
8
|
export type EgressSecretEntry = ResolvedCredentialBinding;
|
|
9
9
|
|
|
10
|
-
export function buildEgressSecrets(): EgressSecretEntry[] {
|
|
10
|
+
export async function buildEgressSecrets(): Promise<EgressSecretEntry[]> {
|
|
11
11
|
const broker = new CredentialBroker(
|
|
12
12
|
{ listActiveBindings: () => [] },
|
|
13
13
|
(configKey) => process.env[configKey],
|
|
14
14
|
DEFAULT_CREDENTIAL_BINDINGS,
|
|
15
15
|
);
|
|
16
|
-
return broker.resolveBindings({});
|
|
16
|
+
return await broker.resolveBindings({});
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export function patchFetchWithEgressSubstitution(secrets: EgressSecretEntry[]): void {
|
|
@@ -36,7 +36,7 @@ export type RunScriptOutput = Omit<ExecutorOutput, "result" | "stdout" | "stderr
|
|
|
36
36
|
|
|
37
37
|
export type { ScriptRuntimeError, ScriptStackFrame } from "./executors/types";
|
|
38
38
|
|
|
39
|
-
function buildConfigPayload(input: RunScriptInput): SwarmConfigPayload {
|
|
39
|
+
async function buildConfigPayload(input: RunScriptInput): Promise<SwarmConfigPayload> {
|
|
40
40
|
const apiKey = getApiKey();
|
|
41
41
|
if (!apiKey) throw new Error("Swarm API key is required to run scripts");
|
|
42
42
|
|
|
@@ -50,7 +50,7 @@ function buildConfigPayload(input: RunScriptInput): SwarmConfigPayload {
|
|
|
50
50
|
},
|
|
51
51
|
},
|
|
52
52
|
user: input.userConfig ?? {},
|
|
53
|
-
egressSecrets: input.egressSecrets ?? buildEgressSecrets(),
|
|
53
|
+
egressSecrets: input.egressSecrets ?? (await buildEgressSecrets()),
|
|
54
54
|
apiConnections: input.apiConnections ?? [],
|
|
55
55
|
mcpConnections: input.mcpConnections ?? [],
|
|
56
56
|
};
|
|
@@ -91,7 +91,7 @@ export async function runScript(input: RunScriptInput): Promise<RunScriptOutput>
|
|
|
91
91
|
const output = await getScriptExecutor().run({
|
|
92
92
|
source: input.source,
|
|
93
93
|
args: input.args ?? null,
|
|
94
|
-
configPayload: buildConfigPayload(input),
|
|
94
|
+
configPayload: await buildConfigPayload(input),
|
|
95
95
|
resources,
|
|
96
96
|
fsMode: input.fsMode ?? "none",
|
|
97
97
|
network: "open",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { afterEach, describe, expect, test } from "bun:test";
|
|
1
|
+
import { afterEach, describe, expect, mock, test } from "bun:test";
|
|
2
2
|
import { deleteSwarmConfig, upsertSwarmConfig } from "../be/db";
|
|
3
3
|
import { buildScriptCredentialBindings } from "../be/script-credential-broker";
|
|
4
|
+
import { createApiRegistryClient } from "../scripts-runtime/api-client";
|
|
4
5
|
import {
|
|
5
6
|
CREDENTIAL_BINDINGS_CONFIG_KEY,
|
|
6
7
|
type CredentialBindingStore,
|
|
@@ -119,7 +120,7 @@ describe("credential broker", () => {
|
|
|
119
120
|
);
|
|
120
121
|
});
|
|
121
122
|
|
|
122
|
-
test("resolves seeded GITHUB_TOKEN binding", () => {
|
|
123
|
+
test("resolves seeded GITHUB_TOKEN binding", async () => {
|
|
123
124
|
const emptyStore: CredentialBindingStore = { listActiveBindings: () => [] };
|
|
124
125
|
const broker = new CredentialBroker(
|
|
125
126
|
emptyStore,
|
|
@@ -127,7 +128,7 @@ describe("credential broker", () => {
|
|
|
127
128
|
DEFAULT_CREDENTIAL_BINDINGS,
|
|
128
129
|
);
|
|
129
130
|
|
|
130
|
-
expect(broker.resolveBindings({})).toEqual([
|
|
131
|
+
expect(await broker.resolveBindings({})).toEqual([
|
|
131
132
|
{
|
|
132
133
|
configKey: "GITHUB_TOKEN",
|
|
133
134
|
allowedHosts: ["api.github.com"],
|
|
@@ -142,6 +143,132 @@ describe("credential broker", () => {
|
|
|
142
143
|
]);
|
|
143
144
|
});
|
|
144
145
|
|
|
146
|
+
test("resolves OAuth bindings with the OAuth resolver and substitutes their header", async () => {
|
|
147
|
+
const oauthResolver = mock(async (provider: string) =>
|
|
148
|
+
provider === "gmailSupport" ? "gmail-access-token" : undefined,
|
|
149
|
+
);
|
|
150
|
+
const broker = new CredentialBroker(
|
|
151
|
+
{
|
|
152
|
+
listActiveBindings: () => [
|
|
153
|
+
{
|
|
154
|
+
configKey: "GMAIL_SUPPORT_OAUTH_BINDING",
|
|
155
|
+
allowedHosts: ["gmail.googleapis.com"],
|
|
156
|
+
headerTemplate: "Authorization: Bearer [REDACTED:GMAIL_SUPPORT_OAUTH_BINDING]",
|
|
157
|
+
scope: "global",
|
|
158
|
+
scopeId: null,
|
|
159
|
+
active: true,
|
|
160
|
+
authKind: "oauth",
|
|
161
|
+
oauthProvider: "gmailSupport",
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
},
|
|
165
|
+
() => {
|
|
166
|
+
throw new Error("config resolver must not be used for OAuth bindings");
|
|
167
|
+
},
|
|
168
|
+
[],
|
|
169
|
+
oauthResolver,
|
|
170
|
+
);
|
|
171
|
+
const bindings = await broker.resolveBindings({});
|
|
172
|
+
|
|
173
|
+
expect(oauthResolver).toHaveBeenCalledWith("gmailSupport");
|
|
174
|
+
let authorization: string | null = null;
|
|
175
|
+
globalThis.fetch = (async (_input: string | URL | Request, init?: RequestInit) => {
|
|
176
|
+
authorization = new Headers(init?.headers).get("authorization");
|
|
177
|
+
return Response.json({ ok: true });
|
|
178
|
+
}) as typeof fetch;
|
|
179
|
+
patchFetchWithCredentialBroker(bindings);
|
|
180
|
+
|
|
181
|
+
await fetch("https://gmail.googleapis.com/gmail/v1/users/me/profile", {
|
|
182
|
+
headers: { Authorization: "Bearer [REDACTED:GMAIL_SUPPORT_OAUTH_BINDING]" },
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
expect(authorization).toBe("Bearer gmail-access-token");
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test("resolved OAuth bindings also authenticate ctx.api clients", async () => {
|
|
189
|
+
let authorization: string | null = null;
|
|
190
|
+
globalThis.fetch = (async (_input: string | URL | Request, init?: RequestInit) => {
|
|
191
|
+
authorization = new Headers(init?.headers).get("authorization");
|
|
192
|
+
return Response.json({ data: { ok: true } });
|
|
193
|
+
}) as typeof fetch;
|
|
194
|
+
const broker = new CredentialBroker(
|
|
195
|
+
{
|
|
196
|
+
listActiveBindings: () => [
|
|
197
|
+
{
|
|
198
|
+
configKey: "GMAIL_SUPPORT_OAUTH_BINDING",
|
|
199
|
+
allowedHosts: ["gmail.googleapis.com"],
|
|
200
|
+
headerTemplate: "Authorization: Bearer [REDACTED:GMAIL_SUPPORT_OAUTH_BINDING]",
|
|
201
|
+
scope: "global",
|
|
202
|
+
scopeId: null,
|
|
203
|
+
active: true,
|
|
204
|
+
authKind: "oauth",
|
|
205
|
+
oauthProvider: "gmailSupport",
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
},
|
|
209
|
+
() => undefined,
|
|
210
|
+
[],
|
|
211
|
+
async () => "gmail-access-token",
|
|
212
|
+
);
|
|
213
|
+
patchFetchWithCredentialBroker(await broker.resolveBindings({}));
|
|
214
|
+
const api = createApiRegistryClient([
|
|
215
|
+
{
|
|
216
|
+
slug: "gmailSupport",
|
|
217
|
+
kind: "graphql",
|
|
218
|
+
baseUrl: "https://gmail.googleapis.com/gmail/v1/users/me/profile",
|
|
219
|
+
credential: {
|
|
220
|
+
configKey: "GMAIL_SUPPORT_OAUTH_BINDING",
|
|
221
|
+
headerTemplate: "Authorization: Bearer [REDACTED:GMAIL_SUPPORT_OAUTH_BINDING]",
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
]);
|
|
225
|
+
|
|
226
|
+
await api.gmailSupport.graphql("query { me { id } }");
|
|
227
|
+
|
|
228
|
+
expect(authorization).toBe("Bearer gmail-access-token");
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test("resolves config bindings via the config resolver even when oauthProvider metadata is present", async () => {
|
|
232
|
+
const oauthResolver = mock(async () => "should-not-be-used");
|
|
233
|
+
const broker = new CredentialBroker(
|
|
234
|
+
{
|
|
235
|
+
listActiveBindings: () => [
|
|
236
|
+
{
|
|
237
|
+
configKey: "VENDOR_CONFIG_KEY",
|
|
238
|
+
allowedHosts: ["api.vendor.test"],
|
|
239
|
+
headerTemplate: "Authorization: Bearer [REDACTED:VENDOR_CONFIG_KEY]",
|
|
240
|
+
scope: "global",
|
|
241
|
+
scopeId: null,
|
|
242
|
+
active: true,
|
|
243
|
+
authKind: "config",
|
|
244
|
+
oauthProvider: "vendorProvider",
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
},
|
|
248
|
+
(key) => (key === "VENDOR_CONFIG_KEY" ? "vendor-config-value" : undefined),
|
|
249
|
+
[],
|
|
250
|
+
oauthResolver,
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
const bindings = await broker.resolveBindings({});
|
|
254
|
+
|
|
255
|
+
expect(oauthResolver).not.toHaveBeenCalled();
|
|
256
|
+
expect(bindings).toEqual([
|
|
257
|
+
{
|
|
258
|
+
configKey: "VENDOR_CONFIG_KEY",
|
|
259
|
+
allowedHosts: ["api.vendor.test"],
|
|
260
|
+
headerTemplate: "Authorization: Bearer [REDACTED:VENDOR_CONFIG_KEY]",
|
|
261
|
+
scope: "global",
|
|
262
|
+
scopeId: null,
|
|
263
|
+
active: true,
|
|
264
|
+
authKind: "config",
|
|
265
|
+
oauthProvider: "vendorProvider",
|
|
266
|
+
placeholder: "[REDACTED:VENDOR_CONFIG_KEY]",
|
|
267
|
+
value: "vendor-config-value",
|
|
268
|
+
},
|
|
269
|
+
]);
|
|
270
|
+
});
|
|
271
|
+
|
|
145
272
|
test("registers resolved broker config values with the scrubber", async () => {
|
|
146
273
|
const bindingsConfig = upsertSwarmConfig({
|
|
147
274
|
scope: "global",
|
|
@@ -49,9 +49,9 @@ describe("runtime secret egress", () => {
|
|
|
49
49
|
|
|
50
50
|
describe("egress-substitution", () => {
|
|
51
51
|
describe("buildEgressSecrets", () => {
|
|
52
|
-
test("includes GITHUB_TOKEN when set in env", () => {
|
|
52
|
+
test("includes GITHUB_TOKEN when set in env", async () => {
|
|
53
53
|
process.env.GITHUB_TOKEN = "ghp_test1234567890abcdef";
|
|
54
|
-
const secrets = buildEgressSecrets();
|
|
54
|
+
const secrets = await buildEgressSecrets();
|
|
55
55
|
expect(secrets).toEqual([
|
|
56
56
|
{
|
|
57
57
|
configKey: "GITHUB_TOKEN",
|
|
@@ -67,9 +67,9 @@ describe("egress-substitution", () => {
|
|
|
67
67
|
]);
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
-
test("returns empty array when GITHUB_TOKEN not set", () => {
|
|
70
|
+
test("returns empty array when GITHUB_TOKEN not set", async () => {
|
|
71
71
|
delete process.env.GITHUB_TOKEN;
|
|
72
|
-
const secrets = buildEgressSecrets();
|
|
72
|
+
const secrets = await buildEgressSecrets();
|
|
73
73
|
expect(secrets).toEqual([]);
|
|
74
74
|
});
|
|
75
75
|
});
|