@mono-agent/agent-app 0.15.2 → 0.15.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/broadcast-recorder.d.ts +27 -0
- package/dist/broadcast-recorder.d.ts.map +1 -0
- package/dist/broadcast-recorder.js +104 -0
- package/dist/broadcast-recorder.js.map +1 -0
- package/dist/channel-drivers/live.d.ts +12 -0
- package/dist/channel-drivers/live.d.ts.map +1 -0
- package/dist/channel-drivers/live.js +48 -0
- package/dist/channel-drivers/live.js.map +1 -0
- package/dist/notify-runtime.d.ts +26 -0
- package/dist/notify-runtime.d.ts.map +1 -0
- package/dist/notify-runtime.js +27 -0
- package/dist/notify-runtime.js.map +1 -0
- package/dist/notify-tool.d.ts +51 -0
- package/dist/notify-tool.d.ts.map +1 -0
- package/dist/notify-tool.js +182 -0
- package/dist/notify-tool.js.map +1 -0
- package/dist/recipes/base.d.ts +15 -0
- package/dist/recipes/base.d.ts.map +1 -0
- package/dist/recipes/base.js +51 -0
- package/dist/recipes/base.js.map +1 -0
- package/dist/recipes/catalog.d.ts +4 -0
- package/dist/recipes/catalog.d.ts.map +1 -0
- package/dist/recipes/catalog.js +525 -0
- package/dist/recipes/catalog.js.map +1 -0
- package/dist/recipes/index.d.ts +11 -0
- package/dist/recipes/index.d.ts.map +1 -0
- package/dist/recipes/index.js +14 -0
- package/dist/recipes/index.js.map +1 -0
- package/dist/recipes/types.d.ts +70 -0
- package/dist/recipes/types.d.ts.map +1 -0
- package/dist/recipes/types.js +15 -0
- package/dist/recipes/types.js.map +1 -0
- package/dist/sessions-command.d.ts +53 -0
- package/dist/sessions-command.d.ts.map +1 -0
- package/dist/sessions-command.js +309 -0
- package/dist/sessions-command.js.map +1 -0
- package/dist/setup.d.ts +29 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +97 -0
- package/dist/setup.js.map +1 -0
- package/package.json +15 -15
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { RunEventSink } from "@mono-agent/agent-contracts";
|
|
2
|
+
import type { RunRecorder } from "@mono-agent/observability";
|
|
3
|
+
/** Stable run context stamped onto every broadcast frame. */
|
|
4
|
+
export interface BroadcastRunContext {
|
|
5
|
+
readonly runId: string;
|
|
6
|
+
readonly conversationId: string;
|
|
7
|
+
/** Producing instance's trace-source id (empty when the host has none). */
|
|
8
|
+
readonly sourceId: string;
|
|
9
|
+
readonly sourceLabel?: string;
|
|
10
|
+
/** Trigger channel, e.g. "cron" | "webhook" | "chat" | "memory". */
|
|
11
|
+
readonly source?: string;
|
|
12
|
+
/** Trigger detail (cron job id / webhook endpoint name). */
|
|
13
|
+
readonly sourceDetail?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Wrap a {@link RunRecorder} so every run start/event/finish is ALSO published to
|
|
17
|
+
* a {@link RunEventSink} (the in-process live bus), giving operator surfaces
|
|
18
|
+
* sub-run visibility the on-disk recorder can't (it flushes only at start/finish).
|
|
19
|
+
*
|
|
20
|
+
* Broadcast is best-effort and additive, exactly like the Phoenix exporter path:
|
|
21
|
+
* the inner recorder is the source of truth for the returned summary, and a
|
|
22
|
+
* publish failure never changes the run outcome (publish is wrapped and the bus's
|
|
23
|
+
* own `publish` is contracted never to throw). `seq` is left 0 here — the bus
|
|
24
|
+
* stamps a process-wide monotonic value on publish.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createBroadcastRunRecorder(inner: RunRecorder, sink: RunEventSink, ctx: BroadcastRunContext): RunRecorder;
|
|
27
|
+
//# sourceMappingURL=broadcast-recorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broadcast-recorder.d.ts","sourceRoot":"","sources":["../src/broadcast-recorder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE/E,OAAO,KAAK,EAAE,WAAW,EAAmD,MAAM,2BAA2B,CAAC;AAE9G,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,YAAY,EAClB,GAAG,EAAE,mBAAmB,GACvB,WAAW,CAyFb"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { LIVE_EVENT_SCHEMA } from "@mono-agent/agent-contracts";
|
|
2
|
+
import { redactJsonValue } from "@mono-agent/observability";
|
|
3
|
+
/**
|
|
4
|
+
* Wrap a {@link RunRecorder} so every run start/event/finish is ALSO published to
|
|
5
|
+
* a {@link RunEventSink} (the in-process live bus), giving operator surfaces
|
|
6
|
+
* sub-run visibility the on-disk recorder can't (it flushes only at start/finish).
|
|
7
|
+
*
|
|
8
|
+
* Broadcast is best-effort and additive, exactly like the Phoenix exporter path:
|
|
9
|
+
* the inner recorder is the source of truth for the returned summary, and a
|
|
10
|
+
* publish failure never changes the run outcome (publish is wrapped and the bus's
|
|
11
|
+
* own `publish` is contracted never to throw). `seq` is left 0 here — the bus
|
|
12
|
+
* stamps a process-wide monotonic value on publish.
|
|
13
|
+
*/
|
|
14
|
+
export function createBroadcastRunRecorder(inner, sink, ctx) {
|
|
15
|
+
let eventIndex = 0;
|
|
16
|
+
let terminalStarted = false;
|
|
17
|
+
let terminalPromise;
|
|
18
|
+
const publish = (frame) => {
|
|
19
|
+
try {
|
|
20
|
+
sink.publish(frame);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Broadcast is best-effort; a sink failure must never break the run.
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const finished = async (summary) => {
|
|
27
|
+
const redactedSummary = redactJsonValue(summary);
|
|
28
|
+
publish({
|
|
29
|
+
t: "run_finished",
|
|
30
|
+
schema: LIVE_EVENT_SCHEMA,
|
|
31
|
+
sourceId: ctx.sourceId,
|
|
32
|
+
runId: ctx.runId,
|
|
33
|
+
status: redactedSummary.status,
|
|
34
|
+
summary: redactedSummary,
|
|
35
|
+
seq: 0,
|
|
36
|
+
});
|
|
37
|
+
return summary;
|
|
38
|
+
};
|
|
39
|
+
const recorder = {
|
|
40
|
+
onEvent(event) {
|
|
41
|
+
// Terminal is a hard boundary in the live protocol. Events accepted after
|
|
42
|
+
// commit starts could otherwise appear after `run_finished` or be absent
|
|
43
|
+
// from the authoritative summary/export.
|
|
44
|
+
if (terminalStarted)
|
|
45
|
+
return;
|
|
46
|
+
inner.onEvent(event);
|
|
47
|
+
const redactedEvent = redactJsonValue(event);
|
|
48
|
+
publish({
|
|
49
|
+
t: "event",
|
|
50
|
+
schema: LIVE_EVENT_SCHEMA,
|
|
51
|
+
sourceId: ctx.sourceId,
|
|
52
|
+
runId: ctx.runId,
|
|
53
|
+
eventIndex: eventIndex++,
|
|
54
|
+
event: redactedEvent,
|
|
55
|
+
seq: 0,
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
async prepareFinish(result) {
|
|
59
|
+
await inner.prepareFinish?.(result);
|
|
60
|
+
},
|
|
61
|
+
async commitFinish(result) {
|
|
62
|
+
if (terminalPromise === undefined) {
|
|
63
|
+
terminalStarted = true;
|
|
64
|
+
terminalPromise = (async () => await finished(inner.commitFinish === undefined ? await inner.finish(result) : await inner.commitFinish(result)))();
|
|
65
|
+
}
|
|
66
|
+
return await terminalPromise;
|
|
67
|
+
},
|
|
68
|
+
async finish(result) {
|
|
69
|
+
await recorder.prepareFinish?.(result);
|
|
70
|
+
return await recorder.commitFinish(result);
|
|
71
|
+
},
|
|
72
|
+
async fail(error) {
|
|
73
|
+
if (terminalPromise === undefined) {
|
|
74
|
+
terminalStarted = true;
|
|
75
|
+
terminalPromise = (async () => await finished(await inner.fail(error)))();
|
|
76
|
+
}
|
|
77
|
+
return await terminalPromise;
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
// `start` is optional on RunRecorder — only expose (and emit run_started) when
|
|
81
|
+
// the inner recorder has one, so callers that probe `recorder.start?.()` behave
|
|
82
|
+
// identically to the unwrapped recorder.
|
|
83
|
+
if (inner.start !== undefined) {
|
|
84
|
+
const innerStart = inner.start.bind(inner);
|
|
85
|
+
recorder.start = async () => {
|
|
86
|
+
const summary = await innerStart();
|
|
87
|
+
publish({
|
|
88
|
+
t: "run_started",
|
|
89
|
+
schema: LIVE_EVENT_SCHEMA,
|
|
90
|
+
sourceId: ctx.sourceId,
|
|
91
|
+
...(ctx.sourceLabel === undefined ? {} : { sourceLabel: ctx.sourceLabel }),
|
|
92
|
+
runId: ctx.runId,
|
|
93
|
+
conversationId: ctx.conversationId,
|
|
94
|
+
...(ctx.source === undefined ? {} : { source: ctx.source }),
|
|
95
|
+
...(ctx.sourceDetail === undefined ? {} : { sourceDetail: ctx.sourceDetail }),
|
|
96
|
+
startedAt: summary.startedAt ?? new Date().toISOString(),
|
|
97
|
+
seq: 0,
|
|
98
|
+
});
|
|
99
|
+
return summary;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return recorder;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=broadcast-recorder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broadcast-recorder.js","sourceRoot":"","sources":["../src/broadcast-recorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAgB5D;;;;;;;;;;GAUG;AACH,MAAM,UAAU,0BAA0B,CACxC,KAAkB,EAClB,IAAkB,EAClB,GAAwB;IAExB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,IAAI,eAAgD,CAAC;IACrD,MAAM,OAAO,GAAG,CAAC,KAAoB,EAAQ,EAAE;QAC7C,IAAI,CAAC;YACH,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;QACvE,CAAC;IACH,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,KAAK,EAAE,OAAmB,EAAuB,EAAE;QAClE,MAAM,eAAe,GAAG,eAAe,CAAC,OAAO,CAAe,CAAC;QAC/D,OAAO,CAAC;YACN,CAAC,EAAE,cAAc;YACjB,MAAM,EAAE,iBAAiB;YACzB,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,MAAM,EAAE,eAAe,CAAC,MAAM;YAC9B,OAAO,EAAE,eAAe;YACxB,GAAG,EAAE,CAAC;SACP,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IACF,MAAM,QAAQ,GAAgB;QAC5B,OAAO,CAAC,KAAuB;YAC7B,0EAA0E;YAC1E,yEAAyE;YACzE,yCAAyC;YACzC,IAAI,eAAe;gBAAE,OAAO;YAC5B,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACrB,MAAM,aAAa,GAAG,eAAe,CAAC,KAAK,CAAqB,CAAC;YACjE,OAAO,CAAC;gBACN,CAAC,EAAE,OAAO;gBACV,MAAM,EAAE,iBAAiB;gBACzB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,UAAU,EAAE,UAAU,EAAE;gBACxB,KAAK,EAAE,aAAa;gBACpB,GAAG,EAAE,CAAC;aACP,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,aAAa,CAAC,MAAyB;YAC3C,MAAM,KAAK,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,CAAC;QACtC,CAAC;QACD,KAAK,CAAC,YAAY,CAAC,MAAyB;YAC1C,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;gBAClC,eAAe,GAAG,IAAI,CAAC;gBACvB,eAAe,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,MAAM,QAAQ,CAC3C,KAAK,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CACjG,CAAC,EAAE,CAAC;YACP,CAAC;YACD,OAAO,MAAM,eAAe,CAAC;QAC/B,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,MAAyB;YACpC,MAAM,QAAQ,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,CAAC;YACvC,OAAO,MAAM,QAAQ,CAAC,YAAa,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,KAAc;YACvB,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;gBAClC,eAAe,GAAG,IAAI,CAAC;gBACvB,eAAe,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,MAAM,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5E,CAAC;YACD,OAAO,MAAM,eAAe,CAAC;QAC/B,CAAC;KACF,CAAC;IACF,+EAA+E;IAC/E,gFAAgF;IAChF,yCAAyC;IACzC,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,QAAQ,CAAC,KAAK,GAAG,KAAK,IAAyB,EAAE;YAC/C,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;YACnC,OAAO,CAAC;gBACN,CAAC,EAAE,aAAa;gBAChB,MAAM,EAAE,iBAAiB;gBACzB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,GAAG,CAAC,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC;gBAC1E,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,cAAc,EAAE,GAAG,CAAC,cAAc;gBAClC,GAAG,CAAC,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;gBAC3D,GAAG,CAAC,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,CAAC,YAAY,EAAE,CAAC;gBAC7E,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACxD,GAAG,EAAE,CAAC;aACP,CAAC,CAAC;YACH,OAAO,OAAO,CAAC;QACjB,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LiveAdapterConfig, LiveAdapterHandle, LiveAdapterOptions } from "@mono-agent/operator-adapter";
|
|
2
|
+
import type { ChannelDriver } from "../channels.js";
|
|
3
|
+
export interface LiveChannelOverrides {
|
|
4
|
+
readonly adapterFactory?: (options: LiveAdapterOptions) => Promise<LiveAdapterHandle>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The live event relay is enabled by default on loopback so read-only operator
|
|
8
|
+
* surfaces (the `@mono-agent/session-web` PWA) can observe a running agent
|
|
9
|
+
* without a per-agent config edit.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createLiveChannelDriver(overrides?: LiveChannelOverrides): ChannelDriver<LiveAdapterConfig>;
|
|
12
|
+
//# sourceMappingURL=live.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/channel-drivers/live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAQpD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACvF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,GAAE,oBAAyB,GACnC,aAAa,CAAC,iBAAiB,CAAC,CAsClC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { buildChannelConfigView } from "../channel-config-view.js";
|
|
2
|
+
let liveModule;
|
|
3
|
+
const loadLiveModule = async () => (liveModule ??= await import("@mono-agent/operator-adapter"));
|
|
4
|
+
/**
|
|
5
|
+
* The live event relay is enabled by default on loopback so read-only operator
|
|
6
|
+
* surfaces (the `@mono-agent/session-web` PWA) can observe a running agent
|
|
7
|
+
* without a per-agent config edit.
|
|
8
|
+
*/
|
|
9
|
+
export function createLiveChannelDriver(overrides = {}) {
|
|
10
|
+
return {
|
|
11
|
+
id: "live",
|
|
12
|
+
label: "Live",
|
|
13
|
+
async configView(input) {
|
|
14
|
+
const adapter = await loadLiveModule();
|
|
15
|
+
return await buildChannelConfigView(this, adapter.LIVE_CONFIG_FIELDS, input, { jsonKey: "live" });
|
|
16
|
+
},
|
|
17
|
+
async loadConfig(input) {
|
|
18
|
+
const adapter = await loadLiveModule();
|
|
19
|
+
return await adapter.loadLiveAdapterConfig({ env: input.env, jsonPath: input.configPath });
|
|
20
|
+
},
|
|
21
|
+
isConfigError(error) {
|
|
22
|
+
return liveModule !== undefined && error instanceof liveModule.LiveAdapterError;
|
|
23
|
+
},
|
|
24
|
+
disabledReason(config) {
|
|
25
|
+
return config.enabled ? undefined : "Live event relay is disabled.";
|
|
26
|
+
},
|
|
27
|
+
async start(input) {
|
|
28
|
+
const adapterModule = await loadLiveModule();
|
|
29
|
+
const adapterFactory = overrides.adapterFactory ?? adapterModule.startLiveAdapter;
|
|
30
|
+
const bus = input.liveEventBus ?? adapterModule.createLiveEventBus();
|
|
31
|
+
const adapter = await adapterFactory({
|
|
32
|
+
bus,
|
|
33
|
+
host: input.config.host,
|
|
34
|
+
port: input.config.port,
|
|
35
|
+
basePath: input.config.basePath,
|
|
36
|
+
allowNonLoopback: input.config.allowNonLoopback,
|
|
37
|
+
...(input.config.apiKey === undefined ? {} : { apiKey: input.config.apiKey }),
|
|
38
|
+
onServerError: (reason) => input.onFailure(reason),
|
|
39
|
+
...(input.logger === undefined ? {} : { logger: input.logger }),
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
summary: { baseUrl: adapter.baseUrl },
|
|
43
|
+
stop: () => adapter.stop(),
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=live.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/channel-drivers/live.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAKnE,IAAI,UAAyC,CAAC;AAC9C,MAAM,cAAc,GAAG,KAAK,IAAgC,EAAE,CAC5D,CAAC,UAAU,KAAK,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC,CAAC;AAMhE;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,YAAkC,EAAE;IAEpC,OAAO;QACL,EAAE,EAAE,MAAM;QACV,KAAK,EAAE,MAAM;QACb,KAAK,CAAC,UAAU,CAAC,KAAK;YACpB,MAAM,OAAO,GAAG,MAAM,cAAc,EAAE,CAAC;YACvC,OAAO,MAAM,sBAAsB,CAAC,IAAI,EAAE,OAAO,CAAC,kBAAkB,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACpG,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,KAAK;YACpB,MAAM,OAAO,GAAG,MAAM,cAAc,EAAE,CAAC;YACvC,OAAO,MAAM,OAAO,CAAC,qBAAqB,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QAC7F,CAAC;QACD,aAAa,CAAC,KAAK;YACjB,OAAO,UAAU,KAAK,SAAS,IAAI,KAAK,YAAY,UAAU,CAAC,gBAAgB,CAAC;QAClF,CAAC;QACD,cAAc,CAAC,MAAM;YACnB,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,+BAA+B,CAAC;QACtE,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,KAAK;YACf,MAAM,aAAa,GAAG,MAAM,cAAc,EAAE,CAAC;YAC7C,MAAM,cAAc,GAAG,SAAS,CAAC,cAAc,IAAI,aAAa,CAAC,gBAAgB,CAAC;YAClF,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,IAAI,aAAa,CAAC,kBAAkB,EAAE,CAAC;YACrE,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC;gBACnC,GAAG;gBACH,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI;gBACvB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI;gBACvB,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ;gBAC/B,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,gBAAgB;gBAC/C,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC7E,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC;gBAClD,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;aAChE,CAAC,CAAC;YACH,OAAO;gBACL,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE;gBACrC,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE;aAC3B,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type NotifyToolsServer } from "./notify-tool.js";
|
|
2
|
+
/**
|
|
3
|
+
* Per-request input the harness hands each runtime-options extension. We only
|
|
4
|
+
* need the request's metadata to decide whether this is a proactive trigger.
|
|
5
|
+
*/
|
|
6
|
+
interface NotifyRuntimeExtensionInput {
|
|
7
|
+
readonly request: {
|
|
8
|
+
readonly metadata?: Record<string, unknown> | undefined;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
interface NotifyRuntimeExtensionResult {
|
|
12
|
+
readonly runtimeOptions: {
|
|
13
|
+
readonly mcpServers?: Record<string, unknown>;
|
|
14
|
+
};
|
|
15
|
+
readonly cleanup: () => Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Runtime extension that exposes the `notify_conversation`/`list_notify_destinations`
|
|
19
|
+
* tools, but ONLY on proactive trigger turns — cron and webhook — identified by the
|
|
20
|
+
* request metadata (`metadata.cron`/`metadata.webhook`, robust regardless of how the
|
|
21
|
+
* turn's conversationId is scoped). Live channel turns (telegram/slack/etc.) never see
|
|
22
|
+
* these tools: a live turn is already in its conversation and just replies.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createNotifyToolsRuntimeExtension(server: Pick<NotifyToolsServer, "url" | "token">): (input: NotifyRuntimeExtensionInput) => Promise<NotifyRuntimeExtensionResult>;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=notify-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify-runtime.d.ts","sourceRoot":"","sources":["../src/notify-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAExF;;;GAGG;AACH,UAAU,2BAA2B;IACnC,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;KAAE,CAAC;CAC/E;AAED,UAAU,4BAA4B;IACpC,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAID;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,IAAI,CAAC,iBAAiB,EAAE,KAAK,GAAG,OAAO,CAAC,GAC/C,CAAC,KAAK,EAAE,2BAA2B,KAAK,OAAO,CAAC,4BAA4B,CAAC,CAa/E"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { NOTIFY_TOOLS_MCP_SERVER_NAME } from "./notify-tool.js";
|
|
2
|
+
const EMPTY = { runtimeOptions: {}, cleanup: async () => { } };
|
|
3
|
+
/**
|
|
4
|
+
* Runtime extension that exposes the `notify_conversation`/`list_notify_destinations`
|
|
5
|
+
* tools, but ONLY on proactive trigger turns — cron and webhook — identified by the
|
|
6
|
+
* request metadata (`metadata.cron`/`metadata.webhook`, robust regardless of how the
|
|
7
|
+
* turn's conversationId is scoped). Live channel turns (telegram/slack/etc.) never see
|
|
8
|
+
* these tools: a live turn is already in its conversation and just replies.
|
|
9
|
+
*/
|
|
10
|
+
export function createNotifyToolsRuntimeExtension(server) {
|
|
11
|
+
const entry = {
|
|
12
|
+
[NOTIFY_TOOLS_MCP_SERVER_NAME]: {
|
|
13
|
+
type: "http",
|
|
14
|
+
url: server.url,
|
|
15
|
+
headers: { Authorization: `Bearer ${server.token}` },
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
return async (input) => {
|
|
19
|
+
return isProactiveTrigger(input.request.metadata)
|
|
20
|
+
? { runtimeOptions: { mcpServers: entry }, cleanup: async () => { } }
|
|
21
|
+
: EMPTY;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function isProactiveTrigger(metadata) {
|
|
25
|
+
return metadata !== undefined && (metadata.cron !== undefined || metadata.webhook !== undefined);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=notify-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify-runtime.js","sourceRoot":"","sources":["../src/notify-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAA0B,MAAM,kBAAkB,CAAC;AAexF,MAAM,KAAK,GAAiC,EAAE,cAAc,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,CAAC;AAE5F;;;;;;GAMG;AACH,MAAM,UAAU,iCAAiC,CAC/C,MAAgD;IAEhD,MAAM,KAAK,GAAG;QACZ,CAAC,4BAA4B,CAAC,EAAE;YAC9B,IAAI,EAAE,MAAM;YACZ,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,CAAC,KAAK,EAAE,EAAE;SACrD;KACF,CAAC;IACF,OAAO,KAAK,EAAE,KAAK,EAAE,EAAE;QACrB,OAAO,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC/C,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE;YACpE,CAAC,CAAC,KAAK,CAAC;IACZ,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,QAA6C;IACvE,OAAO,QAAQ,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC;AACnG,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { MonoAgentAppLogger } from "./channels.js";
|
|
2
|
+
import type { NotifyDeliveryResult } from "./proactive-notify.js";
|
|
3
|
+
/**
|
|
4
|
+
* In-process MCP server that exposes the proactive-notification tools to the agent.
|
|
5
|
+
*
|
|
6
|
+
* Unlike `memory_recall`/the adapter send tools (stdio children that re-derive
|
|
7
|
+
* everything from config/disk), notification delivery has to run a real turn on a
|
|
8
|
+
* destination channel's LIVE session, so the handler must reach the app's running
|
|
9
|
+
* channel registry — which only exists in this process. We therefore host the
|
|
10
|
+
* tools over loopback HTTP (the one MCP transport the runtime's client supports
|
|
11
|
+
* for an in-process server) and close over app-supplied delivery/discovery hooks.
|
|
12
|
+
*
|
|
13
|
+
* Two tools, both intended for proactive cron/webhook turns (the runtime extension
|
|
14
|
+
* only injects this server for those):
|
|
15
|
+
* - `list_notify_destinations` — discover the conversations the agent may notify
|
|
16
|
+
* (answers "how do I get a conversationId?" when there is no triggering payload).
|
|
17
|
+
* - `notify_conversation` — deliver a message as a real turn into one of them.
|
|
18
|
+
*/
|
|
19
|
+
export declare const NOTIFY_TOOLS_MCP_SERVER_NAME = "mono-agent-notify";
|
|
20
|
+
/** A conversation the agent may proactively notify, surfaced to the model for discovery. */
|
|
21
|
+
export interface NotifyToolDestination {
|
|
22
|
+
/** Destination conversationId to pass to `notify_conversation`, e.g. `telegram:42`. */
|
|
23
|
+
readonly conversationId: string;
|
|
24
|
+
/** Owning channel id (telegram/slack). */
|
|
25
|
+
readonly channelId: string;
|
|
26
|
+
/** ISO timestamp of the most recent turn on this conversation, if known. */
|
|
27
|
+
readonly lastSeen?: string;
|
|
28
|
+
/** True when this is an allowlisted destination the agent has not yet conversed with. */
|
|
29
|
+
readonly fromAllowlist?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface NotifyToolsDeps {
|
|
32
|
+
/** Deliver `text` as a real turn into `conversationId` (allowlist-enforced by the owning channel). */
|
|
33
|
+
readonly deliver: (conversationId: string, text: string) => Promise<NotifyDeliveryResult>;
|
|
34
|
+
/** The conversations the agent may notify right now (seen + single-allowlist destinations). */
|
|
35
|
+
readonly listDestinations: () => Promise<readonly NotifyToolDestination[]>;
|
|
36
|
+
readonly logger?: MonoAgentAppLogger | undefined;
|
|
37
|
+
}
|
|
38
|
+
export interface NotifyToolsServer {
|
|
39
|
+
/** Loopback URL the runtime's MCP client connects to (`http://127.0.0.1:<port>/mcp`). */
|
|
40
|
+
readonly url: string;
|
|
41
|
+
/** Bearer token required on every request. */
|
|
42
|
+
readonly token: string;
|
|
43
|
+
close(): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Start the in-process notify MCP server on an ephemeral loopback port. Stateless:
|
|
47
|
+
* each request gets a fresh `McpServer`+transport (the tools are pure request/response),
|
|
48
|
+
* which sidesteps session bookkeeping and concurrent-trigger races.
|
|
49
|
+
*/
|
|
50
|
+
export declare function startNotifyToolsServer(deps: NotifyToolsDeps): Promise<NotifyToolsServer>;
|
|
51
|
+
//# sourceMappingURL=notify-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify-tool.d.ts","sourceRoot":"","sources":["../src/notify-tool.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,4BAA4B,sBAAsB,CAAC;AAEhE,4FAA4F;AAC5F,MAAM,WAAW,qBAAqB;IACpC,uFAAuF;IACvF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,yFAAyF;IACzF,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,sGAAsG;IACtG,QAAQ,CAAC,OAAO,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC1F,+FAA+F;IAC/F,QAAQ,CAAC,gBAAgB,EAAE,MAAM,OAAO,CAAC,SAAS,qBAAqB,EAAE,CAAC,CAAC;IAC3E,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;CAClD;AAED,MAAM,WAAW,iBAAiB;IAChC,yFAAyF;IACzF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAID;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgC9F"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
5
|
+
import * as z from "zod/v4";
|
|
6
|
+
/**
|
|
7
|
+
* In-process MCP server that exposes the proactive-notification tools to the agent.
|
|
8
|
+
*
|
|
9
|
+
* Unlike `memory_recall`/the adapter send tools (stdio children that re-derive
|
|
10
|
+
* everything from config/disk), notification delivery has to run a real turn on a
|
|
11
|
+
* destination channel's LIVE session, so the handler must reach the app's running
|
|
12
|
+
* channel registry — which only exists in this process. We therefore host the
|
|
13
|
+
* tools over loopback HTTP (the one MCP transport the runtime's client supports
|
|
14
|
+
* for an in-process server) and close over app-supplied delivery/discovery hooks.
|
|
15
|
+
*
|
|
16
|
+
* Two tools, both intended for proactive cron/webhook turns (the runtime extension
|
|
17
|
+
* only injects this server for those):
|
|
18
|
+
* - `list_notify_destinations` — discover the conversations the agent may notify
|
|
19
|
+
* (answers "how do I get a conversationId?" when there is no triggering payload).
|
|
20
|
+
* - `notify_conversation` — deliver a message as a real turn into one of them.
|
|
21
|
+
*/
|
|
22
|
+
export const NOTIFY_TOOLS_MCP_SERVER_NAME = "mono-agent-notify";
|
|
23
|
+
const MCP_PATH = "/mcp";
|
|
24
|
+
/**
|
|
25
|
+
* Start the in-process notify MCP server on an ephemeral loopback port. Stateless:
|
|
26
|
+
* each request gets a fresh `McpServer`+transport (the tools are pure request/response),
|
|
27
|
+
* which sidesteps session bookkeeping and concurrent-trigger races.
|
|
28
|
+
*/
|
|
29
|
+
export async function startNotifyToolsServer(deps) {
|
|
30
|
+
const token = randomBytes(24).toString("hex");
|
|
31
|
+
const expectedAuth = `Bearer ${token}`;
|
|
32
|
+
const httpServer = createServer((req, res) => {
|
|
33
|
+
void handleHttpRequest(req, res, expectedAuth, deps);
|
|
34
|
+
});
|
|
35
|
+
await new Promise((resolve, reject) => {
|
|
36
|
+
const onError = (error) => reject(error);
|
|
37
|
+
httpServer.once("error", onError);
|
|
38
|
+
httpServer.listen(0, "127.0.0.1", () => {
|
|
39
|
+
httpServer.removeListener("error", onError);
|
|
40
|
+
resolve();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
const address = httpServer.address();
|
|
44
|
+
if (address === null || typeof address === "string") {
|
|
45
|
+
httpServer.close();
|
|
46
|
+
throw new Error("notify tools server: failed to bind a loopback port.");
|
|
47
|
+
}
|
|
48
|
+
const url = `http://127.0.0.1:${address.port}${MCP_PATH}`;
|
|
49
|
+
return {
|
|
50
|
+
url,
|
|
51
|
+
token,
|
|
52
|
+
close: () => new Promise((resolve) => {
|
|
53
|
+
httpServer.close(() => resolve());
|
|
54
|
+
}),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async function handleHttpRequest(req, res, expectedAuth, deps) {
|
|
58
|
+
if (!isAuthorized(req, expectedAuth)) {
|
|
59
|
+
res.writeHead(401, { "content-type": "application/json" });
|
|
60
|
+
res.end(JSON.stringify({ error: "unauthorized" }));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (req.url?.split("?", 1)[0] !== MCP_PATH) {
|
|
64
|
+
res.writeHead(404, { "content-type": "application/json" });
|
|
65
|
+
res.end(JSON.stringify({ error: "not found" }));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
// Stateless: only POST carries JSON-RPC. The single tool round-trips are
|
|
69
|
+
// request/response, so reject the optional GET/DELETE session streams.
|
|
70
|
+
if (req.method !== "POST") {
|
|
71
|
+
res.writeHead(405, { "content-type": "application/json", allow: "POST" });
|
|
72
|
+
res.end(JSON.stringify({ error: "method not allowed" }));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const server = buildMcpServer(deps);
|
|
76
|
+
// Stateless: omitting sessionIdGenerator runs the transport without session
|
|
77
|
+
// tracking, so a fresh server+transport per request is the correct pattern and
|
|
78
|
+
// concurrent triggers never share state.
|
|
79
|
+
const transport = new StreamableHTTPServerTransport({});
|
|
80
|
+
// Idempotent: with HTTP keep-alive the response can `finish` without firing
|
|
81
|
+
// `close`, so bind both and guard against a double-close leaking nothing.
|
|
82
|
+
let cleaned = false;
|
|
83
|
+
const cleanup = () => {
|
|
84
|
+
if (cleaned)
|
|
85
|
+
return;
|
|
86
|
+
cleaned = true;
|
|
87
|
+
void transport.close();
|
|
88
|
+
void server.close();
|
|
89
|
+
};
|
|
90
|
+
res.on("close", cleanup);
|
|
91
|
+
res.on("finish", cleanup);
|
|
92
|
+
try {
|
|
93
|
+
// The transport implements the SDK Transport interface at runtime; the cast
|
|
94
|
+
// bridges an exactOptionalPropertyTypes mismatch in the SDK's own typings.
|
|
95
|
+
await server.connect(transport);
|
|
96
|
+
await transport.handleRequest(req, res);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
deps.logger?.error?.("notify tools server: request failed.", { reason: reasonOf(error) });
|
|
100
|
+
if (!res.headersSent) {
|
|
101
|
+
res.writeHead(500, { "content-type": "application/json" });
|
|
102
|
+
res.end(JSON.stringify({ error: "internal error" }));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function isAuthorized(req, expectedAuth) {
|
|
107
|
+
const header = req.headers.authorization;
|
|
108
|
+
if (typeof header !== "string") {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
const a = Buffer.from(header);
|
|
112
|
+
const b = Buffer.from(expectedAuth);
|
|
113
|
+
return a.length === b.length && timingSafeEqual(a, b);
|
|
114
|
+
}
|
|
115
|
+
function buildMcpServer(deps) {
|
|
116
|
+
const server = new McpServer({ name: "agent-notify-tools", version: "0.1.0" });
|
|
117
|
+
server.registerTool("list_notify_destinations", {
|
|
118
|
+
title: "List notification destinations",
|
|
119
|
+
description: "List the conversations you can proactively deliver a message to with notify_conversation. " +
|
|
120
|
+
"Use this when you have no triggering conversationId in hand (e.g. a scheduled/cron run) to " +
|
|
121
|
+
"discover where to reach the user. Each entry's `conversationId` is what notify_conversation " +
|
|
122
|
+
"expects — read its description for how delivery works (the destination turn's reply is what is sent).",
|
|
123
|
+
inputSchema: {},
|
|
124
|
+
}, async () => {
|
|
125
|
+
const destinations = await deps.listDestinations();
|
|
126
|
+
const lines = destinations.length === 0
|
|
127
|
+
? ["(no known destinations yet — the agent has not handled any push-channel conversation and no single allowlisted destination is configured)"]
|
|
128
|
+
: destinations.map((d) => `- ${d.conversationId}${d.lastSeen === undefined ? "" : ` (last active ${d.lastSeen})`}${d.fromAllowlist === true ? " (allowlisted, not yet used)" : ""}`);
|
|
129
|
+
return {
|
|
130
|
+
content: [{ type: "text", text: ["Conversations you can notify:", ...lines].join("\n") }],
|
|
131
|
+
structuredContent: { destinations },
|
|
132
|
+
};
|
|
133
|
+
});
|
|
134
|
+
server.registerTool("notify_conversation", {
|
|
135
|
+
title: "Notify a conversation",
|
|
136
|
+
description: "Proactively deliver a message into a conversation you are not currently handling. The message " +
|
|
137
|
+
"runs as a real turn on that conversation's own session and THAT TURN'S REPLY is what the user " +
|
|
138
|
+
"receives (so the user sees it natively and the conversation remembers it). Use this to follow up " +
|
|
139
|
+
"from a cron job or an inbound webhook callback.\n\n" +
|
|
140
|
+
"How `text` is delivered (read carefully — this is the #1 mistake):\n" +
|
|
141
|
+
"- `text` is the stimulus the destination conversation acts on; it is NOT posted verbatim. The " +
|
|
142
|
+
"destination agent reads `text` and composes the user-facing reply with its own context, and that " +
|
|
143
|
+
"reply is delivered automatically.\n" +
|
|
144
|
+
"- To deliver pre-composed or exact content (e.g. a digest), phrase `text` as an explicit reply " +
|
|
145
|
+
"instruction, e.g.: \"Reply with the text below exactly as written, adding nothing, and do not call " +
|
|
146
|
+
"any tools — your reply is delivered automatically:\\n\\n<your content>\".\n" +
|
|
147
|
+
"- The destination must NOT call its own send tools (e.g. slack_send_message) — its reply is already " +
|
|
148
|
+
"delivered, so sending again posts the message twice.\n\n" +
|
|
149
|
+
"How to choose `conversationId`:\n" +
|
|
150
|
+
"- Webhook/async callback: pass the `conversationId` carried in the triggering request payload.\n" +
|
|
151
|
+
"- Otherwise (e.g. a scheduled run): call list_notify_destinations first and pick from it.\n\n" +
|
|
152
|
+
"Delivery is bounded by the channel allowlist and may return delivered:false (e.g. unknown/disallowed " +
|
|
153
|
+
"id, channel offline). The call blocks until the destination turn replies, so keep that turn to a single " +
|
|
154
|
+
"reply — a turn that re-scans, recalls, or hunts for a send tool is slow and can hit the request timeout. " +
|
|
155
|
+
"If you receive delivered:false, do not assume it was also delivered some other way.",
|
|
156
|
+
inputSchema: {
|
|
157
|
+
conversationId: z
|
|
158
|
+
.string()
|
|
159
|
+
.min(1)
|
|
160
|
+
.describe("Destination conversationId, e.g. telegram:42 or slack:C123 (or slack:C123:1718.99 for a thread)."),
|
|
161
|
+
text: z
|
|
162
|
+
.string()
|
|
163
|
+
.min(1)
|
|
164
|
+
.describe("What to deliver. The destination conversation runs this as a turn and its reply is delivered; " +
|
|
165
|
+
"to deliver exact content, phrase this as a reply-verbatim, no-tools instruction (see the tool description)."),
|
|
166
|
+
},
|
|
167
|
+
}, async (args) => {
|
|
168
|
+
const result = await deps.deliver(args.conversationId, args.text);
|
|
169
|
+
const summary = result.delivered
|
|
170
|
+
? `Delivered to ${args.conversationId}.`
|
|
171
|
+
: `Not delivered to ${args.conversationId}${result.reason === undefined ? "" : `: ${result.reason}`}.`;
|
|
172
|
+
return {
|
|
173
|
+
content: [{ type: "text", text: summary }],
|
|
174
|
+
structuredContent: { delivered: result.delivered, ...(result.reason === undefined ? {} : { reason: result.reason }) },
|
|
175
|
+
};
|
|
176
|
+
});
|
|
177
|
+
return server;
|
|
178
|
+
}
|
|
179
|
+
function reasonOf(error) {
|
|
180
|
+
return error instanceof Error ? error.message : String(error);
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=notify-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify-tool.js","sourceRoot":"","sources":["../src/notify-tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { MonoAgentConfigJson } from "@mono-agent/config";
|
|
2
|
+
import type { RecipeInput, RecipeInputValues } from "./types.js";
|
|
3
|
+
export declare const DEFAULT_MODEL = "claude:claude-sonnet-4-6";
|
|
4
|
+
/** The model input every recipe shares; overridable from `--model`. */
|
|
5
|
+
export declare const MODEL_INPUT: RecipeInput;
|
|
6
|
+
/**
|
|
7
|
+
* The adapter-neutral skeleton every recipe extends: runtime model, identity,
|
|
8
|
+
* empty tool policy, local artifacts, and the trace registry. Recipes spread
|
|
9
|
+
* this and add their channel / memory / sandbox / observability blocks. Mirrors
|
|
10
|
+
* `init.ts`'s scaffold so a recipe-built folder matches a hand-init'd one.
|
|
11
|
+
*/
|
|
12
|
+
export declare function baseConfig(input: RecipeInputValues): MonoAgentConfigJson;
|
|
13
|
+
/** A `memory` block for the given tier, rooted at the standard memory path. */
|
|
14
|
+
export declare function memoryBlock(mode: "lite" | "journal" | "bujo"): NonNullable<MonoAgentConfigJson["memory"]>;
|
|
15
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/recipes/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAG9D,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEjE,eAAO,MAAM,aAAa,6BAA6B,CAAC;AAExD,uEAAuE;AACvE,eAAO,MAAM,WAAW,EAAE,WAKzB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,iBAAiB,GAAG,mBAAmB,CA0BxE;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAChC,WAAW,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,CAM5C"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { monoAgentConfigWithSchema } from "../config-reference.js";
|
|
2
|
+
export const DEFAULT_MODEL = "claude:claude-sonnet-4-6";
|
|
3
|
+
/** The model input every recipe shares; overridable from `--model`. */
|
|
4
|
+
export const MODEL_INPUT = {
|
|
5
|
+
id: "model",
|
|
6
|
+
label: "Model",
|
|
7
|
+
description: "Primary runtime model reference, e.g. claude:claude-sonnet-4-6, codex:gpt-5.5, pi:ollama:gemma4:31b.",
|
|
8
|
+
default: DEFAULT_MODEL,
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The adapter-neutral skeleton every recipe extends: runtime model, identity,
|
|
12
|
+
* empty tool policy, local artifacts, and the trace registry. Recipes spread
|
|
13
|
+
* this and add their channel / memory / sandbox / observability blocks. Mirrors
|
|
14
|
+
* `init.ts`'s scaffold so a recipe-built folder matches a hand-init'd one.
|
|
15
|
+
*/
|
|
16
|
+
export function baseConfig(input) {
|
|
17
|
+
return monoAgentConfigWithSchema({
|
|
18
|
+
runtime: {
|
|
19
|
+
model: input.model ?? DEFAULT_MODEL,
|
|
20
|
+
workspace: ".",
|
|
21
|
+
},
|
|
22
|
+
context: {
|
|
23
|
+
identityPath: "./IDENTITY.md",
|
|
24
|
+
selectedSkills: [],
|
|
25
|
+
},
|
|
26
|
+
tools: {
|
|
27
|
+
allowedTools: [],
|
|
28
|
+
disallowedTools: [],
|
|
29
|
+
},
|
|
30
|
+
artifacts: {
|
|
31
|
+
dir: "./.mono-agent/artifacts",
|
|
32
|
+
retention: {
|
|
33
|
+
maxAgeDays: 365,
|
|
34
|
+
maxCount: 50000,
|
|
35
|
+
dryRun: false,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
traceability: {
|
|
39
|
+
registryDir: "./.mono-agent/trace-sources",
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/** A `memory` block for the given tier, rooted at the standard memory path. */
|
|
44
|
+
export function memoryBlock(mode) {
|
|
45
|
+
return {
|
|
46
|
+
mode,
|
|
47
|
+
path: "./.mono-agent/memory",
|
|
48
|
+
writeMode: mode === "bujo" ? "capture" : "append-host-summary",
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/recipes/base.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAGnE,MAAM,CAAC,MAAM,aAAa,GAAG,0BAA0B,CAAC;AAExD,uEAAuE;AACvE,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC,EAAE,EAAE,OAAO;IACX,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,sGAAsG;IACnH,OAAO,EAAE,aAAa;CACvB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,KAAwB;IACjD,OAAO,yBAAyB,CAAC;QAC/B,OAAO,EAAE;YACP,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,aAAa;YACnC,SAAS,EAAE,GAAG;SACf;QACD,OAAO,EAAE;YACP,YAAY,EAAE,eAAe;YAC7B,cAAc,EAAE,EAAE;SACnB;QACD,KAAK,EAAE;YACL,YAAY,EAAE,EAAE;YAChB,eAAe,EAAE,EAAE;SACpB;QACD,SAAS,EAAE;YACT,GAAG,EAAE,yBAAyB;YAC9B,SAAS,EAAE;gBACT,UAAU,EAAE,GAAG;gBACf,QAAQ,EAAE,KAAK;gBACf,MAAM,EAAE,KAAK;aACd;SACF;QACD,YAAY,EAAE;YACZ,WAAW,EAAE,6BAA6B;SAC3C;KACqB,CAAC,CAAC;AAC5B,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,WAAW,CACzB,IAAiC;IAEjC,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,sBAAsB;QAC5B,SAAS,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,qBAAqB;KAC/D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/recipes/catalog.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAqB,MAAM,YAAY,CAAC;AAqhBjE,6EAA6E;AAC7E,eAAO,MAAM,cAAc,EAAE,SAAS,WAAW,EAchD,CAAC"}
|