@agentchatme/agent-core 0.0.13 → 0.0.131
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/daemon-entry.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -216,6 +216,55 @@ declare function offerDeclined(home: string): boolean;
|
|
|
216
216
|
/** Cleared when an identity is established, so a later logout asks again. */
|
|
217
217
|
declare function clearOfferDeclined(home: string): void;
|
|
218
218
|
|
|
219
|
+
declare const HEARTBEAT_FILE = "daemon.heartbeat";
|
|
220
|
+
/** Record that the user wants always-on for this agent.
|
|
221
|
+
*
|
|
222
|
+
* The file's MTIME is load-bearing: `alwaysOnState` uses it as the moment
|
|
223
|
+
* registration happened, so a service that was just installed is not reported
|
|
224
|
+
* as broken before its daemon has had time to draw breath. */
|
|
225
|
+
declare function markAlwaysOnWanted(home: string): void;
|
|
226
|
+
/** Forget the intent (user chose session-only, or uninstalled). */
|
|
227
|
+
declare function clearAlwaysOnWanted(home: string): void;
|
|
228
|
+
declare function alwaysOnWanted(home: string): boolean;
|
|
229
|
+
/** Remember that the user switched always-on off. Survives re-install. */
|
|
230
|
+
declare function markAlwaysOnOptOut(home: string): void;
|
|
231
|
+
/** Cleared only by an explicit `daemon install` — never implicitly. */
|
|
232
|
+
declare function clearAlwaysOnOptOut(home: string): void;
|
|
233
|
+
declare function alwaysOnOptedOut(home: string): boolean;
|
|
234
|
+
/** Touch the liveness beacon. Called by the running daemon. */
|
|
235
|
+
declare function beat(home: string): void;
|
|
236
|
+
/** Clear the beacon. The daemon calls this whenever it is resident but NOT
|
|
237
|
+
* connected, so "idle" is never mistaken for "beating". */
|
|
238
|
+
declare function idle(home: string): void;
|
|
239
|
+
/**
|
|
240
|
+
* Always-on has THREE states, not two.
|
|
241
|
+
*
|
|
242
|
+
* It used to be a boolean pair, which could not tell "idle because nobody is
|
|
243
|
+
* signed in" apart from "installed and broken" — so a signed-out user would be
|
|
244
|
+
* nagged every session about a daemon that was behaving exactly as intended.
|
|
245
|
+
*
|
|
246
|
+
* off — the service is not installed (or was explicitly disabled).
|
|
247
|
+
* idle — installed and resident, but there is no identity to serve.
|
|
248
|
+
* Correct and quiet: the daemon is waiting for a sign-in.
|
|
249
|
+
* starting — registered moments ago and not beating yet. Also quiet: the
|
|
250
|
+
* service manager has not finished bringing it up.
|
|
251
|
+
* connected — holding the wire; the beacon is fresh.
|
|
252
|
+
* down — there IS an identity and the service is installed, but nothing
|
|
253
|
+
* is beating. The only state worth telling a session about.
|
|
254
|
+
*
|
|
255
|
+
* Pure reads, no subprocess, never throws.
|
|
256
|
+
*/
|
|
257
|
+
type AlwaysOnState = 'off' | 'idle' | 'starting' | 'connected' | 'down';
|
|
258
|
+
declare function alwaysOnState(home: string): AlwaysOnState;
|
|
259
|
+
/**
|
|
260
|
+
* Back-compatible view for callers that only need "should I warn?".
|
|
261
|
+
* `healthy` is false ONLY in the `down` state — an idle daemon is healthy.
|
|
262
|
+
*/
|
|
263
|
+
declare function alwaysOnHealth(home: string): {
|
|
264
|
+
wanted: boolean;
|
|
265
|
+
healthy: boolean;
|
|
266
|
+
};
|
|
267
|
+
|
|
219
268
|
declare function formatSessionStart(handle: string | null, rows: SyncRow[]): string;
|
|
220
269
|
declare function formatStopPickup(handle: string | null, rows: SyncRow[]): string;
|
|
221
270
|
/**
|
|
@@ -242,7 +291,24 @@ interface HostCopy {
|
|
|
242
291
|
/** Human label for the host, e.g. `Codex` or `Claude Code`. */
|
|
243
292
|
label: string;
|
|
244
293
|
}
|
|
245
|
-
|
|
294
|
+
/**
|
|
295
|
+
* What a session is told when the integration is installed but has no identity.
|
|
296
|
+
*
|
|
297
|
+
* Two things this must NOT do, both learned from the first real install:
|
|
298
|
+
*
|
|
299
|
+
* • It must not read like a runbook. The earlier version was a numbered list
|
|
300
|
+
* of CLI invocations, and agents did the natural thing with a numbered list
|
|
301
|
+
* of CLI invocations: they pasted it at the user. Someone who just installed
|
|
302
|
+
* a plugin got a wall of `--email`/`--code` syntax instead of "want a handle
|
|
303
|
+
* other agents can message you at?". The commands are the AGENT'S to run;
|
|
304
|
+
* that has to be said outright, because the format alone implies otherwise.
|
|
305
|
+
*
|
|
306
|
+
* • It must not assert always-on is running. That line used to be
|
|
307
|
+
* unconditional, so a session whose registration had just FAILED was told
|
|
308
|
+
* always-on was already up — the one moment the user needed to know it was
|
|
309
|
+
* not.
|
|
310
|
+
*/
|
|
311
|
+
declare function formatRegistrationOffer(copy: HostCopy, alwaysOn?: AlwaysOnState): string;
|
|
246
312
|
/**
|
|
247
313
|
* "You have AgentChat but no handle — offer to set one up."
|
|
248
314
|
*
|
|
@@ -458,49 +524,6 @@ declare function renderManual(copy: ManualCopy, opts?: {
|
|
|
458
524
|
frontMatter?: boolean;
|
|
459
525
|
}): string;
|
|
460
526
|
|
|
461
|
-
declare const HEARTBEAT_FILE = "daemon.heartbeat";
|
|
462
|
-
/** Record that the user wants always-on for this agent. */
|
|
463
|
-
declare function markAlwaysOnWanted(home: string): void;
|
|
464
|
-
/** Forget the intent (user chose session-only, or uninstalled). */
|
|
465
|
-
declare function clearAlwaysOnWanted(home: string): void;
|
|
466
|
-
declare function alwaysOnWanted(home: string): boolean;
|
|
467
|
-
/** Remember that the user switched always-on off. Survives re-install. */
|
|
468
|
-
declare function markAlwaysOnOptOut(home: string): void;
|
|
469
|
-
/** Cleared only by an explicit `daemon install` — never implicitly. */
|
|
470
|
-
declare function clearAlwaysOnOptOut(home: string): void;
|
|
471
|
-
declare function alwaysOnOptedOut(home: string): boolean;
|
|
472
|
-
/** Touch the liveness beacon. Called by the running daemon. */
|
|
473
|
-
declare function beat(home: string): void;
|
|
474
|
-
/** Clear the beacon. The daemon calls this whenever it is resident but NOT
|
|
475
|
-
* connected, so "idle" is never mistaken for "beating". */
|
|
476
|
-
declare function idle(home: string): void;
|
|
477
|
-
/**
|
|
478
|
-
* Always-on has THREE states, not two.
|
|
479
|
-
*
|
|
480
|
-
* It used to be a boolean pair, which could not tell "idle because nobody is
|
|
481
|
-
* signed in" apart from "installed and broken" — so a signed-out user would be
|
|
482
|
-
* nagged every session about a daemon that was behaving exactly as intended.
|
|
483
|
-
*
|
|
484
|
-
* off — the service is not installed (or was explicitly disabled).
|
|
485
|
-
* idle — installed and resident, but there is no identity to serve.
|
|
486
|
-
* Correct and quiet: the daemon is waiting for a sign-in.
|
|
487
|
-
* connected — holding the wire; the beacon is fresh.
|
|
488
|
-
* down — there IS an identity and the service is installed, but nothing
|
|
489
|
-
* is beating. The only state worth telling a session about.
|
|
490
|
-
*
|
|
491
|
-
* Pure reads, no subprocess, never throws.
|
|
492
|
-
*/
|
|
493
|
-
type AlwaysOnState = 'off' | 'idle' | 'connected' | 'down';
|
|
494
|
-
declare function alwaysOnState(home: string): AlwaysOnState;
|
|
495
|
-
/**
|
|
496
|
-
* Back-compatible view for callers that only need "should I warn?".
|
|
497
|
-
* `healthy` is false ONLY in the `down` state — an idle daemon is healthy.
|
|
498
|
-
*/
|
|
499
|
-
declare function alwaysOnHealth(home: string): {
|
|
500
|
-
wanted: boolean;
|
|
501
|
-
healthy: boolean;
|
|
502
|
-
};
|
|
503
|
-
|
|
504
527
|
interface LockHandle {
|
|
505
528
|
release(): void;
|
|
506
529
|
}
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
syncPeek,
|
|
36
36
|
writeCredentials,
|
|
37
37
|
writePending
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-XLRPNQ7G.js";
|
|
39
39
|
|
|
40
40
|
// src/identity/state.ts
|
|
41
41
|
var SESSION_TTL_MS = 48 * 60 * 60 * 1e3;
|
|
@@ -359,29 +359,45 @@ function formatStopPickup(handle, rows) {
|
|
|
359
359
|
function formatAlwaysOnDown(copy) {
|
|
360
360
|
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: \`${copy.invoke} daemon install\``;
|
|
361
361
|
}
|
|
362
|
-
function formatRegistrationOffer(copy) {
|
|
362
|
+
function formatRegistrationOffer(copy, alwaysOn = "off") {
|
|
363
363
|
const { invoke, label } = copy;
|
|
364
364
|
return [
|
|
365
|
-
`
|
|
365
|
+
`This ${label} agent is on AgentChat but has no handle yet \u2014 no address other agents can reach it at.`,
|
|
366
366
|
"",
|
|
367
|
-
"
|
|
368
|
-
|
|
367
|
+
"If the moment is right, offer it in ONE plain sentence and let them answer. Do not paste this block,",
|
|
368
|
+
"do not list the commands, do not walk them through steps. You run the commands; they just talk to you.",
|
|
369
369
|
"",
|
|
370
|
-
"
|
|
371
|
-
"
|
|
372
|
-
|
|
373
|
-
`
|
|
374
|
-
"",
|
|
375
|
-
"ALREADY have an AgentChat agent \u2014 sign in, do NOT register a second one:",
|
|
376
|
-
` \u2022 They have its API key (ac_\u2026): ${invoke} login --api-key <ac_\u2026>`,
|
|
377
|
-
` \u2022 They lost the key: ${invoke} recover --email <email>, then relay the emailed 6-digit code: ${invoke} recover --code <code>`,
|
|
370
|
+
"All you need from them is an email and a handle they like (3\u201330 characters, lowercase letters, digits",
|
|
371
|
+
"and hyphens, starting with a letter). Ask first whether they already have an AgentChat account \u2014 from",
|
|
372
|
+
"another machine, or a Hermes or OpenClaw agent \u2014 so you sign that one in instead of creating a second.",
|
|
373
|
+
`Either way this ${label} agent ends up with its own handle, separate from any other coding agent here,`,
|
|
374
|
+
"which is what lets them message each other.",
|
|
378
375
|
"",
|
|
376
|
+
"Commands \u2014 yours to run, not to show:",
|
|
377
|
+
` new account ${invoke} register --email <email> --handle <handle>`,
|
|
378
|
+
` then, with the 6-digit code they were emailed: ${invoke} register --code <code>`,
|
|
379
|
+
` has an API key ${invoke} login --api-key <ac_\u2026>`,
|
|
380
|
+
` lost the key ${invoke} recover --email <email>, then ${invoke} recover --code <code>`,
|
|
379
381
|
"",
|
|
380
|
-
|
|
382
|
+
alwaysOnNote(alwaysOn, invoke),
|
|
381
383
|
"",
|
|
382
|
-
|
|
384
|
+
`One ask is plenty. If they decline or change the subject, drop it \u2014 and \`${invoke} register --not-now\``,
|
|
385
|
+
"stops it being raised in future sessions too."
|
|
383
386
|
].join("\n");
|
|
384
387
|
}
|
|
388
|
+
function alwaysOnNote(state, invoke) {
|
|
389
|
+
switch (state) {
|
|
390
|
+
case "connected":
|
|
391
|
+
return "Always-on is running: this agent answers DMs even with no session open. Nothing to switch on.";
|
|
392
|
+
case "idle":
|
|
393
|
+
case "starting":
|
|
394
|
+
return "Always-on is set up and will start answering DMs on its own as soon as there is a handle. Nothing to switch on.";
|
|
395
|
+
case "off":
|
|
396
|
+
return "Always-on is not set up here, so DMs are only seen during a session.";
|
|
397
|
+
case "down":
|
|
398
|
+
return `Always-on is registered but not running \u2014 \`${invoke} daemon status\` says why. DMs are only seen during a session until it recovers.`;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
385
401
|
function renderUnregisteredBlock(copy) {
|
|
386
402
|
const { invoke, label } = copy;
|
|
387
403
|
return [
|
|
@@ -469,7 +485,7 @@ async function sessionStart(ctx, input) {
|
|
|
469
485
|
if (identity === null) {
|
|
470
486
|
if (shouldOfferRegistration(ctx.home)) {
|
|
471
487
|
recordRegistrationOffer(ctx.home);
|
|
472
|
-
return { context: formatRegistrationOffer(ctx.copy) };
|
|
488
|
+
return { context: formatRegistrationOffer(ctx.copy, alwaysOnState(ctx.home)) };
|
|
473
489
|
}
|
|
474
490
|
return none;
|
|
475
491
|
}
|