@clawrent/cli 0.4.4 → 0.5.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/index.js +73 -525
- package/dist/index.js.map +1 -1
- package/dist/lib.d.ts +1 -213
- package/dist/lib.js +9 -459
- package/dist/lib.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1,341 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { readFileSync as
|
|
5
|
-
import { dirname, join as
|
|
4
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
5
|
+
import { dirname, join as join2 } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
|
|
9
9
|
// src/commands/auth.ts
|
|
10
10
|
import { createInterface } from "readline";
|
|
11
|
-
|
|
12
|
-
// src/config.ts
|
|
13
|
-
import { readFileSync, writeFileSync, mkdirSync, unlinkSync, existsSync } from "fs";
|
|
14
|
-
import { join } from "path";
|
|
15
|
-
import { homedir } from "os";
|
|
16
|
-
var DEFAULT_CONFIG = {
|
|
17
|
-
apiUrl: "https://clawrent.cloud",
|
|
18
|
-
wsUrl: "wss://clawrent.cloud"
|
|
19
|
-
};
|
|
20
|
-
function getConfigDir() {
|
|
21
|
-
return join(homedir(), ".clawrent");
|
|
22
|
-
}
|
|
23
|
-
function getConfigFilePath() {
|
|
24
|
-
return join(getConfigDir(), "config.json");
|
|
25
|
-
}
|
|
26
|
-
function getConfigPath() {
|
|
27
|
-
return getConfigFilePath();
|
|
28
|
-
}
|
|
29
|
-
function loadConfig() {
|
|
30
|
-
let fileConfig = {};
|
|
31
|
-
const configPath = getConfigFilePath();
|
|
32
|
-
if (existsSync(configPath)) {
|
|
33
|
-
try {
|
|
34
|
-
const raw = readFileSync(configPath, "utf-8");
|
|
35
|
-
fileConfig = JSON.parse(raw);
|
|
36
|
-
} catch {
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
if (fileConfig.apiUrl?.includes("localhost") || fileConfig.wsUrl?.includes("localhost")) {
|
|
40
|
-
delete fileConfig.apiUrl;
|
|
41
|
-
delete fileConfig.wsUrl;
|
|
42
|
-
try {
|
|
43
|
-
const cleaned = { ...fileConfig };
|
|
44
|
-
writeFileSync(configPath, JSON.stringify(cleaned, null, 2), "utf-8");
|
|
45
|
-
} catch {
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
const config = {
|
|
49
|
-
...DEFAULT_CONFIG,
|
|
50
|
-
...fileConfig
|
|
51
|
-
};
|
|
52
|
-
const envApiUrl = process.env["CLAWRENT_API_URL"];
|
|
53
|
-
const envWsUrl = process.env["CLAWRENT_WS_URL"];
|
|
54
|
-
const envToken = process.env["CLAWRENT_TOKEN"];
|
|
55
|
-
const envApiKey = process.env["CLAWRENT_API_KEY"];
|
|
56
|
-
const envUserId = process.env["CLAWRENT_USER_ID"];
|
|
57
|
-
if (envApiUrl) config.apiUrl = envApiUrl;
|
|
58
|
-
if (envWsUrl) config.wsUrl = envWsUrl;
|
|
59
|
-
if (envToken) config.token = envToken;
|
|
60
|
-
if (envApiKey) config.apiKey = envApiKey;
|
|
61
|
-
if (envUserId) config.userId = envUserId;
|
|
62
|
-
return config;
|
|
63
|
-
}
|
|
64
|
-
function saveConfig(partial) {
|
|
65
|
-
const configDir = getConfigDir();
|
|
66
|
-
if (!existsSync(configDir)) {
|
|
67
|
-
mkdirSync(configDir, { recursive: true });
|
|
68
|
-
}
|
|
69
|
-
let existing = {};
|
|
70
|
-
const configPath = getConfigFilePath();
|
|
71
|
-
if (existsSync(configPath)) {
|
|
72
|
-
try {
|
|
73
|
-
existing = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
74
|
-
} catch {
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
const merged = { ...existing, ...partial };
|
|
78
|
-
writeFileSync(configPath, JSON.stringify(merged, null, 2), "utf-8");
|
|
79
|
-
}
|
|
80
|
-
function clearConfig() {
|
|
81
|
-
const configPath = getConfigFilePath();
|
|
82
|
-
if (existsSync(configPath)) {
|
|
83
|
-
unlinkSync(configPath);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// src/api-client.ts
|
|
88
|
-
var ApiClient = class {
|
|
89
|
-
config;
|
|
90
|
-
/** When set (e.g. by ProviderAgent.start), overrides config.token for REST auth. */
|
|
91
|
-
agentTokenOverride = null;
|
|
92
|
-
constructor(config) {
|
|
93
|
-
this.config = config;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Set a token that overrides config.token for subsequent REST requests.
|
|
97
|
-
* Used by the in-process provider agent: once serving with an agentToken,
|
|
98
|
-
* provider REST calls (approve/list/end + internal autoApprove) authenticate
|
|
99
|
-
* as the agent owner via this token, so they work without a separate user
|
|
100
|
-
* JWT login. The backend's resolveAuth accepts the agt_clawrent_* prefix.
|
|
101
|
-
* Pass null to clear (e.g. on stop_serving).
|
|
102
|
-
*/
|
|
103
|
-
setAgentToken(token) {
|
|
104
|
-
this.agentTokenOverride = token;
|
|
105
|
-
}
|
|
106
|
-
get apiUrl() {
|
|
107
|
-
return this.config.apiUrl;
|
|
108
|
-
}
|
|
109
|
-
get wsUrl() {
|
|
110
|
-
return this.config.wsUrl;
|
|
111
|
-
}
|
|
112
|
-
get userId() {
|
|
113
|
-
return this.config.userId;
|
|
114
|
-
}
|
|
115
|
-
// --- Auth (no auth needed) ---
|
|
116
|
-
async sendVerification(email) {
|
|
117
|
-
return this.request("POST", "/api/auth/send-verification", { email }, false);
|
|
118
|
-
}
|
|
119
|
-
async registerUser(input) {
|
|
120
|
-
return this.request("POST", "/api/auth/register", input, false);
|
|
121
|
-
}
|
|
122
|
-
async login(email, password) {
|
|
123
|
-
return this.request("POST", "/api/auth/login", { email, password }, false);
|
|
124
|
-
}
|
|
125
|
-
async getMe() {
|
|
126
|
-
return this.request("GET", "/api/auth/me");
|
|
127
|
-
}
|
|
128
|
-
// --- Marketplace ---
|
|
129
|
-
async browse(query) {
|
|
130
|
-
const params = new URLSearchParams();
|
|
131
|
-
if (query?.search) params.set("search", query.search);
|
|
132
|
-
if (query?.category) params.set("category", query.category);
|
|
133
|
-
if (query?.page) params.set("page", String(query.page));
|
|
134
|
-
if (query?.limit) params.set("limit", String(query.limit));
|
|
135
|
-
const qs = params.toString();
|
|
136
|
-
return this.request("GET", `/api/marketplace/browse${qs ? `?${qs}` : ""}`);
|
|
137
|
-
}
|
|
138
|
-
async getAgent(slug) {
|
|
139
|
-
return this.request("GET", `/api/marketplace/agents/${encodeURIComponent(slug)}`);
|
|
140
|
-
}
|
|
141
|
-
// --- Sessions ---
|
|
142
|
-
async rent(options) {
|
|
143
|
-
return this.request("POST", "/api/sessions", {
|
|
144
|
-
agentId: options.agentId,
|
|
145
|
-
taskDescription: options.taskDescription,
|
|
146
|
-
grantedPermissions: options.grantedPermissions ?? {}
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
async getSessions(query) {
|
|
150
|
-
const params = new URLSearchParams();
|
|
151
|
-
if (query?.role) params.set("role", query.role);
|
|
152
|
-
if (query?.status) params.set("status", query.status);
|
|
153
|
-
if (query?.page) params.set("page", String(query.page));
|
|
154
|
-
if (query?.limit) params.set("limit", String(query.limit));
|
|
155
|
-
const qs = params.toString();
|
|
156
|
-
return this.request("GET", `/api/sessions${qs ? `?${qs}` : ""}`);
|
|
157
|
-
}
|
|
158
|
-
async getSession(sessionId) {
|
|
159
|
-
return this.request("GET", `/api/sessions/${encodeURIComponent(sessionId)}`);
|
|
160
|
-
}
|
|
161
|
-
async getSessionMessages(sessionId, options) {
|
|
162
|
-
const params = new URLSearchParams();
|
|
163
|
-
if (options?.since) params.set("since", options.since);
|
|
164
|
-
if (options?.limit) params.set("limit", String(options.limit));
|
|
165
|
-
const qs = params.toString();
|
|
166
|
-
return this.request(
|
|
167
|
-
"GET",
|
|
168
|
-
`/api/sessions/${encodeURIComponent(sessionId)}/messages${qs ? `?${qs}` : ""}`
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
/** POST a message via REST (WS fallback, e.g. session not attached after restart). */
|
|
172
|
-
async sendSessionMessage(sessionId, body) {
|
|
173
|
-
return this.request(
|
|
174
|
-
"POST",
|
|
175
|
-
`/api/sessions/${encodeURIComponent(sessionId)}/messages`,
|
|
176
|
-
body
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
async endSession(sessionId) {
|
|
180
|
-
return this.request("POST", `/api/sessions/${encodeURIComponent(sessionId)}/end`);
|
|
181
|
-
}
|
|
182
|
-
async approveSession(sessionId) {
|
|
183
|
-
return this.request("POST", `/api/sessions/${encodeURIComponent(sessionId)}/approve`);
|
|
184
|
-
}
|
|
185
|
-
// --- Billing ---
|
|
186
|
-
async getBalance() {
|
|
187
|
-
return this.request("GET", "/api/billing/wallet");
|
|
188
|
-
}
|
|
189
|
-
async topUp(amount) {
|
|
190
|
-
return this.request("POST", "/api/billing/wallet/topup", { amount });
|
|
191
|
-
}
|
|
192
|
-
// --- Provider: Agents ---
|
|
193
|
-
async registerAgent(data) {
|
|
194
|
-
return this.request("POST", "/api/agents", data);
|
|
195
|
-
}
|
|
196
|
-
async getMyAgents(query) {
|
|
197
|
-
const params = new URLSearchParams();
|
|
198
|
-
if (query?.page) params.set("page", String(query.page));
|
|
199
|
-
if (query?.limit) params.set("limit", String(query.limit));
|
|
200
|
-
if (query?.roles) params.set("roles", query.roles);
|
|
201
|
-
const qs = params.toString();
|
|
202
|
-
return this.request("GET", `/api/agents/my${qs ? `?${qs}` : ""}`);
|
|
203
|
-
}
|
|
204
|
-
/** Resolve the current agent from agentToken. Requires agt_clawrent_ token auth. */
|
|
205
|
-
async getMyAgent() {
|
|
206
|
-
return this.request("GET", "/api/agents/me/agent");
|
|
207
|
-
}
|
|
208
|
-
async applyProvider(agentId, data) {
|
|
209
|
-
return this.request("POST", `/api/agents/${encodeURIComponent(agentId)}/apply-provider`, data);
|
|
210
|
-
}
|
|
211
|
-
/** Publish agent — simplified apply-provider with defaults, submits for admin review */
|
|
212
|
-
async publishAgent(agentId, data) {
|
|
213
|
-
return this.request("POST", `/api/agents/${encodeURIComponent(agentId)}/publish`, data ?? {});
|
|
214
|
-
}
|
|
215
|
-
/** Activate agent — verify admin-approved + WebSocket connected, then go online */
|
|
216
|
-
async activateAgent(agentId) {
|
|
217
|
-
return this.request("POST", `/api/agents/${encodeURIComponent(agentId)}/activate`);
|
|
218
|
-
}
|
|
219
|
-
async setOnlineStatus(agentId, onlineStatus) {
|
|
220
|
-
return this.request("PATCH", `/api/agents/${encodeURIComponent(agentId)}/status`, { onlineStatus });
|
|
221
|
-
}
|
|
222
|
-
async generateAgentToken(agentId) {
|
|
223
|
-
return this.request("POST", `/api/agents/${encodeURIComponent(agentId)}/token`);
|
|
224
|
-
}
|
|
225
|
-
async revokeAgentToken(agentId) {
|
|
226
|
-
return this.request("DELETE", `/api/agents/${encodeURIComponent(agentId)}/token`);
|
|
227
|
-
}
|
|
228
|
-
// --- Orders ---
|
|
229
|
-
async createOrder(data) {
|
|
230
|
-
return this.request("POST", "/api/orders", data);
|
|
231
|
-
}
|
|
232
|
-
async getOrders(query) {
|
|
233
|
-
const params = new URLSearchParams();
|
|
234
|
-
if (query?.status) params.set("status", query.status);
|
|
235
|
-
if (query?.page) params.set("page", String(query.page));
|
|
236
|
-
if (query?.limit) params.set("limit", String(query.limit));
|
|
237
|
-
const qs = params.toString();
|
|
238
|
-
return this.request("GET", `/api/orders${qs ? `?${qs}` : ""}`);
|
|
239
|
-
}
|
|
240
|
-
async getOrder(orderId) {
|
|
241
|
-
return this.request("GET", `/api/orders/${encodeURIComponent(orderId)}`);
|
|
242
|
-
}
|
|
243
|
-
async cancelOrder(orderId) {
|
|
244
|
-
return this.request("POST", `/api/orders/${encodeURIComponent(orderId)}/cancel`);
|
|
245
|
-
}
|
|
246
|
-
// --- Cart ---
|
|
247
|
-
async getCart() {
|
|
248
|
-
return this.request("GET", "/api/cart");
|
|
249
|
-
}
|
|
250
|
-
async addToCart(data) {
|
|
251
|
-
return this.request("POST", "/api/cart", data);
|
|
252
|
-
}
|
|
253
|
-
async updateCartItem(itemId, data) {
|
|
254
|
-
return this.request("PATCH", `/api/cart/${encodeURIComponent(itemId)}`, data);
|
|
255
|
-
}
|
|
256
|
-
async removeFromCart(itemId) {
|
|
257
|
-
return this.request("DELETE", `/api/cart/${encodeURIComponent(itemId)}`);
|
|
258
|
-
}
|
|
259
|
-
async clearCart() {
|
|
260
|
-
return this.request("DELETE", "/api/cart");
|
|
261
|
-
}
|
|
262
|
-
// --- Favorites ---
|
|
263
|
-
async listFavorites(query) {
|
|
264
|
-
const params = new URLSearchParams();
|
|
265
|
-
if (query?.page) params.set("page", String(query.page));
|
|
266
|
-
if (query?.limit) params.set("limit", String(query.limit));
|
|
267
|
-
const qs = params.toString();
|
|
268
|
-
return this.request("GET", `/api/favorites${qs ? `?${qs}` : ""}`);
|
|
269
|
-
}
|
|
270
|
-
async addFavorite(agentId) {
|
|
271
|
-
return this.request("POST", `/api/favorites/${encodeURIComponent(agentId)}`);
|
|
272
|
-
}
|
|
273
|
-
async removeFavorite(agentId) {
|
|
274
|
-
return this.request("DELETE", `/api/favorites/${encodeURIComponent(agentId)}`);
|
|
275
|
-
}
|
|
276
|
-
// --- Health ---
|
|
277
|
-
async health() {
|
|
278
|
-
return this.request("GET", "/api/health", void 0, false);
|
|
279
|
-
}
|
|
280
|
-
// --- Docs (MCP interface) ---
|
|
281
|
-
async getDocsTree() {
|
|
282
|
-
return this.request("GET", "/api/mcp/docs/tree", void 0, false);
|
|
283
|
-
}
|
|
284
|
-
async getDocByPath(path) {
|
|
285
|
-
return this.request("GET", `/api/mcp/docs/by-path/${encodeURI(path)}`, void 0, false);
|
|
286
|
-
}
|
|
287
|
-
async searchDocs(query) {
|
|
288
|
-
const params = new URLSearchParams({ q: query });
|
|
289
|
-
return this.request("GET", `/api/mcp/docs/search?${params.toString()}`, void 0, false);
|
|
290
|
-
}
|
|
291
|
-
async getDoc(id) {
|
|
292
|
-
return this.request("GET", `/api/mcp/docs/${encodeURIComponent(id)}`, void 0, false);
|
|
293
|
-
}
|
|
294
|
-
async createDoc(data) {
|
|
295
|
-
return this.request("POST", "/api/mcp/docs", data);
|
|
296
|
-
}
|
|
297
|
-
async updateDoc(id, data) {
|
|
298
|
-
return this.request("PATCH", `/api/mcp/docs/${encodeURIComponent(id)}`, data);
|
|
299
|
-
}
|
|
300
|
-
async deleteDoc(id) {
|
|
301
|
-
return this.request("DELETE", `/api/mcp/docs/${encodeURIComponent(id)}`);
|
|
302
|
-
}
|
|
303
|
-
async publishDoc(id) {
|
|
304
|
-
return this.request("POST", `/api/mcp/docs/${encodeURIComponent(id)}/publish`);
|
|
305
|
-
}
|
|
306
|
-
async unpublishDoc(id) {
|
|
307
|
-
return this.request("POST", `/api/mcp/docs/${encodeURIComponent(id)}/unpublish`);
|
|
308
|
-
}
|
|
309
|
-
// --- Private ---
|
|
310
|
-
async request(method, path, body, requireAuth = true) {
|
|
311
|
-
const url = `${this.config.apiUrl}${path}`;
|
|
312
|
-
const headers = {};
|
|
313
|
-
if (body !== void 0) {
|
|
314
|
-
headers["Content-Type"] = "application/json";
|
|
315
|
-
}
|
|
316
|
-
if (requireAuth) {
|
|
317
|
-
if (this.agentTokenOverride) {
|
|
318
|
-
headers["Authorization"] = `Bearer ${this.agentTokenOverride}`;
|
|
319
|
-
} else if (this.config.token) {
|
|
320
|
-
headers["Authorization"] = `Bearer ${this.config.token}`;
|
|
321
|
-
} else if (this.config.apiKey) {
|
|
322
|
-
headers["x-api-key"] = this.config.apiKey;
|
|
323
|
-
} else {
|
|
324
|
-
throw new Error("Not authenticated. Run `clawrent auth login` first.");
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
const response = await fetch(url, {
|
|
328
|
-
method,
|
|
329
|
-
headers,
|
|
330
|
-
body: body ? JSON.stringify(body) : void 0
|
|
331
|
-
});
|
|
332
|
-
if (!response.ok) {
|
|
333
|
-
const errBody = await response.json().catch(() => ({ message: response.statusText }));
|
|
334
|
-
throw new Error(`API error ${response.status}: ${errBody["message"] ?? JSON.stringify(errBody)}`);
|
|
335
|
-
}
|
|
336
|
-
return response.json();
|
|
337
|
-
}
|
|
338
|
-
};
|
|
11
|
+
import { ApiClient, loadConfig, saveConfig, clearConfig, getConfigPath } from "@clawrent/provider";
|
|
339
12
|
|
|
340
13
|
// src/output.ts
|
|
341
14
|
function printJson(data) {
|
|
@@ -502,10 +175,11 @@ function registerAuthCommand(program2) {
|
|
|
502
175
|
}
|
|
503
176
|
|
|
504
177
|
// src/commands/browse.ts
|
|
178
|
+
import { ApiClient as ApiClient2, loadConfig as loadConfig2 } from "@clawrent/provider";
|
|
505
179
|
function registerBrowseCommand(program2) {
|
|
506
180
|
program2.command("browse").description("Browse available agents on the marketplace").option("-s, --search <query>", "Search by name").option("-c, --category <category>", "Filter by category").option("-p, --page <number>", "Page number", "1").option("-l, --limit <number>", "Results per page", "20").action(async (opts) => {
|
|
507
181
|
try {
|
|
508
|
-
const client = new
|
|
182
|
+
const client = new ApiClient2(loadConfig2());
|
|
509
183
|
const result = await client.browse({
|
|
510
184
|
search: opts.search,
|
|
511
185
|
category: opts.category,
|
|
@@ -521,10 +195,11 @@ function registerBrowseCommand(program2) {
|
|
|
521
195
|
}
|
|
522
196
|
|
|
523
197
|
// src/commands/agent.ts
|
|
198
|
+
import { ApiClient as ApiClient3, loadConfig as loadConfig3 } from "@clawrent/provider";
|
|
524
199
|
function registerAgentCommand(program2) {
|
|
525
200
|
program2.command("agent <slug>").description("Get agent details by slug").action(async (slug) => {
|
|
526
201
|
try {
|
|
527
|
-
const client = new
|
|
202
|
+
const client = new ApiClient3(loadConfig3());
|
|
528
203
|
const result = await client.getAgent(slug);
|
|
529
204
|
printJson(result);
|
|
530
205
|
} catch (err) {
|
|
@@ -535,10 +210,11 @@ function registerAgentCommand(program2) {
|
|
|
535
210
|
}
|
|
536
211
|
|
|
537
212
|
// src/commands/sessions.ts
|
|
213
|
+
import { ApiClient as ApiClient4, loadConfig as loadConfig4 } from "@clawrent/provider";
|
|
538
214
|
function registerSessionsCommand(program2) {
|
|
539
215
|
program2.command("sessions").description("List your sessions").option("-r, --role <role>", "Filter by role (consumer/provider)").option("-s, --status <status>", "Filter by status").option("-p, --page <number>", "Page number", "1").option("-l, --limit <number>", "Results per page", "20").action(async (opts) => {
|
|
540
216
|
try {
|
|
541
|
-
const client = new
|
|
217
|
+
const client = new ApiClient4(loadConfig4());
|
|
542
218
|
const result = await client.getSessions({
|
|
543
219
|
role: opts.role,
|
|
544
220
|
status: opts.status,
|
|
@@ -554,10 +230,11 @@ function registerSessionsCommand(program2) {
|
|
|
554
230
|
}
|
|
555
231
|
|
|
556
232
|
// src/commands/balance.ts
|
|
233
|
+
import { ApiClient as ApiClient5, loadConfig as loadConfig5 } from "@clawrent/provider";
|
|
557
234
|
function registerBalanceCommand(program2) {
|
|
558
235
|
program2.command("balance").description("Check wallet balance").action(async () => {
|
|
559
236
|
try {
|
|
560
|
-
const client = new
|
|
237
|
+
const client = new ApiClient5(loadConfig5());
|
|
561
238
|
const result = await client.getBalance();
|
|
562
239
|
printJson(result);
|
|
563
240
|
} catch (err) {
|
|
@@ -568,10 +245,11 @@ function registerBalanceCommand(program2) {
|
|
|
568
245
|
}
|
|
569
246
|
|
|
570
247
|
// src/commands/topup.ts
|
|
248
|
+
import { ApiClient as ApiClient6, loadConfig as loadConfig6 } from "@clawrent/provider";
|
|
571
249
|
function registerTopupCommand(program2) {
|
|
572
250
|
program2.command("topup <amount>").description("Top up wallet balance").action(async (amount) => {
|
|
573
251
|
try {
|
|
574
|
-
const client = new
|
|
252
|
+
const client = new ApiClient6(loadConfig6());
|
|
575
253
|
const result = await client.topUp(amount);
|
|
576
254
|
printJson(result);
|
|
577
255
|
} catch (err) {
|
|
@@ -582,10 +260,11 @@ function registerTopupCommand(program2) {
|
|
|
582
260
|
}
|
|
583
261
|
|
|
584
262
|
// src/commands/health.ts
|
|
263
|
+
import { ApiClient as ApiClient7, loadConfig as loadConfig7 } from "@clawrent/provider";
|
|
585
264
|
function registerHealthCommand(program2) {
|
|
586
265
|
program2.command("health").description("Check platform health").action(async () => {
|
|
587
266
|
try {
|
|
588
|
-
const client = new
|
|
267
|
+
const client = new ApiClient7(loadConfig7());
|
|
589
268
|
const result = await client.health();
|
|
590
269
|
printJson(result);
|
|
591
270
|
} catch (err) {
|
|
@@ -596,6 +275,7 @@ function registerHealthCommand(program2) {
|
|
|
596
275
|
}
|
|
597
276
|
|
|
598
277
|
// src/commands/rent.ts
|
|
278
|
+
import { ApiClient as ApiClient8, loadConfig as loadConfig8 } from "@clawrent/provider";
|
|
599
279
|
function registerRentCommand(program2) {
|
|
600
280
|
program2.command("rent").description("Rent an agent (create a session)").requiredOption("--agent-id <id>", "Agent ID to rent").requiredOption("--task <description>", "Task description").option("--permissions <json>", "Granted permissions as JSON string", "{}").action(async (opts) => {
|
|
601
281
|
try {
|
|
@@ -606,7 +286,7 @@ function registerRentCommand(program2) {
|
|
|
606
286
|
printError("Invalid JSON for --permissions");
|
|
607
287
|
process.exit(1);
|
|
608
288
|
}
|
|
609
|
-
const client = new
|
|
289
|
+
const client = new ApiClient8(loadConfig8());
|
|
610
290
|
const result = await client.rent({
|
|
611
291
|
agentId: opts.agentId,
|
|
612
292
|
taskDescription: opts.task,
|
|
@@ -621,10 +301,11 @@ function registerRentCommand(program2) {
|
|
|
621
301
|
}
|
|
622
302
|
|
|
623
303
|
// src/commands/end.ts
|
|
304
|
+
import { ApiClient as ApiClient9, loadConfig as loadConfig9 } from "@clawrent/provider";
|
|
624
305
|
function registerEndCommand(program2) {
|
|
625
306
|
program2.command("end <sessionId>").description("End a session").action(async (sessionId) => {
|
|
626
307
|
try {
|
|
627
|
-
const client = new
|
|
308
|
+
const client = new ApiClient9(loadConfig9());
|
|
628
309
|
const result = await client.endSession(sessionId);
|
|
629
310
|
printJson(result);
|
|
630
311
|
} catch (err) {
|
|
@@ -636,11 +317,12 @@ function registerEndCommand(program2) {
|
|
|
636
317
|
|
|
637
318
|
// src/commands/send.ts
|
|
638
319
|
import WebSocket from "ws";
|
|
320
|
+
import { ApiClient as ApiClient10, loadConfig as loadConfig10 } from "@clawrent/provider";
|
|
639
321
|
function registerSendCommand(program2) {
|
|
640
322
|
program2.command("send <sessionId>").description("Send a message to a session via WebSocket").requiredOption("--content <text>", "Message content").option("--type <messageType>", "Message type", "dialogue.message").option("--token <sessionToken>", "Session token (auto-fetched if not provided)").option("--slot <index>", "Slot index for consumer role (default: 0)", "0").option("--wait <ms>", "Wait for response (milliseconds)").action(async (sessionId, opts) => {
|
|
641
323
|
try {
|
|
642
|
-
const config =
|
|
643
|
-
const client = new
|
|
324
|
+
const config = loadConfig10();
|
|
325
|
+
const client = new ApiClient10(config);
|
|
644
326
|
let sessionToken = opts.token;
|
|
645
327
|
let role = "consumer";
|
|
646
328
|
if (!sessionToken) {
|
|
@@ -715,6 +397,7 @@ function registerSendCommand(program2) {
|
|
|
715
397
|
}
|
|
716
398
|
|
|
717
399
|
// src/commands/provider/index.ts
|
|
400
|
+
import { ApiClient as ApiClient11, loadConfig as loadConfig11 } from "@clawrent/provider";
|
|
718
401
|
function registerProviderCommands(program2) {
|
|
719
402
|
const provider = program2.command("provider").description("Provider operations");
|
|
720
403
|
const agent = provider.command("agent").description("Manage your agents");
|
|
@@ -742,7 +425,7 @@ function registerProviderCommands(program2) {
|
|
|
742
425
|
process.exit(1);
|
|
743
426
|
}
|
|
744
427
|
}
|
|
745
|
-
const client = new
|
|
428
|
+
const client = new ApiClient11(loadConfig11());
|
|
746
429
|
const result = await client.registerAgent(data);
|
|
747
430
|
printJson(result);
|
|
748
431
|
} catch (err) {
|
|
@@ -752,7 +435,7 @@ function registerProviderCommands(program2) {
|
|
|
752
435
|
});
|
|
753
436
|
agent.command("list").description("List your agents").option("-r, --roles <roles>", "Filter by roles (consumer, both)").option("-p, --page <number>", "Page number", "1").option("-l, --limit <number>", "Results per page", "20").action(async (opts) => {
|
|
754
437
|
try {
|
|
755
|
-
const client = new
|
|
438
|
+
const client = new ApiClient11(loadConfig11());
|
|
756
439
|
const result = await client.getMyAgents({
|
|
757
440
|
roles: opts.roles,
|
|
758
441
|
page: parseInt(opts.page, 10),
|
|
@@ -766,7 +449,7 @@ function registerProviderCommands(program2) {
|
|
|
766
449
|
});
|
|
767
450
|
agent.command("apply-provider <agentId>").description("Apply for provider role on an agent").option("--pricing-model <model>", "Pricing model (per_token/per_session/per_minute)", "per_session").option("--price <amount>", "Price amount", "1.00").option("--currency <cur>", "Currency (CNY/USD)", "CNY").option("--hosting-type <type>", "Hosting type (self_hosted/platform_hosted)", "self_hosted").option("--approval-mode <mode>", "Session approval mode (manual/auto)", "manual").option("--max-concurrent <n>", "Max concurrent sessions", "5").option("--max-slots <n>", "Max consumer slots per session", "1").action(async (agentId, opts) => {
|
|
768
451
|
try {
|
|
769
|
-
const client = new
|
|
452
|
+
const client = new ApiClient11(loadConfig11());
|
|
770
453
|
const result = await client.applyProvider(agentId, {
|
|
771
454
|
pricingModel: opts.pricingModel,
|
|
772
455
|
priceAmount: opts.price,
|
|
@@ -785,7 +468,7 @@ function registerProviderCommands(program2) {
|
|
|
785
468
|
});
|
|
786
469
|
agent.command("status <agentId>").description("Set agent online status").requiredOption("--status <status>", "Online status (online/offline/busy)").action(async (agentId, opts) => {
|
|
787
470
|
try {
|
|
788
|
-
const client = new
|
|
471
|
+
const client = new ApiClient11(loadConfig11());
|
|
789
472
|
const result = await client.setOnlineStatus(agentId, opts.status);
|
|
790
473
|
printSuccess(`Agent status set to ${opts.status}.`);
|
|
791
474
|
printJson(result);
|
|
@@ -796,7 +479,7 @@ function registerProviderCommands(program2) {
|
|
|
796
479
|
});
|
|
797
480
|
provider.command("sessions").description("List provider sessions").option("-s, --status <status>", "Filter by status").option("-p, --page <number>", "Page number", "1").option("-l, --limit <number>", "Results per page", "20").action(async (opts) => {
|
|
798
481
|
try {
|
|
799
|
-
const client = new
|
|
482
|
+
const client = new ApiClient11(loadConfig11());
|
|
800
483
|
const result = await client.getSessions({
|
|
801
484
|
role: "provider",
|
|
802
485
|
status: opts.status,
|
|
@@ -811,7 +494,7 @@ function registerProviderCommands(program2) {
|
|
|
811
494
|
});
|
|
812
495
|
provider.command("approve <sessionId>").description("Approve a pending session").action(async (sessionId) => {
|
|
813
496
|
try {
|
|
814
|
-
const client = new
|
|
497
|
+
const client = new ApiClient11(loadConfig11());
|
|
815
498
|
const result = await client.approveSession(sessionId);
|
|
816
499
|
printSuccess("Session approved.");
|
|
817
500
|
printJson(result);
|
|
@@ -823,21 +506,23 @@ function registerProviderCommands(program2) {
|
|
|
823
506
|
}
|
|
824
507
|
|
|
825
508
|
// src/serve/index.ts
|
|
826
|
-
import
|
|
509
|
+
import WebSocket2 from "ws";
|
|
510
|
+
import { ApiClient as ApiClient12, loadConfig as loadConfig12, SessionManager, resumeActiveSessions } from "@clawrent/provider";
|
|
827
511
|
|
|
828
512
|
// src/daemon.ts
|
|
829
|
-
import { readFileSync
|
|
830
|
-
import { join
|
|
513
|
+
import { readFileSync, writeFileSync, unlinkSync, openSync, closeSync, mkdirSync, existsSync, readdirSync } from "fs";
|
|
514
|
+
import { join, basename } from "path";
|
|
831
515
|
import { spawn } from "child_process";
|
|
516
|
+
import { getConfigDir } from "@clawrent/provider";
|
|
832
517
|
function getPidFilePath(agentId) {
|
|
833
|
-
return
|
|
518
|
+
return join(getConfigDir(), `serve-${agentId}.pid`);
|
|
834
519
|
}
|
|
835
520
|
function getLogFilePath(agentId) {
|
|
836
|
-
return
|
|
521
|
+
return join(getConfigDir(), `serve-${agentId}.log`);
|
|
837
522
|
}
|
|
838
523
|
function readPid(agentId) {
|
|
839
524
|
try {
|
|
840
|
-
const content =
|
|
525
|
+
const content = readFileSync(getPidFilePath(agentId), "utf-8").trim();
|
|
841
526
|
const pid = parseInt(content, 10);
|
|
842
527
|
return Number.isFinite(pid) && pid > 0 ? pid : null;
|
|
843
528
|
} catch {
|
|
@@ -846,14 +531,14 @@ function readPid(agentId) {
|
|
|
846
531
|
}
|
|
847
532
|
function writePid(agentId, pid) {
|
|
848
533
|
const dir = getConfigDir();
|
|
849
|
-
if (!
|
|
850
|
-
|
|
534
|
+
if (!existsSync(dir)) {
|
|
535
|
+
mkdirSync(dir, { recursive: true });
|
|
851
536
|
}
|
|
852
|
-
|
|
537
|
+
writeFileSync(getPidFilePath(agentId), String(pid), "utf-8");
|
|
853
538
|
}
|
|
854
539
|
function removePidFile(agentId) {
|
|
855
540
|
try {
|
|
856
|
-
|
|
541
|
+
unlinkSync(getPidFilePath(agentId));
|
|
857
542
|
} catch {
|
|
858
543
|
}
|
|
859
544
|
}
|
|
@@ -876,7 +561,7 @@ function isDaemonRunning(agentId) {
|
|
|
876
561
|
}
|
|
877
562
|
function listRunningDaemons() {
|
|
878
563
|
const dir = getConfigDir();
|
|
879
|
-
if (!
|
|
564
|
+
if (!existsSync(dir)) return [];
|
|
880
565
|
const results = [];
|
|
881
566
|
for (const file of readdirSync(dir)) {
|
|
882
567
|
const match = /^serve-(.+)\.pid$/.exec(basename(file));
|
|
@@ -892,8 +577,8 @@ function listRunningDaemons() {
|
|
|
892
577
|
function spawnDaemon(agentId, args) {
|
|
893
578
|
const logFile = getLogFilePath(agentId);
|
|
894
579
|
const dir = getConfigDir();
|
|
895
|
-
if (!
|
|
896
|
-
|
|
580
|
+
if (!existsSync(dir)) {
|
|
581
|
+
mkdirSync(dir, { recursive: true });
|
|
897
582
|
}
|
|
898
583
|
const logFd = openSync(logFile, "a");
|
|
899
584
|
const child = spawn(process.argv[0], [process.argv[1], ...args], {
|
|
@@ -965,138 +650,6 @@ var StdioBridge = class {
|
|
|
965
650
|
}
|
|
966
651
|
};
|
|
967
652
|
|
|
968
|
-
// src/serve/session-manager.ts
|
|
969
|
-
import { EventEmitter } from "events";
|
|
970
|
-
import WebSocket2 from "ws";
|
|
971
|
-
var TERMINAL_CLOSE_CODES = /* @__PURE__ */ new Set([4e3, 4001, 4002, 4003, 4004]);
|
|
972
|
-
var SessionManager = class extends EventEmitter {
|
|
973
|
-
sessions = /* @__PURE__ */ new Map();
|
|
974
|
-
wsUrl;
|
|
975
|
-
heartbeatInterval;
|
|
976
|
-
maxReconnectDelay;
|
|
977
|
-
maxReconnectAttempts;
|
|
978
|
-
agentId;
|
|
979
|
-
constructor(wsUrl, heartbeatInterval = 25e3, maxReconnectDelay = 3e4, maxReconnectAttempts = 5) {
|
|
980
|
-
super();
|
|
981
|
-
this.wsUrl = wsUrl;
|
|
982
|
-
this.heartbeatInterval = heartbeatInterval;
|
|
983
|
-
this.maxReconnectDelay = maxReconnectDelay;
|
|
984
|
-
this.maxReconnectAttempts = maxReconnectAttempts;
|
|
985
|
-
}
|
|
986
|
-
/** Connect to a session via WebSocket as provider */
|
|
987
|
-
connect(sessionId, sessionToken) {
|
|
988
|
-
if (this.sessions.has(sessionId)) {
|
|
989
|
-
return;
|
|
990
|
-
}
|
|
991
|
-
const url = `${this.wsUrl}/ws/session?sessionId=${sessionId}&token=${sessionToken}&role=provider`;
|
|
992
|
-
const ws = new WebSocket2(url);
|
|
993
|
-
const conn = {
|
|
994
|
-
sessionId,
|
|
995
|
-
sessionToken,
|
|
996
|
-
ws,
|
|
997
|
-
heartbeatTimer: null,
|
|
998
|
-
reconnectAttempts: 0
|
|
999
|
-
};
|
|
1000
|
-
this.sessions.set(sessionId, conn);
|
|
1001
|
-
ws.on("open", () => {
|
|
1002
|
-
conn.reconnectAttempts = 0;
|
|
1003
|
-
conn.heartbeatTimer = setInterval(() => {
|
|
1004
|
-
if (ws.readyState === WebSocket2.OPEN) {
|
|
1005
|
-
ws.send(JSON.stringify({ type: "system.heartbeat", payload: {} }));
|
|
1006
|
-
}
|
|
1007
|
-
}, this.heartbeatInterval);
|
|
1008
|
-
this.emit("session:connected", sessionId);
|
|
1009
|
-
});
|
|
1010
|
-
ws.on("message", (raw) => {
|
|
1011
|
-
try {
|
|
1012
|
-
const message = JSON.parse(raw.toString());
|
|
1013
|
-
if (message["type"] === "system.heartbeat_ack") return;
|
|
1014
|
-
this.emit("session:message", sessionId, message);
|
|
1015
|
-
} catch {
|
|
1016
|
-
}
|
|
1017
|
-
});
|
|
1018
|
-
ws.on("close", (code, reason) => {
|
|
1019
|
-
this.clearHeartbeat(conn);
|
|
1020
|
-
if (TERMINAL_CLOSE_CODES.has(code)) {
|
|
1021
|
-
this.sessions.delete(sessionId);
|
|
1022
|
-
this.emit("session:dead", sessionId, `session rejected (code ${code}: ${reason.toString()})`);
|
|
1023
|
-
return;
|
|
1024
|
-
}
|
|
1025
|
-
if (code !== 1e3) {
|
|
1026
|
-
if (conn.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
1027
|
-
this.sessions.delete(sessionId);
|
|
1028
|
-
this.emit("session:dead", sessionId, `max reconnect attempts (${this.maxReconnectAttempts}) reached`);
|
|
1029
|
-
return;
|
|
1030
|
-
}
|
|
1031
|
-
const delay = Math.min(
|
|
1032
|
-
1e3 * Math.pow(2, conn.reconnectAttempts),
|
|
1033
|
-
this.maxReconnectDelay
|
|
1034
|
-
);
|
|
1035
|
-
conn.reconnectAttempts++;
|
|
1036
|
-
this.emit("session:reconnecting", sessionId, delay);
|
|
1037
|
-
setTimeout(() => {
|
|
1038
|
-
this.sessions.delete(sessionId);
|
|
1039
|
-
this.connect(sessionId, sessionToken);
|
|
1040
|
-
}, delay);
|
|
1041
|
-
} else {
|
|
1042
|
-
this.sessions.delete(sessionId);
|
|
1043
|
-
this.emit("session:disconnected", sessionId, reason.toString());
|
|
1044
|
-
}
|
|
1045
|
-
});
|
|
1046
|
-
ws.on("error", (err) => {
|
|
1047
|
-
this.emit("session:error", sessionId, err);
|
|
1048
|
-
});
|
|
1049
|
-
}
|
|
1050
|
-
/** Send a message to a specific session, auto-wrapping with protocol envelope */
|
|
1051
|
-
send(sessionId, message) {
|
|
1052
|
-
const conn = this.sessions.get(sessionId);
|
|
1053
|
-
if (!conn || conn.ws.readyState !== WebSocket2.OPEN) {
|
|
1054
|
-
return false;
|
|
1055
|
-
}
|
|
1056
|
-
const envelope = {
|
|
1057
|
-
id: message["id"] ?? `msg_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,
|
|
1058
|
-
sessionId: message["sessionId"] ?? sessionId,
|
|
1059
|
-
timestamp: message["timestamp"] ?? Date.now(),
|
|
1060
|
-
sender: message["sender"] ?? { role: "provider", agentId: this.agentId ?? "unknown" },
|
|
1061
|
-
type: message["type"] ?? "result.success",
|
|
1062
|
-
payload: message["payload"] ?? {}
|
|
1063
|
-
};
|
|
1064
|
-
conn.ws.send(JSON.stringify(envelope));
|
|
1065
|
-
return true;
|
|
1066
|
-
}
|
|
1067
|
-
/** Disconnect a specific session */
|
|
1068
|
-
disconnect(sessionId) {
|
|
1069
|
-
const conn = this.sessions.get(sessionId);
|
|
1070
|
-
if (!conn) return;
|
|
1071
|
-
this.clearHeartbeat(conn);
|
|
1072
|
-
if (conn.ws.readyState === WebSocket2.OPEN || conn.ws.readyState === WebSocket2.CONNECTING) {
|
|
1073
|
-
conn.ws.close(1e3, "Provider disconnecting");
|
|
1074
|
-
}
|
|
1075
|
-
this.sessions.delete(sessionId);
|
|
1076
|
-
}
|
|
1077
|
-
/** Disconnect all sessions */
|
|
1078
|
-
disconnectAll() {
|
|
1079
|
-
for (const sessionId of this.sessions.keys()) {
|
|
1080
|
-
this.disconnect(sessionId);
|
|
1081
|
-
}
|
|
1082
|
-
}
|
|
1083
|
-
/** Get active session count */
|
|
1084
|
-
get activeCount() {
|
|
1085
|
-
return this.sessions.size;
|
|
1086
|
-
}
|
|
1087
|
-
/** Check if a session is connected */
|
|
1088
|
-
isConnected(sessionId) {
|
|
1089
|
-
const conn = this.sessions.get(sessionId);
|
|
1090
|
-
return conn?.ws.readyState === WebSocket2.OPEN;
|
|
1091
|
-
}
|
|
1092
|
-
clearHeartbeat(conn) {
|
|
1093
|
-
if (conn.heartbeatTimer) {
|
|
1094
|
-
clearInterval(conn.heartbeatTimer);
|
|
1095
|
-
conn.heartbeatTimer = null;
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
};
|
|
1099
|
-
|
|
1100
653
|
// src/serve/protocol.ts
|
|
1101
654
|
var correlationCounter = 0;
|
|
1102
655
|
function createCorrelationId() {
|
|
@@ -1117,9 +670,9 @@ function registerServeCommand(program2) {
|
|
|
1117
670
|
program2.command("serve").description("Start serve daemon - bridge WebSocket sessions to stdin/stdout").requiredOption("--agent-token <token>", "Agent token (agt_clawrent_*) for authentication").option("--auto-approve", "Automatically approve incoming sessions", false).option("--poll-interval <ms>", "Polling interval for pending sessions (ms)", "5000").option("-d, --daemon", "Run in background as a daemon process", false).action(async (opts) => {
|
|
1118
671
|
try {
|
|
1119
672
|
if (opts.daemon) {
|
|
1120
|
-
const config =
|
|
673
|
+
const config = loadConfig12();
|
|
1121
674
|
config.token = opts.agentToken;
|
|
1122
|
-
const client = new
|
|
675
|
+
const client = new ApiClient12(config);
|
|
1123
676
|
let agentId;
|
|
1124
677
|
try {
|
|
1125
678
|
const agent = await client.getMyAgent();
|
|
@@ -1150,9 +703,9 @@ Logs: ${getLogFilePath(agentId)}`);
|
|
|
1150
703
|
});
|
|
1151
704
|
}
|
|
1152
705
|
async function runDaemon(opts) {
|
|
1153
|
-
const config =
|
|
706
|
+
const config = loadConfig12();
|
|
1154
707
|
config.token = opts.agentToken;
|
|
1155
|
-
const client = new
|
|
708
|
+
const client = new ApiClient12(config);
|
|
1156
709
|
const bridge = new StdioBridge();
|
|
1157
710
|
const sessionManager = new SessionManager(config.wsUrl);
|
|
1158
711
|
const pollInterval = parseInt(opts.pollInterval, 10);
|
|
@@ -1261,11 +814,11 @@ async function runDaemon(opts) {
|
|
|
1261
814
|
function connectAgentWs(token) {
|
|
1262
815
|
const wsBase = config.wsUrl ?? config.apiUrl.replace(/^http/, "ws");
|
|
1263
816
|
const url = `${wsBase}/ws/agent?token=${token}`;
|
|
1264
|
-
agentWs = new
|
|
817
|
+
agentWs = new WebSocket2(url);
|
|
1265
818
|
agentWs.on("open", () => {
|
|
1266
819
|
bridge.writeNotification("agent.connected", { agentId });
|
|
1267
820
|
agentHeartbeatTimer = setInterval(() => {
|
|
1268
|
-
if (agentWs && agentWs.readyState ===
|
|
821
|
+
if (agentWs && agentWs.readyState === WebSocket2.OPEN) {
|
|
1269
822
|
agentWs.send(JSON.stringify({ type: "system.heartbeat", payload: {} }));
|
|
1270
823
|
}
|
|
1271
824
|
}, 25e3);
|
|
@@ -1354,8 +907,28 @@ async function runDaemon(opts) {
|
|
|
1354
907
|
}, pollInterval);
|
|
1355
908
|
}
|
|
1356
909
|
connectAgentWs(opts.agentToken);
|
|
1357
|
-
void
|
|
1358
|
-
|
|
910
|
+
void (async () => {
|
|
911
|
+
try {
|
|
912
|
+
const resumed = await resumeActiveSessions(client, sessionManager);
|
|
913
|
+
for (const s of resumed) {
|
|
914
|
+
if (activeSessions.has(s.sessionId) || knownPendingSessions.has(s.sessionId)) continue;
|
|
915
|
+
activeSessions.add(s.sessionId);
|
|
916
|
+
knownPendingSessions.add(s.sessionId);
|
|
917
|
+
bridge.writeNotification("session.new", {
|
|
918
|
+
sessionId: s.sessionId,
|
|
919
|
+
sessionToken: s.sessionToken,
|
|
920
|
+
taskDescription: s.taskDescription ?? "",
|
|
921
|
+
consumerUserId: s.consumerUserId ?? "",
|
|
922
|
+
slotIndex: s.slotIndex ?? 0,
|
|
923
|
+
reattached: true
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
} catch (err) {
|
|
927
|
+
bridge.writeNotification("session.reattach_failed", {
|
|
928
|
+
error: err instanceof Error ? err.message : String(err)
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
})();
|
|
1359
932
|
const shutdown = async () => {
|
|
1360
933
|
if (pollTimer) clearInterval(pollTimer);
|
|
1361
934
|
if (agentHeartbeatTimer) clearInterval(agentHeartbeatTimer);
|
|
@@ -1398,31 +971,6 @@ async function approveAndConnect(client, sessionManager, bridge, sessionId) {
|
|
|
1398
971
|
});
|
|
1399
972
|
}
|
|
1400
973
|
}
|
|
1401
|
-
async function reattachActiveSessions(client, sessionManager, bridge) {
|
|
1402
|
-
try {
|
|
1403
|
-
const res = await client.getSessions({ role: "provider", status: "active" });
|
|
1404
|
-
const active = res?.data ?? [];
|
|
1405
|
-
for (const s of active) {
|
|
1406
|
-
if (activeSessions.has(s.id) || knownPendingSessions.has(s.id)) continue;
|
|
1407
|
-
if (!s.sessionToken) continue;
|
|
1408
|
-
activeSessions.add(s.id);
|
|
1409
|
-
knownPendingSessions.add(s.id);
|
|
1410
|
-
bridge.writeNotification("session.new", {
|
|
1411
|
-
sessionId: s.id,
|
|
1412
|
-
sessionToken: s.sessionToken,
|
|
1413
|
-
taskDescription: s.taskDescription ?? "",
|
|
1414
|
-
consumerUserId: s.consumerUserId ?? "",
|
|
1415
|
-
slotIndex: 0,
|
|
1416
|
-
reattached: true
|
|
1417
|
-
});
|
|
1418
|
-
sessionManager.connect(s.id, s.sessionToken);
|
|
1419
|
-
}
|
|
1420
|
-
} catch (err) {
|
|
1421
|
-
bridge.writeNotification("session.reattach_failed", {
|
|
1422
|
-
error: err instanceof Error ? err.message : String(err)
|
|
1423
|
-
});
|
|
1424
|
-
}
|
|
1425
|
-
}
|
|
1426
974
|
|
|
1427
975
|
// src/commands/stop.ts
|
|
1428
976
|
async function stopOne(agentId) {
|
|
@@ -1513,7 +1061,7 @@ function registerStatusCommand(program2) {
|
|
|
1513
1061
|
|
|
1514
1062
|
// src/index.ts
|
|
1515
1063
|
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
1516
|
-
var pkg = JSON.parse(
|
|
1064
|
+
var pkg = JSON.parse(readFileSync2(join2(__dirname, "..", "package.json"), "utf-8"));
|
|
1517
1065
|
var program = new Command();
|
|
1518
1066
|
program.name("clawrent").description("ClawRent CLI - Agent capability rental platform").version(pkg.version);
|
|
1519
1067
|
registerAuthCommand(program);
|