@clawrent/cli 0.4.3 → 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,326 +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) {
162
- return this.request("GET", `/api/sessions/${encodeURIComponent(sessionId)}/messages`);
163
- }
164
- async endSession(sessionId) {
165
- return this.request("POST", `/api/sessions/${encodeURIComponent(sessionId)}/end`);
166
- }
167
- async approveSession(sessionId) {
168
- return this.request("POST", `/api/sessions/${encodeURIComponent(sessionId)}/approve`);
169
- }
170
- // --- Billing ---
171
- async getBalance() {
172
- return this.request("GET", "/api/billing/wallet");
173
- }
174
- async topUp(amount) {
175
- return this.request("POST", "/api/billing/wallet/topup", { amount });
176
- }
177
- // --- Provider: Agents ---
178
- async registerAgent(data) {
179
- return this.request("POST", "/api/agents", data);
180
- }
181
- async getMyAgents(query) {
182
- const params = new URLSearchParams();
183
- if (query?.page) params.set("page", String(query.page));
184
- if (query?.limit) params.set("limit", String(query.limit));
185
- if (query?.roles) params.set("roles", query.roles);
186
- const qs = params.toString();
187
- return this.request("GET", `/api/agents/my${qs ? `?${qs}` : ""}`);
188
- }
189
- /** Resolve the current agent from agentToken. Requires agt_clawrent_ token auth. */
190
- async getMyAgent() {
191
- return this.request("GET", "/api/agents/me/agent");
192
- }
193
- async applyProvider(agentId, data) {
194
- return this.request("POST", `/api/agents/${encodeURIComponent(agentId)}/apply-provider`, data);
195
- }
196
- /** Publish agent — simplified apply-provider with defaults, submits for admin review */
197
- async publishAgent(agentId, data) {
198
- return this.request("POST", `/api/agents/${encodeURIComponent(agentId)}/publish`, data ?? {});
199
- }
200
- /** Activate agent — verify admin-approved + WebSocket connected, then go online */
201
- async activateAgent(agentId) {
202
- return this.request("POST", `/api/agents/${encodeURIComponent(agentId)}/activate`);
203
- }
204
- async setOnlineStatus(agentId, onlineStatus) {
205
- return this.request("PATCH", `/api/agents/${encodeURIComponent(agentId)}/status`, { onlineStatus });
206
- }
207
- async generateAgentToken(agentId) {
208
- return this.request("POST", `/api/agents/${encodeURIComponent(agentId)}/token`);
209
- }
210
- async revokeAgentToken(agentId) {
211
- return this.request("DELETE", `/api/agents/${encodeURIComponent(agentId)}/token`);
212
- }
213
- // --- Orders ---
214
- async createOrder(data) {
215
- return this.request("POST", "/api/orders", data);
216
- }
217
- async getOrders(query) {
218
- const params = new URLSearchParams();
219
- if (query?.status) params.set("status", query.status);
220
- if (query?.page) params.set("page", String(query.page));
221
- if (query?.limit) params.set("limit", String(query.limit));
222
- const qs = params.toString();
223
- return this.request("GET", `/api/orders${qs ? `?${qs}` : ""}`);
224
- }
225
- async getOrder(orderId) {
226
- return this.request("GET", `/api/orders/${encodeURIComponent(orderId)}`);
227
- }
228
- async cancelOrder(orderId) {
229
- return this.request("POST", `/api/orders/${encodeURIComponent(orderId)}/cancel`);
230
- }
231
- // --- Cart ---
232
- async getCart() {
233
- return this.request("GET", "/api/cart");
234
- }
235
- async addToCart(data) {
236
- return this.request("POST", "/api/cart", data);
237
- }
238
- async updateCartItem(itemId, data) {
239
- return this.request("PATCH", `/api/cart/${encodeURIComponent(itemId)}`, data);
240
- }
241
- async removeFromCart(itemId) {
242
- return this.request("DELETE", `/api/cart/${encodeURIComponent(itemId)}`);
243
- }
244
- async clearCart() {
245
- return this.request("DELETE", "/api/cart");
246
- }
247
- // --- Favorites ---
248
- async listFavorites(query) {
249
- const params = new URLSearchParams();
250
- if (query?.page) params.set("page", String(query.page));
251
- if (query?.limit) params.set("limit", String(query.limit));
252
- const qs = params.toString();
253
- return this.request("GET", `/api/favorites${qs ? `?${qs}` : ""}`);
254
- }
255
- async addFavorite(agentId) {
256
- return this.request("POST", `/api/favorites/${encodeURIComponent(agentId)}`);
257
- }
258
- async removeFavorite(agentId) {
259
- return this.request("DELETE", `/api/favorites/${encodeURIComponent(agentId)}`);
260
- }
261
- // --- Health ---
262
- async health() {
263
- return this.request("GET", "/api/health", void 0, false);
264
- }
265
- // --- Docs (MCP interface) ---
266
- async getDocsTree() {
267
- return this.request("GET", "/api/mcp/docs/tree", void 0, false);
268
- }
269
- async getDocByPath(path) {
270
- return this.request("GET", `/api/mcp/docs/by-path/${encodeURI(path)}`, void 0, false);
271
- }
272
- async searchDocs(query) {
273
- const params = new URLSearchParams({ q: query });
274
- return this.request("GET", `/api/mcp/docs/search?${params.toString()}`, void 0, false);
275
- }
276
- async getDoc(id) {
277
- return this.request("GET", `/api/mcp/docs/${encodeURIComponent(id)}`, void 0, false);
278
- }
279
- async createDoc(data) {
280
- return this.request("POST", "/api/mcp/docs", data);
281
- }
282
- async updateDoc(id, data) {
283
- return this.request("PATCH", `/api/mcp/docs/${encodeURIComponent(id)}`, data);
284
- }
285
- async deleteDoc(id) {
286
- return this.request("DELETE", `/api/mcp/docs/${encodeURIComponent(id)}`);
287
- }
288
- async publishDoc(id) {
289
- return this.request("POST", `/api/mcp/docs/${encodeURIComponent(id)}/publish`);
290
- }
291
- async unpublishDoc(id) {
292
- return this.request("POST", `/api/mcp/docs/${encodeURIComponent(id)}/unpublish`);
293
- }
294
- // --- Private ---
295
- async request(method, path, body, requireAuth = true) {
296
- const url = `${this.config.apiUrl}${path}`;
297
- const headers = {};
298
- if (body !== void 0) {
299
- headers["Content-Type"] = "application/json";
300
- }
301
- if (requireAuth) {
302
- if (this.agentTokenOverride) {
303
- headers["Authorization"] = `Bearer ${this.agentTokenOverride}`;
304
- } else if (this.config.token) {
305
- headers["Authorization"] = `Bearer ${this.config.token}`;
306
- } else if (this.config.apiKey) {
307
- headers["x-api-key"] = this.config.apiKey;
308
- } else {
309
- throw new Error("Not authenticated. Run `clawrent auth login` first.");
310
- }
311
- }
312
- const response = await fetch(url, {
313
- method,
314
- headers,
315
- body: body ? JSON.stringify(body) : void 0
316
- });
317
- if (!response.ok) {
318
- const errBody = await response.json().catch(() => ({ message: response.statusText }));
319
- throw new Error(`API error ${response.status}: ${errBody["message"] ?? JSON.stringify(errBody)}`);
320
- }
321
- return response.json();
322
- }
323
- };
11
+ import { ApiClient, loadConfig, saveConfig, clearConfig, getConfigPath } from "@clawrent/provider";
324
12
 
325
13
  // src/output.ts
326
14
  function printJson(data) {
@@ -487,10 +175,11 @@ function registerAuthCommand(program2) {
487
175
  }
488
176
 
489
177
  // src/commands/browse.ts
178
+ import { ApiClient as ApiClient2, loadConfig as loadConfig2 } from "@clawrent/provider";
490
179
  function registerBrowseCommand(program2) {
491
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) => {
492
181
  try {
493
- const client = new ApiClient(loadConfig());
182
+ const client = new ApiClient2(loadConfig2());
494
183
  const result = await client.browse({
495
184
  search: opts.search,
496
185
  category: opts.category,
@@ -506,10 +195,11 @@ function registerBrowseCommand(program2) {
506
195
  }
507
196
 
508
197
  // src/commands/agent.ts
198
+ import { ApiClient as ApiClient3, loadConfig as loadConfig3 } from "@clawrent/provider";
509
199
  function registerAgentCommand(program2) {
510
200
  program2.command("agent <slug>").description("Get agent details by slug").action(async (slug) => {
511
201
  try {
512
- const client = new ApiClient(loadConfig());
202
+ const client = new ApiClient3(loadConfig3());
513
203
  const result = await client.getAgent(slug);
514
204
  printJson(result);
515
205
  } catch (err) {
@@ -520,10 +210,11 @@ function registerAgentCommand(program2) {
520
210
  }
521
211
 
522
212
  // src/commands/sessions.ts
213
+ import { ApiClient as ApiClient4, loadConfig as loadConfig4 } from "@clawrent/provider";
523
214
  function registerSessionsCommand(program2) {
524
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) => {
525
216
  try {
526
- const client = new ApiClient(loadConfig());
217
+ const client = new ApiClient4(loadConfig4());
527
218
  const result = await client.getSessions({
528
219
  role: opts.role,
529
220
  status: opts.status,
@@ -539,10 +230,11 @@ function registerSessionsCommand(program2) {
539
230
  }
540
231
 
541
232
  // src/commands/balance.ts
233
+ import { ApiClient as ApiClient5, loadConfig as loadConfig5 } from "@clawrent/provider";
542
234
  function registerBalanceCommand(program2) {
543
235
  program2.command("balance").description("Check wallet balance").action(async () => {
544
236
  try {
545
- const client = new ApiClient(loadConfig());
237
+ const client = new ApiClient5(loadConfig5());
546
238
  const result = await client.getBalance();
547
239
  printJson(result);
548
240
  } catch (err) {
@@ -553,10 +245,11 @@ function registerBalanceCommand(program2) {
553
245
  }
554
246
 
555
247
  // src/commands/topup.ts
248
+ import { ApiClient as ApiClient6, loadConfig as loadConfig6 } from "@clawrent/provider";
556
249
  function registerTopupCommand(program2) {
557
250
  program2.command("topup <amount>").description("Top up wallet balance").action(async (amount) => {
558
251
  try {
559
- const client = new ApiClient(loadConfig());
252
+ const client = new ApiClient6(loadConfig6());
560
253
  const result = await client.topUp(amount);
561
254
  printJson(result);
562
255
  } catch (err) {
@@ -567,10 +260,11 @@ function registerTopupCommand(program2) {
567
260
  }
568
261
 
569
262
  // src/commands/health.ts
263
+ import { ApiClient as ApiClient7, loadConfig as loadConfig7 } from "@clawrent/provider";
570
264
  function registerHealthCommand(program2) {
571
265
  program2.command("health").description("Check platform health").action(async () => {
572
266
  try {
573
- const client = new ApiClient(loadConfig());
267
+ const client = new ApiClient7(loadConfig7());
574
268
  const result = await client.health();
575
269
  printJson(result);
576
270
  } catch (err) {
@@ -581,6 +275,7 @@ function registerHealthCommand(program2) {
581
275
  }
582
276
 
583
277
  // src/commands/rent.ts
278
+ import { ApiClient as ApiClient8, loadConfig as loadConfig8 } from "@clawrent/provider";
584
279
  function registerRentCommand(program2) {
585
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) => {
586
281
  try {
@@ -591,7 +286,7 @@ function registerRentCommand(program2) {
591
286
  printError("Invalid JSON for --permissions");
592
287
  process.exit(1);
593
288
  }
594
- const client = new ApiClient(loadConfig());
289
+ const client = new ApiClient8(loadConfig8());
595
290
  const result = await client.rent({
596
291
  agentId: opts.agentId,
597
292
  taskDescription: opts.task,
@@ -606,10 +301,11 @@ function registerRentCommand(program2) {
606
301
  }
607
302
 
608
303
  // src/commands/end.ts
304
+ import { ApiClient as ApiClient9, loadConfig as loadConfig9 } from "@clawrent/provider";
609
305
  function registerEndCommand(program2) {
610
306
  program2.command("end <sessionId>").description("End a session").action(async (sessionId) => {
611
307
  try {
612
- const client = new ApiClient(loadConfig());
308
+ const client = new ApiClient9(loadConfig9());
613
309
  const result = await client.endSession(sessionId);
614
310
  printJson(result);
615
311
  } catch (err) {
@@ -621,11 +317,12 @@ function registerEndCommand(program2) {
621
317
 
622
318
  // src/commands/send.ts
623
319
  import WebSocket from "ws";
320
+ import { ApiClient as ApiClient10, loadConfig as loadConfig10 } from "@clawrent/provider";
624
321
  function registerSendCommand(program2) {
625
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) => {
626
323
  try {
627
- const config = loadConfig();
628
- const client = new ApiClient(config);
324
+ const config = loadConfig10();
325
+ const client = new ApiClient10(config);
629
326
  let sessionToken = opts.token;
630
327
  let role = "consumer";
631
328
  if (!sessionToken) {
@@ -700,6 +397,7 @@ function registerSendCommand(program2) {
700
397
  }
701
398
 
702
399
  // src/commands/provider/index.ts
400
+ import { ApiClient as ApiClient11, loadConfig as loadConfig11 } from "@clawrent/provider";
703
401
  function registerProviderCommands(program2) {
704
402
  const provider = program2.command("provider").description("Provider operations");
705
403
  const agent = provider.command("agent").description("Manage your agents");
@@ -727,7 +425,7 @@ function registerProviderCommands(program2) {
727
425
  process.exit(1);
728
426
  }
729
427
  }
730
- const client = new ApiClient(loadConfig());
428
+ const client = new ApiClient11(loadConfig11());
731
429
  const result = await client.registerAgent(data);
732
430
  printJson(result);
733
431
  } catch (err) {
@@ -737,7 +435,7 @@ function registerProviderCommands(program2) {
737
435
  });
738
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) => {
739
437
  try {
740
- const client = new ApiClient(loadConfig());
438
+ const client = new ApiClient11(loadConfig11());
741
439
  const result = await client.getMyAgents({
742
440
  roles: opts.roles,
743
441
  page: parseInt(opts.page, 10),
@@ -751,7 +449,7 @@ function registerProviderCommands(program2) {
751
449
  });
752
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) => {
753
451
  try {
754
- const client = new ApiClient(loadConfig());
452
+ const client = new ApiClient11(loadConfig11());
755
453
  const result = await client.applyProvider(agentId, {
756
454
  pricingModel: opts.pricingModel,
757
455
  priceAmount: opts.price,
@@ -770,7 +468,7 @@ function registerProviderCommands(program2) {
770
468
  });
771
469
  agent.command("status <agentId>").description("Set agent online status").requiredOption("--status <status>", "Online status (online/offline/busy)").action(async (agentId, opts) => {
772
470
  try {
773
- const client = new ApiClient(loadConfig());
471
+ const client = new ApiClient11(loadConfig11());
774
472
  const result = await client.setOnlineStatus(agentId, opts.status);
775
473
  printSuccess(`Agent status set to ${opts.status}.`);
776
474
  printJson(result);
@@ -781,7 +479,7 @@ function registerProviderCommands(program2) {
781
479
  });
782
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) => {
783
481
  try {
784
- const client = new ApiClient(loadConfig());
482
+ const client = new ApiClient11(loadConfig11());
785
483
  const result = await client.getSessions({
786
484
  role: "provider",
787
485
  status: opts.status,
@@ -796,7 +494,7 @@ function registerProviderCommands(program2) {
796
494
  });
797
495
  provider.command("approve <sessionId>").description("Approve a pending session").action(async (sessionId) => {
798
496
  try {
799
- const client = new ApiClient(loadConfig());
497
+ const client = new ApiClient11(loadConfig11());
800
498
  const result = await client.approveSession(sessionId);
801
499
  printSuccess("Session approved.");
802
500
  printJson(result);
@@ -808,21 +506,23 @@ function registerProviderCommands(program2) {
808
506
  }
809
507
 
810
508
  // src/serve/index.ts
811
- import WebSocket3 from "ws";
509
+ import WebSocket2 from "ws";
510
+ import { ApiClient as ApiClient12, loadConfig as loadConfig12, SessionManager, resumeActiveSessions } from "@clawrent/provider";
812
511
 
813
512
  // src/daemon.ts
814
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2, openSync, closeSync, mkdirSync as mkdirSync2, existsSync as existsSync2, readdirSync } from "fs";
815
- 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";
816
515
  import { spawn } from "child_process";
516
+ import { getConfigDir } from "@clawrent/provider";
817
517
  function getPidFilePath(agentId) {
818
- return join2(getConfigDir(), `serve-${agentId}.pid`);
518
+ return join(getConfigDir(), `serve-${agentId}.pid`);
819
519
  }
820
520
  function getLogFilePath(agentId) {
821
- return join2(getConfigDir(), `serve-${agentId}.log`);
521
+ return join(getConfigDir(), `serve-${agentId}.log`);
822
522
  }
823
523
  function readPid(agentId) {
824
524
  try {
825
- const content = readFileSync2(getPidFilePath(agentId), "utf-8").trim();
525
+ const content = readFileSync(getPidFilePath(agentId), "utf-8").trim();
826
526
  const pid = parseInt(content, 10);
827
527
  return Number.isFinite(pid) && pid > 0 ? pid : null;
828
528
  } catch {
@@ -831,14 +531,14 @@ function readPid(agentId) {
831
531
  }
832
532
  function writePid(agentId, pid) {
833
533
  const dir = getConfigDir();
834
- if (!existsSync2(dir)) {
835
- mkdirSync2(dir, { recursive: true });
534
+ if (!existsSync(dir)) {
535
+ mkdirSync(dir, { recursive: true });
836
536
  }
837
- writeFileSync2(getPidFilePath(agentId), String(pid), "utf-8");
537
+ writeFileSync(getPidFilePath(agentId), String(pid), "utf-8");
838
538
  }
839
539
  function removePidFile(agentId) {
840
540
  try {
841
- unlinkSync2(getPidFilePath(agentId));
541
+ unlinkSync(getPidFilePath(agentId));
842
542
  } catch {
843
543
  }
844
544
  }
@@ -861,7 +561,7 @@ function isDaemonRunning(agentId) {
861
561
  }
862
562
  function listRunningDaemons() {
863
563
  const dir = getConfigDir();
864
- if (!existsSync2(dir)) return [];
564
+ if (!existsSync(dir)) return [];
865
565
  const results = [];
866
566
  for (const file of readdirSync(dir)) {
867
567
  const match = /^serve-(.+)\.pid$/.exec(basename(file));
@@ -877,8 +577,8 @@ function listRunningDaemons() {
877
577
  function spawnDaemon(agentId, args) {
878
578
  const logFile = getLogFilePath(agentId);
879
579
  const dir = getConfigDir();
880
- if (!existsSync2(dir)) {
881
- mkdirSync2(dir, { recursive: true });
580
+ if (!existsSync(dir)) {
581
+ mkdirSync(dir, { recursive: true });
882
582
  }
883
583
  const logFd = openSync(logFile, "a");
884
584
  const child = spawn(process.argv[0], [process.argv[1], ...args], {
@@ -950,125 +650,6 @@ var StdioBridge = class {
950
650
  }
951
651
  };
952
652
 
953
- // src/serve/session-manager.ts
954
- import { EventEmitter } from "events";
955
- import WebSocket2 from "ws";
956
- var SessionManager = class extends EventEmitter {
957
- sessions = /* @__PURE__ */ new Map();
958
- wsUrl;
959
- heartbeatInterval;
960
- maxReconnectDelay;
961
- agentId;
962
- constructor(wsUrl, heartbeatInterval = 25e3, maxReconnectDelay = 3e4) {
963
- super();
964
- this.wsUrl = wsUrl;
965
- this.heartbeatInterval = heartbeatInterval;
966
- this.maxReconnectDelay = maxReconnectDelay;
967
- }
968
- /** Connect to a session via WebSocket as provider */
969
- connect(sessionId, sessionToken) {
970
- if (this.sessions.has(sessionId)) {
971
- return;
972
- }
973
- const url = `${this.wsUrl}/ws/session?sessionId=${sessionId}&token=${sessionToken}&role=provider`;
974
- const ws = new WebSocket2(url);
975
- const conn = {
976
- sessionId,
977
- sessionToken,
978
- ws,
979
- heartbeatTimer: null,
980
- reconnectAttempts: 0
981
- };
982
- this.sessions.set(sessionId, conn);
983
- ws.on("open", () => {
984
- conn.reconnectAttempts = 0;
985
- conn.heartbeatTimer = setInterval(() => {
986
- if (ws.readyState === WebSocket2.OPEN) {
987
- ws.send(JSON.stringify({ type: "system.heartbeat", payload: {} }));
988
- }
989
- }, this.heartbeatInterval);
990
- this.emit("session:connected", sessionId);
991
- });
992
- ws.on("message", (raw) => {
993
- try {
994
- const message = JSON.parse(raw.toString());
995
- if (message["type"] === "system.heartbeat_ack") return;
996
- this.emit("session:message", sessionId, message);
997
- } catch {
998
- }
999
- });
1000
- ws.on("close", (code, reason) => {
1001
- this.clearHeartbeat(conn);
1002
- if (code !== 1e3) {
1003
- const delay = Math.min(
1004
- 1e3 * Math.pow(2, conn.reconnectAttempts),
1005
- this.maxReconnectDelay
1006
- );
1007
- conn.reconnectAttempts++;
1008
- this.emit("session:reconnecting", sessionId, delay);
1009
- setTimeout(() => {
1010
- this.sessions.delete(sessionId);
1011
- this.connect(sessionId, sessionToken);
1012
- }, delay);
1013
- } else {
1014
- this.sessions.delete(sessionId);
1015
- this.emit("session:disconnected", sessionId, reason.toString());
1016
- }
1017
- });
1018
- ws.on("error", (err) => {
1019
- this.emit("session:error", sessionId, err);
1020
- });
1021
- }
1022
- /** Send a message to a specific session, auto-wrapping with protocol envelope */
1023
- send(sessionId, message) {
1024
- const conn = this.sessions.get(sessionId);
1025
- if (!conn || conn.ws.readyState !== WebSocket2.OPEN) {
1026
- return false;
1027
- }
1028
- const envelope = {
1029
- id: message["id"] ?? `msg_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,
1030
- sessionId: message["sessionId"] ?? sessionId,
1031
- timestamp: message["timestamp"] ?? Date.now(),
1032
- sender: message["sender"] ?? { role: "provider", agentId: this.agentId ?? "unknown" },
1033
- type: message["type"] ?? "result.success",
1034
- payload: message["payload"] ?? {}
1035
- };
1036
- conn.ws.send(JSON.stringify(envelope));
1037
- return true;
1038
- }
1039
- /** Disconnect a specific session */
1040
- disconnect(sessionId) {
1041
- const conn = this.sessions.get(sessionId);
1042
- if (!conn) return;
1043
- this.clearHeartbeat(conn);
1044
- if (conn.ws.readyState === WebSocket2.OPEN || conn.ws.readyState === WebSocket2.CONNECTING) {
1045
- conn.ws.close(1e3, "Provider disconnecting");
1046
- }
1047
- this.sessions.delete(sessionId);
1048
- }
1049
- /** Disconnect all sessions */
1050
- disconnectAll() {
1051
- for (const sessionId of this.sessions.keys()) {
1052
- this.disconnect(sessionId);
1053
- }
1054
- }
1055
- /** Get active session count */
1056
- get activeCount() {
1057
- return this.sessions.size;
1058
- }
1059
- /** Check if a session is connected */
1060
- isConnected(sessionId) {
1061
- const conn = this.sessions.get(sessionId);
1062
- return conn?.ws.readyState === WebSocket2.OPEN;
1063
- }
1064
- clearHeartbeat(conn) {
1065
- if (conn.heartbeatTimer) {
1066
- clearInterval(conn.heartbeatTimer);
1067
- conn.heartbeatTimer = null;
1068
- }
1069
- }
1070
- };
1071
-
1072
653
  // src/serve/protocol.ts
1073
654
  var correlationCounter = 0;
1074
655
  function createCorrelationId() {
@@ -1089,9 +670,9 @@ function registerServeCommand(program2) {
1089
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) => {
1090
671
  try {
1091
672
  if (opts.daemon) {
1092
- const config = loadConfig();
673
+ const config = loadConfig12();
1093
674
  config.token = opts.agentToken;
1094
- const client = new ApiClient(config);
675
+ const client = new ApiClient12(config);
1095
676
  let agentId;
1096
677
  try {
1097
678
  const agent = await client.getMyAgent();
@@ -1122,9 +703,9 @@ Logs: ${getLogFilePath(agentId)}`);
1122
703
  });
1123
704
  }
1124
705
  async function runDaemon(opts) {
1125
- const config = loadConfig();
706
+ const config = loadConfig12();
1126
707
  config.token = opts.agentToken;
1127
- const client = new ApiClient(config);
708
+ const client = new ApiClient12(config);
1128
709
  const bridge = new StdioBridge();
1129
710
  const sessionManager = new SessionManager(config.wsUrl);
1130
711
  const pollInterval = parseInt(opts.pollInterval, 10);
@@ -1233,11 +814,11 @@ async function runDaemon(opts) {
1233
814
  function connectAgentWs(token) {
1234
815
  const wsBase = config.wsUrl ?? config.apiUrl.replace(/^http/, "ws");
1235
816
  const url = `${wsBase}/ws/agent?token=${token}`;
1236
- agentWs = new WebSocket3(url);
817
+ agentWs = new WebSocket2(url);
1237
818
  agentWs.on("open", () => {
1238
819
  bridge.writeNotification("agent.connected", { agentId });
1239
820
  agentHeartbeatTimer = setInterval(() => {
1240
- if (agentWs && agentWs.readyState === WebSocket3.OPEN) {
821
+ if (agentWs && agentWs.readyState === WebSocket2.OPEN) {
1241
822
  agentWs.send(JSON.stringify({ type: "system.heartbeat", payload: {} }));
1242
823
  }
1243
824
  }, 25e3);
@@ -1326,6 +907,28 @@ async function runDaemon(opts) {
1326
907
  }, pollInterval);
1327
908
  }
1328
909
  connectAgentWs(opts.agentToken);
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
+ })();
1329
932
  const shutdown = async () => {
1330
933
  if (pollTimer) clearInterval(pollTimer);
1331
934
  if (agentHeartbeatTimer) clearInterval(agentHeartbeatTimer);
@@ -1458,7 +1061,7 @@ function registerStatusCommand(program2) {
1458
1061
 
1459
1062
  // src/index.ts
1460
1063
  var __dirname = dirname(fileURLToPath(import.meta.url));
1461
- var pkg = JSON.parse(readFileSync3(join3(__dirname, "..", "package.json"), "utf-8"));
1064
+ var pkg = JSON.parse(readFileSync2(join2(__dirname, "..", "package.json"), "utf-8"));
1462
1065
  var program = new Command();
1463
1066
  program.name("clawrent").description("ClawRent CLI - Agent capability rental platform").version(pkg.version);
1464
1067
  registerAuthCommand(program);