oomi-ai 0.2.23 → 0.2.24

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/bin/oomi-ai.js CHANGED
@@ -1931,11 +1931,11 @@ async function runBridgePreflight({ brokerWs, gatewayUrl, gatewayConfigPath }) {
1931
1931
  await assertTcpReachable(parsedGatewayUrl.toString());
1932
1932
  }
1933
1933
 
1934
- function buildBridgeDetachArgs(rawFlags = {}) {
1935
- const orderedKeys = [
1936
- 'broker-http',
1937
- 'broker-ws',
1938
- 'pair-code',
1934
+ function buildBridgeDetachArgs(rawFlags = {}) {
1935
+ const orderedKeys = [
1936
+ 'broker-http',
1937
+ 'broker-ws',
1938
+ 'pair-code',
1939
1939
  'app-url',
1940
1940
  'device-id',
1941
1941
  'device-token',
@@ -1953,9 +1953,13 @@ function buildBridgeDetachArgs(rawFlags = {}) {
1953
1953
  if (!text) continue;
1954
1954
  args.push(`--${key}`, text);
1955
1955
  }
1956
-
1957
- return args;
1958
- }
1956
+
1957
+ return args;
1958
+ }
1959
+
1960
+ function isServiceManagedBridgeStart(flags = {}) {
1961
+ return isTruthyFlag(flags['service-managed']);
1962
+ }
1959
1963
 
1960
1964
  function startBridgeDetachedProcess(rawFlags = {}) {
1961
1965
  const existing = findRunningBridgeProcess();
@@ -2126,17 +2130,17 @@ function runLaunchctl(args, { allowFailure = false } = {}) {
2126
2130
  return { status, stdout, stderr };
2127
2131
  }
2128
2132
 
2129
- function buildBridgeLaunchAgentPlist() {
2130
- const scriptPath = (() => {
2131
- try {
2132
- return fs.realpathSync(process.argv[1]);
2133
- } catch {
2134
- return process.argv[1];
2135
- }
2136
- })();
2137
- const programArgs = [process.execPath, scriptPath, 'openclaw', 'bridge', 'start'];
2138
- const bridgeLogPath = resolveBridgeLiveLogPath();
2139
- const argsXml = programArgs.map((arg) => `<string>${xmlEscape(arg)}</string>`).join('\n ');
2133
+ function buildBridgeLaunchAgentPlist() {
2134
+ const scriptPath = (() => {
2135
+ try {
2136
+ return fs.realpathSync(process.argv[1]);
2137
+ } catch {
2138
+ return process.argv[1];
2139
+ }
2140
+ })();
2141
+ const programArgs = [process.execPath, scriptPath, 'openclaw', 'bridge', 'start', '--service-managed'];
2142
+ const bridgeLogPath = resolveBridgeLiveLogPath();
2143
+ const argsXml = programArgs.map((arg) => `<string>${xmlEscape(arg)}</string>`).join('\n ');
2140
2144
 
2141
2145
  return `<?xml version="1.0" encoding="UTF-8"?>
2142
2146
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@@ -2192,17 +2196,18 @@ function readBridgeLaunchdStatus() {
2192
2196
  };
2193
2197
  }
2194
2198
 
2195
- function startBridgeLaunchdService() {
2196
- assertMacOSLaunchdAvailable();
2197
- const plistPath = resolveBridgeLaunchAgentPlistPath();
2198
- if (!fs.existsSync(plistPath)) {
2199
- throw new Error('Bridge service is not installed. Run: oomi openclaw bridge service install');
2200
- }
2201
- const domain = launchctlDomain();
2202
- const target = launchctlServiceTarget();
2203
- runLaunchctl(['bootout', domain, plistPath], { allowFailure: true });
2204
- runLaunchctl(['bootstrap', domain, plistPath]);
2205
- runLaunchctl(['enable', target], { allowFailure: true });
2199
+ function startBridgeLaunchdService() {
2200
+ assertMacOSLaunchdAvailable();
2201
+ const plistPath = resolveBridgeLaunchAgentPlistPath();
2202
+ if (!fs.existsSync(plistPath)) {
2203
+ throw new Error('Bridge service is not installed. Run: oomi openclaw bridge service install');
2204
+ }
2205
+ writeFile(plistPath, buildBridgeLaunchAgentPlist());
2206
+ const domain = launchctlDomain();
2207
+ const target = launchctlServiceTarget();
2208
+ runLaunchctl(['bootout', domain, plistPath], { allowFailure: true });
2209
+ runLaunchctl(['bootstrap', domain, plistPath]);
2210
+ runLaunchctl(['enable', target], { allowFailure: true });
2206
2211
  runLaunchctl(['kickstart', '-k', target], { allowFailure: true });
2207
2212
  }
2208
2213
 
@@ -3976,12 +3981,17 @@ async function handleBridgeServiceCommand(actionRaw = '', flags = {}) {
3976
3981
  );
3977
3982
  }
3978
3983
 
3979
- async function startBridgeLifecycle(flags = {}) {
3980
- if (Boolean(flags.detach)) {
3981
- const detachedFlags = { ...flags };
3982
- delete detachedFlags.detach;
3983
- const result = startBridgeDetachedProcess(detachedFlags);
3984
- if (result.alreadyRunning) {
3984
+ async function startBridgeLifecycle(flags = {}) {
3985
+ const serviceManaged = isServiceManagedBridgeStart(flags);
3986
+ if (serviceManaged && Boolean(flags.detach)) {
3987
+ throw new Error('Detached bridge mode cannot be combined with --service-managed.');
3988
+ }
3989
+
3990
+ if (Boolean(flags.detach)) {
3991
+ const detachedFlags = { ...flags };
3992
+ delete detachedFlags.detach;
3993
+ const result = startBridgeDetachedProcess(detachedFlags);
3994
+ if (result.alreadyRunning) {
3985
3995
  incrementBridgeMetric('duplicate_start_attempt_count');
3986
3996
  console.log(`Bridge already running (pid: ${result.pid}).`);
3987
3997
  return;
@@ -3990,19 +4000,30 @@ async function startBridgeLifecycle(flags = {}) {
3990
4000
  console.log(`Bridge started in background (pid: ${result.pid}).`);
3991
4001
  return;
3992
4002
  }
3993
-
3994
- const running = findRunningBridgeProcess();
3995
- if (running) {
3996
- incrementBridgeMetric('duplicate_start_attempt_count');
3997
- console.log(
3998
- `Bridge already running (pid ${running.pid})${running.deviceId ? ` for device ${running.deviceId}` : ''}.`
3999
- );
4000
- return;
4001
- }
4002
-
4003
- incrementBridgeMetric('bridge_start_count');
4004
- await startOpenclawBridge(flags);
4005
- }
4003
+
4004
+ const running = findRunningBridgeProcess();
4005
+ if (running) {
4006
+ if (!serviceManaged) {
4007
+ incrementBridgeMetric('duplicate_start_attempt_count');
4008
+ console.log(
4009
+ `Bridge already running (pid ${running.pid})${running.deviceId ? ` for device ${running.deviceId}` : ''}.`
4010
+ );
4011
+ return;
4012
+ }
4013
+
4014
+ incrementBridgeMetric('bridge_restart_count');
4015
+ console.log(
4016
+ `Service-managed bridge start detected existing bridge (pid ${running.pid})${running.deviceId ? ` for device ${running.deviceId}` : ''}; reclaiming ownership.`
4017
+ );
4018
+ const result = await stopBridgeProcesses();
4019
+ if (Array.isArray(result.stillAlive) && result.stillAlive.length > 0) {
4020
+ throw new Error(`Failed to stop bridge processes: ${result.stillAlive.join(', ')}`);
4021
+ }
4022
+ }
4023
+
4024
+ incrementBridgeMetric('bridge_start_count');
4025
+ await startOpenclawBridge(flags);
4026
+ }
4006
4027
 
4007
4028
  async function handleBridgeLifecycleCommand(flags = {}, actionRaw = '') {
4008
4029
  const action = String(actionRaw || 'start').trim().toLowerCase();
@@ -4237,16 +4258,18 @@ if (__isDirectExecution) {
4237
4258
  export {
4238
4259
  prepareGatewayFrameForLocalGateway,
4239
4260
  ensureVoiceAssistantSpokenMetadata,
4261
+ buildBridgeLaunchAgentPlist,
4240
4262
  classifyBridgeFailure,
4241
4263
  classifyBridgeSessionScope,
4242
4264
  createBridgeProcessFaultHandler,
4243
- computeReconnectDelayMs,
4244
- resolveBridgeStatusForBrokerOpen,
4245
- resolveBridgeStatusForRuntimeFault,
4246
- runBridgeCallbackSafely,
4247
- extractGatewayRequestMeta,
4248
- extractGatewayResponseMeta,
4249
- isGatewayRunStartedFrame,
4250
- isBridgeWorkerCommand,
4251
- parsePositiveInteger,
4252
- };
4265
+ computeReconnectDelayMs,
4266
+ resolveBridgeStatusForBrokerOpen,
4267
+ resolveBridgeStatusForRuntimeFault,
4268
+ runBridgeCallbackSafely,
4269
+ extractGatewayRequestMeta,
4270
+ extractGatewayResponseMeta,
4271
+ isServiceManagedBridgeStart,
4272
+ isGatewayRunStartedFrame,
4273
+ isBridgeWorkerCommand,
4274
+ parsePositiveInteger,
4275
+ };
@@ -2,7 +2,7 @@
2
2
  "id": "oomi-ai",
3
3
  "name": "Oomi Channel Plugin",
4
4
  "description": "Managed Oomi channel integration for OpenClaw.",
5
- "version": "0.2.23",
5
+ "version": "0.2.24",
6
6
  "author": "Oomi",
7
7
  "license": "MIT",
8
8
  "openclawVersion": ">=0.5.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oomi-ai",
3
- "version": "0.2.23",
3
+ "version": "0.2.24",
4
4
  "description": "Oomi OpenClaw channel plugin and bridge tooling",
5
5
  "bin": {
6
6
  "oomi": "bin/oomi-ai.js"