@meetopenbot/openbot 1.2.1 → 1.2.2
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/history.js +62 -38
- package/package.json +2 -2
package/dist/history.js
CHANGED
|
@@ -71,51 +71,75 @@ function appendAssistantOutput(message, text, reasoningParts) {
|
|
|
71
71
|
insertBeforeToolCalls(parts, [{ type: 'text', text }]);
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
74
|
+
function isToolResultPart(part) {
|
|
75
|
+
return Boolean(part && typeof part === 'object' && part.type === 'tool-result');
|
|
76
|
+
}
|
|
77
|
+
function assistantToolCalls(message) {
|
|
78
|
+
if (message.role !== 'assistant' || !Array.isArray(message.content))
|
|
79
|
+
return [];
|
|
80
|
+
const calls = [];
|
|
81
|
+
for (const part of message.content) {
|
|
82
|
+
if (part.type !== 'tool-call')
|
|
83
|
+
continue;
|
|
84
|
+
const toolCall = part;
|
|
85
|
+
if (typeof toolCall.toolCallId !== 'string')
|
|
86
|
+
continue;
|
|
87
|
+
calls.push({
|
|
88
|
+
toolCallId: toolCall.toolCallId,
|
|
89
|
+
toolName: typeof toolCall.toolName === 'string' ? toolCall.toolName : 'tool',
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return calls;
|
|
93
|
+
}
|
|
94
|
+
function collectToolResults(messages) {
|
|
95
|
+
const results = new Map();
|
|
96
|
+
for (const message of messages) {
|
|
97
|
+
if (message.role !== 'tool' || !Array.isArray(message.content))
|
|
98
|
+
continue;
|
|
99
|
+
for (const part of message.content) {
|
|
100
|
+
if (!isToolResultPart(part) || results.has(part.toolCallId))
|
|
101
|
+
continue;
|
|
102
|
+
results.set(part.toolCallId, part);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return results;
|
|
106
|
+
}
|
|
107
|
+
function toolMessageForCalls(calls, results) {
|
|
108
|
+
return {
|
|
109
|
+
role: 'tool',
|
|
110
|
+
content: calls.map(({ toolCallId, toolName }) => {
|
|
111
|
+
const existing = results.get(toolCallId);
|
|
112
|
+
if (existing) {
|
|
113
|
+
results.delete(toolCallId);
|
|
114
|
+
return existing;
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
88
117
|
type: 'tool-result',
|
|
89
118
|
toolCallId,
|
|
90
119
|
toolName,
|
|
91
120
|
output: { type: 'text', value: '' },
|
|
92
|
-
}
|
|
93
|
-
})
|
|
94
|
-
pending.clear();
|
|
121
|
+
};
|
|
122
|
+
}),
|
|
95
123
|
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Rebuild tool messages so every `tool-call` is followed immediately by matching
|
|
127
|
+
* results. Late results (user invoke between call and `:result`) are moved next
|
|
128
|
+
* to their call; unmatched results are dropped; interrupted calls get an empty
|
|
129
|
+
* result so the next LLM turn does not fail provider validation.
|
|
130
|
+
*/
|
|
131
|
+
function sanitizeToolPairing(messages) {
|
|
132
|
+
const results = collectToolResults(messages);
|
|
133
|
+
const sanitized = [];
|
|
96
134
|
for (const message of messages) {
|
|
97
|
-
if (message.role === 'tool'
|
|
98
|
-
filled.push(message);
|
|
99
|
-
for (const part of message.content) {
|
|
100
|
-
if (part.type === 'tool-result') {
|
|
101
|
-
pending.delete(part.toolCallId);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
135
|
+
if (message.role === 'tool')
|
|
104
136
|
continue;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
for (const part of message.content) {
|
|
110
|
-
if (part.type === 'tool-call') {
|
|
111
|
-
const toolCall = part;
|
|
112
|
-
pending.set(toolCall.toolCallId, toolCall.toolName);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
137
|
+
sanitized.push(message);
|
|
138
|
+
const calls = assistantToolCalls(message);
|
|
139
|
+
if (calls.length > 0)
|
|
140
|
+
sanitized.push(toolMessageForCalls(calls, results));
|
|
116
141
|
}
|
|
117
|
-
|
|
118
|
-
return filled;
|
|
142
|
+
return sanitized;
|
|
119
143
|
}
|
|
120
144
|
function toolResultText(data) {
|
|
121
145
|
if (data && typeof data === 'object') {
|
|
@@ -235,5 +259,5 @@ export function eventsToModelMessages(events, options) {
|
|
|
235
259
|
break;
|
|
236
260
|
}
|
|
237
261
|
}
|
|
238
|
-
return
|
|
262
|
+
return sanitizeToolPairing(messages);
|
|
239
263
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meetopenbot/openbot",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "OpenBot coordinator runtime: ask specialists, route work into Spaces, and track todos.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@ai-sdk/openai": "^4.0.46",
|
|
26
26
|
"ai": "^7.0.77",
|
|
27
27
|
"zod": "^4.3.5",
|
|
28
|
-
"@meetopenbot/plugin-sdk": "^1.1.
|
|
28
|
+
"@meetopenbot/plugin-sdk": "^1.1.3"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/node": "^20.10.1",
|