@clawrent/cli 0.2.1 → 0.2.2
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 +36 -40
- package/dist/index.js.map +1 -1
- package/dist/lib.d.ts +2 -0
- package/dist/lib.js +4 -0
- package/dist/lib.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -167,6 +167,10 @@ var ApiClient = class {
|
|
|
167
167
|
const qs = params.toString();
|
|
168
168
|
return this.request("GET", `/api/agents/my${qs ? `?${qs}` : ""}`);
|
|
169
169
|
}
|
|
170
|
+
/** Resolve the current agent from agentToken. Requires agt_clawrent_ token auth. */
|
|
171
|
+
async getMyAgent() {
|
|
172
|
+
return this.request("GET", "/api/agents/me/agent");
|
|
173
|
+
}
|
|
170
174
|
async publishAgent(agentId) {
|
|
171
175
|
return this.request("POST", `/api/agents/${encodeURIComponent(agentId)}/publish`);
|
|
172
176
|
}
|
|
@@ -966,22 +970,32 @@ var pendingInstructions = /* @__PURE__ */ new Map();
|
|
|
966
970
|
var knownPendingSessions = /* @__PURE__ */ new Set();
|
|
967
971
|
var activeSessions = /* @__PURE__ */ new Set();
|
|
968
972
|
function registerServeCommand(program2) {
|
|
969
|
-
program2.command("serve").description("Start serve daemon - bridge WebSocket sessions to stdin/stdout").requiredOption("--agent-
|
|
973
|
+
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) => {
|
|
970
974
|
try {
|
|
971
975
|
if (opts.daemon) {
|
|
972
|
-
const
|
|
976
|
+
const config = loadConfig();
|
|
977
|
+
config.token = opts.agentToken;
|
|
978
|
+
const client = new ApiClient(config);
|
|
979
|
+
let agentId;
|
|
980
|
+
try {
|
|
981
|
+
const agent = await client.getMyAgent();
|
|
982
|
+
agentId = agent["id"];
|
|
983
|
+
} catch {
|
|
984
|
+
printError("Failed to resolve agent from token. Is the token valid?");
|
|
985
|
+
process.exit(1);
|
|
986
|
+
}
|
|
987
|
+
const { running, pid: existingPid } = isDaemonRunning(agentId);
|
|
973
988
|
if (running) {
|
|
974
|
-
printError(`Daemon already running for agent ${
|
|
989
|
+
printError(`Daemon already running for agent ${agentId} (PID: ${existingPid}). Use 'clawrent stop --agent-id ${agentId}' first.`);
|
|
975
990
|
process.exit(1);
|
|
976
991
|
}
|
|
977
|
-
const args = ["serve", "--agent-
|
|
978
|
-
if (opts.agentToken) args.push("--agent-token", opts.agentToken);
|
|
992
|
+
const args = ["serve", "--agent-token", opts.agentToken];
|
|
979
993
|
if (opts.autoApprove) args.push("--auto-approve");
|
|
980
994
|
if (opts.pollInterval !== "5000") args.push("--poll-interval", opts.pollInterval);
|
|
981
|
-
const pid = spawnDaemon(
|
|
982
|
-
writePid(
|
|
983
|
-
printSuccess(`Daemon started for agent ${
|
|
984
|
-
Logs: ${getLogFilePath(
|
|
995
|
+
const pid = spawnDaemon(agentId, args);
|
|
996
|
+
writePid(agentId, pid);
|
|
997
|
+
printSuccess(`Daemon started for agent ${agentId} (PID: ${pid})
|
|
998
|
+
Logs: ${getLogFilePath(agentId)}`);
|
|
985
999
|
process.exit(0);
|
|
986
1000
|
}
|
|
987
1001
|
await runDaemon(opts);
|
|
@@ -993,34 +1007,26 @@ Logs: ${getLogFilePath(opts.agentId)}`);
|
|
|
993
1007
|
}
|
|
994
1008
|
async function runDaemon(opts) {
|
|
995
1009
|
const config = loadConfig();
|
|
1010
|
+
config.token = opts.agentToken;
|
|
996
1011
|
const client = new ApiClient(config);
|
|
997
1012
|
const bridge = new StdioBridge();
|
|
998
1013
|
const sessionManager = new SessionManager(config.wsUrl);
|
|
999
|
-
sessionManager.agentId = opts.agentId;
|
|
1000
1014
|
const pollInterval = parseInt(opts.pollInterval, 10);
|
|
1001
1015
|
let agentWs = null;
|
|
1002
1016
|
let agentHeartbeatTimer = null;
|
|
1003
|
-
let
|
|
1017
|
+
let agentId;
|
|
1018
|
+
let agentName;
|
|
1004
1019
|
try {
|
|
1005
|
-
const
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
if (!opts.agentToken) {
|
|
1010
|
-
const status = agent["status"];
|
|
1011
|
-
if (status === "draft") {
|
|
1012
|
-
await client.publishAgent(opts.agentId);
|
|
1013
|
-
await client.activateAgent(opts.agentId);
|
|
1014
|
-
} else if (status === "pending_review") {
|
|
1015
|
-
await client.activateAgent(opts.agentId);
|
|
1016
|
-
}
|
|
1017
|
-
await client.setOnlineStatus(opts.agentId, "online");
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
+
const agent = await client.getMyAgent();
|
|
1021
|
+
agentId = agent["id"];
|
|
1022
|
+
agentName = agent["name"] ?? agentId;
|
|
1023
|
+
sessionManager.agentId = agentId;
|
|
1020
1024
|
} catch {
|
|
1025
|
+
printError("Failed to resolve agent from token. Is the token valid?");
|
|
1026
|
+
process.exit(1);
|
|
1021
1027
|
}
|
|
1022
1028
|
bridge.writeNotification("ready", {
|
|
1023
|
-
agentId
|
|
1029
|
+
agentId,
|
|
1024
1030
|
agentName
|
|
1025
1031
|
});
|
|
1026
1032
|
sessionManager.on("session:connected", (sessionId) => {
|
|
@@ -1113,7 +1119,7 @@ async function runDaemon(opts) {
|
|
|
1113
1119
|
const url = `${wsBase}/ws/agent?token=${token}`;
|
|
1114
1120
|
agentWs = new WebSocket3(url);
|
|
1115
1121
|
agentWs.on("open", () => {
|
|
1116
|
-
bridge.writeNotification("agent.connected", { agentId
|
|
1122
|
+
bridge.writeNotification("agent.connected", { agentId });
|
|
1117
1123
|
agentHeartbeatTimer = setInterval(() => {
|
|
1118
1124
|
if (agentWs && agentWs.readyState === WebSocket3.OPEN) {
|
|
1119
1125
|
agentWs.send(JSON.stringify({ type: "system.heartbeat", payload: {} }));
|
|
@@ -1162,7 +1168,7 @@ async function runDaemon(opts) {
|
|
|
1162
1168
|
agentHeartbeatTimer = null;
|
|
1163
1169
|
}
|
|
1164
1170
|
bridge.writeNotification("agent.disconnected", {
|
|
1165
|
-
agentId
|
|
1171
|
+
agentId,
|
|
1166
1172
|
code,
|
|
1167
1173
|
reason: reason.toString()
|
|
1168
1174
|
});
|
|
@@ -1201,11 +1207,7 @@ async function runDaemon(opts) {
|
|
|
1201
1207
|
}
|
|
1202
1208
|
}, pollInterval);
|
|
1203
1209
|
}
|
|
1204
|
-
|
|
1205
|
-
connectAgentWs(opts.agentToken);
|
|
1206
|
-
} else {
|
|
1207
|
-
startPollLoop();
|
|
1208
|
-
}
|
|
1210
|
+
connectAgentWs(opts.agentToken);
|
|
1209
1211
|
const shutdown = async () => {
|
|
1210
1212
|
if (pollTimer) clearInterval(pollTimer);
|
|
1211
1213
|
if (agentHeartbeatTimer) clearInterval(agentHeartbeatTimer);
|
|
@@ -1217,12 +1219,6 @@ async function runDaemon(opts) {
|
|
|
1217
1219
|
}
|
|
1218
1220
|
agentWs = null;
|
|
1219
1221
|
}
|
|
1220
|
-
if (!opts.agentToken) {
|
|
1221
|
-
try {
|
|
1222
|
-
await client.setOnlineStatus(opts.agentId, "offline");
|
|
1223
|
-
} catch {
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
1222
|
sessionManager.disconnectAll();
|
|
1227
1223
|
bridge.writeNotification("shutdown", { reason: "signal" });
|
|
1228
1224
|
setTimeout(() => process.exit(0), 500);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/auth.ts","../src/config.ts","../src/api-client.ts","../src/output.ts","../src/commands/browse.ts","../src/commands/agent.ts","../src/commands/sessions.ts","../src/commands/balance.ts","../src/commands/topup.ts","../src/commands/health.ts","../src/commands/rent.ts","../src/commands/end.ts","../src/commands/send.ts","../src/commands/provider/index.ts","../src/serve/index.ts","../src/daemon.ts","../src/serve/stdio-bridge.ts","../src/serve/session-manager.ts","../src/serve/protocol.ts","../src/commands/stop.ts","../src/commands/status.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\r\nimport { dirname, join } from 'node:path';\r\nimport { fileURLToPath } from 'node:url';\r\nimport { Command } from 'commander';\r\nimport { registerAuthCommand } from './commands/auth.js';\r\nimport { registerBrowseCommand } from './commands/browse.js';\r\nimport { registerAgentCommand } from './commands/agent.js';\r\nimport { registerSessionsCommand } from './commands/sessions.js';\r\nimport { registerBalanceCommand } from './commands/balance.js';\r\nimport { registerTopupCommand } from './commands/topup.js';\r\nimport { registerHealthCommand } from './commands/health.js';\r\nimport { registerRentCommand } from './commands/rent.js';\r\nimport { registerEndCommand } from './commands/end.js';\r\nimport { registerSendCommand } from './commands/send.js';\r\nimport { registerProviderCommands } from './commands/provider/index.js';\r\nimport { registerServeCommand } from './serve/index.js';\r\nimport { registerStopCommand } from './commands/stop.js';\r\nimport { registerStatusCommand } from './commands/status.js';\r\n\r\nconst __dirname = dirname(fileURLToPath(import.meta.url));\r\nconst pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('clawrent')\r\n .description('ClawRent CLI - Agent capability rental platform')\r\n .version(pkg.version);\r\n\r\n// Auth\r\nregisterAuthCommand(program);\r\n\r\n// Consumer commands\r\nregisterBrowseCommand(program);\r\nregisterAgentCommand(program);\r\nregisterSessionsCommand(program);\r\nregisterBalanceCommand(program);\r\nregisterTopupCommand(program);\r\nregisterRentCommand(program);\r\nregisterEndCommand(program);\r\nregisterSendCommand(program);\r\nregisterHealthCommand(program);\r\n\r\n// Provider commands\r\nregisterProviderCommands(program);\r\n\r\n// Serve daemon\r\nregisterServeCommand(program);\r\n\r\n// Daemon management\r\nregisterStopCommand(program);\r\nregisterStatusCommand(program);\r\n\r\nprogram.parse();\r\n","import { Command } from 'commander';\r\nimport { createInterface } from 'node:readline';\r\nimport { loadConfig, saveConfig, clearConfig, getConfigPath } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError, printSuccess } from '../output.js';\r\n\r\nfunction deriveWsUrl(apiUrl: string): string {\r\n return apiUrl.replace(/^http/, 'ws');\r\n}\r\n\r\nasync function promptInput(prompt: string, hidden: boolean = false): Promise<string> {\r\n const rl = createInterface({ input: process.stdin, output: process.stderr });\r\n\r\n return new Promise((resolve) => {\r\n if (hidden) {\r\n // For password: write prompt manually, mute output\r\n process.stderr.write(prompt);\r\n const stdin = process.stdin;\r\n const wasRaw = stdin.isRaw;\r\n if (stdin.isTTY) stdin.setRawMode(true);\r\n let input = '';\r\n const onData = (ch: Buffer) => {\r\n const c = ch.toString('utf-8');\r\n if (c === '\\n' || c === '\\r') {\r\n stdin.removeListener('data', onData);\r\n if (stdin.isTTY && wasRaw !== undefined) stdin.setRawMode(wasRaw);\r\n process.stderr.write('\\n');\r\n rl.close();\r\n resolve(input);\r\n } else if (c === '\\u0003') {\r\n // Ctrl+C\r\n rl.close();\r\n process.exit(1);\r\n } else if (c === '\\u007F' || c === '\\b') {\r\n // Backspace\r\n input = input.slice(0, -1);\r\n } else {\r\n input += c;\r\n }\r\n };\r\n stdin.on('data', onData);\r\n } else {\r\n rl.question(prompt, (answer) => {\r\n rl.close();\r\n resolve(answer);\r\n });\r\n }\r\n });\r\n}\r\n\r\nexport function registerAuthCommand(program: Command): void {\r\n const auth = program\r\n .command('auth')\r\n .description('Authentication management');\r\n\r\n auth\r\n .command('login')\r\n .description('Login to ClawRent platform')\r\n .option('-e, --email <email>', 'Email address')\r\n .option('-p, --password <password>', 'Password')\r\n .option('--api-url <url>', 'Platform API URL')\r\n .action(async (opts: { email?: string; password?: string; apiUrl?: string }) => {\r\n try {\r\n const currentConfig = loadConfig();\r\n const apiUrl = opts.apiUrl ?? currentConfig.apiUrl;\r\n const wsUrl = deriveWsUrl(apiUrl);\r\n\r\n const email = opts.email ?? await promptInput('Email: ');\r\n const password = opts.password ?? await promptInput('Password: ', true);\r\n\r\n if (!email || !password) {\r\n printError('Email and password are required.');\r\n process.exit(1);\r\n }\r\n\r\n const client = new ApiClient({ ...currentConfig, apiUrl, wsUrl });\r\n const result = await client.login(email, password);\r\n\r\n // Save credentials (do NOT save apiUrl/wsUrl — they come from defaults or env vars,\r\n // saving them would pin the config to a specific URL and break after default changes)\r\n saveConfig({\r\n token: result.token,\r\n userId: result.user.id,\r\n email: result.user.email,\r\n name: result.user.name,\r\n });\r\n\r\n printSuccess(`Logged in as ${result.user.name} (${result.user.email})`);\r\n printSuccess(`Config saved to ${getConfigPath()}`);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n auth\r\n .command('logout')\r\n .description('Logout and clear saved credentials')\r\n .action(() => {\r\n try {\r\n clearConfig();\r\n printSuccess('Logged out. Config cleared.');\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n auth\r\n .command('whoami')\r\n .description('Show current user info')\r\n .action(async () => {\r\n try {\r\n const config = loadConfig();\r\n const client = new ApiClient(config);\r\n const me = await client.getMe();\r\n printJson(me);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { readFileSync, writeFileSync, mkdirSync, unlinkSync, existsSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport { homedir } from 'node:os';\r\n\r\nexport interface ClawRentConfig {\r\n apiUrl: string;\r\n wsUrl: string;\r\n token?: string;\r\n apiKey?: string;\r\n userId?: string;\r\n email?: string;\r\n name?: string;\r\n}\r\n\r\nconst DEFAULT_CONFIG: ClawRentConfig = {\r\n apiUrl: 'https://clawrent.cloud',\r\n wsUrl: 'wss://clawrent.cloud',\r\n};\r\n\r\nexport function getConfigDir(): string {\r\n return join(homedir(), '.clawrent');\r\n}\r\n\r\nfunction getConfigFilePath(): string {\r\n return join(getConfigDir(), 'config.json');\r\n}\r\n\r\nexport function getConfigPath(): string {\r\n return getConfigFilePath();\r\n}\r\n\r\nexport function loadConfig(): ClawRentConfig {\r\n let fileConfig: Partial<ClawRentConfig> = {};\r\n\r\n const configPath = getConfigFilePath();\r\n if (existsSync(configPath)) {\r\n try {\r\n const raw = readFileSync(configPath, 'utf-8');\r\n fileConfig = JSON.parse(raw) as Partial<ClawRentConfig>;\r\n } catch {\r\n // Ignore corrupt config file\r\n }\r\n }\r\n\r\n // Migration: remove stale localhost URLs saved by older CLI versions.\r\n // These override the new production defaults and break remote connections.\r\n if (fileConfig.apiUrl?.includes('localhost') || fileConfig.wsUrl?.includes('localhost')) {\r\n delete fileConfig.apiUrl;\r\n delete fileConfig.wsUrl;\r\n // Persist the cleanup so it only runs once\r\n try {\r\n const cleaned = { ...fileConfig };\r\n writeFileSync(configPath, JSON.stringify(cleaned, null, 2), 'utf-8');\r\n } catch {\r\n // Non-fatal\r\n }\r\n }\r\n\r\n // Merge: defaults < file < env vars\r\n const config: ClawRentConfig = {\r\n ...DEFAULT_CONFIG,\r\n ...fileConfig,\r\n };\r\n\r\n // Env vars always override\r\n const envApiUrl = process.env['CLAWRENT_API_URL'];\r\n const envWsUrl = process.env['CLAWRENT_WS_URL'];\r\n const envToken = process.env['CLAWRENT_TOKEN'];\r\n const envApiKey = process.env['CLAWRENT_API_KEY'];\r\n const envUserId = process.env['CLAWRENT_USER_ID'];\r\n\r\n if (envApiUrl) config.apiUrl = envApiUrl;\r\n if (envWsUrl) config.wsUrl = envWsUrl;\r\n if (envToken) config.token = envToken;\r\n if (envApiKey) config.apiKey = envApiKey;\r\n if (envUserId) config.userId = envUserId;\r\n\r\n return config;\r\n}\r\n\r\nexport function saveConfig(partial: Partial<ClawRentConfig>): void {\r\n const configDir = getConfigDir();\r\n if (!existsSync(configDir)) {\r\n mkdirSync(configDir, { recursive: true });\r\n }\r\n\r\n let existing: Partial<ClawRentConfig> = {};\r\n const configPath = getConfigFilePath();\r\n if (existsSync(configPath)) {\r\n try {\r\n existing = JSON.parse(readFileSync(configPath, 'utf-8')) as Partial<ClawRentConfig>;\r\n } catch {\r\n // Overwrite corrupt file\r\n }\r\n }\r\n\r\n const merged = { ...existing, ...partial };\r\n writeFileSync(configPath, JSON.stringify(merged, null, 2), 'utf-8');\r\n}\r\n\r\nexport function clearConfig(): void {\r\n const configPath = getConfigFilePath();\r\n if (existsSync(configPath)) {\r\n unlinkSync(configPath);\r\n }\r\n}\r\n","import type { ClawRentConfig } from './config.js';\r\n\r\nexport class ApiClient {\r\n private config: ClawRentConfig;\r\n\r\n constructor(config: ClawRentConfig) {\r\n this.config = config;\r\n }\r\n\r\n get apiUrl(): string {\r\n return this.config.apiUrl;\r\n }\r\n\r\n get wsUrl(): string {\r\n return this.config.wsUrl;\r\n }\r\n\r\n get userId(): string | undefined {\r\n return this.config.userId;\r\n }\r\n\r\n // --- Auth (no auth needed) ---\r\n\r\n async login(email: string, password: string): Promise<{ user: { id: string; email: string; name: string; role: string }; token: string }> {\r\n return this.request('POST', '/api/auth/login', { email, password }, false);\r\n }\r\n\r\n async getMe(): Promise<Record<string, unknown>> {\r\n return this.request('GET', '/api/auth/me');\r\n }\r\n\r\n // --- Marketplace ---\r\n\r\n async browse(query?: { search?: string; category?: string; page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.search) params.set('search', query.search);\r\n if (query?.category) params.set('category', query.category);\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/marketplace/browse${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async getAgent(slug: string): Promise<unknown> {\r\n return this.request('GET', `/api/marketplace/agents/${encodeURIComponent(slug)}`);\r\n }\r\n\r\n // --- Sessions ---\r\n\r\n async rent(options: { agentId: string; taskDescription: string; grantedPermissions?: Record<string, unknown> }): Promise<unknown> {\r\n return this.request('POST', '/api/sessions', {\r\n agentId: options.agentId,\r\n taskDescription: options.taskDescription,\r\n grantedPermissions: options.grantedPermissions ?? {},\r\n });\r\n }\r\n\r\n async getSessions(query?: { role?: string; status?: string; page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.role) params.set('role', query.role);\r\n if (query?.status) params.set('status', query.status);\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/sessions${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async getSession(sessionId: string): Promise<Record<string, unknown>> {\r\n return this.request('GET', `/api/sessions/${encodeURIComponent(sessionId)}`);\r\n }\r\n\r\n async getSessionMessages(sessionId: string): Promise<unknown> {\r\n return this.request('GET', `/api/sessions/${encodeURIComponent(sessionId)}/messages`);\r\n }\r\n\r\n async endSession(sessionId: string): Promise<unknown> {\r\n return this.request('POST', `/api/sessions/${encodeURIComponent(sessionId)}/end`);\r\n }\r\n\r\n async approveSession(sessionId: string): Promise<unknown> {\r\n return this.request('POST', `/api/sessions/${encodeURIComponent(sessionId)}/approve`);\r\n }\r\n\r\n // --- Billing ---\r\n\r\n async getBalance(): Promise<{ balance: string }> {\r\n return this.request('GET', '/api/billing/wallet');\r\n }\r\n\r\n async topUp(amount: string): Promise<{ balance: string }> {\r\n return this.request('POST', '/api/billing/wallet/topup', { amount });\r\n }\r\n\r\n // --- Provider: Agents ---\r\n\r\n async registerAgent(data: Record<string, unknown>): Promise<unknown> {\r\n return this.request('POST', '/api/agents', data);\r\n }\r\n\r\n async getMyAgents(query?: { page?: number; limit?: number; status?: string }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n if (query?.status) params.set('status', query.status);\r\n const qs = params.toString();\r\n return this.request('GET', `/api/agents/my${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async publishAgent(agentId: string): Promise<unknown> {\r\n return this.request('POST', `/api/agents/${encodeURIComponent(agentId)}/publish`);\r\n }\r\n\r\n async activateAgent(agentId: string): Promise<unknown> {\r\n return this.request('POST', `/api/agents/${encodeURIComponent(agentId)}/activate`);\r\n }\r\n\r\n async setOnlineStatus(agentId: string, onlineStatus: string): Promise<unknown> {\r\n return this.request('PATCH', `/api/agents/${encodeURIComponent(agentId)}/status`, { onlineStatus });\r\n }\r\n\r\n async generateAgentToken(agentId: string): Promise<{ agentId: string; token: string; createdAt: string; warning: string }> {\r\n return this.request('POST', `/api/agents/${encodeURIComponent(agentId)}/token`);\r\n }\r\n\r\n async revokeAgentToken(agentId: string): Promise<{ message: string }> {\r\n return this.request('DELETE', `/api/agents/${encodeURIComponent(agentId)}/token`);\r\n }\r\n\r\n // --- Orders ---\r\n\r\n async createOrder(data: {\r\n items: Array<{ providerAgentId: string; consumerAgentId?: string; taskDescription: string; grantedPermissions?: Record<string, unknown> }>;\r\n note?: string;\r\n fromCart?: boolean;\r\n }): Promise<unknown> {\r\n return this.request('POST', '/api/orders', data);\r\n }\r\n\r\n async getOrders(query?: { status?: string; page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.status) params.set('status', query.status);\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/orders${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async getOrder(orderId: string): Promise<unknown> {\r\n return this.request('GET', `/api/orders/${encodeURIComponent(orderId)}`);\r\n }\r\n\r\n async cancelOrder(orderId: string): Promise<unknown> {\r\n return this.request('POST', `/api/orders/${encodeURIComponent(orderId)}/cancel`);\r\n }\r\n\r\n // --- Cart ---\r\n\r\n async getCart(): Promise<unknown> {\r\n return this.request('GET', '/api/cart');\r\n }\r\n\r\n async addToCart(data: { providerAgentId: string; taskDescription: string }): Promise<unknown> {\r\n return this.request('POST', '/api/cart', data);\r\n }\r\n\r\n async updateCartItem(itemId: string, data: { taskDescription: string }): Promise<unknown> {\r\n return this.request('PATCH', `/api/cart/${encodeURIComponent(itemId)}`, data);\r\n }\r\n\r\n async removeFromCart(itemId: string): Promise<unknown> {\r\n return this.request('DELETE', `/api/cart/${encodeURIComponent(itemId)}`);\r\n }\r\n\r\n async clearCart(): Promise<unknown> {\r\n return this.request('DELETE', '/api/cart');\r\n }\r\n\r\n // --- Favorites ---\r\n\r\n async listFavorites(query?: { page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/favorites${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async addFavorite(agentId: string): Promise<unknown> {\r\n return this.request('POST', `/api/favorites/${encodeURIComponent(agentId)}`);\r\n }\r\n\r\n async removeFavorite(agentId: string): Promise<unknown> {\r\n return this.request('DELETE', `/api/favorites/${encodeURIComponent(agentId)}`);\r\n }\r\n\r\n // --- Health ---\r\n\r\n async health(): Promise<unknown> {\r\n return this.request('GET', '/api/health', undefined, false);\r\n }\r\n\r\n // --- Private ---\r\n\r\n private async request<T = any>(method: string, path: string, body?: unknown, requireAuth: boolean = true): Promise<T> {\r\n const url = `${this.config.apiUrl}${path}`;\r\n const headers: Record<string, string> = {};\r\n\r\n if (body !== undefined) {\r\n headers['Content-Type'] = 'application/json';\r\n }\r\n\r\n if (requireAuth) {\r\n if (this.config.token) {\r\n headers['Authorization'] = `Bearer ${this.config.token}`;\r\n } else if (this.config.apiKey) {\r\n headers['x-api-key'] = this.config.apiKey;\r\n } else {\r\n throw new Error('Not authenticated. Run `clawrent auth login` first.');\r\n }\r\n }\r\n\r\n const response = await fetch(url, {\r\n method,\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n\r\n if (!response.ok) {\r\n const errBody = await response.json().catch(() => ({ message: response.statusText })) as Record<string, unknown>;\r\n throw new Error(`API error ${response.status}: ${errBody['message'] ?? JSON.stringify(errBody)}`);\r\n }\r\n\r\n return response.json() as Promise<T>;\r\n }\r\n}\r\n","export function printJson(data: unknown): void {\r\n process.stdout.write(JSON.stringify(data, null, 2) + '\\n');\r\n}\r\n\r\nexport function printError(message: string): void {\r\n process.stderr.write(`Error: ${message}\\n`);\r\n}\r\n\r\nexport function printSuccess(message: string): void {\r\n process.stdout.write(`${message}\\n`);\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError } from '../output.js';\r\n\r\nexport function registerBrowseCommand(program: Command): void {\r\n program\r\n .command('browse')\r\n .description('Browse available agents on the marketplace')\r\n .option('-s, --search <query>', 'Search by name')\r\n .option('-c, --category <category>', 'Filter by category')\r\n .option('-p, --page <number>', 'Page number', '1')\r\n .option('-l, --limit <number>', 'Results per page', '20')\r\n .action(async (opts: { search?: string; category?: string; page: string; limit: string }) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.browse({\r\n search: opts.search,\r\n category: opts.category,\r\n page: parseInt(opts.page, 10),\r\n limit: parseInt(opts.limit, 10),\r\n });\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError } from '../output.js';\r\n\r\nexport function registerAgentCommand(program: Command): void {\r\n program\r\n .command('agent <slug>')\r\n .description('Get agent details by slug')\r\n .action(async (slug: string) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.getAgent(slug);\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError } from '../output.js';\r\n\r\nexport function registerSessionsCommand(program: Command): void {\r\n program\r\n .command('sessions')\r\n .description('List your sessions')\r\n .option('-r, --role <role>', 'Filter by role (consumer/provider)')\r\n .option('-s, --status <status>', 'Filter by status')\r\n .option('-p, --page <number>', 'Page number', '1')\r\n .option('-l, --limit <number>', 'Results per page', '20')\r\n .action(async (opts: { role?: string; status?: string; page: string; limit: string }) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.getSessions({\r\n role: opts.role,\r\n status: opts.status,\r\n page: parseInt(opts.page, 10),\r\n limit: parseInt(opts.limit, 10),\r\n });\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printSuccess, printError } from '../output.js';\r\n\r\nexport function registerBalanceCommand(program: Command): void {\r\n program\r\n .command('balance')\r\n .description('Check wallet balance')\r\n .action(async () => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.getBalance();\r\n printSuccess(`Balance: ${result.balance}`);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printSuccess, printError } from '../output.js';\r\n\r\nexport function registerTopupCommand(program: Command): void {\r\n program\r\n .command('topup <amount>')\r\n .description('Top up wallet balance')\r\n .action(async (amount: string) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.topUp(amount);\r\n printSuccess(`New balance: ${result.balance}`);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError } from '../output.js';\r\n\r\nexport function registerHealthCommand(program: Command): void {\r\n program\r\n .command('health')\r\n .description('Check platform health')\r\n .action(async () => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.health();\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError } from '../output.js';\r\n\r\nexport function registerRentCommand(program: Command): void {\r\n program\r\n .command('rent')\r\n .description('Rent an agent (create a session)')\r\n .requiredOption('--agent-id <id>', 'Agent ID to rent')\r\n .requiredOption('--task <description>', 'Task description')\r\n .option('--permissions <json>', 'Granted permissions as JSON string', '{}')\r\n .action(async (opts: { agentId: string; task: string; permissions: string }) => {\r\n try {\r\n let grantedPermissions: Record<string, unknown> = {};\r\n try {\r\n grantedPermissions = JSON.parse(opts.permissions) as Record<string, unknown>;\r\n } catch {\r\n printError('Invalid JSON for --permissions');\r\n process.exit(1);\r\n }\r\n\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.rent({\r\n agentId: opts.agentId,\r\n taskDescription: opts.task,\r\n grantedPermissions,\r\n });\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError } from '../output.js';\r\n\r\nexport function registerEndCommand(program: Command): void {\r\n program\r\n .command('end <sessionId>')\r\n .description('End a session')\r\n .action(async (sessionId: string) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.endSession(sessionId);\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport WebSocket from 'ws';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError, printSuccess } from '../output.js';\r\n\r\nexport function registerSendCommand(program: Command): void {\r\n program\r\n .command('send <sessionId>')\r\n .description('Send a message to a session via WebSocket')\r\n .requiredOption('--content <text>', 'Message content')\r\n .option('--type <messageType>', 'Message type', 'dialogue.message')\r\n .option('--token <sessionToken>', 'Session token (auto-fetched if not provided)')\r\n .option('--wait <ms>', 'Wait for response (milliseconds)')\r\n .action(async (sessionId: string, opts: { content: string; type: string; token?: string; wait?: string }) => {\r\n try {\r\n const config = loadConfig();\r\n const client = new ApiClient(config);\r\n\r\n // Get session token if not provided\r\n let sessionToken = opts.token;\r\n let role = 'consumer';\r\n if (!sessionToken) {\r\n const session = await client.getSession(sessionId);\r\n sessionToken = session['sessionToken'] as string;\r\n // Determine role\r\n if (config.userId && session['providerUserId'] === config.userId) {\r\n role = 'provider';\r\n }\r\n }\r\n\r\n if (!sessionToken) {\r\n printError('Could not determine session token. Use --token flag.');\r\n process.exit(1);\r\n }\r\n\r\n const wsUrl = `${config.wsUrl}/ws/session?sessionId=${sessionId}&token=${sessionToken}&role=${role}`;\r\n\r\n await new Promise<void>((resolve, reject) => {\r\n const ws = new WebSocket(wsUrl);\r\n let responded = false;\r\n\r\n ws.on('open', () => {\r\n // Build full protocol envelope as required by ClawRentMessageSchema\r\n const message = {\r\n id: `msg_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\r\n sessionId,\r\n timestamp: Date.now(),\r\n sender: { role, agentId: config.userId ?? 'unknown' },\r\n type: opts.type,\r\n payload: { content: opts.content, dialogueType: 'message' },\r\n };\r\n ws.send(JSON.stringify(message));\r\n\r\n if (opts.wait) {\r\n // Wait for response\r\n setTimeout(() => {\r\n if (!responded) {\r\n ws.close(1000);\r\n printSuccess('Message sent (no response within timeout).');\r\n resolve();\r\n }\r\n }, parseInt(opts.wait, 10));\r\n } else {\r\n // Send and close\r\n setTimeout(() => {\r\n ws.close(1000);\r\n printSuccess('Message sent.');\r\n resolve();\r\n }, 500);\r\n }\r\n });\r\n\r\n ws.on('message', (raw) => {\r\n try {\r\n const data = JSON.parse(raw.toString());\r\n if (data.type !== 'system.heartbeat_ack' && data.type !== 'system.peer_connected') {\r\n responded = true;\r\n printJson(data);\r\n if (opts.wait) {\r\n ws.close(1000);\r\n resolve();\r\n }\r\n }\r\n } catch {\r\n // ignore parse errors\r\n }\r\n });\r\n\r\n ws.on('error', (err) => {\r\n reject(err);\r\n });\r\n\r\n ws.on('close', () => {\r\n if (!responded && opts.wait) {\r\n resolve();\r\n }\r\n });\r\n });\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../../config.js';\r\nimport { ApiClient } from '../../api-client.js';\r\nimport { printJson, printError, printSuccess } from '../../output.js';\r\n\r\nexport function registerProviderCommands(program: Command): void {\r\n const provider = program\r\n .command('provider')\r\n .description('Provider operations');\r\n\r\n // --- Agent subcommands ---\r\n const agent = provider\r\n .command('agent')\r\n .description('Manage your agents');\r\n\r\n agent\r\n .command('create')\r\n .description('Register a new agent')\r\n .requiredOption('--name <name>', 'Agent name')\r\n .requiredOption('--slug <slug>', 'Agent slug (URL-friendly)')\r\n .requiredOption('--description <desc>', 'Agent description (10-500 chars)')\r\n .option('--long-description <text>', 'Detailed description')\r\n .option('--pricing-model <model>', 'Pricing model (per_token/per_session/per_minute)', 'per_session')\r\n .option('--price <amount>', 'Price amount', '1.00')\r\n .option('--currency <cur>', 'Currency (CNY/USD)', 'CNY')\r\n .option('--hosting-type <type>', 'Hosting type (self_hosted/platform_hosted)', 'self_hosted')\r\n .option('--approval-mode <mode>', 'Approval mode (manual/auto)', 'manual')\r\n .option('--max-concurrent <n>', 'Max concurrent sessions', '5')\r\n .option('--capabilities <json>', 'Capabilities as JSON array')\r\n .action(async (opts: {\r\n name: string; slug: string; description: string; longDescription?: string;\r\n pricingModel: string; price: string; currency: string; hostingType: string;\r\n approvalMode: string; maxConcurrent: string; capabilities?: string;\r\n }) => {\r\n try {\r\n const data: Record<string, unknown> = {\r\n name: opts.name,\r\n slug: opts.slug,\r\n description: opts.description,\r\n pricingModel: opts.pricingModel,\r\n priceAmount: opts.price,\r\n currency: opts.currency,\r\n hostingType: opts.hostingType,\r\n approvalMode: opts.approvalMode,\r\n maxConcurrentSessions: parseInt(opts.maxConcurrent, 10),\r\n };\r\n if (opts.longDescription) data['longDescription'] = opts.longDescription;\r\n if (opts.capabilities) {\r\n try {\r\n data['capabilities'] = JSON.parse(opts.capabilities);\r\n } catch {\r\n printError('Invalid JSON for --capabilities');\r\n process.exit(1);\r\n }\r\n }\r\n\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.registerAgent(data);\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n agent\r\n .command('list')\r\n .description('List your agents')\r\n .option('-s, --status <status>', 'Filter by status')\r\n .option('-p, --page <number>', 'Page number', '1')\r\n .option('-l, --limit <number>', 'Results per page', '20')\r\n .action(async (opts: { status?: string; page: string; limit: string }) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.getMyAgents({\r\n status: opts.status,\r\n page: parseInt(opts.page, 10),\r\n limit: parseInt(opts.limit, 10),\r\n });\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n agent\r\n .command('publish <agentId>')\r\n .description('Publish an agent (draft -> pending_review)')\r\n .action(async (agentId: string) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.publishAgent(agentId);\r\n printSuccess('Agent published successfully.');\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n agent\r\n .command('activate <agentId>')\r\n .description('Activate an agent (pending_review -> active)')\r\n .action(async (agentId: string) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.activateAgent(agentId);\r\n printSuccess('Agent activated successfully.');\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n agent\r\n .command('status <agentId>')\r\n .description('Set agent online status')\r\n .requiredOption('--status <status>', 'Online status (online/offline/busy)')\r\n .action(async (agentId: string, opts: { status: string }) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.setOnlineStatus(agentId, opts.status);\r\n printSuccess(`Agent status set to ${opts.status}.`);\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n // --- Provider session commands ---\r\n provider\r\n .command('sessions')\r\n .description('List provider sessions')\r\n .option('-s, --status <status>', 'Filter by status')\r\n .option('-p, --page <number>', 'Page number', '1')\r\n .option('-l, --limit <number>', 'Results per page', '20')\r\n .action(async (opts: { status?: string; page: string; limit: string }) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.getSessions({\r\n role: 'provider',\r\n status: opts.status,\r\n page: parseInt(opts.page, 10),\r\n limit: parseInt(opts.limit, 10),\r\n });\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n provider\r\n .command('approve <sessionId>')\r\n .description('Approve a pending session')\r\n .action(async (sessionId: string) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.approveSession(sessionId);\r\n printSuccess('Session approved.');\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport WebSocket from 'ws';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printError, printSuccess } from '../output.js';\r\nimport { isDaemonRunning, spawnDaemon, writePid, getLogFilePath } from '../daemon.js';\r\nimport { StdioBridge } from './stdio-bridge.js';\r\nimport { SessionManager } from './session-manager.js';\r\nimport {\r\n createCorrelationId,\r\n isResponse,\r\n isRequest,\r\n type JsonRpcMessage,\r\n type ResultPayload,\r\n} from './protocol.js';\r\n\r\ninterface ServeOptions {\r\n agentId: string;\r\n agentToken?: string;\r\n autoApprove: boolean;\r\n pollInterval: string;\r\n daemon: boolean;\r\n}\r\n\r\n/** Pending instruction tracking: correlationId -> sessionId */\r\nconst pendingInstructions = new Map<string, string>();\r\n\r\n/** Known session IDs we've already seen (to avoid duplicate polling notifications) */\r\nconst knownPendingSessions = new Set<string>();\r\nconst activeSessions = new Set<string>();\r\n\r\nexport function registerServeCommand(program: Command): void {\r\n program\r\n .command('serve')\r\n .description('Start serve daemon - bridge WebSocket sessions to stdin/stdout')\r\n .requiredOption('--agent-id <id>', 'Agent ID to serve')\r\n .option('--agent-token <token>', 'Agent token for /ws/agent control channel')\r\n .option('--auto-approve', 'Automatically approve incoming sessions', false)\r\n .option('--poll-interval <ms>', 'Polling interval for pending sessions (ms)', '5000')\r\n .option('-d, --daemon', 'Run in background as a daemon process', false)\r\n .action(async (opts: ServeOptions) => {\r\n try {\r\n if (opts.daemon) {\r\n // --- Daemon mode: fork and exit ---\r\n const { running, pid: existingPid } = isDaemonRunning(opts.agentId);\r\n if (running) {\r\n printError(`Daemon already running for agent ${opts.agentId} (PID: ${existingPid}). Use 'clawrent stop --agent-id ${opts.agentId}' first.`);\r\n process.exit(1);\r\n }\r\n\r\n // Rebuild args without --daemon / -d\r\n const args: string[] = ['serve', '--agent-id', opts.agentId];\r\n if (opts.agentToken) args.push('--agent-token', opts.agentToken);\r\n if (opts.autoApprove) args.push('--auto-approve');\r\n if (opts.pollInterval !== '5000') args.push('--poll-interval', opts.pollInterval);\r\n\r\n const pid = spawnDaemon(opts.agentId, args);\r\n writePid(opts.agentId, pid);\r\n printSuccess(`Daemon started for agent ${opts.agentId} (PID: ${pid})\\nLogs: ${getLogFilePath(opts.agentId)}`);\r\n process.exit(0);\r\n }\r\n\r\n await runDaemon(opts);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n\r\nasync function runDaemon(opts: ServeOptions): Promise<void> {\r\n const config = loadConfig();\r\n const client = new ApiClient(config);\r\n const bridge = new StdioBridge();\r\n const sessionManager = new SessionManager(config.wsUrl);\r\n sessionManager.agentId = opts.agentId;\r\n const pollInterval = parseInt(opts.pollInterval, 10);\r\n let agentWs: WebSocket | null = null;\r\n let agentHeartbeatTimer: ReturnType<typeof setInterval> | null = null;\r\n\r\n // --- 1. Startup: validate auth + resolve agent ---\r\n let agentName = opts.agentId;\r\n try {\r\n const agents = (await client.getMyAgents()) as { data: Array<Record<string, unknown>> };\r\n const agent = agents.data.find((a) => a['id'] === opts.agentId);\r\n if (agent) {\r\n agentName = (agent['name'] as string) ?? opts.agentId;\r\n\r\n // Auto-activate if needed (skip if no token yet — activation requires WS first)\r\n if (!opts.agentToken) {\r\n const status = agent['status'] as string;\r\n if (status === 'draft') {\r\n await client.publishAgent(opts.agentId);\r\n await client.activateAgent(opts.agentId);\r\n } else if (status === 'pending_review') {\r\n await client.activateAgent(opts.agentId);\r\n }\r\n // Set online via REST (legacy fallback)\r\n await client.setOnlineStatus(opts.agentId, 'online');\r\n }\r\n }\r\n } catch {\r\n // Continue anyway — the poll loop will surface errors\r\n }\r\n\r\n // --- 2. Notify ready ---\r\n bridge.writeNotification('ready', {\r\n agentId: opts.agentId,\r\n agentName,\r\n });\r\n\r\n // --- 3. Wire up session manager events ---\r\n sessionManager.on('session:connected', (sessionId: string) => {\r\n bridge.writeNotification('session.connected', { sessionId });\r\n });\r\n\r\n sessionManager.on('session:message', (sessionId: string, message: Record<string, unknown>) => {\r\n const type = message['type'] as string;\r\n\r\n if (type?.startsWith('instruction.')) {\r\n // Instruction from consumer -> forward as JSON-RPC request (expects response)\r\n const corrId = createCorrelationId();\r\n pendingInstructions.set(corrId, sessionId);\r\n\r\n bridge.writeRequest('instruction', corrId, {\r\n sessionId,\r\n messageId: (message['id'] as string) ?? corrId,\r\n type,\r\n payload: (message['payload'] as Record<string, unknown>) ?? {},\r\n sender: message['sender'],\r\n });\r\n } else if (type?.startsWith('dialogue.')) {\r\n // Dialogue from consumer -> forward as notification\r\n const payload = (message['payload'] as Record<string, unknown>) ?? {};\r\n bridge.writeNotification('dialogue', {\r\n sessionId,\r\n content: payload['content'] ?? '',\r\n dialogueType: payload['dialogueType'] ?? 'message',\r\n });\r\n } else if (type?.startsWith('result.')) {\r\n // Result from consumer -> forward as notification\r\n bridge.writeNotification('result', {\r\n sessionId,\r\n type,\r\n payload: (message['payload'] as Record<string, unknown>) ?? {},\r\n });\r\n } else if (type === 'system.session_ended' || type === 'system.peer_disconnected') {\r\n activeSessions.delete(sessionId);\r\n bridge.writeNotification('session.ended', {\r\n sessionId,\r\n reason: type,\r\n });\r\n } else if (type === 'system.peer_connected') {\r\n bridge.writeNotification('session.peer_connected', { sessionId });\r\n } else if (type !== 'system.heartbeat_ack') {\r\n // Forward unknown messages as-is\r\n bridge.writeNotification('message', { sessionId, ...message });\r\n }\r\n });\r\n\r\n sessionManager.on('session:disconnected', (sessionId: string, reason: string) => {\r\n activeSessions.delete(sessionId);\r\n bridge.writeNotification('session.disconnected', { sessionId, reason });\r\n });\r\n\r\n sessionManager.on('session:reconnecting', (sessionId: string, delay: number) => {\r\n bridge.writeNotification('session.reconnecting', { sessionId, delay });\r\n });\r\n\r\n sessionManager.on('session:error', (sessionId: string, err: Error) => {\r\n bridge.writeNotification('session.error', { sessionId, message: err.message });\r\n });\r\n\r\n // --- 4. Handle stdin messages from agent ---\r\n bridge.start((msg: JsonRpcMessage) => {\r\n if (isResponse(msg)) {\r\n // Agent is responding to an instruction we forwarded\r\n const sessionId = pendingInstructions.get(msg.id);\r\n if (sessionId && msg.result) {\r\n pendingInstructions.delete(msg.id);\r\n const result = msg.result as unknown as ResultPayload;\r\n sessionManager.send(sessionId, {\r\n type: result.type ?? 'result.success',\r\n payload: result.payload ?? result,\r\n });\r\n }\r\n } else if (isRequest(msg)) {\r\n // Agent is proactively sending something\r\n if (msg.method === 'send') {\r\n const params = msg.params as Record<string, unknown> | undefined;\r\n if (params?.['sessionId']) {\r\n const sent = sessionManager.send(params['sessionId'] as string, {\r\n type: params['type'] ?? 'dialogue.message',\r\n payload: (params['payload'] as Record<string, unknown>) ?? { content: '' },\r\n });\r\n bridge.writeResponse(msg.id, { success: sent });\r\n }\r\n } else if (msg.method === 'approve') {\r\n const params = msg.params as Record<string, unknown> | undefined;\r\n const sid = params?.['sessionId'] as string | undefined;\r\n if (sid) {\r\n approveAndConnect(client, sessionManager, bridge, sid).catch(() => {\r\n bridge.writeResponse(msg.id, { success: false, error: 'Failed to approve' });\r\n }).then(() => {\r\n bridge.writeResponse(msg.id, { success: true });\r\n });\r\n }\r\n }\r\n }\r\n // Notifications from agent are ignored for now\r\n });\r\n\r\n // --- 5. Agent control channel (/ws/agent) + fallback poll loop ---\r\n let pollTimer: ReturnType<typeof setInterval> | null = null;\r\n\r\n function connectAgentWs(token: string) {\r\n const wsBase = config.wsUrl ?? config.apiUrl.replace(/^http/, 'ws');\r\n const url = `${wsBase}/ws/agent?token=${token}`;\r\n agentWs = new WebSocket(url);\r\n\r\n agentWs.on('open', () => {\r\n bridge.writeNotification('agent.connected', { agentId: opts.agentId });\r\n\r\n // Start heartbeat on agent channel\r\n agentHeartbeatTimer = setInterval(() => {\r\n if (agentWs && agentWs.readyState === WebSocket.OPEN) {\r\n agentWs.send(JSON.stringify({ type: 'system.heartbeat', payload: {} }));\r\n }\r\n }, 25_000);\r\n\r\n // Stop polling when WS is connected\r\n if (pollTimer) {\r\n clearInterval(pollTimer);\r\n pollTimer = null;\r\n }\r\n });\r\n\r\n agentWs.on('message', (raw) => {\r\n try {\r\n const message = JSON.parse(raw.toString());\r\n const type = message.type as string;\r\n\r\n if (type === 'session.new' || type === 'session.approved') {\r\n const payload = message.payload as Record<string, unknown>;\r\n const sid = payload['sessionId'] as string;\r\n const sessionToken = payload['sessionToken'] as string;\r\n\r\n if (knownPendingSessions.has(sid) || activeSessions.has(sid)) return;\r\n knownPendingSessions.add(sid);\r\n\r\n if (opts.autoApprove && type === 'session.new') {\r\n approveAndConnect(client, sessionManager, bridge, sid);\r\n } else if (type === 'session.approved' && sessionToken) {\r\n // Already approved, connect directly\r\n activeSessions.add(sid);\r\n bridge.writeNotification('session.new', {\r\n sessionId: sid,\r\n sessionToken,\r\n taskDescription: (payload['taskDescription'] as string) ?? '',\r\n consumerUserId: (payload['consumerUserId'] as string) ?? '',\r\n });\r\n sessionManager.connect(sid, sessionToken);\r\n } else {\r\n bridge.writeNotification('session.pending', {\r\n sessionId: sid,\r\n taskDescription: (payload['taskDescription'] as string) ?? '',\r\n consumerUserId: (payload['consumerUserId'] as string) ?? '',\r\n });\r\n }\r\n }\r\n // Ignore heartbeat_ack and other system messages\r\n } catch {\r\n // Ignore parse errors on agent channel\r\n }\r\n });\r\n\r\n agentWs.on('close', (code, reason) => {\r\n if (agentHeartbeatTimer) {\r\n clearInterval(agentHeartbeatTimer);\r\n agentHeartbeatTimer = null;\r\n }\r\n bridge.writeNotification('agent.disconnected', {\r\n agentId: opts.agentId,\r\n code,\r\n reason: reason.toString(),\r\n });\r\n\r\n // Fall back to polling\r\n if (!pollTimer) {\r\n startPollLoop();\r\n }\r\n\r\n // Reconnect after 5s unless deliberately closed\r\n if (code !== 1000 && code !== 4009) {\r\n setTimeout(() => connectAgentWs(token), 5000);\r\n }\r\n });\r\n\r\n agentWs.on('error', () => {\r\n // Error will trigger close event\r\n });\r\n }\r\n\r\n function startPollLoop() {\r\n pollTimer = setInterval(async () => {\r\n try {\r\n const sessions = (await client.getSessions({\r\n role: 'provider',\r\n status: 'pending_approval',\r\n })) as { data: Array<Record<string, unknown>> };\r\n\r\n for (const session of sessions.data ?? []) {\r\n const sid = session['id'] as string;\r\n if (knownPendingSessions.has(sid) || activeSessions.has(sid)) continue;\r\n knownPendingSessions.add(sid);\r\n\r\n if (opts.autoApprove) {\r\n await approveAndConnect(client, sessionManager, bridge, sid);\r\n } else {\r\n bridge.writeNotification('session.pending', {\r\n sessionId: sid,\r\n taskDescription: session['taskDescription'] ?? '',\r\n consumerUserId: session['consumerUserId'] ?? '',\r\n });\r\n }\r\n }\r\n } catch {\r\n // Silently retry on next poll\r\n }\r\n }, pollInterval);\r\n }\r\n\r\n // Connect via /ws/agent if token provided, otherwise fallback to polling\r\n if (opts.agentToken) {\r\n connectAgentWs(opts.agentToken);\r\n } else {\r\n startPollLoop();\r\n }\r\n\r\n // --- 6. Graceful shutdown ---\r\n const shutdown = async () => {\r\n if (pollTimer) clearInterval(pollTimer);\r\n if (agentHeartbeatTimer) clearInterval(agentHeartbeatTimer);\r\n bridge.stop();\r\n\r\n // Close agent WS (this triggers server-side offline update)\r\n if (agentWs) {\r\n try { agentWs.close(1000, 'Shutting down'); } catch { /* ignore */ }\r\n agentWs = null;\r\n }\r\n\r\n // Fallback: set offline via REST if no agent WS was used\r\n if (!opts.agentToken) {\r\n try {\r\n await client.setOnlineStatus(opts.agentId, 'offline');\r\n } catch {\r\n // Best effort\r\n }\r\n }\r\n\r\n sessionManager.disconnectAll();\r\n bridge.writeNotification('shutdown', { reason: 'signal' });\r\n\r\n // Give a moment for messages to flush\r\n setTimeout(() => process.exit(0), 500);\r\n };\r\n\r\n process.on('SIGINT', () => { void shutdown(); });\r\n process.on('SIGTERM', () => { void shutdown(); });\r\n}\r\n\r\nasync function approveAndConnect(\r\n client: ApiClient,\r\n sessionManager: SessionManager,\r\n bridge: StdioBridge,\r\n sessionId: string,\r\n): Promise<void> {\r\n try {\r\n const approved = (await client.approveSession(sessionId)) as Record<string, unknown>;\r\n const sessionToken = approved['sessionToken'] as string;\r\n const taskDescription = approved['taskDescription'] as string;\r\n\r\n activeSessions.add(sessionId);\r\n\r\n bridge.writeNotification('session.new', {\r\n sessionId,\r\n sessionToken,\r\n taskDescription: taskDescription ?? '',\r\n consumerUserId: (approved['consumerUserId'] as string) ?? '',\r\n });\r\n\r\n sessionManager.connect(sessionId, sessionToken);\r\n } catch (err: unknown) {\r\n bridge.writeNotification('session.approve_failed', {\r\n sessionId,\r\n error: err instanceof Error ? err.message : String(err),\r\n });\r\n }\r\n}\r\n","import { readFileSync, writeFileSync, unlinkSync, openSync, closeSync, mkdirSync, existsSync, readdirSync } from 'node:fs';\r\nimport { join, basename } from 'node:path';\r\nimport { spawn } from 'node:child_process';\r\nimport { getConfigDir } from './config.js';\r\n\r\nexport function getPidFilePath(agentId: string): string {\r\n return join(getConfigDir(), `serve-${agentId}.pid`);\r\n}\r\n\r\nexport function getLogFilePath(agentId: string): string {\r\n return join(getConfigDir(), `serve-${agentId}.log`);\r\n}\r\n\r\nexport function readPid(agentId: string): number | null {\r\n try {\r\n const content = readFileSync(getPidFilePath(agentId), 'utf-8').trim();\r\n const pid = parseInt(content, 10);\r\n return Number.isFinite(pid) && pid > 0 ? pid : null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport function writePid(agentId: string, pid: number): void {\r\n const dir = getConfigDir();\r\n if (!existsSync(dir)) {\r\n mkdirSync(dir, { recursive: true });\r\n }\r\n writeFileSync(getPidFilePath(agentId), String(pid), 'utf-8');\r\n}\r\n\r\nexport function removePidFile(agentId: string): void {\r\n try {\r\n unlinkSync(getPidFilePath(agentId));\r\n } catch {\r\n // Ignore ENOENT\r\n }\r\n}\r\n\r\nexport function isProcessAlive(pid: number): boolean {\r\n try {\r\n process.kill(pid, 0);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport function isDaemonRunning(agentId: string): { running: boolean; pid: number | null } {\r\n const pid = readPid(agentId);\r\n if (pid === null) return { running: false, pid: null };\r\n\r\n if (isProcessAlive(pid)) {\r\n return { running: true, pid };\r\n }\r\n\r\n // Stale PID file — process is dead, clean up\r\n removePidFile(agentId);\r\n return { running: false, pid: null };\r\n}\r\n\r\n/** List all running daemons by scanning PID files in config dir */\r\nexport function listRunningDaemons(): Array<{ agentId: string; pid: number }> {\r\n const dir = getConfigDir();\r\n if (!existsSync(dir)) return [];\r\n\r\n const results: Array<{ agentId: string; pid: number }> = [];\r\n\r\n for (const file of readdirSync(dir)) {\r\n const match = /^serve-(.+)\\.pid$/.exec(basename(file));\r\n if (!match) continue;\r\n\r\n const agentId = match[1]!;\r\n const { running, pid } = isDaemonRunning(agentId);\r\n if (running && pid !== null) {\r\n results.push({ agentId, pid });\r\n }\r\n }\r\n\r\n return results;\r\n}\r\n\r\nexport function spawnDaemon(agentId: string, args: string[]): number {\r\n const logFile = getLogFilePath(agentId);\r\n const dir = getConfigDir();\r\n if (!existsSync(dir)) {\r\n mkdirSync(dir, { recursive: true });\r\n }\r\n\r\n const logFd = openSync(logFile, 'a');\r\n\r\n const child = spawn(process.argv[0]!, [process.argv[1]!, ...args], {\r\n detached: true,\r\n stdio: ['ignore', logFd, logFd],\r\n windowsHide: true,\r\n });\r\n\r\n child.unref();\r\n closeSync(logFd);\r\n\r\n if (!child.pid) {\r\n throw new Error('Failed to start daemon process');\r\n }\r\n\r\n return child.pid;\r\n}\r\n","import { createInterface } from 'node:readline';\r\nimport type { JsonRpcMessage, JsonRpcResponse, JsonRpcRequest, JsonRpcNotification } from './protocol.js';\r\n\r\nexport type StdinMessageHandler = (msg: JsonRpcMessage) => void;\r\n\r\n/**\r\n * StdioBridge handles JSON Lines communication over stdin/stdout.\r\n * Each line is a JSON-RPC 2.0 message.\r\n */\r\nexport class StdioBridge {\r\n private handler: StdinMessageHandler | null = null;\r\n private rl: ReturnType<typeof createInterface> | null = null;\r\n\r\n /** Start reading from stdin */\r\n start(handler: StdinMessageHandler): void {\r\n this.handler = handler;\r\n this.rl = createInterface({ input: process.stdin, crlfDelay: Infinity });\r\n\r\n this.rl.on('line', (line) => {\r\n const trimmed = line.trim();\r\n if (!trimmed) return;\r\n\r\n try {\r\n const msg = JSON.parse(trimmed) as JsonRpcMessage;\r\n if (msg.jsonrpc !== '2.0') {\r\n this.writeError('Invalid JSON-RPC: missing jsonrpc field');\r\n return;\r\n }\r\n this.handler?.(msg);\r\n } catch {\r\n this.writeError(`Failed to parse JSON: ${trimmed.slice(0, 100)}`);\r\n }\r\n });\r\n\r\n this.rl.on('close', () => {\r\n // stdin closed — process will shut down\r\n });\r\n }\r\n\r\n /** Stop reading */\r\n stop(): void {\r\n this.rl?.close();\r\n this.rl = null;\r\n }\r\n\r\n /** Write a JSON-RPC message to stdout */\r\n write(msg: JsonRpcMessage): void {\r\n process.stdout.write(JSON.stringify(msg) + '\\n');\r\n }\r\n\r\n /** Write a notification */\r\n writeNotification(method: string, params: Record<string, unknown>): void {\r\n const msg: JsonRpcNotification = { jsonrpc: '2.0', method, params };\r\n this.write(msg);\r\n }\r\n\r\n /** Write a request (expects response) */\r\n writeRequest(method: string, id: string, params: Record<string, unknown>): void {\r\n const msg: JsonRpcRequest = { jsonrpc: '2.0', method, id, params };\r\n this.write(msg);\r\n }\r\n\r\n /** Write a response */\r\n writeResponse(id: string, result: Record<string, unknown>): void {\r\n const msg: JsonRpcResponse = { jsonrpc: '2.0', id, result };\r\n this.write(msg);\r\n }\r\n\r\n /** Write an error notification to stdout */\r\n private writeError(message: string): void {\r\n this.writeNotification('error', { message });\r\n }\r\n}\r\n","import { EventEmitter } from 'node:events';\r\nimport WebSocket from 'ws';\r\n\r\nexport interface SessionConnection {\r\n sessionId: string;\r\n sessionToken: string;\r\n ws: WebSocket;\r\n heartbeatTimer: ReturnType<typeof setInterval> | null;\r\n reconnectAttempts: number;\r\n}\r\n\r\n/**\r\n * SessionManager manages multiple concurrent WebSocket connections,\r\n * one per active session.\r\n */\r\nexport class SessionManager extends EventEmitter {\r\n private sessions = new Map<string, SessionConnection>();\r\n private wsUrl: string;\r\n private heartbeatInterval: number;\r\n private maxReconnectDelay: number;\r\n public agentId?: string;\r\n\r\n constructor(wsUrl: string, heartbeatInterval = 25_000, maxReconnectDelay = 30_000) {\r\n super();\r\n this.wsUrl = wsUrl;\r\n this.heartbeatInterval = heartbeatInterval;\r\n this.maxReconnectDelay = maxReconnectDelay;\r\n }\r\n\r\n /** Connect to a session via WebSocket as provider */\r\n connect(sessionId: string, sessionToken: string): void {\r\n if (this.sessions.has(sessionId)) {\r\n return; // Already connected\r\n }\r\n\r\n const url = `${this.wsUrl}/ws/session?sessionId=${sessionId}&token=${sessionToken}&role=provider`;\r\n const ws = new WebSocket(url);\r\n\r\n const conn: SessionConnection = {\r\n sessionId,\r\n sessionToken,\r\n ws,\r\n heartbeatTimer: null,\r\n reconnectAttempts: 0,\r\n };\r\n\r\n this.sessions.set(sessionId, conn);\r\n\r\n ws.on('open', () => {\r\n conn.reconnectAttempts = 0;\r\n conn.heartbeatTimer = setInterval(() => {\r\n if (ws.readyState === WebSocket.OPEN) {\r\n ws.send(JSON.stringify({ type: 'system.heartbeat', payload: {} }));\r\n }\r\n }, this.heartbeatInterval);\r\n\r\n this.emit('session:connected', sessionId);\r\n });\r\n\r\n ws.on('message', (raw) => {\r\n try {\r\n const message = JSON.parse(raw.toString()) as Record<string, unknown>;\r\n // Skip heartbeat acks\r\n if (message['type'] === 'system.heartbeat_ack') return;\r\n\r\n this.emit('session:message', sessionId, message);\r\n } catch {\r\n // Ignore parse errors\r\n }\r\n });\r\n\r\n ws.on('close', (code, reason) => {\r\n this.clearHeartbeat(conn);\r\n\r\n if (code !== 1000) {\r\n // Abnormal close — try reconnect\r\n const delay = Math.min(\r\n 1000 * Math.pow(2, conn.reconnectAttempts),\r\n this.maxReconnectDelay,\r\n );\r\n conn.reconnectAttempts++;\r\n\r\n this.emit('session:reconnecting', sessionId, delay);\r\n\r\n setTimeout(() => {\r\n this.sessions.delete(sessionId);\r\n this.connect(sessionId, sessionToken);\r\n }, delay);\r\n } else {\r\n this.sessions.delete(sessionId);\r\n this.emit('session:disconnected', sessionId, reason.toString());\r\n }\r\n });\r\n\r\n ws.on('error', (err) => {\r\n this.emit('session:error', sessionId, err);\r\n });\r\n }\r\n\r\n /** Send a message to a specific session, auto-wrapping with protocol envelope */\r\n send(sessionId: string, message: Record<string, unknown>): boolean {\r\n const conn = this.sessions.get(sessionId);\r\n if (!conn || conn.ws.readyState !== WebSocket.OPEN) {\r\n return false;\r\n }\r\n // Ensure full ClawRentMessage envelope\r\n const envelope = {\r\n id: message['id'] ?? `msg_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\r\n sessionId: message['sessionId'] ?? sessionId,\r\n timestamp: message['timestamp'] ?? Date.now(),\r\n sender: message['sender'] ?? { role: 'provider', agentId: this.agentId ?? 'unknown' },\r\n type: message['type'] ?? 'result.success',\r\n payload: message['payload'] ?? {},\r\n };\r\n conn.ws.send(JSON.stringify(envelope));\r\n return true;\r\n }\r\n\r\n /** Disconnect a specific session */\r\n disconnect(sessionId: string): void {\r\n const conn = this.sessions.get(sessionId);\r\n if (!conn) return;\r\n\r\n this.clearHeartbeat(conn);\r\n if (conn.ws.readyState === WebSocket.OPEN || conn.ws.readyState === WebSocket.CONNECTING) {\r\n conn.ws.close(1000, 'Provider disconnecting');\r\n }\r\n this.sessions.delete(sessionId);\r\n }\r\n\r\n /** Disconnect all sessions */\r\n disconnectAll(): void {\r\n for (const sessionId of this.sessions.keys()) {\r\n this.disconnect(sessionId);\r\n }\r\n }\r\n\r\n /** Get active session count */\r\n get activeCount(): number {\r\n return this.sessions.size;\r\n }\r\n\r\n /** Check if a session is connected */\r\n isConnected(sessionId: string): boolean {\r\n const conn = this.sessions.get(sessionId);\r\n return conn?.ws.readyState === WebSocket.OPEN;\r\n }\r\n\r\n private clearHeartbeat(conn: SessionConnection): void {\r\n if (conn.heartbeatTimer) {\r\n clearInterval(conn.heartbeatTimer);\r\n conn.heartbeatTimer = null;\r\n }\r\n }\r\n}\r\n","// JSON-RPC 2.0 protocol types for clawrent serve stdin/stdout communication\r\n\r\n/** Base JSON-RPC message */\r\nexport interface JsonRpcBase {\r\n jsonrpc: '2.0';\r\n}\r\n\r\n/** JSON-RPC request (has method + id) */\r\nexport interface JsonRpcRequest extends JsonRpcBase {\r\n method: string;\r\n id: string;\r\n params?: Record<string, unknown>;\r\n}\r\n\r\n/** JSON-RPC notification (has method, no id) */\r\nexport interface JsonRpcNotification extends JsonRpcBase {\r\n method: string;\r\n params?: Record<string, unknown>;\r\n}\r\n\r\n/** JSON-RPC response (has id + result or error) */\r\nexport interface JsonRpcResponse extends JsonRpcBase {\r\n id: string;\r\n result?: Record<string, unknown>;\r\n error?: { code: number; message: string; data?: unknown };\r\n}\r\n\r\nexport type JsonRpcMessage = JsonRpcRequest | JsonRpcNotification | JsonRpcResponse;\r\n\r\n// --- Daemon -> Agent (stdout) methods ---\r\n\r\nexport interface ReadyParams {\r\n agentId: string;\r\n agentName: string;\r\n}\r\n\r\nexport interface SessionNewParams {\r\n sessionId: string;\r\n sessionToken: string;\r\n taskDescription: string;\r\n consumerUserId: string;\r\n}\r\n\r\nexport interface SessionPendingParams {\r\n sessionId: string;\r\n taskDescription: string;\r\n consumerUserId: string;\r\n}\r\n\r\nexport interface InstructionParams {\r\n sessionId: string;\r\n messageId: string;\r\n type: string;\r\n payload: Record<string, unknown>;\r\n sender?: Record<string, unknown>;\r\n}\r\n\r\nexport interface DialogueParams {\r\n sessionId: string;\r\n content: string;\r\n dialogueType: string;\r\n}\r\n\r\nexport interface SessionEndedParams {\r\n sessionId: string;\r\n reason: string;\r\n}\r\n\r\n// --- Agent -> Daemon (stdin) methods ---\r\n\r\nexport interface ResultPayload {\r\n sessionId: string;\r\n type: string;\r\n payload: Record<string, unknown>;\r\n}\r\n\r\nexport interface SendParams {\r\n sessionId: string;\r\n type: string;\r\n payload: Record<string, unknown>;\r\n}\r\n\r\nexport interface ApproveParams {\r\n sessionId: string;\r\n}\r\n\r\n// --- Helpers ---\r\n\r\nlet correlationCounter = 0;\r\n\r\nexport function createCorrelationId(): string {\r\n return `corr_${Date.now().toString(36)}_${(correlationCounter++).toString(36)}`;\r\n}\r\n\r\nexport function createNotification(method: string, params: Record<string, unknown>): JsonRpcNotification {\r\n return { jsonrpc: '2.0', method, params };\r\n}\r\n\r\nexport function createRequest(method: string, params: Record<string, unknown>, id?: string): JsonRpcRequest {\r\n return { jsonrpc: '2.0', method, id: id ?? createCorrelationId(), params };\r\n}\r\n\r\nexport function isResponse(msg: JsonRpcMessage): msg is JsonRpcResponse {\r\n return 'id' in msg && ('result' in msg || 'error' in msg) && !('method' in msg);\r\n}\r\n\r\nexport function isRequest(msg: JsonRpcMessage): msg is JsonRpcRequest {\r\n return 'method' in msg && 'id' in msg;\r\n}\r\n\r\nexport function isNotification(msg: JsonRpcMessage): msg is JsonRpcNotification {\r\n return 'method' in msg && !('id' in msg);\r\n}\r\n","import { Command } from 'commander';\r\nimport { isDaemonRunning, removePidFile, isProcessAlive, listRunningDaemons } from '../daemon.js';\r\nimport { printSuccess, printError } from '../output.js';\r\n\r\nasync function stopOne(agentId: string): Promise<boolean> {\r\n const { running, pid } = isDaemonRunning(agentId);\r\n\r\n if (!running || pid === null) {\r\n return false;\r\n }\r\n\r\n try {\r\n process.kill(pid, 'SIGTERM');\r\n } catch (err: unknown) {\r\n const code = (err as NodeJS.ErrnoException).code;\r\n if (code === 'ESRCH') {\r\n removePidFile(agentId);\r\n return true;\r\n }\r\n if (code === 'EPERM') {\r\n printError(`Permission denied. Cannot stop daemon for agent ${agentId} (PID: ${pid}).`);\r\n return false;\r\n }\r\n throw err;\r\n }\r\n\r\n const maxWait = 3000;\r\n const interval = 200;\r\n let waited = 0;\r\n\r\n while (waited < maxWait) {\r\n await new Promise((r) => setTimeout(r, interval));\r\n waited += interval;\r\n if (!isProcessAlive(pid)) {\r\n removePidFile(agentId);\r\n printSuccess(`Daemon stopped for agent ${agentId} (PID: ${pid}).`);\r\n return true;\r\n }\r\n }\r\n\r\n try {\r\n process.kill(pid, 'SIGKILL');\r\n } catch {\r\n // May have exited between check and kill\r\n }\r\n\r\n removePidFile(agentId);\r\n printSuccess(`Daemon stopped for agent ${agentId} (PID: ${pid}).`);\r\n return true;\r\n}\r\n\r\nexport function registerStopCommand(program: Command): void {\r\n program\r\n .command('stop')\r\n .description('Stop background serve daemon(s)')\r\n .option('--agent-id <id>', 'Stop daemon for a specific agent')\r\n .option('--all', 'Stop all running daemons', false)\r\n .action(async (opts: { agentId?: string; all: boolean }) => {\r\n if (opts.agentId) {\r\n const stopped = await stopOne(opts.agentId);\r\n if (!stopped) {\r\n printSuccess(`No daemon running for agent ${opts.agentId}.`);\r\n }\r\n return;\r\n }\r\n\r\n // Default: stop all\r\n const daemons = listRunningDaemons();\r\n if (daemons.length === 0) {\r\n printSuccess('No daemons are running.');\r\n return;\r\n }\r\n\r\n for (const d of daemons) {\r\n await stopOne(d.agentId);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { isDaemonRunning, getLogFilePath, listRunningDaemons } from '../daemon.js';\r\nimport { printJson } from '../output.js';\r\n\r\nexport function registerStatusCommand(program: Command): void {\r\n program\r\n .command('status')\r\n .description('Check running serve daemon(s)')\r\n .option('--agent-id <id>', 'Check daemon for a specific agent')\r\n .action((opts: { agentId?: string }) => {\r\n if (opts.agentId) {\r\n const { running, pid } = isDaemonRunning(opts.agentId);\r\n if (running && pid !== null) {\r\n printJson({ status: 'running', agentId: opts.agentId, pid, logFile: getLogFilePath(opts.agentId) });\r\n } else {\r\n printJson({ status: 'stopped', agentId: opts.agentId });\r\n }\r\n return;\r\n }\r\n\r\n // List all running daemons\r\n const daemons = listRunningDaemons();\r\n if (daemons.length === 0) {\r\n printJson({ daemons: [] });\r\n } else {\r\n printJson({\r\n daemons: daemons.map((d) => ({\r\n agentId: d.agentId,\r\n pid: d.pid,\r\n logFile: getLogFilePath(d.agentId),\r\n })),\r\n });\r\n }\r\n });\r\n}\r\n"],"mappings":"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","names":["readFileSync","join","program","program","program","program","program","program","program","program","program","program","program","WebSocket","readFileSync","writeFileSync","unlinkSync","mkdirSync","existsSync","join","join","readFileSync","existsSync","mkdirSync","writeFileSync","unlinkSync","createInterface","WebSocket","program","WebSocket","program","program","readFileSync","join"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/auth.ts","../src/config.ts","../src/api-client.ts","../src/output.ts","../src/commands/browse.ts","../src/commands/agent.ts","../src/commands/sessions.ts","../src/commands/balance.ts","../src/commands/topup.ts","../src/commands/health.ts","../src/commands/rent.ts","../src/commands/end.ts","../src/commands/send.ts","../src/commands/provider/index.ts","../src/serve/index.ts","../src/daemon.ts","../src/serve/stdio-bridge.ts","../src/serve/session-manager.ts","../src/serve/protocol.ts","../src/commands/stop.ts","../src/commands/status.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\r\nimport { dirname, join } from 'node:path';\r\nimport { fileURLToPath } from 'node:url';\r\nimport { Command } from 'commander';\r\nimport { registerAuthCommand } from './commands/auth.js';\r\nimport { registerBrowseCommand } from './commands/browse.js';\r\nimport { registerAgentCommand } from './commands/agent.js';\r\nimport { registerSessionsCommand } from './commands/sessions.js';\r\nimport { registerBalanceCommand } from './commands/balance.js';\r\nimport { registerTopupCommand } from './commands/topup.js';\r\nimport { registerHealthCommand } from './commands/health.js';\r\nimport { registerRentCommand } from './commands/rent.js';\r\nimport { registerEndCommand } from './commands/end.js';\r\nimport { registerSendCommand } from './commands/send.js';\r\nimport { registerProviderCommands } from './commands/provider/index.js';\r\nimport { registerServeCommand } from './serve/index.js';\r\nimport { registerStopCommand } from './commands/stop.js';\r\nimport { registerStatusCommand } from './commands/status.js';\r\n\r\nconst __dirname = dirname(fileURLToPath(import.meta.url));\r\nconst pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('clawrent')\r\n .description('ClawRent CLI - Agent capability rental platform')\r\n .version(pkg.version);\r\n\r\n// Auth\r\nregisterAuthCommand(program);\r\n\r\n// Consumer commands\r\nregisterBrowseCommand(program);\r\nregisterAgentCommand(program);\r\nregisterSessionsCommand(program);\r\nregisterBalanceCommand(program);\r\nregisterTopupCommand(program);\r\nregisterRentCommand(program);\r\nregisterEndCommand(program);\r\nregisterSendCommand(program);\r\nregisterHealthCommand(program);\r\n\r\n// Provider commands\r\nregisterProviderCommands(program);\r\n\r\n// Serve daemon\r\nregisterServeCommand(program);\r\n\r\n// Daemon management\r\nregisterStopCommand(program);\r\nregisterStatusCommand(program);\r\n\r\nprogram.parse();\r\n","import { Command } from 'commander';\r\nimport { createInterface } from 'node:readline';\r\nimport { loadConfig, saveConfig, clearConfig, getConfigPath } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError, printSuccess } from '../output.js';\r\n\r\nfunction deriveWsUrl(apiUrl: string): string {\r\n return apiUrl.replace(/^http/, 'ws');\r\n}\r\n\r\nasync function promptInput(prompt: string, hidden: boolean = false): Promise<string> {\r\n const rl = createInterface({ input: process.stdin, output: process.stderr });\r\n\r\n return new Promise((resolve) => {\r\n if (hidden) {\r\n // For password: write prompt manually, mute output\r\n process.stderr.write(prompt);\r\n const stdin = process.stdin;\r\n const wasRaw = stdin.isRaw;\r\n if (stdin.isTTY) stdin.setRawMode(true);\r\n let input = '';\r\n const onData = (ch: Buffer) => {\r\n const c = ch.toString('utf-8');\r\n if (c === '\\n' || c === '\\r') {\r\n stdin.removeListener('data', onData);\r\n if (stdin.isTTY && wasRaw !== undefined) stdin.setRawMode(wasRaw);\r\n process.stderr.write('\\n');\r\n rl.close();\r\n resolve(input);\r\n } else if (c === '\\u0003') {\r\n // Ctrl+C\r\n rl.close();\r\n process.exit(1);\r\n } else if (c === '\\u007F' || c === '\\b') {\r\n // Backspace\r\n input = input.slice(0, -1);\r\n } else {\r\n input += c;\r\n }\r\n };\r\n stdin.on('data', onData);\r\n } else {\r\n rl.question(prompt, (answer) => {\r\n rl.close();\r\n resolve(answer);\r\n });\r\n }\r\n });\r\n}\r\n\r\nexport function registerAuthCommand(program: Command): void {\r\n const auth = program\r\n .command('auth')\r\n .description('Authentication management');\r\n\r\n auth\r\n .command('login')\r\n .description('Login to ClawRent platform')\r\n .option('-e, --email <email>', 'Email address')\r\n .option('-p, --password <password>', 'Password')\r\n .option('--api-url <url>', 'Platform API URL')\r\n .action(async (opts: { email?: string; password?: string; apiUrl?: string }) => {\r\n try {\r\n const currentConfig = loadConfig();\r\n const apiUrl = opts.apiUrl ?? currentConfig.apiUrl;\r\n const wsUrl = deriveWsUrl(apiUrl);\r\n\r\n const email = opts.email ?? await promptInput('Email: ');\r\n const password = opts.password ?? await promptInput('Password: ', true);\r\n\r\n if (!email || !password) {\r\n printError('Email and password are required.');\r\n process.exit(1);\r\n }\r\n\r\n const client = new ApiClient({ ...currentConfig, apiUrl, wsUrl });\r\n const result = await client.login(email, password);\r\n\r\n // Save credentials (do NOT save apiUrl/wsUrl — they come from defaults or env vars,\r\n // saving them would pin the config to a specific URL and break after default changes)\r\n saveConfig({\r\n token: result.token,\r\n userId: result.user.id,\r\n email: result.user.email,\r\n name: result.user.name,\r\n });\r\n\r\n printSuccess(`Logged in as ${result.user.name} (${result.user.email})`);\r\n printSuccess(`Config saved to ${getConfigPath()}`);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n auth\r\n .command('logout')\r\n .description('Logout and clear saved credentials')\r\n .action(() => {\r\n try {\r\n clearConfig();\r\n printSuccess('Logged out. Config cleared.');\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n auth\r\n .command('whoami')\r\n .description('Show current user info')\r\n .action(async () => {\r\n try {\r\n const config = loadConfig();\r\n const client = new ApiClient(config);\r\n const me = await client.getMe();\r\n printJson(me);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { readFileSync, writeFileSync, mkdirSync, unlinkSync, existsSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport { homedir } from 'node:os';\r\n\r\nexport interface ClawRentConfig {\r\n apiUrl: string;\r\n wsUrl: string;\r\n token?: string;\r\n apiKey?: string;\r\n userId?: string;\r\n email?: string;\r\n name?: string;\r\n}\r\n\r\nconst DEFAULT_CONFIG: ClawRentConfig = {\r\n apiUrl: 'https://clawrent.cloud',\r\n wsUrl: 'wss://clawrent.cloud',\r\n};\r\n\r\nexport function getConfigDir(): string {\r\n return join(homedir(), '.clawrent');\r\n}\r\n\r\nfunction getConfigFilePath(): string {\r\n return join(getConfigDir(), 'config.json');\r\n}\r\n\r\nexport function getConfigPath(): string {\r\n return getConfigFilePath();\r\n}\r\n\r\nexport function loadConfig(): ClawRentConfig {\r\n let fileConfig: Partial<ClawRentConfig> = {};\r\n\r\n const configPath = getConfigFilePath();\r\n if (existsSync(configPath)) {\r\n try {\r\n const raw = readFileSync(configPath, 'utf-8');\r\n fileConfig = JSON.parse(raw) as Partial<ClawRentConfig>;\r\n } catch {\r\n // Ignore corrupt config file\r\n }\r\n }\r\n\r\n // Migration: remove stale localhost URLs saved by older CLI versions.\r\n // These override the new production defaults and break remote connections.\r\n if (fileConfig.apiUrl?.includes('localhost') || fileConfig.wsUrl?.includes('localhost')) {\r\n delete fileConfig.apiUrl;\r\n delete fileConfig.wsUrl;\r\n // Persist the cleanup so it only runs once\r\n try {\r\n const cleaned = { ...fileConfig };\r\n writeFileSync(configPath, JSON.stringify(cleaned, null, 2), 'utf-8');\r\n } catch {\r\n // Non-fatal\r\n }\r\n }\r\n\r\n // Merge: defaults < file < env vars\r\n const config: ClawRentConfig = {\r\n ...DEFAULT_CONFIG,\r\n ...fileConfig,\r\n };\r\n\r\n // Env vars always override\r\n const envApiUrl = process.env['CLAWRENT_API_URL'];\r\n const envWsUrl = process.env['CLAWRENT_WS_URL'];\r\n const envToken = process.env['CLAWRENT_TOKEN'];\r\n const envApiKey = process.env['CLAWRENT_API_KEY'];\r\n const envUserId = process.env['CLAWRENT_USER_ID'];\r\n\r\n if (envApiUrl) config.apiUrl = envApiUrl;\r\n if (envWsUrl) config.wsUrl = envWsUrl;\r\n if (envToken) config.token = envToken;\r\n if (envApiKey) config.apiKey = envApiKey;\r\n if (envUserId) config.userId = envUserId;\r\n\r\n return config;\r\n}\r\n\r\nexport function saveConfig(partial: Partial<ClawRentConfig>): void {\r\n const configDir = getConfigDir();\r\n if (!existsSync(configDir)) {\r\n mkdirSync(configDir, { recursive: true });\r\n }\r\n\r\n let existing: Partial<ClawRentConfig> = {};\r\n const configPath = getConfigFilePath();\r\n if (existsSync(configPath)) {\r\n try {\r\n existing = JSON.parse(readFileSync(configPath, 'utf-8')) as Partial<ClawRentConfig>;\r\n } catch {\r\n // Overwrite corrupt file\r\n }\r\n }\r\n\r\n const merged = { ...existing, ...partial };\r\n writeFileSync(configPath, JSON.stringify(merged, null, 2), 'utf-8');\r\n}\r\n\r\nexport function clearConfig(): void {\r\n const configPath = getConfigFilePath();\r\n if (existsSync(configPath)) {\r\n unlinkSync(configPath);\r\n }\r\n}\r\n","import type { ClawRentConfig } from './config.js';\r\n\r\nexport class ApiClient {\r\n private config: ClawRentConfig;\r\n\r\n constructor(config: ClawRentConfig) {\r\n this.config = config;\r\n }\r\n\r\n get apiUrl(): string {\r\n return this.config.apiUrl;\r\n }\r\n\r\n get wsUrl(): string {\r\n return this.config.wsUrl;\r\n }\r\n\r\n get userId(): string | undefined {\r\n return this.config.userId;\r\n }\r\n\r\n // --- Auth (no auth needed) ---\r\n\r\n async login(email: string, password: string): Promise<{ user: { id: string; email: string; name: string; role: string }; token: string }> {\r\n return this.request('POST', '/api/auth/login', { email, password }, false);\r\n }\r\n\r\n async getMe(): Promise<Record<string, unknown>> {\r\n return this.request('GET', '/api/auth/me');\r\n }\r\n\r\n // --- Marketplace ---\r\n\r\n async browse(query?: { search?: string; category?: string; page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.search) params.set('search', query.search);\r\n if (query?.category) params.set('category', query.category);\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/marketplace/browse${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async getAgent(slug: string): Promise<unknown> {\r\n return this.request('GET', `/api/marketplace/agents/${encodeURIComponent(slug)}`);\r\n }\r\n\r\n // --- Sessions ---\r\n\r\n async rent(options: { agentId: string; taskDescription: string; grantedPermissions?: Record<string, unknown> }): Promise<unknown> {\r\n return this.request('POST', '/api/sessions', {\r\n agentId: options.agentId,\r\n taskDescription: options.taskDescription,\r\n grantedPermissions: options.grantedPermissions ?? {},\r\n });\r\n }\r\n\r\n async getSessions(query?: { role?: string; status?: string; page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.role) params.set('role', query.role);\r\n if (query?.status) params.set('status', query.status);\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/sessions${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async getSession(sessionId: string): Promise<Record<string, unknown>> {\r\n return this.request('GET', `/api/sessions/${encodeURIComponent(sessionId)}`);\r\n }\r\n\r\n async getSessionMessages(sessionId: string): Promise<unknown> {\r\n return this.request('GET', `/api/sessions/${encodeURIComponent(sessionId)}/messages`);\r\n }\r\n\r\n async endSession(sessionId: string): Promise<unknown> {\r\n return this.request('POST', `/api/sessions/${encodeURIComponent(sessionId)}/end`);\r\n }\r\n\r\n async approveSession(sessionId: string): Promise<unknown> {\r\n return this.request('POST', `/api/sessions/${encodeURIComponent(sessionId)}/approve`);\r\n }\r\n\r\n // --- Billing ---\r\n\r\n async getBalance(): Promise<{ balance: string }> {\r\n return this.request('GET', '/api/billing/wallet');\r\n }\r\n\r\n async topUp(amount: string): Promise<{ balance: string }> {\r\n return this.request('POST', '/api/billing/wallet/topup', { amount });\r\n }\r\n\r\n // --- Provider: Agents ---\r\n\r\n async registerAgent(data: Record<string, unknown>): Promise<unknown> {\r\n return this.request('POST', '/api/agents', data);\r\n }\r\n\r\n async getMyAgents(query?: { page?: number; limit?: number; status?: string }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n if (query?.status) params.set('status', query.status);\r\n const qs = params.toString();\r\n return this.request('GET', `/api/agents/my${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n /** Resolve the current agent from agentToken. Requires agt_clawrent_ token auth. */\r\n async getMyAgent(): Promise<Record<string, unknown>> {\r\n return this.request('GET', '/api/agents/me/agent');\r\n }\r\n\r\n async publishAgent(agentId: string): Promise<unknown> {\r\n return this.request('POST', `/api/agents/${encodeURIComponent(agentId)}/publish`);\r\n }\r\n\r\n async activateAgent(agentId: string): Promise<unknown> {\r\n return this.request('POST', `/api/agents/${encodeURIComponent(agentId)}/activate`);\r\n }\r\n\r\n async setOnlineStatus(agentId: string, onlineStatus: string): Promise<unknown> {\r\n return this.request('PATCH', `/api/agents/${encodeURIComponent(agentId)}/status`, { onlineStatus });\r\n }\r\n\r\n async generateAgentToken(agentId: string): Promise<{ agentId: string; token: string; createdAt: string; warning: string }> {\r\n return this.request('POST', `/api/agents/${encodeURIComponent(agentId)}/token`);\r\n }\r\n\r\n async revokeAgentToken(agentId: string): Promise<{ message: string }> {\r\n return this.request('DELETE', `/api/agents/${encodeURIComponent(agentId)}/token`);\r\n }\r\n\r\n // --- Orders ---\r\n\r\n async createOrder(data: {\r\n items: Array<{ providerAgentId: string; consumerAgentId?: string; taskDescription: string; grantedPermissions?: Record<string, unknown> }>;\r\n note?: string;\r\n fromCart?: boolean;\r\n }): Promise<unknown> {\r\n return this.request('POST', '/api/orders', data);\r\n }\r\n\r\n async getOrders(query?: { status?: string; page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.status) params.set('status', query.status);\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/orders${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async getOrder(orderId: string): Promise<unknown> {\r\n return this.request('GET', `/api/orders/${encodeURIComponent(orderId)}`);\r\n }\r\n\r\n async cancelOrder(orderId: string): Promise<unknown> {\r\n return this.request('POST', `/api/orders/${encodeURIComponent(orderId)}/cancel`);\r\n }\r\n\r\n // --- Cart ---\r\n\r\n async getCart(): Promise<unknown> {\r\n return this.request('GET', '/api/cart');\r\n }\r\n\r\n async addToCart(data: { providerAgentId: string; taskDescription: string }): Promise<unknown> {\r\n return this.request('POST', '/api/cart', data);\r\n }\r\n\r\n async updateCartItem(itemId: string, data: { taskDescription: string }): Promise<unknown> {\r\n return this.request('PATCH', `/api/cart/${encodeURIComponent(itemId)}`, data);\r\n }\r\n\r\n async removeFromCart(itemId: string): Promise<unknown> {\r\n return this.request('DELETE', `/api/cart/${encodeURIComponent(itemId)}`);\r\n }\r\n\r\n async clearCart(): Promise<unknown> {\r\n return this.request('DELETE', '/api/cart');\r\n }\r\n\r\n // --- Favorites ---\r\n\r\n async listFavorites(query?: { page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/favorites${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async addFavorite(agentId: string): Promise<unknown> {\r\n return this.request('POST', `/api/favorites/${encodeURIComponent(agentId)}`);\r\n }\r\n\r\n async removeFavorite(agentId: string): Promise<unknown> {\r\n return this.request('DELETE', `/api/favorites/${encodeURIComponent(agentId)}`);\r\n }\r\n\r\n // --- Health ---\r\n\r\n async health(): Promise<unknown> {\r\n return this.request('GET', '/api/health', undefined, false);\r\n }\r\n\r\n // --- Private ---\r\n\r\n private async request<T = any>(method: string, path: string, body?: unknown, requireAuth: boolean = true): Promise<T> {\r\n const url = `${this.config.apiUrl}${path}`;\r\n const headers: Record<string, string> = {};\r\n\r\n if (body !== undefined) {\r\n headers['Content-Type'] = 'application/json';\r\n }\r\n\r\n if (requireAuth) {\r\n if (this.config.token) {\r\n headers['Authorization'] = `Bearer ${this.config.token}`;\r\n } else if (this.config.apiKey) {\r\n headers['x-api-key'] = this.config.apiKey;\r\n } else {\r\n throw new Error('Not authenticated. Run `clawrent auth login` first.');\r\n }\r\n }\r\n\r\n const response = await fetch(url, {\r\n method,\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n\r\n if (!response.ok) {\r\n const errBody = await response.json().catch(() => ({ message: response.statusText })) as Record<string, unknown>;\r\n throw new Error(`API error ${response.status}: ${errBody['message'] ?? JSON.stringify(errBody)}`);\r\n }\r\n\r\n return response.json() as Promise<T>;\r\n }\r\n}\r\n","export function printJson(data: unknown): void {\r\n process.stdout.write(JSON.stringify(data, null, 2) + '\\n');\r\n}\r\n\r\nexport function printError(message: string): void {\r\n process.stderr.write(`Error: ${message}\\n`);\r\n}\r\n\r\nexport function printSuccess(message: string): void {\r\n process.stdout.write(`${message}\\n`);\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError } from '../output.js';\r\n\r\nexport function registerBrowseCommand(program: Command): void {\r\n program\r\n .command('browse')\r\n .description('Browse available agents on the marketplace')\r\n .option('-s, --search <query>', 'Search by name')\r\n .option('-c, --category <category>', 'Filter by category')\r\n .option('-p, --page <number>', 'Page number', '1')\r\n .option('-l, --limit <number>', 'Results per page', '20')\r\n .action(async (opts: { search?: string; category?: string; page: string; limit: string }) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.browse({\r\n search: opts.search,\r\n category: opts.category,\r\n page: parseInt(opts.page, 10),\r\n limit: parseInt(opts.limit, 10),\r\n });\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError } from '../output.js';\r\n\r\nexport function registerAgentCommand(program: Command): void {\r\n program\r\n .command('agent <slug>')\r\n .description('Get agent details by slug')\r\n .action(async (slug: string) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.getAgent(slug);\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError } from '../output.js';\r\n\r\nexport function registerSessionsCommand(program: Command): void {\r\n program\r\n .command('sessions')\r\n .description('List your sessions')\r\n .option('-r, --role <role>', 'Filter by role (consumer/provider)')\r\n .option('-s, --status <status>', 'Filter by status')\r\n .option('-p, --page <number>', 'Page number', '1')\r\n .option('-l, --limit <number>', 'Results per page', '20')\r\n .action(async (opts: { role?: string; status?: string; page: string; limit: string }) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.getSessions({\r\n role: opts.role,\r\n status: opts.status,\r\n page: parseInt(opts.page, 10),\r\n limit: parseInt(opts.limit, 10),\r\n });\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printSuccess, printError } from '../output.js';\r\n\r\nexport function registerBalanceCommand(program: Command): void {\r\n program\r\n .command('balance')\r\n .description('Check wallet balance')\r\n .action(async () => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.getBalance();\r\n printSuccess(`Balance: ${result.balance}`);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printSuccess, printError } from '../output.js';\r\n\r\nexport function registerTopupCommand(program: Command): void {\r\n program\r\n .command('topup <amount>')\r\n .description('Top up wallet balance')\r\n .action(async (amount: string) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.topUp(amount);\r\n printSuccess(`New balance: ${result.balance}`);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError } from '../output.js';\r\n\r\nexport function registerHealthCommand(program: Command): void {\r\n program\r\n .command('health')\r\n .description('Check platform health')\r\n .action(async () => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.health();\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError } from '../output.js';\r\n\r\nexport function registerRentCommand(program: Command): void {\r\n program\r\n .command('rent')\r\n .description('Rent an agent (create a session)')\r\n .requiredOption('--agent-id <id>', 'Agent ID to rent')\r\n .requiredOption('--task <description>', 'Task description')\r\n .option('--permissions <json>', 'Granted permissions as JSON string', '{}')\r\n .action(async (opts: { agentId: string; task: string; permissions: string }) => {\r\n try {\r\n let grantedPermissions: Record<string, unknown> = {};\r\n try {\r\n grantedPermissions = JSON.parse(opts.permissions) as Record<string, unknown>;\r\n } catch {\r\n printError('Invalid JSON for --permissions');\r\n process.exit(1);\r\n }\r\n\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.rent({\r\n agentId: opts.agentId,\r\n taskDescription: opts.task,\r\n grantedPermissions,\r\n });\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError } from '../output.js';\r\n\r\nexport function registerEndCommand(program: Command): void {\r\n program\r\n .command('end <sessionId>')\r\n .description('End a session')\r\n .action(async (sessionId: string) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.endSession(sessionId);\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport WebSocket from 'ws';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printJson, printError, printSuccess } from '../output.js';\r\n\r\nexport function registerSendCommand(program: Command): void {\r\n program\r\n .command('send <sessionId>')\r\n .description('Send a message to a session via WebSocket')\r\n .requiredOption('--content <text>', 'Message content')\r\n .option('--type <messageType>', 'Message type', 'dialogue.message')\r\n .option('--token <sessionToken>', 'Session token (auto-fetched if not provided)')\r\n .option('--wait <ms>', 'Wait for response (milliseconds)')\r\n .action(async (sessionId: string, opts: { content: string; type: string; token?: string; wait?: string }) => {\r\n try {\r\n const config = loadConfig();\r\n const client = new ApiClient(config);\r\n\r\n // Get session token if not provided\r\n let sessionToken = opts.token;\r\n let role = 'consumer';\r\n if (!sessionToken) {\r\n const session = await client.getSession(sessionId);\r\n sessionToken = session['sessionToken'] as string;\r\n // Determine role\r\n if (config.userId && session['providerUserId'] === config.userId) {\r\n role = 'provider';\r\n }\r\n }\r\n\r\n if (!sessionToken) {\r\n printError('Could not determine session token. Use --token flag.');\r\n process.exit(1);\r\n }\r\n\r\n const wsUrl = `${config.wsUrl}/ws/session?sessionId=${sessionId}&token=${sessionToken}&role=${role}`;\r\n\r\n await new Promise<void>((resolve, reject) => {\r\n const ws = new WebSocket(wsUrl);\r\n let responded = false;\r\n\r\n ws.on('open', () => {\r\n // Build full protocol envelope as required by ClawRentMessageSchema\r\n const message = {\r\n id: `msg_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\r\n sessionId,\r\n timestamp: Date.now(),\r\n sender: { role, agentId: config.userId ?? 'unknown' },\r\n type: opts.type,\r\n payload: { content: opts.content, dialogueType: 'message' },\r\n };\r\n ws.send(JSON.stringify(message));\r\n\r\n if (opts.wait) {\r\n // Wait for response\r\n setTimeout(() => {\r\n if (!responded) {\r\n ws.close(1000);\r\n printSuccess('Message sent (no response within timeout).');\r\n resolve();\r\n }\r\n }, parseInt(opts.wait, 10));\r\n } else {\r\n // Send and close\r\n setTimeout(() => {\r\n ws.close(1000);\r\n printSuccess('Message sent.');\r\n resolve();\r\n }, 500);\r\n }\r\n });\r\n\r\n ws.on('message', (raw) => {\r\n try {\r\n const data = JSON.parse(raw.toString());\r\n if (data.type !== 'system.heartbeat_ack' && data.type !== 'system.peer_connected') {\r\n responded = true;\r\n printJson(data);\r\n if (opts.wait) {\r\n ws.close(1000);\r\n resolve();\r\n }\r\n }\r\n } catch {\r\n // ignore parse errors\r\n }\r\n });\r\n\r\n ws.on('error', (err) => {\r\n reject(err);\r\n });\r\n\r\n ws.on('close', () => {\r\n if (!responded && opts.wait) {\r\n resolve();\r\n }\r\n });\r\n });\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { loadConfig } from '../../config.js';\r\nimport { ApiClient } from '../../api-client.js';\r\nimport { printJson, printError, printSuccess } from '../../output.js';\r\n\r\nexport function registerProviderCommands(program: Command): void {\r\n const provider = program\r\n .command('provider')\r\n .description('Provider operations');\r\n\r\n // --- Agent subcommands ---\r\n const agent = provider\r\n .command('agent')\r\n .description('Manage your agents');\r\n\r\n agent\r\n .command('create')\r\n .description('Register a new agent')\r\n .requiredOption('--name <name>', 'Agent name')\r\n .requiredOption('--slug <slug>', 'Agent slug (URL-friendly)')\r\n .requiredOption('--description <desc>', 'Agent description (10-500 chars)')\r\n .option('--long-description <text>', 'Detailed description')\r\n .option('--pricing-model <model>', 'Pricing model (per_token/per_session/per_minute)', 'per_session')\r\n .option('--price <amount>', 'Price amount', '1.00')\r\n .option('--currency <cur>', 'Currency (CNY/USD)', 'CNY')\r\n .option('--hosting-type <type>', 'Hosting type (self_hosted/platform_hosted)', 'self_hosted')\r\n .option('--approval-mode <mode>', 'Approval mode (manual/auto)', 'manual')\r\n .option('--max-concurrent <n>', 'Max concurrent sessions', '5')\r\n .option('--capabilities <json>', 'Capabilities as JSON array')\r\n .action(async (opts: {\r\n name: string; slug: string; description: string; longDescription?: string;\r\n pricingModel: string; price: string; currency: string; hostingType: string;\r\n approvalMode: string; maxConcurrent: string; capabilities?: string;\r\n }) => {\r\n try {\r\n const data: Record<string, unknown> = {\r\n name: opts.name,\r\n slug: opts.slug,\r\n description: opts.description,\r\n pricingModel: opts.pricingModel,\r\n priceAmount: opts.price,\r\n currency: opts.currency,\r\n hostingType: opts.hostingType,\r\n approvalMode: opts.approvalMode,\r\n maxConcurrentSessions: parseInt(opts.maxConcurrent, 10),\r\n };\r\n if (opts.longDescription) data['longDescription'] = opts.longDescription;\r\n if (opts.capabilities) {\r\n try {\r\n data['capabilities'] = JSON.parse(opts.capabilities);\r\n } catch {\r\n printError('Invalid JSON for --capabilities');\r\n process.exit(1);\r\n }\r\n }\r\n\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.registerAgent(data);\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n agent\r\n .command('list')\r\n .description('List your agents')\r\n .option('-s, --status <status>', 'Filter by status')\r\n .option('-p, --page <number>', 'Page number', '1')\r\n .option('-l, --limit <number>', 'Results per page', '20')\r\n .action(async (opts: { status?: string; page: string; limit: string }) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.getMyAgents({\r\n status: opts.status,\r\n page: parseInt(opts.page, 10),\r\n limit: parseInt(opts.limit, 10),\r\n });\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n agent\r\n .command('publish <agentId>')\r\n .description('Publish an agent (draft -> pending_review)')\r\n .action(async (agentId: string) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.publishAgent(agentId);\r\n printSuccess('Agent published successfully.');\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n agent\r\n .command('activate <agentId>')\r\n .description('Activate an agent (pending_review -> active)')\r\n .action(async (agentId: string) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.activateAgent(agentId);\r\n printSuccess('Agent activated successfully.');\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n agent\r\n .command('status <agentId>')\r\n .description('Set agent online status')\r\n .requiredOption('--status <status>', 'Online status (online/offline/busy)')\r\n .action(async (agentId: string, opts: { status: string }) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.setOnlineStatus(agentId, opts.status);\r\n printSuccess(`Agent status set to ${opts.status}.`);\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n // --- Provider session commands ---\r\n provider\r\n .command('sessions')\r\n .description('List provider sessions')\r\n .option('-s, --status <status>', 'Filter by status')\r\n .option('-p, --page <number>', 'Page number', '1')\r\n .option('-l, --limit <number>', 'Results per page', '20')\r\n .action(async (opts: { status?: string; page: string; limit: string }) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.getSessions({\r\n role: 'provider',\r\n status: opts.status,\r\n page: parseInt(opts.page, 10),\r\n limit: parseInt(opts.limit, 10),\r\n });\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n provider\r\n .command('approve <sessionId>')\r\n .description('Approve a pending session')\r\n .action(async (sessionId: string) => {\r\n try {\r\n const client = new ApiClient(loadConfig());\r\n const result = await client.approveSession(sessionId);\r\n printSuccess('Session approved.');\r\n printJson(result);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport WebSocket from 'ws';\r\nimport { loadConfig } from '../config.js';\r\nimport { ApiClient } from '../api-client.js';\r\nimport { printError, printSuccess } from '../output.js';\r\nimport { isDaemonRunning, spawnDaemon, writePid, getLogFilePath } from '../daemon.js';\r\nimport { StdioBridge } from './stdio-bridge.js';\r\nimport { SessionManager } from './session-manager.js';\r\nimport {\r\n createCorrelationId,\r\n isResponse,\r\n isRequest,\r\n type JsonRpcMessage,\r\n type ResultPayload,\r\n} from './protocol.js';\r\n\r\ninterface ServeOptions {\r\n agentToken: string;\r\n autoApprove: boolean;\r\n pollInterval: string;\r\n daemon: boolean;\r\n}\r\n\r\n/** Pending instruction tracking: correlationId -> sessionId */\r\nconst pendingInstructions = new Map<string, string>();\r\n\r\n/** Known session IDs we've already seen (to avoid duplicate polling notifications) */\r\nconst knownPendingSessions = new Set<string>();\r\nconst activeSessions = new Set<string>();\r\n\r\nexport function registerServeCommand(program: Command): void {\r\n program\r\n .command('serve')\r\n .description('Start serve daemon - bridge WebSocket sessions to stdin/stdout')\r\n .requiredOption('--agent-token <token>', 'Agent token (agt_clawrent_*) for authentication')\r\n .option('--auto-approve', 'Automatically approve incoming sessions', false)\r\n .option('--poll-interval <ms>', 'Polling interval for pending sessions (ms)', '5000')\r\n .option('-d, --daemon', 'Run in background as a daemon process', false)\r\n .action(async (opts: ServeOptions) => {\r\n try {\r\n if (opts.daemon) {\r\n // --- Daemon mode: resolve agentId first, then fork ---\r\n const config = loadConfig();\r\n // Override token for this request\r\n config.token = opts.agentToken;\r\n const client = new ApiClient(config);\r\n\r\n let agentId: string;\r\n try {\r\n const agent = await client.getMyAgent();\r\n agentId = agent['id'] as string;\r\n } catch {\r\n printError('Failed to resolve agent from token. Is the token valid?');\r\n process.exit(1);\r\n }\r\n\r\n const { running, pid: existingPid } = isDaemonRunning(agentId);\r\n if (running) {\r\n printError(`Daemon already running for agent ${agentId} (PID: ${existingPid}). Use 'clawrent stop --agent-id ${agentId}' first.`);\r\n process.exit(1);\r\n }\r\n\r\n // Rebuild args without --daemon / -d\r\n const args: string[] = ['serve', '--agent-token', opts.agentToken];\r\n if (opts.autoApprove) args.push('--auto-approve');\r\n if (opts.pollInterval !== '5000') args.push('--poll-interval', opts.pollInterval);\r\n\r\n const pid = spawnDaemon(agentId, args);\r\n writePid(agentId, pid);\r\n printSuccess(`Daemon started for agent ${agentId} (PID: ${pid})\\nLogs: ${getLogFilePath(agentId)}`);\r\n process.exit(0);\r\n }\r\n\r\n await runDaemon(opts);\r\n } catch (err: unknown) {\r\n printError(err instanceof Error ? err.message : String(err));\r\n process.exit(1);\r\n }\r\n });\r\n}\r\n\r\nasync function runDaemon(opts: ServeOptions): Promise<void> {\r\n const config = loadConfig();\r\n // Override token for agentToken auth\r\n config.token = opts.agentToken;\r\n const client = new ApiClient(config);\r\n const bridge = new StdioBridge();\r\n const sessionManager = new SessionManager(config.wsUrl);\r\n const pollInterval = parseInt(opts.pollInterval, 10);\r\n let agentWs: WebSocket | null = null;\r\n let agentHeartbeatTimer: ReturnType<typeof setInterval> | null = null;\r\n\r\n // --- 1. Startup: resolve agent from token ---\r\n let agentId: string;\r\n let agentName: string;\r\n try {\r\n const agent = await client.getMyAgent();\r\n agentId = agent['id'] as string;\r\n agentName = (agent['name'] as string) ?? agentId;\r\n sessionManager.agentId = agentId;\r\n } catch {\r\n printError('Failed to resolve agent from token. Is the token valid?');\r\n process.exit(1);\r\n }\r\n\r\n // --- 2. Notify ready ---\r\n bridge.writeNotification('ready', {\r\n agentId,\r\n agentName,\r\n });\r\n\r\n // --- 3. Wire up session manager events ---\r\n sessionManager.on('session:connected', (sessionId: string) => {\r\n bridge.writeNotification('session.connected', { sessionId });\r\n });\r\n\r\n sessionManager.on('session:message', (sessionId: string, message: Record<string, unknown>) => {\r\n const type = message['type'] as string;\r\n\r\n if (type?.startsWith('instruction.')) {\r\n // Instruction from consumer -> forward as JSON-RPC request (expects response)\r\n const corrId = createCorrelationId();\r\n pendingInstructions.set(corrId, sessionId);\r\n\r\n bridge.writeRequest('instruction', corrId, {\r\n sessionId,\r\n messageId: (message['id'] as string) ?? corrId,\r\n type,\r\n payload: (message['payload'] as Record<string, unknown>) ?? {},\r\n sender: message['sender'],\r\n });\r\n } else if (type?.startsWith('dialogue.')) {\r\n // Dialogue from consumer -> forward as notification\r\n const payload = (message['payload'] as Record<string, unknown>) ?? {};\r\n bridge.writeNotification('dialogue', {\r\n sessionId,\r\n content: payload['content'] ?? '',\r\n dialogueType: payload['dialogueType'] ?? 'message',\r\n });\r\n } else if (type?.startsWith('result.')) {\r\n // Result from consumer -> forward as notification\r\n bridge.writeNotification('result', {\r\n sessionId,\r\n type,\r\n payload: (message['payload'] as Record<string, unknown>) ?? {},\r\n });\r\n } else if (type === 'system.session_ended' || type === 'system.peer_disconnected') {\r\n activeSessions.delete(sessionId);\r\n bridge.writeNotification('session.ended', {\r\n sessionId,\r\n reason: type,\r\n });\r\n } else if (type === 'system.peer_connected') {\r\n bridge.writeNotification('session.peer_connected', { sessionId });\r\n } else if (type !== 'system.heartbeat_ack') {\r\n // Forward unknown messages as-is\r\n bridge.writeNotification('message', { sessionId, ...message });\r\n }\r\n });\r\n\r\n sessionManager.on('session:disconnected', (sessionId: string, reason: string) => {\r\n activeSessions.delete(sessionId);\r\n bridge.writeNotification('session.disconnected', { sessionId, reason });\r\n });\r\n\r\n sessionManager.on('session:reconnecting', (sessionId: string, delay: number) => {\r\n bridge.writeNotification('session.reconnecting', { sessionId, delay });\r\n });\r\n\r\n sessionManager.on('session:error', (sessionId: string, err: Error) => {\r\n bridge.writeNotification('session.error', { sessionId, message: err.message });\r\n });\r\n\r\n // --- 4. Handle stdin messages from agent ---\r\n bridge.start((msg: JsonRpcMessage) => {\r\n if (isResponse(msg)) {\r\n // Agent is responding to an instruction we forwarded\r\n const sessionId = pendingInstructions.get(msg.id);\r\n if (sessionId && msg.result) {\r\n pendingInstructions.delete(msg.id);\r\n const result = msg.result as unknown as ResultPayload;\r\n sessionManager.send(sessionId, {\r\n type: result.type ?? 'result.success',\r\n payload: result.payload ?? result,\r\n });\r\n }\r\n } else if (isRequest(msg)) {\r\n // Agent is proactively sending something\r\n if (msg.method === 'send') {\r\n const params = msg.params as Record<string, unknown> | undefined;\r\n if (params?.['sessionId']) {\r\n const sent = sessionManager.send(params['sessionId'] as string, {\r\n type: params['type'] ?? 'dialogue.message',\r\n payload: (params['payload'] as Record<string, unknown>) ?? { content: '' },\r\n });\r\n bridge.writeResponse(msg.id, { success: sent });\r\n }\r\n } else if (msg.method === 'approve') {\r\n const params = msg.params as Record<string, unknown> | undefined;\r\n const sid = params?.['sessionId'] as string | undefined;\r\n if (sid) {\r\n approveAndConnect(client, sessionManager, bridge, sid).catch(() => {\r\n bridge.writeResponse(msg.id, { success: false, error: 'Failed to approve' });\r\n }).then(() => {\r\n bridge.writeResponse(msg.id, { success: true });\r\n });\r\n }\r\n }\r\n }\r\n // Notifications from agent are ignored for now\r\n });\r\n\r\n // --- 5. Agent control channel (/ws/agent) + fallback poll loop ---\r\n let pollTimer: ReturnType<typeof setInterval> | null = null;\r\n\r\n function connectAgentWs(token: string) {\r\n const wsBase = config.wsUrl ?? config.apiUrl.replace(/^http/, 'ws');\r\n const url = `${wsBase}/ws/agent?token=${token}`;\r\n agentWs = new WebSocket(url);\r\n\r\n agentWs.on('open', () => {\r\n bridge.writeNotification('agent.connected', { agentId });\r\n\r\n // Start heartbeat on agent channel\r\n agentHeartbeatTimer = setInterval(() => {\r\n if (agentWs && agentWs.readyState === WebSocket.OPEN) {\r\n agentWs.send(JSON.stringify({ type: 'system.heartbeat', payload: {} }));\r\n }\r\n }, 25_000);\r\n\r\n // Stop polling when WS is connected\r\n if (pollTimer) {\r\n clearInterval(pollTimer);\r\n pollTimer = null;\r\n }\r\n });\r\n\r\n agentWs.on('message', (raw) => {\r\n try {\r\n const message = JSON.parse(raw.toString());\r\n const type = message.type as string;\r\n\r\n if (type === 'session.new' || type === 'session.approved') {\r\n const payload = message.payload as Record<string, unknown>;\r\n const sid = payload['sessionId'] as string;\r\n const sessionToken = payload['sessionToken'] as string;\r\n\r\n if (knownPendingSessions.has(sid) || activeSessions.has(sid)) return;\r\n knownPendingSessions.add(sid);\r\n\r\n if (opts.autoApprove && type === 'session.new') {\r\n approveAndConnect(client, sessionManager, bridge, sid);\r\n } else if (type === 'session.approved' && sessionToken) {\r\n // Already approved, connect directly\r\n activeSessions.add(sid);\r\n bridge.writeNotification('session.new', {\r\n sessionId: sid,\r\n sessionToken,\r\n taskDescription: (payload['taskDescription'] as string) ?? '',\r\n consumerUserId: (payload['consumerUserId'] as string) ?? '',\r\n });\r\n sessionManager.connect(sid, sessionToken);\r\n } else {\r\n bridge.writeNotification('session.pending', {\r\n sessionId: sid,\r\n taskDescription: (payload['taskDescription'] as string) ?? '',\r\n consumerUserId: (payload['consumerUserId'] as string) ?? '',\r\n });\r\n }\r\n }\r\n // Ignore heartbeat_ack and other system messages\r\n } catch {\r\n // Ignore parse errors on agent channel\r\n }\r\n });\r\n\r\n agentWs.on('close', (code, reason) => {\r\n if (agentHeartbeatTimer) {\r\n clearInterval(agentHeartbeatTimer);\r\n agentHeartbeatTimer = null;\r\n }\r\n bridge.writeNotification('agent.disconnected', {\r\n agentId,\r\n code,\r\n reason: reason.toString(),\r\n });\r\n\r\n // Fall back to polling\r\n if (!pollTimer) {\r\n startPollLoop();\r\n }\r\n\r\n // Reconnect after 5s unless deliberately closed\r\n if (code !== 1000 && code !== 4009) {\r\n setTimeout(() => connectAgentWs(token), 5000);\r\n }\r\n });\r\n\r\n agentWs.on('error', () => {\r\n // Error will trigger close event\r\n });\r\n }\r\n\r\n function startPollLoop() {\r\n pollTimer = setInterval(async () => {\r\n try {\r\n const sessions = (await client.getSessions({\r\n role: 'provider',\r\n status: 'pending_approval',\r\n })) as { data: Array<Record<string, unknown>> };\r\n\r\n for (const session of sessions.data ?? []) {\r\n const sid = session['id'] as string;\r\n if (knownPendingSessions.has(sid) || activeSessions.has(sid)) continue;\r\n knownPendingSessions.add(sid);\r\n\r\n if (opts.autoApprove) {\r\n await approveAndConnect(client, sessionManager, bridge, sid);\r\n } else {\r\n bridge.writeNotification('session.pending', {\r\n sessionId: sid,\r\n taskDescription: session['taskDescription'] ?? '',\r\n consumerUserId: session['consumerUserId'] ?? '',\r\n });\r\n }\r\n }\r\n } catch {\r\n // Silently retry on next poll\r\n }\r\n }, pollInterval);\r\n }\r\n\r\n // Connect via /ws/agent with the token\r\n connectAgentWs(opts.agentToken);\r\n\r\n // --- 6. Graceful shutdown ---\r\n const shutdown = async () => {\r\n if (pollTimer) clearInterval(pollTimer);\r\n if (agentHeartbeatTimer) clearInterval(agentHeartbeatTimer);\r\n bridge.stop();\r\n\r\n // Close agent WS (this triggers server-side offline update)\r\n if (agentWs) {\r\n try { agentWs.close(1000, 'Shutting down'); } catch { /* ignore */ }\r\n agentWs = null;\r\n }\r\n\r\n sessionManager.disconnectAll();\r\n bridge.writeNotification('shutdown', { reason: 'signal' });\r\n\r\n // Give a moment for messages to flush\r\n setTimeout(() => process.exit(0), 500);\r\n };\r\n\r\n process.on('SIGINT', () => { void shutdown(); });\r\n process.on('SIGTERM', () => { void shutdown(); });\r\n}\r\n\r\nasync function approveAndConnect(\r\n client: ApiClient,\r\n sessionManager: SessionManager,\r\n bridge: StdioBridge,\r\n sessionId: string,\r\n): Promise<void> {\r\n try {\r\n const approved = (await client.approveSession(sessionId)) as Record<string, unknown>;\r\n const sessionToken = approved['sessionToken'] as string;\r\n const taskDescription = approved['taskDescription'] as string;\r\n\r\n activeSessions.add(sessionId);\r\n\r\n bridge.writeNotification('session.new', {\r\n sessionId,\r\n sessionToken,\r\n taskDescription: taskDescription ?? '',\r\n consumerUserId: (approved['consumerUserId'] as string) ?? '',\r\n });\r\n\r\n sessionManager.connect(sessionId, sessionToken);\r\n } catch (err: unknown) {\r\n bridge.writeNotification('session.approve_failed', {\r\n sessionId,\r\n error: err instanceof Error ? err.message : String(err),\r\n });\r\n }\r\n}\r\n","import { readFileSync, writeFileSync, unlinkSync, openSync, closeSync, mkdirSync, existsSync, readdirSync } from 'node:fs';\r\nimport { join, basename } from 'node:path';\r\nimport { spawn } from 'node:child_process';\r\nimport { getConfigDir } from './config.js';\r\n\r\nexport function getPidFilePath(agentId: string): string {\r\n return join(getConfigDir(), `serve-${agentId}.pid`);\r\n}\r\n\r\nexport function getLogFilePath(agentId: string): string {\r\n return join(getConfigDir(), `serve-${agentId}.log`);\r\n}\r\n\r\nexport function readPid(agentId: string): number | null {\r\n try {\r\n const content = readFileSync(getPidFilePath(agentId), 'utf-8').trim();\r\n const pid = parseInt(content, 10);\r\n return Number.isFinite(pid) && pid > 0 ? pid : null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport function writePid(agentId: string, pid: number): void {\r\n const dir = getConfigDir();\r\n if (!existsSync(dir)) {\r\n mkdirSync(dir, { recursive: true });\r\n }\r\n writeFileSync(getPidFilePath(agentId), String(pid), 'utf-8');\r\n}\r\n\r\nexport function removePidFile(agentId: string): void {\r\n try {\r\n unlinkSync(getPidFilePath(agentId));\r\n } catch {\r\n // Ignore ENOENT\r\n }\r\n}\r\n\r\nexport function isProcessAlive(pid: number): boolean {\r\n try {\r\n process.kill(pid, 0);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport function isDaemonRunning(agentId: string): { running: boolean; pid: number | null } {\r\n const pid = readPid(agentId);\r\n if (pid === null) return { running: false, pid: null };\r\n\r\n if (isProcessAlive(pid)) {\r\n return { running: true, pid };\r\n }\r\n\r\n // Stale PID file — process is dead, clean up\r\n removePidFile(agentId);\r\n return { running: false, pid: null };\r\n}\r\n\r\n/** List all running daemons by scanning PID files in config dir */\r\nexport function listRunningDaemons(): Array<{ agentId: string; pid: number }> {\r\n const dir = getConfigDir();\r\n if (!existsSync(dir)) return [];\r\n\r\n const results: Array<{ agentId: string; pid: number }> = [];\r\n\r\n for (const file of readdirSync(dir)) {\r\n const match = /^serve-(.+)\\.pid$/.exec(basename(file));\r\n if (!match) continue;\r\n\r\n const agentId = match[1]!;\r\n const { running, pid } = isDaemonRunning(agentId);\r\n if (running && pid !== null) {\r\n results.push({ agentId, pid });\r\n }\r\n }\r\n\r\n return results;\r\n}\r\n\r\nexport function spawnDaemon(agentId: string, args: string[]): number {\r\n const logFile = getLogFilePath(agentId);\r\n const dir = getConfigDir();\r\n if (!existsSync(dir)) {\r\n mkdirSync(dir, { recursive: true });\r\n }\r\n\r\n const logFd = openSync(logFile, 'a');\r\n\r\n const child = spawn(process.argv[0]!, [process.argv[1]!, ...args], {\r\n detached: true,\r\n stdio: ['ignore', logFd, logFd],\r\n windowsHide: true,\r\n });\r\n\r\n child.unref();\r\n closeSync(logFd);\r\n\r\n if (!child.pid) {\r\n throw new Error('Failed to start daemon process');\r\n }\r\n\r\n return child.pid;\r\n}\r\n","import { createInterface } from 'node:readline';\r\nimport type { JsonRpcMessage, JsonRpcResponse, JsonRpcRequest, JsonRpcNotification } from './protocol.js';\r\n\r\nexport type StdinMessageHandler = (msg: JsonRpcMessage) => void;\r\n\r\n/**\r\n * StdioBridge handles JSON Lines communication over stdin/stdout.\r\n * Each line is a JSON-RPC 2.0 message.\r\n */\r\nexport class StdioBridge {\r\n private handler: StdinMessageHandler | null = null;\r\n private rl: ReturnType<typeof createInterface> | null = null;\r\n\r\n /** Start reading from stdin */\r\n start(handler: StdinMessageHandler): void {\r\n this.handler = handler;\r\n this.rl = createInterface({ input: process.stdin, crlfDelay: Infinity });\r\n\r\n this.rl.on('line', (line) => {\r\n const trimmed = line.trim();\r\n if (!trimmed) return;\r\n\r\n try {\r\n const msg = JSON.parse(trimmed) as JsonRpcMessage;\r\n if (msg.jsonrpc !== '2.0') {\r\n this.writeError('Invalid JSON-RPC: missing jsonrpc field');\r\n return;\r\n }\r\n this.handler?.(msg);\r\n } catch {\r\n this.writeError(`Failed to parse JSON: ${trimmed.slice(0, 100)}`);\r\n }\r\n });\r\n\r\n this.rl.on('close', () => {\r\n // stdin closed — process will shut down\r\n });\r\n }\r\n\r\n /** Stop reading */\r\n stop(): void {\r\n this.rl?.close();\r\n this.rl = null;\r\n }\r\n\r\n /** Write a JSON-RPC message to stdout */\r\n write(msg: JsonRpcMessage): void {\r\n process.stdout.write(JSON.stringify(msg) + '\\n');\r\n }\r\n\r\n /** Write a notification */\r\n writeNotification(method: string, params: Record<string, unknown>): void {\r\n const msg: JsonRpcNotification = { jsonrpc: '2.0', method, params };\r\n this.write(msg);\r\n }\r\n\r\n /** Write a request (expects response) */\r\n writeRequest(method: string, id: string, params: Record<string, unknown>): void {\r\n const msg: JsonRpcRequest = { jsonrpc: '2.0', method, id, params };\r\n this.write(msg);\r\n }\r\n\r\n /** Write a response */\r\n writeResponse(id: string, result: Record<string, unknown>): void {\r\n const msg: JsonRpcResponse = { jsonrpc: '2.0', id, result };\r\n this.write(msg);\r\n }\r\n\r\n /** Write an error notification to stdout */\r\n private writeError(message: string): void {\r\n this.writeNotification('error', { message });\r\n }\r\n}\r\n","import { EventEmitter } from 'node:events';\r\nimport WebSocket from 'ws';\r\n\r\nexport interface SessionConnection {\r\n sessionId: string;\r\n sessionToken: string;\r\n ws: WebSocket;\r\n heartbeatTimer: ReturnType<typeof setInterval> | null;\r\n reconnectAttempts: number;\r\n}\r\n\r\n/**\r\n * SessionManager manages multiple concurrent WebSocket connections,\r\n * one per active session.\r\n */\r\nexport class SessionManager extends EventEmitter {\r\n private sessions = new Map<string, SessionConnection>();\r\n private wsUrl: string;\r\n private heartbeatInterval: number;\r\n private maxReconnectDelay: number;\r\n public agentId?: string;\r\n\r\n constructor(wsUrl: string, heartbeatInterval = 25_000, maxReconnectDelay = 30_000) {\r\n super();\r\n this.wsUrl = wsUrl;\r\n this.heartbeatInterval = heartbeatInterval;\r\n this.maxReconnectDelay = maxReconnectDelay;\r\n }\r\n\r\n /** Connect to a session via WebSocket as provider */\r\n connect(sessionId: string, sessionToken: string): void {\r\n if (this.sessions.has(sessionId)) {\r\n return; // Already connected\r\n }\r\n\r\n const url = `${this.wsUrl}/ws/session?sessionId=${sessionId}&token=${sessionToken}&role=provider`;\r\n const ws = new WebSocket(url);\r\n\r\n const conn: SessionConnection = {\r\n sessionId,\r\n sessionToken,\r\n ws,\r\n heartbeatTimer: null,\r\n reconnectAttempts: 0,\r\n };\r\n\r\n this.sessions.set(sessionId, conn);\r\n\r\n ws.on('open', () => {\r\n conn.reconnectAttempts = 0;\r\n conn.heartbeatTimer = setInterval(() => {\r\n if (ws.readyState === WebSocket.OPEN) {\r\n ws.send(JSON.stringify({ type: 'system.heartbeat', payload: {} }));\r\n }\r\n }, this.heartbeatInterval);\r\n\r\n this.emit('session:connected', sessionId);\r\n });\r\n\r\n ws.on('message', (raw) => {\r\n try {\r\n const message = JSON.parse(raw.toString()) as Record<string, unknown>;\r\n // Skip heartbeat acks\r\n if (message['type'] === 'system.heartbeat_ack') return;\r\n\r\n this.emit('session:message', sessionId, message);\r\n } catch {\r\n // Ignore parse errors\r\n }\r\n });\r\n\r\n ws.on('close', (code, reason) => {\r\n this.clearHeartbeat(conn);\r\n\r\n if (code !== 1000) {\r\n // Abnormal close — try reconnect\r\n const delay = Math.min(\r\n 1000 * Math.pow(2, conn.reconnectAttempts),\r\n this.maxReconnectDelay,\r\n );\r\n conn.reconnectAttempts++;\r\n\r\n this.emit('session:reconnecting', sessionId, delay);\r\n\r\n setTimeout(() => {\r\n this.sessions.delete(sessionId);\r\n this.connect(sessionId, sessionToken);\r\n }, delay);\r\n } else {\r\n this.sessions.delete(sessionId);\r\n this.emit('session:disconnected', sessionId, reason.toString());\r\n }\r\n });\r\n\r\n ws.on('error', (err) => {\r\n this.emit('session:error', sessionId, err);\r\n });\r\n }\r\n\r\n /** Send a message to a specific session, auto-wrapping with protocol envelope */\r\n send(sessionId: string, message: Record<string, unknown>): boolean {\r\n const conn = this.sessions.get(sessionId);\r\n if (!conn || conn.ws.readyState !== WebSocket.OPEN) {\r\n return false;\r\n }\r\n // Ensure full ClawRentMessage envelope\r\n const envelope = {\r\n id: message['id'] ?? `msg_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\r\n sessionId: message['sessionId'] ?? sessionId,\r\n timestamp: message['timestamp'] ?? Date.now(),\r\n sender: message['sender'] ?? { role: 'provider', agentId: this.agentId ?? 'unknown' },\r\n type: message['type'] ?? 'result.success',\r\n payload: message['payload'] ?? {},\r\n };\r\n conn.ws.send(JSON.stringify(envelope));\r\n return true;\r\n }\r\n\r\n /** Disconnect a specific session */\r\n disconnect(sessionId: string): void {\r\n const conn = this.sessions.get(sessionId);\r\n if (!conn) return;\r\n\r\n this.clearHeartbeat(conn);\r\n if (conn.ws.readyState === WebSocket.OPEN || conn.ws.readyState === WebSocket.CONNECTING) {\r\n conn.ws.close(1000, 'Provider disconnecting');\r\n }\r\n this.sessions.delete(sessionId);\r\n }\r\n\r\n /** Disconnect all sessions */\r\n disconnectAll(): void {\r\n for (const sessionId of this.sessions.keys()) {\r\n this.disconnect(sessionId);\r\n }\r\n }\r\n\r\n /** Get active session count */\r\n get activeCount(): number {\r\n return this.sessions.size;\r\n }\r\n\r\n /** Check if a session is connected */\r\n isConnected(sessionId: string): boolean {\r\n const conn = this.sessions.get(sessionId);\r\n return conn?.ws.readyState === WebSocket.OPEN;\r\n }\r\n\r\n private clearHeartbeat(conn: SessionConnection): void {\r\n if (conn.heartbeatTimer) {\r\n clearInterval(conn.heartbeatTimer);\r\n conn.heartbeatTimer = null;\r\n }\r\n }\r\n}\r\n","// JSON-RPC 2.0 protocol types for clawrent serve stdin/stdout communication\r\n\r\n/** Base JSON-RPC message */\r\nexport interface JsonRpcBase {\r\n jsonrpc: '2.0';\r\n}\r\n\r\n/** JSON-RPC request (has method + id) */\r\nexport interface JsonRpcRequest extends JsonRpcBase {\r\n method: string;\r\n id: string;\r\n params?: Record<string, unknown>;\r\n}\r\n\r\n/** JSON-RPC notification (has method, no id) */\r\nexport interface JsonRpcNotification extends JsonRpcBase {\r\n method: string;\r\n params?: Record<string, unknown>;\r\n}\r\n\r\n/** JSON-RPC response (has id + result or error) */\r\nexport interface JsonRpcResponse extends JsonRpcBase {\r\n id: string;\r\n result?: Record<string, unknown>;\r\n error?: { code: number; message: string; data?: unknown };\r\n}\r\n\r\nexport type JsonRpcMessage = JsonRpcRequest | JsonRpcNotification | JsonRpcResponse;\r\n\r\n// --- Daemon -> Agent (stdout) methods ---\r\n\r\nexport interface ReadyParams {\r\n agentId: string;\r\n agentName: string;\r\n}\r\n\r\nexport interface SessionNewParams {\r\n sessionId: string;\r\n sessionToken: string;\r\n taskDescription: string;\r\n consumerUserId: string;\r\n}\r\n\r\nexport interface SessionPendingParams {\r\n sessionId: string;\r\n taskDescription: string;\r\n consumerUserId: string;\r\n}\r\n\r\nexport interface InstructionParams {\r\n sessionId: string;\r\n messageId: string;\r\n type: string;\r\n payload: Record<string, unknown>;\r\n sender?: Record<string, unknown>;\r\n}\r\n\r\nexport interface DialogueParams {\r\n sessionId: string;\r\n content: string;\r\n dialogueType: string;\r\n}\r\n\r\nexport interface SessionEndedParams {\r\n sessionId: string;\r\n reason: string;\r\n}\r\n\r\n// --- Agent -> Daemon (stdin) methods ---\r\n\r\nexport interface ResultPayload {\r\n sessionId: string;\r\n type: string;\r\n payload: Record<string, unknown>;\r\n}\r\n\r\nexport interface SendParams {\r\n sessionId: string;\r\n type: string;\r\n payload: Record<string, unknown>;\r\n}\r\n\r\nexport interface ApproveParams {\r\n sessionId: string;\r\n}\r\n\r\n// --- Helpers ---\r\n\r\nlet correlationCounter = 0;\r\n\r\nexport function createCorrelationId(): string {\r\n return `corr_${Date.now().toString(36)}_${(correlationCounter++).toString(36)}`;\r\n}\r\n\r\nexport function createNotification(method: string, params: Record<string, unknown>): JsonRpcNotification {\r\n return { jsonrpc: '2.0', method, params };\r\n}\r\n\r\nexport function createRequest(method: string, params: Record<string, unknown>, id?: string): JsonRpcRequest {\r\n return { jsonrpc: '2.0', method, id: id ?? createCorrelationId(), params };\r\n}\r\n\r\nexport function isResponse(msg: JsonRpcMessage): msg is JsonRpcResponse {\r\n return 'id' in msg && ('result' in msg || 'error' in msg) && !('method' in msg);\r\n}\r\n\r\nexport function isRequest(msg: JsonRpcMessage): msg is JsonRpcRequest {\r\n return 'method' in msg && 'id' in msg;\r\n}\r\n\r\nexport function isNotification(msg: JsonRpcMessage): msg is JsonRpcNotification {\r\n return 'method' in msg && !('id' in msg);\r\n}\r\n","import { Command } from 'commander';\r\nimport { isDaemonRunning, removePidFile, isProcessAlive, listRunningDaemons } from '../daemon.js';\r\nimport { printSuccess, printError } from '../output.js';\r\n\r\nasync function stopOne(agentId: string): Promise<boolean> {\r\n const { running, pid } = isDaemonRunning(agentId);\r\n\r\n if (!running || pid === null) {\r\n return false;\r\n }\r\n\r\n try {\r\n process.kill(pid, 'SIGTERM');\r\n } catch (err: unknown) {\r\n const code = (err as NodeJS.ErrnoException).code;\r\n if (code === 'ESRCH') {\r\n removePidFile(agentId);\r\n return true;\r\n }\r\n if (code === 'EPERM') {\r\n printError(`Permission denied. Cannot stop daemon for agent ${agentId} (PID: ${pid}).`);\r\n return false;\r\n }\r\n throw err;\r\n }\r\n\r\n const maxWait = 3000;\r\n const interval = 200;\r\n let waited = 0;\r\n\r\n while (waited < maxWait) {\r\n await new Promise((r) => setTimeout(r, interval));\r\n waited += interval;\r\n if (!isProcessAlive(pid)) {\r\n removePidFile(agentId);\r\n printSuccess(`Daemon stopped for agent ${agentId} (PID: ${pid}).`);\r\n return true;\r\n }\r\n }\r\n\r\n try {\r\n process.kill(pid, 'SIGKILL');\r\n } catch {\r\n // May have exited between check and kill\r\n }\r\n\r\n removePidFile(agentId);\r\n printSuccess(`Daemon stopped for agent ${agentId} (PID: ${pid}).`);\r\n return true;\r\n}\r\n\r\nexport function registerStopCommand(program: Command): void {\r\n program\r\n .command('stop')\r\n .description('Stop background serve daemon(s)')\r\n .option('--agent-id <id>', 'Stop daemon for a specific agent')\r\n .option('--all', 'Stop all running daemons', false)\r\n .action(async (opts: { agentId?: string; all: boolean }) => {\r\n if (opts.agentId) {\r\n const stopped = await stopOne(opts.agentId);\r\n if (!stopped) {\r\n printSuccess(`No daemon running for agent ${opts.agentId}.`);\r\n }\r\n return;\r\n }\r\n\r\n // Default: stop all\r\n const daemons = listRunningDaemons();\r\n if (daemons.length === 0) {\r\n printSuccess('No daemons are running.');\r\n return;\r\n }\r\n\r\n for (const d of daemons) {\r\n await stopOne(d.agentId);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { isDaemonRunning, getLogFilePath, listRunningDaemons } from '../daemon.js';\r\nimport { printJson } from '../output.js';\r\n\r\nexport function registerStatusCommand(program: Command): void {\r\n program\r\n .command('status')\r\n .description('Check running serve daemon(s)')\r\n .option('--agent-id <id>', 'Check daemon for a specific agent')\r\n .action((opts: { agentId?: string }) => {\r\n if (opts.agentId) {\r\n const { running, pid } = isDaemonRunning(opts.agentId);\r\n if (running && pid !== null) {\r\n printJson({ status: 'running', agentId: opts.agentId, pid, logFile: getLogFilePath(opts.agentId) });\r\n } else {\r\n printJson({ status: 'stopped', agentId: opts.agentId });\r\n }\r\n return;\r\n }\r\n\r\n // List all running daemons\r\n const daemons = listRunningDaemons();\r\n if (daemons.length === 0) {\r\n printJson({ daemons: [] });\r\n } else {\r\n printJson({\r\n daemons: daemons.map((d) => ({\r\n agentId: d.agentId,\r\n pid: d.pid,\r\n logFile: getLogFilePath(d.agentId),\r\n })),\r\n });\r\n }\r\n });\r\n}\r\n"],"mappings":"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","names":["readFileSync","join","program","program","program","program","program","program","program","program","program","program","program","WebSocket","readFileSync","writeFileSync","unlinkSync","mkdirSync","existsSync","join","join","readFileSync","existsSync","mkdirSync","writeFileSync","unlinkSync","createInterface","WebSocket","program","WebSocket","program","program","readFileSync","join"]}
|
package/dist/lib.d.ts
CHANGED
|
@@ -65,6 +65,8 @@ declare class ApiClient {
|
|
|
65
65
|
limit?: number;
|
|
66
66
|
status?: string;
|
|
67
67
|
}): Promise<unknown>;
|
|
68
|
+
/** Resolve the current agent from agentToken. Requires agt_clawrent_ token auth. */
|
|
69
|
+
getMyAgent(): Promise<Record<string, unknown>>;
|
|
68
70
|
publishAgent(agentId: string): Promise<unknown>;
|
|
69
71
|
activateAgent(agentId: string): Promise<unknown>;
|
|
70
72
|
setOnlineStatus(agentId: string, onlineStatus: string): Promise<unknown>;
|
package/dist/lib.js
CHANGED
|
@@ -81,6 +81,10 @@ var ApiClient = class {
|
|
|
81
81
|
const qs = params.toString();
|
|
82
82
|
return this.request("GET", `/api/agents/my${qs ? `?${qs}` : ""}`);
|
|
83
83
|
}
|
|
84
|
+
/** Resolve the current agent from agentToken. Requires agt_clawrent_ token auth. */
|
|
85
|
+
async getMyAgent() {
|
|
86
|
+
return this.request("GET", "/api/agents/me/agent");
|
|
87
|
+
}
|
|
84
88
|
async publishAgent(agentId) {
|
|
85
89
|
return this.request("POST", `/api/agents/${encodeURIComponent(agentId)}/publish`);
|
|
86
90
|
}
|
package/dist/lib.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api-client.ts","../src/config.ts","../src/serve/session-manager.ts"],"sourcesContent":["import type { ClawRentConfig } from './config.js';\r\n\r\nexport class ApiClient {\r\n private config: ClawRentConfig;\r\n\r\n constructor(config: ClawRentConfig) {\r\n this.config = config;\r\n }\r\n\r\n get apiUrl(): string {\r\n return this.config.apiUrl;\r\n }\r\n\r\n get wsUrl(): string {\r\n return this.config.wsUrl;\r\n }\r\n\r\n get userId(): string | undefined {\r\n return this.config.userId;\r\n }\r\n\r\n // --- Auth (no auth needed) ---\r\n\r\n async login(email: string, password: string): Promise<{ user: { id: string; email: string; name: string; role: string }; token: string }> {\r\n return this.request('POST', '/api/auth/login', { email, password }, false);\r\n }\r\n\r\n async getMe(): Promise<Record<string, unknown>> {\r\n return this.request('GET', '/api/auth/me');\r\n }\r\n\r\n // --- Marketplace ---\r\n\r\n async browse(query?: { search?: string; category?: string; page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.search) params.set('search', query.search);\r\n if (query?.category) params.set('category', query.category);\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/marketplace/browse${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async getAgent(slug: string): Promise<unknown> {\r\n return this.request('GET', `/api/marketplace/agents/${encodeURIComponent(slug)}`);\r\n }\r\n\r\n // --- Sessions ---\r\n\r\n async rent(options: { agentId: string; taskDescription: string; grantedPermissions?: Record<string, unknown> }): Promise<unknown> {\r\n return this.request('POST', '/api/sessions', {\r\n agentId: options.agentId,\r\n taskDescription: options.taskDescription,\r\n grantedPermissions: options.grantedPermissions ?? {},\r\n });\r\n }\r\n\r\n async getSessions(query?: { role?: string; status?: string; page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.role) params.set('role', query.role);\r\n if (query?.status) params.set('status', query.status);\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/sessions${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async getSession(sessionId: string): Promise<Record<string, unknown>> {\r\n return this.request('GET', `/api/sessions/${encodeURIComponent(sessionId)}`);\r\n }\r\n\r\n async getSessionMessages(sessionId: string): Promise<unknown> {\r\n return this.request('GET', `/api/sessions/${encodeURIComponent(sessionId)}/messages`);\r\n }\r\n\r\n async endSession(sessionId: string): Promise<unknown> {\r\n return this.request('POST', `/api/sessions/${encodeURIComponent(sessionId)}/end`);\r\n }\r\n\r\n async approveSession(sessionId: string): Promise<unknown> {\r\n return this.request('POST', `/api/sessions/${encodeURIComponent(sessionId)}/approve`);\r\n }\r\n\r\n // --- Billing ---\r\n\r\n async getBalance(): Promise<{ balance: string }> {\r\n return this.request('GET', '/api/billing/wallet');\r\n }\r\n\r\n async topUp(amount: string): Promise<{ balance: string }> {\r\n return this.request('POST', '/api/billing/wallet/topup', { amount });\r\n }\r\n\r\n // --- Provider: Agents ---\r\n\r\n async registerAgent(data: Record<string, unknown>): Promise<unknown> {\r\n return this.request('POST', '/api/agents', data);\r\n }\r\n\r\n async getMyAgents(query?: { page?: number; limit?: number; status?: string }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n if (query?.status) params.set('status', query.status);\r\n const qs = params.toString();\r\n return this.request('GET', `/api/agents/my${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async publishAgent(agentId: string): Promise<unknown> {\r\n return this.request('POST', `/api/agents/${encodeURIComponent(agentId)}/publish`);\r\n }\r\n\r\n async activateAgent(agentId: string): Promise<unknown> {\r\n return this.request('POST', `/api/agents/${encodeURIComponent(agentId)}/activate`);\r\n }\r\n\r\n async setOnlineStatus(agentId: string, onlineStatus: string): Promise<unknown> {\r\n return this.request('PATCH', `/api/agents/${encodeURIComponent(agentId)}/status`, { onlineStatus });\r\n }\r\n\r\n async generateAgentToken(agentId: string): Promise<{ agentId: string; token: string; createdAt: string; warning: string }> {\r\n return this.request('POST', `/api/agents/${encodeURIComponent(agentId)}/token`);\r\n }\r\n\r\n async revokeAgentToken(agentId: string): Promise<{ message: string }> {\r\n return this.request('DELETE', `/api/agents/${encodeURIComponent(agentId)}/token`);\r\n }\r\n\r\n // --- Orders ---\r\n\r\n async createOrder(data: {\r\n items: Array<{ providerAgentId: string; consumerAgentId?: string; taskDescription: string; grantedPermissions?: Record<string, unknown> }>;\r\n note?: string;\r\n fromCart?: boolean;\r\n }): Promise<unknown> {\r\n return this.request('POST', '/api/orders', data);\r\n }\r\n\r\n async getOrders(query?: { status?: string; page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.status) params.set('status', query.status);\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/orders${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async getOrder(orderId: string): Promise<unknown> {\r\n return this.request('GET', `/api/orders/${encodeURIComponent(orderId)}`);\r\n }\r\n\r\n async cancelOrder(orderId: string): Promise<unknown> {\r\n return this.request('POST', `/api/orders/${encodeURIComponent(orderId)}/cancel`);\r\n }\r\n\r\n // --- Cart ---\r\n\r\n async getCart(): Promise<unknown> {\r\n return this.request('GET', '/api/cart');\r\n }\r\n\r\n async addToCart(data: { providerAgentId: string; taskDescription: string }): Promise<unknown> {\r\n return this.request('POST', '/api/cart', data);\r\n }\r\n\r\n async updateCartItem(itemId: string, data: { taskDescription: string }): Promise<unknown> {\r\n return this.request('PATCH', `/api/cart/${encodeURIComponent(itemId)}`, data);\r\n }\r\n\r\n async removeFromCart(itemId: string): Promise<unknown> {\r\n return this.request('DELETE', `/api/cart/${encodeURIComponent(itemId)}`);\r\n }\r\n\r\n async clearCart(): Promise<unknown> {\r\n return this.request('DELETE', '/api/cart');\r\n }\r\n\r\n // --- Favorites ---\r\n\r\n async listFavorites(query?: { page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/favorites${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async addFavorite(agentId: string): Promise<unknown> {\r\n return this.request('POST', `/api/favorites/${encodeURIComponent(agentId)}`);\r\n }\r\n\r\n async removeFavorite(agentId: string): Promise<unknown> {\r\n return this.request('DELETE', `/api/favorites/${encodeURIComponent(agentId)}`);\r\n }\r\n\r\n // --- Health ---\r\n\r\n async health(): Promise<unknown> {\r\n return this.request('GET', '/api/health', undefined, false);\r\n }\r\n\r\n // --- Private ---\r\n\r\n private async request<T = any>(method: string, path: string, body?: unknown, requireAuth: boolean = true): Promise<T> {\r\n const url = `${this.config.apiUrl}${path}`;\r\n const headers: Record<string, string> = {};\r\n\r\n if (body !== undefined) {\r\n headers['Content-Type'] = 'application/json';\r\n }\r\n\r\n if (requireAuth) {\r\n if (this.config.token) {\r\n headers['Authorization'] = `Bearer ${this.config.token}`;\r\n } else if (this.config.apiKey) {\r\n headers['x-api-key'] = this.config.apiKey;\r\n } else {\r\n throw new Error('Not authenticated. Run `clawrent auth login` first.');\r\n }\r\n }\r\n\r\n const response = await fetch(url, {\r\n method,\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n\r\n if (!response.ok) {\r\n const errBody = await response.json().catch(() => ({ message: response.statusText })) as Record<string, unknown>;\r\n throw new Error(`API error ${response.status}: ${errBody['message'] ?? JSON.stringify(errBody)}`);\r\n }\r\n\r\n return response.json() as Promise<T>;\r\n }\r\n}\r\n","import { readFileSync, writeFileSync, mkdirSync, unlinkSync, existsSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport { homedir } from 'node:os';\r\n\r\nexport interface ClawRentConfig {\r\n apiUrl: string;\r\n wsUrl: string;\r\n token?: string;\r\n apiKey?: string;\r\n userId?: string;\r\n email?: string;\r\n name?: string;\r\n}\r\n\r\nconst DEFAULT_CONFIG: ClawRentConfig = {\r\n apiUrl: 'https://clawrent.cloud',\r\n wsUrl: 'wss://clawrent.cloud',\r\n};\r\n\r\nexport function getConfigDir(): string {\r\n return join(homedir(), '.clawrent');\r\n}\r\n\r\nfunction getConfigFilePath(): string {\r\n return join(getConfigDir(), 'config.json');\r\n}\r\n\r\nexport function getConfigPath(): string {\r\n return getConfigFilePath();\r\n}\r\n\r\nexport function loadConfig(): ClawRentConfig {\r\n let fileConfig: Partial<ClawRentConfig> = {};\r\n\r\n const configPath = getConfigFilePath();\r\n if (existsSync(configPath)) {\r\n try {\r\n const raw = readFileSync(configPath, 'utf-8');\r\n fileConfig = JSON.parse(raw) as Partial<ClawRentConfig>;\r\n } catch {\r\n // Ignore corrupt config file\r\n }\r\n }\r\n\r\n // Migration: remove stale localhost URLs saved by older CLI versions.\r\n // These override the new production defaults and break remote connections.\r\n if (fileConfig.apiUrl?.includes('localhost') || fileConfig.wsUrl?.includes('localhost')) {\r\n delete fileConfig.apiUrl;\r\n delete fileConfig.wsUrl;\r\n // Persist the cleanup so it only runs once\r\n try {\r\n const cleaned = { ...fileConfig };\r\n writeFileSync(configPath, JSON.stringify(cleaned, null, 2), 'utf-8');\r\n } catch {\r\n // Non-fatal\r\n }\r\n }\r\n\r\n // Merge: defaults < file < env vars\r\n const config: ClawRentConfig = {\r\n ...DEFAULT_CONFIG,\r\n ...fileConfig,\r\n };\r\n\r\n // Env vars always override\r\n const envApiUrl = process.env['CLAWRENT_API_URL'];\r\n const envWsUrl = process.env['CLAWRENT_WS_URL'];\r\n const envToken = process.env['CLAWRENT_TOKEN'];\r\n const envApiKey = process.env['CLAWRENT_API_KEY'];\r\n const envUserId = process.env['CLAWRENT_USER_ID'];\r\n\r\n if (envApiUrl) config.apiUrl = envApiUrl;\r\n if (envWsUrl) config.wsUrl = envWsUrl;\r\n if (envToken) config.token = envToken;\r\n if (envApiKey) config.apiKey = envApiKey;\r\n if (envUserId) config.userId = envUserId;\r\n\r\n return config;\r\n}\r\n\r\nexport function saveConfig(partial: Partial<ClawRentConfig>): void {\r\n const configDir = getConfigDir();\r\n if (!existsSync(configDir)) {\r\n mkdirSync(configDir, { recursive: true });\r\n }\r\n\r\n let existing: Partial<ClawRentConfig> = {};\r\n const configPath = getConfigFilePath();\r\n if (existsSync(configPath)) {\r\n try {\r\n existing = JSON.parse(readFileSync(configPath, 'utf-8')) as Partial<ClawRentConfig>;\r\n } catch {\r\n // Overwrite corrupt file\r\n }\r\n }\r\n\r\n const merged = { ...existing, ...partial };\r\n writeFileSync(configPath, JSON.stringify(merged, null, 2), 'utf-8');\r\n}\r\n\r\nexport function clearConfig(): void {\r\n const configPath = getConfigFilePath();\r\n if (existsSync(configPath)) {\r\n unlinkSync(configPath);\r\n }\r\n}\r\n","import { EventEmitter } from 'node:events';\r\nimport WebSocket from 'ws';\r\n\r\nexport interface SessionConnection {\r\n sessionId: string;\r\n sessionToken: string;\r\n ws: WebSocket;\r\n heartbeatTimer: ReturnType<typeof setInterval> | null;\r\n reconnectAttempts: number;\r\n}\r\n\r\n/**\r\n * SessionManager manages multiple concurrent WebSocket connections,\r\n * one per active session.\r\n */\r\nexport class SessionManager extends EventEmitter {\r\n private sessions = new Map<string, SessionConnection>();\r\n private wsUrl: string;\r\n private heartbeatInterval: number;\r\n private maxReconnectDelay: number;\r\n public agentId?: string;\r\n\r\n constructor(wsUrl: string, heartbeatInterval = 25_000, maxReconnectDelay = 30_000) {\r\n super();\r\n this.wsUrl = wsUrl;\r\n this.heartbeatInterval = heartbeatInterval;\r\n this.maxReconnectDelay = maxReconnectDelay;\r\n }\r\n\r\n /** Connect to a session via WebSocket as provider */\r\n connect(sessionId: string, sessionToken: string): void {\r\n if (this.sessions.has(sessionId)) {\r\n return; // Already connected\r\n }\r\n\r\n const url = `${this.wsUrl}/ws/session?sessionId=${sessionId}&token=${sessionToken}&role=provider`;\r\n const ws = new WebSocket(url);\r\n\r\n const conn: SessionConnection = {\r\n sessionId,\r\n sessionToken,\r\n ws,\r\n heartbeatTimer: null,\r\n reconnectAttempts: 0,\r\n };\r\n\r\n this.sessions.set(sessionId, conn);\r\n\r\n ws.on('open', () => {\r\n conn.reconnectAttempts = 0;\r\n conn.heartbeatTimer = setInterval(() => {\r\n if (ws.readyState === WebSocket.OPEN) {\r\n ws.send(JSON.stringify({ type: 'system.heartbeat', payload: {} }));\r\n }\r\n }, this.heartbeatInterval);\r\n\r\n this.emit('session:connected', sessionId);\r\n });\r\n\r\n ws.on('message', (raw) => {\r\n try {\r\n const message = JSON.parse(raw.toString()) as Record<string, unknown>;\r\n // Skip heartbeat acks\r\n if (message['type'] === 'system.heartbeat_ack') return;\r\n\r\n this.emit('session:message', sessionId, message);\r\n } catch {\r\n // Ignore parse errors\r\n }\r\n });\r\n\r\n ws.on('close', (code, reason) => {\r\n this.clearHeartbeat(conn);\r\n\r\n if (code !== 1000) {\r\n // Abnormal close — try reconnect\r\n const delay = Math.min(\r\n 1000 * Math.pow(2, conn.reconnectAttempts),\r\n this.maxReconnectDelay,\r\n );\r\n conn.reconnectAttempts++;\r\n\r\n this.emit('session:reconnecting', sessionId, delay);\r\n\r\n setTimeout(() => {\r\n this.sessions.delete(sessionId);\r\n this.connect(sessionId, sessionToken);\r\n }, delay);\r\n } else {\r\n this.sessions.delete(sessionId);\r\n this.emit('session:disconnected', sessionId, reason.toString());\r\n }\r\n });\r\n\r\n ws.on('error', (err) => {\r\n this.emit('session:error', sessionId, err);\r\n });\r\n }\r\n\r\n /** Send a message to a specific session, auto-wrapping with protocol envelope */\r\n send(sessionId: string, message: Record<string, unknown>): boolean {\r\n const conn = this.sessions.get(sessionId);\r\n if (!conn || conn.ws.readyState !== WebSocket.OPEN) {\r\n return false;\r\n }\r\n // Ensure full ClawRentMessage envelope\r\n const envelope = {\r\n id: message['id'] ?? `msg_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\r\n sessionId: message['sessionId'] ?? sessionId,\r\n timestamp: message['timestamp'] ?? Date.now(),\r\n sender: message['sender'] ?? { role: 'provider', agentId: this.agentId ?? 'unknown' },\r\n type: message['type'] ?? 'result.success',\r\n payload: message['payload'] ?? {},\r\n };\r\n conn.ws.send(JSON.stringify(envelope));\r\n return true;\r\n }\r\n\r\n /** Disconnect a specific session */\r\n disconnect(sessionId: string): void {\r\n const conn = this.sessions.get(sessionId);\r\n if (!conn) return;\r\n\r\n this.clearHeartbeat(conn);\r\n if (conn.ws.readyState === WebSocket.OPEN || conn.ws.readyState === WebSocket.CONNECTING) {\r\n conn.ws.close(1000, 'Provider disconnecting');\r\n }\r\n this.sessions.delete(sessionId);\r\n }\r\n\r\n /** Disconnect all sessions */\r\n disconnectAll(): void {\r\n for (const sessionId of this.sessions.keys()) {\r\n this.disconnect(sessionId);\r\n }\r\n }\r\n\r\n /** Get active session count */\r\n get activeCount(): number {\r\n return this.sessions.size;\r\n }\r\n\r\n /** Check if a session is connected */\r\n isConnected(sessionId: string): boolean {\r\n const conn = this.sessions.get(sessionId);\r\n return conn?.ws.readyState === WebSocket.OPEN;\r\n }\r\n\r\n private clearHeartbeat(conn: SessionConnection): void {\r\n if (conn.heartbeatTimer) {\r\n clearInterval(conn.heartbeatTimer);\r\n conn.heartbeatTimer = null;\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/api-client.ts","../src/config.ts","../src/serve/session-manager.ts"],"sourcesContent":["import type { ClawRentConfig } from './config.js';\r\n\r\nexport class ApiClient {\r\n private config: ClawRentConfig;\r\n\r\n constructor(config: ClawRentConfig) {\r\n this.config = config;\r\n }\r\n\r\n get apiUrl(): string {\r\n return this.config.apiUrl;\r\n }\r\n\r\n get wsUrl(): string {\r\n return this.config.wsUrl;\r\n }\r\n\r\n get userId(): string | undefined {\r\n return this.config.userId;\r\n }\r\n\r\n // --- Auth (no auth needed) ---\r\n\r\n async login(email: string, password: string): Promise<{ user: { id: string; email: string; name: string; role: string }; token: string }> {\r\n return this.request('POST', '/api/auth/login', { email, password }, false);\r\n }\r\n\r\n async getMe(): Promise<Record<string, unknown>> {\r\n return this.request('GET', '/api/auth/me');\r\n }\r\n\r\n // --- Marketplace ---\r\n\r\n async browse(query?: { search?: string; category?: string; page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.search) params.set('search', query.search);\r\n if (query?.category) params.set('category', query.category);\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/marketplace/browse${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async getAgent(slug: string): Promise<unknown> {\r\n return this.request('GET', `/api/marketplace/agents/${encodeURIComponent(slug)}`);\r\n }\r\n\r\n // --- Sessions ---\r\n\r\n async rent(options: { agentId: string; taskDescription: string; grantedPermissions?: Record<string, unknown> }): Promise<unknown> {\r\n return this.request('POST', '/api/sessions', {\r\n agentId: options.agentId,\r\n taskDescription: options.taskDescription,\r\n grantedPermissions: options.grantedPermissions ?? {},\r\n });\r\n }\r\n\r\n async getSessions(query?: { role?: string; status?: string; page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.role) params.set('role', query.role);\r\n if (query?.status) params.set('status', query.status);\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/sessions${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async getSession(sessionId: string): Promise<Record<string, unknown>> {\r\n return this.request('GET', `/api/sessions/${encodeURIComponent(sessionId)}`);\r\n }\r\n\r\n async getSessionMessages(sessionId: string): Promise<unknown> {\r\n return this.request('GET', `/api/sessions/${encodeURIComponent(sessionId)}/messages`);\r\n }\r\n\r\n async endSession(sessionId: string): Promise<unknown> {\r\n return this.request('POST', `/api/sessions/${encodeURIComponent(sessionId)}/end`);\r\n }\r\n\r\n async approveSession(sessionId: string): Promise<unknown> {\r\n return this.request('POST', `/api/sessions/${encodeURIComponent(sessionId)}/approve`);\r\n }\r\n\r\n // --- Billing ---\r\n\r\n async getBalance(): Promise<{ balance: string }> {\r\n return this.request('GET', '/api/billing/wallet');\r\n }\r\n\r\n async topUp(amount: string): Promise<{ balance: string }> {\r\n return this.request('POST', '/api/billing/wallet/topup', { amount });\r\n }\r\n\r\n // --- Provider: Agents ---\r\n\r\n async registerAgent(data: Record<string, unknown>): Promise<unknown> {\r\n return this.request('POST', '/api/agents', data);\r\n }\r\n\r\n async getMyAgents(query?: { page?: number; limit?: number; status?: string }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n if (query?.status) params.set('status', query.status);\r\n const qs = params.toString();\r\n return this.request('GET', `/api/agents/my${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n /** Resolve the current agent from agentToken. Requires agt_clawrent_ token auth. */\r\n async getMyAgent(): Promise<Record<string, unknown>> {\r\n return this.request('GET', '/api/agents/me/agent');\r\n }\r\n\r\n async publishAgent(agentId: string): Promise<unknown> {\r\n return this.request('POST', `/api/agents/${encodeURIComponent(agentId)}/publish`);\r\n }\r\n\r\n async activateAgent(agentId: string): Promise<unknown> {\r\n return this.request('POST', `/api/agents/${encodeURIComponent(agentId)}/activate`);\r\n }\r\n\r\n async setOnlineStatus(agentId: string, onlineStatus: string): Promise<unknown> {\r\n return this.request('PATCH', `/api/agents/${encodeURIComponent(agentId)}/status`, { onlineStatus });\r\n }\r\n\r\n async generateAgentToken(agentId: string): Promise<{ agentId: string; token: string; createdAt: string; warning: string }> {\r\n return this.request('POST', `/api/agents/${encodeURIComponent(agentId)}/token`);\r\n }\r\n\r\n async revokeAgentToken(agentId: string): Promise<{ message: string }> {\r\n return this.request('DELETE', `/api/agents/${encodeURIComponent(agentId)}/token`);\r\n }\r\n\r\n // --- Orders ---\r\n\r\n async createOrder(data: {\r\n items: Array<{ providerAgentId: string; consumerAgentId?: string; taskDescription: string; grantedPermissions?: Record<string, unknown> }>;\r\n note?: string;\r\n fromCart?: boolean;\r\n }): Promise<unknown> {\r\n return this.request('POST', '/api/orders', data);\r\n }\r\n\r\n async getOrders(query?: { status?: string; page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.status) params.set('status', query.status);\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/orders${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async getOrder(orderId: string): Promise<unknown> {\r\n return this.request('GET', `/api/orders/${encodeURIComponent(orderId)}`);\r\n }\r\n\r\n async cancelOrder(orderId: string): Promise<unknown> {\r\n return this.request('POST', `/api/orders/${encodeURIComponent(orderId)}/cancel`);\r\n }\r\n\r\n // --- Cart ---\r\n\r\n async getCart(): Promise<unknown> {\r\n return this.request('GET', '/api/cart');\r\n }\r\n\r\n async addToCart(data: { providerAgentId: string; taskDescription: string }): Promise<unknown> {\r\n return this.request('POST', '/api/cart', data);\r\n }\r\n\r\n async updateCartItem(itemId: string, data: { taskDescription: string }): Promise<unknown> {\r\n return this.request('PATCH', `/api/cart/${encodeURIComponent(itemId)}`, data);\r\n }\r\n\r\n async removeFromCart(itemId: string): Promise<unknown> {\r\n return this.request('DELETE', `/api/cart/${encodeURIComponent(itemId)}`);\r\n }\r\n\r\n async clearCart(): Promise<unknown> {\r\n return this.request('DELETE', '/api/cart');\r\n }\r\n\r\n // --- Favorites ---\r\n\r\n async listFavorites(query?: { page?: number; limit?: number }): Promise<unknown> {\r\n const params = new URLSearchParams();\r\n if (query?.page) params.set('page', String(query.page));\r\n if (query?.limit) params.set('limit', String(query.limit));\r\n const qs = params.toString();\r\n return this.request('GET', `/api/favorites${qs ? `?${qs}` : ''}`);\r\n }\r\n\r\n async addFavorite(agentId: string): Promise<unknown> {\r\n return this.request('POST', `/api/favorites/${encodeURIComponent(agentId)}`);\r\n }\r\n\r\n async removeFavorite(agentId: string): Promise<unknown> {\r\n return this.request('DELETE', `/api/favorites/${encodeURIComponent(agentId)}`);\r\n }\r\n\r\n // --- Health ---\r\n\r\n async health(): Promise<unknown> {\r\n return this.request('GET', '/api/health', undefined, false);\r\n }\r\n\r\n // --- Private ---\r\n\r\n private async request<T = any>(method: string, path: string, body?: unknown, requireAuth: boolean = true): Promise<T> {\r\n const url = `${this.config.apiUrl}${path}`;\r\n const headers: Record<string, string> = {};\r\n\r\n if (body !== undefined) {\r\n headers['Content-Type'] = 'application/json';\r\n }\r\n\r\n if (requireAuth) {\r\n if (this.config.token) {\r\n headers['Authorization'] = `Bearer ${this.config.token}`;\r\n } else if (this.config.apiKey) {\r\n headers['x-api-key'] = this.config.apiKey;\r\n } else {\r\n throw new Error('Not authenticated. Run `clawrent auth login` first.');\r\n }\r\n }\r\n\r\n const response = await fetch(url, {\r\n method,\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n\r\n if (!response.ok) {\r\n const errBody = await response.json().catch(() => ({ message: response.statusText })) as Record<string, unknown>;\r\n throw new Error(`API error ${response.status}: ${errBody['message'] ?? JSON.stringify(errBody)}`);\r\n }\r\n\r\n return response.json() as Promise<T>;\r\n }\r\n}\r\n","import { readFileSync, writeFileSync, mkdirSync, unlinkSync, existsSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport { homedir } from 'node:os';\r\n\r\nexport interface ClawRentConfig {\r\n apiUrl: string;\r\n wsUrl: string;\r\n token?: string;\r\n apiKey?: string;\r\n userId?: string;\r\n email?: string;\r\n name?: string;\r\n}\r\n\r\nconst DEFAULT_CONFIG: ClawRentConfig = {\r\n apiUrl: 'https://clawrent.cloud',\r\n wsUrl: 'wss://clawrent.cloud',\r\n};\r\n\r\nexport function getConfigDir(): string {\r\n return join(homedir(), '.clawrent');\r\n}\r\n\r\nfunction getConfigFilePath(): string {\r\n return join(getConfigDir(), 'config.json');\r\n}\r\n\r\nexport function getConfigPath(): string {\r\n return getConfigFilePath();\r\n}\r\n\r\nexport function loadConfig(): ClawRentConfig {\r\n let fileConfig: Partial<ClawRentConfig> = {};\r\n\r\n const configPath = getConfigFilePath();\r\n if (existsSync(configPath)) {\r\n try {\r\n const raw = readFileSync(configPath, 'utf-8');\r\n fileConfig = JSON.parse(raw) as Partial<ClawRentConfig>;\r\n } catch {\r\n // Ignore corrupt config file\r\n }\r\n }\r\n\r\n // Migration: remove stale localhost URLs saved by older CLI versions.\r\n // These override the new production defaults and break remote connections.\r\n if (fileConfig.apiUrl?.includes('localhost') || fileConfig.wsUrl?.includes('localhost')) {\r\n delete fileConfig.apiUrl;\r\n delete fileConfig.wsUrl;\r\n // Persist the cleanup so it only runs once\r\n try {\r\n const cleaned = { ...fileConfig };\r\n writeFileSync(configPath, JSON.stringify(cleaned, null, 2), 'utf-8');\r\n } catch {\r\n // Non-fatal\r\n }\r\n }\r\n\r\n // Merge: defaults < file < env vars\r\n const config: ClawRentConfig = {\r\n ...DEFAULT_CONFIG,\r\n ...fileConfig,\r\n };\r\n\r\n // Env vars always override\r\n const envApiUrl = process.env['CLAWRENT_API_URL'];\r\n const envWsUrl = process.env['CLAWRENT_WS_URL'];\r\n const envToken = process.env['CLAWRENT_TOKEN'];\r\n const envApiKey = process.env['CLAWRENT_API_KEY'];\r\n const envUserId = process.env['CLAWRENT_USER_ID'];\r\n\r\n if (envApiUrl) config.apiUrl = envApiUrl;\r\n if (envWsUrl) config.wsUrl = envWsUrl;\r\n if (envToken) config.token = envToken;\r\n if (envApiKey) config.apiKey = envApiKey;\r\n if (envUserId) config.userId = envUserId;\r\n\r\n return config;\r\n}\r\n\r\nexport function saveConfig(partial: Partial<ClawRentConfig>): void {\r\n const configDir = getConfigDir();\r\n if (!existsSync(configDir)) {\r\n mkdirSync(configDir, { recursive: true });\r\n }\r\n\r\n let existing: Partial<ClawRentConfig> = {};\r\n const configPath = getConfigFilePath();\r\n if (existsSync(configPath)) {\r\n try {\r\n existing = JSON.parse(readFileSync(configPath, 'utf-8')) as Partial<ClawRentConfig>;\r\n } catch {\r\n // Overwrite corrupt file\r\n }\r\n }\r\n\r\n const merged = { ...existing, ...partial };\r\n writeFileSync(configPath, JSON.stringify(merged, null, 2), 'utf-8');\r\n}\r\n\r\nexport function clearConfig(): void {\r\n const configPath = getConfigFilePath();\r\n if (existsSync(configPath)) {\r\n unlinkSync(configPath);\r\n }\r\n}\r\n","import { EventEmitter } from 'node:events';\r\nimport WebSocket from 'ws';\r\n\r\nexport interface SessionConnection {\r\n sessionId: string;\r\n sessionToken: string;\r\n ws: WebSocket;\r\n heartbeatTimer: ReturnType<typeof setInterval> | null;\r\n reconnectAttempts: number;\r\n}\r\n\r\n/**\r\n * SessionManager manages multiple concurrent WebSocket connections,\r\n * one per active session.\r\n */\r\nexport class SessionManager extends EventEmitter {\r\n private sessions = new Map<string, SessionConnection>();\r\n private wsUrl: string;\r\n private heartbeatInterval: number;\r\n private maxReconnectDelay: number;\r\n public agentId?: string;\r\n\r\n constructor(wsUrl: string, heartbeatInterval = 25_000, maxReconnectDelay = 30_000) {\r\n super();\r\n this.wsUrl = wsUrl;\r\n this.heartbeatInterval = heartbeatInterval;\r\n this.maxReconnectDelay = maxReconnectDelay;\r\n }\r\n\r\n /** Connect to a session via WebSocket as provider */\r\n connect(sessionId: string, sessionToken: string): void {\r\n if (this.sessions.has(sessionId)) {\r\n return; // Already connected\r\n }\r\n\r\n const url = `${this.wsUrl}/ws/session?sessionId=${sessionId}&token=${sessionToken}&role=provider`;\r\n const ws = new WebSocket(url);\r\n\r\n const conn: SessionConnection = {\r\n sessionId,\r\n sessionToken,\r\n ws,\r\n heartbeatTimer: null,\r\n reconnectAttempts: 0,\r\n };\r\n\r\n this.sessions.set(sessionId, conn);\r\n\r\n ws.on('open', () => {\r\n conn.reconnectAttempts = 0;\r\n conn.heartbeatTimer = setInterval(() => {\r\n if (ws.readyState === WebSocket.OPEN) {\r\n ws.send(JSON.stringify({ type: 'system.heartbeat', payload: {} }));\r\n }\r\n }, this.heartbeatInterval);\r\n\r\n this.emit('session:connected', sessionId);\r\n });\r\n\r\n ws.on('message', (raw) => {\r\n try {\r\n const message = JSON.parse(raw.toString()) as Record<string, unknown>;\r\n // Skip heartbeat acks\r\n if (message['type'] === 'system.heartbeat_ack') return;\r\n\r\n this.emit('session:message', sessionId, message);\r\n } catch {\r\n // Ignore parse errors\r\n }\r\n });\r\n\r\n ws.on('close', (code, reason) => {\r\n this.clearHeartbeat(conn);\r\n\r\n if (code !== 1000) {\r\n // Abnormal close — try reconnect\r\n const delay = Math.min(\r\n 1000 * Math.pow(2, conn.reconnectAttempts),\r\n this.maxReconnectDelay,\r\n );\r\n conn.reconnectAttempts++;\r\n\r\n this.emit('session:reconnecting', sessionId, delay);\r\n\r\n setTimeout(() => {\r\n this.sessions.delete(sessionId);\r\n this.connect(sessionId, sessionToken);\r\n }, delay);\r\n } else {\r\n this.sessions.delete(sessionId);\r\n this.emit('session:disconnected', sessionId, reason.toString());\r\n }\r\n });\r\n\r\n ws.on('error', (err) => {\r\n this.emit('session:error', sessionId, err);\r\n });\r\n }\r\n\r\n /** Send a message to a specific session, auto-wrapping with protocol envelope */\r\n send(sessionId: string, message: Record<string, unknown>): boolean {\r\n const conn = this.sessions.get(sessionId);\r\n if (!conn || conn.ws.readyState !== WebSocket.OPEN) {\r\n return false;\r\n }\r\n // Ensure full ClawRentMessage envelope\r\n const envelope = {\r\n id: message['id'] ?? `msg_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\r\n sessionId: message['sessionId'] ?? sessionId,\r\n timestamp: message['timestamp'] ?? Date.now(),\r\n sender: message['sender'] ?? { role: 'provider', agentId: this.agentId ?? 'unknown' },\r\n type: message['type'] ?? 'result.success',\r\n payload: message['payload'] ?? {},\r\n };\r\n conn.ws.send(JSON.stringify(envelope));\r\n return true;\r\n }\r\n\r\n /** Disconnect a specific session */\r\n disconnect(sessionId: string): void {\r\n const conn = this.sessions.get(sessionId);\r\n if (!conn) return;\r\n\r\n this.clearHeartbeat(conn);\r\n if (conn.ws.readyState === WebSocket.OPEN || conn.ws.readyState === WebSocket.CONNECTING) {\r\n conn.ws.close(1000, 'Provider disconnecting');\r\n }\r\n this.sessions.delete(sessionId);\r\n }\r\n\r\n /** Disconnect all sessions */\r\n disconnectAll(): void {\r\n for (const sessionId of this.sessions.keys()) {\r\n this.disconnect(sessionId);\r\n }\r\n }\r\n\r\n /** Get active session count */\r\n get activeCount(): number {\r\n return this.sessions.size;\r\n }\r\n\r\n /** Check if a session is connected */\r\n isConnected(sessionId: string): boolean {\r\n const conn = this.sessions.get(sessionId);\r\n return conn?.ws.readyState === WebSocket.OPEN;\r\n }\r\n\r\n private clearHeartbeat(conn: SessionConnection): void {\r\n if (conn.heartbeatTimer) {\r\n clearInterval(conn.heartbeatTimer);\r\n conn.heartbeatTimer = null;\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clawrent/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/lib.js",
|
|
6
6
|
"types": "./dist/lib.d.ts",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"commander": "^13.0.0",
|
|
24
24
|
"ws": "^8.18.0",
|
|
25
|
-
"@clawrent/
|
|
26
|
-
"@clawrent/
|
|
25
|
+
"@clawrent/shared-types": "0.1.0",
|
|
26
|
+
"@clawrent/protocol": "0.1.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^22.0.0",
|