@napuketto/kernel 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +60 -101
- package/dist/index.d.cts +2 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +60 -101
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -4420,7 +4420,6 @@ function resolveMainFromStartup(ctx) {
|
|
|
4420
4420
|
*
|
|
4421
4421
|
* - serialize:深度受限序列化(BigInt 转字符串,Map/Set/Promise 展开,循环引用防护)
|
|
4422
4422
|
* - tryShape:解析 service getter 返回形状
|
|
4423
|
-
* - shapeKeyGetters:探测 service 关键数据 getter 返回形状
|
|
4424
4423
|
*/
|
|
4425
4424
|
/** 序列化深度上限(循环引用/深层对象防护)。 */
|
|
4426
4425
|
const MAX_SERIALIZE_DEPTH = 4;
|
|
@@ -4494,15 +4493,6 @@ function tryShape(session, getter) {
|
|
|
4494
4493
|
return "[error]";
|
|
4495
4494
|
}
|
|
4496
4495
|
}
|
|
4497
|
-
/** 数据 getter 方法名模式(探测返回形状用)。 */
|
|
4498
|
-
const DATA_GETTER_RE = /^(get|query|fetch|load)/i;
|
|
4499
|
-
/** 探测 service 的关键数据 getter 返回形状(取前几个无参调用)。 */
|
|
4500
|
-
function shapeKeyGetters(session, serviceMethods) {
|
|
4501
|
-
const out = {};
|
|
4502
|
-
const candidates = serviceMethods.filter((m) => DATA_GETTER_RE.test(m) && !m.endsWith("Listener"));
|
|
4503
|
-
for (const m of candidates.slice(0, 8)) out[m] = tryShape(session, m);
|
|
4504
|
-
return out;
|
|
4505
|
-
}
|
|
4506
4496
|
//#endregion
|
|
4507
4497
|
//#region src/wrapper/probe/probe-utils.ts
|
|
4508
4498
|
/**
|
|
@@ -4560,29 +4550,6 @@ function tryCall(obj, name) {
|
|
|
4560
4550
|
function isServiceGetter(name) {
|
|
4561
4551
|
return name.startsWith("get") && name.endsWith("Service");
|
|
4562
4552
|
}
|
|
4563
|
-
/** 非空服务实例计数(逐个调用 get*Service 数非空返回;候选可用度评分)。
|
|
4564
|
-
* 自建宿主下 QQ 主 session 未被 init,get*Service 恒 null(2026-10-31 实测
|
|
4565
|
-
* napuketto-probe-late.json),kernel 自建 session 服务可用——主目标按此评分选取。 */
|
|
4566
|
-
function countNonNullServices(session) {
|
|
4567
|
-
if (session === null || session === void 0) return 0;
|
|
4568
|
-
let count = 0;
|
|
4569
|
-
for (const name of listMethods(session)) {
|
|
4570
|
-
if (!isServiceGetter(name)) continue;
|
|
4571
|
-
const call = tryCall(session, name);
|
|
4572
|
-
if (call.ok && call.value !== null && call.value !== void 0) count += 1;
|
|
4573
|
-
}
|
|
4574
|
-
return count;
|
|
4575
|
-
}
|
|
4576
|
-
/** 主探测目标选取:服务实例最多者优先,评分并列保持候选顺序(主 session 在前)。 */
|
|
4577
|
-
function pickPrimaryCandidate(candidates) {
|
|
4578
|
-
let best = candidates[0];
|
|
4579
|
-
for (const candidate of candidates.slice(1)) if (best !== void 0 && candidate.serviceNonNull > best.serviceNonNull) best = candidate;
|
|
4580
|
-
return best ?? {
|
|
4581
|
-
source: "own-create",
|
|
4582
|
-
session: null,
|
|
4583
|
-
serviceNonNull: 0
|
|
4584
|
-
};
|
|
4585
|
-
}
|
|
4586
4553
|
//#endregion
|
|
4587
4554
|
//#region src/wrapper/probe/probe-services.ts
|
|
4588
4555
|
/** 探测关键 export 构造器方法(get/create/getNTWrapperSession 等)。 */
|
|
@@ -4833,89 +4800,76 @@ function probeCreatedChain(ctx, created) {
|
|
|
4833
4800
|
function findMainProbeId(sessionIds) {
|
|
4834
4801
|
return sessionIds.find((id) => id.startsWith("nt_")) ?? sessionIds[0];
|
|
4835
4802
|
}
|
|
4836
|
-
/** 探测 session 与 service
|
|
4837
|
-
*
|
|
4838
|
-
*
|
|
4839
|
-
* 服务可用——主目标按 countNonNullServices 评分选取,并列保持主 session 优先。 */
|
|
4840
|
-
function probeSession(ctx) {
|
|
4841
|
-
const out = {};
|
|
4842
|
-
const candidates = collectProbeCandidates(ctx).map(scoreCandidate);
|
|
4843
|
-
const primary = pickPrimaryCandidate(candidates);
|
|
4844
|
-
out["sessionSource"] = primary.source;
|
|
4845
|
-
out["session"] = sessionFace(primary.session);
|
|
4846
|
-
if (primary.session !== null && primary.session !== void 0) out["services"] = collectServiceGetters(primary.session);
|
|
4847
|
-
if (candidates.length > 1) out["sessionAlternates"] = alternateFaces(candidates, primary);
|
|
4848
|
-
return out;
|
|
4849
|
-
}
|
|
4850
|
-
/** 候选评分(非空服务实例数)。 */
|
|
4851
|
-
function scoreCandidate(candidate) {
|
|
4852
|
-
return {
|
|
4853
|
-
...candidate,
|
|
4854
|
-
serviceNonNull: countNonNullServices(candidate.session)
|
|
4855
|
-
};
|
|
4856
|
-
}
|
|
4857
|
-
/** 落选候选的概要面(方法数 + 评分,诊断用)。 */
|
|
4858
|
-
function alternateFaces(candidates, primary) {
|
|
4859
|
-
return candidates.filter((candidate) => candidate !== primary).map((candidate) => ({
|
|
4860
|
-
source: candidate.source,
|
|
4861
|
-
methodCount: listMethods(candidate.session).length,
|
|
4862
|
-
serviceNonNull: candidate.serviceNonNull
|
|
4863
|
-
}));
|
|
4864
|
-
}
|
|
4865
|
-
/** 收集候选 session:kernel 自建 session + QQ 主 session(若可得)。
|
|
4803
|
+
/** 探测 session 与 service 方法名面。
|
|
4804
|
+
* 主目标 = ctx.session 快照(kernel 自建就绪 session),缺省回退 QQ 主 session;
|
|
4805
|
+
* 自建宿主下主 session 未被 init(get*Service 恒 null,2026-10-31 实测)。
|
|
4866
4806
|
* ⚠️ 先快照 ctx.session 再枚举主 session——getMainSession 有 P1-4 遗留副作用
|
|
4867
|
-
* (resolveMainFromStartup 把空壳主 session 写回 ctx.session,session-resolver.ts
|
|
4868
|
-
*
|
|
4869
|
-
|
|
4807
|
+
* (resolveMainFromStartup 把空壳主 session 写回 ctx.session,session-resolver.ts)。
|
|
4808
|
+
* ⚠️ names-only:不对服务实例做无参 shape 调用——活 session 上无参调原生方法
|
|
4809
|
+
* = 访问违例 0xC0000005(2026-10-31 实测崩溃,tryShape 捕不住原生段错误)。 */
|
|
4810
|
+
/** 非空判定(null / undefined 均视为缺省)。 */
|
|
4811
|
+
function hasValue(value) {
|
|
4812
|
+
return value !== null && value !== void 0;
|
|
4813
|
+
}
|
|
4814
|
+
function probeSession(ctx, persist) {
|
|
4815
|
+
const out = {};
|
|
4870
4816
|
const own = ctx.session;
|
|
4871
|
-
const
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4817
|
+
const main = tryMainSession(ctx);
|
|
4818
|
+
const primary = hasValue(own) ? own : main;
|
|
4819
|
+
out["sessionSource"] = hasValue(own) ? "own-create" : "mainSession";
|
|
4820
|
+
out["session"] = sessionFace(primary);
|
|
4821
|
+
assignServices(out, primary, persist);
|
|
4822
|
+
assignAlternates(out, own, main);
|
|
4823
|
+
return out;
|
|
4875
4824
|
}
|
|
4876
|
-
/**
|
|
4877
|
-
function
|
|
4825
|
+
/** 并入主目标的服务方法名面(主目标缺省时跳过)。 */
|
|
4826
|
+
function assignServices(out, primary, persist) {
|
|
4827
|
+
if (!hasValue(primary)) return;
|
|
4828
|
+
out["services"] = collectServiceGetters(primary, persist);
|
|
4829
|
+
}
|
|
4830
|
+
/** 并入落选候选概要(仅主目标为自建 session 时记录主 session 方法数,诊断用)。 */
|
|
4831
|
+
function assignAlternates(out, own, main) {
|
|
4832
|
+
if (!hasValue(own) || !hasValue(main)) return;
|
|
4833
|
+
out["sessionAlternates"] = [{
|
|
4834
|
+
source: "mainSession(getNTWrapperSession)",
|
|
4835
|
+
methodCount: listMethods(main).length
|
|
4836
|
+
}];
|
|
4837
|
+
}
|
|
4838
|
+
/** QQ 主 session(getMainSession 有写回 ctx.session 的副作用——调用前须已快照)。 */
|
|
4839
|
+
function tryMainSession(ctx) {
|
|
4878
4840
|
try {
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
});
|
|
4884
|
-
} catch {}
|
|
4885
|
-
}
|
|
4886
|
-
/** 并入 kernel 自建 session 候选(与已有候选同一实例时去重)。 */
|
|
4887
|
-
function pushOwnCandidate(own, out) {
|
|
4888
|
-
if (own === null || own === void 0) return;
|
|
4889
|
-
if (out.some((candidate) => candidate.session === own)) return;
|
|
4890
|
-
out.push({
|
|
4891
|
-
source: "own-create",
|
|
4892
|
-
session: own
|
|
4893
|
-
});
|
|
4841
|
+
return getMainSession(ctx);
|
|
4842
|
+
} catch {
|
|
4843
|
+
return null;
|
|
4844
|
+
}
|
|
4894
4845
|
}
|
|
4895
|
-
/** 收集 session 的 get*Service
|
|
4896
|
-
|
|
4897
|
-
|
|
4846
|
+
/** 收集 session 的 get*Service 方法名面(names-only,不做 shape 无参调用)。
|
|
4847
|
+
* 每个服务完成即 persist 一次——活 session 上个别 getter 若触发原生崩溃,
|
|
4848
|
+
* 文件里留下最后一个成功项,精确定位肇事 getter。 */
|
|
4849
|
+
function collectServiceGetters(session, persist) {
|
|
4898
4850
|
const services = {};
|
|
4899
|
-
for (const getter of
|
|
4851
|
+
for (const getter of listMethods(session).filter(isServiceGetter)) {
|
|
4852
|
+
services[getter] = probeServiceGetter(session, getter);
|
|
4853
|
+
persist?.();
|
|
4854
|
+
}
|
|
4900
4855
|
return services;
|
|
4901
4856
|
}
|
|
4902
|
-
/** 探测单个 getter
|
|
4857
|
+
/** 探测单个 getter:成功记录方法名面(不调用服务方法),失败记录错误。 */
|
|
4903
4858
|
function probeServiceGetter(session, getter) {
|
|
4904
4859
|
const call = tryCall(session, getter);
|
|
4905
4860
|
if (!(call.ok && call.value)) return {
|
|
4906
4861
|
error: call.error ?? "null/undefined",
|
|
4907
4862
|
ok: call.ok
|
|
4908
4863
|
};
|
|
4909
|
-
const methods = listMethods(call.value);
|
|
4910
4864
|
return {
|
|
4911
|
-
methods,
|
|
4912
|
-
ownKeys: Object.getOwnPropertyNames(call.value).slice(0, 20)
|
|
4913
|
-
shapes: shapeKeyGetters(call.value, methods)
|
|
4865
|
+
methods: listMethods(call.value),
|
|
4866
|
+
ownKeys: Object.getOwnPropertyNames(call.value).slice(0, 20)
|
|
4914
4867
|
};
|
|
4915
4868
|
}
|
|
4916
4869
|
/**
|
|
4917
|
-
* 探测 wrapper 运行时:dump session 方法与各 service
|
|
4870
|
+
* 探测 wrapper 运行时:dump session 方法与各 service 方法名到 JSON。
|
|
4918
4871
|
* 返回探测结果对象;同时写文件(NAPUTO_CFG_DIR/<file>,默认 napuketto-probe.json)。
|
|
4872
|
+
* 服务枚举逐项增量落盘(persist)——活 session 上原生崩溃时文件保留断点。
|
|
4919
4873
|
*/
|
|
4920
4874
|
function probeRuntime(ctx, file = "napuketto-probe.json") {
|
|
4921
4875
|
const result = {
|
|
@@ -4925,9 +4879,15 @@ function probeRuntime(ctx, file = "napuketto-probe.json") {
|
|
|
4925
4879
|
exportCtors: probeExportCtors(ctx),
|
|
4926
4880
|
engineCalls: probeEngineCalls(ctx),
|
|
4927
4881
|
loginService: probeLoginService(ctx),
|
|
4928
|
-
startup: probeStartup(ctx)
|
|
4929
|
-
...probeSession(ctx)
|
|
4882
|
+
startup: probeStartup(ctx)
|
|
4930
4883
|
};
|
|
4884
|
+
const persist = () => writeProbeFile(result, file);
|
|
4885
|
+
Object.assign(result, probeSession(ctx, persist));
|
|
4886
|
+
writeProbeFile(result, file);
|
|
4887
|
+
return result;
|
|
4888
|
+
}
|
|
4889
|
+
/** 探测结果落盘(增量与最终共用;最终写入后记 probeFile 路径)。 */
|
|
4890
|
+
function writeProbeFile(result, file) {
|
|
4931
4891
|
try {
|
|
4932
4892
|
const dir = process.env["NAPUTO_CFG_DIR"] ?? process.cwd();
|
|
4933
4893
|
mkdirSync(dir, { recursive: true });
|
|
@@ -4935,9 +4895,8 @@ function probeRuntime(ctx, file = "napuketto-probe.json") {
|
|
|
4935
4895
|
writeFileSync(full, JSON.stringify(result, null, 2), "utf8");
|
|
4936
4896
|
result["probeFile"] = full;
|
|
4937
4897
|
} catch (e) {
|
|
4938
|
-
result["probeFileError"] =
|
|
4898
|
+
result["probeFileError"] = errMsgString(e);
|
|
4939
4899
|
}
|
|
4940
|
-
return result;
|
|
4941
4900
|
}
|
|
4942
4901
|
//#endregion
|
|
4943
4902
|
//#region src/wrapper/wrapper-version.ts
|