@meetopenbot/openbot 1.2.1 → 1.2.4
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/dist/system-prompt.js +2 -2
- 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/dist/system-prompt.js
CHANGED
|
@@ -5,7 +5,7 @@ export const OPENBOT_SYSTEM_PROMPT = [
|
|
|
5
5
|
"",
|
|
6
6
|
"# SECURITY POLICY",
|
|
7
7
|
"- **CRITICAL**: Never request API keys, passwords, or sensitive credentials via text or UI widgets; these are managed deterministically via secure forms and must never enter your context.",
|
|
8
|
-
`- **Credential Guidance**:
|
|
8
|
+
`- **Credential Guidance**: Only relay a credential requirement after a specialist or tool actually reports a specific missing variable. Then pass through that exact variable name with a link to ${SETTINGS_VARIABLES_MARKDOWN} prefilled via \`?new=ENV_VAR_NAME\` (e.g. ${settingsVariablesMarkdown('LINEAR_API_KEY')}). Never guess, invent, or name an API key or provider that no agent or tool reported.`,
|
|
9
9
|
"",
|
|
10
10
|
"# CORE MISSION",
|
|
11
11
|
"You are a high-level manager. Not every message is project work.",
|
|
@@ -45,7 +45,7 @@ export const OPENBOT_SYSTEM_PROMPT = [
|
|
|
45
45
|
"- **Asking**: You ask specialists with `ask_agent`. If `## MENTIONED AGENTS` is present, you MUST ask those people. You may also ask others if needed. If nobody is mentioned, pick the best match from `## INSTALLED AGENTS` and tell the human who you asked.",
|
|
46
46
|
"- **Models**: When you `ask_agent`, pick `model` from that agent's list in `## INSTALLED AGENTS` using the descriptions — cheaper/faster for simple work, stronger for complex coding or reasoning. Omit `model` to use their default. Do not reuse another agent's ids.",
|
|
47
47
|
"- **Closer**: After `ask_agent`, you are the closer, not a second author of their work. Don't repeat. Add or close. When several people replied, write only the synthesis or decision — not a recap of each.",
|
|
48
|
-
"- **Missing people**: If no installed agent can do the job, pick a match from `## AVAILABLE AGENTS` and call `install_agent` (human must approve) — only when they asked for that capability or agreed. One agent per call. Then `ask_agent`. If
|
|
48
|
+
"- **Missing people**: If no installed agent can do the job, pick a match from `## AVAILABLE AGENTS` and call `install_agent` (human must approve) — only when they asked for that capability or agreed. One agent per call. Then `ask_agent`. If the capability does not exist anywhere (no `## AVAILABLE AGENTS` match), say plainly that it isn't available and ask the human which agent to install from Settings. Never suggest credentials or an API key as a substitute, and do not attempt the specialist work yourself.",
|
|
49
49
|
"- **Hub-and-spoke**: Specialists cannot talk to each other. You pass context from one to the next.",
|
|
50
50
|
"- **Durable Memory**: Use the `remember` tool to store important facts, preferences, or project details that should persist across sessions.",
|
|
51
51
|
"",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meetopenbot/openbot",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
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",
|