@xmoxmo/bncr 0.3.5 → 0.3.7

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.
Files changed (164) hide show
  1. package/README.md +5 -0
  2. package/dist/index.js +28 -5
  3. package/index.ts +55 -721
  4. package/package.json +8 -4
  5. package/scripts/check-pack.mjs +93 -18
  6. package/scripts/check-register-drift.mjs +35 -13
  7. package/scripts/selfcheck.mjs +80 -11
  8. package/src/bootstrap/channel-plugin-runtime.ts +81 -0
  9. package/src/bootstrap/cli.ts +97 -0
  10. package/src/bootstrap/register-runtime-gateway.ts +129 -0
  11. package/src/bootstrap/register-runtime-helpers.ts +140 -0
  12. package/src/bootstrap/register-runtime-singleton.ts +137 -0
  13. package/src/bootstrap/register-runtime.ts +201 -0
  14. package/src/bootstrap/runtime-discovery.ts +187 -0
  15. package/src/bootstrap/runtime-loader.ts +54 -0
  16. package/src/channel.ts +1590 -4967
  17. package/src/core/accounts.ts +23 -4
  18. package/src/core/dead-letter-diagnostics.ts +37 -5
  19. package/src/core/diagnostics.ts +31 -15
  20. package/src/core/downlink-health.ts +3 -11
  21. package/src/core/extended-diagnostics.ts +78 -36
  22. package/src/core/file-transfer-payloads.ts +1 -1
  23. package/src/core/logging.ts +1 -0
  24. package/src/core/outbox-enqueue.ts +13 -2
  25. package/src/core/outbox-entry-builders.ts +2 -0
  26. package/src/core/outbox-summary.ts +75 -3
  27. package/src/core/permissions.ts +15 -2
  28. package/src/core/persisted-outbox-entry.ts +21 -6
  29. package/src/core/policy.ts +45 -4
  30. package/src/core/probe.ts +3 -15
  31. package/src/core/register-trace.ts +3 -3
  32. package/src/core/status.ts +43 -4
  33. package/src/core/targets.ts +216 -205
  34. package/src/core/types.ts +221 -0
  35. package/src/core/value-sanitize.ts +29 -0
  36. package/src/messaging/inbound/commands.ts +147 -172
  37. package/src/messaging/inbound/context-facts.ts +4 -2
  38. package/src/messaging/inbound/contracts.ts +70 -0
  39. package/src/messaging/inbound/dispatch-prep.ts +303 -0
  40. package/src/messaging/inbound/dispatch.ts +49 -462
  41. package/src/messaging/inbound/gate.ts +18 -5
  42. package/src/messaging/inbound/last-route.ts +10 -4
  43. package/src/messaging/inbound/media-url-download.ts +109 -0
  44. package/src/messaging/inbound/native-command-runtime.ts +225 -0
  45. package/src/messaging/inbound/parse.ts +2 -1
  46. package/src/messaging/inbound/remote-media.ts +49 -0
  47. package/src/messaging/inbound/reply-config.ts +16 -4
  48. package/src/messaging/inbound/reply-dispatch.ts +162 -0
  49. package/src/messaging/inbound/runtime-compat.ts +31 -10
  50. package/src/messaging/inbound/session-label.ts +15 -7
  51. package/src/messaging/inbound/turn-context.ts +131 -0
  52. package/src/messaging/outbound/actions.ts +24 -10
  53. package/src/messaging/outbound/diagnostics-debug-builders.ts +365 -0
  54. package/src/messaging/outbound/diagnostics.ts +31 -355
  55. package/src/messaging/outbound/durable-message-adapter.ts +20 -16
  56. package/src/messaging/outbound/durable-queue-adapter.ts +20 -7
  57. package/src/messaging/outbound/media.ts +24 -13
  58. package/src/messaging/outbound/reply-enqueue-media.ts +181 -0
  59. package/src/messaging/outbound/reply-enqueue.ts +57 -134
  60. package/src/messaging/outbound/send-params.ts +3 -0
  61. package/src/messaging/outbound/send.ts +19 -10
  62. package/src/messaging/outbound/session-route.ts +18 -3
  63. package/src/openclaw/channel-runtime-contracts.ts +76 -0
  64. package/src/openclaw/config-runtime.ts +13 -7
  65. package/src/openclaw/inbound-session-runtime.ts +7 -3
  66. package/src/openclaw/ingress-runtime.ts +17 -27
  67. package/src/openclaw/reply-runtime.ts +54 -59
  68. package/src/openclaw/routing-runtime.ts +35 -18
  69. package/src/openclaw/runtime-surface.ts +156 -12
  70. package/src/openclaw/sdk-helpers.ts +8 -1
  71. package/src/openclaw/session-route-runtime.ts +12 -12
  72. package/src/plugin/ack-outbox-runtime-group.ts +264 -0
  73. package/src/plugin/bridge-ack-facade.ts +137 -0
  74. package/src/plugin/bridge-connection-facade.ts +111 -0
  75. package/src/plugin/bridge-diagnostics-facade.ts +23 -0
  76. package/src/plugin/bridge-drain-facade.ts +98 -0
  77. package/src/plugin/bridge-extended-diagnostics-facade.ts +149 -0
  78. package/src/plugin/bridge-file-transfer-push-facade.ts +140 -0
  79. package/src/plugin/bridge-lifecycle.ts +156 -0
  80. package/src/plugin/bridge-media-facade.ts +241 -0
  81. package/src/plugin/bridge-outbox-facade.ts +182 -0
  82. package/src/plugin/bridge-runtime-helpers.ts +266 -0
  83. package/src/plugin/bridge-runtime-snapshots.ts +104 -0
  84. package/src/plugin/bridge-runtime-surface-facade.ts +8 -0
  85. package/src/plugin/bridge-status-facade.ts +76 -0
  86. package/src/plugin/bridge-status-worker-facade.ts +72 -0
  87. package/src/plugin/bridge-support-runtime.ts +137 -0
  88. package/src/plugin/bridge-surface-handlers-group.ts +242 -0
  89. package/src/plugin/bridge-surface-helpers.ts +28 -0
  90. package/src/plugin/capabilities.ts +1 -3
  91. package/src/plugin/channel-components.ts +289 -0
  92. package/src/plugin/channel-inbound-helpers.ts +149 -0
  93. package/src/plugin/channel-plugin-bridge-group.ts +129 -0
  94. package/src/plugin/channel-plugin-surface-group.ts +202 -0
  95. package/src/plugin/channel-runtime-builders-delivery.ts +513 -0
  96. package/src/plugin/channel-runtime-builders-status.ts +331 -0
  97. package/src/plugin/channel-runtime-builders.ts +25 -0
  98. package/src/plugin/channel-runtime-constants.ts +40 -0
  99. package/src/plugin/channel-runtime-types.ts +146 -0
  100. package/src/plugin/channel-send-runtime-group.ts +37 -0
  101. package/src/plugin/channel-send.ts +226 -0
  102. package/src/plugin/channel-utils.ts +102 -0
  103. package/src/plugin/config.ts +24 -3
  104. package/src/plugin/connection-handlers-helpers.ts +254 -0
  105. package/src/plugin/connection-handlers.ts +440 -0
  106. package/src/plugin/connection-state-helpers.ts +159 -0
  107. package/src/plugin/connection-state-runtime-group.ts +51 -0
  108. package/src/plugin/connection-state.ts +527 -0
  109. package/src/plugin/diagnostics-handlers.ts +211 -0
  110. package/src/plugin/error-message.ts +15 -0
  111. package/src/plugin/file-ack-runtime.ts +284 -0
  112. package/src/plugin/file-inbound-abort.ts +112 -0
  113. package/src/plugin/file-inbound-chunk.ts +146 -0
  114. package/src/plugin/file-inbound-complete.ts +153 -0
  115. package/src/plugin/file-inbound-handlers.ts +19 -0
  116. package/src/plugin/file-inbound-init.ts +122 -0
  117. package/src/plugin/file-inbound-runtime.ts +51 -0
  118. package/src/plugin/file-inbound-state.ts +62 -0
  119. package/src/plugin/file-transfer-logs.ts +227 -0
  120. package/src/plugin/file-transfer-orchestrator-chunk.ts +135 -0
  121. package/src/plugin/file-transfer-orchestrator.ts +304 -0
  122. package/src/plugin/file-transfer-runtime-group.ts +102 -0
  123. package/src/plugin/file-transfer-send.ts +89 -0
  124. package/src/plugin/file-transfer-setup.ts +206 -0
  125. package/src/plugin/gateway-event-context.ts +41 -0
  126. package/src/plugin/gateway-runtime.ts +14 -4
  127. package/src/plugin/inbound-acceptance.ts +107 -0
  128. package/src/plugin/inbound-handlers.ts +248 -0
  129. package/src/plugin/inbound-surface-handlers-group.ts +152 -0
  130. package/src/plugin/media-dedupe-runtime.ts +90 -0
  131. package/src/plugin/media-orchestrators-runtime-group.ts +316 -0
  132. package/src/plugin/message-ack-runtime.ts +284 -0
  133. package/src/plugin/message-send.ts +16 -6
  134. package/src/plugin/messaging.ts +98 -36
  135. package/src/plugin/outbound.ts +50 -8
  136. package/src/plugin/outbox-ack-logs.ts +136 -0
  137. package/src/plugin/outbox-ack-outcome.ts +128 -0
  138. package/src/plugin/outbox-drain-ack.ts +145 -0
  139. package/src/plugin/outbox-drain-failure.ts +84 -0
  140. package/src/plugin/outbox-drain-loop.ts +554 -0
  141. package/src/plugin/outbox-drain-post-push.ts +159 -0
  142. package/src/plugin/outbox-drain-runtime.ts +141 -0
  143. package/src/plugin/outbox-drain-schedule.ts +116 -0
  144. package/src/plugin/outbox-file-push-flow.ts +69 -0
  145. package/src/plugin/outbox-push-route-runtime-group.ts +81 -0
  146. package/src/plugin/outbox-push.ts +267 -0
  147. package/src/plugin/outbox-route.ts +181 -0
  148. package/src/plugin/outbox-text-push-flow.ts +90 -0
  149. package/src/plugin/runtime-diagnostics-assembler.ts +183 -0
  150. package/src/plugin/runtime-diagnostics-helpers.ts +302 -0
  151. package/src/plugin/runtime-diagnostics-payload-builders.ts +171 -0
  152. package/src/plugin/runtime-diagnostics-snapshot.ts +31 -0
  153. package/src/plugin/setup.ts +33 -6
  154. package/src/plugin/state-store.ts +249 -0
  155. package/src/plugin/state-transient-runtime-group.ts +105 -0
  156. package/src/plugin/status-runtime.ts +251 -0
  157. package/src/plugin/status.ts +33 -7
  158. package/src/plugin/target-runtime.ts +141 -0
  159. package/src/plugin/target-status-runtime-group.ts +130 -0
  160. package/src/plugin/transient-state-runtime.ts +82 -0
  161. package/src/runtime/outbound-ack-timeout.ts +5 -3
  162. package/src/runtime/outbound-flags.ts +24 -8
  163. package/src/runtime/status-snapshots.ts +36 -7
  164. package/src/runtime/status-worker.ts +34 -4
@@ -0,0 +1,187 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ const pluginPackageName = '@xmoxmo/bncr';
6
+ const sdkCoreSpecifier = 'openclaw/plugin-sdk/core';
7
+ const linkType = process.platform === 'win32' ? 'junction' : 'dir';
8
+
9
+ export function resolveBncrPluginRoot(filePath: string) {
10
+ let current =
11
+ fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()
12
+ ? filePath
13
+ : path.dirname(filePath);
14
+ while (true) {
15
+ const pkgPath = path.join(current, 'package.json');
16
+ if (fs.existsSync(pkgPath)) {
17
+ try {
18
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')) as { name?: string };
19
+ if (pkg.name === pluginPackageName) return current;
20
+ } catch {
21
+ // Keep walking; package metadata is diagnostic-only for root resolution.
22
+ }
23
+ }
24
+ if (fs.existsSync(path.join(current, 'openclaw.plugin.json'))) return current;
25
+ const parent = path.dirname(current);
26
+ if (parent === current) return path.dirname(filePath);
27
+ current = parent;
28
+ }
29
+ }
30
+
31
+ function tryExec(command: string, args: string[]) {
32
+ try {
33
+ return execFileSync(command, args, {
34
+ encoding: 'utf8',
35
+ stdio: ['ignore', 'pipe', 'ignore'],
36
+ }).trim();
37
+ } catch {
38
+ return '';
39
+ }
40
+ }
41
+
42
+ function readOpenClawPackageName(pkgPath: string) {
43
+ try {
44
+ const raw = fs.readFileSync(pkgPath, 'utf8');
45
+ const parsed = JSON.parse(raw);
46
+ return typeof parsed?.name === 'string' ? parsed.name : '';
47
+ } catch {
48
+ return '';
49
+ }
50
+ }
51
+
52
+ function unique(items: string[]) {
53
+ const seen = new Set<string>();
54
+ const out: string[] = [];
55
+ for (const item of items) {
56
+ if (!item) continue;
57
+ const normalized = path.normalize(item);
58
+ if (seen.has(normalized)) continue;
59
+ seen.add(normalized);
60
+ out.push(normalized);
61
+ }
62
+ return out;
63
+ }
64
+
65
+ function findOpenClawPackageRoot(startPath: string) {
66
+ let current = startPath;
67
+ try {
68
+ current = fs.realpathSync(startPath);
69
+ } catch {
70
+ // keep original path when realpath fails
71
+ }
72
+
73
+ let cursor = current;
74
+ while (true) {
75
+ const statPath = fs.existsSync(cursor) ? cursor : path.dirname(cursor);
76
+ const pkgPath = path.join(statPath, 'package.json');
77
+ if (fs.existsSync(pkgPath) && readOpenClawPackageName(pkgPath) === 'openclaw') {
78
+ return statPath;
79
+ }
80
+ const parent = path.dirname(statPath);
81
+ if (parent === statPath) break;
82
+ cursor = parent;
83
+ }
84
+ return '';
85
+ }
86
+
87
+ function collectOpenClawCandidates(pluginDir: string) {
88
+ const directCandidates = [
89
+ path.join(pluginDir, 'node_modules', 'openclaw'),
90
+ path.join('/usr/lib/node_modules', 'openclaw'),
91
+ path.join('/usr/local/lib/node_modules', 'openclaw'),
92
+ path.join('/opt/homebrew/lib/node_modules', 'openclaw'),
93
+ path.join(process.env.HOME || '', '.npm-global/lib/node_modules', 'openclaw'),
94
+ ];
95
+
96
+ const npmRoot = tryExec('npm', ['root', '-g']);
97
+ if (npmRoot) directCandidates.push(path.join(npmRoot, 'openclaw'));
98
+
99
+ const nodePathEntries = (process.env.NODE_PATH || '')
100
+ .split(path.delimiter)
101
+ .map((entry) => entry.trim())
102
+ .filter(Boolean);
103
+ for (const entry of nodePathEntries) {
104
+ directCandidates.push(path.join(entry, 'openclaw'));
105
+ }
106
+
107
+ const openclawBin = tryExec('which', ['openclaw']);
108
+ if (openclawBin) {
109
+ directCandidates.push(openclawBin);
110
+ directCandidates.push(path.dirname(openclawBin));
111
+ }
112
+
113
+ const packageRoots = unique(
114
+ directCandidates.map((candidate) => findOpenClawPackageRoot(candidate)).filter(Boolean),
115
+ );
116
+
117
+ return packageRoots.filter((candidate) => {
118
+ const pkgJson = path.join(candidate, 'package.json');
119
+ return fs.existsSync(pkgJson) && readOpenClawPackageName(pkgJson) === 'openclaw';
120
+ });
121
+ }
122
+
123
+ function canResolveSdkCore(pluginRequire: NodeRequire) {
124
+ try {
125
+ pluginRequire.resolve(sdkCoreSpecifier);
126
+ return true;
127
+ } catch {
128
+ return false;
129
+ }
130
+ }
131
+
132
+ function ensurePluginNodeModulesLink(pluginDir: string, targetRoot: string) {
133
+ const nodeModulesDir = path.join(pluginDir, 'node_modules');
134
+ const linkPath = path.join(nodeModulesDir, 'openclaw');
135
+ fs.mkdirSync(nodeModulesDir, { recursive: true });
136
+
137
+ try {
138
+ const stat = fs.lstatSync(linkPath);
139
+ if (stat.isSymbolicLink()) {
140
+ const existingTarget = fs.realpathSync(linkPath);
141
+ const normalizedExisting = path.normalize(existingTarget);
142
+ const normalizedTarget = path.normalize(fs.realpathSync(targetRoot));
143
+ if (normalizedExisting === normalizedTarget) return;
144
+ fs.unlinkSync(linkPath);
145
+ } else {
146
+ return;
147
+ }
148
+ } catch {
149
+ // missing link is fine
150
+ }
151
+
152
+ fs.symlinkSync(targetRoot, linkPath, linkType as fs.symlink.Type);
153
+ }
154
+
155
+ export function resolveBncrRuntimeSourceDir(pluginDir: string) {
156
+ const direct = path.join(pluginDir, 'src');
157
+ if (fs.existsSync(path.join(direct, 'channel.ts'))) return direct;
158
+
159
+ const parent = path.join(pluginDir, '..', 'src');
160
+ if (fs.existsSync(path.join(parent, 'channel.ts'))) return parent;
161
+
162
+ return direct;
163
+ }
164
+
165
+ export function ensureBncrOpenClawSdkResolution(pluginDir: string, pluginRequire: NodeRequire) {
166
+ if (canResolveSdkCore(pluginRequire)) return;
167
+
168
+ let lastError = '';
169
+ const candidates = collectOpenClawCandidates(pluginDir);
170
+ for (const candidate of candidates) {
171
+ try {
172
+ ensurePluginNodeModulesLink(pluginDir, candidate);
173
+ if (canResolveSdkCore(pluginRequire)) return;
174
+ } catch (error) {
175
+ lastError = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
176
+ }
177
+ }
178
+
179
+ const suffix = candidates.length
180
+ ? ` Tried candidates: ${candidates.join(', ')}.`
181
+ : ' No openclaw package root candidates were found from npm root, NODE_PATH, common global paths, or the openclaw binary path.';
182
+ const extra = lastError ? ` Last repair error: ${lastError}.` : '';
183
+ throw new Error(
184
+ `bncr failed to resolve ${sdkCoreSpecifier} from ${pluginDir}.${suffix}${extra} ` +
185
+ `You can repair manually with: mkdir -p ${path.join(pluginDir, 'node_modules')} && ln -s "$(npm root -g)/openclaw" ${path.join(pluginDir, 'node_modules', 'openclaw')}`,
186
+ );
187
+ }
@@ -0,0 +1,54 @@
1
+ import fs from 'node:fs';
2
+ import { createRequire } from 'node:module';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import {
6
+ ensureBncrOpenClawSdkResolution,
7
+ resolveBncrPluginRoot,
8
+ resolveBncrRuntimeSourceDir,
9
+ } from './runtime-discovery.ts';
10
+
11
+ export type ChannelModule = typeof import('../channel.ts');
12
+
13
+ export type LoadedRuntime = {
14
+ createBncrBridge: ChannelModule['createBncrBridge'];
15
+ createBncrChannelPlugin: ChannelModule['createBncrChannelPlugin'];
16
+ };
17
+
18
+ export const pluginFile = fileURLToPath(new URL('../../index.ts', import.meta.url));
19
+ export const pluginDir = path.dirname(pluginFile);
20
+ export const pluginRequire = createRequire(new URL('../../index.ts', import.meta.url));
21
+ export const pluginRoot = resolveBncrPluginRoot(pluginFile);
22
+
23
+ const runtimeSourceDir = resolveBncrRuntimeSourceDir(pluginDir);
24
+ let runtime: LoadedRuntime | null = null;
25
+
26
+ export const readPluginVersion = (rootDir = pluginRoot) => {
27
+ try {
28
+ const raw = fs.readFileSync(path.join(rootDir, 'package.json'), 'utf8');
29
+ const parsed = JSON.parse(raw);
30
+ return typeof parsed?.version === 'string' ? parsed.version : 'unknown';
31
+ } catch {
32
+ return 'unknown';
33
+ }
34
+ };
35
+
36
+ export const pluginVersion = readPluginVersion();
37
+
38
+ export const loadBncrRuntimeSync = (): LoadedRuntime => {
39
+ if (runtime) return runtime;
40
+ ensureBncrOpenClawSdkResolution(pluginDir, pluginRequire as NodeRequire);
41
+ try {
42
+ const mod = pluginRequire(path.join(runtimeSourceDir, 'channel.ts')) as ChannelModule;
43
+ runtime = {
44
+ createBncrBridge: mod.createBncrBridge,
45
+ createBncrChannelPlugin: mod.createBncrChannelPlugin,
46
+ };
47
+ return runtime;
48
+ } catch (error) {
49
+ const detail = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
50
+ throw new Error(
51
+ `bncr failed to load channel runtime after dependency bootstrap from ${runtimeSourceDir}: ${detail}`,
52
+ );
53
+ }
54
+ };