@clawling/clawchat-plugin-openclaw 2026.8.14-1 → 2026.8.14-2
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/api-client.js +6 -1
- package/dist/src/config.js +24 -2
- package/package.json +1 -1
- package/src/api-client.ts +6 -1
- package/src/config.ts +29 -2
package/dist/src/api-client.js
CHANGED
|
@@ -153,8 +153,13 @@ export function createOpenclawClawlingApiClient(opts) {
|
|
|
153
153
|
// `X-Device-Id` is sent on every request so the server can correlate
|
|
154
154
|
// activity back to this plugin instance. Callers may override via
|
|
155
155
|
// `extra` (e.g. tests) but the default is the channel id.
|
|
156
|
+
//
|
|
157
|
+
// A blank token gets NO Authorization header at all: `Bearer ` with an
|
|
158
|
+
// empty credential is a zero-segment JWT that the backend logs as
|
|
159
|
+
// malformed-token 401 noise (the unauthenticated plugin-report call sent
|
|
160
|
+
// one on every gateway entry).
|
|
156
161
|
return {
|
|
157
|
-
authorization: `Bearer ${opts.token}
|
|
162
|
+
...(opts.token.trim() ? { authorization: `Bearer ${opts.token}` } : {}),
|
|
158
163
|
"x-device-id": CHANNEL_ID,
|
|
159
164
|
...extra,
|
|
160
165
|
};
|
package/dist/src/config.js
CHANGED
|
@@ -221,6 +221,28 @@ function decodeJwtStringClaim(token, claim) {
|
|
|
221
221
|
* wins; the mismatch is logged. Also derives userId from `sub` when nothing is
|
|
222
222
|
* configured, mirroring the `oid` fallback above.
|
|
223
223
|
*/
|
|
224
|
+
/**
|
|
225
|
+
* Reject an ownerUserId that is an unrendered provisioning-template
|
|
226
|
+
* placeholder — treat it as absent (fall through to the next source) instead
|
|
227
|
+
* of using it verbatim.
|
|
228
|
+
*
|
|
229
|
+
* 2026-08 production incident: a provisioner shipped the literal `usr_owner`
|
|
230
|
+
* (this repo's own test-fixture value) un-rendered; every affected agent
|
|
231
|
+
* passed the connect gate and hammered prod with `GET /v1/users/usr_owner`
|
|
232
|
+
* plus malformed-JWT retries for days. Dev/mock ids stay loose on purpose —
|
|
233
|
+
* only the known fixture literal and unmistakable template syntax
|
|
234
|
+
* ({{…}}, ${…}, <…>, %…%) are rejected.
|
|
235
|
+
*/
|
|
236
|
+
function rejectPlaceholderOwnerUserId(value, source) {
|
|
237
|
+
if (!value)
|
|
238
|
+
return "";
|
|
239
|
+
const looksUnrendered = value === "usr_owner" || /[{}<>%]|\$\{/.test(value);
|
|
240
|
+
if (looksUnrendered) {
|
|
241
|
+
console.warn(`clawchat ownerUserId from ${source} looks like an unrendered template placeholder ("${value}"); ignoring it. Fix the provisioning template — without a real owner id (or an oid claim in the token) the agent stays in activation-wait instead of hammering the backend.`);
|
|
242
|
+
return "";
|
|
243
|
+
}
|
|
244
|
+
return value;
|
|
245
|
+
}
|
|
224
246
|
function resolveUserId(token, configured) {
|
|
225
247
|
const tokenSub = decodeJwtStringClaim(token, "sub");
|
|
226
248
|
if (!tokenSub)
|
|
@@ -336,8 +358,8 @@ export function resolveOpenclawClawlingAccount(cfg, env = process.env) {
|
|
|
336
358
|
const token = readOptionalString(channel.token) || readEnvString(env, CLAWCHAT_TOKEN_ENV);
|
|
337
359
|
const agentId = readOptionalString(channel.agentId) || readEnvString(env, CLAWCHAT_AGENT_ID_ENV);
|
|
338
360
|
const userId = resolveUserId(token, readOptionalString(channel.userId) || readEnvString(env, CLAWCHAT_USER_ID_ENV));
|
|
339
|
-
const ownerUserId = readOptionalString(channel.ownerUserId) ||
|
|
340
|
-
readEnvString(env, CLAWCHAT_OWNER_USER_ID_ENV) ||
|
|
361
|
+
const ownerUserId = rejectPlaceholderOwnerUserId(readOptionalString(channel.ownerUserId), "channel ownerUserId") ||
|
|
362
|
+
rejectPlaceholderOwnerUserId(readEnvString(env, CLAWCHAT_OWNER_USER_ID_ENV), CLAWCHAT_OWNER_USER_ID_ENV) ||
|
|
341
363
|
// Fall back to the access token's `oid` (owner) claim. A provisioner may
|
|
342
364
|
// inject token + userId but omit ownerUserId; without it the connect gate
|
|
343
365
|
// (hasOpenclawClawlingConnectCredentials) never passes and the plugin sits
|
package/package.json
CHANGED
package/src/api-client.ts
CHANGED
|
@@ -337,8 +337,13 @@ export function createOpenclawClawlingApiClient(opts: ApiClientOptions): Opencla
|
|
|
337
337
|
// `X-Device-Id` is sent on every request so the server can correlate
|
|
338
338
|
// activity back to this plugin instance. Callers may override via
|
|
339
339
|
// `extra` (e.g. tests) but the default is the channel id.
|
|
340
|
+
//
|
|
341
|
+
// A blank token gets NO Authorization header at all: `Bearer ` with an
|
|
342
|
+
// empty credential is a zero-segment JWT that the backend logs as
|
|
343
|
+
// malformed-token 401 noise (the unauthenticated plugin-report call sent
|
|
344
|
+
// one on every gateway entry).
|
|
340
345
|
return {
|
|
341
|
-
authorization: `Bearer ${opts.token}
|
|
346
|
+
...(opts.token.trim() ? { authorization: `Bearer ${opts.token}` } : {}),
|
|
342
347
|
"x-device-id": CHANNEL_ID,
|
|
343
348
|
...extra,
|
|
344
349
|
};
|
package/src/config.ts
CHANGED
|
@@ -349,6 +349,30 @@ function decodeJwtStringClaim(token: string, claim: string): string {
|
|
|
349
349
|
* wins; the mismatch is logged. Also derives userId from `sub` when nothing is
|
|
350
350
|
* configured, mirroring the `oid` fallback above.
|
|
351
351
|
*/
|
|
352
|
+
/**
|
|
353
|
+
* Reject an ownerUserId that is an unrendered provisioning-template
|
|
354
|
+
* placeholder — treat it as absent (fall through to the next source) instead
|
|
355
|
+
* of using it verbatim.
|
|
356
|
+
*
|
|
357
|
+
* 2026-08 production incident: a provisioner shipped the literal `usr_owner`
|
|
358
|
+
* (this repo's own test-fixture value) un-rendered; every affected agent
|
|
359
|
+
* passed the connect gate and hammered prod with `GET /v1/users/usr_owner`
|
|
360
|
+
* plus malformed-JWT retries for days. Dev/mock ids stay loose on purpose —
|
|
361
|
+
* only the known fixture literal and unmistakable template syntax
|
|
362
|
+
* ({{…}}, ${…}, <…>, %…%) are rejected.
|
|
363
|
+
*/
|
|
364
|
+
function rejectPlaceholderOwnerUserId(value: string, source: string): string {
|
|
365
|
+
if (!value) return "";
|
|
366
|
+
const looksUnrendered = value === "usr_owner" || /[{}<>%]|\$\{/.test(value);
|
|
367
|
+
if (looksUnrendered) {
|
|
368
|
+
console.warn(
|
|
369
|
+
`clawchat ownerUserId from ${source} looks like an unrendered template placeholder ("${value}"); ignoring it. Fix the provisioning template — without a real owner id (or an oid claim in the token) the agent stays in activation-wait instead of hammering the backend.`,
|
|
370
|
+
);
|
|
371
|
+
return "";
|
|
372
|
+
}
|
|
373
|
+
return value;
|
|
374
|
+
}
|
|
375
|
+
|
|
352
376
|
function resolveUserId(token: string, configured: string): string {
|
|
353
377
|
const tokenSub = decodeJwtStringClaim(token, "sub");
|
|
354
378
|
if (!tokenSub) return configured;
|
|
@@ -498,8 +522,11 @@ export function resolveOpenclawClawlingAccount(
|
|
|
498
522
|
readOptionalString(channel.userId) || readEnvString(env, CLAWCHAT_USER_ID_ENV),
|
|
499
523
|
);
|
|
500
524
|
const ownerUserId =
|
|
501
|
-
readOptionalString(channel.ownerUserId) ||
|
|
502
|
-
|
|
525
|
+
rejectPlaceholderOwnerUserId(readOptionalString(channel.ownerUserId), "channel ownerUserId") ||
|
|
526
|
+
rejectPlaceholderOwnerUserId(
|
|
527
|
+
readEnvString(env, CLAWCHAT_OWNER_USER_ID_ENV),
|
|
528
|
+
CLAWCHAT_OWNER_USER_ID_ENV,
|
|
529
|
+
) ||
|
|
503
530
|
// Fall back to the access token's `oid` (owner) claim. A provisioner may
|
|
504
531
|
// inject token + userId but omit ownerUserId; without it the connect gate
|
|
505
532
|
// (hasOpenclawClawlingConnectCredentials) never passes and the plugin sits
|