@mono-agent/agent-app 0.20.11 → 0.20.14

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 (220) hide show
  1. package/README.md +33 -18
  2. package/dist/app-controller-channels.d.ts +4 -0
  3. package/dist/app-controller-channels.d.ts.map +1 -1
  4. package/dist/app-controller-channels.js +20 -2
  5. package/dist/app-controller-channels.js.map +1 -1
  6. package/dist/app-controller-continuation.d.ts.map +1 -1
  7. package/dist/app-controller-continuation.js +2 -3
  8. package/dist/app-controller-continuation.js.map +1 -1
  9. package/dist/app-controller-lifecycle.d.ts +4 -0
  10. package/dist/app-controller-lifecycle.d.ts.map +1 -1
  11. package/dist/app-controller-lifecycle.js +7 -0
  12. package/dist/app-controller-lifecycle.js.map +1 -1
  13. package/dist/app-controller-monitors.d.ts +26 -0
  14. package/dist/app-controller-monitors.d.ts.map +1 -0
  15. package/dist/app-controller-monitors.js +127 -0
  16. package/dist/app-controller-monitors.js.map +1 -0
  17. package/dist/app-controller-responder.d.ts +7 -17
  18. package/dist/app-controller-responder.d.ts.map +1 -1
  19. package/dist/app-controller-responder.js +33 -69
  20. package/dist/app-controller-responder.js.map +1 -1
  21. package/dist/app-controller-utils.d.ts +1 -5
  22. package/dist/app-controller-utils.d.ts.map +1 -1
  23. package/dist/app-controller-utils.js +4 -21
  24. package/dist/app-controller-utils.js.map +1 -1
  25. package/dist/app-controller.d.ts +24 -10
  26. package/dist/app-controller.d.ts.map +1 -1
  27. package/dist/app-controller.js +36 -1
  28. package/dist/app-controller.js.map +1 -1
  29. package/dist/channel-drivers/slack.d.ts.map +1 -1
  30. package/dist/channel-drivers/slack.js +18 -0
  31. package/dist/channel-drivers/slack.js.map +1 -1
  32. package/dist/channel-drivers/telegram.d.ts.map +1 -1
  33. package/dist/channel-drivers/telegram.js +26 -0
  34. package/dist/channel-drivers/telegram.js.map +1 -1
  35. package/dist/channel-drivers/tui.d.ts +68 -8
  36. package/dist/channel-drivers/tui.d.ts.map +1 -1
  37. package/dist/channel-drivers/tui.js +388 -89
  38. package/dist/channel-drivers/tui.js.map +1 -1
  39. package/dist/channel-runtime-controls.d.ts +2 -1
  40. package/dist/channel-runtime-controls.d.ts.map +1 -1
  41. package/dist/channel-runtime-controls.js +79 -22
  42. package/dist/channel-runtime-controls.js.map +1 -1
  43. package/dist/cli-args.d.ts +4 -6
  44. package/dist/cli-args.d.ts.map +1 -1
  45. package/dist/cli-args.js +16 -36
  46. package/dist/cli-args.js.map +1 -1
  47. package/dist/cli-commands.d.ts.map +1 -1
  48. package/dist/cli-commands.js +11 -0
  49. package/dist/cli-commands.js.map +1 -1
  50. package/dist/cli-help.d.ts +26 -0
  51. package/dist/cli-help.d.ts.map +1 -1
  52. package/dist/cli-help.js +25 -34
  53. package/dist/cli-help.js.map +1 -1
  54. package/dist/cli-init-command.d.ts +1 -2
  55. package/dist/cli-init-command.d.ts.map +1 -1
  56. package/dist/cli-init-command.js +5 -49
  57. package/dist/cli-init-command.js.map +1 -1
  58. package/dist/config-reference.d.ts.map +1 -1
  59. package/dist/config-reference.js +153 -52
  60. package/dist/config-reference.js.map +1 -1
  61. package/dist/configuration-proposal-tool.d.ts.map +1 -1
  62. package/dist/configuration-proposal-tool.js +3 -11
  63. package/dist/configuration-proposal-tool.js.map +1 -1
  64. package/dist/configured-agent.d.ts +18 -3
  65. package/dist/configured-agent.d.ts.map +1 -1
  66. package/dist/configured-agent.js +67 -86
  67. package/dist/configured-agent.js.map +1 -1
  68. package/dist/conversation-title.d.ts.map +1 -1
  69. package/dist/conversation-title.js +9 -2
  70. package/dist/conversation-title.js.map +1 -1
  71. package/dist/doctor.d.ts +7 -13
  72. package/dist/doctor.d.ts.map +1 -1
  73. package/dist/doctor.js +191 -725
  74. package/dist/doctor.js.map +1 -1
  75. package/dist/first-run-readiness.d.ts.map +1 -1
  76. package/dist/first-run-readiness.js +0 -6
  77. package/dist/first-run-readiness.js.map +1 -1
  78. package/dist/local-configuration.d.ts.map +1 -1
  79. package/dist/local-configuration.js +9 -37
  80. package/dist/local-configuration.js.map +1 -1
  81. package/dist/memory-remember.d.ts +49 -0
  82. package/dist/memory-remember.d.ts.map +1 -0
  83. package/dist/memory-remember.js +190 -0
  84. package/dist/memory-remember.js.map +1 -0
  85. package/dist/memory-retrieval.d.ts +24 -0
  86. package/dist/memory-retrieval.d.ts.map +1 -1
  87. package/dist/memory-retrieval.js +23 -0
  88. package/dist/memory-retrieval.js.map +1 -1
  89. package/dist/model-effort-capabilities.d.ts +8 -9
  90. package/dist/model-effort-capabilities.d.ts.map +1 -1
  91. package/dist/model-effort-capabilities.js +17 -35
  92. package/dist/model-effort-capabilities.js.map +1 -1
  93. package/dist/modules/base.d.ts +3 -4
  94. package/dist/modules/base.d.ts.map +1 -1
  95. package/dist/modules/base.js +3 -5
  96. package/dist/modules/base.js.map +1 -1
  97. package/dist/modules/catalog.d.ts.map +1 -1
  98. package/dist/modules/catalog.js +11 -9
  99. package/dist/modules/catalog.js.map +1 -1
  100. package/dist/modules/known-tools.d.ts +2 -2
  101. package/dist/modules/known-tools.d.ts.map +1 -1
  102. package/dist/modules/known-tools.js +6 -0
  103. package/dist/modules/known-tools.js.map +1 -1
  104. package/dist/monitor-channel-routing.d.ts +20 -0
  105. package/dist/monitor-channel-routing.d.ts.map +1 -0
  106. package/dist/monitor-channel-routing.js +73 -0
  107. package/dist/monitor-channel-routing.js.map +1 -0
  108. package/dist/monitors-command.d.ts +23 -0
  109. package/dist/monitors-command.d.ts.map +1 -0
  110. package/dist/monitors-command.js +207 -0
  111. package/dist/monitors-command.js.map +1 -0
  112. package/dist/monitors-config.d.ts +74 -0
  113. package/dist/monitors-config.d.ts.map +1 -0
  114. package/dist/monitors-config.js +146 -0
  115. package/dist/monitors-config.js.map +1 -0
  116. package/dist/monitors-context.d.ts +58 -0
  117. package/dist/monitors-context.d.ts.map +1 -0
  118. package/dist/monitors-context.js +182 -0
  119. package/dist/monitors-context.js.map +1 -0
  120. package/dist/monitors-runtime.d.ts +36 -0
  121. package/dist/monitors-runtime.d.ts.map +1 -0
  122. package/dist/monitors-runtime.js +103 -0
  123. package/dist/monitors-runtime.js.map +1 -0
  124. package/dist/monitors-service.d.ts +71 -0
  125. package/dist/monitors-service.d.ts.map +1 -0
  126. package/dist/monitors-service.js +1665 -0
  127. package/dist/monitors-service.js.map +1 -0
  128. package/dist/monitors-store.d.ts +83 -0
  129. package/dist/monitors-store.d.ts.map +1 -0
  130. package/dist/monitors-store.js +283 -0
  131. package/dist/monitors-store.js.map +1 -0
  132. package/dist/process-jobs-context.d.ts +8 -0
  133. package/dist/process-jobs-context.d.ts.map +1 -1
  134. package/dist/process-jobs-context.js +11 -0
  135. package/dist/process-jobs-context.js.map +1 -1
  136. package/dist/process-jobs-protection.js +1 -1
  137. package/dist/process-jobs-protection.js.map +1 -1
  138. package/dist/process-jobs-runtime.d.ts.map +1 -1
  139. package/dist/process-jobs-runtime.js +1 -12
  140. package/dist/process-jobs-runtime.js.map +1 -1
  141. package/dist/process-jobs-service.d.ts.map +1 -1
  142. package/dist/process-jobs-service.js +3 -149
  143. package/dist/process-jobs-service.js.map +1 -1
  144. package/dist/process-output-redaction.d.ts +33 -0
  145. package/dist/process-output-redaction.d.ts.map +1 -0
  146. package/dist/process-output-redaction.js +149 -0
  147. package/dist/process-output-redaction.js.map +1 -0
  148. package/dist/provider-model-catalog.d.ts +78 -0
  149. package/dist/provider-model-catalog.d.ts.map +1 -0
  150. package/dist/provider-model-catalog.js +439 -0
  151. package/dist/provider-model-catalog.js.map +1 -0
  152. package/dist/provider-setup.d.ts +4 -13
  153. package/dist/provider-setup.d.ts.map +1 -1
  154. package/dist/provider-setup.js +5 -115
  155. package/dist/provider-setup.js.map +1 -1
  156. package/dist/readiness-probe-worker.d.ts +1 -2
  157. package/dist/readiness-probe-worker.d.ts.map +1 -1
  158. package/dist/readiness-probe-worker.js +3 -8
  159. package/dist/readiness-probe-worker.js.map +1 -1
  160. package/dist/readiness-probe.d.ts +1 -1
  161. package/dist/readiness-probe.d.ts.map +1 -1
  162. package/dist/readiness-probe.js +3 -33
  163. package/dist/readiness-probe.js.map +1 -1
  164. package/dist/request-model-override.d.ts +4 -36
  165. package/dist/request-model-override.d.ts.map +1 -1
  166. package/dist/request-model-override.js +58 -146
  167. package/dist/request-model-override.js.map +1 -1
  168. package/dist/runtime-option-extensions.d.ts +2 -4
  169. package/dist/runtime-option-extensions.d.ts.map +1 -1
  170. package/dist/runtime-option-extensions.js +4 -8
  171. package/dist/runtime-option-extensions.js.map +1 -1
  172. package/dist/runtime-routes.d.ts +5 -5
  173. package/dist/runtime-routes.d.ts.map +1 -1
  174. package/dist/runtime-routes.js +29 -18
  175. package/dist/runtime-routes.js.map +1 -1
  176. package/dist/sandbox-settings-cleanup.d.ts +15 -0
  177. package/dist/sandbox-settings-cleanup.d.ts.map +1 -0
  178. package/dist/sandbox-settings-cleanup.js +88 -0
  179. package/dist/sandbox-settings-cleanup.js.map +1 -0
  180. package/dist/trigger-overrides.d.ts +6 -0
  181. package/dist/trigger-overrides.d.ts.map +1 -1
  182. package/dist/trigger-overrides.js +36 -4
  183. package/dist/trigger-overrides.js.map +1 -1
  184. package/dist/untrusted-text.d.ts +36 -0
  185. package/dist/untrusted-text.d.ts.map +1 -0
  186. package/dist/untrusted-text.js +150 -0
  187. package/dist/untrusted-text.js.map +1 -0
  188. package/dist/wizard/answers.d.ts +3 -9
  189. package/dist/wizard/answers.d.ts.map +1 -1
  190. package/dist/wizard/answers.js +11 -36
  191. package/dist/wizard/answers.js.map +1 -1
  192. package/dist/wizard/from-flags.d.ts +1 -2
  193. package/dist/wizard/from-flags.d.ts.map +1 -1
  194. package/dist/wizard/from-flags.js +8 -3
  195. package/dist/wizard/from-flags.js.map +1 -1
  196. package/dist/wizard/model-discovery.d.ts +7 -8
  197. package/dist/wizard/model-discovery.d.ts.map +1 -1
  198. package/dist/wizard/model-discovery.js +58 -431
  199. package/dist/wizard/model-discovery.js.map +1 -1
  200. package/dist/wizard/presets.js +2 -2
  201. package/dist/wizard/presets.js.map +1 -1
  202. package/dist/wizard/prompts.d.ts +13 -12
  203. package/dist/wizard/prompts.d.ts.map +1 -1
  204. package/dist/wizard/prompts.js +24 -45
  205. package/dist/wizard/prompts.js.map +1 -1
  206. package/dist/wizard/run.d.ts.map +1 -1
  207. package/dist/wizard/run.js +29 -152
  208. package/dist/wizard/run.js.map +1 -1
  209. package/package.json +17 -17
  210. package/schema/mono-agent.config.schema.json +183 -47
  211. package/skills/mono-agent-composer/SKILL.md +2 -2
  212. package/skills/mono-agent-composer/references/config-blueprint.md +43 -40
  213. package/skills/mono-agent-composer/references/discovery-questions.md +8 -13
  214. package/skills/mono-agent-composer/references/feature-coverage.md +10 -8
  215. package/skills/mono-agent-composer/references/package-map.md +21 -15
  216. package/skills/mono-agent-composer/references/playbooks.md +19 -23
  217. package/dist/codex-model-catalog.d.ts +0 -15
  218. package/dist/codex-model-catalog.d.ts.map +0 -1
  219. package/dist/codex-model-catalog.js +0 -220
  220. package/dist/codex-model-catalog.js.map +0 -1
@@ -0,0 +1,146 @@
1
+ import { readFile } from "node:fs/promises";
2
+ /**
3
+ * Host-only `monitors` configuration.
4
+ *
5
+ * Monitors are a STREAMING class of the background process-job substrate: they
6
+ * reuse its protected private-state root, its registration proof, its sandbox
7
+ * protection, and its origin binding, and therefore require
8
+ * `processJobs.enabled`. What they do not share is capacity — a persistent watch
9
+ * that held an ordinary background slot would starve real background work — so
10
+ * every limit below is counted independently of `processJobs.*`.
11
+ */
12
+ export const MONITORS_DEFAULTS = Object.freeze({
13
+ enabled: false,
14
+ maxActive: 8,
15
+ maxActivePerConversation: 2,
16
+ /** Ceiling for a timed monitor; `timeout_ms` may lower it, never raise it. */
17
+ maxRuntimeMs: 60 * 60 * 1_000,
18
+ /** Ceiling for a `persistent: true` monitor. */
19
+ persistentMaxRuntimeMs: 24 * 60 * 60 * 1_000,
20
+ /** Stdout lines produced within this window are delivered as one batch. */
21
+ coalesceMs: 200,
22
+ maxBatchLines: 200,
23
+ maxBatchBytes: 64 * 1024,
24
+ maxLineBytes: 4 * 1024,
25
+ maxChainDepth: 4,
26
+ rateLimit: Object.freeze({
27
+ windowMs: 1_000,
28
+ maxLinesPerWindow: 200,
29
+ sustainedWindows: 5,
30
+ }),
31
+ });
32
+ export const MONITORS_CAPS = Object.freeze({
33
+ maxActive: 32,
34
+ maxActivePerConversation: 8,
35
+ maxRuntimeMs: 60 * 60 * 1_000,
36
+ persistentMaxRuntimeMs: 24 * 60 * 60 * 1_000,
37
+ coalesceMs: 5_000,
38
+ maxBatchLines: 2_000,
39
+ maxBatchBytes: 1024 * 1024,
40
+ maxLineBytes: 64 * 1024,
41
+ maxChainDepth: 8,
42
+ rateLimit: Object.freeze({
43
+ windowMs: 60_000,
44
+ maxLinesPerWindow: 20_000,
45
+ sustainedWindows: 60,
46
+ }),
47
+ });
48
+ /** Terminal monitors retained only until their single final wake settles. */
49
+ export const MONITORS_MAX_TERMINAL_RECORDS = 32;
50
+ const MONITORS_KEYS = [
51
+ "enabled",
52
+ "maxActive",
53
+ "maxActivePerConversation",
54
+ "maxRuntimeMs",
55
+ "persistentMaxRuntimeMs",
56
+ "coalesceMs",
57
+ "maxBatchLines",
58
+ "maxBatchBytes",
59
+ "maxLineBytes",
60
+ "maxChainDepth",
61
+ "rateLimit",
62
+ ];
63
+ const RATE_LIMIT_KEYS = ["windowMs", "maxLinesPerWindow", "sustainedWindows"];
64
+ /** Load the host-only monitor block, failing closed on every unknown key. */
65
+ export async function loadMonitorsSettings(input) {
66
+ let raw = {};
67
+ try {
68
+ raw = JSON.parse(await readFile(input.configPath, "utf8"));
69
+ }
70
+ catch {
71
+ // The core loader owns malformed/missing config reporting. This optional
72
+ // host block stays disabled until that loader accepts the file.
73
+ }
74
+ return parseMonitorsSettings(raw);
75
+ }
76
+ /** Parse one already-loaded config object; unknown keys fail closed. */
77
+ export function parseMonitorsSettings(raw) {
78
+ const root = objectOf(raw);
79
+ const value = root.monitors;
80
+ if (value === undefined)
81
+ return resolved(false, {});
82
+ const block = requireObject(value, "monitors");
83
+ rejectUnknownKeys(block, "monitors", MONITORS_KEYS);
84
+ return resolved(true, block);
85
+ }
86
+ function resolved(configured, block) {
87
+ const rateLimitValue = block.rateLimit;
88
+ const rateLimit = rateLimitValue === undefined
89
+ ? {}
90
+ : requireObject(rateLimitValue, "monitors.rateLimit");
91
+ rejectUnknownKeys(rateLimit, "monitors.rateLimit", RATE_LIMIT_KEYS);
92
+ return {
93
+ configured,
94
+ enabled: optionalBoolean(block.enabled, "monitors.enabled") ?? MONITORS_DEFAULTS.enabled,
95
+ maxActive: bounded(block.maxActive, "monitors.maxActive", MONITORS_DEFAULTS.maxActive, MONITORS_CAPS.maxActive),
96
+ maxActivePerConversation: bounded(block.maxActivePerConversation, "monitors.maxActivePerConversation", MONITORS_DEFAULTS.maxActivePerConversation, MONITORS_CAPS.maxActivePerConversation),
97
+ maxRuntimeMs: bounded(block.maxRuntimeMs, "monitors.maxRuntimeMs", MONITORS_DEFAULTS.maxRuntimeMs, MONITORS_CAPS.maxRuntimeMs),
98
+ persistentMaxRuntimeMs: bounded(block.persistentMaxRuntimeMs, "monitors.persistentMaxRuntimeMs", MONITORS_DEFAULTS.persistentMaxRuntimeMs, MONITORS_CAPS.persistentMaxRuntimeMs),
99
+ coalesceMs: bounded(block.coalesceMs, "monitors.coalesceMs", MONITORS_DEFAULTS.coalesceMs, MONITORS_CAPS.coalesceMs),
100
+ maxBatchLines: bounded(block.maxBatchLines, "monitors.maxBatchLines", MONITORS_DEFAULTS.maxBatchLines, MONITORS_CAPS.maxBatchLines),
101
+ maxBatchBytes: bounded(block.maxBatchBytes, "monitors.maxBatchBytes", MONITORS_DEFAULTS.maxBatchBytes, MONITORS_CAPS.maxBatchBytes),
102
+ maxLineBytes: bounded(block.maxLineBytes, "monitors.maxLineBytes", MONITORS_DEFAULTS.maxLineBytes, MONITORS_CAPS.maxLineBytes),
103
+ maxChainDepth: bounded(block.maxChainDepth, "monitors.maxChainDepth", MONITORS_DEFAULTS.maxChainDepth, MONITORS_CAPS.maxChainDepth),
104
+ rateLimit: {
105
+ windowMs: bounded(rateLimit.windowMs, "monitors.rateLimit.windowMs", MONITORS_DEFAULTS.rateLimit.windowMs, MONITORS_CAPS.rateLimit.windowMs),
106
+ maxLinesPerWindow: bounded(rateLimit.maxLinesPerWindow, "monitors.rateLimit.maxLinesPerWindow", MONITORS_DEFAULTS.rateLimit.maxLinesPerWindow, MONITORS_CAPS.rateLimit.maxLinesPerWindow),
107
+ sustainedWindows: bounded(rateLimit.sustainedWindows, "monitors.rateLimit.sustainedWindows", MONITORS_DEFAULTS.rateLimit.sustainedWindows, MONITORS_CAPS.rateLimit.sustainedWindows),
108
+ },
109
+ };
110
+ }
111
+ function bounded(value, path, fallback, cap) {
112
+ if (value === undefined)
113
+ return fallback;
114
+ if (!Number.isSafeInteger(value) || Number(value) <= 0) {
115
+ throw new Error(`${path} must be a positive safe integer.`);
116
+ }
117
+ if (Number(value) > cap)
118
+ throw new Error(`${path} cannot exceed ${String(cap)}.`);
119
+ return Number(value);
120
+ }
121
+ function objectOf(value) {
122
+ return typeof value === "object" && value !== null && !Array.isArray(value)
123
+ ? value
124
+ : {};
125
+ }
126
+ function requireObject(value, path) {
127
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
128
+ throw new Error(`${path} must be an object.`);
129
+ }
130
+ return value;
131
+ }
132
+ function optionalBoolean(value, path) {
133
+ if (value === undefined)
134
+ return undefined;
135
+ if (typeof value !== "boolean")
136
+ throw new Error(`${path} must be a boolean.`);
137
+ return value;
138
+ }
139
+ function rejectUnknownKeys(value, path, allowed) {
140
+ const allowedSet = new Set(allowed);
141
+ const unknown = Object.keys(value).filter((key) => !allowedSet.has(key));
142
+ if (unknown.length > 0) {
143
+ throw new Error(`${path} has unknown ${unknown.length === 1 ? "key" : "keys"}: ${unknown.join(", ")}.`);
144
+ }
145
+ }
146
+ //# sourceMappingURL=monitors-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitors-config.js","sourceRoot":"","sources":["../src/monitors-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import { type AgentRequestBase, type AgentResponder, type AgentResponse } from "@mono-agent/agent-contracts";
2
+ import type { MonoAgentAppLogger } from "./channels.js";
3
+ export interface MonitorWakeContext {
4
+ readonly monitorId: string;
5
+ readonly chainDepth: number;
6
+ }
7
+ export type MonitorWakeContextResolution = {
8
+ readonly kind: "none";
9
+ } | {
10
+ readonly kind: "resolved";
11
+ readonly context: MonitorWakeContext;
12
+ } | {
13
+ readonly kind: "missed";
14
+ };
15
+ /**
16
+ * Run a genuine channel turn as a monitor wake.
17
+ *
18
+ * This nests INSIDE the process-job wake context on purpose. Both features raise
19
+ * host-owned turns on the same conversation, and the steering registry admits
20
+ * exactly one active run per conversation: a second, parallel registration would
21
+ * make every steer ambiguous and silently downgrade process-job wakes to a
22
+ * follow-up turn. Sharing it also means a monitor wake inherits the same
23
+ * targeted-run steering and the same unforgeable chain-depth increment, so a
24
+ * monitor started from a wake turn cannot escape `maxChainDepth`.
25
+ */
26
+ export declare function runWithMonitorWakeContext<T>(context: MonitorWakeContext, operation: () => Promise<T>, deliveryKey: string): Promise<T>;
27
+ /**
28
+ * Capture an admitted monitor wake on the request identity that survives the
29
+ * responder-to-harness queue boundary, and suppress a sentinel-only answer.
30
+ *
31
+ * The suppression is the point of this wrapper. A monitor raises turns nobody
32
+ * asked for, so it must be able to conclude "nothing worth saying" without
33
+ * posting anything — but `NOTHING_TO_REPORT` is only honoured by the native
34
+ * cron/webhook notify path, which a channel wake turn does not go through.
35
+ * Blanking the answer here makes the adapters' existing "agent produced no
36
+ * answer" path do the suppressing, without teaching any adapter about monitors.
37
+ */
38
+ export declare function bindMonitorWakeContextToResponder(responder: AgentResponder, options?: {
39
+ readonly logger?: MonoAgentAppLogger;
40
+ }): AgentResponder;
41
+ /**
42
+ * Blank a monitor wake answer that ends with the sentinel. Attachments are
43
+ * dropped with it: a turn that decided it has nothing to say must not still post
44
+ * files. A `narrated-sentinel` is honoured but logged, exactly as the native
45
+ * notify path does, because it means the model wrote prose before the marker.
46
+ */
47
+ export declare function suppressSilentMonitorReply(response: AgentResponse, context: MonitorWakeContext & {
48
+ readonly deliveryKey?: string;
49
+ }, logger?: MonoAgentAppLogger): AgentResponse;
50
+ /**
51
+ * Whether this wake's turn ran and chose silence. Consumed once: the settling
52
+ * wake is the only reader, and a stale key must not make a later batch look
53
+ * delivered.
54
+ */
55
+ export declare function consumeSilentMonitorWake(deliveryKey: string): boolean;
56
+ /** Resolve only an association previously issued by this app-owned seam. */
57
+ export declare function monitorWakeContextForRequest(request: Pick<AgentRequestBase, "metadata">): MonitorWakeContextResolution;
58
+ //# sourceMappingURL=monitors-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitors-context.d.ts","sourceRoot":"","sources":["../src/monitors-context.ts"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGxD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAOD,MAAM,MAAM,4BAA4B,GACpC;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,GACnE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AA0BhC;;;;;;;;;;GAUG;AACH,wBAAsB,yBAAyB,CAAC,CAAC,EAC/C,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,CAAC,CAAC,CAgBZ;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,cAAc,EACzB,OAAO,GAAE;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAAO,GACrD,cAAc,CAgDhB;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,aAAa,EACvB,OAAO,EAAE,kBAAkB,GAAG;IAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/D,MAAM,CAAC,EAAE,kBAAkB,GAC1B,aAAa,CAYf;AAaD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAErE;AAED,4EAA4E;AAC5E,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,GAC1C,4BAA4B,CAU9B"}
@@ -0,0 +1,182 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { classifyNotifySuppression, } from "@mono-agent/agent-contracts";
3
+ import { runWithProcessJobWakeContext } from "./process-jobs-context.js";
4
+ const wakeContext = new AsyncLocalStorage();
5
+ /**
6
+ * Monitor wakes reuse the process-job delivery-key metadata symbol because the
7
+ * adapters already carry that exact non-JSON key through their queued proactive
8
+ * turns. The key VALUE namespaces the two: a monitor delivery key is always
9
+ * `monitor:<id>:<seq>`, so a lookup here can never resolve a job's flight.
10
+ */
11
+ const HOST_WAKE_DELIVERY_METADATA = Symbol.for("mono-agent.process-job-wake.delivery-key.v1");
12
+ const wakeContextByRequestMetadata = new WeakMap();
13
+ const wakeFlightsByDeliveryKey = new Map();
14
+ /**
15
+ * Wakes whose turn ran and deliberately said nothing.
16
+ *
17
+ * Adapters classify an empty answer as "not delivered", which is right for a
18
+ * proactive notification but wrong for a monitor: the batch WAS consumed, the
19
+ * model simply had nothing worth saying. Without this the host would count a
20
+ * successful silent turn as a lost batch and report a gap that never happened.
21
+ */
22
+ const silentWakeDeliveryKeys = new Set();
23
+ const MAX_SILENT_WAKE_KEYS = 512;
24
+ /**
25
+ * Run a genuine channel turn as a monitor wake.
26
+ *
27
+ * This nests INSIDE the process-job wake context on purpose. Both features raise
28
+ * host-owned turns on the same conversation, and the steering registry admits
29
+ * exactly one active run per conversation: a second, parallel registration would
30
+ * make every steer ambiguous and silently downgrade process-job wakes to a
31
+ * follow-up turn. Sharing it also means a monitor wake inherits the same
32
+ * targeted-run steering and the same unforgeable chain-depth increment, so a
33
+ * monitor started from a wake turn cannot escape `maxChainDepth`.
34
+ */
35
+ export async function runWithMonitorWakeContext(context, operation, deliveryKey) {
36
+ const flight = Object.freeze({ ...context, token: Object.freeze({}), deliveryKey });
37
+ const current = wakeFlightsByDeliveryKey.get(deliveryKey) ?? [];
38
+ wakeFlightsByDeliveryKey.set(deliveryKey, [...current, flight]);
39
+ try {
40
+ return await wakeContext.run(flight, async () => await runWithProcessJobWakeContext({ jobId: context.monitorId, chainDepth: context.chainDepth }, operation, deliveryKey));
41
+ }
42
+ finally {
43
+ const active = wakeFlightsByDeliveryKey.get(deliveryKey) ?? [];
44
+ const remaining = active.filter((candidate) => candidate.token !== flight.token);
45
+ if (remaining.length === 0)
46
+ wakeFlightsByDeliveryKey.delete(deliveryKey);
47
+ else
48
+ wakeFlightsByDeliveryKey.set(deliveryKey, remaining);
49
+ }
50
+ }
51
+ /**
52
+ * Capture an admitted monitor wake on the request identity that survives the
53
+ * responder-to-harness queue boundary, and suppress a sentinel-only answer.
54
+ *
55
+ * The suppression is the point of this wrapper. A monitor raises turns nobody
56
+ * asked for, so it must be able to conclude "nothing worth saying" without
57
+ * posting anything — but `NOTHING_TO_REPORT` is only honoured by the native
58
+ * cron/webhook notify path, which a channel wake turn does not go through.
59
+ * Blanking the answer here makes the adapters' existing "agent produced no
60
+ * answer" path do the suppressing, without teaching any adapter about monitors.
61
+ */
62
+ export function bindMonitorWakeContextToResponder(responder, options = {}) {
63
+ const dispose = responder.dispose;
64
+ const startNewSession = responder.startNewSession;
65
+ return {
66
+ respond: async (request, stream) => {
67
+ const context = wakeContext.getStore();
68
+ let installed;
69
+ if (context !== undefined) {
70
+ if (request.metadata === undefined) {
71
+ throw new Error("A monitor wake request is missing its host-owned request identity.");
72
+ }
73
+ installed = { token: Object.freeze({}), flight: context };
74
+ const current = wakeContextByRequestMetadata.get(request.metadata) ?? [];
75
+ wakeContextByRequestMetadata.set(request.metadata, [...current, installed]);
76
+ }
77
+ try {
78
+ const response = await responder.respond(request, stream);
79
+ return context === undefined
80
+ ? response
81
+ : suppressSilentMonitorReply(response, context, options.logger);
82
+ }
83
+ finally {
84
+ if (installed !== undefined && request.metadata !== undefined) {
85
+ const current = wakeContextByRequestMetadata.get(request.metadata) ?? [];
86
+ const remaining = current.filter((candidate) => candidate.token !== installed.token);
87
+ if (remaining.length === 0)
88
+ wakeContextByRequestMetadata.delete(request.metadata);
89
+ else
90
+ wakeContextByRequestMetadata.set(request.metadata, remaining);
91
+ }
92
+ }
93
+ },
94
+ ...(responder.cancel === undefined ? {} : { cancel: responder.cancel.bind(responder) }),
95
+ ...(responder.offerLiveInput === undefined
96
+ ? {}
97
+ : { offerLiveInput: (request) => responder.offerLiveInput(request) }),
98
+ ...(responder.deliverVerbatim === undefined
99
+ ? {}
100
+ : { deliverVerbatim: responder.deliverVerbatim.bind(responder) }),
101
+ ...(responder.openReplyArtifact === undefined
102
+ ? {}
103
+ : { openReplyArtifact: responder.openReplyArtifact.bind(responder) }),
104
+ ...(responder.loadMcpApp === undefined ? {} : { loadMcpApp: responder.loadMcpApp.bind(responder) }),
105
+ ...(responder.requestMcpApp === undefined ? {} : { requestMcpApp: responder.requestMcpApp.bind(responder) }),
106
+ ...(startNewSession === undefined
107
+ ? {}
108
+ : { startNewSession: (conversationId) => startNewSession.call(responder, conversationId) }),
109
+ ...(dispose === undefined ? {} : { dispose: dispose.bind(responder) }),
110
+ };
111
+ }
112
+ /**
113
+ * Blank a monitor wake answer that ends with the sentinel. Attachments are
114
+ * dropped with it: a turn that decided it has nothing to say must not still post
115
+ * files. A `narrated-sentinel` is honoured but logged, exactly as the native
116
+ * notify path does, because it means the model wrote prose before the marker.
117
+ */
118
+ export function suppressSilentMonitorReply(response, context, logger) {
119
+ const suppression = classifyNotifySuppression(response.text);
120
+ if (suppression === "none" || suppression === "empty")
121
+ return response;
122
+ if (suppression === "narrated-sentinel") {
123
+ logger?.warn?.("Monitor wake reply suppressed: the final answer ended with the NOTHING_TO_REPORT sentinel but was not the sentinel alone.", { monitorId: context.monitorId });
124
+ }
125
+ markSilentMonitorWake(context.deliveryKey);
126
+ const { text: _text, parts: _parts, ...rest } = response;
127
+ return { ...rest, text: "" };
128
+ }
129
+ function markSilentMonitorWake(deliveryKey) {
130
+ if (deliveryKey === undefined)
131
+ return;
132
+ // Bounded: a key is consumed by the settling wake, and this cap keeps a
133
+ // pathological run from retaining keys nobody will ever read.
134
+ if (silentWakeDeliveryKeys.size >= MAX_SILENT_WAKE_KEYS) {
135
+ const oldest = silentWakeDeliveryKeys.values().next().value;
136
+ if (oldest !== undefined)
137
+ silentWakeDeliveryKeys.delete(oldest);
138
+ }
139
+ silentWakeDeliveryKeys.add(deliveryKey);
140
+ }
141
+ /**
142
+ * Whether this wake's turn ran and chose silence. Consumed once: the settling
143
+ * wake is the only reader, and a stale key must not make a later batch look
144
+ * delivered.
145
+ */
146
+ export function consumeSilentMonitorWake(deliveryKey) {
147
+ return silentWakeDeliveryKeys.delete(deliveryKey);
148
+ }
149
+ /** Resolve only an association previously issued by this app-owned seam. */
150
+ export function monitorWakeContextForRequest(request) {
151
+ const bindings = request.metadata === undefined
152
+ ? []
153
+ : wakeContextByRequestMetadata.get(request.metadata) ?? [];
154
+ if (bindings.length > 0)
155
+ return resolveFlights(bindings.map((binding) => binding.flight));
156
+ const deliveryKey = monitorWakeDeliveryKey(request.metadata);
157
+ if (deliveryKey === undefined)
158
+ return { kind: "none" };
159
+ const flights = wakeFlightsByDeliveryKey.get(deliveryKey) ?? [];
160
+ if (flights.length === 0)
161
+ return { kind: "none" };
162
+ return resolveFlights(flights);
163
+ }
164
+ function monitorWakeDeliveryKey(metadata) {
165
+ if (metadata === undefined)
166
+ return undefined;
167
+ try {
168
+ const descriptor = Object.getOwnPropertyDescriptor(metadata, HOST_WAKE_DELIVERY_METADATA);
169
+ const value = descriptor !== undefined && "value" in descriptor ? descriptor.value : undefined;
170
+ return typeof value === "string" && value.startsWith("monitor:") ? value : undefined;
171
+ }
172
+ catch {
173
+ return undefined;
174
+ }
175
+ }
176
+ function resolveFlights(flights) {
177
+ const distinct = [...new Map(flights.map((flight) => [flight.token, flight])).values()];
178
+ return distinct.length === 1
179
+ ? { kind: "resolved", context: Object.freeze({ monitorId: distinct[0].monitorId, chainDepth: distinct[0].chainDepth }) }
180
+ : { kind: "missed" };
181
+ }
182
+ //# sourceMappingURL=monitors-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitors-context.js","sourceRoot":"","sources":["../src/monitors-context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { AgentHarnessRuntimeOptionsInput } from "@mono-agent/agent-harness";
2
+ import type { MonoAgentConfig } from "@mono-agent/config";
3
+ import type { ChannelId } from "./channels.js";
4
+ import type { MonitorsServiceHandle } from "./monitors-service.js";
5
+ import type { ProcessJobOriginRecord } from "./process-jobs-store.js";
6
+ import type { RuntimeOptionsExtension } from "./runtime-option-extensions.js";
7
+ /** Channel schemes whose adapters can deliver a monitor wake to an exact conversation. */
8
+ export declare const MONITOR_WAKE_CAPABLE_SCHEMES: ReadonlySet<string>;
9
+ export interface MonitorsRuntimeExtensionOptions {
10
+ readonly next?: RuntimeOptionsExtension;
11
+ /** Optional because monitors stay unavailable when their service cannot open. */
12
+ readonly service: MonitorsServiceHandle | undefined;
13
+ readonly coreConfig: MonoAgentConfig;
14
+ readonly channelId: ChannelId | undefined;
15
+ readonly conversationScheme?: string | undefined;
16
+ readonly routesOnlyPiNative?: (metadata: Record<string, unknown> | undefined) => boolean;
17
+ }
18
+ /** Inject the monitor controller only for a Pi-native, wake-capable, allowed turn. */
19
+ export declare function createMonitorsRuntimeExtension(options: MonitorsRuntimeExtensionOptions): RuntimeOptionsExtension;
20
+ /** Strict host-origin classifier narrowed to schemes that can deliver a wake. */
21
+ export declare function monitorOriginForRequest(input: Pick<AgentHarnessRuntimeOptionsInput, "request" | "runId">, channelId: ChannelId | undefined, conversationScheme?: string): ProcessJobOriginRecord | undefined;
22
+ export interface MonitorsAvailabilityOptions {
23
+ readonly service: MonitorsServiceHandle | undefined;
24
+ readonly coreConfig: MonoAgentConfig;
25
+ readonly channelId: ChannelId | undefined;
26
+ readonly conversationScheme?: string | undefined;
27
+ readonly routesOnlyPiNative?: (metadata: Record<string, unknown> | undefined) => boolean;
28
+ }
29
+ /**
30
+ * The same gate the extension applies, minus the checks that only exist once a
31
+ * run is under way. Exported so prompt guidance and tool availability are
32
+ * decided by one predicate; it errs strict, because telling the model it can
33
+ * watch something it cannot is the worse failure.
34
+ */
35
+ export declare function monitorsAvailableForRequest(input: Pick<AgentHarnessRuntimeOptionsInput, "request" | "runId">, options: MonitorsAvailabilityOptions): boolean;
36
+ //# sourceMappingURL=monitors-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitors-runtime.d.ts","sourceRoot":"","sources":["../src/monitors-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AASnE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAE9E,0FAA0F;AAC1F,eAAO,MAAM,4BAA4B,EAAE,WAAW,CAAC,MAAM,CAAyC,CAAC;AAEvG,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,uBAAuB,CAAC;IACxC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,qBAAqB,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,KAAK,OAAO,CAAC;CAC1F;AAED,sFAAsF;AACtF,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,+BAA+B,GACvC,uBAAuB,CAiDzB;AAED,iFAAiF;AACjF,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,IAAI,CAAC,+BAA+B,EAAE,SAAS,GAAG,OAAO,CAAC,EACjE,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,kBAAkB,CAAC,EAAE,MAAM,GAC1B,sBAAsB,GAAG,SAAS,CAGpC;AAyBD,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,OAAO,EAAE,qBAAqB,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,KAAK,OAAO,CAAC;CAC1F;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,IAAI,CAAC,+BAA+B,EAAE,SAAS,GAAG,OAAO,CAAC,EACjE,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAYT"}
@@ -0,0 +1,103 @@
1
+ import { monitorWakeContextForRequest } from "./monitors-context.js";
2
+ import { processJobOriginForRequest, PROCESS_JOBS_PI_NATIVE_REQUIRED_ERROR, } from "./process-jobs-runtime.js";
3
+ import { processJobSteeringDepth, processJobWakeContextForRequest, } from "./process-jobs-context.js";
4
+ /** Channel schemes whose adapters can deliver a monitor wake to an exact conversation. */
5
+ export const MONITOR_WAKE_CAPABLE_SCHEMES = new Set(["telegram", "slack", "web"]);
6
+ /** Inject the monitor controller only for a Pi-native, wake-capable, allowed turn. */
7
+ export function createMonitorsRuntimeExtension(options) {
8
+ return async (input) => {
9
+ let result;
10
+ try {
11
+ if (options.service !== undefined
12
+ && options.routesOnlyPiNative !== undefined
13
+ && !options.routesOnlyPiNative(input.request.metadata)) {
14
+ throw new Error(`${PROCESS_JOBS_PI_NATIVE_REQUIRED_ERROR} Not every route reachable for this request is Pi-native.`);
15
+ }
16
+ result = options.next === undefined
17
+ ? { runtimeOptions: {}, cleanup: async () => { } }
18
+ : await options.next(input);
19
+ let runtimeOptions = result.runtimeOptions ?? {};
20
+ const service = options.service;
21
+ if (service !== undefined) {
22
+ const origin = monitorOriginForRequest(input, options.channelId, options.conversationScheme);
23
+ // Chain depth comes from whichever host wake raised this turn. Monitor
24
+ // wakes nest inside the process-job wake context, so both resolvers see
25
+ // the same flight and the depth cannot be forged from either side.
26
+ const monitorWake = monitorWakeContextForRequest(input.request);
27
+ const hostWake = processJobWakeContextForRequest(input.request);
28
+ const missed = monitorWake.kind === "missed" || hostWake.kind === "missed";
29
+ const chainDepth = Math.max(monitorWake.kind === "resolved" ? monitorWake.context.chainDepth : 0, hostWake.kind === "resolved" ? hostWake.context.chainDepth : 0);
30
+ // The steering target is registered ONCE per run, by the process-jobs
31
+ // extension. Registering a second one here would make the conversation's
32
+ // active run ambiguous and silently break process-job steering, because
33
+ // that registry admits a steer only when exactly one candidate matches.
34
+ if (monitorsAdmissible(origin, missed, chainDepth, service, options.coreConfig)) {
35
+ runtimeOptions = {
36
+ ...runtimeOptions,
37
+ monitors: service.controller(origin, () => steeringDepth(origin, chainDepth)),
38
+ };
39
+ }
40
+ }
41
+ return { ...result, runtimeOptions };
42
+ }
43
+ catch (error) {
44
+ try {
45
+ await result?.cleanup?.();
46
+ }
47
+ finally {
48
+ await result?.settleCleanup?.();
49
+ }
50
+ throw error;
51
+ }
52
+ };
53
+ }
54
+ /** Strict host-origin classifier narrowed to schemes that can deliver a wake. */
55
+ export function monitorOriginForRequest(input, channelId, conversationScheme) {
56
+ const origin = processJobOriginForRequest(input, channelId, conversationScheme);
57
+ return origin !== undefined && MONITOR_WAKE_CAPABLE_SCHEMES.has(origin.channel) ? origin : undefined;
58
+ }
59
+ function monitorsAdmissible(origin, missedWake, chainDepth, service, coreConfig) {
60
+ return origin !== undefined
61
+ && !missedWake
62
+ && service !== undefined
63
+ && chainDepth < service.settings.maxChainDepth
64
+ && hasAllowedMonitorTools(coreConfig);
65
+ }
66
+ /**
67
+ * Read the live depth from the shared steering registration when this run has
68
+ * one, so a monitor started after a wake was steered into this very turn still
69
+ * sees the raised depth rather than the depth the run began with.
70
+ */
71
+ function steeringDepth(origin, fallback) {
72
+ return Math.max(fallback, processJobSteeringDepth(origin.baseConversationId) ?? fallback);
73
+ }
74
+ /**
75
+ * The same gate the extension applies, minus the checks that only exist once a
76
+ * run is under way. Exported so prompt guidance and tool availability are
77
+ * decided by one predicate; it errs strict, because telling the model it can
78
+ * watch something it cannot is the worse failure.
79
+ */
80
+ export function monitorsAvailableForRequest(input, options) {
81
+ if (options.service === undefined)
82
+ return false;
83
+ if (options.routesOnlyPiNative?.(input.request.metadata) === false)
84
+ return false;
85
+ const origin = monitorOriginForRequest(input, options.channelId, options.conversationScheme);
86
+ const monitorWake = monitorWakeContextForRequest(input.request);
87
+ const hostWake = processJobWakeContextForRequest(input.request);
88
+ const missed = monitorWake.kind === "missed" || hostWake.kind === "missed";
89
+ const chainDepth = Math.max(monitorWake.kind === "resolved" ? monitorWake.context.chainDepth : 0, hostWake.kind === "resolved" ? hostWake.context.chainDepth : 0);
90
+ return monitorsAdmissible(origin, missed, chainDepth, options.service, options.coreConfig);
91
+ }
92
+ /**
93
+ * Both names must be reachable. A Monitor the model cannot stop is a capacity
94
+ * leak it has no way to repair, so denying MonitorStop denies Monitor too.
95
+ */
96
+ function hasAllowedMonitorTools(config) {
97
+ const allowed = config.tools.allowedTools;
98
+ const denied = new Set(config.tools.disallowedTools.map((name) => name.toLowerCase()));
99
+ const allowAll = allowed.some((name) => name === "*");
100
+ return ["Monitor", "MonitorStop"].every((name) => !denied.has(name.toLowerCase())
101
+ && (allowAll || allowed.some((allowedName) => allowedName.toLowerCase() === name.toLowerCase())));
102
+ }
103
+ //# sourceMappingURL=monitors-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitors-runtime.js","sourceRoot":"","sources":["../src/monitors-runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ import { type MonitorErrorCode, type MonitorProjection, type NotifyDeliveryResult } from "@mono-agent/agent-contracts";
2
+ import type { MonitorsController } from "@mono-agent/runtime-adapter";
3
+ import { type OwnerPrivateLock } from "./owner-private-lock.js";
4
+ import { type MonitorsSettings } from "./monitors-config.js";
5
+ import { writeMonitorStore } from "./monitors-store.js";
6
+ import { isSameProcessIncarnation, readProcessIncarnation, type ProcessIncarnation } from "./process-incarnation.js";
7
+ import type { ProcessJobOriginRecord } from "./process-jobs-store.js";
8
+ export declare class MonitorServiceError extends Error {
9
+ readonly code: MonitorErrorCode;
10
+ constructor(code: MonitorErrorCode);
11
+ }
12
+ export interface MonitorWakeInput {
13
+ readonly projection: MonitorProjection;
14
+ readonly prompt: string;
15
+ readonly conversationId: string;
16
+ readonly deliveryKey: string;
17
+ readonly chainDepth: number;
18
+ }
19
+ export interface OpenMonitorsServiceOptions {
20
+ /** The already-prepared, protected process-job private-state root. */
21
+ readonly stateDir: string;
22
+ readonly settings: MonitorsSettings;
23
+ readonly wake: (input: MonitorWakeInput) => Promise<NotifyDeliveryResult>;
24
+ readonly logger?: {
25
+ info?(message: string, details?: Readonly<Record<string, unknown>>): void;
26
+ warn?(message: string, details?: Readonly<Record<string, unknown>>): void;
27
+ };
28
+ readonly now?: () => Date;
29
+ readonly platform?: NodeJS.Platform;
30
+ readonly randomId?: () => string;
31
+ readonly currentIncarnation?: () => Promise<ProcessIncarnation>;
32
+ readonly readIncarnation?: typeof readProcessIncarnation;
33
+ readonly sameIncarnation?: typeof isSameProcessIncarnation;
34
+ readonly signalProcess?: (pid: number, signal: NodeJS.Signals) => void;
35
+ readonly processGroupExists?: (pgid: number) => boolean;
36
+ readonly sleep?: (milliseconds: number) => Promise<void>;
37
+ readonly wakeRearmMs?: number;
38
+ /** Bounded wait for watchers and wakes at shutdown; a test seam, not a knob. */
39
+ readonly shutdownGraceMs?: number;
40
+ /** Test seam for blocking one durable write at an exact lifecycle boundary. */
41
+ readonly writeStore?: typeof writeMonitorStore;
42
+ /** Test seam for pausing inside the serialized wake-admission boundary. */
43
+ readonly beforeWakePreparation?: () => Promise<void>;
44
+ readonly acquireLock?: () => Promise<OwnerPrivateLock | undefined>;
45
+ readonly operatorSecret?: () => Promise<Uint8Array>;
46
+ }
47
+ export interface MonitorsServiceHandle {
48
+ readonly settings: MonitorsSettings;
49
+ /** The protected state root this service actually opened. */
50
+ readonly stateDir: string;
51
+ readonly operatorToken: string;
52
+ controller(origin: ProcessJobOriginRecord, chainDepth: number | (() => number)): MonitorsController;
53
+ list(): Promise<readonly MonitorProjection[]>;
54
+ get(monitorId: string): Promise<MonitorProjection | undefined>;
55
+ cancel(monitorId: string): Promise<MonitorProjection>;
56
+ activateWakes(): Promise<void>;
57
+ stop(): Promise<void>;
58
+ }
59
+ /** Acquire exclusive ownership, recover interrupted watches, and expose one controller. */
60
+ export declare function openMonitorsService(options: OpenMonitorsServiceOptions): Promise<MonitorsServiceHandle>;
61
+ /**
62
+ * The envelope has three jobs the model routinely gets wrong without it: this is
63
+ * not a user message, the fenced text is data and not instruction, and a batch
64
+ * that changes nothing should end the turn silently rather than posting noise.
65
+ */
66
+ export declare function monitorWakePrompt(projection: MonitorProjection, payload: {
67
+ readonly lines: readonly string[];
68
+ readonly terminal: boolean;
69
+ readonly stderrTail: string;
70
+ }): string;
71
+ //# sourceMappingURL=monitors-service.d.ts.map