@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 CHANGED
@@ -1,341 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { readFileSync as readFileSync3 } from "fs";
5
- import { dirname, join as join3 } from "path";
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 ApiClient(loadConfig());
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 ApiClient(loadConfig());
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 ApiClient(loadConfig());
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 ApiClient(loadConfig());
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 ApiClient(loadConfig());
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 ApiClient(loadConfig());
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 ApiClient(loadConfig());
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 ApiClient(loadConfig());
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 = loadConfig();
643
- const client = new ApiClient(config);
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 ApiClient(loadConfig());
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 ApiClient(loadConfig());
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 ApiClient(loadConfig());
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 ApiClient(loadConfig());
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 ApiClient(loadConfig());
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 ApiClient(loadConfig());
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 WebSocket3 from "ws";
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 as readFileSync2, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2, openSync, closeSync, mkdirSync as mkdirSync2, existsSync as existsSync2, readdirSync } from "fs";
830
- import { join as join2, basename } from "path";
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 join2(getConfigDir(), `serve-${agentId}.pid`);
518
+ return join(getConfigDir(), `serve-${agentId}.pid`);
834
519
  }
835
520
  function getLogFilePath(agentId) {
836
- return join2(getConfigDir(), `serve-${agentId}.log`);
521
+ return join(getConfigDir(), `serve-${agentId}.log`);
837
522
  }
838
523
  function readPid(agentId) {
839
524
  try {
840
- const content = readFileSync2(getPidFilePath(agentId), "utf-8").trim();
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 (!existsSync2(dir)) {
850
- mkdirSync2(dir, { recursive: true });
534
+ if (!existsSync(dir)) {
535
+ mkdirSync(dir, { recursive: true });
851
536
  }
852
- writeFileSync2(getPidFilePath(agentId), String(pid), "utf-8");
537
+ writeFileSync(getPidFilePath(agentId), String(pid), "utf-8");
853
538
  }
854
539
  function removePidFile(agentId) {
855
540
  try {
856
- unlinkSync2(getPidFilePath(agentId));
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 (!existsSync2(dir)) return [];
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 (!existsSync2(dir)) {
896
- mkdirSync2(dir, { recursive: true });
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 = loadConfig();
673
+ const config = loadConfig12();
1121
674
  config.token = opts.agentToken;
1122
- const client = new ApiClient(config);
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 = loadConfig();
706
+ const config = loadConfig12();
1154
707
  config.token = opts.agentToken;
1155
- const client = new ApiClient(config);
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 WebSocket3(url);
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 === WebSocket3.OPEN) {
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 reattachActiveSessions(client, sessionManager, bridge).catch(() => {
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(readFileSync3(join3(__dirname, "..", "package.json"), "utf-8"));
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);