@alfe.ai/gateway 0.0.21 → 0.0.23

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 (2) hide show
  1. package/dist/health.js +256 -111
  2. package/package.json +3 -3
package/dist/health.js CHANGED
@@ -20,6 +20,7 @@ import url from "url";
20
20
  import http2 from "http2";
21
21
  import zlib from "zlib";
22
22
  import { EventEmitter } from "events";
23
+ import { pathToFileURL } from "node:url";
23
24
  import { randomUUID } from "node:crypto";
24
25
  //#region \0rolldown/runtime.js
25
26
  var __create = Object.create;
@@ -365,6 +366,15 @@ var AuthService = class {
365
366
  getReferralHistory() {
366
367
  return this.client.request(`${this.prefix}/referral/history`);
367
368
  }
369
+ getOnboardingStatus() {
370
+ return this.client.request(`${this.prefix}/onboarding/status`);
371
+ }
372
+ completeOnboarding(input) {
373
+ return this.client.request(`${this.prefix}/onboarding/complete`, {
374
+ method: "POST",
375
+ body: JSON.stringify(input)
376
+ });
377
+ }
368
378
  };
369
379
  //#endregion
370
380
  //#region ../../packages-internal/api-client/dist/services/integrations.js
@@ -3705,7 +3715,7 @@ function isIPCResponse(msg) {
3705
3715
  const PROTOCOL_VERSION = 1;
3706
3716
  //#endregion
3707
3717
  //#region src/reconciliation.ts
3708
- const log$1 = logger$1.child({ component: "Reconciliation" });
3718
+ const log$2 = logger$1.child({ component: "Reconciliation" });
3709
3719
  var ReconciliationEngine = class {
3710
3720
  constructor(manager) {
3711
3721
  this.manager = manager;
@@ -3726,7 +3736,7 @@ var ReconciliationEngine = class {
3726
3736
  try {
3727
3737
  localIntegrations = await this.manager.getInstalledIntegrations();
3728
3738
  } catch (err) {
3729
- log$1.error({ err }, "Failed to get local integrations");
3739
+ log$2.error({ err }, "Failed to get local integrations");
3730
3740
  localIntegrations = [];
3731
3741
  }
3732
3742
  const localMap = new Map(localIntegrations.map((i) => [i.id, i]));
@@ -3740,10 +3750,10 @@ var ReconciliationEngine = class {
3740
3750
  const id = desired.integrationId;
3741
3751
  try {
3742
3752
  if (!local) {
3743
- log$1.info(`Installing ${id}@${desired.version}`);
3753
+ log$2.info(`Installing ${id}@${desired.version}`);
3744
3754
  await this.manager.install(id, desired.version, desired.config);
3745
3755
  report.installed.push(id);
3746
- log$1.info(`Activating ${id}`);
3756
+ log$2.info(`Activating ${id}`);
3747
3757
  await this.manager.activate(id);
3748
3758
  report.activated.push(id);
3749
3759
  report.results.push({
@@ -3754,14 +3764,14 @@ var ReconciliationEngine = class {
3754
3764
  return;
3755
3765
  }
3756
3766
  if (local.version !== desired.version && desired.version !== "" && local.version !== "unknown") {
3757
- log$1.info(`Upgrading ${id}: ${local.version} → ${desired.version}`);
3767
+ log$2.info(`Upgrading ${id}: ${local.version} → ${desired.version}`);
3758
3768
  try {
3759
3769
  await this.manager.deactivate(id);
3760
3770
  await this.manager.uninstall(id);
3761
3771
  } catch {}
3762
3772
  await this.manager.install(id, desired.version, desired.config);
3763
3773
  report.installed.push(id);
3764
- log$1.info(`Activating ${id}`);
3774
+ log$2.info(`Activating ${id}`);
3765
3775
  await this.manager.activate(id);
3766
3776
  report.activated.push(id);
3767
3777
  report.results.push({
@@ -3772,7 +3782,7 @@ var ReconciliationEngine = class {
3772
3782
  return;
3773
3783
  }
3774
3784
  if (local.status !== "active") {
3775
- log$1.info(`Activating ${id}`);
3785
+ log$2.info(`Activating ${id}`);
3776
3786
  await this.manager.activate(id);
3777
3787
  report.activated.push(id);
3778
3788
  report.results.push({
@@ -3789,7 +3799,7 @@ var ReconciliationEngine = class {
3789
3799
  });
3790
3800
  } catch (err) {
3791
3801
  const message = err instanceof Error ? err.message : String(err);
3792
- log$1.error({ err }, `Error reconciling ${id}`);
3802
+ log$2.error({ err }, `Error reconciling ${id}`);
3793
3803
  report.errors.push({
3794
3804
  integrationId: id,
3795
3805
  error: message
@@ -3812,7 +3822,7 @@ var ReconciliationEngine = class {
3812
3822
  return;
3813
3823
  }
3814
3824
  try {
3815
- log$1.info(`Removing ${id}`);
3825
+ log$2.info(`Removing ${id}`);
3816
3826
  if (local.status === "active") {
3817
3827
  await this.manager.deactivate(id);
3818
3828
  report.deactivated.push(id);
@@ -3826,7 +3836,7 @@ var ReconciliationEngine = class {
3826
3836
  });
3827
3837
  } catch (err) {
3828
3838
  const message = err instanceof Error ? err.message : String(err);
3829
- log$1.error({ err }, `Error removing ${id}`);
3839
+ log$2.error({ err }, `Error removing ${id}`);
3830
3840
  report.errors.push({
3831
3841
  integrationId: id,
3832
3842
  error: message
@@ -3861,6 +3871,7 @@ var CloudClient = class {
3861
3871
  onCommand = null;
3862
3872
  onConnectionChange = null;
3863
3873
  onPluginsChanged = null;
3874
+ onReconciliationComplete = null;
3864
3875
  reconciliationEngine = null;
3865
3876
  constructor(config) {
3866
3877
  this.config = config;
@@ -3890,6 +3901,12 @@ var CloudClient = class {
3890
3901
  setPluginsChangedHandler(handler) {
3891
3902
  this.onPluginsChanged = handler;
3892
3903
  }
3904
+ /**
3905
+ * Set a callback for when reconciliation completes — used to rebuild command registry.
3906
+ */
3907
+ setOnReconciliationComplete(handler) {
3908
+ this.onReconciliationComplete = handler;
3909
+ }
3893
3910
  setIntegrationManager(manager) {
3894
3911
  this.reconciliationEngine = new ReconciliationEngine(manager);
3895
3912
  }
@@ -3922,6 +3939,13 @@ var CloudClient = class {
3922
3939
  logger$1.debug("Cloud client stopped");
3923
3940
  }
3924
3941
  /**
3942
+ * Send a typed message to the cloud gateway.
3943
+ * Silently drops if WebSocket is not open.
3944
+ */
3945
+ sendMessage(msg) {
3946
+ this.send(msg);
3947
+ }
3948
+ /**
3925
3949
  * Get connection latency (time since last pong).
3926
3950
  * Returns -1 if no pong received yet.
3927
3951
  */
@@ -4083,6 +4107,7 @@ var CloudClient = class {
4083
4107
  const reportMsg = createReconciliationReport(report.results);
4084
4108
  this.send(reportMsg);
4085
4109
  if ((report.installed.length > 0 || report.uninstalled.length > 0) && this.onPluginsChanged) this.onPluginsChanged();
4110
+ this.onReconciliationComplete?.();
4086
4111
  } catch (err) {
4087
4112
  const message = err instanceof Error ? err.message : String(err);
4088
4113
  logger$1.error({ err: message }, "Cloud: reconciliation failed");
@@ -19743,7 +19768,7 @@ function createLogger(component, additionalData) {
19743
19768
  * Spawns the runtime binary, pipes stdout/stderr to the daemon logger,
19744
19769
  * and restarts on crash with exponential backoff.
19745
19770
  */
19746
- const log = createLogger("RuntimeProcess");
19771
+ const log$1 = createLogger("RuntimeProcess");
19747
19772
  const BACKOFF_INITIAL_MS = 1e3;
19748
19773
  const BACKOFF_MAX_MS = 3e4;
19749
19774
  const STABLE_UPTIME_MS = 6e4;
@@ -19779,7 +19804,7 @@ var RuntimeProcess = class {
19779
19804
  if (this.stopped) return;
19780
19805
  const { command, args } = this.resolveCommand();
19781
19806
  this.lastStartTime = Date.now();
19782
- log.info({
19807
+ log$1.info({
19783
19808
  runtime: this.options.runtime,
19784
19809
  command,
19785
19810
  args,
@@ -19798,14 +19823,14 @@ var RuntimeProcess = class {
19798
19823
  });
19799
19824
  this.child.stdout?.on("data", (data) => {
19800
19825
  const lines = data.toString().trim().split("\n");
19801
- for (const line of lines) log.info({
19826
+ for (const line of lines) log$1.info({
19802
19827
  runtime: this.options.runtime,
19803
19828
  stream: "stdout"
19804
19829
  }, line);
19805
19830
  });
19806
19831
  this.child.stderr?.on("data", (data) => {
19807
19832
  const lines = data.toString().trim().split("\n");
19808
- for (const line of lines) log.warn({
19833
+ for (const line of lines) log$1.warn({
19809
19834
  runtime: this.options.runtime,
19810
19835
  stream: "stderr"
19811
19836
  }, line);
@@ -19813,14 +19838,14 @@ var RuntimeProcess = class {
19813
19838
  this.child.on("exit", (code, signal) => {
19814
19839
  this.child = null;
19815
19840
  if (this.stopped) {
19816
- log.info({
19841
+ log$1.info({
19817
19842
  runtime: this.options.runtime,
19818
19843
  code,
19819
19844
  signal
19820
19845
  }, "Runtime stopped (expected)");
19821
19846
  return;
19822
19847
  }
19823
- log.warn({
19848
+ log$1.warn({
19824
19849
  runtime: this.options.runtime,
19825
19850
  code,
19826
19851
  signal,
@@ -19834,7 +19859,7 @@ var RuntimeProcess = class {
19834
19859
  this.backoffMs = Math.min(this.backoffMs * 2, BACKOFF_MAX_MS);
19835
19860
  });
19836
19861
  this.child.on("error", (err) => {
19837
- log.error({
19862
+ log$1.error({
19838
19863
  runtime: this.options.runtime,
19839
19864
  err: err.message
19840
19865
  }, "Runtime process error");
@@ -19853,7 +19878,7 @@ var RuntimeProcess = class {
19853
19878
  if (!child) return;
19854
19879
  return new Promise((resolve) => {
19855
19880
  const killTimer = setTimeout(() => {
19856
- log.warn({ runtime: this.options.runtime }, "Runtime did not exit in time — sending SIGKILL");
19881
+ log$1.warn({ runtime: this.options.runtime }, "Runtime did not exit in time — sending SIGKILL");
19857
19882
  child.kill("SIGKILL");
19858
19883
  }, 5e3);
19859
19884
  child.on("exit", () => {
@@ -19867,7 +19892,7 @@ var RuntimeProcess = class {
19867
19892
  * Restart the runtime process (stop then start with fresh backoff).
19868
19893
  */
19869
19894
  async restart() {
19870
- log.info({ runtime: this.options.runtime }, "Restarting runtime...");
19895
+ log$1.info({ runtime: this.options.runtime }, "Restarting runtime...");
19871
19896
  await this.stop();
19872
19897
  this.stopped = false;
19873
19898
  this.backoffMs = BACKOFF_INITIAL_MS;
@@ -19881,6 +19906,154 @@ var RuntimeProcess = class {
19881
19906
  }
19882
19907
  };
19883
19908
  //#endregion
19909
+ //#region src/command-registry.ts
19910
+ /**
19911
+ * Command Registry — maps integration command names to local handler files.
19912
+ *
19913
+ * After reconciliation installs/activates integrations, the daemon rebuilds
19914
+ * this registry from active integration manifests. Handler files are loaded
19915
+ * via ESM dynamic import on first use and cached until the registry is cleared.
19916
+ */
19917
+ const log = createLogger("CommandRegistry");
19918
+ var CommandRegistry = class {
19919
+ commands = /* @__PURE__ */ new Map();
19920
+ version = 0;
19921
+ /**
19922
+ * Register a command from an integration.
19923
+ * Rejects duplicate command names — first registration wins.
19924
+ */
19925
+ register(integrationId, name, handlerPath, method = "handle", timeoutMs = 3e4) {
19926
+ const existing = this.commands.get(name);
19927
+ if (existing) {
19928
+ log.warn({
19929
+ command: name,
19930
+ existing: existing.integrationId,
19931
+ attempted: integrationId
19932
+ }, "Command name collision — ignoring duplicate registration");
19933
+ return;
19934
+ }
19935
+ if (!existsSync(handlerPath)) {
19936
+ log.warn({
19937
+ command: name,
19938
+ handlerPath,
19939
+ integrationId
19940
+ }, "Handler file does not exist — skipping registration");
19941
+ return;
19942
+ }
19943
+ this.commands.set(name, {
19944
+ commandName: name,
19945
+ integrationId,
19946
+ handlerPath,
19947
+ handlerMethod: method,
19948
+ timeoutMs,
19949
+ handler: null
19950
+ });
19951
+ log.info({
19952
+ command: name,
19953
+ integrationId,
19954
+ handlerPath,
19955
+ method,
19956
+ timeoutMs
19957
+ }, "Registered command");
19958
+ }
19959
+ /**
19960
+ * Unregister all commands owned by an integration.
19961
+ */
19962
+ unregisterAll(integrationId) {
19963
+ for (const [name, entry] of this.commands) if (entry.integrationId === integrationId) {
19964
+ this.commands.delete(name);
19965
+ log.info({
19966
+ command: name,
19967
+ integrationId
19968
+ }, "Unregistered command");
19969
+ }
19970
+ }
19971
+ /**
19972
+ * Check if a command is registered.
19973
+ */
19974
+ has(name) {
19975
+ return this.commands.has(name);
19976
+ }
19977
+ /**
19978
+ * Execute a registered command handler.
19979
+ * Lazily imports the handler module on first call, caches it.
19980
+ * Wraps execution in Promise.race with the command's timeout.
19981
+ */
19982
+ async execute(name, payload, context) {
19983
+ const entry = this.commands.get(name);
19984
+ if (!entry) return {
19985
+ status: "error",
19986
+ result: {
19987
+ code: "UNKNOWN_COMMAND",
19988
+ message: `Command "${name}" not registered`
19989
+ }
19990
+ };
19991
+ if (!entry.handler) try {
19992
+ const fn = (await import(pathToFileURL(entry.handlerPath).href + "?v=" + String(this.version)))[entry.handlerMethod];
19993
+ if (typeof fn !== "function") return {
19994
+ status: "error",
19995
+ result: {
19996
+ code: "HANDLER_NOT_FOUND",
19997
+ message: `Handler "${entry.handlerMethod}" not found in ${entry.handlerPath}`
19998
+ }
19999
+ };
20000
+ entry.handler = fn;
20001
+ } catch (err) {
20002
+ const message = err instanceof Error ? err.message : String(err);
20003
+ log.error({
20004
+ err: message,
20005
+ command: name,
20006
+ handlerPath: entry.handlerPath
20007
+ }, "Failed to import handler");
20008
+ return {
20009
+ status: "error",
20010
+ result: {
20011
+ code: "IMPORT_FAILED",
20012
+ message
20013
+ }
20014
+ };
20015
+ }
20016
+ try {
20017
+ return await Promise.race([entry.handler(payload, context), new Promise((_, reject) => {
20018
+ setTimeout(() => {
20019
+ reject(/* @__PURE__ */ new Error(`Command "${name}" timed out after ${String(entry.timeoutMs)}ms`));
20020
+ }, entry.timeoutMs);
20021
+ })]);
20022
+ } catch (err) {
20023
+ const message = err instanceof Error ? err.message : String(err);
20024
+ log.error({
20025
+ err: message,
20026
+ command: name
20027
+ }, "Command execution failed");
20028
+ return {
20029
+ status: "error",
20030
+ result: {
20031
+ code: "EXECUTION_FAILED",
20032
+ message
20033
+ }
20034
+ };
20035
+ }
20036
+ }
20037
+ /**
20038
+ * List all registered commands (for COMMANDS_AVAILABLE message).
20039
+ */
20040
+ listCommands() {
20041
+ return Array.from(this.commands.values()).map((e) => ({
20042
+ name: e.commandName,
20043
+ integrationId: e.integrationId,
20044
+ timeoutMs: e.timeoutMs
20045
+ }));
20046
+ }
20047
+ /**
20048
+ * Clear all entries and increment version (busts ESM import cache).
20049
+ */
20050
+ clear() {
20051
+ this.commands.clear();
20052
+ this.version++;
20053
+ log.info({ version: this.version }, "Command registry cleared");
20054
+ }
20055
+ };
20056
+ //#endregion
19884
20057
  //#region src/daemon.ts
19885
20058
  /**
19886
20059
  * Alfe Gateway Daemon — main entry point.
@@ -19908,6 +20081,7 @@ let aiProxyUrl = null;
19908
20081
  let aiProxyRunning = false;
19909
20082
  let cloudConnected = false;
19910
20083
  let shuttingDown = false;
20084
+ let commandRegistry;
19911
20085
  let resolvedCliVersion;
19912
20086
  /**
19913
20087
  * Resolve the installed @alfe.ai/cli version.
@@ -19984,6 +20158,7 @@ async function startDaemon() {
19984
20158
  logger$1.debug("Initializing command queue...");
19985
20159
  commandQueue = new CommandQueue();
19986
20160
  commandQueue.startGC();
20161
+ commandRegistry = new CommandRegistry();
19987
20162
  logger$1.debug("Starting AI proxy...");
19988
20163
  try {
19989
20164
  const { createProxyServer, DEFAULT_AI_PROXY_PORT } = await import("@alfe.ai/ai-proxy-local");
@@ -20079,6 +20254,21 @@ async function startDaemon() {
20079
20254
  });
20080
20255
  }
20081
20256
  });
20257
+ cloudClient.setOnReconciliationComplete(() => {
20258
+ try {
20259
+ const activeCommands = integrationManager.getActiveCommands();
20260
+ commandRegistry.clear();
20261
+ for (const { integrationId, commands } of activeCommands) for (const cmd of commands) commandRegistry.register(integrationId, cmd.name, cmd.resolvedPath, cmd.method, cmd.timeoutMs);
20262
+ const commandsMsg = {
20263
+ type: "COMMANDS_AVAILABLE",
20264
+ commands: commandRegistry.listCommands()
20265
+ };
20266
+ cloudClient.sendMessage(commandsMsg);
20267
+ logger$1.info({ commandCount: commandsMsg.commands.length }, "Reported available commands to cloud");
20268
+ } catch (err) {
20269
+ logger$1.error({ err: err instanceof Error ? err.message : String(err) }, "Failed to rebuild command registry");
20270
+ }
20271
+ });
20082
20272
  cloudClient.start();
20083
20273
  logger$1.debug("Cloud client started");
20084
20274
  if (config.autoStartRuntime && config.runtime) {
@@ -20146,98 +20336,6 @@ async function startDaemon() {
20146
20336
  }, "Alfe Gateway Daemon started ✅");
20147
20337
  }
20148
20338
  async function handleCloudCommand(command) {
20149
- if (command.command === "support.diagnostic") {
20150
- const payload = command.payload;
20151
- if (!payload.apiKey && !aiProxyRunning) return {
20152
- type: "COMMAND_ACK",
20153
- commandId: command.commandId,
20154
- status: "error",
20155
- result: {
20156
- code: "PROXY_NOT_RUNNING",
20157
- message: "AI proxy is not running — diagnostic requires LLM access"
20158
- }
20159
- };
20160
- let proxyUrl;
20161
- if (aiProxyRunning) proxyUrl = aiProxyUrl ?? void 0;
20162
- else {
20163
- const { getAiServiceUrlFromToken } = await import("@alfe.ai/config");
20164
- proxyUrl = getAiServiceUrlFromToken(config.apiKey);
20165
- }
20166
- try {
20167
- const { runDiagnostic } = await import("@alfe.ai/doctor");
20168
- const workspacePath = Object.values(config.runtimes)[0]?.workspace ?? "~/.openclaw";
20169
- const report = await runDiagnostic({
20170
- task: payload.task,
20171
- workspacePath,
20172
- timeoutSeconds: 300,
20173
- proxyUrl,
20174
- apiKey: payload.apiKey
20175
- });
20176
- return {
20177
- type: "COMMAND_ACK",
20178
- commandId: command.commandId,
20179
- status: report.success ? "ok" : "error",
20180
- result: report
20181
- };
20182
- } catch (err) {
20183
- const message = err instanceof Error ? err.message : String(err);
20184
- logger$1.error({ err: message }, "Diagnostic failed");
20185
- return {
20186
- type: "COMMAND_ACK",
20187
- commandId: command.commandId,
20188
- status: "error",
20189
- result: {
20190
- code: "DIAGNOSTIC_FAILED",
20191
- message
20192
- }
20193
- };
20194
- }
20195
- }
20196
- if (command.command === "support.bash") {
20197
- const payload = command.payload;
20198
- if (!payload.cmd) return {
20199
- type: "COMMAND_ACK",
20200
- commandId: command.commandId,
20201
- status: "error",
20202
- result: {
20203
- code: "MISSING_CMD",
20204
- message: "No command provided"
20205
- }
20206
- };
20207
- const workspacePath = Object.values(config.runtimes)[0]?.workspace ?? "~/.openclaw";
20208
- try {
20209
- const { exec } = await import("child_process");
20210
- const { promisify } = await import("util");
20211
- const { stdout, stderr } = await promisify(exec)(payload.cmd, {
20212
- cwd: workspacePath,
20213
- timeout: 25e3,
20214
- maxBuffer: 512 * 1024
20215
- });
20216
- return {
20217
- type: "COMMAND_ACK",
20218
- commandId: command.commandId,
20219
- status: "ok",
20220
- result: {
20221
- stdout: stdout.trim(),
20222
- stderr: stderr.trim()
20223
- }
20224
- };
20225
- } catch (err) {
20226
- const execErr = err;
20227
- return {
20228
- type: "COMMAND_ACK",
20229
- commandId: command.commandId,
20230
- status: "error",
20231
- result: {
20232
- code: "EXEC_FAILED",
20233
- stdout: execErr.stdout?.trim() ?? "",
20234
- stderr: execErr.stderr?.trim() ?? "",
20235
- message: execErr.message ?? String(err),
20236
- exitCode: execErr.code
20237
- }
20238
- };
20239
- }
20240
- }
20241
20339
  if (command.command === "daemon.update") {
20242
20340
  const version = command.payload?.version ?? "latest";
20243
20341
  setTimeout(() => {
@@ -20298,6 +20396,31 @@ async function handleCloudCommand(command) {
20298
20396
  };
20299
20397
  }
20300
20398
  }
20399
+ if (commandRegistry.has(command.command)) try {
20400
+ const ctx = buildCommandContext();
20401
+ const result = await commandRegistry.execute(command.command, typeof command.payload === "object" && command.payload !== null ? command.payload : {}, ctx);
20402
+ return {
20403
+ type: "COMMAND_ACK",
20404
+ commandId: command.commandId,
20405
+ status: result.status,
20406
+ result: result.result
20407
+ };
20408
+ } catch (err) {
20409
+ const message = err instanceof Error ? err.message : String(err);
20410
+ logger$1.error({
20411
+ err: message,
20412
+ command: command.command
20413
+ }, "Command registry execution failed");
20414
+ return {
20415
+ type: "COMMAND_ACK",
20416
+ commandId: command.commandId,
20417
+ status: "error",
20418
+ result: {
20419
+ code: "REGISTRY_ERROR",
20420
+ message
20421
+ }
20422
+ };
20423
+ }
20301
20424
  const ipcRequest = cloudCommandToIPCRequest(command);
20302
20425
  if (!ipcRequest) {
20303
20426
  logger$1.warn({ command: command.command }, "Unrecognized cloud command");
@@ -20354,6 +20477,28 @@ async function handleCloudCommand(command) {
20354
20477
  };
20355
20478
  }
20356
20479
  }
20480
+ function buildCommandContext() {
20481
+ const workspacePath = Object.values(config.runtimes)[0]?.workspace ?? "~/.openclaw";
20482
+ return {
20483
+ workspacePath,
20484
+ aiProxyUrl: aiProxyUrl ?? void 0,
20485
+ aiProxyRunning,
20486
+ apiKey: config.apiKey,
20487
+ async exec(cmd, opts) {
20488
+ const { exec: execCb } = await import("child_process");
20489
+ const { promisify } = await import("util");
20490
+ const { stdout, stderr } = await promisify(execCb)(cmd, {
20491
+ cwd: workspacePath,
20492
+ timeout: opts?.timeoutMs ?? 25e3,
20493
+ maxBuffer: opts?.maxBuffer ?? 512 * 1024
20494
+ });
20495
+ return {
20496
+ stdout: stdout.trim(),
20497
+ stderr: stderr.trim()
20498
+ };
20499
+ }
20500
+ };
20501
+ }
20357
20502
  function handlePluginRequest(method, params, pluginId) {
20358
20503
  switch (method) {
20359
20504
  case "status": return Promise.resolve(handleStatus());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfe.ai/gateway",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "description": "Alfe local gateway daemon — persistent control plane for agent integrations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -24,8 +24,8 @@
24
24
  "ws": "^8.18.0",
25
25
  "@alfe.ai/ai-proxy-local": "^0.0.5",
26
26
  "@alfe.ai/config": "^0.0.5",
27
- "@alfe.ai/doctor": "^0.0.6",
28
- "@alfe.ai/integrations": "^0.0.13"
27
+ "@alfe.ai/integration-manifest": "^0.0.6",
28
+ "@alfe.ai/integrations": "^0.0.15"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/ws": "^8.5.13",