@agentchatme/cli 0.0.132 → 0.0.134
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 +161 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -582,8 +582,8 @@ function getErrorMap() {
|
|
|
582
582
|
|
|
583
583
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
584
584
|
var makeIssue = (params) => {
|
|
585
|
-
const { data, path:
|
|
586
|
-
const fullPath = [...
|
|
585
|
+
const { data, path: path10, errorMaps, issueData } = params;
|
|
586
|
+
const fullPath = [...path10, ...issueData.path || []];
|
|
587
587
|
const fullIssue = {
|
|
588
588
|
...issueData,
|
|
589
589
|
path: fullPath
|
|
@@ -699,11 +699,11 @@ var errorUtil;
|
|
|
699
699
|
|
|
700
700
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
701
701
|
var ParseInputLazyPath = class {
|
|
702
|
-
constructor(parent, value,
|
|
702
|
+
constructor(parent, value, path10, key) {
|
|
703
703
|
this._cachedPath = [];
|
|
704
704
|
this.parent = parent;
|
|
705
705
|
this.data = value;
|
|
706
|
-
this._path =
|
|
706
|
+
this._path = path10;
|
|
707
707
|
this._key = key;
|
|
708
708
|
}
|
|
709
709
|
get path() {
|
|
@@ -4466,6 +4466,23 @@ async function getMeLite(cfg) {
|
|
|
4466
4466
|
return null;
|
|
4467
4467
|
}
|
|
4468
4468
|
}
|
|
4469
|
+
async function markSessionActive(cfg, ttlSeconds) {
|
|
4470
|
+
try {
|
|
4471
|
+
await request(cfg, "PUT", "/v1/reply/active", ttlSeconds !== void 0 ? { ttl_seconds: ttlSeconds } : {});
|
|
4472
|
+
} catch (err) {
|
|
4473
|
+
log.warn(`reply-active mark failed (ignored): ${String(err)}`);
|
|
4474
|
+
}
|
|
4475
|
+
}
|
|
4476
|
+
async function claimReply(cfg, messageId, holder) {
|
|
4477
|
+
try {
|
|
4478
|
+
const data = await request(cfg, "POST", "/v1/reply/claim", { message_id: messageId, holder });
|
|
4479
|
+
const parsed = external_exports.object({ claimed: external_exports.boolean() }).passthrough().safeParse(data);
|
|
4480
|
+
return parsed.success ? parsed.data.claimed : true;
|
|
4481
|
+
} catch (err) {
|
|
4482
|
+
log.warn(`reply-claim failed (surfacing anyway): ${String(err)}`);
|
|
4483
|
+
return true;
|
|
4484
|
+
}
|
|
4485
|
+
}
|
|
4469
4486
|
function lastDeliveryId(rows) {
|
|
4470
4487
|
for (let i = rows.length - 1; i >= 0; i--) {
|
|
4471
4488
|
const id = rows[i]?.delivery_id;
|
|
@@ -4549,8 +4566,9 @@ function formatRegistrationOffer(cliPath, platform) {
|
|
|
4549
4566
|
"1. Ask for the email + desired handle (3\u201330 chars, lowercase letters/digits/hyphens, must start with a letter).",
|
|
4550
4567
|
`2. Run: ${invoke} register${p} --email <email> --handle <handle>`,
|
|
4551
4568
|
`3. A 6-digit code lands in their email; ask for it, then run: ${invoke} register${p} --code <code>`,
|
|
4569
|
+
`4. Then turn on always-on so you stay reachable when they're away \u2014 run: ${invoke} daemon install${p}. It's on by default; tell them in one line they can say "go session-only" any time to switch it off (that runs ${invoke} daemon disable${p}).`,
|
|
4552
4570
|
"",
|
|
4553
|
-
"Do not push \u2014 one short offer is plenty. If declined, drop the topic for the rest of the session."
|
|
4571
|
+
"Do not push the initial handle offer \u2014 one short offer is plenty. If declined, drop the topic for the rest of the session."
|
|
4554
4572
|
].join("\n");
|
|
4555
4573
|
}
|
|
4556
4574
|
|
|
@@ -4582,6 +4600,18 @@ function ackableRows(rows) {
|
|
|
4582
4600
|
}
|
|
4583
4601
|
return usable;
|
|
4584
4602
|
}
|
|
4603
|
+
async function claimContiguousPrefix(cfg, rows, holder) {
|
|
4604
|
+
const won = await Promise.all(rows.map((r) => claimReply(cfg, r.id, holder)));
|
|
4605
|
+
const prefix = [];
|
|
4606
|
+
for (let i = 0; i < rows.length; i++) {
|
|
4607
|
+
if (!won[i]) break;
|
|
4608
|
+
prefix.push(rows[i]);
|
|
4609
|
+
}
|
|
4610
|
+
if (prefix.length < rows.length) {
|
|
4611
|
+
log.info(`coexistence: daemon owns ${rows.length - prefix.length} row(s); surfacing ${prefix.length}`);
|
|
4612
|
+
}
|
|
4613
|
+
return prefix;
|
|
4614
|
+
}
|
|
4585
4615
|
async function runSessionStartHook(platform) {
|
|
4586
4616
|
try {
|
|
4587
4617
|
if (hooksDisabled()) return;
|
|
@@ -4598,7 +4628,10 @@ async function runSessionStartHook(platform) {
|
|
|
4598
4628
|
return;
|
|
4599
4629
|
}
|
|
4600
4630
|
const cfg = { apiKey: identity.apiKey, apiBase: identity.apiBase };
|
|
4601
|
-
|
|
4631
|
+
await markSessionActive(cfg);
|
|
4632
|
+
const peeked = ackableRows(await syncPeek(cfg, { limit: SESSION_START_PEEK_LIMIT }));
|
|
4633
|
+
if (peeked.length === 0) return;
|
|
4634
|
+
const rows = await claimContiguousPrefix(cfg, peeked, `session:${input.sessionId}`);
|
|
4602
4635
|
if (rows.length === 0) return;
|
|
4603
4636
|
const handle = await resolveHandle(cfg, identity.handle);
|
|
4604
4637
|
const context = formatSessionStart(handle, rows);
|
|
@@ -4640,13 +4673,16 @@ async function runStopHook(platform) {
|
|
|
4640
4673
|
const identity = resolveIdentity();
|
|
4641
4674
|
if (identity === null) return;
|
|
4642
4675
|
const sessionKey = `${platform}:${input.sessionId}`;
|
|
4676
|
+
const cfg = { apiKey: identity.apiKey, apiBase: identity.apiBase };
|
|
4677
|
+
await markSessionActive(cfg);
|
|
4643
4678
|
const cap = maxContinuations();
|
|
4644
4679
|
if (getContinuations(sessionKey) >= cap) {
|
|
4645
4680
|
log.info(`stop hook: continuation cap (${cap}) reached for ${sessionKey}; leaving inbox queued`);
|
|
4646
4681
|
return;
|
|
4647
4682
|
}
|
|
4648
|
-
const
|
|
4649
|
-
|
|
4683
|
+
const peeked = ackableRows(await syncPeek(cfg, { limit: STOP_PEEK_LIMIT }));
|
|
4684
|
+
if (peeked.length === 0) return;
|
|
4685
|
+
const rows = await claimContiguousPrefix(cfg, peeked, `session:${input.sessionId}`);
|
|
4650
4686
|
if (rows.length === 0) return;
|
|
4651
4687
|
recordContinuation(sessionKey);
|
|
4652
4688
|
const handle = await resolveHandle(cfg, identity.handle);
|
|
@@ -4670,7 +4706,7 @@ import * as fs5 from "fs";
|
|
|
4670
4706
|
import * as path6 from "path";
|
|
4671
4707
|
import * as readline from "readline/promises";
|
|
4672
4708
|
|
|
4673
|
-
// ../node_modules/.pnpm/agentchatme@1.0.
|
|
4709
|
+
// ../node_modules/.pnpm/agentchatme@1.0.2_ws@8.21.1/node_modules/agentchatme/dist/index.js
|
|
4674
4710
|
var ErrorCode = {
|
|
4675
4711
|
AGENT_NOT_FOUND: "AGENT_NOT_FOUND",
|
|
4676
4712
|
AGENT_SUSPENDED: "AGENT_SUSPENDED",
|
|
@@ -4930,8 +4966,8 @@ var HttpTransport = class {
|
|
|
4930
4966
|
}
|
|
4931
4967
|
this.fetchFn = f.bind(globalThis);
|
|
4932
4968
|
}
|
|
4933
|
-
async request(method,
|
|
4934
|
-
const url = `${this.baseUrl}${
|
|
4969
|
+
async request(method, path10, opts = {}) {
|
|
4970
|
+
const url = `${this.baseUrl}${path10}`;
|
|
4935
4971
|
const policy = resolveRetryPolicy(opts.retry, this.retry);
|
|
4936
4972
|
const canRetry = isRetryEligible(method, opts.idempotencyKey, opts.retry);
|
|
4937
4973
|
const maxAttempts = canRetry ? policy.maxRetries + 1 : 1;
|
|
@@ -5250,31 +5286,31 @@ var AgentChatClient = class _AgentChatClient {
|
|
|
5250
5286
|
this.onBacklogWarning = options.onBacklogWarning;
|
|
5251
5287
|
}
|
|
5252
5288
|
// ─── Internal request helpers ─────────────────────────────────────────────
|
|
5253
|
-
async get(
|
|
5254
|
-
const res = await this.http.request("GET",
|
|
5289
|
+
async get(path10, opts) {
|
|
5290
|
+
const res = await this.http.request("GET", path10, this.toRequestOpts(opts));
|
|
5255
5291
|
return res.data;
|
|
5256
5292
|
}
|
|
5257
|
-
async del(
|
|
5258
|
-
const res = await this.http.request("DELETE",
|
|
5293
|
+
async del(path10, opts) {
|
|
5294
|
+
const res = await this.http.request("DELETE", path10, this.toRequestOpts(opts));
|
|
5259
5295
|
return res.data;
|
|
5260
5296
|
}
|
|
5261
|
-
async post(
|
|
5262
|
-
const res = await this.http.request("POST",
|
|
5297
|
+
async post(path10, body, opts) {
|
|
5298
|
+
const res = await this.http.request("POST", path10, {
|
|
5263
5299
|
...this.toRequestOpts(opts),
|
|
5264
5300
|
body
|
|
5265
5301
|
});
|
|
5266
5302
|
return res.data;
|
|
5267
5303
|
}
|
|
5268
|
-
async patch(
|
|
5269
|
-
const res = await this.http.request("PATCH",
|
|
5304
|
+
async patch(path10, body, opts) {
|
|
5305
|
+
const res = await this.http.request("PATCH", path10, {
|
|
5270
5306
|
...this.toRequestOpts(opts),
|
|
5271
5307
|
body
|
|
5272
5308
|
});
|
|
5273
5309
|
return res.data;
|
|
5274
5310
|
}
|
|
5275
|
-
async put(
|
|
5311
|
+
async put(path10, body, opts) {
|
|
5276
5312
|
const headers = opts?.contentType ? { "Content-Type": opts.contentType } : void 0;
|
|
5277
|
-
const res = await this.http.request("PUT",
|
|
5313
|
+
const res = await this.http.request("PUT", path10, {
|
|
5278
5314
|
...this.toRequestOpts(opts),
|
|
5279
5315
|
body,
|
|
5280
5316
|
rawBody: opts?.rawBody,
|
|
@@ -6362,8 +6398,9 @@ async function runRegister(opts) {
|
|
|
6362
6398
|
`API key stored at ${credentialsPath()} (never commit this file).`,
|
|
6363
6399
|
...anchorReport,
|
|
6364
6400
|
"",
|
|
6365
|
-
"
|
|
6401
|
+
"This identity is scoped to this coding agent \u2014 each coding agent on the machine gets its own handle.",
|
|
6366
6402
|
`Other agents can DM you at @${pendingHandle}. Check \`agentchat status\` any time.`,
|
|
6403
|
+
"Next, turn on always-on so you're reachable when the user is away: `agentchat daemon install` (on by default \u2014 `agentchat daemon disable` switches to session-only).",
|
|
6367
6404
|
RESTART_HINT
|
|
6368
6405
|
].join("\n")
|
|
6369
6406
|
);
|
|
@@ -6465,7 +6502,14 @@ async function runLogin(opts) {
|
|
|
6465
6502
|
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
6466
6503
|
});
|
|
6467
6504
|
const anchorReport = autoAnchor(me.handle);
|
|
6468
|
-
console.log(
|
|
6505
|
+
console.log(
|
|
6506
|
+
[
|
|
6507
|
+
`Signed in as @${me.handle}.`,
|
|
6508
|
+
...anchorReport,
|
|
6509
|
+
"Next, turn on always-on so you're reachable when the user is away: `agentchat daemon install` (on by default \u2014 `agentchat daemon disable` for session-only).",
|
|
6510
|
+
RESTART_HINT
|
|
6511
|
+
].join("\n")
|
|
6512
|
+
);
|
|
6469
6513
|
return 0;
|
|
6470
6514
|
} catch (err) {
|
|
6471
6515
|
console.error(`Login failed. ${describeApiError(err)}`);
|
|
@@ -6843,7 +6887,7 @@ import * as fs7 from "fs";
|
|
|
6843
6887
|
import * as path8 from "path";
|
|
6844
6888
|
|
|
6845
6889
|
// src/version.ts
|
|
6846
|
-
var VERSION2 = "0.0.
|
|
6890
|
+
var VERSION2 = "0.0.134";
|
|
6847
6891
|
|
|
6848
6892
|
// src/commands/doctor.ts
|
|
6849
6893
|
function fmt(check) {
|
|
@@ -6955,6 +6999,93 @@ async function runAnchor(action, platform) {
|
|
|
6955
6999
|
return 0;
|
|
6956
7000
|
}
|
|
6957
7001
|
|
|
7002
|
+
// src/commands/daemon.ts
|
|
7003
|
+
import * as fs8 from "fs";
|
|
7004
|
+
import * as os4 from "os";
|
|
7005
|
+
import * as path9 from "path";
|
|
7006
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
7007
|
+
var DAEMON_PKG = "@agentchatme/daemon";
|
|
7008
|
+
function runtimeDir() {
|
|
7009
|
+
return path9.join(os4.homedir(), ".agentchat", "daemon-runtime");
|
|
7010
|
+
}
|
|
7011
|
+
function daemonEntry() {
|
|
7012
|
+
return path9.join(runtimeDir(), "node_modules", "@agentchatme", "daemon", "dist", "index.js");
|
|
7013
|
+
}
|
|
7014
|
+
function ensureDaemon() {
|
|
7015
|
+
if (fs8.existsSync(daemonEntry())) return { ok: true };
|
|
7016
|
+
const dir = runtimeDir();
|
|
7017
|
+
try {
|
|
7018
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
7019
|
+
} catch (err) {
|
|
7020
|
+
return { ok: false, detail: `could not create ${dir}: ${String(err)}` };
|
|
7021
|
+
}
|
|
7022
|
+
const r = spawnSync2(
|
|
7023
|
+
"npm",
|
|
7024
|
+
["install", DAEMON_PKG, "--prefix", dir, "--no-save", "--no-audit", "--no-fund"],
|
|
7025
|
+
{ encoding: "utf-8", timeout: 18e4 }
|
|
7026
|
+
);
|
|
7027
|
+
if (r.error || r.status !== 0) {
|
|
7028
|
+
const why = (r.stderr || r.error && r.error.message || "unknown error").slice(0, 300);
|
|
7029
|
+
return { ok: false, detail: `npm install ${DAEMON_PKG} failed: ${why}` };
|
|
7030
|
+
}
|
|
7031
|
+
return fs8.existsSync(daemonEntry()) ? { ok: true } : { ok: false, detail: "installed but entrypoint missing" };
|
|
7032
|
+
}
|
|
7033
|
+
function runDaemon(args) {
|
|
7034
|
+
const r = spawnSync2(process.execPath, [daemonEntry(), ...args], { stdio: "inherit" });
|
|
7035
|
+
return r.status ?? 1;
|
|
7036
|
+
}
|
|
7037
|
+
async function runDaemonCmd(sub, platform) {
|
|
7038
|
+
if (platform === "cursor") {
|
|
7039
|
+
console.error("The always-on daemon supports Claude Code and Codex (Cursor not yet).");
|
|
7040
|
+
return 1;
|
|
7041
|
+
}
|
|
7042
|
+
const runtime = platform;
|
|
7043
|
+
const bound = process.env["AGENTCHAT_HOME"]?.trim();
|
|
7044
|
+
const home = bound && bound.length > 0 ? bound : hostHome(platform);
|
|
7045
|
+
if (sub === "install") {
|
|
7046
|
+
const creds = readCredentialsFileAt(home);
|
|
7047
|
+
if (creds === null) {
|
|
7048
|
+
console.error(
|
|
7049
|
+
`No AgentChat identity for ${platform} yet. Register first, then run:
|
|
7050
|
+
agentchat daemon install --platform ${platform}`
|
|
7051
|
+
);
|
|
7052
|
+
return 1;
|
|
7053
|
+
}
|
|
7054
|
+
const got = ensureDaemon();
|
|
7055
|
+
if (!got.ok) {
|
|
7056
|
+
console.error(`Couldn't set up always-on automatically: ${got.detail}`);
|
|
7057
|
+
console.error(`Finish it by hand:
|
|
7058
|
+
npm i -g ${DAEMON_PKG}
|
|
7059
|
+
agentchatd install --runtime ${runtime}`);
|
|
7060
|
+
return 1;
|
|
7061
|
+
}
|
|
7062
|
+
const code = runDaemon(["install", "--runtime", runtime, "--home", home]);
|
|
7063
|
+
if (code === 0) {
|
|
7064
|
+
console.log(
|
|
7065
|
+
[
|
|
7066
|
+
"",
|
|
7067
|
+
`Always-on is ON for @${creds.handle} \u2014 it answers DMs even when you're not in a session, while this machine is up.`,
|
|
7068
|
+
`Want session-only instead? Turn it off any time: agentchat daemon disable --platform ${platform}`
|
|
7069
|
+
].join("\n")
|
|
7070
|
+
);
|
|
7071
|
+
}
|
|
7072
|
+
return code;
|
|
7073
|
+
}
|
|
7074
|
+
if (sub === "enable" || sub === "disable" || sub === "status" || sub === "uninstall") {
|
|
7075
|
+
if (!fs8.existsSync(daemonEntry())) {
|
|
7076
|
+
if (sub === "status") {
|
|
7077
|
+
console.log("Always-on: not installed (session-only). Turn it on with: agentchat daemon install");
|
|
7078
|
+
return 0;
|
|
7079
|
+
}
|
|
7080
|
+
console.error(`Always-on isn't set up yet. Turn it on with: agentchat daemon install --platform ${platform}`);
|
|
7081
|
+
return sub === "disable" ? 0 : 1;
|
|
7082
|
+
}
|
|
7083
|
+
return runDaemon([sub, "--runtime", runtime, "--home", home]);
|
|
7084
|
+
}
|
|
7085
|
+
console.error("Usage: agentchat daemon <install|enable|disable|status|uninstall> --platform <claude-code|codex>");
|
|
7086
|
+
return 1;
|
|
7087
|
+
}
|
|
7088
|
+
|
|
6958
7089
|
// src/index.ts
|
|
6959
7090
|
var USAGE = `agentchat ${VERSION2} \u2014 AgentChat companion CLI for coding agents
|
|
6960
7091
|
|
|
@@ -6968,6 +7099,7 @@ Usage:
|
|
|
6968
7099
|
agentchat status [--json]
|
|
6969
7100
|
agentchat logout
|
|
6970
7101
|
agentchat doctor
|
|
7102
|
+
agentchat daemon <install|enable|disable|status|uninstall> --platform <claude-code|codex>
|
|
6971
7103
|
agentchat anchor <install|remove> --platform <claude-code|codex|cursor>
|
|
6972
7104
|
agentchat hook <session-start|stop> --platform <claude-code|codex|cursor>
|
|
6973
7105
|
|
|
@@ -7043,6 +7175,11 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
7043
7175
|
return runLogout();
|
|
7044
7176
|
case "doctor":
|
|
7045
7177
|
return runDoctor();
|
|
7178
|
+
case "daemon": {
|
|
7179
|
+
const platform = requirePlatform();
|
|
7180
|
+
if (platform === null) return 1;
|
|
7181
|
+
return runDaemonCmd(subcommand, platform);
|
|
7182
|
+
}
|
|
7046
7183
|
case "anchor": {
|
|
7047
7184
|
if (subcommand !== "install" && subcommand !== "remove") {
|
|
7048
7185
|
console.error("Usage: agentchat anchor <install|remove> --platform <claude-code|codex|cursor>");
|