@2kw/ai 7.3.0-dev.9 → 7.3.1
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.
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
* Kept as a TS constant: package.json `files` publishes only dist JS/d.ts.
|
|
6
6
|
*/
|
|
7
7
|
export declare const AGENT_SCHEMA_ID = "https://docs.2kw.ai/schemas/agent.v1.json";
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Types the backend injects or cannot execute; authoring them has no effect or breaks the run.
|
|
10
|
+
* The backend refuses the same map on save (NonAuthorableTools, #1263); its test fails if they differ.
|
|
11
|
+
*/
|
|
9
12
|
export declare const NON_AUTHORABLE_TOOL_TYPES: Record<string, string>;
|
|
10
13
|
export declare const agentSchema: {
|
|
11
14
|
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
@@ -209,6 +212,35 @@ export declare const agentSchema: {
|
|
|
209
212
|
};
|
|
210
213
|
};
|
|
211
214
|
};
|
|
215
|
+
readonly webFetchTool: {
|
|
216
|
+
readonly type: "object";
|
|
217
|
+
readonly additionalProperties: false;
|
|
218
|
+
readonly required: readonly ["type"];
|
|
219
|
+
readonly properties: {
|
|
220
|
+
readonly type: {
|
|
221
|
+
readonly const: "web_fetch";
|
|
222
|
+
};
|
|
223
|
+
readonly config: {
|
|
224
|
+
readonly type: "object";
|
|
225
|
+
readonly properties: {
|
|
226
|
+
readonly source: {
|
|
227
|
+
readonly enum: readonly ["proxy", "native"];
|
|
228
|
+
};
|
|
229
|
+
readonly allowedDomains: {
|
|
230
|
+
readonly type: "array";
|
|
231
|
+
readonly items: {
|
|
232
|
+
readonly type: "string";
|
|
233
|
+
readonly pattern: "^(?=.{1,253}$)([\\p{L}\\p{N}](?:[\\p{L}\\p{N}-]{0,61}[\\p{L}\\p{N}])?\\.)+\\p{L}(?:[\\p{L}\\p{N}-]{0,61}[\\p{L}\\p{N}])?$";
|
|
234
|
+
};
|
|
235
|
+
readonly maxItems: 10;
|
|
236
|
+
};
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
readonly requiresConfirmation: {
|
|
240
|
+
readonly type: "boolean";
|
|
241
|
+
};
|
|
242
|
+
};
|
|
243
|
+
};
|
|
212
244
|
readonly extractionTool: {
|
|
213
245
|
readonly type: "object";
|
|
214
246
|
readonly additionalProperties: false;
|
|
@@ -389,6 +421,18 @@ export declare const agentSchema: {
|
|
|
389
421
|
readonly then: {
|
|
390
422
|
readonly $ref: "#/$defs/webSearchTool";
|
|
391
423
|
};
|
|
424
|
+
}, {
|
|
425
|
+
readonly if: {
|
|
426
|
+
required: string[];
|
|
427
|
+
properties: {
|
|
428
|
+
type: {
|
|
429
|
+
const: string;
|
|
430
|
+
};
|
|
431
|
+
};
|
|
432
|
+
};
|
|
433
|
+
readonly then: {
|
|
434
|
+
readonly $ref: "#/$defs/webFetchTool";
|
|
435
|
+
};
|
|
392
436
|
}, {
|
|
393
437
|
readonly if: {
|
|
394
438
|
required: string[];
|
|
@@ -20,9 +20,13 @@ const MODEL_REF = {
|
|
|
20
20
|
// inner hyphens, Unicode or ASCII. Mirrors WebToolEntryValidator.HOST; needs a Unicode-aware regex engine.
|
|
21
21
|
const HOSTNAME = "^(?=.{1,253}$)([\\p{L}\\p{N}](?:[\\p{L}\\p{N}-]{0,61}[\\p{L}\\p{N}])?\\.)+\\p{L}(?:[\\p{L}\\p{N}-]{0,61}[\\p{L}\\p{N}])?$";
|
|
22
22
|
const oneOfLowercase = (...values) => ({ type: "string", enum: values });
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Types the backend injects or cannot execute; authoring them has no effect or breaks the run.
|
|
25
|
+
* The backend refuses the same map on save (NonAuthorableTools, #1263); its test fails if they differ.
|
|
26
|
+
*/
|
|
24
27
|
export const NON_AUTHORABLE_TOOL_TYPES = {
|
|
25
|
-
"backbone.tool_search": "
|
|
28
|
+
"backbone.tool_search": "it is added automatically when tool discovery is on",
|
|
29
|
+
"backbone.tool_call": "it is added automatically when tool discovery is on",
|
|
26
30
|
"backbone.skill_read": "it is added at run time when skills are pinned",
|
|
27
31
|
// #944: SkillsetPinner injects it for eligible callers and strips any stored copy (#779).
|
|
28
32
|
"backbone.skills_apply": "it is added at run time for callers allowed to author skills",
|
|
@@ -34,6 +38,7 @@ export const NON_AUTHORABLE_TOOL_TYPES = {
|
|
|
34
38
|
const BUILTIN_TYPES = [
|
|
35
39
|
"file_search",
|
|
36
40
|
"web_search",
|
|
41
|
+
"web_fetch",
|
|
37
42
|
"backbone.extraction",
|
|
38
43
|
"backbone.document_convert",
|
|
39
44
|
"backbone.todo",
|
|
@@ -150,6 +155,24 @@ export const agentSchema = {
|
|
|
150
155
|
requiresConfirmation: { type: "boolean" },
|
|
151
156
|
},
|
|
152
157
|
},
|
|
158
|
+
// Backbone's own fetcher reads a page the user or an earlier search named. A missing config, `config: {}`
|
|
159
|
+
// or a missing source is the proxy; `native` is accepted and answers provider_unavailable until it ships.
|
|
160
|
+
webFetchTool: {
|
|
161
|
+
type: "object",
|
|
162
|
+
additionalProperties: false,
|
|
163
|
+
required: ["type"],
|
|
164
|
+
properties: {
|
|
165
|
+
type: { const: "web_fetch" },
|
|
166
|
+
config: {
|
|
167
|
+
type: "object",
|
|
168
|
+
properties: {
|
|
169
|
+
source: { enum: ["proxy", "native"] },
|
|
170
|
+
allowedDomains: { type: "array", items: { type: "string", pattern: HOSTNAME }, maxItems: 10 },
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
requiresConfirmation: { type: "boolean" },
|
|
174
|
+
},
|
|
175
|
+
},
|
|
153
176
|
extractionTool: {
|
|
154
177
|
type: "object",
|
|
155
178
|
additionalProperties: false,
|
|
@@ -237,6 +260,7 @@ export const agentSchema = {
|
|
|
237
260
|
allOf: [
|
|
238
261
|
{ if: typeIs("file_search"), then: { $ref: "#/$defs/fileSearchTool" } },
|
|
239
262
|
{ if: typeIs("web_search"), then: { $ref: "#/$defs/webSearchTool" } },
|
|
263
|
+
{ if: typeIs("web_fetch"), then: { $ref: "#/$defs/webFetchTool" } },
|
|
240
264
|
{ if: typeIs("backbone.extraction"), then: { $ref: "#/$defs/extractionTool" } },
|
|
241
265
|
{ if: typeIs("backbone.document_convert"), then: { $ref: "#/$defs/documentConvertTool" } },
|
|
242
266
|
{ if: typeIs("backbone.todo"), then: { $ref: "#/$defs/todoTool" } },
|
|
@@ -8,6 +8,8 @@ const NULLABLE_KEYS = ["description", "models", "instructions", "tools", "hitlPo
|
|
|
8
8
|
const TOOL_RULE_CLASSES = new Set(["read", "write", "destructive"]);
|
|
9
9
|
/** web_search config keys whose explicit `null` the backend reads as absent. */
|
|
10
10
|
const WEB_SEARCH_NULLABLE_KEYS = ["source", "fallback", "searchProviderId", "allowedDomains"];
|
|
11
|
+
/** web_fetch config keys whose explicit `null` the backend reads as absent. */
|
|
12
|
+
const WEB_FETCH_NULLABLE_KEYS = ["source", "allowedDomains"];
|
|
11
13
|
const isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
12
14
|
/**
|
|
13
15
|
* A deep copy of `doc` in the form the backend actually checks: explicit nulls it treats as absent
|
|
@@ -34,7 +36,9 @@ export function normalizeForValidation(doc) {
|
|
|
34
36
|
if (isPlainObject(tool) && tool.annotations === null)
|
|
35
37
|
delete tool.annotations;
|
|
36
38
|
if (isPlainObject(tool) && tool.type === "web_search")
|
|
37
|
-
|
|
39
|
+
normalizeWebTool(tool, WEB_SEARCH_NULLABLE_KEYS);
|
|
40
|
+
if (isPlainObject(tool) && tool.type === "web_fetch")
|
|
41
|
+
normalizeWebTool(tool, WEB_FETCH_NULLABLE_KEYS);
|
|
38
42
|
}
|
|
39
43
|
}
|
|
40
44
|
const policy = copy.hitlPolicy;
|
|
@@ -55,13 +59,13 @@ export function normalizeForValidation(doc) {
|
|
|
55
59
|
return copy;
|
|
56
60
|
}
|
|
57
61
|
/** WebToolEntryValidator reads a null config and null config fields as absent, and trims each domain. */
|
|
58
|
-
function
|
|
62
|
+
function normalizeWebTool(tool, nullableKeys) {
|
|
59
63
|
if (tool.config === null)
|
|
60
64
|
delete tool.config;
|
|
61
65
|
const config = tool.config;
|
|
62
66
|
if (!isPlainObject(config))
|
|
63
67
|
return;
|
|
64
|
-
for (const key of
|
|
68
|
+
for (const key of nullableKeys) {
|
|
65
69
|
if (config[key] === null)
|
|
66
70
|
delete config[key];
|
|
67
71
|
}
|
|
@@ -125,6 +129,7 @@ export function validateAgentConfig(raw) {
|
|
|
125
129
|
}
|
|
126
130
|
if (Array.isArray(record.tools)) {
|
|
127
131
|
let webSearchSeen = false;
|
|
132
|
+
let webFetchSeen = false;
|
|
128
133
|
record.tools.forEach((tool, i) => {
|
|
129
134
|
const type = tool?.type;
|
|
130
135
|
if (typeof type === "string" && Object.hasOwn(NON_AUTHORABLE_TOOL_TYPES, type)) {
|
|
@@ -136,6 +141,11 @@ export function validateAgentConfig(raw) {
|
|
|
136
141
|
issues.push({ pointer: `/tools/${i}/type`, message: "an agent may carry only one web_search tool" });
|
|
137
142
|
webSearchSeen = true;
|
|
138
143
|
}
|
|
144
|
+
if (type === "web_fetch") {
|
|
145
|
+
if (webFetchSeen)
|
|
146
|
+
issues.push({ pointer: `/tools/${i}/type`, message: "an agent may carry only one web_fetch tool" });
|
|
147
|
+
webFetchSeen = true;
|
|
148
|
+
}
|
|
139
149
|
});
|
|
140
150
|
}
|
|
141
151
|
if (Array.isArray(record.skills)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@2kw/ai",
|
|
3
|
-
"version": "7.3.
|
|
3
|
+
"version": "7.3.1",
|
|
4
4
|
"description": "CLI for 2kw.ai — schema-driven document extraction, an OpenAI-compatible EU LLM gateway, transcription, prompts, datasets, and experiments from your terminal or agentic workflows. Ships as 2kw, backbone, and bb.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|