@holon-run/agentinbox 0.6.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.
@@ -9,6 +9,7 @@ const source_resolution_1 = require("./source_resolution");
9
9
  const filter_1 = require("./filter");
10
10
  const terminal_1 = require("./terminal");
11
11
  const runtime_gate_1 = require("./runtime_gate");
12
+ const logging_1 = require("./logging");
12
13
  const DEFAULT_SUBSCRIPTION_POLL_LIMIT = 100;
13
14
  const DEFAULT_ACTIVATION_WINDOW_MS = 3_000;
14
15
  const DEFAULT_ACTIVATION_MAX_ITEMS = 20;
@@ -43,7 +44,7 @@ class AgentInboxService {
43
44
  lastAckedInboxGcAt = 0;
44
45
  lastLifecycleCleanupAt = 0;
45
46
  lastOfflineAgentGcAt = 0;
46
- constructor(store, adapters, activationDispatcher = new ActivationDispatcher(), backend, activationPolicy, terminalDispatcher = new terminal_1.TerminalDispatcher(), activationGate = new runtime_gate_1.DefaultActivationGate()) {
47
+ constructor(store, adapters, activationDispatcher = new ActivationDispatcher(), backend, activationPolicy, terminalDispatcher = new terminal_1.TerminalDispatcher(), activationGate, logger = new logging_1.NoopLogger()) {
47
48
  this.store = store;
48
49
  this.adapters = adapters;
49
50
  this.activationDispatcher = activationDispatcher;
@@ -52,11 +53,13 @@ class AgentInboxService {
52
53
  this.activationMaxItems = activationPolicy?.maxItems ?? DEFAULT_ACTIVATION_MAX_ITEMS;
53
54
  this.ackedRetentionMs = DEFAULT_ACKED_RETENTION_MS;
54
55
  this.terminalDispatcher = terminalDispatcher;
55
- this.activationGate = activationGate;
56
+ this.logger = logger;
57
+ this.activationGate = activationGate ?? new runtime_gate_1.DefaultActivationGate(undefined, undefined, this.logger.child("gate"));
56
58
  }
57
59
  activationDispatcher;
58
60
  terminalDispatcher;
59
61
  activationGate;
62
+ logger;
60
63
  async start() {
61
64
  if (this.syncInterval) {
62
65
  return;
@@ -1550,12 +1553,32 @@ class AgentInboxService {
1550
1553
  try {
1551
1554
  if (target.kind === "terminal") {
1552
1555
  const gate = await this.activationGate.evaluate(target);
1556
+ this.logger.debug("activation.gate_decision", {
1557
+ agentId: input.agentId,
1558
+ targetId: target.targetId,
1559
+ runtimeKind: target.runtimeKind,
1560
+ backend: target.backend,
1561
+ outcome: gate.outcome,
1562
+ reason: gate.reason,
1563
+ });
1553
1564
  if (gate.outcome === "offline") {
1565
+ this.logger.info("activation.target_offline", {
1566
+ agentId: input.agentId,
1567
+ targetId: target.targetId,
1568
+ reason: gate.reason,
1569
+ transition: "runtime_gate",
1570
+ });
1554
1571
  this.markActivationTargetOffline(target.targetId, `runtime gate: ${gate.reason}`);
1555
1572
  this.reconcileAgentStatus(target.agentId);
1556
1573
  return "offline";
1557
1574
  }
1558
1575
  if (gate.outcome === "defer") {
1576
+ this.logger.debug("activation.dispatch_deferred", {
1577
+ agentId: input.agentId,
1578
+ targetId: target.targetId,
1579
+ reason: gate.reason,
1580
+ retryMs: DEFAULT_NOTIFY_RETRY_MS,
1581
+ });
1559
1582
  this.store.upsertActivationDispatchState({
1560
1583
  agentId: input.agentId,
1561
1584
  targetId: input.targetId,
@@ -1594,6 +1617,11 @@ class AgentInboxService {
1594
1617
  terminalPrompt = prompt;
1595
1618
  const promptFingerprint = terminalReminderFingerprint(prompt, input.items);
1596
1619
  if (state?.status === "dirty" && state.lastNotifiedFingerprint === promptFingerprint) {
1620
+ this.logger.debug("activation.dispatch_suppressed", {
1621
+ agentId: input.agentId,
1622
+ targetId: target.targetId,
1623
+ reason: "unchanged_terminal_prompt",
1624
+ });
1597
1625
  this.store.upsertActivationDispatchState({
1598
1626
  agentId: input.agentId,
1599
1627
  targetId: input.targetId,
@@ -1608,7 +1636,19 @@ class AgentInboxService {
1608
1636
  });
1609
1637
  return "suppressed";
1610
1638
  }
1639
+ this.logger.debug("activation.terminal_dispatch_start", {
1640
+ agentId: input.agentId,
1641
+ targetId: target.targetId,
1642
+ totalUnackedCount,
1643
+ newItemCount: input.newItemCount,
1644
+ sourceIds: input.sourceIds,
1645
+ subscriptionIds: input.subscriptionIds,
1646
+ });
1611
1647
  await this.terminalDispatcher.dispatch(target, prompt);
1648
+ this.logger.debug("activation.terminal_dispatch_succeeded", {
1649
+ agentId: input.agentId,
1650
+ targetId: target.targetId,
1651
+ });
1612
1652
  }
1613
1653
  else {
1614
1654
  const activation = {
@@ -1648,11 +1688,28 @@ class AgentInboxService {
1648
1688
  return "dispatched";
1649
1689
  }
1650
1690
  catch (error) {
1651
- console.warn(`activation target dispatch failed for ${target.targetId}:`, error);
1652
1691
  const message = error instanceof Error ? error.message : String(error);
1692
+ this.logger.warn("activation.dispatch_failed", {
1693
+ agentId: input.agentId,
1694
+ targetId: target.targetId,
1695
+ targetKind: target.kind,
1696
+ error,
1697
+ message,
1698
+ });
1653
1699
  if (target.kind === "terminal") {
1654
1700
  const exists = await this.terminalDispatcher.probe(target);
1701
+ this.logger.debug("activation.terminal_probe_after_failure", {
1702
+ agentId: input.agentId,
1703
+ targetId: target.targetId,
1704
+ exists,
1705
+ });
1655
1706
  if (!exists) {
1707
+ this.logger.info("activation.target_offline", {
1708
+ agentId: input.agentId,
1709
+ targetId: target.targetId,
1710
+ reason: message,
1711
+ transition: "dispatch_probe",
1712
+ });
1656
1713
  this.markActivationTargetOffline(target.targetId, message);
1657
1714
  this.reconcileAgentStatus(target.agentId);
1658
1715
  return "offline";
@@ -4,7 +4,7 @@ exports.resolveSourceIdentity = resolveSourceIdentity;
4
4
  exports.resolveSourceSchema = resolveSourceSchema;
5
5
  exports.withResolvedIdentity = withResolvedIdentity;
6
6
  const paths_1 = require("./paths");
7
- const remote_profiles_1 = require("./sources/remote_profiles");
7
+ const remote_modules_1 = require("./sources/remote_modules");
8
8
  const source_schema_1 = require("./source_schema");
9
9
  async function resolveSourceIdentity(source, context = {}) {
10
10
  if (source.sourceType === "local_event") {
@@ -14,7 +14,7 @@ async function resolveSourceIdentity(source, context = {}) {
14
14
  implementationId: "builtin.local_event",
15
15
  };
16
16
  }
17
- const builtinImplementationId = (0, remote_profiles_1.builtInProfileIdForSourceType)(source.sourceType);
17
+ const builtinImplementationId = (0, remote_modules_1.builtInModuleIdForSourceType)(source.sourceType);
18
18
  if (builtinImplementationId) {
19
19
  return {
20
20
  hostType: "remote_source",
@@ -25,30 +25,30 @@ async function resolveSourceIdentity(source, context = {}) {
25
25
  if (source.sourceType !== "remote_source") {
26
26
  throw new Error(`unsupported source type for source resolution: ${source.sourceType}`);
27
27
  }
28
- const profileRegistry = context.profileRegistry ?? new remote_profiles_1.RemoteSourceProfileRegistry();
28
+ const moduleRegistry = context.moduleRegistry ?? context.profileRegistry ?? new remote_modules_1.RemoteSourceModuleRegistry();
29
29
  const homeDir = context.homeDir ?? (0, paths_1.resolveAgentInboxHome)(process.env);
30
- const profile = await profileRegistry.resolve(source, homeDir);
31
- const capabilityDescription = typeof profile.describeCapabilities === "function"
32
- ? profile.describeCapabilities(profileInputSource(source))
30
+ const module = await moduleRegistry.resolve(source, homeDir);
31
+ const capabilityDescription = typeof module.describeCapabilities === "function"
32
+ ? module.describeCapabilities(moduleInputSource(source))
33
33
  : undefined;
34
34
  return {
35
35
  hostType: "remote_source",
36
- sourceKind: capabilityDescription?.sourceKind?.trim() || `remote:${profile.id}`,
37
- implementationId: profile.id,
36
+ sourceKind: capabilityDescription?.sourceKind?.trim() || `remote:${module.id}`,
37
+ implementationId: module.id,
38
38
  };
39
39
  }
40
40
  async function resolveSourceSchema(source, context = {}) {
41
- const profileRegistry = context.profileRegistry ?? new remote_profiles_1.RemoteSourceProfileRegistry();
41
+ const moduleRegistry = context.moduleRegistry ?? context.profileRegistry ?? new remote_modules_1.RemoteSourceModuleRegistry();
42
42
  const homeDir = context.homeDir ?? (0, paths_1.resolveAgentInboxHome)(process.env);
43
- const resolvedContext = { ...context, profileRegistry, homeDir };
43
+ const resolvedContext = { ...context, moduleRegistry, homeDir };
44
44
  const identity = await resolveSourceIdentity(source, resolvedContext);
45
45
  const staticSchema = (0, source_schema_1.getSourceSchema)(source.sourceType);
46
46
  let capabilityDescription;
47
- let profile = null;
47
+ let module = null;
48
48
  if (identity.hostType === "remote_source") {
49
- profile = await profileRegistry.resolve(source, homeDir);
50
- capabilityDescription = typeof profile.describeCapabilities === "function"
51
- ? profile.describeCapabilities(profileInputSource(source))
49
+ module = await moduleRegistry.resolve(source, homeDir);
50
+ capabilityDescription = typeof module.describeCapabilities === "function"
51
+ ? module.describeCapabilities(moduleInputSource(source))
52
52
  : undefined;
53
53
  }
54
54
  return withResolvedIdentity(source.sourceId, {
@@ -60,10 +60,10 @@ async function resolveSourceSchema(source, context = {}) {
60
60
  }, identity, identity.hostType === "remote_source"
61
61
  ? {
62
62
  aliases: capabilityDescription?.aliases,
63
- supportsTrackedResourceRef: typeof profile?.deriveTrackedResource === "function",
64
- supportsLifecycleSignals: typeof profile?.projectLifecycleSignal === "function",
65
- shortcuts: typeof profile?.listSubscriptionShortcuts === "function"
66
- ? profile.listSubscriptionShortcuts(profileInputSource(source))
63
+ supportsTrackedResourceRef: typeof module?.deriveTrackedResource === "function",
64
+ supportsLifecycleSignals: typeof module?.projectLifecycleSignal === "function",
65
+ shortcuts: typeof module?.listSubscriptionShortcuts === "function"
66
+ ? module.listSubscriptionShortcuts(moduleInputSource(source))
67
67
  : [],
68
68
  }
69
69
  : undefined);
@@ -89,12 +89,12 @@ function withResolvedIdentity(sourceId, schema, identity, capabilityMetadata) {
89
89
  } : {}),
90
90
  };
91
91
  }
92
- function profileInputSource(source) {
92
+ function moduleInputSource(source) {
93
93
  if (source.sourceType !== "remote_source") {
94
94
  return source;
95
95
  }
96
96
  return {
97
97
  ...source,
98
- config: (0, remote_profiles_1.profileConfigForSource)(source),
98
+ config: (0, remote_modules_1.moduleConfigForSource)(source),
99
99
  };
100
100
  }
@@ -21,8 +21,8 @@ const SOURCE_SCHEMAS = {
21
21
  payloadExamples: [],
22
22
  eventVariantExamples: [],
23
23
  configFields: [
24
- { name: "profilePath", type: "string", required: true, description: "Local profile module path under $AGENTINBOX_HOME/source-profiles." },
25
- { name: "profileConfig", type: "object", required: false, description: "Profile-specific configuration passed to validate/spec/map hooks." },
24
+ { name: "profilePath", type: "string", required: true, description: "Local module path under $AGENTINBOX_HOME/source-profiles." },
25
+ { name: "profileConfig", type: "object", required: false, description: "Module-specific configuration passed to validate/spec/map hooks." },
26
26
  ],
27
27
  },
28
28
  github_repo: {
@@ -4,7 +4,7 @@ exports.RemoteSourceRuntime = exports.RpcUxcRemoteSourceClient = void 0;
4
4
  const uxc_daemon_client_1 = require("@holon-run/uxc-daemon-client");
5
5
  const paths_1 = require("../paths");
6
6
  const util_1 = require("../util");
7
- const remote_profiles_1 = require("./remote_profiles");
7
+ const remote_modules_1 = require("./remote_modules");
8
8
  const REMOTE_SOURCE_TYPES = new Set([
9
9
  "remote_source",
10
10
  "github_repo",
@@ -55,7 +55,7 @@ exports.RpcUxcRemoteSourceClient = RpcUxcRemoteSourceClient;
55
55
  class RemoteSourceRuntime {
56
56
  store;
57
57
  appendSourceEvent;
58
- profileRegistry;
58
+ moduleRegistry;
59
59
  client;
60
60
  interval = null;
61
61
  inFlight = new Set();
@@ -65,7 +65,7 @@ class RemoteSourceRuntime {
65
65
  constructor(store, appendSourceEvent, options) {
66
66
  this.store = store;
67
67
  this.appendSourceEvent = appendSourceEvent;
68
- this.profileRegistry = options?.profileRegistry ?? new remote_profiles_1.RemoteSourceProfileRegistry();
68
+ this.moduleRegistry = options?.moduleRegistry ?? options?.profileRegistry ?? new remote_modules_1.RemoteSourceModuleRegistry();
69
69
  this.client = options?.client ?? new RpcUxcRemoteSourceClient();
70
70
  this.homeDir = options?.homeDir ?? (0, paths_1.resolveAgentInboxHome)(process.env);
71
71
  }
@@ -79,10 +79,10 @@ class RemoteSourceRuntime {
79
79
  if (!REMOTE_SOURCE_TYPES.has(source.sourceType)) {
80
80
  return;
81
81
  }
82
- const profile = await this.profileRegistry.resolve(source, this.homeDir);
83
- const profileSource = profileInputSource(source);
84
- profile.validateConfig(profileSource);
85
- profile.buildManagedSourceSpec(profileSource);
82
+ const module = await this.moduleRegistry.resolve(source, this.homeDir);
83
+ const moduleSource = moduleInputSource(source);
84
+ module.validateConfig(moduleSource);
85
+ module.buildManagedSourceSpec(moduleSource);
86
86
  }
87
87
  async start() {
88
88
  if (this.interval) {
@@ -171,35 +171,35 @@ class RemoteSourceRuntime {
171
171
  if (!REMOTE_SOURCE_TYPES.has(source.sourceType)) {
172
172
  return null;
173
173
  }
174
- const profile = await this.profileRegistry.resolve(source, this.homeDir);
175
- if (typeof profile.projectLifecycleSignal !== "function") {
174
+ const module = await this.moduleRegistry.resolve(source, this.homeDir);
175
+ if (typeof module.projectLifecycleSignal !== "function") {
176
176
  return null;
177
177
  }
178
- return profile.projectLifecycleSignal(rawPayload, profileInputSource(source));
178
+ return module.projectLifecycleSignal(rawPayload, moduleInputSource(source));
179
179
  }
180
180
  async expandSubscriptionShortcut(source, input) {
181
181
  if (!REMOTE_SOURCE_TYPES.has(source.sourceType)) {
182
182
  return null;
183
183
  }
184
- const profile = await this.profileRegistry.resolve(source, this.homeDir);
185
- if (typeof profile.expandSubscriptionShortcut !== "function") {
184
+ const module = await this.moduleRegistry.resolve(source, this.homeDir);
185
+ if (typeof module.expandSubscriptionShortcut !== "function") {
186
186
  return null;
187
187
  }
188
- return profile.expandSubscriptionShortcut({
188
+ return module.expandSubscriptionShortcut({
189
189
  name: input.name,
190
190
  args: input.args,
191
- source: profileInputSource(source),
191
+ source: moduleInputSource(source),
192
192
  });
193
193
  }
194
194
  async deriveInlinePreview(source, item) {
195
195
  if (!REMOTE_SOURCE_TYPES.has(source.sourceType)) {
196
196
  return null;
197
197
  }
198
- const profile = await this.profileRegistry.resolve(source, this.homeDir);
199
- if (typeof profile.deriveInlinePreview !== "function") {
198
+ const module = await this.moduleRegistry.resolve(source, this.homeDir);
199
+ if (typeof module.deriveInlinePreview !== "function") {
200
200
  return null;
201
201
  }
202
- return profile.deriveInlinePreview(item, profileInputSource(source));
202
+ return module.deriveInlinePreview(item, moduleInputSource(source));
203
203
  }
204
204
  async syncAll() {
205
205
  const sources = this.store
@@ -255,10 +255,10 @@ class RemoteSourceRuntime {
255
255
  };
256
256
  }
257
257
  }
258
- const profile = await this.profileRegistry.resolve(source, this.homeDir);
259
- const profileSource = profileInputSource(source);
260
- profile.validateConfig(profileSource);
261
- const spec = profile.buildManagedSourceSpec(profileSource);
258
+ const module = await this.moduleRegistry.resolve(source, this.homeDir);
259
+ const moduleSource = moduleInputSource(source);
260
+ module.validateConfig(moduleSource);
261
+ const spec = module.buildManagedSourceSpec(moduleSource);
262
262
  const binding = managedBindingForSource(source);
263
263
  const ensured = await this.client.sourceEnsure({
264
264
  namespace: binding.namespace,
@@ -279,7 +279,7 @@ class RemoteSourceRuntime {
279
279
  if (Object.keys(rawPayload).length === 0) {
280
280
  continue;
281
281
  }
282
- const mapped = profile.mapRawEvent(rawPayload, profileSource);
282
+ const mapped = module.mapRawEvent(rawPayload, moduleSource);
283
283
  if (!mapped) {
284
284
  continue;
285
285
  }
@@ -348,7 +348,7 @@ class RemoteSourceRuntime {
348
348
  }
349
349
  }
350
350
  exports.RemoteSourceRuntime = RemoteSourceRuntime;
351
- function profileInputSource(source) {
351
+ function moduleInputSource(source) {
352
352
  if (source.sourceType !== "remote_source") {
353
353
  return source;
354
354
  }