@bolloon/bolloon-agent 0.4.33 → 0.5.1
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/agents/contacts/chain.js +27 -7
- package/dist/agents/execution-supervisor.js +580 -40
- package/dist/agents/external-events.js +35 -6
- package/dist/agents/gateway-group.js +100 -12
- package/dist/agents/goal-criteria.js +10 -3
- package/dist/agents/goal-flywheel/block-executor.js +346 -0
- package/dist/agents/goal-flywheel/continuation-decision.js +592 -0
- package/dist/agents/goal-flywheel/goal-change.js +754 -0
- package/dist/agents/goal-flywheel/index.js +26 -0
- package/dist/agents/goal-flywheel/memory-layers.js +227 -0
- package/dist/agents/goal-flywheel/run-closure.js +809 -0
- package/dist/agents/goal-flywheel/skill-candidate.js +628 -0
- package/dist/agents/goal-flywheel/types.js +329 -0
- package/dist/agents/goal-flywheel/wiring/change.js +288 -0
- package/dist/agents/goal-flywheel/wiring/closure.js +697 -0
- package/dist/agents/goal-flywheel/wiring/continuation.js +432 -0
- package/dist/agents/goal-flywheel/wiring/contract.js +270 -0
- package/dist/agents/goal-flywheel/wiring/index.js +26 -0
- package/dist/agents/goal-flywheel/wiring/monitor.js +254 -0
- package/dist/agents/goal-flywheel/wiring/seams.js +592 -0
- package/dist/agents/goal-flywheel/work-contract.js +478 -0
- package/dist/agents/goal-flywheel/work-monitor.js +488 -0
- package/dist/agents/goal-flywheel-wiring.js +1870 -0
- package/dist/agents/goal-state-reducer.js +406 -0
- package/dist/agents/goal-store.js +35 -1
- package/dist/agents/mobile-flywheel-view.js +144 -0
- package/dist/agents/mobile-task-actions-verify.js +74 -0
- package/dist/agents/mobile-task-actions.js +178 -0
- package/dist/agents/mobile-task-views.js +199 -0
- package/dist/agents/model-policy.js +651 -0
- package/dist/agents/network-pulse.js +304 -18
- package/dist/agents/pi-sdk-tools.js +84 -33
- package/dist/agents/pi-sdk.js +157 -42
- package/dist/agents/run-store.js +71 -5
- package/dist/agents/skill-readiness.js +52 -10
- package/dist/agents/subagent-manager.js +209 -3
- package/dist/agents/task/task-runner.js +17 -4
- package/dist/agents/task-group.js +8 -51
- package/dist/agents/task-public-text.js +89 -0
- package/dist/agents/workflow-pivot-loop.js +19 -12
- package/dist/cli/clipboard.js +65 -0
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/tasks.js +350 -2
- package/dist/cli/identity-command.js +177 -0
- package/dist/cli/ink-app.js +145 -17
- package/dist/cli/log-gate.js +386 -0
- package/dist/cli/mention-data.js +2 -0
- package/dist/cli/model-selector.js +538 -0
- package/dist/cli/reply-hygiene.js +54 -0
- package/dist/cli/setup-wizard.js +757 -69
- package/dist/cli/startup-notice.js +160 -0
- package/dist/cli/stores.js +22 -1
- package/dist/cli/theme.js +49 -0
- package/dist/cli/tui-select.js +970 -0
- package/dist/cli/update-commands.js +150 -24
- package/dist/cli-entry.js +137 -20
- package/dist/electron-build/agents/contacts/chain.js +26 -6
- package/dist/electron-build/agents/contacts/chain.js.map +1 -1
- package/dist/electron-build/agents/execution-supervisor.js +578 -38
- package/dist/electron-build/agents/execution-supervisor.js.map +1 -1
- package/dist/electron-build/agents/external-events.js +34 -5
- package/dist/electron-build/agents/external-events.js.map +1 -1
- package/dist/electron-build/agents/goal-criteria.js +10 -3
- package/dist/electron-build/agents/goal-criteria.js.map +1 -1
- package/dist/electron-build/agents/goal-flywheel/continuation-decision.js +598 -0
- package/dist/electron-build/agents/goal-flywheel/continuation-decision.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/goal-change.js +773 -0
- package/dist/electron-build/agents/goal-flywheel/goal-change.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/memory-layers.js +269 -0
- package/dist/electron-build/agents/goal-flywheel/memory-layers.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/run-closure.js +818 -0
- package/dist/electron-build/agents/goal-flywheel/run-closure.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/skill-candidate.js +642 -0
- package/dist/electron-build/agents/goal-flywheel/skill-candidate.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/types.js +333 -0
- package/dist/electron-build/agents/goal-flywheel/types.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/change.js +294 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/change.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/closure.js +742 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/closure.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/continuation.js +444 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/continuation.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/contract.js +279 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/contract.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/index.js +111 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/index.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/monitor.js +264 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/monitor.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/seams.js +612 -0
- package/dist/electron-build/agents/goal-flywheel/wiring/seams.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/work-contract.js +488 -0
- package/dist/electron-build/agents/goal-flywheel/work-contract.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel/work-monitor.js +501 -0
- package/dist/electron-build/agents/goal-flywheel/work-monitor.js.map +1 -0
- package/dist/electron-build/agents/goal-flywheel-wiring.js +1962 -0
- package/dist/electron-build/agents/goal-flywheel-wiring.js.map +1 -0
- package/dist/electron-build/agents/goal-state-reducer.js +414 -0
- package/dist/electron-build/agents/goal-state-reducer.js.map +1 -0
- package/dist/electron-build/agents/goal-store.js +35 -1
- package/dist/electron-build/agents/goal-store.js.map +1 -1
- package/dist/electron-build/agents/model-policy.js +706 -0
- package/dist/electron-build/agents/model-policy.js.map +1 -0
- package/dist/electron-build/agents/network-pulse.js +307 -19
- package/dist/electron-build/agents/network-pulse.js.map +1 -1
- package/dist/electron-build/agents/pi-sdk-tools.js +84 -33
- package/dist/electron-build/agents/pi-sdk-tools.js.map +1 -1
- package/dist/electron-build/agents/pi-sdk-types.js.map +1 -1
- package/dist/electron-build/agents/pi-sdk.js +156 -41
- package/dist/electron-build/agents/pi-sdk.js.map +1 -1
- package/dist/electron-build/agents/run-store.js +75 -6
- package/dist/electron-build/agents/run-store.js.map +1 -1
- package/dist/electron-build/agents/skill-readiness.js +52 -9
- package/dist/electron-build/agents/skill-readiness.js.map +1 -1
- package/dist/electron-build/agents/task/task-runner.js +16 -3
- package/dist/electron-build/agents/task/task-runner.js.map +1 -1
- package/dist/electron-build/agents/workflow-pivot-loop.js +19 -12
- package/dist/electron-build/agents/workflow-pivot-loop.js.map +1 -1
- package/dist/electron-build/llm/config-store.js +146 -6
- package/dist/electron-build/llm/config-store.js.map +1 -1
- package/dist/electron-build/llm/connection-probe.js +764 -0
- package/dist/electron-build/llm/connection-probe.js.map +1 -0
- package/dist/electron-build/llm/custom-provider-store.js +272 -0
- package/dist/electron-build/llm/custom-provider-store.js.map +1 -0
- package/dist/electron-build/llm/data/provider-catalog-baked.js +23 -0
- package/dist/electron-build/llm/data/provider-catalog-baked.js.map +1 -0
- package/dist/electron-build/llm/model-catalog.js +778 -0
- package/dist/electron-build/llm/model-catalog.js.map +1 -0
- package/dist/electron-build/llm/model-discovery.js +1202 -0
- package/dist/electron-build/llm/model-discovery.js.map +1 -0
- package/dist/electron-build/llm/model-selection.js +1315 -0
- package/dist/electron-build/llm/model-selection.js.map +1 -0
- package/dist/electron-build/llm/pi-ai.js +70 -11
- package/dist/electron-build/llm/pi-ai.js.map +1 -1
- package/dist/electron-build/llm/provider-catalog.js +969 -0
- package/dist/electron-build/llm/provider-catalog.js.map +1 -0
- package/dist/electron-build/llm/provider-registry.js +950 -0
- package/dist/electron-build/llm/provider-registry.js.map +1 -0
- package/dist/electron-build/llm/tool-name.js +266 -0
- package/dist/electron-build/llm/tool-name.js.map +1 -0
- package/dist/electron-build/orbitdb/cid-database.js +83 -17
- package/dist/electron-build/orbitdb/cid-database.js.map +1 -1
- package/dist/electron-build/orbitdb/ipfs-node.js +31 -2
- package/dist/electron-build/orbitdb/ipfs-node.js.map +1 -1
- package/dist/electron-build/utils/dual-source-facts.js +236 -0
- package/dist/electron-build/utils/dual-source-facts.js.map +1 -0
- package/dist/electron-build/utils/dual-source.js +347 -0
- package/dist/electron-build/utils/dual-source.js.map +1 -0
- package/dist/electron-build/utils/update-manager.js +328 -104
- package/dist/electron-build/utils/update-manager.js.map +1 -1
- package/dist/electron-build/utils/update-state.js +9 -11
- package/dist/electron-build/utils/update-state.js.map +1 -1
- package/dist/electron-build/utils/version-identity.js +193 -0
- package/dist/electron-build/utils/version-identity.js.map +1 -0
- package/dist/electron-build/utils/version-info.js +57 -31
- package/dist/electron-build/utils/version-info.js.map +1 -1
- package/dist/index.js +385 -108
- package/dist/ios/bolloon-web.json +10 -0
- package/dist/ios/chain-explorer.js +617 -0
- package/dist/ios/explorer.html +163 -0
- package/dist/ios/index.html +96 -0
- package/dist/ios/mobile-agent.js +2 -2
- package/dist/ios/mobile-contacts.js +362 -0
- package/dist/ios/mobile-core.js +3102 -310
- package/dist/ios/mobile-privacy.js +185 -0
- package/dist/ios/mobile-tasks.js +339 -0
- package/dist/ios/mobile-update.js +1442 -0
- package/dist/ios/mobile.css +19 -0
- package/dist/ios/mobile.html +96 -0
- package/dist/ios/mobile.js +1013 -41
- package/dist/ios/routes-chain-index.js +108 -0
- package/dist/ios/routes-contacts.js +420 -0
- package/dist/ios/routes-llm-config.js +344 -52
- package/dist/ios/routes-mobile-tasks.js +353 -0
- package/dist/ios/routes-onchain-trade.js +99 -0
- package/dist/ios/routes-x402-info.js +1 -0
- package/dist/ios/server.js +921 -0
- package/dist/ios/sw.js +1 -1
- package/dist/ios/task-frame-server.js +211 -0
- package/dist/llm/config-store.js +146 -6
- package/dist/llm/connection-probe.js +744 -0
- package/dist/llm/custom-provider-store.js +224 -0
- package/dist/llm/data/provider-catalog-baked.js +19 -0
- package/dist/llm/model-catalog.js +717 -0
- package/dist/llm/model-discovery.js +1137 -0
- package/dist/llm/model-selection.js +1241 -0
- package/dist/llm/pi-ai.js +70 -11
- package/dist/llm/provider-catalog.js +898 -0
- package/dist/llm/provider-registry.js +917 -0
- package/dist/llm/tool-name.js +220 -0
- package/dist/orbitdb/cid-database.js +81 -16
- package/dist/orbitdb/ipfs-node.js +31 -2
- package/dist/setup/onboard.js +34 -8
- package/dist/utils/dual-source-facts.js +223 -0
- package/dist/utils/dual-source.js +297 -0
- package/dist/utils/update-cli.js +16 -21
- package/dist/utils/update-health.js +35 -5
- package/dist/utils/update-manager.js +325 -96
- package/dist/utils/update-state.js +13 -10
- package/dist/utils/version-identity.js +176 -0
- package/dist/utils/version-info.js +27 -22
- package/dist/web/bolloon-web.json +10 -0
- package/dist/web/mobile-contacts.js +44 -11
- package/dist/web/mobile-core.js +2901 -580
- package/dist/web/mobile-tasks.js +339 -0
- package/dist/web/mobile-update.js +1442 -0
- package/dist/web/mobile.css +19 -0
- package/dist/web/mobile.html +64 -0
- package/dist/web/mobile.js +838 -35
- package/dist/web/routes-llm-config.js +344 -52
- package/dist/web/routes-mobile-tasks.js +353 -0
- package/dist/web/server.js +163 -4
- package/dist/web/sw.js +1 -1
- package/package.json +3 -1
- package/scripts/build-web.ts +36 -0
package/dist/web/mobile-core.js
CHANGED
|
@@ -1374,7 +1374,7 @@
|
|
|
1374
1374
|
}
|
|
1375
1375
|
function encode(data, alphabet4, bitsPerChar) {
|
|
1376
1376
|
const pad2 = alphabet4[alphabet4.length - 1] === "=";
|
|
1377
|
-
const
|
|
1377
|
+
const mask2 = (1 << bitsPerChar) - 1;
|
|
1378
1378
|
let out = "";
|
|
1379
1379
|
let bits = 0;
|
|
1380
1380
|
let buffer6 = 0;
|
|
@@ -1383,11 +1383,11 @@
|
|
|
1383
1383
|
bits += 8;
|
|
1384
1384
|
while (bits > bitsPerChar) {
|
|
1385
1385
|
bits -= bitsPerChar;
|
|
1386
|
-
out += alphabet4[
|
|
1386
|
+
out += alphabet4[mask2 & buffer6 >> bits];
|
|
1387
1387
|
}
|
|
1388
1388
|
}
|
|
1389
1389
|
if (bits !== 0) {
|
|
1390
|
-
out += alphabet4[
|
|
1390
|
+
out += alphabet4[mask2 & buffer6 << bitsPerChar - bits];
|
|
1391
1391
|
}
|
|
1392
1392
|
if (pad2) {
|
|
1393
1393
|
while ((out.length * bitsPerChar & 7) !== 0) {
|
|
@@ -3361,8 +3361,8 @@
|
|
|
3361
3361
|
}
|
|
3362
3362
|
function encodeInteger(value2) {
|
|
3363
3363
|
const contents = new Uint8ArrayList();
|
|
3364
|
-
const
|
|
3365
|
-
const positive2 = (value2.subarray()[0] &
|
|
3364
|
+
const mask2 = 128;
|
|
3365
|
+
const positive2 = (value2.subarray()[0] & mask2) === mask2;
|
|
3366
3366
|
if (positive2) {
|
|
3367
3367
|
contents.append(Uint8Array.from([0]));
|
|
3368
3368
|
}
|
|
@@ -4974,13 +4974,13 @@
|
|
|
4974
4974
|
const windows = Math.ceil(scalarBits2 / W2) + 1;
|
|
4975
4975
|
const windowSize = 2 ** (W2 - 1);
|
|
4976
4976
|
const maxNumber = 2 ** W2;
|
|
4977
|
-
const
|
|
4977
|
+
const mask2 = bitMask(W2);
|
|
4978
4978
|
const shiftBy = BigInt(W2);
|
|
4979
|
-
return { windows, windowSize, mask, maxNumber, shiftBy };
|
|
4979
|
+
return { windows, windowSize, mask: mask2, maxNumber, shiftBy };
|
|
4980
4980
|
}
|
|
4981
4981
|
function calcOffsets(n, window2, wOpts) {
|
|
4982
|
-
const { windowSize, mask, maxNumber, shiftBy } = wOpts;
|
|
4983
|
-
let wbits = Number(n &
|
|
4982
|
+
const { windowSize, mask: mask2, maxNumber, shiftBy } = wOpts;
|
|
4983
|
+
let wbits = Number(n & mask2);
|
|
4984
4984
|
let nextN = n >> shiftBy;
|
|
4985
4985
|
if (wbits > windowSize) {
|
|
4986
4986
|
wbits -= maxNumber;
|
|
@@ -6801,18 +6801,18 @@
|
|
|
6801
6801
|
* Zig-zag encodes this long bits
|
|
6802
6802
|
*/
|
|
6803
6803
|
zzEncode() {
|
|
6804
|
-
const
|
|
6805
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
6806
|
-
this.lo = (this.lo << 1 ^
|
|
6804
|
+
const mask2 = this.hi >> 31;
|
|
6805
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
6806
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
6807
6807
|
return this;
|
|
6808
6808
|
}
|
|
6809
6809
|
/**
|
|
6810
6810
|
* Zig-zag decodes this long bits
|
|
6811
6811
|
*/
|
|
6812
6812
|
zzDecode() {
|
|
6813
|
-
const
|
|
6814
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
6815
|
-
this.hi = (this.hi >>> 1 ^
|
|
6813
|
+
const mask2 = -(this.lo & 1);
|
|
6814
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
6815
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
6816
6816
|
return this;
|
|
6817
6817
|
}
|
|
6818
6818
|
/**
|
|
@@ -12897,9 +12897,9 @@ ${indent}[Error list was empty]`;
|
|
|
12897
12897
|
}
|
|
12898
12898
|
}
|
|
12899
12899
|
}
|
|
12900
|
-
function simpleMaskLength(
|
|
12900
|
+
function simpleMaskLength(mask2) {
|
|
12901
12901
|
let ones = 0;
|
|
12902
|
-
for (let [index, byte] of
|
|
12902
|
+
for (let [index, byte] of mask2.entries()) {
|
|
12903
12903
|
if (byte === 255) {
|
|
12904
12904
|
ones += 8;
|
|
12905
12905
|
continue;
|
|
@@ -12911,8 +12911,8 @@ ${indent}[Error list was empty]`;
|
|
|
12911
12911
|
if ((byte & 128) != 0) {
|
|
12912
12912
|
return -1;
|
|
12913
12913
|
}
|
|
12914
|
-
for (let i = index + 1; i <
|
|
12915
|
-
if (
|
|
12914
|
+
for (let i = index + 1; i < mask2.length; i++) {
|
|
12915
|
+
if (mask2[i] != 0) {
|
|
12916
12916
|
return -1;
|
|
12917
12917
|
}
|
|
12918
12918
|
}
|
|
@@ -12920,9 +12920,9 @@ ${indent}[Error list was empty]`;
|
|
|
12920
12920
|
}
|
|
12921
12921
|
return ones;
|
|
12922
12922
|
}
|
|
12923
|
-
function maskToHex(
|
|
12923
|
+
function maskToHex(mask2) {
|
|
12924
12924
|
let hex = "0x";
|
|
12925
|
-
for (const byte of
|
|
12925
|
+
for (const byte of mask2) {
|
|
12926
12926
|
hex += (byte >> 4).toString(16) + (byte & 15).toString(16);
|
|
12927
12927
|
}
|
|
12928
12928
|
return hex;
|
|
@@ -12934,20 +12934,20 @@ ${indent}[Error list was empty]`;
|
|
|
12934
12934
|
});
|
|
12935
12935
|
|
|
12936
12936
|
// node_modules/@chainsafe/netmask/dist/src/ip.js
|
|
12937
|
-
function maskIp(ip,
|
|
12938
|
-
if (
|
|
12939
|
-
|
|
12937
|
+
function maskIp(ip, mask2) {
|
|
12938
|
+
if (mask2.length === IPv6Len && ip.length === IPv4Len && allFF(mask2, 0, 11)) {
|
|
12939
|
+
mask2 = mask2.slice(12);
|
|
12940
12940
|
}
|
|
12941
|
-
if (
|
|
12941
|
+
if (mask2.length === IPv4Len && ip.length === IPv6Len && deepEqual(ip, ipv4Prefix, 0, 11)) {
|
|
12942
12942
|
ip = ip.slice(12);
|
|
12943
12943
|
}
|
|
12944
12944
|
const n = ip.length;
|
|
12945
|
-
if (n !=
|
|
12945
|
+
if (n != mask2.length) {
|
|
12946
12946
|
throw new Error("Failed to mask ip");
|
|
12947
12947
|
}
|
|
12948
12948
|
const out = new Uint8Array(n);
|
|
12949
12949
|
for (let i = 0; i < n; i++) {
|
|
12950
|
-
out[i] = ip[i] &
|
|
12950
|
+
out[i] = ip[i] & mask2[i];
|
|
12951
12951
|
}
|
|
12952
12952
|
return out;
|
|
12953
12953
|
}
|
|
@@ -13009,10 +13009,10 @@ ${indent}[Error list was empty]`;
|
|
|
13009
13009
|
if (Number.isNaN(m2) || String(m2).length !== maskString.length || m2 < 0 || m2 > ipLength * 8) {
|
|
13010
13010
|
throw new Error("Failed to parse given CIDR: " + s2);
|
|
13011
13011
|
}
|
|
13012
|
-
const
|
|
13012
|
+
const mask2 = cidrMask(m2, 8 * ipLength);
|
|
13013
13013
|
return {
|
|
13014
|
-
network: maskIp(ip,
|
|
13015
|
-
mask
|
|
13014
|
+
network: maskIp(ip, mask2),
|
|
13015
|
+
mask: mask2
|
|
13016
13016
|
};
|
|
13017
13017
|
}
|
|
13018
13018
|
function cidrMask(ones, bits) {
|
|
@@ -13054,18 +13054,18 @@ ${indent}[Error list was empty]`;
|
|
|
13054
13054
|
* @param ipOrCidr either network ip or full cidr address
|
|
13055
13055
|
* @param mask in case ipOrCidr is network this can be either mask in decimal format or as ip address
|
|
13056
13056
|
*/
|
|
13057
|
-
constructor(ipOrCidr,
|
|
13058
|
-
if (
|
|
13057
|
+
constructor(ipOrCidr, mask2) {
|
|
13058
|
+
if (mask2 == null) {
|
|
13059
13059
|
({ network: this.network, mask: this.mask } = parseCidr(ipOrCidr));
|
|
13060
13060
|
} else {
|
|
13061
13061
|
const ipResult = parseIP(ipOrCidr);
|
|
13062
13062
|
if (ipResult == null) {
|
|
13063
13063
|
throw new Error("Failed to parse network");
|
|
13064
13064
|
}
|
|
13065
|
-
|
|
13066
|
-
const m2 = parseInt(
|
|
13067
|
-
if (Number.isNaN(m2) || String(m2).length !==
|
|
13068
|
-
const maskResult = parseIP(
|
|
13065
|
+
mask2 = String(mask2);
|
|
13066
|
+
const m2 = parseInt(mask2, 10);
|
|
13067
|
+
if (Number.isNaN(m2) || String(m2).length !== mask2.length || m2 < 0 || m2 > ipResult.length * 8) {
|
|
13068
|
+
const maskResult = parseIP(mask2);
|
|
13069
13069
|
if (maskResult == null) {
|
|
13070
13070
|
throw new Error("Failed to parse mask");
|
|
13071
13071
|
}
|
|
@@ -13087,8 +13087,8 @@ ${indent}[Error list was empty]`;
|
|
|
13087
13087
|
/**Serializes back to string format */
|
|
13088
13088
|
toString() {
|
|
13089
13089
|
const l = simpleMaskLength(this.mask);
|
|
13090
|
-
const
|
|
13091
|
-
return ipToString(this.network) + "/" +
|
|
13090
|
+
const mask2 = l !== -1 ? String(l) : maskToHex(this.mask);
|
|
13091
|
+
return ipToString(this.network) + "/" + mask2;
|
|
13092
13092
|
}
|
|
13093
13093
|
};
|
|
13094
13094
|
}
|
|
@@ -13309,11 +13309,11 @@ ${indent}[Error list was empty]`;
|
|
|
13309
13309
|
}
|
|
13310
13310
|
}
|
|
13311
13311
|
var Netmask4Impl = class _Netmask4Impl {
|
|
13312
|
-
constructor(net,
|
|
13312
|
+
constructor(net, mask2) {
|
|
13313
13313
|
if (typeof net !== "string") {
|
|
13314
13314
|
throw new Error("Missing `net' parameter");
|
|
13315
13315
|
}
|
|
13316
|
-
let maskStr =
|
|
13316
|
+
let maskStr = mask2;
|
|
13317
13317
|
if (!maskStr) {
|
|
13318
13318
|
const parts = net.split("/", 2);
|
|
13319
13319
|
net = parts[0];
|
|
@@ -13498,11 +13498,11 @@ ${indent}[Error list was empty]`;
|
|
|
13498
13498
|
}
|
|
13499
13499
|
}
|
|
13500
13500
|
var Netmask6Impl = class _Netmask6Impl {
|
|
13501
|
-
constructor(net,
|
|
13501
|
+
constructor(net, mask2) {
|
|
13502
13502
|
if (typeof net !== "string") {
|
|
13503
13503
|
throw new Error("Missing `net' parameter");
|
|
13504
13504
|
}
|
|
13505
|
-
let prefixLen =
|
|
13505
|
+
let prefixLen = mask2;
|
|
13506
13506
|
if (prefixLen === void 0 || prefixLen === null) {
|
|
13507
13507
|
const slashIdx = net.indexOf("/");
|
|
13508
13508
|
if (slashIdx !== -1) {
|
|
@@ -13585,15 +13585,15 @@ ${indent}[Error list was empty]`;
|
|
|
13585
13585
|
} });
|
|
13586
13586
|
var netmask6_1 = require_netmask6();
|
|
13587
13587
|
var Netmask2 = class _Netmask {
|
|
13588
|
-
constructor(net,
|
|
13588
|
+
constructor(net, mask2) {
|
|
13589
13589
|
if (typeof net !== "string") {
|
|
13590
13590
|
throw new Error("Missing `net' parameter");
|
|
13591
13591
|
}
|
|
13592
13592
|
const addrPart = net.indexOf("/") !== -1 ? net.substring(0, net.indexOf("/")) : net;
|
|
13593
13593
|
if (addrPart.indexOf(":") !== -1) {
|
|
13594
|
-
this._impl = new netmask6_1.Netmask6Impl(net,
|
|
13594
|
+
this._impl = new netmask6_1.Netmask6Impl(net, mask2);
|
|
13595
13595
|
} else {
|
|
13596
|
-
this._impl = new netmask4_1.Netmask4Impl(net,
|
|
13596
|
+
this._impl = new netmask4_1.Netmask4Impl(net, mask2);
|
|
13597
13597
|
}
|
|
13598
13598
|
this.base = this._impl.base;
|
|
13599
13599
|
this.mask = this._impl.mask;
|
|
@@ -18414,11 +18414,11 @@ ${indent}[Error list was empty]`;
|
|
|
18414
18414
|
function toToken2(data, pos, prefix, length20, options2) {
|
|
18415
18415
|
const totLength = prefix + length20;
|
|
18416
18416
|
assertEnoughData(data, pos, totLength);
|
|
18417
|
-
const
|
|
18417
|
+
const tok2 = new Token(Type.string, toStr(data, pos + prefix, pos + totLength), totLength);
|
|
18418
18418
|
if (options2.retainStringBytes === true) {
|
|
18419
|
-
|
|
18419
|
+
tok2.byteValue = data.slice(pos + prefix, pos + totLength);
|
|
18420
18420
|
}
|
|
18421
|
-
return
|
|
18421
|
+
return tok2;
|
|
18422
18422
|
}
|
|
18423
18423
|
function decodeStringCompact(data, pos, minor, options2) {
|
|
18424
18424
|
return toToken2(data, pos, 1, minor, options2);
|
|
@@ -21481,18 +21481,18 @@ ${indent}[Error list was empty]`;
|
|
|
21481
21481
|
* Zig-zag encodes this long bits
|
|
21482
21482
|
*/
|
|
21483
21483
|
zzEncode() {
|
|
21484
|
-
const
|
|
21485
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
21486
|
-
this.lo = (this.lo << 1 ^
|
|
21484
|
+
const mask2 = this.hi >> 31;
|
|
21485
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
21486
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
21487
21487
|
return this;
|
|
21488
21488
|
}
|
|
21489
21489
|
/**
|
|
21490
21490
|
* Zig-zag decodes this long bits
|
|
21491
21491
|
*/
|
|
21492
21492
|
zzDecode() {
|
|
21493
|
-
const
|
|
21494
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
21495
|
-
this.hi = (this.hi >>> 1 ^
|
|
21493
|
+
const mask2 = -(this.lo & 1);
|
|
21494
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
21495
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
21496
21496
|
return this;
|
|
21497
21497
|
}
|
|
21498
21498
|
/**
|
|
@@ -24141,18 +24141,18 @@ ${indent}[Error list was empty]`;
|
|
|
24141
24141
|
* Zig-zag encodes this long bits
|
|
24142
24142
|
*/
|
|
24143
24143
|
zzEncode() {
|
|
24144
|
-
const
|
|
24145
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
24146
|
-
this.lo = (this.lo << 1 ^
|
|
24144
|
+
const mask2 = this.hi >> 31;
|
|
24145
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
24146
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
24147
24147
|
return this;
|
|
24148
24148
|
}
|
|
24149
24149
|
/**
|
|
24150
24150
|
* Zig-zag decodes this long bits
|
|
24151
24151
|
*/
|
|
24152
24152
|
zzDecode() {
|
|
24153
|
-
const
|
|
24154
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
24155
|
-
this.hi = (this.hi >>> 1 ^
|
|
24153
|
+
const mask2 = -(this.lo & 1);
|
|
24154
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
24155
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
24156
24156
|
return this;
|
|
24157
24157
|
}
|
|
24158
24158
|
/**
|
|
@@ -28712,18 +28712,18 @@ ${indent}[Error list was empty]`;
|
|
|
28712
28712
|
}
|
|
28713
28713
|
function multiaddrToIpNet(ma) {
|
|
28714
28714
|
const config = getNetConfig(ma);
|
|
28715
|
-
let
|
|
28715
|
+
let mask2 = config.cidr;
|
|
28716
28716
|
if (config.type !== "ip4" && config.type !== "ip6") {
|
|
28717
28717
|
throw new InvalidParametersError(`Multiaddr ${ma} was not an IPv4 or IPv6 address`);
|
|
28718
28718
|
}
|
|
28719
|
-
if (
|
|
28719
|
+
if (mask2 == null) {
|
|
28720
28720
|
switch (config.type) {
|
|
28721
28721
|
case "ip4": {
|
|
28722
|
-
|
|
28722
|
+
mask2 = 32;
|
|
28723
28723
|
break;
|
|
28724
28724
|
}
|
|
28725
28725
|
case "ip6": {
|
|
28726
|
-
|
|
28726
|
+
mask2 = 128;
|
|
28727
28727
|
break;
|
|
28728
28728
|
}
|
|
28729
28729
|
default: {
|
|
@@ -28731,7 +28731,7 @@ ${indent}[Error list was empty]`;
|
|
|
28731
28731
|
}
|
|
28732
28732
|
}
|
|
28733
28733
|
}
|
|
28734
|
-
return new IpNet(config.host,
|
|
28734
|
+
return new IpNet(config.host, mask2);
|
|
28735
28735
|
}
|
|
28736
28736
|
function isDirect(ma) {
|
|
28737
28737
|
return !Circuit.exactMatch(ma);
|
|
@@ -35926,12 +35926,12 @@ ${[...listenStats.errors.entries()].map(([addr, err2]) => {
|
|
|
35926
35926
|
g[i] &= 8191;
|
|
35927
35927
|
}
|
|
35928
35928
|
g[9] -= 1 << 13;
|
|
35929
|
-
let
|
|
35929
|
+
let mask2 = (c ^ 1) - 1;
|
|
35930
35930
|
for (let i = 0; i < 10; i++)
|
|
35931
|
-
g[i] &=
|
|
35932
|
-
|
|
35931
|
+
g[i] &= mask2;
|
|
35932
|
+
mask2 = ~mask2;
|
|
35933
35933
|
for (let i = 0; i < 10; i++)
|
|
35934
|
-
h3[i] = h3[i] &
|
|
35934
|
+
h3[i] = h3[i] & mask2 | g[i];
|
|
35935
35935
|
h3[0] = (h3[0] | h3[1] << 13) & 65535;
|
|
35936
35936
|
h3[1] = (h3[1] >>> 3 | h3[2] << 10) & 65535;
|
|
35937
35937
|
h3[2] = (h3[2] >>> 6 | h3[3] << 7) & 65535;
|
|
@@ -36669,7 +36669,7 @@ ${[...listenStats.errors.entries()].map(([addr, err2]) => {
|
|
|
36669
36669
|
}
|
|
36670
36670
|
function encode10(data, alphabet4, bitsPerChar) {
|
|
36671
36671
|
const pad2 = alphabet4[alphabet4.length - 1] === "=";
|
|
36672
|
-
const
|
|
36672
|
+
const mask2 = (1 << bitsPerChar) - 1;
|
|
36673
36673
|
let out = "";
|
|
36674
36674
|
let bits = 0;
|
|
36675
36675
|
let buffer6 = 0;
|
|
@@ -36678,11 +36678,11 @@ ${[...listenStats.errors.entries()].map(([addr, err2]) => {
|
|
|
36678
36678
|
bits += 8;
|
|
36679
36679
|
while (bits > bitsPerChar) {
|
|
36680
36680
|
bits -= bitsPerChar;
|
|
36681
|
-
out += alphabet4[
|
|
36681
|
+
out += alphabet4[mask2 & buffer6 >> bits];
|
|
36682
36682
|
}
|
|
36683
36683
|
}
|
|
36684
36684
|
if (bits !== 0) {
|
|
36685
|
-
out += alphabet4[
|
|
36685
|
+
out += alphabet4[mask2 & buffer6 << bitsPerChar - bits];
|
|
36686
36686
|
}
|
|
36687
36687
|
if (pad2) {
|
|
36688
36688
|
while ((out.length * bitsPerChar & 7) !== 0) {
|
|
@@ -38978,18 +38978,18 @@ ${[...listenStats.errors.entries()].map(([addr, err2]) => {
|
|
|
38978
38978
|
* Zig-zag encodes this long bits
|
|
38979
38979
|
*/
|
|
38980
38980
|
zzEncode() {
|
|
38981
|
-
const
|
|
38982
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
38983
|
-
this.lo = (this.lo << 1 ^
|
|
38981
|
+
const mask2 = this.hi >> 31;
|
|
38982
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
38983
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
38984
38984
|
return this;
|
|
38985
38985
|
}
|
|
38986
38986
|
/**
|
|
38987
38987
|
* Zig-zag decodes this long bits
|
|
38988
38988
|
*/
|
|
38989
38989
|
zzDecode() {
|
|
38990
|
-
const
|
|
38991
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
38992
|
-
this.hi = (this.hi >>> 1 ^
|
|
38990
|
+
const mask2 = -(this.lo & 1);
|
|
38991
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
38992
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
38993
38993
|
return this;
|
|
38994
38994
|
}
|
|
38995
38995
|
/**
|
|
@@ -41706,18 +41706,18 @@ ${[...listenStats.errors.entries()].map(([addr, err2]) => {
|
|
|
41706
41706
|
* Zig-zag encodes this long bits
|
|
41707
41707
|
*/
|
|
41708
41708
|
zzEncode() {
|
|
41709
|
-
const
|
|
41710
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
41711
|
-
this.lo = (this.lo << 1 ^
|
|
41709
|
+
const mask2 = this.hi >> 31;
|
|
41710
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
41711
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
41712
41712
|
return this;
|
|
41713
41713
|
}
|
|
41714
41714
|
/**
|
|
41715
41715
|
* Zig-zag decodes this long bits
|
|
41716
41716
|
*/
|
|
41717
41717
|
zzDecode() {
|
|
41718
|
-
const
|
|
41719
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
41720
|
-
this.hi = (this.hi >>> 1 ^
|
|
41718
|
+
const mask2 = -(this.lo & 1);
|
|
41719
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
41720
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
41721
41721
|
return this;
|
|
41722
41722
|
}
|
|
41723
41723
|
/**
|
|
@@ -43635,18 +43635,18 @@ ${[...listenStats.errors.entries()].map(([addr, err2]) => {
|
|
|
43635
43635
|
* Zig-zag encodes this long bits
|
|
43636
43636
|
*/
|
|
43637
43637
|
zzEncode() {
|
|
43638
|
-
const
|
|
43639
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
43640
|
-
this.lo = (this.lo << 1 ^
|
|
43638
|
+
const mask2 = this.hi >> 31;
|
|
43639
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
43640
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
43641
43641
|
return this;
|
|
43642
43642
|
}
|
|
43643
43643
|
/**
|
|
43644
43644
|
* Zig-zag decodes this long bits
|
|
43645
43645
|
*/
|
|
43646
43646
|
zzDecode() {
|
|
43647
|
-
const
|
|
43648
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
43649
|
-
this.hi = (this.hi >>> 1 ^
|
|
43647
|
+
const mask2 = -(this.lo & 1);
|
|
43648
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
43649
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
43650
43650
|
return this;
|
|
43651
43651
|
}
|
|
43652
43652
|
/**
|
|
@@ -45169,18 +45169,18 @@ ${[...listenStats.errors.entries()].map(([addr, err2]) => {
|
|
|
45169
45169
|
* Zig-zag encodes this long bits
|
|
45170
45170
|
*/
|
|
45171
45171
|
zzEncode() {
|
|
45172
|
-
const
|
|
45173
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
45174
|
-
this.lo = (this.lo << 1 ^
|
|
45172
|
+
const mask2 = this.hi >> 31;
|
|
45173
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
45174
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
45175
45175
|
return this;
|
|
45176
45176
|
}
|
|
45177
45177
|
/**
|
|
45178
45178
|
* Zig-zag decodes this long bits
|
|
45179
45179
|
*/
|
|
45180
45180
|
zzDecode() {
|
|
45181
|
-
const
|
|
45182
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
45183
|
-
this.hi = (this.hi >>> 1 ^
|
|
45181
|
+
const mask2 = -(this.lo & 1);
|
|
45182
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
45183
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
45184
45184
|
return this;
|
|
45185
45185
|
}
|
|
45186
45186
|
/**
|
|
@@ -66360,8 +66360,8 @@ ${[...listenStats.errors.entries()].map(([addr, err2]) => {
|
|
|
66360
66360
|
const view = new DataView(localKadId.buffer, localKadId.byteOffset, localKadId.byteLength);
|
|
66361
66361
|
const localPrefix = view.getUint16(0, false);
|
|
66362
66362
|
const toggledLocalPrefix = localPrefix ^ 32768 >> targetCommonPrefixLength;
|
|
66363
|
-
const
|
|
66364
|
-
const targetPrefix = toggledLocalPrefix &
|
|
66363
|
+
const mask2 = 65535 << 16 - (targetCommonPrefixLength + 1);
|
|
66364
|
+
const targetPrefix = toggledLocalPrefix & mask2 | randomPrefix & ~mask2;
|
|
66365
66365
|
const keyPrefix3 = generated_prefix_list_browser_default[targetPrefix];
|
|
66366
66366
|
const keyBuffer = new ArrayBuffer(34);
|
|
66367
66367
|
const keyView = new DataView(keyBuffer, 0, keyBuffer.byteLength);
|
|
@@ -67641,18 +67641,18 @@ ${[...listenStats.errors.entries()].map(([addr, err2]) => {
|
|
|
67641
67641
|
* Zig-zag encodes this long bits
|
|
67642
67642
|
*/
|
|
67643
67643
|
zzEncode() {
|
|
67644
|
-
const
|
|
67645
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
67646
|
-
this.lo = (this.lo << 1 ^
|
|
67644
|
+
const mask2 = this.hi >> 31;
|
|
67645
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
67646
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
67647
67647
|
return this;
|
|
67648
67648
|
}
|
|
67649
67649
|
/**
|
|
67650
67650
|
* Zig-zag decodes this long bits
|
|
67651
67651
|
*/
|
|
67652
67652
|
zzDecode() {
|
|
67653
|
-
const
|
|
67654
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
67655
|
-
this.hi = (this.hi >>> 1 ^
|
|
67653
|
+
const mask2 = -(this.lo & 1);
|
|
67654
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
67655
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
67656
67656
|
return this;
|
|
67657
67657
|
}
|
|
67658
67658
|
/**
|
|
@@ -75209,18 +75209,18 @@ ${[...listenStats.errors.entries()].map(([addr, err2]) => {
|
|
|
75209
75209
|
* Zig-zag encodes this long bits
|
|
75210
75210
|
*/
|
|
75211
75211
|
zzEncode() {
|
|
75212
|
-
const
|
|
75213
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
75214
|
-
this.lo = (this.lo << 1 ^
|
|
75212
|
+
const mask2 = this.hi >> 31;
|
|
75213
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
75214
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
75215
75215
|
return this;
|
|
75216
75216
|
}
|
|
75217
75217
|
/**
|
|
75218
75218
|
* Zig-zag decodes this long bits
|
|
75219
75219
|
*/
|
|
75220
75220
|
zzDecode() {
|
|
75221
|
-
const
|
|
75222
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
75223
|
-
this.hi = (this.hi >>> 1 ^
|
|
75221
|
+
const mask2 = -(this.lo & 1);
|
|
75222
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
75223
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
75224
75224
|
return this;
|
|
75225
75225
|
}
|
|
75226
75226
|
/**
|
|
@@ -81244,7 +81244,7 @@ ${[...listenStats.errors.entries()].map(([addr, err2]) => {
|
|
|
81244
81244
|
let carry = 0;
|
|
81245
81245
|
let pos = 0;
|
|
81246
81246
|
const max = powers[from6];
|
|
81247
|
-
const
|
|
81247
|
+
const mask2 = powers[to] - 1;
|
|
81248
81248
|
const res = [];
|
|
81249
81249
|
for (const n of data) {
|
|
81250
81250
|
anumber6(n);
|
|
@@ -81255,13 +81255,13 @@ ${[...listenStats.errors.entries()].map(([addr, err2]) => {
|
|
|
81255
81255
|
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from6}`);
|
|
81256
81256
|
pos += from6;
|
|
81257
81257
|
for (; pos >= to; pos -= to)
|
|
81258
|
-
res.push((carry >> pos - to &
|
|
81258
|
+
res.push((carry >> pos - to & mask2) >>> 0);
|
|
81259
81259
|
const pow = powers[pos];
|
|
81260
81260
|
if (pow === void 0)
|
|
81261
81261
|
throw new Error("invalid carry");
|
|
81262
81262
|
carry &= pow - 1;
|
|
81263
81263
|
}
|
|
81264
|
-
carry = carry << to - pos &
|
|
81264
|
+
carry = carry << to - pos & mask2;
|
|
81265
81265
|
if (!padding2 && pos >= from6)
|
|
81266
81266
|
throw new Error("Excess padding");
|
|
81267
81267
|
if (!padding2 && carry > 0)
|
|
@@ -84769,13 +84769,13 @@ zoo`.split("\n");
|
|
|
84769
84769
|
const windows = Math.ceil(scalarBits2 / W2) + 1;
|
|
84770
84770
|
const windowSize = 2 ** (W2 - 1);
|
|
84771
84771
|
const maxNumber = 2 ** W2;
|
|
84772
|
-
const
|
|
84772
|
+
const mask2 = bitMask2(W2);
|
|
84773
84773
|
const shiftBy = BigInt(W2);
|
|
84774
|
-
return { windows, windowSize, mask, maxNumber, shiftBy };
|
|
84774
|
+
return { windows, windowSize, mask: mask2, maxNumber, shiftBy };
|
|
84775
84775
|
}
|
|
84776
84776
|
function calcOffsets2(n, window2, wOpts) {
|
|
84777
|
-
const { windowSize, mask, maxNumber, shiftBy } = wOpts;
|
|
84778
|
-
let wbits = Number(n &
|
|
84777
|
+
const { windowSize, mask: mask2, maxNumber, shiftBy } = wOpts;
|
|
84778
|
+
let wbits = Number(n & mask2);
|
|
84779
84779
|
let nextN = n >> shiftBy;
|
|
84780
84780
|
if (wbits > windowSize) {
|
|
84781
84781
|
wbits -= maxNumber;
|
|
@@ -87666,6 +87666,406 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
87666
87666
|
}
|
|
87667
87667
|
});
|
|
87668
87668
|
|
|
87669
|
+
// src/agents/contacts/grant-payload.ts
|
|
87670
|
+
function canonicalGrantPayload(g) {
|
|
87671
|
+
return JSON.stringify({
|
|
87672
|
+
grantId: g.grantId,
|
|
87673
|
+
identityId: g.identityId,
|
|
87674
|
+
ownerDid: g.ownerDid,
|
|
87675
|
+
level: g.level,
|
|
87676
|
+
channels: g.channels,
|
|
87677
|
+
contactScope: g.contactScope,
|
|
87678
|
+
taskScope: g.taskScope,
|
|
87679
|
+
contentScope: g.contentScope,
|
|
87680
|
+
replyWakeAllowed: g.replyWakeAllowed,
|
|
87681
|
+
autoSend: g.autoSend,
|
|
87682
|
+
sensitiveContentAllowed: g.sensitiveContentAllowed,
|
|
87683
|
+
newRecipientAllowed: g.newRecipientAllowed,
|
|
87684
|
+
grantedAt: g.grantedAt,
|
|
87685
|
+
grantedBy: g.grantedBy,
|
|
87686
|
+
grantedVia: g.grantedVia,
|
|
87687
|
+
deviceIds: [...g.deviceIds].sort(),
|
|
87688
|
+
status: g.status,
|
|
87689
|
+
revokedAt: g.revokedAt || "",
|
|
87690
|
+
grantVersion: g.grantVersion
|
|
87691
|
+
});
|
|
87692
|
+
}
|
|
87693
|
+
function canonicalRevocationPayload(r) {
|
|
87694
|
+
return JSON.stringify({ grantId: r.grantId, grantVersion: r.grantVersion, revokedAt: r.revokedAt, by: r.by });
|
|
87695
|
+
}
|
|
87696
|
+
function presetForChoice(choice) {
|
|
87697
|
+
const base6 = { channels: "both", replyWakeAllowed: true, autoSend: true, newRecipientAllowed: false };
|
|
87698
|
+
switch (choice) {
|
|
87699
|
+
case "task_once":
|
|
87700
|
+
return { ...base6, level: "task_once", contactScope: "verified_contacts", taskScope: "current_goal", contentScope: "normal", autoSend: false, sensitiveContentAllowed: false };
|
|
87701
|
+
case "persistent":
|
|
87702
|
+
return { ...base6, level: "persistent", contactScope: "verified_contacts", taskScope: "all_future_goals", contentScope: "normal", sensitiveContentAllowed: false };
|
|
87703
|
+
case "full_contact_access":
|
|
87704
|
+
return { ...base6, level: "full_contact_access", contactScope: "all_contacts", taskScope: "all_future_goals", contentScope: "sensitive", sensitiveContentAllowed: true };
|
|
87705
|
+
}
|
|
87706
|
+
}
|
|
87707
|
+
var init_grant_payload = __esm({
|
|
87708
|
+
"src/agents/contacts/grant-payload.ts"() {
|
|
87709
|
+
"use strict";
|
|
87710
|
+
}
|
|
87711
|
+
});
|
|
87712
|
+
|
|
87713
|
+
// src/web/mobile-contacts.ts
|
|
87714
|
+
var mobile_contacts_exports = {};
|
|
87715
|
+
__export(mobile_contacts_exports, {
|
|
87716
|
+
authorizeFromPhone: () => authorizeFromPhone,
|
|
87717
|
+
bindFromPhone: () => bindFromPhone,
|
|
87718
|
+
buildPhoneCard: () => buildPhoneCard,
|
|
87719
|
+
decideApprovalFromPhone: () => decideApprovalFromPhone,
|
|
87720
|
+
ed25519Available: () => ed25519Available,
|
|
87721
|
+
flushQueuedGrants: () => flushQueuedGrants,
|
|
87722
|
+
loadCapabilityCopy: () => loadCapabilityCopy,
|
|
87723
|
+
loadFromDesktop: () => loadFromDesktop,
|
|
87724
|
+
loadOrCreateDeviceKey: () => loadOrCreateDeviceKey,
|
|
87725
|
+
pendingQueue: () => pendingQueue,
|
|
87726
|
+
registerDeviceOnDesktop: () => registerDeviceOnDesktop,
|
|
87727
|
+
revokeFromPhone: () => revokeFromPhone,
|
|
87728
|
+
saveCapabilityCopy: () => saveCapabilityCopy,
|
|
87729
|
+
sha256HexOf: () => sha256HexOf,
|
|
87730
|
+
signGrantOnDevice: () => signGrantOnDevice,
|
|
87731
|
+
signPayloadOnDevice: () => signPayloadOnDevice,
|
|
87732
|
+
signPayloadWithMaterial: () => signPayloadWithMaterial,
|
|
87733
|
+
signRevocationOnDevice: () => signRevocationOnDevice,
|
|
87734
|
+
verifyFromPhone: () => verifyFromPhone
|
|
87735
|
+
});
|
|
87736
|
+
function ed25519Available(c) {
|
|
87737
|
+
const cobj = cryptoOf(c);
|
|
87738
|
+
if (!cobj?.subtle) return false;
|
|
87739
|
+
try {
|
|
87740
|
+
const alg = { name: "Ed25519" };
|
|
87741
|
+
return typeof cobj.subtle.importKey === "function" && !!alg;
|
|
87742
|
+
} catch {
|
|
87743
|
+
return false;
|
|
87744
|
+
}
|
|
87745
|
+
}
|
|
87746
|
+
function bytesOf(s2) {
|
|
87747
|
+
const src4 = new TextEncoder().encode(s2);
|
|
87748
|
+
const out = new Uint8Array(new ArrayBuffer(src4.byteLength));
|
|
87749
|
+
out.set(src4);
|
|
87750
|
+
return out;
|
|
87751
|
+
}
|
|
87752
|
+
function b64(buf) {
|
|
87753
|
+
const arr = new Uint8Array(buf);
|
|
87754
|
+
let out = "";
|
|
87755
|
+
for (let i = 0; i < arr.length; i++) out += String.fromCharCode(arr[i]);
|
|
87756
|
+
return btoa(out);
|
|
87757
|
+
}
|
|
87758
|
+
function pemFromSpki(spki) {
|
|
87759
|
+
const b = b64(spki).replace(/(.{64})/g, "$1\n").trim();
|
|
87760
|
+
return `-----BEGIN PUBLIC KEY-----
|
|
87761
|
+
${b}
|
|
87762
|
+
-----END PUBLIC KEY-----
|
|
87763
|
+
`;
|
|
87764
|
+
}
|
|
87765
|
+
async function sha256Hex(c, text) {
|
|
87766
|
+
const d2 = await c.subtle.digest("SHA-256", bytesOf(text));
|
|
87767
|
+
return [...new Uint8Array(d2)].map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
87768
|
+
}
|
|
87769
|
+
async function loadOrCreateDeviceKey(storage2, c) {
|
|
87770
|
+
const cobj = cryptoOf(c);
|
|
87771
|
+
if (!cobj?.subtle) throw new Error("device_signing_unavailable: \u672C\u673A\u6CA1\u6709 WebCrypto");
|
|
87772
|
+
const raw = storage2.getItem(K_DEVICE);
|
|
87773
|
+
if (raw) {
|
|
87774
|
+
try {
|
|
87775
|
+
const parsed = JSON.parse(raw);
|
|
87776
|
+
if (parsed?.privateKeyJwk && parsed?.publicKeyPem && parsed?.deviceId) return parsed;
|
|
87777
|
+
} catch {
|
|
87778
|
+
}
|
|
87779
|
+
}
|
|
87780
|
+
let pair;
|
|
87781
|
+
try {
|
|
87782
|
+
pair = await cobj.subtle.generateKey({ name: "Ed25519" }, true, ["sign", "verify"]);
|
|
87783
|
+
} catch (err2) {
|
|
87784
|
+
throw new Error(`device_signing_unavailable: ${String(err2?.message || err2)}`);
|
|
87785
|
+
}
|
|
87786
|
+
const publicKeyPem = pemFromSpki(await cobj.subtle.exportKey("spki", pair.publicKey));
|
|
87787
|
+
const privateKeyJwk = await cobj.subtle.exportKey("jwk", pair.privateKey);
|
|
87788
|
+
const deviceId = `dev-${(await sha256Hex(cobj, publicKeyPem)).slice(0, 12)}`;
|
|
87789
|
+
const material = { deviceId, publicKeyPem, privateKeyJwk };
|
|
87790
|
+
storage2.setItem(K_DEVICE, JSON.stringify(material));
|
|
87791
|
+
return material;
|
|
87792
|
+
}
|
|
87793
|
+
async function signGrantOnDevice(grant, storage2, c) {
|
|
87794
|
+
return signPayloadOnDevice(canonicalGrantPayload(grant), storage2, c);
|
|
87795
|
+
}
|
|
87796
|
+
async function signRevocationOnDevice(rev, storage2, c) {
|
|
87797
|
+
return signPayloadOnDevice(canonicalRevocationPayload(rev), storage2, c);
|
|
87798
|
+
}
|
|
87799
|
+
async function signPayloadOnDevice(payload, storage2, c) {
|
|
87800
|
+
const cobj = cryptoOf(c);
|
|
87801
|
+
if (!cobj?.subtle) throw new Error("device_signing_unavailable: \u672C\u673A\u6CA1\u6709 WebCrypto");
|
|
87802
|
+
const material = await loadOrCreateDeviceKey(storage2, cobj);
|
|
87803
|
+
const key = await cobj.subtle.importKey("jwk", material.privateKeyJwk, { name: "Ed25519" }, false, ["sign"]);
|
|
87804
|
+
const bytes = bytesOf(String(payload ?? ""));
|
|
87805
|
+
const sig = await cobj.subtle.sign({ name: "Ed25519" }, key, bytes);
|
|
87806
|
+
return { deviceId: material.deviceId, alg: "ed25519", payloadHash: await sha256Hex(cobj, String(payload ?? "")), sig: b64(sig) };
|
|
87807
|
+
}
|
|
87808
|
+
async function sha256HexOf(text, c) {
|
|
87809
|
+
const cobj = cryptoOf(c);
|
|
87810
|
+
if (!cobj?.subtle) throw new Error("device_signing_unavailable: \u672C\u673A\u6CA1\u6709 WebCrypto");
|
|
87811
|
+
return sha256Hex(cobj, String(text ?? ""));
|
|
87812
|
+
}
|
|
87813
|
+
async function signPayloadWithMaterial(payload, material, c) {
|
|
87814
|
+
const cobj = cryptoOf(c);
|
|
87815
|
+
if (!cobj?.subtle) throw new Error("device_signing_unavailable: \u672C\u673A\u6CA1\u6709 WebCrypto");
|
|
87816
|
+
const key = await cobj.subtle.importKey("jwk", material.privateKeyJwk, { name: "Ed25519" }, false, ["sign"]);
|
|
87817
|
+
const sig = await cobj.subtle.sign({ name: "Ed25519" }, key, bytesOf(String(payload ?? "")));
|
|
87818
|
+
return { deviceId: material.deviceId, alg: "ed25519", payloadHash: await sha256Hex(cobj, String(payload ?? "")), sig: b64(sig) };
|
|
87819
|
+
}
|
|
87820
|
+
async function post(base6, path, body, f) {
|
|
87821
|
+
const res = await f(`${String(base6).replace(/\/+$/, "")}${path}`, {
|
|
87822
|
+
method: "POST",
|
|
87823
|
+
headers: { "Content-Type": "application/json" },
|
|
87824
|
+
body: JSON.stringify(body ?? {})
|
|
87825
|
+
});
|
|
87826
|
+
let json = null;
|
|
87827
|
+
try {
|
|
87828
|
+
json = await res.json();
|
|
87829
|
+
} catch {
|
|
87830
|
+
}
|
|
87831
|
+
return { status: res.status, json };
|
|
87832
|
+
}
|
|
87833
|
+
async function get(base6, path, f) {
|
|
87834
|
+
const res = await f(`${String(base6).replace(/\/+$/, "")}${path}`);
|
|
87835
|
+
let json = null;
|
|
87836
|
+
try {
|
|
87837
|
+
json = await res.json();
|
|
87838
|
+
} catch {
|
|
87839
|
+
}
|
|
87840
|
+
return { status: res.status, json };
|
|
87841
|
+
}
|
|
87842
|
+
async function registerDeviceOnDesktop(base6, storage2, opts = {}) {
|
|
87843
|
+
const f = opts.fetchImpl || fetch;
|
|
87844
|
+
const dev = await loadOrCreateDeviceKey(storage2, opts.cryptoObj);
|
|
87845
|
+
const r = await post(base6, "/api/contacts/devices", { deviceId: dev.deviceId, publicKeyPem: dev.publicKeyPem, label: opts.label || "\u624B\u673A" }, f);
|
|
87846
|
+
if (r.status !== 200 || !r.json?.ok) return { ok: false, error: `\u684C\u9762\u672A\u63A5\u53D7\u8BBE\u5907\u767B\u8BB0: ${r.json?.error || r.status}`, data: dev };
|
|
87847
|
+
return { ok: true, data: dev };
|
|
87848
|
+
}
|
|
87849
|
+
function saveCapabilityCopy(storage2, items) {
|
|
87850
|
+
const clean8 = (items || []).map((c) => ({
|
|
87851
|
+
contactId: String(c.contactId || ""),
|
|
87852
|
+
kind: c.kind,
|
|
87853
|
+
displayValue: String(c.displayValue || ""),
|
|
87854
|
+
verificationStatus: String(c.verificationStatus || ""),
|
|
87855
|
+
capabilities: [...c.capabilities || []],
|
|
87856
|
+
provider: c.provider ? String(c.provider) : void 0,
|
|
87857
|
+
state: c.state ? String(c.state) : void 0
|
|
87858
|
+
}));
|
|
87859
|
+
storage2.setItem(K_CAPS, JSON.stringify(clean8));
|
|
87860
|
+
}
|
|
87861
|
+
function loadCapabilityCopy(storage2) {
|
|
87862
|
+
try {
|
|
87863
|
+
const v = JSON.parse(storage2.getItem(K_CAPS) || "[]");
|
|
87864
|
+
return Array.isArray(v) ? v : [];
|
|
87865
|
+
} catch {
|
|
87866
|
+
return [];
|
|
87867
|
+
}
|
|
87868
|
+
}
|
|
87869
|
+
function pendingQueue(storage2) {
|
|
87870
|
+
try {
|
|
87871
|
+
const v = JSON.parse(storage2.getItem(K_QUEUE) || "[]");
|
|
87872
|
+
return Array.isArray(v) ? v : [];
|
|
87873
|
+
} catch {
|
|
87874
|
+
return [];
|
|
87875
|
+
}
|
|
87876
|
+
}
|
|
87877
|
+
function setQueue(storage2, q) {
|
|
87878
|
+
storage2.setItem(K_QUEUE, JSON.stringify(q.slice(-20)));
|
|
87879
|
+
}
|
|
87880
|
+
async function flushQueuedGrants(base6, storage2, opts = {}) {
|
|
87881
|
+
const f = opts.fetchImpl || fetch;
|
|
87882
|
+
const q = pendingQueue(storage2);
|
|
87883
|
+
const keep = [];
|
|
87884
|
+
const results = [];
|
|
87885
|
+
let sent = 0, failed = 0;
|
|
87886
|
+
for (const item of q) {
|
|
87887
|
+
try {
|
|
87888
|
+
const r = await post(base6, "/api/contacts/grants/sync", { grant: { ...item.grant, signature: item.signature } }, f);
|
|
87889
|
+
if (r.status === 200 && r.json?.ok) {
|
|
87890
|
+
sent++;
|
|
87891
|
+
results.push({ grantId: item.grant.grantId, ok: true });
|
|
87892
|
+
continue;
|
|
87893
|
+
}
|
|
87894
|
+
failed++;
|
|
87895
|
+
keep.push(item);
|
|
87896
|
+
results.push({ grantId: item.grant.grantId, ok: false, error: r.json?.code || r.status });
|
|
87897
|
+
} catch {
|
|
87898
|
+
failed++;
|
|
87899
|
+
keep.push(item);
|
|
87900
|
+
results.push({ grantId: item.grant.grantId, ok: false, error: "network" });
|
|
87901
|
+
}
|
|
87902
|
+
}
|
|
87903
|
+
setQueue(storage2, keep);
|
|
87904
|
+
return { sent, failed, results };
|
|
87905
|
+
}
|
|
87906
|
+
async function authorizeFromPhone(input) {
|
|
87907
|
+
const c = cryptoOf(input.cryptoObj);
|
|
87908
|
+
if (!ed25519Available(c || void 0)) {
|
|
87909
|
+
return { ok: false, error: "device_signing_unavailable: \u672C\u673A WebView \u4E0D\u652F\u6301 Ed25519 \u8BBE\u5907\u7B7E\u540D \u2014\u2014 \u8BF7\u5728\u684C\u9762\u7AEF\u6388\u6743 (\u6216\u5347\u7EA7\u7CFB\u7EDF WebView)" };
|
|
87910
|
+
}
|
|
87911
|
+
const dev = await loadOrCreateDeviceKey(input.storage, c);
|
|
87912
|
+
const preset = presetForChoice(input.choice);
|
|
87913
|
+
const grant = {
|
|
87914
|
+
grantId: `gr-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
87915
|
+
identityId: input.identityId || `sid-phone-${dev.deviceId.slice(-6)}`,
|
|
87916
|
+
ownerDid: input.ownerDid,
|
|
87917
|
+
...preset,
|
|
87918
|
+
grantedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
87919
|
+
grantedBy: input.grantedBy || "leo",
|
|
87920
|
+
grantedVia: "mobile",
|
|
87921
|
+
deviceIds: [dev.deviceId],
|
|
87922
|
+
status: "active",
|
|
87923
|
+
grantVersion: 1
|
|
87924
|
+
};
|
|
87925
|
+
const signature = await signGrantOnDevice(grant, input.storage, c);
|
|
87926
|
+
const f = input.fetchImpl || fetch;
|
|
87927
|
+
const reg = await registerDeviceOnDesktop(input.base, input.storage, { fetchImpl: f, cryptoObj: c }).catch(() => ({ ok: false }));
|
|
87928
|
+
if (!reg.ok) {
|
|
87929
|
+
const q2 = pendingQueue(input.storage);
|
|
87930
|
+
q2.push({ grant, signature, queuedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
87931
|
+
setQueue(input.storage, q2);
|
|
87932
|
+
return {
|
|
87933
|
+
ok: false,
|
|
87934
|
+
queued: true,
|
|
87935
|
+
error: `\u684C\u9762\u6682\u4E0D\u53EF\u8FBE \u2192 \u6388\u6743\u5DF2\u5B58\u5728\u624B\u673A, \u5F85\u684C\u9762\u5728\u7EBF\u65F6\u81EA\u52A8\u540C\u6B65 (${reg.error || "offline"})`,
|
|
87936
|
+
data: { grantId: grant.grantId, level: grant.level, signature },
|
|
87937
|
+
note: "\u684C\u9762\u4E0D\u5728\u7EBF\u65F6\u4E0D\u5047\u88C5\u5DF2\u751F\u6548: \u6388\u6743\u5728\u672C\u5730\u961F\u5217\u91CC, \u684C\u9762\u4E00\u4E0A\u7EBF\u5C31\u8865\u540C\u6B65"
|
|
87938
|
+
};
|
|
87939
|
+
}
|
|
87940
|
+
const r = await post(input.base, "/api/contacts/grants/sync", { grant: { ...grant, signature } }, f);
|
|
87941
|
+
if (r.status === 200 && r.json?.ok) {
|
|
87942
|
+
return { ok: true, data: { grantId: grant.grantId, level: grant.level, signature }, note: "\u684C\u9762\u5DF2\u9A8C\u7B7E\u63A5\u53D7" };
|
|
87943
|
+
}
|
|
87944
|
+
const q = pendingQueue(input.storage);
|
|
87945
|
+
q.push({ grant, signature, queuedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
87946
|
+
setQueue(input.storage, q);
|
|
87947
|
+
return {
|
|
87948
|
+
ok: false,
|
|
87949
|
+
queued: true,
|
|
87950
|
+
error: `\u684C\u9762\u62D2\u7EDD/\u672A\u63A5\u53D7: ${r.json?.code || r.json?.reason || r.status}`,
|
|
87951
|
+
data: { grantId: grant.grantId, level: grant.level, signature },
|
|
87952
|
+
note: "\u5DF2\u4FDD\u5B58\u5728\u624B\u673A\u672C\u5730\u961F\u5217 (\u4E0D\u4F1A\u56E0\u4E3A\u5931\u8D25\u5C31\u5F53\u6210\u5DF2\u6388\u6743)"
|
|
87953
|
+
};
|
|
87954
|
+
}
|
|
87955
|
+
async function revokeFromPhone(opts) {
|
|
87956
|
+
const c = cryptoOf(opts.cryptoObj);
|
|
87957
|
+
if (!ed25519Available(c || void 0)) return { ok: false, error: "device_signing_unavailable: \u672C\u673A\u4E0D\u652F\u6301\u8BBE\u5907\u7B7E\u540D, \u64A4\u9500\u9700\u5728\u684C\u9762\u7AEF\u8FDB\u884C" };
|
|
87958
|
+
const revokedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
87959
|
+
const payload = { grantId: opts.grantId, grantVersion: opts.version || 1, revokedAt, by: "mobile" };
|
|
87960
|
+
const signature = await signRevocationOnDevice(payload, opts.storage, c);
|
|
87961
|
+
const f = opts.fetchImpl || fetch;
|
|
87962
|
+
const r = await post(opts.base, "/api/contacts/grants/revoke-sync", { grantId: opts.grantId, by: "mobile", reason: opts.reason, version: payload.grantVersion, revokedAt, signature }, f);
|
|
87963
|
+
if (r.status === 200 && r.json?.ok) return { ok: true, data: { grantId: opts.grantId }, note: "\u684C\u9762\u5DF2\u9A8C\u7B7E\u5E76\u7ACB\u5373\u5931\u6548" };
|
|
87964
|
+
return { ok: false, error: `\u64A4\u9500\u672A\u9001\u8FBE: ${r.json?.code || r.json?.error || r.status}`, note: "\u684C\u9762\u4E0D\u5728\u7EBF\u65F6\u64A4\u9500**\u4E0D\u4F1A**\u88AB\u5F53\u4F5C\u5DF2\u5B8C\u6210 \u2014\u2014 \u8BF7\u5728\u684C\u9762\u5728\u7EBF\u540E\u91CD\u8BD5 (\u6216\u684C\u9762\u7AEF\u64A4\u9500)" };
|
|
87965
|
+
}
|
|
87966
|
+
async function loadFromDesktop(base6, storage2, opts = {}) {
|
|
87967
|
+
const f = opts.fetchImpl || fetch;
|
|
87968
|
+
if (!base6) {
|
|
87969
|
+
const caps = loadCapabilityCopy(storage2);
|
|
87970
|
+
return {
|
|
87971
|
+
ok: false,
|
|
87972
|
+
error: "desktop_offline",
|
|
87973
|
+
data: { contacts: caps, grants: [], effective: "\u684C\u9762\u4E0D\u5728\u7EBF (\u663E\u793A\u624B\u673A\u672C\u5730\u526F\u672C)", approvals: [], waiting: [] },
|
|
87974
|
+
note: "\u4EE5\u4E0B\u662F\u4F60\u624B\u673A\u4E0A\u4FDD\u5B58\u7684\u80FD\u529B\u526F\u672C (\u4E0D\u662F\u684C\u9762\u5B9E\u65F6\u72B6\u6001)"
|
|
87975
|
+
};
|
|
87976
|
+
}
|
|
87977
|
+
try {
|
|
87978
|
+
const a = await get(base6, "/api/contacts", f);
|
|
87979
|
+
const b = await get(base6, "/api/contacts/grants", f);
|
|
87980
|
+
if (a.status !== 200 && b.status !== 200) return { ok: false, error: `desktop_http_${a.status || b.status}` };
|
|
87981
|
+
const view = {
|
|
87982
|
+
contacts: a.json?.contacts || [],
|
|
87983
|
+
grants: b.json?.grants || [],
|
|
87984
|
+
effective: b.json?.effective || "",
|
|
87985
|
+
approvals: a.json?.approvals || [],
|
|
87986
|
+
waiting: a.json?.waiting || []
|
|
87987
|
+
};
|
|
87988
|
+
saveCapabilityCopy(storage2, (view.contacts || []).filter((c) => c.capabilities?.includes("send")).map((c) => ({
|
|
87989
|
+
contactId: c.contactId,
|
|
87990
|
+
kind: c.kind,
|
|
87991
|
+
displayValue: c.displayValue,
|
|
87992
|
+
verificationStatus: c.status,
|
|
87993
|
+
capabilities: c.capabilities,
|
|
87994
|
+
provider: c.provider,
|
|
87995
|
+
state: c.status
|
|
87996
|
+
})));
|
|
87997
|
+
return { ok: true, data: view };
|
|
87998
|
+
} catch (err2) {
|
|
87999
|
+
const caps = loadCapabilityCopy(storage2);
|
|
88000
|
+
return {
|
|
88001
|
+
ok: false,
|
|
88002
|
+
error: "desktop_offline",
|
|
88003
|
+
data: { contacts: caps, grants: [], effective: "\u684C\u9762\u4E0D\u5728\u7EBF (\u663E\u793A\u624B\u673A\u672C\u5730\u526F\u672C)", approvals: [], waiting: [] },
|
|
88004
|
+
note: `\u8FDE\u4E0D\u4E0A\u684C\u9762 (${String(err2?.message || err2).slice(0, 60)}) \u2014\u2014 \u663E\u793A\u672C\u5730\u526F\u672C`
|
|
88005
|
+
};
|
|
88006
|
+
}
|
|
88007
|
+
}
|
|
88008
|
+
async function bindFromPhone(base6, opts, storage2, f) {
|
|
88009
|
+
const impl = f || fetch;
|
|
88010
|
+
if (!base6) return { ok: false, error: "desktop_offline: \u7ED1\u5B9A\u9700\u8981\u684C\u9762\u7AEF\u5728\u7EBF (\u684C\u9762\u8D1F\u8D23\u843D\u76D8\u4E0E\u9A8C\u8BC1\u7801\u901A\u9053)" };
|
|
88011
|
+
const r = await post(base6, "/api/contacts/bind", { kind: opts.kind, value: opts.value, region: opts.region }, impl);
|
|
88012
|
+
if (r.status === 200 && r.json?.ok) return { ok: true, data: r.json };
|
|
88013
|
+
return { ok: false, error: r.json?.error || `HTTP ${r.status}` };
|
|
88014
|
+
}
|
|
88015
|
+
async function verifyFromPhone(base6, opts, storage2, f) {
|
|
88016
|
+
const impl = f || fetch;
|
|
88017
|
+
if (!base6) return { ok: false, error: "desktop_offline: \u9A8C\u8BC1\u9700\u8981\u684C\u9762\u7AEF\u5728\u7EBF" };
|
|
88018
|
+
const r = await post(base6, "/api/contacts/verify", { contactId: opts.contactId, challengeId: opts.challengeId, code: opts.code }, impl);
|
|
88019
|
+
if (r.status === 200 && r.json?.ok) return { ok: true, data: r.json };
|
|
88020
|
+
return { ok: false, error: r.json?.error || `HTTP ${r.status}` };
|
|
88021
|
+
}
|
|
88022
|
+
async function decideApprovalFromPhone(base6, opts, f) {
|
|
88023
|
+
const impl = f || fetch;
|
|
88024
|
+
if (!base6) return { ok: false, error: "desktop_offline: \u6279\u51C6\u9700\u8981\u684C\u9762\u7AEF\u5728\u7EBF (\u624B\u673A\u4E0D\u5728\u7EBF\u65F6\u4E0D\u4F1A\u5047\u88C5\u5DF2\u6279\u51C6)" };
|
|
88025
|
+
const r = await post(base6, `/api/contacts/approvals/${encodeURIComponent(opts.consentId)}/${opts.action}`, { by: "leo", via: "mobile", body: opts.body, reason: opts.reason }, impl);
|
|
88026
|
+
if (r.status === 200 && r.json?.ok) return { ok: true, data: r.json };
|
|
88027
|
+
return { ok: false, error: r.json?.error || `HTTP ${r.status}` };
|
|
88028
|
+
}
|
|
88029
|
+
function buildPhoneCard(view, opts) {
|
|
88030
|
+
return {
|
|
88031
|
+
title: "\u8BA9 Bolloon \u4EE3\u8868\u4F60\u8054\u7CFB\u5916\u90E8\u7684\u4EBA",
|
|
88032
|
+
effective: view?.effective || opts.offline || "\u672A\u77E5",
|
|
88033
|
+
contacts: (view?.contacts || []).map((c) => ({
|
|
88034
|
+
displayValue: c.displayValue || "",
|
|
88035
|
+
kind: c.kind || "",
|
|
88036
|
+
state: c.status || c.verificationStatus || "",
|
|
88037
|
+
label: c.capabilities?.includes("send") ? "\u53EF\u8054\u7CFB" : "\u4E0D\u53EF\u8054\u7CFB"
|
|
88038
|
+
})),
|
|
88039
|
+
approvals: (view?.approvals || []).map((a) => ({
|
|
88040
|
+
consentId: a.consentId,
|
|
88041
|
+
contactName: a.contactName,
|
|
88042
|
+
channel: a.channel,
|
|
88043
|
+
subject: a.subject,
|
|
88044
|
+
bodyPreview: a.bodyPreview || "",
|
|
88045
|
+
reason: a.reason,
|
|
88046
|
+
reallySent: !!a.reallySent
|
|
88047
|
+
})),
|
|
88048
|
+
choices: [
|
|
88049
|
+
{ id: "task_once", label: "\u4EC5\u672C\u6B21\u4EFB\u52A1" },
|
|
88050
|
+
{ id: "persistent", label: "\u957F\u671F\u4F7F\u7528 (\u63A8\u8350)" },
|
|
88051
|
+
{ id: "full_contact_access", label: "\u5B8C\u5168\u6388\u6743\u8054\u7CFB\u65B9\u5F0F\u80FD\u529B" }
|
|
88052
|
+
],
|
|
88053
|
+
willNotGet: ["\u8BFB\u53D6\u5168\u90E8\u90AE\u7BB1", "\u8BFB\u53D6\u901A\u8BAF\u5F55", "\u7FA4\u53D1\u6D88\u606F", "\u81EA\u52A8\u652F\u4ED8/\u8F6C\u8D26", "\u4EE3\u8868\u4F60\u7B7E\u7F72\u5408\u540C", "\u62FF\u5230\u624B\u673A\u53F7/\u90AE\u7BB1\u660E\u6587"],
|
|
88054
|
+
deviceSigning: opts.deviceSigning
|
|
88055
|
+
};
|
|
88056
|
+
}
|
|
88057
|
+
var K_DEVICE, K_QUEUE, K_CAPS, cryptoOf;
|
|
88058
|
+
var init_mobile_contacts = __esm({
|
|
88059
|
+
"src/web/mobile-contacts.ts"() {
|
|
88060
|
+
"use strict";
|
|
88061
|
+
init_grant_payload();
|
|
88062
|
+
K_DEVICE = "bolloon.contacts.device.v1";
|
|
88063
|
+
K_QUEUE = "bolloon.contacts.queue.v1";
|
|
88064
|
+
K_CAPS = "bolloon.contacts.capabilities.v1";
|
|
88065
|
+
cryptoOf = (c) => c || globalThis.crypto || null;
|
|
88066
|
+
}
|
|
88067
|
+
});
|
|
88068
|
+
|
|
87669
88069
|
// src/web/mobile-social.ts
|
|
87670
88070
|
var mobile_social_exports = {};
|
|
87671
88071
|
__export(mobile_social_exports, {
|
|
@@ -88980,7 +89380,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
88980
89380
|
});
|
|
88981
89381
|
|
|
88982
89382
|
// node_modules/viem/_esm/utils/encoding/toHex.js
|
|
88983
|
-
function
|
|
89383
|
+
function toHex2(value2, opts = {}) {
|
|
88984
89384
|
if (typeof value2 === "number" || typeof value2 === "bigint")
|
|
88985
89385
|
return numberToHex(value2, opts);
|
|
88986
89386
|
if (typeof value2 === "string") {
|
|
@@ -90103,13 +90503,13 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
90103
90503
|
const windows = Math.ceil(scalarBits2 / W2) + 1;
|
|
90104
90504
|
const windowSize = 2 ** (W2 - 1);
|
|
90105
90505
|
const maxNumber = 2 ** W2;
|
|
90106
|
-
const
|
|
90506
|
+
const mask2 = bitMask3(W2);
|
|
90107
90507
|
const shiftBy = BigInt(W2);
|
|
90108
|
-
return { windows, windowSize, mask, maxNumber, shiftBy };
|
|
90508
|
+
return { windows, windowSize, mask: mask2, maxNumber, shiftBy };
|
|
90109
90509
|
}
|
|
90110
90510
|
function calcOffsets3(n, window2, wOpts) {
|
|
90111
|
-
const { windowSize, mask, maxNumber, shiftBy } = wOpts;
|
|
90112
|
-
let wbits = Number(n &
|
|
90511
|
+
const { windowSize, mask: mask2, maxNumber, shiftBy } = wOpts;
|
|
90512
|
+
let wbits = Number(n & mask2);
|
|
90113
90513
|
let nextN = n >> shiftBy;
|
|
90114
90514
|
if (wbits > windowSize) {
|
|
90115
90515
|
wbits -= maxNumber;
|
|
@@ -91555,7 +91955,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
91555
91955
|
const bytes = keccak_2562(isHex(value2, { strict: false }) ? toBytes3(value2) : value2);
|
|
91556
91956
|
if (to === "bytes")
|
|
91557
91957
|
return bytes;
|
|
91558
|
-
return
|
|
91958
|
+
return toHex2(bytes);
|
|
91559
91959
|
}
|
|
91560
91960
|
var init_keccak256 = __esm({
|
|
91561
91961
|
"node_modules/viem/_esm/utils/hash/keccak256.js"() {
|
|
@@ -92241,9 +92641,9 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
92241
92641
|
const { chainId, nonce, ...signature } = authorization;
|
|
92242
92642
|
const contractAddress = authorization.address;
|
|
92243
92643
|
serializedAuthorizationList.push([
|
|
92244
|
-
chainId ?
|
|
92644
|
+
chainId ? toHex2(chainId) : "0x",
|
|
92245
92645
|
contractAddress,
|
|
92246
|
-
nonce ?
|
|
92646
|
+
nonce ? toHex2(nonce) : "0x",
|
|
92247
92647
|
...toYParitySignatureArray({}, signature)
|
|
92248
92648
|
]);
|
|
92249
92649
|
}
|
|
@@ -92309,7 +92709,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
92309
92709
|
const bytes = sha2568(isHex(value2, { strict: false }) ? toBytes3(value2) : value2);
|
|
92310
92710
|
if (to === "bytes")
|
|
92311
92711
|
return bytes;
|
|
92312
|
-
return
|
|
92712
|
+
return toHex2(bytes);
|
|
92313
92713
|
}
|
|
92314
92714
|
var init_sha2562 = __esm({
|
|
92315
92715
|
"node_modules/viem/_esm/utils/hash/sha256.js"() {
|
|
@@ -93758,7 +94158,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
93758
94158
|
return encodeAbiParameters(encodedTypes, encodedValues);
|
|
93759
94159
|
}
|
|
93760
94160
|
function hashType({ primaryType, types }) {
|
|
93761
|
-
const encodedHashType =
|
|
94161
|
+
const encodedHashType = toHex2(encodeType({ primaryType, types }));
|
|
93762
94162
|
return keccak256(encodedHashType);
|
|
93763
94163
|
}
|
|
93764
94164
|
function encodeType({ primaryType, types }) {
|
|
@@ -93793,7 +94193,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
93793
94193
|
if (type === "bytes")
|
|
93794
94194
|
return [{ type: "bytes32" }, keccak256(value2)];
|
|
93795
94195
|
if (type === "string")
|
|
93796
|
-
return [{ type: "bytes32" }, keccak256(
|
|
94196
|
+
return [{ type: "bytes32" }, keccak256(toHex2(value2))];
|
|
93797
94197
|
if (type.lastIndexOf("]") === type.length - 1) {
|
|
93798
94198
|
const parsedType = type.slice(0, type.lastIndexOf("["));
|
|
93799
94199
|
const typeValuePairs = value2.map((item) => encodeField({
|
|
@@ -93838,7 +94238,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
93838
94238
|
// node_modules/viem/_esm/accounts/privateKeyToAccount.js
|
|
93839
94239
|
function privateKeyToAccount(privateKey, options2 = {}) {
|
|
93840
94240
|
const { nonceManager } = options2;
|
|
93841
|
-
const publicKey2 =
|
|
94241
|
+
const publicKey2 = toHex2(secp256k13.getPublicKey(privateKey.slice(2), false));
|
|
93842
94242
|
const address = publicKeyToAddress(publicKey2);
|
|
93843
94243
|
const account = toAccount({
|
|
93844
94244
|
address,
|
|
@@ -94318,7 +94718,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
94318
94718
|
} else {
|
|
94319
94719
|
for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);
|
|
94320
94720
|
}
|
|
94321
|
-
return
|
|
94721
|
+
return toHex2(bytes);
|
|
94322
94722
|
}
|
|
94323
94723
|
function bytesToBase64(bytes) {
|
|
94324
94724
|
let out = "";
|
|
@@ -94569,7 +94969,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
94569
94969
|
}
|
|
94570
94970
|
}
|
|
94571
94971
|
function deriveTokenId(agentId, serviceName) {
|
|
94572
|
-
return BigInt(keccak256(
|
|
94972
|
+
return BigInt(keccak256(toHex2(`${agentId}:${serviceName}`)));
|
|
94573
94973
|
}
|
|
94574
94974
|
async function registerServiceOnChain(params) {
|
|
94575
94975
|
try {
|
|
@@ -95154,10 +95554,10 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
95154
95554
|
let f = G;
|
|
95155
95555
|
const pow_2_w = 2 ** W;
|
|
95156
95556
|
const maxNum = pow_2_w;
|
|
95157
|
-
const
|
|
95557
|
+
const mask2 = big(pow_2_w - 1);
|
|
95158
95558
|
const shiftBy = big(W);
|
|
95159
95559
|
for (let w2 = 0; w2 < pwindows; w2++) {
|
|
95160
|
-
let wbits = Number(n &
|
|
95560
|
+
let wbits = Number(n & mask2);
|
|
95161
95561
|
n >>= shiftBy;
|
|
95162
95562
|
if (wbits > pwindowSize) {
|
|
95163
95563
|
wbits -= maxNum;
|
|
@@ -96895,11 +97295,11 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
96895
97295
|
function toToken6(data, pos, prefix, length20, options2) {
|
|
96896
97296
|
const totLength = prefix + length20;
|
|
96897
97297
|
assertEnoughData2(data, pos, totLength);
|
|
96898
|
-
const
|
|
97298
|
+
const tok2 = new Token2(Type2.string, toStr2(data, pos + prefix, pos + totLength), totLength);
|
|
96899
97299
|
if (options2.retainStringBytes === true) {
|
|
96900
|
-
|
|
97300
|
+
tok2.byteValue = data.slice(pos + prefix, pos + totLength);
|
|
96901
97301
|
}
|
|
96902
|
-
return
|
|
97302
|
+
return tok2;
|
|
96903
97303
|
}
|
|
96904
97304
|
function decodeStringCompact2(data, pos, minor, options2) {
|
|
96905
97305
|
return toToken6(data, pos, 1, minor, options2);
|
|
@@ -98382,7 +98782,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
98382
98782
|
}
|
|
98383
98783
|
function encode15(data, alphabet4, bitsPerChar) {
|
|
98384
98784
|
const pad2 = alphabet4[alphabet4.length - 1] === "=";
|
|
98385
|
-
const
|
|
98785
|
+
const mask2 = (1 << bitsPerChar) - 1;
|
|
98386
98786
|
let out = "";
|
|
98387
98787
|
let bits = 0;
|
|
98388
98788
|
let buffer6 = 0;
|
|
@@ -98391,11 +98791,11 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
98391
98791
|
bits += 8;
|
|
98392
98792
|
while (bits > bitsPerChar) {
|
|
98393
98793
|
bits -= bitsPerChar;
|
|
98394
|
-
out += alphabet4[
|
|
98794
|
+
out += alphabet4[mask2 & buffer6 >> bits];
|
|
98395
98795
|
}
|
|
98396
98796
|
}
|
|
98397
98797
|
if (bits !== 0) {
|
|
98398
|
-
out += alphabet4[
|
|
98798
|
+
out += alphabet4[mask2 & buffer6 << bitsPerChar - bits];
|
|
98399
98799
|
}
|
|
98400
98800
|
if (pad2) {
|
|
98401
98801
|
while ((out.length * bitsPerChar & 7) !== 0) {
|
|
@@ -99216,7 +99616,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
99216
99616
|
computeCid: () => computeCid,
|
|
99217
99617
|
createIpfsClient: () => createIpfsClient,
|
|
99218
99618
|
createMemoryStorage: () => createMemoryStorage,
|
|
99219
|
-
defaultStorage: () =>
|
|
99619
|
+
defaultStorage: () => defaultStorage3,
|
|
99220
99620
|
getIpfsConfig: () => getIpfsConfig,
|
|
99221
99621
|
ipfsCacheGet: () => ipfsCacheGet,
|
|
99222
99622
|
ipfsCacheSet: () => ipfsCacheSet,
|
|
@@ -99247,7 +99647,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
99247
99647
|
}
|
|
99248
99648
|
};
|
|
99249
99649
|
}
|
|
99250
|
-
function
|
|
99650
|
+
function defaultStorage3() {
|
|
99251
99651
|
try {
|
|
99252
99652
|
if (typeof localStorage !== "undefined" && localStorage) {
|
|
99253
99653
|
const probe = "__bolloon_ipfs_probe__";
|
|
@@ -99317,7 +99717,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
99317
99717
|
}
|
|
99318
99718
|
}
|
|
99319
99719
|
}
|
|
99320
|
-
function getIpfsConfig(storage2 =
|
|
99720
|
+
function getIpfsConfig(storage2 = defaultStorage3()) {
|
|
99321
99721
|
const base6 = { mode: "public", gateways: [...DEFAULT_GATEWAYS] };
|
|
99322
99722
|
try {
|
|
99323
99723
|
const raw = storage2.getItem(IPFS_CONFIG_KEY);
|
|
@@ -99336,7 +99736,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
99336
99736
|
return base6;
|
|
99337
99737
|
}
|
|
99338
99738
|
}
|
|
99339
|
-
function setIpfsConfig(cfg, storage2 =
|
|
99739
|
+
function setIpfsConfig(cfg, storage2 = defaultStorage3()) {
|
|
99340
99740
|
try {
|
|
99341
99741
|
if (cfg.mode !== void 0 && !VALID_MODES.includes(cfg.mode)) {
|
|
99342
99742
|
return { ok: false, error: `\u975E\u6CD5 mode: ${String(cfg.mode)} (\u5E94\u4E3A public|remote|pinata)` };
|
|
@@ -99384,7 +99784,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
99384
99784
|
}
|
|
99385
99785
|
return kept;
|
|
99386
99786
|
}
|
|
99387
|
-
function ipfsCacheGet(cid, storage2 =
|
|
99787
|
+
function ipfsCacheGet(cid, storage2 = defaultStorage3()) {
|
|
99388
99788
|
try {
|
|
99389
99789
|
const key = normalizeCid(cid);
|
|
99390
99790
|
if (!key) return null;
|
|
@@ -99404,7 +99804,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
99404
99804
|
return null;
|
|
99405
99805
|
}
|
|
99406
99806
|
}
|
|
99407
|
-
function ipfsCacheSet(cid, text, storage2 =
|
|
99807
|
+
function ipfsCacheSet(cid, text, storage2 = defaultStorage3()) {
|
|
99408
99808
|
try {
|
|
99409
99809
|
const key = normalizeCid(cid);
|
|
99410
99810
|
if (!key) return { ok: false, error: "cid \u4E0D\u80FD\u4E3A\u7A7A" };
|
|
@@ -99488,7 +99888,7 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
99488
99888
|
async function ipfsFetch(cid, opts = {}) {
|
|
99489
99889
|
const key = normalizeCid(cid);
|
|
99490
99890
|
if (!key) return { ok: false, error: "cid \u4E0D\u80FD\u4E3A\u7A7A" };
|
|
99491
|
-
const storage2 = opts.storage ??
|
|
99891
|
+
const storage2 = opts.storage ?? defaultStorage3();
|
|
99492
99892
|
const useCache = opts.useCache !== false;
|
|
99493
99893
|
if (useCache) {
|
|
99494
99894
|
const cached = ipfsCacheGet(key, storage2);
|
|
@@ -100794,8 +101194,8 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
100794
101194
|
}
|
|
100795
101195
|
function encodeInteger2(value2) {
|
|
100796
101196
|
const contents = new Uint8ArrayList10();
|
|
100797
|
-
const
|
|
100798
|
-
const positive2 = (value2.subarray()[0] &
|
|
101197
|
+
const mask2 = 128;
|
|
101198
|
+
const positive2 = (value2.subarray()[0] & mask2) === mask2;
|
|
100799
101199
|
if (positive2) {
|
|
100800
101200
|
contents.append(Uint8Array.from([0]));
|
|
100801
101201
|
}
|
|
@@ -100952,18 +101352,18 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
100952
101352
|
* Zig-zag encodes this long bits
|
|
100953
101353
|
*/
|
|
100954
101354
|
zzEncode() {
|
|
100955
|
-
const
|
|
100956
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
100957
|
-
this.lo = (this.lo << 1 ^
|
|
101355
|
+
const mask2 = this.hi >> 31;
|
|
101356
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
101357
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
100958
101358
|
return this;
|
|
100959
101359
|
}
|
|
100960
101360
|
/**
|
|
100961
101361
|
* Zig-zag decodes this long bits
|
|
100962
101362
|
*/
|
|
100963
101363
|
zzDecode() {
|
|
100964
|
-
const
|
|
100965
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
100966
|
-
this.hi = (this.hi >>> 1 ^
|
|
101364
|
+
const mask2 = -(this.lo & 1);
|
|
101365
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
101366
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
100967
101367
|
return this;
|
|
100968
101368
|
}
|
|
100969
101369
|
/**
|
|
@@ -103864,18 +104264,18 @@ ${r.steps.map((s3) => `${s3.ok ? "\u2713" : "\u2717"} ${s3.step}: ${s3.note}`).j
|
|
|
103864
104264
|
* Zig-zag encodes this long bits
|
|
103865
104265
|
*/
|
|
103866
104266
|
zzEncode() {
|
|
103867
|
-
const
|
|
103868
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
103869
|
-
this.lo = (this.lo << 1 ^
|
|
104267
|
+
const mask2 = this.hi >> 31;
|
|
104268
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
104269
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
103870
104270
|
return this;
|
|
103871
104271
|
}
|
|
103872
104272
|
/**
|
|
103873
104273
|
* Zig-zag decodes this long bits
|
|
103874
104274
|
*/
|
|
103875
104275
|
zzDecode() {
|
|
103876
|
-
const
|
|
103877
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
103878
|
-
this.hi = (this.hi >>> 1 ^
|
|
104276
|
+
const mask2 = -(this.lo & 1);
|
|
104277
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
104278
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
103879
104279
|
return this;
|
|
103880
104280
|
}
|
|
103881
104281
|
/**
|
|
@@ -114756,18 +115156,18 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
114756
115156
|
* Zig-zag encodes this long bits
|
|
114757
115157
|
*/
|
|
114758
115158
|
zzEncode() {
|
|
114759
|
-
const
|
|
114760
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
114761
|
-
this.lo = (this.lo << 1 ^
|
|
115159
|
+
const mask2 = this.hi >> 31;
|
|
115160
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
115161
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
114762
115162
|
return this;
|
|
114763
115163
|
}
|
|
114764
115164
|
/**
|
|
114765
115165
|
* Zig-zag decodes this long bits
|
|
114766
115166
|
*/
|
|
114767
115167
|
zzDecode() {
|
|
114768
|
-
const
|
|
114769
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
114770
|
-
this.hi = (this.hi >>> 1 ^
|
|
115168
|
+
const mask2 = -(this.lo & 1);
|
|
115169
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
115170
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
114771
115171
|
return this;
|
|
114772
115172
|
}
|
|
114773
115173
|
/**
|
|
@@ -117096,18 +117496,18 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
117096
117496
|
* Zig-zag encodes this long bits
|
|
117097
117497
|
*/
|
|
117098
117498
|
zzEncode() {
|
|
117099
|
-
const
|
|
117100
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
117101
|
-
this.lo = (this.lo << 1 ^
|
|
117499
|
+
const mask2 = this.hi >> 31;
|
|
117500
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
117501
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
117102
117502
|
return this;
|
|
117103
117503
|
}
|
|
117104
117504
|
/**
|
|
117105
117505
|
* Zig-zag decodes this long bits
|
|
117106
117506
|
*/
|
|
117107
117507
|
zzDecode() {
|
|
117108
|
-
const
|
|
117109
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
117110
|
-
this.hi = (this.hi >>> 1 ^
|
|
117508
|
+
const mask2 = -(this.lo & 1);
|
|
117509
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
117510
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
117111
117511
|
return this;
|
|
117112
117512
|
}
|
|
117113
117513
|
/**
|
|
@@ -122983,7 +123383,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
122983
123383
|
// node_modules/process/browser.js
|
|
122984
123384
|
var require_browser4 = __commonJS({
|
|
122985
123385
|
"node_modules/process/browser.js"(exports, module) {
|
|
122986
|
-
var
|
|
123386
|
+
var process2 = module.exports = {};
|
|
122987
123387
|
var cachedSetTimeout;
|
|
122988
123388
|
var cachedClearTimeout;
|
|
122989
123389
|
function defaultSetTimout() {
|
|
@@ -123088,7 +123488,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123088
123488
|
draining = false;
|
|
123089
123489
|
runClearTimeout(timeout);
|
|
123090
123490
|
}
|
|
123091
|
-
|
|
123491
|
+
process2.nextTick = function(fun) {
|
|
123092
123492
|
var args = new Array(arguments.length - 1);
|
|
123093
123493
|
if (arguments.length > 1) {
|
|
123094
123494
|
for (var i = 1; i < arguments.length; i++) {
|
|
@@ -123107,36 +123507,36 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123107
123507
|
Item.prototype.run = function() {
|
|
123108
123508
|
this.fun.apply(null, this.array);
|
|
123109
123509
|
};
|
|
123110
|
-
|
|
123111
|
-
|
|
123112
|
-
|
|
123113
|
-
|
|
123114
|
-
|
|
123115
|
-
|
|
123510
|
+
process2.title = "browser";
|
|
123511
|
+
process2.browser = true;
|
|
123512
|
+
process2.env = {};
|
|
123513
|
+
process2.argv = [];
|
|
123514
|
+
process2.version = "";
|
|
123515
|
+
process2.versions = {};
|
|
123116
123516
|
function noop16() {
|
|
123117
123517
|
}
|
|
123118
|
-
|
|
123119
|
-
|
|
123120
|
-
|
|
123121
|
-
|
|
123122
|
-
|
|
123123
|
-
|
|
123124
|
-
|
|
123125
|
-
|
|
123126
|
-
|
|
123127
|
-
|
|
123518
|
+
process2.on = noop16;
|
|
123519
|
+
process2.addListener = noop16;
|
|
123520
|
+
process2.once = noop16;
|
|
123521
|
+
process2.off = noop16;
|
|
123522
|
+
process2.removeListener = noop16;
|
|
123523
|
+
process2.removeAllListeners = noop16;
|
|
123524
|
+
process2.emit = noop16;
|
|
123525
|
+
process2.prependListener = noop16;
|
|
123526
|
+
process2.prependOnceListener = noop16;
|
|
123527
|
+
process2.listeners = function(name10) {
|
|
123128
123528
|
return [];
|
|
123129
123529
|
};
|
|
123130
|
-
|
|
123530
|
+
process2.binding = function(name10) {
|
|
123131
123531
|
throw new Error("process.binding is not supported");
|
|
123132
123532
|
};
|
|
123133
|
-
|
|
123533
|
+
process2.cwd = function() {
|
|
123134
123534
|
return "/";
|
|
123135
123535
|
};
|
|
123136
|
-
|
|
123536
|
+
process2.chdir = function(dir) {
|
|
123137
123537
|
throw new Error("process.chdir is not supported");
|
|
123138
123538
|
};
|
|
123139
|
-
|
|
123539
|
+
process2.umask = function() {
|
|
123140
123540
|
return 0;
|
|
123141
123541
|
};
|
|
123142
123542
|
}
|
|
@@ -123355,7 +123755,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123355
123755
|
var require_end_of_stream = __commonJS({
|
|
123356
123756
|
"node_modules/@libp2p/http-utils/node_modules/readable-stream/lib/internal/streams/end-of-stream.js"(exports, module) {
|
|
123357
123757
|
"use strict";
|
|
123358
|
-
var
|
|
123758
|
+
var process2 = require_browser4();
|
|
123359
123759
|
var { AbortError: AbortError6, codes } = require_errors();
|
|
123360
123760
|
var { ERR_INVALID_ARG_TYPE, ERR_STREAM_PREMATURE_CLOSE } = codes;
|
|
123361
123761
|
var { kEmptyObject, once } = require_util();
|
|
@@ -123491,17 +123891,17 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123491
123891
|
}
|
|
123492
123892
|
stream.on("close", onclose);
|
|
123493
123893
|
if (closed) {
|
|
123494
|
-
|
|
123894
|
+
process2.nextTick(onclose);
|
|
123495
123895
|
} else if (wState !== null && wState !== void 0 && wState.errorEmitted || rState !== null && rState !== void 0 && rState.errorEmitted) {
|
|
123496
123896
|
if (!willEmitClose) {
|
|
123497
|
-
|
|
123897
|
+
process2.nextTick(onclosed);
|
|
123498
123898
|
}
|
|
123499
123899
|
} else if (!readable && (!willEmitClose || isReadable(stream)) && (writableFinished || isWritable(stream) === false)) {
|
|
123500
|
-
|
|
123900
|
+
process2.nextTick(onclosed);
|
|
123501
123901
|
} else if (!writable && (!willEmitClose || isWritable(stream)) && (readableFinished || isReadable(stream) === false)) {
|
|
123502
|
-
|
|
123902
|
+
process2.nextTick(onclosed);
|
|
123503
123903
|
} else if (rState && stream.req && stream.aborted) {
|
|
123504
|
-
|
|
123904
|
+
process2.nextTick(onclosed);
|
|
123505
123905
|
}
|
|
123506
123906
|
const cleanup = () => {
|
|
123507
123907
|
callback = nop;
|
|
@@ -123529,7 +123929,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123529
123929
|
);
|
|
123530
123930
|
};
|
|
123531
123931
|
if (options2.signal.aborted) {
|
|
123532
|
-
|
|
123932
|
+
process2.nextTick(abort);
|
|
123533
123933
|
} else {
|
|
123534
123934
|
addAbortListener = addAbortListener || require_util().addAbortListener;
|
|
123535
123935
|
const disposable = addAbortListener(options2.signal, abort);
|
|
@@ -123556,7 +123956,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123556
123956
|
);
|
|
123557
123957
|
};
|
|
123558
123958
|
if (options2.signal.aborted) {
|
|
123559
|
-
|
|
123959
|
+
process2.nextTick(abort);
|
|
123560
123960
|
} else {
|
|
123561
123961
|
addAbortListener = addAbortListener || require_util().addAbortListener;
|
|
123562
123962
|
const disposable = addAbortListener(options2.signal, abort);
|
|
@@ -123569,7 +123969,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123569
123969
|
}
|
|
123570
123970
|
const resolverFn = (...args) => {
|
|
123571
123971
|
if (!isAborted) {
|
|
123572
|
-
|
|
123972
|
+
process2.nextTick(() => callback.apply(stream, args));
|
|
123573
123973
|
}
|
|
123574
123974
|
};
|
|
123575
123975
|
PromisePrototypeThen(stream[kIsClosedPromise].promise, resolverFn, resolverFn);
|
|
@@ -123607,7 +124007,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123607
124007
|
var require_destroy = __commonJS({
|
|
123608
124008
|
"node_modules/@libp2p/http-utils/node_modules/readable-stream/lib/internal/streams/destroy.js"(exports, module) {
|
|
123609
124009
|
"use strict";
|
|
123610
|
-
var
|
|
124010
|
+
var process2 = require_browser4();
|
|
123611
124011
|
var {
|
|
123612
124012
|
aggregateTwoErrors,
|
|
123613
124013
|
codes: { ERR_MULTIPLE_CALLBACK },
|
|
@@ -123674,9 +124074,9 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123674
124074
|
cb(err3);
|
|
123675
124075
|
}
|
|
123676
124076
|
if (err3) {
|
|
123677
|
-
|
|
124077
|
+
process2.nextTick(emitErrorCloseNT, self2, err3);
|
|
123678
124078
|
} else {
|
|
123679
|
-
|
|
124079
|
+
process2.nextTick(emitCloseNT, self2);
|
|
123680
124080
|
}
|
|
123681
124081
|
}
|
|
123682
124082
|
try {
|
|
@@ -123761,7 +124161,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123761
124161
|
r.errored = err2;
|
|
123762
124162
|
}
|
|
123763
124163
|
if (sync) {
|
|
123764
|
-
|
|
124164
|
+
process2.nextTick(emitErrorNT, stream, err2);
|
|
123765
124165
|
} else {
|
|
123766
124166
|
emitErrorNT(stream, err2);
|
|
123767
124167
|
}
|
|
@@ -123783,7 +124183,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123783
124183
|
if (stream.listenerCount(kConstruct) > 1) {
|
|
123784
124184
|
return;
|
|
123785
124185
|
}
|
|
123786
|
-
|
|
124186
|
+
process2.nextTick(constructNT, stream);
|
|
123787
124187
|
}
|
|
123788
124188
|
function constructNT(stream) {
|
|
123789
124189
|
let called = false;
|
|
@@ -123807,15 +124207,15 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123807
124207
|
} else if (err2) {
|
|
123808
124208
|
errorOrDestroy(stream, err2, true);
|
|
123809
124209
|
} else {
|
|
123810
|
-
|
|
124210
|
+
process2.nextTick(emitConstructNT, stream);
|
|
123811
124211
|
}
|
|
123812
124212
|
}
|
|
123813
124213
|
try {
|
|
123814
124214
|
stream._construct((err2) => {
|
|
123815
|
-
|
|
124215
|
+
process2.nextTick(onConstruct, err2);
|
|
123816
124216
|
});
|
|
123817
124217
|
} catch (err2) {
|
|
123818
|
-
|
|
124218
|
+
process2.nextTick(onConstruct, err2);
|
|
123819
124219
|
}
|
|
123820
124220
|
}
|
|
123821
124221
|
function emitConstructNT(stream) {
|
|
@@ -123829,7 +124229,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123829
124229
|
}
|
|
123830
124230
|
function emitErrorCloseLegacy(stream, err2) {
|
|
123831
124231
|
stream.emit("error", err2);
|
|
123832
|
-
|
|
124232
|
+
process2.nextTick(emitCloseLegacy, stream);
|
|
123833
124233
|
}
|
|
123834
124234
|
function destroyer(stream, err2) {
|
|
123835
124235
|
if (!stream || isDestroyed(stream)) {
|
|
@@ -123850,9 +124250,9 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
123850
124250
|
} else if (typeof stream.close === "function") {
|
|
123851
124251
|
stream.close();
|
|
123852
124252
|
} else if (err2) {
|
|
123853
|
-
|
|
124253
|
+
process2.nextTick(emitErrorCloseLegacy, stream, err2);
|
|
123854
124254
|
} else {
|
|
123855
|
-
|
|
124255
|
+
process2.nextTick(emitCloseLegacy, stream);
|
|
123856
124256
|
}
|
|
123857
124257
|
if (!stream.destroyed) {
|
|
123858
124258
|
stream[kIsDestroyed] = true;
|
|
@@ -124494,7 +124894,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
124494
124894
|
var require_from = __commonJS({
|
|
124495
124895
|
"node_modules/@libp2p/http-utils/node_modules/readable-stream/lib/internal/streams/from.js"(exports, module) {
|
|
124496
124896
|
"use strict";
|
|
124497
|
-
var
|
|
124897
|
+
var process2 = require_browser4();
|
|
124498
124898
|
var { PromisePrototypeThen, SymbolAsyncIterator, SymbolIterator } = require_primordials();
|
|
124499
124899
|
var { Buffer: Buffer2 } = require_buffer();
|
|
124500
124900
|
var { ERR_INVALID_ARG_TYPE, ERR_STREAM_NULL_VALUES } = require_errors().codes;
|
|
@@ -124536,9 +124936,9 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
124536
124936
|
readable._destroy = function(error, cb) {
|
|
124537
124937
|
PromisePrototypeThen(
|
|
124538
124938
|
close(error),
|
|
124539
|
-
() =>
|
|
124939
|
+
() => process2.nextTick(cb, error),
|
|
124540
124940
|
// nextTick is here in case cb throws
|
|
124541
|
-
(e) =>
|
|
124941
|
+
(e) => process2.nextTick(cb, e || error)
|
|
124542
124942
|
);
|
|
124543
124943
|
};
|
|
124544
124944
|
async function close(error) {
|
|
@@ -124589,7 +124989,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
124589
124989
|
var require_readable = __commonJS({
|
|
124590
124990
|
"node_modules/@libp2p/http-utils/node_modules/readable-stream/lib/internal/streams/readable.js"(exports, module) {
|
|
124591
124991
|
"use strict";
|
|
124592
|
-
var
|
|
124992
|
+
var process2 = require_browser4();
|
|
124593
124993
|
var {
|
|
124594
124994
|
ArrayPrototypeIndexOf,
|
|
124595
124995
|
NumberIsInteger,
|
|
@@ -124974,7 +125374,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
124974
125374
|
if (!state2.emittedReadable) {
|
|
124975
125375
|
debug("emitReadable", state2.flowing);
|
|
124976
125376
|
state2.emittedReadable = true;
|
|
124977
|
-
|
|
125377
|
+
process2.nextTick(emitReadable_, stream);
|
|
124978
125378
|
}
|
|
124979
125379
|
}
|
|
124980
125380
|
function emitReadable_(stream) {
|
|
@@ -124990,7 +125390,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
124990
125390
|
function maybeReadMore(stream, state2) {
|
|
124991
125391
|
if (!state2.readingMore && state2.constructed) {
|
|
124992
125392
|
state2.readingMore = true;
|
|
124993
|
-
|
|
125393
|
+
process2.nextTick(maybeReadMore_, stream, state2);
|
|
124994
125394
|
}
|
|
124995
125395
|
}
|
|
124996
125396
|
function maybeReadMore_(stream, state2) {
|
|
@@ -125017,9 +125417,9 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
125017
125417
|
}
|
|
125018
125418
|
state2.pipes.push(dest);
|
|
125019
125419
|
debug("pipe count=%d opts=%j", state2.pipes.length, pipeOpts);
|
|
125020
|
-
const doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !==
|
|
125420
|
+
const doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process2.stdout && dest !== process2.stderr;
|
|
125021
125421
|
const endFn = doEnd ? onend : unpipe;
|
|
125022
|
-
if (state2.endEmitted)
|
|
125422
|
+
if (state2.endEmitted) process2.nextTick(endFn);
|
|
125023
125423
|
else src4.once("end", endFn);
|
|
125024
125424
|
dest.on("unpipe", onunpipe);
|
|
125025
125425
|
function onunpipe(readable, unpipeInfo) {
|
|
@@ -125169,7 +125569,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
125169
125569
|
if (state2.length) {
|
|
125170
125570
|
emitReadable(this);
|
|
125171
125571
|
} else if (!state2.reading) {
|
|
125172
|
-
|
|
125572
|
+
process2.nextTick(nReadingNextTick, this);
|
|
125173
125573
|
}
|
|
125174
125574
|
}
|
|
125175
125575
|
}
|
|
@@ -125179,7 +125579,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
125179
125579
|
Readable.prototype.removeListener = function(ev, fn) {
|
|
125180
125580
|
const res = Stream.prototype.removeListener.call(this, ev, fn);
|
|
125181
125581
|
if (ev === "readable") {
|
|
125182
|
-
|
|
125582
|
+
process2.nextTick(updateReadableListening, this);
|
|
125183
125583
|
}
|
|
125184
125584
|
return res;
|
|
125185
125585
|
};
|
|
@@ -125187,7 +125587,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
125187
125587
|
Readable.prototype.removeAllListeners = function(ev) {
|
|
125188
125588
|
const res = Stream.prototype.removeAllListeners.apply(this, arguments);
|
|
125189
125589
|
if (ev === "readable" || ev === void 0) {
|
|
125190
|
-
|
|
125590
|
+
process2.nextTick(updateReadableListening, this);
|
|
125191
125591
|
}
|
|
125192
125592
|
return res;
|
|
125193
125593
|
};
|
|
@@ -125219,7 +125619,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
125219
125619
|
function resume(stream, state2) {
|
|
125220
125620
|
if (!state2.resumeScheduled) {
|
|
125221
125621
|
state2.resumeScheduled = true;
|
|
125222
|
-
|
|
125622
|
+
process2.nextTick(resume_, stream, state2);
|
|
125223
125623
|
}
|
|
125224
125624
|
}
|
|
125225
125625
|
function resume_(stream, state2) {
|
|
@@ -125496,7 +125896,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
125496
125896
|
debug("endReadable", state2.endEmitted);
|
|
125497
125897
|
if (!state2.endEmitted) {
|
|
125498
125898
|
state2.ended = true;
|
|
125499
|
-
|
|
125899
|
+
process2.nextTick(endReadableNT, state2, stream);
|
|
125500
125900
|
}
|
|
125501
125901
|
}
|
|
125502
125902
|
function endReadableNT(state2, stream) {
|
|
@@ -125505,7 +125905,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
125505
125905
|
state2.endEmitted = true;
|
|
125506
125906
|
stream.emit("end");
|
|
125507
125907
|
if (stream.writable && stream.allowHalfOpen === false) {
|
|
125508
|
-
|
|
125908
|
+
process2.nextTick(endWritableNT, stream);
|
|
125509
125909
|
} else if (state2.autoDestroy) {
|
|
125510
125910
|
const wState = stream._writableState;
|
|
125511
125911
|
const autoDestroy = !wState || wState.autoDestroy && // We don't expect the writable to ever 'finish'
|
|
@@ -125555,7 +125955,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
125555
125955
|
var require_writable = __commonJS({
|
|
125556
125956
|
"node_modules/@libp2p/http-utils/node_modules/readable-stream/lib/internal/streams/writable.js"(exports, module) {
|
|
125557
125957
|
"use strict";
|
|
125558
|
-
var
|
|
125958
|
+
var process2 = require_browser4();
|
|
125559
125959
|
var {
|
|
125560
125960
|
ArrayPrototypeSlice,
|
|
125561
125961
|
Error: Error2,
|
|
@@ -125708,7 +126108,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
125708
126108
|
err2 = new ERR_STREAM_DESTROYED("write");
|
|
125709
126109
|
}
|
|
125710
126110
|
if (err2) {
|
|
125711
|
-
|
|
126111
|
+
process2.nextTick(cb, err2);
|
|
125712
126112
|
errorOrDestroy(stream, err2, true);
|
|
125713
126113
|
return err2;
|
|
125714
126114
|
}
|
|
@@ -125798,7 +126198,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
125798
126198
|
stream._readableState.errored = er;
|
|
125799
126199
|
}
|
|
125800
126200
|
if (sync) {
|
|
125801
|
-
|
|
126201
|
+
process2.nextTick(onwriteError, stream, state2, er, cb);
|
|
125802
126202
|
} else {
|
|
125803
126203
|
onwriteError(stream, state2, er, cb);
|
|
125804
126204
|
}
|
|
@@ -125816,7 +126216,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
125816
126216
|
stream,
|
|
125817
126217
|
state: state2
|
|
125818
126218
|
};
|
|
125819
|
-
|
|
126219
|
+
process2.nextTick(afterWriteTick, state2.afterWriteTickInfo);
|
|
125820
126220
|
}
|
|
125821
126221
|
} else {
|
|
125822
126222
|
afterWrite(stream, state2, 1, cb);
|
|
@@ -125953,7 +126353,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
125953
126353
|
}
|
|
125954
126354
|
if (typeof cb === "function") {
|
|
125955
126355
|
if (err2 || state2.finished) {
|
|
125956
|
-
|
|
126356
|
+
process2.nextTick(cb, err2);
|
|
125957
126357
|
} else {
|
|
125958
126358
|
state2[kOnFinished].push(cb);
|
|
125959
126359
|
}
|
|
@@ -125982,7 +126382,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
125982
126382
|
state2.prefinished = true;
|
|
125983
126383
|
stream.emit("prefinish");
|
|
125984
126384
|
state2.pendingcb++;
|
|
125985
|
-
|
|
126385
|
+
process2.nextTick(finish, stream, state2);
|
|
125986
126386
|
}
|
|
125987
126387
|
}
|
|
125988
126388
|
state2.sync = true;
|
|
@@ -126011,7 +126411,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
126011
126411
|
if (state2.pendingcb === 0) {
|
|
126012
126412
|
if (sync) {
|
|
126013
126413
|
state2.pendingcb++;
|
|
126014
|
-
|
|
126414
|
+
process2.nextTick(
|
|
126015
126415
|
(stream2, state3) => {
|
|
126016
126416
|
if (needFinish(state3)) {
|
|
126017
126417
|
finish(stream2, state3);
|
|
@@ -126146,7 +126546,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
126146
126546
|
Writable.prototype.destroy = function(err2, cb) {
|
|
126147
126547
|
const state2 = this._writableState;
|
|
126148
126548
|
if (!state2.destroyed && (state2.bufferedIndex < state2.buffered.length || state2[kOnFinished].length)) {
|
|
126149
|
-
|
|
126549
|
+
process2.nextTick(errorBuffer, state2);
|
|
126150
126550
|
}
|
|
126151
126551
|
destroy.call(this, err2, cb);
|
|
126152
126552
|
return this;
|
|
@@ -126175,7 +126575,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
126175
126575
|
// node_modules/@libp2p/http-utils/node_modules/readable-stream/lib/internal/streams/duplexify.js
|
|
126176
126576
|
var require_duplexify = __commonJS({
|
|
126177
126577
|
"node_modules/@libp2p/http-utils/node_modules/readable-stream/lib/internal/streams/duplexify.js"(exports, module) {
|
|
126178
|
-
var
|
|
126578
|
+
var process2 = require_browser4();
|
|
126179
126579
|
var bufferModule = require_buffer();
|
|
126180
126580
|
var {
|
|
126181
126581
|
isReadable,
|
|
@@ -126288,9 +126688,9 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
126288
126688
|
final(async () => {
|
|
126289
126689
|
try {
|
|
126290
126690
|
await promise;
|
|
126291
|
-
|
|
126691
|
+
process2.nextTick(cb, null);
|
|
126292
126692
|
} catch (err2) {
|
|
126293
|
-
|
|
126693
|
+
process2.nextTick(cb, err2);
|
|
126294
126694
|
}
|
|
126295
126695
|
});
|
|
126296
126696
|
},
|
|
@@ -126369,7 +126769,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
126369
126769
|
const _promise = promise;
|
|
126370
126770
|
promise = null;
|
|
126371
126771
|
const { chunk, done, cb } = await _promise;
|
|
126372
|
-
|
|
126772
|
+
process2.nextTick(cb);
|
|
126373
126773
|
if (done) return;
|
|
126374
126774
|
if (signal.aborted)
|
|
126375
126775
|
throw new AbortError6(void 0, {
|
|
@@ -126760,7 +127160,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
126760
127160
|
// node_modules/@libp2p/http-utils/node_modules/readable-stream/lib/internal/streams/pipeline.js
|
|
126761
127161
|
var require_pipeline = __commonJS({
|
|
126762
127162
|
"node_modules/@libp2p/http-utils/node_modules/readable-stream/lib/internal/streams/pipeline.js"(exports, module) {
|
|
126763
|
-
var
|
|
127163
|
+
var process2 = require_browser4();
|
|
126764
127164
|
var { ArrayIsArray, Promise: Promise2, SymbolAsyncIterator, SymbolDispose } = require_primordials();
|
|
126765
127165
|
var eos = require_end_of_stream();
|
|
126766
127166
|
var { once } = require_util();
|
|
@@ -126962,7 +127362,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
126962
127362
|
if (!error) {
|
|
126963
127363
|
lastStreamCleanup.forEach((fn) => fn());
|
|
126964
127364
|
}
|
|
126965
|
-
|
|
127365
|
+
process2.nextTick(callback, error, value2);
|
|
126966
127366
|
}
|
|
126967
127367
|
}
|
|
126968
127368
|
let ret;
|
|
@@ -127041,11 +127441,11 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
127041
127441
|
if (end) {
|
|
127042
127442
|
pt.end();
|
|
127043
127443
|
}
|
|
127044
|
-
|
|
127444
|
+
process2.nextTick(finish);
|
|
127045
127445
|
},
|
|
127046
127446
|
(err2) => {
|
|
127047
127447
|
pt.destroy(err2);
|
|
127048
|
-
|
|
127448
|
+
process2.nextTick(finish, err2);
|
|
127049
127449
|
}
|
|
127050
127450
|
);
|
|
127051
127451
|
} else if (isIterable2(ret, true)) {
|
|
@@ -127126,7 +127526,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
127126
127526
|
}
|
|
127127
127527
|
}
|
|
127128
127528
|
if (signal !== null && signal !== void 0 && signal.aborted || outerSignal !== null && outerSignal !== void 0 && outerSignal.aborted) {
|
|
127129
|
-
|
|
127529
|
+
process2.nextTick(abort);
|
|
127130
127530
|
}
|
|
127131
127531
|
return ret;
|
|
127132
127532
|
}
|
|
@@ -127147,7 +127547,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
127147
127547
|
};
|
|
127148
127548
|
var endFn = endFn2;
|
|
127149
127549
|
if (isReadableFinished(src4)) {
|
|
127150
|
-
|
|
127550
|
+
process2.nextTick(endFn2);
|
|
127151
127551
|
} else {
|
|
127152
127552
|
src4.once("end", endFn2);
|
|
127153
127553
|
}
|
|
@@ -129350,12 +129750,12 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
129350
129750
|
type: MESSAGE_TYPES[opcode]
|
|
129351
129751
|
};
|
|
129352
129752
|
}
|
|
129353
|
-
let
|
|
129753
|
+
let mask2;
|
|
129354
129754
|
if (isMasked) {
|
|
129355
129755
|
if (buf.byteLength < offset + 4) {
|
|
129356
129756
|
return;
|
|
129357
129757
|
}
|
|
129358
|
-
|
|
129758
|
+
mask2 = buf.subarray(offset, offset + 4);
|
|
129359
129759
|
offset += 4;
|
|
129360
129760
|
}
|
|
129361
129761
|
if (buf.byteLength < offset + length20) {
|
|
@@ -129363,8 +129763,8 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
129363
129763
|
}
|
|
129364
129764
|
let data = buf.subarray(offset, offset + length20);
|
|
129365
129765
|
offset += length20;
|
|
129366
|
-
if (
|
|
129367
|
-
data = applyMask(data,
|
|
129766
|
+
if (mask2 != null) {
|
|
129767
|
+
data = applyMask(data, mask2);
|
|
129368
129768
|
}
|
|
129369
129769
|
buf.consume(offset);
|
|
129370
129770
|
return {
|
|
@@ -129372,12 +129772,12 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
129372
129772
|
data
|
|
129373
129773
|
};
|
|
129374
129774
|
}
|
|
129375
|
-
function applyMask(data,
|
|
129775
|
+
function applyMask(data, mask2) {
|
|
129376
129776
|
let m2 = 0;
|
|
129377
129777
|
for (let i = 0; i < data.byteLength; i++) {
|
|
129378
|
-
data[i] = data[i] ^
|
|
129778
|
+
data[i] = data[i] ^ mask2[m2];
|
|
129379
129779
|
m2++;
|
|
129380
|
-
if (m2 ===
|
|
129780
|
+
if (m2 === mask2.byteLength) {
|
|
129381
129781
|
m2 = 0;
|
|
129382
129782
|
}
|
|
129383
129783
|
}
|
|
@@ -131917,18 +132317,18 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
131917
132317
|
* Zig-zag encodes this long bits
|
|
131918
132318
|
*/
|
|
131919
132319
|
zzEncode() {
|
|
131920
|
-
const
|
|
131921
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
131922
|
-
this.lo = (this.lo << 1 ^
|
|
132320
|
+
const mask2 = this.hi >> 31;
|
|
132321
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
132322
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
131923
132323
|
return this;
|
|
131924
132324
|
}
|
|
131925
132325
|
/**
|
|
131926
132326
|
* Zig-zag decodes this long bits
|
|
131927
132327
|
*/
|
|
131928
132328
|
zzDecode() {
|
|
131929
|
-
const
|
|
131930
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
131931
|
-
this.hi = (this.hi >>> 1 ^
|
|
132329
|
+
const mask2 = -(this.lo & 1);
|
|
132330
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
132331
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
131932
132332
|
return this;
|
|
131933
132333
|
}
|
|
131934
132334
|
/**
|
|
@@ -135418,12 +135818,12 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
135418
135818
|
g[i] &= 8191;
|
|
135419
135819
|
}
|
|
135420
135820
|
g[9] -= 1 << 13;
|
|
135421
|
-
let
|
|
135821
|
+
let mask2 = (c ^ 1) - 1;
|
|
135422
135822
|
for (let i = 0; i < 10; i++)
|
|
135423
|
-
g[i] &=
|
|
135424
|
-
|
|
135823
|
+
g[i] &= mask2;
|
|
135824
|
+
mask2 = ~mask2;
|
|
135425
135825
|
for (let i = 0; i < 10; i++)
|
|
135426
|
-
h3[i] = h3[i] &
|
|
135826
|
+
h3[i] = h3[i] & mask2 | g[i];
|
|
135427
135827
|
h3[0] = (h3[0] | h3[1] << 13) & 65535;
|
|
135428
135828
|
h3[1] = (h3[1] >>> 3 | h3[2] << 10) & 65535;
|
|
135429
135829
|
h3[2] = (h3[2] >>> 6 | h3[3] << 7) & 65535;
|
|
@@ -136870,18 +137270,18 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
136870
137270
|
* Zig-zag encodes this long bits
|
|
136871
137271
|
*/
|
|
136872
137272
|
zzEncode() {
|
|
136873
|
-
const
|
|
136874
|
-
this.hi = ((this.hi << 1 | this.lo >>> 31) ^
|
|
136875
|
-
this.lo = (this.lo << 1 ^
|
|
137273
|
+
const mask2 = this.hi >> 31;
|
|
137274
|
+
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask2) >>> 0;
|
|
137275
|
+
this.lo = (this.lo << 1 ^ mask2) >>> 0;
|
|
136876
137276
|
return this;
|
|
136877
137277
|
}
|
|
136878
137278
|
/**
|
|
136879
137279
|
* Zig-zag decodes this long bits
|
|
136880
137280
|
*/
|
|
136881
137281
|
zzDecode() {
|
|
136882
|
-
const
|
|
136883
|
-
this.lo = ((this.lo >>> 1 | this.hi << 31) ^
|
|
136884
|
-
this.hi = (this.hi >>> 1 ^
|
|
137282
|
+
const mask2 = -(this.lo & 1);
|
|
137283
|
+
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask2) >>> 0;
|
|
137284
|
+
this.hi = (this.hi >>> 1 ^ mask2) >>> 0;
|
|
136885
137285
|
return this;
|
|
136886
137286
|
}
|
|
136887
137287
|
/**
|
|
@@ -139954,11 +140354,11 @@ a=end-of-candidates
|
|
|
139954
140354
|
function toToken10(data, pos, prefix, length20, options2) {
|
|
139955
140355
|
const totLength = prefix + length20;
|
|
139956
140356
|
assertEnoughData3(data, pos, totLength);
|
|
139957
|
-
const
|
|
140357
|
+
const tok2 = new Token3(Type3.string, toStr3(data, pos + prefix, pos + totLength), totLength);
|
|
139958
140358
|
if (options2.retainStringBytes === true) {
|
|
139959
|
-
|
|
140359
|
+
tok2.byteValue = data.slice(pos + prefix, pos + totLength);
|
|
139960
140360
|
}
|
|
139961
|
-
return
|
|
140361
|
+
return tok2;
|
|
139962
140362
|
}
|
|
139963
140363
|
function decodeStringCompact3(data, pos, minor, options2) {
|
|
139964
140364
|
return toToken10(data, pos, 1, minor, options2);
|
|
@@ -142177,11 +142577,11 @@ a=end-of-candidates
|
|
|
142177
142577
|
function toToken14(data, pos, prefix, length20, options2) {
|
|
142178
142578
|
const totLength = prefix + length20;
|
|
142179
142579
|
assertEnoughData4(data, pos, totLength);
|
|
142180
|
-
const
|
|
142580
|
+
const tok2 = new Token4(Type4.string, toStr4(data, pos + prefix, pos + totLength), totLength);
|
|
142181
142581
|
if (options2.retainStringBytes === true) {
|
|
142182
|
-
|
|
142582
|
+
tok2.byteValue = data.slice(pos + prefix, pos + totLength);
|
|
142183
142583
|
}
|
|
142184
|
-
return
|
|
142584
|
+
return tok2;
|
|
142185
142585
|
}
|
|
142186
142586
|
function decodeStringCompact4(data, pos, minor, options2) {
|
|
142187
142587
|
return toToken14(data, pos, 1, minor, options2);
|
|
@@ -148151,11 +148551,11 @@ ${indent}[Error list was empty]`;
|
|
|
148151
148551
|
function toToken18(data, pos, prefix, length20, options2) {
|
|
148152
148552
|
const totLength = prefix + length20;
|
|
148153
148553
|
assertEnoughData5(data, pos, totLength);
|
|
148154
|
-
const
|
|
148554
|
+
const tok2 = new Token5(Type5.string, toStr5(data, pos + prefix, pos + totLength), totLength);
|
|
148155
148555
|
if (options2.retainStringBytes === true) {
|
|
148156
|
-
|
|
148556
|
+
tok2.byteValue = data.slice(pos + prefix, pos + totLength);
|
|
148157
148557
|
}
|
|
148158
|
-
return
|
|
148558
|
+
return tok2;
|
|
148159
148559
|
}
|
|
148160
148560
|
function decodeStringCompact5(data, pos, minor, options2) {
|
|
148161
148561
|
return toToken18(data, pos, 1, minor, options2);
|
|
@@ -150573,14 +150973,14 @@ ${error.stack}` : head;
|
|
|
150573
150973
|
return out;
|
|
150574
150974
|
}
|
|
150575
150975
|
}
|
|
150576
|
-
function heliaEnabled(storage2 =
|
|
150976
|
+
function heliaEnabled(storage2 = defaultStorage3()) {
|
|
150577
150977
|
try {
|
|
150578
150978
|
return storage2.getItem(HELIA_ENABLED_KEY) === "1";
|
|
150579
150979
|
} catch {
|
|
150580
150980
|
return false;
|
|
150581
150981
|
}
|
|
150582
150982
|
}
|
|
150583
|
-
function setHeliaEnabled(enabled, storage2 =
|
|
150983
|
+
function setHeliaEnabled(enabled, storage2 = defaultStorage3()) {
|
|
150584
150984
|
try {
|
|
150585
150985
|
storage2.setItem(HELIA_ENABLED_KEY, enabled ? "1" : "0");
|
|
150586
150986
|
return { ok: true, enabled: !!enabled };
|
|
@@ -150926,8 +151326,8 @@ ${error.stack}` : head;
|
|
|
150926
151326
|
N3: 40,
|
|
150927
151327
|
N4: 10
|
|
150928
151328
|
};
|
|
150929
|
-
exports.isValid = function isValid2(
|
|
150930
|
-
return
|
|
151329
|
+
exports.isValid = function isValid2(mask2) {
|
|
151330
|
+
return mask2 != null && mask2 !== "" && !isNaN(mask2) && mask2 >= 0 && mask2 <= 7;
|
|
150931
151331
|
};
|
|
150932
151332
|
exports.from = function from6(value2) {
|
|
150933
151333
|
return exports.isValid(value2) ? parseInt(value2, 10) : void 0;
|
|
@@ -151731,8 +152131,8 @@ ${error.stack}` : head;
|
|
|
151731
152131
|
var G15 = 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0;
|
|
151732
152132
|
var G15_MASK = 1 << 14 | 1 << 12 | 1 << 10 | 1 << 4 | 1 << 1;
|
|
151733
152133
|
var G15_BCH = Utils.getBCHDigit(G15);
|
|
151734
|
-
exports.getEncodedBits = function getEncodedBits(errorCorrectionLevel,
|
|
151735
|
-
const data = errorCorrectionLevel.bit << 3 |
|
|
152134
|
+
exports.getEncodedBits = function getEncodedBits(errorCorrectionLevel, mask2) {
|
|
152135
|
+
const data = errorCorrectionLevel.bit << 3 | mask2;
|
|
151736
152136
|
let d2 = data << 10;
|
|
151737
152137
|
while (Utils.getBCHDigit(d2) - G15_BCH >= 0) {
|
|
151738
152138
|
d2 ^= G15 << Utils.getBCHDigit(d2) - G15_BCH;
|
|
@@ -152459,16 +152859,16 @@ ${error.stack}` : head;
|
|
|
152459
152859
|
}
|
|
152460
152860
|
let errorCorrectionLevel = ECLevel.M;
|
|
152461
152861
|
let version4;
|
|
152462
|
-
let
|
|
152862
|
+
let mask2;
|
|
152463
152863
|
if (typeof options2 !== "undefined") {
|
|
152464
152864
|
errorCorrectionLevel = ECLevel.from(options2.errorCorrectionLevel, ECLevel.M);
|
|
152465
152865
|
version4 = Version.from(options2.version);
|
|
152466
|
-
|
|
152866
|
+
mask2 = MaskPattern.from(options2.maskPattern);
|
|
152467
152867
|
if (options2.toSJISFunc) {
|
|
152468
152868
|
Utils.setToSJISFunction(options2.toSJISFunc);
|
|
152469
152869
|
}
|
|
152470
152870
|
}
|
|
152471
|
-
return createSymbol(data, version4, errorCorrectionLevel,
|
|
152871
|
+
return createSymbol(data, version4, errorCorrectionLevel, mask2);
|
|
152472
152872
|
};
|
|
152473
152873
|
}
|
|
152474
152874
|
});
|
|
@@ -153787,8 +154187,8 @@ ${error.stack}` : head;
|
|
|
153787
154187
|
var bitsLeft = 8 - this.bitOffset;
|
|
153788
154188
|
var toRead = numBits < bitsLeft ? numBits : bitsLeft;
|
|
153789
154189
|
var bitsToNotRead = bitsLeft - toRead;
|
|
153790
|
-
var
|
|
153791
|
-
result = (this.bytes[this.byteOffset] &
|
|
154190
|
+
var mask2 = 255 >> 8 - toRead << bitsToNotRead;
|
|
154191
|
+
result = (this.bytes[this.byteOffset] & mask2) >> bitsToNotRead;
|
|
153792
154192
|
numBits -= toRead;
|
|
153793
154193
|
this.bitOffset += toRead;
|
|
153794
154194
|
if (this.bitOffset === 8) {
|
|
@@ -153804,8 +154204,8 @@ ${error.stack}` : head;
|
|
|
153804
154204
|
}
|
|
153805
154205
|
if (numBits > 0) {
|
|
153806
154206
|
var bitsToNotRead = 8 - numBits;
|
|
153807
|
-
var
|
|
153808
|
-
result = result << numBits | (this.bytes[this.byteOffset] &
|
|
154207
|
+
var mask2 = 255 >> bitsToNotRead << bitsToNotRead;
|
|
154208
|
+
result = result << numBits | (this.bytes[this.byteOffset] & mask2) >> bitsToNotRead;
|
|
153809
154209
|
this.bitOffset += numBits;
|
|
153810
154210
|
}
|
|
153811
154211
|
}
|
|
@@ -162923,129 +163323,345 @@ ${error.stack}` : head;
|
|
|
162923
163323
|
return result;
|
|
162924
163324
|
}
|
|
162925
163325
|
|
|
162926
|
-
// src/
|
|
162927
|
-
|
|
163326
|
+
// src/web/mobile-core.ts
|
|
163327
|
+
init_mobile_contacts();
|
|
163328
|
+
|
|
163329
|
+
// src/agents/mobile-task-actions.ts
|
|
163330
|
+
var MOBILE_TASK_ACTION_KINDS = [
|
|
163331
|
+
"group_join",
|
|
163332
|
+
// 入群 (加入一个 OrbitDB 群 store)
|
|
163333
|
+
"group_leave",
|
|
163334
|
+
// 退群
|
|
163335
|
+
"group_create",
|
|
163336
|
+
// 建群 (会自动入群)
|
|
163337
|
+
"announce_publish",
|
|
163338
|
+
// 发布任务公告 (落盘公告 + 向注册表公告 + 记脉冲)
|
|
163339
|
+
"announce_to_group",
|
|
163340
|
+
// 把板上的公告推进群里 (CLI: bolloon task announce)
|
|
163341
|
+
"trail_post"
|
|
163342
|
+
// 过程留痕: 接单/交付/初筛/终审 (CLI: bolloon task post)
|
|
163343
|
+
];
|
|
163344
|
+
var TASK_ACTION_TTL_MS = 10 * 6e4;
|
|
163345
|
+
var TASK_ACTION_DEFAULT_TTL_MS = 5 * 6e4;
|
|
163346
|
+
var TASK_ACTION_CLOCK_SKEW_MS = 2 * 6e4;
|
|
163347
|
+
function tok(v) {
|
|
163348
|
+
if (v === null || v === void 0) return "-";
|
|
163349
|
+
const s2 = String(v);
|
|
163350
|
+
if (!s2) return "-";
|
|
163351
|
+
return s2.replace(/\r?\n/g, "\\n");
|
|
163352
|
+
}
|
|
163353
|
+
function taskActionContentText(req) {
|
|
163354
|
+
const kind = String(req?.kind ?? "");
|
|
163355
|
+
const base6 = [
|
|
163356
|
+
`kind=${tok(kind)}`,
|
|
163357
|
+
`group=${tok(req?.groupRef)}`,
|
|
163358
|
+
`ann=${tok(req?.announcementId)}`
|
|
163359
|
+
];
|
|
163360
|
+
if (kind === "announce_publish") {
|
|
163361
|
+
base6.push(`cap=${tok(req?.capability)}`);
|
|
163362
|
+
base6.push(`budget=${tok(req?.budgetHuman)}${req?.currency ? `@${tok(req.currency)}` : ""}`);
|
|
163363
|
+
base6.push(`deadline=${tok(req?.deadline)}`);
|
|
163364
|
+
base6.push(`instruction=${tok(req?.instruction)}`);
|
|
163365
|
+
} else if (kind === "announce_to_group") {
|
|
163366
|
+
base6.push(`criteria=${tok(req?.criteria)}`);
|
|
163367
|
+
} else if (kind === "trail_post") {
|
|
163368
|
+
base6.push(`trail=${tok(req?.trailKind)}`);
|
|
163369
|
+
base6.push(`round=${tok(req?.round)}`);
|
|
163370
|
+
base6.push(`price=${tok(req?.price)}`);
|
|
163371
|
+
base6.push(`hash=${tok(req?.hash)}`);
|
|
163372
|
+
base6.push(`bytes=${tok(req?.bytes)}`);
|
|
163373
|
+
base6.push(`checks=${tok(req?.checks)}`);
|
|
163374
|
+
base6.push(`verdict=${tok(req?.verdict)}`);
|
|
163375
|
+
}
|
|
163376
|
+
return base6.join("\n");
|
|
163377
|
+
}
|
|
163378
|
+
function canonicalTaskActionPayload(a) {
|
|
162928
163379
|
return JSON.stringify({
|
|
162929
|
-
|
|
162930
|
-
|
|
162931
|
-
|
|
162932
|
-
|
|
162933
|
-
|
|
162934
|
-
|
|
162935
|
-
|
|
162936
|
-
|
|
162937
|
-
|
|
162938
|
-
|
|
162939
|
-
sensitiveContentAllowed: g.sensitiveContentAllowed,
|
|
162940
|
-
newRecipientAllowed: g.newRecipientAllowed,
|
|
162941
|
-
grantedAt: g.grantedAt,
|
|
162942
|
-
grantedBy: g.grantedBy,
|
|
162943
|
-
grantedVia: g.grantedVia,
|
|
162944
|
-
deviceIds: [...g.deviceIds].sort(),
|
|
162945
|
-
status: g.status,
|
|
162946
|
-
revokedAt: g.revokedAt || "",
|
|
162947
|
-
grantVersion: g.grantVersion
|
|
163380
|
+
actionId: a.actionId,
|
|
163381
|
+
kind: a.kind,
|
|
163382
|
+
deviceId: a.deviceId,
|
|
163383
|
+
ownerDid: a.ownerDid,
|
|
163384
|
+
targetRef: a.targetRef || "",
|
|
163385
|
+
contentDigest: a.contentDigest,
|
|
163386
|
+
createdAt: a.createdAt,
|
|
163387
|
+
expiresAt: a.expiresAt,
|
|
163388
|
+
grantedBy: a.grantedBy,
|
|
163389
|
+
via: a.via
|
|
162948
163390
|
});
|
|
162949
163391
|
}
|
|
162950
|
-
function
|
|
162951
|
-
return
|
|
162952
|
-
}
|
|
162953
|
-
function
|
|
162954
|
-
|
|
162955
|
-
|
|
162956
|
-
|
|
162957
|
-
|
|
162958
|
-
|
|
162959
|
-
|
|
162960
|
-
|
|
162961
|
-
|
|
162962
|
-
}
|
|
163392
|
+
function isIso(s2) {
|
|
163393
|
+
return typeof s2 === "string" && s2.length >= 20 && Number.isFinite(Date.parse(s2));
|
|
163394
|
+
}
|
|
163395
|
+
function checkTaskActionFreshness(a, now) {
|
|
163396
|
+
if (!isIso(a?.createdAt) || !isIso(a?.expiresAt)) return { ok: false, reason: "bad_time" };
|
|
163397
|
+
const created = Date.parse(a.createdAt);
|
|
163398
|
+
const expires = Date.parse(a.expiresAt);
|
|
163399
|
+
if (expires - created > TASK_ACTION_TTL_MS) return { ok: false, reason: "ttl_too_long" };
|
|
163400
|
+
if (expires < created) return { ok: false, reason: "bad_time" };
|
|
163401
|
+
if (now > expires) return { ok: false, reason: "expired" };
|
|
163402
|
+
if (now < created - TASK_ACTION_CLOCK_SKEW_MS) return { ok: false, reason: "not_yet_valid" };
|
|
163403
|
+
return { ok: true };
|
|
162963
163404
|
}
|
|
162964
163405
|
|
|
162965
|
-
// src/
|
|
162966
|
-
var
|
|
162967
|
-
|
|
162968
|
-
|
|
162969
|
-
|
|
162970
|
-
|
|
162971
|
-
|
|
162972
|
-
|
|
162973
|
-
|
|
162974
|
-
|
|
162975
|
-
|
|
162976
|
-
|
|
162977
|
-
|
|
162978
|
-
}
|
|
163406
|
+
// src/agents/task-public-text.ts
|
|
163407
|
+
var PRIVACY_RULES = [
|
|
163408
|
+
{ rule: "wallet-address", why: "\u4EE5\u592A\u574A/EVM \u94B1\u5305\u5730\u5740", re: /(?<![0-9a-fA-FxX])0x[0-9a-fA-F]{40}(?![0-9a-fA-F])/ },
|
|
163409
|
+
{ rule: "private-key-hex", why: "32 \u5B57\u8282\u79C1\u94A5\u5F62\u6001 (0x + 64 hex)", re: /(?<![0-9a-fA-FxX])0x[0-9a-fA-F]{64}(?![0-9a-fA-F])/ },
|
|
163410
|
+
{ rule: "hex-0x-blob", why: "0x \u5F00\u5934\u7684\u5341\u516D\u8FDB\u5236\u5757 (\u7B7E\u540D/\u54C8\u5E0C/\u5BC6\u94A5\u90FD\u957F\u8FD9\u6837, \u7FA4\u91CC\u4E00\u5F8B\u4E0D\u653E\u539F\u6587)", re: /(?<![0-9a-fA-FxX])0x[0-9a-fA-F]{8,}(?![0-9a-fA-F])/ },
|
|
163411
|
+
{ rule: "did", why: "\u53BB\u4E2D\u5FC3\u5316\u8EAB\u4EFD DID", re: /did:[a-z0-9]+:[A-Za-z0-9._:%-]{3,}/i },
|
|
163412
|
+
{ rule: "peer-id", why: "libp2p peerId (12D3Koo\u2026/Qm\u2026)", re: /12D3Koo[A-Za-z0-9]{8,}|Qm[1-9A-HJ-NP-Za-km-z]{30,}/ },
|
|
163413
|
+
{ rule: "multiaddr", why: "libp2p multiaddr \u6216 store \u5730\u5740 (/ip4 /tcp /p2p /orbitdb \u2026)", re: /\/(ip4|ip6|dns|dns4|dns6|tcp|udp|ws|wss|quic|p2p|p2p-circuit|ipfs|orbitdb)(?![A-Za-z0-9])/i },
|
|
163414
|
+
{ rule: "orbitdb-link", why: "OrbitDB \u94FE\u63A5 (\u7FA4\u9080\u8BF7\u94FE\u63A5\u672C\u8EAB\u4E5F\u4E0D\u8FDB\u7FA4\u6D88\u606F)", re: /orbitdb:\/\//i },
|
|
163415
|
+
{ rule: "ipv4", why: "IPv4 \u5730\u5740", re: /(?<!\d)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?!\d)/ },
|
|
163416
|
+
{ rule: "ipv6", why: "IPv6 \u5730\u5740 (\u4E0D\u542B ISO \u65F6\u95F4\u6233)", re: /(?<![0-9A-Za-z])(?:[0-9a-fA-F]{1,4})?::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}(?![0-9A-Za-z])|(?<![0-9A-Za-z:])(?:[0-9a-fA-F]{1,4}:){3,}[0-9a-fA-F]{1,4}(?![0-9A-Za-z])/ },
|
|
163417
|
+
{ rule: "pem", why: "PEM \u6750\u6599 (\u79C1\u94A5/\u8BC1\u4E66)", re: /-----BEGIN [A-Z ]*(PRIVATE KEY|CERTIFICATE)/ },
|
|
163418
|
+
{ rule: "secret-words", why: "\u79C1\u94A5/\u52A9\u8BB0\u8BCD/\u5BC6\u94A5\u5B57\u6837 (\u6B63\u6587\u91CC\u63D0\u5230\u5373\u505C, \u4EBA\u4E0D\u8BE5\u628A\u5BC6\u94A5\u5199\u8FDB\u7FA4)", re: /(private\s*key|seed\s*phrase|mnemonic|私钥|助记词|密钥材料)/i },
|
|
163419
|
+
{ rule: "url", why: "http(s) \u7AEF\u70B9 (\u7AEF\u70B9\u4F1A\u5E26 host/IP \u4E0E\u7528\u9014\u6307\u7EB9)", re: /https?:\/\/\S+/i },
|
|
163420
|
+
{ rule: "email", why: "\u90AE\u7BB1\u5730\u5740", re: /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/ }
|
|
163421
|
+
];
|
|
163422
|
+
function mask(s2) {
|
|
163423
|
+
const t = String(s2 || "");
|
|
163424
|
+
return t.length <= 4 ? "****" : `${t.slice(0, 4)}\u2026`;
|
|
162979
163425
|
}
|
|
162980
|
-
function
|
|
162981
|
-
const
|
|
162982
|
-
const out =
|
|
162983
|
-
|
|
163426
|
+
function scanPublicText(text) {
|
|
163427
|
+
const t = String(text ?? "");
|
|
163428
|
+
const out = [];
|
|
163429
|
+
const seen = /* @__PURE__ */ new Set();
|
|
163430
|
+
for (const r of PRIVACY_RULES) {
|
|
163431
|
+
const m2 = r.re.exec(t);
|
|
163432
|
+
if (!m2) continue;
|
|
163433
|
+
if (seen.has(r.rule)) continue;
|
|
163434
|
+
seen.add(r.rule);
|
|
163435
|
+
out.push({ rule: r.rule, why: r.why, masked: mask(String(m2[0])), chars: String(m2[0]).length });
|
|
163436
|
+
}
|
|
162984
163437
|
return out;
|
|
162985
163438
|
}
|
|
162986
|
-
function
|
|
162987
|
-
const
|
|
162988
|
-
|
|
162989
|
-
|
|
162990
|
-
|
|
162991
|
-
|
|
162992
|
-
|
|
162993
|
-
|
|
162994
|
-
|
|
162995
|
-
|
|
162996
|
-
|
|
162997
|
-
|
|
163439
|
+
function requirePublicText(text) {
|
|
163440
|
+
const v = scanPublicText(text);
|
|
163441
|
+
return v.length === 0 ? { ok: true } : { ok: false, violations: v };
|
|
163442
|
+
}
|
|
163443
|
+
var NODE_IDENTITY_RULES = PRIVACY_RULES.filter((r) => r.rule !== "orbitdb-link").map((r) => r.rule === "multiaddr" ? { ...r, re: /\/(ip4|ip6|dns|dns4|dns6|tcp|udp|ws|wss|quic|p2p|p2p-circuit|ipfs)(?![A-Za-z0-9])/i } : r);
|
|
163444
|
+
|
|
163445
|
+
// src/agents/mobile-task-views.ts
|
|
163446
|
+
function shortId(id, n = 12) {
|
|
163447
|
+
const s2 = String(id ?? "").trim();
|
|
163448
|
+
if (!s2) return "";
|
|
163449
|
+
return s2.length <= n ? s2 : `${s2.slice(0, n)}\u2026`;
|
|
163450
|
+
}
|
|
163451
|
+
function isProtocolId(s2) {
|
|
163452
|
+
const v = String(s2 ?? "").trim();
|
|
163453
|
+
return /^ann-[0-9a-f]{8,}$/i.test(v) || /^act-[a-z0-9-]{6,}$/i.test(v) || /^zdpu[0-9a-zA-Z]{8,}$/.test(v) || /^\/orbitdb\//.test(v);
|
|
163454
|
+
}
|
|
163455
|
+
function formatRelative(ms2, lang) {
|
|
163456
|
+
if (ms2 === null || !Number.isFinite(ms2)) return lang === "zh" ? "\u2014" : "\u2014";
|
|
163457
|
+
const past = ms2 >= 0;
|
|
163458
|
+
const abs = Math.abs(ms2);
|
|
163459
|
+
const min = Math.floor(abs / 6e4);
|
|
163460
|
+
const hr = Math.floor(abs / 36e5);
|
|
163461
|
+
const day = Math.floor(abs / 864e5);
|
|
163462
|
+
const unit = day >= 1 ? lang === "zh" ? `${day} \u5929` : `${day} d` : hr >= 1 ? lang === "zh" ? `${hr} \u5C0F\u65F6` : `${hr} h` : min >= 1 ? lang === "zh" ? `${min} \u5206\u949F` : `${min} min` : lang === "zh" ? "\u4E0D\u5230 1 \u5206\u949F" : "under a minute";
|
|
163463
|
+
if (lang === "zh") return past ? `${unit}\u524D` : `${unit}\u540E`;
|
|
163464
|
+
return past ? `${unit} ago` : `in ${unit}`;
|
|
163465
|
+
}
|
|
163466
|
+
var STATUS_LABELS = {
|
|
163467
|
+
open: { zh: "\u53EF\u63A5\u5355", en: "Open for claims" },
|
|
163468
|
+
claimed: { zh: "\u5DF2\u88AB\u63A5\u5355", en: "Claimed" },
|
|
163469
|
+
cancelled: { zh: "\u5DF2\u53D6\u6D88", en: "Cancelled" },
|
|
163470
|
+
unknown: { zh: "\u72B6\u6001\u672A\u77E5", en: "Unknown status" }
|
|
163471
|
+
};
|
|
163472
|
+
function budgetLabelOf(b) {
|
|
163473
|
+
if (!b || typeof b !== "object") return "";
|
|
163474
|
+
const amt = String(b.maxAmount ?? "").trim();
|
|
163475
|
+
if (!amt) return "";
|
|
163476
|
+
return `${amt} ${String(b.currency || "").toUpperCase()}${b.network ? ` \xB7 ${String(b.network)}` : ""}`;
|
|
163477
|
+
}
|
|
163478
|
+
function boardItemOf(e, now) {
|
|
163479
|
+
const dl = Number.isFinite(Number(e?.deadline)) ? Number(e.deadline) : null;
|
|
163480
|
+
const ca = Number.isFinite(Number(e?.createdAt)) ? Number(e.createdAt) : null;
|
|
163481
|
+
const status = String(e?.status || "unknown");
|
|
163482
|
+
return {
|
|
163483
|
+
idShort: shortId(e?.announcementId),
|
|
163484
|
+
ref: String(e?.announcementId || ""),
|
|
163485
|
+
capability: String(e?.capability || ""),
|
|
163486
|
+
status,
|
|
163487
|
+
statusLabel: STATUS_LABELS[status] || STATUS_LABELS.unknown,
|
|
163488
|
+
budgetLabel: budgetLabelOf(e?.budget),
|
|
163489
|
+
deadlineInMs: dl === null ? null : dl - now,
|
|
163490
|
+
createdAtMs: ca,
|
|
163491
|
+
claimCount: Number.isFinite(Number(e?.claimCount)) ? Number(e.claimCount) : 0,
|
|
163492
|
+
preview: e?.instructionPreview ? String(e.instructionPreview).slice(0, 120) : null,
|
|
163493
|
+
remote: !!e?.remote,
|
|
163494
|
+
claimable: !!e?.claimable,
|
|
163495
|
+
signatureVerified: e?.signatureVerified === true ? true : e?.signatureVerified === false ? false : null
|
|
163496
|
+
};
|
|
162998
163497
|
}
|
|
162999
|
-
|
|
163000
|
-
const
|
|
163001
|
-
return
|
|
163498
|
+
function buildBoardView(view, now) {
|
|
163499
|
+
const items = (Array.isArray(view?.entries) ? view.entries : []).map((e) => boardItemOf(e, now));
|
|
163500
|
+
return {
|
|
163501
|
+
items,
|
|
163502
|
+
localCount: Number(view?.localCount) || 0,
|
|
163503
|
+
remoteCount: Number(view?.remoteCount) || 0,
|
|
163504
|
+
registryReady: view?.registryReady === true,
|
|
163505
|
+
registryError: view?.registryError ? String(view.registryError).slice(0, 160) : null,
|
|
163506
|
+
notes: Array.isArray(view?.notes) ? view.notes.map((n) => String(n)) : [],
|
|
163507
|
+
openCount: items.filter((i) => i.claimable).length
|
|
163508
|
+
};
|
|
163002
163509
|
}
|
|
163003
|
-
|
|
163004
|
-
|
|
163005
|
-
|
|
163006
|
-
|
|
163007
|
-
|
|
163008
|
-
|
|
163009
|
-
|
|
163010
|
-
|
|
163011
|
-
|
|
163510
|
+
var TRAIL_KIND_LABELS = {
|
|
163511
|
+
announce: { zh: "\u516C\u544A", en: "Announce" },
|
|
163512
|
+
claim: { zh: "\u63A5\u5355\u58F0\u660E", en: "Claim" },
|
|
163513
|
+
deliver: { zh: "\u4EA4\u4ED8", en: "Delivery" },
|
|
163514
|
+
screen: { zh: "\u521D\u7B5B\u7ED3\u679C", en: "Screening" },
|
|
163515
|
+
final: { zh: "\u7EC8\u5BA1\u7ED3\u8BBA", en: "Final verdict" }
|
|
163516
|
+
};
|
|
163517
|
+
var INCONSISTENCY_LABELS = {
|
|
163518
|
+
"final-accept-without-delivery": { zh: "\u8BF4\u901A\u8FC7\u4E86, \u4F46\u7FA4\u91CC\u6CA1\u6709\u4EA4\u4ED8\u75D5\u8FF9", en: "Accepted, but no delivery trace in the group" },
|
|
163519
|
+
"screen-without-delivery": { zh: "\u6709\u521D\u7B5B\u7ED3\u679C, \u4F46\u6CA1\u6709\u4EA4\u4ED8\u75D5\u8FF9", en: "Screening exists without a delivery trace" },
|
|
163520
|
+
"claim-without-announce": { zh: "\u6709\u4EBA\u63A5\u5355, \u4F46\u7FA4\u91CC\u6CA1\u6709\u516C\u544A\u75D5\u8FF9", en: "Claim without an announcement trace" },
|
|
163521
|
+
"deliver-without-claim": { zh: "\u6709\u4EA4\u4ED8, \u4F46\u6CA1\u4EBA\u63A5\u8FC7\u5355", en: "Delivery without a claim" },
|
|
163522
|
+
"both-accept-and-reject": { zh: "\u540C\u65F6\u51FA\u73B0\u901A\u8FC7\u548C\u62D2\u7EDD", en: "Both accepted and rejected appear" },
|
|
163523
|
+
"group-message-hit-privacy-rule": { zh: "\u7FA4\u91CC\u6709\u4EBA\u53D1\u4E86\u5E26\u6807\u8BC6\u7B26\u7684\u6D88\u606F (\u5DF2\u906E\u853D, \u4E0D\u5F53\u4E8B\u5B9E\u91C7\u7528)", en: "A group message hit a privacy rule (masked, not used as fact)" }
|
|
163524
|
+
};
|
|
163525
|
+
function buildTrailView(summary) {
|
|
163526
|
+
const entries = (Array.isArray(summary?.entries) ? summary.entries : []).map((e) => {
|
|
163527
|
+
const facts = [];
|
|
163528
|
+
for (const [k, v] of Object.entries(e?.fields || {})) {
|
|
163529
|
+
if (k === "kind") continue;
|
|
163530
|
+
const raw = String(v ?? "");
|
|
163531
|
+
const hit = scanPublicText(raw);
|
|
163532
|
+
if (hit.length) {
|
|
163533
|
+
facts.push({ k: String(k), v: `[\u5DF2\u906E\u853D:${hit[0].rule}]` });
|
|
163534
|
+
continue;
|
|
163535
|
+
}
|
|
163536
|
+
facts.push({ k: String(k), v: k === "id" || isProtocolId(raw) ? shortId(raw) : raw });
|
|
163012
163537
|
}
|
|
163013
|
-
|
|
163014
|
-
|
|
163538
|
+
const kind = String(e?.kind || "");
|
|
163539
|
+
return {
|
|
163540
|
+
idShort: shortId(e?.announcementId),
|
|
163541
|
+
kind,
|
|
163542
|
+
kindLabel: TRAIL_KIND_LABELS[kind] || { zh: kind, en: kind },
|
|
163543
|
+
sender: String(e?.sender || "unknown"),
|
|
163544
|
+
atMs: Number.isFinite(Number(e?.at)) ? Number(e.at) : 0,
|
|
163545
|
+
facts
|
|
163546
|
+
};
|
|
163547
|
+
});
|
|
163548
|
+
const inc = (Array.isArray(summary?.inconsistencies) ? summary.inconsistencies : []).map((c) => ({
|
|
163549
|
+
code: String(c),
|
|
163550
|
+
label: INCONSISTENCY_LABELS[String(c)] || { zh: String(c), en: String(c) }
|
|
163551
|
+
}));
|
|
163552
|
+
return {
|
|
163553
|
+
count: Number(summary?.count) || entries.length,
|
|
163554
|
+
byKind: summary?.byKind || {},
|
|
163555
|
+
entries,
|
|
163556
|
+
announcementIdsShort: (Array.isArray(summary?.announcements) ? summary.announcements : []).map((a) => shortId(a)),
|
|
163557
|
+
flags: summary?.flags || {},
|
|
163558
|
+
inconsistencies: inc,
|
|
163559
|
+
redactedCount: Array.isArray(summary?.redacted) ? summary.redacted.length : 0,
|
|
163560
|
+
ignoredMessages: Number(summary?.ignoredMessages) || 0,
|
|
163561
|
+
privacyHits: inc.some((x) => x.code === "group-message-hit-privacy-rule") || Array.isArray(summary?.redacted) && summary.redacted.length > 0
|
|
163562
|
+
};
|
|
163563
|
+
}
|
|
163564
|
+
function buildGroupsView(groups) {
|
|
163565
|
+
return (Array.isArray(groups) ? groups : []).map((g) => ({
|
|
163566
|
+
idShort: shortId(g?.id),
|
|
163567
|
+
name: String(g?.name || ""),
|
|
163568
|
+
joinedAt: String(g?.createdAt || "")
|
|
163569
|
+
}));
|
|
163570
|
+
}
|
|
163571
|
+
function describeTaskActionForConfirm(kind, req) {
|
|
163572
|
+
const lines = [];
|
|
163573
|
+
const push = (k, kEn, v) => {
|
|
163574
|
+
const s2 = String(v ?? "").trim();
|
|
163575
|
+
if (s2 && s2 !== "-") lines.push({ k, kEn, v: s2 });
|
|
163576
|
+
};
|
|
163577
|
+
push("\u7FA4", "group", req?.groupRef ? shortId(req.groupRef, 24) : "");
|
|
163578
|
+
push("\u516C\u544A\u53F7", "announcement", req?.announcementId ? shortId(req.announcementId) : "");
|
|
163579
|
+
push("\u80FD\u529B", "capability", req?.capability);
|
|
163580
|
+
push("\u9884\u7B97", "budget", req?.budgetHuman ? `${req.budgetHuman} ${String(req?.currency || "").toUpperCase()}` : "");
|
|
163581
|
+
push("\u4EFB\u52A1\u6B63\u6587", "instruction", req?.instruction);
|
|
163582
|
+
push("\u622A\u6B62", "deadline", req?.deadline);
|
|
163583
|
+
push("\u9A8C\u6536\u5224\u636E", "criteria", req?.criteria);
|
|
163584
|
+
push("\u671F\u53F7", "round", req?.round);
|
|
163585
|
+
push("\u75D5\u8FF9\u7C7B\u578B", "trail kind", req?.trailKind ? TRAIL_KIND_LABELS[String(req.trailKind)]?.zh || String(req.trailKind) : "");
|
|
163586
|
+
push("\u58F0\u660E\u4EF7\u683C", "declared price", req?.price);
|
|
163587
|
+
push("\u4EA4\u4ED8\u54C8\u5E0C", "delivery hash", req?.hash);
|
|
163588
|
+
push("\u5B57\u8282\u6570", "bytes", req?.bytes);
|
|
163589
|
+
push("\u9010\u6761\u521D\u7B5B", "per-item screen", req?.checks);
|
|
163590
|
+
push("\u7EC8\u5BA1\u7ED3\u8BBA", "final verdict", req?.verdict);
|
|
163591
|
+
const titles = {
|
|
163592
|
+
group_join: { zh: "\u52A0\u5165\u8FD9\u4E2A\u7FA4", en: "Join this group" },
|
|
163593
|
+
group_leave: { zh: "\u9000\u51FA\u8FD9\u4E2A\u7FA4", en: "Leave this group" },
|
|
163594
|
+
group_create: { zh: "\u5EFA\u4E00\u4E2A\u65B0\u7FA4", en: "Create a new group" },
|
|
163595
|
+
announce_publish: { zh: "\u53D1\u5E03\u4EFB\u52A1\u516C\u544A", en: "Publish a task announcement" },
|
|
163596
|
+
announce_to_group: { zh: "\u628A\u8FD9\u671F\u516C\u544A\u53D1\u8FDB\u7FA4", en: "Post this announcement into the group" },
|
|
163597
|
+
trail_post: { zh: "\u5F80\u7FA4\u91CC\u7559\u4E00\u6761\u8FC7\u7A0B\u75D5\u8FF9", en: "Post a process trail entry into the group" }
|
|
163598
|
+
};
|
|
163599
|
+
const t = titles[String(kind)] || { zh: "\u6267\u884C\u8FD9\u4E2A\u52A8\u4F5C", en: "Run this action" };
|
|
163600
|
+
return { titleZh: t.zh, titleEn: t.en, lines };
|
|
163601
|
+
}
|
|
163602
|
+
|
|
163603
|
+
// src/agents/goal-flywheel/types.ts
|
|
163604
|
+
var MUST_NOT_EXPOSE_FIELDS = [
|
|
163605
|
+
"lease",
|
|
163606
|
+
"reducer",
|
|
163607
|
+
"internal_status",
|
|
163608
|
+
"retry_counter",
|
|
163609
|
+
"worker_owner"
|
|
163610
|
+
];
|
|
163611
|
+
|
|
163612
|
+
// src/agents/goal-flywheel/work-monitor.ts
|
|
163613
|
+
var NO_PROGRESS_FALLBACK_MS = 30 * 60 * 1e3;
|
|
163614
|
+
var DEFAULT_REPORT_GRACE_MS = 60 * 1e3;
|
|
163615
|
+
var DEFAULT_ESCALATION_MS = 10 * 60 * 1e3;
|
|
163616
|
+
var TERMINAL_GOAL_STATES = ["completed", "failed", "abandoned"];
|
|
163617
|
+
var TERMINAL_GOAL_STATUSES = [...TERMINAL_GOAL_STATES];
|
|
163618
|
+
|
|
163619
|
+
// src/agents/mobile-flywheel-view.ts
|
|
163620
|
+
function findInternalFieldLeaks(text) {
|
|
163621
|
+
const t = String(text ?? "");
|
|
163622
|
+
return MUST_NOT_EXPOSE_FIELDS.filter((f) => t.includes(f));
|
|
163623
|
+
}
|
|
163624
|
+
|
|
163625
|
+
// src/web/mobile-tasks.ts
|
|
163626
|
+
init_mobile_contacts();
|
|
163627
|
+
var K_TASKS_HINT = "bolloon.mobile.tasks.hint.v1";
|
|
163628
|
+
function defaultStorage2() {
|
|
163015
163629
|
try {
|
|
163016
|
-
|
|
163017
|
-
} catch
|
|
163018
|
-
throw new Error(`device_signing_unavailable: ${String(err2?.message || err2)}`);
|
|
163630
|
+
if (typeof localStorage !== "undefined") return localStorage;
|
|
163631
|
+
} catch {
|
|
163019
163632
|
}
|
|
163020
|
-
const
|
|
163021
|
-
|
|
163022
|
-
|
|
163023
|
-
|
|
163024
|
-
|
|
163025
|
-
|
|
163633
|
+
const mem2 = /* @__PURE__ */ new Map();
|
|
163634
|
+
return { getItem: (k) => mem2.has(k) ? mem2.get(k) : null, setItem: (k, v) => {
|
|
163635
|
+
mem2.set(k, v);
|
|
163636
|
+
}, removeItem: (k) => {
|
|
163637
|
+
mem2.delete(k);
|
|
163638
|
+
} };
|
|
163026
163639
|
}
|
|
163027
|
-
async function
|
|
163028
|
-
|
|
163029
|
-
|
|
163640
|
+
async function baseOf(deps) {
|
|
163641
|
+
if (deps.base && String(deps.base).trim()) return String(deps.base).replace(/\/+$/, "");
|
|
163642
|
+
try {
|
|
163643
|
+
if (typeof localStorage !== "undefined") {
|
|
163644
|
+
const v = localStorage.getItem("bolloon_desktop_base_url");
|
|
163645
|
+
if (v) return String(v).replace(/\/+$/, "");
|
|
163646
|
+
}
|
|
163647
|
+
} catch {
|
|
163648
|
+
}
|
|
163649
|
+
return "";
|
|
163030
163650
|
}
|
|
163031
|
-
|
|
163032
|
-
|
|
163033
|
-
const key = await importPrivate(storage2, cobj);
|
|
163034
|
-
const payload = canonicalGrantPayload(grant);
|
|
163035
|
-
const sig = await cobj.subtle.sign({ name: "Ed25519" }, key, bytesOf(payload));
|
|
163036
|
-
const dev = await loadOrCreateDeviceKey(storage2, cobj);
|
|
163037
|
-
return { deviceId: dev.deviceId, alg: "ed25519", payloadHash: await sha256Hex(cobj, payload), sig: b64(sig) };
|
|
163651
|
+
function fetchOf(deps) {
|
|
163652
|
+
return deps.fetchImpl || globalThis.fetch;
|
|
163038
163653
|
}
|
|
163039
|
-
async function
|
|
163040
|
-
const
|
|
163041
|
-
|
|
163042
|
-
|
|
163043
|
-
|
|
163044
|
-
|
|
163045
|
-
|
|
163654
|
+
async function getJson(base6, path, f) {
|
|
163655
|
+
const res = await f(`${base6}${path}`);
|
|
163656
|
+
let json = null;
|
|
163657
|
+
try {
|
|
163658
|
+
json = await res.json();
|
|
163659
|
+
} catch {
|
|
163660
|
+
}
|
|
163661
|
+
return { status: res.status, json };
|
|
163046
163662
|
}
|
|
163047
|
-
async function
|
|
163048
|
-
const res = await f(`${
|
|
163663
|
+
async function postJson(base6, path, body, f) {
|
|
163664
|
+
const res = await f(`${base6}${path}`, {
|
|
163049
163665
|
method: "POST",
|
|
163050
163666
|
headers: { "Content-Type": "application/json" },
|
|
163051
163667
|
body: JSON.stringify(body ?? {})
|
|
@@ -163057,232 +163673,1809 @@ ${b}
|
|
|
163057
163673
|
}
|
|
163058
163674
|
return { status: res.status, json };
|
|
163059
163675
|
}
|
|
163060
|
-
|
|
163061
|
-
|
|
163062
|
-
|
|
163676
|
+
var OFFLINE_NOTE = "\u5730\u5740\u5728 \u6211 \u2192 \u8BBE\u7F6E \u2192 \u7535\u8111\u7AEF\u5730\u5740 \u91CC\u586B; \u624B\u673A\u4E0D\u66FF\u684C\u9762\u8BB0\u8D26";
|
|
163677
|
+
function mapFail(r, what) {
|
|
163678
|
+
const code10 = r.json?.code ? String(r.json.code) : r.status ? `desktop_http_${r.status}` : "desktop_unreachable";
|
|
163679
|
+
return { ok: false, code: code10, error: `${what} \u5931\u8D25: ${r.json?.error || r.json?.message || code10}`, note: OFFLINE_NOTE };
|
|
163680
|
+
}
|
|
163681
|
+
function emptyTaskActionRequest(kind) {
|
|
163682
|
+
return {
|
|
163683
|
+
kind,
|
|
163684
|
+
groupRef: null,
|
|
163685
|
+
announcementId: null,
|
|
163686
|
+
capability: null,
|
|
163687
|
+
instruction: null,
|
|
163688
|
+
budgetHuman: null,
|
|
163689
|
+
currency: null,
|
|
163690
|
+
deadline: null,
|
|
163691
|
+
criteria: null,
|
|
163692
|
+
round: null,
|
|
163693
|
+
price: null,
|
|
163694
|
+
hash: null,
|
|
163695
|
+
bytes: null,
|
|
163696
|
+
checks: null,
|
|
163697
|
+
verdict: null,
|
|
163698
|
+
trailKind: null
|
|
163699
|
+
};
|
|
163700
|
+
}
|
|
163701
|
+
async function signTaskAction(req, deps = {}) {
|
|
163702
|
+
const storage2 = deps.storage || defaultStorage2();
|
|
163703
|
+
const c = deps.cryptoObj || globalThis.crypto;
|
|
163704
|
+
if (!ed25519Available(c)) {
|
|
163705
|
+
return { ok: false, code: "device_signing_unavailable", error: "\u672C\u673A WebView \u4E0D\u652F\u6301 Ed25519 \u8BBE\u5907\u7B7E\u540D \u2014\u2014 \u8BF7\u5728\u684C\u9762\u7AEF\u6267\u884C\u8FD9\u4E2A\u52A8\u4F5C (\u6216\u5347\u7EA7\u7CFB\u7EDF WebView)" };
|
|
163706
|
+
}
|
|
163707
|
+
if (!MOBILE_TASK_ACTION_KINDS.includes(String(req?.kind))) {
|
|
163708
|
+
return { ok: false, code: "unknown_kind", error: `\u672A\u77E5\u52A8\u4F5C: ${String(req?.kind || "")}` };
|
|
163709
|
+
}
|
|
163710
|
+
const text = taskActionContentText(req);
|
|
163711
|
+
if (req.kind === "trail_post" || req.kind === "announce_publish" || req.kind === "announce_to_group") {
|
|
163712
|
+
for (const fieldText of [req.round, req.price, req.criteria, req.checks, req.verdict, req.capability, req.hash]) {
|
|
163713
|
+
if (!fieldText) continue;
|
|
163714
|
+
const gate = requirePublicText(String(fieldText));
|
|
163715
|
+
if (!gate.ok) {
|
|
163716
|
+
return { ok: false, code: "privacy_denied", error: `\u672C\u5730\u9690\u79C1\u95F8\u62E6\u4E0B: ${gate.violations.map((v) => v.rule).join(", ")} (\u7FA4\u91CC/\u516C\u544A\u91CC\u4E0D\u653E\u6807\u8BC6\u7B26)`, violations: gate.violations };
|
|
163717
|
+
}
|
|
163718
|
+
}
|
|
163719
|
+
}
|
|
163720
|
+
const now = deps.now ? deps.now() : Date.now();
|
|
163721
|
+
const ttl = Math.min(Number(deps.ttlMs) || TASK_ACTION_DEFAULT_TTL_MS, TASK_ACTION_DEFAULT_TTL_MS);
|
|
163722
|
+
let contentDigest;
|
|
163063
163723
|
try {
|
|
163064
|
-
|
|
163724
|
+
contentDigest = await sha256HexOf(text, c);
|
|
163725
|
+
} catch (e) {
|
|
163726
|
+
return { ok: false, code: "device_signing_unavailable", error: String(e?.message || e) };
|
|
163727
|
+
}
|
|
163728
|
+
const action = {
|
|
163729
|
+
actionId: `act-${now.toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
163730
|
+
kind: req.kind,
|
|
163731
|
+
deviceId: "",
|
|
163732
|
+
// 由 signPayloadOnDevice 填 (它知道设备 id)
|
|
163733
|
+
ownerDid: String(deps.ownerDid || "").trim(),
|
|
163734
|
+
targetRef: String(req.groupRef || req.announcementId || ""),
|
|
163735
|
+
contentDigest,
|
|
163736
|
+
createdAt: new Date(now).toISOString(),
|
|
163737
|
+
expiresAt: new Date(now + ttl).toISOString(),
|
|
163738
|
+
grantedBy: deps.grantedBy || "leo",
|
|
163739
|
+
via: "mobile"
|
|
163740
|
+
};
|
|
163741
|
+
let signature;
|
|
163742
|
+
try {
|
|
163743
|
+
const { loadOrCreateDeviceKey: loadOrCreateDeviceKey2, signPayloadWithMaterial: signPayloadWithMaterial2 } = await Promise.resolve().then(() => (init_mobile_contacts(), mobile_contacts_exports));
|
|
163744
|
+
const material = await loadOrCreateDeviceKey2(storage2, c);
|
|
163745
|
+
action.deviceId = material.deviceId;
|
|
163746
|
+
signature = await signPayloadWithMaterial2(canonicalTaskActionPayload(action), material, c);
|
|
163747
|
+
if (signature.deviceId !== action.deviceId) {
|
|
163748
|
+
return { ok: false, code: "device_signing_unavailable", error: "\u8BBE\u5907\u5BC6\u94A5\u4E0D\u4E00\u81F4 (\u7B7E\u540D\u4E0E\u8F7D\u8377\u8BBE\u5907\u5BF9\u4E0D\u4E0A) \u2192 \u4E0D\u53D1\u9001" };
|
|
163749
|
+
}
|
|
163750
|
+
const fresh = checkTaskActionFreshness(action, now);
|
|
163751
|
+
if (!fresh.ok) return { ok: false, code: fresh.reason, error: `\u52A8\u4F5C\u65F6\u6548\u4E0D\u5408\u6CD5: ${fresh.reason}` };
|
|
163752
|
+
} catch (e) {
|
|
163753
|
+
return { ok: false, code: "device_signing_unavailable", error: String(e?.message || e).slice(0, 160) };
|
|
163754
|
+
}
|
|
163755
|
+
return {
|
|
163756
|
+
ok: true,
|
|
163757
|
+
data: { signed: { action, signature }, contentText: text, confirm: describeTaskActionForConfirm(req.kind, req) }
|
|
163758
|
+
};
|
|
163759
|
+
}
|
|
163760
|
+
async function executeTaskAction(req, deps = {}) {
|
|
163761
|
+
const storage2 = deps.storage || defaultStorage2();
|
|
163762
|
+
const base6 = await baseOf(deps);
|
|
163763
|
+
if (!base6) return { ok: false, code: "desktop_offline", error: "\u8FD8\u6CA1\u8BBE\u7F6E\u7535\u8111\u7AEF\u5730\u5740: \u9AD8\u98CE\u9669\u52A8\u4F5C\u5FC5\u987B\u7531\u684C\u9762\u6267\u884C (\u624B\u673A\u7B7E\u4E86\u540D\u4E5F\u8981\u9001\u5230\u684C\u9762)", note: OFFLINE_NOTE };
|
|
163764
|
+
const signed = await signTaskAction(req, { ...deps, storage: storage2 });
|
|
163765
|
+
if (!signed.ok || !signed.data) return { ok: false, code: signed.code, error: signed.error, violations: signed.violations };
|
|
163766
|
+
const f = fetchOf(deps);
|
|
163767
|
+
let r;
|
|
163768
|
+
try {
|
|
163769
|
+
r = await postJson(base6, "/api/mobile/tasks/execute", { request: req, ...signed.data.signed }, f);
|
|
163770
|
+
} catch (e) {
|
|
163771
|
+
return { ok: false, code: "desktop_offline", error: `\u684C\u9762\u4E0D\u53EF\u8FBE: ${String(e?.message || e).slice(0, 120)}`, note: OFFLINE_NOTE };
|
|
163772
|
+
}
|
|
163773
|
+
if (r.status !== 200 || !r.json?.ok) return mapFail(r, "\u6267\u884C");
|
|
163774
|
+
return { ok: true, data: r.json, note: "\u684C\u9762\u5DF2\u9A8C\u7B7E\u5E76\u6267\u884C (\u540C\u4E00\u5957\u5B58\u50A8\u4E0E\u534F\u8BAE)" };
|
|
163775
|
+
}
|
|
163776
|
+
async function previewGroupMessage(req, deps = {}) {
|
|
163777
|
+
const base6 = await baseOf(deps);
|
|
163778
|
+
if (!base6) return { ok: false, code: "desktop_offline", error: "\u9884\u89C8\u9700\u8981\u684C\u9762\u5728\u7EBF (\u7FA4\u6D88\u606F\u7531\u684C\u9762\u7684\u6784\u9020\u5668\u751F\u6210)", note: OFFLINE_NOTE };
|
|
163779
|
+
const c = deps.cryptoObj || globalThis.crypto;
|
|
163780
|
+
let digestPreview = "";
|
|
163781
|
+
try {
|
|
163782
|
+
digestPreview = await sha256HexOf(taskActionContentText(req), c);
|
|
163065
163783
|
} catch {
|
|
163784
|
+
digestPreview = "";
|
|
163785
|
+
}
|
|
163786
|
+
const f = fetchOf(deps);
|
|
163787
|
+
try {
|
|
163788
|
+
const r = await postJson(base6, "/api/mobile/tasks/preview", { request: req }, f);
|
|
163789
|
+
if (r.status !== 200 || !r.json?.ok) return mapFail(r, "\u9884\u89C8");
|
|
163790
|
+
return { ok: true, data: { text: String(r.json.text || ""), contentText: taskActionContentText(req), digestPreview } };
|
|
163791
|
+
} catch (e) {
|
|
163792
|
+
return { ok: false, code: "desktop_offline", error: `\u684C\u9762\u4E0D\u53EF\u8FBE: ${String(e?.message || e).slice(0, 120)}`, note: OFFLINE_NOTE };
|
|
163066
163793
|
}
|
|
163067
|
-
return { status: res.status, json };
|
|
163068
163794
|
}
|
|
163069
|
-
async function
|
|
163070
|
-
const
|
|
163071
|
-
|
|
163072
|
-
|
|
163073
|
-
|
|
163074
|
-
|
|
163795
|
+
async function listGroups(deps = {}) {
|
|
163796
|
+
const base6 = await baseOf(deps);
|
|
163797
|
+
if (!base6) return { ok: false, code: "desktop_offline", error: "\u770B\u7FA4\u5217\u8868\u9700\u8981\u7535\u8111\u7AEF\u5728\u7EBF (\u7FA4\u5B58\u5728\u4E8E\u684C\u9762\u8282\u70B9\u7684 OrbitDB)", note: OFFLINE_NOTE };
|
|
163798
|
+
try {
|
|
163799
|
+
const r = await getJson(base6, "/api/mobile/tasks/groups", fetchOf(deps));
|
|
163800
|
+
if (r.status !== 200 || !r.json?.ok) return mapFail(r, "\u8BFB\u7FA4\u5217\u8868");
|
|
163801
|
+
return { ok: true, data: buildGroupsView(r.json.groups || []) };
|
|
163802
|
+
} catch (e) {
|
|
163803
|
+
return { ok: false, code: "desktop_offline", error: `\u684C\u9762\u4E0D\u53EF\u8FBE: ${String(e?.message || e).slice(0, 120)}`, note: OFFLINE_NOTE };
|
|
163804
|
+
}
|
|
163075
163805
|
}
|
|
163076
|
-
function
|
|
163077
|
-
const
|
|
163078
|
-
|
|
163079
|
-
kind: c.kind,
|
|
163080
|
-
displayValue: String(c.displayValue || ""),
|
|
163081
|
-
verificationStatus: String(c.verificationStatus || ""),
|
|
163082
|
-
capabilities: [...c.capabilities || []],
|
|
163083
|
-
provider: c.provider ? String(c.provider) : void 0,
|
|
163084
|
-
state: c.state ? String(c.state) : void 0
|
|
163085
|
-
}));
|
|
163086
|
-
storage2.setItem(K_CAPS, JSON.stringify(clean8));
|
|
163806
|
+
function joinGroup(link, deps = {}) {
|
|
163807
|
+
const req = { ...emptyTaskActionRequest("group_join"), groupRef: String(link || "").trim() };
|
|
163808
|
+
return executeTaskAction(req, deps);
|
|
163087
163809
|
}
|
|
163088
|
-
function
|
|
163810
|
+
function leaveGroup(groupRef, deps = {}) {
|
|
163811
|
+
const req = { ...emptyTaskActionRequest("group_leave"), groupRef: String(groupRef || "").trim() };
|
|
163812
|
+
return executeTaskAction(req, deps);
|
|
163813
|
+
}
|
|
163814
|
+
function createGroup(name10, deps = {}) {
|
|
163815
|
+
const req = { ...emptyTaskActionRequest("group_create"), groupRef: String(name10 || "").trim() };
|
|
163816
|
+
return executeTaskAction(req, deps);
|
|
163817
|
+
}
|
|
163818
|
+
async function loadBoard(deps = {}) {
|
|
163819
|
+
const base6 = await baseOf(deps);
|
|
163820
|
+
if (!base6) return { ok: false, code: "desktop_offline", error: "\u770B\u677F\u9700\u8981\u7535\u8111\u7AEF\u5728\u7EBF (\u516C\u544A\u677F\u5728\u684C\u9762\u8282\u70B9\u4E0A)", note: OFFLINE_NOTE };
|
|
163821
|
+
const now = deps.now ? deps.now() : Date.now();
|
|
163089
163822
|
try {
|
|
163090
|
-
const
|
|
163091
|
-
|
|
163823
|
+
const r = await getJson(base6, "/api/mobile/tasks/board", fetchOf(deps));
|
|
163824
|
+
if (r.status !== 200 || !r.json?.ok) return mapFail(r, "\u8BFB\u770B\u677F");
|
|
163825
|
+
return { ok: true, data: buildBoardView(r.json, now) };
|
|
163826
|
+
} catch (e) {
|
|
163827
|
+
return { ok: false, code: "desktop_offline", error: `\u684C\u9762\u4E0D\u53EF\u8FBE: ${String(e?.message || e).slice(0, 120)}`, note: OFFLINE_NOTE };
|
|
163828
|
+
}
|
|
163829
|
+
}
|
|
163830
|
+
function publishAnnouncement(input, deps = {}) {
|
|
163831
|
+
const req = {
|
|
163832
|
+
...emptyTaskActionRequest("announce_publish"),
|
|
163833
|
+
capability: String(input.capability || "").trim(),
|
|
163834
|
+
instruction: String(input.instruction || ""),
|
|
163835
|
+
budgetHuman: String(input.budgetHuman || "").trim(),
|
|
163836
|
+
currency: String(input.currency || "USDC").toUpperCase(),
|
|
163837
|
+
deadline: input.deadline ? String(input.deadline).trim() : null
|
|
163838
|
+
};
|
|
163839
|
+
return executeTaskAction(req, deps);
|
|
163840
|
+
}
|
|
163841
|
+
function announceIntoGroup(input, deps = {}) {
|
|
163842
|
+
const req = {
|
|
163843
|
+
...emptyTaskActionRequest("announce_to_group"),
|
|
163844
|
+
groupRef: String(input.groupRef || "").trim(),
|
|
163845
|
+
announcementId: String(input.announcementId || "").trim(),
|
|
163846
|
+
round: input.round ? String(input.round) : null,
|
|
163847
|
+
criteria: input.criteria ? String(input.criteria) : null
|
|
163848
|
+
};
|
|
163849
|
+
return executeTaskAction(req, deps);
|
|
163850
|
+
}
|
|
163851
|
+
function postTrail(input, deps = {}) {
|
|
163852
|
+
const req = {
|
|
163853
|
+
...emptyTaskActionRequest("trail_post"),
|
|
163854
|
+
groupRef: String(input.groupRef || "").trim(),
|
|
163855
|
+
announcementId: String(input.announcementId || "").trim(),
|
|
163856
|
+
round: input.round ? String(input.round) : null,
|
|
163857
|
+
price: input.price ? String(input.price) : null,
|
|
163858
|
+
hash: input.hash ? String(input.hash) : null,
|
|
163859
|
+
bytes: typeof input.bytes === "number" ? input.bytes : null,
|
|
163860
|
+
checks: input.checks ? String(input.checks) : null,
|
|
163861
|
+
verdict: input.verdict ? String(input.verdict) : null,
|
|
163862
|
+
trailKind: input.kind
|
|
163863
|
+
};
|
|
163864
|
+
return executeTaskAction(req, deps);
|
|
163865
|
+
}
|
|
163866
|
+
async function loadTrail(input, deps = {}) {
|
|
163867
|
+
const base6 = await baseOf(deps);
|
|
163868
|
+
if (!base6) return { ok: false, code: "desktop_offline", error: "\u8BFB\u7FA4\u75D5\u8FF9\u9700\u8981\u7535\u8111\u7AEF\u5728\u7EBF", note: OFFLINE_NOTE };
|
|
163869
|
+
const q = new URLSearchParams();
|
|
163870
|
+
q.set("group", String(input.groupRef || "").trim());
|
|
163871
|
+
if (input.announcementId) q.set("announcementId", String(input.announcementId));
|
|
163872
|
+
if (input.limit) q.set("limit", String(input.limit));
|
|
163873
|
+
try {
|
|
163874
|
+
const r = await getJson(base6, `/api/mobile/tasks/trail?${q.toString()}`, fetchOf(deps));
|
|
163875
|
+
if (r.status !== 200 || !r.json?.ok) return mapFail(r, "\u8BFB\u7FA4\u75D5\u8FF9");
|
|
163876
|
+
return { ok: true, data: buildTrailView(r.json.summary || r.json) };
|
|
163877
|
+
} catch (e) {
|
|
163878
|
+
return { ok: false, code: "desktop_offline", error: `\u684C\u9762\u4E0D\u53EF\u8FBE: ${String(e?.message || e).slice(0, 120)}`, note: OFFLINE_NOTE };
|
|
163879
|
+
}
|
|
163880
|
+
}
|
|
163881
|
+
async function loadFlywheel(deps = {}) {
|
|
163882
|
+
const base6 = await baseOf(deps);
|
|
163883
|
+
if (!base6) return { ok: false, code: "desktop_offline", error: "\u770B\u98DE\u8F6E\u8FDB\u5EA6\u9700\u8981\u7535\u8111\u7AEF\u5728\u7EBF (Goal \u8BB0\u5F55\u5728\u684C\u9762\u8282\u70B9\u4E0A)", note: OFFLINE_NOTE };
|
|
163884
|
+
try {
|
|
163885
|
+
const r = await getJson(base6, "/api/mobile/tasks/flywheel", fetchOf(deps));
|
|
163886
|
+
if (r.status !== 200 || !r.json?.ok) return mapFail(r, "\u8BFB\u98DE\u8F6E\u8FDB\u5EA6");
|
|
163887
|
+
const goals = Array.isArray(r.json.goals) ? r.json.goals : [];
|
|
163888
|
+
const leaks = findInternalFieldLeaks(JSON.stringify(goals));
|
|
163889
|
+
if (leaks.length) return { ok: false, code: "view_leak", error: `\u89C6\u56FE\u91CC\u542B\u5185\u90E8\u5B57\u6BB5 (${leaks.join(", ")}) \u2192 \u62D2\u7EDD\u6E32\u67D3` };
|
|
163890
|
+
return { ok: true, data: { goals, hint: r.json.hint ? String(r.json.hint) : null } };
|
|
163891
|
+
} catch (e) {
|
|
163892
|
+
return { ok: false, code: "desktop_offline", error: `\u684C\u9762\u4E0D\u53EF\u8FBE: ${String(e?.message || e).slice(0, 120)}`, note: OFFLINE_NOTE };
|
|
163893
|
+
}
|
|
163894
|
+
}
|
|
163895
|
+
function setTaskHint(text, storage2 = defaultStorage2()) {
|
|
163896
|
+
try {
|
|
163897
|
+
storage2.setItem(K_TASKS_HINT, String(text || "").slice(0, 160));
|
|
163092
163898
|
} catch {
|
|
163093
|
-
return [];
|
|
163094
163899
|
}
|
|
163095
163900
|
}
|
|
163096
|
-
function
|
|
163901
|
+
function getTaskHint(storage2 = defaultStorage2()) {
|
|
163097
163902
|
try {
|
|
163098
|
-
|
|
163099
|
-
return Array.isArray(v) ? v : [];
|
|
163903
|
+
return String(storage2.getItem(K_TASKS_HINT) || "");
|
|
163100
163904
|
} catch {
|
|
163101
|
-
return
|
|
163905
|
+
return "";
|
|
163102
163906
|
}
|
|
163103
163907
|
}
|
|
163104
|
-
|
|
163105
|
-
|
|
163908
|
+
|
|
163909
|
+
// src/utils/version-identity.ts
|
|
163910
|
+
var PKG_NAME = "@bolloon/bolloon-agent";
|
|
163911
|
+
var GITHUB_UPSTREAM_SLUG = "logos-42/bolloon";
|
|
163912
|
+
function envValue(key) {
|
|
163913
|
+
try {
|
|
163914
|
+
const cfg = globalThis?.__bolloonUpdateConfig;
|
|
163915
|
+
if (cfg && cfg[key] !== void 0 && cfg[key] !== null) return String(cfg[key]);
|
|
163916
|
+
const env = typeof process !== "undefined" ? process?.env : null;
|
|
163917
|
+
const v = env ? env[key] : void 0;
|
|
163918
|
+
return v === void 0 || v === null ? void 0 : String(v);
|
|
163919
|
+
} catch {
|
|
163920
|
+
return void 0;
|
|
163921
|
+
}
|
|
163106
163922
|
}
|
|
163107
|
-
|
|
163108
|
-
|
|
163109
|
-
|
|
163110
|
-
|
|
163111
|
-
|
|
163112
|
-
|
|
163113
|
-
|
|
163114
|
-
|
|
163115
|
-
|
|
163116
|
-
|
|
163117
|
-
|
|
163118
|
-
|
|
163119
|
-
|
|
163120
|
-
|
|
163121
|
-
|
|
163122
|
-
|
|
163123
|
-
|
|
163124
|
-
|
|
163125
|
-
|
|
163126
|
-
|
|
163127
|
-
|
|
163128
|
-
|
|
163923
|
+
var NPM_REGISTRY_BASE = (envValue("BOLLOON_NPM_REGISTRY") || "https://registry.npmjs.org").replace(/\/+$/, "");
|
|
163924
|
+
var GITHUB_API_BASE = (envValue("BOLLOON_GITHUB_API") || "https://api.github.com").replace(/\/+$/, "");
|
|
163925
|
+
var DEV_BRANCH = "master";
|
|
163926
|
+
var DEV_REF = `refs/heads/${DEV_BRANCH}`;
|
|
163927
|
+
function resolveUpdateChannel(explicit, env) {
|
|
163928
|
+
const raw = (explicit || (env ? env.BOLLOON_UPDATE_CHANNEL : envValue("BOLLOON_UPDATE_CHANNEL")) || "").trim().toLowerCase();
|
|
163929
|
+
if (raw === "stable" || raw === "beta" || raw === "dev") return raw;
|
|
163930
|
+
return "stable";
|
|
163931
|
+
}
|
|
163932
|
+
function distTagForChannel(channel) {
|
|
163933
|
+
return channel === "beta" ? "beta" : "latest";
|
|
163934
|
+
}
|
|
163935
|
+
function channelKindOf(channel) {
|
|
163936
|
+
return channel === "dev" ? "git-ref" : "semver";
|
|
163937
|
+
}
|
|
163938
|
+
var DEV_IDENTITY_SEP = "+dev.";
|
|
163939
|
+
function devIdentity(baseVersion, sha4) {
|
|
163940
|
+
return `${baseVersionOf(baseVersion)}${DEV_IDENTITY_SEP}${String(sha4).slice(0, 7)}`;
|
|
163941
|
+
}
|
|
163942
|
+
function baseVersionOf(v) {
|
|
163943
|
+
return String(v || "").split(DEV_IDENTITY_SEP)[0].trim();
|
|
163944
|
+
}
|
|
163945
|
+
function isDevIdentity(v) {
|
|
163946
|
+
return String(v || "").includes(DEV_IDENTITY_SEP);
|
|
163947
|
+
}
|
|
163948
|
+
function devShaFromIdentity(v) {
|
|
163949
|
+
if (!isDevIdentity(v)) return null;
|
|
163950
|
+
const sha4 = String(v).split(DEV_IDENTITY_SEP)[1]?.trim();
|
|
163951
|
+
return sha4 ? sha4 : null;
|
|
163952
|
+
}
|
|
163953
|
+
var DEV_CHANNEL_WARNING = "\u26A0\uFE0F dev \u901A\u9053 = GitHub master HEAD \u7684\u5373\u65F6\u5FEB\u7167 (\u672A\u8D70\u53D1\u5E03\u95E8): \u53EF\u80FD\u4E2D\u65AD\u6B63\u5728\u8DD1\u7684 Goal/Run, \u4E14\u4E0D\u4FDD\u8BC1\u53EF\u56DE\u6EDA\u5230\u4E0A\u4E00\u4E2A dev \u7248\u3002";
|
|
163954
|
+
var DEV_BACK_TO_STABLE_HINT_MOBILE = "\u4E00\u952E\u56DE\u7A33\u5B9A\u7248: \u624B\u673A\u7AEF\u300C\u66F4\u65B0\u300D\u9875 \u2192 \u5207\u56DE stable";
|
|
163955
|
+
function parseVersion(v) {
|
|
163956
|
+
const clean8 = String(v || "").trim().replace(/^v/, "").split("-")[0];
|
|
163957
|
+
const parts = clean8.split(".").map((p) => parseInt(p.replace(/\D.*$/, ""), 10));
|
|
163958
|
+
return parts.map((n) => Number.isFinite(n) ? n : 0);
|
|
163959
|
+
}
|
|
163960
|
+
function compareVersions(a, b) {
|
|
163961
|
+
const pa = parseVersion(a);
|
|
163962
|
+
const pb = parseVersion(b);
|
|
163963
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
163964
|
+
const x = pa[i] ?? 0;
|
|
163965
|
+
const y2 = pb[i] ?? 0;
|
|
163966
|
+
if (x < y2) return -1;
|
|
163967
|
+
if (x > y2) return 1;
|
|
163129
163968
|
}
|
|
163130
|
-
|
|
163131
|
-
return { sent, failed, results };
|
|
163969
|
+
return 0;
|
|
163132
163970
|
}
|
|
163133
|
-
|
|
163134
|
-
|
|
163135
|
-
|
|
163136
|
-
|
|
163971
|
+
function isKnownVersion(v) {
|
|
163972
|
+
return !!v && v !== "unknown" && /^\d/.test(String(v).trim().replace(/^v/, ""));
|
|
163973
|
+
}
|
|
163974
|
+
var CHECK_STATUSES = [
|
|
163975
|
+
"up_to_date",
|
|
163976
|
+
// 确认最新
|
|
163977
|
+
"update_available",
|
|
163978
|
+
// 有新版本
|
|
163979
|
+
"check_skipped",
|
|
163980
|
+
// 节流/显式跳过, 结论来自缓存
|
|
163981
|
+
"offline",
|
|
163982
|
+
// 网络不可达 (≠ 最新)
|
|
163983
|
+
"registry_unavailable",
|
|
163984
|
+
// 可达但拿不到有效数据 (5xx / 包不存在 / 无 dist-tags)
|
|
163985
|
+
"local_version_unknown",
|
|
163986
|
+
// 读不到本地版本 (不猜 0.0.0)
|
|
163987
|
+
"unsupported_installation",
|
|
163988
|
+
// 认得出本地版本, 但这种安装方式不支持自动更新
|
|
163989
|
+
"github_unavailable",
|
|
163990
|
+
// GitHub 源不可用 (offline / rate_limited / not_found / http_error)
|
|
163991
|
+
"cross_check_mismatch"
|
|
163992
|
+
// npm 与 GitHub 两个源不一致 → 拒绝更新
|
|
163993
|
+
];
|
|
163994
|
+
var REFUSED_STATUSES = ["offline", "registry_unavailable", "local_version_unknown", "github_unavailable", "cross_check_mismatch"];
|
|
163995
|
+
function describeSourceIdentity(info) {
|
|
163996
|
+
const src4 = info.installedDevSha ? "dev (GitHub master \u5FEB\u7167)" : "stable (npm registry)";
|
|
163997
|
+
const ident = info.installedDevSha ? `commit ${info.installedDevSha}` : baseVersionOf(info.packageVersion);
|
|
163998
|
+
const back = info.switchableTo ? ` \xB7 \u53EF\u5207\u56DE ${info.switchableTo.channel} (${info.switchableTo.source})` : "";
|
|
163999
|
+
return `\u5F53\u524D\u5B89\u88C5\u6E90: ${src4} \xB7 \u7248\u672C/commit: ${ident} \xB7 \u6BD4\u8F83\u8BED\u4E49: ${info.channelKind}${back}`;
|
|
164000
|
+
}
|
|
164001
|
+
|
|
164002
|
+
// src/utils/dual-source-facts.ts
|
|
164003
|
+
function toGithubReport(r) {
|
|
164004
|
+
if (!r.ok) {
|
|
164005
|
+
return {
|
|
164006
|
+
reachable: false,
|
|
164007
|
+
reason: r.reason,
|
|
164008
|
+
detail: r.detail,
|
|
164009
|
+
retryAt: r.retryAt,
|
|
164010
|
+
headSha: r.facts?.headSha ?? null,
|
|
164011
|
+
ref: r.facts?.ref ?? `refs/heads/${DEV_BRANCH}`,
|
|
164012
|
+
releases: r.facts?.releases.length,
|
|
164013
|
+
tags: r.facts?.tags.length,
|
|
164014
|
+
newestVersion: r.facts ? newestGithubVersion(r.facts) : null,
|
|
164015
|
+
partial: r.facts?.partial,
|
|
164016
|
+
fetchedAt: r.facts?.fetchedAt
|
|
164017
|
+
};
|
|
163137
164018
|
}
|
|
163138
|
-
|
|
163139
|
-
|
|
163140
|
-
|
|
163141
|
-
|
|
163142
|
-
|
|
163143
|
-
|
|
163144
|
-
|
|
163145
|
-
|
|
163146
|
-
|
|
163147
|
-
grantedVia: "mobile",
|
|
163148
|
-
deviceIds: [dev.deviceId],
|
|
163149
|
-
status: "active",
|
|
163150
|
-
grantVersion: 1
|
|
164019
|
+
return {
|
|
164020
|
+
reachable: true,
|
|
164021
|
+
headSha: r.facts.headSha,
|
|
164022
|
+
ref: r.facts.ref,
|
|
164023
|
+
releases: r.facts.releases.length,
|
|
164024
|
+
tags: r.facts.tags.length,
|
|
164025
|
+
newestVersion: newestGithubVersion(r.facts),
|
|
164026
|
+
partial: r.facts.partial,
|
|
164027
|
+
fetchedAt: r.facts.fetchedAt
|
|
163151
164028
|
};
|
|
163152
|
-
|
|
163153
|
-
|
|
163154
|
-
|
|
163155
|
-
if (!
|
|
163156
|
-
const
|
|
163157
|
-
|
|
163158
|
-
|
|
164029
|
+
}
|
|
164030
|
+
function renderGithubReportLine(g) {
|
|
164031
|
+
if (!g) return "GitHub \u6E90: \u672A\u67E5\u8BE2";
|
|
164032
|
+
if (!g.reachable) {
|
|
164033
|
+
const retry = g.retryAt ? `, \u9650\u6D41\u91CD\u8BD5\u65F6\u95F4 ${g.retryAt}` : "";
|
|
164034
|
+
return `GitHub \u6E90: \u4E0D\u53EF\u8FBE \u2014 github_unavailable(${g.reason}) ${g.detail || ""}${retry}`;
|
|
164035
|
+
}
|
|
164036
|
+
return `GitHub \u6E90: \u53EF\u8FBE \xB7 master HEAD ${g.headSha ? g.headSha.slice(0, 7) : "\u672A\u77E5"} \xB7 Release ${g.releases ?? 0} \u4E2A \xB7 Tag ${g.tags ?? 0} \u4E2A \xB7 \u6700\u65B0\u7248\u672C\u6807\u7B7E ${g.newestVersion || "\u65E0"}${g.partial ? " (\u90E8\u5206\u8BF7\u6C42\u5931\u8D25)" : ""}`;
|
|
164037
|
+
}
|
|
164038
|
+
var OFFLINE_CODES = /* @__PURE__ */ new Set(["ENOTFOUND", "EAI_AGAIN", "ECONNREFUSED", "ECONNRESET", "ETIMEDOUT", "EHOSTUNREACH", "ENETUNREACH", "ENETDOWN", "EAI_FAIL", "UND_ERR_CONNECT_TIMEOUT", "CERT_HAS_EXPIRED"]);
|
|
164039
|
+
function collectNetEvidence(err2) {
|
|
164040
|
+
const codes = [];
|
|
164041
|
+
const msgs = [];
|
|
164042
|
+
let cur = err2;
|
|
164043
|
+
for (let depth = 0; cur && depth < 6; depth++) {
|
|
164044
|
+
const inner = Array.isArray(cur.errors) ? cur.errors : [];
|
|
164045
|
+
for (const e of inner) {
|
|
164046
|
+
if (e?.code) codes.push(String(e.code));
|
|
164047
|
+
if (e?.message) msgs.push(String(e.message));
|
|
164048
|
+
}
|
|
164049
|
+
if (cur.code) codes.push(String(cur.code));
|
|
164050
|
+
if (cur.errno) codes.push(String(cur.errno));
|
|
164051
|
+
if (cur.message) msgs.push(String(cur.message));
|
|
164052
|
+
cur = cur.cause;
|
|
164053
|
+
}
|
|
164054
|
+
const code10 = codes.find((c) => OFFLINE_CODES.has(c)) || codes[0] || "";
|
|
164055
|
+
const message16 = msgs.join(" \xB7 ");
|
|
164056
|
+
const offline = codes.some((c) => OFFLINE_CODES.has(c)) || /timeout|timed out|ENOTFOUND|getaddrinfo|network|socket hang up|超时|Failed to fetch|fetch failed|NetworkError|Load failed|ECONNREFUSED|ECONNRESET/i.test(message16);
|
|
164057
|
+
return { code: code10, message: message16, offline };
|
|
164058
|
+
}
|
|
164059
|
+
function classifyGithubError(err2, httpStatus, headers = {}) {
|
|
164060
|
+
const retryAt = headers["x-ratelimit-reset"] ? new Date(Number(headers["x-ratelimit-reset"]) * 1e3).toISOString() : null;
|
|
164061
|
+
const net = collectNetEvidence(err2);
|
|
164062
|
+
if (net.offline) {
|
|
164063
|
+
return { kind: "github_unavailable", reason: "offline", detail: `${net.code || net.message || "\u7F51\u7EDC\u4E0D\u53EF\u8FBE"}`, retryAt: null };
|
|
164064
|
+
}
|
|
164065
|
+
if (httpStatus === 403 || httpStatus === 429) {
|
|
164066
|
+
return { kind: "github_unavailable", reason: "rate_limited", detail: `GitHub \u8FD4\u56DE HTTP ${httpStatus} (\u9650\u6D41/\u6743\u9650)`, retryAt };
|
|
164067
|
+
}
|
|
164068
|
+
if (httpStatus === 404) {
|
|
164069
|
+
return { kind: "github_unavailable", reason: "not_found", detail: `GitHub \u4E0A\u6CA1\u6709 ${GITHUB_UPSTREAM_SLUG} \u7684\u8BE5\u9879\u8BB0\u5F55 (HTTP 404)`, retryAt: null };
|
|
164070
|
+
}
|
|
164071
|
+
if (httpStatus && httpStatus >= 400) {
|
|
164072
|
+
return { kind: "github_unavailable", reason: "http_error", detail: `GitHub \u8FD4\u56DE HTTP ${httpStatus}`, retryAt };
|
|
164073
|
+
}
|
|
164074
|
+
return { kind: "github_unavailable", reason: "http_error", detail: net.code || net.message || "\u672A\u77E5\u9519\u8BEF", retryAt: null };
|
|
164075
|
+
}
|
|
164076
|
+
function classifyRegistryError(err2, httpStatus) {
|
|
164077
|
+
const net = collectNetEvidence(err2);
|
|
164078
|
+
if (net.offline) {
|
|
164079
|
+
return { kind: "offline", detail: `${net.code || net.message || "\u7F51\u7EDC\u4E0D\u53EF\u8FBE"}` };
|
|
164080
|
+
}
|
|
164081
|
+
if (httpStatus && httpStatus >= 500) return { kind: "registry_unavailable", detail: `registry \u8FD4\u56DE HTTP ${httpStatus}` };
|
|
164082
|
+
if (httpStatus === 404) return { kind: "registry_unavailable", detail: `registry \u4E0A\u6CA1\u6709\u8BE5\u5305 (HTTP 404)` };
|
|
164083
|
+
if (httpStatus && httpStatus >= 400) return { kind: "registry_unavailable", detail: `registry \u8FD4\u56DE HTTP ${httpStatus}` };
|
|
164084
|
+
return { kind: "registry_unavailable", detail: net.code || net.message || "\u672A\u77E5\u9519\u8BEF" };
|
|
164085
|
+
}
|
|
164086
|
+
function newestGithubVersion(facts) {
|
|
164087
|
+
const all2 = [...facts.releases, ...facts.tags.map((t) => t.name)].map((n) => String(n).trim().replace(/^v/, "")).filter((n) => /^\d+\.\d+\.\d+/.test(n));
|
|
164088
|
+
if (all2.length === 0) return null;
|
|
164089
|
+
return all2.sort((a, b) => numericCompare(a, b) < 0 ? 1 : -1)[0];
|
|
164090
|
+
}
|
|
164091
|
+
function numericCompare(a, b) {
|
|
164092
|
+
const p = (v) => v.split("-")[0].split(".").map((x) => parseInt(x.replace(/\D.*$/, ""), 10) || 0);
|
|
164093
|
+
const pa = p(a);
|
|
164094
|
+
const pb = p(b);
|
|
164095
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
164096
|
+
const x = pa[i] ?? 0;
|
|
164097
|
+
const y2 = pb[i] ?? 0;
|
|
164098
|
+
if (x < y2) return -1;
|
|
164099
|
+
if (x > y2) return 1;
|
|
164100
|
+
}
|
|
164101
|
+
return 0;
|
|
164102
|
+
}
|
|
164103
|
+
function hasName(names, v) {
|
|
164104
|
+
const set = new Set(names.map((n) => String(n).trim().replace(/^v/, "")));
|
|
164105
|
+
return set.has(v.replace(/^v/, ""));
|
|
164106
|
+
}
|
|
164107
|
+
function crossCheckStable(registryLatest, facts) {
|
|
164108
|
+
const common = {
|
|
164109
|
+
registryLatest,
|
|
164110
|
+
githubVersion: newestGithubVersion(facts),
|
|
164111
|
+
releases: facts.releases.length,
|
|
164112
|
+
tags: facts.tags.length
|
|
164113
|
+
};
|
|
164114
|
+
if (!registryLatest) {
|
|
164115
|
+
return { ...common, kind: "no_record_at_all", hasTag: false, hasRelease: false, blocking: false, detail: "npm \u6CA1\u6709\u7ED9\u51FA latest, \u65E0\u4ECE\u4EA4\u53C9\u6821\u9A8C" };
|
|
164116
|
+
}
|
|
164117
|
+
const allNames = [...facts.releases, ...facts.tags.map((t) => t.name)];
|
|
164118
|
+
const hasTag = hasName(facts.tags.map((t) => t.name), registryLatest);
|
|
164119
|
+
const hasRelease = hasName(facts.releases, registryLatest);
|
|
164120
|
+
const ghNewest = common.githubVersion;
|
|
164121
|
+
if (ghNewest && numericCompare(ghNewest, registryLatest) > 0) {
|
|
163159
164122
|
return {
|
|
163160
|
-
|
|
163161
|
-
|
|
163162
|
-
|
|
163163
|
-
|
|
163164
|
-
|
|
164123
|
+
...common,
|
|
164124
|
+
kind: "mismatch",
|
|
164125
|
+
hasTag,
|
|
164126
|
+
hasRelease,
|
|
164127
|
+
blocking: true,
|
|
164128
|
+
detail: `GitHub \u4E0A\u6709 ${ghNewest} \u7684\u53D1\u5E03\u8BB0\u5F55, \u4F46 npm registry \u7684 latest \u8FD8\u662F ${registryLatest} \u2014 \u62D2\u7EDD\u6309 GitHub \u7684\u8BB0\u5F55\u5B89\u88C5`
|
|
163165
164129
|
};
|
|
163166
164130
|
}
|
|
163167
|
-
|
|
163168
|
-
|
|
163169
|
-
|
|
164131
|
+
if (hasTag || hasRelease) {
|
|
164132
|
+
return {
|
|
164133
|
+
...common,
|
|
164134
|
+
kind: "agree",
|
|
164135
|
+
hasTag,
|
|
164136
|
+
hasRelease,
|
|
164137
|
+
blocking: false,
|
|
164138
|
+
detail: `npm latest=${registryLatest} \u5728 GitHub \u4E0A\u6709\u540C\u540D\u8BB0\u5F55 (${hasRelease ? `Release v${registryLatest}` : `Tag v${registryLatest}`}) \u2014 \u4E24\u4E2A\u6E90\u6307\u5411\u540C\u4E00\u7248`
|
|
164139
|
+
};
|
|
164140
|
+
}
|
|
164141
|
+
if (allNames.length === 0) {
|
|
164142
|
+
return {
|
|
164143
|
+
...common,
|
|
164144
|
+
kind: "no_record_at_all",
|
|
164145
|
+
hasTag: false,
|
|
164146
|
+
hasRelease: false,
|
|
164147
|
+
blocking: false,
|
|
164148
|
+
detail: `GitHub \u4E0A\u6682\u65E0\u4EFB\u4F55 tag / Release (0 \u4E2A) \u2014 \u6682\u65E0\u53EF\u4EA4\u53C9\u6821\u9A8C\u7684\u8BB0\u5F55, npm \u4ECD\u662F\u6743\u5A01 (latest=${registryLatest})`
|
|
164149
|
+
};
|
|
163170
164150
|
}
|
|
163171
|
-
const q = pendingQueue(input.storage);
|
|
163172
|
-
q.push({ grant, signature, queuedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
163173
|
-
setQueue(input.storage, q);
|
|
163174
164151
|
return {
|
|
163175
|
-
|
|
163176
|
-
|
|
163177
|
-
|
|
163178
|
-
|
|
163179
|
-
|
|
164152
|
+
...common,
|
|
164153
|
+
kind: "missing_record",
|
|
164154
|
+
hasTag,
|
|
164155
|
+
hasRelease,
|
|
164156
|
+
blocking: false,
|
|
164157
|
+
detail: `npm latest=${registryLatest} \u5728 GitHub \u4E0A\u6CA1\u6709\u5BF9\u5E94\u8BB0\u5F55 (GitHub \u6700\u65B0\u7248\u672C\u6807\u7B7E ${ghNewest || "\u65E0"}; Release ${facts.releases.length} \u4E2A / Tag ${facts.tags.length} \u4E2A) \u2014 \u53D1\u5E03\u8BB0\u5F55\u7F3A Tag, \u4E0D\u963B\u585E stable \u66F4\u65B0`
|
|
163180
164158
|
};
|
|
163181
164159
|
}
|
|
163182
|
-
|
|
163183
|
-
const
|
|
163184
|
-
if (!
|
|
163185
|
-
|
|
163186
|
-
|
|
163187
|
-
|
|
163188
|
-
|
|
163189
|
-
|
|
163190
|
-
|
|
163191
|
-
return {
|
|
164160
|
+
function compareDevSnapshots(installedSha, headSha, ref = `refs/heads/${DEV_BRANCH}`) {
|
|
164161
|
+
const short = (s2) => s2 ? s2.slice(0, 7) : "\u672A\u77E5";
|
|
164162
|
+
if (!headSha) {
|
|
164163
|
+
return { ref, headSha, installedSha, same: false, behind: false, detail: `${ref} \u7684 HEAD \u8BFB\u4E0D\u5230 \u2014 \u65E0\u6CD5\u5224\u5B9A dev \u5FEB\u7167\u65B0\u65E7` };
|
|
164164
|
+
}
|
|
164165
|
+
if (!installedSha) {
|
|
164166
|
+
return { ref, headSha, installedSha, same: false, behind: false, detail: `\u5F53\u524D\u4E0D\u662F dev \u5FEB\u7167 (stable \u5B89\u88C5) \u2014 \u5207\u5230 dev \u5C06\u5F97\u5230 ${ref} @ ${short(headSha)}` };
|
|
164167
|
+
}
|
|
164168
|
+
const same = installedSha.slice(0, 7) === headSha.slice(0, 7);
|
|
164169
|
+
return {
|
|
164170
|
+
ref,
|
|
164171
|
+
headSha,
|
|
164172
|
+
installedSha,
|
|
164173
|
+
same,
|
|
164174
|
+
behind: !same,
|
|
164175
|
+
detail: same ? `\u5DF2\u662F\u6700\u65B0\u7684 dev \u5FEB\u7167 (${ref} @ ${short(headSha)}) \u2014 \u540C\u4E00\u4E2A commit` : `dev \u5FEB\u7167\u843D\u540E: \u5DF2\u88C5 ${short(installedSha)} \u2192 master HEAD ${short(headSha)} (\u6309 commit sha \u5224\u5B9A, \u4E0D\u770B\u7248\u672C\u53F7)`
|
|
164176
|
+
};
|
|
163192
164177
|
}
|
|
163193
|
-
|
|
163194
|
-
|
|
163195
|
-
|
|
163196
|
-
|
|
164178
|
+
|
|
164179
|
+
// src/web/mobile-update.ts
|
|
164180
|
+
var MOBILE_WEB_STATUSES = [
|
|
164181
|
+
...CHECK_STATUSES,
|
|
164182
|
+
"dev_bundle_unavailable",
|
|
164183
|
+
"dev_sha_mismatch",
|
|
164184
|
+
"target_unpublished",
|
|
164185
|
+
"digest_mismatch",
|
|
164186
|
+
"web_bundle_malformed",
|
|
164187
|
+
"decompress_unavailable",
|
|
164188
|
+
"payload_too_large",
|
|
164189
|
+
"native_shell_not_wired"
|
|
164190
|
+
];
|
|
164191
|
+
var MOBILE_REFUSED_STATUSES = [
|
|
164192
|
+
...REFUSED_STATUSES,
|
|
164193
|
+
"target_unpublished",
|
|
164194
|
+
"dev_bundle_unavailable",
|
|
164195
|
+
"dev_sha_mismatch",
|
|
164196
|
+
"digest_mismatch",
|
|
164197
|
+
"web_bundle_malformed",
|
|
164198
|
+
"decompress_unavailable",
|
|
164199
|
+
"payload_too_large",
|
|
164200
|
+
"native_shell_not_wired"
|
|
164201
|
+
];
|
|
164202
|
+
var MOBILE_WEB_REQUIRED_FILES = ["mobile.html", "mobile.js", "mobile-core.js", "mobile.css"];
|
|
164203
|
+
var MOBILE_WEB_JS_FILES = ["mobile.js", "mobile-core.js", "a2ui-client.js"];
|
|
164204
|
+
var MOBILE_MAX_PAYLOAD_BYTES = 80 * 1024 * 1024;
|
|
164205
|
+
var WEB_LAYOUT = {
|
|
164206
|
+
current: "current",
|
|
164207
|
+
staging: "staging",
|
|
164208
|
+
previous: "previous",
|
|
164209
|
+
state: "state.json"
|
|
164210
|
+
};
|
|
164211
|
+
function joinRel(...parts) {
|
|
164212
|
+
return parts.map((p) => String(p).replace(/^\/+|\/+$/g, "")).filter(Boolean).join("/");
|
|
164213
|
+
}
|
|
164214
|
+
function createMemoryWebStore(opts = {}) {
|
|
164215
|
+
const files = /* @__PURE__ */ new Map();
|
|
164216
|
+
const dirs = /* @__PURE__ */ new Set([""]);
|
|
164217
|
+
const norm = (rel) => joinRel(rel);
|
|
164218
|
+
const isDir = (rel) => dirs.has(norm(rel));
|
|
164219
|
+
return {
|
|
164220
|
+
kind: opts.kind || "memory",
|
|
164221
|
+
rootLabel: opts.rootLabel || "memory://bolloon-web",
|
|
164222
|
+
async list(rel) {
|
|
164223
|
+
const d2 = norm(rel);
|
|
164224
|
+
const out = [];
|
|
164225
|
+
for (const k of files.keys()) {
|
|
164226
|
+
if (d2 === "") {
|
|
164227
|
+
if (!k.includes("/")) out.push(k);
|
|
164228
|
+
continue;
|
|
164229
|
+
}
|
|
164230
|
+
if (k.startsWith(d2 + "/")) {
|
|
164231
|
+
const rest = k.slice(d2.length + 1);
|
|
164232
|
+
if (!rest.includes("/")) out.push(rest);
|
|
164233
|
+
}
|
|
164234
|
+
}
|
|
164235
|
+
return out.sort();
|
|
164236
|
+
},
|
|
164237
|
+
async exists(rel) {
|
|
164238
|
+
const k = norm(rel);
|
|
164239
|
+
return files.has(k) || isDir(k);
|
|
164240
|
+
},
|
|
164241
|
+
async readBytes(rel) {
|
|
164242
|
+
const v = files.get(norm(rel));
|
|
164243
|
+
return v ? v.slice() : null;
|
|
164244
|
+
},
|
|
164245
|
+
async readText(rel) {
|
|
164246
|
+
const v = files.get(norm(rel));
|
|
164247
|
+
return v ? new TextDecoder().decode(v) : null;
|
|
164248
|
+
},
|
|
164249
|
+
async writeBytes(rel, data) {
|
|
164250
|
+
const k = norm(rel);
|
|
164251
|
+
const parts = k.split("/");
|
|
164252
|
+
for (let i = 1; i < parts.length; i++) dirs.add(parts.slice(0, i).join("/"));
|
|
164253
|
+
files.set(k, data.slice ? data.slice() : data);
|
|
164254
|
+
},
|
|
164255
|
+
async remove(rel) {
|
|
164256
|
+
const k = norm(rel);
|
|
164257
|
+
for (const key of Array.from(files.keys())) if (key === k || key.startsWith(k + "/")) files.delete(key);
|
|
164258
|
+
for (const d2 of Array.from(dirs)) if (d2 === k || d2.startsWith(k + "/")) dirs.delete(d2);
|
|
164259
|
+
},
|
|
164260
|
+
async rename(from6, to) {
|
|
164261
|
+
const f = norm(from6);
|
|
164262
|
+
const t = norm(to);
|
|
164263
|
+
const moves = [];
|
|
164264
|
+
for (const key of Array.from(files.keys())) {
|
|
164265
|
+
if (key === f) moves.push({ from: key, to: t });
|
|
164266
|
+
else if (key.startsWith(f + "/")) moves.push({ from: key, to: t + key.slice(f.length) });
|
|
164267
|
+
}
|
|
164268
|
+
await this.remove(t);
|
|
164269
|
+
for (const m2 of moves) {
|
|
164270
|
+
const v = files.get(m2.from);
|
|
164271
|
+
files.delete(m2.from);
|
|
164272
|
+
const parts = m2.to.split("/");
|
|
164273
|
+
for (let i = 1; i < parts.length; i++) dirs.add(parts.slice(0, i).join("/"));
|
|
164274
|
+
files.set(m2.to, v);
|
|
164275
|
+
}
|
|
164276
|
+
dirs.delete(f);
|
|
164277
|
+
dirs.add(t);
|
|
164278
|
+
},
|
|
164279
|
+
baseUrl() {
|
|
164280
|
+
return opts.baseUrl ?? null;
|
|
164281
|
+
}
|
|
164282
|
+
};
|
|
164283
|
+
}
|
|
164284
|
+
function createCapacitorWebStore(plugin, opts = {}) {
|
|
164285
|
+
const directory = opts.directory ?? "DATA";
|
|
164286
|
+
const basePath = (opts.basePath || "bolloon-web").replace(/^\/+|\/+$/g, "");
|
|
164287
|
+
const full = (rel) => joinRel(basePath, rel);
|
|
164288
|
+
const b64ToBytes2 = (b642) => {
|
|
164289
|
+
if (typeof atob === "function") {
|
|
164290
|
+
const bin = atob(b642);
|
|
164291
|
+
const out = new Uint8Array(bin.length);
|
|
164292
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
164293
|
+
return out;
|
|
164294
|
+
}
|
|
164295
|
+
return new Uint8Array(Buffer.from(b642, "base64"));
|
|
164296
|
+
};
|
|
164297
|
+
const bytesToB642 = (data) => {
|
|
164298
|
+
let bin = "";
|
|
164299
|
+
for (let i = 0; i < data.length; i++) bin += String.fromCharCode(data[i]);
|
|
164300
|
+
if (typeof btoa === "function") return btoa(bin);
|
|
164301
|
+
return Buffer.from(data).toString("base64");
|
|
164302
|
+
};
|
|
164303
|
+
return {
|
|
164304
|
+
kind: "capacitor-fs",
|
|
164305
|
+
rootLabel: `${String(directory)}:${basePath}`,
|
|
164306
|
+
async list(rel) {
|
|
164307
|
+
try {
|
|
164308
|
+
const r = await plugin.readdir({ path: full(rel), directory });
|
|
164309
|
+
return (r?.files || []).filter((f) => f?.type !== "directory").map((f) => String(f.name)).sort();
|
|
164310
|
+
} catch {
|
|
164311
|
+
return [];
|
|
164312
|
+
}
|
|
164313
|
+
},
|
|
164314
|
+
async exists(rel) {
|
|
164315
|
+
try {
|
|
164316
|
+
await plugin.stat({ path: full(rel), directory });
|
|
164317
|
+
return true;
|
|
164318
|
+
} catch {
|
|
164319
|
+
return false;
|
|
164320
|
+
}
|
|
164321
|
+
},
|
|
164322
|
+
async readBytes(rel) {
|
|
164323
|
+
try {
|
|
164324
|
+
const r = await plugin.readFile({ path: full(rel), directory });
|
|
164325
|
+
const data = String(r?.data || "");
|
|
164326
|
+
return data ? b64ToBytes2(data) : null;
|
|
164327
|
+
} catch {
|
|
164328
|
+
return null;
|
|
164329
|
+
}
|
|
164330
|
+
},
|
|
164331
|
+
async readText(rel) {
|
|
164332
|
+
try {
|
|
164333
|
+
const r = await plugin.readFile({ path: full(rel), directory, encoding: "utf8" });
|
|
164334
|
+
return r?.data === void 0 ? null : String(r.data);
|
|
164335
|
+
} catch {
|
|
164336
|
+
return null;
|
|
164337
|
+
}
|
|
164338
|
+
},
|
|
164339
|
+
async writeBytes(rel, data) {
|
|
164340
|
+
const path = full(rel);
|
|
164341
|
+
const parts = full(rel).split("/");
|
|
164342
|
+
for (let i = 1; i < parts.length; i++) {
|
|
164343
|
+
try {
|
|
164344
|
+
await plugin.mkdir({ path: parts.slice(0, i).join("/"), directory, recursive: true });
|
|
164345
|
+
} catch {
|
|
164346
|
+
}
|
|
164347
|
+
}
|
|
164348
|
+
await plugin.writeFile({ path, data: bytesToB642(data), directory });
|
|
164349
|
+
},
|
|
164350
|
+
async remove(rel) {
|
|
164351
|
+
try {
|
|
164352
|
+
await plugin.rmdir({ path: full(rel), directory, recursive: true });
|
|
164353
|
+
return;
|
|
164354
|
+
} catch {
|
|
164355
|
+
}
|
|
164356
|
+
try {
|
|
164357
|
+
await plugin.rmdir({ path: full(rel), directory });
|
|
164358
|
+
} catch {
|
|
164359
|
+
}
|
|
164360
|
+
},
|
|
164361
|
+
async rename(from6, to) {
|
|
164362
|
+
try {
|
|
164363
|
+
await plugin.rmdir({ path: full(to), directory, recursive: true });
|
|
164364
|
+
} catch {
|
|
164365
|
+
}
|
|
164366
|
+
await plugin.rename({ from: full(from6), to: full(to), directory, toDirectory: directory });
|
|
164367
|
+
},
|
|
164368
|
+
baseUrl() {
|
|
164369
|
+
return opts.baseUrl ?? null;
|
|
164370
|
+
}
|
|
164371
|
+
};
|
|
164372
|
+
}
|
|
164373
|
+
async function gunzipBytes(data) {
|
|
164374
|
+
const DS = globalThis.DecompressionStream;
|
|
164375
|
+
if (typeof DS !== "function") return null;
|
|
164376
|
+
try {
|
|
164377
|
+
const stream = new globalThis.Blob([data]).stream().pipeThrough(new DS("gzip"));
|
|
164378
|
+
const buf = await new Response(stream).arrayBuffer();
|
|
164379
|
+
return new Uint8Array(buf);
|
|
164380
|
+
} catch {
|
|
164381
|
+
return null;
|
|
164382
|
+
}
|
|
164383
|
+
}
|
|
164384
|
+
function untarBytes(buf) {
|
|
164385
|
+
const out = [];
|
|
164386
|
+
const td = new TextDecoder();
|
|
164387
|
+
const readStr = (off, len) => {
|
|
164388
|
+
let end = off;
|
|
164389
|
+
while (end < off + len && buf[end] !== 0) end++;
|
|
164390
|
+
return td.decode(buf.subarray(off, end));
|
|
164391
|
+
};
|
|
164392
|
+
const readOctal = (off, len) => {
|
|
164393
|
+
const s2 = readStr(off, len).trim().replace(/\0/g, "");
|
|
164394
|
+
const v = parseInt(s2, 8);
|
|
164395
|
+
return Number.isFinite(v) ? v : 0;
|
|
164396
|
+
};
|
|
164397
|
+
let p = 0;
|
|
164398
|
+
let paxPath = null;
|
|
164399
|
+
while (p + 512 <= buf.length) {
|
|
164400
|
+
const name0 = readStr(p, 100);
|
|
164401
|
+
if (!name0) break;
|
|
164402
|
+
const size2 = readOctal(p + 124, 12);
|
|
164403
|
+
const typeflag = String.fromCharCode(buf[p + 156] || 48);
|
|
164404
|
+
const prefix = readStr(p + 345, 155);
|
|
164405
|
+
const dataStart = p + 512;
|
|
164406
|
+
const dataEnd = dataStart + size2;
|
|
164407
|
+
if (dataEnd > buf.length) break;
|
|
164408
|
+
let name10 = prefix ? `${prefix}/${name0}` : name0;
|
|
164409
|
+
if (typeflag === "x" || typeflag === "g") {
|
|
164410
|
+
const text = td.decode(buf.subarray(dataStart, dataEnd));
|
|
164411
|
+
const m2 = text.match(/\d+ path=([^\n]+)\n/);
|
|
164412
|
+
if (m2) paxPath = m2[1];
|
|
164413
|
+
} else if (typeflag === "L") {
|
|
164414
|
+
paxPath = td.decode(buf.subarray(dataStart, dataEnd)).replace(/\0+$/, "").trim();
|
|
164415
|
+
} else if (typeflag === "0" || typeflag === "\0" || typeflag === "" || typeflag === "0") {
|
|
164416
|
+
if (paxPath) {
|
|
164417
|
+
name10 = paxPath;
|
|
164418
|
+
paxPath = null;
|
|
164419
|
+
}
|
|
164420
|
+
out.push({ path: name10.replace(/^\.\//, ""), data: buf.slice(dataStart, dataEnd) });
|
|
164421
|
+
} else {
|
|
164422
|
+
paxPath = null;
|
|
164423
|
+
}
|
|
164424
|
+
p = dataStart + Math.ceil(size2 / 512) * 512;
|
|
164425
|
+
}
|
|
164426
|
+
return out;
|
|
164427
|
+
}
|
|
164428
|
+
var WEB_PATH_PREFIXES = ["package/dist/web/", "dist/web/", "./dist/web/"];
|
|
164429
|
+
function isWebResourcePath(path) {
|
|
164430
|
+
const p = String(path).replace(/^\.\//, "");
|
|
164431
|
+
for (const pre of WEB_PATH_PREFIXES) {
|
|
164432
|
+
if (p.startsWith(pre)) return { hit: true, rel: p.slice(pre.length) };
|
|
164433
|
+
}
|
|
164434
|
+
return { hit: false, rel: "" };
|
|
164435
|
+
}
|
|
164436
|
+
function pickWebLayer(entries) {
|
|
164437
|
+
const files = [];
|
|
164438
|
+
let snapshot2 = null;
|
|
164439
|
+
const td = new TextDecoder();
|
|
164440
|
+
for (const e of entries) {
|
|
164441
|
+
const p = String(e.path).replace(/^\.\//, "");
|
|
164442
|
+
if (/(^|\/)\.bolloon-dev-snapshot\.json$/.test(p)) {
|
|
164443
|
+
try {
|
|
164444
|
+
snapshot2 = JSON.parse(td.decode(e.data));
|
|
164445
|
+
} catch {
|
|
164446
|
+
snapshot2 = null;
|
|
164447
|
+
}
|
|
164448
|
+
continue;
|
|
164449
|
+
}
|
|
164450
|
+
const w2 = isWebResourcePath(p);
|
|
164451
|
+
if (w2.hit && w2.rel && !w2.rel.endsWith("/")) files.push({ rel: w2.rel, data: e.data });
|
|
164452
|
+
}
|
|
164453
|
+
return { files, snapshot: snapshot2 };
|
|
164454
|
+
}
|
|
164455
|
+
function toHex(buf) {
|
|
164456
|
+
const b = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
|
|
164457
|
+
let s2 = "";
|
|
164458
|
+
for (let i = 0; i < b.length; i++) s2 += b[i].toString(16).padStart(2, "0");
|
|
164459
|
+
return s2;
|
|
164460
|
+
}
|
|
164461
|
+
function normalizeAlgo(a) {
|
|
164462
|
+
const k = String(a || "").toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
164463
|
+
if (k === "sha1") return "SHA-1";
|
|
164464
|
+
if (k === "sha256") return "SHA-256";
|
|
164465
|
+
if (k === "sha512") return "SHA-512";
|
|
164466
|
+
return null;
|
|
164467
|
+
}
|
|
164468
|
+
async function digestHex(data, algo) {
|
|
164469
|
+
const c = globalThis.crypto?.subtle;
|
|
164470
|
+
if (!c) return null;
|
|
164471
|
+
const name10 = normalizeAlgo(algo);
|
|
164472
|
+
if (!name10) return null;
|
|
164473
|
+
try {
|
|
164474
|
+
return toHex(await c.digest(name10, data));
|
|
164475
|
+
} catch {
|
|
164476
|
+
return null;
|
|
164477
|
+
}
|
|
164478
|
+
}
|
|
164479
|
+
function parseSri(integrity) {
|
|
164480
|
+
const s2 = String(integrity || "").trim();
|
|
164481
|
+
const m2 = s2.match(/^(sha512|sha256|sha1)-([A-Za-z0-9+/=]+)/);
|
|
164482
|
+
if (!m2) return null;
|
|
164483
|
+
return { algo: m2[1], b64: m2[2] };
|
|
164484
|
+
}
|
|
164485
|
+
function b64Of(bytes) {
|
|
164486
|
+
let bin = "";
|
|
164487
|
+
for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
|
|
164488
|
+
if (typeof btoa === "function") return btoa(bin);
|
|
164489
|
+
return Buffer.from(bytes).toString("base64");
|
|
164490
|
+
}
|
|
164491
|
+
var MOBILE_UPDATE_STATE_SCHEMA = "bolloon-mobile-web/1";
|
|
164492
|
+
function emptyMobileUpdateState() {
|
|
164493
|
+
return {
|
|
164494
|
+
schema: MOBILE_UPDATE_STATE_SCHEMA,
|
|
164495
|
+
currentVersion: null,
|
|
164496
|
+
installedChannel: null,
|
|
164497
|
+
installedDevSha: null,
|
|
164498
|
+
channelPref: null,
|
|
164499
|
+
installedFrom: null,
|
|
164500
|
+
switchableTo: null,
|
|
164501
|
+
lastDevSha: null,
|
|
164502
|
+
devRef: null,
|
|
164503
|
+
devCheckedAt: null,
|
|
164504
|
+
lastCheck: null,
|
|
164505
|
+
lastUpdate: null,
|
|
164506
|
+
lastFailure: null,
|
|
164507
|
+
autoPrepared: null,
|
|
164508
|
+
history: [],
|
|
164509
|
+
needsReload: false
|
|
164510
|
+
};
|
|
164511
|
+
}
|
|
164512
|
+
async function readMobileUpdateState(store) {
|
|
164513
|
+
const base6 = emptyMobileUpdateState();
|
|
164514
|
+
const text = await store.readText(WEB_LAYOUT.state);
|
|
164515
|
+
if (!text) return base6;
|
|
164516
|
+
try {
|
|
164517
|
+
const raw = JSON.parse(text);
|
|
164518
|
+
if (!raw || raw.schema !== MOBILE_UPDATE_STATE_SCHEMA) return base6;
|
|
164519
|
+
return { ...base6, ...raw, history: Array.isArray(raw.history) ? raw.history.slice(0, 20) : [] };
|
|
164520
|
+
} catch {
|
|
164521
|
+
return base6;
|
|
164522
|
+
}
|
|
164523
|
+
}
|
|
164524
|
+
async function writeMobileUpdateState(patch, store) {
|
|
164525
|
+
const cur = await readMobileUpdateState(store);
|
|
164526
|
+
const next = { ...cur, ...patch, schema: MOBILE_UPDATE_STATE_SCHEMA };
|
|
164527
|
+
await store.writeBytes(WEB_LAYOUT.state, new TextEncoder().encode(JSON.stringify(next, null, 2)));
|
|
164528
|
+
return next;
|
|
164529
|
+
}
|
|
164530
|
+
async function fetchJson(url, fetchImpl, timeoutMs = 15e3) {
|
|
164531
|
+
try {
|
|
164532
|
+
const ac = globalThis.AbortController ? new AbortController() : null;
|
|
164533
|
+
const timer = ac ? setTimeout(() => {
|
|
164534
|
+
try {
|
|
164535
|
+
ac.abort();
|
|
164536
|
+
} catch {
|
|
164537
|
+
}
|
|
164538
|
+
}, timeoutMs) : null;
|
|
164539
|
+
const res = await fetchImpl(url, { headers: { Accept: "application/json" }, signal: ac?.signal });
|
|
164540
|
+
const status = Number(res?.status || 0);
|
|
164541
|
+
const text = await res.text();
|
|
164542
|
+
if (timer) clearTimeout(timer);
|
|
164543
|
+
let json = null;
|
|
164544
|
+
try {
|
|
164545
|
+
json = JSON.parse(text);
|
|
164546
|
+
} catch {
|
|
164547
|
+
json = null;
|
|
164548
|
+
}
|
|
164549
|
+
return { ok: status >= 200 && status < 300, status, json, text };
|
|
164550
|
+
} catch (e) {
|
|
164551
|
+
return { ok: false, status: 0, json: null, text: "", err: e };
|
|
164552
|
+
}
|
|
164553
|
+
}
|
|
164554
|
+
async function queryMobileNpmFacts(deps, pkg) {
|
|
164555
|
+
if (deps.npmDoc !== void 0 && deps.npmDoc !== null) return normalizeNpmDoc(deps.npmDoc, null);
|
|
164556
|
+
if (deps.npmDoc === null && deps.githubFacts !== void 0) {
|
|
164557
|
+
return { reachable: false, kind: "offline", detail: "\u6CE8\u5165\u7684 registry \u4E8B\u5B9E\u4E3A null (\u53D7\u63A7\u4E0D\u53EF\u8FBE: offline)", latest: null, distTags: {}, versions: [], dist: null };
|
|
164558
|
+
}
|
|
164559
|
+
const base6 = (deps.registryBase || NPM_REGISTRY_BASE).replace(/\/+$/, "");
|
|
164560
|
+
const url = `${base6}/${encodeURIComponent(pkg).replace("%40", "@")}`;
|
|
164561
|
+
const fetchImpl = deps.fetchImpl || globalThis.fetch?.bind(globalThis);
|
|
164562
|
+
if (!fetchImpl) return { reachable: false, kind: "offline", detail: "\u672C\u673A\u6CA1\u6709 fetch (offline)", latest: null, distTags: {}, versions: [], dist: null };
|
|
164563
|
+
const r = await fetchJson(url, fetchImpl);
|
|
164564
|
+
if (!r.ok) {
|
|
164565
|
+
const cls = classifyRegistryError(r.err || null, r.status || void 0);
|
|
164566
|
+
return { reachable: false, kind: cls.kind, detail: cls.kind === "offline" ? `offline: ${cls.detail}` : `registry_unavailable: ${cls.detail}`, latest: null, distTags: {}, versions: [], dist: null };
|
|
164567
|
+
}
|
|
164568
|
+
if (!r.json) return { reachable: false, kind: "registry_unavailable", detail: "registry_unavailable: registry \u8FD4\u56DE\u4E86\u65E0\u6CD5\u89E3\u6790\u7684\u5185\u5BB9", latest: null, distTags: {}, versions: [], dist: null };
|
|
164569
|
+
return normalizeNpmDoc(r.json, null);
|
|
164570
|
+
}
|
|
164571
|
+
function normalizeNpmDoc(doc, detail) {
|
|
164572
|
+
const distTags = doc?.["dist-tags"] || {};
|
|
164573
|
+
const versions = Object.keys(doc?.versions || {});
|
|
164574
|
+
if (!distTags.latest && versions.length === 0) {
|
|
164575
|
+
return { reachable: false, detail: detail || "registry \u4E0A\u6CA1\u6709\u53EF\u7528\u7248\u672C", latest: null, distTags: {}, versions: [], dist: null };
|
|
164576
|
+
}
|
|
164577
|
+
const latest = distTags.latest || versions[versions.length - 1] || null;
|
|
164578
|
+
const v = latest ? doc?.versions?.[latest] : null;
|
|
164579
|
+
return {
|
|
164580
|
+
reachable: true,
|
|
164581
|
+
latest,
|
|
164582
|
+
distTags,
|
|
164583
|
+
versions,
|
|
164584
|
+
dist: v?.dist ? { tarball: String(v.dist.tarball || ""), shasum: v.dist.shasum ? String(v.dist.shasum) : null, integrity: v.dist.integrity ? String(v.dist.integrity) : null } : null
|
|
164585
|
+
};
|
|
164586
|
+
}
|
|
164587
|
+
async function queryMobileGithubFacts(deps) {
|
|
164588
|
+
if (deps.githubFacts !== void 0 && deps.githubFacts !== null) return deps.githubFacts;
|
|
164589
|
+
if (deps.githubFacts === null) return null;
|
|
164590
|
+
const fetchImpl = deps.fetchImpl || globalThis.fetch?.bind(globalThis);
|
|
164591
|
+
if (!fetchImpl) return null;
|
|
164592
|
+
const base6 = (deps.apiBase || GITHUB_API_BASE).replace(/\/+$/, "");
|
|
164593
|
+
const missing = [];
|
|
164594
|
+
let releases = [];
|
|
164595
|
+
let tags = [];
|
|
164596
|
+
let headSha = null;
|
|
164597
|
+
const failures = [];
|
|
164598
|
+
const note = (e, what) => {
|
|
164599
|
+
missing.push(what);
|
|
164600
|
+
failures.push({ reason: e.reason, detail: `${what}: ${e.detail}`, retryAt: e.retryAt });
|
|
164601
|
+
};
|
|
164602
|
+
const rel = await fetchJson(`${base6}/repos/${GITHUB_UPSTREAM_SLUG}/releases?per_page=100`, fetchImpl);
|
|
164603
|
+
if (rel.ok && Array.isArray(rel.json)) releases = rel.json.map((x) => String(x?.tag_name || "")).filter(Boolean);
|
|
164604
|
+
else note(classifyGithubError(rel.err || null, rel.status || void 0), "releases");
|
|
164605
|
+
const tg = await fetchJson(`${base6}/repos/${GITHUB_UPSTREAM_SLUG}/tags?per_page=100`, fetchImpl);
|
|
164606
|
+
if (tg.ok && Array.isArray(tg.json)) tags = tg.json.map((x) => ({ name: String(x?.name || ""), sha: x?.commit?.sha ? String(x.commit.sha) : null })).filter((t) => t.name);
|
|
164607
|
+
else note(classifyGithubError(tg.err || null, tg.status || void 0), "tags");
|
|
164608
|
+
const hd = await fetchJson(`${base6}/repos/${GITHUB_UPSTREAM_SLUG}/commits/${DEV_BRANCH}`, fetchImpl);
|
|
164609
|
+
if (hd.ok && hd.json?.sha) headSha = String(hd.json.sha);
|
|
164610
|
+
else if (hd.ok) note({ reason: "parse_error", detail: "commits/master \u6CA1\u6709 sha \u5B57\u6BB5", retryAt: null }, "head");
|
|
164611
|
+
else note(classifyGithubError(hd.err || null, hd.status || void 0), "head");
|
|
164612
|
+
const facts = { slug: GITHUB_UPSTREAM_SLUG, ref: DEV_REF, headSha, releases, tags, fetchedAt: (/* @__PURE__ */ new Date()).toISOString(), partial: missing.length > 0, missing };
|
|
164613
|
+
if (failures.length) {
|
|
164614
|
+
const f = failures[0];
|
|
164615
|
+
return { ok: false, kind: "github_unavailable", reason: f.reason, detail: f.detail, retryAt: f.retryAt, facts };
|
|
164616
|
+
}
|
|
164617
|
+
return { ok: true, facts };
|
|
164618
|
+
}
|
|
164619
|
+
async function resolveLocalWebIdentity(deps) {
|
|
164620
|
+
if (deps.localIdentity && isKnownVersion(deps.localIdentity.version)) {
|
|
164621
|
+
const devSha = devShaFromIdentity(deps.localIdentity.version);
|
|
164622
|
+
return { version: String(deps.localIdentity.version), channel: devSha ? "dev" : deps.localIdentity.channel || "stable", source: "shell-injected" };
|
|
164623
|
+
}
|
|
164624
|
+
const st = await readMobileUpdateState(deps.store);
|
|
164625
|
+
if (st.currentVersion && isKnownVersion(st.currentVersion)) {
|
|
164626
|
+
const devSha = devShaFromIdentity(st.currentVersion);
|
|
164627
|
+
return { version: st.currentVersion, channel: devSha ? "dev" : st.installedChannel || "stable", source: "ota-state" };
|
|
164628
|
+
}
|
|
164629
|
+
const url = deps.localIdentityUrl === null ? null : deps.localIdentityUrl || "./bolloon-web.json";
|
|
164630
|
+
const fetchImpl = deps.fetchImpl || globalThis.fetch?.bind(globalThis);
|
|
164631
|
+
if (url && fetchImpl) {
|
|
164632
|
+
const r = await fetchJson(url, fetchImpl, 8e3).catch(() => null);
|
|
164633
|
+
const v = r?.json?.version;
|
|
164634
|
+
if (r?.ok && isKnownVersion(v)) {
|
|
164635
|
+
const devSha = devShaFromIdentity(v);
|
|
164636
|
+
return { version: String(v), channel: devSha ? "dev" : r.json.channel === "dev" ? "dev" : "stable", source: "build-stamp" };
|
|
164637
|
+
}
|
|
164638
|
+
}
|
|
164639
|
+
return null;
|
|
164640
|
+
}
|
|
164641
|
+
function refused(s2) {
|
|
164642
|
+
return MOBILE_REFUSED_STATUSES.includes(s2);
|
|
164643
|
+
}
|
|
164644
|
+
function nativeWired(deps) {
|
|
164645
|
+
if (deps.nativeWritable === true) return true;
|
|
164646
|
+
if (deps.nativeWritable === false) return false;
|
|
164647
|
+
return deps.store.kind === "memory";
|
|
164648
|
+
}
|
|
164649
|
+
function warnFor(channel, wired = true) {
|
|
164650
|
+
const w2 = channelKindOf(channel) === "git-ref" ? [DEV_CHANNEL_WARNING, DEV_BACK_TO_STABLE_HINT_MOBILE] : [];
|
|
164651
|
+
if (!wired) w2.push(NATIVE_CEILING_LINE);
|
|
164652
|
+
return w2;
|
|
164653
|
+
}
|
|
164654
|
+
async function checkMobileUpdate(deps) {
|
|
164655
|
+
const store = deps.store;
|
|
164656
|
+
const now = new Date(deps.now ? deps.now() : Date.now()).toISOString();
|
|
164657
|
+
const local = await resolveLocalWebIdentity(deps);
|
|
164658
|
+
const channel = resolveUpdateChannel(deps.channel);
|
|
164659
|
+
const channelKind = channelKindOf(channel);
|
|
164660
|
+
const base6 = {
|
|
164661
|
+
channel,
|
|
164662
|
+
channelKind,
|
|
164663
|
+
currentVersion: local?.version || "unknown",
|
|
164664
|
+
installedChannel: local ? devShaFromIdentity(local.version) ? "dev" : "stable" : null,
|
|
164665
|
+
installedDevSha: local ? devShaFromIdentity(local.version) : null,
|
|
164666
|
+
latestVersion: null,
|
|
164667
|
+
targetIdentity: null,
|
|
164668
|
+
switchableTo: null,
|
|
164669
|
+
crossCheck: null,
|
|
164670
|
+
github: null,
|
|
164671
|
+
dev: null,
|
|
164672
|
+
sourceFacts: null,
|
|
164673
|
+
targetPublished: null,
|
|
164674
|
+
artifact: null,
|
|
164675
|
+
warnings: warnFor(channel, nativeWired(deps)),
|
|
164676
|
+
checkedAt: now,
|
|
164677
|
+
identityLine: describeSourceIdentity({
|
|
164678
|
+
packageVersion: local?.version || "unknown",
|
|
164679
|
+
installedDevSha: local ? devShaFromIdentity(local.version) : null,
|
|
164680
|
+
switchableTo: null,
|
|
164681
|
+
channelKind
|
|
164682
|
+
}),
|
|
164683
|
+
localIdentitySource: local?.source || null,
|
|
164684
|
+
storeKind: store.kind,
|
|
164685
|
+
nativeWritable: nativeWired(deps),
|
|
164686
|
+
effectiveAfterReload: nativeWired(deps)
|
|
164687
|
+
};
|
|
164688
|
+
if (!local || !isKnownVersion(local.version)) {
|
|
164689
|
+
return { ...base6, status: "local_version_unknown", reason: `\u8BFB\u4E0D\u5230\u672C\u673A web \u5C42\u7684\u7248\u672C\u8EAB\u4EFD (\u58F3\u5C42\u6CE8\u5165 / OTA state / \u6784\u5EFA\u6233 bolloon-web.json \u90FD\u6CA1\u6709) \u2014 \u4E0D\u5224\u65AD\u6709\u6CA1\u6709\u66F4\u65B0` };
|
|
164690
|
+
}
|
|
164691
|
+
const npm = await queryMobileNpmFacts(deps, deps.pkgName || PKG_NAME);
|
|
164692
|
+
const githubRes = await queryMobileGithubFacts(deps);
|
|
164693
|
+
const github = githubRes ? toGithubReport(githubRes) : null;
|
|
164694
|
+
const npmLatest = npm.reachable ? npm.distTags[distTagForChannel(channel)] || npm.latest : null;
|
|
164695
|
+
const sourceFacts = {
|
|
164696
|
+
npm: npm.reachable ? { reachable: true, latest: npmLatest } : { reachable: false, latest: null, detail: npm.detail },
|
|
164697
|
+
github: github ? {
|
|
164698
|
+
reachable: github.reachable,
|
|
164699
|
+
reason: github.reason,
|
|
164700
|
+
detail: github.detail,
|
|
164701
|
+
retryAt: github.retryAt ?? null,
|
|
164702
|
+
ref: github.ref,
|
|
164703
|
+
headSha: github.headSha,
|
|
164704
|
+
newestVersion: github.newestVersion,
|
|
164705
|
+
releases: github.releases,
|
|
164706
|
+
tags: github.tags
|
|
164707
|
+
} : null,
|
|
164708
|
+
crossCheck: null
|
|
164709
|
+
};
|
|
164710
|
+
const switchableTo = base6.installedDevSha ? { channel: "stable", source: "npm", target: npmLatest } : { channel: "dev", source: "github", target: github?.headSha ? github.headSha.slice(0, 7) : null };
|
|
164711
|
+
const identityLine = describeSourceIdentity({
|
|
164712
|
+
packageVersion: local.version,
|
|
164713
|
+
installedDevSha: base6.installedDevSha,
|
|
164714
|
+
switchableTo,
|
|
164715
|
+
channelKind
|
|
164716
|
+
});
|
|
164717
|
+
const withSources = { ...base6, github, sourceFacts, switchableTo, identityLine };
|
|
164718
|
+
if (channelKind === "git-ref") {
|
|
164719
|
+
if (!github || !github.reachable) {
|
|
164720
|
+
const reason = github?.reason || "offline";
|
|
164721
|
+
const detail = github?.detail || (githubRes === null ? "\u672C\u6B21\u672A\u67E5\u8BE2 GitHub \u6E90" : "GitHub \u6E90\u4E0D\u53EF\u8FBE");
|
|
164722
|
+
return {
|
|
164723
|
+
...withSources,
|
|
164724
|
+
status: "github_unavailable",
|
|
164725
|
+
latestVersion: null,
|
|
164726
|
+
reason: `github_unavailable(${reason}): ${detail} \u2014 dev \u901A\u9053\u53EA\u6709 GitHub \u4E00\u4E2A\u6E90, \u62D2\u7EDD\u5B89\u88C5 (\u4E0D\u56DE\u843D\u5230 stable \u88C5\u4E00\u4E2A npm \u7248\u672C)`
|
|
164727
|
+
};
|
|
164728
|
+
}
|
|
164729
|
+
if (!github.headSha) {
|
|
164730
|
+
return { ...withSources, status: "github_unavailable", latestVersion: null, reason: `github_unavailable(not_found): GitHub \u4E0A\u6CA1\u6709 ${DEV_REF} \u6216\u8BFB\u4E0D\u5230 HEAD \u2014 \u62D2\u7EDD\u5B89\u88C5\u4E00\u4E2A\u8EAB\u4EFD\u4E0D\u660E\u7684\u5FEB\u7167` };
|
|
164731
|
+
}
|
|
164732
|
+
const dev = compareDevSnapshots(base6.installedDevSha, github.headSha, DEV_REF);
|
|
164733
|
+
const targetIdentity = devIdentity(baseVersionOf(local.version), github.headSha);
|
|
164734
|
+
const devBundleUrl = deps.devBundleUrl !== void 0 ? deps.devBundleUrl : envValue("BOLLOON_MOBILE_DEV_BUNDLE_URL");
|
|
164735
|
+
const devBundleSha256 = deps.devBundleSha256 !== void 0 ? deps.devBundleSha256 : envValue("BOLLOON_MOBILE_DEV_BUNDLE_SHA256");
|
|
164736
|
+
const common = { ...withSources, dev, targetIdentity, latestVersion: targetIdentity, sourceFacts: { ...sourceFacts, github: sourceFacts.github } };
|
|
164737
|
+
if (dev.same) {
|
|
164738
|
+
return { ...common, status: "up_to_date", reason: dev.detail };
|
|
164739
|
+
}
|
|
164740
|
+
if (!devBundleUrl || !/\{sha\}/.test(devBundleUrl)) {
|
|
164741
|
+
return {
|
|
164742
|
+
...common,
|
|
164743
|
+
status: "dev_bundle_unavailable",
|
|
164744
|
+
reason: `dev_bundle_unavailable: dev \u901A\u9053\u7684 web \u5305\u8981\u7531\u6709\u6784\u5EFA\u80FD\u529B\u7684\u4E00\u7AEF\u4EA7\u51FA \u2014\u2014 GitHub master \u7684\u6E90\u7801\u5FEB\u7167\u91CC\u6CA1\u6709 dist/web (dist \u662F\u6784\u5EFA\u4EA7\u7269, \u4E0D\u5728 git \u91CC), \u624B\u673A\u7AEF\u65E0\u6CD5\u73B0\u573A\u6784\u5EFA\u3002\u8BF7\u7528\u684C\u9762\u5BFC\u51FA: npx tsx scripts/build-mobile-web-bundle.ts --channel dev (\u4EA7\u51FA dist/web + .bolloon-dev-snapshot.json \u7684 tar.gz \u4E0E\u540C\u540D .sha256), \u5E76\u628A\u5730\u5740\u914D\u5230\u624B\u673A\u7AEF BOLLOON_MOBILE_DEV_BUNDLE_URL (\u6A21\u677F\u9700\u542B {sha}, {sha} \u4F1A\u88AB\u66FF\u6362\u6210 master HEAD \u7684\u5B8C\u6574 40 \u4F4D sha)\u3002${devBundleUrl ? ` \u5F53\u524D\u914D\u7F6E\u7684\u6A21\u677F\u4E0D\u542B {sha}: ${devBundleUrl}` : " \u5F53\u524D\u6CA1\u6709\u914D\u7F6E dev web \u5305\u5730\u5740\u3002"} stable \u901A\u9053\u4E0D\u53D7\u5F71\u54CD (npm tarball \u81EA\u5E26 dist/web)\u3002`
|
|
164745
|
+
};
|
|
164746
|
+
}
|
|
164747
|
+
const pinned = devBundleSha256 ? String(devBundleSha256).trim().toLowerCase() : null;
|
|
164748
|
+
const url = String(devBundleUrl).replace("{sha}", github.headSha);
|
|
163197
164749
|
return {
|
|
163198
|
-
|
|
163199
|
-
|
|
163200
|
-
|
|
163201
|
-
|
|
164750
|
+
...common,
|
|
164751
|
+
status: "update_available",
|
|
164752
|
+
targetPublished: true,
|
|
164753
|
+
artifact: {
|
|
164754
|
+
channel: "dev",
|
|
164755
|
+
identity: targetIdentity,
|
|
164756
|
+
source: `github master @ ${github.headSha.slice(0, 7)}`,
|
|
164757
|
+
url,
|
|
164758
|
+
// pin 了才校验载荷摘要; 没 pin 就如实标"没有载荷锚点"(不给虚假的安全感)
|
|
164759
|
+
digest: pinned ? { algo: "sha256", hex: pinned } : null,
|
|
164760
|
+
expectedDevSha: github.headSha,
|
|
164761
|
+
expectedBundleSha256: pinned
|
|
164762
|
+
},
|
|
164763
|
+
reason: `${dev.detail} \xB7 web \u5305\u6765\u81EA ${url} (\u5305\u5185 sha \u5FC5\u987B\u7B49\u4E8E master HEAD, \u5426\u5219\u62D2\u7EDD)` + (pinned ? ` \xB7 \u8F7D\u8377\u6458\u8981\u5DF2 pin (sha256:${pinned.slice(0, 12)}\u2026)` : " \xB7 \u8F7D\u8377\u6458\u8981\u672A pin (dev \u901A\u9053\u56FA\u6709: \u53EA\u6709\u8EAB\u4EFD\u88AB GitHub \u951A\u5B9A)"),
|
|
164764
|
+
warnings: common.warnings.concat(pinned ? [] : [
|
|
164765
|
+
'dev \u8F7D\u8377\u6458\u8981\u672A pin \u21D2 \u53EA\u4FDD\u8BC1"\u8EAB\u4EFD\u662F master HEAD \u7684\u90A3\u4E2A commit", \u4E0D\u4FDD\u8BC1"\u5B57\u8282\u5C31\u662F\u684C\u9762\u6253\u7684\u90A3\u4E00\u4EFD" (\u8981\u5F3A\u6821\u9A8C\u5C31\u628A .sha256 \u6E05\u5355\u7684\u503C\u914D\u5230 BOLLOON_MOBILE_DEV_BUNDLE_SHA256)'
|
|
164766
|
+
])
|
|
163202
164767
|
};
|
|
163203
164768
|
}
|
|
163204
|
-
|
|
163205
|
-
const
|
|
163206
|
-
const
|
|
163207
|
-
|
|
163208
|
-
|
|
163209
|
-
|
|
163210
|
-
|
|
163211
|
-
|
|
163212
|
-
|
|
163213
|
-
|
|
164769
|
+
if (!npm.reachable) {
|
|
164770
|
+
const detail = npm.detail || "registry \u4E0D\u53EF\u8FBE";
|
|
164771
|
+
const offline = npm.kind === "offline";
|
|
164772
|
+
return {
|
|
164773
|
+
...withSources,
|
|
164774
|
+
status: offline ? "offline" : "registry_unavailable",
|
|
164775
|
+
latestVersion: null,
|
|
164776
|
+
reason: `${detail}${github ? ` \xB7 ${renderGithubReportLine(github)}` : ""} \u2014 \u4E0D\u80FD\u5224\u5B9A\u4E3A\u6700\u65B0`
|
|
164777
|
+
};
|
|
164778
|
+
}
|
|
164779
|
+
const latest = npmLatest;
|
|
164780
|
+
const facts = githubRes && githubRes.ok ? githubRes.facts : null;
|
|
164781
|
+
const crossCheck = facts ? crossCheckStable(latest, facts) : null;
|
|
164782
|
+
const withCross = {
|
|
164783
|
+
...withSources,
|
|
164784
|
+
crossCheck,
|
|
164785
|
+
latestVersion: latest,
|
|
164786
|
+
sourceFacts: { ...sourceFacts, crossCheck: crossCheck ? { kind: crossCheck.kind, blocking: crossCheck.blocking, detail: crossCheck.detail } : null }
|
|
164787
|
+
};
|
|
164788
|
+
if (crossCheck?.kind === "mismatch") {
|
|
164789
|
+
return {
|
|
164790
|
+
...withCross,
|
|
164791
|
+
status: "cross_check_mismatch",
|
|
164792
|
+
reason: `cross_check_mismatch: ${crossCheck.detail} (npm latest=${latest} / GitHub ${crossCheck.githubVersion || "\u65E0\u8BB0\u5F55"})`
|
|
163214
164793
|
};
|
|
163215
|
-
|
|
163216
|
-
|
|
163217
|
-
|
|
163218
|
-
|
|
163219
|
-
|
|
163220
|
-
|
|
163221
|
-
|
|
163222
|
-
|
|
163223
|
-
}
|
|
163224
|
-
return {
|
|
163225
|
-
|
|
163226
|
-
|
|
164794
|
+
}
|
|
164795
|
+
if (isDevIdentity(local.version)) {
|
|
164796
|
+
const target = latest;
|
|
164797
|
+
if (!target || !npm.versions.includes(baseVersionOf(target))) {
|
|
164798
|
+
return { ...withCross, status: "target_unpublished", reason: `target_unpublished: registry \u4E0A\u6CA1\u6709 ${target || "\u76EE\u6807\u7248\u672C"} \u8FD9\u4E2A\u7248\u672C \u2014 \u62D2\u7EDD\u5207\u56DE (\u5F53\u524D dev \u5FEB\u7167 ${local.version} \u539F\u6837\u4FDD\u7559)` };
|
|
164799
|
+
}
|
|
164800
|
+
if (!npm.dist?.tarball) {
|
|
164801
|
+
return { ...withCross, status: "target_unpublished", reason: `target_unpublished: registry \u6CA1\u7ED9\u51FA ${target} \u7684\u4E0B\u8F7D\u5730\u5740 (dist.tarball \u7F3A\u5931) \u2014 \u62D2\u7EDD\u5207\u56DE` };
|
|
164802
|
+
}
|
|
164803
|
+
return {
|
|
164804
|
+
...withCross,
|
|
164805
|
+
status: "update_available",
|
|
164806
|
+
targetPublished: true,
|
|
164807
|
+
artifact: {
|
|
164808
|
+
channel: "stable",
|
|
164809
|
+
identity: String(target),
|
|
164810
|
+
source: "npm registry (dist-tags.latest)",
|
|
164811
|
+
url: npm.dist.tarball,
|
|
164812
|
+
digest: npm.dist.shasum ? { algo: "sha1", hex: npm.dist.shasum } : npm.dist.integrity ? { algo: "sha512", b64: parseSri(npm.dist.integrity)?.b64 ?? null } : null
|
|
164813
|
+
},
|
|
164814
|
+
reason: `\u5F53\u524D\u88C5\u7684\u662F dev \u5FEB\u7167 ${local.version} \u2192 \u5207\u56DE stable \u7684 ${target} (${DEV_BACK_TO_STABLE_HINT_MOBILE})`
|
|
164815
|
+
};
|
|
164816
|
+
}
|
|
164817
|
+
if (latest && !npm.versions.includes(latest)) {
|
|
164818
|
+
return { ...withCross, status: "target_unpublished", targetPublished: false, reason: `target_unpublished: registry \u7684 dist-tags \u6307\u5230 ${latest}, \u4F46 versions \u91CC\u6CA1\u6709\u8FD9\u4E2A\u7248\u672C \u2014 \u62D2\u7EDD\u66F4\u65B0 (0 \u5B57\u8282\u4E0B\u8F7D)` };
|
|
164819
|
+
}
|
|
164820
|
+
if (latest && compareVersions(baseVersionOf(local.version), latest) < 0) {
|
|
164821
|
+
if (!npm.dist?.tarball) {
|
|
164822
|
+
return { ...withCross, status: "target_unpublished", targetPublished: true, reason: `target_unpublished: registry \u6CA1\u7ED9\u51FA ${latest} \u7684\u4E0B\u8F7D\u5730\u5740 (dist.tarball \u7F3A\u5931) \u2014 \u62D2\u7EDD\u66F4\u65B0` };
|
|
164823
|
+
}
|
|
164824
|
+
return {
|
|
164825
|
+
...withCross,
|
|
164826
|
+
status: "update_available",
|
|
164827
|
+
targetPublished: true,
|
|
164828
|
+
artifact: {
|
|
164829
|
+
channel: "stable",
|
|
164830
|
+
identity: latest,
|
|
164831
|
+
source: "npm registry (dist-tags.latest)",
|
|
164832
|
+
url: npm.dist.tarball,
|
|
164833
|
+
digest: npm.dist.shasum ? { algo: "sha1", hex: npm.dist.shasum } : npm.dist.integrity ? { algo: "sha512", b64: parseSri(npm.dist.integrity)?.b64 ?? null } : null
|
|
164834
|
+
},
|
|
164835
|
+
reason: `\u5F53\u524D ${local.version} \u2192 \u76EE\u6807 ${latest}${crossCheck ? ` \xB7 \u4EA4\u53C9\u6821\u9A8C: ${crossCheck.kind}` : ""}`
|
|
164836
|
+
};
|
|
164837
|
+
}
|
|
164838
|
+
return { ...withCross, status: "up_to_date", targetPublished: latest ? npm.versions.includes(latest) : null };
|
|
164839
|
+
}
|
|
164840
|
+
async function downloadArtifact(artifact, deps) {
|
|
164841
|
+
const fetchImpl = deps.fetchImpl || globalThis.fetch?.bind(globalThis);
|
|
164842
|
+
const maxBytes = deps.maxPayloadBytes ?? MOBILE_MAX_PAYLOAD_BYTES;
|
|
164843
|
+
if (!fetchImpl) return { ok: false, status: "offline", detail: "\u672C\u673A\u6CA1\u6709 fetch, \u65E0\u6CD5\u4E0B\u8F7D", digest: { algo: "", matched: null } };
|
|
164844
|
+
let bytes;
|
|
164845
|
+
try {
|
|
164846
|
+
const res = await fetchImpl(artifact.url, { headers: { Accept: "application/octet-stream, application/gzip, */*" } });
|
|
164847
|
+
const status = Number(res?.status || 0);
|
|
164848
|
+
if (!(status >= 200 && status < 300)) {
|
|
164849
|
+
const cls = classifyGithubError(null, status || void 0);
|
|
164850
|
+
const bucket = cls.reason === "not_found" ? "target_unpublished" : cls.reason === "offline" ? "offline" : "registry_unavailable";
|
|
164851
|
+
return { ok: false, status: bucket, detail: `\u4E0B\u8F7D ${artifact.url} \u5931\u8D25: HTTP ${status || "\u65E0\u54CD\u5E94"} (${cls.reason})`, digest: { algo: "", matched: null } };
|
|
164852
|
+
}
|
|
164853
|
+
const lenHint = Number(res?.headers?.get?.("content-length") || 0);
|
|
164854
|
+
if (lenHint && lenHint > maxBytes) {
|
|
164855
|
+
return { ok: false, status: "payload_too_large", detail: `\u4E0B\u8F7D\u7269 ${(lenHint / 1048576).toFixed(1)} MiB \u8D85\u8FC7\u4E0A\u9650 ${(maxBytes / 1048576).toFixed(0)} MiB \u2014 \u62D2\u7EDD`, digest: { algo: "", matched: null } };
|
|
164856
|
+
}
|
|
164857
|
+
const buf = await res.arrayBuffer();
|
|
164858
|
+
bytes = new Uint8Array(buf);
|
|
164859
|
+
if (bytes.length > maxBytes) {
|
|
164860
|
+
return { ok: false, status: "payload_too_large", detail: `\u4E0B\u8F7D\u7269 ${(bytes.length / 1048576).toFixed(1)} MiB \u8D85\u8FC7\u4E0A\u9650 ${(maxBytes / 1048576).toFixed(0)} MiB \u2014 \u62D2\u7EDD`, digest: { algo: "", matched: null } };
|
|
164861
|
+
}
|
|
164862
|
+
} catch (e) {
|
|
164863
|
+
const cls = classifyGithubError(e);
|
|
164864
|
+
return { ok: false, status: cls.reason === "offline" ? "offline" : "registry_unavailable", detail: `\u4E0B\u8F7D ${artifact.url} \u5931\u8D25: ${cls.detail}`, digest: { algo: "", matched: null } };
|
|
164865
|
+
}
|
|
164866
|
+
if (!artifact.digest) {
|
|
164867
|
+
return { ok: true, detail: "\u8BE5\u6E90\u6CA1\u6709\u63D0\u4F9B\u6458\u8981 (dev web \u5305\u4EE5\u5305\u5185 sha \u4F5C\u4E3A\u8EAB\u4EFD\u6821\u9A8C, \u89C1 dev_sha_mismatch)", bytes, digest: { algo: "", matched: null } };
|
|
164868
|
+
}
|
|
164869
|
+
const algo = artifact.digest.algo;
|
|
164870
|
+
const want = artifact.digest.hex || artifact.digest.b64;
|
|
164871
|
+
if (!want) return { ok: true, detail: "\u58F0\u660E\u7684\u6458\u8981\u4E3A\u7A7A (\u8DF3\u8FC7)", bytes, digest: { algo, matched: null } };
|
|
164872
|
+
let got = null;
|
|
164873
|
+
if (artifact.digest.hex) got = await digestHex(bytes, algo);
|
|
164874
|
+
else {
|
|
164875
|
+
const bytesDigest = await digestHex(bytes, algo);
|
|
164876
|
+
if (bytesDigest) got = null;
|
|
164877
|
+
const h3 = bytesDigest;
|
|
164878
|
+
if (h3) {
|
|
164879
|
+
const pairs = h3.match(/.{2}/g) || [];
|
|
164880
|
+
const arr = new Uint8Array(pairs.map((x) => parseInt(x, 16)));
|
|
164881
|
+
got = b64Of(arr) === artifact.digest.b64 ? artifact.digest.b64 : b64Of(arr);
|
|
164882
|
+
}
|
|
164883
|
+
}
|
|
164884
|
+
const matched = got !== null && got.toLowerCase() === want.toLowerCase();
|
|
164885
|
+
if (!matched) {
|
|
163227
164886
|
return {
|
|
163228
164887
|
ok: false,
|
|
163229
|
-
|
|
163230
|
-
|
|
163231
|
-
|
|
164888
|
+
status: "digest_mismatch",
|
|
164889
|
+
detail: `digest_mismatch: \u6458\u8981\u5BF9\u4E0D\u4E0A (${algo}) \u2014 \u58F0\u660E ${String(want).slice(0, 24)}\u2026, \u5B9E\u9645 ${String(got).slice(0, 24)}\u2026, \u62D2\u7EDD\u5B89\u88C5`,
|
|
164890
|
+
bytes,
|
|
164891
|
+
digest: { algo, hex: artifact.digest.hex ? got : null, b64: artifact.digest.b64 ? got : null, matched: false }
|
|
163232
164892
|
};
|
|
163233
164893
|
}
|
|
164894
|
+
return { ok: true, detail: `\u6458\u8981\u5DF2\u6838\u5BF9 (${algo})`, bytes, digest: { algo, hex: artifact.digest.hex ? got : null, b64: artifact.digest.b64 ? got : null, matched: true } };
|
|
163234
164895
|
}
|
|
163235
|
-
|
|
163236
|
-
const
|
|
163237
|
-
|
|
163238
|
-
|
|
163239
|
-
|
|
163240
|
-
return
|
|
164896
|
+
function scriptRefsOf(html) {
|
|
164897
|
+
const out = [];
|
|
164898
|
+
const re = /<script[^>]*\ssrc=["']([^"']+)["']/gi;
|
|
164899
|
+
let m2;
|
|
164900
|
+
while (m2 = re.exec(html)) out.push(m2[1]);
|
|
164901
|
+
return out;
|
|
163241
164902
|
}
|
|
163242
|
-
async function
|
|
163243
|
-
const
|
|
163244
|
-
|
|
163245
|
-
const
|
|
163246
|
-
|
|
163247
|
-
|
|
164903
|
+
async function verifyWebLayer(store, prefix, opts = {}) {
|
|
164904
|
+
const checks = [];
|
|
164905
|
+
const present = {};
|
|
164906
|
+
for (const f of MOBILE_WEB_REQUIRED_FILES) {
|
|
164907
|
+
const text = await store.readText(joinRel(prefix, f));
|
|
164908
|
+
const bytes = text === null ? await store.readBytes(joinRel(prefix, f)) : null;
|
|
164909
|
+
const size2 = text !== null ? text.length : bytes?.length ?? 0;
|
|
164910
|
+
present[f] = String(text ?? "");
|
|
164911
|
+
checks.push({ name: `\u5FC5\u9700\u6587\u4EF6 ${f}`, ok: size2 > 0, detail: size2 > 0 ? `${size2} \u5B57\u8282` : "\u7F3A\u5931\u6216\u4E3A\u7A7A" });
|
|
164912
|
+
}
|
|
164913
|
+
const html = present["mobile.html"] || "";
|
|
164914
|
+
const refs = scriptRefsOf(html);
|
|
164915
|
+
const refMiss = [];
|
|
164916
|
+
for (const r of refs) {
|
|
164917
|
+
if (/^https?:|^\/\//i.test(r)) continue;
|
|
164918
|
+
const rel = r.replace(/^\.\//, "").split("?")[0];
|
|
164919
|
+
if (!await store.exists(joinRel(prefix, rel))) refMiss.push(r);
|
|
164920
|
+
}
|
|
164921
|
+
checks.push({ name: "mobile.html \u5F15\u7528\u7684\u811A\u672C\u90FD\u5728", ok: refMiss.length === 0, detail: refMiss.length ? `\u7F3A\u5931: ${refMiss.join(", ")}` : `${refs.length} \u4E2A\u5F15\u7528\u90FD\u547D\u4E2D` });
|
|
164922
|
+
const syntaxBad = [];
|
|
164923
|
+
for (const f of MOBILE_WEB_JS_FILES) {
|
|
164924
|
+
const src4 = await store.readText(joinRel(prefix, f));
|
|
164925
|
+
if (src4 === null || src4 === "") continue;
|
|
164926
|
+
try {
|
|
164927
|
+
new Function(src4);
|
|
164928
|
+
} catch (e) {
|
|
164929
|
+
syntaxBad.push(`${f}: ${String(e?.message || e).slice(0, 120)}`);
|
|
164930
|
+
}
|
|
164931
|
+
}
|
|
164932
|
+
checks.push({ name: "JS \u8BED\u6CD5\u81EA\u68C0 (\u771F\u7F16\u8BD1\u4E00\u6B21)", ok: syntaxBad.length === 0, detail: syntaxBad.length ? syntaxBad.join(" | ") : `${MOBILE_WEB_JS_FILES.length} \u4E2A\u6587\u4EF6\u53EF\u7F16\u8BD1` });
|
|
164933
|
+
const structural = checks.every((c) => c.ok);
|
|
164934
|
+
if (!structural) {
|
|
164935
|
+
return { ok: false, mode: "static-only", detail: `\u7ED3\u6784\u4E0E\u8BED\u6CD5\u68C0\u67E5\u672A\u901A\u8FC7: ${checks.filter((c) => !c.ok).map((c) => `${c.name}(${c.detail})`).join("; ")}`, checks };
|
|
164936
|
+
}
|
|
164937
|
+
const base6 = store.baseUrl();
|
|
164938
|
+
if (!base6) {
|
|
164939
|
+
return { ok: true, mode: "static-only", detail: '\u7ED3\u6784 + \u8BED\u6CD5\u901A\u8FC7; \u672C store \u6CA1\u6709\u53EF\u52A0\u8F7D URL \u21D2 \u672A\u505A\u771F\u542F\u52A8\u63A2\u6D4B (\u5982\u5B9E\u6807\u6CE8, \u4E0D\u5F53\u6210"\u5DF2\u9A8C\u8BC1\u80FD\u542F\u52A8")', checks };
|
|
164940
|
+
}
|
|
164941
|
+
if (!hasDom()) {
|
|
164942
|
+
return {
|
|
164943
|
+
ok: true,
|
|
164944
|
+
mode: "static-only",
|
|
164945
|
+
detail: "\u7ED3\u6784 + \u8BED\u6CD5\u901A\u8FC7; \u6709\u53EF\u52A0\u8F7D URL \u4F46\u672C\u73AF\u5883\u6CA1\u6709 DOM (\u975E\u6D4F\u89C8\u5668) \u21D2 \u672A\u505A\u771F\u542F\u52A8\u63A2\u6D4B (\u5982\u5B9E\u6807\u6CE8; \u771F\u63A2\u6D4B\u89C1 scripts/verify-mobile-update-ui.ts)",
|
|
164946
|
+
checks
|
|
164947
|
+
};
|
|
164948
|
+
}
|
|
164949
|
+
const url = `${String(base6).replace(/\/+$/, "")}/${joinRel(prefix, "mobile.html")}`;
|
|
164950
|
+
const probe = await iframeBootProbe(url, opts.bootTimeoutMs ?? 12e3);
|
|
164951
|
+
checks.push({ name: "\u771F\u542F\u52A8\u63A2\u6D4B (iframe \u52A0\u8F7D staged \u8D44\u6E90)", ok: probe.ok, detail: probe.detail });
|
|
164952
|
+
return { ok: probe.ok, mode: "iframe", detail: probe.ok ? `\u771F\u542F\u52A8\u63A2\u6D4B\u901A\u8FC7: ${probe.detail}` : `\u771F\u542F\u52A8\u63A2\u6D4B\u5931\u8D25: ${probe.detail}`, checks };
|
|
164953
|
+
}
|
|
164954
|
+
function hasDom() {
|
|
164955
|
+
const d2 = globalThis.document;
|
|
164956
|
+
return !!(d2 && typeof d2.createElement === "function");
|
|
164957
|
+
}
|
|
164958
|
+
async function iframeBootProbe(url, timeoutMs) {
|
|
164959
|
+
const doc = globalThis.document;
|
|
164960
|
+
if (!doc || typeof doc.createElement !== "function") return { ok: false, detail: "\u6CA1\u6709 DOM, \u65E0\u6CD5\u505A\u542F\u52A8\u63A2\u6D4B" };
|
|
164961
|
+
return await new Promise((resolve) => {
|
|
164962
|
+
let done = false;
|
|
164963
|
+
const frame = doc.createElement("iframe");
|
|
164964
|
+
frame.style.cssText = "position:absolute;left:-9999px;width:430px;height:932px;border:0;";
|
|
164965
|
+
frame.setAttribute("aria-hidden", "true");
|
|
164966
|
+
frame.src = url;
|
|
164967
|
+
const finish = (ok, detail) => {
|
|
164968
|
+
if (done) return;
|
|
164969
|
+
done = true;
|
|
164970
|
+
try {
|
|
164971
|
+
frame.remove();
|
|
164972
|
+
} catch {
|
|
164973
|
+
}
|
|
164974
|
+
resolve({ ok, detail });
|
|
164975
|
+
};
|
|
164976
|
+
const timer = setTimeout(() => {
|
|
164977
|
+
const w2 = (() => {
|
|
164978
|
+
try {
|
|
164979
|
+
return frame.contentWindow;
|
|
164980
|
+
} catch {
|
|
164981
|
+
return null;
|
|
164982
|
+
}
|
|
164983
|
+
})();
|
|
164984
|
+
finish(false, `\u7B49 ${timeoutMs}ms \u672A\u89C1 staged \u8D44\u6E90\u542F\u52A8 (readyState=${w2?.document?.readyState || "\u672A\u77E5"}, BolloonCore=${typeof w2?.BolloonCore})`);
|
|
164985
|
+
}, timeoutMs);
|
|
164986
|
+
frame.onload = () => {
|
|
164987
|
+
let tries = 0;
|
|
164988
|
+
const tick = () => {
|
|
164989
|
+
tries++;
|
|
164990
|
+
let w2 = null;
|
|
164991
|
+
try {
|
|
164992
|
+
w2 = frame.contentWindow;
|
|
164993
|
+
} catch {
|
|
164994
|
+
}
|
|
164995
|
+
const d2 = w2?.document;
|
|
164996
|
+
if (d2 && d2.readyState === "complete" && d2.querySelector && d2.querySelector(".tabbar") && w2.BolloonCore && typeof w2.BolloonCore === "object") {
|
|
164997
|
+
clearTimeout(timer);
|
|
164998
|
+
finish(true, `staged \u8D44\u6E90\u771F\u8D77\u6765\u4E86 (tabbar + BolloonCore, ${tries} \u6B21\u63A2\u6D4B)`);
|
|
164999
|
+
return;
|
|
165000
|
+
}
|
|
165001
|
+
if (tries > 60) {
|
|
165002
|
+
clearTimeout(timer);
|
|
165003
|
+
finish(false, `staged \u8D44\u6E90\u52A0\u8F7D\u5B8C\u4F46\u6CA1\u8D77\u6765 (readyState=${d2?.readyState || "\u672A\u77E5"}, tabbar=${!!d2?.querySelector?.(".tabbar")}, BolloonCore=${typeof w2?.BolloonCore})`);
|
|
165004
|
+
return;
|
|
165005
|
+
}
|
|
165006
|
+
setTimeout(tick, 150);
|
|
165007
|
+
};
|
|
165008
|
+
tick();
|
|
165009
|
+
};
|
|
165010
|
+
frame.onerror = () => {
|
|
165011
|
+
clearTimeout(timer);
|
|
165012
|
+
finish(false, "iframe \u52A0\u8F7D\u5931\u8D25");
|
|
165013
|
+
};
|
|
165014
|
+
try {
|
|
165015
|
+
doc.body.appendChild(frame);
|
|
165016
|
+
} catch (e) {
|
|
165017
|
+
clearTimeout(timer);
|
|
165018
|
+
finish(false, `\u6302\u8F7D iframe \u5931\u8D25: ${e?.message || e}`);
|
|
165019
|
+
}
|
|
165020
|
+
});
|
|
163248
165021
|
}
|
|
163249
|
-
async function
|
|
163250
|
-
const
|
|
163251
|
-
|
|
163252
|
-
const
|
|
163253
|
-
|
|
163254
|
-
|
|
165022
|
+
async function prepareMobileUpdate(deps, check) {
|
|
165023
|
+
const store = deps.store;
|
|
165024
|
+
const now = new Date(deps.now ? deps.now() : Date.now()).toISOString();
|
|
165025
|
+
const stage = (s2, detail) => {
|
|
165026
|
+
try {
|
|
165027
|
+
deps.onStage?.(s2, detail);
|
|
165028
|
+
} catch {
|
|
165029
|
+
}
|
|
165030
|
+
};
|
|
165031
|
+
const steps = [];
|
|
165032
|
+
const mark = (s2) => {
|
|
165033
|
+
steps.push(s2);
|
|
165034
|
+
};
|
|
165035
|
+
const r = check || await checkMobileUpdate(deps);
|
|
165036
|
+
const from6 = r.currentVersion;
|
|
165037
|
+
const to = r.artifact?.identity || r.targetIdentity || from6;
|
|
165038
|
+
const fail = async (stageName, status, reason, extra = {}) => {
|
|
165039
|
+
mark(`${stageName}: ${reason}`);
|
|
165040
|
+
await store.remove(WEB_LAYOUT.staging);
|
|
165041
|
+
await writeMobileUpdateState({
|
|
165042
|
+
lastCheck: { at: now, status: r.status, reason: r.reason, channel: r.channel, latestVersion: r.latestVersion },
|
|
165043
|
+
lastFailure: { at: now, stage: stageName, reason },
|
|
165044
|
+
autoPrepared: null
|
|
165045
|
+
}, store);
|
|
165046
|
+
return { ok: false, stage: "failed", failedAt: stageName, status, from: from6, to, reason, steps, fileCount: 0, digest: null, probe: null, skippedDownload: false, ...extra };
|
|
165047
|
+
};
|
|
165048
|
+
if (refused(r.status)) {
|
|
165049
|
+
return fail("blocked", r.status, `\u62D2\u7EDD\u66F4\u65B0 (${r.status}): ${r.reason || "\u6E90\u4E0D\u53EF\u8FBE / \u7248\u672C\u4E0D\u5B58\u5728"}`, { stage: "blocked" });
|
|
165050
|
+
}
|
|
165051
|
+
if (r.status === "up_to_date") {
|
|
165052
|
+
mark(`up_to_date: ${r.reason || "\u5DF2\u662F\u6700\u65B0"}`);
|
|
165053
|
+
return { ok: false, stage: "blocked", status: "up_to_date", from: from6, to, reason: `\u5DF2\u662F\u6700\u65B0 (${from6}), \u65E0\u9700\u66F4\u65B0`, steps, fileCount: 0, digest: null, probe: null, skippedDownload: true };
|
|
165054
|
+
}
|
|
165055
|
+
if (!r.artifact) return fail("planned", "target_unpublished", "\u6CA1\u6709\u53EF\u6267\u884C\u7684\u4E0B\u8F7D\u8BA1\u5212 (artifact \u7F3A\u5931)");
|
|
165056
|
+
const prevState = await readMobileUpdateState(store);
|
|
165057
|
+
if (prevState.autoPrepared?.identity === to && await store.exists(joinRel(WEB_LAYOUT.staging, "mobile.html"))) {
|
|
165058
|
+
mark(`reuse-staging: \u590D\u7528\u5DF2\u51C6\u5907\u5E76\u9A8C\u8BC1\u8FC7\u7684 ${to}`);
|
|
165059
|
+
const probe2 = await verifyWebLayer(store, WEB_LAYOUT.staging, { bootTimeoutMs: deps.bootTimeoutMs });
|
|
165060
|
+
if (probe2.ok) {
|
|
165061
|
+
return { ok: true, stage: "awaiting_human", status: "update_available", from: from6, to, reason: `staging \u91CC\u5DF2\u6709\u9A8C\u8BC1\u8FC7\u7684 ${to} (digest ${prevState.autoPrepared.digest || "\u65E0"}) \u2014 \u7B49\u4EBA\u5DE5\u786E\u8BA4\u5207\u6362`, steps, fileCount: 0, digest: prevState.autoPrepared.digest, probe: probe2, skippedDownload: true };
|
|
165062
|
+
}
|
|
165063
|
+
mark("reuse-staging: \u590D\u7528\u7684 staging \u6CA1\u901A\u8FC7\u9A8C\u8BC1 \u2192 \u91CD\u65B0\u4E0B\u8F7D");
|
|
165064
|
+
}
|
|
165065
|
+
stage("downloading", `${r.artifact.channel} \xB7 ${r.artifact.identity} \u2190 ${r.artifact.url}`);
|
|
165066
|
+
mark(`downloading: ${r.artifact.url}`);
|
|
165067
|
+
const dl = await downloadArtifact(r.artifact, deps);
|
|
165068
|
+
if (!dl.ok || !dl.bytes) {
|
|
165069
|
+
return fail("downloading", dl.status || "registry_unavailable", dl.detail);
|
|
165070
|
+
}
|
|
165071
|
+
stage("downloaded", `\u5DF2\u4E0B\u8F7D ${(dl.bytes.length / 1048576).toFixed(2)} MiB \xB7 ${dl.detail}`);
|
|
165072
|
+
mark(`downloaded: ${(dl.bytes.length / 1048576).toFixed(2)} MiB \xB7 ${dl.detail}`);
|
|
165073
|
+
stage("extracting", "\u89E3\u538B tar.gz \u5E76\u6311\u51FA web \u8D44\u6E90 (dist/web)");
|
|
165074
|
+
const tarBytes = await gunzipBytes(dl.bytes);
|
|
165075
|
+
if (!tarBytes) {
|
|
165076
|
+
return fail(
|
|
165077
|
+
"extracting",
|
|
165078
|
+
"decompress_unavailable",
|
|
165079
|
+
"decompress_unavailable: \u672C\u673A WebView \u6CA1\u6709 DecompressionStream('gzip') \u21D2 \u65E0\u6CD5\u89E3\u5F00 tar.gz \u2014 \u62D2\u7EDD (\u4E0D\u88C5\u534A\u4E2A)\u3002 iOS 16.4+ / Chrome 80+ \u624D\u6709; \u65E7 WebView \u8BF7\u5347\u7EA7\u7CFB\u7EDF\u6216\u8D70\u5546\u5E97\u66F4\u65B0\u6574\u4E2A App\u3002"
|
|
165080
|
+
);
|
|
165081
|
+
}
|
|
165082
|
+
const entries = untarBytes(tarBytes);
|
|
165083
|
+
const { files, snapshot: snapshot2 } = pickWebLayer(entries);
|
|
165084
|
+
if (files.length === 0) {
|
|
165085
|
+
return fail("extracting", "web_bundle_malformed", `web_bundle_malformed: \u5305\u91CC\u6CA1\u6709 dist/web/** \u8D44\u6E90 (tar \u6761\u76EE ${entries.length} \u4E2A) \u2014 \u62D2\u7EDD`);
|
|
165086
|
+
}
|
|
165087
|
+
mark(`extracting: ${files.length} \u4E2A web \u6587\u4EF6, \u5305\u5185 snapshot \u6807\u8BB0 = ${snapshot2 ? `\u6709 (sha ${String(snapshot2.sha || "").slice(0, 7)})` : "\u65E0"}`);
|
|
165088
|
+
if (r.artifact.channel === "dev") {
|
|
165089
|
+
const want = (r.artifact.expectedDevSha || "").slice(0, 7);
|
|
165090
|
+
const got = snapshot2?.sha ? String(snapshot2.sha).slice(0, 7) : null;
|
|
165091
|
+
if (!snapshot2) {
|
|
165092
|
+
return fail("extracting", "dev_sha_mismatch", `dev_sha_mismatch: dev web \u5305\u91CC\u6CA1\u6709 .bolloon-dev-snapshot.json \u21D2 \u65E0\u6CD5\u8BC1\u660E\u5B83\u662F ${want} \u7684\u5FEB\u7167 \u2014 \u62D2\u7EDD`);
|
|
165093
|
+
}
|
|
165094
|
+
if (snapshot2.channel !== "dev") {
|
|
165095
|
+
return fail("extracting", "dev_sha_mismatch", `dev_sha_mismatch: \u5305\u5185 snapshot \u6807\u7684\u662F channel=${snapshot2.channel} (\u4E0D\u662F dev) \u2014 \u62D2\u7EDD`);
|
|
165096
|
+
}
|
|
165097
|
+
if (!got || got !== want) {
|
|
165098
|
+
return fail("extracting", "dev_sha_mismatch", `dev_sha_mismatch: \u5305\u5185 sha=${got || "\u7A7A"} \u2260 GitHub master HEAD ${want} \u2014 \u62D2\u7EDD\u5B89\u88C5\u8EAB\u4EFD\u5BF9\u4E0D\u4E0A\u7684\u5FEB\u7167`);
|
|
165099
|
+
}
|
|
165100
|
+
if (snapshot2.identity && to && String(snapshot2.identity) !== to) {
|
|
165101
|
+
return fail("extracting", "dev_sha_mismatch", `dev_sha_mismatch: \u5305\u5185 identity=${snapshot2.identity} \u4E0E\u76EE\u6807\u8EAB\u4EFD ${to} \u4E0D\u4E00\u81F4 \u2014 \u62D2\u7EDD`);
|
|
165102
|
+
}
|
|
165103
|
+
}
|
|
165104
|
+
await store.remove(WEB_LAYOUT.staging);
|
|
165105
|
+
for (const f of files) await store.writeBytes(joinRel(WEB_LAYOUT.staging, f.rel), f.data);
|
|
165106
|
+
stage("staged", `${files.length} \u4E2A\u6587\u4EF6\u5DF2\u5199\u5165 ${store.rootLabel}/${WEB_LAYOUT.staging}`);
|
|
165107
|
+
mark(`staged: ${files.length} \u4E2A\u6587\u4EF6 \u2192 ${WEB_LAYOUT.staging}`);
|
|
165108
|
+
stage("verifying", "\u9A8C\u8BC1 staging \u80FD\u4E0D\u80FD\u542F\u52A8 (\u7ED3\u6784 + \u8BED\u6CD5 + iframe \u771F\u52A0\u8F7D)");
|
|
165109
|
+
const probe = await verifyWebLayer(store, WEB_LAYOUT.staging, { bootTimeoutMs: deps.bootTimeoutMs });
|
|
165110
|
+
mark(`verifying: ${probe.mode} \u2014 ${probe.detail}`);
|
|
165111
|
+
if (!probe.ok) {
|
|
165112
|
+
return fail("verifying", "web_bundle_malformed", `\u5207\u6362\u524D\u9A8C\u8BC1\u5931\u8D25 (staged \u8D44\u6E90\u8D77\u4E0D\u6765): ${probe.detail}`, { probe });
|
|
165113
|
+
}
|
|
165114
|
+
const digest3 = dl.digest.matched === true ? `${dl.digest.algo}:${dl.digest.hex || dl.digest.b64}` : null;
|
|
165115
|
+
await writeMobileUpdateState({
|
|
165116
|
+
lastCheck: { at: now, status: r.status, reason: r.reason, channel: r.channel, latestVersion: r.latestVersion },
|
|
165117
|
+
autoPrepared: { identity: to, digest: digest3, verifiedAt: now, steps: steps.slice() }
|
|
165118
|
+
}, store);
|
|
165119
|
+
return { ok: true, stage: "awaiting_human", status: "update_available", from: from6, to, reason: `\u5DF2\u51C6\u5907\u5E76\u9A8C\u8BC1 ${to} (\u7B49\u4EBA\u5DE5\u786E\u8BA4\u5207\u6362)`, steps, fileCount: files.length, digest: digest3, probe, skippedDownload: false };
|
|
165120
|
+
}
|
|
165121
|
+
async function applyMobileUpdate(opts) {
|
|
165122
|
+
const started = Date.now();
|
|
165123
|
+
const store = opts.store;
|
|
165124
|
+
const now = new Date(opts.now ? opts.now() : Date.now()).toISOString();
|
|
165125
|
+
const stage = (s2, detail) => {
|
|
165126
|
+
try {
|
|
165127
|
+
opts.onStage?.(s2, detail);
|
|
165128
|
+
} catch {
|
|
165129
|
+
}
|
|
165130
|
+
};
|
|
165131
|
+
const r = await checkMobileUpdate(opts);
|
|
165132
|
+
const from6 = r.currentVersion;
|
|
165133
|
+
const to = r.artifact?.identity || r.targetIdentity || from6;
|
|
165134
|
+
const steps = [];
|
|
165135
|
+
const finish = async (o) => {
|
|
165136
|
+
const out = { ...o, durationMs: Date.now() - started, steps };
|
|
165137
|
+
const hist = [{ at: now, from: out.from, to: out.to, stage: out.stage, reason: out.reason }];
|
|
165138
|
+
const st = await readMobileUpdateState(store);
|
|
165139
|
+
await writeMobileUpdateState({
|
|
165140
|
+
lastUpdate: hist[0],
|
|
165141
|
+
history: [...hist, ...st.history || []].slice(0, 20),
|
|
165142
|
+
lastFailure: out.ok ? null : { at: now, stage: out.failedAt || out.stage, reason: out.reason },
|
|
165143
|
+
needsReload: out.ok ? true : st.needsReload,
|
|
165144
|
+
...out.ok ? {
|
|
165145
|
+
currentVersion: out.to,
|
|
165146
|
+
installedChannel: r.artifact?.channel || "stable",
|
|
165147
|
+
installedDevSha: devShaFromIdentity(out.to),
|
|
165148
|
+
installedFrom: {
|
|
165149
|
+
channel: r.artifact?.channel || "stable",
|
|
165150
|
+
source: r.artifact?.source || "unknown",
|
|
165151
|
+
url: r.artifact?.url || null,
|
|
165152
|
+
digest: out.digest,
|
|
165153
|
+
digestAlgo: out.digest ? out.digest.split(":")[0] : null,
|
|
165154
|
+
at: now
|
|
165155
|
+
},
|
|
165156
|
+
switchableTo: r.artifact?.channel === "dev" ? { channel: "stable", source: "npm", target: r.sourceFacts?.npm?.latest ?? null } : { channel: "dev", source: "github", target: r.github?.headSha ? r.github.headSha.slice(0, 7) : null },
|
|
165157
|
+
// 从 dev 切回 stable 时, **保留**刚离开的那个 dev 快照 sha: 用户回头想回 dev 时知道上次是哪个
|
|
165158
|
+
...r.artifact?.channel === "dev" ? { lastDevSha: devShaFromIdentity(out.to), devRef: DEV_REF, devCheckedAt: now } : { lastDevSha: r.installedDevSha || null },
|
|
165159
|
+
autoPrepared: null
|
|
165160
|
+
} : {}
|
|
165161
|
+
}, store);
|
|
165162
|
+
return out;
|
|
165163
|
+
};
|
|
165164
|
+
if (refused(r.status)) {
|
|
165165
|
+
stage("blocked", `\u62D2\u7EDD\u66F4\u65B0 (${r.status})`);
|
|
165166
|
+
return finish({ ok: false, stage: "blocked", status: r.status, from: from6, to, reason: `\u62D2\u7EDD\u66F4\u65B0 (${r.status}): ${r.reason || "\u6E90\u4E0D\u53EF\u8FBE / \u7248\u672C\u4E0D\u5B58\u5728"} \u2014 \u4E00\u4E2A\u5B57\u8282\u90FD\u6CA1\u4E0B\u8F7D, \u4E5F\u6CA1\u52A8 current`, digest: null, probe: null, needsReload: false });
|
|
165167
|
+
}
|
|
165168
|
+
if (!r.artifact) {
|
|
165169
|
+
stage("blocked", "\u6CA1\u6709\u53EF\u6267\u884C\u7684\u66F4\u65B0");
|
|
165170
|
+
return finish({ ok: false, stage: "blocked", status: r.status, from: from6, to, reason: r.status === "up_to_date" ? `\u5DF2\u662F\u6700\u65B0 (${from6})` : `\u6CA1\u6709\u53EF\u6267\u884C\u7684\u66F4\u65B0 (${r.status})`, digest: null, probe: null, needsReload: false });
|
|
165171
|
+
}
|
|
165172
|
+
if (!opts.confirm) {
|
|
165173
|
+
stage("blocked", "\u9700\u8981\u4EBA\u5DE5\u786E\u8BA4");
|
|
165174
|
+
return finish({
|
|
165175
|
+
ok: false,
|
|
165176
|
+
stage: "blocked",
|
|
165177
|
+
status: "update_available",
|
|
165178
|
+
from: from6,
|
|
165179
|
+
to,
|
|
165180
|
+
reason: "human_confirm_required: \u5207\u6362 web \u8D44\u6E90\u5C42\u4F1A\u6362\u6389\u6B63\u5728\u8DD1\u7684\u754C\u9762\u4E0E\u903B\u8F91 \u2014 \u5FC5\u987B\u6709\u4EBA\u5728\u73AF (\u667A\u80FD\u4F53\u53EA\u80FD\u81EA\u52A8\u8DD1\u5230 prepare/verify)",
|
|
165181
|
+
digest: null,
|
|
165182
|
+
probe: null,
|
|
165183
|
+
needsReload: false
|
|
165184
|
+
});
|
|
165185
|
+
}
|
|
165186
|
+
let prep = null;
|
|
165187
|
+
if (opts.reuseStaging) {
|
|
165188
|
+
stage("verifying", "\u590D\u7528 staging \u91CC\u5DF2\u51C6\u5907\u5E76\u9A8C\u8BC1\u8FC7\u7684\u8D44\u6E90");
|
|
165189
|
+
const probe = await verifyWebLayer(store, WEB_LAYOUT.staging, { bootTimeoutMs: opts.bootTimeoutMs });
|
|
165190
|
+
if (probe.ok) {
|
|
165191
|
+
const st = await readMobileUpdateState(store);
|
|
165192
|
+
const identity5 = st.autoPrepared?.identity || to;
|
|
165193
|
+
if (identity5 !== to) {
|
|
165194
|
+
stage("blocked", `staging \u7684\u8EAB\u4EFD ${identity5} \u2260 \u76EE\u6807 ${to}`);
|
|
165195
|
+
return finish({ ok: false, stage: "blocked", status: "web_bundle_malformed", from: from6, to, reason: `staging \u91CC\u51C6\u5907\u7684\u662F ${identity5}, \u4E0E\u672C\u6B21\u76EE\u6807 ${to} \u4E0D\u4E00\u81F4 \u2014 \u62D2\u7EDD\u5207\u6362 (\u5B81\u53EF\u4E0D\u88C5, \u4E0D\u88C5\u9519\u7684)`, digest: null, probe, needsReload: false });
|
|
165196
|
+
}
|
|
165197
|
+
prep = { ok: true, stage: "awaiting_human", status: "update_available", from: from6, to, reason: "\u590D\u7528 staging", steps: st.autoPrepared?.steps || [], fileCount: 0, digest: st.autoPrepared?.digest ?? null, probe, skippedDownload: true };
|
|
165198
|
+
steps.push(...(prep.steps || []).map((s2) => `auto: ${s2}`));
|
|
165199
|
+
}
|
|
165200
|
+
}
|
|
165201
|
+
if (!prep) {
|
|
165202
|
+
const p = await prepareMobileUpdate(opts, r);
|
|
165203
|
+
if (!p.ok) {
|
|
165204
|
+
return finish({ ok: false, stage: p.stage, failedAt: p.failedAt, status: p.status, from: from6, to, reason: p.reason, digest: p.digest, probe: p.probe, needsReload: false });
|
|
165205
|
+
}
|
|
165206
|
+
prep = p;
|
|
165207
|
+
steps.push(...p.steps);
|
|
165208
|
+
}
|
|
165209
|
+
if (!nativeWired(opts)) {
|
|
165210
|
+
stage("blocked", "\u539F\u751F\u58F3\u8FD8\u6CA1\u6307\u5411\u53EF\u5199\u76EE\u5F55 \u2192 \u4E0D\u5207\u6362");
|
|
165211
|
+
steps.push(`native_shell_not_wired: \u8D44\u6E90\u5DF2\u51C6\u5907\u5E76\u9A8C\u8BC1\u8FC7 (${WEB_LAYOUT.staging}), \u4F46\u5F53\u524D\u539F\u751F\u58F3\u4E0D\u4F1A\u52A0\u8F7D\u53EF\u5199\u76EE\u5F55\u91CC\u7684\u8D44\u6E90 \u21D2 \u5207\u6362\u53EA\u4F1A\u628A"\u80FD\u7528\u7684\u65E7\u7248\u672C"\u6362\u6210"\u58F3\u5C42\u52A0\u8F7D\u4E0D\u5230\u7684\u65B0\u7248\u672C" \u2014 \u62D2\u7EDD\u5207\u6362`);
|
|
165212
|
+
return finish({
|
|
165213
|
+
ok: false,
|
|
165214
|
+
stage: "blocked",
|
|
165215
|
+
status: "native_shell_not_wired",
|
|
165216
|
+
from: from6,
|
|
165217
|
+
to,
|
|
165218
|
+
reason: `native_shell_not_wired: \u624B\u673A App \u7684\u539F\u751F\u58F3\u8FD8\u6307\u5411\u5305\u5185\u8D44\u6E90 (\u6CA1\u6709\u6307\u5411\u53EF\u5199\u76EE\u5F55), \u6240\u4EE5\u8FD9\u6B21\u88C5\u5230 ${to} \u4E0D\u4F1A\u751F\u6548 \u2014 \u5DF2\u5728 ${WEB_LAYOUT.staging} \u51C6\u5907\u597D\u5E76\u901A\u8FC7\u542F\u52A8\u9A8C\u8BC1, \u4F46\u6CA1\u6709\u5207\u6362 current\u3002\u4FEE\u6CD5 (\u4E8C\u9009\u4E00, \u89C1 update-protocol \xA713.4): \u2460 \u628A\u58F3\u5C42 server.url \u6307\u5411\u672C\u673A http \u670D\u52A1\u7684\u53EF\u5199\u76EE\u5F55; \u2461 \u7B49\u539F\u751F\u5C42\u6539\u9020\u968F\u5546\u5E97/\u4FA7\u8F7D\u53D1\u4E00\u6B21\u3002` + NATIVE_CEILING_LINE,
|
|
165219
|
+
digest: prep.digest,
|
|
165220
|
+
probe: prep.probe,
|
|
165221
|
+
needsReload: false
|
|
165222
|
+
});
|
|
165223
|
+
}
|
|
165224
|
+
stage("switching", `\u539F\u5B50\u66FF\u6362: ${WEB_LAYOUT.current} \u2192 ${WEB_LAYOUT.previous}, ${WEB_LAYOUT.staging} \u2192 ${WEB_LAYOUT.current}`);
|
|
165225
|
+
const hadCurrent = await store.exists(joinRel(WEB_LAYOUT.current, "mobile.html"));
|
|
165226
|
+
let backupMade = false;
|
|
165227
|
+
try {
|
|
165228
|
+
const injectAt = opts.failSwitch === true ? "before_backup" : opts.failSwitch;
|
|
165229
|
+
if (injectAt === "before_backup") throw Object.assign(new Error("\u6CE8\u5165\u7684\u5207\u6362\u5931\u8D25 (\u5728\u52A8 current \u4E4B\u524D)"), { injected: true });
|
|
165230
|
+
await store.remove(WEB_LAYOUT.previous);
|
|
165231
|
+
if (hadCurrent) {
|
|
165232
|
+
await store.rename(WEB_LAYOUT.current, WEB_LAYOUT.previous);
|
|
165233
|
+
backupMade = true;
|
|
165234
|
+
}
|
|
165235
|
+
if (injectAt === "after_backup") throw Object.assign(new Error("\u6CE8\u5165\u7684\u5207\u6362\u5931\u8D25 (\u5907\u4EFD\u5DF2\u505A, staging \u672A\u4E0A\u4F4D)"), { injected: true });
|
|
165236
|
+
await store.rename(WEB_LAYOUT.staging, WEB_LAYOUT.current);
|
|
165237
|
+
steps.push(`switching: ${WEB_LAYOUT.current} \u5DF2\u66FF\u6362 (\u65E7\u8D44\u6E90\u4FDD\u7559\u5728 ${WEB_LAYOUT.previous})`);
|
|
165238
|
+
} catch (e) {
|
|
165239
|
+
const reason = String(e?.message || e);
|
|
165240
|
+
let rolled = false;
|
|
165241
|
+
try {
|
|
165242
|
+
await store.remove(WEB_LAYOUT.staging);
|
|
165243
|
+
if (backupMade) {
|
|
165244
|
+
await store.remove(WEB_LAYOUT.current);
|
|
165245
|
+
await store.rename(WEB_LAYOUT.previous, WEB_LAYOUT.current);
|
|
165246
|
+
rolled = true;
|
|
165247
|
+
} else if (hadCurrent) {
|
|
165248
|
+
rolled = false;
|
|
165249
|
+
}
|
|
165250
|
+
const probeAfter = rolled || hadCurrent ? await verifyWebLayer(store, WEB_LAYOUT.current, { bootTimeoutMs: opts.bootTimeoutMs }) : null;
|
|
165251
|
+
steps.push(`rolled_back: ${rolled ? "\u5DF2\u628A previous \u642C\u56DE current" : "current \u672A\u88AB\u6539\u52A8"} \xB7 \u542F\u52A8\u9A8C\u8BC1 ${probeAfter ? probeAfter.ok ? "\u901A\u8FC7" : "\u672A\u901A\u8FC7" : "\u8DF3\u8FC7"}`);
|
|
165252
|
+
stage(rolled ? "rolled_back" : "failed", `${reason}; ${rolled ? "\u5DF2\u56DE\u6EDA\u5230\u65E7\u8D44\u6E90" : "\u65E7\u8D44\u6E90\u672A\u88AB\u6539\u52A8"}`);
|
|
165253
|
+
return finish({
|
|
165254
|
+
ok: false,
|
|
165255
|
+
stage: rolled ? "rolled_back" : "failed",
|
|
165256
|
+
failedAt: "switching",
|
|
165257
|
+
status: "update_available",
|
|
165258
|
+
from: from6,
|
|
165259
|
+
to,
|
|
165260
|
+
reason: `${reason}; ${rolled ? `\u5DF2\u56DE\u6EDA\u5230 ${from6} (\u65E7\u8D44\u6E90\u56DE\u5230 current \u4E14\u9A8C\u8BC1${probeAfter?.ok ? "\u901A\u8FC7" : "\u672A\u901A\u8FC7"})` : "current \u672A\u88AB\u6539\u52A8, \u65E7\u8D44\u6E90\u4ECD\u5728"}`,
|
|
165261
|
+
digest: prep.digest,
|
|
165262
|
+
probe: probeAfter,
|
|
165263
|
+
needsReload: false
|
|
165264
|
+
});
|
|
165265
|
+
} catch (e2) {
|
|
165266
|
+
stage("failed", `${reason}; \u56DE\u6EDA\u8FC7\u7A0B\u51FA\u9519: ${e2?.message || e2}`);
|
|
165267
|
+
return finish({
|
|
165268
|
+
ok: false,
|
|
165269
|
+
stage: "failed",
|
|
165270
|
+
failedAt: "switching",
|
|
165271
|
+
status: "update_available",
|
|
165272
|
+
from: from6,
|
|
165273
|
+
to,
|
|
165274
|
+
reason: `${reason}; \u56DE\u6EDA\u8FC7\u7A0B\u51FA\u9519: ${e2?.message || e2}`,
|
|
165275
|
+
digest: prep.digest,
|
|
165276
|
+
probe: null,
|
|
165277
|
+
needsReload: false
|
|
165278
|
+
});
|
|
165279
|
+
}
|
|
165280
|
+
}
|
|
165281
|
+
stage("verifying", "\u5207\u6362\u540E\u518D\u9A8C\u4E00\u6B21 (\u80FD\u4E0D\u80FD\u542F\u52A8)");
|
|
165282
|
+
const after = await verifyWebLayer(store, WEB_LAYOUT.current, { bootTimeoutMs: opts.bootTimeoutMs });
|
|
165283
|
+
steps.push(`post-switch verify: ${after.mode} \u2014 ${after.detail}`);
|
|
165284
|
+
if (!after.ok) {
|
|
165285
|
+
let rolled = false;
|
|
165286
|
+
try {
|
|
165287
|
+
await store.remove(WEB_LAYOUT.current);
|
|
165288
|
+
if (backupMade) {
|
|
165289
|
+
await store.rename(WEB_LAYOUT.previous, WEB_LAYOUT.current);
|
|
165290
|
+
rolled = true;
|
|
165291
|
+
}
|
|
165292
|
+
stage("rolled_back", `\u5207\u6362\u540E\u9A8C\u8BC1\u5931\u8D25, ${rolled ? "\u5DF2\u56DE\u6EDA" : "\u6CA1\u6709\u53EF\u56DE\u6EDA\u7684\u65E7\u8D44\u6E90"}`);
|
|
165293
|
+
} catch {
|
|
165294
|
+
}
|
|
165295
|
+
return finish({
|
|
165296
|
+
ok: false,
|
|
165297
|
+
stage: rolled ? "rolled_back" : "failed",
|
|
165298
|
+
failedAt: "verifying",
|
|
165299
|
+
status: "update_available",
|
|
165300
|
+
from: from6,
|
|
165301
|
+
to,
|
|
165302
|
+
reason: `\u5207\u6362\u540E\u9A8C\u8BC1\u5931\u8D25: ${after.detail}; ${rolled ? `\u5DF2\u56DE\u6EDA\u5230 ${from6}` : "\u56DE\u6EDA\u5931\u8D25 \u2014 \u9700\u8981\u91CD\u88C5 App"}`,
|
|
165303
|
+
digest: prep.digest,
|
|
165304
|
+
probe: after,
|
|
165305
|
+
needsReload: false
|
|
165306
|
+
});
|
|
165307
|
+
}
|
|
165308
|
+
stage("succeeded", `\u5DF2\u5207\u5230 ${to}`);
|
|
165309
|
+
return finish({ ok: true, stage: "succeeded", status: "update_available", from: from6, to, reason: `\u5DF2\u66F4\u65B0\u5230 ${to} (\u91CD\u542F/\u91CD\u8F7D webview \u540E\u751F\u6548)`, digest: prep.digest, probe: after, needsReload: true });
|
|
163255
165310
|
}
|
|
163256
|
-
function
|
|
163257
|
-
|
|
163258
|
-
|
|
163259
|
-
|
|
163260
|
-
|
|
163261
|
-
|
|
163262
|
-
|
|
163263
|
-
|
|
163264
|
-
|
|
163265
|
-
|
|
163266
|
-
|
|
163267
|
-
|
|
163268
|
-
|
|
163269
|
-
|
|
163270
|
-
subject: a.subject,
|
|
163271
|
-
bodyPreview: a.bodyPreview || "",
|
|
163272
|
-
reason: a.reason,
|
|
163273
|
-
reallySent: !!a.reallySent
|
|
163274
|
-
})),
|
|
163275
|
-
choices: [
|
|
163276
|
-
{ id: "task_once", label: "\u4EC5\u672C\u6B21\u4EFB\u52A1" },
|
|
163277
|
-
{ id: "persistent", label: "\u957F\u671F\u4F7F\u7528 (\u63A8\u8350)" },
|
|
163278
|
-
{ id: "full_contact_access", label: "\u5B8C\u5168\u6388\u6743\u8054\u7CFB\u65B9\u5F0F\u80FD\u529B" }
|
|
163279
|
-
],
|
|
163280
|
-
willNotGet: ["\u8BFB\u53D6\u5168\u90E8\u90AE\u7BB1", "\u8BFB\u53D6\u901A\u8BAF\u5F55", "\u7FA4\u53D1\u6D88\u606F", "\u81EA\u52A8\u652F\u4ED8/\u8F6C\u8D26", "\u4EE3\u8868\u4F60\u7B7E\u7F72\u5408\u540C", "\u62FF\u5230\u624B\u673A\u53F7/\u90AE\u7BB1\u660E\u6587"],
|
|
163281
|
-
deviceSigning: opts.deviceSigning
|
|
165311
|
+
async function rollbackMobileUpdate(opts) {
|
|
165312
|
+
const store = opts.store;
|
|
165313
|
+
const started = Date.now();
|
|
165314
|
+
const now = new Date(opts.now ? opts.now() : Date.now()).toISOString();
|
|
165315
|
+
const st = await readMobileUpdateState(store);
|
|
165316
|
+
const from6 = st.currentVersion || "unknown";
|
|
165317
|
+
const steps = [];
|
|
165318
|
+
const finish = async (o) => {
|
|
165319
|
+
const out = { ...o, durationMs: Date.now() - started, steps };
|
|
165320
|
+
await writeMobileUpdateState({
|
|
165321
|
+
lastUpdate: { at: now, from: out.from, to: out.to, stage: out.stage, reason: out.reason },
|
|
165322
|
+
history: [{ at: now, from: out.from, to: out.to, stage: out.stage, reason: out.reason }, ...st.history || []].slice(0, 20)
|
|
165323
|
+
}, store);
|
|
165324
|
+
return out;
|
|
163282
165325
|
};
|
|
165326
|
+
if (!opts.confirm) {
|
|
165327
|
+
return finish({ ok: false, stage: "blocked", status: "update_available", from: from6, to: from6, reason: "human_confirm_required: \u56DE\u6EDA\u4F1A\u6362\u6389\u6B63\u5728\u8DD1\u7684 web \u8D44\u6E90 \u2014 \u5FC5\u987B\u6709\u4EBA\u5728\u73AF", digest: null, probe: null, needsReload: false });
|
|
165328
|
+
}
|
|
165329
|
+
if (!await store.exists(joinRel(WEB_LAYOUT.previous, "mobile.html"))) {
|
|
165330
|
+
return finish({ ok: false, stage: "blocked", status: "web_bundle_malformed", from: from6, to: from6, reason: `\u6CA1\u6709\u53EF\u56DE\u6EDA\u7684\u65E7\u8D44\u6E90 (${WEB_LAYOUT.previous} \u7A7A) \u2014 \u4E0D\u5047\u88C5\u56DE\u6EDA\u8FC7`, digest: null, probe: null, needsReload: false });
|
|
165331
|
+
}
|
|
165332
|
+
const probeBefore = await verifyWebLayer(store, WEB_LAYOUT.previous, { bootTimeoutMs: opts.bootTimeoutMs });
|
|
165333
|
+
steps.push(`previous \u63A2\u6D4B: ${probeBefore.detail}`);
|
|
165334
|
+
if (!probeBefore.ok) {
|
|
165335
|
+
return finish({ ok: false, stage: "blocked", status: "web_bundle_malformed", from: from6, to: from6, reason: `previous \u91CC\u7684\u65E7\u8D44\u6E90\u8D77\u4E0D\u6765 (${probeBefore.detail}) \u2014 \u56DE\u6EDA\u5B83\u53EA\u4F1A\u66F4\u7CDF, \u62D2\u7EDD`, digest: null, probe: probeBefore, needsReload: false });
|
|
165336
|
+
}
|
|
165337
|
+
try {
|
|
165338
|
+
await store.remove(joinRel(WEB_LAYOUT.current, ""));
|
|
165339
|
+
await store.rename(WEB_LAYOUT.previous, WEB_LAYOUT.current);
|
|
165340
|
+
} catch (e) {
|
|
165341
|
+
return finish({ ok: false, stage: "failed", failedAt: "switching", status: "update_available", from: from6, to: from6, reason: `\u56DE\u6EDA\u5931\u8D25: ${e?.message || e}`, digest: null, probe: null, needsReload: false });
|
|
165342
|
+
}
|
|
165343
|
+
const after = await verifyWebLayer(store, WEB_LAYOUT.current, { bootTimeoutMs: opts.bootTimeoutMs });
|
|
165344
|
+
steps.push(`\u56DE\u6EDA\u540E\u63A2\u6D4B: ${after.detail}`);
|
|
165345
|
+
return finish({
|
|
165346
|
+
ok: after.ok,
|
|
165347
|
+
stage: after.ok ? "rolled_back" : "failed",
|
|
165348
|
+
status: "update_available",
|
|
165349
|
+
from: from6,
|
|
165350
|
+
to: from6,
|
|
165351
|
+
reason: after.ok ? `\u5DF2\u56DE\u6EDA\u5230\u4E0A\u4E00\u4E2A\u8D44\u6E90\u5C42 (\u9700\u8981\u91CD\u8F7D webview \u751F\u6548)` : `\u56DE\u6EDA\u540E\u8D44\u6E90\u8D77\u4E0D\u6765: ${after.detail}`,
|
|
165352
|
+
digest: null,
|
|
165353
|
+
probe: after,
|
|
165354
|
+
needsReload: after.ok
|
|
165355
|
+
});
|
|
165356
|
+
}
|
|
165357
|
+
var MOBILE_UPDATE_AGENT_CONTRACT = {
|
|
165358
|
+
schema: "bolloon-mobile-agent-update/1",
|
|
165359
|
+
/** 可以自动做 (只读 + 只在 staging 里写, 不影响正在跑的资源) */
|
|
165360
|
+
autoAllowedSteps: ["check", "prepare", "download", "digest-verify", "extract", "stage", "verify"],
|
|
165361
|
+
/** 必须人在环 (会换掉正在跑的界面与逻辑 ⇒ 代价不对称) */
|
|
165362
|
+
humanRequiredSteps: ["switch", "reload", "rollback", "channel-switch"],
|
|
165363
|
+
preconditions: [
|
|
165364
|
+
"\u672C\u673A web \u5C42\u7684\u8EAB\u4EFD\u53EF\u8BFB (\u58F3\u5C42\u6CE8\u5165 / OTA state / \u6784\u5EFA\u6233 bolloon-web.json \u4E09\u8005\u4E4B\u4E00) \u2014\u2014 \u8BFB\u4E0D\u5230\u5C31 local_version_unknown, \u4E0D\u731C",
|
|
165365
|
+
"\u539F\u751F\u58F3\u5DF2\u6307\u5411\u53EF\u5199\u76EE\u5F55 (native_writable) \u2014\u2014 \u5426\u5219\u8D44\u6E90\u51C6\u5907\u597D\u4E86\u4E5F\u4E0D\u4F1A\u751F\u6548, \u4E00\u5F8B native_shell_not_wired \u5E76\u8BF4\u6E05\u4FEE\u6CD5",
|
|
165366
|
+
"\u8BBE\u5907\u5B58\u50A8\u4F59\u91CF\u591F (\u4E0B\u8F7D\u7269 \u2264 \u4E0A\u9650, \u9ED8\u8BA4 80 MiB) \u2014\u2014 \u8D85\u4E86\u5224 payload_too_large, \u4E0D\u8D4C\u5185\u5B58",
|
|
165367
|
+
"\u672C\u673A WebView \u6709 DecompressionStream('gzip') (iOS 16.4+ / Chrome 80+) \u2014\u2014 \u6CA1\u6709\u5C31 decompress_unavailable",
|
|
165368
|
+
'\u7A33\u5B9A\u7F51\u7EDC: \u6E90\u4E0D\u53EF\u8FBE\u4E00\u5F8B offline / registry_unavailable / github_unavailable(reason) \u62D2\u7EDD, \u4E0D\u9759\u9ED8\u91CD\u8BD5\u5230"\u770B\u8D77\u6765\u6210\u529F"',
|
|
165369
|
+
"\u6458\u8981\u53EF\u6821\u9A8C: npm \u4FA7\u7528 dist.shasum/dist.integrity; dev \u4FA7\u7528\u5305\u5185 .bolloon-dev-snapshot.json \u7684 sha + bundleSha256"
|
|
165370
|
+
],
|
|
165371
|
+
riskBoundaries: [
|
|
165372
|
+
'iOS \u539F\u751F\u58F3\u5C42**\u4E0D\u80FD\u81EA\u66F4** (App Store \u89C4\u5219) \u21D2 \u4E0D\u627F\u8BFA"iOS \u6574\u4F53\u81EA\u52A8\u66F4\u65B0"; web \u5C42\u80FD\u66F4, \u4E8C\u8FDB\u5236\u8D70\u5546\u5E97/TestFlight',
|
|
165373
|
+
"Android \u4FA7\u8F7D APK \u81EA\u66F4**\u9700\u7528\u6237\u5141\u8BB8\u672A\u77E5\u6765\u6E90** \u21D2 \u5FC5\u987B\u663E\u5F0F\u544A\u77E5 + \u7528\u6237\u5728\u73AF, \u672C\u8F6E\u4E0D\u505A\u9759\u9ED8\u88C5\u5305",
|
|
165374
|
+
'\u5207\u6362\u524D\u5FC5\u987B\u771F\u8DD1\u4E00\u6B21"\u80FD\u4E0D\u80FD\u542F\u52A8"\u63A2\u6D4B (\u7ED3\u6784+\u8BED\u6CD5+iframe), \u63A2\u6D4B\u4E0D\u901A\u8FC7\u4E0D\u8BB8\u5207\u8FDB current',
|
|
165375
|
+
'\u5207\u6362\u5FC5\u987B\u539F\u5B50 (rename) \u4E14\u4FDD\u7559 previous; \u4EFB\u4F55\u4E00\u6B65\u5931\u8D25\u90FD\u8981\u56DE\u5230"\u80FD\u542F\u52A8\u7684\u65E7\u8D44\u6E90"',
|
|
165376
|
+
"dev \u901A\u9053\u4E0D\u4FDD\u8BC1\u53EF\u56DE\u6EDA\u5230\u4E0A\u4E00\u4E2A dev \u7248 (\u4E0E\u684C\u9762\u540C\u4E00\u53E5\u8B66\u544A); \u4E00\u952E\u56DE stable \u59CB\u7EC8\u53EF\u7528",
|
|
165377
|
+
"\u6E90\u4E0D\u53EF\u8FBE/\u7248\u672C\u4E0D\u5B58\u5728/\u4EA4\u53C9\u6821\u9A8C\u4E0D\u4E00\u81F4/\u6458\u8981\u4E0D\u7B26 \u21D2 \u62D2\u7EDD\u5E76\u5206\u7C7B\u8BF4\u6E05, \u7EDD\u4E0D\u9759\u9ED8\u88C5\u56DE\u65E7\u7248\u3001\u7EDD\u4E0D\u5047\u88C5\u6210\u529F"
|
|
165378
|
+
]
|
|
165379
|
+
};
|
|
165380
|
+
async function autoPrepareMobileUpdate(deps) {
|
|
165381
|
+
return prepareMobileUpdate(deps);
|
|
165382
|
+
}
|
|
165383
|
+
function renderMobileUpdateReport(r, st) {
|
|
165384
|
+
const L2 = [];
|
|
165385
|
+
L2.push(r.identityLine);
|
|
165386
|
+
L2.push(`\u66F4\u65B0\u5C42: web \u8D44\u6E90\u5C42 (\u754C\u9762\u4E0E\u903B\u8F91: \u5165\u7FA4 / \u53D1\u4EFB\u52A1\u516C\u544A / \u770B\u98DE\u8F6E\u8FDB\u5EA6 / \u6388\u6743\u7B7E\u540D) \xB7 store=${r.storeKind}`);
|
|
165387
|
+
L2.push(`\u80FD\u5207\u56DE: ${r.switchableTo ? `${r.switchableTo.channel} (${r.switchableTo.source}${r.switchableTo.target ? ` @ ${r.switchableTo.target}` : ""})` : "\u65E0 (\u672A\u77E5\u6765\u6E90)"}`);
|
|
165388
|
+
L2.push(`\u76EE\u6807\u7248\u672C: ${r.targetIdentity || r.latestVersion || "\u672A\u77E5"}`);
|
|
165389
|
+
L2.push(`\u66F4\u65B0\u901A\u9053: ${r.channel} (\u6BD4\u8F83\u8BED\u4E49: ${r.channelKind})`);
|
|
165390
|
+
L2.push(renderGithubReportLine(r.github));
|
|
165391
|
+
if (r.crossCheck) L2.push(`\u4EA4\u53C9\u6821\u9A8C: ${r.crossCheck.kind}${r.crossCheck.blocking ? " (\u963B\u585E)" : ""} \u2014 ${r.crossCheck.detail}`);
|
|
165392
|
+
if (r.dev) L2.push(`dev \u5224\u5B9A: ${r.dev.detail}`);
|
|
165393
|
+
if (r.sourceFacts?.npm) L2.push(`npm \u6E90: ${r.sourceFacts.npm.reachable ? `\u53EF\u8FBE (latest=${r.sourceFacts.npm.latest || "\u672A\u77E5"})` : `\u4E0D\u53EF\u8FBE (${r.sourceFacts.npm.detail || "\u672A\u77E5"})`}`);
|
|
165394
|
+
if (st?.installedFrom) L2.push(`\u5F53\u524D\u6765\u6E90: ${st.installedFrom.channel} \xB7 ${st.installedFrom.source}${st.installedFrom.digest ? ` \xB7 \u6458\u8981 ${st.installedFrom.digest}` : ""}${st.installedFrom.at ? ` \xB7 ${st.installedFrom.at}` : ""}`);
|
|
165395
|
+
if (st?.lastDevSha && r.installedChannel !== "dev") L2.push(`\u4E0A\u6B21 dev: commit ${st.lastDevSha} (\u5DF2\u5207\u56DE stable)`);
|
|
165396
|
+
L2.push(`\u7ED3\u8BBA: ${r.status}${refused(r.status) ? " \u2014 \u62D2\u7EDD (\u6CA1\u6709\u5B89\u88C5\u4EFB\u4F55\u4E1C\u897F)" : ""}`);
|
|
165397
|
+
if (r.reason) L2.push(`\u8BF4\u660E: ${r.reason}`);
|
|
165398
|
+
for (const w2 of r.warnings) L2.push(w2);
|
|
165399
|
+
return L2;
|
|
165400
|
+
}
|
|
165401
|
+
var NATIVE_CEILING_LINE = '\u539F\u751F\u58F3\u5C42\u4E0D\u80FD\u5728\u8FD9\u91CC\u81EA\u66F4: iOS \u53D7 App Store \u89C4\u5219\u9650\u5236 (\u4E8C\u8FDB\u5236\u8D70\u5546\u5E97/TestFlight), Android \u4FA7\u8F7D APK \u81EA\u66F4\u9700\u8981\u4F60\u5141\u8BB8"\u672A\u77E5\u6765\u6E90" \u2014\u2014 \u8FD9\u91CC\u80FD\u81EA\u52A8\u66F4\u65B0\u7684\u662F web \u8D44\u6E90\u5C42 (\u754C\u9762\u4E0E\u903B\u8F91)\u3002';
|
|
165402
|
+
var MOBILE_CHANNEL_KEY = "bolloon.update.channel";
|
|
165403
|
+
function createAutoWebStore() {
|
|
165404
|
+
const injected = globalThis.__bolloonWebStore;
|
|
165405
|
+
if (injected && typeof injected.writeBytes === "function" && typeof injected.rename === "function") return injected;
|
|
165406
|
+
const cap = globalThis.Capacitor;
|
|
165407
|
+
const fs = cap?.Plugins?.Filesystem;
|
|
165408
|
+
if (fs && typeof fs.writeFile === "function") {
|
|
165409
|
+
const base6 = globalThis.__bolloonWebBaseUrl || null;
|
|
165410
|
+
return createCapacitorWebStore(fs, { basePath: "bolloon-web", directory: "DATA", baseUrl: base6 });
|
|
165411
|
+
}
|
|
165412
|
+
return createMemoryWebStore({ kind: "memory", rootLabel: "memory://webview", baseUrl: globalThis.__bolloonWebBaseUrl || null });
|
|
165413
|
+
}
|
|
165414
|
+
function storedMobileChannel() {
|
|
165415
|
+
try {
|
|
165416
|
+
const v = globalThis.localStorage?.getItem?.(MOBILE_CHANNEL_KEY);
|
|
165417
|
+
return v ? String(v) : null;
|
|
165418
|
+
} catch {
|
|
165419
|
+
return null;
|
|
165420
|
+
}
|
|
165421
|
+
}
|
|
165422
|
+
async function setMobileUpdateChannel(channel, store) {
|
|
165423
|
+
const want = String(channel || "").toLowerCase();
|
|
165424
|
+
if (want !== "stable" && want !== "dev") {
|
|
165425
|
+
const cur = storedMobileChannel() || "stable";
|
|
165426
|
+
return { ok: false, channel: cur, detail: `\u672A\u77E5\u901A\u9053 "${channel}" (\u53EA\u6709 stable / dev) \u2014 \u4FDD\u6301 ${cur}` };
|
|
165427
|
+
}
|
|
165428
|
+
const prev = storedMobileChannel();
|
|
165429
|
+
try {
|
|
165430
|
+
globalThis.localStorage?.setItem?.(MOBILE_CHANNEL_KEY, want);
|
|
165431
|
+
} catch {
|
|
165432
|
+
}
|
|
165433
|
+
if (store) await writeMobileUpdateState({ channelPref: want }, store);
|
|
165434
|
+
return { ok: true, channel: want, detail: `\u901A\u9053 ${prev || "stable"} \u2192 ${want} (\u53EA\u6539\u504F\u597D, \u8FD8\u6CA1\u6709\u5B89\u88C5\u4EFB\u4F55\u4E1C\u897F; \u70B9\u300C\u68C0\u67E5\u66F4\u65B0\u300D\u518D\u51B3\u5B9A\u88C5\u4E0D\u88C5)` };
|
|
165435
|
+
}
|
|
165436
|
+
async function reloadMobileWeb() {
|
|
165437
|
+
const cap = globalThis.Capacitor;
|
|
165438
|
+
try {
|
|
165439
|
+
if (cap?.Plugins?.WebView?.reload) {
|
|
165440
|
+
await cap.Plugins.WebView.reload();
|
|
165441
|
+
return { ok: true, how: "capacitor-webview", detail: "\u5DF2\u8BF7\u6C42 WebView \u91CD\u8F7D (\u65B0 web \u8D44\u6E90\u751F\u6548)" };
|
|
165442
|
+
}
|
|
165443
|
+
} catch (e) {
|
|
165444
|
+
return { ok: false, how: "capacitor-webview", detail: `WebView \u91CD\u8F7D\u5931\u8D25: ${String(e?.message || e)} \u2014 \u8BF7\u624B\u52A8\u91CD\u542F App` };
|
|
165445
|
+
}
|
|
165446
|
+
const loc = globalThis.location;
|
|
165447
|
+
if (loc && typeof loc.reload === "function") {
|
|
165448
|
+
loc.reload();
|
|
165449
|
+
return { ok: true, how: "location.reload", detail: "\u5DF2\u91CD\u8F7D\u9875\u9762" };
|
|
165450
|
+
}
|
|
165451
|
+
return { ok: false, how: "none", detail: "\u672C\u73AF\u5883\u6CA1\u6709\u53EF\u91CD\u8F7D\u7684 WebView (\u9A8C\u6536/Node) \u2014 \u672A\u5047\u88C5\u91CD\u8F7D" };
|
|
163283
165452
|
}
|
|
163284
165453
|
|
|
163285
165454
|
// src/web/mobile-core.ts
|
|
165455
|
+
var __webStore = null;
|
|
165456
|
+
function currentWebStore() {
|
|
165457
|
+
if (!__webStore) __webStore = createAutoWebStore();
|
|
165458
|
+
return __webStore;
|
|
165459
|
+
}
|
|
165460
|
+
function injectedWebIdentity() {
|
|
165461
|
+
const v = globalThis.__bolloonWebIdentity;
|
|
165462
|
+
if (v && typeof v === "object" && typeof v.version === "string" && v.version) {
|
|
165463
|
+
return { version: v.version, channel: v.channel === "dev" ? "dev" : v.channel === "stable" ? "stable" : void 0 };
|
|
165464
|
+
}
|
|
165465
|
+
return null;
|
|
165466
|
+
}
|
|
165467
|
+
function mobileUpdateDeps(opts = {}) {
|
|
165468
|
+
return {
|
|
165469
|
+
// 透传: 壳层/验收可以覆盖 registryBase / apiBase / devBundleUrl / devBundleSha256 / fetchImpl …
|
|
165470
|
+
// (只有 store / 通道 / 身份 / 壳层判据由本层接管 —— 那几项是"设备说了算"的)
|
|
165471
|
+
...opts,
|
|
165472
|
+
store: currentWebStore(),
|
|
165473
|
+
channel: opts.channel || storedMobileChannel() || void 0,
|
|
165474
|
+
localIdentity: opts.localIdentity !== void 0 ? opts.localIdentity : injectedWebIdentity(),
|
|
165475
|
+
nativeWritable: opts.nativeWritable !== void 0 ? opts.nativeWritable : void 0,
|
|
165476
|
+
onStage: opts.onStage
|
|
165477
|
+
};
|
|
165478
|
+
}
|
|
163286
165479
|
var busHandlers = /* @__PURE__ */ new Set();
|
|
163287
165480
|
function busBroadcast(msg) {
|
|
163288
165481
|
for (const h3 of busHandlers) h3(msg);
|
|
@@ -164259,6 +166452,134 @@ ${b}
|
|
|
164259
166452
|
return snap && Array.isArray(snap.skills) ? snap.skills : [];
|
|
164260
166453
|
}
|
|
164261
166454
|
},
|
|
166455
|
+
/**
|
|
166456
|
+
* 任务协作 (2026-09-25) — 手机与桌面/CLI 共用同一套存储与协议:
|
|
166457
|
+
* 入群 (`task group …`) · 发公告 (`task publish/announce/post`) · 看飞轮进度 (goal-flywheel 冻结类型, 只读)
|
|
166458
|
+
* 四个高风险动作 (入群/退群/建群/发公告/留痕) 一律**先签设备名再由桌面验签执行** —— 手机不自己执行、不记账。
|
|
166459
|
+
* 桌面不可达 → 明确失败 (任务动作**不进离线队列**: 几小时后突然生效的批准比失败更危险)。
|
|
166460
|
+
*/
|
|
166461
|
+
tasks: {
|
|
166462
|
+
/** 本机能不能签 (老 WebView 没 Ed25519 → 高风险动作一律拒, 不降级) */
|
|
166463
|
+
deviceSigning() {
|
|
166464
|
+
return ed25519Available();
|
|
166465
|
+
},
|
|
166466
|
+
/** 桌面基址 (拿不到 → null, 不猜) */
|
|
166467
|
+
async desktopBase() {
|
|
166468
|
+
return core.contacts.desktopBase();
|
|
166469
|
+
},
|
|
166470
|
+
deps() {
|
|
166471
|
+
return { storage: core.contacts.storage(), ownerDid: void 0, grantedBy: "leo" };
|
|
166472
|
+
},
|
|
166473
|
+
/** ① 群: 列本机已加入的群 (脱敏, 只给缩短 id/群名/时间) */
|
|
166474
|
+
listGroups: () => listGroups(core.tasks.deps()),
|
|
166475
|
+
/** ① 入群 (高风险: 展示待发内容 → 设备签名 → 桌面验签执行) */
|
|
166476
|
+
joinGroup: (link) => joinGroup(link, core.tasks.deps()),
|
|
166477
|
+
/** ① 退群 (高风险) */
|
|
166478
|
+
leaveGroup: (ref) => leaveGroup(ref, core.tasks.deps()),
|
|
166479
|
+
/** ① 建群 (高风险; 建完自动入群) */
|
|
166480
|
+
createGroup: (name10) => createGroup(name10, core.tasks.deps()),
|
|
166481
|
+
/** ② 看板 (只读; 与 CLI `task board` 同一份事实) */
|
|
166482
|
+
loadBoard: () => loadBoard(core.tasks.deps()),
|
|
166483
|
+
/** ② 发布公告 (高风险) */
|
|
166484
|
+
publishAnnouncement: (input) => publishAnnouncement(input, core.tasks.deps()),
|
|
166485
|
+
/** ② 把公告发进群 (高风险; 预览 → 确认 → 签名) */
|
|
166486
|
+
announceIntoGroup: (input) => announceIntoGroup(input, core.tasks.deps()),
|
|
166487
|
+
/** ② 过程留痕 (高风险: claim/deliver/screen/final) */
|
|
166488
|
+
postTrail: (input) => postTrail(input, core.tasks.deps()),
|
|
166489
|
+
/** ② 读群里的一期痕迹 (只读) */
|
|
166490
|
+
loadTrail: (input) => loadTrail(input, core.tasks.deps()),
|
|
166491
|
+
/** 预览群消息那一行 (由桌面同一个构造器生成) */
|
|
166492
|
+
previewGroupMessage: (req) => previewGroupMessage(req, core.tasks.deps()),
|
|
166493
|
+
/** ③ 飞轮进度 (只读消费 goal-flywheel 冻结类型; 投影在桌面做) */
|
|
166494
|
+
loadFlywheel: () => loadFlywheel(core.tasks.deps()),
|
|
166495
|
+
/** 确认页文案 (展示待发内容) */
|
|
166496
|
+
describeConfirm: (kind, req) => describeTaskActionForConfirm(kind, req),
|
|
166497
|
+
/** 直接执行一个已构造好的请求 (UI 的统一入口: 签名 → 桌面验签执行) */
|
|
166498
|
+
execute: (req) => executeTaskAction(req, core.tasks.deps()),
|
|
166499
|
+
/** 相对时间人话 (毫秒差 → 双语; 只用于写文字节点) */
|
|
166500
|
+
relative: (ms2, lang) => formatRelative(ms2, lang === "en" ? "en" : "zh"),
|
|
166501
|
+
/** id 缩短 (页面上不出现原文) */
|
|
166502
|
+
shorten: (id, n) => shortId(id, n),
|
|
166503
|
+
/** 公开文本红线 (UI 最后一道自检: 渲染前扫一遍, 命中就不显示原文) */
|
|
166504
|
+
scanText: (text) => scanPublicText(String(text ?? "")),
|
|
166505
|
+
/** 构造一个空请求 (UI 填字段用) */
|
|
166506
|
+
emptyRequest: (kind) => emptyTaskActionRequest(kind),
|
|
166507
|
+
/** 最近一条操作提示 */
|
|
166508
|
+
hint() {
|
|
166509
|
+
return getTaskHint(core.contacts.storage());
|
|
166510
|
+
},
|
|
166511
|
+
setHint(text) {
|
|
166512
|
+
setTaskHint(text, core.contacts.storage());
|
|
166513
|
+
}
|
|
166514
|
+
},
|
|
166515
|
+
/**
|
|
166516
|
+
* web 资源层双源 OTA 更新 (2026-09-26, update-protocol §13) — 与桌面 `bolloon update` 同语义:
|
|
166517
|
+
* ① 身份: stable = npm dist-tag 权威 + GitHub Tag 交叉校验; dev = master `ref` + commit sha, 身份 `<版本>+dev.<sha7>`
|
|
166518
|
+
* ② 拒绝: 源不可达 / 版本不存在 / 交叉校验不一致 ⇒ **拒绝并说清分类**, 绝不静默装回旧版、绝不假装成功
|
|
166519
|
+
* ③ 可见: 当前装的是哪个源 / 哪个 sha / 能切回哪个源 (与桌面同措辞)
|
|
166520
|
+
* ④ 智能体: check/plan/download/verify 可程序调用; **switch / reload / rollback / 切通道必须人确认**
|
|
166521
|
+
*
|
|
166522
|
+
* 天花板 (不许承诺做不到的): iOS 原生壳层**不能自更** (App Store 规则) —— 自更的只是 web 资源层;
|
|
166523
|
+
* 二进制要走商店 / TestFlight。Android 侧载 APK 可自更但要用户允许未知来源 (显式告知 + 人在环)。
|
|
166524
|
+
*/
|
|
166525
|
+
update: {
|
|
166526
|
+
/** 结论/阶段枚举与拒绝表 (给 UI 与智能体做判断, 不用猜字符串) */
|
|
166527
|
+
vocabulary() {
|
|
166528
|
+
return {
|
|
166529
|
+
statuses: MOBILE_WEB_STATUSES.slice(),
|
|
166530
|
+
refused: MOBILE_REFUSED_STATUSES.slice(),
|
|
166531
|
+
requiredFiles: MOBILE_WEB_REQUIRED_FILES.slice(),
|
|
166532
|
+
layout: { ...WEB_LAYOUT },
|
|
166533
|
+
nativeCeiling: NATIVE_CEILING_LINE,
|
|
166534
|
+
agentContract: MOBILE_UPDATE_AGENT_CONTRACT
|
|
166535
|
+
};
|
|
166536
|
+
},
|
|
166537
|
+
/** 可写 web 资源目录接上没有 (真机: 原生壳要指向它才生效) */
|
|
166538
|
+
nativeWired() {
|
|
166539
|
+
return nativeWired(mobileUpdateDeps());
|
|
166540
|
+
},
|
|
166541
|
+
/** 当前 web 层的身份/来源/能切回谁 (读 state + 壳层注入的构建戳) */
|
|
166542
|
+
async state() {
|
|
166543
|
+
return readMobileUpdateState(currentWebStore());
|
|
166544
|
+
},
|
|
166545
|
+
async identity() {
|
|
166546
|
+
return resolveLocalWebIdentity(mobileUpdateDeps());
|
|
166547
|
+
},
|
|
166548
|
+
/** 检查两源 (只读, 不下载任何东西) */
|
|
166549
|
+
async check(opts = {}) {
|
|
166550
|
+
return checkMobileUpdate(mobileUpdateDeps(opts));
|
|
166551
|
+
},
|
|
166552
|
+
/** 检查 + 说明 (报告行: 与桌面 `update --status` 同口径) */
|
|
166553
|
+
async report(opts = {}) {
|
|
166554
|
+
const r = await checkMobileUpdate(mobileUpdateDeps(opts));
|
|
166555
|
+
const st = await readMobileUpdateState(currentWebStore());
|
|
166556
|
+
return { result: r, lines: renderMobileUpdateReport(r, st) };
|
|
166557
|
+
},
|
|
166558
|
+
/** 下载 → 解压 → 落 staging → 验证可启动; **不切换** (智能体能自动跑到这一步) */
|
|
166559
|
+
async prepare(opts = {}) {
|
|
166560
|
+
return autoPrepareMobileUpdate(mobileUpdateDeps(opts));
|
|
166561
|
+
},
|
|
166562
|
+
/** 切换 (人在环: 必须 confirm) → 原子替换 + 失败回滚; 成功后提示重载 */
|
|
166563
|
+
async apply(opts = {}) {
|
|
166564
|
+
return applyMobileUpdate({ ...mobileUpdateDeps(opts), confirm: opts.confirm === true, reuseStaging: opts.reuseStaging === true });
|
|
166565
|
+
},
|
|
166566
|
+
/** 回滚到 previous (人在环) */
|
|
166567
|
+
async rollback(opts = {}) {
|
|
166568
|
+
return rollbackMobileUpdate({ ...mobileUpdateDeps(opts), confirm: opts.confirm === true });
|
|
166569
|
+
},
|
|
166570
|
+
/** 切换通道 (stable ↔ dev; 只写偏好, 不装东西) */
|
|
166571
|
+
async setChannel(channel) {
|
|
166572
|
+
return setMobileUpdateChannel(channel, currentWebStore());
|
|
166573
|
+
},
|
|
166574
|
+
/** 当前通道偏好 */
|
|
166575
|
+
channel() {
|
|
166576
|
+
return storedMobileChannel() || "stable";
|
|
166577
|
+
},
|
|
166578
|
+
/** 重载 web 层让新资源生效 (人在环) */
|
|
166579
|
+
async reload() {
|
|
166580
|
+
return reloadMobileWeb();
|
|
166581
|
+
}
|
|
166582
|
+
},
|
|
164262
166583
|
message: {
|
|
164263
166584
|
async send({ text, channelId }) {
|
|
164264
166585
|
if (!text || !channelId) return { ok: false, error: "text \u548C channelId \u5FC5\u586B" };
|