@adhdev/daemon-core 0.9.77-rc.48 → 0.9.77-rc.49
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.d.ts +4 -2
- package/dist/index.js +171 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +166 -6
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-ledger-reconciliation.d.ts +55 -0
- package/dist/mesh/mesh-ledger.d.ts +46 -4
- package/package.json +1 -1
- package/src/commands/router.ts +35 -0
- package/src/index.ts +4 -2
- package/src/mesh/mesh-ledger-reconciliation.ts +115 -0
- package/src/mesh/mesh-ledger.ts +120 -7
package/dist/index.d.ts
CHANGED
|
@@ -31,8 +31,10 @@ export { buildCoordinatorSystemPrompt } from './mesh/coordinator-prompt.js';
|
|
|
31
31
|
export type { CoordinatorPromptContext } from './mesh/coordinator-prompt.js';
|
|
32
32
|
export { syncMeshes } from './mesh/mesh-sync.js';
|
|
33
33
|
export type { MeshSyncTransport, MeshSyncResult, RemoteMeshRecord } from './mesh/mesh-sync.js';
|
|
34
|
-
export { appendLedgerEntry, readLedgerEntries, getLedgerSummary, getLedgerDir, getSessionRecoveryContext } from './mesh/mesh-ledger.js';
|
|
35
|
-
export type { MeshLedgerEntry, MeshLedgerKind, MeshLedgerSummary, ReadLedgerOptions, SessionRecoveryContext } from './mesh/mesh-ledger.js';
|
|
34
|
+
export { appendLedgerEntry, appendRemoteLedgerEntries, readLedgerEntries, readLedgerSlice, getLedgerSummary, getLedgerDir, getSessionRecoveryContext, MAX_LEDGER_SLICE_LIMIT } from './mesh/mesh-ledger.js';
|
|
35
|
+
export type { AppendRemoteLedgerResult, MeshLedgerEntry, MeshLedgerKind, MeshLedgerSlice, MeshLedgerSummary, ReadLedgerOptions, ReadLedgerSliceOptions, SessionRecoveryContext } from './mesh/mesh-ledger.js';
|
|
36
|
+
export { buildMeshLedgerReconciliationEvidence, buildMeshLedgerReplicaEvidence } from './mesh/mesh-ledger-reconciliation.js';
|
|
37
|
+
export type { MeshLedgerReconciliationEvidence, MeshLedgerReplicaEvidence, MeshLedgerReplicaStatus } from './mesh/mesh-ledger-reconciliation.js';
|
|
36
38
|
export { enqueueTask, getQueue, claimNextTask, updateTaskStatus, updateSessionTaskStatus, cancelTask, requeueTask, getMeshQueueStats } from './mesh/mesh-work-queue.js';
|
|
37
39
|
export type { MeshWorkQueueEntry, MeshTaskStatus, MeshWorkQueueStats } from './mesh/mesh-work-queue.js';
|
|
38
40
|
export { triggerMeshQueue } from './mesh/mesh-events.js';
|
package/dist/index.js
CHANGED
|
@@ -795,13 +795,15 @@ Follow these recovery rules:
|
|
|
795
795
|
// src/mesh/mesh-ledger.ts
|
|
796
796
|
var mesh_ledger_exports = {};
|
|
797
797
|
__export(mesh_ledger_exports, {
|
|
798
|
+
MAX_LEDGER_SLICE_LIMIT: () => MAX_LEDGER_SLICE_LIMIT,
|
|
798
799
|
appendLedgerEntry: () => appendLedgerEntry,
|
|
799
800
|
appendRemoteLedgerEntries: () => appendRemoteLedgerEntries,
|
|
800
801
|
getLedgerDir: () => getLedgerDir,
|
|
801
802
|
getLedgerSummary: () => getLedgerSummary,
|
|
802
803
|
getSessionRecoveryContext: () => getSessionRecoveryContext,
|
|
803
804
|
meshLedgerEvents: () => meshLedgerEvents,
|
|
804
|
-
readLedgerEntries: () => readLedgerEntries
|
|
805
|
+
readLedgerEntries: () => readLedgerEntries,
|
|
806
|
+
readLedgerSlice: () => readLedgerSlice
|
|
805
807
|
});
|
|
806
808
|
function getLedgerDir() {
|
|
807
809
|
const dir = (0, import_path3.join)(getConfigDir(), LEDGER_DIR_NAME);
|
|
@@ -844,15 +846,49 @@ function appendLedgerEntry(meshId, partial) {
|
|
|
844
846
|
throw new Error(`Failed to append to ledger for mesh ${meshId}: ${e.message}`);
|
|
845
847
|
}
|
|
846
848
|
}
|
|
849
|
+
function clampLedgerSliceLimit(limit) {
|
|
850
|
+
if (typeof limit !== "number" || !Number.isFinite(limit)) return DEFAULT_LEDGER_SLICE_LIMIT;
|
|
851
|
+
return Math.max(1, Math.min(MAX_LEDGER_SLICE_LIMIT, Math.floor(limit)));
|
|
852
|
+
}
|
|
853
|
+
function isValidRemoteLedgerEntry(meshId, value) {
|
|
854
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
855
|
+
const entry = value;
|
|
856
|
+
if (typeof entry.id !== "string" || !entry.id.trim()) return false;
|
|
857
|
+
if (entry.meshId !== meshId) return false;
|
|
858
|
+
if (typeof entry.timestamp !== "string" || Number.isNaN(new Date(entry.timestamp).getTime())) return false;
|
|
859
|
+
if (typeof entry.kind !== "string" || !entry.kind.trim()) return false;
|
|
860
|
+
if (!entry.payload || typeof entry.payload !== "object" || Array.isArray(entry.payload)) return false;
|
|
861
|
+
return true;
|
|
862
|
+
}
|
|
847
863
|
function appendRemoteLedgerEntries(meshId, entries) {
|
|
848
|
-
if (entries.length === 0) return;
|
|
864
|
+
if (entries.length === 0) return { accepted: 0, skippedDuplicate: 0, rejectedInvalid: 0, entries: [] };
|
|
849
865
|
const ledgerPath = getLedgerPath(meshId);
|
|
850
866
|
const existing = new Set(readLedgerEntries(meshId).map((e) => e.id));
|
|
851
|
-
const
|
|
852
|
-
|
|
867
|
+
const validEntries = [];
|
|
868
|
+
let rejectedInvalid = 0;
|
|
869
|
+
let skippedDuplicate = 0;
|
|
870
|
+
for (const entry of entries) {
|
|
871
|
+
if (!isValidRemoteLedgerEntry(meshId, entry)) {
|
|
872
|
+
rejectedInvalid++;
|
|
873
|
+
continue;
|
|
874
|
+
}
|
|
875
|
+
if (existing.has(entry.id)) {
|
|
876
|
+
skippedDuplicate++;
|
|
877
|
+
continue;
|
|
878
|
+
}
|
|
879
|
+
existing.add(entry.id);
|
|
880
|
+
validEntries.push(entry);
|
|
881
|
+
}
|
|
882
|
+
if (validEntries.length === 0) {
|
|
883
|
+
return { accepted: 0, skippedDuplicate, rejectedInvalid, entries: [] };
|
|
884
|
+
}
|
|
853
885
|
try {
|
|
854
|
-
const lines =
|
|
886
|
+
const lines = validEntries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
855
887
|
(0, import_fs3.appendFileSync)(ledgerPath, lines, { encoding: "utf-8", mode: 384 });
|
|
888
|
+
for (const entry of validEntries) {
|
|
889
|
+
meshLedgerEvents.emit("append", meshId, entry);
|
|
890
|
+
}
|
|
891
|
+
return { accepted: validEntries.length, skippedDuplicate, rejectedInvalid, entries: validEntries };
|
|
856
892
|
} catch (e) {
|
|
857
893
|
throw new Error(`Failed to append remote ledger entries for mesh ${meshId}: ${e.message}`);
|
|
858
894
|
}
|
|
@@ -891,6 +927,34 @@ function readLedgerEntries(meshId, opts) {
|
|
|
891
927
|
}
|
|
892
928
|
return entries;
|
|
893
929
|
}
|
|
930
|
+
function readLedgerSlice(meshId, opts) {
|
|
931
|
+
const limit = clampLedgerSliceLimit(opts?.limit);
|
|
932
|
+
let entries = readLedgerEntries(meshId, { since: opts?.since, kind: opts?.kind });
|
|
933
|
+
const afterId = typeof opts?.afterId === "string" && opts.afterId.trim() ? opts.afterId.trim() : null;
|
|
934
|
+
if (afterId) {
|
|
935
|
+
const index = entries.findIndex((entry) => entry.id === afterId);
|
|
936
|
+
entries = index >= 0 ? entries.slice(index + 1) : entries;
|
|
937
|
+
}
|
|
938
|
+
const bounded = entries.slice(0, limit);
|
|
939
|
+
return {
|
|
940
|
+
protocol: "adhdev.mesh.ledger.slice.v1",
|
|
941
|
+
meshId,
|
|
942
|
+
entries: bounded,
|
|
943
|
+
cursor: {
|
|
944
|
+
afterId,
|
|
945
|
+
nextAfterId: bounded.length ? bounded[bounded.length - 1].id : afterId,
|
|
946
|
+
limit,
|
|
947
|
+
hasMore: entries.length > bounded.length
|
|
948
|
+
},
|
|
949
|
+
summary: getLedgerSummary(meshId),
|
|
950
|
+
sourceOfTruth: {
|
|
951
|
+
kind: "local_jsonl",
|
|
952
|
+
path: getLedgerPath(meshId),
|
|
953
|
+
bounded: true,
|
|
954
|
+
maxLimit: MAX_LEDGER_SLICE_LIMIT
|
|
955
|
+
}
|
|
956
|
+
};
|
|
957
|
+
}
|
|
894
958
|
function getLedgerSummary(meshId) {
|
|
895
959
|
const entries = readLedgerEntries(meshId);
|
|
896
960
|
const now = Date.now();
|
|
@@ -1013,7 +1077,7 @@ function rotateLedgerFile(meshId, currentPath) {
|
|
|
1013
1077
|
} catch {
|
|
1014
1078
|
}
|
|
1015
1079
|
}
|
|
1016
|
-
var import_fs3, import_path3, import_crypto4, import_events, LEDGER_DIR_NAME, MAX_FILE_SIZE_BYTES, RECENT_FAILURE_WINDOW_MS, meshLedgerEvents;
|
|
1080
|
+
var import_fs3, import_path3, import_crypto4, import_events, LEDGER_DIR_NAME, MAX_FILE_SIZE_BYTES, RECENT_FAILURE_WINDOW_MS, DEFAULT_LEDGER_SLICE_LIMIT, MAX_LEDGER_SLICE_LIMIT, meshLedgerEvents;
|
|
1017
1081
|
var init_mesh_ledger = __esm({
|
|
1018
1082
|
"src/mesh/mesh-ledger.ts"() {
|
|
1019
1083
|
"use strict";
|
|
@@ -1025,6 +1089,8 @@ var init_mesh_ledger = __esm({
|
|
|
1025
1089
|
LEDGER_DIR_NAME = "mesh-ledger";
|
|
1026
1090
|
MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;
|
|
1027
1091
|
RECENT_FAILURE_WINDOW_MS = 30 * 60 * 1e3;
|
|
1092
|
+
DEFAULT_LEDGER_SLICE_LIMIT = 100;
|
|
1093
|
+
MAX_LEDGER_SLICE_LIMIT = 500;
|
|
1028
1094
|
meshLedgerEvents = new import_events.EventEmitter();
|
|
1029
1095
|
}
|
|
1030
1096
|
});
|
|
@@ -5318,6 +5384,7 @@ __export(index_exports, {
|
|
|
5318
5384
|
IdeProviderInstance: () => IdeProviderInstance,
|
|
5319
5385
|
InMemoryGitSnapshotStore: () => InMemoryGitSnapshotStore,
|
|
5320
5386
|
LOG: () => LOG,
|
|
5387
|
+
MAX_LEDGER_SLICE_LIMIT: () => MAX_LEDGER_SLICE_LIMIT,
|
|
5321
5388
|
MIN_GIT_WORKSPACE_POLL_INTERVAL_MS: () => MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
5322
5389
|
MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
|
|
5323
5390
|
MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
@@ -5333,12 +5400,15 @@ __export(index_exports, {
|
|
|
5333
5400
|
addNode: () => addNode,
|
|
5334
5401
|
appendLedgerEntry: () => appendLedgerEntry,
|
|
5335
5402
|
appendRecentActivity: () => appendRecentActivity,
|
|
5403
|
+
appendRemoteLedgerEntries: () => appendRemoteLedgerEntries,
|
|
5336
5404
|
buildAssistantChatMessage: () => buildAssistantChatMessage,
|
|
5337
5405
|
buildChatMessage: () => buildChatMessage,
|
|
5338
5406
|
buildChatMessageSignature: () => buildChatMessageSignature,
|
|
5339
5407
|
buildChatTailDeliverySignature: () => buildChatTailDeliverySignature,
|
|
5340
5408
|
buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt,
|
|
5341
5409
|
buildMachineInfo: () => buildMachineInfo,
|
|
5410
|
+
buildMeshLedgerReconciliationEvidence: () => buildMeshLedgerReconciliationEvidence,
|
|
5411
|
+
buildMeshLedgerReplicaEvidence: () => buildMeshLedgerReplicaEvidence,
|
|
5342
5412
|
buildP2pRelayFailurePayload: () => buildP2pRelayFailurePayload,
|
|
5343
5413
|
buildPinnedGlobalInstallCommand: () => buildPinnedGlobalInstallCommand,
|
|
5344
5414
|
buildRuntimeSystemChatMessage: () => buildRuntimeSystemChatMessage,
|
|
@@ -5461,6 +5531,7 @@ __export(index_exports, {
|
|
|
5461
5531
|
probeCdpPort: () => probeCdpPort,
|
|
5462
5532
|
readChatHistory: () => readChatHistory,
|
|
5463
5533
|
readLedgerEntries: () => readLedgerEntries,
|
|
5534
|
+
readLedgerSlice: () => readLedgerSlice,
|
|
5464
5535
|
recordDebugTrace: () => recordDebugTrace,
|
|
5465
5536
|
registerExtensionProviders: () => registerExtensionProviders,
|
|
5466
5537
|
removeNode: () => removeNode,
|
|
@@ -7367,6 +7438,66 @@ async function syncMeshes(transport) {
|
|
|
7367
7438
|
|
|
7368
7439
|
// src/index.ts
|
|
7369
7440
|
init_mesh_ledger();
|
|
7441
|
+
|
|
7442
|
+
// src/mesh/mesh-ledger-reconciliation.ts
|
|
7443
|
+
function lastTimestamp(slice) {
|
|
7444
|
+
const entries = Array.isArray(slice?.entries) ? slice.entries : [];
|
|
7445
|
+
return entries.length ? entries[entries.length - 1].timestamp : null;
|
|
7446
|
+
}
|
|
7447
|
+
function buildMeshLedgerReplicaEvidence(args) {
|
|
7448
|
+
const entriesReceived = Array.isArray(args.slice?.entries) ? args.slice.entries.length : 0;
|
|
7449
|
+
return {
|
|
7450
|
+
nodeId: args.nodeId,
|
|
7451
|
+
...args.daemonId ? { daemonId: args.daemonId } : {},
|
|
7452
|
+
status: args.status ?? (args.importResult && args.importResult.accepted > 0 ? "imported" : "queried"),
|
|
7453
|
+
transport: args.transport,
|
|
7454
|
+
protocol: "adhdev.mesh.ledger.slice.v1",
|
|
7455
|
+
entriesReceived,
|
|
7456
|
+
entriesImported: args.importResult?.accepted ?? 0,
|
|
7457
|
+
skippedDuplicate: args.importResult?.skippedDuplicate ?? 0,
|
|
7458
|
+
rejectedInvalid: args.importResult?.rejectedInvalid ?? 0,
|
|
7459
|
+
hasMore: args.slice?.cursor?.hasMore === true,
|
|
7460
|
+
nextAfterId: args.slice?.cursor?.nextAfterId ?? null,
|
|
7461
|
+
lastTimestamp: lastTimestamp(args.slice),
|
|
7462
|
+
...args.slice?.summary ? { summary: args.slice.summary } : {},
|
|
7463
|
+
...args.error ? {
|
|
7464
|
+
error: args.error,
|
|
7465
|
+
noFallbackReason: "Ledger reconciliation is P2P/local-first only; Cloud/D1 ledger sync is intentionally disabled."
|
|
7466
|
+
} : {}
|
|
7467
|
+
};
|
|
7468
|
+
}
|
|
7469
|
+
function buildMeshLedgerReconciliationEvidence(meshId, replicas) {
|
|
7470
|
+
const failedNodes = replicas.filter((replica) => replica.status === "failed").map((replica) => replica.nodeId);
|
|
7471
|
+
const pendingNodes = replicas.filter((replica) => replica.hasMore && replica.status !== "failed").map((replica) => replica.nodeId);
|
|
7472
|
+
return {
|
|
7473
|
+
protocol: "adhdev.mesh.ledger.reconciliation.v1",
|
|
7474
|
+
meshId,
|
|
7475
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7476
|
+
sourceOfTruth: {
|
|
7477
|
+
kind: "coordinator_local_jsonl",
|
|
7478
|
+
p2pOnly: true,
|
|
7479
|
+
cloudD1LedgerSync: false,
|
|
7480
|
+
notes: "Coordinator reconciles bounded slices from daemon-local JSONL ledgers over P2P DataChannel; Cloud/D1 is not a ledger source of truth."
|
|
7481
|
+
},
|
|
7482
|
+
replicas,
|
|
7483
|
+
totals: {
|
|
7484
|
+
replicas: replicas.length,
|
|
7485
|
+
queried: replicas.filter((replica) => replica.status !== "failed").length,
|
|
7486
|
+
failed: failedNodes.length,
|
|
7487
|
+
entriesReceived: replicas.reduce((sum, replica) => sum + replica.entriesReceived, 0),
|
|
7488
|
+
entriesImported: replicas.reduce((sum, replica) => sum + replica.entriesImported, 0),
|
|
7489
|
+
skippedDuplicate: replicas.reduce((sum, replica) => sum + replica.skippedDuplicate, 0),
|
|
7490
|
+
rejectedInvalid: replicas.reduce((sum, replica) => sum + replica.rejectedInvalid, 0)
|
|
7491
|
+
},
|
|
7492
|
+
convergence: {
|
|
7493
|
+
complete: failedNodes.length === 0 && pendingNodes.length === 0,
|
|
7494
|
+
pendingNodes,
|
|
7495
|
+
failedNodes
|
|
7496
|
+
}
|
|
7497
|
+
};
|
|
7498
|
+
}
|
|
7499
|
+
|
|
7500
|
+
// src/index.ts
|
|
7370
7501
|
init_mesh_work_queue();
|
|
7371
7502
|
init_mesh_events();
|
|
7372
7503
|
|
|
@@ -24900,6 +25031,35 @@ var DaemonCommandRouter = class {
|
|
|
24900
25031
|
return { success: false, error: e.message };
|
|
24901
25032
|
}
|
|
24902
25033
|
}
|
|
25034
|
+
case "get_mesh_ledger_slice": {
|
|
25035
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
25036
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
25037
|
+
try {
|
|
25038
|
+
const { readLedgerSlice: readLedgerSlice2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
25039
|
+
const kind = Array.isArray(args?.kind) ? args.kind.filter((k) => typeof k === "string") : void 0;
|
|
25040
|
+
const slice = readLedgerSlice2(meshId, {
|
|
25041
|
+
afterId: typeof args?.afterId === "string" ? args.afterId : void 0,
|
|
25042
|
+
since: typeof args?.since === "string" ? args.since : void 0,
|
|
25043
|
+
kind,
|
|
25044
|
+
limit: typeof args?.limit === "number" ? args.limit : void 0
|
|
25045
|
+
});
|
|
25046
|
+
return { success: true, slice };
|
|
25047
|
+
} catch (e) {
|
|
25048
|
+
return { success: false, error: e.message };
|
|
25049
|
+
}
|
|
25050
|
+
}
|
|
25051
|
+
case "import_mesh_ledger_slice": {
|
|
25052
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
25053
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
25054
|
+
try {
|
|
25055
|
+
const { appendRemoteLedgerEntries: appendRemoteLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
25056
|
+
const entries = Array.isArray(args?.entries) ? args.entries : Array.isArray(args?.slice?.entries) ? args.slice.entries : [];
|
|
25057
|
+
const result = appendRemoteLedgerEntries2(meshId, entries);
|
|
25058
|
+
return { success: true, result, summary: getLedgerSummary2(meshId) };
|
|
25059
|
+
} catch (e) {
|
|
25060
|
+
return { success: false, error: e.message };
|
|
25061
|
+
}
|
|
25062
|
+
}
|
|
24903
25063
|
case "get_mesh_queue": {
|
|
24904
25064
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
24905
25065
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
@@ -33660,6 +33820,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
33660
33820
|
IdeProviderInstance,
|
|
33661
33821
|
InMemoryGitSnapshotStore,
|
|
33662
33822
|
LOG,
|
|
33823
|
+
MAX_LEDGER_SLICE_LIMIT,
|
|
33663
33824
|
MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
33664
33825
|
MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
|
|
33665
33826
|
MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
@@ -33675,12 +33836,15 @@ async function shutdownDaemonComponents(components) {
|
|
|
33675
33836
|
addNode,
|
|
33676
33837
|
appendLedgerEntry,
|
|
33677
33838
|
appendRecentActivity,
|
|
33839
|
+
appendRemoteLedgerEntries,
|
|
33678
33840
|
buildAssistantChatMessage,
|
|
33679
33841
|
buildChatMessage,
|
|
33680
33842
|
buildChatMessageSignature,
|
|
33681
33843
|
buildChatTailDeliverySignature,
|
|
33682
33844
|
buildCoordinatorSystemPrompt,
|
|
33683
33845
|
buildMachineInfo,
|
|
33846
|
+
buildMeshLedgerReconciliationEvidence,
|
|
33847
|
+
buildMeshLedgerReplicaEvidence,
|
|
33684
33848
|
buildP2pRelayFailurePayload,
|
|
33685
33849
|
buildPinnedGlobalInstallCommand,
|
|
33686
33850
|
buildRuntimeSystemChatMessage,
|
|
@@ -33803,6 +33967,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
33803
33967
|
probeCdpPort,
|
|
33804
33968
|
readChatHistory,
|
|
33805
33969
|
readLedgerEntries,
|
|
33970
|
+
readLedgerSlice,
|
|
33806
33971
|
recordDebugTrace,
|
|
33807
33972
|
registerExtensionProviders,
|
|
33808
33973
|
removeNode,
|