@alfe.ai/gateway 0.9.19 → 0.10.0
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/health.js +50 -5
- package/package.json +2 -2
package/dist/health.js
CHANGED
|
@@ -5662,16 +5662,20 @@ const MAX_IPC_MESSAGE_BYTES = 1024 * 1024;
|
|
|
5662
5662
|
* Map a cloud command name to an IPC method name.
|
|
5663
5663
|
* Cloud commands use dot-notation matching IPC methods.
|
|
5664
5664
|
*
|
|
5665
|
-
*
|
|
5666
|
-
*
|
|
5665
|
+
* Work reads are dispatched by executeWorkCommand so they select a capable
|
|
5666
|
+
* OpenClaw plugin and fail immediately instead of joining an offline queue.
|
|
5667
5667
|
*/
|
|
5668
|
-
const CLOUD_COMMAND_TO_IPC = {
|
|
5668
|
+
const CLOUD_COMMAND_TO_IPC = {
|
|
5669
|
+
"work.snapshot": "work.snapshot",
|
|
5670
|
+
"work.job_runs": "work.job_runs",
|
|
5671
|
+
"work.actions": "work.actions"
|
|
5672
|
+
};
|
|
5669
5673
|
/**
|
|
5670
5674
|
* Translate a cloud COMMAND into a local IPC request.
|
|
5671
5675
|
* Returns null if the command isn't recognized.
|
|
5672
5676
|
*/
|
|
5673
5677
|
function cloudCommandToIPCRequest(command) {
|
|
5674
|
-
const method = CLOUD_COMMAND_TO_IPC[command.command];
|
|
5678
|
+
const method = Object.hasOwn(CLOUD_COMMAND_TO_IPC, command.command) ? CLOUD_COMMAND_TO_IPC[command.command] : void 0;
|
|
5675
5679
|
if (!method) return null;
|
|
5676
5680
|
return {
|
|
5677
5681
|
type: "req",
|
|
@@ -6997,6 +7001,42 @@ var CommandQueue = class {
|
|
|
6997
7001
|
}
|
|
6998
7002
|
};
|
|
6999
7003
|
//#endregion
|
|
7004
|
+
//#region src/work-commands.ts
|
|
7005
|
+
const WORK_COMMANDS = [
|
|
7006
|
+
"work.snapshot",
|
|
7007
|
+
"work.job_runs",
|
|
7008
|
+
"work.actions"
|
|
7009
|
+
];
|
|
7010
|
+
function isWorkCommand(command) {
|
|
7011
|
+
return WORK_COMMANDS.includes(command);
|
|
7012
|
+
}
|
|
7013
|
+
const MAX_WORK_RESPONSE_BYTES = 768 * 1024;
|
|
7014
|
+
/** Read requests never enter an offline queue or choose an arbitrary connected plugin. */
|
|
7015
|
+
async function executeWorkCommand(command, agentId, runtime, ipc) {
|
|
7016
|
+
const error = (code, message) => ({
|
|
7017
|
+
type: "COMMAND_ACK",
|
|
7018
|
+
commandId: command.commandId,
|
|
7019
|
+
status: "error",
|
|
7020
|
+
result: {
|
|
7021
|
+
code,
|
|
7022
|
+
message
|
|
7023
|
+
}
|
|
7024
|
+
});
|
|
7025
|
+
if (!isWorkCommand(command.command)) return error("UNKNOWN_COMMAND", "Unsupported work command");
|
|
7026
|
+
if (command.agentId !== agentId) return error("AGENT_MISMATCH", "Work request targets a different agent");
|
|
7027
|
+
if (runtime !== "openclaw") return error("UNSUPPORTED_RUNTIME", "Work visibility is available for OpenClaw agents");
|
|
7028
|
+
if (!command.payload || typeof command.payload !== "object" || Array.isArray(command.payload)) return error("INVALID_PARAMS", "Work parameters must be an object");
|
|
7029
|
+
const plugin = ipc?.getRegisteredPlugins().find(([, info]) => info.name === "@alfe.ai/openclaw" && info.capabilities.includes("work.read"));
|
|
7030
|
+
if (!ipc || !plugin) return error("WORK_UNAVAILABLE", "The runtime work bridge is unavailable; update the agent if needed");
|
|
7031
|
+
try {
|
|
7032
|
+
const response = await ipc.sendRequest(plugin[0], command.command, command.payload, 6e3);
|
|
7033
|
+
if (Buffer.byteLength(JSON.stringify(response), "utf8") > MAX_WORK_RESPONSE_BYTES) return error("RESPONSE_TOO_LARGE", "Runtime work data exceeds the response limit");
|
|
7034
|
+
return ipcResponseToCloudAck(command.commandId, response);
|
|
7035
|
+
} catch {
|
|
7036
|
+
return error("WORK_UNAVAILABLE", "The runtime work bridge did not respond");
|
|
7037
|
+
}
|
|
7038
|
+
}
|
|
7039
|
+
//#endregion
|
|
7000
7040
|
//#region src/process-manager.ts
|
|
7001
7041
|
/**
|
|
7002
7042
|
* Process management — launchd/systemd service installation.
|
|
@@ -9211,6 +9251,10 @@ let cloudConnected = false;
|
|
|
9211
9251
|
* so a duplicate is ACKed with the prior result without re-executing.
|
|
9212
9252
|
*/
|
|
9213
9253
|
const commandDedupe = new CommandDedupe();
|
|
9254
|
+
const workCommandDedupe = new CommandDedupe({
|
|
9255
|
+
maxEntries: 4,
|
|
9256
|
+
ttlMs: 5e3
|
|
9257
|
+
});
|
|
9214
9258
|
let shuttingDown = false;
|
|
9215
9259
|
let commandRegistry;
|
|
9216
9260
|
let resolvedCliVersion;
|
|
@@ -9553,7 +9597,7 @@ async function startDaemon() {
|
|
|
9553
9597
|
* bounce the box a second time.
|
|
9554
9598
|
*/
|
|
9555
9599
|
async function handleCloudCommand(command) {
|
|
9556
|
-
const { ack, duplicate } = await commandDedupe.run(command.commandId, () => executeCloudCommand(command));
|
|
9600
|
+
const { ack, duplicate } = await (isWorkCommand(command.command) ? workCommandDedupe : commandDedupe).run(command.commandId, () => executeCloudCommand(command));
|
|
9557
9601
|
if (duplicate) {
|
|
9558
9602
|
logger.info({
|
|
9559
9603
|
commandId: command.commandId,
|
|
@@ -9606,6 +9650,7 @@ async function drainRuntimeBeforeExit(reason) {
|
|
|
9606
9650
|
}, "Runtime still mid-turn at drain grace deadline — proceeding with daemon exit");
|
|
9607
9651
|
}
|
|
9608
9652
|
async function executeCloudCommand(command) {
|
|
9653
|
+
if (isWorkCommand(command.command)) return executeWorkCommand(command, config.agentId, config.runtime, ipcServer);
|
|
9609
9654
|
if (command.command === "daemon.update") {
|
|
9610
9655
|
const version = command.payload?.version ?? "latest";
|
|
9611
9656
|
setTimeout(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfe.ai/gateway",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Alfe local gateway daemon — persistent control plane for agent integrations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"pino-roll": "^1.2.0",
|
|
24
24
|
"smol-toml": ">=1.6.1",
|
|
25
25
|
"ws": "^8.18.0",
|
|
26
|
-
"@alfe.ai/agent-api-client": "^0.19.
|
|
26
|
+
"@alfe.ai/agent-api-client": "^0.19.2",
|
|
27
27
|
"@alfe.ai/ai-proxy-local": "^0.0.17",
|
|
28
28
|
"@alfe.ai/config": "^0.4.1",
|
|
29
29
|
"@alfe.ai/integration-manifest": "^0.4.2",
|