multiclaws 0.4.15 → 0.4.17
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/infra/frp.js
CHANGED
|
@@ -362,8 +362,9 @@ class FrpTunnelManager {
|
|
|
362
362
|
(0, node_child_process_1.execSync)(`tar -xzf "${archivePath}" -C "${downloadDir}"`, { stdio: "ignore" });
|
|
363
363
|
}
|
|
364
364
|
else {
|
|
365
|
-
// Windows:
|
|
366
|
-
|
|
365
|
+
// Windows: suppress progress bar to prevent silent failure in headless environments;
|
|
366
|
+
// use stdio:"pipe" so execSync captures errors if PowerShell exits non-zero
|
|
367
|
+
(0, node_child_process_1.execSync)(`powershell -NoProfile -Command "$ProgressPreference = 'SilentlyContinue'; Expand-Archive -LiteralPath '${archivePath}' -DestinationPath '${downloadDir}' -Force"`, { stdio: "pipe" });
|
|
367
368
|
}
|
|
368
369
|
// Move binary to target
|
|
369
370
|
const extractedBinary = node_path_1.default.join(downloadDir, archiveName, binaryName);
|
|
@@ -27,17 +27,20 @@ export declare class OpenClawAgentExecutor implements AgentExecutor {
|
|
|
27
27
|
constructor(options: A2AAdapterOptions);
|
|
28
28
|
execute(context: RequestContext, eventBus: ExecutionEventBus): Promise<void>;
|
|
29
29
|
/**
|
|
30
|
-
* Poll sessions_history until the subagent
|
|
31
|
-
*
|
|
30
|
+
* Poll sessions_history until the subagent session completes.
|
|
31
|
+
* Collects ALL assistant text messages and returns them joined.
|
|
32
32
|
*/
|
|
33
33
|
private waitForCompletion;
|
|
34
34
|
/**
|
|
35
|
-
* Extract
|
|
35
|
+
* Extract all assistant text from session history once the session is complete.
|
|
36
36
|
* Returns null if the session is still running.
|
|
37
|
+
* Returns all assistant text messages joined (not just the last one).
|
|
37
38
|
*
|
|
38
39
|
* Gateway /tools/invoke returns: { content: [...], details: { messages: [...], isComplete?: boolean } }
|
|
39
40
|
*/
|
|
40
41
|
private extractCompletedResult;
|
|
42
|
+
/** Extract text content from a single history message. */
|
|
43
|
+
private extractTextFromHistoryMessage;
|
|
41
44
|
cancelTask(taskId: string, eventBus: ExecutionEventBus): Promise<void>;
|
|
42
45
|
updateGatewayConfig(config: GatewayConfig): void;
|
|
43
46
|
private publishMessage;
|
|
@@ -103,14 +103,13 @@ class OpenClawAgentExecutor {
|
|
|
103
103
|
eventBus.finished();
|
|
104
104
|
}
|
|
105
105
|
/**
|
|
106
|
-
* Poll sessions_history until the subagent
|
|
107
|
-
*
|
|
106
|
+
* Poll sessions_history until the subagent session completes.
|
|
107
|
+
* Collects ALL assistant text messages and returns them joined.
|
|
108
108
|
*/
|
|
109
109
|
async waitForCompletion(sessionKey, timeoutMs) {
|
|
110
110
|
const gateway = this.gatewayConfig;
|
|
111
111
|
const startTime = Date.now();
|
|
112
112
|
let attempt = 0;
|
|
113
|
-
// Start aggressive, max out at 500ms to minimize result latency
|
|
114
113
|
const pollDelays = [100, 200, 300, 500];
|
|
115
114
|
while (Date.now() - startTime < timeoutMs) {
|
|
116
115
|
const delay = pollDelays[Math.min(attempt, pollDelays.length - 1)];
|
|
@@ -122,7 +121,7 @@ class OpenClawAgentExecutor {
|
|
|
122
121
|
tool: "sessions_history",
|
|
123
122
|
args: {
|
|
124
123
|
sessionKey,
|
|
125
|
-
limit:
|
|
124
|
+
limit: 50,
|
|
126
125
|
includeTools: false,
|
|
127
126
|
},
|
|
128
127
|
timeoutMs: 8_000,
|
|
@@ -140,8 +139,9 @@ class OpenClawAgentExecutor {
|
|
|
140
139
|
throw new Error(`task timed out after ${Math.round(timeoutMs / 1000)}s waiting for subagent`);
|
|
141
140
|
}
|
|
142
141
|
/**
|
|
143
|
-
* Extract
|
|
142
|
+
* Extract all assistant text from session history once the session is complete.
|
|
144
143
|
* Returns null if the session is still running.
|
|
144
|
+
* Returns all assistant text messages joined (not just the last one).
|
|
145
145
|
*
|
|
146
146
|
* Gateway /tools/invoke returns: { content: [...], details: { messages: [...], isComplete?: boolean } }
|
|
147
147
|
*/
|
|
@@ -152,37 +152,69 @@ class OpenClawAgentExecutor {
|
|
|
152
152
|
// Respect explicit completion flag from gateway
|
|
153
153
|
if (details.isComplete === false)
|
|
154
154
|
return null;
|
|
155
|
+
// Check for session-level error/status from gateway
|
|
156
|
+
const sessionError = details.error;
|
|
157
|
+
const sessionStatus = details.status;
|
|
155
158
|
const messages = (details.messages ?? []);
|
|
156
|
-
if (messages.length === 0)
|
|
159
|
+
if (messages.length === 0 && !details.isComplete)
|
|
157
160
|
return null;
|
|
158
|
-
// If no explicit flag,
|
|
161
|
+
// If no explicit isComplete flag, use heuristic: check if the session is still executing
|
|
159
162
|
if (details.isComplete === undefined) {
|
|
163
|
+
if (messages.length === 0)
|
|
164
|
+
return null;
|
|
160
165
|
const lastMsg = messages[messages.length - 1];
|
|
161
166
|
if (lastMsg && Array.isArray(lastMsg.content)) {
|
|
162
167
|
const content = lastMsg.content;
|
|
163
168
|
const hasToolCalls = content.some((c) => c?.type === "toolCall" || c?.type === "tool_use");
|
|
169
|
+
// If the last message only has tool calls (no text), still running
|
|
164
170
|
const hasText = content.some((c) => c?.type === "text" && typeof c.text === "string" && c.text.trim());
|
|
165
171
|
if (hasToolCalls && !hasText)
|
|
166
172
|
return null;
|
|
167
173
|
}
|
|
174
|
+
// If the last message is a user message, the agent hasn't responded yet
|
|
175
|
+
if (lastMsg?.role === "user")
|
|
176
|
+
return null;
|
|
168
177
|
}
|
|
169
|
-
//
|
|
170
|
-
|
|
171
|
-
|
|
178
|
+
// Session is complete — collect ALL assistant text messages in order
|
|
179
|
+
const allTexts = [];
|
|
180
|
+
for (const msg of messages) {
|
|
172
181
|
if (msg.role !== "assistant")
|
|
173
182
|
continue;
|
|
174
|
-
const
|
|
175
|
-
if (
|
|
176
|
-
|
|
183
|
+
const text = this.extractTextFromHistoryMessage(msg);
|
|
184
|
+
if (text)
|
|
185
|
+
allTexts.push(text);
|
|
186
|
+
}
|
|
187
|
+
// If we have assistant text, return it (even if there's also an error)
|
|
188
|
+
if (allTexts.length > 0) {
|
|
189
|
+
// Append error info if present so the delegating agent sees both
|
|
190
|
+
if (sessionError) {
|
|
191
|
+
allTexts.push(`[session error: ${sessionError}]`);
|
|
177
192
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
193
|
+
return allTexts.join("\n\n");
|
|
194
|
+
}
|
|
195
|
+
// No assistant text — check if the session reported an error
|
|
196
|
+
if (sessionError) {
|
|
197
|
+
return `Error: ${sessionError}`;
|
|
198
|
+
}
|
|
199
|
+
if (sessionStatus === "failed" || sessionStatus === "error") {
|
|
200
|
+
return `Error: session ended with status "${sessionStatus}"`;
|
|
201
|
+
}
|
|
202
|
+
// Session truly completed with no output at all
|
|
203
|
+
return "(task completed with no text output)";
|
|
204
|
+
}
|
|
205
|
+
/** Extract text content from a single history message. */
|
|
206
|
+
extractTextFromHistoryMessage(msg) {
|
|
207
|
+
const content = msg.content;
|
|
208
|
+
if (typeof content === "string" && content.trim()) {
|
|
209
|
+
return content;
|
|
210
|
+
}
|
|
211
|
+
if (Array.isArray(content)) {
|
|
212
|
+
const parts = content;
|
|
213
|
+
const textParts = parts
|
|
214
|
+
.filter((c) => c?.type === "text" && typeof c.text === "string" && c.text.trim())
|
|
215
|
+
.map((c) => c.text);
|
|
216
|
+
if (textParts.length > 0) {
|
|
217
|
+
return textParts.join("\n");
|
|
186
218
|
}
|
|
187
219
|
}
|
|
188
220
|
return null;
|