@sider-ai/chrome-openclaw-sider 1.0.31 → 1.0.34
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/src/channel-hooks.js +77 -0
- package/dist/src/channel-send.d.ts +2 -1
- package/dist/src/channel-send.js +20 -2
- package/dist/src/channel-types.d.ts +2 -0
- package/dist/src/channel.js +42 -3
- package/dist/src/config.d.ts +1 -1
- package/dist/src/config.js +1 -1
- package/dist/src/user-agent.js +1 -1
- package/package.json +1 -1
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
parseUsageTotals,
|
|
33
33
|
toRecord
|
|
34
34
|
} from "./channel-util.js";
|
|
35
|
+
const NO_QUOTA_REMAINING_TEXT = "NO_QUOTA_REMAINING";
|
|
35
36
|
function recordSiderPersistedAgentMessage(params) {
|
|
36
37
|
const binding = resolveSiderSessionBinding(params.sessionKey);
|
|
37
38
|
const runId = binding?.currentRunId;
|
|
@@ -63,6 +64,13 @@ function recordSiderPersistedAgentMessage(params) {
|
|
|
63
64
|
runState.usage = fallbackUsage;
|
|
64
65
|
}
|
|
65
66
|
}
|
|
67
|
+
maybeSendNoQuotaRemainingError({
|
|
68
|
+
binding,
|
|
69
|
+
runId,
|
|
70
|
+
runState,
|
|
71
|
+
source: message,
|
|
72
|
+
context: "before_message_write.no_quota_remaining"
|
|
73
|
+
});
|
|
66
74
|
const parsed = parseAssistantOutput(message);
|
|
67
75
|
if (!parsed) {
|
|
68
76
|
return;
|
|
@@ -166,6 +174,75 @@ function recordSiderLlmOutputUsage(params) {
|
|
|
166
174
|
if (parsed && hasUsageTotals(parsed)) {
|
|
167
175
|
runState.usage = parsed;
|
|
168
176
|
}
|
|
177
|
+
if (binding) {
|
|
178
|
+
maybeSendNoQuotaRemainingError({
|
|
179
|
+
binding,
|
|
180
|
+
runId,
|
|
181
|
+
runState,
|
|
182
|
+
source: params.lastAssistant,
|
|
183
|
+
context: "llm_output.no_quota_remaining"
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function maybeSendNoQuotaRemainingError(params) {
|
|
188
|
+
if (params.runState.noQuotaRemainingErrorSent || !isNoQuotaRemainingAssistantError(params.source)) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
params.runState.noQuotaRemainingErrorSent = true;
|
|
192
|
+
const quotaPart = {
|
|
193
|
+
...buildTextPart(NO_QUOTA_REMAINING_TEXT),
|
|
194
|
+
payload: {
|
|
195
|
+
text: NO_QUOTA_REMAINING_TEXT,
|
|
196
|
+
is_error: true
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
enqueueCompletedParts({
|
|
200
|
+
runId: params.runId,
|
|
201
|
+
parts: [
|
|
202
|
+
quotaPart
|
|
203
|
+
],
|
|
204
|
+
sessionId: params.binding.sessionId,
|
|
205
|
+
accountId: params.binding.account.accountId,
|
|
206
|
+
provider: params.runState.provider,
|
|
207
|
+
model: params.runState.model
|
|
208
|
+
});
|
|
209
|
+
void (async () => {
|
|
210
|
+
try {
|
|
211
|
+
await flushQueuedPartsExceptTailForRun({
|
|
212
|
+
runId: params.runId,
|
|
213
|
+
account: params.binding.account,
|
|
214
|
+
sessionId: params.binding.sessionId,
|
|
215
|
+
context: `${params.context}.except_tail`
|
|
216
|
+
});
|
|
217
|
+
await flushFinalQueuedPartForRun({
|
|
218
|
+
runId: params.runId,
|
|
219
|
+
account: params.binding.account,
|
|
220
|
+
sessionId: params.binding.sessionId,
|
|
221
|
+
context: `${params.context}.final_tail`
|
|
222
|
+
});
|
|
223
|
+
} catch (err) {
|
|
224
|
+
logWarn("sider failed to persist NO_QUOTA_REMAINING final message", {
|
|
225
|
+
accountId: params.binding.account.accountId,
|
|
226
|
+
sessionId: params.binding.sessionId,
|
|
227
|
+
runId: params.runId,
|
|
228
|
+
context: params.context,
|
|
229
|
+
error: String(err)
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
})();
|
|
233
|
+
}
|
|
234
|
+
function isNoQuotaRemainingAssistantError(source) {
|
|
235
|
+
const assistant = toRecord(source);
|
|
236
|
+
if (!assistant) {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
for (const key of ["errorBody", "errorMessage", "errorCode", "errorType", "content"]) {
|
|
240
|
+
const value = assistant[key];
|
|
241
|
+
if (typeof value === "string" && value.includes(NO_QUOTA_REMAINING_TEXT)) {
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return false;
|
|
169
246
|
}
|
|
170
247
|
async function emitSiderToolHookEvent(params) {
|
|
171
248
|
const binding = resolveSiderSessionBinding(params.sessionKey);
|
|
@@ -28,6 +28,7 @@ type DispatchedSiderParts = {
|
|
|
28
28
|
messageId: string;
|
|
29
29
|
conversationId: string;
|
|
30
30
|
};
|
|
31
|
+
declare function buildSiderDispatchReceipt(dispatchResult: DispatchedSiderParts): Record<string, unknown>;
|
|
31
32
|
declare function readSiderSendText(params: Record<string, unknown>): string | undefined;
|
|
32
33
|
declare function collectSiderSendAttachments(params: Record<string, unknown>): NormalizedSiderAttachment[];
|
|
33
34
|
declare function prepareSiderSendParts(params: {
|
|
@@ -70,4 +71,4 @@ declare function sendToSider(params: {
|
|
|
70
71
|
conversationId: string;
|
|
71
72
|
}>;
|
|
72
73
|
|
|
73
|
-
export { type DispatchedSiderParts, type PreparedSiderSend, collectSiderSendAttachments, dispatchSiderParts, handleSiderSendAction, prepareSiderSendParts, readSiderSendText, sendToSider };
|
|
74
|
+
export { type DispatchedSiderParts, type PreparedSiderSend, buildSiderDispatchReceipt, collectSiderSendAttachments, dispatchSiderParts, handleSiderSendAction, prepareSiderSendParts, readSiderSendText, sendToSider };
|
package/dist/src/channel-send.js
CHANGED
|
@@ -20,6 +20,21 @@ import {
|
|
|
20
20
|
startDeferredSiderUploads
|
|
21
21
|
} from "./media-upload.js";
|
|
22
22
|
import { buildTextPart } from "./channel-builders.js";
|
|
23
|
+
function buildSiderDispatchReceipt(dispatchResult) {
|
|
24
|
+
if (dispatchResult.kind === "sent") {
|
|
25
|
+
return {
|
|
26
|
+
ok: true,
|
|
27
|
+
status: "sent",
|
|
28
|
+
messageId: dispatchResult.messageId,
|
|
29
|
+
conversationId: dispatchResult.conversationId
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
ok: true,
|
|
34
|
+
runId: dispatchResult.runId,
|
|
35
|
+
sessionKey: dispatchResult.sessionKey
|
|
36
|
+
};
|
|
37
|
+
}
|
|
23
38
|
const SIDER_ATTACHMENT_SOURCE_KEYS = [
|
|
24
39
|
"path",
|
|
25
40
|
"filePath",
|
|
@@ -246,7 +261,7 @@ async function handleSiderSendAction(params) {
|
|
|
246
261
|
})
|
|
247
262
|
)
|
|
248
263
|
);
|
|
249
|
-
await dispatchSiderParts({
|
|
264
|
+
const dispatchResult = await dispatchSiderParts({
|
|
250
265
|
account: prepared.account,
|
|
251
266
|
sessionId: prepared.sessionId,
|
|
252
267
|
parts: prepared.parts,
|
|
@@ -254,11 +269,13 @@ async function handleSiderSendAction(params) {
|
|
|
254
269
|
allowMergeActiveRun: true,
|
|
255
270
|
context: "action.send"
|
|
256
271
|
});
|
|
272
|
+
const receipt = buildSiderDispatchReceipt(dispatchResult);
|
|
257
273
|
if (fileResults.length === 0) {
|
|
258
|
-
return
|
|
274
|
+
return receipt;
|
|
259
275
|
}
|
|
260
276
|
return {
|
|
261
277
|
...fileResults[0],
|
|
278
|
+
...receipt,
|
|
262
279
|
files: fileResults,
|
|
263
280
|
fileCount: fileResults.length
|
|
264
281
|
};
|
|
@@ -282,6 +299,7 @@ async function sendToSider(params) {
|
|
|
282
299
|
};
|
|
283
300
|
}
|
|
284
301
|
export {
|
|
302
|
+
buildSiderDispatchReceipt,
|
|
285
303
|
collectSiderSendAttachments,
|
|
286
304
|
dispatchSiderParts,
|
|
287
305
|
handleSiderSendAction,
|
|
@@ -93,6 +93,8 @@ type SiderRunState = {
|
|
|
93
93
|
pendingFinalText?: string;
|
|
94
94
|
pendingFinalThinking?: string;
|
|
95
95
|
pendingFinalStopReason?: string;
|
|
96
|
+
noQuotaRemainingErrorSent?: boolean;
|
|
97
|
+
noQuotaRemainingFollowupErrorSuppressed?: boolean;
|
|
96
98
|
updatedAt: number;
|
|
97
99
|
};
|
|
98
100
|
type SiderRealtimeLaneState = {
|
package/dist/src/channel.js
CHANGED
|
@@ -68,10 +68,12 @@ import {
|
|
|
68
68
|
buildPendingMessageContextForRun,
|
|
69
69
|
consumePendingMessageContextForRun,
|
|
70
70
|
resolvePendingFinalTextForRun,
|
|
71
|
+
resolveSiderRunState,
|
|
71
72
|
updateSiderRunStateContext
|
|
72
73
|
} from "./channel-state.js";
|
|
73
74
|
import { buildTextPart } from "./channel-builders.js";
|
|
74
75
|
import {
|
|
76
|
+
buildSiderDispatchReceipt,
|
|
75
77
|
dispatchSiderParts,
|
|
76
78
|
handleSiderSendAction,
|
|
77
79
|
sendToSider
|
|
@@ -97,6 +99,7 @@ import {
|
|
|
97
99
|
finalizeQueuedRunMessages
|
|
98
100
|
} from "./channel-streaming.js";
|
|
99
101
|
import { runManagedSiderRelayMonitor } from "./channel-monitor.js";
|
|
102
|
+
const NO_QUOTA_REMAINING_TEXT = "NO_QUOTA_REMAINING";
|
|
100
103
|
import { setSiderRuntime } from "./channel-runtime.js";
|
|
101
104
|
import {
|
|
102
105
|
recordSiderPersistedAgentMessage,
|
|
@@ -371,6 +374,15 @@ async function handleInboundRealtimeMessage(params) {
|
|
|
371
374
|
if (payload.isError === true && !SIDER_PUSH_TOOL_ERROR_WARNINGS && typeof payload.text === "string" && SIDER_TOOL_ERROR_WARNING_TEXT_RE.test(payload.text)) {
|
|
372
375
|
return;
|
|
373
376
|
}
|
|
377
|
+
if (shouldSuppressFollowupErrorAfterNoQuotaRemaining(streamState.currentRunId, payload)) {
|
|
378
|
+
logDebug("skip sider deliver: follow-up error after NO_QUOTA_REMAINING", {
|
|
379
|
+
accountId: account.accountId,
|
|
380
|
+
sessionId,
|
|
381
|
+
runId: streamState.currentRunId,
|
|
382
|
+
kind: info.kind
|
|
383
|
+
});
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
374
386
|
logDebug("sider dispatch deliver payload", {
|
|
375
387
|
accountId: account.accountId,
|
|
376
388
|
sessionId,
|
|
@@ -517,7 +529,9 @@ async function handleInboundRealtimeMessage(params) {
|
|
|
517
529
|
}
|
|
518
530
|
return;
|
|
519
531
|
}
|
|
520
|
-
const pendingFinalPayloads =
|
|
532
|
+
const pendingFinalPayloads = streamState.pendingFinalPayloads.filter(
|
|
533
|
+
(payload) => !shouldSuppressFollowupErrorAfterNoQuotaRemaining(streamState.currentRunId, payload)
|
|
534
|
+
);
|
|
521
535
|
streamState.pendingFinalPayloads = [];
|
|
522
536
|
if (pendingFinalPayloads.length > 0) {
|
|
523
537
|
const pendingRunFinalText = resolvePendingFinalTextForRun(streamState.currentRunId).trim();
|
|
@@ -660,6 +674,28 @@ async function handleInboundRealtimeMessage(params) {
|
|
|
660
674
|
releaseSiderTyping({ account, sessionId });
|
|
661
675
|
}
|
|
662
676
|
}
|
|
677
|
+
function shouldSuppressFollowupErrorAfterNoQuotaRemaining(runId, payload) {
|
|
678
|
+
const runState = resolveSiderRunState(runId);
|
|
679
|
+
if (runState?.noQuotaRemainingErrorSent !== true) {
|
|
680
|
+
return false;
|
|
681
|
+
}
|
|
682
|
+
if (runState.noQuotaRemainingFollowupErrorSuppressed === true) {
|
|
683
|
+
return false;
|
|
684
|
+
}
|
|
685
|
+
if (payload.isError !== true && payload.is_error !== true) {
|
|
686
|
+
return false;
|
|
687
|
+
}
|
|
688
|
+
const text = typeof payload.text === "string" ? payload.text.trim() : "";
|
|
689
|
+
if (text.includes(NO_QUOTA_REMAINING_TEXT)) {
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
runState.noQuotaRemainingFollowupErrorSuppressed = true;
|
|
693
|
+
logDebug("suppressing follow-up error after NO_QUOTA_REMAINING", {
|
|
694
|
+
runId,
|
|
695
|
+
textLength: text.length
|
|
696
|
+
});
|
|
697
|
+
return true;
|
|
698
|
+
}
|
|
663
699
|
const siderPlugin = {
|
|
664
700
|
id: SIDER_CHANNEL_ID,
|
|
665
701
|
...siderChannelPluginCommon,
|
|
@@ -737,7 +773,7 @@ const siderPlugin = {
|
|
|
737
773
|
source: savedAttachment.path,
|
|
738
774
|
path: savedAttachment.path
|
|
739
775
|
});
|
|
740
|
-
await dispatchSiderParts({
|
|
776
|
+
const dispatchResult = await dispatchSiderParts({
|
|
741
777
|
account,
|
|
742
778
|
sessionId,
|
|
743
779
|
parts: sendParts,
|
|
@@ -745,7 +781,10 @@ const siderPlugin = {
|
|
|
745
781
|
allowMergeActiveRun: true,
|
|
746
782
|
context: "action.sendAttachment"
|
|
747
783
|
});
|
|
748
|
-
return jsonResult(
|
|
784
|
+
return jsonResult({
|
|
785
|
+
...attachmentResult,
|
|
786
|
+
...buildSiderDispatchReceipt(dispatchResult)
|
|
787
|
+
});
|
|
749
788
|
}
|
|
750
789
|
},
|
|
751
790
|
outbound: {
|
package/dist/src/config.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ declare const SIDER_CHANNEL_DOCS_LABEL = "sider";
|
|
|
10
10
|
declare const SIDER_CHANNEL_BLURB = "Command your OpenClaw from Chrome Sidebar directly.";
|
|
11
11
|
declare const SIDER_CHANNEL_ALIASES: readonly ["sider"];
|
|
12
12
|
declare const SIDER_DEFAULT_BASE_URL = "https://sider.ai/api/claw/self";
|
|
13
|
-
declare const SIDER_PUSH_TOOL_ERROR_WARNINGS
|
|
13
|
+
declare const SIDER_PUSH_TOOL_ERROR_WARNINGS: boolean;
|
|
14
14
|
declare const SIDER_TOOL_ERROR_WARNING_TEXT_RE: RegExp;
|
|
15
15
|
declare function readSiderBaseUrlEnv(): string | undefined;
|
|
16
16
|
declare function readDefaultSiderSetupTokenEnv(): string | undefined;
|
package/dist/src/config.js
CHANGED
|
@@ -10,7 +10,7 @@ const SIDER_CHANNEL_DOCS_LABEL = "sider";
|
|
|
10
10
|
const SIDER_CHANNEL_BLURB = "Command your OpenClaw from Chrome Sidebar directly.";
|
|
11
11
|
const SIDER_CHANNEL_ALIASES = ["sider"];
|
|
12
12
|
const SIDER_DEFAULT_BASE_URL = "https://sider.ai/api/claw/self";
|
|
13
|
-
const SIDER_PUSH_TOOL_ERROR_WARNINGS = true;
|
|
13
|
+
const SIDER_PUSH_TOOL_ERROR_WARNINGS = false ? true : false;
|
|
14
14
|
const SIDER_TOOL_ERROR_WARNING_TEXT_RE = /^⚠️ [^\n]+ failed(?:: [^\n]+)?$/u;
|
|
15
15
|
function readSiderBaseUrlEnv() {
|
|
16
16
|
return process.env.SIDER_GATEWAY_URL;
|
package/dist/src/user-agent.js
CHANGED
package/package.json
CHANGED