@yoooclaw/phone-notifications 1.6.2 → 1.7.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/README.md +59 -24
- package/dist/index.js +186 -121
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3647,7 +3647,7 @@ var require_websocket_server = __commonJS({
|
|
|
3647
3647
|
});
|
|
3648
3648
|
|
|
3649
3649
|
// src/index.ts
|
|
3650
|
-
import { readFileSync as
|
|
3650
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
3651
3651
|
import { basename as basename2, dirname as dirname5 } from "path";
|
|
3652
3652
|
|
|
3653
3653
|
// src/light/protocol.ts
|
|
@@ -3793,8 +3793,75 @@ function quantizeWindow(value) {
|
|
|
3793
3793
|
import { randomUUID } from "crypto";
|
|
3794
3794
|
|
|
3795
3795
|
// src/env.ts
|
|
3796
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
3797
|
-
import {
|
|
3796
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
3797
|
+
import { dirname } from "path";
|
|
3798
|
+
|
|
3799
|
+
// src/host.ts
|
|
3800
|
+
import { existsSync, readFileSync } from "fs";
|
|
3801
|
+
import { join } from "path";
|
|
3802
|
+
function trimToUndefined(value) {
|
|
3803
|
+
if (typeof value !== "string") {
|
|
3804
|
+
return void 0;
|
|
3805
|
+
}
|
|
3806
|
+
const trimmed = value.trim();
|
|
3807
|
+
return trimmed || void 0;
|
|
3808
|
+
}
|
|
3809
|
+
function homeDir() {
|
|
3810
|
+
return process.env.HOME || process.env.USERPROFILE || "/tmp";
|
|
3811
|
+
}
|
|
3812
|
+
function candidateMetaPaths() {
|
|
3813
|
+
const home = homeDir();
|
|
3814
|
+
return [
|
|
3815
|
+
join(home, ".qclaw", "qclaw.json"),
|
|
3816
|
+
join(home, ".qclow", "qclaw.json")
|
|
3817
|
+
];
|
|
3818
|
+
}
|
|
3819
|
+
function loadQClawMeta() {
|
|
3820
|
+
for (const metaPath of candidateMetaPaths()) {
|
|
3821
|
+
if (!existsSync(metaPath)) {
|
|
3822
|
+
continue;
|
|
3823
|
+
}
|
|
3824
|
+
try {
|
|
3825
|
+
const parsed = JSON.parse(readFileSync(metaPath, "utf-8"));
|
|
3826
|
+
return {
|
|
3827
|
+
stateDir: trimToUndefined(parsed?.stateDir),
|
|
3828
|
+
configPath: trimToUndefined(parsed?.configPath)
|
|
3829
|
+
};
|
|
3830
|
+
} catch {
|
|
3831
|
+
}
|
|
3832
|
+
}
|
|
3833
|
+
return void 0;
|
|
3834
|
+
}
|
|
3835
|
+
function resolveStateDirFromEnv() {
|
|
3836
|
+
return trimToUndefined(process.env.OPENCLAW_STATE_DIR) ?? trimToUndefined(process.env.QCLAW_STATE_DIR) ?? trimToUndefined(process.env.OPENCLAW_ROOT) ?? trimToUndefined(process.env.OPENCLAW_HOME) ?? trimToUndefined(process.env.QCLAW_HOME);
|
|
3837
|
+
}
|
|
3838
|
+
function resolveStateDir() {
|
|
3839
|
+
const envDir = resolveStateDirFromEnv();
|
|
3840
|
+
if (envDir) {
|
|
3841
|
+
return envDir;
|
|
3842
|
+
}
|
|
3843
|
+
const meta = loadQClawMeta();
|
|
3844
|
+
if (meta?.stateDir) {
|
|
3845
|
+
return meta.stateDir;
|
|
3846
|
+
}
|
|
3847
|
+
return join(homeDir(), ".openclaw");
|
|
3848
|
+
}
|
|
3849
|
+
function resolveConfigPath(stateDir = resolveStateDir()) {
|
|
3850
|
+
const envConfigPath = trimToUndefined(process.env.OPENCLAW_CONFIG_PATH) ?? trimToUndefined(process.env.QCLAW_CONFIG_PATH);
|
|
3851
|
+
if (envConfigPath) {
|
|
3852
|
+
return envConfigPath;
|
|
3853
|
+
}
|
|
3854
|
+
const meta = loadQClawMeta();
|
|
3855
|
+
if (meta?.configPath && (!meta.stateDir || !stateDir || meta.stateDir === stateDir)) {
|
|
3856
|
+
return meta.configPath;
|
|
3857
|
+
}
|
|
3858
|
+
return join(stateDir, "openclaw.json");
|
|
3859
|
+
}
|
|
3860
|
+
function resolveStateFile(filename) {
|
|
3861
|
+
return join(resolveStateDir(), filename);
|
|
3862
|
+
}
|
|
3863
|
+
|
|
3864
|
+
// src/env.ts
|
|
3798
3865
|
var ENV_CONFIG = {
|
|
3799
3866
|
development: {
|
|
3800
3867
|
lightApiUrl: "https://openclaw-service-dev.yoootek.com/api/message/tob/sendMessage",
|
|
@@ -3809,14 +3876,13 @@ var ENV_CONFIG = {
|
|
|
3809
3876
|
};
|
|
3810
3877
|
var VALID_ENVS = new Set(Object.keys(ENV_CONFIG));
|
|
3811
3878
|
function envFilePath() {
|
|
3812
|
-
|
|
3813
|
-
return join(home, ".openclaw", "env.json");
|
|
3879
|
+
return resolveStateFile("env.json");
|
|
3814
3880
|
}
|
|
3815
3881
|
function loadEnvName() {
|
|
3816
3882
|
const filePath = envFilePath();
|
|
3817
|
-
if (!
|
|
3883
|
+
if (!existsSync2(filePath)) return "production";
|
|
3818
3884
|
try {
|
|
3819
|
-
const data = JSON.parse(
|
|
3885
|
+
const data = JSON.parse(readFileSync2(filePath, "utf-8"));
|
|
3820
3886
|
if (data.env && VALID_ENVS.has(data.env)) return data.env;
|
|
3821
3887
|
} catch {
|
|
3822
3888
|
}
|
|
@@ -3887,27 +3953,26 @@ async function sendLightEffect(apiKey, segments, logger, repeat) {
|
|
|
3887
3953
|
}
|
|
3888
3954
|
|
|
3889
3955
|
// src/notification/app-name-map.ts
|
|
3890
|
-
import { existsSync as
|
|
3891
|
-
import { join as
|
|
3956
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
3957
|
+
import { join as join2 } from "path";
|
|
3892
3958
|
|
|
3893
3959
|
// src/auth/credentials.ts
|
|
3894
3960
|
import {
|
|
3895
|
-
existsSync as
|
|
3961
|
+
existsSync as existsSync3,
|
|
3896
3962
|
mkdirSync as mkdirSync2,
|
|
3897
|
-
readFileSync as
|
|
3963
|
+
readFileSync as readFileSync3,
|
|
3898
3964
|
writeFileSync as writeFileSync2,
|
|
3899
3965
|
watch
|
|
3900
3966
|
} from "fs";
|
|
3901
|
-
import {
|
|
3967
|
+
import { dirname as dirname2, basename } from "path";
|
|
3902
3968
|
function credentialsPath() {
|
|
3903
|
-
|
|
3904
|
-
return join2(home, ".openclaw", "credentials.json");
|
|
3969
|
+
return resolveStateFile("credentials.json");
|
|
3905
3970
|
}
|
|
3906
3971
|
function readCredentials() {
|
|
3907
3972
|
const path2 = credentialsPath();
|
|
3908
|
-
if (!
|
|
3973
|
+
if (!existsSync3(path2)) return {};
|
|
3909
3974
|
try {
|
|
3910
|
-
return JSON.parse(
|
|
3975
|
+
return JSON.parse(readFileSync3(path2, "utf-8"));
|
|
3911
3976
|
} catch {
|
|
3912
3977
|
return {};
|
|
3913
3978
|
}
|
|
@@ -3928,7 +3993,7 @@ function requireApiKey() {
|
|
|
3928
3993
|
const apiKey = loadApiKey();
|
|
3929
3994
|
if (!apiKey) {
|
|
3930
3995
|
throw new Error(
|
|
3931
|
-
|
|
3996
|
+
`API Key \u672A\u8BBE\u7F6E\uFF0C\u8BF7\u5148\u5199\u5165 ${credentialsPath()}\uFF0C\u6216\u901A\u8FC7\u5BBF\u4E3B CLI \u6267\u884C ntf auth set-api-key <apiKey>`
|
|
3932
3997
|
);
|
|
3933
3998
|
}
|
|
3934
3999
|
return apiKey;
|
|
@@ -3977,7 +4042,7 @@ function isAppNameMapApiResponse(v) {
|
|
|
3977
4042
|
);
|
|
3978
4043
|
}
|
|
3979
4044
|
function getCachePath(stateDir) {
|
|
3980
|
-
return
|
|
4045
|
+
return join2(stateDir, "plugins", PLUGIN_STATE_DIR, CACHE_FILE);
|
|
3981
4046
|
}
|
|
3982
4047
|
function createAppNameMapProvider(opts) {
|
|
3983
4048
|
const { stateDir, logger } = opts;
|
|
@@ -3989,9 +4054,9 @@ function createAppNameMapProvider(opts) {
|
|
|
3989
4054
|
let inFlightFetch = null;
|
|
3990
4055
|
function loadFromDisk() {
|
|
3991
4056
|
const path2 = getCachePath(stateDir);
|
|
3992
|
-
if (!
|
|
4057
|
+
if (!existsSync4(path2)) return;
|
|
3993
4058
|
try {
|
|
3994
|
-
const raw = JSON.parse(
|
|
4059
|
+
const raw = JSON.parse(readFileSync4(path2, "utf-8"));
|
|
3995
4060
|
if (!isRecordOfStrings(raw)) return;
|
|
3996
4061
|
map.clear();
|
|
3997
4062
|
for (const [k, v] of Object.entries(raw)) map.set(k, v);
|
|
@@ -4035,7 +4100,7 @@ function createAppNameMapProvider(opts) {
|
|
|
4035
4100
|
logger.warn("[app-name-map] refresh succeeded but got 0 entries");
|
|
4036
4101
|
return;
|
|
4037
4102
|
}
|
|
4038
|
-
const dir =
|
|
4103
|
+
const dir = join2(stateDir, "plugins", PLUGIN_STATE_DIR);
|
|
4039
4104
|
mkdirSync3(dir, { recursive: true });
|
|
4040
4105
|
const cachePath = getCachePath(stateDir);
|
|
4041
4106
|
writeFileSync3(cachePath, JSON.stringify(Object.fromEntries(map), null, 2), "utf-8");
|
|
@@ -4087,19 +4152,19 @@ import {
|
|
|
4087
4152
|
mkdirSync as mkdirSync4,
|
|
4088
4153
|
appendFileSync,
|
|
4089
4154
|
readdirSync,
|
|
4090
|
-
readFileSync as
|
|
4155
|
+
readFileSync as readFileSync5,
|
|
4091
4156
|
writeFileSync as writeFileSync4,
|
|
4092
|
-
existsSync as
|
|
4157
|
+
existsSync as existsSync5,
|
|
4093
4158
|
rmSync,
|
|
4094
4159
|
constants
|
|
4095
4160
|
} from "fs";
|
|
4096
4161
|
import { createHash } from "crypto";
|
|
4097
|
-
import { join as
|
|
4162
|
+
import { join as join3 } from "path";
|
|
4098
4163
|
var NOTIFICATION_DIR_NAME = "notifications";
|
|
4099
4164
|
var ID_INDEX_DIR_NAME = ".ids";
|
|
4100
4165
|
var CONTENT_KEY_INDEX_DIR_NAME = ".keys";
|
|
4101
4166
|
function getStateFallbackNotificationDir(stateDir) {
|
|
4102
|
-
return
|
|
4167
|
+
return join3(stateDir, "plugins", "phone-notifications", NOTIFICATION_DIR_NAME);
|
|
4103
4168
|
}
|
|
4104
4169
|
function ensureWritableDirectory(dir) {
|
|
4105
4170
|
try {
|
|
@@ -4117,7 +4182,7 @@ function resolveNotificationStorageDir(ctx, logger) {
|
|
|
4117
4182
|
return stateNotifDir;
|
|
4118
4183
|
}
|
|
4119
4184
|
if (ctx.workspaceDir) {
|
|
4120
|
-
const workspaceDir =
|
|
4185
|
+
const workspaceDir = join3(ctx.workspaceDir, NOTIFICATION_DIR_NAME);
|
|
4121
4186
|
if (ensureWritableDirectory(workspaceDir)) {
|
|
4122
4187
|
logger.warn(
|
|
4123
4188
|
`stateDir \u4E0D\u53EF\u7528\uFF0C\u901A\u77E5\u5DF2\u56DE\u9000\u5230 workspace \u8DEF\u5F84: ${workspaceDir}`
|
|
@@ -4132,8 +4197,8 @@ var NotificationStorage = class {
|
|
|
4132
4197
|
this.config = config;
|
|
4133
4198
|
this.logger = logger;
|
|
4134
4199
|
this.dir = dir;
|
|
4135
|
-
this.idIndexDir =
|
|
4136
|
-
this.contentKeyIndexDir =
|
|
4200
|
+
this.idIndexDir = join3(dir, ID_INDEX_DIR_NAME);
|
|
4201
|
+
this.contentKeyIndexDir = join3(dir, CONTENT_KEY_INDEX_DIR_NAME);
|
|
4137
4202
|
this.resolveDisplayName = resolveDisplayName;
|
|
4138
4203
|
}
|
|
4139
4204
|
dir;
|
|
@@ -4170,7 +4235,7 @@ var NotificationStorage = class {
|
|
|
4170
4235
|
return "invalid";
|
|
4171
4236
|
}
|
|
4172
4237
|
const dateKey = this.formatDate(ts);
|
|
4173
|
-
const filePath =
|
|
4238
|
+
const filePath = join3(this.dir, `${dateKey}.json`);
|
|
4174
4239
|
const normalizedId = typeof n.id === "string" ? n.id.trim() : "";
|
|
4175
4240
|
const entry = this.buildStoredNotification(n);
|
|
4176
4241
|
return this.withDateWriteLock(dateKey, async () => {
|
|
@@ -4224,7 +4289,7 @@ var NotificationStorage = class {
|
|
|
4224
4289
|
return `${year}-${month}-${day}`;
|
|
4225
4290
|
}
|
|
4226
4291
|
getIdIndexPath(dateKey) {
|
|
4227
|
-
return
|
|
4292
|
+
return join3(this.idIndexDir, `${dateKey}.ids`);
|
|
4228
4293
|
}
|
|
4229
4294
|
getIdSet(dateKey) {
|
|
4230
4295
|
const cached = this.idCache.get(dateKey);
|
|
@@ -4233,8 +4298,8 @@ var NotificationStorage = class {
|
|
|
4233
4298
|
}
|
|
4234
4299
|
const idPath = this.getIdIndexPath(dateKey);
|
|
4235
4300
|
const ids = /* @__PURE__ */ new Set();
|
|
4236
|
-
if (
|
|
4237
|
-
const lines =
|
|
4301
|
+
if (existsSync5(idPath)) {
|
|
4302
|
+
const lines = readFileSync5(idPath, "utf-8").split(/\r?\n/);
|
|
4238
4303
|
for (const line of lines) {
|
|
4239
4304
|
const id = line.trim();
|
|
4240
4305
|
if (id) {
|
|
@@ -4246,7 +4311,7 @@ var NotificationStorage = class {
|
|
|
4246
4311
|
return ids;
|
|
4247
4312
|
}
|
|
4248
4313
|
getContentKeyIndexPath(dateKey) {
|
|
4249
|
-
return
|
|
4314
|
+
return join3(this.contentKeyIndexDir, `${dateKey}.keys`);
|
|
4250
4315
|
}
|
|
4251
4316
|
getContentKeySet(dateKey, filePath) {
|
|
4252
4317
|
const cached = this.contentKeyCache.get(dateKey);
|
|
@@ -4255,15 +4320,15 @@ var NotificationStorage = class {
|
|
|
4255
4320
|
}
|
|
4256
4321
|
const keyPath = this.getContentKeyIndexPath(dateKey);
|
|
4257
4322
|
const keys = /* @__PURE__ */ new Set();
|
|
4258
|
-
if (
|
|
4259
|
-
const lines =
|
|
4323
|
+
if (existsSync5(keyPath)) {
|
|
4324
|
+
const lines = readFileSync5(keyPath, "utf-8").split(/\r?\n/);
|
|
4260
4325
|
for (const line of lines) {
|
|
4261
4326
|
const key = line.trim();
|
|
4262
4327
|
if (key) {
|
|
4263
4328
|
keys.add(key);
|
|
4264
4329
|
}
|
|
4265
4330
|
}
|
|
4266
|
-
} else if (
|
|
4331
|
+
} else if (existsSync5(filePath)) {
|
|
4267
4332
|
for (const item of this.readStoredNotifications(filePath)) {
|
|
4268
4333
|
keys.add(this.buildNotificationContentKey(item));
|
|
4269
4334
|
}
|
|
@@ -4306,11 +4371,11 @@ var NotificationStorage = class {
|
|
|
4306
4371
|
return createHash("sha256").update(entry.appName).update("").update(entry.title).update("").update(entry.content).digest("hex");
|
|
4307
4372
|
}
|
|
4308
4373
|
readStoredNotifications(filePath) {
|
|
4309
|
-
if (!
|
|
4374
|
+
if (!existsSync5(filePath)) {
|
|
4310
4375
|
return [];
|
|
4311
4376
|
}
|
|
4312
4377
|
try {
|
|
4313
|
-
const parsed = JSON.parse(
|
|
4378
|
+
const parsed = JSON.parse(readFileSync5(filePath, "utf-8"));
|
|
4314
4379
|
return Array.isArray(parsed) ? parsed : [];
|
|
4315
4380
|
} catch {
|
|
4316
4381
|
return [];
|
|
@@ -4351,10 +4416,10 @@ var NotificationStorage = class {
|
|
|
4351
4416
|
if (entry.isFile()) {
|
|
4352
4417
|
const match = dateFilePattern.exec(entry.name);
|
|
4353
4418
|
if (match && match[1] < cutoffDate) {
|
|
4354
|
-
rmSync(
|
|
4419
|
+
rmSync(join3(this.dir, entry.name), { force: true });
|
|
4355
4420
|
}
|
|
4356
4421
|
} else if (entry.isDirectory() && dateDirPattern.test(entry.name) && entry.name < cutoffDate) {
|
|
4357
|
-
rmSync(
|
|
4422
|
+
rmSync(join3(this.dir, entry.name), { recursive: true, force: true });
|
|
4358
4423
|
}
|
|
4359
4424
|
}
|
|
4360
4425
|
} catch {
|
|
@@ -4367,7 +4432,7 @@ var NotificationStorage = class {
|
|
|
4367
4432
|
if (!entry.isFile()) continue;
|
|
4368
4433
|
const match = /^(\d{4}-\d{2}-\d{2})\.ids$/.exec(entry.name);
|
|
4369
4434
|
if (match && match[1] < cutoffDate) {
|
|
4370
|
-
rmSync(
|
|
4435
|
+
rmSync(join3(this.idIndexDir, entry.name), { force: true });
|
|
4371
4436
|
this.idCache.delete(match[1]);
|
|
4372
4437
|
}
|
|
4373
4438
|
}
|
|
@@ -4381,7 +4446,7 @@ var NotificationStorage = class {
|
|
|
4381
4446
|
if (!entry.isFile()) continue;
|
|
4382
4447
|
const match = /^(\d{4}-\d{2}-\d{2})\.keys$/.exec(entry.name);
|
|
4383
4448
|
if (match && match[1] < cutoffDate) {
|
|
4384
|
-
rmSync(
|
|
4449
|
+
rmSync(join3(this.contentKeyIndexDir, entry.name), { force: true });
|
|
4385
4450
|
this.contentKeyCache.delete(match[1]);
|
|
4386
4451
|
}
|
|
4387
4452
|
}
|
|
@@ -4396,24 +4461,24 @@ var NotificationStorage = class {
|
|
|
4396
4461
|
};
|
|
4397
4462
|
|
|
4398
4463
|
// src/cli/auth.ts
|
|
4399
|
-
import { existsSync as
|
|
4464
|
+
import { existsSync as existsSync7, rmSync as rmSync2 } from "fs";
|
|
4400
4465
|
|
|
4401
4466
|
// src/cli/helpers.ts
|
|
4402
|
-
import { existsSync as
|
|
4403
|
-
import { join as
|
|
4467
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, readdirSync as readdirSync2 } from "fs";
|
|
4468
|
+
import { join as join4 } from "path";
|
|
4404
4469
|
function resolveNotificationsDir(ctx) {
|
|
4405
4470
|
if (ctx.stateDir) {
|
|
4406
|
-
const dir =
|
|
4471
|
+
const dir = join4(
|
|
4407
4472
|
ctx.stateDir,
|
|
4408
4473
|
"plugins",
|
|
4409
4474
|
"phone-notifications",
|
|
4410
4475
|
"notifications"
|
|
4411
4476
|
);
|
|
4412
|
-
if (
|
|
4477
|
+
if (existsSync6(dir)) return dir;
|
|
4413
4478
|
}
|
|
4414
4479
|
if (ctx.workspaceDir) {
|
|
4415
|
-
const dir =
|
|
4416
|
-
if (
|
|
4480
|
+
const dir = join4(ctx.workspaceDir, "notifications");
|
|
4481
|
+
if (existsSync6(dir)) return dir;
|
|
4417
4482
|
}
|
|
4418
4483
|
return null;
|
|
4419
4484
|
}
|
|
@@ -4428,10 +4493,10 @@ function listDateKeys(dir) {
|
|
|
4428
4493
|
return keys.sort().reverse();
|
|
4429
4494
|
}
|
|
4430
4495
|
function readDateFile(dir, dateKey) {
|
|
4431
|
-
const filePath =
|
|
4432
|
-
if (!
|
|
4496
|
+
const filePath = join4(dir, `${dateKey}.json`);
|
|
4497
|
+
if (!existsSync6(filePath)) return [];
|
|
4433
4498
|
try {
|
|
4434
|
-
return JSON.parse(
|
|
4499
|
+
return JSON.parse(readFileSync6(filePath, "utf-8"));
|
|
4435
4500
|
} catch {
|
|
4436
4501
|
return [];
|
|
4437
4502
|
}
|
|
@@ -4496,7 +4561,7 @@ function registerAuthCli(program) {
|
|
|
4496
4561
|
});
|
|
4497
4562
|
auth.command("clear").description("\u6E05\u9664\u5DF2\u4FDD\u5B58\u7684\u8BA4\u8BC1\u4FE1\u606F").action(() => {
|
|
4498
4563
|
const path2 = credentialsPath();
|
|
4499
|
-
if (
|
|
4564
|
+
if (existsSync7(path2)) {
|
|
4500
4565
|
const creds = readCredentials();
|
|
4501
4566
|
delete creds.apiKey;
|
|
4502
4567
|
delete creds.token;
|
|
@@ -4596,16 +4661,16 @@ function registerNtfStats(ntf, ctx) {
|
|
|
4596
4661
|
}
|
|
4597
4662
|
|
|
4598
4663
|
// src/cli/ntf-sync.ts
|
|
4599
|
-
import { existsSync as
|
|
4600
|
-
import { join as
|
|
4664
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
4665
|
+
import { join as join5 } from "path";
|
|
4601
4666
|
function checkpointPath(dir) {
|
|
4602
|
-
return
|
|
4667
|
+
return join5(dir, ".checkpoint.json");
|
|
4603
4668
|
}
|
|
4604
4669
|
function readCheckpoint(dir) {
|
|
4605
4670
|
const p = checkpointPath(dir);
|
|
4606
|
-
if (!
|
|
4671
|
+
if (!existsSync8(p)) return {};
|
|
4607
4672
|
try {
|
|
4608
|
-
return JSON.parse(
|
|
4673
|
+
return JSON.parse(readFileSync7(p, "utf-8"));
|
|
4609
4674
|
} catch {
|
|
4610
4675
|
return {};
|
|
4611
4676
|
}
|
|
@@ -4685,30 +4750,30 @@ function registerNtfSync(ntf, ctx) {
|
|
|
4685
4750
|
|
|
4686
4751
|
// src/cli/ntf-monitor.ts
|
|
4687
4752
|
import {
|
|
4688
|
-
existsSync as
|
|
4753
|
+
existsSync as existsSync9,
|
|
4689
4754
|
mkdirSync as mkdirSync5,
|
|
4690
|
-
readFileSync as
|
|
4755
|
+
readFileSync as readFileSync8,
|
|
4691
4756
|
writeFileSync as writeFileSync6,
|
|
4692
4757
|
rmSync as rmSync3,
|
|
4693
4758
|
readdirSync as readdirSync3
|
|
4694
4759
|
} from "fs";
|
|
4695
|
-
import { join as
|
|
4760
|
+
import { join as join6 } from "path";
|
|
4696
4761
|
function tasksDir(ctx) {
|
|
4697
4762
|
const base = ctx.workspaceDir || ctx.stateDir;
|
|
4698
4763
|
if (!base) throw new Error("workspaceDir and stateDir both unavailable");
|
|
4699
|
-
return
|
|
4764
|
+
return join6(base, "tasks");
|
|
4700
4765
|
}
|
|
4701
4766
|
function readMeta(taskDir) {
|
|
4702
|
-
const metaPath =
|
|
4703
|
-
if (!
|
|
4767
|
+
const metaPath = join6(taskDir, "meta.json");
|
|
4768
|
+
if (!existsSync9(metaPath)) return null;
|
|
4704
4769
|
try {
|
|
4705
|
-
return JSON.parse(
|
|
4770
|
+
return JSON.parse(readFileSync8(metaPath, "utf-8"));
|
|
4706
4771
|
} catch {
|
|
4707
4772
|
return null;
|
|
4708
4773
|
}
|
|
4709
4774
|
}
|
|
4710
4775
|
function writeMeta(taskDir, meta) {
|
|
4711
|
-
writeFileSync6(
|
|
4776
|
+
writeFileSync6(join6(taskDir, "meta.json"), JSON.stringify(meta, null, 2), "utf-8");
|
|
4712
4777
|
}
|
|
4713
4778
|
function generateFetchPy(name, matchRules) {
|
|
4714
4779
|
const appName = matchRules.appName || "";
|
|
@@ -4785,27 +4850,27 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
4785
4850
|
const monitor = ntf.command("monitor").description("\u901A\u77E5\u76D1\u63A7\u4EFB\u52A1\u7BA1\u7406");
|
|
4786
4851
|
monitor.command("list").description("\u5217\u51FA\u6240\u6709\u76D1\u63A7\u4EFB\u52A1").action(() => {
|
|
4787
4852
|
const dir = tasksDir(ctx);
|
|
4788
|
-
if (!
|
|
4853
|
+
if (!existsSync9(dir)) {
|
|
4789
4854
|
output({ ok: true, tasks: [] });
|
|
4790
4855
|
return;
|
|
4791
4856
|
}
|
|
4792
4857
|
const tasks = [];
|
|
4793
4858
|
for (const entry of readdirSync3(dir, { withFileTypes: true })) {
|
|
4794
4859
|
if (!entry.isDirectory()) continue;
|
|
4795
|
-
const meta = readMeta(
|
|
4860
|
+
const meta = readMeta(join6(dir, entry.name));
|
|
4796
4861
|
if (meta) tasks.push(meta);
|
|
4797
4862
|
}
|
|
4798
4863
|
output({ ok: true, tasks });
|
|
4799
4864
|
});
|
|
4800
4865
|
monitor.command("show <name>").description("\u67E5\u770B\u76D1\u63A7\u4EFB\u52A1\u8BE6\u60C5").action((name) => {
|
|
4801
|
-
const taskDir =
|
|
4866
|
+
const taskDir = join6(tasksDir(ctx), name);
|
|
4802
4867
|
const meta = readMeta(taskDir);
|
|
4803
4868
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
4804
|
-
const checkpointPath2 =
|
|
4869
|
+
const checkpointPath2 = join6(taskDir, "checkpoint.json");
|
|
4805
4870
|
let checkpoint = {};
|
|
4806
|
-
if (
|
|
4871
|
+
if (existsSync9(checkpointPath2)) {
|
|
4807
4872
|
try {
|
|
4808
|
-
checkpoint = JSON.parse(
|
|
4873
|
+
checkpoint = JSON.parse(readFileSync8(checkpointPath2, "utf-8"));
|
|
4809
4874
|
} catch {
|
|
4810
4875
|
}
|
|
4811
4876
|
}
|
|
@@ -4820,8 +4885,8 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
4820
4885
|
monitor.command("create <name>").description("\u521B\u5EFA\u76D1\u63A7\u4EFB\u52A1").requiredOption("--description <text>", "\u4EFB\u52A1\u63CF\u8FF0").requiredOption("--match-rules <json>", "\u5339\u914D\u89C4\u5219 JSON").requiredOption("--schedule <cron>", "cron \u8868\u8FBE\u5F0F").action(
|
|
4821
4886
|
(name, opts) => {
|
|
4822
4887
|
const dir = tasksDir(ctx);
|
|
4823
|
-
const taskDir =
|
|
4824
|
-
if (
|
|
4888
|
+
const taskDir = join6(dir, name);
|
|
4889
|
+
if (existsSync9(taskDir)) {
|
|
4825
4890
|
exitError("ALREADY_EXISTS", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u5DF2\u5B58\u5728`);
|
|
4826
4891
|
}
|
|
4827
4892
|
let matchRules;
|
|
@@ -4844,12 +4909,12 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
4844
4909
|
};
|
|
4845
4910
|
writeMeta(taskDir, meta);
|
|
4846
4911
|
writeFileSync6(
|
|
4847
|
-
|
|
4912
|
+
join6(taskDir, "fetch.py"),
|
|
4848
4913
|
generateFetchPy(name, matchRules),
|
|
4849
4914
|
"utf-8"
|
|
4850
4915
|
);
|
|
4851
4916
|
writeFileSync6(
|
|
4852
|
-
|
|
4917
|
+
join6(taskDir, "README.md"),
|
|
4853
4918
|
generateReadme(name, opts.description),
|
|
4854
4919
|
"utf-8"
|
|
4855
4920
|
);
|
|
@@ -4877,8 +4942,8 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
4877
4942
|
}
|
|
4878
4943
|
);
|
|
4879
4944
|
monitor.command("delete <name>").description("\u5220\u9664\u76D1\u63A7\u4EFB\u52A1").option("--yes", "\u8DF3\u8FC7\u786E\u8BA4").action((name, opts) => {
|
|
4880
|
-
const taskDir =
|
|
4881
|
-
if (!
|
|
4945
|
+
const taskDir = join6(tasksDir(ctx), name);
|
|
4946
|
+
if (!existsSync9(taskDir)) {
|
|
4882
4947
|
exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
4883
4948
|
}
|
|
4884
4949
|
if (!opts.yes) {
|
|
@@ -4903,7 +4968,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
4903
4968
|
});
|
|
4904
4969
|
});
|
|
4905
4970
|
monitor.command("enable <name>").description("\u542F\u7528\u76D1\u63A7\u4EFB\u52A1").action((name) => {
|
|
4906
|
-
const taskDir =
|
|
4971
|
+
const taskDir = join6(tasksDir(ctx), name);
|
|
4907
4972
|
const meta = readMeta(taskDir);
|
|
4908
4973
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
4909
4974
|
meta.enabled = true;
|
|
@@ -4911,7 +4976,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
4911
4976
|
output({ ok: true, name, enabled: true });
|
|
4912
4977
|
});
|
|
4913
4978
|
monitor.command("disable <name>").description("\u6682\u505C\u76D1\u63A7\u4EFB\u52A1").action((name) => {
|
|
4914
|
-
const taskDir =
|
|
4979
|
+
const taskDir = join6(tasksDir(ctx), name);
|
|
4915
4980
|
const meta = readMeta(taskDir);
|
|
4916
4981
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
4917
4982
|
meta.enabled = false;
|
|
@@ -4921,8 +4986,8 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
4921
4986
|
}
|
|
4922
4987
|
|
|
4923
4988
|
// src/cli/light-rules.ts
|
|
4924
|
-
import { existsSync as
|
|
4925
|
-
import { join as
|
|
4989
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
4990
|
+
import { join as join7 } from "path";
|
|
4926
4991
|
|
|
4927
4992
|
// src/light/validators.ts
|
|
4928
4993
|
var VALID_MODES = ["wave", "breath", "strobe", "steady", "wave_rainbow"];
|
|
@@ -4987,12 +5052,12 @@ var LIGHT_RULES_SECTION = "## \u706F\u6548\u89C4\u5219";
|
|
|
4987
5052
|
function memoryPath(ctx) {
|
|
4988
5053
|
const base = ctx.workspaceDir || ctx.stateDir;
|
|
4989
5054
|
if (!base) throw new Error("workspaceDir and stateDir both unavailable");
|
|
4990
|
-
return
|
|
5055
|
+
return join7(base, "MEMORY.md");
|
|
4991
5056
|
}
|
|
4992
5057
|
function readMemory(ctx) {
|
|
4993
5058
|
const p = memoryPath(ctx);
|
|
4994
|
-
if (!
|
|
4995
|
-
return
|
|
5059
|
+
if (!existsSync10(p)) return "";
|
|
5060
|
+
return readFileSync9(p, "utf-8");
|
|
4996
5061
|
}
|
|
4997
5062
|
function writeMemory(ctx, content) {
|
|
4998
5063
|
writeFileSync7(memoryPath(ctx), content, "utf-8");
|
|
@@ -5174,15 +5239,15 @@ function registerLightSend(light) {
|
|
|
5174
5239
|
}
|
|
5175
5240
|
|
|
5176
5241
|
// src/cli/tunnel-status.ts
|
|
5177
|
-
import { existsSync as
|
|
5178
|
-
import { join as
|
|
5179
|
-
var STATUS_REL_PATH =
|
|
5242
|
+
import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
|
|
5243
|
+
import { join as join8 } from "path";
|
|
5244
|
+
var STATUS_REL_PATH = join8("plugins", "phone-notifications", "tunnel-status.json");
|
|
5180
5245
|
function readTunnelStatus(ctx) {
|
|
5181
5246
|
if (!ctx.stateDir) return null;
|
|
5182
|
-
const filePath =
|
|
5183
|
-
if (!
|
|
5247
|
+
const filePath = join8(ctx.stateDir, STATUS_REL_PATH);
|
|
5248
|
+
if (!existsSync11(filePath)) return null;
|
|
5184
5249
|
try {
|
|
5185
|
-
return JSON.parse(
|
|
5250
|
+
return JSON.parse(readFileSync10(filePath, "utf-8"));
|
|
5186
5251
|
} catch {
|
|
5187
5252
|
return null;
|
|
5188
5253
|
}
|
|
@@ -5250,17 +5315,17 @@ function registerNtfStoragePath(ntf, ctx) {
|
|
|
5250
5315
|
}
|
|
5251
5316
|
|
|
5252
5317
|
// src/cli/log-search.ts
|
|
5253
|
-
import { existsSync as
|
|
5254
|
-
import { join as
|
|
5318
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11, readdirSync as readdirSync4 } from "fs";
|
|
5319
|
+
import { join as join9 } from "path";
|
|
5255
5320
|
function resolveLogsDir(ctx) {
|
|
5256
5321
|
if (ctx.stateDir) {
|
|
5257
|
-
const dir =
|
|
5322
|
+
const dir = join9(
|
|
5258
5323
|
ctx.stateDir,
|
|
5259
5324
|
"plugins",
|
|
5260
5325
|
"phone-notifications",
|
|
5261
5326
|
"logs"
|
|
5262
5327
|
);
|
|
5263
|
-
if (
|
|
5328
|
+
if (existsSync12(dir)) return dir;
|
|
5264
5329
|
}
|
|
5265
5330
|
return null;
|
|
5266
5331
|
}
|
|
@@ -5275,9 +5340,9 @@ function listLogDateKeys(dir) {
|
|
|
5275
5340
|
return keys.sort().reverse();
|
|
5276
5341
|
}
|
|
5277
5342
|
function collectLogLines(dir, dateKey, keyword, limit, collected) {
|
|
5278
|
-
const filePath =
|
|
5279
|
-
if (!
|
|
5280
|
-
const content =
|
|
5343
|
+
const filePath = join9(dir, `${dateKey}.log`);
|
|
5344
|
+
if (!existsSync12(filePath)) return;
|
|
5345
|
+
const content = readFileSync11(filePath, "utf-8");
|
|
5281
5346
|
const lowerKeyword = keyword?.toLowerCase();
|
|
5282
5347
|
for (const line of content.split("\n")) {
|
|
5283
5348
|
if (collected.length >= limit) return;
|
|
@@ -5343,12 +5408,12 @@ function registerEnvCli(ntf) {
|
|
|
5343
5408
|
}
|
|
5344
5409
|
|
|
5345
5410
|
// src/version.ts
|
|
5346
|
-
import { readFileSync as
|
|
5411
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
5347
5412
|
function readPluginVersion() {
|
|
5348
5413
|
try {
|
|
5349
5414
|
const packageJsonUrl = new URL("../package.json", import.meta.url);
|
|
5350
5415
|
const packageJson = JSON.parse(
|
|
5351
|
-
|
|
5416
|
+
readFileSync12(packageJsonUrl, "utf-8")
|
|
5352
5417
|
);
|
|
5353
5418
|
return packageJson.version ?? "unknown";
|
|
5354
5419
|
} catch {
|
|
@@ -5378,11 +5443,11 @@ import {
|
|
|
5378
5443
|
closeSync,
|
|
5379
5444
|
mkdirSync as mkdirSync7,
|
|
5380
5445
|
openSync,
|
|
5381
|
-
readFileSync as
|
|
5446
|
+
readFileSync as readFileSync13,
|
|
5382
5447
|
unlinkSync,
|
|
5383
5448
|
writeFileSync as writeFileSync9
|
|
5384
5449
|
} from "fs";
|
|
5385
|
-
import { dirname as dirname4, join as
|
|
5450
|
+
import { dirname as dirname4, join as join10 } from "path";
|
|
5386
5451
|
|
|
5387
5452
|
// src/tunnel/relay-client.ts
|
|
5388
5453
|
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync6 } from "fs";
|
|
@@ -5716,11 +5781,11 @@ function buildDeviceAuthPayload(params) {
|
|
|
5716
5781
|
params.nonce
|
|
5717
5782
|
].join("|");
|
|
5718
5783
|
}
|
|
5719
|
-
function
|
|
5720
|
-
return
|
|
5784
|
+
function resolveStateDir2() {
|
|
5785
|
+
return resolveStateDir();
|
|
5721
5786
|
}
|
|
5722
5787
|
function loadOrCreateDeviceIdentity() {
|
|
5723
|
-
const filePath = path.join(
|
|
5788
|
+
const filePath = path.join(resolveStateDir2(), "identity", "device.json");
|
|
5724
5789
|
try {
|
|
5725
5790
|
if (fs.existsSync(filePath)) {
|
|
5726
5791
|
const raw = fs.readFileSync(filePath, "utf8");
|
|
@@ -6270,7 +6335,7 @@ function createTunnelService(opts) {
|
|
|
6270
6335
|
}
|
|
6271
6336
|
function readLockOwner(filePath) {
|
|
6272
6337
|
try {
|
|
6273
|
-
const parsed = JSON.parse(
|
|
6338
|
+
const parsed = JSON.parse(readFileSync13(filePath, "utf-8"));
|
|
6274
6339
|
return typeof parsed.pid === "number" ? parsed.pid : null;
|
|
6275
6340
|
} catch {
|
|
6276
6341
|
return null;
|
|
@@ -6356,12 +6421,12 @@ function createTunnelService(opts) {
|
|
|
6356
6421
|
return;
|
|
6357
6422
|
}
|
|
6358
6423
|
const { logger } = opts;
|
|
6359
|
-
const baseStateDir =
|
|
6424
|
+
const baseStateDir = join10(ctx.stateDir, "plugins", "phone-notifications");
|
|
6360
6425
|
logger.info(
|
|
6361
6426
|
`Relay tunnel: starting (pid=${process.pid}, url=${opts.tunnelUrl}, heartbeat=${opts.heartbeatSec ?? DEFAULT_HEARTBEAT_SEC}s, backoff=${opts.reconnectBackoffMs ?? DEFAULT_RECONNECT_BACKOFF_MS}ms, gateway=${opts.gatewayBaseUrl}, hasGatewayToken=${!!opts.gatewayToken}, hasGatewayPwd=${!!opts.gatewayPassword})`
|
|
6362
6427
|
);
|
|
6363
|
-
const statusFilePath =
|
|
6364
|
-
const lockPath =
|
|
6428
|
+
const statusFilePath = join10(baseStateDir, "tunnel-status.json");
|
|
6429
|
+
const lockPath = join10(baseStateDir, "relay-tunnel.lock");
|
|
6365
6430
|
if (!acquireLock(lockPath)) {
|
|
6366
6431
|
return;
|
|
6367
6432
|
}
|
|
@@ -6410,11 +6475,11 @@ function createTunnelService(opts) {
|
|
|
6410
6475
|
|
|
6411
6476
|
// src/logger.ts
|
|
6412
6477
|
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync8 } from "fs";
|
|
6413
|
-
import { join as
|
|
6478
|
+
import { join as join11 } from "path";
|
|
6414
6479
|
var PluginFileLogger = class {
|
|
6415
6480
|
constructor(upstream, stateDir) {
|
|
6416
6481
|
this.upstream = upstream;
|
|
6417
|
-
this.logsDir =
|
|
6482
|
+
this.logsDir = join11(stateDir, "plugins", "phone-notifications", "logs");
|
|
6418
6483
|
mkdirSync8(this.logsDir, { recursive: true });
|
|
6419
6484
|
}
|
|
6420
6485
|
logsDir;
|
|
@@ -6437,7 +6502,7 @@ var PluginFileLogger = class {
|
|
|
6437
6502
|
const line = `${time} [${level}] ${msg}
|
|
6438
6503
|
`;
|
|
6439
6504
|
try {
|
|
6440
|
-
appendFileSync2(
|
|
6505
|
+
appendFileSync2(join11(this.logsDir, `${dateKey}.log`), line);
|
|
6441
6506
|
} catch {
|
|
6442
6507
|
}
|
|
6443
6508
|
}
|
|
@@ -6458,7 +6523,7 @@ function readBody(req) {
|
|
|
6458
6523
|
req.on("error", reject);
|
|
6459
6524
|
});
|
|
6460
6525
|
}
|
|
6461
|
-
function
|
|
6526
|
+
function trimToUndefined2(value) {
|
|
6462
6527
|
if (typeof value !== "string") {
|
|
6463
6528
|
return void 0;
|
|
6464
6529
|
}
|
|
@@ -6475,21 +6540,21 @@ function createEmptyIngestResult() {
|
|
|
6475
6540
|
};
|
|
6476
6541
|
}
|
|
6477
6542
|
function resolveLocalGatewayAuth(params) {
|
|
6478
|
-
const envGatewayToken =
|
|
6479
|
-
const envGatewayPassword =
|
|
6543
|
+
const envGatewayToken = trimToUndefined2(process.env.OPENCLAW_GATEWAY_TOKEN) ?? trimToUndefined2(process.env.QCLAW_GATEWAY_TOKEN) ?? trimToUndefined2(process.env.CLAWDBOT_GATEWAY_TOKEN);
|
|
6544
|
+
const envGatewayPassword = trimToUndefined2(process.env.OPENCLAW_GATEWAY_PASSWORD) ?? trimToUndefined2(process.env.QCLAW_GATEWAY_PASSWORD) ?? trimToUndefined2(process.env.CLAWDBOT_GATEWAY_PASSWORD);
|
|
6480
6545
|
let configGatewayAuthMode;
|
|
6481
6546
|
let configGatewayToken;
|
|
6482
6547
|
let configGatewayPassword;
|
|
6483
|
-
const configPath = params.stateDir ?
|
|
6548
|
+
const configPath = params.stateDir ? resolveConfigPath(params.stateDir) : void 0;
|
|
6484
6549
|
if (configPath) {
|
|
6485
6550
|
try {
|
|
6486
|
-
const configData = JSON.parse(
|
|
6487
|
-
const rawGatewayAuthMode =
|
|
6551
|
+
const configData = JSON.parse(readFileSync14(configPath, "utf-8"));
|
|
6552
|
+
const rawGatewayAuthMode = trimToUndefined2(configData?.gateway?.auth?.mode);
|
|
6488
6553
|
if (rawGatewayAuthMode === "token" || rawGatewayAuthMode === "password") {
|
|
6489
6554
|
configGatewayAuthMode = rawGatewayAuthMode;
|
|
6490
6555
|
}
|
|
6491
|
-
configGatewayToken =
|
|
6492
|
-
configGatewayPassword =
|
|
6556
|
+
configGatewayToken = trimToUndefined2(configData?.gateway?.auth?.token);
|
|
6557
|
+
configGatewayPassword = trimToUndefined2(configData?.gateway?.auth?.password);
|
|
6493
6558
|
} catch (err) {
|
|
6494
6559
|
if (err?.code !== "ENOENT") {
|
|
6495
6560
|
params.logger.warn(
|
|
@@ -6541,7 +6606,7 @@ var index_default = {
|
|
|
6541
6606
|
});
|
|
6542
6607
|
const tunnelUrl = getEnvUrls().relayTunnelUrl;
|
|
6543
6608
|
if (tunnelUrl) {
|
|
6544
|
-
const gatewayPort = process.env.OPENCLAW_GATEWAY_PORT
|
|
6609
|
+
const gatewayPort = process.env.OPENCLAW_GATEWAY_PORT ?? process.env.QCLAW_GATEWAY_PORT ?? "18789";
|
|
6545
6610
|
const { gatewayAuthMode, gatewayToken, gatewayPassword } = resolveLocalGatewayAuth({
|
|
6546
6611
|
stateDir: openclawDir,
|
|
6547
6612
|
logger
|