@2kw/ai 6.4.0-dev.10 → 6.4.0-dev.8
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/agent-config/schema.d.ts +0 -31
- package/dist/agent-config/schema.js +0 -15
- package/dist/agent-config/template.js +0 -2
- package/dist/commands/experiments.js +3 -20
- package/dist/lib/agent-run.d.ts +0 -3
- package/dist/lib/agent-run.js +0 -33
- package/dist/lib/approval-prompt.js +3 -8
- package/package.json +1 -1
|
@@ -221,25 +221,6 @@ export declare const agentSchema: {
|
|
|
221
221
|
};
|
|
222
222
|
};
|
|
223
223
|
};
|
|
224
|
-
readonly bashTool: {
|
|
225
|
-
readonly type: "object";
|
|
226
|
-
readonly additionalProperties: false;
|
|
227
|
-
readonly required: readonly ["type"];
|
|
228
|
-
readonly properties: {
|
|
229
|
-
readonly type: {
|
|
230
|
-
readonly const: "backbone.bash";
|
|
231
|
-
};
|
|
232
|
-
readonly approval: {
|
|
233
|
-
readonly enum: readonly ["sandbox", "pause"];
|
|
234
|
-
};
|
|
235
|
-
readonly outputs: {
|
|
236
|
-
readonly enum: readonly ["immediate", "held"];
|
|
237
|
-
};
|
|
238
|
-
readonly annotations: {
|
|
239
|
-
readonly $ref: "#/$defs/annotations";
|
|
240
|
-
};
|
|
241
|
-
};
|
|
242
|
-
};
|
|
243
224
|
readonly functionTool: {
|
|
244
225
|
readonly type: "object";
|
|
245
226
|
readonly additionalProperties: false;
|
|
@@ -354,18 +335,6 @@ export declare const agentSchema: {
|
|
|
354
335
|
readonly then: {
|
|
355
336
|
readonly $ref: "#/$defs/skillTool";
|
|
356
337
|
};
|
|
357
|
-
}, {
|
|
358
|
-
readonly if: {
|
|
359
|
-
required: string[];
|
|
360
|
-
properties: {
|
|
361
|
-
type: {
|
|
362
|
-
const: string;
|
|
363
|
-
};
|
|
364
|
-
};
|
|
365
|
-
};
|
|
366
|
-
readonly then: {
|
|
367
|
-
readonly $ref: "#/$defs/bashTool";
|
|
368
|
-
};
|
|
369
338
|
}, {
|
|
370
339
|
readonly if: {
|
|
371
340
|
required: string[];
|
|
@@ -35,7 +35,6 @@ const BUILTIN_TYPES = [
|
|
|
35
35
|
"backbone.document_convert",
|
|
36
36
|
"backbone.todo",
|
|
37
37
|
"backbone.skill",
|
|
38
|
-
"backbone.bash",
|
|
39
38
|
"function",
|
|
40
39
|
];
|
|
41
40
|
const typeIs = (t) => ({ required: ["type"], properties: { type: { const: t } } });
|
|
@@ -162,19 +161,6 @@ export const agentSchema = {
|
|
|
162
161
|
skills: { type: "array", minItems: 1, maxItems: 20, uniqueItems: true, items: { type: "string", pattern: SKILL_REF } },
|
|
163
162
|
},
|
|
164
163
|
},
|
|
165
|
-
// The envelope BashToolEntryValidator accepts: no name, no requiresConfirmation, and none of
|
|
166
|
-
// the egress of the withdrawn per-agent network design (#925).
|
|
167
|
-
bashTool: {
|
|
168
|
-
type: "object",
|
|
169
|
-
additionalProperties: false,
|
|
170
|
-
required: ["type"],
|
|
171
|
-
properties: {
|
|
172
|
-
type: { const: "backbone.bash" },
|
|
173
|
-
approval: { enum: ["sandbox", "pause"] },
|
|
174
|
-
outputs: { enum: ["immediate", "held"] },
|
|
175
|
-
annotations: { $ref: "#/$defs/annotations" },
|
|
176
|
-
},
|
|
177
|
-
},
|
|
178
164
|
functionTool: {
|
|
179
165
|
type: "object",
|
|
180
166
|
additionalProperties: false,
|
|
@@ -208,7 +194,6 @@ export const agentSchema = {
|
|
|
208
194
|
{ if: typeIs("backbone.document_convert"), then: { $ref: "#/$defs/documentConvertTool" } },
|
|
209
195
|
{ if: typeIs("backbone.todo"), then: { $ref: "#/$defs/todoTool" } },
|
|
210
196
|
{ if: typeIs("backbone.skill"), then: { $ref: "#/$defs/skillTool" } },
|
|
211
|
-
{ if: typeIs("backbone.bash"), then: { $ref: "#/$defs/bashTool" } },
|
|
212
197
|
{ if: typeIs("function"), then: { $ref: "#/$defs/functionTool" } },
|
|
213
198
|
{
|
|
214
199
|
// The validator reports these with the reason from NON_AUTHORABLE_TOOL_TYPES; this keeps the published schema honest.
|
|
@@ -16,18 +16,8 @@ function formatComparisonCell(result) {
|
|
|
16
16
|
return chalk.red("ERROR");
|
|
17
17
|
const scores = result.scores ?? [];
|
|
18
18
|
if (scores.length > 0) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const rated = scores.filter((s) => s.label !== "SKIP" && s.score != null);
|
|
22
|
-
if (rated.length > 0) {
|
|
23
|
-
return (rated.reduce((sum, s) => sum + s.score, 0) / rated.length).toFixed(2);
|
|
24
|
-
}
|
|
25
|
-
// A label-only verdict (#1163) has no number; show its label, as the console does.
|
|
26
|
-
const verdict = scores.find((s) => s.label && s.label !== "SKIP");
|
|
27
|
-
if (verdict)
|
|
28
|
-
return String(verdict.label);
|
|
29
|
-
if (scores.every((s) => s.label === "SKIP"))
|
|
30
|
-
return chalk.dim("skipped");
|
|
19
|
+
const avg = scores.reduce((sum, s) => sum + (s.score ?? 0), 0) / scores.length;
|
|
20
|
+
return avg.toFixed(2);
|
|
31
21
|
}
|
|
32
22
|
return result.durationMs != null ? `${result.durationMs}ms` : chalk.dim("done");
|
|
33
23
|
}
|
|
@@ -402,14 +392,8 @@ export function makeExperimentsCommand() {
|
|
|
402
392
|
console.log(chalk.dim(`Page ${(page.number ?? 0) + 1} of ${page.totalPages ?? 0} (${page.totalElements ?? 0} total)`));
|
|
403
393
|
}
|
|
404
394
|
if (aggregates.length > 0) {
|
|
405
|
-
const skippedOf = (agg) => Object.entries((agg.skippedEvaluatorCounts ?? {}))
|
|
406
|
-
.filter(([, n]) => n > 0)
|
|
407
|
-
.map(([evaluatorId, n]) => `${evaluatorId}: ${n}`)
|
|
408
|
-
.join(", ");
|
|
409
|
-
// Only when something was skipped, so a clean run keeps its narrow table (#693).
|
|
410
|
-
const showSkipped = aggregates.some((agg) => skippedOf(agg) !== "");
|
|
411
395
|
const aggTable = new Table({
|
|
412
|
-
head: ["Variant", "Items", "Avg Duration", "Avg Tokens", "Total Cost"
|
|
396
|
+
head: ["Variant", "Items", "Avg Duration", "Avg Tokens", "Total Cost"].map((h) => chalk.cyan(h)),
|
|
413
397
|
wordWrap: true,
|
|
414
398
|
});
|
|
415
399
|
for (const agg of aggregates) {
|
|
@@ -419,7 +403,6 @@ export function makeExperimentsCommand() {
|
|
|
419
403
|
agg.avgDurationMs != null ? `${Math.round(agg.avgDurationMs)}ms` : "—",
|
|
420
404
|
agg.avgTokens != null ? Math.round(agg.avgTokens) : "—",
|
|
421
405
|
agg.totalCost != null ? `$${agg.totalCost}` : "—",
|
|
422
|
-
...(showSkipped ? [skippedOf(agg) || "—"] : []),
|
|
423
406
|
]);
|
|
424
407
|
}
|
|
425
408
|
console.log(chalk.bold("\nAggregates:"));
|
package/dist/lib/agent-run.d.ts
CHANGED
|
@@ -116,9 +116,6 @@ export declare function parseAgentModel(model?: string): {
|
|
|
116
116
|
* clipboard. Newlines and tabs stay. JSON output is never passed through this.
|
|
117
117
|
*/
|
|
118
118
|
export declare function stripControl(s: string): string;
|
|
119
|
-
export declare function hasInvisible(s: string): boolean;
|
|
120
|
-
/** Replaces each hidden code point with a visible `<U+XXXX>`, so approving a diff means having seen it. */
|
|
121
|
-
export declare function revealInvisible(s: string): string;
|
|
122
119
|
export declare function shellQuote(value: string): string;
|
|
123
120
|
/** "Connect a (h), allow the agent to use b (h) and reconnect c (h)". */
|
|
124
121
|
export declare function connectionsSentence(connections: PendingConnection[]): string;
|
package/dist/lib/agent-run.js
CHANGED
|
@@ -89,39 +89,6 @@ const CONTROL_CHARS = /[\x00-\x08\x0b-\x1f\x7f-\x9f]/g;
|
|
|
89
89
|
export function stripControl(s) {
|
|
90
90
|
return s.replace(CONTROL_CHARS, "");
|
|
91
91
|
}
|
|
92
|
-
/**
|
|
93
|
-
* Code points that print as nothing, or reorder what surrounds them, yet reach the model: Unicode
|
|
94
|
-
* tags, zero-width characters, directional marks, embeddings, overrides and isolates, the word
|
|
95
|
-
* joiner and the byte-order mark (#1027). As numbers, not an escaped regex, so no tool can fold
|
|
96
|
-
* them into the source. Kept in step with `surface/src/core/skills-apply-preview.ts`.
|
|
97
|
-
*/
|
|
98
|
-
const INVISIBLE_RANGES = [
|
|
99
|
-
[0xe0000, 0xe007f],
|
|
100
|
-
[0x200b, 0x200f],
|
|
101
|
-
[0x202a, 0x202e],
|
|
102
|
-
[0x2060, 0x2060],
|
|
103
|
-
[0x2066, 0x2069],
|
|
104
|
-
[0x061c, 0x061c],
|
|
105
|
-
[0xfeff, 0xfeff],
|
|
106
|
-
];
|
|
107
|
-
function isInvisible(codePoint) {
|
|
108
|
-
return INVISIBLE_RANGES.some(([low, high]) => codePoint >= low && codePoint <= high);
|
|
109
|
-
}
|
|
110
|
-
export function hasInvisible(s) {
|
|
111
|
-
for (const char of s)
|
|
112
|
-
if (isInvisible(char.codePointAt(0)))
|
|
113
|
-
return true;
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
/** Replaces each hidden code point with a visible `<U+XXXX>`, so approving a diff means having seen it. */
|
|
117
|
-
export function revealInvisible(s) {
|
|
118
|
-
let out = "";
|
|
119
|
-
for (const char of s) {
|
|
120
|
-
const codePoint = char.codePointAt(0);
|
|
121
|
-
out += isInvisible(codePoint) ? `<U+${codePoint.toString(16).toUpperCase().padStart(4, "0")}>` : char;
|
|
122
|
-
}
|
|
123
|
-
return out;
|
|
124
|
-
}
|
|
125
92
|
export function shellQuote(value) {
|
|
126
93
|
if (/^[A-Za-z0-9._@/:-]+$/.test(value))
|
|
127
94
|
return value;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createInterface } from "node:readline/promises";
|
|
2
2
|
import chalk from "chalk";
|
|
3
|
-
import {
|
|
3
|
+
import { stripControl } from "./agent-run.js";
|
|
4
4
|
import { REMEMBER_NOTE, previewIsIncomplete, previewLines } from "./skills-apply-preview.js";
|
|
5
5
|
/** Raised when the prompt's input closes (EOF, Ctrl+C, Ctrl+D) before an answer arrives. */
|
|
6
6
|
export class PromptAbortedError extends Error {
|
|
@@ -50,7 +50,7 @@ export function readlineAsk(input = process.stdin, output = process.stderr) {
|
|
|
50
50
|
}
|
|
51
51
|
export async function promptApprovals(pending, ask, write = (line) => console.error(line)) {
|
|
52
52
|
const answers = new Map();
|
|
53
|
-
const s =
|
|
53
|
+
const s = stripControl;
|
|
54
54
|
for (const [index, a] of pending.entries()) {
|
|
55
55
|
// A connector approval carries no policy class (#949): "unknown" may be destructive, so it is never
|
|
56
56
|
// offered a standing grant here; the server drops one for a destructive row anyway.
|
|
@@ -62,12 +62,7 @@ export async function promptApprovals(pending, ask, write = (line) => console.er
|
|
|
62
62
|
// A SkillsApply change reads as its diff (#782, spec §10). When the preview leaves changes
|
|
63
63
|
// out, the full arguments follow it: this prompt never runs with --json, so it is the only
|
|
64
64
|
// place the member can read what would persist (spec D7).
|
|
65
|
-
const
|
|
66
|
-
// Hidden characters are shown as <U+XXXX> below; the warning says why (#1027, spec D7).
|
|
67
|
-
if (lines.some(hasInvisible)) {
|
|
68
|
-
write(chalk.yellow("Hidden characters found: shown as <U+XXXX>. A model reads them; you would not see them. Check each marked line before you approve."));
|
|
69
|
-
}
|
|
70
|
-
for (const line of lines)
|
|
65
|
+
for (const line of previewLines(a.preview))
|
|
71
66
|
write(colourPreviewLine(s(line)));
|
|
72
67
|
if (previewIsIncomplete(a.preview)) {
|
|
73
68
|
write(chalk.dim("Full request (the preview leaves changes out):"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@2kw/ai",
|
|
3
|
-
"version": "6.4.0-dev.
|
|
3
|
+
"version": "6.4.0-dev.8",
|
|
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",
|