nexgenr 1.0.3 → 1.1.0
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/main.mjs +222 -9
- package/package.json +1 -1
package/dist/main.mjs
CHANGED
|
@@ -188855,6 +188855,112 @@ var init_capability$6 = __esmMin((() => {
|
|
|
188855
188855
|
dynamically_loaded_tools: false
|
|
188856
188856
|
}, UNKNOWN_CAPABILITY_MARKER$1, { value: true }));
|
|
188857
188857
|
}));
|
|
188858
|
+
// ../../packages/agent-core-v2/src/human/llm/repair/inline-tool-call.ts
|
|
188859
|
+
function parseParameterValue(raw) {
|
|
188860
|
+
const trimmed = raw.trim();
|
|
188861
|
+
if (trimmed === "") return "";
|
|
188862
|
+
const first = trimmed[0];
|
|
188863
|
+
if (first === "{" || first === "[" || first === "\"" || trimmed === "true" || trimmed === "false") try {
|
|
188864
|
+
return JSON.parse(trimmed);
|
|
188865
|
+
} catch {
|
|
188866
|
+
return trimmed;
|
|
188867
|
+
}
|
|
188868
|
+
if (/^-?\d+(\.\d+)?$/.test(trimmed)) return Number(trimmed);
|
|
188869
|
+
return trimmed;
|
|
188870
|
+
}
|
|
188871
|
+
function parseBlockBody(body) {
|
|
188872
|
+
const trimmed = body.trim();
|
|
188873
|
+
if (trimmed.startsWith("{")) try {
|
|
188874
|
+
const decoded = JSON.parse(trimmed);
|
|
188875
|
+
if (typeof decoded.name === "string" && decoded.name !== "") {
|
|
188876
|
+
const args = decoded.arguments ?? decoded.parameters ?? {};
|
|
188877
|
+
return {
|
|
188878
|
+
name: decoded.name,
|
|
188879
|
+
arguments: JSON.stringify(args)
|
|
188880
|
+
};
|
|
188881
|
+
}
|
|
188882
|
+
} catch {
|
|
188883
|
+
return;
|
|
188884
|
+
}
|
|
188885
|
+
const functionMatch = FUNCTION_PATTERN.exec(trimmed);
|
|
188886
|
+
if (functionMatch === null) return void 0;
|
|
188887
|
+
const name = functionMatch[1];
|
|
188888
|
+
if (name === void 0 || name === "") return void 0;
|
|
188889
|
+
const args = {};
|
|
188890
|
+
for (const match of trimmed.matchAll(PARAMETER_PATTERN)) {
|
|
188891
|
+
const key = match[1];
|
|
188892
|
+
if (key === void 0 || key === "") continue;
|
|
188893
|
+
args[key] = parseParameterValue(match[2] ?? "");
|
|
188894
|
+
}
|
|
188895
|
+
return {
|
|
188896
|
+
name,
|
|
188897
|
+
arguments: JSON.stringify(args)
|
|
188898
|
+
};
|
|
188899
|
+
}
|
|
188900
|
+
function extractInlineToolCalls(content) {
|
|
188901
|
+
if (!content.includes("<tool_call>")) return {
|
|
188902
|
+
text: content,
|
|
188903
|
+
calls: []
|
|
188904
|
+
};
|
|
188905
|
+
const calls = [];
|
|
188906
|
+
let consumed = false;
|
|
188907
|
+
const text = content.replace(BLOCK_PATTERN, (block, body) => {
|
|
188908
|
+
const call = parseBlockBody(body);
|
|
188909
|
+
if (call === void 0) return block;
|
|
188910
|
+
calls.push(call);
|
|
188911
|
+
consumed = true;
|
|
188912
|
+
return "";
|
|
188913
|
+
});
|
|
188914
|
+
return consumed ? {
|
|
188915
|
+
text: text.replace(/\n{3,}/g, "\n\n").trim(),
|
|
188916
|
+
calls
|
|
188917
|
+
} : {
|
|
188918
|
+
text: content,
|
|
188919
|
+
calls: []
|
|
188920
|
+
};
|
|
188921
|
+
}
|
|
188922
|
+
function sameCall(left, call) {
|
|
188923
|
+
return left.name === call.name && left.arguments === call.arguments;
|
|
188924
|
+
}
|
|
188925
|
+
function repairAssistantMessage(message) {
|
|
188926
|
+
const recovered = [];
|
|
188927
|
+
const kept = [];
|
|
188928
|
+
for (const part of message.content) {
|
|
188929
|
+
if (part.type !== "text") {
|
|
188930
|
+
kept.push(part);
|
|
188931
|
+
continue;
|
|
188932
|
+
}
|
|
188933
|
+
const scan = extractInlineToolCalls(part.text);
|
|
188934
|
+
if (scan.calls.length === 0) {
|
|
188935
|
+
kept.push(part);
|
|
188936
|
+
continue;
|
|
188937
|
+
}
|
|
188938
|
+
recovered.push(...scan.calls);
|
|
188939
|
+
const rest = scan.text.trim();
|
|
188940
|
+
if (rest !== "") kept.push({
|
|
188941
|
+
...part,
|
|
188942
|
+
text: rest
|
|
188943
|
+
});
|
|
188944
|
+
}
|
|
188945
|
+
if (recovered.length === 0) return;
|
|
188946
|
+
message.content.length = 0;
|
|
188947
|
+
message.content.push(...kept);
|
|
188948
|
+
for (const call of recovered) {
|
|
188949
|
+
if (message.toolCalls.some((existing) => sameCall(existing, call))) continue;
|
|
188950
|
+
message.toolCalls.push({
|
|
188951
|
+
type: "function",
|
|
188952
|
+
id: crypto.randomUUID(),
|
|
188953
|
+
name: call.name,
|
|
188954
|
+
arguments: call.arguments
|
|
188955
|
+
});
|
|
188956
|
+
}
|
|
188957
|
+
}
|
|
188958
|
+
var BLOCK_PATTERN, FUNCTION_PATTERN, PARAMETER_PATTERN;
|
|
188959
|
+
var init_inline_tool_call = __esmMin((() => {
|
|
188960
|
+
BLOCK_PATTERN = /<tool_call>([\s\S]*?)<\/tool_call>/g;
|
|
188961
|
+
FUNCTION_PATTERN = /<function=([^>\s]+)>/;
|
|
188962
|
+
PARAMETER_PATTERN = /<parameter=([^>\s]+)>([\s\S]*?)<\/parameter>/g;
|
|
188963
|
+
}));
|
|
188858
188964
|
// ../../packages/agent-core-v2/src/human/llm/message.ts
|
|
188859
188965
|
function isContentPart(part) {
|
|
188860
188966
|
const t = part.type;
|
|
@@ -188984,11 +189090,14 @@ function createMessageAccumulator() {
|
|
|
188984
189090
|
},
|
|
188985
189091
|
finish() {
|
|
188986
189092
|
flush();
|
|
189093
|
+
repairAssistantMessage(message);
|
|
188987
189094
|
return message;
|
|
188988
189095
|
}
|
|
188989
189096
|
};
|
|
188990
189097
|
}
|
|
188991
|
-
var init_message$2 = __esmMin((() => {
|
|
189098
|
+
var init_message$2 = __esmMin((() => {
|
|
189099
|
+
init_inline_tool_call();
|
|
189100
|
+
}));
|
|
188992
189101
|
// ../../packages/agent-core-v2/src/llm-adapter/contract/message.ts
|
|
188993
189102
|
function createUserMessage(content) {
|
|
188994
189103
|
return {
|
|
@@ -197085,7 +197194,9 @@ function extractReasoningStrings(source) {
|
|
|
197085
197194
|
value
|
|
197086
197195
|
});
|
|
197087
197196
|
}
|
|
197088
|
-
|
|
197197
|
+
const [first] = found;
|
|
197198
|
+
if (first === void 0 || found.length === 1) return found;
|
|
197199
|
+
return found.every((entry) => entry.value === first.value) ? [first] : found;
|
|
197089
197200
|
}
|
|
197090
197201
|
function extractReasoning(source, explicitKey) {
|
|
197091
197202
|
if (explicitKey !== void 0) {
|
|
@@ -200163,12 +200274,24 @@ function createEmptyResponseError(model, finish, thinkOnly) {
|
|
|
200163
200274
|
rawFinishReason: finish.rawFinishReason
|
|
200164
200275
|
};
|
|
200165
200276
|
}
|
|
200277
|
+
function createUnrecoveredToolCallError(model, finish) {
|
|
200278
|
+
return {
|
|
200279
|
+
kind: "empty_response",
|
|
200280
|
+
message: `The model wrote a tool call as text instead of calling a tool, and it could not be recovered from the response.${formatFinishReasonHint(finish)} Provider: ${model.provider}, model: ${model.model}`,
|
|
200281
|
+
finishReason: finish.finishReason,
|
|
200282
|
+
rawFinishReason: finish.rawFinishReason
|
|
200283
|
+
};
|
|
200284
|
+
}
|
|
200285
|
+
function hasUnrecoveredToolCallText(message) {
|
|
200286
|
+
return message.content.some((part) => part.type === "text" && part.text.includes("<tool_call"));
|
|
200287
|
+
}
|
|
200166
200288
|
function emptyResponseError(message, model, finish) {
|
|
200167
200289
|
const hasToolCalls = message.toolCalls.length > 0;
|
|
200168
200290
|
if (message.content.length === 0 && !hasToolCalls) return createEmptyResponseError(model, finish, false);
|
|
200169
200291
|
const hasThink = message.content.some((part) => part.type === "think");
|
|
200170
200292
|
const hasText = message.content.some((part) => part.type === "text" && part.text.trim().length > 0);
|
|
200171
200293
|
if (hasThink && !hasText && !hasToolCalls) return createEmptyResponseError(model, finish, true);
|
|
200294
|
+
if (!hasToolCalls && hasUnrecoveredToolCallText(message)) return createUnrecoveredToolCallError(model, finish);
|
|
200172
200295
|
return null;
|
|
200173
200296
|
}
|
|
200174
200297
|
var init_empty_response = __esmMin((() => {}));
|
|
@@ -223949,7 +224072,7 @@ function createAgentMachine({ abortTimeoutMs, maxStepsPerTurn }) {
|
|
|
223949
224072
|
event: [...event.output.produced.map((message) => messageAppended({ message })), turnEnded({
|
|
223950
224073
|
turnId: context.activeTurnId ?? context.turnId,
|
|
223951
224074
|
outcome: event.output.type,
|
|
223952
|
-
errorMessage: event.output.type === "failed" ?
|
|
224075
|
+
errorMessage: event.output.type === "failed" ? toErrorMessage(event.output.error) : void 0
|
|
223953
224076
|
})]
|
|
223954
224077
|
}))
|
|
223955
224078
|
]
|
|
@@ -223967,7 +224090,7 @@ function createAgentMachine({ abortTimeoutMs, maxStepsPerTurn }) {
|
|
|
223967
224090
|
event: turnEnded({
|
|
223968
224091
|
turnId: context.activeTurnId ?? context.turnId,
|
|
223969
224092
|
outcome: "failed",
|
|
223970
|
-
errorMessage:
|
|
224093
|
+
errorMessage: toErrorMessage(event.error)
|
|
223971
224094
|
})
|
|
223972
224095
|
}))]
|
|
223973
224096
|
},
|
|
@@ -224093,6 +224216,7 @@ function createAgentMachine({ abortTimeoutMs, maxStepsPerTurn }) {
|
|
|
224093
224216
|
}
|
|
224094
224217
|
var init_machine$2 = __esmMin((() => {
|
|
224095
224218
|
init_xstate2();
|
|
224219
|
+
init_errorMessage();
|
|
224096
224220
|
init_message$2();
|
|
224097
224221
|
init_machine$3();
|
|
224098
224222
|
init_wait_for$1();
|
|
@@ -270915,7 +271039,7 @@ function preflightToolCall(toolRegistry, toolCall, guard, describeUnavailableToo
|
|
|
270915
271039
|
toolCall,
|
|
270916
271040
|
toolName,
|
|
270917
271041
|
args: parsedArgs.data,
|
|
270918
|
-
output: describeMissingTool?.(toolName) ??
|
|
271042
|
+
output: describeMissingTool?.(toolName) ?? missingToolMessage(toolRegistry, toolName)
|
|
270919
271043
|
};
|
|
270920
271044
|
const source = toolRegistry.list().find((entry) => entry.name === toolName)?.source ?? "builtin";
|
|
270921
271045
|
const denied = guard?.({
|
|
@@ -270953,6 +271077,19 @@ function preflightToolCall(toolRegistry, toolCall, guard, describeUnavailableToo
|
|
|
270953
271077
|
args: parsedArgs.data
|
|
270954
271078
|
};
|
|
270955
271079
|
}
|
|
271080
|
+
function missingToolMessage(toolRegistry, toolName) {
|
|
271081
|
+
const base = `Tool "${toolName}" not found`;
|
|
271082
|
+
const wanted = toolName.toLowerCase();
|
|
271083
|
+
const suggestions = [];
|
|
271084
|
+
for (const entry of toolRegistry.list()) {
|
|
271085
|
+
if (!entry.name.startsWith("mcp__")) continue;
|
|
271086
|
+
if (!entry.name.toLowerCase().includes(wanted)) continue;
|
|
271087
|
+
suggestions.push(entry.name);
|
|
271088
|
+
if (suggestions.length === 5) break;
|
|
271089
|
+
}
|
|
271090
|
+
if (suggestions.length === 0) return base;
|
|
271091
|
+
return `${base}. Registered MCP tools with a similar name: ${suggestions.join(", ")}. Use the exact name.`;
|
|
271092
|
+
}
|
|
270956
271093
|
function validateExecutableToolArgs(tool, args) {
|
|
270957
271094
|
const schema = tool.parameters;
|
|
270958
271095
|
let cached = validators.get(tool);
|
|
@@ -279532,6 +279669,7 @@ var init_toolRegistryService = __esmMin((() => {
|
|
|
279532
279669
|
init_scopes();
|
|
279533
279670
|
init_scope();
|
|
279534
279671
|
init_toolRegistry();
|
|
279672
|
+
init_tool_naming();
|
|
279535
279673
|
init_builtinToolAssemblyService();
|
|
279536
279674
|
AgentToolRegistryService = class {
|
|
279537
279675
|
tools = /* @__PURE__ */ new Map();
|
|
@@ -279564,7 +279702,22 @@ var init_toolRegistryService = __esmMin((() => {
|
|
|
279564
279702
|
})).toSorted((a, b) => a.name.localeCompare(b.name));
|
|
279565
279703
|
}
|
|
279566
279704
|
resolve(name) {
|
|
279567
|
-
|
|
279705
|
+
const direct = this.tools.get(name)?.tool;
|
|
279706
|
+
if (direct !== void 0) return direct;
|
|
279707
|
+
return this.resolveMcpAlias(name);
|
|
279708
|
+
}
|
|
279709
|
+
resolveMcpAlias(name) {
|
|
279710
|
+
if (name.startsWith("mcp__")) return void 0;
|
|
279711
|
+
const wanted = sanitizeMcpNamePart(name);
|
|
279712
|
+
const matches = [];
|
|
279713
|
+
for (const [qualified, entry] of this.tools) {
|
|
279714
|
+
if (!qualified.startsWith("mcp__")) continue;
|
|
279715
|
+
const rest = qualified.slice(5);
|
|
279716
|
+
const separator = rest.indexOf("__");
|
|
279717
|
+
if (separator < 0) continue;
|
|
279718
|
+
if (rest.slice(separator + 2) === wanted) matches.push(entry);
|
|
279719
|
+
}
|
|
279720
|
+
return matches.length === 1 ? matches[0]?.tool : void 0;
|
|
279568
279721
|
}
|
|
279569
279722
|
unregisterTool(name) {
|
|
279570
279723
|
const entry = this.tools.get(name);
|
|
@@ -279863,6 +280016,7 @@ var init_src$10 = __esmMin((() => {
|
|
|
279863
280016
|
init_capability$6();
|
|
279864
280017
|
init_errors$38();
|
|
279865
280018
|
init_message$1();
|
|
280019
|
+
init_message$2();
|
|
279866
280020
|
init_request_trace();
|
|
279867
280021
|
init_sessionIndex();
|
|
279868
280022
|
init_sessionIndexService();
|
|
@@ -323257,6 +323411,51 @@ async function callRedteamTool(input) {
|
|
|
323257
323411
|
text: text.slice(0, 2e3)
|
|
323258
323412
|
};
|
|
323259
323413
|
}
|
|
323414
|
+
async function listRedteamToolNames(input) {
|
|
323415
|
+
const doFetch = input.fetchImpl ?? fetch;
|
|
323416
|
+
const timeoutMs = input.timeoutMs ?? PROBE_TIMEOUT_MS$1;
|
|
323417
|
+
const origin = input.origin ?? "https://redteam.nexgen.systems";
|
|
323418
|
+
const headers = {
|
|
323419
|
+
...mcpHeaders(input.apiKey),
|
|
323420
|
+
"content-type": "application/json",
|
|
323421
|
+
accept: "application/json, text/event-stream"
|
|
323422
|
+
};
|
|
323423
|
+
const initResponse = await timedFetch(doFetch, `${origin}/mcp`, {
|
|
323424
|
+
method: "POST",
|
|
323425
|
+
headers,
|
|
323426
|
+
body: JSON.stringify({
|
|
323427
|
+
jsonrpc: "2.0",
|
|
323428
|
+
id: 1,
|
|
323429
|
+
method: "initialize",
|
|
323430
|
+
params: {
|
|
323431
|
+
protocolVersion: "2025-06-18",
|
|
323432
|
+
capabilities: {},
|
|
323433
|
+
clientInfo: {
|
|
323434
|
+
name: "nexgenr-doctor",
|
|
323435
|
+
version: "1"
|
|
323436
|
+
}
|
|
323437
|
+
}
|
|
323438
|
+
})
|
|
323439
|
+
}, timeoutMs);
|
|
323440
|
+
if (!initResponse.ok) return [];
|
|
323441
|
+
const sessionId = initResponse.headers.get("mcp-session-id") ?? "";
|
|
323442
|
+
await readJsonRpc(initResponse, 1);
|
|
323443
|
+
const listResponse = await timedFetch(doFetch, `${origin}/mcp`, {
|
|
323444
|
+
method: "POST",
|
|
323445
|
+
headers: sessionId === "" ? headers : {
|
|
323446
|
+
...headers,
|
|
323447
|
+
"mcp-session-id": sessionId
|
|
323448
|
+
},
|
|
323449
|
+
body: JSON.stringify({
|
|
323450
|
+
jsonrpc: "2.0",
|
|
323451
|
+
id: 2,
|
|
323452
|
+
method: "tools/list",
|
|
323453
|
+
params: {}
|
|
323454
|
+
})
|
|
323455
|
+
}, timeoutMs);
|
|
323456
|
+
if (!listResponse.ok) return [];
|
|
323457
|
+
return (((await readJsonRpc(listResponse, 2))?.["result"])?.tools ?? []).flatMap((tool) => typeof tool.name === "string" ? [tool.name] : []);
|
|
323458
|
+
}
|
|
323260
323459
|
async function probeRedteam(input = {}) {
|
|
323261
323460
|
const doFetch = input.fetchImpl ?? fetch;
|
|
323262
323461
|
const timeoutMs = input.timeoutMs ?? PROBE_TIMEOUT_MS$1;
|
|
@@ -323316,6 +323515,19 @@ async function handleDoctorRedteam(deps) {
|
|
|
323316
323515
|
}
|
|
323317
323516
|
const verdict = verdictOf$1(rows);
|
|
323318
323517
|
deps.stdout.write(deps.json === true ? formatJson$1(rows, verdict) : formatTable$1(rows, verdict));
|
|
323518
|
+
if (deps.listTools === true) {
|
|
323519
|
+
const names = await listRedteamToolNames({
|
|
323520
|
+
apiKey: process.env["NEXGENR_REDTEAM_MCP_KEY"] ?? apiKey,
|
|
323521
|
+
fetchImpl: deps.fetchImpl
|
|
323522
|
+
});
|
|
323523
|
+
deps.stdout.write([
|
|
323524
|
+
`Gateway tools (${names.length}):`,
|
|
323525
|
+
...names.map((name) => ` ${name}`),
|
|
323526
|
+
"",
|
|
323527
|
+
"The model sees them as mcp__<server>__<name>. A bare gateway name resolves only when it is unambiguous.",
|
|
323528
|
+
""
|
|
323529
|
+
].join("\n"));
|
|
323530
|
+
}
|
|
323319
323531
|
deps.exit(EXIT_CODES$1[verdict]);
|
|
323320
323532
|
}
|
|
323321
323533
|
function formatJson$1(rows, verdict) {
|
|
@@ -323707,7 +323919,7 @@ function registerDoctorCommand(parent, deps) {
|
|
|
323707
323919
|
json: options.json === true
|
|
323708
323920
|
});
|
|
323709
323921
|
});
|
|
323710
|
-
doctor.command("redteam").description("Probe the red-team surface: contract, inference catalog and MCP gateway.").option("--json", "Emit a machine-readable report instead of the table.").option("--call <tool>", "Call one MCP tool after the probes (this spends service credits).").option("--args <json>", "JSON arguments for --call.").action(async (options) => {
|
|
323922
|
+
doctor.command("redteam").description("Probe the red-team surface: contract, inference catalog and MCP gateway.").option("--json", "Emit a machine-readable report instead of the table.").option("--tools", "List the gateway tool names after the probes.").option("--call <tool>", "Call one MCP tool after the probes (this spends service credits).").option("--args <json>", "JSON arguments for --call.").action(async (options) => {
|
|
323711
323923
|
const resolved = resolveDeps$1(deps);
|
|
323712
323924
|
let args;
|
|
323713
323925
|
if (options.args !== void 0) try {
|
|
@@ -323721,6 +323933,7 @@ function registerDoctorCommand(parent, deps) {
|
|
|
323721
323933
|
stderr: resolved.stderr,
|
|
323722
323934
|
exit: resolved.exit,
|
|
323723
323935
|
json: options.json === true,
|
|
323936
|
+
listTools: options.tools === true,
|
|
323724
323937
|
call: options.call === void 0 ? void 0 : {
|
|
323725
323938
|
tool: options.call,
|
|
323726
323939
|
args
|
|
@@ -497579,7 +497792,7 @@ function sameStringArrays(a, b) {
|
|
|
497579
497792
|
return a.length === b.length && a.every((value, index) => value === b[index]);
|
|
497580
497793
|
}
|
|
497581
497794
|
function createInitialAppState(input) {
|
|
497582
|
-
const startupPermission = input.cliOptions.
|
|
497795
|
+
const startupPermission = input.cliOptions.yolo ? "yolo" : "auto";
|
|
497583
497796
|
return {
|
|
497584
497797
|
model: "",
|
|
497585
497798
|
workDir: input.workDir,
|
|
@@ -499251,7 +499464,7 @@ var NexgenTUI = class {
|
|
|
499251
499464
|
const { startup } = this.options;
|
|
499252
499465
|
const config = await this.harness.getConfig({ reload: true });
|
|
499253
499466
|
const patch = includeModel ? lazyModelSelection(config, startup.model ?? config.defaultModel) : {};
|
|
499254
|
-
if (!startup.auto && !startup.yolo) patch.permissionMode = config.defaultPermissionMode ?? "
|
|
499467
|
+
if (!startup.auto && !startup.yolo) patch.permissionMode = config.defaultPermissionMode ?? "auto";
|
|
499255
499468
|
patch.configDefaultPlanMode = config.defaultPlanMode === true;
|
|
499256
499469
|
if (!startup.plan) patch.planMode = config.defaultPlanMode === true;
|
|
499257
499470
|
if (startup.agentProfile !== void 0 || startup.agentFiles !== void 0) {
|