@alook/cli 0.0.158 → 0.0.159

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -15189,6 +15189,11 @@ var CommunityAgentChannelMemberRequestSchema = exports_external.object({
15189
15189
  var CommunityAgentJoinServerRequestSchema = exports_external.object({
15190
15190
  invite: exports_external.string().min(1)
15191
15191
  });
15192
+ var CommunityAgentReactAddRequestSchema = exports_external.object({
15193
+ channel: exports_external.string().min(1),
15194
+ seq: CommunityAgentPositiveSeqSchema,
15195
+ emoji: exports_external.string().min(1)
15196
+ });
15192
15197
  var AuditLogCliInvocationPayloadSchema = exports_external.object({
15193
15198
  subcommand: exports_external.string().min(1)
15194
15199
  });
@@ -15201,15 +15206,28 @@ var AuditLogThinkingPayloadSchema = exports_external.object({
15201
15206
  truncated: exports_external.boolean(),
15202
15207
  chars: exports_external.number().int().nonnegative()
15203
15208
  });
15209
+ var AuditLogWakeTriggerPayloadSchema = exports_external.object({
15210
+ messageId: exports_external.string().min(1),
15211
+ channel: exports_external.string().min(1),
15212
+ seq: CommunityAgentPositiveSeqSchema,
15213
+ senderId: exports_external.string().min(1),
15214
+ senderHandle: exports_external.string().min(1),
15215
+ reason: exports_external.enum(["unread", "mention"])
15216
+ });
15217
+ var AuditLogSessionResetPayloadSchema = exports_external.object({});
15204
15218
  var BotAuditEventSchema = exports_external.discriminatedUnion("kind", [
15205
15219
  exports_external.object({ kind: exports_external.literal("cli_invocation"), payload: AuditLogCliInvocationPayloadSchema }),
15206
15220
  exports_external.object({ kind: exports_external.literal("tool_call"), payload: AuditLogToolCallPayloadSchema }),
15207
- exports_external.object({ kind: exports_external.literal("thinking"), payload: AuditLogThinkingPayloadSchema })
15221
+ exports_external.object({ kind: exports_external.literal("thinking"), payload: AuditLogThinkingPayloadSchema }),
15222
+ exports_external.object({ kind: exports_external.literal("wake_trigger"), payload: AuditLogWakeTriggerPayloadSchema }),
15223
+ exports_external.object({ kind: exports_external.literal("session_reset"), payload: AuditLogSessionResetPayloadSchema })
15208
15224
  ]);
15209
15225
  var BotAuditEventKindSchema = exports_external.enum([
15210
15226
  "cli_invocation",
15211
15227
  "tool_call",
15212
- "thinking"
15228
+ "thinking",
15229
+ "wake_trigger",
15230
+ "session_reset"
15213
15231
  ]);
15214
15232
  var HostBotAuditEventFrameSchema = exports_external.object({
15215
15233
  type: exports_external.literal("bot_audit_event"),
@@ -17824,6 +17842,39 @@ import { dirname as dirname4 } from "path";
17824
17842
  import { readFileSync, writeFileSync, mkdirSync } from "fs";
17825
17843
  import { join } from "path";
17826
17844
  import { homedir } from "os";
17845
+ function workspaceStatus(ws) {
17846
+ return ws.status ?? (ws.id ? "active" : "deleted");
17847
+ }
17848
+ function activeWorkspaces(workspaces) {
17849
+ return (workspaces || []).filter((ws) => workspaceStatus(ws) === "active" && !!ws.id);
17850
+ }
17851
+ function markWorkspaceActive(watched, fields) {
17852
+ const existing = watched.find((w) => w.id === fields.id);
17853
+ if (existing) {
17854
+ existing.status = "active";
17855
+ existing.name = fields.name;
17856
+ if (fields.token !== undefined)
17857
+ existing.token = fields.token;
17858
+ if (fields.agent_ids !== undefined)
17859
+ existing.agent_ids = fields.agent_ids;
17860
+ } else {
17861
+ watched.push({
17862
+ id: fields.id,
17863
+ name: fields.name,
17864
+ token: fields.token ?? "",
17865
+ status: "active",
17866
+ agent_ids: fields.agent_ids ?? []
17867
+ });
17868
+ }
17869
+ return watched;
17870
+ }
17871
+ function markWorkspaceDeletedInList(watched, workspaceId) {
17872
+ const entry = watched.find((w) => w.id === workspaceId);
17873
+ if (!entry)
17874
+ return false;
17875
+ entry.status = "deleted";
17876
+ return true;
17877
+ }
17827
17878
  function configDir() {
17828
17879
  return process.env.ALOOK_PROJECT_ROOT || join(homedir(), ".alook");
17829
17880
  }
@@ -17850,7 +17901,7 @@ function loadCLIConfigForProfile(profile) {
17850
17901
  };
17851
17902
  for (const ws of result.watched_workspaces) {
17852
17903
  if (!ws.status)
17853
- ws.status = ws.id ? "active" : "deleted";
17904
+ ws.status = workspaceStatus(ws);
17854
17905
  }
17855
17906
  return result;
17856
17907
  }
@@ -22315,6 +22366,11 @@ class DaemonWsClient {
22315
22366
  this.opts.onConnected();
22316
22367
  return;
22317
22368
  }
22369
+ if (msg.type === "error" && msg.code === "AUTH_REJECTED") {
22370
+ log10.warn("machine token rejected by server (AUTH_REJECTED)", { reason: msg.reason });
22371
+ this.opts.onAuthRejected?.(msg.reason);
22372
+ return;
22373
+ }
22318
22374
  const parsed = DaemonPushMessageSchema.safeParse(msg);
22319
22375
  if (!parsed.success) {
22320
22376
  log10.warn("invalid push message", { err: parsed.error.message });
@@ -22325,13 +22381,16 @@ class DaemonWsClient {
22325
22381
  log10.debug("message parse error", { err: String(err) });
22326
22382
  }
22327
22383
  });
22328
- this.ws.addEventListener("error", () => {
22329
- log10.debug("ws error");
22384
+ this.ws.addEventListener("error", (event) => {
22385
+ const err = event;
22386
+ log10.warn("ws error", { err: String(err?.message ?? err?.error ?? "unknown") });
22330
22387
  });
22331
- this.ws.addEventListener("close", () => {
22388
+ this.ws.addEventListener("close", (event) => {
22389
+ const { code, reason } = event;
22332
22390
  const wasConnected = this.connected;
22333
22391
  this.connected = false;
22334
22392
  this.stopHeartbeat();
22393
+ log10.info("ws closed", { code, reason, wasConnected });
22335
22394
  if (wasConnected) {
22336
22395
  this.opts.onDisconnected();
22337
22396
  }
@@ -22364,7 +22423,7 @@ class DaemonWsClient {
22364
22423
  const delay = Math.min(this.reconnectDelay, WS_RECONNECT_MAX);
22365
22424
  this.reconnectDelay = Math.min(delay * 2, WS_RECONNECT_MAX);
22366
22425
  const jitter = Math.random() * 500;
22367
- log10.debug("reconnecting", { delayMs: Math.round(delay + jitter) });
22426
+ log10.info("reconnecting", { delayMs: Math.round(delay + jitter) });
22368
22427
  this.reconnectTimer = setTimeout(() => {
22369
22428
  this.reconnectTimer = null;
22370
22429
  this.connect();
@@ -23061,6 +23120,7 @@ function isValidMarker(data) {
23061
23120
  }
23062
23121
  var MARKER_STALE_MS = 24 * 60 * 60 * 1000;
23063
23122
  var TMP_STALE_MS = 60 * 60 * 1000;
23123
+ var WS_AUTH_401_THRESHOLD = 5;
23064
23124
  async function reconcilePendingCompletions(workspacesRoot) {
23065
23125
  const dir = join12(workspacesRoot, ".pending_completions");
23066
23126
  let entries;
@@ -23167,8 +23227,7 @@ async function startDaemon(profile, serverUrl) {
23167
23227
  }
23168
23228
  }
23169
23229
  const cliConfig = loadCLIConfigForProfile(profile);
23170
- const allEntries = cliConfig.watched_workspaces || [];
23171
- const workspaces = allEntries.filter((ws) => ws.status !== "deleted" && !!ws.id);
23230
+ const workspaces = activeWorkspaces(cliConfig.watched_workspaces);
23172
23231
  if (workspaces.length === 0) {
23173
23232
  log13.info("No workspaces configured — daemon starting in standby mode. Register a workspace to begin.");
23174
23233
  }
@@ -23204,6 +23263,7 @@ async function startDaemon(profile, serverUrl) {
23204
23263
  const workspaceStates = [];
23205
23264
  const runtimeIndex = new Map;
23206
23265
  let hadWorkspaces = workspaces.length > 0;
23266
+ const consecutive401 = new Map;
23207
23267
  for (const ws of workspaces) {
23208
23268
  const runtimes = providers.map((p) => ({
23209
23269
  type: p.type,
@@ -23267,7 +23327,7 @@ async function startDaemon(profile, serverUrl) {
23267
23327
  }
23268
23328
  } catch {}
23269
23329
  }
23270
- function evictWorkspace(workspaceId) {
23330
+ function markWorkspaceDeleted(workspaceId, reason) {
23271
23331
  const idx = workspaceStates.findIndex((ws2) => ws2.workspaceId === workspaceId);
23272
23332
  if (idx === -1)
23273
23333
  return;
@@ -23276,13 +23336,15 @@ async function startDaemon(profile, serverUrl) {
23276
23336
  runtimeIndex.delete(rid);
23277
23337
  }
23278
23338
  workspaceStates.splice(idx, 1);
23339
+ consecutive401.delete(workspaceId);
23279
23340
  health.setRuntimeCount(workspaceStates.reduce((sum, w) => sum + w.runtimeIds.length, 0));
23280
23341
  try {
23281
23342
  const cfg = loadCLIConfigForProfile(profile);
23282
- cfg.watched_workspaces = (cfg.watched_workspaces || []).filter((w) => w.id !== workspaceId);
23283
- saveCLIConfigForProfile(profile, cfg);
23343
+ if (markWorkspaceDeletedInList(cfg.watched_workspaces || [], workspaceId)) {
23344
+ saveCLIConfigForProfile(profile, cfg);
23345
+ }
23284
23346
  } catch {}
23285
- log13.info(`Workspace ${workspaceId} deleted server-sideremoved from config`);
23347
+ log13.info(`Workspace ${workspaceId} removed from polling ${reason}`);
23286
23348
  }
23287
23349
  const pollCycle = async () => {
23288
23350
  let remaining = config2.maxConcurrentTasks - activeTasks.size;
@@ -23290,7 +23352,7 @@ async function startDaemon(profile, serverUrl) {
23290
23352
  return;
23291
23353
  const N = workspaceStates.length;
23292
23354
  const staggerMs = N > 1 ? Math.floor(config2.pollInterval / N) : 0;
23293
- const evictedIds = [];
23355
+ const toRemove = new Map;
23294
23356
  for (let i = 0;i < N; i++) {
23295
23357
  if (remaining <= 0)
23296
23358
  break;
@@ -23300,8 +23362,9 @@ async function startDaemon(profile, serverUrl) {
23300
23362
  }
23301
23363
  try {
23302
23364
  const { tasks: apiTasks, evicted, pending_update, pending_rescan, file_requests, meetings } = await client.poll(ws.token, config2.daemonId, remaining, config2.cliVersion);
23365
+ consecutive401.delete(ws.workspaceId);
23303
23366
  if (evicted) {
23304
- evictedIds.push(ws.workspaceId);
23367
+ toRemove.set(ws.workspaceId, "server evicted");
23305
23368
  continue;
23306
23369
  }
23307
23370
  if (pending_update && !isUpdating() && pending_update.version !== config2.cliVersion) {
@@ -23309,8 +23372,8 @@ async function startDaemon(profile, serverUrl) {
23309
23372
  }
23310
23373
  if (pending_rescan) {
23311
23374
  log13.info("Rescan requested — restarting daemon to re-detect runtimes");
23312
- for (const id of evictedIds) {
23313
- evictWorkspace(id);
23375
+ for (const [id, reason] of toRemove) {
23376
+ markWorkspaceDeleted(id, reason);
23314
23377
  }
23315
23378
  requestRestart();
23316
23379
  return;
@@ -23350,14 +23413,26 @@ async function startDaemon(profile, serverUrl) {
23350
23413
  }
23351
23414
  } catch (e) {
23352
23415
  if (e instanceof Error && e.message.startsWith("HTTP 401")) {
23353
- log13.warn(`Workspace ${ws.workspaceId} poll returned 401 — will retry next cycle`);
23416
+ const n = (consecutive401.get(ws.workspaceId) ?? 0) + 1;
23417
+ consecutive401.set(ws.workspaceId, n);
23418
+ if (n >= WS_AUTH_401_THRESHOLD) {
23419
+ toRemove.set(ws.workspaceId, `poll 401 x${n}`);
23420
+ } else {
23421
+ log13.warn(`Workspace ${ws.workspaceId} poll 401 (${n}/${WS_AUTH_401_THRESHOLD}) — will retry`);
23422
+ }
23354
23423
  } else {
23424
+ consecutive401.delete(ws.workspaceId);
23355
23425
  log13.debug("Poll error", e);
23356
23426
  }
23357
23427
  }
23358
23428
  }
23359
- for (const id of evictedIds) {
23360
- evictWorkspace(id);
23429
+ if (toRemove.size > 0) {
23430
+ const wsTokenWorkspaceDropped = wsWorkspaceId != null && toRemove.has(wsWorkspaceId);
23431
+ for (const [id, reason] of toRemove) {
23432
+ markWorkspaceDeleted(id, reason);
23433
+ }
23434
+ if (wsTokenWorkspaceDropped)
23435
+ rebuildWsClient();
23361
23436
  }
23362
23437
  if (workspaceStates.length === 0 && hadWorkspaces) {
23363
23438
  log13.info("All workspaces evicted — shutting down");
@@ -23373,7 +23448,6 @@ async function startDaemon(profile, serverUrl) {
23373
23448
  }
23374
23449
  };
23375
23450
  const heartbeatTimer = setInterval(heartbeatPing, config2.heartbeatInterval);
23376
- const firstToken = workspaceStates[0]?.token;
23377
23451
  function updatePollInterval(newInterval) {
23378
23452
  clearInterval(pollTimer);
23379
23453
  pollTimer = setInterval(pollCycle, newInterval);
@@ -23429,9 +23503,17 @@ async function startDaemon(profile, serverUrl) {
23429
23503
  });
23430
23504
  }
23431
23505
  break;
23432
- case "daemon.evict":
23433
- evictWorkspace(msg.workspaceId);
23506
+ case "daemon.evict": {
23507
+ const wasWsToken = wsWorkspaceId === msg.workspaceId;
23508
+ markWorkspaceDeleted(msg.workspaceId, "server evicted");
23509
+ if (wasWsToken)
23510
+ rebuildWsClient();
23511
+ if (workspaceStates.length === 0 && hadWorkspaces) {
23512
+ log13.info("All workspaces removed — shutting down");
23513
+ shutdown();
23514
+ }
23434
23515
  break;
23516
+ }
23435
23517
  case "daemon.update":
23436
23518
  if (!isUpdating() && msg.version !== config2.cliVersion) {
23437
23519
  handleCliUpdate(msg.version, () => requestRestart(), profile);
@@ -23474,11 +23556,9 @@ async function startDaemon(profile, serverUrl) {
23474
23556
  }
23475
23557
  }
23476
23558
  }
23477
- const wsToken = firstToken;
23478
- let wsClient = wsToken ? new DaemonWsClient({
23479
- serverURL: config2.serverURL,
23480
- daemonId: config2.daemonId,
23481
- machineToken: wsToken,
23559
+ let wsClient = null;
23560
+ let wsWorkspaceId;
23561
+ const wsCallbacks = {
23482
23562
  onMessage: handleWsPush,
23483
23563
  onConnected: () => {
23484
23564
  log13.info("WS connected — switching to low-frequency poll");
@@ -23487,9 +23567,57 @@ async function startDaemon(profile, serverUrl) {
23487
23567
  onDisconnected: () => {
23488
23568
  log13.info("WS disconnected — reverting to high-frequency poll");
23489
23569
  updatePollInterval(config2.pollInterval);
23570
+ },
23571
+ onAuthRejected: (reason) => {
23572
+ const rejectedWorkspaceId = wsWorkspaceId;
23573
+ const rejectedToken = workspaceStates.find((ws) => ws.workspaceId === rejectedWorkspaceId)?.token;
23574
+ wsClient?.close();
23575
+ wsClient = null;
23576
+ wsWorkspaceId = undefined;
23577
+ if (rejectedWorkspaceId != null && rejectedToken) {
23578
+ confirmAuthRejection(rejectedWorkspaceId, rejectedToken, reason);
23579
+ } else {
23580
+ rebuildWsClient();
23581
+ }
23490
23582
  }
23491
- }) : null;
23492
- wsClient?.connect();
23583
+ };
23584
+ async function confirmAuthRejection(workspaceId, token, reason) {
23585
+ let confirmedDead = false;
23586
+ try {
23587
+ await client.poll(token, config2.daemonId, 0, config2.cliVersion);
23588
+ log13.info(`Workspace ${workspaceId} WS auth rejection not confirmed by poll — keeping (likely transient)`);
23589
+ } catch (e) {
23590
+ if (e instanceof Error && e.message.startsWith("HTTP 401")) {
23591
+ confirmedDead = true;
23592
+ markWorkspaceDeleted(workspaceId, `WS auth rejected${reason ? ` (${reason})` : ""} — confirmed by poll 401`);
23593
+ } else {
23594
+ log13.debug("Confirm-poll error (transient) — keeping workspace", e);
23595
+ }
23596
+ }
23597
+ rebuildWsClient();
23598
+ if (confirmedDead && workspaceStates.length === 0 && hadWorkspaces) {
23599
+ log13.info("All workspaces removed — shutting down");
23600
+ shutdown();
23601
+ }
23602
+ }
23603
+ function rebuildWsClient() {
23604
+ wsClient?.close();
23605
+ const first = workspaceStates[0];
23606
+ if (!first) {
23607
+ wsClient = null;
23608
+ wsWorkspaceId = undefined;
23609
+ return;
23610
+ }
23611
+ wsWorkspaceId = first.workspaceId;
23612
+ wsClient = new DaemonWsClient({
23613
+ serverURL: config2.serverURL,
23614
+ daemonId: config2.daemonId,
23615
+ machineToken: first.token,
23616
+ ...wsCallbacks
23617
+ });
23618
+ wsClient.connect();
23619
+ }
23620
+ rebuildWsClient();
23493
23621
  const sweepTick = async () => {
23494
23622
  for (const ws of workspaceStates) {
23495
23623
  client.sweep(ws.token, config2.daemonId).catch((e) => {
@@ -23575,7 +23703,7 @@ async function startDaemon(profile, serverUrl) {
23575
23703
  log13.info("SIGHUP received — reloading config...");
23576
23704
  try {
23577
23705
  const freshConfig = loadCLIConfigForProfile(profile);
23578
- const freshWorkspaces = (freshConfig.watched_workspaces || []).filter((ws) => ws.status !== "deleted" && !!ws.id);
23706
+ const freshWorkspaces = activeWorkspaces(freshConfig.watched_workspaces);
23579
23707
  const existingIds = new Set(workspaceStates.map((ws) => ws.workspaceId));
23580
23708
  const newWorkspaces = freshWorkspaces.filter((ws) => ws.token && !existingIds.has(ws.id));
23581
23709
  for (const ws of newWorkspaces) {
@@ -23608,22 +23736,7 @@ async function startDaemon(profile, serverUrl) {
23608
23736
  hadWorkspaces = true;
23609
23737
  health.setRuntimeCount(workspaceStates.reduce((sum, w) => sum + w.runtimeIds.length, 0));
23610
23738
  if (!wsClient && workspaceStates.length > 0) {
23611
- const token = workspaceStates[0].token;
23612
- wsClient = new DaemonWsClient({
23613
- serverURL: config2.serverURL,
23614
- daemonId: config2.daemonId,
23615
- machineToken: token,
23616
- onMessage: handleWsPush,
23617
- onConnected: () => {
23618
- log13.info("WS connected — switching to low-frequency poll");
23619
- updatePollInterval(config2.wsPollInterval);
23620
- },
23621
- onDisconnected: () => {
23622
- log13.info("WS disconnected — reverting to high-frequency poll");
23623
- updatePollInterval(config2.pollInterval);
23624
- }
23625
- });
23626
- wsClient.connect();
23739
+ rebuildWsClient();
23627
23740
  log13.info("WS push client initialized after SIGHUP reload");
23628
23741
  }
23629
23742
  log13.info(`Reload complete — now polling ${workspaceStates.length} workspace(s)`);
@@ -24125,13 +24238,12 @@ async function activateAndSave(opts) {
24125
24238
  agentIds = agents.map((a) => a.id);
24126
24239
  } catch {}
24127
24240
  const existing = loadCLIConfigForProfile(profile);
24128
- const watched = existing.watched_workspaces || [];
24129
- const idx = watched.findIndex((w) => w.id === ws.id);
24130
- if (idx >= 0) {
24131
- watched[idx] = { id: ws.id, name: ws.name, token, status: "active", agent_ids: agentIds };
24132
- } else {
24133
- watched.push({ id: ws.id, name: ws.name, token, status: "active", agent_ids: agentIds });
24134
- }
24241
+ const watched = markWorkspaceActive(existing.watched_workspaces || [], {
24242
+ id: ws.id,
24243
+ name: ws.name,
24244
+ token,
24245
+ agent_ids: agentIds
24246
+ });
24135
24247
  saveCLIConfigForProfile(profile, {
24136
24248
  server_url: serverUrl,
24137
24249
  watched_workspaces: watched
@@ -24236,17 +24348,11 @@ function syncWorkspacesToConfig(serverWorkspaces, profile, sessionToken) {
24236
24348
  const watched = cfg.watched_workspaces || [];
24237
24349
  const serverIds = new Set(serverWorkspaces.map((w) => w.id));
24238
24350
  for (const sw of serverWorkspaces) {
24239
- const existing = watched.find((w) => w.id === sw.id);
24240
- if (existing) {
24241
- existing.status = "active";
24242
- existing.name = sw.name;
24243
- } else {
24244
- watched.push({ id: sw.id, name: sw.name, token: "", status: "active", agent_ids: [] });
24245
- }
24351
+ markWorkspaceActive(watched, { id: sw.id, name: sw.name });
24246
24352
  }
24247
24353
  for (const w of watched) {
24248
24354
  if (w.id && !serverIds.has(w.id)) {
24249
- w.status = "deleted";
24355
+ markWorkspaceDeletedInList(watched, w.id);
24250
24356
  }
24251
24357
  }
24252
24358
  saveCLIConfigForProfile(profile, {
@@ -24352,7 +24458,7 @@ if (process.argv.includes("--__login-poll")) {
24352
24458
  async function checkExistingAuth(serverUrl, profile) {
24353
24459
  const config2 = loadCLIConfigForProfile(profile);
24354
24460
  const sessionToken = config2.session_token;
24355
- const workspaces = config2.watched_workspaces || [];
24461
+ const workspaces = activeWorkspaces(config2.watched_workspaces);
24356
24462
  const ws = workspaces[0];
24357
24463
  const authToken = sessionToken || ws?.token;
24358
24464
  if (!authToken) {
@@ -24366,7 +24472,7 @@ async function checkExistingAuth(serverUrl, profile) {
24366
24472
  return { valid: false };
24367
24473
  }
24368
24474
  const serverWorkspaces = await res.json();
24369
- const hasValidWorkspace = workspaces.some((w) => w.id && w.status !== "deleted");
24475
+ const hasValidWorkspace = workspaces.length > 0;
24370
24476
  if (!hasValidWorkspace && serverWorkspaces.length > 0) {
24371
24477
  syncWorkspacesToConfig(serverWorkspaces, profile);
24372
24478
  }
@@ -24467,7 +24573,7 @@ function statusCommand() {
24467
24573
  const cmd = new Command3("status").description("Show registration status").action((_opts, command) => {
24468
24574
  const profile = command.parent?.opts().profile;
24469
24575
  const cfg = loadCLIConfigForProfile(profile);
24470
- const ws = cfg.watched_workspaces?.[0];
24576
+ const ws = activeWorkspaces(cfg.watched_workspaces)[0];
24471
24577
  if (!ws?.token) {
24472
24578
  console.log("Not registered");
24473
24579
  console.log(`Run '${cmdPrefix()} register --token <token>' to register.`);
@@ -24692,7 +24798,7 @@ function resolveClientOptsPartial(command, opts = {}) {
24692
24798
  console.error("Error: no server URL configured. Set ALOOK_SERVER_URL or run register.");
24693
24799
  process.exit(1);
24694
24800
  }
24695
- const workspaces = cfg.watched_workspaces || [];
24801
+ const workspaces = activeWorkspaces(cfg.watched_workspaces);
24696
24802
  let ws;
24697
24803
  const envWorkspaceId = process.env.ALOOK_WORKSPACE_ID;
24698
24804
  if (opts.workspace) {
@@ -25844,15 +25950,11 @@ function workspaceCommand() {
25844
25950
  const res = await wsClient.postJSON("/api/studios", payload2);
25845
25951
  try {
25846
25952
  const freshCfg = loadCLIConfigForProfile(parentOpts.profile);
25847
- const watched = freshCfg.watched_workspaces || [];
25848
- const existing = watched.find((w) => w.id === targetWorkspaceId);
25849
- if (existing) {
25850
- existing.status = "active";
25851
- existing.name = res.workspace.name;
25852
- } else {
25853
- watched.push({ id: targetWorkspaceId, name: res.workspace.name, token, status: "active", agent_ids: [] });
25854
- }
25855
- freshCfg.watched_workspaces = watched;
25953
+ freshCfg.watched_workspaces = markWorkspaceActive(freshCfg.watched_workspaces || [], {
25954
+ id: targetWorkspaceId,
25955
+ name: res.workspace.name,
25956
+ token
25957
+ });
25856
25958
  saveCLIConfigForProfile(parentOpts.profile, freshCfg);
25857
25959
  } catch {}
25858
25960
  if (opts.json)
@@ -15094,6 +15094,11 @@ var CommunityAgentChannelMemberRequestSchema = exports_external.object({
15094
15094
  var CommunityAgentJoinServerRequestSchema = exports_external.object({
15095
15095
  invite: exports_external.string().min(1)
15096
15096
  });
15097
+ var CommunityAgentReactAddRequestSchema = exports_external.object({
15098
+ channel: exports_external.string().min(1),
15099
+ seq: CommunityAgentPositiveSeqSchema,
15100
+ emoji: exports_external.string().min(1)
15101
+ });
15097
15102
  var AuditLogCliInvocationPayloadSchema = exports_external.object({
15098
15103
  subcommand: exports_external.string().min(1)
15099
15104
  });
@@ -15106,15 +15111,28 @@ var AuditLogThinkingPayloadSchema = exports_external.object({
15106
15111
  truncated: exports_external.boolean(),
15107
15112
  chars: exports_external.number().int().nonnegative()
15108
15113
  });
15114
+ var AuditLogWakeTriggerPayloadSchema = exports_external.object({
15115
+ messageId: exports_external.string().min(1),
15116
+ channel: exports_external.string().min(1),
15117
+ seq: CommunityAgentPositiveSeqSchema,
15118
+ senderId: exports_external.string().min(1),
15119
+ senderHandle: exports_external.string().min(1),
15120
+ reason: exports_external.enum(["unread", "mention"])
15121
+ });
15122
+ var AuditLogSessionResetPayloadSchema = exports_external.object({});
15109
15123
  var BotAuditEventSchema = exports_external.discriminatedUnion("kind", [
15110
15124
  exports_external.object({ kind: exports_external.literal("cli_invocation"), payload: AuditLogCliInvocationPayloadSchema }),
15111
15125
  exports_external.object({ kind: exports_external.literal("tool_call"), payload: AuditLogToolCallPayloadSchema }),
15112
- exports_external.object({ kind: exports_external.literal("thinking"), payload: AuditLogThinkingPayloadSchema })
15126
+ exports_external.object({ kind: exports_external.literal("thinking"), payload: AuditLogThinkingPayloadSchema }),
15127
+ exports_external.object({ kind: exports_external.literal("wake_trigger"), payload: AuditLogWakeTriggerPayloadSchema }),
15128
+ exports_external.object({ kind: exports_external.literal("session_reset"), payload: AuditLogSessionResetPayloadSchema })
15113
15129
  ]);
15114
15130
  var BotAuditEventKindSchema = exports_external.enum([
15115
15131
  "cli_invocation",
15116
15132
  "tool_call",
15117
- "thinking"
15133
+ "thinking",
15134
+ "wake_trigger",
15135
+ "session_reset"
15118
15136
  ]);
15119
15137
  var HostBotAuditEventFrameSchema = exports_external.object({
15120
15138
  type: exports_external.literal("bot_audit_event"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alook/cli",
3
- "version": "0.0.158",
3
+ "version": "0.0.159",
4
4
  "description": "Alook CLI — Enable Your Person Colleague",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/alookai/alook#readme",