@slashfi/agents-sdk 0.90.1 → 0.90.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/adk.js +61 -11
- package/dist/adk.js.map +1 -1
- package/dist/cjs/config-store.js +227 -33
- package/dist/cjs/config-store.js.map +1 -1
- package/dist/cjs/define-config.js.map +1 -1
- package/dist/cjs/registry-consumer.js +10 -1
- package/dist/cjs/registry-consumer.js.map +1 -1
- package/dist/config-store.d.ts +36 -0
- package/dist/config-store.d.ts.map +1 -1
- package/dist/config-store.js +227 -33
- package/dist/config-store.js.map +1 -1
- package/dist/define-config.d.ts +4 -0
- package/dist/define-config.d.ts.map +1 -1
- package/dist/define-config.js.map +1 -1
- package/dist/registry-consumer.d.ts.map +1 -1
- package/dist/registry-consumer.js +10 -1
- package/dist/registry-consumer.js.map +1 -1
- package/package.json +1 -1
- package/src/adk.ts +61 -13
- package/src/config-store.test.ts +350 -0
- package/src/config-store.ts +316 -36
- package/src/consumer.test.ts +54 -0
- package/src/define-config.ts +1 -0
- package/src/registry-consumer.ts +10 -1
package/dist/cjs/config-store.js
CHANGED
|
@@ -238,7 +238,7 @@ function renderCredentialForm(name, fields, error) {
|
|
|
238
238
|
<div class="field">
|
|
239
239
|
<label for="${esc(f.name)}">${esc(f.label)}</label>
|
|
240
240
|
${f.description ? `<p class="desc">${esc(f.description)}</p>` : ""}
|
|
241
|
-
<input id="${esc(f.name)}" name="${esc(f.name)}" type="${f.secret ? "password" : "text"}" required autocomplete="off" spellcheck="false" />
|
|
241
|
+
<input id="${esc(f.name)}" name="${esc(f.name)}" type="${f.secret ? "password" : "text"}" ${f.optional ? "" : "required"} autocomplete="off" spellcheck="false" />
|
|
242
242
|
</div>`)
|
|
243
243
|
.join("");
|
|
244
244
|
const errorHtml = error ? `<div class="error">${esc(error)}</div>` : "";
|
|
@@ -480,6 +480,159 @@ function createAdk(fs, options = {}) {
|
|
|
480
480
|
});
|
|
481
481
|
};
|
|
482
482
|
}
|
|
483
|
+
/**
|
|
484
|
+
* Call-time credential lookup: stored ref config first, then the host
|
|
485
|
+
* `resolveCredentials` callback. Does not persist resolved values.
|
|
486
|
+
*/
|
|
487
|
+
async function resolveCallCredential(ctx, field) {
|
|
488
|
+
const stored = await readRefSecret(ctx.name, field);
|
|
489
|
+
if (stored)
|
|
490
|
+
return stored;
|
|
491
|
+
return makeTryResolve(ctx)(field);
|
|
492
|
+
}
|
|
493
|
+
const CALL_BEARER_FIELDS = ["access_token", "api_key", "token"];
|
|
494
|
+
function isBearerAuthField(field) {
|
|
495
|
+
return CALL_BEARER_FIELDS.includes(field);
|
|
496
|
+
}
|
|
497
|
+
/** Legacy cache entries may omit `outbound`; these are never call-time creds. */
|
|
498
|
+
const LEGACY_CONNECT_ONLY_FIELDS = new Set([
|
|
499
|
+
"client_id",
|
|
500
|
+
"client_secret",
|
|
501
|
+
"refresh_token",
|
|
502
|
+
]);
|
|
503
|
+
function isCallOutboundAuthField(field, info) {
|
|
504
|
+
if (info.outbound === false)
|
|
505
|
+
return false;
|
|
506
|
+
if (info.outbound === true)
|
|
507
|
+
return true;
|
|
508
|
+
return !LEGACY_CONNECT_ONLY_FIELDS.has(field);
|
|
509
|
+
}
|
|
510
|
+
function readRegistryDeclaredAuthFields(security) {
|
|
511
|
+
if (!security || typeof security !== "object")
|
|
512
|
+
return undefined;
|
|
513
|
+
const raw = security.authFields;
|
|
514
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
515
|
+
return undefined;
|
|
516
|
+
const out = {};
|
|
517
|
+
for (const [field, meta] of Object.entries(raw)) {
|
|
518
|
+
if (!meta || typeof meta !== "object" || Array.isArray(meta))
|
|
519
|
+
continue;
|
|
520
|
+
const m = meta;
|
|
521
|
+
if (typeof m.required !== "boolean" || typeof m.automated !== "boolean") {
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
out[field] = { required: m.required, automated: m.automated };
|
|
525
|
+
if (typeof m.outbound === "boolean") {
|
|
526
|
+
out[field].outbound = m.outbound;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
530
|
+
}
|
|
531
|
+
async function mergeRegistryDeclaredAuthFields(fields, declared, canResolve, configKeys, refConfig) {
|
|
532
|
+
if (!declared)
|
|
533
|
+
return fields;
|
|
534
|
+
const next = {};
|
|
535
|
+
for (const [field, meta] of Object.entries(declared)) {
|
|
536
|
+
next[field] = {
|
|
537
|
+
required: meta.required,
|
|
538
|
+
automated: meta.automated,
|
|
539
|
+
present: configKeys.includes(field) || hasCredentialField(refConfig, field),
|
|
540
|
+
resolvable: await canResolve(field),
|
|
541
|
+
...(meta.format && { format: meta.format }),
|
|
542
|
+
...(meta.parts && { parts: meta.parts }),
|
|
543
|
+
...(meta.outbound === false && { outbound: false }),
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
return next;
|
|
547
|
+
}
|
|
548
|
+
function bearerFieldSatisfied(accessToken, refConfig, field) {
|
|
549
|
+
if (accessToken)
|
|
550
|
+
return true;
|
|
551
|
+
return hasCredentialField(refConfig, field);
|
|
552
|
+
}
|
|
553
|
+
function fallbackCallAuthFields() {
|
|
554
|
+
return {
|
|
555
|
+
access_token: { required: true, automated: true },
|
|
556
|
+
api_key: { required: false, automated: true },
|
|
557
|
+
token: { required: false, automated: true },
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
function headerFieldSatisfied(headers, field) {
|
|
561
|
+
const wanted = normalizeCredentialKey(field);
|
|
562
|
+
return Object.keys(headers).some((key) => normalizeCredentialKey(key) === wanted);
|
|
563
|
+
}
|
|
564
|
+
function resolveHeaderNameForField(field, refConfig) {
|
|
565
|
+
const wanted = normalizeCredentialKey(field);
|
|
566
|
+
const configHeaders = refConfig.headers;
|
|
567
|
+
if (configHeaders &&
|
|
568
|
+
typeof configHeaders === "object" &&
|
|
569
|
+
!Array.isArray(configHeaders)) {
|
|
570
|
+
for (const key of Object.keys(configHeaders)) {
|
|
571
|
+
if (normalizeCredentialKey(key) === wanted)
|
|
572
|
+
return key;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
// x_api_key → X-API-KEY (registry codegen declares the canonical name;
|
|
576
|
+
// env-resolved keys use the normalized storage field name).
|
|
577
|
+
return field
|
|
578
|
+
.split("_")
|
|
579
|
+
.filter(Boolean)
|
|
580
|
+
.map((part) => part.toUpperCase())
|
|
581
|
+
.join("-");
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Supplement call-time credentials from `resolveCredentials` when they
|
|
585
|
+
* are not already present in consumer-config. Stored values and config
|
|
586
|
+
* headers win — this only fills gaps. Walks cached `authFields` as the
|
|
587
|
+
* source of truth (registry-declared when auth-status has run).
|
|
588
|
+
*/
|
|
589
|
+
async function resolveAllCallCredentials(opts) {
|
|
590
|
+
if (!options.resolveCredentials) {
|
|
591
|
+
return {
|
|
592
|
+
accessToken: opts.accessToken,
|
|
593
|
+
resolvedHeaders: opts.resolvedHeaders,
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
let accessToken = opts.accessToken;
|
|
597
|
+
let resolvedHeaders = opts.resolvedHeaders;
|
|
598
|
+
const { ctx, refConfig } = opts;
|
|
599
|
+
const cache = await readRegistryCache();
|
|
600
|
+
const authFields = cache.refs[ctx.name]?.authFields ?? fallbackCallAuthFields();
|
|
601
|
+
for (const [field, info] of Object.entries(authFields)) {
|
|
602
|
+
if (!isCallOutboundAuthField(field, info))
|
|
603
|
+
continue;
|
|
604
|
+
if (!info.required && !info.automated)
|
|
605
|
+
continue;
|
|
606
|
+
if (isBearerAuthField(field)) {
|
|
607
|
+
if (bearerFieldSatisfied(accessToken, refConfig, field))
|
|
608
|
+
continue;
|
|
609
|
+
const value = await resolveCallCredential(ctx, field);
|
|
610
|
+
if (value)
|
|
611
|
+
accessToken = accessToken ?? value;
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
if (hasCredentialField(refConfig, field))
|
|
615
|
+
continue;
|
|
616
|
+
if (resolvedHeaders && headerFieldSatisfied(resolvedHeaders, field)) {
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
const value = await resolveCallCredential(ctx, field);
|
|
620
|
+
if (!value)
|
|
621
|
+
continue;
|
|
622
|
+
resolvedHeaders = resolvedHeaders ?? {};
|
|
623
|
+
if (!headerFieldSatisfied(resolvedHeaders, field)) {
|
|
624
|
+
resolvedHeaders[resolveHeaderNameForField(field, refConfig)] = value;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
if (!accessToken) {
|
|
628
|
+
const username = await resolveCallCredential(ctx, "username");
|
|
629
|
+
const password = await resolveCallCredential(ctx, "password");
|
|
630
|
+
if (username && password) {
|
|
631
|
+
accessToken = btoa(`${username}:${password}`);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return { accessToken, resolvedHeaders };
|
|
635
|
+
}
|
|
483
636
|
/**
|
|
484
637
|
* Resolve OAuth client credentials (client_id + client_secret) for a
|
|
485
638
|
* ref. Walks: `resolveCredentials` callback → per-ref VCS storage.
|
|
@@ -766,11 +919,15 @@ function createAdk(fs, options = {}) {
|
|
|
766
919
|
return r;
|
|
767
920
|
found = true;
|
|
768
921
|
const existing = typeof r === "string" ? { url: r } : { ...r };
|
|
769
|
-
mutate(existing);
|
|
770
922
|
return existing;
|
|
771
923
|
});
|
|
772
924
|
if (!found)
|
|
773
925
|
return false;
|
|
926
|
+
for (const r of registries) {
|
|
927
|
+
if (typeof r !== "string" && (registryDisplayName(r) === nameOrUrl || registryUrl(r) === nameOrUrl)) {
|
|
928
|
+
await mutate(r);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
774
931
|
await writeConfig({ ...config, registries });
|
|
775
932
|
return true;
|
|
776
933
|
}
|
|
@@ -865,6 +1022,7 @@ function createAdk(fs, options = {}) {
|
|
|
865
1022
|
return;
|
|
866
1023
|
const hasUsableAuth = entry.auth && entry.auth.type !== "none"
|
|
867
1024
|
? (entry.auth.type === "bearer" && !!entry.auth.token) ||
|
|
1025
|
+
(entry.auth.type === "basic" && !!entry.auth.username) ||
|
|
868
1026
|
(entry.auth.type === "api-key" && !!entry.auth.key)
|
|
869
1027
|
: false;
|
|
870
1028
|
if (hasUsableAuth)
|
|
@@ -898,6 +1056,7 @@ function createAdk(fs, options = {}) {
|
|
|
898
1056
|
let authRequirement;
|
|
899
1057
|
const hasUsableAuth = entry.auth && entry.auth.type !== "none"
|
|
900
1058
|
? (entry.auth.type === "bearer" && !!entry.auth.token) ||
|
|
1059
|
+
(entry.auth.type === "basic" && !!entry.auth.username) ||
|
|
901
1060
|
(entry.auth.type === "api-key" && !!entry.auth.key)
|
|
902
1061
|
: false;
|
|
903
1062
|
if (!hasUsableAuth) {
|
|
@@ -994,6 +1153,7 @@ function createAdk(fs, options = {}) {
|
|
|
994
1153
|
if (typeof r !== "string" && r.authRequirement) {
|
|
995
1154
|
const hasUsableAuth = r.auth && r.auth.type !== "none"
|
|
996
1155
|
? (r.auth.type === "bearer" && !!r.auth.token) ||
|
|
1156
|
+
(r.auth.type === "basic" && !!r.auth.username) ||
|
|
997
1157
|
(r.auth.type === "api-key" && !!r.auth.key)
|
|
998
1158
|
: false;
|
|
999
1159
|
if (!hasUsableAuth) {
|
|
@@ -1030,23 +1190,29 @@ function createAdk(fs, options = {}) {
|
|
|
1030
1190
|
});
|
|
1031
1191
|
},
|
|
1032
1192
|
async auth(nameOrUrl, credential) {
|
|
1033
|
-
// Encrypt
|
|
1034
|
-
//
|
|
1035
|
-
const
|
|
1036
|
-
? await protectSecret(credential.token)
|
|
1037
|
-
: await protectSecret(credential.apiKey);
|
|
1038
|
-
const updated = await updateRegistryEntry(nameOrUrl, (existing) => {
|
|
1193
|
+
// Encrypt secret values before writing. `buildConsumer` decrypts on the
|
|
1194
|
+
// read side via `decryptConfigSecrets`.
|
|
1195
|
+
const updated = await updateRegistryEntry(nameOrUrl, async (existing) => {
|
|
1039
1196
|
if ("token" in credential) {
|
|
1040
1197
|
existing.auth = {
|
|
1041
1198
|
type: "bearer",
|
|
1042
|
-
token:
|
|
1199
|
+
token: await protectSecret(credential.token),
|
|
1043
1200
|
...(credential.tokenUrl && { tokenUrl: credential.tokenUrl }),
|
|
1044
1201
|
};
|
|
1045
1202
|
}
|
|
1203
|
+
else if ("username" in credential) {
|
|
1204
|
+
existing.auth = {
|
|
1205
|
+
type: "basic",
|
|
1206
|
+
username: await protectSecret(credential.username),
|
|
1207
|
+
...(credential.password && {
|
|
1208
|
+
password: await protectSecret(credential.password),
|
|
1209
|
+
}),
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1046
1212
|
else {
|
|
1047
1213
|
existing.auth = {
|
|
1048
1214
|
type: "api-key",
|
|
1049
|
-
key:
|
|
1215
|
+
key: await protectSecret(credential.apiKey),
|
|
1050
1216
|
...(credential.header && { header: credential.header }),
|
|
1051
1217
|
};
|
|
1052
1218
|
}
|
|
@@ -1097,6 +1263,7 @@ function createAdk(fs, options = {}) {
|
|
|
1097
1263
|
// Already authenticated — nothing to do (unless forced above).
|
|
1098
1264
|
const hasUsableAuth = target.auth && target.auth.type !== "none"
|
|
1099
1265
|
? (target.auth.type === "bearer" && !!target.auth.token) ||
|
|
1266
|
+
(target.auth.type === "basic" && !!target.auth.username) ||
|
|
1100
1267
|
(target.auth.type === "api-key" && !!target.auth.key)
|
|
1101
1268
|
: false;
|
|
1102
1269
|
if (hasUsableAuth && !target.authRequirement) {
|
|
@@ -1528,7 +1695,7 @@ function createAdk(fs, options = {}) {
|
|
|
1528
1695
|
const entry = findRef(config.refs ?? [], name);
|
|
1529
1696
|
if (!entry)
|
|
1530
1697
|
throw new Error(`Ref "${name}" not found`);
|
|
1531
|
-
|
|
1698
|
+
let accessToken = (await readRefSecret(name, "access_token")) ??
|
|
1532
1699
|
(await readRefSecret(name, "api_key")) ??
|
|
1533
1700
|
(await readRefSecret(name, "token"));
|
|
1534
1701
|
// Resolve custom headers from config (e.g. { "X-API-Key": "secret:..." })
|
|
@@ -1575,6 +1742,16 @@ function createAdk(fs, options = {}) {
|
|
|
1575
1742
|
}
|
|
1576
1743
|
}
|
|
1577
1744
|
}
|
|
1745
|
+
if (options.resolveCredentials) {
|
|
1746
|
+
const supplemented = await resolveAllCallCredentials({
|
|
1747
|
+
ctx: { name, entry, security: null },
|
|
1748
|
+
refConfig,
|
|
1749
|
+
accessToken,
|
|
1750
|
+
resolvedHeaders,
|
|
1751
|
+
});
|
|
1752
|
+
accessToken = supplemented.accessToken;
|
|
1753
|
+
resolvedHeaders = supplemented.resolvedHeaders;
|
|
1754
|
+
}
|
|
1578
1755
|
const doCall = async (token) => {
|
|
1579
1756
|
// Direct MCP only for redirect/proxy agents with an MCP upstream.
|
|
1580
1757
|
// API-mode agents must go through the registry (it does REST translation).
|
|
@@ -1686,7 +1863,7 @@ function createAdk(fs, options = {}) {
|
|
|
1686
1863
|
async function canResolve(field, oauthMetadata) {
|
|
1687
1864
|
return (await tryResolveField(field, oauthMetadata)) !== null;
|
|
1688
1865
|
}
|
|
1689
|
-
|
|
1866
|
+
let fields = {};
|
|
1690
1867
|
if (security.type === "oauth2") {
|
|
1691
1868
|
const securityExt = security;
|
|
1692
1869
|
const hasRegistration = !!securityExt.dynamicRegistration;
|
|
@@ -1720,6 +1897,7 @@ function createAdk(fs, options = {}) {
|
|
|
1720
1897
|
automated: hasRegistration,
|
|
1721
1898
|
present: configKeys.includes("client_id"),
|
|
1722
1899
|
resolvable: await canResolve("client_id", oauthMetadata),
|
|
1900
|
+
outbound: false,
|
|
1723
1901
|
};
|
|
1724
1902
|
if (needsSecret) {
|
|
1725
1903
|
fields.client_secret = {
|
|
@@ -1727,13 +1905,14 @@ function createAdk(fs, options = {}) {
|
|
|
1727
1905
|
automated: hasRegistration,
|
|
1728
1906
|
present: configKeys.includes("client_secret"),
|
|
1729
1907
|
resolvable: await canResolve("client_secret", oauthMetadata),
|
|
1908
|
+
outbound: false,
|
|
1730
1909
|
};
|
|
1731
1910
|
}
|
|
1732
1911
|
fields.access_token = {
|
|
1733
1912
|
required: true,
|
|
1734
1913
|
automated: accessTokenAutomated,
|
|
1735
1914
|
present: configKeys.includes("access_token"),
|
|
1736
|
-
resolvable:
|
|
1915
|
+
resolvable: await canResolve("access_token"),
|
|
1737
1916
|
};
|
|
1738
1917
|
}
|
|
1739
1918
|
else if (security.type === "apiKey") {
|
|
@@ -1776,11 +1955,23 @@ function createAdk(fs, options = {}) {
|
|
|
1776
1955
|
}
|
|
1777
1956
|
}
|
|
1778
1957
|
else if (security.type === "http") {
|
|
1958
|
+
const httpSec = security;
|
|
1959
|
+
const isBasic = httpSec.scheme === "basic";
|
|
1779
1960
|
fields.token = {
|
|
1780
1961
|
required: true,
|
|
1781
1962
|
automated: false,
|
|
1782
1963
|
present: configKeys.includes("token"),
|
|
1783
|
-
resolvable:
|
|
1964
|
+
resolvable: isBasic
|
|
1965
|
+
? (await canResolve("username")) &&
|
|
1966
|
+
(await tryResolveField("password")) !== null
|
|
1967
|
+
: await canResolve("token"),
|
|
1968
|
+
...(isBasic && {
|
|
1969
|
+
format: "basic",
|
|
1970
|
+
parts: [
|
|
1971
|
+
{ name: "username", label: "Username", secret: false },
|
|
1972
|
+
{ name: "password", label: "Password", secret: true, optional: true },
|
|
1973
|
+
],
|
|
1974
|
+
}),
|
|
1784
1975
|
};
|
|
1785
1976
|
}
|
|
1786
1977
|
else if (security.type === "form") {
|
|
@@ -1799,7 +1990,8 @@ function createAdk(fs, options = {}) {
|
|
|
1799
1990
|
resolvable: await canResolve("access_token"),
|
|
1800
1991
|
};
|
|
1801
1992
|
}
|
|
1802
|
-
|
|
1993
|
+
fields = await mergeRegistryDeclaredAuthFields(fields, readRegistryDeclaredAuthFields(security), canResolve, configKeys, (entry.config ?? {}));
|
|
1994
|
+
const complete = Object.values(fields).every((f) => !f.required || f.automated || f.present || f.resolvable);
|
|
1803
1995
|
// Persist the slim {required, automated} per-field shape into the
|
|
1804
1996
|
// registry cache so `isRefAuthComplete` can answer subsequent
|
|
1805
1997
|
// host-side "is this ref ready?" checks without re-fetching the
|
|
@@ -1811,6 +2003,9 @@ function createAdk(fs, options = {}) {
|
|
|
1811
2003
|
authFields[field] = {
|
|
1812
2004
|
required: info.required,
|
|
1813
2005
|
automated: info.automated,
|
|
2006
|
+
...(info.format && { format: info.format }),
|
|
2007
|
+
...(info.parts && { parts: info.parts }),
|
|
2008
|
+
...(info.outbound === false && { outbound: false }),
|
|
1814
2009
|
};
|
|
1815
2010
|
}
|
|
1816
2011
|
await upsertRegistryCacheAuthFields(name, entry.ref, authFields);
|
|
@@ -1908,24 +2103,23 @@ function createAdk(fs, options = {}) {
|
|
|
1908
2103
|
const isBasic = httpSec.scheme === "basic";
|
|
1909
2104
|
if (isBasic) {
|
|
1910
2105
|
const username = opts?.credentials?.["username"] ?? (await tryResolve("username"));
|
|
1911
|
-
const password = opts?.credentials?.["password"] ?? (await tryResolve("password"));
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
});
|
|
1926
|
-
return { type: "http", complete: false, fields: missingFields };
|
|
2106
|
+
const password = opts?.credentials?.["password"] ?? (await tryResolve("password")) ?? "";
|
|
2107
|
+
const hasUsername = username !== undefined && username !== null && username !== "";
|
|
2108
|
+
if (!hasUsername) {
|
|
2109
|
+
return {
|
|
2110
|
+
type: "http",
|
|
2111
|
+
complete: false,
|
|
2112
|
+
fields: [
|
|
2113
|
+
{
|
|
2114
|
+
name: "username",
|
|
2115
|
+
label: "Username",
|
|
2116
|
+
secret: false,
|
|
2117
|
+
},
|
|
2118
|
+
],
|
|
2119
|
+
};
|
|
1927
2120
|
}
|
|
1928
|
-
// Store as base64 encoded basic auth token
|
|
2121
|
+
// Store as base64 encoded basic auth token. Password may be blank
|
|
2122
|
+
// for APIs that use the Basic username slot as an API key.
|
|
1929
2123
|
const token = btoa(`${username}:${password}`);
|
|
1930
2124
|
await storeRefSecret(name, "token", token);
|
|
1931
2125
|
return { type: "http", complete: true };
|
|
@@ -2101,7 +2295,7 @@ function createAdk(fs, options = {}) {
|
|
|
2101
2295
|
const credentials = {};
|
|
2102
2296
|
for (const field of result.fields) {
|
|
2103
2297
|
const val = params.get(field.name);
|
|
2104
|
-
if (val)
|
|
2298
|
+
if (val !== null)
|
|
2105
2299
|
credentials[field.name] = val;
|
|
2106
2300
|
}
|
|
2107
2301
|
try {
|