@sider-ai/chrome-openclaw-sider 1.0.31 → 1.0.33

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.
@@ -7,7 +7,7 @@ import {
7
7
  buildToolResultEvent,
8
8
  buildToolResultPart
9
9
  } from "./channel-builders.js";
10
- import { sendSiderEventBestEffort } from "./channel-relay.js";
10
+ import { sendSiderEventBestEffort, sendSiderMessageBestEffort } from "./channel-relay.js";
11
11
  import { logDebug, logWarn } from "./channel-runtime.js";
12
12
  import {
13
13
  clearBindingRunId,
@@ -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,52 @@ 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
+ void sendSiderMessageBestEffort({
193
+ account: params.binding.account,
194
+ sessionId: params.binding.sessionId,
195
+ parts: [
196
+ {
197
+ ...buildTextPart(NO_QUOTA_REMAINING_TEXT),
198
+ payload: {
199
+ text: NO_QUOTA_REMAINING_TEXT,
200
+ is_error: true
201
+ }
202
+ }
203
+ ],
204
+ meta: {
205
+ provider: params.runState.provider,
206
+ model: params.runState.model
207
+ },
208
+ context: params.context
209
+ });
210
+ }
211
+ function isNoQuotaRemainingAssistantError(source) {
212
+ const assistant = toRecord(source);
213
+ if (!assistant) {
214
+ return false;
215
+ }
216
+ for (const key of ["errorBody", "errorMessage", "errorCode", "errorType", "content"]) {
217
+ const value = assistant[key];
218
+ if (typeof value === "string" && value.includes(NO_QUOTA_REMAINING_TEXT)) {
219
+ return true;
220
+ }
221
+ }
222
+ return false;
169
223
  }
170
224
  async function emitSiderToolHookEvent(params) {
171
225
  const binding = resolveSiderSessionBinding(params.sessionKey);
@@ -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 = {
@@ -68,6 +68,7 @@ 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";
@@ -97,6 +98,7 @@ import {
97
98
  finalizeQueuedRunMessages
98
99
  } from "./channel-streaming.js";
99
100
  import { runManagedSiderRelayMonitor } from "./channel-monitor.js";
101
+ const NO_QUOTA_REMAINING_TEXT = "NO_QUOTA_REMAINING";
100
102
  import { setSiderRuntime } from "./channel-runtime.js";
101
103
  import {
102
104
  recordSiderPersistedAgentMessage,
@@ -371,6 +373,15 @@ async function handleInboundRealtimeMessage(params) {
371
373
  if (payload.isError === true && !SIDER_PUSH_TOOL_ERROR_WARNINGS && typeof payload.text === "string" && SIDER_TOOL_ERROR_WARNING_TEXT_RE.test(payload.text)) {
372
374
  return;
373
375
  }
376
+ if (shouldSuppressFollowupErrorAfterNoQuotaRemaining(streamState.currentRunId, payload)) {
377
+ logDebug("skip sider deliver: follow-up error after NO_QUOTA_REMAINING", {
378
+ accountId: account.accountId,
379
+ sessionId,
380
+ runId: streamState.currentRunId,
381
+ kind: info.kind
382
+ });
383
+ return;
384
+ }
374
385
  logDebug("sider dispatch deliver payload", {
375
386
  accountId: account.accountId,
376
387
  sessionId,
@@ -517,7 +528,9 @@ async function handleInboundRealtimeMessage(params) {
517
528
  }
518
529
  return;
519
530
  }
520
- const pendingFinalPayloads = [...streamState.pendingFinalPayloads];
531
+ const pendingFinalPayloads = streamState.pendingFinalPayloads.filter(
532
+ (payload) => !shouldSuppressFollowupErrorAfterNoQuotaRemaining(streamState.currentRunId, payload)
533
+ );
521
534
  streamState.pendingFinalPayloads = [];
522
535
  if (pendingFinalPayloads.length > 0) {
523
536
  const pendingRunFinalText = resolvePendingFinalTextForRun(streamState.currentRunId).trim();
@@ -660,6 +673,28 @@ async function handleInboundRealtimeMessage(params) {
660
673
  releaseSiderTyping({ account, sessionId });
661
674
  }
662
675
  }
676
+ function shouldSuppressFollowupErrorAfterNoQuotaRemaining(runId, payload) {
677
+ const runState = resolveSiderRunState(runId);
678
+ if (runState?.noQuotaRemainingErrorSent !== true) {
679
+ return false;
680
+ }
681
+ if (runState.noQuotaRemainingFollowupErrorSuppressed === true) {
682
+ return false;
683
+ }
684
+ if (payload.isError !== true && payload.is_error !== true) {
685
+ return false;
686
+ }
687
+ const text = typeof payload.text === "string" ? payload.text.trim() : "";
688
+ if (text.includes(NO_QUOTA_REMAINING_TEXT)) {
689
+ return false;
690
+ }
691
+ runState.noQuotaRemainingFollowupErrorSuppressed = true;
692
+ logDebug("suppressing follow-up error after NO_QUOTA_REMAINING", {
693
+ runId,
694
+ textLength: text.length
695
+ });
696
+ return true;
697
+ }
663
698
  const siderPlugin = {
664
699
  id: SIDER_CHANNEL_ID,
665
700
  ...siderChannelPluginCommon,
@@ -1,4 +1,4 @@
1
- const SIDER_PLUGIN_VERSION = "1.0.31";
1
+ const SIDER_PLUGIN_VERSION = "1.0.33";
2
2
  const SIDER_USER_AGENT = `openclaw-sider/${SIDER_PLUGIN_VERSION}`;
3
3
  export {
4
4
  SIDER_PLUGIN_VERSION,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sider-ai/chrome-openclaw-sider",
3
3
  "private": false,
4
- "version": "1.0.31",
4
+ "version": "1.0.33",
5
5
  "description": "Official Chrome channel plugin for connecting OpenClaw in Sider Chrome extension",
6
6
  "type": "module",
7
7
  "files": [