@yoooclaw/phone-notifications 1.11.14 → 1.11.16
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 +1 -1
- package/dist/index.cjs +146 -51
- package/dist/index.cjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -152,7 +152,7 @@ bash install.sh --tgz-url ./yoooclaw-phone-notifications-1.2.3.tgz
|
|
|
152
152
|
5. 写入 `<configPath>` 配置:
|
|
153
153
|
- `plugins.entries` — 启用插件,合并用户配置
|
|
154
154
|
- `plugins.installs` — 记录安装来源和版本
|
|
155
|
-
- `tools.
|
|
155
|
+
- `tools.allow` / `tools.alsoAllow` 与 `agents.main.tools.*` — 自动放行 `light_control` 与 `lightrules_*` 工具
|
|
156
156
|
- 若宿主已启用 `plugins.allow` 白名单,会自动补入 `phone-notifications`,确保插件能被宿主加载
|
|
157
157
|
- 清理该插件旧的 `plugins.load.paths` / 旧安装记录,避免继续命中之前通过 `openclaw plugins install` 或 `--link` 保留的副本
|
|
158
158
|
6. 如传入 `--api-key` / `--token`,写入 `<stateDir>/credentials.json`
|
package/dist/index.cjs
CHANGED
|
@@ -5574,7 +5574,7 @@ function readBuildInjectedVersion() {
|
|
|
5574
5574
|
if (false) {
|
|
5575
5575
|
return void 0;
|
|
5576
5576
|
}
|
|
5577
|
-
const version = "1.11.
|
|
5577
|
+
const version = "1.11.16".trim();
|
|
5578
5578
|
return version || void 0;
|
|
5579
5579
|
}
|
|
5580
5580
|
function readPluginVersionFromPackageJson() {
|
|
@@ -9243,6 +9243,39 @@ function ensureArray(obj, key) {
|
|
|
9243
9243
|
obj[key] = next;
|
|
9244
9244
|
return next;
|
|
9245
9245
|
}
|
|
9246
|
+
function hasOwnProperty(obj, key) {
|
|
9247
|
+
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
9248
|
+
}
|
|
9249
|
+
function appendUniqueValues(target, values) {
|
|
9250
|
+
let changed = false;
|
|
9251
|
+
for (const value of values) {
|
|
9252
|
+
if (!target.includes(value)) {
|
|
9253
|
+
target.push(value);
|
|
9254
|
+
changed = true;
|
|
9255
|
+
}
|
|
9256
|
+
}
|
|
9257
|
+
return changed;
|
|
9258
|
+
}
|
|
9259
|
+
function upsertToolsForPolicy(policy, tools) {
|
|
9260
|
+
if (Array.isArray(policy.allow)) {
|
|
9261
|
+
let changed = false;
|
|
9262
|
+
if (Array.isArray(policy.alsoAllow)) {
|
|
9263
|
+
changed = appendUniqueValues(
|
|
9264
|
+
policy.allow,
|
|
9265
|
+
policy.alsoAllow.filter((value) => typeof value === "string")
|
|
9266
|
+
);
|
|
9267
|
+
}
|
|
9268
|
+
changed = appendUniqueValues(policy.allow, tools) || changed;
|
|
9269
|
+
if (hasOwnProperty(policy, "alsoAllow")) {
|
|
9270
|
+
delete policy.alsoAllow;
|
|
9271
|
+
changed = true;
|
|
9272
|
+
}
|
|
9273
|
+
return changed;
|
|
9274
|
+
}
|
|
9275
|
+
if (hasOwnProperty(policy, "allow")) return false;
|
|
9276
|
+
const alsoAllow = ensureArray(policy, "alsoAllow");
|
|
9277
|
+
return appendUniqueValues(alsoAllow, tools);
|
|
9278
|
+
}
|
|
9246
9279
|
function resolveConfigPath2() {
|
|
9247
9280
|
const fromEnv = process.env.OPENCLAW_CONFIG_PATH?.trim();
|
|
9248
9281
|
if (fromEnv) return fromEnv;
|
|
@@ -9251,14 +9284,7 @@ function resolveConfigPath2() {
|
|
|
9251
9284
|
var LIGHT_TOOLS = ["light_control", ...LIGHT_RULE_TOOL_NAME_LIST];
|
|
9252
9285
|
function upsertLightControlAlsoAllow(cfg) {
|
|
9253
9286
|
if (!isObject(cfg.tools)) cfg.tools = {};
|
|
9254
|
-
const
|
|
9255
|
-
let globalChanged = false;
|
|
9256
|
-
for (const tool of LIGHT_TOOLS) {
|
|
9257
|
-
if (!toolsAlsoAllow.includes(tool)) {
|
|
9258
|
-
toolsAlsoAllow.push(tool);
|
|
9259
|
-
globalChanged = true;
|
|
9260
|
-
}
|
|
9261
|
-
}
|
|
9287
|
+
const globalChanged = upsertToolsForPolicy(cfg.tools, LIGHT_TOOLS);
|
|
9262
9288
|
if (!isObject(cfg.agents)) cfg.agents = {};
|
|
9263
9289
|
const agents = cfg.agents;
|
|
9264
9290
|
const list = ensureArray(agents, "list");
|
|
@@ -9270,18 +9296,11 @@ function upsertLightControlAlsoAllow(cfg) {
|
|
|
9270
9296
|
list.push(mainAgent);
|
|
9271
9297
|
}
|
|
9272
9298
|
if (!isObject(mainAgent.tools)) mainAgent.tools = {};
|
|
9273
|
-
const
|
|
9274
|
-
let mainAgentChanged = false;
|
|
9275
|
-
for (const tool of LIGHT_TOOLS) {
|
|
9276
|
-
if (!mainAlsoAllow.includes(tool)) {
|
|
9277
|
-
mainAlsoAllow.push(tool);
|
|
9278
|
-
mainAgentChanged = true;
|
|
9279
|
-
}
|
|
9280
|
-
}
|
|
9299
|
+
const mainAgentChanged = upsertToolsForPolicy(mainAgent.tools, LIGHT_TOOLS);
|
|
9281
9300
|
return { globalChanged, mainAgentChanged };
|
|
9282
9301
|
}
|
|
9283
9302
|
function registerLightSetupTools(light) {
|
|
9284
|
-
light.command("setup").description("\u81EA\u52A8\u653E\u884C light_control\uFF08\
|
|
9303
|
+
light.command("setup").description("\u81EA\u52A8\u653E\u884C light_control\uFF08\u517C\u5BB9 tools.allow / tools.alsoAllow\uFF09").action(() => {
|
|
9285
9304
|
const configPath = resolveConfigPath2();
|
|
9286
9305
|
if (!(0, import_node_fs12.existsSync)(configPath)) {
|
|
9287
9306
|
exitError("CONFIG_NOT_FOUND", `\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6: ${configPath}`);
|
|
@@ -12009,56 +12028,123 @@ init_asr();
|
|
|
12009
12028
|
// src/recording/account-oss.ts
|
|
12010
12029
|
init_credentials();
|
|
12011
12030
|
init_env();
|
|
12012
|
-
|
|
12013
|
-
|
|
12014
|
-
|
|
12015
|
-
|
|
12031
|
+
var DEFAULT_DELETE_MAX_ATTEMPTS = 3;
|
|
12032
|
+
var DEFAULT_DELETE_BACKOFF_MS = 500;
|
|
12033
|
+
function getDeleteMaxAttempts() {
|
|
12034
|
+
const raw = process.env.OPENCLAW_OSS_DELETE_MAX_ATTEMPTS;
|
|
12035
|
+
if (raw) {
|
|
12036
|
+
const parsed = Number(raw);
|
|
12037
|
+
if (Number.isFinite(parsed) && parsed >= 1) return Math.floor(parsed);
|
|
12016
12038
|
}
|
|
12017
|
-
|
|
12018
|
-
|
|
12019
|
-
|
|
12039
|
+
return DEFAULT_DELETE_MAX_ATTEMPTS;
|
|
12040
|
+
}
|
|
12041
|
+
function getDeleteBackoffMs() {
|
|
12042
|
+
const raw = process.env.OPENCLAW_OSS_DELETE_BACKOFF_MS;
|
|
12043
|
+
if (raw) {
|
|
12044
|
+
const parsed = Number(raw);
|
|
12045
|
+
if (Number.isFinite(parsed) && parsed >= 0) return parsed;
|
|
12020
12046
|
}
|
|
12021
|
-
|
|
12022
|
-
|
|
12023
|
-
|
|
12024
|
-
|
|
12025
|
-
|
|
12026
|
-
|
|
12047
|
+
return DEFAULT_DELETE_BACKOFF_MS;
|
|
12048
|
+
}
|
|
12049
|
+
function sleep3(ms) {
|
|
12050
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
12051
|
+
}
|
|
12052
|
+
function isRetryableStatus(status) {
|
|
12053
|
+
return status === 429 || status >= 500;
|
|
12054
|
+
}
|
|
12055
|
+
function parseBody(text) {
|
|
12056
|
+
if (!text) return void 0;
|
|
12057
|
+
try {
|
|
12058
|
+
return JSON.parse(text);
|
|
12059
|
+
} catch {
|
|
12060
|
+
return "invalid-json";
|
|
12061
|
+
}
|
|
12062
|
+
}
|
|
12063
|
+
function extractCode(payload) {
|
|
12064
|
+
if (!payload) return void 0;
|
|
12065
|
+
if (typeof payload.code === "number") return String(payload.code);
|
|
12066
|
+
return payload.code?.trim?.();
|
|
12067
|
+
}
|
|
12068
|
+
async function attemptDelete(endpoint, headerKey, logger) {
|
|
12027
12069
|
let res;
|
|
12028
12070
|
try {
|
|
12029
12071
|
res = await fetch(endpoint, {
|
|
12030
12072
|
method: "POST",
|
|
12031
|
-
headers: {
|
|
12032
|
-
"X-Api-Key-Id": headerKey
|
|
12033
|
-
}
|
|
12073
|
+
headers: { "X-Api-Key-Id": headerKey }
|
|
12034
12074
|
});
|
|
12035
12075
|
} catch (err2) {
|
|
12036
|
-
|
|
12037
|
-
logger.warn(`[account-oss-delete] \u7F51\u7EDC\u5F02\u5E38: ${error}`);
|
|
12038
|
-
return { ok: false, error };
|
|
12076
|
+
return { kind: "retryable", error: err2?.message ?? String(err2) };
|
|
12039
12077
|
}
|
|
12040
12078
|
const text = await res.text();
|
|
12041
12079
|
if (!res.ok) {
|
|
12080
|
+
const error = `HTTP ${res.status} ${text.slice(0, 200)}`;
|
|
12081
|
+
if (isRetryableStatus(res.status)) {
|
|
12082
|
+
return { kind: "retryable", error };
|
|
12083
|
+
}
|
|
12042
12084
|
logger.warn(
|
|
12043
12085
|
`[account-oss-delete] HTTP \u9519\u8BEF: status=${res.status}, body=${text.slice(0, 300)}`
|
|
12044
12086
|
);
|
|
12045
|
-
return {
|
|
12087
|
+
return { kind: "permanent", error };
|
|
12046
12088
|
}
|
|
12047
|
-
|
|
12048
|
-
|
|
12049
|
-
payload = text ? JSON.parse(text) : void 0;
|
|
12050
|
-
} catch {
|
|
12089
|
+
const payload = parseBody(text);
|
|
12090
|
+
if (payload === "invalid-json") {
|
|
12051
12091
|
logger.warn(`[account-oss-delete] \u54CD\u5E94\u975E JSON: body=${text.slice(0, 300)}`);
|
|
12052
|
-
return {
|
|
12092
|
+
return { kind: "permanent", error: "response is not JSON" };
|
|
12053
12093
|
}
|
|
12054
|
-
const code =
|
|
12094
|
+
const code = extractCode(payload);
|
|
12055
12095
|
if (code !== "000000") {
|
|
12056
12096
|
const msg = payload?.msg?.trim?.() || text.slice(0, 200);
|
|
12057
12097
|
logger.warn(`[account-oss-delete] \u4E1A\u52A1\u5931\u8D25: code=${code ?? "n/a"}, msg=${msg}`);
|
|
12058
|
-
return {
|
|
12098
|
+
return { kind: "permanent", error: `${code ?? "unknown"} ${msg}`.trim() };
|
|
12099
|
+
}
|
|
12100
|
+
return { kind: "ok" };
|
|
12101
|
+
}
|
|
12102
|
+
async function deleteAccountOssFile(fileUrl, logger, options) {
|
|
12103
|
+
const trimmed = fileUrl?.trim();
|
|
12104
|
+
if (!trimmed) {
|
|
12105
|
+
return { ok: false, error: "fileUrl is empty" };
|
|
12106
|
+
}
|
|
12107
|
+
const apiKey = loadApiKey();
|
|
12108
|
+
if (!apiKey) {
|
|
12109
|
+
return { ok: false, error: "API Key \u672A\u8BBE\u7F6E\uFF0C\u8DF3\u8FC7 OSS \u6587\u4EF6\u5220\u9664" };
|
|
12110
|
+
}
|
|
12111
|
+
const baseEndpoint = getEnvUrls().accountFileDeleteUrl;
|
|
12112
|
+
const headerKey = apiKey.startsWith("Bearer ") ? apiKey.slice("Bearer ".length) : apiKey;
|
|
12113
|
+
const url = new URL(baseEndpoint);
|
|
12114
|
+
url.searchParams.set("fileUrl", trimmed);
|
|
12115
|
+
const endpoint = url.toString();
|
|
12116
|
+
const maxAttempts = Math.max(
|
|
12117
|
+
1,
|
|
12118
|
+
Math.floor(options?.maxAttempts ?? getDeleteMaxAttempts())
|
|
12119
|
+
);
|
|
12120
|
+
const baseBackoff = Math.max(0, options?.backoffMs ?? getDeleteBackoffMs());
|
|
12121
|
+
logger.info(
|
|
12122
|
+
`[account-oss-delete] \u63D0\u4EA4 OSS \u6587\u4EF6\u5220\u9664: endpoint=${endpoint}, maxAttempts=${maxAttempts}`
|
|
12123
|
+
);
|
|
12124
|
+
let lastError = "unknown error";
|
|
12125
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
12126
|
+
const outcome = await attemptDelete(endpoint, headerKey, logger);
|
|
12127
|
+
if (outcome.kind === "ok") {
|
|
12128
|
+
logger.info(`[account-oss-delete] OSS \u6587\u4EF6\u5DF2\u5220\u9664: fileUrl=${trimmed}`);
|
|
12129
|
+
return { ok: true };
|
|
12130
|
+
}
|
|
12131
|
+
if (outcome.kind === "permanent") {
|
|
12132
|
+
return { ok: false, error: outcome.error };
|
|
12133
|
+
}
|
|
12134
|
+
lastError = outcome.error;
|
|
12135
|
+
if (attempt < maxAttempts) {
|
|
12136
|
+
const delay = baseBackoff * Math.pow(2, attempt - 1);
|
|
12137
|
+
logger.warn(
|
|
12138
|
+
`[account-oss-delete] \u4E34\u65F6\u5931\u8D25 (attempt ${attempt}/${maxAttempts}): ${outcome.error}, ${delay}ms \u540E\u91CD\u8BD5`
|
|
12139
|
+
);
|
|
12140
|
+
await sleep3(delay);
|
|
12141
|
+
} else {
|
|
12142
|
+
logger.warn(
|
|
12143
|
+
`[account-oss-delete] \u4E34\u65F6\u5931\u8D25 (attempt ${attempt}/${maxAttempts}, \u653E\u5F03): ${outcome.error}`
|
|
12144
|
+
);
|
|
12145
|
+
}
|
|
12059
12146
|
}
|
|
12060
|
-
|
|
12061
|
-
return { ok: true };
|
|
12147
|
+
return { ok: false, error: lastError };
|
|
12062
12148
|
}
|
|
12063
12149
|
|
|
12064
12150
|
// src/recording/handler.ts
|
|
@@ -13386,6 +13472,15 @@ var WsProxy = class {
|
|
|
13386
13472
|
|
|
13387
13473
|
// src/tunnel/proxy.ts
|
|
13388
13474
|
var RELAY_TUNNEL_GATEWAY_CLIENT_INSTANCE_ID = "phone-notifications-relay-tunnel";
|
|
13475
|
+
var GATEWAY_OPERATOR_SCOPES = [
|
|
13476
|
+
"operator.admin",
|
|
13477
|
+
"operator.approvals",
|
|
13478
|
+
"operator.pairing",
|
|
13479
|
+
"operator.read",
|
|
13480
|
+
"operator.write"
|
|
13481
|
+
];
|
|
13482
|
+
var GATEWAY_RPC_MIN_PROTOCOL = 3;
|
|
13483
|
+
var GATEWAY_RPC_MAX_PROTOCOL = 4;
|
|
13389
13484
|
var MAX_AUTO_PAIRING_APPROVALS = 3;
|
|
13390
13485
|
var RECENT_ABORTED_CHAT_RUN_TTL_MS = 6e4;
|
|
13391
13486
|
var GATEWAY_RPC_HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
@@ -13981,7 +14076,7 @@ var TunnelProxy = class {
|
|
|
13981
14076
|
clearHandshakeTimer();
|
|
13982
14077
|
this.storeIssuedDeviceToken({
|
|
13983
14078
|
fallbackRole: "operator",
|
|
13984
|
-
fallbackScopes: [
|
|
14079
|
+
fallbackScopes: [...GATEWAY_OPERATOR_SCOPES],
|
|
13985
14080
|
authInfo: frame.payload?.auth
|
|
13986
14081
|
});
|
|
13987
14082
|
this.gatewayWsAutoPairingApprovals = 0;
|
|
@@ -14090,7 +14185,7 @@ var TunnelProxy = class {
|
|
|
14090
14185
|
const challengeNonce = frame.payload?.nonce ?? "";
|
|
14091
14186
|
const connectRequestId = `tunnel-connect-${(0, import_node_crypto5.randomUUID)()}`;
|
|
14092
14187
|
const role = "operator";
|
|
14093
|
-
const scopes = [
|
|
14188
|
+
const scopes = [...GATEWAY_OPERATOR_SCOPES];
|
|
14094
14189
|
const gatewayConnectAuth = this.buildGatewayConnectAuth(role);
|
|
14095
14190
|
this.opts.logger.info(
|
|
14096
14191
|
`TunnelProxy: received connect.challenge (nonce=${challengeNonce}, connectReqId=${connectRequestId}, hasToken=${!!gatewayConnectAuth.authToken}, hasPassword=${!!gatewayConnectAuth.authPassword}, hasDeviceToken=${!!gatewayConnectAuth.deviceToken}), sending connect request with device identity`
|
|
@@ -14117,8 +14212,8 @@ var TunnelProxy = class {
|
|
|
14117
14212
|
id: connectRequestId,
|
|
14118
14213
|
method: "connect",
|
|
14119
14214
|
params: {
|
|
14120
|
-
minProtocol:
|
|
14121
|
-
maxProtocol:
|
|
14215
|
+
minProtocol: GATEWAY_RPC_MIN_PROTOCOL,
|
|
14216
|
+
maxProtocol: GATEWAY_RPC_MAX_PROTOCOL,
|
|
14122
14217
|
client: {
|
|
14123
14218
|
id: clientId,
|
|
14124
14219
|
version: "1.0.0",
|