clawrk 0.0.1 → 0.0.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.
Files changed (2) hide show
  1. package/dist/index.js +216 -12
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -3,12 +3,87 @@
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
5
 
6
+ // src/auth.ts
7
+ import fs from "fs";
8
+ import { mkdir, writeFile } from "fs/promises";
9
+
10
+ // src/constants.ts
11
+ import os from "os";
12
+ import path from "path";
13
+ var USER_DATA_DIR = path.join(os.homedir(), ".clawrk");
14
+ var CLI_CREDENTIALS_PATH = path.join(USER_DATA_DIR, "credentials.json");
15
+ var CLI_LOGIN_PATH = "/cli-login";
16
+ var CLI_LOGIN_EXCHANGE_PATH = "/api/cli-login/consume";
17
+ var CLI_WHOAMI_PATH = "/api/whoami";
18
+ var DEV_BASE_URL = "http://localhost:3000";
19
+ var PROD_BASE_URL = "https://clawrk.sh";
20
+ function getBaseUrl() {
21
+ if (process.env.CLAWRK_API_URL) {
22
+ return process.env.CLAWRK_API_URL.trim();
23
+ }
24
+ if (process.env.__CLAWRK_DEV === "1") {
25
+ return DEV_BASE_URL;
26
+ }
27
+ return process.env.API_URL || PROD_BASE_URL;
28
+ }
29
+ function getCliLoginUrl() {
30
+ return `${getBaseUrl()}${CLI_LOGIN_PATH}`;
31
+ }
32
+
33
+ // src/auth.ts
34
+ function getEnvApiKey() {
35
+ const value = process.env.CLAWRK_API_KEY;
36
+ return value && value.trim() ? value.trim() : void 0;
37
+ }
38
+ function loadStoredApiKey() {
39
+ try {
40
+ if (!fs.existsSync(CLI_CREDENTIALS_PATH)) return void 0;
41
+ const raw = fs.readFileSync(CLI_CREDENTIALS_PATH, "utf8");
42
+ const parsed = JSON.parse(raw);
43
+ if (parsed && typeof parsed.apiKey === "string" && parsed.apiKey.trim()) {
44
+ return parsed.apiKey.trim();
45
+ }
46
+ return void 0;
47
+ } catch {
48
+ return void 0;
49
+ }
50
+ }
51
+ async function saveApiKey(apiKey) {
52
+ await mkdir(USER_DATA_DIR, { recursive: true });
53
+ await writeFile(
54
+ CLI_CREDENTIALS_PATH,
55
+ JSON.stringify({ apiKey, createdAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
56
+ { mode: 384 }
57
+ );
58
+ }
59
+ function clearStoredApiKey() {
60
+ try {
61
+ if (fs.existsSync(CLI_CREDENTIALS_PATH)) {
62
+ fs.unlinkSync(CLI_CREDENTIALS_PATH);
63
+ }
64
+ } catch {
65
+ }
66
+ }
67
+ function getEffectiveApiKey() {
68
+ return getEnvApiKey() ?? loadStoredApiKey();
69
+ }
70
+ function isLoggedIn() {
71
+ return Boolean(getEffectiveApiKey());
72
+ }
73
+
6
74
  // src/api.ts
7
- var API_URL = process.env.API_URL || "http://localhost:3000";
8
- async function api(path, opts) {
9
- const res = await fetch(`${API_URL}${path}`, {
75
+ async function api(path2, opts) {
76
+ const baseUrl = getBaseUrl();
77
+ const apiKey = getEffectiveApiKey();
78
+ const headers = {
79
+ "Content-Type": "application/json"
80
+ };
81
+ if (apiKey) {
82
+ headers["Authorization"] = `Bearer ${apiKey}`;
83
+ }
84
+ const res = await fetch(`${baseUrl}${path2}`, {
10
85
  method: opts?.method ?? "GET",
11
- headers: { "Content-Type": "application/json" },
86
+ headers,
12
87
  ...opts?.body ? { body: JSON.stringify(opts.body) } : {}
13
88
  });
14
89
  if (!res.ok) {
@@ -20,10 +95,10 @@ async function api(path, opts) {
20
95
 
21
96
  // src/commands/create.ts
22
97
  function registerCreate(program2) {
23
- program2.command("create").description("Create a new job from a prompt").argument("<prompt>", "The job prompt").option("-s, --sender <sender>", "Sender identity", process.env.SENDER_ID || "cli-sender").action(async (prompt, opts) => {
98
+ program2.command("create").description("Create a new job from a prompt").argument("<prompt>", "The job prompt").action(async (prompt2) => {
24
99
  const job = await api("/api/jobs", {
25
100
  method: "POST",
26
- body: { prompt, sender: opts.sender }
101
+ body: { prompt: prompt2 }
27
102
  });
28
103
  console.log("Job created:");
29
104
  console.log(JSON.stringify(job, null, 2));
@@ -32,11 +107,9 @@ function registerCreate(program2) {
32
107
 
33
108
  // src/commands/list.ts
34
109
  function registerList(program2) {
35
- program2.command("list").description("List jobs").option("--status <status>", "Filter by status").option("--sender <sender>", "Filter by sender").option("--receiver <receiver>", "Filter by receiver").action(async (opts) => {
110
+ program2.command("list").description("List jobs").option("--status <status>", "Filter by status").action(async (opts) => {
36
111
  const params = new URLSearchParams();
37
112
  if (opts.status) params.set("status", opts.status);
38
- if (opts.sender) params.set("sender", opts.sender);
39
- if (opts.receiver) params.set("receiver", opts.receiver);
40
113
  const qs = params.toString();
41
114
  const jobs = await api(`/api/jobs${qs ? `?${qs}` : ""}`);
42
115
  if (jobs.length === 0) {
@@ -51,10 +124,9 @@ function registerList(program2) {
51
124
 
52
125
  // src/commands/accept.ts
53
126
  function registerAccept(program2) {
54
- program2.command("accept").description("Accept a job").argument("<id>", "Job ID").option("-r, --receiver <receiver>", "Receiver identity", process.env.RECEIVER_ID || "cli-receiver").action(async (id, opts) => {
127
+ program2.command("accept").description("Accept a job").argument("<id>", "Job ID").action(async (id) => {
55
128
  const job = await api(`/api/jobs/${id}/accept`, {
56
- method: "POST",
57
- body: { receiver: opts.receiver }
129
+ method: "POST"
58
130
  });
59
131
  console.log("Job accepted:");
60
132
  console.log(JSON.stringify(job, null, 2));
@@ -165,9 +237,141 @@ function registerVerify(program2) {
165
237
  });
166
238
  }
167
239
 
240
+ // src/commands/login.ts
241
+ import { createInterface } from "readline";
242
+
243
+ // src/login-flow.ts
244
+ import { exec } from "child_process";
245
+ import { promisify } from "util";
246
+ var execAsync = promisify(exec);
247
+ async function openLoginBrowser(loginUrl) {
248
+ const platform = process.platform;
249
+ const command = platform === "win32" ? `cmd /c start "" "${loginUrl}"` : platform === "darwin" ? `open "${loginUrl}"` : `xdg-open "${loginUrl}"`;
250
+ await execAsync(command);
251
+ }
252
+ async function exchangeLoginCode(baseUrl, code) {
253
+ const exchangeRes = await fetch(`${baseUrl}${CLI_LOGIN_EXCHANGE_PATH}`, {
254
+ method: "POST",
255
+ headers: { "Content-Type": "application/json" },
256
+ body: JSON.stringify({ code })
257
+ });
258
+ const exchangeBody = await exchangeRes.json().catch(() => ({}));
259
+ if (!exchangeRes.ok) {
260
+ throw new Error(
261
+ exchangeBody?.error || `Login failed: ${exchangeRes.status}`
262
+ );
263
+ }
264
+ const apiKey = exchangeBody?.apiKey;
265
+ if (!apiKey) {
266
+ throw new Error("Login failed: missing API key");
267
+ }
268
+ return apiKey;
269
+ }
270
+ async function verifyApiKey(baseUrl, apiKey) {
271
+ const verifyRes = await fetch(`${baseUrl}${CLI_WHOAMI_PATH}`, {
272
+ method: "POST",
273
+ headers: { Authorization: `Bearer ${apiKey}` }
274
+ });
275
+ const verifyBody = await verifyRes.json().catch(() => ({}));
276
+ if (!verifyRes.ok) {
277
+ throw new Error(
278
+ verifyBody?.error || `Verification failed: ${verifyRes.status}`
279
+ );
280
+ }
281
+ return verifyBody;
282
+ }
283
+ async function loginWithCode(baseUrl, code) {
284
+ const apiKey = await exchangeLoginCode(baseUrl, code);
285
+ await saveApiKey(apiKey);
286
+ return apiKey;
287
+ }
288
+
289
+ // src/commands/login.ts
290
+ function prompt(question) {
291
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
292
+ return new Promise((resolve) => {
293
+ rl.question(question, (answer) => {
294
+ rl.close();
295
+ resolve(answer.trim());
296
+ });
297
+ });
298
+ }
299
+ function registerLogin(program2) {
300
+ program2.command("login").description("Authenticate with clawrk").action(async () => {
301
+ if (isLoggedIn()) {
302
+ console.log("Already logged in. Use 'clawrk logout' first to re-authenticate.");
303
+ return;
304
+ }
305
+ const baseUrl = getBaseUrl();
306
+ const loginUrl = getCliLoginUrl();
307
+ console.log(`Opening browser to: ${loginUrl}`);
308
+ console.log("(If it doesn't open, visit the URL manually)\n");
309
+ try {
310
+ await openLoginBrowser(loginUrl);
311
+ } catch {
312
+ }
313
+ const code = await prompt("Paste the login code here: ");
314
+ if (!code) {
315
+ console.error("No code provided.");
316
+ process.exit(1);
317
+ }
318
+ try {
319
+ await loginWithCode(baseUrl, code);
320
+ console.log("Logged in successfully!");
321
+ } catch (err) {
322
+ console.error(
323
+ "Login failed:",
324
+ err instanceof Error ? err.message : err
325
+ );
326
+ process.exit(1);
327
+ }
328
+ });
329
+ }
330
+
331
+ // src/commands/logout.ts
332
+ function registerLogout(program2) {
333
+ program2.command("logout").description("Clear stored credentials").action(() => {
334
+ clearStoredApiKey();
335
+ if (getEnvApiKey()) {
336
+ console.log(
337
+ "Cleared local credentials. CLAWRK_API_KEY is set in your shell; unset it to fully log out."
338
+ );
339
+ } else {
340
+ console.log("Logged out and cleared local credentials.");
341
+ }
342
+ });
343
+ }
344
+
345
+ // src/commands/whoami.ts
346
+ function registerWhoami(program2) {
347
+ program2.command("whoami").description("Show current authenticated user").action(async () => {
348
+ const apiKey = getEffectiveApiKey();
349
+ if (!apiKey) {
350
+ console.log("Not logged in. Use 'clawrk login' to authenticate.");
351
+ return;
352
+ }
353
+ try {
354
+ const baseUrl = getBaseUrl();
355
+ const whoami = await verifyApiKey(baseUrl, apiKey);
356
+ console.log(`Logged in as user ${whoami.user?.id ?? "unknown"}`);
357
+ if (whoami.user?.credits !== void 0) {
358
+ console.log(`Credits: ${whoami.user.credits}`);
359
+ }
360
+ } catch (err) {
361
+ console.error(
362
+ "Login check failed:",
363
+ err instanceof Error ? err.message : err
364
+ );
365
+ }
366
+ });
367
+ }
368
+
168
369
  // src/index.ts
169
370
  var program = new Command();
170
371
  program.name("clawrk").description("Agent Job Exchange CLI").version("0.0.1");
372
+ registerLogin(program);
373
+ registerLogout(program);
374
+ registerWhoami(program);
171
375
  registerCreate(program);
172
376
  registerList(program);
173
377
  registerAccept(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawrk",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "clawrk": "./dist/index.js"
@@ -10,14 +10,14 @@
10
10
  ],
11
11
  "dependencies": {
12
12
  "commander": "^13",
13
- "openai": "^4",
14
- "@clawrk/openai": "0.0.1",
15
- "@clawrk/skills": "0.0.1"
13
+ "openai": "^4"
16
14
  },
17
15
  "devDependencies": {
18
16
  "tsup": "^8",
19
17
  "tsx": "^4",
20
- "typescript": "^5"
18
+ "typescript": "^5",
19
+ "@clawrk/openai": "0.0.1",
20
+ "@clawrk/skills": "0.0.1"
21
21
  },
22
22
  "scripts": {
23
23
  "build": "tsup",