@yoooclaw/phone-notifications 1.11.0-beta.2 → 1.11.0-beta.4
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/index.cjs +127 -248
- package/dist/index.cjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5422,7 +5422,7 @@ function readBuildInjectedVersion() {
|
|
|
5422
5422
|
if (false) {
|
|
5423
5423
|
return void 0;
|
|
5424
5424
|
}
|
|
5425
|
-
const version = "1.11.0-beta.
|
|
5425
|
+
const version = "1.11.0-beta.4".trim();
|
|
5426
5426
|
return version || void 0;
|
|
5427
5427
|
}
|
|
5428
5428
|
function readPluginVersionFromPackageJson() {
|
|
@@ -5989,112 +5989,6 @@ function isRecord(value) {
|
|
|
5989
5989
|
// src/light-rules/storage.ts
|
|
5990
5990
|
var import_node_fs4 = require("fs");
|
|
5991
5991
|
var import_node_path3 = require("path");
|
|
5992
|
-
|
|
5993
|
-
// src/monitor/fetch-gen.ts
|
|
5994
|
-
function generateFetchPy(name, matchRules) {
|
|
5995
|
-
const appName = typeof matchRules.appName === "string" ? matchRules.appName : "";
|
|
5996
|
-
const senderKeywords = stringArray(matchRules.senderKeywords);
|
|
5997
|
-
const contentKeywords = stringArray(matchRules.contentKeywords);
|
|
5998
|
-
return `#!/usr/bin/env python3
|
|
5999
|
-
"""Auto-generated fetch script for monitor task: ${name}"""
|
|
6000
|
-
import json, sys, os
|
|
6001
|
-
from pathlib import Path
|
|
6002
|
-
|
|
6003
|
-
def matches(notification: dict) -> bool:
|
|
6004
|
-
app = str(notification.get("appName", "") or "")
|
|
6005
|
-
title = str(notification.get("title", "") or "")
|
|
6006
|
-
content = str(notification.get("content", "") or "")
|
|
6007
|
-
body = str(notification.get("body", "") or "")
|
|
6008
|
-
|
|
6009
|
-
app_name = ${pyLiteral(appName)}
|
|
6010
|
-
if app_name and app != app_name:
|
|
6011
|
-
return False
|
|
6012
|
-
|
|
6013
|
-
sender_keywords = ${pyLiteral(senderKeywords)}
|
|
6014
|
-
sender_haystack = f"{title}\\n{content}\\n{body}"
|
|
6015
|
-
if sender_keywords and not any(keyword in sender_haystack for keyword in sender_keywords):
|
|
6016
|
-
return False
|
|
6017
|
-
|
|
6018
|
-
content_keywords = ${pyLiteral(contentKeywords)}
|
|
6019
|
-
content_haystack = f"{content}\\n{body}"
|
|
6020
|
-
if content_keywords and not any(keyword in content_haystack for keyword in content_keywords):
|
|
6021
|
-
return False
|
|
6022
|
-
|
|
6023
|
-
return True
|
|
6024
|
-
|
|
6025
|
-
def main():
|
|
6026
|
-
import argparse
|
|
6027
|
-
parser = argparse.ArgumentParser()
|
|
6028
|
-
parser.add_argument("--notifications-dir", required=True)
|
|
6029
|
-
args = parser.parse_args()
|
|
6030
|
-
|
|
6031
|
-
checkpoint_path = Path(__file__).parent / "checkpoint.json"
|
|
6032
|
-
checkpoint = {}
|
|
6033
|
-
if checkpoint_path.exists():
|
|
6034
|
-
checkpoint = json.loads(checkpoint_path.read_text())
|
|
6035
|
-
|
|
6036
|
-
ntf_dir = Path(args.notifications_dir)
|
|
6037
|
-
matched = []
|
|
6038
|
-
new_checkpoint = dict(checkpoint)
|
|
6039
|
-
|
|
6040
|
-
for f in sorted(ntf_dir.glob("*.json")):
|
|
6041
|
-
date_key = f.stem
|
|
6042
|
-
items = json.loads(f.read_text())
|
|
6043
|
-
last_idx = checkpoint.get(date_key, {}).get("lastIndex", -1)
|
|
6044
|
-
for i, item in enumerate(items):
|
|
6045
|
-
if i <= last_idx:
|
|
6046
|
-
continue
|
|
6047
|
-
if matches(item):
|
|
6048
|
-
matched.append(item)
|
|
6049
|
-
new_checkpoint[date_key] = {"lastIndex": len(items) - 1}
|
|
6050
|
-
|
|
6051
|
-
checkpoint_path.write_text(json.dumps(new_checkpoint, indent=2))
|
|
6052
|
-
|
|
6053
|
-
if not matched:
|
|
6054
|
-
print("NO_MATCH")
|
|
6055
|
-
return
|
|
6056
|
-
|
|
6057
|
-
for m in matched:
|
|
6058
|
-
print(json.dumps(m, ensure_ascii=False))
|
|
6059
|
-
|
|
6060
|
-
if __name__ == "__main__":
|
|
6061
|
-
main()
|
|
6062
|
-
`;
|
|
6063
|
-
}
|
|
6064
|
-
function stringArray(value) {
|
|
6065
|
-
if (!Array.isArray(value)) return [];
|
|
6066
|
-
return value.filter((item) => typeof item === "string" && item.length > 0);
|
|
6067
|
-
}
|
|
6068
|
-
function pyLiteral(value) {
|
|
6069
|
-
return JSON.stringify(value);
|
|
6070
|
-
}
|
|
6071
|
-
|
|
6072
|
-
// src/light-rules/storage.ts
|
|
6073
|
-
var LEGACY_DEFAULT_CRON_SCHEDULE = "*/5 * * * *";
|
|
6074
|
-
function legacyReadMatchRules(input) {
|
|
6075
|
-
return input.matchRules ?? {};
|
|
6076
|
-
}
|
|
6077
|
-
function legacyReadCronSchedule(input) {
|
|
6078
|
-
return input.cronSchedule ?? LEGACY_DEFAULT_CRON_SCHEDULE;
|
|
6079
|
-
}
|
|
6080
|
-
function legacyHasMatchRules(input) {
|
|
6081
|
-
return input.matchRules !== void 0;
|
|
6082
|
-
}
|
|
6083
|
-
function legacyHasCronSchedule(input) {
|
|
6084
|
-
return input.cronSchedule !== void 0;
|
|
6085
|
-
}
|
|
6086
|
-
function legacyAssignMatchRules(meta, matchRules) {
|
|
6087
|
-
meta.matchRules = matchRules;
|
|
6088
|
-
}
|
|
6089
|
-
function legacyAssignCronSchedule(meta, cronSchedule) {
|
|
6090
|
-
meta.cronSchedule = cronSchedule;
|
|
6091
|
-
}
|
|
6092
|
-
function legacyReadMetaMatchRules(meta) {
|
|
6093
|
-
return meta.matchRules ?? {};
|
|
6094
|
-
}
|
|
6095
|
-
function legacyReadMetaCronSchedule(meta) {
|
|
6096
|
-
return meta.cronSchedule;
|
|
6097
|
-
}
|
|
6098
5992
|
function resolveBaseDir(ctx) {
|
|
6099
5993
|
if (ctx.workspaceDir) return ctx.workspaceDir;
|
|
6100
5994
|
if (ctx.stateDir) {
|
|
@@ -6178,34 +6072,6 @@ function readMeta(taskDir) {
|
|
|
6178
6072
|
function writeMeta(taskDir, meta) {
|
|
6179
6073
|
(0, import_node_fs4.writeFileSync)((0, import_node_path3.join)(taskDir, "meta.json"), JSON.stringify(meta, null, 2), "utf-8");
|
|
6180
6074
|
}
|
|
6181
|
-
function generateLightRuleReadme(name, description, segments, repeatTimes) {
|
|
6182
|
-
const segmentsJson = JSON.stringify(segments, null, 2);
|
|
6183
|
-
return `# ${name}
|
|
6184
|
-
|
|
6185
|
-
## \u76D1\u63A7\u76EE\u6807
|
|
6186
|
-
|
|
6187
|
-
${description}
|
|
6188
|
-
|
|
6189
|
-
## \u89E6\u53D1\u540E\u5982\u4F55\u5904\u7406
|
|
6190
|
-
|
|
6191
|
-
\u5F53\u4EFB\u52A1\u811A\u672C\u8F93\u51FA\u5339\u914D\u7ED3\u679C\u65F6\uFF1A
|
|
6192
|
-
|
|
6193
|
-
1. \u5C06\u8F93\u51FA\u6309"\u6BCF\u884C\u4E00\u4E2A JSON \u5BF9\u8C61"\u89E3\u6790
|
|
6194
|
-
2. \u8FD9\u4E9B\u662F\u5019\u9009\u901A\u77E5\uFF0C\u4E0D\u4EE3\u8868\u5DF2\u7ECF\u547D\u4E2D
|
|
6195
|
-
3. \u6839\u636E\u76D1\u63A7\u76EE\u6807\u5224\u65AD\u662F\u5426\u771F\u6B63\u547D\u4E2D
|
|
6196
|
-
|
|
6197
|
-
**\u547D\u4E2D\u540E\u6267\u884C\u706F\u6548**\uFF1A\u8C03\u7528 light_control \u5DE5\u5177\uFF0C\u4F20\u5165\u4EE5\u4E0B\u706F\u6548\u53C2\u6570\uFF1A
|
|
6198
|
-
|
|
6199
|
-
\`\`\`json
|
|
6200
|
-
${segmentsJson}
|
|
6201
|
-
\`\`\`
|
|
6202
|
-
|
|
6203
|
-
repeat_times: ${repeatTimes}
|
|
6204
|
-
reason: "${description}"
|
|
6205
|
-
|
|
6206
|
-
\u53EA\u6267\u884C\u706F\u6548\uFF0C\u4E0D\u4E3B\u52A8\u53D1\u9001\u901A\u77E5\u6458\u8981\u6216\u56DE\u590D\u7528\u6237\u3002
|
|
6207
|
-
`;
|
|
6208
|
-
}
|
|
6209
6075
|
function listLightRules(ctx) {
|
|
6210
6076
|
const dir = tasksDir(ctx);
|
|
6211
6077
|
if (!(0, import_node_fs4.existsSync)(dir)) return [];
|
|
@@ -6229,8 +6095,6 @@ function createLightRule(ctx, params) {
|
|
|
6229
6095
|
repeat_times: params.repeat_times
|
|
6230
6096
|
});
|
|
6231
6097
|
assertAncsRepeatTimes(repeatTimes);
|
|
6232
|
-
const effectiveMatchRules = legacyReadMatchRules(params);
|
|
6233
|
-
const effectiveCronSchedule = legacyReadCronSchedule(params);
|
|
6234
6098
|
const meta = {
|
|
6235
6099
|
name: params.name,
|
|
6236
6100
|
type: "light-rule",
|
|
@@ -6240,34 +6104,8 @@ function createLightRule(ctx, params) {
|
|
|
6240
6104
|
enabled: true,
|
|
6241
6105
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6242
6106
|
};
|
|
6243
|
-
legacyAssignMatchRules(meta, effectiveMatchRules);
|
|
6244
|
-
legacyAssignCronSchedule(meta, effectiveCronSchedule);
|
|
6245
6107
|
writeMeta(taskDir, meta);
|
|
6246
|
-
|
|
6247
|
-
(0, import_node_path3.join)(taskDir, "fetch.py"),
|
|
6248
|
-
generateFetchPy(params.name, effectiveMatchRules),
|
|
6249
|
-
"utf-8"
|
|
6250
|
-
);
|
|
6251
|
-
(0, import_node_fs4.writeFileSync)(
|
|
6252
|
-
(0, import_node_path3.join)(taskDir, "README.md"),
|
|
6253
|
-
generateLightRuleReadme(params.name, params.description, params.segments, repeatTimes),
|
|
6254
|
-
"utf-8"
|
|
6255
|
-
);
|
|
6256
|
-
return {
|
|
6257
|
-
meta,
|
|
6258
|
-
cronHint: {
|
|
6259
|
-
action: "add",
|
|
6260
|
-
job: {
|
|
6261
|
-
name: `notif-${params.name}`,
|
|
6262
|
-
schedule: effectiveCronSchedule,
|
|
6263
|
-
sessionTarget: "isolated",
|
|
6264
|
-
message: `\u624B\u673A\u901A\u77E5\u5DF2\u7531\u72EC\u7ACB\u670D\u52A1\u5B9E\u65F6\u6355\u83B7\u5230 notifications/ \u76EE\u5F55\u7684 JSON \u6587\u4EF6\u4E2D\u3002
|
|
6265
|
-
\u6267\u884C\uFF1Apython3 tasks/${params.name}/fetch.py --notifications-dir notifications
|
|
6266
|
-
- NO_CHANGE \u6216 NO_MATCH \u2192 \u4E0D\u56DE\u590D\uFF0C\u76F4\u63A5\u7ED3\u675F\u3002
|
|
6267
|
-
- \u6709\u8F93\u51FA \u2192 \u8BFB tasks/${params.name}/README.md \u4E86\u89E3\u5982\u4F55\u5904\u7406\u6570\u636E\u5E76\u901A\u77E5\u7528\u6237\u3002`
|
|
6268
|
-
}
|
|
6269
|
-
}
|
|
6270
|
-
};
|
|
6108
|
+
return { meta };
|
|
6271
6109
|
}
|
|
6272
6110
|
function updateLightRule(ctx, params) {
|
|
6273
6111
|
const resolved = resolveLightRuleTask(ctx, params.name);
|
|
@@ -6276,19 +6114,11 @@ function updateLightRule(ctx, params) {
|
|
|
6276
6114
|
if (!taskDir || !meta) {
|
|
6277
6115
|
throw new LightRuleError("NOT_FOUND", `\u706F\u6548\u89C4\u5219 '${params.name}' \u4E0D\u5B58\u5728`);
|
|
6278
6116
|
}
|
|
6279
|
-
let regenerateFetch = false;
|
|
6280
|
-
let regenerateReadme = false;
|
|
6281
6117
|
if (params.description !== void 0) {
|
|
6282
6118
|
meta.description = params.description;
|
|
6283
|
-
regenerateReadme = true;
|
|
6284
|
-
}
|
|
6285
|
-
if (legacyHasMatchRules(params)) {
|
|
6286
|
-
legacyAssignMatchRules(meta, legacyReadMatchRules(params));
|
|
6287
|
-
regenerateFetch = true;
|
|
6288
6119
|
}
|
|
6289
6120
|
if (params.segments !== void 0) {
|
|
6290
6121
|
meta.segments = params.segments;
|
|
6291
|
-
regenerateReadme = true;
|
|
6292
6122
|
}
|
|
6293
6123
|
if (params.repeat !== void 0 || params.repeat_times !== void 0) {
|
|
6294
6124
|
meta.repeat_times = normalizeRepeatTimes({
|
|
@@ -6296,38 +6126,13 @@ function updateLightRule(ctx, params) {
|
|
|
6296
6126
|
repeat_times: params.repeat_times
|
|
6297
6127
|
});
|
|
6298
6128
|
assertAncsRepeatTimes(meta.repeat_times);
|
|
6299
|
-
regenerateReadme = true;
|
|
6300
|
-
}
|
|
6301
|
-
if (legacyHasCronSchedule(params)) {
|
|
6302
|
-
legacyAssignCronSchedule(meta, legacyReadCronSchedule(params));
|
|
6303
6129
|
}
|
|
6304
6130
|
if (params.enabled !== void 0) {
|
|
6305
6131
|
meta.enabled = params.enabled;
|
|
6306
6132
|
}
|
|
6307
6133
|
meta.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
6308
6134
|
writeMeta(taskDir, meta);
|
|
6309
|
-
|
|
6310
|
-
(0, import_node_fs4.writeFileSync)(
|
|
6311
|
-
(0, import_node_path3.join)(taskDir, "fetch.py"),
|
|
6312
|
-
generateFetchPy(meta.name, legacyReadMetaMatchRules(meta)),
|
|
6313
|
-
"utf-8"
|
|
6314
|
-
);
|
|
6315
|
-
}
|
|
6316
|
-
if (regenerateReadme) {
|
|
6317
|
-
(0, import_node_fs4.writeFileSync)(
|
|
6318
|
-
(0, import_node_path3.join)(taskDir, "README.md"),
|
|
6319
|
-
generateLightRuleReadme(meta.name, meta.description, meta.segments, meta.repeat_times),
|
|
6320
|
-
"utf-8"
|
|
6321
|
-
);
|
|
6322
|
-
}
|
|
6323
|
-
const cronHint = legacyHasCronSchedule(params) ? {
|
|
6324
|
-
action: "update",
|
|
6325
|
-
job: {
|
|
6326
|
-
name: `notif-${meta.name}`,
|
|
6327
|
-
schedule: legacyReadMetaCronSchedule(meta)
|
|
6328
|
-
}
|
|
6329
|
-
} : void 0;
|
|
6330
|
-
return { meta, cronHint };
|
|
6135
|
+
return { meta };
|
|
6331
6136
|
}
|
|
6332
6137
|
function deleteLightRule(ctx, name) {
|
|
6333
6138
|
const resolved = resolveLightRuleTask(ctx, name);
|
|
@@ -6337,13 +6142,7 @@ function deleteLightRule(ctx, name) {
|
|
|
6337
6142
|
throw new LightRuleError("NOT_FOUND", `\u706F\u6548\u89C4\u5219 '${name}' \u4E0D\u5B58\u5728`);
|
|
6338
6143
|
}
|
|
6339
6144
|
(0, import_node_fs4.rmSync)(taskDir, { recursive: true, force: true });
|
|
6340
|
-
return {
|
|
6341
|
-
name: meta.name,
|
|
6342
|
-
cronHint: {
|
|
6343
|
-
action: "remove",
|
|
6344
|
-
name: `notif-${meta.name}`
|
|
6345
|
-
}
|
|
6346
|
-
};
|
|
6145
|
+
return { name: meta.name };
|
|
6347
6146
|
}
|
|
6348
6147
|
var LightRuleError = class extends Error {
|
|
6349
6148
|
constructor(code, message) {
|
|
@@ -6354,7 +6153,6 @@ var LightRuleError = class extends Error {
|
|
|
6354
6153
|
};
|
|
6355
6154
|
|
|
6356
6155
|
// src/light-rules/gateway.ts
|
|
6357
|
-
var DEFAULT_CRON_SCHEDULE = "*/5 * * * *";
|
|
6358
6156
|
function resolveRuleIdentifier(params) {
|
|
6359
6157
|
if (!params || typeof params !== "object") return void 0;
|
|
6360
6158
|
const raw = params;
|
|
@@ -6390,7 +6188,7 @@ function registerLightRulesGateway(api, registry, logger, rememberBroadcast) {
|
|
|
6390
6188
|
}
|
|
6391
6189
|
});
|
|
6392
6190
|
registerGatewayMethodWithBroadcastCapture("lightrules.create", async ({ params, respond }) => {
|
|
6393
|
-
const { name, description,
|
|
6191
|
+
const { name, description, segments, repeat, repeat_times } = params;
|
|
6394
6192
|
if (!name || typeof name !== "string") {
|
|
6395
6193
|
respond(false, null, { code: "INVALID_PARAMS", message: "name is required" });
|
|
6396
6194
|
return;
|
|
@@ -6399,10 +6197,6 @@ function registerLightRulesGateway(api, registry, logger, rememberBroadcast) {
|
|
|
6399
6197
|
respond(false, null, { code: "INVALID_PARAMS", message: "description is required" });
|
|
6400
6198
|
return;
|
|
6401
6199
|
}
|
|
6402
|
-
if (!matchRules || typeof matchRules !== "object") {
|
|
6403
|
-
respond(false, null, { code: "INVALID_PARAMS", message: "matchRules is required" });
|
|
6404
|
-
return;
|
|
6405
|
-
}
|
|
6406
6200
|
const validation = validateSegments(segments);
|
|
6407
6201
|
if (!validation.valid) {
|
|
6408
6202
|
respond(false, null, {
|
|
@@ -6423,13 +6217,11 @@ function registerLightRulesGateway(api, registry, logger, rememberBroadcast) {
|
|
|
6423
6217
|
const result = await registry.create({
|
|
6424
6218
|
name,
|
|
6425
6219
|
description,
|
|
6426
|
-
matchRules,
|
|
6427
6220
|
segments: validation.segments,
|
|
6428
|
-
repeat_times: repeatTimes
|
|
6429
|
-
cronSchedule: cronSchedule || DEFAULT_CRON_SCHEDULE
|
|
6221
|
+
repeat_times: repeatTimes
|
|
6430
6222
|
});
|
|
6431
6223
|
logger.info(`Light rule created: ${name}`);
|
|
6432
|
-
respond(true, { ok: true, name,
|
|
6224
|
+
respond(true, { ok: true, name, rule: result.meta });
|
|
6433
6225
|
} catch (err2) {
|
|
6434
6226
|
if (err2 instanceof LightRuleError) {
|
|
6435
6227
|
respond(false, null, { code: err2.code, message: err2.message });
|
|
@@ -6440,15 +6232,7 @@ function registerLightRulesGateway(api, registry, logger, rememberBroadcast) {
|
|
|
6440
6232
|
}
|
|
6441
6233
|
});
|
|
6442
6234
|
registerGatewayMethodWithBroadcastCapture("lightrules.update", async ({ params, respond }) => {
|
|
6443
|
-
const {
|
|
6444
|
-
description,
|
|
6445
|
-
matchRules,
|
|
6446
|
-
segments,
|
|
6447
|
-
repeat,
|
|
6448
|
-
repeat_times,
|
|
6449
|
-
cronSchedule,
|
|
6450
|
-
enabled
|
|
6451
|
-
} = params;
|
|
6235
|
+
const { description, segments, repeat, repeat_times, enabled } = params;
|
|
6452
6236
|
const name = resolveRuleIdentifier(params);
|
|
6453
6237
|
if (!name) {
|
|
6454
6238
|
respond(false, null, {
|
|
@@ -6483,10 +6267,8 @@ function registerLightRulesGateway(api, registry, logger, rememberBroadcast) {
|
|
|
6483
6267
|
const result = await registry.update({
|
|
6484
6268
|
name,
|
|
6485
6269
|
description,
|
|
6486
|
-
matchRules,
|
|
6487
6270
|
segments: validatedSegments,
|
|
6488
6271
|
repeat_times: repeatTimes,
|
|
6489
|
-
cronSchedule,
|
|
6490
6272
|
enabled
|
|
6491
6273
|
});
|
|
6492
6274
|
logger.info(`Light rule updated: ${name}`);
|
|
@@ -6495,8 +6277,7 @@ function registerLightRulesGateway(api, registry, logger, rememberBroadcast) {
|
|
|
6495
6277
|
id: result.meta.name,
|
|
6496
6278
|
name: result.meta.name,
|
|
6497
6279
|
updated: true,
|
|
6498
|
-
rule: result.meta
|
|
6499
|
-
cronHint: result.cronHint
|
|
6280
|
+
rule: result.meta
|
|
6500
6281
|
});
|
|
6501
6282
|
} catch (err2) {
|
|
6502
6283
|
if (err2 instanceof LightRuleError) {
|
|
@@ -6523,8 +6304,7 @@ function registerLightRulesGateway(api, registry, logger, rememberBroadcast) {
|
|
|
6523
6304
|
ok: true,
|
|
6524
6305
|
id: result.name,
|
|
6525
6306
|
name: result.name,
|
|
6526
|
-
deleted: true
|
|
6527
|
-
cronHint: result.cronHint
|
|
6307
|
+
deleted: true
|
|
6528
6308
|
});
|
|
6529
6309
|
} catch (err2) {
|
|
6530
6310
|
if (err2 instanceof LightRuleError) {
|
|
@@ -6960,7 +6740,7 @@ function registerLightRulesTools(api, registry, logger) {
|
|
|
6960
6740
|
registerToolWithAliases(api, {
|
|
6961
6741
|
name: "lightrules.create",
|
|
6962
6742
|
label: "Create Light Rule",
|
|
6963
|
-
description: '\u521B\u5EFA\u4E00\u6761\u706F\u6548\u89C4\u5219\uFF0C\u6307\u5B9A\u540D\u79F0\u3001\u81EA\u7136\u8BED\u8A00\u89E6\u53D1\u63CF\u8FF0\u548C\u706F\u6548\u53C2\u6570\u3002\u5F53\u7528\u6237\u8BF4"\
|
|
6743
|
+
description: '\u521B\u5EFA\u4E00\u6761\u6301\u4E45\u706F\u6548\u89C4\u5219\uFF0C\u6307\u5B9A\u540D\u79F0\u3001\u81EA\u7136\u8BED\u8A00\u89E6\u53D1\u63CF\u8FF0\u548C\u706F\u6548\u53C2\u6570\u3002\u89C4\u5219\u4F1A\u4FDD\u5B58\u5230 tasks/<name>/meta.json\uFF0C\u5E76\u7531\u901A\u77E5\u5230\u8FBE\u540E\u7684\u4E8B\u4EF6\u9A71\u52A8\u8BC4\u4F30\u89E6\u53D1\u3002\u5F53\u7528\u6237\u8BF4"\u6536\u5230\u67D0\u7C7B\u901A\u77E5/\u6D88\u606F\u65F6\u4EAE\u706F/\u95EA\u706F/\u53D8\u706F\u6548"\u3001"\u5F53\u8001\u677F\u53D1\u6D88\u606F\u4EAE\u7EA2\u706F"\u3001"\u65B0\u589E/\u521B\u5EFA\u706F\u6548\u89C4\u5219"\u7B49\u65F6\u8C03\u7528\u3002\u4E0D\u8981\u76F4\u63A5\u8C03\u7528 light_control \u4EE3\u66FF\u521B\u5EFA\u89C4\u5219\uFF1Blight_control \u53EA\u4F1A\u7ACB\u5373\u4EAE\u4E00\u6B21\u706F\uFF0C\u4E0D\u4F1A\u51FA\u73B0\u5728\u706F\u6548\u89C4\u5219\u67E5\u8BE2\u4E2D\u3002',
|
|
6964
6744
|
parameters: {
|
|
6965
6745
|
type: "object",
|
|
6966
6746
|
required: ["name", "description", "segments"],
|
|
@@ -6997,13 +6777,11 @@ function registerLightRulesTools(api, registry, logger) {
|
|
|
6997
6777
|
const result = await registry.create({
|
|
6998
6778
|
name,
|
|
6999
6779
|
description,
|
|
7000
|
-
matchRules: {},
|
|
7001
6780
|
segments: validation.segments,
|
|
7002
|
-
repeat_times: repeatTimes
|
|
7003
|
-
cronSchedule: "*/5 * * * *"
|
|
6781
|
+
repeat_times: repeatTimes
|
|
7004
6782
|
});
|
|
7005
6783
|
logger.info(`lightrules.create tool: created ${name}`);
|
|
7006
|
-
return ok({ ok: true, name,
|
|
6784
|
+
return ok({ ok: true, name, rule: result.meta });
|
|
7007
6785
|
} catch (e) {
|
|
7008
6786
|
if (e instanceof LightRuleError) return err(e.code, e.message);
|
|
7009
6787
|
logger.warn(`lightrules.create tool failed: ${e?.message}`);
|
|
@@ -7059,8 +6837,7 @@ function registerLightRulesTools(api, registry, logger) {
|
|
|
7059
6837
|
ok: true,
|
|
7060
6838
|
name: result.meta.name,
|
|
7061
6839
|
updated: true,
|
|
7062
|
-
rule: result.meta
|
|
7063
|
-
cronHint: result.cronHint
|
|
6840
|
+
rule: result.meta
|
|
7064
6841
|
});
|
|
7065
6842
|
} catch (e) {
|
|
7066
6843
|
if (e instanceof LightRuleError) return err(e.code, e.message);
|
|
@@ -7088,7 +6865,7 @@ function registerLightRulesTools(api, registry, logger) {
|
|
|
7088
6865
|
try {
|
|
7089
6866
|
const result = await registry.delete(name);
|
|
7090
6867
|
logger.info(`lightrules.delete tool: deleted ${name}`);
|
|
7091
|
-
return ok({ ok: true, name: result.name, deleted: true
|
|
6868
|
+
return ok({ ok: true, name: result.name, deleted: true });
|
|
7092
6869
|
} catch (e) {
|
|
7093
6870
|
if (e instanceof LightRuleError) return err(e.code, e.message);
|
|
7094
6871
|
logger.warn(`lightrules.delete tool failed: ${e?.message}`);
|
|
@@ -7273,15 +7050,32 @@ function migrateTaskDir(taskDir, logger) {
|
|
|
7273
7050
|
}
|
|
7274
7051
|
if (meta.type !== "light-rule") return;
|
|
7275
7052
|
const name = typeof meta.name === "string" ? meta.name : taskDir;
|
|
7276
|
-
|
|
7053
|
+
cleanupLegacyMetaFields(meta, name, metaPath, logger);
|
|
7277
7054
|
replaceFetchPy(taskDir, name, logger);
|
|
7278
7055
|
for (const filename of ["README.md", "checkpoint.json"]) {
|
|
7279
7056
|
removeFile((0, import_node_path7.join)(taskDir, filename), name, filename, logger);
|
|
7280
7057
|
}
|
|
7281
7058
|
}
|
|
7282
|
-
function
|
|
7059
|
+
function cleanupLegacyMetaFields(meta, name, metaPath, logger) {
|
|
7060
|
+
const cleaned = [];
|
|
7061
|
+
if (mergeMatchRulesIntoDescription(meta)) cleaned.push("matchRules");
|
|
7062
|
+
if (meta.cronSchedule !== void 0) {
|
|
7063
|
+
delete meta.cronSchedule;
|
|
7064
|
+
cleaned.push("cronSchedule");
|
|
7065
|
+
}
|
|
7066
|
+
if (cleaned.length === 0) return;
|
|
7067
|
+
try {
|
|
7068
|
+
(0, import_node_fs8.writeFileSync)(metaPath, JSON.stringify(meta, null, 2), "utf-8");
|
|
7069
|
+
logger.info(
|
|
7070
|
+
`migration: cleaned deprecated field(s) [${cleaned.join(", ")}] in meta.json for light rule: ${name}`
|
|
7071
|
+
);
|
|
7072
|
+
} catch (err2) {
|
|
7073
|
+
logger.warn(`migration: failed to update meta.json for ${name}: ${err2?.message}`);
|
|
7074
|
+
}
|
|
7075
|
+
}
|
|
7076
|
+
function mergeMatchRulesIntoDescription(meta) {
|
|
7283
7077
|
const matchRules = meta.matchRules;
|
|
7284
|
-
if (!matchRules || typeof matchRules !== "object") return;
|
|
7078
|
+
if (!matchRules || typeof matchRules !== "object") return false;
|
|
7285
7079
|
const rules = matchRules;
|
|
7286
7080
|
const parts = [];
|
|
7287
7081
|
if (rules.appName) parts.push(`app=${rules.appName}`);
|
|
@@ -7296,12 +7090,7 @@ function mergeMatchRulesIntoDescription(meta, name, metaPath, logger) {
|
|
|
7296
7090
|
meta.description = existing ? `${existing}\u3002\u5339\u914D\u89C4\u5219\uFF1A${parts.join("\uFF0C")}` : `\u5339\u914D\u89C4\u5219\uFF1A${parts.join("\uFF0C")}`;
|
|
7297
7091
|
}
|
|
7298
7092
|
delete meta.matchRules;
|
|
7299
|
-
|
|
7300
|
-
(0, import_node_fs8.writeFileSync)(metaPath, JSON.stringify(meta, null, 2), "utf-8");
|
|
7301
|
-
logger.info(`migration: merged matchRules into description for light rule: ${name}`);
|
|
7302
|
-
} catch (err2) {
|
|
7303
|
-
logger.warn(`migration: failed to update meta.json for ${name}: ${err2?.message}`);
|
|
7304
|
-
}
|
|
7093
|
+
return true;
|
|
7305
7094
|
}
|
|
7306
7095
|
function replaceFetchPy(taskDir, name, logger) {
|
|
7307
7096
|
const fetchPyPath = (0, import_node_path7.join)(taskDir, "fetch.py");
|
|
@@ -8153,6 +7942,87 @@ function registerNtfSync(ntf, ctx) {
|
|
|
8153
7942
|
// src/cli/ntf-monitor.ts
|
|
8154
7943
|
var import_node_fs12 = require("fs");
|
|
8155
7944
|
var import_node_path11 = require("path");
|
|
7945
|
+
|
|
7946
|
+
// src/monitor/fetch-gen.ts
|
|
7947
|
+
function generateFetchPy(name, matchRules) {
|
|
7948
|
+
const appName = typeof matchRules.appName === "string" ? matchRules.appName : "";
|
|
7949
|
+
const senderKeywords = stringArray(matchRules.senderKeywords);
|
|
7950
|
+
const contentKeywords = stringArray(matchRules.contentKeywords);
|
|
7951
|
+
return `#!/usr/bin/env python3
|
|
7952
|
+
"""Auto-generated fetch script for monitor task: ${name}"""
|
|
7953
|
+
import json, sys, os
|
|
7954
|
+
from pathlib import Path
|
|
7955
|
+
|
|
7956
|
+
def matches(notification: dict) -> bool:
|
|
7957
|
+
app = str(notification.get("appName", "") or "")
|
|
7958
|
+
title = str(notification.get("title", "") or "")
|
|
7959
|
+
content = str(notification.get("content", "") or "")
|
|
7960
|
+
body = str(notification.get("body", "") or "")
|
|
7961
|
+
|
|
7962
|
+
app_name = ${pyLiteral(appName)}
|
|
7963
|
+
if app_name and app != app_name:
|
|
7964
|
+
return False
|
|
7965
|
+
|
|
7966
|
+
sender_keywords = ${pyLiteral(senderKeywords)}
|
|
7967
|
+
sender_haystack = f"{title}\\n{content}\\n{body}"
|
|
7968
|
+
if sender_keywords and not any(keyword in sender_haystack for keyword in sender_keywords):
|
|
7969
|
+
return False
|
|
7970
|
+
|
|
7971
|
+
content_keywords = ${pyLiteral(contentKeywords)}
|
|
7972
|
+
content_haystack = f"{content}\\n{body}"
|
|
7973
|
+
if content_keywords and not any(keyword in content_haystack for keyword in content_keywords):
|
|
7974
|
+
return False
|
|
7975
|
+
|
|
7976
|
+
return True
|
|
7977
|
+
|
|
7978
|
+
def main():
|
|
7979
|
+
import argparse
|
|
7980
|
+
parser = argparse.ArgumentParser()
|
|
7981
|
+
parser.add_argument("--notifications-dir", required=True)
|
|
7982
|
+
args = parser.parse_args()
|
|
7983
|
+
|
|
7984
|
+
checkpoint_path = Path(__file__).parent / "checkpoint.json"
|
|
7985
|
+
checkpoint = {}
|
|
7986
|
+
if checkpoint_path.exists():
|
|
7987
|
+
checkpoint = json.loads(checkpoint_path.read_text())
|
|
7988
|
+
|
|
7989
|
+
ntf_dir = Path(args.notifications_dir)
|
|
7990
|
+
matched = []
|
|
7991
|
+
new_checkpoint = dict(checkpoint)
|
|
7992
|
+
|
|
7993
|
+
for f in sorted(ntf_dir.glob("*.json")):
|
|
7994
|
+
date_key = f.stem
|
|
7995
|
+
items = json.loads(f.read_text())
|
|
7996
|
+
last_idx = checkpoint.get(date_key, {}).get("lastIndex", -1)
|
|
7997
|
+
for i, item in enumerate(items):
|
|
7998
|
+
if i <= last_idx:
|
|
7999
|
+
continue
|
|
8000
|
+
if matches(item):
|
|
8001
|
+
matched.append(item)
|
|
8002
|
+
new_checkpoint[date_key] = {"lastIndex": len(items) - 1}
|
|
8003
|
+
|
|
8004
|
+
checkpoint_path.write_text(json.dumps(new_checkpoint, indent=2))
|
|
8005
|
+
|
|
8006
|
+
if not matched:
|
|
8007
|
+
print("NO_MATCH")
|
|
8008
|
+
return
|
|
8009
|
+
|
|
8010
|
+
for m in matched:
|
|
8011
|
+
print(json.dumps(m, ensure_ascii=False))
|
|
8012
|
+
|
|
8013
|
+
if __name__ == "__main__":
|
|
8014
|
+
main()
|
|
8015
|
+
`;
|
|
8016
|
+
}
|
|
8017
|
+
function stringArray(value) {
|
|
8018
|
+
if (!Array.isArray(value)) return [];
|
|
8019
|
+
return value.filter((item) => typeof item === "string" && item.length > 0);
|
|
8020
|
+
}
|
|
8021
|
+
function pyLiteral(value) {
|
|
8022
|
+
return JSON.stringify(value);
|
|
8023
|
+
}
|
|
8024
|
+
|
|
8025
|
+
// src/cli/ntf-monitor.ts
|
|
8156
8026
|
function tasksDir2(ctx) {
|
|
8157
8027
|
const base = ctx.workspaceDir || ctx.stateDir;
|
|
8158
8028
|
if (!base) throw new Error("workspaceDir and stateDir both unavailable");
|
|
@@ -9538,7 +9408,7 @@ function registerLightControlTool(api, logger) {
|
|
|
9538
9408
|
api.registerTool({
|
|
9539
9409
|
name: "light_control",
|
|
9540
9410
|
label: "Light Control",
|
|
9541
|
-
description: '\u63A7\u5236\u786C\u4EF6\u706F\u6548\uFF0C\u652F\u6301 1\u201312 \u6BB5\u987A\u5E8F\u706F\u6548\uFF0C\u6BCF\u6BB5\u72EC\u7ACB\u53C2\u6570\uFF086 \u79CD\u6A21\u5F0F\uFF1A\u6CE2\u6D6A/\u547C\u5438/\u9891\u95EA/\u5E38\u4EAE/\u6D41\u5149/\u9010\u7EC4\u50CF\u7D20\u5E27\uFF09\u3002Tool \u5185\u90E8\u81EA\u52A8\u91CF\u5316\u4E3A\u5D4C\u5165\u5F0F\u534F\u8BAE\u5B9A\u4E49\u7684\u79BB\u6563\u6863\u4F4D\uFF0C\u5E76\u6309\u6A21\u5F0F\u7CBE\u7B80\u4E3A\u53D8\u957F ANCS \u63A7\u5236\u5E8F\u5217\uFF0C\u901A\u8FC7 HTTP \u63A5\u53E3\u4E0B\u53D1\u706F\u6548\u6307\u4EE4\u3002\u5F53\u7528\u6237\u8BF4"\u5F00\u706F"\u3001"\u6362\u4E2A\u706F\u6548"\u3001"\u628A\u706F\u8C03\u6210\u7EA2\u8272"\u3001"\u8425\u9020\u6C1B\u56F4"\u7B49\u4E0E\u706F\u5149\u63A7\u5236\u76F8\u5173\u7684\u8868\u8FBE\u65F6\u8C03\u7528\u3002',
|
|
9411
|
+
description: '\u7ACB\u5373\u63A7\u5236\u786C\u4EF6\u706F\u6548\uFF08\u4E00\u6B21\u6027\u6267\u884C\uFF0C\u4E0D\u4F1A\u521B\u5EFA\u6216\u4FDD\u5B58\u901A\u77E5\u89E6\u53D1\u89C4\u5219\uFF09\uFF0C\u652F\u6301 1\u201312 \u6BB5\u987A\u5E8F\u706F\u6548\uFF0C\u6BCF\u6BB5\u72EC\u7ACB\u53C2\u6570\uFF086 \u79CD\u6A21\u5F0F\uFF1A\u6CE2\u6D6A/\u547C\u5438/\u9891\u95EA/\u5E38\u4EAE/\u6D41\u5149/\u9010\u7EC4\u50CF\u7D20\u5E27\uFF09\u3002Tool \u5185\u90E8\u81EA\u52A8\u91CF\u5316\u4E3A\u5D4C\u5165\u5F0F\u534F\u8BAE\u5B9A\u4E49\u7684\u79BB\u6563\u6863\u4F4D\uFF0C\u5E76\u6309\u6A21\u5F0F\u7CBE\u7B80\u4E3A\u53D8\u957F ANCS \u63A7\u5236\u5E8F\u5217\uFF0C\u901A\u8FC7 HTTP \u63A5\u53E3\u4E0B\u53D1\u706F\u6548\u6307\u4EE4\u3002\u5F53\u7528\u6237\u8BF4"\u5F00\u706F"\u3001"\u6362\u4E2A\u706F\u6548"\u3001"\u628A\u706F\u8C03\u6210\u7EA2\u8272"\u3001"\u8425\u9020\u6C1B\u56F4"\u3001"\u6D4B\u8BD5/\u9884\u89C8\u706F\u6548"\u7B49\u4E0E\u5F53\u524D\u5373\u65F6\u706F\u5149\u63A7\u5236\u76F8\u5173\u7684\u8868\u8FBE\u65F6\u8C03\u7528\u3002\u5982\u679C\u7528\u6237\u8BF4"\u6536\u5230\u67D0\u7C7B\u901A\u77E5/\u6D88\u606F\u65F6\u4EAE\u706F/\u95EA\u706F/\u53D8\u706F\u6548"\uFF0C\u90A3\u662F\u6301\u4E45\u706F\u6548\u89C4\u5219\uFF0C\u6539\u7528 lightrules.create \u6216 lightrules.update\u3002',
|
|
9542
9412
|
parameters: lightControlParameters,
|
|
9543
9413
|
async execute(_toolCallId, params) {
|
|
9544
9414
|
let apiKey;
|
|
@@ -13205,6 +13075,12 @@ function isPluginCliInvocation(argv = process.argv) {
|
|
|
13205
13075
|
}
|
|
13206
13076
|
|
|
13207
13077
|
// src/index.ts
|
|
13078
|
+
var LIGHT_RULE_PROMPT_GUIDANCE = [
|
|
13079
|
+
"\u706F\u6548\u89C4\u5219\u8DEF\u7531\u63D0\u793A\uFF1A",
|
|
13080
|
+
"- \u5F53\u7528\u6237\u8868\u8FBE\u201C\u6536\u5230/\u5F53/\u5982\u679C/\u6709\u67D0\u7C7B\u901A\u77E5\u6216\u6D88\u606F\u65F6\uFF0C\u4EAE\u706F/\u95EA\u706F/\u53D8\u6210\u67D0\u79CD\u706F\u6548\u201D\u65F6\uFF0C\u8FD9\u662F\u6301\u4E45\u706F\u6548\u89C4\u5219\u8BF7\u6C42\uFF0C\u5FC5\u987B\u8C03\u7528 lightrules.create \u6216 lightrules.update\u3002",
|
|
13081
|
+
"- \u4E0D\u8981\u4E3A\u8FD9\u7C7B\u901A\u77E5\u89E6\u53D1\u89C4\u5219\u76F4\u63A5\u8C03\u7528 light_control\uFF1Blight_control \u53EA\u7528\u4E8E\u5F53\u524D\u7ACB\u5373\u6267\u884C\u7684\u4E00\u6B21\u6027\u706F\u6548\u3001\u6D4B\u8BD5\u6216\u9884\u89C8\u3002",
|
|
13082
|
+
"- \u4E0D\u8981\u624B\u5199\u6216\u7F16\u8F91 tasks/*/meta.json\uFF1B\u706F\u6548\u89C4\u5219\u7684\u521B\u5EFA\u3001\u4FEE\u6539\u3001\u5220\u9664\u548C\u67E5\u8BE2\u90FD\u8D70 lightrules.* \u5DE5\u5177\u3002"
|
|
13083
|
+
].join("\n");
|
|
13208
13084
|
var index_default = {
|
|
13209
13085
|
id: "phone-notifications",
|
|
13210
13086
|
name: "Phone Notifications & Light Control",
|
|
@@ -13232,6 +13108,9 @@ var index_default = {
|
|
|
13232
13108
|
);
|
|
13233
13109
|
return;
|
|
13234
13110
|
}
|
|
13111
|
+
api.on("before_prompt_build", () => ({
|
|
13112
|
+
appendSystemContext: LIGHT_RULE_PROMPT_GUIDANCE
|
|
13113
|
+
}));
|
|
13235
13114
|
function cacheBroadcast(broadcast) {
|
|
13236
13115
|
if (!broadcast) {
|
|
13237
13116
|
return;
|