@sofer_agent/cli 0.7.1 → 0.7.3

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/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { agentPaths } from "@sofer_agent/core";
3
3
  import { chatCommand } from "./chat.js";
4
- import { daemonStart, daemonStop } from "./daemon.js";
4
+ import { daemonLogs, daemonRestart, daemonRun, daemonStart, daemonStatus, daemonStop } from "./daemon.js";
5
5
  import { infoCommand } from "./info.js";
6
6
  import { initCommand } from "./init.js";
7
7
  import { telegramCommand } from "./telegram-start.js";
@@ -12,8 +12,12 @@ function printHelp() {
12
12
  sofer --resume <id> resume a previous session
13
13
  sofer init interactive setup — mint agent + provision memory
14
14
  sofer info print on-chain agent state
15
- sofer daemon start start persistent background agent
16
- sofer daemon stop stop the background agent
15
+ sofer daemon run start daemon in foreground
16
+ sofer daemon start start daemon in background (fork)
17
+ sofer daemon stop stop the daemon
18
+ sofer daemon restart stop + start
19
+ sofer daemon status show PID, uptime, socket
20
+ sofer daemon logs tail daemon logs
17
21
  sofer telegram start the Telegram bot
18
22
  sofer help show this help
19
23
 
@@ -42,12 +46,29 @@ async function main() {
42
46
  break;
43
47
  case "daemon": {
44
48
  const sub = args[1];
45
- if (sub === "start")
46
- await daemonStart();
47
- else if (sub === "stop")
48
- await daemonStop();
49
- else
50
- console.error("usage: sofer daemon <start|stop>");
49
+ switch (sub) {
50
+ case "run":
51
+ await daemonRun();
52
+ break;
53
+ case "start":
54
+ await daemonStart();
55
+ break;
56
+ case "stop":
57
+ await daemonStop();
58
+ break;
59
+ case "restart":
60
+ await daemonRestart();
61
+ break;
62
+ case "status":
63
+ await daemonStatus();
64
+ break;
65
+ case "logs":
66
+ await daemonLogs();
67
+ break;
68
+ default:
69
+ console.error("usage: sofer daemon <run|start|stop|restart|status|logs>");
70
+ break;
71
+ }
51
72
  break;
52
73
  }
53
74
  case "help":
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CACT;;;;;;;;;;;;6BAYyB,UAAU,CAAC,IAAI;gDACI,CAC7C,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAChE,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;IAE9B,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,MAAM,CAAC;QACZ,KAAK,UAAU;YACb,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACnD,MAAM;QACR,KAAK,MAAM;YACT,MAAM,WAAW,EAAE,CAAC;YACpB,MAAM;QACR,KAAK,MAAM;YACT,MAAM,WAAW,EAAE,CAAC;YACpB,MAAM;QACR,KAAK,UAAU;YACb,MAAM,eAAe,EAAE,CAAC;YACxB,MAAM;QACR,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACpB,IAAI,GAAG,KAAK,OAAO;gBAAE,MAAM,WAAW,EAAE,CAAC;iBACpC,IAAI,GAAG,KAAK,MAAM;gBAAE,MAAM,UAAU,EAAE,CAAC;;gBACvC,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;YACvD,MAAM;QACR,CAAC;QACD,KAAK,MAAM,CAAC;QACZ,KAAK,IAAI,CAAC;QACV,KAAK,QAAQ;YACX,SAAS,EAAE,CAAC;YACZ,MAAM;QACR;YACE,OAAO,CAAC,KAAK,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;YAC3C,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;IACjB,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,IACE,GAAG,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACpC,GAAG,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACjC,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAChC,CAAC;QACD,OAAO,CAAC,KAAK,CACX,qEAAqE,UAAU,CAAC,IAAI,KAAK,CAC1F,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
package/dist/daemon.d.ts CHANGED
@@ -1,3 +1,7 @@
1
- export declare function daemonStop(): Promise<void>;
1
+ export declare function daemonRun(): Promise<void>;
2
2
  export declare function daemonStart(): Promise<void>;
3
+ export declare function daemonStop(): Promise<void>;
4
+ export declare function daemonStatus(): Promise<void>;
5
+ export declare function daemonRestart(): Promise<void>;
6
+ export declare function daemonLogs(tail?: number, follow?: boolean): Promise<void>;
3
7
  //# sourceMappingURL=daemon.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AA2CA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAKhD;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAuLjD"}
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAwCA,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAM/C;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAqBjD;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAKhD;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAoBlD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAInD;AAED,wBAAsB,UAAU,CAAC,IAAI,SAAK,EAAE,MAAM,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBzE"}
package/dist/daemon.js CHANGED
@@ -1,12 +1,13 @@
1
1
  import { createServer } from "node:http";
2
- import { chmodSync, existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { chmodSync, existsSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
- import { agentPaths, decryptWithKey, loadConfig, readSecret, shortAgentId, SoferAgent, } from "@sofer_agent/core";
4
+ import { spawn } from "node:child_process";
5
+ import { agentPaths, decryptWithKey, loadConfig, readSecret, SoferAgent, } from "@sofer_agent/core";
5
6
  import { TelegramListener } from "@sofer_agent/plugin-telegram";
6
7
  import { loadSecrets } from "./env.js";
7
8
  const LOCK_FILE = join(agentPaths.root, "daemon.lock");
8
9
  const SOCK_PATH = join(agentPaths.root, "daemon.sock");
9
- // ── Process lock ──────────────────────────────────────────────────────────
10
+ const LOG_FILE = join(agentPaths.root, "daemon.log");
10
11
  function acquireLock() {
11
12
  try {
12
13
  if (existsSync(LOCK_FILE)) {
@@ -32,7 +33,34 @@ function releaseLock() {
32
33
  catch { /* */ }
33
34
  }
34
35
  let state = "bootstrapping";
35
- // ── Main ──────────────────────────────────────────────────────────────────
36
+ // ── Commands ─────────────────────────────────────────────────────────────
37
+ export async function daemonRun() {
38
+ if (!acquireLock()) {
39
+ console.error("Daemon already running. Use `sofer daemon stop` first.");
40
+ process.exit(1);
41
+ }
42
+ await runServer();
43
+ }
44
+ export async function daemonStart() {
45
+ if (!acquireLock()) {
46
+ console.error("Daemon already running. Use `sofer daemon stop` first.");
47
+ process.exit(1);
48
+ }
49
+ releaseLock(); // let the child take the lock
50
+ const logFd = existsSync(LOG_FILE)
51
+ ? require("node:fs").openSync(LOG_FILE, "a")
52
+ : require("node:fs").openSync(LOG_FILE, "w");
53
+ const execPath = process.argv[1] ?? process.execPath;
54
+ const child = spawn(process.execPath, [...process.execArgv, execPath, "daemon", "run"], {
55
+ detached: true,
56
+ stdio: ["ignore", logFd, logFd],
57
+ env: { ...process.env },
58
+ });
59
+ child.unref();
60
+ console.log(`[daemon] started (PID ${child.pid})`);
61
+ console.log(` socket: ${SOCK_PATH}`);
62
+ console.log(` logs: ${LOG_FILE}`);
63
+ }
36
64
  export async function daemonStop() {
37
65
  if (!existsSync(LOCK_FILE)) {
38
66
  console.log("No daemon running.");
@@ -41,21 +69,75 @@ export async function daemonStop() {
41
69
  const pid = Number(readFileSync(LOCK_FILE, "utf8").trim());
42
70
  try {
43
71
  process.kill(pid, "SIGTERM");
44
- console.log(`Sent stop to PID ${pid}.`);
72
+ console.log(`Stopped daemon (PID ${pid}).`);
45
73
  }
46
74
  catch {
47
75
  console.log("Stale lock. Cleaning up.");
48
76
  releaseLock();
49
77
  }
50
78
  }
51
- export async function daemonStart() {
52
- if (!acquireLock()) {
53
- console.error("Daemon already running (lock exists). Use `sofer daemon stop` first.");
54
- process.exit(1);
79
+ export async function daemonStatus() {
80
+ if (!existsSync(LOCK_FILE)) {
81
+ console.log("Daemon not running.");
82
+ return;
83
+ }
84
+ const pid = Number(readFileSync(LOCK_FILE, "utf8").trim());
85
+ let alive = false;
86
+ try {
87
+ process.kill(pid, 0);
88
+ alive = true;
89
+ }
90
+ catch { /* dead */ }
91
+ if (!alive) {
92
+ console.log("Daemon not running (stale lock).");
93
+ return;
94
+ }
95
+ let uptime = "unknown";
96
+ try {
97
+ const stat = statSync(LOCK_FILE);
98
+ const sec = Math.floor((Date.now() - stat.mtimeMs) / 1000);
99
+ uptime = sec < 60 ? `${sec}s` : sec < 3600 ? `${Math.floor(sec / 60)}m` : `${Math.floor(sec / 3600)}h`;
100
+ }
101
+ catch { /* */ }
102
+ console.log(` PID: ${pid}`);
103
+ console.log(` Status: running`);
104
+ console.log(` Uptime: ${uptime}`);
105
+ console.log(` Socket: ${SOCK_PATH}`);
106
+ console.log(` Lock: ${LOCK_FILE}`);
107
+ console.log(` Logs: ${LOG_FILE}`);
108
+ }
109
+ export async function daemonRestart() {
110
+ await daemonStop();
111
+ await new Promise((r) => setTimeout(r, 500));
112
+ await daemonStart();
113
+ }
114
+ export async function daemonLogs(tail = 50, follow = false) {
115
+ if (!existsSync(LOG_FILE)) {
116
+ console.log("No daemon logs found.");
117
+ return;
118
+ }
119
+ const lines = readFileSync(LOG_FILE, "utf8").split("\n").filter(Boolean);
120
+ const recent = lines.slice(-tail);
121
+ console.log(recent.join("\n"));
122
+ if (follow) {
123
+ const { watchFile } = require("node:fs");
124
+ let count = lines.length;
125
+ watchFile(LOG_FILE, () => {
126
+ const all = readFileSync(LOG_FILE, "utf8").split("\n").filter(Boolean);
127
+ for (let i = count; i < all.length; i++) {
128
+ console.log(all[i]);
129
+ }
130
+ count = all.length;
131
+ });
132
+ // Keep alive
133
+ await new Promise(() => { });
55
134
  }
135
+ }
136
+ // ── Server (shared by run + start) ───────────────────────────────────────
137
+ async function runServer() {
56
138
  const secrets = loadSecrets();
57
139
  if (!secrets.suiSecretKey || !secrets.anthropicApiKey) {
58
- console.error("Missing secrets. Run `sofer init` first.");
140
+ console.error("[daemon] missing secrets. Run `sofer init` first.");
59
141
  process.exit(1);
60
142
  }
61
143
  console.log("[daemon] bootstrapping…");
@@ -68,20 +150,59 @@ export async function daemonStart() {
68
150
  });
69
151
  }
70
152
  catch (e) {
71
- console.error("[daemon] failed to create agent:", e.message);
153
+ console.error("[daemon] failed:", e.message);
72
154
  releaseLock();
73
155
  process.exit(1);
74
156
  }
75
- // SSE clients
76
157
  let sseId = 0;
77
158
  const sseClients = new Set();
78
159
  function broadcast(event, data) {
79
160
  const payload = JSON.stringify(data);
80
- for (const c of sseClients) {
161
+ for (const c of sseClients)
81
162
  c.res.write(`event: ${event}\ndata: ${payload}\n\n`);
163
+ }
164
+ // ── Message queue ──────────────────────────────────────────────────────
165
+ const MAX_QUEUE = 64;
166
+ let queue = [];
167
+ let processing = false;
168
+ async function drainQueue() {
169
+ if (processing)
170
+ return;
171
+ processing = true;
172
+ broadcast("queue", { status: "processing", length: queue.length });
173
+ try {
174
+ while (queue.length > 0) {
175
+ const item = queue.shift();
176
+ try {
177
+ const { text } = await agent.chat(item.message);
178
+ item.resolve(text);
179
+ broadcast("response", { text, source: item.type });
180
+ }
181
+ catch (e) {
182
+ item.reject(e instanceof Error ? e : new Error(String(e)));
183
+ broadcast("error", { error: e.message, source: item.type });
184
+ }
185
+ }
186
+ }
187
+ finally {
188
+ processing = false;
189
+ broadcast("queue", { status: "idle", length: queue.length });
82
190
  }
83
191
  }
84
- // ── HTTP server ────────────────────────────────────────────────────────
192
+ function enqueue(type, message) {
193
+ if (queue.length >= MAX_QUEUE)
194
+ throw new Error("Queue full — try again later");
195
+ return new Promise((resolve, reject) => {
196
+ queue.push({ type, message, resolve, reject });
197
+ drainQueue();
198
+ });
199
+ }
200
+ // Telemetry interval — report queue stats every 30s
201
+ setInterval(() => {
202
+ if (queue.length > 0 || processing) {
203
+ broadcast("telemetry", { queue: queue.length, processing, tokens: agent.usage.tokens });
204
+ }
205
+ }, 30_000);
85
206
  const server = createServer(async (req, res) => {
86
207
  res.setHeader("Access-Control-Allow-Origin", "*");
87
208
  if (req.method === "OPTIONS") {
@@ -89,26 +210,18 @@ export async function daemonStart() {
89
210
  return;
90
211
  }
91
212
  const url = req.url ?? "/";
92
- // GET /healthz
93
- if (req.method === "GET" && url === "/healthz") {
94
- res.writeHead(200, { "content-type": "application/json" });
95
- res.end(JSON.stringify({ status: state, agent: agent.address.slice(0, 10), network: config.network }));
213
+ if (url === "/healthz") {
214
+ res.writeHead(200).end(JSON.stringify({ status: state, agent: agent.address.slice(0, 10), network: config.network }));
96
215
  return;
97
216
  }
98
- // GET /events (SSE)
99
- if (req.method === "GET" && url === "/events") {
100
- res.writeHead(200, {
101
- "content-type": "text/event-stream",
102
- "cache-control": "no-cache",
103
- connection: "keep-alive",
104
- });
217
+ if (url === "/events") {
218
+ res.writeHead(200, { "content-type": "text/event-stream", "cache-control": "no-cache", connection: "keep-alive" });
105
219
  const client = { id: ++sseId, res };
106
220
  sseClients.add(client);
107
221
  res.write(`data: ${JSON.stringify({ event: "connected", agent: agent.address })}\n\n`);
108
222
  req.on("close", () => sseClients.delete(client));
109
223
  return;
110
224
  }
111
- // POST /chat
112
225
  if (req.method === "POST" && url === "/chat") {
113
226
  const body = await readBody(req);
114
227
  try {
@@ -118,22 +231,16 @@ export async function daemonStart() {
118
231
  return;
119
232
  }
120
233
  broadcast("thinking", { status: "thinking" });
121
- const { text } = await agent.chat(message);
122
- broadcast("response", { text });
234
+ const text = await enqueue("http", message);
123
235
  broadcast("idle", { status: "idle" });
124
- res.writeHead(200, { "content-type": "application/json" });
125
236
  res.end(JSON.stringify({ text }));
126
237
  }
127
238
  catch (e) {
128
- broadcast("error", { error: e.message });
129
- res.writeHead(500).end(e.message);
239
+ res.writeHead(503).end(JSON.stringify({ error: e.message }));
130
240
  }
131
241
  return;
132
242
  }
133
- // POST /sync — force memory flush
134
243
  if (req.method === "POST" && url === "/sync") {
135
- broadcast("sync", { status: "syncing" });
136
- // Memory is already persisted via JSONL; trigger a fresh agent state read
137
244
  try {
138
245
  const bal = await agent.getBalance();
139
246
  broadcast("sync", { status: "done", balance: (Number(bal) / 1e9).toFixed(4) });
@@ -144,22 +251,17 @@ export async function daemonStart() {
144
251
  }
145
252
  return;
146
253
  }
147
- // GET /status
148
- if (req.method === "GET" && url === "/status") {
149
- res.writeHead(200, { "content-type": "application/json" });
150
- res.end(JSON.stringify({
151
- state,
152
- agent: agent.address,
153
- name: agent.name,
154
- network: config.network,
155
- tokens: agent.usage.tokens,
156
- cost: agent.usage.costUsd.toFixed(6),
157
- }));
254
+ if (url === "/status") {
255
+ res.end(JSON.stringify({ state, agent: agent.address, name: agent.name, network: config.network, tokens: agent.usage.tokens, cost: agent.usage.costUsd.toFixed(6) }));
158
256
  return;
159
257
  }
160
- res.writeHead(404).end("not found");
258
+ if (url === "/queue") {
259
+ res.end(JSON.stringify({ length: queue.length, processing }));
260
+ return;
261
+ }
262
+ res.writeHead(404).end();
161
263
  });
162
- // ── Telegram ───────────────────────────────────────────────────────────
264
+ // Telegram
163
265
  const tgPath = `${agentPaths.root}/telegram.enc`;
164
266
  const tgEnc = readSecret(tgPath);
165
267
  let tgListener = null;
@@ -168,52 +270,42 @@ export async function daemonStart() {
168
270
  const raw = decryptWithKey(secrets.suiSecretKey, tgEnc);
169
271
  if (raw) {
170
272
  const tgConfig = JSON.parse(raw);
171
- tgListener = new TelegramListener({
172
- botToken: tgConfig.botToken,
173
- allowedUserIds: tgConfig.allowedUserIds,
174
- agentName: agent.name.toLowerCase(),
175
- });
273
+ tgListener = new TelegramListener({ botToken: tgConfig.botToken, allowedUserIds: tgConfig.allowedUserIds, agentName: agent.name.toLowerCase() });
176
274
  tgListener.onDispatch(async (input) => {
177
275
  broadcast("tg-message", { from: input.displayName, text: input.text.slice(0, 200) });
178
- const { text } = await agent.chat(input.text);
276
+ const text = await enqueue("telegram", input.text);
179
277
  broadcast("tg-response", { text: text.slice(0, 200) });
180
278
  return text;
181
279
  });
182
280
  }
183
281
  }
184
- catch { /* skip */ }
282
+ catch { /* */ }
185
283
  }
186
- // ── Bind ───────────────────────────────────────────────────────────────
187
284
  const PORT = Number(process.env.SOFER_DAEMON_PORT ?? 4242);
188
- // Try Unix socket first, fall back to TCP
189
285
  try {
190
286
  if (existsSync(SOCK_PATH))
191
287
  unlinkSync(SOCK_PATH);
192
288
  server.listen(SOCK_PATH, () => {
193
289
  chmodSync(SOCK_PATH, 0o600);
194
290
  state = "ready";
195
- console.log(`[daemon] ready — unix socket ${SOCK_PATH}`);
196
- console.log(`[daemon] agent: ${agent.address.slice(0, 10)}… network: ${config.network}`);
197
- if (tgListener) {
198
- console.log("[daemon] telegram: starting bot…");
291
+ console.log(`[daemon] ready — ${SOCK_PATH}`);
292
+ console.log(`[daemon] agent: ${agent.address.slice(0, 10)}… ${config.network}`);
293
+ if (tgListener)
199
294
  tgListener.start().catch((e) => console.error("[daemon] telegram:", e.message));
200
- }
201
295
  });
202
296
  }
203
297
  catch {
204
298
  server.listen(PORT, () => {
205
299
  state = "ready";
206
- console.log(`[daemon] ready — tcp port ${PORT} (SOFER_DAEMON_PORT)`);
207
- console.log(`[daemon] agent: ${agent.address.slice(0, 10)}… network: ${config.network}`);
208
- if (tgListener) {
300
+ console.log(`[daemon] ready — tcp :${PORT}`);
301
+ console.log(`[daemon] agent: ${agent.address.slice(0, 10)}… ${config.network}`);
302
+ if (tgListener)
209
303
  tgListener.start().catch((e) => console.error("[daemon] telegram:", e.message));
210
- }
211
304
  });
212
305
  }
213
- // ── Shutdown ───────────────────────────────────────────────────────────
214
306
  const shutdown = async () => {
215
307
  state = "shutting_down";
216
- console.log("\n[daemon] shutting down…");
308
+ console.log("[daemon] shutting down…");
217
309
  if (tgListener)
218
310
  await tgListener.stop().catch(() => { });
219
311
  server.close();
@@ -231,7 +323,7 @@ export async function daemonStart() {
231
323
  function readBody(req) {
232
324
  return new Promise((resolve) => {
233
325
  let data = "";
234
- req.on("data", (chunk) => { data += chunk; });
326
+ req.on("data", (c) => { data += c; });
235
327
  req.on("end", () => resolve(data));
236
328
  });
237
329
  }
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sofer_agent/cli",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "sofer": "./bin/sofer"
@@ -29,7 +29,7 @@
29
29
  "@clack/prompts": "^1.5.1",
30
30
  "@types/blessed": "^0.1.27",
31
31
  "blessed": "^0.1.81",
32
- "@sofer_agent/core": "0.6.0",
32
+ "@sofer_agent/core": "0.6.1",
33
33
  "@sofer_agent/plugin-telegram": "0.1.0"
34
34
  },
35
35
  "devDependencies": {
package/src/bin.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { agentPaths } from "@sofer_agent/core";
3
3
  import { chatCommand } from "./chat.js";
4
- import { daemonStart, daemonStop } from "./daemon.js";
4
+ import { daemonLogs, daemonRestart, daemonRun, daemonStart, daemonStatus, daemonStop } from "./daemon.js";
5
5
  import { infoCommand } from "./info.js";
6
6
  import { initCommand } from "./init.js";
7
7
  import { telegramCommand } from "./telegram-start.js";
@@ -14,8 +14,12 @@ function printHelp(): void {
14
14
  sofer --resume <id> resume a previous session
15
15
  sofer init interactive setup — mint agent + provision memory
16
16
  sofer info print on-chain agent state
17
- sofer daemon start start persistent background agent
18
- sofer daemon stop stop the background agent
17
+ sofer daemon run start daemon in foreground
18
+ sofer daemon start start daemon in background (fork)
19
+ sofer daemon stop stop the daemon
20
+ sofer daemon restart stop + start
21
+ sofer daemon status show PID, uptime, socket
22
+ sofer daemon logs tail daemon logs
19
23
  sofer telegram start the Telegram bot
20
24
  sofer help show this help
21
25
 
@@ -47,9 +51,15 @@ async function main(): Promise<void> {
47
51
  break;
48
52
  case "daemon": {
49
53
  const sub = args[1];
50
- if (sub === "start") await daemonStart();
51
- else if (sub === "stop") await daemonStop();
52
- else console.error("usage: sofer daemon <start|stop>");
54
+ switch (sub) {
55
+ case "run": await daemonRun(); break;
56
+ case "start": await daemonStart(); break;
57
+ case "stop": await daemonStop(); break;
58
+ case "restart": await daemonRestart(); break;
59
+ case "status": await daemonStatus(); break;
60
+ case "logs": await daemonLogs(); break;
61
+ default: console.error("usage: sofer daemon <run|start|stop|restart|status|logs>"); break;
62
+ }
53
63
  break;
54
64
  }
55
65
  case "help":
package/src/daemon.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { createServer, type IncomingMessage, type ServerResponse } from "node:http";
2
- import { chmodSync, existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { chmodSync, existsSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
+ import { spawn } from "node:child_process";
4
5
  import {
5
6
  agentPaths,
6
7
  decryptWithKey,
7
8
  loadConfig,
8
9
  readSecret,
9
- shortAgentId,
10
10
  SoferAgent,
11
11
  } from "@sofer_agent/core";
12
12
  import { TelegramListener } from "@sofer_agent/plugin-telegram";
@@ -14,11 +14,10 @@ import { loadSecrets } from "./env.js";
14
14
 
15
15
  const LOCK_FILE = join(agentPaths.root, "daemon.lock");
16
16
  const SOCK_PATH = join(agentPaths.root, "daemon.sock");
17
+ const LOG_FILE = join(agentPaths.root, "daemon.log");
17
18
 
18
19
  interface SSEClient { id: number; res: ServerResponse; }
19
20
 
20
- // ── Process lock ──────────────────────────────────────────────────────────
21
-
22
21
  function acquireLock(): boolean {
23
22
  try {
24
23
  if (existsSync(LOCK_FILE)) {
@@ -34,29 +33,104 @@ function releaseLock(): void {
34
33
  try { if (existsSync(LOCK_FILE)) unlinkSync(LOCK_FILE); } catch { /* */ }
35
34
  }
36
35
 
37
- // ── State machine ─────────────────────────────────────────────────────────
38
-
39
36
  type DaemonState = "bootstrapping" | "ready" | "shutting_down";
40
37
  let state: DaemonState = "bootstrapping";
41
38
 
42
- // ── Main ──────────────────────────────────────────────────────────────────
39
+ // ── Commands ─────────────────────────────────────────────────────────────
40
+
41
+ export async function daemonRun(): Promise<void> {
42
+ if (!acquireLock()) {
43
+ console.error("Daemon already running. Use `sofer daemon stop` first.");
44
+ process.exit(1);
45
+ }
46
+ await runServer();
47
+ }
48
+
49
+ export async function daemonStart(): Promise<void> {
50
+ if (!acquireLock()) {
51
+ console.error("Daemon already running. Use `sofer daemon stop` first.");
52
+ process.exit(1);
53
+ }
54
+ releaseLock(); // let the child take the lock
55
+
56
+ const logFd = existsSync(LOG_FILE)
57
+ ? require("node:fs").openSync(LOG_FILE, "a")
58
+ : require("node:fs").openSync(LOG_FILE, "w");
59
+
60
+ const execPath = process.argv[1] ?? process.execPath;
61
+ const child = spawn(process.execPath, [...process.execArgv, execPath, "daemon", "run"], {
62
+ detached: true,
63
+ stdio: ["ignore", logFd, logFd] as const,
64
+ env: { ...process.env },
65
+ });
66
+ child.unref();
67
+ console.log(`[daemon] started (PID ${child.pid})`);
68
+ console.log(` socket: ${SOCK_PATH}`);
69
+ console.log(` logs: ${LOG_FILE}`);
70
+ }
43
71
 
44
72
  export async function daemonStop(): Promise<void> {
45
73
  if (!existsSync(LOCK_FILE)) { console.log("No daemon running."); return; }
46
74
  const pid = Number(readFileSync(LOCK_FILE, "utf8").trim());
47
- try { process.kill(pid, "SIGTERM"); console.log(`Sent stop to PID ${pid}.`); }
75
+ try { process.kill(pid, "SIGTERM"); console.log(`Stopped daemon (PID ${pid}).`); }
48
76
  catch { console.log("Stale lock. Cleaning up."); releaseLock(); }
49
77
  }
50
78
 
51
- export async function daemonStart(): Promise<void> {
52
- if (!acquireLock()) {
53
- console.error("Daemon already running (lock exists). Use `sofer daemon stop` first.");
54
- process.exit(1);
79
+ export async function daemonStatus(): Promise<void> {
80
+ if (!existsSync(LOCK_FILE)) { console.log("Daemon not running."); return; }
81
+ const pid = Number(readFileSync(LOCK_FILE, "utf8").trim());
82
+ let alive = false;
83
+ try { process.kill(pid, 0); alive = true; } catch { /* dead */ }
84
+ if (!alive) { console.log("Daemon not running (stale lock)."); return; }
85
+
86
+ let uptime = "unknown";
87
+ try {
88
+ const stat = statSync(LOCK_FILE);
89
+ const sec = Math.floor((Date.now() - stat.mtimeMs) / 1000);
90
+ uptime = sec < 60 ? `${sec}s` : sec < 3600 ? `${Math.floor(sec / 60)}m` : `${Math.floor(sec / 3600)}h`;
91
+ } catch { /* */ }
92
+
93
+ console.log(` PID: ${pid}`);
94
+ console.log(` Status: running`);
95
+ console.log(` Uptime: ${uptime}`);
96
+ console.log(` Socket: ${SOCK_PATH}`);
97
+ console.log(` Lock: ${LOCK_FILE}`);
98
+ console.log(` Logs: ${LOG_FILE}`);
99
+ }
100
+
101
+ export async function daemonRestart(): Promise<void> {
102
+ await daemonStop();
103
+ await new Promise((r) => setTimeout(r, 500));
104
+ await daemonStart();
105
+ }
106
+
107
+ export async function daemonLogs(tail = 50, follow = false): Promise<void> {
108
+ if (!existsSync(LOG_FILE)) { console.log("No daemon logs found."); return; }
109
+ const lines = readFileSync(LOG_FILE, "utf8").split("\n").filter(Boolean);
110
+ const recent = lines.slice(-tail);
111
+ console.log(recent.join("\n"));
112
+
113
+ if (follow) {
114
+ const { watchFile } = require("node:fs") as typeof import("node:fs");
115
+ let count = lines.length;
116
+ watchFile(LOG_FILE, () => {
117
+ const all = readFileSync(LOG_FILE, "utf8").split("\n").filter(Boolean);
118
+ for (let i = count; i < all.length; i++) {
119
+ console.log(all[i]);
120
+ }
121
+ count = all.length;
122
+ });
123
+ // Keep alive
124
+ await new Promise(() => {});
55
125
  }
126
+ }
56
127
 
128
+ // ── Server (shared by run + start) ───────────────────────────────────────
129
+
130
+ async function runServer(): Promise<void> {
57
131
  const secrets = loadSecrets();
58
132
  if (!secrets.suiSecretKey || !secrets.anthropicApiKey) {
59
- console.error("Missing secrets. Run `sofer init` first.");
133
+ console.error("[daemon] missing secrets. Run `sofer init` first.");
60
134
  process.exit(1);
61
135
  }
62
136
 
@@ -69,103 +143,112 @@ export async function daemonStart(): Promise<void> {
69
143
  anthropicApiKey: secrets.anthropicApiKey,
70
144
  });
71
145
  } catch (e) {
72
- console.error("[daemon] failed to create agent:", (e as Error).message);
146
+ console.error("[daemon] failed:", (e as Error).message);
73
147
  releaseLock();
74
148
  process.exit(1);
75
149
  }
76
150
 
77
- // SSE clients
78
151
  let sseId = 0;
79
152
  const sseClients = new Set<SSEClient>();
80
153
 
81
154
  function broadcast(event: string, data: Record<string, unknown>): void {
82
155
  const payload = JSON.stringify(data);
83
- for (const c of sseClients) {
84
- c.res.write(`event: ${event}\ndata: ${payload}\n\n`);
156
+ for (const c of sseClients) c.res.write(`event: ${event}\ndata: ${payload}\n\n`);
157
+ }
158
+
159
+ // ── Message queue ──────────────────────────────────────────────────────
160
+ const MAX_QUEUE = 64;
161
+ let queue: Array<{ type: "http" | "telegram"; message: string; resolve: (text: string) => void; reject: (err: Error) => void }> = [];
162
+ let processing = false;
163
+
164
+ async function drainQueue(): Promise<void> {
165
+ if (processing) return;
166
+ processing = true;
167
+ broadcast("queue", { status: "processing", length: queue.length });
168
+ try {
169
+ while (queue.length > 0) {
170
+ const item = queue.shift()!;
171
+ try {
172
+ const { text } = await agent.chat(item.message);
173
+ item.resolve(text);
174
+ broadcast("response", { text, source: item.type });
175
+ } catch (e) {
176
+ item.reject(e instanceof Error ? e : new Error(String(e)));
177
+ broadcast("error", { error: (e as Error).message, source: item.type });
178
+ }
179
+ }
180
+ } finally {
181
+ processing = false;
182
+ broadcast("queue", { status: "idle", length: queue.length });
85
183
  }
86
184
  }
87
185
 
88
- // ── HTTP server ────────────────────────────────────────────────────────
186
+ function enqueue(type: "http" | "telegram", message: string): Promise<string> {
187
+ if (queue.length >= MAX_QUEUE) throw new Error("Queue full — try again later");
188
+ return new Promise<string>((resolve, reject) => {
189
+ queue.push({ type, message, resolve, reject });
190
+ drainQueue();
191
+ });
192
+ }
193
+
194
+ // Telemetry interval — report queue stats every 30s
195
+ setInterval(() => {
196
+ if (queue.length > 0 || processing) {
197
+ broadcast("telemetry", { queue: queue.length, processing, tokens: agent.usage.tokens });
198
+ }
199
+ }, 30_000);
89
200
 
90
- const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {
201
+ const server = createServer(async (req, res) => {
91
202
  res.setHeader("Access-Control-Allow-Origin", "*");
92
203
  if (req.method === "OPTIONS") { res.writeHead(204).end(); return; }
93
-
94
204
  const url = req.url ?? "/";
95
205
 
96
- // GET /healthz
97
- if (req.method === "GET" && url === "/healthz") {
98
- res.writeHead(200, { "content-type": "application/json" });
99
- res.end(JSON.stringify({ status: state, agent: agent.address.slice(0, 10), network: config.network }));
206
+ if (url === "/healthz") {
207
+ res.writeHead(200).end(JSON.stringify({ status: state, agent: agent.address.slice(0, 10), network: config.network }));
100
208
  return;
101
209
  }
102
-
103
- // GET /events (SSE)
104
- if (req.method === "GET" && url === "/events") {
105
- res.writeHead(200, {
106
- "content-type": "text/event-stream",
107
- "cache-control": "no-cache",
108
- connection: "keep-alive",
109
- });
210
+ if (url === "/events") {
211
+ res.writeHead(200, { "content-type": "text/event-stream", "cache-control": "no-cache", connection: "keep-alive" });
110
212
  const client: SSEClient = { id: ++sseId, res };
111
213
  sseClients.add(client);
112
214
  res.write(`data: ${JSON.stringify({ event: "connected", agent: agent.address })}\n\n`);
113
215
  req.on("close", () => sseClients.delete(client));
114
216
  return;
115
217
  }
116
-
117
- // POST /chat
118
218
  if (req.method === "POST" && url === "/chat") {
119
219
  const body = await readBody(req);
120
220
  try {
121
221
  const { message } = JSON.parse(body);
122
222
  if (!message) { res.writeHead(400).end("missing message"); return; }
123
223
  broadcast("thinking", { status: "thinking" });
124
- const { text } = await agent.chat(message);
125
- broadcast("response", { text });
224
+ const text = await enqueue("http", message);
126
225
  broadcast("idle", { status: "idle" });
127
- res.writeHead(200, { "content-type": "application/json" });
128
226
  res.end(JSON.stringify({ text }));
129
227
  } catch (e) {
130
- broadcast("error", { error: (e as Error).message });
131
- res.writeHead(500).end((e as Error).message);
228
+ res.writeHead(503).end(JSON.stringify({ error: (e as Error).message }));
132
229
  }
133
230
  return;
134
231
  }
135
-
136
- // POST /sync — force memory flush
137
232
  if (req.method === "POST" && url === "/sync") {
138
- broadcast("sync", { status: "syncing" });
139
- // Memory is already persisted via JSONL; trigger a fresh agent state read
140
233
  try {
141
234
  const bal = await agent.getBalance();
142
235
  broadcast("sync", { status: "done", balance: (Number(bal) / 1e9).toFixed(4) });
143
236
  res.writeHead(200).end("synced");
144
- } catch (e) {
145
- res.writeHead(500).end((e as Error).message);
146
- }
237
+ } catch (e) { res.writeHead(500).end((e as Error).message); }
147
238
  return;
148
239
  }
149
-
150
- // GET /status
151
- if (req.method === "GET" && url === "/status") {
152
- res.writeHead(200, { "content-type": "application/json" });
153
- res.end(JSON.stringify({
154
- state,
155
- agent: agent.address,
156
- name: agent.name,
157
- network: config.network,
158
- tokens: agent.usage.tokens,
159
- cost: agent.usage.costUsd.toFixed(6),
160
- }));
240
+ if (url === "/status") {
241
+ res.end(JSON.stringify({ state, agent: agent.address, name: agent.name, network: config.network, tokens: agent.usage.tokens, cost: agent.usage.costUsd.toFixed(6) }));
161
242
  return;
162
243
  }
163
-
164
- res.writeHead(404).end("not found");
244
+ if (url === "/queue") {
245
+ res.end(JSON.stringify({ length: queue.length, processing }));
246
+ return;
247
+ }
248
+ res.writeHead(404).end();
165
249
  });
166
250
 
167
- // ── Telegram ───────────────────────────────────────────────────────────
168
-
251
+ // Telegram
169
252
  const tgPath = `${agentPaths.root}/telegram.enc`;
170
253
  const tgEnc = readSecret(tgPath);
171
254
  let tgListener: TelegramListener | null = null;
@@ -174,61 +257,45 @@ export async function daemonStart(): Promise<void> {
174
257
  const raw = decryptWithKey(secrets.suiSecretKey, tgEnc);
175
258
  if (raw) {
176
259
  const tgConfig = JSON.parse(raw) as { botToken: string; allowedUserIds: number[] };
177
- tgListener = new TelegramListener({
178
- botToken: tgConfig.botToken,
179
- allowedUserIds: tgConfig.allowedUserIds,
180
- agentName: agent.name.toLowerCase(),
181
- });
260
+ tgListener = new TelegramListener({ botToken: tgConfig.botToken, allowedUserIds: tgConfig.allowedUserIds, agentName: agent.name.toLowerCase() });
182
261
  tgListener.onDispatch(async (input) => {
183
262
  broadcast("tg-message", { from: input.displayName, text: input.text.slice(0, 200) });
184
- const { text } = await agent.chat(input.text);
263
+ const text = await enqueue("telegram", input.text);
185
264
  broadcast("tg-response", { text: text.slice(0, 200) });
186
265
  return text;
187
266
  });
188
267
  }
189
- } catch { /* skip */ }
268
+ } catch { /* */ }
190
269
  }
191
270
 
192
- // ── Bind ───────────────────────────────────────────────────────────────
193
-
194
271
  const PORT = Number(process.env.SOFER_DAEMON_PORT ?? 4242);
195
-
196
- // Try Unix socket first, fall back to TCP
197
272
  try {
198
273
  if (existsSync(SOCK_PATH)) unlinkSync(SOCK_PATH);
199
274
  server.listen(SOCK_PATH, () => {
200
275
  chmodSync(SOCK_PATH, 0o600);
201
276
  state = "ready";
202
- console.log(`[daemon] ready — unix socket ${SOCK_PATH}`);
203
- console.log(`[daemon] agent: ${agent.address.slice(0, 10)}… network: ${config.network}`);
204
- if (tgListener) {
205
- console.log("[daemon] telegram: starting bot…");
206
- tgListener.start().catch((e) => console.error("[daemon] telegram:", e.message));
207
- }
277
+ console.log(`[daemon] ready — ${SOCK_PATH}`);
278
+ console.log(`[daemon] agent: ${agent.address.slice(0, 10)}… ${config.network}`);
279
+ if (tgListener) tgListener.start().catch((e) => console.error("[daemon] telegram:", e.message));
208
280
  });
209
281
  } catch {
210
282
  server.listen(PORT, () => {
211
283
  state = "ready";
212
- console.log(`[daemon] ready — tcp port ${PORT} (SOFER_DAEMON_PORT)`);
213
- console.log(`[daemon] agent: ${agent.address.slice(0, 10)}… network: ${config.network}`);
214
- if (tgListener) {
215
- tgListener.start().catch((e) => console.error("[daemon] telegram:", e.message));
216
- }
284
+ console.log(`[daemon] ready — tcp :${PORT}`);
285
+ console.log(`[daemon] agent: ${agent.address.slice(0, 10)}… ${config.network}`);
286
+ if (tgListener) tgListener.start().catch((e) => console.error("[daemon] telegram:", e.message));
217
287
  });
218
288
  }
219
289
 
220
- // ── Shutdown ───────────────────────────────────────────────────────────
221
-
222
290
  const shutdown = async () => {
223
291
  state = "shutting_down";
224
- console.log("\n[daemon] shutting down…");
292
+ console.log("[daemon] shutting down…");
225
293
  if (tgListener) await tgListener.stop().catch(() => {});
226
294
  server.close();
227
295
  releaseLock();
228
296
  try { if (existsSync(SOCK_PATH)) unlinkSync(SOCK_PATH); } catch { /* */ }
229
297
  process.exit(0);
230
298
  };
231
-
232
299
  process.on("SIGINT", shutdown);
233
300
  process.on("SIGTERM", shutdown);
234
301
  }
@@ -236,7 +303,7 @@ export async function daemonStart(): Promise<void> {
236
303
  function readBody(req: IncomingMessage): Promise<string> {
237
304
  return new Promise((resolve) => {
238
305
  let data = "";
239
- req.on("data", (chunk) => { data += chunk; });
306
+ req.on("data", (c) => { data += c; });
240
307
  req.on("end", () => resolve(data));
241
308
  });
242
309
  }