orquesta-cli 0.2.105 → 0.2.107
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.
|
@@ -711,6 +711,7 @@ export class LLMClient {
|
|
|
711
711
|
let finalResponseFailures = 0;
|
|
712
712
|
const MAX_NO_TOOL_CALL_RETRIES = 3;
|
|
713
713
|
const MAX_FINAL_RESPONSE_FAILURES = 3;
|
|
714
|
+
const toolChoiceAuto = /^(1|true|yes|on)$/i.test(process.env['ORQUESTA_TOOL_CHOICE_AUTO'] || '');
|
|
714
715
|
const MAX_ITERATIONS = Number(process.env['ORQUESTA_MAX_TOOL_ITERATIONS']) || 50;
|
|
715
716
|
const recentToolSignatures = [];
|
|
716
717
|
const recentNormalizedSignatures = [];
|
|
@@ -742,7 +743,7 @@ export class LLMClient {
|
|
|
742
743
|
response = await this.chatCompletion({
|
|
743
744
|
messages: workingMessages,
|
|
744
745
|
tools,
|
|
745
|
-
tool_choice: 'required',
|
|
746
|
+
tool_choice: toolChoiceAuto ? 'auto' : 'required',
|
|
746
747
|
...(roleModel ? { model: roleModel } : {}),
|
|
747
748
|
});
|
|
748
749
|
}
|
|
@@ -951,6 +952,23 @@ export class LLMClient {
|
|
|
951
952
|
continue;
|
|
952
953
|
}
|
|
953
954
|
else {
|
|
955
|
+
const hasMalformedToolCall = !!assistantMessage.content &&
|
|
956
|
+
(/<tool_call>/i.test(assistantMessage.content) ||
|
|
957
|
+
/<arg_key>/i.test(assistantMessage.content) ||
|
|
958
|
+
/<arg_value>/i.test(assistantMessage.content) ||
|
|
959
|
+
/<\/tool_call>/i.test(assistantMessage.content) ||
|
|
960
|
+
/bash<arg_key>/i.test(assistantMessage.content));
|
|
961
|
+
if (toolChoiceAuto && !hasMalformedToolCall && assistantMessage.content && assistantMessage.content.trim()) {
|
|
962
|
+
const direct = assistantMessage.content;
|
|
963
|
+
logger.flow('tool_choice:auto — accepting direct text answer as final response');
|
|
964
|
+
const { emitAssistantResponse } = await import('../../tools/llm/simple/file-tools.js');
|
|
965
|
+
emitAssistantResponse(direct);
|
|
966
|
+
return {
|
|
967
|
+
message: { role: 'assistant', content: direct },
|
|
968
|
+
toolCalls: toolCallHistory,
|
|
969
|
+
allMessages: workingMessages,
|
|
970
|
+
};
|
|
971
|
+
}
|
|
954
972
|
noToolCallRetries++;
|
|
955
973
|
logger.flow(`No tool call - enforcing tool usage (attempt ${noToolCallRetries}/${MAX_NO_TOOL_CALL_RETRIES})`);
|
|
956
974
|
if (noToolCallRetries > MAX_NO_TOOL_CALL_RETRIES) {
|
|
@@ -964,12 +982,6 @@ export class LLMClient {
|
|
|
964
982
|
allMessages: workingMessages,
|
|
965
983
|
};
|
|
966
984
|
}
|
|
967
|
-
const hasMalformedToolCall = assistantMessage.content &&
|
|
968
|
-
(/<tool_call>/i.test(assistantMessage.content) ||
|
|
969
|
-
/<arg_key>/i.test(assistantMessage.content) ||
|
|
970
|
-
/<arg_value>/i.test(assistantMessage.content) ||
|
|
971
|
-
/<\/tool_call>/i.test(assistantMessage.content) ||
|
|
972
|
-
/bash<arg_key>/i.test(assistantMessage.content));
|
|
973
985
|
const retryMessage = hasMalformedToolCall
|
|
974
986
|
? 'Your previous response contained a malformed tool call (XML tags in content). You MUST use the proper tool_calls API format. Use final_response tool to deliver your message to the user.'
|
|
975
987
|
: 'You must use tools for all actions. Use final_response tool to deliver your final message to the user after completing all tasks.';
|
|
@@ -51,16 +51,33 @@ export const BASH_DANGEROUS_PATTERNS = [
|
|
|
51
51
|
/\brm\s+-rf\s+[\/~]/i,
|
|
52
52
|
/\brm\s+-rf\s+\*/i,
|
|
53
53
|
/\bdd\s+if=/i,
|
|
54
|
+
/\bdd\b[^\n]*\bof=\/dev\/sd/i,
|
|
54
55
|
/\bmkfs\b/i,
|
|
55
56
|
/\b:(){ :|:& };:/,
|
|
56
|
-
/\bchmod\s
|
|
57
|
+
/\bchmod\s+(-R\s+)?777\s+[\/~]/i,
|
|
57
58
|
/\bsudo\s+rm/i,
|
|
58
59
|
/>\s*\/dev\/sd[a-z]/i,
|
|
60
|
+
/\b(curl|wget)\b[^|]*\|\s*(sudo\s+)?(ba|z)?sh\b/i,
|
|
61
|
+
/\bgit\s+push\b[^\n]*(?:^|\s)(?:--force|-f)\b[^\n]*\b(?:main|master|prod)\b/i,
|
|
62
|
+
/\bgit\s+push\b[^\n]*\b(?:main|master|prod)\b[^\n]*(?:^|\s)(?:--force|-f)\b/i,
|
|
59
63
|
/\bshutdown\b/i,
|
|
60
64
|
/\breboot\b/i,
|
|
61
65
|
/\bhalt\b/i,
|
|
62
66
|
/\bpoweroff\b/i,
|
|
63
67
|
];
|
|
68
|
+
const CATASTROPHIC_RM_TARGET = /^(\/|~\/?|\*|\.\/?|\.\.\/?|\/\*|~\/\*)$/;
|
|
69
|
+
function isCatastrophicRm(command) {
|
|
70
|
+
const m = command.match(/\brm\b((?:\s+-{1,2}[A-Za-z-]+)*)\s+(\S+)/i);
|
|
71
|
+
if (!m)
|
|
72
|
+
return false;
|
|
73
|
+
const flags = (m[1] ?? '').toLowerCase();
|
|
74
|
+
const target = m[2] ?? '';
|
|
75
|
+
const hasRecursive = /-{1,2}\w*r/.test(flags) || flags.includes('recursive');
|
|
76
|
+
const hasForce = /-{1,2}\w*f/.test(flags) || flags.includes('force');
|
|
77
|
+
if (!hasRecursive || !hasForce)
|
|
78
|
+
return false;
|
|
79
|
+
return CATASTROPHIC_RM_TARGET.test(target);
|
|
80
|
+
}
|
|
64
81
|
export const POWERSHELL_DANGEROUS_PATTERNS = [
|
|
65
82
|
/Remove-Item\s+.*-Recurse\s+.*-Force\s+[A-Z]:\\/i,
|
|
66
83
|
/ri\s+.*-r\s+.*-fo\s+[A-Z]:\\/i,
|
|
@@ -79,6 +96,8 @@ export const POWERSHELL_DANGEROUS_PATTERNS = [
|
|
|
79
96
|
/for\s*\(\s*;\s*;\s*\)\s*\{.*Start-Process/i,
|
|
80
97
|
];
|
|
81
98
|
export function isDangerousBashCommand(command) {
|
|
99
|
+
if (isCatastrophicRm(command))
|
|
100
|
+
return true;
|
|
82
101
|
return BASH_DANGEROUS_PATTERNS.some(pattern => pattern.test(command));
|
|
83
102
|
}
|
|
84
103
|
export function isDangerousPowerShellCommand(command) {
|