@leemour/cli-messaging 0.39.0 → 0.41.0

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 (92) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/index.d.ts +3 -2
  3. package/dist/cli/index.d.ts.map +1 -1
  4. package/dist/cli/index.js +2 -1
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/cli/messenger/after.d.ts +5 -0
  7. package/dist/cli/messenger/after.d.ts.map +1 -0
  8. package/dist/cli/messenger/after.js +10 -0
  9. package/dist/cli/messenger/after.js.map +1 -0
  10. package/dist/cli/messenger/backfill-jobs.d.ts +1 -5
  11. package/dist/cli/messenger/backfill-jobs.d.ts.map +1 -1
  12. package/dist/cli/messenger/backfill-jobs.js +4 -27
  13. package/dist/cli/messenger/backfill-jobs.js.map +1 -1
  14. package/dist/cli/messenger/chats-command.d.ts +32 -0
  15. package/dist/cli/messenger/chats-command.d.ts.map +1 -1
  16. package/dist/cli/messenger/chats-command.js +90 -4
  17. package/dist/cli/messenger/chats-command.js.map +1 -1
  18. package/dist/cli/messenger/context.d.ts +2 -0
  19. package/dist/cli/messenger/context.d.ts.map +1 -1
  20. package/dist/cli/messenger/context.js.map +1 -1
  21. package/dist/cli/messenger/messages-command.d.ts +1 -1
  22. package/dist/cli/messenger/messages-command.d.ts.map +1 -1
  23. package/dist/cli/messenger/messages-command.js +16 -6
  24. package/dist/cli/messenger/messages-command.js.map +1 -1
  25. package/dist/cli/messenger/models-command.d.ts +9 -0
  26. package/dist/cli/messenger/models-command.d.ts.map +1 -0
  27. package/dist/cli/messenger/models-command.js +69 -0
  28. package/dist/cli/messenger/models-command.js.map +1 -0
  29. package/dist/cli/messenger/port.d.ts +16 -1
  30. package/dist/cli/messenger/port.d.ts.map +1 -1
  31. package/dist/cli/messenger/port.js.map +1 -1
  32. package/dist/cli/messenger/processes.d.ts +9 -0
  33. package/dist/cli/messenger/processes.d.ts.map +1 -0
  34. package/dist/cli/messenger/processes.js +37 -0
  35. package/dist/cli/messenger/processes.js.map +1 -0
  36. package/dist/cli/messenger/serve-command.d.ts +4 -5
  37. package/dist/cli/messenger/serve-command.d.ts.map +1 -1
  38. package/dist/cli/messenger/serve-command.js +14 -22
  39. package/dist/cli/messenger/serve-command.js.map +1 -1
  40. package/dist/cli/messenger/server-command.d.ts +27 -0
  41. package/dist/cli/messenger/server-command.d.ts.map +1 -0
  42. package/dist/cli/messenger/server-command.js +453 -0
  43. package/dist/cli/messenger/server-command.js.map +1 -0
  44. package/dist/cli/messenger/transcribe-command.d.ts +1 -1
  45. package/dist/cli/messenger/transcribe-command.d.ts.map +1 -1
  46. package/dist/cli/messenger/transcribe-command.js +16 -7
  47. package/dist/cli/messenger/transcribe-command.js.map +1 -1
  48. package/dist/cli/messenger/watch-command.d.ts +2 -1
  49. package/dist/cli/messenger/watch-command.d.ts.map +1 -1
  50. package/dist/cli/messenger/watch-command.js +2 -2
  51. package/dist/cli/messenger/watch-command.js.map +1 -1
  52. package/dist/cli/settings.d.ts +4 -0
  53. package/dist/cli/settings.d.ts.map +1 -1
  54. package/dist/cli/settings.js +2 -0
  55. package/dist/cli/settings.js.map +1 -1
  56. package/dist/domain/models.d.ts +26 -0
  57. package/dist/domain/models.d.ts.map +1 -1
  58. package/dist/mcp/server.js +1 -1
  59. package/dist/mcp/server.js.map +1 -1
  60. package/dist/mcp/tool.d.ts +4 -0
  61. package/dist/mcp/tool.d.ts.map +1 -1
  62. package/dist/mcp/tool.js.map +1 -1
  63. package/dist/mcp/tools/chats.d.ts.map +1 -1
  64. package/dist/mcp/tools/chats.js +30 -5
  65. package/dist/mcp/tools/chats.js.map +1 -1
  66. package/dist/mcp/tools/messages-transcribe.d.ts.map +1 -1
  67. package/dist/mcp/tools/messages-transcribe.js +15 -8
  68. package/dist/mcp/tools/messages-transcribe.js.map +1 -1
  69. package/dist/mcp/tools/messages.d.ts.map +1 -1
  70. package/dist/mcp/tools/messages.js +15 -5
  71. package/dist/mcp/tools/messages.js.map +1 -1
  72. package/dist/speech/install.d.ts +23 -0
  73. package/dist/speech/install.d.ts.map +1 -0
  74. package/dist/speech/install.js +106 -0
  75. package/dist/speech/install.js.map +1 -0
  76. package/dist/speech/models.d.ts +38 -0
  77. package/dist/speech/models.d.ts.map +1 -0
  78. package/dist/speech/models.js +130 -0
  79. package/dist/speech/models.js.map +1 -0
  80. package/dist/speech/recognize.d.ts +24 -0
  81. package/dist/speech/recognize.d.ts.map +1 -0
  82. package/dist/speech/recognize.js +106 -0
  83. package/dist/speech/recognize.js.map +1 -0
  84. package/dist/speech/transcribe.d.ts +36 -0
  85. package/dist/speech/transcribe.d.ts.map +1 -0
  86. package/dist/speech/transcribe.js +80 -0
  87. package/dist/speech/transcribe.js.map +1 -0
  88. package/package.json +3 -1
  89. package/dist/cli/messenger/service-command.d.ts +0 -21
  90. package/dist/cli/messenger/service-command.d.ts.map +0 -1
  91. package/dist/cli/messenger/service-command.js +0 -305
  92. package/dist/cli/messenger/service-command.js.map +0 -1
@@ -0,0 +1,69 @@
1
+ import { Command } from "commander";
2
+ import { install, installedBytes, isInstalled, megabytes, modelPath, modelsDirectory, vadPath, } from "../../speech/install.js";
3
+ import { orderedModels, speechModel, VAD } from "../../speech/models.js";
4
+ import { choose } from "../../speech/transcribe.js";
5
+ import { baseContext } from "../context.js";
6
+ /**
7
+ * Models that run on this machine, by what they work on; `audio` is the speech models behind
8
+ * `messages transcribe --local`. Nothing here talks to the messenger. The folder is shared by every
9
+ * messenger CLI, so a model downloaded once serves them all.
10
+ */
11
+ export const modelsCommand = (messenger) => {
12
+ const models = new Command("models").description("models that run on this machine");
13
+ const audio = models.command("audio").description("speech models for transcribing voice messages");
14
+ audio
15
+ .command("list")
16
+ .description("the speech models, most suitable first, which are downloaded, and which one is the default")
17
+ .action(async function () {
18
+ const context = baseContext(this, messenger.resolveSettings);
19
+ await context.run(async () => {
20
+ const directory = modelsDirectory(context.env);
21
+ const chosen = choose(messenger, context.settings, {}, context.env).model.id;
22
+ const items = orderedModels(messenger.speechModels).map((model) => ({
23
+ id: model.id,
24
+ title: model.title,
25
+ languages: model.languages,
26
+ size: megabytes(installedBytes(model)),
27
+ downloaded: isInstalled(model, directory),
28
+ default: model.id === chosen,
29
+ }));
30
+ if (context.format === "pretty") {
31
+ const line = (item) => `${item.default ? "*" : " "} ${item.id.padEnd(14)} ${item.size.padStart(7)} ${item.downloaded ? "downloaded" : "—".padEnd(10)} ${item.languages}`;
32
+ context.streams.data(`${items.map(line).join("\n")}\n`);
33
+ }
34
+ else if (context.format === "jsonl")
35
+ context.renderer.stream(items);
36
+ else
37
+ context.renderer.result({ items, directory });
38
+ });
39
+ });
40
+ audio
41
+ .command("download")
42
+ .argument("<model>", "a model id from `models audio list`")
43
+ .description("download a speech model once, checked against the sha256 this version expects")
44
+ .action(async function (id) {
45
+ const context = baseContext(this, messenger.resolveSettings);
46
+ await context.run(async () => {
47
+ const model = speechModel(id);
48
+ const directory = modelsDirectory(context.env);
49
+ if (!isInstalled(model, directory)) {
50
+ context.renderer.note(`${model.id}: ${megabytes(installedBytes(model) + VAD.bytes)} from Hugging Face and GitHub`);
51
+ await install(model, directory, { progress: (line) => context.renderer.note(line) });
52
+ }
53
+ // Loading is the test — the files, the WebAssembly engine and the memory it needs — on a
54
+ // second of silence, since no recording ships with the package.
55
+ context.renderer.note(`${model.id}: loading it once to check it works`);
56
+ const { openRecognizer, SAMPLE_RATE } = await import("../../speech/recognize.js");
57
+ const recognizer = openRecognizer(model, modelPath(directory, model), vadPath(directory));
58
+ try {
59
+ recognizer.recognize(new Float32Array(SAMPLE_RATE));
60
+ }
61
+ finally {
62
+ recognizer.free();
63
+ }
64
+ context.renderer.result({ id: model.id, downloaded: true, works: true, directory });
65
+ }, { unbounded: true });
66
+ });
67
+ return models;
68
+ };
69
+ //# sourceMappingURL=models-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models-command.js","sourceRoot":"","sources":["../../../src/cli/messenger/models-command.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { Markup } from "../../domain/markdown.js";
2
- import type { Account, Chat, ChatCard, Id, Message, MessageEvent, Page, PersonCard, WindowedMessage } from "../../domain/models.js";
2
+ import type { Account, Chat, ChatCard, ChatEvents, Id, Message, MessageEvent, Page, PersonCard, WindowedMessage } from "../../domain/models.js";
3
3
  /** One attachment's bytes, fetched over the adapter's connection when `bytes` is read — so read it before the command closes. */
4
4
  export interface RemoteFile {
5
5
  kind: string;
@@ -30,6 +30,12 @@ export interface Transcript {
30
30
  text: string;
31
31
  pending: boolean;
32
32
  }
33
+ /** A message id — exact within one chat — or a moment in ms, which works in every chat. */
34
+ export type After = {
35
+ id: Id;
36
+ } | {
37
+ time: number;
38
+ };
33
39
  export interface Sent {
34
40
  message: Message;
35
41
  /** The send's identity. Repeat it after an unknown outcome, never a new one. */
@@ -58,6 +64,11 @@ export interface MessengerAdapter {
58
64
  limit: number;
59
65
  before?: string;
60
66
  }): Promise<Page<Message>>;
67
+ /** The oldest `limit` newer than a message or a moment, oldest first; `hasMore` when newer ones remain. */
68
+ historyAfter?(chat: string, window: {
69
+ limit: number;
70
+ after: After;
71
+ }): Promise<Page<Message>>;
61
72
  resolve(chat: string): Promise<Chat>;
62
73
  /** One chat and who is in it; `members` is `null` where the messenger does not say — a channel, a hidden list. */
63
74
  chat(chat: string): Promise<ChatCard>;
@@ -86,6 +97,10 @@ export interface MessengerAdapter {
86
97
  download?(chat: string, messageId: Id): Promise<Download>;
87
98
  /** A voice or video note as text, by the messenger's own speech recognition. */
88
99
  transcribe?(chat: string, messageId: Id): Promise<Transcript>;
100
+ /** Who joined, left, was added or removed since `since` (ms), from the chat's service messages. */
101
+ chatEvents?(chat: string, window: {
102
+ since: number;
103
+ }): Promise<ChatEvents>;
89
104
  /** A group's admins, whose answer counts as the group's in `review --unanswered`; `null` where the group hides them. */
90
105
  admins?(chat: string): Promise<Id[] | null>;
91
106
  logout(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../../src/cli/messenger/port.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../../src/cli/messenger/port.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"port.js","sourceRoot":"","sources":["../../../src/cli/messenger/port.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAsG5C;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,KAAuB,EACvB,OAAyB,EACzB,IAAI,GAA6E,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAChF,EAAE,CACpB,IAAI,KAAK,CAAC,OAAO,EAAE;IACjB,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAChB,IAAI,GAAG,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC,GAA6B,CAAC,CAAA;QACzD,MAAM,KAAK,GAAG,KAAK,CAAC,GAA6B,CAAY,CAAA;QAC7D,OAAO,OAAO,KAAK,KAAK,UAAU;YAChC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CAAE,KAA+C,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACrG,CAAC,CAAC,KAAK,CAAA;IACX,CAAC;IACD,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,KAAK;CAC9C,CAAC,CAAA;AAEJ,iFAAiF;AACjF,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,OAAyB,EACzB,MAAS,EACT,IAAY,EACsB,EAAE;IACpC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC7B,IAAI,OAAO,KAAK,KAAK,UAAU;QAAE,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,yBAAyB,IAAI,EAAE,CAAC,CAAA;IACxG,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAqC,CAAA;AAChE,CAAC,CAAA"}
1
+ {"version":3,"file":"port.js","sourceRoot":"","sources":["../../../src/cli/messenger/port.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AA8G5C;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,KAAuB,EACvB,OAAyB,EACzB,IAAI,GAA6E,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAChF,EAAE,CACpB,IAAI,KAAK,CAAC,OAAO,EAAE;IACjB,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAChB,IAAI,GAAG,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC,GAA6B,CAAC,CAAA;QACzD,MAAM,KAAK,GAAG,KAAK,CAAC,GAA6B,CAAY,CAAA;QAC7D,OAAO,OAAO,KAAK,KAAK,UAAU;YAChC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CAAE,KAA+C,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACrG,CAAC,CAAC,KAAK,CAAA;IACX,CAAC;IACD,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,KAAK;CAC9C,CAAC,CAAA;AAEJ,iFAAiF;AACjF,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,OAAyB,EACzB,MAAS,EACT,IAAY,EACsB,EAAE;IACpC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC7B,IAAI,OAAO,KAAK,KAAK,UAAU;QAAE,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,yBAAyB,IAAI,EAAE,CAAC,CAAA;IACxG,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAqC,CAAA;AAChE,CAAC,CAAA"}
@@ -0,0 +1,9 @@
1
+ /** Signal 0 checks that the process exists without touching it. */
2
+ export declare const alive: (pid: number) => boolean;
3
+ /**
4
+ * Whether `pid` is alive **and** carries `marker` (`NAME=value`) in its environment. A PID is handed
5
+ * out again once its process is gone — after a crash or a reboot a recorded number may belong to
6
+ * somebody else, who must never be signalled. Only the owner of a process may read its environment.
7
+ */
8
+ export declare const carries: (pid: number, marker: string) => boolean;
9
+ //# sourceMappingURL=processes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processes.d.ts","sourceRoot":"","sources":["../../../src/cli/messenger/processes.ts"],"names":[],"mappings":"AAGA,mEAAmE;AACnE,eAAO,MAAM,KAAK,QAAS,MAAM,KAAG,OAOnC,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,OAAO,QAAS,MAAM,UAAU,MAAM,KAAG,OAgBrD,CAAA"}
@@ -0,0 +1,37 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { readFileSync } from "node:fs";
3
+ /** Signal 0 checks that the process exists without touching it. */
4
+ export const alive = (pid) => {
5
+ try {
6
+ process.kill(pid, 0);
7
+ return true;
8
+ }
9
+ catch (error) {
10
+ return error.code === "EPERM";
11
+ }
12
+ };
13
+ /**
14
+ * Whether `pid` is alive **and** carries `marker` (`NAME=value`) in its environment. A PID is handed
15
+ * out again once its process is gone — after a crash or a reboot a recorded number may belong to
16
+ * somebody else, who must never be signalled. Only the owner of a process may read its environment.
17
+ */
18
+ export const carries = (pid, marker) => {
19
+ // PID 0 would ask about this whole process group.
20
+ if (pid <= 0 || !alive(pid))
21
+ return false;
22
+ try {
23
+ if (process.platform === "linux") {
24
+ return readFileSync(`/proc/${pid}/environ`, "latin1")
25
+ .split("\0")
26
+ .some((entry) => entry.endsWith(marker));
27
+ }
28
+ if (process.platform === "darwin") {
29
+ return execFileSync("ps", ["eww", "-o", "command=", "-p", String(pid)], { encoding: "utf8" }).includes(marker);
30
+ }
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ return false;
36
+ };
37
+ //# sourceMappingURL=processes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processes.js","sourceRoot":"","sources":["../../../src/cli/messenger/processes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,mEAAmE;AACnE,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,GAAW,EAAW,EAAE;IAC5C,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;QACpB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAQ,KAA+B,CAAC,IAAI,KAAK,OAAO,CAAA;IAC1D,CAAC;AACH,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,MAAc,EAAW,EAAE;IAC9D,kDAAkD;IAClD,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAA;IACzC,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,OAAO,YAAY,CAAC,SAAS,GAAG,UAAU,EAAE,QAAQ,CAAC;iBAClD,KAAK,CAAC,IAAI,CAAC;iBACX,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;QAC5C,CAAC;QACD,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAClC,OAAO,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;QAChH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
@@ -1,19 +1,18 @@
1
1
  import { Command } from "commander";
2
2
  import type { AppIdentity } from "../app.js";
3
3
  import { type Messenger } from "./context.js";
4
- interface Lock {
4
+ export interface Lock {
5
5
  pid: number;
6
6
  startedAt: string;
7
+ /** Set once the connection is open and updates arrive — before it, `serve` is still starting. */
8
+ listeningAt?: string;
7
9
  }
8
10
  export declare const lockPath: (app: AppIdentity, profile: string, env: NodeJS.ProcessEnv) => string;
9
11
  export declare const readLock: (path: string) => Lock | undefined;
10
- /** Signal 0 checks that the process exists without touching it. */
11
- export declare const alive: (pid: number) => boolean;
12
12
  /**
13
13
  * Keeps the store current: every new message, edit, deletion and reaction, and on start what arrived
14
14
  * while nothing listened. **One per profile**, held by a lock file; a lock whose process is gone is
15
- * taken over. Started by a person or a service unit — no command starts it (NEED-9).
15
+ * taken over. Started by a person, a service unit or `server start` — never by itself (NEED-9).
16
16
  */
17
17
  export declare const serveCommand: (messenger: Messenger) => Command;
18
- export {};
19
18
  //# sourceMappingURL=serve-command.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"serve-command.d.ts","sourceRoot":"","sources":["../../../src/cli/messenger/serve-command.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,cAAc,CAAA;AAG/D,UAAU,IAAI;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,eAAO,MAAM,QAAQ,QAAS,WAAW,WAAW,MAAM,OAAO,MAAM,CAAC,UAAU,WAC0B,CAAA;AAE5G,eAAO,MAAM,QAAQ,SAAU,MAAM,KAAG,IAAI,GAAG,SAO9C,CAAA;AAED,mEAAmE;AACnE,eAAO,MAAM,KAAK,QAAS,MAAM,KAAG,OAOnC,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,cAAe,SAAS,KAAG,OA0CnD,CAAA"}
1
+ {"version":3,"file":"serve-command.d.ts","sourceRoot":"","sources":["../../../src/cli/messenger/serve-command.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,cAAc,CAAA;AAI/D,MAAM,WAAW,IAAI;IACnB,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,iGAAiG;IACjG,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,eAAO,MAAM,QAAQ,QAAS,WAAW,WAAW,MAAM,OAAO,MAAM,CAAC,UAAU,WAC0B,CAAA;AAE5G,eAAO,MAAM,QAAQ,SAAU,MAAM,KAAG,IAAI,GAAG,SAO9C,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,cAAe,SAAS,KAAG,OA0CnD,CAAA"}
@@ -3,6 +3,7 @@ import { join } from "node:path";
3
3
  import { CliError, resolvePaths, writeSecurely } from "@leemour/cli-core";
4
4
  import { Command } from "commander";
5
5
  import { messengerContext } from "./context.js";
6
+ import { alive } from "./processes.js";
6
7
  import { listenUntilStopped } from "./watch-command.js";
7
8
  export const lockPath = (app, profile, env) => join(resolvePaths({ appName: app.appName, prefix: app.envPrefix, env }).state, "serve", `${profile}.lock`);
8
9
  export const readLock = (path) => {
@@ -14,20 +15,10 @@ export const readLock = (path) => {
14
15
  return undefined;
15
16
  }
16
17
  };
17
- /** Signal 0 checks that the process exists without touching it. */
18
- export const alive = (pid) => {
19
- try {
20
- process.kill(pid, 0);
21
- return true;
22
- }
23
- catch (error) {
24
- return error.code === "EPERM";
25
- }
26
- };
27
18
  /**
28
19
  * Keeps the store current: every new message, edit, deletion and reaction, and on start what arrived
29
20
  * while nothing listened. **One per profile**, held by a lock file; a lock whose process is gone is
30
- * taken over. Started by a person or a service unit — no command starts it (NEED-9).
21
+ * taken over. Started by a person, a service unit or `server start` — never by itself (NEED-9).
31
22
  */
32
23
  export const serveCommand = (messenger) => {
33
24
  const command = new Command("serve").description("keep the local store current until stopped — what a systemd or launchd unit runs");
@@ -41,13 +32,23 @@ export const serveCommand = (messenger) => {
41
32
  throw new CliError("validation_error", `${messenger.app.command} serve is already running for profile ${context.profile} (PID ${held.pid}, since ${held.startedAt})`);
42
33
  }
43
34
  const startedAt = new Date().toISOString();
44
- writeSecurely(path, `${JSON.stringify({ pid: process.pid, startedAt })}\n`, 0o600);
35
+ const hold = (lock) => writeSecurely(path, `${JSON.stringify(lock)}\n`, 0o600);
36
+ hold({ pid: process.pid, startedAt });
37
+ // `server start` answers on this, not on the lock alone: a lock is written before the connection opens.
38
+ const onReady = () => {
39
+ hold({ pid: process.pid, startedAt, listeningAt: new Date().toISOString() });
40
+ context.renderer.note(`listening for profile ${context.profile}, catching up on what arrived while it was down`);
41
+ };
45
42
  const counts = {};
46
43
  const count = (event) => {
47
44
  counts[event.event] = (counts[event.event] ?? 0) + 1;
48
45
  };
49
46
  try {
50
- await listenUntilStopped(this, context, messenger, count, { stop: new AbortController(), catchUp: true });
47
+ await listenUntilStopped(this, context, messenger, count, {
48
+ stop: new AbortController(),
49
+ catchUp: true,
50
+ onReady,
51
+ });
51
52
  }
52
53
  finally {
53
54
  if (readLock(path)?.pid === process.pid)
@@ -55,15 +56,6 @@ export const serveCommand = (messenger) => {
55
56
  }
56
57
  context.renderer.result({ profile: context.profile, startedAt, stoppedAt: new Date().toISOString(), kept: counts });
57
58
  });
58
- command
59
- .command("status")
60
- .description("whether a serve is running for this profile, and since when")
61
- .action(function () {
62
- const { profile, env, renderer } = messengerContext(this, messenger);
63
- const lock = readLock(lockPath(messenger.app, profile, env));
64
- const running = lock !== undefined && alive(lock.pid);
65
- renderer.result({ profile, running, ...(running && lock ? { pid: lock.pid, since: lock.startedAt } : {}) });
66
- });
67
59
  return command;
68
60
  };
69
61
  //# sourceMappingURL=serve-command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"serve-command.js","sourceRoot":"","sources":["../../../src/cli/messenger/serve-command.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"serve-command.js","sourceRoot":"","sources":["../../../src/cli/messenger/serve-command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { Command } from "commander";
2
+ import { type Messenger } from "./context.js";
3
+ export interface Ran {
4
+ code: number;
5
+ stdout: string;
6
+ stderr: string;
7
+ }
8
+ /** What `server` asks of the machine. Tests hand one in; nothing else does. */
9
+ export interface ServerSystem {
10
+ platform: NodeJS.Platform;
11
+ run: (argv: string[], env: NodeJS.ProcessEnv) => Promise<Ran>;
12
+ /** The command line that starts this CLI: the node binary and the script, both absolute. */
13
+ entry: string[];
14
+ uid: number;
15
+ /** Starts `<cli> <argv>` apart from this process, writing to `log`, and answers its PID. */
16
+ spawn: (argv: string[], env: NodeJS.ProcessEnv, log: string) => number;
17
+ /** The pause between two looks at whether `serve` is listening yet. */
18
+ pause: () => Promise<void>;
19
+ }
20
+ /**
21
+ * `serve` in the background, the way max-cli's `server` is: `start`, `stop`, `restart`, `status`,
22
+ * `logs`. Without a unit, `start` runs `serve` as a process of its own; with one — `install`, a
23
+ * systemd user unit or a launchd agent — it goes through systemd or launchd. **Nothing starts until
24
+ * `start` is typed** (NEED-9): `install` only writes the file.
25
+ */
26
+ export declare const serverCommand: (messenger: Messenger) => Command;
27
+ //# sourceMappingURL=server-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-command.d.ts","sourceRoot":"","sources":["../../../src/cli/messenger/server-command.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGnC,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,cAAc,CAAA;AAI/D,MAAM,WAAW,GAAG;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf;AAED,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAA;IACzB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IAC7D,4FAA4F;IAC5F,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,4FAA4F;IAC5F,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IACtE,uEAAuE;IACvE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B;AA2QD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,cAAe,SAAS,KAAG,OA6OpD,CAAA"}