@holon-run/agentinbox 0.5.0 → 0.7.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.
@@ -5,7 +5,7 @@ const paths_1 = require("./paths");
5
5
  const feishu_1 = require("./sources/feishu");
6
6
  const github_1 = require("./sources/github");
7
7
  const remote_1 = require("./sources/remote");
8
- const remote_profiles_1 = require("./sources/remote_profiles");
8
+ const remote_modules_1 = require("./sources/remote_modules");
9
9
  const source_resolution_1 = require("./source_resolution");
10
10
  class NoopSourceAdapter {
11
11
  sourceType;
@@ -41,14 +41,14 @@ class AdapterRegistry {
41
41
  feishuDelivery = new feishu_1.FeishuDeliveryAdapter();
42
42
  githubDelivery = new github_1.GithubDeliveryAdapter();
43
43
  homeDir;
44
- remoteProfileRegistry;
44
+ remoteModuleRegistry;
45
45
  constructor(store, appendSourceEvent, options) {
46
46
  this.homeDir = options?.homeDir ?? (0, paths_1.resolveAgentInboxHome)(process.env);
47
- this.remoteProfileRegistry = options?.remoteProfileRegistry ?? new remote_profiles_1.RemoteSourceProfileRegistry();
47
+ this.remoteModuleRegistry = options?.remoteModuleRegistry ?? new remote_modules_1.RemoteSourceModuleRegistry();
48
48
  this.remoteSource = new remote_1.RemoteSourceRuntime(store, appendSourceEvent, {
49
49
  homeDir: this.homeDir,
50
50
  client: options?.remoteSourceClient,
51
- profileRegistry: this.remoteProfileRegistry,
51
+ moduleRegistry: this.remoteModuleRegistry,
52
52
  });
53
53
  }
54
54
  sourceAdapterFor(type) {
@@ -119,13 +119,13 @@ class AdapterRegistry {
119
119
  async resolveSourceIdentity(source) {
120
120
  return (0, source_resolution_1.resolveSourceIdentity)(source, {
121
121
  homeDir: this.homeDir,
122
- profileRegistry: this.remoteProfileRegistry,
122
+ moduleRegistry: this.remoteModuleRegistry,
123
123
  });
124
124
  }
125
125
  async resolveSourceSchema(source) {
126
126
  return (0, source_resolution_1.resolveSourceSchema)(source, {
127
127
  homeDir: this.homeDir,
128
- profileRegistry: this.remoteProfileRegistry,
128
+ moduleRegistry: this.remoteModuleRegistry,
129
129
  });
130
130
  }
131
131
  async projectLifecycleSignal(source, rawPayload) {
@@ -140,6 +140,12 @@ class AdapterRegistry {
140
140
  }
141
141
  return this.remoteSource.expandSubscriptionShortcut(source, input);
142
142
  }
143
+ async deriveInlinePreview(source, item) {
144
+ if (source.sourceType === "local_event") {
145
+ return null;
146
+ }
147
+ return this.remoteSource.deriveInlinePreview(source, item);
148
+ }
143
149
  status() {
144
150
  return {
145
151
  remote: this.remoteSource.status?.() ?? {},
package/dist/src/cli.js CHANGED
@@ -12,6 +12,7 @@ const control_server_1 = require("./control_server");
12
12
  const current_agent_1 = require("./current_agent");
13
13
  const daemon_1 = require("./daemon");
14
14
  const http_1 = require("./http");
15
+ const logging_1 = require("./logging");
15
16
  const paths_1 = require("./paths");
16
17
  const service_1 = require("./service");
17
18
  const store_1 = require("./store");
@@ -555,27 +556,37 @@ async function main() {
555
556
  }
556
557
  async function runServe(args) {
557
558
  const port = parseOptionalNumber(takeFlagValue(args, "--port"));
559
+ const homeOverride = takeFlagValue(args, "--home");
558
560
  const serveConfig = (0, paths_1.resolveServeConfig)({
559
561
  env: process.env,
560
- homeDirOverride: takeFlagValue(args, "--home"),
562
+ homeDirOverride: homeOverride,
561
563
  statePathOverride: takeFlagValue(args, "--state"),
562
564
  socketPathOverride: takeFlagValue(args, "--socket"),
563
565
  portOverride: port,
564
566
  });
567
+ const daemonPaths = (0, paths_1.resolveDaemonPaths)(process.env, homeOverride);
568
+ const logLevel = (0, logging_1.parseLogLevel)(takeFlagValue(args, "--log-level") ?? process.env.AGENTINBOX_LOG_LEVEL);
569
+ const logger = new logging_1.JsonLogger(logLevel, "agentinbox");
565
570
  const store = await store_1.AgentInboxStore.open(serveConfig.dbPath);
566
571
  let service;
567
572
  const adapters = new adapters_1.AdapterRegistry(store, async (input) => service.appendSourceEvent(input), {
568
573
  homeDir: serveConfig.homeDir,
569
574
  });
570
- service = new service_1.AgentInboxService(store, adapters);
575
+ service = new service_1.AgentInboxService(store, adapters, undefined, undefined, undefined, undefined, undefined, logger.child("service"));
571
576
  const server = (0, http_1.createServer)(service);
572
577
  await adapters.start();
573
578
  await service.start();
574
579
  const controlServer = await (0, control_server_1.startControlServer)(server, serveConfig.transport);
575
- const daemonPaths = (0, paths_1.resolveDaemonPaths)(process.env, takeFlagValue(args, "--home"));
576
580
  if (serveConfig.transport.kind === "socket") {
577
581
  (0, daemon_1.writePidFile)(daemonPaths.pidPath, process.pid);
578
582
  }
583
+ (0, daemon_1.writeDaemonMetadata)(daemonPaths.metadataPath, { logLevel });
584
+ logger.info("daemon.ready", {
585
+ homeDir: serveConfig.homeDir,
586
+ dbPath: serveConfig.dbPath,
587
+ transport: controlServer.info,
588
+ logLevel,
589
+ });
579
590
  console.log((0, util_1.jsonResponse)({
580
591
  ok: true,
581
592
  homeDir: serveConfig.homeDir,
@@ -590,6 +601,7 @@ async function runServe(args) {
590
601
  if (serveConfig.transport.kind === "socket") {
591
602
  (0, daemon_1.removePidFile)(daemonPaths.pidPath);
592
603
  }
604
+ (0, daemon_1.removePidFile)(daemonPaths.metadataPath);
593
605
  process.exit(0);
594
606
  });
595
607
  };
@@ -603,6 +615,7 @@ async function runDaemon(args) {
603
615
  homeDirOverride: takeFlagValue(args, "--home"),
604
616
  socketPathOverride: takeFlagValue(args, "--socket"),
605
617
  baseUrlOverride: takeFlagValue(args, "--url"),
618
+ logLevelOverride: (0, logging_1.parseLogLevel)(takeFlagValue(args, "--log-level") ?? process.env.AGENTINBOX_LOG_LEVEL),
606
619
  };
607
620
  if (action === "start") {
608
621
  const result = await (0, daemon_1.startDaemon)(options);
@@ -888,13 +901,13 @@ Commands:
888
901
  serve: `agentinbox serve
889
902
 
890
903
  Usage:
891
- agentinbox serve [--home ~/.agentinbox] [--socket ~/.agentinbox/agentinbox.sock]
904
+ agentinbox serve [--home ~/.agentinbox] [--socket ~/.agentinbox/agentinbox.sock] [--log-level error|warn|info|debug|trace]
892
905
  agentinbox serve --port 4747 [--state ~/.agentinbox/agentinbox.sqlite]
893
906
  `,
894
907
  daemon: `agentinbox daemon
895
908
 
896
909
  Usage:
897
- agentinbox daemon start [--home ~/.agentinbox] [--socket ~/.agentinbox/agentinbox.sock]
910
+ agentinbox daemon start [--home ~/.agentinbox] [--socket ~/.agentinbox/agentinbox.sock] [--log-level error|warn|info|debug|trace]
898
911
  agentinbox daemon stop [--home ~/.agentinbox] [--socket ~/.agentinbox/agentinbox.sock]
899
912
  agentinbox daemon status [--home ~/.agentinbox] [--socket ~/.agentinbox/agentinbox.sock]
900
913
  `,
@@ -9,11 +9,14 @@ exports.stopDaemon = stopDaemon;
9
9
  exports.daemonStatus = daemonStatus;
10
10
  exports.writePidFile = writePidFile;
11
11
  exports.removePidFile = removePidFile;
12
+ exports.resolveDaemonLogLevel = resolveDaemonLogLevel;
13
+ exports.writeDaemonMetadata = writeDaemonMetadata;
12
14
  const node_fs_1 = __importDefault(require("node:fs"));
13
15
  const node_path_1 = __importDefault(require("node:path"));
14
16
  const node_child_process_1 = require("node:child_process");
15
17
  const client_1 = require("./client");
16
18
  const paths_1 = require("./paths");
19
+ const logging_1 = require("./logging");
17
20
  const START_TIMEOUT_MS = 15_000;
18
21
  const PACKAGE_VERSION = readOwnPackageVersion();
19
22
  async function ensureDaemonForClient(options = {}) {
@@ -30,6 +33,7 @@ async function ensureDaemonForClient(options = {}) {
30
33
  async function startDaemon(options = {}) {
31
34
  const env = options.env ?? process.env;
32
35
  const transport = requireSocketTransport(resolveDaemonClientTransport(options), "daemon start");
36
+ const logLevel = resolveDaemonLogLevel(env, options.logLevelOverride);
33
37
  const homeDir = (0, paths_1.resolveAgentInboxHome)(env, options.homeDirOverride);
34
38
  const { pidPath, logPath } = (0, paths_1.resolveDaemonPaths)(env, options.homeDirOverride);
35
39
  node_fs_1.default.mkdirSync(homeDir, { recursive: true });
@@ -39,6 +43,7 @@ async function startDaemon(options = {}) {
39
43
  return {
40
44
  started: false,
41
45
  pid: pid ?? -1,
46
+ logLevel,
42
47
  pidPath,
43
48
  logPath,
44
49
  transport,
@@ -54,6 +59,7 @@ async function startDaemon(options = {}) {
54
59
  AGENTINBOX_HOME: homeDir,
55
60
  AGENTINBOX_SOCKET: transport.socketPath,
56
61
  AGENTINBOX_URL: "",
62
+ AGENTINBOX_LOG_LEVEL: logLevel,
57
63
  },
58
64
  detached: true,
59
65
  stdio: ["ignore", logFd, logFd],
@@ -67,6 +73,7 @@ async function startDaemon(options = {}) {
67
73
  return {
68
74
  started: true,
69
75
  pid: child.pid ?? -1,
76
+ logLevel,
70
77
  pidPath,
71
78
  logPath,
72
79
  transport,
@@ -75,7 +82,7 @@ async function startDaemon(options = {}) {
75
82
  async function stopDaemon(options = {}) {
76
83
  const env = options.env ?? process.env;
77
84
  const transport = requireSocketTransport(resolveDaemonClientTransport(options), "daemon stop");
78
- const { pidPath, logPath } = (0, paths_1.resolveDaemonPaths)(env, options.homeDirOverride);
85
+ const { pidPath, logPath, metadataPath } = (0, paths_1.resolveDaemonPaths)(env, options.homeDirOverride);
79
86
  const pid = readPidFile(pidPath);
80
87
  if (pid != null && isProcessAlive(pid)) {
81
88
  process.kill(pid, "SIGTERM");
@@ -83,19 +90,22 @@ async function stopDaemon(options = {}) {
83
90
  }
84
91
  cleanupStalePidFile(pidPath, true);
85
92
  cleanupFile(transport.socketPath);
93
+ cleanupFile(metadataPath);
86
94
  return daemonStatus(options);
87
95
  }
88
96
  async function daemonStatus(options = {}) {
89
97
  const env = options.env ?? process.env;
90
98
  const transport = requireSocketTransport(resolveDaemonClientTransport(options), "daemon status");
91
- const { pidPath, logPath } = (0, paths_1.resolveDaemonPaths)(env, options.homeDirOverride);
99
+ const { pidPath, logPath, metadataPath } = (0, paths_1.resolveDaemonPaths)(env, options.homeDirOverride);
92
100
  const pid = readPidFile(pidPath);
93
101
  if (pid != null && !isProcessAlive(pid)) {
94
102
  cleanupStalePidFile(pidPath, true);
95
103
  cleanupFile(transport.socketPath);
104
+ cleanupFile(metadataPath);
96
105
  return {
97
106
  running: false,
98
107
  pid: null,
108
+ logLevel: null,
99
109
  version: null,
100
110
  startedAt: null,
101
111
  command: null,
@@ -106,9 +116,11 @@ async function daemonStatus(options = {}) {
106
116
  };
107
117
  }
108
118
  const processInfo = pid == null ? null : readProcessMetadata(pid);
119
+ const daemonMetadata = readDaemonMetadata(metadataPath);
109
120
  return {
110
121
  running: await canReachHealthz(transport),
111
122
  pid,
123
+ logLevel: daemonMetadata?.logLevel ?? null,
112
124
  version: pid == null ? null : PACKAGE_VERSION,
113
125
  startedAt: processInfo?.startedAt ?? null,
114
126
  command: processInfo?.command ?? null,
@@ -237,6 +249,28 @@ function cleanupStalePidFile(pidPath, force = false) {
237
249
  cleanupFile(pidPath);
238
250
  }
239
251
  }
252
+ function resolveDaemonLogLevel(env = process.env, override) {
253
+ if (override) {
254
+ return override;
255
+ }
256
+ return (0, logging_1.parseLogLevel)(env.AGENTINBOX_LOG_LEVEL, (0, logging_1.defaultLogLevel)());
257
+ }
258
+ function writeDaemonMetadata(metadataPath, metadata) {
259
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(metadataPath), { recursive: true });
260
+ node_fs_1.default.writeFileSync(metadataPath, JSON.stringify(metadata), "utf8");
261
+ }
262
+ function readDaemonMetadata(metadataPath) {
263
+ try {
264
+ const parsed = JSON.parse(node_fs_1.default.readFileSync(metadataPath, "utf8"));
265
+ if ((0, logging_1.isLogLevel)(parsed.logLevel)) {
266
+ return { logLevel: parsed.logLevel };
267
+ }
268
+ return null;
269
+ }
270
+ catch {
271
+ return null;
272
+ }
273
+ }
240
274
  function readPidFile(pidPath) {
241
275
  try {
242
276
  const raw = node_fs_1.default.readFileSync(pidPath, "utf8").trim();
package/dist/src/http.js CHANGED
@@ -1280,6 +1280,7 @@ function isBadRequestError(message) {
1280
1280
  message.startsWith("invalid webhook activation target") ||
1281
1281
  message.startsWith("remote_source requires") ||
1282
1282
  message.startsWith("remote_source profile") ||
1283
+ message.startsWith("remote_source module") ||
1283
1284
  message.includes("requires tmuxPaneId") ||
1284
1285
  message.includes("requires iTerm2 session identity") ||
1285
1286
  message.includes("requires a supported terminal context") ||
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JsonLogger = exports.NoopLogger = void 0;
4
+ exports.parseLogLevel = parseLogLevel;
5
+ exports.isLogLevel = isLogLevel;
6
+ exports.defaultLogLevel = defaultLogLevel;
7
+ const LOG_LEVEL_RANK = {
8
+ error: 0,
9
+ warn: 1,
10
+ info: 2,
11
+ debug: 3,
12
+ trace: 4,
13
+ };
14
+ const LOG_LEVELS = new Set(["error", "warn", "info", "debug", "trace"]);
15
+ const DEFAULT_LOG_LEVEL = "info";
16
+ class NoopLogger {
17
+ level;
18
+ constructor(level = DEFAULT_LOG_LEVEL) {
19
+ this.level = level;
20
+ }
21
+ enabled(_level) {
22
+ return false;
23
+ }
24
+ child(_component) {
25
+ return this;
26
+ }
27
+ error(_event, _fields) { }
28
+ warn(_event, _fields) { }
29
+ info(_event, _fields) { }
30
+ debug(_event, _fields) { }
31
+ trace(_event, _fields) { }
32
+ }
33
+ exports.NoopLogger = NoopLogger;
34
+ class JsonLogger {
35
+ level;
36
+ component;
37
+ writeLine;
38
+ constructor(level, component, writeLine = (line) => process.stdout.write(`${line}\n`)) {
39
+ this.level = level;
40
+ this.component = component;
41
+ this.writeLine = writeLine;
42
+ }
43
+ enabled(level) {
44
+ return LOG_LEVEL_RANK[level] <= LOG_LEVEL_RANK[this.level];
45
+ }
46
+ child(component) {
47
+ return new JsonLogger(this.level, `${this.component}.${component}`, this.writeLine);
48
+ }
49
+ error(event, fields) {
50
+ this.log("error", event, fields);
51
+ }
52
+ warn(event, fields) {
53
+ this.log("warn", event, fields);
54
+ }
55
+ info(event, fields) {
56
+ this.log("info", event, fields);
57
+ }
58
+ debug(event, fields) {
59
+ this.log("debug", event, fields);
60
+ }
61
+ trace(event, fields) {
62
+ this.log("trace", event, fields);
63
+ }
64
+ log(level, event, fields) {
65
+ if (!this.enabled(level)) {
66
+ return;
67
+ }
68
+ this.writeLine(JSON.stringify({
69
+ ts: new Date().toISOString(),
70
+ level,
71
+ component: this.component,
72
+ event,
73
+ ...(fields ? serializeFields(fields) : {}),
74
+ }));
75
+ }
76
+ }
77
+ exports.JsonLogger = JsonLogger;
78
+ function parseLogLevel(value, fallback = DEFAULT_LOG_LEVEL) {
79
+ if (typeof value !== "string") {
80
+ return fallback;
81
+ }
82
+ const normalized = value.trim().toLowerCase();
83
+ if (LOG_LEVELS.has(normalized)) {
84
+ return normalized;
85
+ }
86
+ return fallback;
87
+ }
88
+ function isLogLevel(value) {
89
+ return typeof value === "string" && LOG_LEVELS.has(value);
90
+ }
91
+ function defaultLogLevel() {
92
+ return DEFAULT_LOG_LEVEL;
93
+ }
94
+ function serializeFields(fields) {
95
+ return Object.fromEntries(Object.entries(fields).map(([key, value]) => [key, serializeValue(value)]));
96
+ }
97
+ function serializeValue(value) {
98
+ if (value instanceof Error) {
99
+ return {
100
+ name: value.name,
101
+ message: value.message,
102
+ stack: value.stack,
103
+ };
104
+ }
105
+ if (Array.isArray(value)) {
106
+ return value.map((entry) => serializeValue(entry));
107
+ }
108
+ if (value && typeof value === "object") {
109
+ return Object.fromEntries(Object.entries(value).map(([key, nested]) => [key, serializeValue(nested)]));
110
+ }
111
+ return value;
112
+ }
package/dist/src/paths.js CHANGED
@@ -71,6 +71,7 @@ function resolveDaemonPaths(env = process.env, homeDirOverride) {
71
71
  return {
72
72
  pidPath: node_path_1.default.join(homeDir, "agentinbox.pid"),
73
73
  logPath: node_path_1.default.join(homeDir, "agentinbox.log"),
74
+ metadataPath: node_path_1.default.join(homeDir, "agentinbox.daemon.json"),
74
75
  };
75
76
  }
76
77
  function resolveClientTransport(input = {}) {