@openclaw-cloud/agent-controller 3.0.0-beta.2 → 3.0.0-beta.21
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/agent-controller.js +5 -9
- package/dist/api.d.ts +16 -0
- package/dist/api.js.map +1 -1
- package/dist/commands/agent-update-cli.js +23 -38
- package/dist/commands/agent-update-cli.js.map +1 -1
- package/dist/commands/backup-cli.js +6 -4
- package/dist/commands/backup-cli.js.map +1 -1
- package/dist/commands/bootstrap.d.ts +10 -1
- package/dist/commands/bootstrap.js +33 -73
- package/dist/commands/bootstrap.js.map +1 -1
- package/dist/commands/channel-server.js +4 -3
- package/dist/commands/channel-server.js.map +1 -1
- package/dist/commands/heartbeat-cli.js +2 -6
- package/dist/commands/heartbeat-cli.js.map +1 -1
- package/dist/commands/install-deps.d.ts +10 -0
- package/dist/commands/install-deps.js +33 -43
- package/dist/commands/install-deps.js.map +1 -1
- package/dist/commands/knowledge-sync-cli.js +6 -4
- package/dist/commands/knowledge-sync-cli.js.map +1 -1
- package/dist/commands/plugin-update-cli.js +4 -8
- package/dist/commands/plugin-update-cli.js.map +1 -1
- package/dist/commands/self-update.d.ts +1 -0
- package/dist/commands/self-update.js +76 -37
- package/dist/commands/self-update.js.map +1 -1
- package/dist/commands/update-skills.js +7 -6
- package/dist/commands/update-skills.js.map +1 -1
- package/dist/config-file.d.ts +24 -0
- package/dist/config-file.js +59 -20
- package/dist/config-file.js.map +1 -1
- package/dist/config.d.ts +10 -0
- package/dist/config.js +28 -0
- package/dist/config.js.map +1 -1
- package/dist/connection.d.ts +4 -0
- package/dist/connection.js +50 -5
- package/dist/connection.js.map +1 -1
- package/dist/handlers/agent-update.d.ts +4 -0
- package/dist/handlers/agent-update.js +16 -44
- package/dist/handlers/agent-update.js.map +1 -1
- package/dist/handlers/deploy.d.ts +1 -2
- package/dist/handlers/deploy.js +4 -20
- package/dist/handlers/deploy.js.map +1 -1
- package/dist/handlers/diagnostics.js +0 -12
- package/dist/handlers/diagnostics.js.map +1 -1
- package/dist/handlers/file-delete.js +4 -5
- package/dist/handlers/file-delete.js.map +1 -1
- package/dist/handlers/file-write.js +4 -4
- package/dist/handlers/file-write.js.map +1 -1
- package/dist/handlers/knowledge-sync.js +2 -14
- package/dist/handlers/knowledge-sync.js.map +1 -1
- package/dist/handlers/memory.d.ts +11 -1
- package/dist/handlers/memory.js.map +1 -1
- package/dist/handlers/onboarding.d.ts +1 -2
- package/dist/handlers/onboarding.js +3 -20
- package/dist/handlers/onboarding.js.map +1 -1
- package/dist/handlers/package-install.js +1 -1
- package/dist/handlers/package-install.js.map +1 -1
- package/dist/handlers/pair.js +0 -12
- package/dist/handlers/pair.js.map +1 -1
- package/dist/handlers/restart.d.ts +1 -2
- package/dist/handlers/restart.js +3 -8
- package/dist/handlers/restart.js.map +1 -1
- package/dist/handlers/slack-event.d.ts +13 -0
- package/dist/handlers/slack-event.js +40 -0
- package/dist/handlers/slack-event.js.map +1 -0
- package/dist/handlers/stop.js +0 -7
- package/dist/handlers/stop.js.map +1 -1
- package/dist/handlers/telegram-webhook.js +3 -22
- package/dist/handlers/telegram-webhook.js.map +1 -1
- package/dist/handlers/update-config.js +4 -13
- package/dist/handlers/update-config.js.map +1 -1
- package/dist/heartbeat.d.ts +7 -1
- package/dist/heartbeat.js +35 -6
- package/dist/heartbeat.js.map +1 -1
- package/dist/index.d.ts +0 -8
- package/dist/index.js +96 -119
- package/dist/index.js.map +1 -1
- package/dist/lockfile.js +2 -1
- package/dist/lockfile.js.map +1 -1
- package/dist/mock-board-worker.d.ts +31 -0
- package/dist/mock-board-worker.js +125 -0
- package/dist/mock-board-worker.js.map +1 -0
- package/dist/platform/linux.js +6 -5
- package/dist/platform/linux.js.map +1 -1
- package/dist/platform/macos.js +3 -2
- package/dist/platform/macos.js.map +1 -1
- package/dist/platform/windows.js +3 -2
- package/dist/platform/windows.js.map +1 -1
- package/dist/providers/claude-code/channel-server.js +2 -1
- package/dist/providers/claude-code/channel-server.js.map +1 -1
- package/dist/providers/claude-code/settings-writer.d.ts +3 -2
- package/dist/providers/claude-code/settings-writer.js +6 -15
- package/dist/providers/claude-code/settings-writer.js.map +1 -1
- package/dist/providers/index.d.ts +13 -0
- package/dist/providers/index.js +25 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/openclaw/gateway-adapter.js +2 -0
- package/dist/providers/openclaw/gateway-adapter.js.map +1 -1
- package/dist/providers/openclaw/gateway-client.js +6 -1
- package/dist/providers/openclaw/gateway-client.js.map +1 -1
- package/dist/providers/openclaw/index.js +34 -13
- package/dist/providers/openclaw/index.js.map +1 -1
- package/dist/slack-relay-server.d.ts +48 -0
- package/dist/slack-relay-server.js +197 -0
- package/dist/slack-relay-server.js.map +1 -0
- package/dist/types.d.ts +16 -1
- package/dist/utils/anthropic-auth.d.ts +14 -0
- package/dist/utils/anthropic-auth.js +24 -0
- package/dist/utils/anthropic-auth.js.map +1 -1
- package/dist/utils/apply-config.d.ts +65 -12
- package/dist/utils/apply-config.js +308 -100
- package/dist/utils/apply-config.js.map +1 -1
- package/dist/utils/claude-env.d.ts +6 -0
- package/dist/utils/claude-env.js +29 -28
- package/dist/utils/claude-env.js.map +1 -1
- package/dist/utils/config-merge-paths.d.ts +15 -1
- package/dist/utils/config-merge-paths.js +17 -3
- package/dist/utils/config-merge-paths.js.map +1 -1
- package/dist/utils/deploy-type.d.ts +16 -0
- package/dist/utils/deploy-type.js +34 -0
- package/dist/utils/deploy-type.js.map +1 -0
- package/dist/utils/env.d.ts +0 -1
- package/dist/utils/env.js +0 -8
- package/dist/utils/env.js.map +1 -1
- package/dist/utils/exec.d.ts +11 -0
- package/dist/utils/exec.js +47 -1
- package/dist/utils/exec.js.map +1 -1
- package/dist/utils/gateway-restart-handler.d.ts +6 -2
- package/dist/utils/gateway-restart-handler.js +11 -2
- package/dist/utils/gateway-restart-handler.js.map +1 -1
- package/dist/utils/gateway-restart.d.ts +7 -0
- package/dist/utils/gateway-restart.js +12 -4
- package/dist/utils/gateway-restart.js.map +1 -1
- package/dist/utils/knowledge-graph.d.ts +13 -1
- package/dist/utils/knowledge-graph.js +75 -29
- package/dist/utils/knowledge-graph.js.map +1 -1
- package/dist/utils/legacy-mcp-servers.d.ts +12 -0
- package/dist/utils/legacy-mcp-servers.js +37 -0
- package/dist/utils/legacy-mcp-servers.js.map +1 -0
- package/dist/utils/log-collector.js +2 -1
- package/dist/utils/log-collector.js.map +1 -1
- package/dist/utils/openclaw-ops.d.ts +45 -3
- package/dist/utils/openclaw-ops.js +94 -15
- package/dist/utils/openclaw-ops.js.map +1 -1
- package/dist/utils/openclaw-stack-update.d.ts +31 -0
- package/dist/utils/openclaw-stack-update.js +50 -0
- package/dist/utils/openclaw-stack-update.js.map +1 -0
- package/dist/utils/package-install.js +4 -12
- package/dist/utils/package-install.js.map +1 -1
- package/dist/utils/package-version.d.ts +10 -0
- package/dist/utils/package-version.js +18 -0
- package/dist/utils/package-version.js.map +1 -0
- package/dist/utils/parse-id-at-version.d.ts +15 -0
- package/dist/utils/parse-id-at-version.js +22 -0
- package/dist/utils/parse-id-at-version.js.map +1 -0
- package/dist/utils/plugin-reconcile.d.ts +46 -0
- package/dist/utils/plugin-reconcile.js +201 -0
- package/dist/utils/plugin-reconcile.js.map +1 -0
- package/dist/utils/response.js +1 -0
- package/dist/utils/response.js.map +1 -1
- package/dist/utils/write-home-files.d.ts +27 -0
- package/dist/utils/write-home-files.js +72 -0
- package/dist/utils/write-home-files.js.map +1 -0
- package/dist/utils/write-workspace-files.d.ts +1 -1
- package/dist/utils/write-workspace-files.js +19 -7
- package/dist/utils/write-workspace-files.js.map +1 -1
- package/dist/workspace.d.ts +11 -0
- package/dist/workspace.js +20 -0
- package/dist/workspace.js.map +1 -1
- package/package.json +9 -4
package/dist/index.js
CHANGED
|
@@ -1,43 +1,39 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { dirname, join } from 'node:path';
|
|
4
|
-
import fs from 'node:fs';
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
5
3
|
import { createConnection, logCollector } from './connection.js';
|
|
6
4
|
import { startHeartbeat } from './heartbeat.js';
|
|
7
5
|
import { createAgentApi } from './api.js';
|
|
8
|
-
import { configureProvider,
|
|
6
|
+
import { configureProvider, createProviderFromConfig, getProvider } from './providers/index.js';
|
|
9
7
|
import { ClaudeCodeProvider } from './providers/claude-code/index.js';
|
|
10
8
|
import { registerClaudeReplyPublisher } from './handlers/chat.js';
|
|
11
9
|
import { DEBUG } from './debug.js';
|
|
12
10
|
import { getBackendUrl } from './utils/env.js';
|
|
13
11
|
import { config, requireConfig } from './config.js';
|
|
14
12
|
import { createLockFile } from './lockfile.js';
|
|
15
|
-
import {
|
|
13
|
+
import { fetchAndApplyConfig, getOpenclawJsonPath, writeOpenclawJson, } from './utils/apply-config.js';
|
|
14
|
+
import { migrateLegacyMcpServers } from './utils/legacy-mcp-servers.js';
|
|
15
|
+
import { reconcilePlugins } from './utils/plugin-reconcile.js';
|
|
16
16
|
import { KnowledgeGraphManager } from './utils/knowledge-graph.js';
|
|
17
17
|
import { startMemoryMcpServer } from './memory-mcp-server.js';
|
|
18
|
+
import { startSlackRelayServer } from './slack-relay-server.js';
|
|
19
|
+
import { startMockBoardWorker } from './mock-board-worker.js';
|
|
18
20
|
import { wireMemoryDeltaLogging } from './handlers/memory.js';
|
|
19
21
|
import { toErrorMessage } from './utils/response.js';
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
/** On startup, fetch latest config from bootstrap API and apply.
|
|
23
|
-
*
|
|
24
|
-
* - vm / k8s → full `applyBootstrapConfig` (writes openclaw.json,
|
|
25
|
-
* auth-profiles.json, ~/.claude/settings.json, .env, restarts gateway).
|
|
26
|
-
* - standalone / undefined → `applyMergeableConfig` does a SCOPED merge of
|
|
27
|
-
* allowlisted safe-additive sections (mcpServers, tools.media.*, etc.)
|
|
28
|
-
* into the user's existing openclaw.json. Local values always win on
|
|
29
|
-
* conflict, and auth-profiles.json / .env / gateway are left untouched.
|
|
30
|
-
*/
|
|
22
|
+
import { getPackageVersion } from './utils/package-version.js';
|
|
23
|
+
const CONTROLLER_VERSION = getPackageVersion();
|
|
31
24
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
25
|
+
* Startup config refresh — OFF unless `AC_RUN_BOOTSTRAP=1` is set explicitly.
|
|
26
|
+
*
|
|
27
|
+
* Bootstrap runs automatically only at agent *setup* time: the k8s first-boot
|
|
28
|
+
* entrypoint marker and the VM user-data both invoke the `agent-controller
|
|
29
|
+
* bootstrap` CLI once. Runtime reconfiguration arrives over the WS
|
|
30
|
+
* `update_config` command. Startup therefore never auto-bootstraps — the
|
|
31
|
+
* previous managed-deploy auto-branch here was dead in production (nothing set
|
|
32
|
+
* `AGENT_DEPLOY_TYPE`) and only ever fired on machines we do not own.
|
|
35
33
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* standalone (e.g. when the user runs `agent-controller bootstrap`
|
|
40
|
-
* intentionally).
|
|
34
|
+
* When it does run, `fetchAndApplyConfig` picks the apply mode from the
|
|
35
|
+
* bootstrap payload's `deploymentType` (env `AGENT_DEPLOY_TYPE` as fallback):
|
|
36
|
+
* managed 'vm'/'k8s' get the full apply, everything else the scoped merge.
|
|
41
37
|
*/
|
|
42
38
|
async function refreshConfigFromBootstrap() {
|
|
43
39
|
const backendUrl = config.backendUrl;
|
|
@@ -45,69 +41,32 @@ async function refreshConfigFromBootstrap() {
|
|
|
45
41
|
const agentId = config.agentId;
|
|
46
42
|
if (!backendUrl || !agentToken || !agentId)
|
|
47
43
|
return;
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (!managedDeploy && !explicitOptIn) {
|
|
52
|
-
console.log(`[startup] Skipping bootstrap (deployType=${deployType ?? 'standalone'}). ` +
|
|
53
|
-
`Set AC_RUN_BOOTSTRAP=1 to opt in.`);
|
|
44
|
+
const optIn = !!process.env.AC_RUN_BOOTSTRAP && process.env.AC_RUN_BOOTSTRAP !== '0';
|
|
45
|
+
if (!optIn) {
|
|
46
|
+
console.log('[startup] Skipping bootstrap. Set AC_RUN_BOOTSTRAP=1 to opt in.');
|
|
54
47
|
return;
|
|
55
48
|
}
|
|
56
49
|
try {
|
|
57
50
|
const api = createAgentApi(backendUrl, agentToken);
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
else {
|
|
64
|
-
await applyMergeableConfig(data);
|
|
65
|
-
console.log(`[startup] Scoped merge of mergeable config sections applied (deployType=${deployType ?? 'standalone'}, AC_RUN_BOOTSTRAP=1); local config preserved on conflict`);
|
|
66
|
-
}
|
|
51
|
+
const { managed } = await fetchAndApplyConfig(api, agentId);
|
|
52
|
+
console.log(managed
|
|
53
|
+
? '[startup] Config refreshed from bootstrap API (managed install — full apply)'
|
|
54
|
+
: '[startup] Scoped merge of mergeable config sections applied (third-party install); ' +
|
|
55
|
+
'local config preserved on conflict');
|
|
67
56
|
}
|
|
68
57
|
catch (err) {
|
|
69
|
-
console.error('[startup] Failed to refresh config from bootstrap:', err
|
|
58
|
+
console.error('[startup] Failed to refresh config from bootstrap:', toErrorMessage(err));
|
|
70
59
|
}
|
|
71
60
|
}
|
|
72
|
-
/**
|
|
73
|
-
* Lift any legacy flat `mcpServers` at the root of openclaw.json into the
|
|
74
|
-
* canonical `mcp.servers` location. The OpenClaw CLI switched to strict
|
|
75
|
-
* schema validation that rejects the unknown top-level `mcpServers` key, so
|
|
76
|
-
* leaving it behind crashes the gateway on startup. Mutates `fileConfig`
|
|
77
|
-
* in place; returns true if anything changed.
|
|
78
|
-
*/
|
|
79
|
-
export function migrateLegacyMcpServers(fileConfig) {
|
|
80
|
-
const flat = fileConfig.mcpServers;
|
|
81
|
-
if (!flat || typeof flat !== 'object' || Array.isArray(flat))
|
|
82
|
-
return false;
|
|
83
|
-
const mcp = (fileConfig.mcp && typeof fileConfig.mcp === 'object' && !Array.isArray(fileConfig.mcp)
|
|
84
|
-
? fileConfig.mcp
|
|
85
|
-
: {});
|
|
86
|
-
const nested = (mcp.servers && typeof mcp.servers === 'object' && !Array.isArray(mcp.servers) ? mcp.servers : {});
|
|
87
|
-
for (const [name, value] of Object.entries(flat)) {
|
|
88
|
-
if (!(name in nested)) {
|
|
89
|
-
nested[name] = value;
|
|
90
|
-
console.log(`[startup] Migrated legacy mcpServers.${name} → mcp.servers.${name}`);
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
console.warn(`[startup] Migration skip: mcp.servers.${name} already exists, dropping legacy flat entry`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
mcp.servers = nested;
|
|
97
|
-
fileConfig.mcp = mcp;
|
|
98
|
-
delete fileConfig.mcpServers;
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
61
|
/** Inject agent-memory MCP server into openclaw.json so OpenClaw agent can discover it. */
|
|
102
|
-
function injectMemoryMcpConfig() {
|
|
62
|
+
async function injectMemoryMcpConfig() {
|
|
103
63
|
try {
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
if (!fs.existsSync(configPath))
|
|
64
|
+
const raw = await fs.readFile(getOpenclawJsonPath(), 'utf-8').catch(() => null);
|
|
65
|
+
if (raw === null)
|
|
107
66
|
return;
|
|
108
|
-
const fileConfig = JSON.parse(
|
|
67
|
+
const fileConfig = JSON.parse(raw);
|
|
109
68
|
// Clean up pre-rebrand configs before injecting — see migrateLegacyMcpServers.
|
|
110
|
-
migrateLegacyMcpServers(fileConfig);
|
|
69
|
+
migrateLegacyMcpServers(fileConfig, '[startup]');
|
|
111
70
|
const mcp = (fileConfig.mcp && typeof fileConfig.mcp === 'object' && !Array.isArray(fileConfig.mcp)
|
|
112
71
|
? fileConfig.mcp
|
|
113
72
|
: {});
|
|
@@ -120,17 +79,30 @@ function injectMemoryMcpConfig() {
|
|
|
120
79
|
};
|
|
121
80
|
mcp.servers = servers;
|
|
122
81
|
fileConfig.mcp = mcp;
|
|
123
|
-
|
|
82
|
+
await writeOpenclawJson(fileConfig);
|
|
124
83
|
console.log('[startup] Injected agent-memory MCP server into openclaw.json');
|
|
125
84
|
}
|
|
126
85
|
catch (err) {
|
|
127
|
-
console.warn('[startup] Failed to inject memory MCP config:', err
|
|
86
|
+
console.warn('[startup] Failed to inject memory MCP config:', toErrorMessage(err));
|
|
128
87
|
}
|
|
129
88
|
}
|
|
130
89
|
export async function main() {
|
|
131
90
|
createLockFile();
|
|
132
|
-
|
|
91
|
+
// Plugin reconcile runs on EVERY start — that is what makes a reboot or a
|
|
92
|
+
// controller restart self-heal a plugin that never got installed (a whole VM
|
|
93
|
+
// cohort ran for months with `plugins.allow` declaring @openclaw-cloud/
|
|
94
|
+
// mcp-warmup and no package on disk). Chained after the optional config
|
|
95
|
+
// refresh so it reads the freshest openclaw.json, and fire-and-forget: it is
|
|
96
|
+
// cheap when nothing is missing, but an actual install takes minutes and must
|
|
97
|
+
// not hold the agent offline. Nothing here needs to run before the gateway —
|
|
98
|
+
// reconcilePlugins() restarts the gateway itself when it installs something.
|
|
99
|
+
refreshConfigFromBootstrap()
|
|
100
|
+
.catch((err) => {
|
|
133
101
|
console.error('[startup] refreshConfigFromBootstrap failed:', err);
|
|
102
|
+
})
|
|
103
|
+
.then(() => reconcilePlugins('startup'))
|
|
104
|
+
.catch((err) => {
|
|
105
|
+
console.error('[startup] reconcilePlugins failed:', toErrorMessage(err));
|
|
134
106
|
});
|
|
135
107
|
const url = requireConfig('centrifugoUrl');
|
|
136
108
|
const token = requireConfig('agentToken');
|
|
@@ -151,7 +123,7 @@ export async function main() {
|
|
|
151
123
|
await knowledgeGraphManager.init();
|
|
152
124
|
console.log('[memory] KnowledgeGraphManager initialized');
|
|
153
125
|
closeMemoryMcp = await startMemoryMcpServer(knowledgeGraphManager);
|
|
154
|
-
injectMemoryMcpConfig();
|
|
126
|
+
await injectMemoryMcpConfig();
|
|
155
127
|
}
|
|
156
128
|
catch (err) {
|
|
157
129
|
console.error('[memory] Failed to initialize memory:', toErrorMessage(err));
|
|
@@ -162,7 +134,18 @@ export async function main() {
|
|
|
162
134
|
console.error('[memory] Failed to push delta:', toErrorMessage(err));
|
|
163
135
|
});
|
|
164
136
|
});
|
|
165
|
-
|
|
137
|
+
// ---------------------------------------------------------------------------
|
|
138
|
+
// Slack relay — local WS server the in-pod openclaw relay client dials into.
|
|
139
|
+
// The slack_event handler pushes events to whatever client is connected.
|
|
140
|
+
// ---------------------------------------------------------------------------
|
|
141
|
+
let closeSlackRelay = null;
|
|
142
|
+
try {
|
|
143
|
+
closeSlackRelay = startSlackRelayServer().close;
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
console.error('[slack-relay] Failed to start Slack relay server:', toErrorMessage(err));
|
|
147
|
+
}
|
|
148
|
+
const { client, drainCommands, getCentrifugoStatus } = createConnection({
|
|
166
149
|
url,
|
|
167
150
|
token,
|
|
168
151
|
agentId,
|
|
@@ -173,64 +156,58 @@ export async function main() {
|
|
|
173
156
|
});
|
|
174
157
|
// Wire structured delta logs AFTER createConnection() so logCollector is set.
|
|
175
158
|
wireMemoryDeltaLogging(knowledgeGraphManager);
|
|
176
|
-
|
|
159
|
+
let mockBoardWorker = null;
|
|
160
|
+
// Configure agent provider. The openclaw provider is the chat transport, so
|
|
161
|
+
// without a gateway token we leave it unconfigured on purpose — chat commands
|
|
162
|
+
// then fail fast instead of retrying a doomed WS connect. (Gateway *restarts*
|
|
163
|
+
// no longer depend on this: restartGateway() builds its own provider.)
|
|
177
164
|
const providerType = config.agentProvider;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (providerType === 'openclaw') {
|
|
181
|
-
if (gatewayToken) {
|
|
182
|
-
const provider = createProvider('openclaw', { wsUrl: gatewayWsUrl, wsToken: gatewayToken });
|
|
183
|
-
configureProvider(provider);
|
|
184
|
-
console.log('Chat provider configured (lazy connect on first use)');
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
console.warn('OPENCLAW_GATEWAY_TOKEN not set, chat provider disabled');
|
|
188
|
-
}
|
|
165
|
+
if (providerType === 'openclaw' && !config.gatewayToken) {
|
|
166
|
+
console.warn('OPENCLAW_GATEWAY_TOKEN not set, chat provider disabled');
|
|
189
167
|
}
|
|
190
|
-
else
|
|
191
|
-
const provider =
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
console.log('Mock provider configured');
|
|
197
|
-
}
|
|
198
|
-
else if (providerType === 'claude-code') {
|
|
199
|
-
const provider = createProvider('claude-code', {
|
|
200
|
-
workspaceDir: config.claudeWorkspaceDir,
|
|
201
|
-
anthropicApiKey: config.anthropicApiKey,
|
|
202
|
-
anthropicAuthToken: config.anthropicAuthToken,
|
|
203
|
-
claudeCodeOauthToken: config.claudeCodeOauthToken,
|
|
204
|
-
backendUrl,
|
|
205
|
-
agentToken: token,
|
|
206
|
-
});
|
|
168
|
+
else {
|
|
169
|
+
const provider = createProviderFromConfig({ backendUrl, agentToken: token });
|
|
170
|
+
if (!provider) {
|
|
171
|
+
console.error(`Unknown provider type: ${providerType}`);
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
207
174
|
configureProvider(provider);
|
|
208
175
|
// Wire the reply publisher: Claude's async reply tool calls are published
|
|
209
176
|
// to the backend as `chat_response` events so the chat UI receives them.
|
|
210
177
|
if (provider instanceof ClaudeCodeProvider) {
|
|
211
178
|
registerClaudeReplyPublisher(provider, (payload) => api.publishResponse(agentId, payload).catch((err) => {
|
|
212
|
-
console.error('[claude-code] reply publish failed:', err
|
|
179
|
+
console.error('[claude-code] reply publish failed:', toErrorMessage(err));
|
|
213
180
|
}));
|
|
214
181
|
}
|
|
215
|
-
|
|
216
|
-
console.
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
182
|
+
if (providerType === 'openclaw') {
|
|
183
|
+
console.log('Chat provider configured (lazy connect on first use)');
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
provider.connect().catch((err) => {
|
|
187
|
+
console.error(`${providerType} provider connect failed:`, toErrorMessage(err));
|
|
188
|
+
});
|
|
189
|
+
console.log(`${providerType} provider configured`);
|
|
190
|
+
}
|
|
191
|
+
// The mock provider has no gateway to drive board work, so the controller
|
|
192
|
+
// polls take-task itself — that is what lets a local stack run cards end
|
|
193
|
+
// to end without an LLM.
|
|
194
|
+
if (provider.name === 'mock') {
|
|
195
|
+
mockBoardWorker = startMockBoardWorker({ api });
|
|
196
|
+
}
|
|
223
197
|
}
|
|
224
198
|
console.log('Heartbeat via backend API');
|
|
225
199
|
const heartbeatHandle = startHeartbeat({
|
|
226
200
|
api,
|
|
227
201
|
agentId,
|
|
228
202
|
version: CONTROLLER_VERSION,
|
|
203
|
+
getCentrifugoStatus,
|
|
229
204
|
});
|
|
230
205
|
const shutdown = () => {
|
|
231
206
|
console.log('Shutting down...');
|
|
232
207
|
heartbeatHandle.stop();
|
|
208
|
+
mockBoardWorker?.stop();
|
|
233
209
|
closeMemoryMcp?.();
|
|
210
|
+
closeSlackRelay?.();
|
|
234
211
|
getProvider()?.disconnect();
|
|
235
212
|
client.disconnect();
|
|
236
213
|
const drainWithTimeout = Promise.race([
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAE/D,MAAM,kBAAkB,GAAG,iBAAiB,EAAE,CAAC;AAE/C;;;;;;;;;;;;;GAaG;AACH,KAAK,UAAU,0BAA0B;IACvC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IACrC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IACrC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IAC/B,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,IAAI,CAAC,OAAO;QAAE,OAAO;IAEnD,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,GAAG,CAAC;IACrF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;QAC/E,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,cAAc,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACnD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CACT,OAAO;YACL,CAAC,CAAC,8EAA8E;YAChF,CAAC,CAAC,qFAAqF;gBACnF,oCAAoC,CAC3C,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,oDAAoD,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3F,CAAC;AACH,CAAC;AAED,2FAA2F;AAC3F,KAAK,UAAU,qBAAqB;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,EAAE,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAChF,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO;QAEzB,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;QAE9D,+EAA+E;QAC/E,uBAAuB,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAEjD,MAAM,GAAG,GAAG,CACV,UAAU,CAAC,GAAG,IAAI,OAAO,UAAU,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YACpF,CAAC,CAAC,UAAU,CAAC,GAAG;YAChB,CAAC,CAAC,EAAE,CACoB,CAAC;QAC7B,MAAM,OAAO,GAAG,CACd,GAAG,CAAC,OAAO,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;YAC3E,CAAC,CAAC,GAAG,CAAC,OAAO;YACb,CAAC,CAAC,EAAE,CACoB,CAAC;QAE7B,OAAO,CAAC,cAAc,CAAC,GAAG;YACxB,GAAG,EAAE,2BAA2B;YAChC,SAAS,EAAE,iBAAiB;SAC7B,CAAC;QACF,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC;QACtB,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC;QAErB,MAAM,iBAAiB,CAAC,UAAU,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;IAC/E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,+CAA+C,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;IACrF,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,cAAc,EAAE,CAAC;IAEjB,0EAA0E;IAC1E,6EAA6E;IAC7E,wEAAwE;IACxE,wEAAwE;IACxE,6EAA6E;IAC7E,8EAA8E;IAC9E,6EAA6E;IAC7E,6EAA6E;IAC7E,0BAA0B,EAAE;SACzB,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACb,OAAO,CAAC,KAAK,CAAC,8CAA8C,EAAE,GAAG,CAAC,CAAC;IACrE,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;SACvC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACb,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEL,MAAM,GAAG,GAAG,aAAa,CAAC,eAAe,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,IAAI,KAAK;QAAE,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,wCAAwC,OAAO,EAAE,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,gBAAgB,UAAU,aAAa,CAAC,CAAC;IAErD,MAAM,GAAG,GAAG,cAAc,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAE9C,8EAA8E;IAC9E,yEAAyE;IACzE,8EAA8E;IAC9E,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IACjE,MAAM,qBAAqB,GAAG,IAAI,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACnE,IAAI,cAAc,GAAwB,IAAI,CAAC;IAE/C,IAAI,CAAC;QACH,MAAM,qBAAqB,CAAC,IAAI,EAAE,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;QAC1D,cAAc,GAAG,MAAM,oBAAoB,CAAC,qBAAqB,CAAC,CAAC;QACnE,MAAM,qBAAqB,EAAE,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9E,CAAC;IAED,wCAAwC;IACxC,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAkB,EAAE,EAAE;QACvD,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YAChD,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAC9E,6EAA6E;IAC7E,yEAAyE;IACzE,8EAA8E;IAC9E,IAAI,eAAe,GAAwB,IAAI,CAAC;IAChD,IAAI,CAAC;QACH,eAAe,GAAG,qBAAqB,EAAE,CAAC,KAAK,CAAC;IAClD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,mDAAmD,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1F,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,mBAAmB,EAAE,GAAG,gBAAgB,CAAC;QACtE,GAAG;QACH,KAAK;QACL,OAAO;QACP,UAAU;QACV,GAAG;QACH,OAAO,EAAE,kBAAkB;QAC3B,qBAAqB;KACtB,CAAC,CAAC;IAEH,8EAA8E;IAC9E,sBAAsB,CAAC,qBAAqB,CAAC,CAAC;IAE9C,IAAI,eAAe,GAAiC,IAAI,CAAC;IAEzD,4EAA4E;IAC5E,8EAA8E;IAC9E,8EAA8E;IAC9E,uEAAuE;IACvE,MAAM,YAAY,GAAG,MAAM,CAAC,aAAa,CAAC;IAC1C,IAAI,YAAY,KAAK,UAAU,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;IACzE,CAAC;SAAM,CAAC;QACN,MAAM,QAAQ,GAAG,wBAAwB,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7E,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,0BAA0B,YAAY,EAAE,CAAC,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAE5B,0EAA0E;QAC1E,yEAAyE;QACzE,IAAI,QAAQ,YAAY,kBAAkB,EAAE,CAAC;YAC3C,4BAA4B,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CACjD,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBAClD,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5E,CAAC,CAAC,CACH,CAAC;QACJ,CAAC;QAED,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;gBACxC,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,2BAA2B,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;YACjF,CAAC,CAAC,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,GAAG,YAAY,sBAAsB,CAAC,CAAC;QACrD,CAAC;QAED,0EAA0E;QAC1E,yEAAyE;QACzE,yBAAyB;QACzB,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC7B,eAAe,GAAG,oBAAoB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,MAAM,eAAe,GAAG,cAAc,CAAC;QACrC,GAAG;QACH,OAAO;QACP,OAAO,EAAE,kBAAkB;QAC3B,mBAAmB;KACpB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,GAAG,EAAE;QACpB,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAChC,eAAe,CAAC,IAAI,EAAE,CAAC;QACvB,eAAe,EAAE,IAAI,EAAE,CAAC;QACxB,cAAc,EAAE,EAAE,CAAC;QACnB,eAAe,EAAE,EAAE,CAAC;QACpB,WAAW,EAAE,EAAE,UAAU,EAAE,CAAC;QAC5B,MAAM,CAAC,UAAU,EAAE,CAAC;QAEpB,MAAM,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7E,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;SAC1D,CAAC,CAAC;QAEH,gBAAgB;aACb,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;aACf,OAAO,CAAC,GAAG,EAAE;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAClC,CAAC"}
|
package/dist/lockfile.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import os from 'node:os';
|
|
4
|
+
import { toErrorMessage } from './utils/response.js';
|
|
4
5
|
const LOCK_FILE = 'agent-controller.lock';
|
|
5
6
|
function getLockDir() {
|
|
6
7
|
// VM/K8s: /opt/openclaw-cloud/agent-controller
|
|
@@ -22,7 +23,7 @@ export function createLockFile() {
|
|
|
22
23
|
console.log(`[lock] Created lock file: ${getLockPath()}`);
|
|
23
24
|
}
|
|
24
25
|
catch (err) {
|
|
25
|
-
console.error('[lock] Failed to create lock file:', err
|
|
26
|
+
console.error('[lock] Failed to create lock file:', toErrorMessage(err));
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
/** Remove lock file (triggers restart on next heartbeat) */
|
package/dist/lockfile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,MAAM,SAAS,GAAG,uBAAuB,CAAC;AAE1C,SAAS,UAAU;IACjB,+CAA+C;IAC/C,2CAA2C;IAC3C,IAAI,EAAE,CAAC,UAAU,CAAC,sCAAsC,CAAC,EAAE,CAAC;QAC1D,OAAO,sCAAsC,CAAC;IAChD,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,WAAW;IAClB,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,CAAC,CAAC;AAC5C,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,6BAA6B,WAAW,EAAE,EAAE,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,6BAA6B,WAAW,EAAE,EAAE,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,8BAA8B;IAChC,CAAC;AACH,CAAC;AAED,gCAAgC;AAChC,MAAM,UAAU,iBAAiB;IAC/B,OAAO,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACnD,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { AgentApi } from './api.js';
|
|
2
|
+
export interface MockBoardWorkerOptions {
|
|
3
|
+
api: AgentApi;
|
|
4
|
+
}
|
|
5
|
+
export interface MockBoardWorkerHandle {
|
|
6
|
+
stop(): void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Board worker for the `mock` provider — the piece that makes a mock agent
|
|
10
|
+
* process board cards end to end so the platform can be developed locally
|
|
11
|
+
* without an LLM.
|
|
12
|
+
*
|
|
13
|
+
* The loop mirrors what the mcp-warmup plugin does on a real agent:
|
|
14
|
+
*
|
|
15
|
+
* 1. `POST /api/agent/board/take-task` — 204 means no work (idle poll),
|
|
16
|
+
* 200 returns `{ cardId, card }` with the card already CLAIMED by us.
|
|
17
|
+
* 2. Wait `MOCK_TASK_DELAY_MS`. Claiming is what makes the orchestrator
|
|
18
|
+
* create the CardProcessing, dispatch the prompt and block the CP in
|
|
19
|
+
* `waiting_for_mcp_response`; the mock never receives that prompt, it
|
|
20
|
+
* just has to submit after the CP exists.
|
|
21
|
+
* 3. `POST /api/agent/board/cards/{cardId}/submit` — retried on any
|
|
22
|
+
* non-2xx, because a submit landing before the CP is blocked gets a
|
|
23
|
+
* 404 (`no active card_processing`) or 400 (`not waiting for a
|
|
24
|
+
* response`) from the backend.
|
|
25
|
+
* 4. Straight back to take-task, so a burst of waiting cards drains
|
|
26
|
+
* back-to-back instead of one per poll interval.
|
|
27
|
+
*
|
|
28
|
+
* Nothing in here may throw out of the loop: a mock agent that dies on a
|
|
29
|
+
* transient backend blip is worse than one that logs and polls again.
|
|
30
|
+
*/
|
|
31
|
+
export declare function startMockBoardWorker(opts: MockBoardWorkerOptions): MockBoardWorkerHandle;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { config } from './config.js';
|
|
2
|
+
import { toErrorMessage } from './utils/response.js';
|
|
3
|
+
/** Backoff between submit retries while the orchestrator blocks the CardProcessing. */
|
|
4
|
+
const SUBMIT_RETRY_DELAY_MS = 2_000;
|
|
5
|
+
/** Total time a single card's submit may spend retrying before we drop it. */
|
|
6
|
+
const SUBMIT_RETRY_BUDGET_MS = 60_000;
|
|
7
|
+
/**
|
|
8
|
+
* Board worker for the `mock` provider — the piece that makes a mock agent
|
|
9
|
+
* process board cards end to end so the platform can be developed locally
|
|
10
|
+
* without an LLM.
|
|
11
|
+
*
|
|
12
|
+
* The loop mirrors what the mcp-warmup plugin does on a real agent:
|
|
13
|
+
*
|
|
14
|
+
* 1. `POST /api/agent/board/take-task` — 204 means no work (idle poll),
|
|
15
|
+
* 200 returns `{ cardId, card }` with the card already CLAIMED by us.
|
|
16
|
+
* 2. Wait `MOCK_TASK_DELAY_MS`. Claiming is what makes the orchestrator
|
|
17
|
+
* create the CardProcessing, dispatch the prompt and block the CP in
|
|
18
|
+
* `waiting_for_mcp_response`; the mock never receives that prompt, it
|
|
19
|
+
* just has to submit after the CP exists.
|
|
20
|
+
* 3. `POST /api/agent/board/cards/{cardId}/submit` — retried on any
|
|
21
|
+
* non-2xx, because a submit landing before the CP is blocked gets a
|
|
22
|
+
* 404 (`no active card_processing`) or 400 (`not waiting for a
|
|
23
|
+
* response`) from the backend.
|
|
24
|
+
* 4. Straight back to take-task, so a burst of waiting cards drains
|
|
25
|
+
* back-to-back instead of one per poll interval.
|
|
26
|
+
*
|
|
27
|
+
* Nothing in here may throw out of the loop: a mock agent that dies on a
|
|
28
|
+
* transient backend blip is worse than one that logs and polls again.
|
|
29
|
+
*/
|
|
30
|
+
export function startMockBoardWorker(opts) {
|
|
31
|
+
const { api } = opts;
|
|
32
|
+
let stopped = false;
|
|
33
|
+
/** Resolver for the sleep currently in flight, so stop() cuts it short. */
|
|
34
|
+
let wake = null;
|
|
35
|
+
function sleep(ms) {
|
|
36
|
+
return new Promise((resolve) => {
|
|
37
|
+
if (stopped)
|
|
38
|
+
return resolve();
|
|
39
|
+
const timer = setTimeout(() => {
|
|
40
|
+
wake = null;
|
|
41
|
+
resolve();
|
|
42
|
+
}, ms);
|
|
43
|
+
wake = () => {
|
|
44
|
+
clearTimeout(timer);
|
|
45
|
+
wake = null;
|
|
46
|
+
resolve();
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/** Claim the next card. Returns its id, or null for "nothing to do". */
|
|
51
|
+
async function takeTask() {
|
|
52
|
+
try {
|
|
53
|
+
const res = await api.post('/api/agent/board/take-task', {});
|
|
54
|
+
if (res.status === 204)
|
|
55
|
+
return null;
|
|
56
|
+
if (!res.ok) {
|
|
57
|
+
const body = await res.text().catch(() => '');
|
|
58
|
+
console.warn(`[mock-board] take-task failed: HTTP ${res.status} ${body.slice(0, 200)}`);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const data = (await res.json());
|
|
62
|
+
if (!data?.cardId) {
|
|
63
|
+
console.warn('[mock-board] take-task returned 200 without a cardId');
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
return data.cardId;
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
console.warn(`[mock-board] take-task error: ${toErrorMessage(err)}`);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function submit(cardId) {
|
|
74
|
+
const deadline = Date.now() + SUBMIT_RETRY_BUDGET_MS;
|
|
75
|
+
while (!stopped) {
|
|
76
|
+
try {
|
|
77
|
+
const res = await api.post(`/api/agent/board/cards/${cardId}/submit`, {
|
|
78
|
+
text: config.mockTaskText,
|
|
79
|
+
decision: 'approve',
|
|
80
|
+
});
|
|
81
|
+
if (res.ok) {
|
|
82
|
+
console.log(`[mock-board] card ${cardId} submitted`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const body = await res.text().catch(() => '');
|
|
86
|
+
console.warn(`[mock-board] submit ${cardId} failed: HTTP ${res.status} ${body.slice(0, 200)}`);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
console.warn(`[mock-board] submit ${cardId} error: ${toErrorMessage(err)}`);
|
|
90
|
+
}
|
|
91
|
+
if (Date.now() >= deadline) {
|
|
92
|
+
console.warn(`[mock-board] giving up on card ${cardId} after ${SUBMIT_RETRY_BUDGET_MS}ms`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
await sleep(SUBMIT_RETRY_DELAY_MS);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function loop() {
|
|
99
|
+
while (!stopped) {
|
|
100
|
+
const cardId = await takeTask();
|
|
101
|
+
if (stopped)
|
|
102
|
+
return;
|
|
103
|
+
if (!cardId) {
|
|
104
|
+
await sleep(config.mockBoardPollMs);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
await sleep(config.mockTaskDelayMs);
|
|
108
|
+
if (stopped)
|
|
109
|
+
return;
|
|
110
|
+
await submit(cardId);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
console.log(`[mock-board] worker started (poll ${config.mockBoardPollMs}ms)`);
|
|
114
|
+
loop().catch((err) => {
|
|
115
|
+
// Defensive: every await above already swallows its own failures.
|
|
116
|
+
console.error(`[mock-board] loop crashed: ${toErrorMessage(err)}`);
|
|
117
|
+
});
|
|
118
|
+
return {
|
|
119
|
+
stop() {
|
|
120
|
+
stopped = true;
|
|
121
|
+
wake?.();
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=mock-board-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-board-worker.js","sourceRoot":"","sources":["../src/mock-board-worker.ts"],"names":[],"mappings":"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"}
|
package/dist/platform/linux.js
CHANGED
|
@@ -3,6 +3,7 @@ import { homedir, userInfo } from 'node:os';
|
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { execAsync } from '../utils/exec.js';
|
|
5
5
|
import { which } from './common.js';
|
|
6
|
+
import { toErrorMessage } from '../utils/response.js';
|
|
6
7
|
const SYSTEM_SERVICE_PATH = '/etc/systemd/system/agent-controller.service';
|
|
7
8
|
const DBUS_ERROR_PATTERNS = [
|
|
8
9
|
'No medium found',
|
|
@@ -16,7 +17,7 @@ async function isUserSystemdAvailable() {
|
|
|
16
17
|
}
|
|
17
18
|
catch (err) {
|
|
18
19
|
// Node exec error includes message, stderr, and stdout — check all
|
|
19
|
-
const msg =
|
|
20
|
+
const msg = toErrorMessage(err);
|
|
20
21
|
const stderr = err?.stderr ?? '';
|
|
21
22
|
const stdout = err?.stdout ?? '';
|
|
22
23
|
const combined = `${msg}\n${stderr}\n${stdout}`;
|
|
@@ -127,7 +128,7 @@ export async function installLinux(config) {
|
|
|
127
128
|
console.log('Service enabled and started.');
|
|
128
129
|
}
|
|
129
130
|
catch (err) {
|
|
130
|
-
console.warn('systemctl command failed:', err
|
|
131
|
+
console.warn('systemctl command failed:', toErrorMessage(err));
|
|
131
132
|
}
|
|
132
133
|
console.log('');
|
|
133
134
|
console.log('Agent Controller installed as a systemd system service.');
|
|
@@ -147,7 +148,7 @@ export async function installLinux(config) {
|
|
|
147
148
|
console.log('Service enabled and started.');
|
|
148
149
|
}
|
|
149
150
|
catch (err) {
|
|
150
|
-
console.warn('systemctl command failed:', err
|
|
151
|
+
console.warn('systemctl command failed:', toErrorMessage(err));
|
|
151
152
|
}
|
|
152
153
|
console.log('');
|
|
153
154
|
console.log('Agent Controller installed as a systemd user service.');
|
|
@@ -168,7 +169,7 @@ export async function uninstallLinux() {
|
|
|
168
169
|
userDisableSucceeded = true;
|
|
169
170
|
}
|
|
170
171
|
catch (err) {
|
|
171
|
-
console.warn('systemctl --user disable failed, trying system-level:', err
|
|
172
|
+
console.warn('systemctl --user disable failed, trying system-level:', toErrorMessage(err));
|
|
172
173
|
}
|
|
173
174
|
if (!userDisableSucceeded) {
|
|
174
175
|
try {
|
|
@@ -176,7 +177,7 @@ export async function uninstallLinux() {
|
|
|
176
177
|
console.log('Service disabled and stopped (system).');
|
|
177
178
|
}
|
|
178
179
|
catch (err) {
|
|
179
|
-
console.warn('systemctl disable failed (may not be enabled):', err
|
|
180
|
+
console.warn('systemctl disable failed (may not be enabled):', toErrorMessage(err));
|
|
180
181
|
}
|
|
181
182
|
}
|
|
182
183
|
const userServicePath = join(homedir(), '.config', 'systemd', 'user', 'agent-controller.service');
|