@stagewhisper/stagewhisper 0.59.0 → 0.60.0
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/index.js +185 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -119,6 +119,54 @@ var init_client = __esm({
|
|
|
119
119
|
throw new Error(`Chat reply failed (${res.status}): ${text}`);
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
|
+
async startChatReply(userMessageId) {
|
|
123
|
+
const res = await fetch(
|
|
124
|
+
`${this.baseUrl}/api/v1/openclaw/chat/messages/${userMessageId}/reply/start`,
|
|
125
|
+
{
|
|
126
|
+
method: "POST",
|
|
127
|
+
headers: this.headers()
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
if (!res.ok) {
|
|
131
|
+
const text = await res.text();
|
|
132
|
+
throw new Error(`Chat reply start failed (${res.status}): ${text}`);
|
|
133
|
+
}
|
|
134
|
+
return await res.json();
|
|
135
|
+
}
|
|
136
|
+
async postChatReplyDelta(assistantMessageId, delta) {
|
|
137
|
+
const res = await fetch(
|
|
138
|
+
`${this.baseUrl}/api/v1/openclaw/chat/messages/${assistantMessageId}/reply/delta`,
|
|
139
|
+
{
|
|
140
|
+
method: "POST",
|
|
141
|
+
headers: this.headers(),
|
|
142
|
+
body: JSON.stringify({ delta })
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
if (!res.ok) {
|
|
146
|
+
const text = await res.text();
|
|
147
|
+
throw new Error(`Chat reply delta failed (${res.status}): ${text}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async completeChatReply(assistantMessageId, options) {
|
|
151
|
+
const body = {
|
|
152
|
+
status: options?.status ?? "completed"
|
|
153
|
+
};
|
|
154
|
+
if (options?.content !== void 0) body.content = options.content;
|
|
155
|
+
if (options?.errorCode) body.error_code = options.errorCode;
|
|
156
|
+
if (options?.errorMessage) body.error_message = options.errorMessage;
|
|
157
|
+
const res = await fetch(
|
|
158
|
+
`${this.baseUrl}/api/v1/openclaw/chat/messages/${assistantMessageId}/reply/complete`,
|
|
159
|
+
{
|
|
160
|
+
method: "POST",
|
|
161
|
+
headers: this.headers(),
|
|
162
|
+
body: JSON.stringify(body)
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
if (!res.ok) {
|
|
166
|
+
const text = await res.text();
|
|
167
|
+
throw new Error(`Chat reply complete failed (${res.status}): ${text}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
122
170
|
async heartbeat(capabilities) {
|
|
123
171
|
const res = await fetch(
|
|
124
172
|
`${this.baseUrl}/api/v1/openclaw/integrations/${this.integrationId}/heartbeat`,
|
|
@@ -4898,6 +4946,15 @@ function createRelayService(api) {
|
|
|
4898
4946
|
const decoratedPrompt = `${plaintextContent}
|
|
4899
4947
|
|
|
4900
4948
|
[StageWhisper chat: ${userMessageId}]`;
|
|
4949
|
+
if (envelopeKey === null) {
|
|
4950
|
+
await handleChatMessageStreaming(
|
|
4951
|
+
client,
|
|
4952
|
+
sessionKey,
|
|
4953
|
+
userMessageId,
|
|
4954
|
+
decoratedPrompt
|
|
4955
|
+
);
|
|
4956
|
+
return;
|
|
4957
|
+
}
|
|
4901
4958
|
try {
|
|
4902
4959
|
const result = await api.runtime.subagent.run({
|
|
4903
4960
|
sessionKey,
|
|
@@ -4948,6 +5005,134 @@ function createRelayService(api) {
|
|
|
4948
5005
|
}
|
|
4949
5006
|
}
|
|
4950
5007
|
}
|
|
5008
|
+
async function handleChatMessageStreaming(client, sessionKey, userMessageId, decoratedPrompt) {
|
|
5009
|
+
let assistantId;
|
|
5010
|
+
try {
|
|
5011
|
+
const started = await client.startChatReply(userMessageId);
|
|
5012
|
+
assistantId = started.id;
|
|
5013
|
+
} catch (err) {
|
|
5014
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
5015
|
+
api.logger.error(
|
|
5016
|
+
`Chat ${userMessageId} failed to start streaming reply: ${errMsg}`
|
|
5017
|
+
);
|
|
5018
|
+
try {
|
|
5019
|
+
await client.postChatReply(userMessageId, "(streaming start failed)", {
|
|
5020
|
+
status: "errored",
|
|
5021
|
+
errorCode: "stream_start_failed",
|
|
5022
|
+
errorMessage: errMsg
|
|
5023
|
+
});
|
|
5024
|
+
} catch (postErr) {
|
|
5025
|
+
api.logger.error(
|
|
5026
|
+
`Chat ${userMessageId} fallback errored post failed: ${postErr}`
|
|
5027
|
+
);
|
|
5028
|
+
}
|
|
5029
|
+
return;
|
|
5030
|
+
}
|
|
5031
|
+
let ackedText = "";
|
|
5032
|
+
const sendDelta = async (full) => {
|
|
5033
|
+
if (!full || full.length <= ackedText.length) return;
|
|
5034
|
+
if (!full.startsWith(ackedText)) return;
|
|
5035
|
+
const diff = full.slice(ackedText.length);
|
|
5036
|
+
if (!diff) return;
|
|
5037
|
+
try {
|
|
5038
|
+
await client.postChatReplyDelta(assistantId, diff);
|
|
5039
|
+
ackedText = full;
|
|
5040
|
+
} catch (err) {
|
|
5041
|
+
api.logger.warn(`Chat ${userMessageId} delta post failed: ${err}`);
|
|
5042
|
+
}
|
|
5043
|
+
};
|
|
5044
|
+
const finalizeErrored = async (content, errorCode, errorMessage) => {
|
|
5045
|
+
try {
|
|
5046
|
+
await client.completeChatReply(assistantId, {
|
|
5047
|
+
status: "errored",
|
|
5048
|
+
content: content || void 0,
|
|
5049
|
+
errorCode,
|
|
5050
|
+
errorMessage
|
|
5051
|
+
});
|
|
5052
|
+
} catch (postErr) {
|
|
5053
|
+
api.logger.error(
|
|
5054
|
+
`Chat ${userMessageId} finalize errored failed: ${postErr}`
|
|
5055
|
+
);
|
|
5056
|
+
}
|
|
5057
|
+
};
|
|
5058
|
+
let pollDone = false;
|
|
5059
|
+
const pollInterval = 400;
|
|
5060
|
+
const pollLoop = (async () => {
|
|
5061
|
+
while (!pollDone) {
|
|
5062
|
+
await new Promise((r) => setTimeout(r, pollInterval));
|
|
5063
|
+
if (pollDone) break;
|
|
5064
|
+
try {
|
|
5065
|
+
const partial = await extractReplyForChatMessage(
|
|
5066
|
+
sessionKey,
|
|
5067
|
+
userMessageId,
|
|
5068
|
+
1
|
|
5069
|
+
);
|
|
5070
|
+
if (partial) await sendDelta(partial);
|
|
5071
|
+
} catch (err) {
|
|
5072
|
+
api.logger.warn(`Chat ${userMessageId} poll failed: ${err}`);
|
|
5073
|
+
}
|
|
5074
|
+
}
|
|
5075
|
+
})();
|
|
5076
|
+
try {
|
|
5077
|
+
const result = await api.runtime.subagent.run({
|
|
5078
|
+
sessionKey,
|
|
5079
|
+
message: decoratedPrompt,
|
|
5080
|
+
deliver: true,
|
|
5081
|
+
idempotencyKey: `sw-chat-${userMessageId}`
|
|
5082
|
+
});
|
|
5083
|
+
const waitResult = await api.runtime.subagent.waitForRun({
|
|
5084
|
+
runId: result.runId,
|
|
5085
|
+
timeoutMs: 12e4
|
|
5086
|
+
});
|
|
5087
|
+
pollDone = true;
|
|
5088
|
+
await pollLoop;
|
|
5089
|
+
const finalReply = await extractReplyForChatMessage(
|
|
5090
|
+
sessionKey,
|
|
5091
|
+
userMessageId
|
|
5092
|
+
);
|
|
5093
|
+
if (waitResult.status !== "ok") {
|
|
5094
|
+
api.logger.error(
|
|
5095
|
+
`Agent run failed for chat ${userMessageId}: ${waitResult.error}`
|
|
5096
|
+
);
|
|
5097
|
+
await finalizeErrored(
|
|
5098
|
+
finalReply ?? ackedText,
|
|
5099
|
+
"agent_error",
|
|
5100
|
+
waitResult.error ?? "Agent run failed"
|
|
5101
|
+
);
|
|
5102
|
+
return;
|
|
5103
|
+
}
|
|
5104
|
+
if (!finalReply) {
|
|
5105
|
+
api.logger.warn(
|
|
5106
|
+
`Chat message ${userMessageId} completed but no reply found`
|
|
5107
|
+
);
|
|
5108
|
+
await finalizeErrored(
|
|
5109
|
+
ackedText,
|
|
5110
|
+
"no_reply",
|
|
5111
|
+
"Agent run produced no reply"
|
|
5112
|
+
);
|
|
5113
|
+
return;
|
|
5114
|
+
}
|
|
5115
|
+
try {
|
|
5116
|
+
await client.completeChatReply(assistantId, { content: finalReply });
|
|
5117
|
+
api.logger.info(`Chat message ${userMessageId} streamed`);
|
|
5118
|
+
} catch (completeErr) {
|
|
5119
|
+
const errMsg = completeErr instanceof Error ? completeErr.message : String(completeErr);
|
|
5120
|
+
api.logger.error(
|
|
5121
|
+
`Chat ${userMessageId} complete failed: ${errMsg}`
|
|
5122
|
+
);
|
|
5123
|
+
await finalizeErrored(finalReply, "complete_failed", errMsg);
|
|
5124
|
+
}
|
|
5125
|
+
} catch (err) {
|
|
5126
|
+
pollDone = true;
|
|
5127
|
+
try {
|
|
5128
|
+
await pollLoop;
|
|
5129
|
+
} catch {
|
|
5130
|
+
}
|
|
5131
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
5132
|
+
api.logger.error(`Failed to stream chat ${userMessageId}: ${errMsg}`);
|
|
5133
|
+
await finalizeErrored(ackedText, "execution_error", errMsg);
|
|
5134
|
+
}
|
|
5135
|
+
}
|
|
4951
5136
|
async function handleReasoningJob(job, client) {
|
|
4952
5137
|
const hydrated = await hydrateReasoningJobEnvelope(
|
|
4953
5138
|
job,
|
package/openclaw.plugin.json
CHANGED