@stagewhisper/stagewhisper 0.32.0 → 0.35.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/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/plugin-main.ts +8 -7
- package/src/service.ts +68 -7
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
package/plugin-main.ts
CHANGED
|
@@ -56,12 +56,13 @@ export default definePluginEntry({
|
|
|
56
56
|
plugins["entries"] = entries;
|
|
57
57
|
(cfg as Record<string, unknown>)["plugins"] = plugins;
|
|
58
58
|
|
|
59
|
-
const channels = (
|
|
60
|
-
channels["stagewhisper"]
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
const channels = (cfg as Record<string, unknown>)["channels"] as Record<string, unknown> | undefined;
|
|
60
|
+
if (channels?.["stagewhisper"]) {
|
|
61
|
+
delete channels["stagewhisper"];
|
|
62
|
+
if (Object.keys(channels).length === 0) {
|
|
63
|
+
delete (cfg as Record<string, unknown>)["channels"];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
65
66
|
|
|
66
67
|
await api.runtime.config.writeConfigFile(cfg);
|
|
67
68
|
|
|
@@ -120,7 +121,7 @@ export default definePluginEntry({
|
|
|
120
121
|
if (!configured) {
|
|
121
122
|
console.log("\nStageWhisper: not paired\n");
|
|
122
123
|
console.log(
|
|
123
|
-
" Run: openclaw stagewhisper pair --code <CODE
|
|
124
|
+
" Run: openclaw stagewhisper pair --code <CODE> [--api-url <URL>]\n",
|
|
124
125
|
);
|
|
125
126
|
console.log(
|
|
126
127
|
" Get the pairing code from StageWhisper desktop: Settings → Assistant → Generate Pairing Code\n",
|
package/src/service.ts
CHANGED
|
@@ -77,6 +77,32 @@ export function createRelayService(api: OpenClawPluginApi) {
|
|
|
77
77
|
return lines.join("\n");
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
function isTestTask(task: TaskPayload): boolean {
|
|
81
|
+
return task.action_type === "test";
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function updateStatus(
|
|
85
|
+
client: StageWhisperClient,
|
|
86
|
+
task: TaskPayload,
|
|
87
|
+
status: string,
|
|
88
|
+
): Promise<void> {
|
|
89
|
+
if (isTestTask(task)) return;
|
|
90
|
+
await client.updateTaskStatus(task.id, status);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function extractAssistantReply(
|
|
94
|
+
messages: unknown[],
|
|
95
|
+
): string | null {
|
|
96
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
97
|
+
const msg = messages[i] as Record<string, unknown> | undefined;
|
|
98
|
+
if (!msg) continue;
|
|
99
|
+
if (msg["role"] === "assistant" && typeof msg["content"] === "string") {
|
|
100
|
+
return msg["content"];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
80
106
|
async function handleTask(
|
|
81
107
|
task: TaskPayload,
|
|
82
108
|
client: StageWhisperClient,
|
|
@@ -84,7 +110,7 @@ export function createRelayService(api: OpenClawPluginApi) {
|
|
|
84
110
|
api.logger.info(`Received task: ${task.title} (${task.id})`);
|
|
85
111
|
|
|
86
112
|
try {
|
|
87
|
-
await client
|
|
113
|
+
await updateStatus(client, task, "delivered");
|
|
88
114
|
} catch (err) {
|
|
89
115
|
api.logger.warn(`Failed to mark task as delivered: ${err}`);
|
|
90
116
|
}
|
|
@@ -95,23 +121,56 @@ export function createRelayService(api: OpenClawPluginApi) {
|
|
|
95
121
|
const sessionKey = buildAgentSessionKey({
|
|
96
122
|
agentId: "default",
|
|
97
123
|
channel: "stagewhisper",
|
|
98
|
-
peer: { kind: "direct", id: `sw-
|
|
124
|
+
peer: { kind: "direct", id: `sw-task-${task.id}` },
|
|
99
125
|
});
|
|
100
126
|
|
|
101
127
|
const result = await api.runtime.subagent.run({
|
|
102
128
|
sessionKey,
|
|
103
129
|
message: messageContent,
|
|
104
|
-
deliver:
|
|
130
|
+
deliver: false,
|
|
105
131
|
idempotencyKey: randomUUID(),
|
|
106
132
|
});
|
|
107
133
|
|
|
108
134
|
api.logger.info(
|
|
109
135
|
`Task ${task.id} dispatched to agent session (runId: ${result.runId})`,
|
|
110
136
|
);
|
|
111
|
-
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
await updateStatus(client, task, "running");
|
|
140
|
+
} catch (err) {
|
|
141
|
+
api.logger.warn(`Failed to mark task as running: ${err}`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const waitResult = await api.runtime.subagent.waitForRun({
|
|
145
|
+
runId: result.runId,
|
|
146
|
+
timeoutMs: 120_000,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
if (waitResult.status === "ok") {
|
|
150
|
+
const session = await api.runtime.subagent.getSessionMessages({
|
|
151
|
+
sessionKey,
|
|
152
|
+
limit: 20,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const reply = extractAssistantReply(session.messages);
|
|
156
|
+
if (reply) {
|
|
157
|
+
if (!isTestTask(task)) {
|
|
158
|
+
await client.postReply(task.id, reply);
|
|
159
|
+
}
|
|
160
|
+
api.logger.info(`Task ${task.id} completed with reply`);
|
|
161
|
+
} else {
|
|
162
|
+
api.logger.warn(`Task ${task.id} completed but no assistant reply found`);
|
|
163
|
+
await updateStatus(client, task, "completed").catch(() => {});
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
api.logger.error(
|
|
167
|
+
`Agent run failed for task ${task.id}: ${waitResult.error}`,
|
|
168
|
+
);
|
|
169
|
+
await updateStatus(client, task, "failed").catch(() => {});
|
|
170
|
+
}
|
|
112
171
|
} catch (err) {
|
|
113
|
-
api.logger.error(`Failed to
|
|
114
|
-
await client
|
|
172
|
+
api.logger.error(`Failed to process task ${task.id}: ${err}`);
|
|
173
|
+
await updateStatus(client, task, "failed").catch(() => {});
|
|
115
174
|
}
|
|
116
175
|
}
|
|
117
176
|
|
|
@@ -163,7 +222,9 @@ export function createRelayService(api: OpenClawPluginApi) {
|
|
|
163
222
|
|
|
164
223
|
try {
|
|
165
224
|
const task = JSON.parse(jsonStr) as TaskPayload;
|
|
166
|
-
|
|
225
|
+
handleTask(task, client).catch((err) => {
|
|
226
|
+
api.logger.error(`Unhandled error processing task: ${err}`);
|
|
227
|
+
});
|
|
167
228
|
} catch (parseErr) {
|
|
168
229
|
api.logger.warn(`Failed to parse stream event: ${parseErr}`);
|
|
169
230
|
}
|