@qvac/harness 0.2.9 → 0.2.10
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 +15 -7
- package/dist/harness.bundle +7 -59
- package/dist/prebuilds-manifest.json +0 -8
- package/dist-lib/lib/capabilities/completion.d.ts +1 -0
- package/dist-lib/lib/capabilities/completion.js +66 -9
- package/dist-lib/lib/connect.js +2 -1
- package/dist-lib/lib/contract-types.d.ts +1 -0
- package/dist-lib/lib/docx/index.js +4 -27
- package/dist-lib/lib/hooks/built-in/index.d.ts +1 -0
- package/dist-lib/lib/hooks/built-in/index.js +1 -0
- package/dist-lib/lib/hooks/built-in/sandbox.d.ts +5 -0
- package/dist-lib/lib/hooks/built-in/sandbox.js +43 -0
- package/dist-lib/lib/hooks/built-in/skill-catalog.js +7 -2
- package/dist-lib/lib/hooks/registry.js +2 -1
- package/dist-lib/lib/hooks/types.d.ts +1 -0
- package/dist-lib/lib/office/index.d.ts +6 -0
- package/dist-lib/lib/office/index.js +38 -0
- package/dist-lib/lib/office/pptx.d.ts +1 -0
- package/dist-lib/lib/office/pptx.js +26 -0
- package/dist-lib/lib/office/python.d.ts +7 -0
- package/dist-lib/lib/office/python.js +32 -0
- package/dist-lib/lib/office/xlsx.d.ts +1 -0
- package/dist-lib/lib/office/xlsx.js +26 -0
- package/dist-lib/lib/tools/edit-image.js +1 -1
- package/dist-lib/lib/tools/generate-image.js +1 -1
- package/dist-lib/lib/tools/generate-music.js +1 -1
- package/dist-lib/lib/tools/http-request.js +3 -3
- package/dist-lib/lib/tools/mcp-call.js +3 -3
- package/dist-lib/lib/tools/skill.js +4 -2
- package/dist-lib/lib/tools/skills/auth-resolver.d.ts +1 -0
- package/dist-lib/lib/tools/skills/auth-resolver.js +59 -29
- package/dist-lib/lib/tools/toolsets.d.ts +1 -0
- package/dist-lib/lib/tools/toolsets.js +1 -0
- package/dist-lib/lib/tools/weather-lookup.js +9 -3
- package/dist-lib/lib/tools/web-fetch.js +6 -3
- package/dist-lib/lib/tools/web-search.js +5 -2
- package/dist-lib/schema/harness.js +2 -1
- package/dist-lib/spec/hrpc/messages.js +8 -5
- package/dist-lib/spec/hyperschema/index.js +8 -5
- package/dist-lib/spec/hyperschema/schema.json +6 -1
- package/dist-lib/spec/hyperschema/types.d.ts +2 -1
- package/package.json +5 -1
|
@@ -60,49 +60,79 @@ export function parseAuth(v) {
|
|
|
60
60
|
}
|
|
61
61
|
return { ok: true, value: { type: 'bearer', tokenCredentialKey: key } };
|
|
62
62
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
function grantedKeys(url, credentialAllowList) {
|
|
64
|
+
return Object.entries(credentialAllowList)
|
|
65
|
+
.filter(([, entry]) => urlAllowed(url, Array.isArray(entry) ? entry : [entry]))
|
|
66
|
+
.map(([key]) => key);
|
|
67
|
+
}
|
|
68
|
+
async function connectedCredentials(keys, credentialStore, ctx) {
|
|
69
|
+
const connected = [];
|
|
70
|
+
for (const key of keys) {
|
|
71
|
+
const record = credentialRecord(await credentialStore(key, ctx));
|
|
72
|
+
if (record)
|
|
73
|
+
connected.push({ token: record.token, key });
|
|
74
|
+
}
|
|
75
|
+
return connected;
|
|
76
|
+
}
|
|
77
|
+
function ambiguous(keys) {
|
|
78
|
+
return {
|
|
79
|
+
error: `multiple credentials match this URL; set auth.tokenCredentialKey to one of ${keys.join(', ')}`
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async function resolveGuessedKey(key, url, credentialStore, credentialAllowList, ctx) {
|
|
83
|
+
const granted = grantedKeys(url, credentialAllowList);
|
|
84
|
+
if (granted.length === 0) {
|
|
69
85
|
return {
|
|
70
|
-
error: `credential ${key}
|
|
86
|
+
error: `unknown credential key ${key}; no loaded skill grants a credential for ${url.host} — omit auth, or load the skill that declares it`
|
|
71
87
|
};
|
|
72
88
|
}
|
|
89
|
+
const [first, ...rest] = await connectedCredentials(granted, credentialStore, ctx);
|
|
90
|
+
if (!first) {
|
|
91
|
+
return {
|
|
92
|
+
error: `unknown credential key ${key}; no connected credential for ${url.host} (${granted.join(', ')}). Tell the user to connect it in Skills; do not retry`
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (rest.length > 0)
|
|
96
|
+
return ambiguous([first, ...rest].map((c) => c.key));
|
|
97
|
+
return first;
|
|
98
|
+
}
|
|
99
|
+
async function resolveDeclaredKey(key, url, credentialStore, credentialAllowList, ctx) {
|
|
100
|
+
const entry = credentialAllowList?.[key];
|
|
101
|
+
if (!entry)
|
|
102
|
+
return null;
|
|
73
103
|
const patterns = Array.isArray(entry) ? entry : [entry];
|
|
74
104
|
if (!urlAllowed(url, patterns)) {
|
|
75
105
|
return { error: `credential ${key} is not allowed for URL ${url.href}` };
|
|
76
106
|
}
|
|
77
107
|
const record = credentialRecord(await credentialStore(key, ctx));
|
|
78
|
-
if (!record)
|
|
79
|
-
return {
|
|
80
|
-
|
|
108
|
+
if (!record) {
|
|
109
|
+
return {
|
|
110
|
+
error: `credential ${key} is not connected for ${url.host}. Tell the user to connect it in Skills; do not retry`
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return { token: record.token, key };
|
|
114
|
+
}
|
|
115
|
+
export async function resolveAuth(auth, url, credentialStore, credentialAllowList, ctx) {
|
|
116
|
+
const key = auth.tokenCredentialKey;
|
|
117
|
+
if (!credentialStore)
|
|
118
|
+
return { error: 'credentials not configured' };
|
|
119
|
+
return ((await resolveDeclaredKey(key, url, credentialStore, credentialAllowList, ctx)) ??
|
|
120
|
+
resolveGuessedKey(key, url, credentialStore, credentialAllowList ?? {}, ctx));
|
|
81
121
|
}
|
|
82
122
|
export async function resolveAutoAuth(url, credentialStore, credentialAllowList, ctx) {
|
|
83
123
|
if (!credentialStore || !credentialAllowList)
|
|
84
124
|
return null;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
continue;
|
|
90
|
-
const record = credentialRecord(await credentialStore(key, ctx));
|
|
91
|
-
if (!record)
|
|
92
|
-
continue;
|
|
93
|
-
if (selected) {
|
|
94
|
-
return { error: 'multiple credentials match this URL; set auth.tokenCredentialKey' };
|
|
95
|
-
}
|
|
96
|
-
selected = { token: record.token, key };
|
|
97
|
-
}
|
|
98
|
-
return selected;
|
|
125
|
+
const connected = await connectedCredentials(grantedKeys(url, credentialAllowList), credentialStore, ctx);
|
|
126
|
+
if (connected.length > 1)
|
|
127
|
+
return ambiguous(connected.map((c) => c.key));
|
|
128
|
+
return connected[0] ?? null;
|
|
99
129
|
}
|
|
100
130
|
export async function resolveBearerHeader(auth, url, credentialStore, credentialAllowList, ctx, signal) {
|
|
101
131
|
if (auth) {
|
|
102
132
|
const resolved = await raceAbort(resolveAuth(auth, url, credentialStore, credentialAllowList, ctx), signal);
|
|
103
133
|
if ('error' in resolved)
|
|
104
134
|
return { error: resolved.error };
|
|
105
|
-
return { header: `Bearer ${resolved.token}`, credentialKey:
|
|
135
|
+
return { header: `Bearer ${resolved.token}`, credentialKey: resolved.key };
|
|
106
136
|
}
|
|
107
137
|
const resolved = await raceAbort(resolveAutoAuth(url, credentialStore, credentialAllowList, ctx), signal);
|
|
108
138
|
if (resolved && 'error' in resolved)
|
|
@@ -112,10 +142,10 @@ export async function resolveBearerHeader(auth, url, credentialStore, credential
|
|
|
112
142
|
: { header: null };
|
|
113
143
|
}
|
|
114
144
|
export async function resolveRedirectBearerHeader(auth, url, credentialStore, credentialAllowList, ctx, signal) {
|
|
115
|
-
if (!auth)
|
|
145
|
+
if (!auth || !credentialStore)
|
|
116
146
|
return { header: null };
|
|
117
|
-
const resolved = await raceAbort(
|
|
118
|
-
return 'error' in resolved
|
|
147
|
+
const resolved = await raceAbort(resolveDeclaredKey(auth.tokenCredentialKey, url, credentialStore, credentialAllowList, ctx), signal);
|
|
148
|
+
return !resolved || 'error' in resolved
|
|
119
149
|
? { header: null }
|
|
120
|
-
: { header: `Bearer ${resolved.token}`, credentialKey:
|
|
150
|
+
: { header: `Bearer ${resolved.token}`, credentialKey: resolved.key };
|
|
121
151
|
}
|
|
@@ -4,5 +4,6 @@ export declare function asToolset(value?: string | null): Toolset | null;
|
|
|
4
4
|
export interface ToolsetScoped {
|
|
5
5
|
toolset?: string | null;
|
|
6
6
|
}
|
|
7
|
+
export declare const NETWORK_TOOLSETS: ReadonlyArray<Toolset>;
|
|
7
8
|
export declare function permittedTools<T extends ToolsetScoped>(tools: ReadonlyArray<T>, disabled?: ReadonlyArray<string> | null): T[];
|
|
8
9
|
export declare function toolsetEnabled(toolset: Toolset, disabled?: ReadonlyArray<string> | null): boolean;
|
|
@@ -9,6 +9,7 @@ export const TOOLSETS = [
|
|
|
9
9
|
export function asToolset(value) {
|
|
10
10
|
return TOOLSETS.find((toolset) => toolset === value) ?? null;
|
|
11
11
|
}
|
|
12
|
+
export const NETWORK_TOOLSETS = ['web-search', 'http-request', 'mcp-call'];
|
|
12
13
|
export function permittedTools(tools, disabled) {
|
|
13
14
|
if (!disabled?.length)
|
|
14
15
|
return [...tools];
|
|
@@ -63,7 +63,7 @@ export function createWeatherLookupTool({ fetch: fetchImpl, resolveHost = lookup
|
|
|
63
63
|
if (/location not found/i.test(body))
|
|
64
64
|
return { content: notFound(location) };
|
|
65
65
|
if (response.status !== 200) {
|
|
66
|
-
return { error: unavailable(`it answered HTTP ${response.status}`) };
|
|
66
|
+
return { error: unavailable(`it answered HTTP ${response.status}`), code: 'transport' };
|
|
67
67
|
}
|
|
68
68
|
let json;
|
|
69
69
|
try {
|
|
@@ -91,9 +91,15 @@ export function createWeatherLookupTool({ fetch: fetchImpl, resolveHost = lookup
|
|
|
91
91
|
if (ctx?.signal?.aborted)
|
|
92
92
|
return { error: 'weather_lookup cancelled' };
|
|
93
93
|
if (controller.signal.aborted) {
|
|
94
|
-
return {
|
|
94
|
+
return {
|
|
95
|
+
error: `weather_lookup timed out after ${LOOKUP_TIMEOUT_MS} ms`,
|
|
96
|
+
code: 'timeout'
|
|
97
|
+
};
|
|
95
98
|
}
|
|
96
|
-
return {
|
|
99
|
+
return {
|
|
100
|
+
error: unavailable(err instanceof Error ? err.message : String(err)),
|
|
101
|
+
code: 'transport'
|
|
102
|
+
};
|
|
97
103
|
}
|
|
98
104
|
finally {
|
|
99
105
|
clearTimeout(timeout);
|
|
@@ -79,7 +79,10 @@ export function createWebFetchTool({ fetch: fetchImpl, resolveHost = lookupHost
|
|
|
79
79
|
return { error: got.error };
|
|
80
80
|
const { response, finalUrl: currentUrl } = got;
|
|
81
81
|
if (response.status < 200 || response.status >= 300) {
|
|
82
|
-
return {
|
|
82
|
+
return {
|
|
83
|
+
error: `HTTP ${response.status} fetching ${currentUrl.toString()}`,
|
|
84
|
+
status: response.status
|
|
85
|
+
};
|
|
83
86
|
}
|
|
84
87
|
const rawBody = await response.text();
|
|
85
88
|
const body = rawBody.length > MAX_HTML_CHARS ? rawBody.slice(0, MAX_HTML_CHARS) : rawBody;
|
|
@@ -140,9 +143,9 @@ export function createWebFetchTool({ fetch: fetchImpl, resolveHost = lookupHost
|
|
|
140
143
|
return { error: 'web_fetch cancelled' };
|
|
141
144
|
}
|
|
142
145
|
if (controller.signal.aborted) {
|
|
143
|
-
return { error: `${url.hostname} timed out after ${PAGE_TIMEOUT_MS}ms
|
|
146
|
+
return { error: `${url.hostname} timed out after ${PAGE_TIMEOUT_MS}ms`, code: 'timeout' };
|
|
144
147
|
}
|
|
145
|
-
return { error: err instanceof Error ? err.message : String(err) };
|
|
148
|
+
return { error: err instanceof Error ? err.message : String(err), code: 'transport' };
|
|
146
149
|
}
|
|
147
150
|
finally {
|
|
148
151
|
clearTimeout(timeout);
|
|
@@ -43,12 +43,15 @@ export function createWebSearchTool({ fetch } = {}) {
|
|
|
43
43
|
}
|
|
44
44
|
const failed = engineSummary.filter((e) => e.status !== 'ok').length;
|
|
45
45
|
if (engineSummary.length > 0 && failed === engineSummary.length) {
|
|
46
|
-
return {
|
|
46
|
+
return {
|
|
47
|
+
error: `web_search unavailable: all ${failed} engines failed (timeout/error)`,
|
|
48
|
+
code: 'transport'
|
|
49
|
+
};
|
|
47
50
|
}
|
|
48
51
|
return { content: `No web results found for "${query}".` };
|
|
49
52
|
}
|
|
50
53
|
catch (err) {
|
|
51
|
-
return { error: err instanceof Error ? err.message : String(err) };
|
|
54
|
+
return { error: err instanceof Error ? err.message : String(err), code: 'transport' };
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
};
|
|
@@ -23,7 +23,8 @@ export function registerHarnessTypes(ns) {
|
|
|
23
23
|
{ name: 'imageWidth', type: 'uint' },
|
|
24
24
|
{ name: 'imageHeight', type: 'uint' },
|
|
25
25
|
{ name: 'approvalMode', type: '@harness/approval-mode' },
|
|
26
|
-
{ name: 'disabledToolsets', type: 'string', array: true }
|
|
26
|
+
{ name: 'disabledToolsets', type: 'string', array: true },
|
|
27
|
+
{ name: 'sandboxMode', type: 'bool' }
|
|
27
28
|
]
|
|
28
29
|
});
|
|
29
30
|
ns.register({
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// This file is autogenerated by the hyperschema compiler
|
|
2
|
-
// Schema Version:
|
|
2
|
+
// Schema Version: 10
|
|
3
3
|
/* eslint-disable camelcase */
|
|
4
4
|
/* eslint-disable quotes */
|
|
5
5
|
/* eslint-disable space-before-function-paren */
|
|
6
6
|
|
|
7
7
|
import { c } from 'hyperschema/runtime'
|
|
8
8
|
|
|
9
|
-
const VERSION =
|
|
9
|
+
const VERSION = 10
|
|
10
10
|
|
|
11
11
|
// eslint-disable-next-line no-unused-vars
|
|
12
12
|
let version = VERSION
|
|
@@ -143,7 +143,8 @@ const encoding4 = {
|
|
|
143
143
|
(m.imageWidth ? 8192 : 0) |
|
|
144
144
|
(m.imageHeight ? 16384 : 0) |
|
|
145
145
|
((version >= 5 && m.approvalMode) ? 32768 : 0) |
|
|
146
|
-
((version >= 5 && m.disabledToolsets) ? 65536 : 0)
|
|
146
|
+
((version >= 5 && m.disabledToolsets) ? 65536 : 0) |
|
|
147
|
+
((version >= 10 && m.sandboxMode) ? 131072 : 0)
|
|
147
148
|
|
|
148
149
|
c.uint.preencode(state, flags)
|
|
149
150
|
|
|
@@ -183,7 +184,8 @@ const encoding4 = {
|
|
|
183
184
|
(m.imageWidth ? 8192 : 0) |
|
|
184
185
|
(m.imageHeight ? 16384 : 0) |
|
|
185
186
|
((version >= 5 && m.approvalMode) ? 32768 : 0) |
|
|
186
|
-
((version >= 5 && m.disabledToolsets) ? 65536 : 0)
|
|
187
|
+
((version >= 5 && m.disabledToolsets) ? 65536 : 0) |
|
|
188
|
+
((version >= 10 && m.sandboxMode) ? 131072 : 0)
|
|
187
189
|
|
|
188
190
|
c.uint.encode(state, flags)
|
|
189
191
|
|
|
@@ -225,7 +227,8 @@ const encoding4 = {
|
|
|
225
227
|
imageWidth: (flags & 8192) !== 0 ? c.uint.decode(state) : 0,
|
|
226
228
|
imageHeight: (flags & 16384) !== 0 ? c.uint.decode(state) : 0,
|
|
227
229
|
approvalMode: (version >= 5 && (flags & 32768) !== 0) ? encoding59.decode(state) : null,
|
|
228
|
-
disabledToolsets: (version >= 5 && (flags & 65536) !== 0) ? encoding4_16.decode(state) : null
|
|
230
|
+
disabledToolsets: (version >= 5 && (flags & 65536) !== 0) ? encoding4_16.decode(state) : null,
|
|
231
|
+
sandboxMode: (version >= 10 && (flags & 131072) !== 0)
|
|
229
232
|
}
|
|
230
233
|
}
|
|
231
234
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// This file is autogenerated by the hyperschema compiler
|
|
2
|
-
// Schema Version:
|
|
2
|
+
// Schema Version: 10
|
|
3
3
|
/* eslint-disable camelcase */
|
|
4
4
|
/* eslint-disable quotes */
|
|
5
5
|
/* eslint-disable space-before-function-paren */
|
|
6
6
|
|
|
7
7
|
import { c } from 'hyperschema/runtime'
|
|
8
8
|
|
|
9
|
-
const VERSION =
|
|
9
|
+
const VERSION = 10
|
|
10
10
|
|
|
11
11
|
// eslint-disable-next-line no-unused-vars
|
|
12
12
|
let version = VERSION
|
|
@@ -143,7 +143,8 @@ const encoding4 = {
|
|
|
143
143
|
(m.imageWidth ? 8192 : 0) |
|
|
144
144
|
(m.imageHeight ? 16384 : 0) |
|
|
145
145
|
((version >= 5 && m.approvalMode) ? 32768 : 0) |
|
|
146
|
-
((version >= 5 && m.disabledToolsets) ? 65536 : 0)
|
|
146
|
+
((version >= 5 && m.disabledToolsets) ? 65536 : 0) |
|
|
147
|
+
((version >= 10 && m.sandboxMode) ? 131072 : 0)
|
|
147
148
|
|
|
148
149
|
c.uint.preencode(state, flags)
|
|
149
150
|
|
|
@@ -183,7 +184,8 @@ const encoding4 = {
|
|
|
183
184
|
(m.imageWidth ? 8192 : 0) |
|
|
184
185
|
(m.imageHeight ? 16384 : 0) |
|
|
185
186
|
((version >= 5 && m.approvalMode) ? 32768 : 0) |
|
|
186
|
-
((version >= 5 && m.disabledToolsets) ? 65536 : 0)
|
|
187
|
+
((version >= 5 && m.disabledToolsets) ? 65536 : 0) |
|
|
188
|
+
((version >= 10 && m.sandboxMode) ? 131072 : 0)
|
|
187
189
|
|
|
188
190
|
c.uint.encode(state, flags)
|
|
189
191
|
|
|
@@ -225,7 +227,8 @@ const encoding4 = {
|
|
|
225
227
|
imageWidth: (flags & 8192) !== 0 ? c.uint.decode(state) : 0,
|
|
226
228
|
imageHeight: (flags & 16384) !== 0 ? c.uint.decode(state) : 0,
|
|
227
229
|
approvalMode: (version >= 5 && (flags & 32768) !== 0) ? encoding59.decode(state) : null,
|
|
228
|
-
disabledToolsets: (version >= 5 && (flags & 65536) !== 0) ? encoding4_16.decode(state) : null
|
|
230
|
+
disabledToolsets: (version >= 5 && (flags & 65536) !== 0) ? encoding4_16.decode(state) : null,
|
|
231
|
+
sandboxMode: (version >= 10 && (flags & 131072) !== 0)
|
|
229
232
|
}
|
|
230
233
|
}
|
|
231
234
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version":
|
|
2
|
+
"version": 10,
|
|
3
3
|
"schema": [
|
|
4
4
|
{
|
|
5
5
|
"name": "empty",
|
|
@@ -151,6 +151,11 @@
|
|
|
151
151
|
"array": true,
|
|
152
152
|
"type": "string",
|
|
153
153
|
"version": 5
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"name": "sandboxMode",
|
|
157
|
+
"type": "bool",
|
|
158
|
+
"version": 10
|
|
154
159
|
}
|
|
155
160
|
]
|
|
156
161
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// This file is autogenerated by hyperschema-ts
|
|
2
|
-
// Schema version:
|
|
2
|
+
// Schema version: 10
|
|
3
3
|
// Do not edit manually.
|
|
4
4
|
|
|
5
5
|
export interface HarnessEmpty {
|
|
@@ -31,6 +31,7 @@ export interface HarnessAgentKnobs {
|
|
|
31
31
|
imageHeight?: number
|
|
32
32
|
approvalMode?: HarnessApprovalMode | null
|
|
33
33
|
disabledToolsets?: string[] | null
|
|
34
|
+
sandboxMode?: boolean
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
export type HarnessMessageRole = "system" | "user" | "assistant" | "tool"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qvac/harness",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "An AI harness implementing generate(context) via @qvac/sdk. Knows nothing about workbench, hyperdb, or chunks — just inference in, events out.",
|
|
6
6
|
"exports": {
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
"types": "./dist-lib/lib/docx/index.d.ts",
|
|
13
13
|
"default": "./dist-lib/lib/docx/index.js"
|
|
14
14
|
},
|
|
15
|
+
"./office": {
|
|
16
|
+
"types": "./dist-lib/lib/office/index.d.ts",
|
|
17
|
+
"default": "./dist-lib/lib/office/index.js"
|
|
18
|
+
},
|
|
15
19
|
"./lib/dns-lookup.ts": {
|
|
16
20
|
"types": "./dist-lib/lib/dns-lookup.d.ts",
|
|
17
21
|
"default": "./dist-lib/lib/dns-lookup.js"
|