ff1-cli 1.0.2 → 1.0.3
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 +4 -2
- package/config.json.example +10 -8
- package/dist/index.js +255 -80
- package/dist/src/ai-orchestrator/index.js +62 -5
- package/dist/src/config.js +12 -12
- package/dist/src/intent-parser/index.js +110 -84
- package/dist/src/intent-parser/utils.js +5 -2
- package/dist/src/logger.js +10 -0
- package/dist/src/utilities/ff1-compatibility.js +269 -0
- package/dist/src/utilities/ff1-device.js +9 -27
- package/dist/src/utilities/ff1-discovery.js +147 -0
- package/dist/src/utilities/functions.js +8 -26
- package/dist/src/utilities/index.js +9 -3
- package/dist/src/utilities/playlist-send.js +36 -17
- package/dist/src/utilities/playlist-source.js +77 -0
- package/dist/src/utilities/ssh-access.js +145 -0
- package/docs/CONFIGURATION.md +20 -6
- package/docs/EXAMPLES.md +13 -4
- package/docs/README.md +25 -5
- package/docs/RELEASING.md +6 -1
- package/package.json +3 -2
package/dist/src/config.js
CHANGED
|
@@ -49,11 +49,11 @@ function loadConfig() {
|
|
|
49
49
|
maxTokens: parseInt(process.env.MAX_TOKENS || '4000', 10),
|
|
50
50
|
supportsFunctionCalling: true,
|
|
51
51
|
},
|
|
52
|
-
|
|
52
|
+
gpt: {
|
|
53
53
|
apiKey: process.env.OPENAI_API_KEY || '',
|
|
54
54
|
baseURL: 'https://api.openai.com/v1',
|
|
55
|
-
model: 'gpt-
|
|
56
|
-
availableModels: ['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo'],
|
|
55
|
+
model: 'gpt-4.1',
|
|
56
|
+
availableModels: ['gpt-4.1', 'gpt-4.1-mini', 'gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo'],
|
|
57
57
|
timeout: 30000,
|
|
58
58
|
maxRetries: 3,
|
|
59
59
|
temperature: 0.3,
|
|
@@ -105,8 +105,9 @@ function loadConfig() {
|
|
|
105
105
|
models: mergedModels,
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
|
-
catch (
|
|
109
|
-
|
|
108
|
+
catch (error) {
|
|
109
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
110
|
+
console.warn(`Warning: Failed to parse config at ${configPath}. ${message}. Using defaults.`);
|
|
110
111
|
return defaultConfig;
|
|
111
112
|
}
|
|
112
113
|
}
|
|
@@ -161,7 +162,7 @@ function getBrowserConfig() {
|
|
|
161
162
|
* Get playlist configuration including private key for signing
|
|
162
163
|
*
|
|
163
164
|
* @returns {Object} Playlist configuration
|
|
164
|
-
* @returns {string|null} returns.privateKey - Ed25519 private key in base64 format (null if not configured)
|
|
165
|
+
* @returns {string|null} returns.privateKey - Ed25519 private key in base64 or hex format (null if not configured)
|
|
165
166
|
*/
|
|
166
167
|
function getPlaylistConfig() {
|
|
167
168
|
const config = getConfig();
|
|
@@ -303,13 +304,12 @@ function validateConfig(modelName) {
|
|
|
303
304
|
// Validate playlist configuration (optional, but warn if configured incorrectly)
|
|
304
305
|
if (config.playlist && config.playlist.privateKey) {
|
|
305
306
|
const key = config.playlist.privateKey;
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
key.length > 0) {
|
|
309
|
-
// Check if it looks like valid base64
|
|
307
|
+
const placeholderPattern = /your_ed25519_private_key/i;
|
|
308
|
+
if (!placeholderPattern.test(key) && typeof key === 'string' && key.length > 0) {
|
|
310
309
|
const base64Regex = /^[A-Za-z0-9+/]+=*$/;
|
|
311
|
-
|
|
312
|
-
|
|
310
|
+
const hexRegex = /^(0x)?[0-9a-fA-F]+$/;
|
|
311
|
+
if (!base64Regex.test(key) && !hexRegex.test(key)) {
|
|
312
|
+
errors.push('playlist.privateKey must be a valid base64- or hex-encoded ed25519 private key');
|
|
313
313
|
}
|
|
314
314
|
}
|
|
315
315
|
}
|
|
@@ -48,6 +48,7 @@ const openai_1 = __importDefault(require("openai"));
|
|
|
48
48
|
const chalk_1 = __importDefault(require("chalk"));
|
|
49
49
|
const config_1 = require("../config");
|
|
50
50
|
const utils_1 = require("./utils");
|
|
51
|
+
const logger = __importStar(require("../logger"));
|
|
51
52
|
// Cache for AI clients
|
|
52
53
|
const clientCache = new Map();
|
|
53
54
|
/**
|
|
@@ -369,13 +370,13 @@ const intentParserFunctionSchemas = [
|
|
|
369
370
|
type: 'function',
|
|
370
371
|
function: {
|
|
371
372
|
name: 'confirm_send_playlist',
|
|
372
|
-
description: 'Confirm the playlist file path and device name for sending. This function is called after the user mentions "send" or similar phrases.',
|
|
373
|
+
description: 'Confirm the playlist file path or hosted URL and device name for sending. This function is called after the user mentions "send" or similar phrases.',
|
|
373
374
|
parameters: {
|
|
374
375
|
type: 'object',
|
|
375
376
|
properties: {
|
|
376
377
|
filePath: {
|
|
377
378
|
type: 'string',
|
|
378
|
-
description: 'Path to
|
|
379
|
+
description: 'Path to playlist file or playlist URL (default: "./playlist.json")',
|
|
379
380
|
},
|
|
380
381
|
deviceName: {
|
|
381
382
|
type: 'string',
|
|
@@ -483,16 +484,67 @@ function printMarkdownContent(content) {
|
|
|
483
484
|
const lines = content.split('\n');
|
|
484
485
|
for (const line of lines) {
|
|
485
486
|
if (line.trim()) {
|
|
486
|
-
|
|
487
|
+
logger.verbose(formatMarkdown(line));
|
|
487
488
|
}
|
|
488
489
|
else if (line === '') {
|
|
489
|
-
|
|
490
|
+
logger.verbose();
|
|
490
491
|
}
|
|
491
492
|
}
|
|
492
493
|
}
|
|
493
494
|
function sleep(ms) {
|
|
494
495
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
495
496
|
}
|
|
497
|
+
function extractDomains(text) {
|
|
498
|
+
if (!text) {
|
|
499
|
+
return [];
|
|
500
|
+
}
|
|
501
|
+
const matches = text.match(/[a-z0-9-]+\.(eth|tez)/gi);
|
|
502
|
+
return matches ? matches.map((match) => match.toLowerCase()) : [];
|
|
503
|
+
}
|
|
504
|
+
function normalizeDomainInput(address, userDomains) {
|
|
505
|
+
if (!address || userDomains.length === 0) {
|
|
506
|
+
return address;
|
|
507
|
+
}
|
|
508
|
+
const lower = address.toLowerCase();
|
|
509
|
+
if (!lower.endsWith('.eth') && !lower.endsWith('.tez')) {
|
|
510
|
+
return address;
|
|
511
|
+
}
|
|
512
|
+
const baseName = lower.replace(/\.(eth|tez)$/i, '');
|
|
513
|
+
const match = userDomains.find((domain) => domain.replace(/\.(eth|tez)$/i, '') === baseName);
|
|
514
|
+
return match || address;
|
|
515
|
+
}
|
|
516
|
+
function normalizeRequirementDomains(params, userDomains) {
|
|
517
|
+
if (userDomains.length === 0) {
|
|
518
|
+
return params;
|
|
519
|
+
}
|
|
520
|
+
const normalized = params.requirements.map((req) => {
|
|
521
|
+
if (req.type !== 'query_address' || typeof req.ownerAddress !== 'string') {
|
|
522
|
+
return req;
|
|
523
|
+
}
|
|
524
|
+
return {
|
|
525
|
+
...req,
|
|
526
|
+
ownerAddress: normalizeDomainInput(req.ownerAddress, userDomains),
|
|
527
|
+
};
|
|
528
|
+
});
|
|
529
|
+
return {
|
|
530
|
+
...params,
|
|
531
|
+
requirements: normalized,
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
function buildToolResponseMessages(toolCalls, responses) {
|
|
535
|
+
return toolCalls
|
|
536
|
+
.filter((toolCall) => toolCall.id)
|
|
537
|
+
.map((toolCall) => {
|
|
538
|
+
const content = toolCall.id && Object.prototype.hasOwnProperty.call(responses, toolCall.id)
|
|
539
|
+
? responses[toolCall.id]
|
|
540
|
+
: { error: `Unknown function: ${toolCall.function.name}` };
|
|
541
|
+
return {
|
|
542
|
+
role: 'tool',
|
|
543
|
+
tool_call_id: toolCall.id,
|
|
544
|
+
content: JSON.stringify(content),
|
|
545
|
+
};
|
|
546
|
+
});
|
|
547
|
+
}
|
|
496
548
|
async function processNonStreamingResponse(response) {
|
|
497
549
|
const message = response.choices[0]?.message;
|
|
498
550
|
if (!message) {
|
|
@@ -500,7 +552,7 @@ async function processNonStreamingResponse(response) {
|
|
|
500
552
|
}
|
|
501
553
|
if (message.content) {
|
|
502
554
|
printMarkdownContent(message.content);
|
|
503
|
-
|
|
555
|
+
logger.verbose();
|
|
504
556
|
}
|
|
505
557
|
return { message };
|
|
506
558
|
}
|
|
@@ -572,10 +624,10 @@ async function processStreamingResponse(stream) {
|
|
|
572
624
|
for (const line of lines) {
|
|
573
625
|
if (line.trim()) {
|
|
574
626
|
const formatted = formatMarkdown(line);
|
|
575
|
-
|
|
627
|
+
logger.verbose(formatted);
|
|
576
628
|
}
|
|
577
629
|
else if (line === '') {
|
|
578
|
-
|
|
630
|
+
logger.verbose();
|
|
579
631
|
}
|
|
580
632
|
}
|
|
581
633
|
printedUpTo = lastNewlineIndex + 1;
|
|
@@ -621,11 +673,11 @@ async function processStreamingResponse(stream) {
|
|
|
621
673
|
const remainingText = contentBuffer.substring(printedUpTo);
|
|
622
674
|
if (remainingText.trim()) {
|
|
623
675
|
const formatted = formatMarkdown(remainingText);
|
|
624
|
-
|
|
676
|
+
logger.verbose(formatted);
|
|
625
677
|
}
|
|
626
678
|
}
|
|
627
679
|
if (contentBuffer.length > 0) {
|
|
628
|
-
|
|
680
|
+
logger.verbose(); // Extra newline after AI response
|
|
629
681
|
}
|
|
630
682
|
// Convert toolCallsMap to array
|
|
631
683
|
toolCalls = Object.values(toolCallsMap).filter((tc) => tc.id);
|
|
@@ -650,6 +702,7 @@ async function processStreamingResponse(stream) {
|
|
|
650
702
|
*/
|
|
651
703
|
async function processIntentParserRequest(userRequest, options = {}) {
|
|
652
704
|
const { modelName, conversationContext } = options;
|
|
705
|
+
const userDomains = extractDomains(userRequest);
|
|
653
706
|
const client = createIntentParserClient(modelName);
|
|
654
707
|
const modelConfig = (0, config_1.getModelConfig)(modelName);
|
|
655
708
|
const config = (0, config_1.getConfig)();
|
|
@@ -691,13 +744,10 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
691
744
|
// Get the list of configured devices
|
|
692
745
|
const { getConfiguredDevices } = await Promise.resolve().then(() => __importStar(require('../utilities/functions')));
|
|
693
746
|
const result = await getConfiguredDevices();
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
content: JSON.stringify(result),
|
|
699
|
-
};
|
|
700
|
-
const updatedMessages = [...messages, message, toolResultMessage];
|
|
747
|
+
const toolResultMessages = buildToolResponseMessages(message.tool_calls, {
|
|
748
|
+
[toolCall.id]: result,
|
|
749
|
+
});
|
|
750
|
+
const updatedMessages = [...messages, message, ...toolResultMessages];
|
|
701
751
|
// Continue the conversation with the device list
|
|
702
752
|
const followUpRequest = {
|
|
703
753
|
model: modelConfig.model,
|
|
@@ -723,7 +773,7 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
723
773
|
if (followUpMessage.tool_calls && followUpMessage.tool_calls.length > 0) {
|
|
724
774
|
const followUpToolCall = followUpMessage.tool_calls[0];
|
|
725
775
|
if (followUpToolCall.function.name === 'parse_requirements') {
|
|
726
|
-
const params = JSON.parse(followUpToolCall.function.arguments);
|
|
776
|
+
const params = normalizeRequirementDomains(JSON.parse(followUpToolCall.function.arguments), userDomains);
|
|
727
777
|
// Apply constraints and defaults
|
|
728
778
|
const validatedParams = (0, utils_1.applyConstraints)(params, config);
|
|
729
779
|
return {
|
|
@@ -741,16 +791,13 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
741
791
|
apiKey: server.apiKey,
|
|
742
792
|
})) ||
|
|
743
793
|
feedConfig.baseURLs.map((url) => ({ baseUrl: url, apiKey: feedConfig.apiKey }));
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
tool_call_id: followUpToolCall.id,
|
|
748
|
-
content: JSON.stringify({ servers: serverList }),
|
|
749
|
-
};
|
|
794
|
+
const feedToolResultMessages = buildToolResponseMessages(followUpMessage.tool_calls, {
|
|
795
|
+
[followUpToolCall.id]: { servers: serverList },
|
|
796
|
+
});
|
|
750
797
|
const feedUpdatedMessages = [
|
|
751
798
|
...updatedMessages,
|
|
752
799
|
followUpMessage,
|
|
753
|
-
|
|
800
|
+
...feedToolResultMessages,
|
|
754
801
|
];
|
|
755
802
|
// Continue the conversation with the feed server list
|
|
756
803
|
const feedFollowUpRequest = {
|
|
@@ -778,7 +825,7 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
778
825
|
if (feedFollowUpMessage.tool_calls && feedFollowUpMessage.tool_calls.length > 0) {
|
|
779
826
|
const feedToolCall = feedFollowUpMessage.tool_calls[0];
|
|
780
827
|
if (feedToolCall.function.name === 'parse_requirements') {
|
|
781
|
-
const params = JSON.parse(feedToolCall.function.arguments);
|
|
828
|
+
const params = normalizeRequirementDomains(JSON.parse(feedToolCall.function.arguments), userDomains);
|
|
782
829
|
// Apply constraints and defaults
|
|
783
830
|
const validatedParams = (0, utils_1.applyConstraints)(params, config);
|
|
784
831
|
return {
|
|
@@ -886,15 +933,8 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
886
933
|
}
|
|
887
934
|
}
|
|
888
935
|
else {
|
|
889
|
-
|
|
890
|
-
const
|
|
891
|
-
role: 'tool',
|
|
892
|
-
tool_call_id: followUpToolCall.id,
|
|
893
|
-
content: JSON.stringify({
|
|
894
|
-
error: `Unknown function: ${followUpToolCall.function.name}`,
|
|
895
|
-
}),
|
|
896
|
-
};
|
|
897
|
-
const validMessages = [...updatedMessages, followUpMessage, toolResultMessage];
|
|
936
|
+
const toolResultMessages = buildToolResponseMessages(followUpMessage.tool_calls, {});
|
|
937
|
+
const validMessages = [...updatedMessages, followUpMessage, ...toolResultMessages];
|
|
898
938
|
// AI is still asking for more information after the error
|
|
899
939
|
return {
|
|
900
940
|
approved: false,
|
|
@@ -921,13 +961,10 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
921
961
|
baseUrl: server.baseUrl,
|
|
922
962
|
apiKey: server.apiKey,
|
|
923
963
|
})) || feedConfig.baseURLs.map((url) => ({ baseUrl: url, apiKey: feedConfig.apiKey }));
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
content: JSON.stringify({ servers: serverList }),
|
|
929
|
-
};
|
|
930
|
-
const updatedMessages = [...messages, message, toolResultMessage];
|
|
964
|
+
const toolResultMessages = buildToolResponseMessages(message.tool_calls, {
|
|
965
|
+
[toolCall.id]: { servers: serverList },
|
|
966
|
+
});
|
|
967
|
+
const updatedMessages = [...messages, message, ...toolResultMessages];
|
|
931
968
|
// Continue the conversation with the feed server list
|
|
932
969
|
const followUpRequest = {
|
|
933
970
|
model: modelConfig.model,
|
|
@@ -953,7 +990,7 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
953
990
|
if (followUpMessage.tool_calls && followUpMessage.tool_calls.length > 0) {
|
|
954
991
|
const followUpToolCall = followUpMessage.tool_calls[0];
|
|
955
992
|
if (followUpToolCall.function.name === 'parse_requirements') {
|
|
956
|
-
const params = JSON.parse(followUpToolCall.function.arguments);
|
|
993
|
+
const params = normalizeRequirementDomains(JSON.parse(followUpToolCall.function.arguments), userDomains);
|
|
957
994
|
// Apply constraints and defaults
|
|
958
995
|
const validatedParams = (0, utils_1.applyConstraints)(params, config);
|
|
959
996
|
return {
|
|
@@ -1016,7 +1053,7 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
1016
1053
|
};
|
|
1017
1054
|
}
|
|
1018
1055
|
else if (toolCall.function.name === 'parse_requirements') {
|
|
1019
|
-
const params = JSON.parse(toolCall.function.arguments);
|
|
1056
|
+
const params = normalizeRequirementDomains(JSON.parse(toolCall.function.arguments), userDomains);
|
|
1020
1057
|
// Apply constraints and defaults
|
|
1021
1058
|
const validatedParams = (0, utils_1.applyConstraints)(params, config);
|
|
1022
1059
|
return {
|
|
@@ -1031,17 +1068,14 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
1031
1068
|
// Validate and confirm the playlist
|
|
1032
1069
|
const confirmation = await confirmPlaylistForSending(args.filePath, args.deviceName);
|
|
1033
1070
|
if (!confirmation.success) {
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
role: 'tool',
|
|
1037
|
-
tool_call_id: toolCall.id,
|
|
1038
|
-
content: JSON.stringify({
|
|
1071
|
+
const toolResultMessages = buildToolResponseMessages(message.tool_calls, {
|
|
1072
|
+
[toolCall.id]: {
|
|
1039
1073
|
success: false,
|
|
1040
1074
|
error: confirmation.error,
|
|
1041
1075
|
message: confirmation.message,
|
|
1042
|
-
}
|
|
1043
|
-
};
|
|
1044
|
-
const validMessages = [...messages, message,
|
|
1076
|
+
},
|
|
1077
|
+
});
|
|
1078
|
+
const validMessages = [...messages, message, ...toolResultMessages];
|
|
1045
1079
|
// Check if this is a device selection needed case
|
|
1046
1080
|
if (confirmation.needsDeviceSelection) {
|
|
1047
1081
|
// Multiple devices available - ask user to choose
|
|
@@ -1122,20 +1156,20 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
1122
1156
|
}
|
|
1123
1157
|
else if (toolCall.function.name === 'verify_addresses') {
|
|
1124
1158
|
const args = JSON.parse(toolCall.function.arguments);
|
|
1159
|
+
if (Array.isArray(args.addresses) && userDomains.length > 0) {
|
|
1160
|
+
args.addresses = args.addresses.map((address) => normalizeDomainInput(address, userDomains));
|
|
1161
|
+
}
|
|
1125
1162
|
const { verifyAddresses } = await Promise.resolve().then(() => __importStar(require('../utilities/functions')));
|
|
1126
1163
|
const verificationResult = await verifyAddresses({ addresses: args.addresses });
|
|
1127
1164
|
if (!verificationResult.valid) {
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
role: 'tool',
|
|
1131
|
-
tool_call_id: toolCall.id,
|
|
1132
|
-
content: JSON.stringify({
|
|
1165
|
+
const toolResultMessages = buildToolResponseMessages(message.tool_calls, {
|
|
1166
|
+
[toolCall.id]: {
|
|
1133
1167
|
valid: false,
|
|
1134
1168
|
errors: verificationResult.errors,
|
|
1135
1169
|
results: verificationResult.results,
|
|
1136
|
-
}
|
|
1137
|
-
};
|
|
1138
|
-
const validMessages = [...messages, message,
|
|
1170
|
+
},
|
|
1171
|
+
});
|
|
1172
|
+
const validMessages = [...messages, message, ...toolResultMessages];
|
|
1139
1173
|
// Ask user to correct the addresses
|
|
1140
1174
|
return {
|
|
1141
1175
|
approved: false,
|
|
@@ -1144,16 +1178,13 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
1144
1178
|
messages: validMessages,
|
|
1145
1179
|
};
|
|
1146
1180
|
}
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
role: 'tool',
|
|
1150
|
-
tool_call_id: toolCall.id,
|
|
1151
|
-
content: JSON.stringify({
|
|
1181
|
+
const toolResultMessages = buildToolResponseMessages(message.tool_calls, {
|
|
1182
|
+
[toolCall.id]: {
|
|
1152
1183
|
valid: true,
|
|
1153
1184
|
results: verificationResult.results,
|
|
1154
|
-
}
|
|
1155
|
-
};
|
|
1156
|
-
const validMessages = [...messages, message,
|
|
1185
|
+
},
|
|
1186
|
+
});
|
|
1187
|
+
const validMessages = [...messages, message, ...toolResultMessages];
|
|
1157
1188
|
// Continue conversation after validation
|
|
1158
1189
|
const followUpRequest = {
|
|
1159
1190
|
model: modelConfig.model,
|
|
@@ -1179,7 +1210,7 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
1179
1210
|
if (followUpMessage.tool_calls && followUpMessage.tool_calls.length > 0) {
|
|
1180
1211
|
const followUpToolCall = followUpMessage.tool_calls[0];
|
|
1181
1212
|
if (followUpToolCall.function.name === 'parse_requirements') {
|
|
1182
|
-
const params = JSON.parse(followUpToolCall.function.arguments);
|
|
1213
|
+
const params = normalizeRequirementDomains(JSON.parse(followUpToolCall.function.arguments), userDomains);
|
|
1183
1214
|
// Apply constraints and defaults
|
|
1184
1215
|
const validatedParams = (0, utils_1.applyConstraints)(params, config);
|
|
1185
1216
|
return {
|
|
@@ -1198,12 +1229,14 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
1198
1229
|
})) ||
|
|
1199
1230
|
feedConfig.baseURLs.map((url) => ({ baseUrl: url, apiKey: feedConfig.apiKey }));
|
|
1200
1231
|
// Add tool result to messages and continue conversation
|
|
1201
|
-
const
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1232
|
+
const feedToolResultMessages = buildToolResponseMessages(followUpMessage.tool_calls, {
|
|
1233
|
+
[followUpToolCall.id]: { servers: serverList },
|
|
1234
|
+
});
|
|
1235
|
+
const feedUpdatedMessages = [
|
|
1236
|
+
...validMessages,
|
|
1237
|
+
followUpMessage,
|
|
1238
|
+
...feedToolResultMessages,
|
|
1239
|
+
];
|
|
1207
1240
|
// Continue the conversation with the feed server list
|
|
1208
1241
|
const feedFollowUpRequest = {
|
|
1209
1242
|
model: modelConfig.model,
|
|
@@ -1230,7 +1263,7 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
1230
1263
|
if (feedFollowUpMessage.tool_calls && feedFollowUpMessage.tool_calls.length > 0) {
|
|
1231
1264
|
const feedToolCall = feedFollowUpMessage.tool_calls[0];
|
|
1232
1265
|
if (feedToolCall.function.name === 'parse_requirements') {
|
|
1233
|
-
const params = JSON.parse(feedToolCall.function.arguments);
|
|
1266
|
+
const params = normalizeRequirementDomains(JSON.parse(feedToolCall.function.arguments), userDomains);
|
|
1234
1267
|
// Apply constraints and defaults
|
|
1235
1268
|
const validatedParams = (0, utils_1.applyConstraints)(params, config);
|
|
1236
1269
|
return {
|
|
@@ -1308,15 +1341,8 @@ async function processIntentParserRequest(userRequest, options = {}) {
|
|
|
1308
1341
|
};
|
|
1309
1342
|
}
|
|
1310
1343
|
else {
|
|
1311
|
-
|
|
1312
|
-
const
|
|
1313
|
-
role: 'tool',
|
|
1314
|
-
tool_call_id: toolCall.id,
|
|
1315
|
-
content: JSON.stringify({
|
|
1316
|
-
error: `Unknown function: ${toolCall.function.name}`,
|
|
1317
|
-
}),
|
|
1318
|
-
};
|
|
1319
|
-
const validMessages = [...messages, message, toolResultMessage];
|
|
1344
|
+
const toolResultMessages = buildToolResponseMessages(message.tool_calls, {});
|
|
1345
|
+
const validMessages = [...messages, message, ...toolResultMessages];
|
|
1320
1346
|
return {
|
|
1321
1347
|
approved: false,
|
|
1322
1348
|
needsMoreInfo: true,
|
|
@@ -57,8 +57,11 @@ function applyConstraints(params, config) {
|
|
|
57
57
|
// Set default quantity if not provided
|
|
58
58
|
// Allow "all" as a string value for query_address type
|
|
59
59
|
let quantity;
|
|
60
|
-
if (r.quantity === 'all'
|
|
61
|
-
quantity =
|
|
60
|
+
if (r.quantity === 'all') {
|
|
61
|
+
quantity = 'all';
|
|
62
|
+
}
|
|
63
|
+
else if (r.quantity === null || r.quantity === undefined) {
|
|
64
|
+
quantity = 5;
|
|
62
65
|
}
|
|
63
66
|
else if (typeof r.quantity === 'string') {
|
|
64
67
|
// Try to parse string numbers
|
package/dist/src/logger.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.setVerbose = setVerbose;
|
|
|
10
10
|
exports.debug = debug;
|
|
11
11
|
exports.info = info;
|
|
12
12
|
exports.warn = warn;
|
|
13
|
+
exports.verbose = verbose;
|
|
13
14
|
exports.error = error;
|
|
14
15
|
exports.always = always;
|
|
15
16
|
const chalk_1 = __importDefault(require("chalk"));
|
|
@@ -49,6 +50,15 @@ function warn(...args) {
|
|
|
49
50
|
console.warn(chalk_1.default.yellow('[WARN]'), ...args);
|
|
50
51
|
}
|
|
51
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Log message only in verbose mode (no prefix)
|
|
55
|
+
* @param {...any} args - Arguments to log
|
|
56
|
+
*/
|
|
57
|
+
function verbose(...args) {
|
|
58
|
+
if (isVerbose) {
|
|
59
|
+
console.log(...args);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
52
62
|
/**
|
|
53
63
|
* Log error message (always shown, but with more details in verbose mode)
|
|
54
64
|
* @param {...any} args - Arguments to log
|