@clawling/clawchat-plugin-openclaw 2026.9.11-1 → 2026.9.13-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/account-config-writes.js +67 -0
- package/dist/src/account-removal.js +44 -0
- package/dist/src/channel.js +30 -1
- package/dist/src/channel.setup.js +79 -42
- package/dist/src/commands.js +50 -27
- package/dist/src/config.js +83 -13
- package/dist/src/liveware-cli.js +49 -4
- package/dist/src/liveware-sample.js +16 -2
- package/dist/src/login.runtime.js +25 -29
- package/dist/src/outbound.js +4 -4
- package/dist/src/runtime.js +35 -32
- package/dist/src/tools.js +799 -685
- package/openclaw.plugin.json +150 -0
- package/package.json +1 -1
- package/src/account-config-writes.ts +74 -0
- package/src/account-removal.ts +52 -0
- package/src/channel.setup.ts +86 -43
- package/src/channel.ts +28 -1
- package/src/commands.ts +60 -26
- package/src/config.ts +113 -14
- package/src/liveware-cli.ts +52 -4
- package/src/liveware-sample.ts +24 -5
- package/src/login.runtime.ts +30 -26
- package/src/outbound.ts +4 -4
- package/src/runtime.ts +52 -36
- package/src/tools.ts +896 -768
package/src/runtime.ts
CHANGED
|
@@ -19,7 +19,12 @@ import { createOpenclawClawlingApiClient } from "./api-client.ts";
|
|
|
19
19
|
import { buildActivationBootstrapText } from "./activation-greeting.ts";
|
|
20
20
|
import { reportPluginVersionSafe, resolvePluginVersion } from "./plugin-report.ts";
|
|
21
21
|
import path from "node:path";
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
ensureLivewareCli,
|
|
24
|
+
livewareCliHomeDir,
|
|
25
|
+
livewareSampleRootDir,
|
|
26
|
+
resolveLivewarePath,
|
|
27
|
+
} from "./liveware-cli.ts";
|
|
23
28
|
import {
|
|
24
29
|
LivewareSampleSupervisor,
|
|
25
30
|
type LivewareSampleStoreLike,
|
|
@@ -38,10 +43,14 @@ import {
|
|
|
38
43
|
effectiveGroupCommandMode,
|
|
39
44
|
effectiveGroupMode,
|
|
40
45
|
hasOpenclawClawlingConnectCredentials,
|
|
46
|
+
normalizeOpenclawClawlingAccountId,
|
|
47
|
+
readOpenclawClawlingAccountSection,
|
|
41
48
|
resolveOpenclawClawlingAccount,
|
|
42
49
|
type ResolvedOpenclawClawlingAccount,
|
|
43
50
|
CLAWCHAT_REFRESH_TOKEN_ENV,
|
|
44
51
|
} from "./config.ts";
|
|
52
|
+
import { patchOpenclawClawlingAccountSection } from "./account-config-writes.ts";
|
|
53
|
+
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/setup";
|
|
45
54
|
import { isValidChatId, type ClawlingChatClient } from "./ws-client.ts";
|
|
46
55
|
import { dispatchOpenclawClawlingInbound, type IngestTurnParams } from "./inbound.ts";
|
|
47
56
|
import {
|
|
@@ -234,21 +243,24 @@ export function classifyHelloFailReason(
|
|
|
234
243
|
return "generic";
|
|
235
244
|
}
|
|
236
245
|
|
|
237
|
-
/** Read `channels.<CHANNEL_ID>.refreshToken` from a live config, or null. */
|
|
238
246
|
/**
|
|
239
|
-
* The refresh token paired with the
|
|
240
|
-
* `refreshToken` wins. `CLAWCHAT_REFRESH_TOKEN`
|
|
241
|
-
*
|
|
242
|
-
* of its own
|
|
243
|
-
*
|
|
244
|
-
* never paired with a stray refresh token left in the environment.
|
|
247
|
+
* The refresh token paired with the account's access token. The account
|
|
248
|
+
* section's `refreshToken` wins. `CLAWCHAT_REFRESH_TOKEN` is process-wide, so
|
|
249
|
+
* it is honoured ONLY for the default account and ONLY when that section
|
|
250
|
+
* carries no `token` of its own (i.e. the access token itself came from
|
|
251
|
+
* `CLAWCHAT_TOKEN`) — an env-provisioned pair can rotate, while a login-written
|
|
252
|
+
* token is never paired with a stray refresh token left in the environment.
|
|
245
253
|
*/
|
|
246
|
-
function readConfigRefreshToken(
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
254
|
+
function readConfigRefreshToken(
|
|
255
|
+
cfg: OpenClawConfig,
|
|
256
|
+
accountId: string,
|
|
257
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
258
|
+
): string | null {
|
|
259
|
+
const section = readOpenclawClawlingAccountSection(cfg, accountId);
|
|
260
|
+
const refreshToken = section.refreshToken;
|
|
250
261
|
if (typeof refreshToken === "string" && refreshToken.trim()) return refreshToken.trim();
|
|
251
|
-
|
|
262
|
+
if (normalizeOpenclawClawlingAccountId(accountId) !== DEFAULT_ACCOUNT_ID) return null;
|
|
263
|
+
const configToken = section.token;
|
|
252
264
|
if (typeof configToken === "string" && configToken.trim()) return null;
|
|
253
265
|
const envRefreshToken = env[CLAWCHAT_REFRESH_TOKEN_ENV];
|
|
254
266
|
return typeof envRefreshToken === "string" && envRefreshToken.trim() ? envRefreshToken.trim() : null;
|
|
@@ -697,7 +709,7 @@ export interface AutoActivateFromEnvParams {
|
|
|
697
709
|
/** Test seam — login implementation. */
|
|
698
710
|
runLogin?: (params: LoginParams) => Promise<void>;
|
|
699
711
|
/** Test seam — account resolver applied to the (mutated) cfg after login. */
|
|
700
|
-
resolveAccount?: (cfg: OpenClawConfig) => ResolvedOpenclawClawlingAccount;
|
|
712
|
+
resolveAccount?: (cfg: OpenClawConfig, accountId?: string | null) => ResolvedOpenclawClawlingAccount;
|
|
701
713
|
}
|
|
702
714
|
|
|
703
715
|
/**
|
|
@@ -714,6 +726,14 @@ export async function maybeAutoActivateFromEnv(
|
|
|
714
726
|
): Promise<ResolvedOpenclawClawlingAccount> {
|
|
715
727
|
const code = (params.connectCode ?? "").trim();
|
|
716
728
|
if (!code) return params.account;
|
|
729
|
+
// The env var is process-wide: it can only ever describe ONE identity, and
|
|
730
|
+
// that is the default account. A named account never redeems it.
|
|
731
|
+
if (normalizeOpenclawClawlingAccountId(params.account.accountId) !== DEFAULT_ACCOUNT_ID) {
|
|
732
|
+
params.log?.info?.(
|
|
733
|
+
`[${params.account.accountId}] clawchat-plugin-openclaw ${CONNECT_CODE_ENV} present but ignored: env activation is for the default account only`,
|
|
734
|
+
);
|
|
735
|
+
return params.account;
|
|
736
|
+
}
|
|
717
737
|
if (accountHasConnectCredentials(params.account)) return params.account;
|
|
718
738
|
const accountId = params.account.accountId;
|
|
719
739
|
const stored = params.store?.getActivationCredentials?.({ platform: "openclaw", accountId });
|
|
@@ -750,7 +770,7 @@ export async function maybeAutoActivateFromEnv(
|
|
|
750
770
|
);
|
|
751
771
|
return params.account;
|
|
752
772
|
}
|
|
753
|
-
const next = resolveAccount(params.cfg);
|
|
773
|
+
const next = resolveAccount(params.cfg, accountId);
|
|
754
774
|
params.log?.info?.(
|
|
755
775
|
`[${accountId}] clawchat-plugin-openclaw ${CONNECT_CODE_ENV} activation succeeded hasToken=${Boolean(next.token)}`,
|
|
756
776
|
);
|
|
@@ -1098,7 +1118,7 @@ export async function startOpenclawClawlingGateway(params: StartGatewayParams):
|
|
|
1098
1118
|
userId: account.userId,
|
|
1099
1119
|
ownerUserId: account.ownerUserId,
|
|
1100
1120
|
accessToken: account.token,
|
|
1101
|
-
refreshToken: readConfigRefreshToken(cfg),
|
|
1121
|
+
refreshToken: readConfigRefreshToken(cfg, accountId),
|
|
1102
1122
|
loginMethod: "config-seed",
|
|
1103
1123
|
deviceId: CHANNEL_ID,
|
|
1104
1124
|
});
|
|
@@ -1186,13 +1206,16 @@ export async function startOpenclawClawlingGateway(params: StartGatewayParams):
|
|
|
1186
1206
|
// `RuntimeConnectionStore` only `Pick`s a subset of its methods, so widen
|
|
1187
1207
|
// through the structural `LivewareSampleStoreLike` contract (Task 8/4).
|
|
1188
1208
|
store: store as unknown as LivewareSampleStoreLike,
|
|
1189
|
-
|
|
1209
|
+
// Per account: two supervisors in one process otherwise install, swap and
|
|
1210
|
+
// delete inside the SAME `app/` tree. `default` keeps the legacy path.
|
|
1211
|
+
sampleRoot: livewareSampleRootDir(stateDirForSample ?? "", accountId),
|
|
1190
1212
|
resolveToken: () => account.token ?? "",
|
|
1191
1213
|
resolveAgentUserId: () => account.userId ?? null,
|
|
1192
1214
|
resolveLivewarePath: () => resolveLivewarePath(stateDirForSample),
|
|
1193
|
-
// Per-instance HOME for the liveware CLI: its credentials
|
|
1194
|
-
// in the host-global `$HOME/.clawling`, which a second
|
|
1195
|
-
|
|
1215
|
+
// Per-instance AND per-account HOME for the liveware CLI: its credentials
|
|
1216
|
+
// otherwise live in the host-global `$HOME/.clawling`, which a second
|
|
1217
|
+
// profile — or a second account in this very process — clobbers.
|
|
1218
|
+
cliHome: livewareCliHomeDir(stateDirForSample, accountId),
|
|
1196
1219
|
cliReady: livewareCliReady,
|
|
1197
1220
|
listApps: async () => {
|
|
1198
1221
|
const client = getConversationApiClient();
|
|
@@ -1246,7 +1269,7 @@ export async function startOpenclawClawlingGateway(params: StartGatewayParams):
|
|
|
1246
1269
|
: undefined;
|
|
1247
1270
|
};
|
|
1248
1271
|
|
|
1249
|
-
// §0/§C.1 — write the
|
|
1272
|
+
// §0/§C.1 — write the account slot's `token`/`refreshToken` keys. `tokens=null`
|
|
1250
1273
|
// blanks them (auto-logout); otherwise persists the rotated pair.
|
|
1251
1274
|
const persistConfigTokens = async (
|
|
1252
1275
|
tokens: { accessToken: string; refreshToken: string } | null,
|
|
@@ -1261,20 +1284,13 @@ export async function startOpenclawClawlingGateway(params: StartGatewayParams):
|
|
|
1261
1284
|
await mutateConfigFile({
|
|
1262
1285
|
afterWrite: { mode: "none", reason: "clawchat-plugin-openclaw token refresh" },
|
|
1263
1286
|
mutate(draft) {
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
token: tokens ? tokens.accessToken : "",
|
|
1272
|
-
refreshToken: tokens ? tokens.refreshToken : "",
|
|
1273
|
-
};
|
|
1274
|
-
Object.assign(draft, {
|
|
1275
|
-
...draft,
|
|
1276
|
-
channels: { ...channels, [CHANNEL_ID]: nextSection },
|
|
1277
|
-
});
|
|
1287
|
+
Object.assign(
|
|
1288
|
+
draft,
|
|
1289
|
+
patchOpenclawClawlingAccountSection(draft, accountId, {
|
|
1290
|
+
token: tokens ? tokens.accessToken : "",
|
|
1291
|
+
refreshToken: tokens ? tokens.refreshToken : "",
|
|
1292
|
+
}),
|
|
1293
|
+
);
|
|
1278
1294
|
},
|
|
1279
1295
|
});
|
|
1280
1296
|
};
|
|
@@ -1375,7 +1391,7 @@ export async function startOpenclawClawlingGateway(params: StartGatewayParams):
|
|
|
1375
1391
|
(activationAccount.source === "sqlite" && store?.getActivationCredentials
|
|
1376
1392
|
? store.getActivationCredentials({ platform: "openclaw", accountId })?.refreshToken
|
|
1377
1393
|
: null) ??
|
|
1378
|
-
readConfigRefreshToken(cfg);
|
|
1394
|
+
readConfigRefreshToken(cfg, accountId);
|
|
1379
1395
|
|
|
1380
1396
|
const refreshManager = new RefreshManager({
|
|
1381
1397
|
baseUrl: account.baseUrl,
|