@agentchatme/cli 0.0.136 → 0.0.137

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
@@ -4554,6 +4554,9 @@ function formatStopPickup(handle, rows) {
4554
4554
  "Handle these per your AgentChat skill, then finish. Reply via agentchat_send_message only where warranted \u2014 if nothing is actionable, simply end the turn (silence is a valid outcome)."
4555
4555
  ].join("\n");
4556
4556
  }
4557
+ function formatAlwaysOnDown(platform) {
4558
+ return `\u26A0 Always-on is down \u2014 while you are away I won\u2019t be able to answer messages (they queue for your next session, nothing is lost). Turn it back on: \`agentchat daemon install --platform ${platform}\``;
4559
+ }
4557
4560
  function formatRegistrationOffer(cliPath, platform) {
4558
4561
  const invoke = cliPath ? `node "${cliPath}"` : "agentchat";
4559
4562
  const p = platform ? ` --platform ${platform}` : "";
@@ -4579,6 +4582,140 @@ function formatRegistrationOffer(cliPath, platform) {
4579
4582
  ].join("\n");
4580
4583
  }
4581
4584
 
4585
+ // src/commands/daemon.ts
4586
+ import * as fs3 from "fs";
4587
+ import * as os2 from "os";
4588
+ import * as path4 from "path";
4589
+ import { spawnSync } from "child_process";
4590
+ var DAEMON_PKG = "@agentchatme/daemon";
4591
+ function runtimeDir() {
4592
+ return path4.join(os2.homedir(), ".agentchat", "daemon-runtime");
4593
+ }
4594
+ function daemonEntry() {
4595
+ return path4.join(runtimeDir(), "node_modules", "@agentchatme", "daemon", "dist", "index.js");
4596
+ }
4597
+ var ALWAYS_ON_WANTED = "always-on.wanted";
4598
+ var HEARTBEAT_FILE = "daemon.heartbeat";
4599
+ var HEARTBEAT_STALE_MS = 3 * 6e4;
4600
+ function markAlwaysOnWanted(home) {
4601
+ try {
4602
+ fs3.mkdirSync(home, { recursive: true });
4603
+ fs3.writeFileSync(path4.join(home, ALWAYS_ON_WANTED), "");
4604
+ } catch {
4605
+ }
4606
+ }
4607
+ function clearAlwaysOnWanted(home) {
4608
+ try {
4609
+ fs3.rmSync(path4.join(home, ALWAYS_ON_WANTED), { force: true });
4610
+ } catch {
4611
+ }
4612
+ }
4613
+ function alwaysOnHealth(home) {
4614
+ if (!fs3.existsSync(path4.join(home, ALWAYS_ON_WANTED))) return { wanted: false, healthy: true };
4615
+ try {
4616
+ const age = Date.now() - fs3.statSync(path4.join(home, HEARTBEAT_FILE)).mtimeMs;
4617
+ return { wanted: true, healthy: age <= HEARTBEAT_STALE_MS };
4618
+ } catch {
4619
+ return { wanted: true, healthy: false };
4620
+ }
4621
+ }
4622
+ function ensureDaemon() {
4623
+ if (fs3.existsSync(daemonEntry())) return { ok: true };
4624
+ const dir = runtimeDir();
4625
+ try {
4626
+ fs3.mkdirSync(dir, { recursive: true });
4627
+ } catch (err) {
4628
+ return { ok: false, detail: `could not create ${dir}: ${String(err)}` };
4629
+ }
4630
+ const r = spawnSync(
4631
+ "npm",
4632
+ ["install", DAEMON_PKG, "--prefix", dir, "--no-save", "--no-audit", "--no-fund"],
4633
+ { encoding: "utf-8", timeout: 18e4 }
4634
+ );
4635
+ if (r.error || r.status !== 0) {
4636
+ const why = (r.stderr || r.error && r.error.message || "unknown error").slice(0, 300);
4637
+ return { ok: false, detail: `npm install ${DAEMON_PKG} failed: ${why}` };
4638
+ }
4639
+ return fs3.existsSync(daemonEntry()) ? { ok: true } : { ok: false, detail: "installed but entrypoint missing" };
4640
+ }
4641
+ function runDaemon(args) {
4642
+ const r = spawnSync(process.execPath, [daemonEntry(), ...args], { stdio: "inherit" });
4643
+ return r.status ?? 1;
4644
+ }
4645
+ function tryInstallDaemon(platform, home) {
4646
+ const got = ensureDaemon();
4647
+ if (!got.ok) return { ok: false, detail: got.detail ?? "runtime fetch failed" };
4648
+ const r = spawnSync(
4649
+ process.execPath,
4650
+ [daemonEntry(), "install", "--runtime", platform, "--home", home],
4651
+ { encoding: "utf-8", timeout: 12e4 }
4652
+ );
4653
+ if (r.error || r.status !== 0) {
4654
+ const raw = r.stderr || r.stdout || r.error?.message || "";
4655
+ return { ok: false, detail: raw.slice(0, 300).trim() || "service install failed" };
4656
+ }
4657
+ markAlwaysOnWanted(home);
4658
+ return { ok: true };
4659
+ }
4660
+ async function runDaemonCmd(sub, platform) {
4661
+ if (platform === "cursor") {
4662
+ console.error("The always-on daemon supports Claude Code and Codex (Cursor not yet).");
4663
+ return 1;
4664
+ }
4665
+ const runtime = platform;
4666
+ const bound = process.env["AGENTCHAT_HOME"]?.trim();
4667
+ const home = bound && bound.length > 0 ? bound : hostHome(platform);
4668
+ if (sub === "install") {
4669
+ const creds = readCredentialsFileAt(home);
4670
+ if (creds === null) {
4671
+ console.error(
4672
+ `No AgentChat identity for ${platform} yet. Register first, then run:
4673
+ agentchat daemon install --platform ${platform}`
4674
+ );
4675
+ return 1;
4676
+ }
4677
+ const got = ensureDaemon();
4678
+ if (!got.ok) {
4679
+ console.error(`Couldn't set up always-on automatically: ${got.detail}`);
4680
+ console.error(`Finish it by hand:
4681
+ npm i -g ${DAEMON_PKG}
4682
+ agentchatd install --runtime ${runtime}`);
4683
+ return 1;
4684
+ }
4685
+ const code = runDaemon(["install", "--runtime", runtime, "--home", home]);
4686
+ if (code === 0) {
4687
+ markAlwaysOnWanted(home);
4688
+ console.log(
4689
+ [
4690
+ "",
4691
+ `Always-on is ON for @${creds.handle} \u2014 it answers DMs even when you're not in a session, while this machine is up.`,
4692
+ `Want session-only instead? Turn it off any time: agentchat daemon disable --platform ${platform}`
4693
+ ].join("\n")
4694
+ );
4695
+ }
4696
+ return code;
4697
+ }
4698
+ if (sub === "enable" || sub === "disable" || sub === "status" || sub === "uninstall") {
4699
+ if (!fs3.existsSync(daemonEntry())) {
4700
+ if (sub === "status") {
4701
+ console.log("Always-on: not installed (session-only). Turn it on with: agentchat daemon install");
4702
+ return 0;
4703
+ }
4704
+ if (sub === "disable") clearAlwaysOnWanted(home);
4705
+ console.error(`Always-on isn't set up yet. Turn it on with: agentchat daemon install --platform ${platform}`);
4706
+ return sub === "disable" ? 0 : 1;
4707
+ }
4708
+ const code = runDaemon([sub, "--runtime", runtime, "--home", home]);
4709
+ if (code === 0) {
4710
+ if (sub === "enable") markAlwaysOnWanted(home);
4711
+ else if (sub === "disable" || sub === "uninstall") clearAlwaysOnWanted(home);
4712
+ }
4713
+ return code;
4714
+ }
4715
+ console.error("Usage: agentchat daemon <install|enable|disable|status|uninstall> --platform <claude-code|codex>");
4716
+ return 1;
4717
+ }
4718
+
4582
4719
  // src/commands/hook.ts
4583
4720
  var SESSION_START_PEEK_LIMIT = 100;
4584
4721
  var STOP_PEEK_LIMIT = 50;
@@ -4622,7 +4759,7 @@ async function claimContiguousPrefix(cfg, rows, holder) {
4622
4759
  async function runSessionStartHook(platform) {
4623
4760
  try {
4624
4761
  if (hooksDisabled()) return;
4625
- bindHostHome(platform);
4762
+ const home = bindHostHome(platform);
4626
4763
  const input = await readHookInput();
4627
4764
  if (input.source === "compact") return;
4628
4765
  resetSession(`${platform}:${input.sessionId}`);
@@ -4636,12 +4773,19 @@ async function runSessionStartHook(platform) {
4636
4773
  }
4637
4774
  const cfg = { apiKey: identity.apiKey, apiBase: identity.apiBase };
4638
4775
  await markSessionActive(cfg);
4776
+ const h = alwaysOnHealth(home);
4777
+ const alert = h.wanted && !h.healthy ? formatAlwaysOnDown(platform) : null;
4639
4778
  const peeked = ackableRows(await syncPeek(cfg, { limit: SESSION_START_PEEK_LIMIT }));
4640
- if (peeked.length === 0) return;
4641
- const rows = await claimContiguousPrefix(cfg, peeked, `session:${input.sessionId}`);
4642
- if (rows.length === 0) return;
4779
+ const rows = peeked.length > 0 ? await claimContiguousPrefix(cfg, peeked, `session:${input.sessionId}`) : [];
4780
+ if (rows.length === 0) {
4781
+ if (alert !== null) printJson(sessionStartOutput(platform, alert));
4782
+ return;
4783
+ }
4643
4784
  const handle = await resolveHandle(cfg, identity.handle);
4644
- const context = formatSessionStart(handle, rows);
4785
+ const digest = formatSessionStart(handle, rows);
4786
+ const context = alert !== null ? `${alert}
4787
+
4788
+ ${digest}` : digest;
4645
4789
  const cursor = lastDeliveryId(rows);
4646
4790
  if (cursor !== null) {
4647
4791
  setPendingAck(`${platform}:${input.sessionId}`, cursor);
@@ -5979,9 +6123,9 @@ var AgentChatClient = class _AgentChatClient {
5979
6123
  var MAX_ATTACHMENT_SIZE = 25 * 1024 * 1024;
5980
6124
 
5981
6125
  // src/lib/anchor.ts
5982
- import * as fs3 from "fs";
5983
- import * as os2 from "os";
5984
- import * as path4 from "path";
6126
+ import * as fs4 from "fs";
6127
+ import * as os3 from "os";
6128
+ import * as path5 from "path";
5985
6129
  var ANCHOR_START = "<!-- agentchat:start -->";
5986
6130
  var ANCHOR_END = "<!-- agentchat:end -->";
5987
6131
  var LEGACY_ANCHOR_START = "<!-- agentchat-skill:start -->";
@@ -5989,9 +6133,9 @@ var LEGACY_ANCHOR_END = "<!-- agentchat-skill:end -->";
5989
6133
  function anchorFilePath(platform) {
5990
6134
  switch (platform) {
5991
6135
  case "claude-code":
5992
- return path4.join(os2.homedir(), ".claude", "CLAUDE.md");
6136
+ return path5.join(os3.homedir(), ".claude", "CLAUDE.md");
5993
6137
  case "codex":
5994
- return path4.join(codexHome(), "AGENTS.md");
6138
+ return path5.join(codexHome(), "AGENTS.md");
5995
6139
  case "cursor":
5996
6140
  return null;
5997
6141
  }
@@ -6016,11 +6160,11 @@ function installAnchor(platform, handle) {
6016
6160
  if (filePath === null) return { platform, path: null, action: "unsupported" };
6017
6161
  const trimmedHandle = handle.trim();
6018
6162
  if (!trimmedHandle) throw new Error("installAnchor: handle is empty");
6019
- fs3.mkdirSync(path4.dirname(filePath), { recursive: true });
6020
- const existing = fs3.existsSync(filePath) ? fs3.readFileSync(filePath, "utf-8") : "";
6163
+ fs4.mkdirSync(path5.dirname(filePath), { recursive: true });
6164
+ const existing = fs4.existsSync(filePath) ? fs4.readFileSync(filePath, "utf-8") : "";
6021
6165
  const next = upsertAnchorBlock(existing, renderAnchorBlock(trimmedHandle));
6022
- fs3.writeFileSync(filePath, next, "utf-8");
6023
- const verify = fs3.readFileSync(filePath, "utf-8");
6166
+ fs4.writeFileSync(filePath, next, "utf-8");
6167
+ const verify = fs4.readFileSync(filePath, "utf-8");
6024
6168
  if (!verify.includes(`@${trimmedHandle}`)) {
6025
6169
  throw new Error(
6026
6170
  `installAnchor: handle @${trimmedHandle} did not land in ${filePath} \u2014 please remove the agentchat block manually and re-run.`
@@ -6031,17 +6175,17 @@ function installAnchor(platform, handle) {
6031
6175
  function removeAnchor(platform) {
6032
6176
  const filePath = anchorFilePath(platform);
6033
6177
  if (filePath === null) return { platform, path: null, action: "unsupported" };
6034
- if (!fs3.existsSync(filePath)) return { platform, path: filePath, action: "noop" };
6035
- const existing = fs3.readFileSync(filePath, "utf-8");
6178
+ if (!fs4.existsSync(filePath)) return { platform, path: filePath, action: "noop" };
6179
+ const existing = fs4.readFileSync(filePath, "utf-8");
6036
6180
  const next = stripAnchorBlock(existing);
6037
6181
  if (next === existing) return { platform, path: filePath, action: "noop" };
6038
- fs3.writeFileSync(filePath, next, "utf-8");
6182
+ fs4.writeFileSync(filePath, next, "utf-8");
6039
6183
  return { platform, path: filePath, action: "removed" };
6040
6184
  }
6041
6185
  function hasAnchor(platform) {
6042
6186
  const filePath = anchorFilePath(platform);
6043
- if (filePath === null || !fs3.existsSync(filePath)) return false;
6044
- const content = fs3.readFileSync(filePath, "utf-8");
6187
+ if (filePath === null || !fs4.existsSync(filePath)) return false;
6188
+ const content = fs4.readFileSync(filePath, "utf-8");
6045
6189
  return findBlock(content, ANCHOR_START, ANCHOR_END) !== null;
6046
6190
  }
6047
6191
  function lineAnchoredIndex(text, marker, fromIndex = 0) {
@@ -6090,22 +6234,22 @@ function stripAllBlocks(existing, start, end) {
6090
6234
  }
6091
6235
 
6092
6236
  // src/lib/codex-config.ts
6093
- import * as fs4 from "fs";
6094
- import * as path5 from "path";
6237
+ import * as fs5 from "fs";
6238
+ import * as path6 from "path";
6095
6239
  var TOML_START = "# agentchat:start";
6096
6240
  var TOML_END = "# agentchat:end";
6097
- var BUNDLE_REL = path5.join("bin", "agentchat.mjs");
6241
+ var BUNDLE_REL = path6.join("bin", "agentchat.mjs");
6098
6242
  function codexConfigPath() {
6099
- return path5.join(codexHome(), "config.toml");
6243
+ return path6.join(codexHome(), "config.toml");
6100
6244
  }
6101
6245
  function codexHooksPath() {
6102
- return path5.join(codexHome(), "hooks.json");
6246
+ return path6.join(codexHome(), "hooks.json");
6103
6247
  }
6104
6248
  function codexIdentityHome() {
6105
6249
  return hostHome("codex");
6106
6250
  }
6107
6251
  function stableBundlePath() {
6108
- return path5.join(codexIdentityHome(), BUNDLE_REL);
6252
+ return path6.join(codexIdentityHome(), BUNDLE_REL);
6109
6253
  }
6110
6254
  function renderCodexAgents(handle) {
6111
6255
  return [
@@ -6219,17 +6363,17 @@ function unmergeHooks(existing) {
6219
6363
  }
6220
6364
  function copyBundle(bundleSrc) {
6221
6365
  const dest = stableBundlePath();
6222
- fs4.mkdirSync(path5.dirname(dest), { recursive: true });
6223
- const srcResolved = path5.resolve(bundleSrc);
6224
- if (srcResolved !== path5.resolve(dest)) {
6225
- fs4.copyFileSync(srcResolved, dest);
6366
+ fs5.mkdirSync(path6.dirname(dest), { recursive: true });
6367
+ const srcResolved = path6.resolve(bundleSrc);
6368
+ if (srcResolved !== path6.resolve(dest)) {
6369
+ fs5.copyFileSync(srcResolved, dest);
6226
6370
  }
6227
6371
  return dest;
6228
6372
  }
6229
6373
  function installCodex(bundleSrc, handle) {
6230
6374
  const actions = [];
6231
6375
  const warnings = [];
6232
- fs4.mkdirSync(codexHome(), { recursive: true });
6376
+ fs5.mkdirSync(codexHome(), { recursive: true });
6233
6377
  let bundle;
6234
6378
  try {
6235
6379
  bundle = copyBundle(bundleSrc);
@@ -6241,36 +6385,36 @@ function installCodex(bundleSrc, handle) {
6241
6385
  );
6242
6386
  }
6243
6387
  const cfgPath = codexConfigPath();
6244
- const existingCfg = fs4.existsSync(cfgPath) ? fs4.readFileSync(cfgPath, "utf-8") : "";
6388
+ const existingCfg = fs5.existsSync(cfgPath) ? fs5.readFileSync(cfgPath, "utf-8") : "";
6245
6389
  if (hasUnfencedAgentchatServer(existingCfg)) {
6246
6390
  warnings.push(
6247
6391
  `${cfgPath} already defines [mcp_servers.agentchat] outside our block \u2014 left it untouched; remove it and re-run if it isn't ours`
6248
6392
  );
6249
6393
  } else {
6250
- fs4.writeFileSync(cfgPath, upsertTomlBlock(existingCfg, mcpBlock()), "utf-8");
6394
+ fs5.writeFileSync(cfgPath, upsertTomlBlock(existingCfg, mcpBlock()), "utf-8");
6251
6395
  actions.push(`config.toml \u2190 [mcp_servers.agentchat]`);
6252
6396
  }
6253
6397
  const hooksPath = codexHooksPath();
6254
6398
  let existingHooks = null;
6255
- if (fs4.existsSync(hooksPath)) {
6399
+ if (fs5.existsSync(hooksPath)) {
6256
6400
  try {
6257
- existingHooks = JSON.parse(fs4.readFileSync(hooksPath, "utf-8"));
6401
+ existingHooks = JSON.parse(fs5.readFileSync(hooksPath, "utf-8"));
6258
6402
  } catch {
6259
6403
  warnings.push(`${hooksPath} was not valid JSON \u2014 leaving it; wire hooks manually if needed`);
6260
6404
  }
6261
6405
  }
6262
- if (existingHooks !== null || !fs4.existsSync(hooksPath)) {
6406
+ if (existingHooks !== null || !fs5.existsSync(hooksPath)) {
6263
6407
  const merged = mergeHooks(existingHooks, bundle);
6264
- fs4.writeFileSync(hooksPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
6408
+ fs5.writeFileSync(hooksPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
6265
6409
  actions.push("hooks.json \u2190 SessionStart + Stop + UserPromptSubmit");
6266
6410
  }
6267
6411
  if (handle) {
6268
6412
  try {
6269
- const agentsPath = path5.join(codexHome(), "AGENTS.md");
6270
- const existing = fs4.existsSync(agentsPath) ? fs4.readFileSync(agentsPath, "utf-8") : "";
6413
+ const agentsPath = path6.join(codexHome(), "AGENTS.md");
6414
+ const existing = fs5.existsSync(agentsPath) ? fs5.readFileSync(agentsPath, "utf-8") : "";
6271
6415
  const next = upsertAnchorBlock(existing, renderCodexAgents(handle));
6272
- fs4.writeFileSync(agentsPath, next, "utf-8");
6273
- if (!fs4.readFileSync(agentsPath, "utf-8").includes(`@${handle}`)) {
6416
+ fs5.writeFileSync(agentsPath, next, "utf-8");
6417
+ if (!fs5.readFileSync(agentsPath, "utf-8").includes(`@${handle}`)) {
6274
6418
  throw new Error("handle did not land in AGENTS.md");
6275
6419
  }
6276
6420
  actions.push(`AGENTS.md \u2190 identity + etiquette (@${handle})`);
@@ -6286,17 +6430,17 @@ function installCodex(bundleSrc, handle) {
6286
6430
  function removeCodex() {
6287
6431
  const removed = [];
6288
6432
  const cfgPath = codexConfigPath();
6289
- if (fs4.existsSync(cfgPath)) {
6290
- const stripped = stripTomlBlock(fs4.readFileSync(cfgPath, "utf-8"));
6291
- fs4.writeFileSync(cfgPath, stripped, "utf-8");
6433
+ if (fs5.existsSync(cfgPath)) {
6434
+ const stripped = stripTomlBlock(fs5.readFileSync(cfgPath, "utf-8"));
6435
+ fs5.writeFileSync(cfgPath, stripped, "utf-8");
6292
6436
  removed.push("config.toml [mcp_servers.agentchat]");
6293
6437
  }
6294
6438
  const hooksPath = codexHooksPath();
6295
- if (fs4.existsSync(hooksPath)) {
6439
+ if (fs5.existsSync(hooksPath)) {
6296
6440
  try {
6297
- const next = unmergeHooks(JSON.parse(fs4.readFileSync(hooksPath, "utf-8")));
6298
- if (next === null) fs4.unlinkSync(hooksPath);
6299
- else fs4.writeFileSync(hooksPath, JSON.stringify(next, null, 2) + "\n", "utf-8");
6441
+ const next = unmergeHooks(JSON.parse(fs5.readFileSync(hooksPath, "utf-8")));
6442
+ if (next === null) fs5.unlinkSync(hooksPath);
6443
+ else fs5.writeFileSync(hooksPath, JSON.stringify(next, null, 2) + "\n", "utf-8");
6300
6444
  removed.push("hooks.json entries");
6301
6445
  } catch {
6302
6446
  }
@@ -6306,107 +6450,6 @@ function removeCodex() {
6306
6450
  return removed;
6307
6451
  }
6308
6452
 
6309
- // src/commands/daemon.ts
6310
- import * as fs5 from "fs";
6311
- import * as os3 from "os";
6312
- import * as path6 from "path";
6313
- import { spawnSync } from "child_process";
6314
- var DAEMON_PKG = "@agentchatme/daemon";
6315
- function runtimeDir() {
6316
- return path6.join(os3.homedir(), ".agentchat", "daemon-runtime");
6317
- }
6318
- function daemonEntry() {
6319
- return path6.join(runtimeDir(), "node_modules", "@agentchatme", "daemon", "dist", "index.js");
6320
- }
6321
- function ensureDaemon() {
6322
- if (fs5.existsSync(daemonEntry())) return { ok: true };
6323
- const dir = runtimeDir();
6324
- try {
6325
- fs5.mkdirSync(dir, { recursive: true });
6326
- } catch (err) {
6327
- return { ok: false, detail: `could not create ${dir}: ${String(err)}` };
6328
- }
6329
- const r = spawnSync(
6330
- "npm",
6331
- ["install", DAEMON_PKG, "--prefix", dir, "--no-save", "--no-audit", "--no-fund"],
6332
- { encoding: "utf-8", timeout: 18e4 }
6333
- );
6334
- if (r.error || r.status !== 0) {
6335
- const why = (r.stderr || r.error && r.error.message || "unknown error").slice(0, 300);
6336
- return { ok: false, detail: `npm install ${DAEMON_PKG} failed: ${why}` };
6337
- }
6338
- return fs5.existsSync(daemonEntry()) ? { ok: true } : { ok: false, detail: "installed but entrypoint missing" };
6339
- }
6340
- function runDaemon(args) {
6341
- const r = spawnSync(process.execPath, [daemonEntry(), ...args], { stdio: "inherit" });
6342
- return r.status ?? 1;
6343
- }
6344
- function tryInstallDaemon(platform, home) {
6345
- const got = ensureDaemon();
6346
- if (!got.ok) return { ok: false, detail: got.detail ?? "runtime fetch failed" };
6347
- const r = spawnSync(
6348
- process.execPath,
6349
- [daemonEntry(), "install", "--runtime", platform, "--home", home],
6350
- { encoding: "utf-8", timeout: 12e4 }
6351
- );
6352
- if (r.error || r.status !== 0) {
6353
- const raw = r.stderr || r.stdout || r.error?.message || "";
6354
- return { ok: false, detail: raw.slice(0, 300).trim() || "service install failed" };
6355
- }
6356
- return { ok: true };
6357
- }
6358
- async function runDaemonCmd(sub, platform) {
6359
- if (platform === "cursor") {
6360
- console.error("The always-on daemon supports Claude Code and Codex (Cursor not yet).");
6361
- return 1;
6362
- }
6363
- const runtime = platform;
6364
- const bound = process.env["AGENTCHAT_HOME"]?.trim();
6365
- const home = bound && bound.length > 0 ? bound : hostHome(platform);
6366
- if (sub === "install") {
6367
- const creds = readCredentialsFileAt(home);
6368
- if (creds === null) {
6369
- console.error(
6370
- `No AgentChat identity for ${platform} yet. Register first, then run:
6371
- agentchat daemon install --platform ${platform}`
6372
- );
6373
- return 1;
6374
- }
6375
- const got = ensureDaemon();
6376
- if (!got.ok) {
6377
- console.error(`Couldn't set up always-on automatically: ${got.detail}`);
6378
- console.error(`Finish it by hand:
6379
- npm i -g ${DAEMON_PKG}
6380
- agentchatd install --runtime ${runtime}`);
6381
- return 1;
6382
- }
6383
- const code = runDaemon(["install", "--runtime", runtime, "--home", home]);
6384
- if (code === 0) {
6385
- console.log(
6386
- [
6387
- "",
6388
- `Always-on is ON for @${creds.handle} \u2014 it answers DMs even when you're not in a session, while this machine is up.`,
6389
- `Want session-only instead? Turn it off any time: agentchat daemon disable --platform ${platform}`
6390
- ].join("\n")
6391
- );
6392
- }
6393
- return code;
6394
- }
6395
- if (sub === "enable" || sub === "disable" || sub === "status" || sub === "uninstall") {
6396
- if (!fs5.existsSync(daemonEntry())) {
6397
- if (sub === "status") {
6398
- console.log("Always-on: not installed (session-only). Turn it on with: agentchat daemon install");
6399
- return 0;
6400
- }
6401
- console.error(`Always-on isn't set up yet. Turn it on with: agentchat daemon install --platform ${platform}`);
6402
- return sub === "disable" ? 0 : 1;
6403
- }
6404
- return runDaemon([sub, "--runtime", runtime, "--home", home]);
6405
- }
6406
- console.error("Usage: agentchat daemon <install|enable|disable|status|uninstall> --platform <claude-code|codex>");
6407
- return 1;
6408
- }
6409
-
6410
6453
  // src/commands/identity.ts
6411
6454
  var HANDLE_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
6412
6455
  function describeApiError(err) {
@@ -7014,7 +7057,7 @@ import * as fs8 from "fs";
7014
7057
  import * as path9 from "path";
7015
7058
 
7016
7059
  // src/version.ts
7017
- var VERSION2 = "0.0.136";
7060
+ var VERSION2 = "0.0.137";
7018
7061
 
7019
7062
  // src/commands/doctor.ts
7020
7063
  function fmt(check) {