@agents-tower/core 0.1.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/adapters/claude.d.ts +2 -0
- package/dist/adapters/claude.js +43 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/adapters/codex-cloud.d.ts +4 -0
- package/dist/adapters/codex-cloud.js +80 -0
- package/dist/adapters/codex-cloud.js.map +1 -0
- package/dist/adapters/codex-local.d.ts +17 -0
- package/dist/adapters/codex-local.js +180 -0
- package/dist/adapters/codex-local.js.map +1 -0
- package/dist/adapters/cursor-cloud.d.ts +2 -0
- package/dist/adapters/cursor-cloud.js +54 -0
- package/dist/adapters/cursor-cloud.js.map +1 -0
- package/dist/adapters/cursor-local.d.ts +2 -0
- package/dist/adapters/cursor-local.js +37 -0
- package/dist/adapters/cursor-local.js.map +1 -0
- package/dist/adapters/helpers.d.ts +15 -0
- package/dist/adapters/helpers.js +33 -0
- package/dist/adapters/helpers.js.map +1 -0
- package/dist/adapters/hermes.d.ts +2 -0
- package/dist/adapters/hermes.js +41 -0
- package/dist/adapters/hermes.js.map +1 -0
- package/dist/adapters/index.d.ts +2 -0
- package/dist/adapters/index.js +37 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/openclaw.d.ts +2 -0
- package/dist/adapters/openclaw.js +41 -0
- package/dist/adapters/openclaw.js.map +1 -0
- package/dist/adapters/presence.d.ts +2 -0
- package/dist/adapters/presence.js +36 -0
- package/dist/adapters/presence.js.map +1 -0
- package/dist/adapters/static-source.d.ts +15 -0
- package/dist/adapters/static-source.js +41 -0
- package/dist/adapters/static-source.js.map +1 -0
- package/dist/adapters/types.d.ts +44 -0
- package/dist/adapters/types.js +3 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/app-server.d.ts +94 -0
- package/dist/app-server.js +382 -0
- package/dist/app-server.js.map +1 -0
- package/dist/app-settings.d.ts +52 -0
- package/dist/app-settings.js +268 -0
- package/dist/app-settings.js.map +1 -0
- package/dist/appearance.d.ts +6 -0
- package/dist/appearance.js +84 -0
- package/dist/appearance.js.map +1 -0
- package/dist/aseprite.d.ts +4 -0
- package/dist/aseprite.js +42 -0
- package/dist/aseprite.js.map +1 -0
- package/dist/claude-agent-sdk.d.ts +44 -0
- package/dist/claude-agent-sdk.js +347 -0
- package/dist/claude-agent-sdk.js.map +1 -0
- package/dist/claude-home-cache.d.ts +61 -0
- package/dist/claude-home-cache.js +438 -0
- package/dist/claude-home-cache.js.map +1 -0
- package/dist/claude.d.ts +154 -0
- package/dist/claude.js +3495 -0
- package/dist/claude.js.map +1 -0
- package/dist/cloud.d.ts +2 -0
- package/dist/cloud.js +25 -0
- package/dist/cloud.js.map +1 -0
- package/dist/codex-command.d.ts +25 -0
- package/dist/codex-command.js +235 -0
- package/dist/codex-command.js.map +1 -0
- package/dist/codex-session-files.d.ts +8 -0
- package/dist/codex-session-files.js +509 -0
- package/dist/codex-session-files.js.map +1 -0
- package/dist/codex-thread-query.d.ts +14 -0
- package/dist/codex-thread-query.js +82 -0
- package/dist/codex-thread-query.js.map +1 -0
- package/dist/cursor-cloud-data.d.ts +34 -0
- package/dist/cursor-cloud-data.js +344 -0
- package/dist/cursor-cloud-data.js.map +1 -0
- package/dist/cursor-lib/local-discovery.d.ts +17 -0
- package/dist/cursor-lib/local-discovery.js +251 -0
- package/dist/cursor-lib/local-discovery.js.map +1 -0
- package/dist/cursor-lib/shared.d.ts +5 -0
- package/dist/cursor-lib/shared.js +88 -0
- package/dist/cursor-lib/shared.js.map +1 -0
- package/dist/cursor.d.ts +8 -0
- package/dist/cursor.js +1584 -0
- package/dist/cursor.js.map +1 -0
- package/dist/domain/codex-turn-semantics.d.ts +4 -0
- package/dist/domain/codex-turn-semantics.js +49 -0
- package/dist/domain/codex-turn-semantics.js.map +1 -0
- package/dist/domain/workload-policy.d.ts +8 -0
- package/dist/domain/workload-policy.js +268 -0
- package/dist/domain/workload-policy.js.map +1 -0
- package/dist/domain/workspace-activity.d.ts +10 -0
- package/dist/domain/workspace-activity.js +372 -0
- package/dist/domain/workspace-activity.js.map +1 -0
- package/dist/goal.d.ts +11 -0
- package/dist/goal.js +76 -0
- package/dist/goal.js.map +1 -0
- package/dist/hermes-hook-install.d.ts +12 -0
- package/dist/hermes-hook-install.js +335 -0
- package/dist/hermes-hook-install.js.map +1 -0
- package/dist/hermes.d.ts +97 -0
- package/dist/hermes.js +2446 -0
- package/dist/hermes.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/live-monitor-lib/events.d.ts +43 -0
- package/dist/live-monitor-lib/events.js +1463 -0
- package/dist/live-monitor-lib/events.js.map +1 -0
- package/dist/live-monitor-lib/rollout-hooks.d.ts +13 -0
- package/dist/live-monitor-lib/rollout-hooks.js +253 -0
- package/dist/live-monitor-lib/rollout-hooks.js.map +1 -0
- package/dist/live-monitor.d.ts +102 -0
- package/dist/live-monitor.js +1461 -0
- package/dist/live-monitor.js.map +1 -0
- package/dist/local-thread-selection.d.ts +2 -0
- package/dist/local-thread-selection.js +58 -0
- package/dist/local-thread-selection.js.map +1 -0
- package/dist/openclaw.d.ts +41 -0
- package/dist/openclaw.js +715 -0
- package/dist/openclaw.js.map +1 -0
- package/dist/presence.d.ts +9 -0
- package/dist/presence.js +108 -0
- package/dist/presence.js.map +1 -0
- package/dist/project-identity.d.ts +7 -0
- package/dist/project-identity.js +162 -0
- package/dist/project-identity.js.map +1 -0
- package/dist/project-paths.d.ts +23 -0
- package/dist/project-paths.js +394 -0
- package/dist/project-paths.js.map +1 -0
- package/dist/project-storage.d.ts +7 -0
- package/dist/project-storage.js +79 -0
- package/dist/project-storage.js.map +1 -0
- package/dist/room-config.d.ts +21 -0
- package/dist/room-config.js +230 -0
- package/dist/room-config.js.map +1 -0
- package/dist/services/project-discovery.d.ts +1 -0
- package/dist/services/project-discovery.js +16 -0
- package/dist/services/project-discovery.js.map +1 -0
- package/dist/services/project-live-monitor.d.ts +1 -0
- package/dist/services/project-live-monitor.js +6 -0
- package/dist/services/project-live-monitor.js.map +1 -0
- package/dist/services/project-snapshot-coordinator.d.ts +49 -0
- package/dist/services/project-snapshot-coordinator.js +152 -0
- package/dist/services/project-snapshot-coordinator.js.map +1 -0
- package/dist/services/refresh-scheduler.d.ts +8 -0
- package/dist/services/refresh-scheduler.js +44 -0
- package/dist/services/refresh-scheduler.js.map +1 -0
- package/dist/services/snapshot-assembler.d.ts +8 -0
- package/dist/services/snapshot-assembler.js +167 -0
- package/dist/services/snapshot-assembler.js.map +1 -0
- package/dist/services/thread-store.d.ts +4 -0
- package/dist/services/thread-store.js +8 -0
- package/dist/services/thread-store.js.map +1 -0
- package/dist/snapshot-lib/activity-summary.d.ts +3 -0
- package/dist/snapshot-lib/activity-summary.js +220 -0
- package/dist/snapshot-lib/activity-summary.js.map +1 -0
- package/dist/snapshot-lib/dashboard-builder.d.ts +21 -0
- package/dist/snapshot-lib/dashboard-builder.js +146 -0
- package/dist/snapshot-lib/dashboard-builder.js.map +1 -0
- package/dist/snapshot-lib/thread-summary.d.ts +27 -0
- package/dist/snapshot-lib/thread-summary.js +953 -0
- package/dist/snapshot-lib/thread-summary.js.map +1 -0
- package/dist/snapshot.d.ts +2 -0
- package/dist/snapshot.js +21 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/types.d.ts +368 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/json.d.ts +4 -0
- package/dist/utils/json.js +29 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/text.d.ts +3 -0
- package/dist/utils/text.js +26 -0
- package/dist/utils/text.js.map +1 -0
- package/dist/web-search.d.ts +1 -0
- package/dist/web-search.js +52 -0
- package/dist/web-search.js.map +1 -0
- package/dist/workload.d.ts +1 -0
- package/dist/workload.js +12 -0
- package/dist/workload.js.map +1 -0
- package/package.json +19 -0
package/dist/openclaw.js
ADDED
|
@@ -0,0 +1,715 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.openClawSessionToActivityState = openClawSessionToActivityState;
|
|
4
|
+
exports.openClawSessionDetail = openClawSessionDetail;
|
|
5
|
+
exports.openClawWorkspaceMatchesProject = openClawWorkspaceMatchesProject;
|
|
6
|
+
exports.discoverOpenClawProjects = discoverOpenClawProjects;
|
|
7
|
+
exports.loadOpenClawAgents = loadOpenClawAgents;
|
|
8
|
+
exports.loadRoamingOpenClawSnapshotData = loadRoamingOpenClawSnapshotData;
|
|
9
|
+
exports.openClawSessionWorkspaceLabel = openClawSessionWorkspaceLabel;
|
|
10
|
+
const node_crypto_1 = require("node:crypto");
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
const appearance_1 = require("./appearance");
|
|
13
|
+
const project_paths_1 = require("./project-paths");
|
|
14
|
+
const DEFAULT_OPENCLAW_GATEWAY_URL = "ws://127.0.0.1:18789";
|
|
15
|
+
const OPENCLAW_REQUEST_TIMEOUT_MS = 4000;
|
|
16
|
+
const OPENCLAW_CONNECT_TIMEOUT_MS = 2500;
|
|
17
|
+
const OPENCLAW_CACHE_TTL_MS = 5000;
|
|
18
|
+
const OPENCLAW_DISCOVERY_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
19
|
+
const OPENCLAW_PROTOCOL_VERSION = 1;
|
|
20
|
+
let cachedWorkspaceData = null;
|
|
21
|
+
let cachedWorkspaceDataAt = 0;
|
|
22
|
+
let cachedIdentity = null;
|
|
23
|
+
function openClawEnabled() {
|
|
24
|
+
return [
|
|
25
|
+
process.env.OPENCLAW_GATEWAY_URL,
|
|
26
|
+
process.env.OPENCLAW_GATEWAY_TOKEN,
|
|
27
|
+
process.env.OPENCLAW_GATEWAY_PASSWORD
|
|
28
|
+
].some((value) => typeof value === "string" && value.trim().length > 0);
|
|
29
|
+
}
|
|
30
|
+
function openClawGatewayUrl() {
|
|
31
|
+
const configured = process.env.OPENCLAW_GATEWAY_URL;
|
|
32
|
+
if (typeof configured !== "string" || configured.trim().length === 0) {
|
|
33
|
+
return DEFAULT_OPENCLAW_GATEWAY_URL;
|
|
34
|
+
}
|
|
35
|
+
return configured.trim();
|
|
36
|
+
}
|
|
37
|
+
function openClawGatewayToken() {
|
|
38
|
+
const configured = process.env.OPENCLAW_GATEWAY_TOKEN;
|
|
39
|
+
if (typeof configured !== "string") {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
const trimmed = configured.trim();
|
|
43
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
44
|
+
}
|
|
45
|
+
function openClawGatewayPassword() {
|
|
46
|
+
const configured = process.env.OPENCLAW_GATEWAY_PASSWORD;
|
|
47
|
+
if (typeof configured !== "string") {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
const trimmed = configured.trim();
|
|
51
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
52
|
+
}
|
|
53
|
+
function openClawTimeoutError(label, timeoutMs) {
|
|
54
|
+
return new Error(`OpenClaw ${label} timed out after ${timeoutMs}ms`);
|
|
55
|
+
}
|
|
56
|
+
function shorten(text, maxLength) {
|
|
57
|
+
const normalized = text.replace(/\s+/g, " ").trim();
|
|
58
|
+
if (normalized.length <= maxLength) {
|
|
59
|
+
return normalized;
|
|
60
|
+
}
|
|
61
|
+
return `${normalized.slice(0, maxLength - 1)}…`;
|
|
62
|
+
}
|
|
63
|
+
function base64UrlEncode(buffer) {
|
|
64
|
+
return buffer.toString("base64").replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/g, "");
|
|
65
|
+
}
|
|
66
|
+
function normalizeAgentIdFromSessionKey(sessionKey) {
|
|
67
|
+
if (typeof sessionKey !== "string") {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const match = sessionKey.trim().match(/^agent:([^:]+):/i);
|
|
71
|
+
return match ? match[1].trim().toLowerCase() : null;
|
|
72
|
+
}
|
|
73
|
+
function cachedOpenClawIdentity() {
|
|
74
|
+
if (cachedIdentity) {
|
|
75
|
+
return cachedIdentity;
|
|
76
|
+
}
|
|
77
|
+
const { publicKey, privateKey } = (0, node_crypto_1.generateKeyPairSync)("ed25519");
|
|
78
|
+
const publicKeyDer = publicKey.export({ type: "spki", format: "der" });
|
|
79
|
+
const publicKeyRaw = publicKeyDer.subarray(publicKeyDer.length - 32);
|
|
80
|
+
cachedIdentity = {
|
|
81
|
+
deviceId: (0, node_crypto_1.createHash)("sha256").update(publicKeyRaw).digest("hex"),
|
|
82
|
+
publicKeyRawBase64Url: base64UrlEncode(publicKeyRaw),
|
|
83
|
+
privateKeyPem: privateKey.export({ type: "pkcs8", format: "pem" }).toString()
|
|
84
|
+
};
|
|
85
|
+
return cachedIdentity;
|
|
86
|
+
}
|
|
87
|
+
function buildDeviceAuthPayload(params) {
|
|
88
|
+
return [
|
|
89
|
+
"v3",
|
|
90
|
+
params.deviceId,
|
|
91
|
+
params.clientId,
|
|
92
|
+
params.clientMode,
|
|
93
|
+
params.role,
|
|
94
|
+
params.scopes.join(","),
|
|
95
|
+
String(params.signedAtMs),
|
|
96
|
+
params.token ?? "",
|
|
97
|
+
params.nonce,
|
|
98
|
+
params.platform ?? "",
|
|
99
|
+
params.deviceFamily ?? ""
|
|
100
|
+
].join("|");
|
|
101
|
+
}
|
|
102
|
+
function onceSocketEvent(socket, eventType, timeoutMs, predicate) {
|
|
103
|
+
return new Promise((resolve, reject) => {
|
|
104
|
+
const timeout = setTimeout(() => {
|
|
105
|
+
cleanup();
|
|
106
|
+
reject(openClawTimeoutError(eventType, timeoutMs));
|
|
107
|
+
}, timeoutMs);
|
|
108
|
+
const onEvent = (event) => {
|
|
109
|
+
if (predicate && !predicate(event)) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
cleanup();
|
|
113
|
+
resolve(event);
|
|
114
|
+
};
|
|
115
|
+
const cleanup = () => {
|
|
116
|
+
clearTimeout(timeout);
|
|
117
|
+
socket.removeEventListener(eventType, onEvent);
|
|
118
|
+
};
|
|
119
|
+
socket.addEventListener(eventType, onEvent);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function readSocketMessageData(event) {
|
|
123
|
+
const candidate = typeof event === "object" && event && "data" in event
|
|
124
|
+
? event.data
|
|
125
|
+
: null;
|
|
126
|
+
if (typeof candidate === "string") {
|
|
127
|
+
return candidate;
|
|
128
|
+
}
|
|
129
|
+
if (candidate instanceof ArrayBuffer) {
|
|
130
|
+
return Buffer.from(candidate).toString("utf8");
|
|
131
|
+
}
|
|
132
|
+
if (ArrayBuffer.isView(candidate)) {
|
|
133
|
+
return Buffer.from(candidate.buffer, candidate.byteOffset, candidate.byteLength).toString("utf8");
|
|
134
|
+
}
|
|
135
|
+
return "";
|
|
136
|
+
}
|
|
137
|
+
class OpenClawGatewayClient {
|
|
138
|
+
socket;
|
|
139
|
+
pending = new Map();
|
|
140
|
+
connectNonce = null;
|
|
141
|
+
closed = false;
|
|
142
|
+
constructor(socket) {
|
|
143
|
+
this.socket = socket;
|
|
144
|
+
this.socket.addEventListener("message", (event) => this.onMessage(event));
|
|
145
|
+
this.socket.addEventListener("close", () => this.failAll(new Error("OpenClaw gateway closed")));
|
|
146
|
+
this.socket.addEventListener("error", () => this.failAll(new Error("OpenClaw gateway error")));
|
|
147
|
+
}
|
|
148
|
+
static async connect() {
|
|
149
|
+
const WebSocketCtor = globalThis.WebSocket;
|
|
150
|
+
if (typeof WebSocketCtor !== "function") {
|
|
151
|
+
throw new Error("WebSocket runtime unavailable");
|
|
152
|
+
}
|
|
153
|
+
const socket = new WebSocketCtor(openClawGatewayUrl());
|
|
154
|
+
await onceSocketEvent(socket, "open", OPENCLAW_CONNECT_TIMEOUT_MS);
|
|
155
|
+
const client = new OpenClawGatewayClient(socket);
|
|
156
|
+
await client.handshake();
|
|
157
|
+
return client;
|
|
158
|
+
}
|
|
159
|
+
async close() {
|
|
160
|
+
if (this.closed) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
this.closed = true;
|
|
164
|
+
this.failAll(new Error("OpenClaw gateway client closed"));
|
|
165
|
+
this.socket.close(1000, "done");
|
|
166
|
+
}
|
|
167
|
+
async request(method, params) {
|
|
168
|
+
if (this.closed) {
|
|
169
|
+
throw new Error("OpenClaw gateway client already closed");
|
|
170
|
+
}
|
|
171
|
+
const id = (0, node_crypto_1.randomUUID)();
|
|
172
|
+
const frame = JSON.stringify({
|
|
173
|
+
type: "req",
|
|
174
|
+
id,
|
|
175
|
+
method,
|
|
176
|
+
params
|
|
177
|
+
});
|
|
178
|
+
return await new Promise((resolve, reject) => {
|
|
179
|
+
const timeout = setTimeout(() => {
|
|
180
|
+
this.pending.delete(id);
|
|
181
|
+
reject(openClawTimeoutError(method, OPENCLAW_REQUEST_TIMEOUT_MS));
|
|
182
|
+
}, OPENCLAW_REQUEST_TIMEOUT_MS);
|
|
183
|
+
this.pending.set(id, {
|
|
184
|
+
resolve: (value) => resolve(value),
|
|
185
|
+
reject,
|
|
186
|
+
timeout
|
|
187
|
+
});
|
|
188
|
+
this.socket.send(frame);
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
async handshake() {
|
|
192
|
+
this.connectNonce = await this.waitForConnectChallenge();
|
|
193
|
+
const identity = cachedOpenClawIdentity();
|
|
194
|
+
const clientId = "codex-agents-office";
|
|
195
|
+
const clientMode = "backend";
|
|
196
|
+
const role = "operator";
|
|
197
|
+
const scopes = ["operator.read"];
|
|
198
|
+
const signedAtMs = Date.now();
|
|
199
|
+
const signaturePayload = buildDeviceAuthPayload({
|
|
200
|
+
deviceId: identity.deviceId,
|
|
201
|
+
clientId,
|
|
202
|
+
clientMode,
|
|
203
|
+
role,
|
|
204
|
+
scopes,
|
|
205
|
+
signedAtMs,
|
|
206
|
+
token: openClawGatewayToken(),
|
|
207
|
+
nonce: this.connectNonce,
|
|
208
|
+
platform: process.platform,
|
|
209
|
+
deviceFamily: "desktop"
|
|
210
|
+
});
|
|
211
|
+
const signature = base64UrlEncode((0, node_crypto_1.sign)(null, Buffer.from(signaturePayload, "utf8"), identity.privateKeyPem));
|
|
212
|
+
await this.request("connect", {
|
|
213
|
+
minProtocol: OPENCLAW_PROTOCOL_VERSION,
|
|
214
|
+
maxProtocol: OPENCLAW_PROTOCOL_VERSION,
|
|
215
|
+
client: {
|
|
216
|
+
id: clientId,
|
|
217
|
+
displayName: "Codex Agents Office",
|
|
218
|
+
version: "0.1.0",
|
|
219
|
+
platform: process.platform,
|
|
220
|
+
mode: clientMode
|
|
221
|
+
},
|
|
222
|
+
caps: [],
|
|
223
|
+
commands: [],
|
|
224
|
+
role,
|
|
225
|
+
scopes,
|
|
226
|
+
auth: openClawGatewayToken() || openClawGatewayPassword()
|
|
227
|
+
? {
|
|
228
|
+
token: openClawGatewayToken(),
|
|
229
|
+
password: openClawGatewayPassword()
|
|
230
|
+
}
|
|
231
|
+
: undefined,
|
|
232
|
+
device: {
|
|
233
|
+
id: identity.deviceId,
|
|
234
|
+
publicKey: identity.publicKeyRawBase64Url,
|
|
235
|
+
signature,
|
|
236
|
+
signedAt: signedAtMs,
|
|
237
|
+
nonce: this.connectNonce
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
async waitForConnectChallenge() {
|
|
242
|
+
return await new Promise((resolve, reject) => {
|
|
243
|
+
const timeout = setTimeout(() => {
|
|
244
|
+
cleanup();
|
|
245
|
+
reject(openClawTimeoutError("connect.challenge", OPENCLAW_CONNECT_TIMEOUT_MS));
|
|
246
|
+
}, OPENCLAW_CONNECT_TIMEOUT_MS);
|
|
247
|
+
const onMessage = (event) => {
|
|
248
|
+
const text = readSocketMessageData(event);
|
|
249
|
+
if (!text) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
let parsed;
|
|
253
|
+
try {
|
|
254
|
+
parsed = JSON.parse(text);
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (parsed.type !== "event" || parsed.event !== "connect.challenge") {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const nonce = typeof parsed.payload?.nonce === "string" ? parsed.payload.nonce.trim() : "";
|
|
263
|
+
if (!nonce) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
cleanup();
|
|
267
|
+
resolve(nonce);
|
|
268
|
+
};
|
|
269
|
+
const cleanup = () => {
|
|
270
|
+
clearTimeout(timeout);
|
|
271
|
+
this.socket.removeEventListener("message", onMessage);
|
|
272
|
+
};
|
|
273
|
+
this.socket.addEventListener("message", onMessage);
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
onMessage(event) {
|
|
277
|
+
const text = readSocketMessageData(event);
|
|
278
|
+
if (!text) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
let parsed;
|
|
282
|
+
try {
|
|
283
|
+
parsed = JSON.parse(text);
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (parsed.type !== "res" || typeof parsed.id !== "string") {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const pending = this.pending.get(parsed.id);
|
|
292
|
+
if (!pending) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
this.pending.delete(parsed.id);
|
|
296
|
+
clearTimeout(pending.timeout);
|
|
297
|
+
if (parsed.ok) {
|
|
298
|
+
pending.resolve(parsed.payload);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
pending.reject(new Error(parsed.error?.message ?? parsed.error?.code ?? "OpenClaw gateway request failed"));
|
|
302
|
+
}
|
|
303
|
+
failAll(error) {
|
|
304
|
+
for (const [id, pending] of this.pending.entries()) {
|
|
305
|
+
this.pending.delete(id);
|
|
306
|
+
clearTimeout(pending.timeout);
|
|
307
|
+
pending.reject(error);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
function sessionRowTimestamp(row) {
|
|
312
|
+
if (typeof row.updatedAt === "number" && Number.isFinite(row.updatedAt)) {
|
|
313
|
+
return row.updatedAt;
|
|
314
|
+
}
|
|
315
|
+
if (typeof row.endedAt === "number" && Number.isFinite(row.endedAt)) {
|
|
316
|
+
return row.endedAt;
|
|
317
|
+
}
|
|
318
|
+
if (typeof row.startedAt === "number" && Number.isFinite(row.startedAt)) {
|
|
319
|
+
return row.startedAt;
|
|
320
|
+
}
|
|
321
|
+
return Number.NaN;
|
|
322
|
+
}
|
|
323
|
+
function workspaceAgentsFromGatewayData(input) {
|
|
324
|
+
const workspaceAgents = new Map();
|
|
325
|
+
const configuredAgents = Array.isArray(input.config?.agents?.list) ? input.config.agents.list : [];
|
|
326
|
+
const defaultWorkspace = (0, project_paths_1.canonicalizeProjectPath)(input.config?.agents?.defaults?.workspace ?? null);
|
|
327
|
+
const gatewayAgentNames = new Map();
|
|
328
|
+
for (const agent of input.gatewayAgents) {
|
|
329
|
+
gatewayAgentNames.set(agent.id.trim().toLowerCase(), agent.name?.trim() || agent.identity?.name?.trim() || null);
|
|
330
|
+
}
|
|
331
|
+
for (const configuredAgent of configuredAgents) {
|
|
332
|
+
const agentId = typeof configuredAgent?.id === "string" ? configuredAgent.id.trim().toLowerCase() : "";
|
|
333
|
+
if (!agentId) {
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
const workspaceRoot = (0, project_paths_1.canonicalizeProjectPath)(configuredAgent.workspace ?? null);
|
|
337
|
+
if (!workspaceRoot) {
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
workspaceAgents.set(agentId, {
|
|
341
|
+
agentId,
|
|
342
|
+
name: configuredAgent.name?.trim()
|
|
343
|
+
|| gatewayAgentNames.get(agentId)
|
|
344
|
+
|| null,
|
|
345
|
+
workspaceRoot,
|
|
346
|
+
isDefault: input.defaultAgentId === agentId
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
if (input.defaultAgentId && defaultWorkspace && !workspaceAgents.has(input.defaultAgentId)) {
|
|
350
|
+
workspaceAgents.set(input.defaultAgentId, {
|
|
351
|
+
agentId: input.defaultAgentId,
|
|
352
|
+
name: gatewayAgentNames.get(input.defaultAgentId) ?? null,
|
|
353
|
+
workspaceRoot: defaultWorkspace,
|
|
354
|
+
isDefault: true
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
return [...workspaceAgents.values()];
|
|
358
|
+
}
|
|
359
|
+
function openClawDisplayLabel(params) {
|
|
360
|
+
return (params.row.label?.trim()
|
|
361
|
+
|| params.row.displayName?.trim()
|
|
362
|
+
|| params.row.derivedTitle?.trim()
|
|
363
|
+
|| params.agent.name?.trim()
|
|
364
|
+
|| params.row.key);
|
|
365
|
+
}
|
|
366
|
+
function openClawLatestMessage(row) {
|
|
367
|
+
const preview = row.lastMessagePreview?.trim() ?? "";
|
|
368
|
+
return preview.length > 0 ? preview : null;
|
|
369
|
+
}
|
|
370
|
+
function pathWithinOpenClawProject(projectRoot, candidate) {
|
|
371
|
+
if (!candidate) {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
if ((0, project_paths_1.sameProjectPath)(projectRoot, candidate)) {
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
377
|
+
const rootKey = (0, project_paths_1.projectPathIdentityKey)(projectRoot);
|
|
378
|
+
const candidateKey = (0, project_paths_1.projectPathIdentityKey)(candidate);
|
|
379
|
+
return Boolean(rootKey && candidateKey && candidateKey.startsWith(`${rootKey}/`));
|
|
380
|
+
}
|
|
381
|
+
function openClawWorkspaceInsideAnyProject(workspaceRoot, projectRoots) {
|
|
382
|
+
if (!workspaceRoot) {
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
return projectRoots.some((projectRoot) => pathWithinOpenClawProject(projectRoot, workspaceRoot));
|
|
386
|
+
}
|
|
387
|
+
function openClawSessionToActivityState(params) {
|
|
388
|
+
if (params.activeChildCount > 0) {
|
|
389
|
+
return "delegating";
|
|
390
|
+
}
|
|
391
|
+
switch (params.row.status) {
|
|
392
|
+
case "running":
|
|
393
|
+
return "thinking";
|
|
394
|
+
case "done":
|
|
395
|
+
return "done";
|
|
396
|
+
case "failed":
|
|
397
|
+
case "killed":
|
|
398
|
+
case "timeout":
|
|
399
|
+
return "blocked";
|
|
400
|
+
default:
|
|
401
|
+
return "idle";
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
function openClawSessionDetail(params) {
|
|
405
|
+
if (params.activeChildCount > 0) {
|
|
406
|
+
return `Delegating to ${params.activeChildCount} session${params.activeChildCount === 1 ? "" : "s"}`;
|
|
407
|
+
}
|
|
408
|
+
const preview = openClawLatestMessage(params.row);
|
|
409
|
+
if (preview) {
|
|
410
|
+
return shorten(preview, 88);
|
|
411
|
+
}
|
|
412
|
+
if (params.row.derivedTitle?.trim()) {
|
|
413
|
+
return shorten(params.row.derivedTitle, 88);
|
|
414
|
+
}
|
|
415
|
+
switch (params.row.status) {
|
|
416
|
+
case "running":
|
|
417
|
+
return "Thinking";
|
|
418
|
+
case "done":
|
|
419
|
+
return "Finished recently";
|
|
420
|
+
case "failed":
|
|
421
|
+
return "Session failed";
|
|
422
|
+
case "killed":
|
|
423
|
+
return "Session stopped";
|
|
424
|
+
case "timeout":
|
|
425
|
+
return "Session timed out";
|
|
426
|
+
default:
|
|
427
|
+
return "Idle";
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
function sessionDepthForKey(key, parentByKey, seen = new Set()) {
|
|
431
|
+
const parent = parentByKey.get(key) ?? null;
|
|
432
|
+
if (!parent) {
|
|
433
|
+
return 0;
|
|
434
|
+
}
|
|
435
|
+
if (seen.has(key) || seen.has(parent)) {
|
|
436
|
+
return 1;
|
|
437
|
+
}
|
|
438
|
+
seen.add(key);
|
|
439
|
+
return 1 + sessionDepthForKey(parent, parentByKey, seen);
|
|
440
|
+
}
|
|
441
|
+
function activeOpenClawChildCounts(sessions) {
|
|
442
|
+
const activeChildCountByKey = new Map();
|
|
443
|
+
for (const session of sessions) {
|
|
444
|
+
const parentKey = session.parentSessionKey?.trim() || null;
|
|
445
|
+
if (!parentKey) {
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
const state = openClawSessionToActivityState({ row: session, activeChildCount: 0 });
|
|
449
|
+
if (state === "done" || state === "idle") {
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
activeChildCountByKey.set(parentKey, (activeChildCountByKey.get(parentKey) ?? 0) + 1);
|
|
453
|
+
}
|
|
454
|
+
return activeChildCountByKey;
|
|
455
|
+
}
|
|
456
|
+
async function openClawDashboardAgentFromSession(input) {
|
|
457
|
+
const updatedAtMs = sessionRowTimestamp(input.session);
|
|
458
|
+
if (!Number.isFinite(updatedAtMs)) {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
const agentId = normalizeAgentIdFromSessionKey(input.session.key);
|
|
462
|
+
const labelAgent = input.agent ?? {
|
|
463
|
+
agentId: agentId ?? "openclaw",
|
|
464
|
+
name: null,
|
|
465
|
+
workspaceRoot: input.projectRoot,
|
|
466
|
+
isDefault: false
|
|
467
|
+
};
|
|
468
|
+
const activeChildCount = input.activeChildCount;
|
|
469
|
+
const state = openClawSessionToActivityState({
|
|
470
|
+
row: input.session,
|
|
471
|
+
activeChildCount
|
|
472
|
+
});
|
|
473
|
+
const sourceKind = input.sourceKind
|
|
474
|
+
?? (input.session.modelProvider && input.session.model
|
|
475
|
+
? `openclaw:${input.session.modelProvider}/${input.session.model}`
|
|
476
|
+
: input.session.model
|
|
477
|
+
? `openclaw:${input.session.model}`
|
|
478
|
+
: "openclaw");
|
|
479
|
+
const appearance = await (0, appearance_1.ensureAgentAppearance)(input.projectRoot, `openclaw:${input.session.key}`);
|
|
480
|
+
const cwd = input.agent?.workspaceRoot ?? null;
|
|
481
|
+
return {
|
|
482
|
+
id: `openclaw:${input.session.key}`,
|
|
483
|
+
label: openClawDisplayLabel({ row: input.session, agent: labelAgent }),
|
|
484
|
+
source: "openclaw",
|
|
485
|
+
sourceKind,
|
|
486
|
+
parentThreadId: input.session.parentSessionKey ? `openclaw:${input.session.parentSessionKey}` : null,
|
|
487
|
+
depth: sessionDepthForKey(input.session.key, input.parentByKey),
|
|
488
|
+
isCurrent: false,
|
|
489
|
+
isOngoing: input.session.status === "running",
|
|
490
|
+
statusText: input.statusText ?? input.session.status ?? null,
|
|
491
|
+
role: labelAgent.isDefault ? (labelAgent.name ?? "openclaw") : labelAgent.agentId,
|
|
492
|
+
nickname: labelAgent.name,
|
|
493
|
+
isSubagent: Boolean(input.session.parentSessionKey),
|
|
494
|
+
state,
|
|
495
|
+
detail: openClawSessionDetail({ row: input.session, activeChildCount }),
|
|
496
|
+
cwd,
|
|
497
|
+
roomId: null,
|
|
498
|
+
appearance,
|
|
499
|
+
updatedAt: new Date(updatedAtMs).toISOString(),
|
|
500
|
+
stoppedAt: typeof input.session.endedAt === "number" && Number.isFinite(input.session.endedAt)
|
|
501
|
+
? new Date(input.session.endedAt).toISOString()
|
|
502
|
+
: null,
|
|
503
|
+
paths: cwd ? [cwd] : [],
|
|
504
|
+
activityEvent: null,
|
|
505
|
+
latestMessage: openClawLatestMessage(input.session),
|
|
506
|
+
threadId: input.session.key,
|
|
507
|
+
taskId: null,
|
|
508
|
+
resumeCommand: null,
|
|
509
|
+
url: null,
|
|
510
|
+
git: null,
|
|
511
|
+
provenance: "openclaw",
|
|
512
|
+
confidence: "typed",
|
|
513
|
+
needsUser: null,
|
|
514
|
+
liveSubscription: "readOnly",
|
|
515
|
+
network: null
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
async function loadOpenClawWorkspaceDataUncached() {
|
|
519
|
+
if (!openClawEnabled()) {
|
|
520
|
+
return null;
|
|
521
|
+
}
|
|
522
|
+
const client = await OpenClawGatewayClient.connect();
|
|
523
|
+
try {
|
|
524
|
+
const [configResult, agentsResult, sessionsResult] = await Promise.all([
|
|
525
|
+
client.request("config.get", {}),
|
|
526
|
+
client.request("agents.list", {}),
|
|
527
|
+
client.request("sessions.list", {
|
|
528
|
+
includeGlobal: false,
|
|
529
|
+
includeUnknown: false,
|
|
530
|
+
includeDerivedTitles: true,
|
|
531
|
+
includeLastMessage: true
|
|
532
|
+
})
|
|
533
|
+
]);
|
|
534
|
+
const defaultAgentId = typeof agentsResult?.defaultId === "string" && agentsResult.defaultId.trim().length > 0
|
|
535
|
+
? agentsResult.defaultId.trim().toLowerCase()
|
|
536
|
+
: null;
|
|
537
|
+
return {
|
|
538
|
+
fetchedAt: Date.now(),
|
|
539
|
+
agents: workspaceAgentsFromGatewayData({
|
|
540
|
+
config: configResult?.config,
|
|
541
|
+
gatewayAgents: Array.isArray(agentsResult?.agents) ? agentsResult.agents : [],
|
|
542
|
+
defaultAgentId
|
|
543
|
+
}),
|
|
544
|
+
sessions: Array.isArray(sessionsResult?.sessions) ? sessionsResult.sessions : []
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
finally {
|
|
548
|
+
await client.close();
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
async function loadOpenClawWorkspaceData() {
|
|
552
|
+
const now = Date.now();
|
|
553
|
+
if (cachedWorkspaceData && now - cachedWorkspaceDataAt <= OPENCLAW_CACHE_TTL_MS) {
|
|
554
|
+
return await cachedWorkspaceData;
|
|
555
|
+
}
|
|
556
|
+
cachedWorkspaceDataAt = now;
|
|
557
|
+
cachedWorkspaceData = loadOpenClawWorkspaceDataUncached().catch((error) => {
|
|
558
|
+
cachedWorkspaceData = null;
|
|
559
|
+
cachedWorkspaceDataAt = 0;
|
|
560
|
+
throw error;
|
|
561
|
+
});
|
|
562
|
+
return await cachedWorkspaceData;
|
|
563
|
+
}
|
|
564
|
+
function openClawWorkspaceMatchesProject(workspaceRoot, projectRoot) {
|
|
565
|
+
return pathWithinOpenClawProject(projectRoot, workspaceRoot);
|
|
566
|
+
}
|
|
567
|
+
async function discoverOpenClawProjects(limit = 20) {
|
|
568
|
+
const data = await loadOpenClawWorkspaceData();
|
|
569
|
+
if (!data) {
|
|
570
|
+
return [];
|
|
571
|
+
}
|
|
572
|
+
const recentCutoff = Date.now() - OPENCLAW_DISCOVERY_WINDOW_MS;
|
|
573
|
+
const projects = new Map();
|
|
574
|
+
const workspaceByAgentId = new Map(data.agents.map((agent) => [agent.agentId, agent.workspaceRoot]));
|
|
575
|
+
for (const session of data.sessions) {
|
|
576
|
+
const updatedAt = sessionRowTimestamp(session);
|
|
577
|
+
if (!Number.isFinite(updatedAt) || updatedAt < recentCutoff) {
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
const agentId = normalizeAgentIdFromSessionKey(session.key);
|
|
581
|
+
const workspaceRoot = agentId ? workspaceByAgentId.get(agentId) ?? null : null;
|
|
582
|
+
if (!workspaceRoot) {
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
const existing = projects.get(workspaceRoot);
|
|
586
|
+
if (existing) {
|
|
587
|
+
existing.updatedAt = Math.max(existing.updatedAt, updatedAt);
|
|
588
|
+
existing.count += 1;
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
projects.set(workspaceRoot, {
|
|
592
|
+
root: workspaceRoot,
|
|
593
|
+
label: openClawSessionWorkspaceLabel(workspaceRoot) ?? workspaceRoot,
|
|
594
|
+
updatedAt,
|
|
595
|
+
count: 1
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
return [...projects.values()]
|
|
599
|
+
.sort((left, right) => right.updatedAt - left.updatedAt)
|
|
600
|
+
.slice(0, limit);
|
|
601
|
+
}
|
|
602
|
+
async function loadOpenClawAgents(projectRoot) {
|
|
603
|
+
const data = await loadOpenClawWorkspaceData();
|
|
604
|
+
if (!data) {
|
|
605
|
+
return [];
|
|
606
|
+
}
|
|
607
|
+
const matchedAgents = data.agents.filter((agent) => openClawWorkspaceMatchesProject(agent.workspaceRoot, projectRoot));
|
|
608
|
+
if (matchedAgents.length === 0) {
|
|
609
|
+
return [];
|
|
610
|
+
}
|
|
611
|
+
const matchedAgentIds = new Set(matchedAgents.map((agent) => agent.agentId));
|
|
612
|
+
const agentById = new Map(matchedAgents.map((agent) => [agent.agentId, agent]));
|
|
613
|
+
const relevantSessions = data.sessions.filter((session) => {
|
|
614
|
+
const agentId = normalizeAgentIdFromSessionKey(session.key);
|
|
615
|
+
return Boolean(agentId && matchedAgentIds.has(agentId));
|
|
616
|
+
});
|
|
617
|
+
const parentByKey = new Map();
|
|
618
|
+
for (const session of relevantSessions) {
|
|
619
|
+
parentByKey.set(session.key, session.parentSessionKey?.trim() || null);
|
|
620
|
+
}
|
|
621
|
+
const activeChildCountByKey = activeOpenClawChildCounts(relevantSessions);
|
|
622
|
+
const agents = [];
|
|
623
|
+
for (const session of relevantSessions.sort((left, right) => {
|
|
624
|
+
return sessionRowTimestamp(right) - sessionRowTimestamp(left);
|
|
625
|
+
})) {
|
|
626
|
+
const agentId = normalizeAgentIdFromSessionKey(session.key);
|
|
627
|
+
if (!agentId) {
|
|
628
|
+
continue;
|
|
629
|
+
}
|
|
630
|
+
const agent = agentById.get(agentId);
|
|
631
|
+
if (!agent) {
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
const activeChildCount = activeChildCountByKey.get(session.key) ?? 0;
|
|
635
|
+
const dashboardAgent = await openClawDashboardAgentFromSession({
|
|
636
|
+
projectRoot,
|
|
637
|
+
session,
|
|
638
|
+
agent,
|
|
639
|
+
parentByKey,
|
|
640
|
+
activeChildCount
|
|
641
|
+
});
|
|
642
|
+
if (dashboardAgent) {
|
|
643
|
+
agents.push(dashboardAgent);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
return agents;
|
|
647
|
+
}
|
|
648
|
+
async function loadRoamingOpenClawSnapshotData(input) {
|
|
649
|
+
const anchorRoot = (0, project_paths_1.canonicalizeProjectPath)(input.anchorProjectRoot);
|
|
650
|
+
if (!anchorRoot) {
|
|
651
|
+
return { agents: [], notes: [] };
|
|
652
|
+
}
|
|
653
|
+
const data = await loadOpenClawWorkspaceData();
|
|
654
|
+
if (!data) {
|
|
655
|
+
return { agents: [], notes: [] };
|
|
656
|
+
}
|
|
657
|
+
const knownRoots = input.knownProjectRoots
|
|
658
|
+
.map((root) => (0, project_paths_1.canonicalizeProjectPath)(root))
|
|
659
|
+
.filter((root) => Boolean(root));
|
|
660
|
+
const limit = input.limit ?? 4;
|
|
661
|
+
const recentCutoff = Date.now() - OPENCLAW_DISCOVERY_WINDOW_MS;
|
|
662
|
+
const agentById = new Map(data.agents.map((agent) => [agent.agentId, agent]));
|
|
663
|
+
const candidateSessions = data.sessions.filter((session) => {
|
|
664
|
+
const updatedAt = sessionRowTimestamp(session);
|
|
665
|
+
if (!Number.isFinite(updatedAt) || updatedAt < recentCutoff) {
|
|
666
|
+
return false;
|
|
667
|
+
}
|
|
668
|
+
const agentId = normalizeAgentIdFromSessionKey(session.key);
|
|
669
|
+
const agent = agentId ? agentById.get(agentId) ?? null : null;
|
|
670
|
+
return !openClawWorkspaceInsideAnyProject(agent?.workspaceRoot ?? null, knownRoots);
|
|
671
|
+
});
|
|
672
|
+
const parentByKey = new Map();
|
|
673
|
+
for (const session of candidateSessions) {
|
|
674
|
+
parentByKey.set(session.key, session.parentSessionKey?.trim() || null);
|
|
675
|
+
}
|
|
676
|
+
const activeChildCountByKey = activeOpenClawChildCounts(candidateSessions);
|
|
677
|
+
const agents = [];
|
|
678
|
+
for (const session of candidateSessions.sort((left, right) => {
|
|
679
|
+
return sessionRowTimestamp(right) - sessionRowTimestamp(left);
|
|
680
|
+
})) {
|
|
681
|
+
const agentId = normalizeAgentIdFromSessionKey(session.key);
|
|
682
|
+
const sourceAgent = agentId ? agentById.get(agentId) ?? null : null;
|
|
683
|
+
const activeChildCount = activeChildCountByKey.get(session.key) ?? 0;
|
|
684
|
+
const dashboardAgent = await openClawDashboardAgentFromSession({
|
|
685
|
+
projectRoot: anchorRoot,
|
|
686
|
+
session,
|
|
687
|
+
agent: sourceAgent,
|
|
688
|
+
parentByKey,
|
|
689
|
+
activeChildCount,
|
|
690
|
+
sourceKind: "openclaw:roaming",
|
|
691
|
+
statusText: session.status === "running" ? "roaming" : session.status ?? null
|
|
692
|
+
});
|
|
693
|
+
if (!dashboardAgent) {
|
|
694
|
+
continue;
|
|
695
|
+
}
|
|
696
|
+
if (dashboardAgent.state === "idle" && dashboardAgent.isOngoing !== true) {
|
|
697
|
+
continue;
|
|
698
|
+
}
|
|
699
|
+
agents.push(dashboardAgent);
|
|
700
|
+
}
|
|
701
|
+
return {
|
|
702
|
+
agents: agents
|
|
703
|
+
.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt))
|
|
704
|
+
.slice(0, limit),
|
|
705
|
+
notes: []
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
function openClawSessionWorkspaceLabel(workspaceRoot) {
|
|
709
|
+
const canonical = (0, project_paths_1.canonicalizeProjectPath)(workspaceRoot);
|
|
710
|
+
if (!canonical) {
|
|
711
|
+
return null;
|
|
712
|
+
}
|
|
713
|
+
return (0, node_path_1.basename)(canonical) || canonical;
|
|
714
|
+
}
|
|
715
|
+
//# sourceMappingURL=openclaw.js.map
|