@alook/cli 0.0.2 → 0.0.3

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 +48 -158
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -97,7 +97,7 @@ function isDev() {
97
97
  return !!process.env.ALOOK_SERVER_URL;
98
98
  }
99
99
  function cmdPrefix() {
100
- return isDev() ? "pnpm dev:cli" : "alook";
100
+ return isDev() ? "pnpm dev:cli" : "npx @alook/cli";
101
101
  }
102
102
 
103
103
  // lib/config.ts
@@ -145,137 +145,6 @@ function saveCLIConfigForProfile(profile, profileConfig) {
145
145
  saveCLIConfig(cfg);
146
146
  }
147
147
 
148
- // lib/installer.ts
149
- import { spawnSync } from "child_process";
150
-
151
- // lib/version.ts
152
- import { readFileSync as readFileSync2 } from "fs";
153
- import { join as join2, dirname } from "path";
154
- import { fileURLToPath } from "url";
155
- function getCurrentVersion() {
156
- const __dirname2 = dirname(fileURLToPath(import.meta.url));
157
- const candidates = [
158
- join2(__dirname2, "..", "package.json"),
159
- join2(__dirname2, "..", "..", "package.json")
160
- ];
161
- for (const candidate of candidates) {
162
- try {
163
- const pkg = JSON.parse(readFileSync2(candidate, "utf-8"));
164
- if (typeof pkg.version === "string")
165
- return pkg.version;
166
- } catch {}
167
- }
168
- return "unknown";
169
- }
170
-
171
- // lib/installer.ts
172
- var PACKAGE = "@alook/cli";
173
- var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE}/latest`;
174
- var FETCH_TIMEOUT_MS = 3000;
175
- async function fetchLatestVersion() {
176
- const ctrl = new AbortController;
177
- const timer = setTimeout(() => ctrl.abort(), FETCH_TIMEOUT_MS);
178
- try {
179
- const res = await fetch(REGISTRY_URL, { signal: ctrl.signal });
180
- if (!res.ok)
181
- return null;
182
- const data = await res.json();
183
- return typeof data.version === "string" ? data.version : null;
184
- } catch {
185
- return null;
186
- } finally {
187
- clearTimeout(timer);
188
- }
189
- }
190
- function isNewer(current, latest) {
191
- const parse = (v) => v.split("-")[0].split(".").map((n) => Number.parseInt(n, 10) || 0);
192
- const [cMaj = 0, cMin = 0, cPatch = 0] = parse(current);
193
- const [lMaj = 0, lMin = 0, lPatch = 0] = parse(latest);
194
- if (lMaj !== cMaj)
195
- return lMaj > cMaj;
196
- if (lMin !== cMin)
197
- return lMin > cMin;
198
- return lPatch > cPatch;
199
- }
200
- function isNpx() {
201
- return process.env.npm_command === "exec" || !!process.env.npm_execpath?.includes("npx-cli");
202
- }
203
- function detectPackageManager() {
204
- const ua = process.env.npm_config_user_agent || "";
205
- if (ua.startsWith("pnpm/"))
206
- return "pnpm";
207
- if (ua.startsWith("yarn/"))
208
- return "yarn";
209
- return "npm";
210
- }
211
- function installArgs(pm) {
212
- switch (pm) {
213
- case "pnpm":
214
- return ["pnpm", ["add", "-g", PACKAGE]];
215
- case "yarn":
216
- return ["yarn", ["global", "add", PACKAGE]];
217
- case "npm":
218
- return ["npm", ["install", "-g", `${PACKAGE}@latest`]];
219
- }
220
- }
221
- function installCmdString(pm) {
222
- const [bin, args] = installArgs(pm);
223
- return `${bin} ${args.join(" ")}`;
224
- }
225
- function runInstall(pm) {
226
- const [bin, args] = installArgs(pm);
227
- const result = spawnSync(bin, args, { stdio: "inherit" });
228
- return result.status === 0;
229
- }
230
- async function ensureInstalled(opts = {}, deps = {}) {
231
- const fetchLatest = deps.fetchLatest ?? fetchLatestVersion;
232
- const runInst = deps.runInstall ?? runInstall;
233
- const getCurrent = deps.getCurrent ?? getCurrentVersion;
234
- const isNpxFn = deps.isNpxFn ?? isNpx;
235
- const isDevFn = deps.isDevFn ?? isDev;
236
- const log = deps.log ?? ((m) => console.log(m));
237
- const current = getCurrent();
238
- const pm = detectPackageManager();
239
- if (isDevFn() || opts.skip) {
240
- return { skipped: true, action: "none", current, latest: null, pm };
241
- }
242
- const latest = await fetchLatest();
243
- if (!latest) {
244
- return { skipped: false, action: "none", current, latest: null, pm };
245
- }
246
- const runningViaNpx = isNpxFn();
247
- const needsInstall = runningViaNpx;
248
- const needsUpdate = !runningViaNpx && isNewer(current, latest);
249
- if (!needsInstall && !needsUpdate) {
250
- log(`
251
- ✓ ${PACKAGE} is up to date (${current})`);
252
- return { skipped: false, action: "none", current, latest, pm };
253
- }
254
- const cmdStr = installCmdString(pm);
255
- if (needsInstall) {
256
- log(`
257
- Installing ${PACKAGE} globally (${cmdStr})...`);
258
- } else {
259
- log(`
260
- Updating ${PACKAGE} ${current} → ${latest} (${cmdStr})...`);
261
- }
262
- const ok = runInst(pm);
263
- if (!ok) {
264
- log(`
265
- Could not ${needsInstall ? "install" : "update"} ${PACKAGE} automatically.`);
266
- log(`Install it manually: ${cmdStr}`);
267
- return { skipped: false, action: "failed", current, latest, pm };
268
- }
269
- log(`✓ ${needsInstall ? "Installed" : "Updated"} ${PACKAGE} ${latest}`);
270
- return {
271
- skipped: false,
272
- action: needsInstall ? "installed" : "updated",
273
- current,
274
- latest,
275
- pm
276
- };
277
- }
278
-
279
148
  // commands/register.ts
280
149
  function isCommandAvailable(cmd) {
281
150
  try {
@@ -299,7 +168,7 @@ function detectRuntimes() {
299
168
  return found;
300
169
  }
301
170
  function registerCommand() {
302
- const cmd = new Command("register").description("Register CLI with your Alook account").requiredOption("--token <token>", "API token (starts with al_)").option("--server <url>", "Server URL").option("--profile <name>", "Profile name").option("--no-install", "Skip auto-install/update of @alook/cli").action(async (opts, command) => {
171
+ const cmd = new Command("register").description("Register CLI with your Alook account").requiredOption("--token <token>", "API token (starts with al_)").option("--server <url>", "Server URL").option("--profile <name>", "Profile name").action(async (opts, command) => {
303
172
  const token = opts.token;
304
173
  const profile = opts.profile || command.parent?.opts().profile;
305
174
  const serverUrl = opts.server || command.parent?.opts().server || process.env.ALOOK_SERVER_URL || "https://alook.ai";
@@ -380,7 +249,6 @@ Usage: ${cmdPrefix()} register --token <token>`);
380
249
  Registered as ${me.email}`);
381
250
  console.log(`Workspace: ${ws.name} (${ws.id})`);
382
251
  console.log(`Runtimes: ${activateResp.runtimes.map((r) => r.provider).join(", ")}`);
383
- await ensureInstalled({ skip: opts.install === false });
384
252
  console.log();
385
253
  console.log(`Run '${cmdPrefix()} daemon start --foreground' to start the daemon.`);
386
254
  });
@@ -410,7 +278,7 @@ function statusCommand() {
410
278
  import { Command as Command3 } from "commander";
411
279
  import { spawn as spawn2 } from "child_process";
412
280
  import { openSync, closeSync, mkdirSync as mkdirSync3 } from "fs";
413
- import { dirname as dirname4 } from "path";
281
+ import { dirname as dirname3 } from "path";
414
282
 
415
283
  // ../shared/src/constants.ts
416
284
  var POLL_INTERVAL_MS = Number(process.env.POLL_INTERVAL_MS) || 3000;
@@ -14650,7 +14518,7 @@ function sql(strings, ...params) {
14650
14518
  return new SQL([new StringChunk(str)]);
14651
14519
  }
14652
14520
  sql2.raw = raw;
14653
- function join3(chunks, separator) {
14521
+ function join2(chunks, separator) {
14654
14522
  const result = [];
14655
14523
  for (const [i, chunk] of chunks.entries()) {
14656
14524
  if (i > 0 && separator !== undefined) {
@@ -14660,7 +14528,7 @@ function sql(strings, ...params) {
14660
14528
  }
14661
14529
  return new SQL(result);
14662
14530
  }
14663
- sql2.join = join3;
14531
+ sql2.join = join2;
14664
14532
  function identifier(value) {
14665
14533
  return new Name(value);
14666
14534
  }
@@ -15713,19 +15581,19 @@ class DaemonClient {
15713
15581
 
15714
15582
  // daemon/config.ts
15715
15583
  import { hostname as hostname4 } from "os";
15716
- import { join as join3 } from "path";
15584
+ import { join as join2 } from "path";
15717
15585
  function pidFilePath(profile) {
15718
15586
  const name = profile ? `daemon_${profile}.pid` : "daemon.pid";
15719
- return join3(configDir(), name);
15587
+ return join2(configDir(), name);
15720
15588
  }
15721
15589
  function daemonLogDir() {
15722
- return join3(configDir(), "daemon", "logs");
15590
+ return join2(configDir(), "daemon", "logs");
15723
15591
  }
15724
15592
  function daemonLogFilePath(date5 = new Date) {
15725
15593
  const y = date5.getFullYear();
15726
15594
  const m = String(date5.getMonth() + 1).padStart(2, "0");
15727
15595
  const d = String(date5.getDate()).padStart(2, "0");
15728
- return join3(daemonLogDir(), `${y}-${m}-${d}.log`);
15596
+ return join2(daemonLogDir(), `${y}-${m}-${d}.log`);
15729
15597
  }
15730
15598
  function parseDuration(s) {
15731
15599
  if (!s)
@@ -15765,7 +15633,7 @@ function loadDaemonConfig(profile) {
15765
15633
  if (profile && !daemonId.endsWith(`-${profile}`)) {
15766
15634
  daemonId = `${daemonId}-${profile}`;
15767
15635
  }
15768
- const defaultRoot = join3(configDir(), profile ? `workspaces_${profile}` : "workspaces");
15636
+ const defaultRoot = join2(configDir(), profile ? `workspaces_${profile}` : "workspaces");
15769
15637
  const workspacesRoot = process.env.ALOOK_WORKSPACES_ROOT || defaultRoot;
15770
15638
  return {
15771
15639
  serverURL: normalizeServerBaseURL(process.env.ALOOK_SERVER_URL || "https://alook.ai"),
@@ -15947,8 +15815,8 @@ function createLogger2(level) {
15947
15815
  var log = createLogger2();
15948
15816
 
15949
15817
  // daemon/pidfile.ts
15950
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, unlinkSync, mkdirSync as mkdirSync2 } from "fs";
15951
- import { dirname as dirname2 } from "path";
15818
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, unlinkSync, mkdirSync as mkdirSync2 } from "fs";
15819
+ import { dirname } from "path";
15952
15820
  function isProcessAlive(pid) {
15953
15821
  try {
15954
15822
  process.kill(pid, 0);
@@ -15959,7 +15827,7 @@ function isProcessAlive(pid) {
15959
15827
  }
15960
15828
  function readDaemonPid(profile) {
15961
15829
  try {
15962
- const content = readFileSync3(pidFilePath(profile), "utf-8").trim();
15830
+ const content = readFileSync2(pidFilePath(profile), "utf-8").trim();
15963
15831
  const pid = parseInt(content, 10);
15964
15832
  return Number.isNaN(pid) ? null : pid;
15965
15833
  } catch {
@@ -15969,14 +15837,14 @@ function readDaemonPid(profile) {
15969
15837
  function acquireDaemonPid(profile) {
15970
15838
  const pidPath = pidFilePath(profile);
15971
15839
  try {
15972
- const content = readFileSync3(pidPath, "utf-8").trim();
15840
+ const content = readFileSync2(pidPath, "utf-8").trim();
15973
15841
  const existingPid = parseInt(content, 10);
15974
15842
  if (!isNaN(existingPid) && isProcessAlive(existingPid)) {
15975
15843
  log.error(`Another daemon is already running (PID ${existingPid}). ` + `Remove ${pidPath} if this is stale.`);
15976
15844
  return false;
15977
15845
  }
15978
15846
  } catch {}
15979
- mkdirSync2(dirname2(pidPath), { recursive: true, mode: 448 });
15847
+ mkdirSync2(dirname(pidPath), { recursive: true, mode: 448 });
15980
15848
  writeFileSync2(pidPath, String(process.pid), { mode: 384 });
15981
15849
  return true;
15982
15850
  }
@@ -15995,8 +15863,8 @@ function releaseDaemonPid(profile) {
15995
15863
 
15996
15864
  // daemon/daemon.ts
15997
15865
  import { execSync as execSync3, spawn } from "child_process";
15998
- import { fileURLToPath as fileURLToPath2 } from "url";
15999
- import { dirname as dirname3, join as join4 } from "path";
15866
+ import { fileURLToPath } from "url";
15867
+ import { dirname as dirname2, join as join3 } from "path";
16000
15868
  function isCommandAvailable2(cmd) {
16001
15869
  try {
16002
15870
  execSync3(`which ${cmd}`, { stdio: "ignore" });
@@ -16168,7 +16036,7 @@ async function startDaemon(profile, serverUrl) {
16168
16036
  process.on("SIGINT", shutdown);
16169
16037
  await pollCycle();
16170
16038
  }
16171
- var SESSION_RUNNER_PATH = join4(dirname3(fileURLToPath2(import.meta.url)), "session-runner.ts");
16039
+ var SESSION_RUNNER_PATH = join3(dirname2(fileURLToPath(import.meta.url)), "session-runner.ts");
16172
16040
  function spawnSessionRunner(input) {
16173
16041
  const encoded = Buffer.from(JSON.stringify(input)).toString("base64");
16174
16042
  const child = spawn("bun", ["run", SESSION_RUNNER_PATH, encoded], {
@@ -16246,7 +16114,7 @@ async function startInBackground(profile, serverUrl) {
16246
16114
  return;
16247
16115
  }
16248
16116
  const logPath = daemonLogFilePath();
16249
- mkdirSync3(dirname4(logPath), { recursive: true, mode: 448 });
16117
+ mkdirSync3(dirname3(logPath), { recursive: true, mode: 448 });
16250
16118
  const logFd = openSync(logPath, "a", 384);
16251
16119
  const child = spawn2(process.execPath, buildChildArgs(profile, serverUrl), {
16252
16120
  detached: true,
@@ -16357,7 +16225,7 @@ function configCommand() {
16357
16225
  // commands/email.ts
16358
16226
  import { Command as Command5 } from "commander";
16359
16227
  import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync4 } from "fs";
16360
- import { join as join5 } from "path";
16228
+ import { join as join4 } from "path";
16361
16229
  import PostalMime from "postal-mime";
16362
16230
  var VALID_STATUSES = ["unread", "read", "archived"];
16363
16231
  var EMAIL_DIR = "/tmp/alook-emails";
@@ -16407,7 +16275,7 @@ function emailCommand() {
16407
16275
  mkdirSync4(EMAIL_DIR, { recursive: true });
16408
16276
  const downloadedPaths = [];
16409
16277
  for (const email3 of emails2) {
16410
- const emailDir = join5(EMAIL_DIR, email3.id);
16278
+ const emailDir = join4(EMAIL_DIR, email3.id);
16411
16279
  mkdirSync4(emailDir, { recursive: true });
16412
16280
  const metadata = {
16413
16281
  id: email3.id,
@@ -16417,7 +16285,7 @@ function emailCommand() {
16417
16285
  date: email3.created_at,
16418
16286
  status: email3.status
16419
16287
  };
16420
- const metadataPath = join5(emailDir, "metadata.json");
16288
+ const metadataPath = join4(emailDir, "metadata.json");
16421
16289
  writeFileSync3(metadataPath, JSON.stringify(metadata, null, 2));
16422
16290
  downloadedPaths.push(metadataPath);
16423
16291
  let rawMime;
@@ -16433,17 +16301,17 @@ function emailCommand() {
16433
16301
  }
16434
16302
  const parsed = await new PostalMime().parse(rawMime);
16435
16303
  if (parsed.text) {
16436
- const bodyPath = join5(emailDir, "body.txt");
16304
+ const bodyPath = join4(emailDir, "body.txt");
16437
16305
  writeFileSync3(bodyPath, parsed.text);
16438
16306
  downloadedPaths.push(bodyPath);
16439
16307
  }
16440
16308
  if (parsed.html) {
16441
- const htmlPath = join5(emailDir, "body.html");
16309
+ const htmlPath = join4(emailDir, "body.html");
16442
16310
  writeFileSync3(htmlPath, parsed.html);
16443
16311
  downloadedPaths.push(htmlPath);
16444
16312
  }
16445
16313
  if (parsed.attachments && parsed.attachments.length > 0) {
16446
- const attDir = join5(emailDir, "attachments");
16314
+ const attDir = join4(emailDir, "attachments");
16447
16315
  mkdirSync4(attDir, { recursive: true });
16448
16316
  const usedFilenames = new Set;
16449
16317
  for (let i = 0;i < parsed.attachments.length; i++) {
@@ -16453,7 +16321,7 @@ function emailCommand() {
16453
16321
  filename = `${i}-${filename}`;
16454
16322
  }
16455
16323
  usedFilenames.add(filename);
16456
- const attPath = join5(attDir, filename);
16324
+ const attPath = join4(attDir, filename);
16457
16325
  const content = att.content;
16458
16326
  let buf;
16459
16327
  if (typeof content === "string") {
@@ -16499,6 +16367,28 @@ function emailCommand() {
16499
16367
 
16500
16368
  // commands/version.ts
16501
16369
  import { Command as Command6 } from "commander";
16370
+
16371
+ // lib/version.ts
16372
+ import { readFileSync as readFileSync3 } from "fs";
16373
+ import { join as join5, dirname as dirname4 } from "path";
16374
+ import { fileURLToPath as fileURLToPath2 } from "url";
16375
+ function getCurrentVersion() {
16376
+ const __dirname2 = dirname4(fileURLToPath2(import.meta.url));
16377
+ const candidates = [
16378
+ join5(__dirname2, "..", "package.json"),
16379
+ join5(__dirname2, "..", "..", "package.json")
16380
+ ];
16381
+ for (const candidate of candidates) {
16382
+ try {
16383
+ const pkg = JSON.parse(readFileSync3(candidate, "utf-8"));
16384
+ if (typeof pkg.version === "string")
16385
+ return pkg.version;
16386
+ } catch {}
16387
+ }
16388
+ return "unknown";
16389
+ }
16390
+
16391
+ // commands/version.ts
16502
16392
  function versionCommand() {
16503
16393
  const cmd = new Command6("version").description("Show CLI version").action(() => {
16504
16394
  console.log(`alook version ${getCurrentVersion()}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alook/cli",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Alook CLI — register and run always-on AI coding agents.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/alookai/alook#readme",