@mono-agent/agent-app 0.8.0 → 0.9.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.
- package/README.md +71 -22
- package/dist/account-home.d.ts +6 -0
- package/dist/account-home.d.ts.map +1 -0
- package/dist/account-home.js +9 -0
- package/dist/account-home.js.map +1 -0
- package/dist/app-config.d.ts +3 -1
- package/dist/app-config.d.ts.map +1 -1
- package/dist/app-config.js +8 -5
- package/dist/app-config.js.map +1 -1
- package/dist/app.d.ts +25 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +237 -16
- package/dist/app.js.map +1 -1
- package/dist/background-environment.d.ts +16 -0
- package/dist/background-environment.d.ts.map +1 -0
- package/dist/background-environment.js +68 -0
- package/dist/background-environment.js.map +1 -0
- package/dist/background-runtime.d.ts +62 -0
- package/dist/background-runtime.d.ts.map +1 -0
- package/dist/background-runtime.js +1115 -0
- package/dist/background-runtime.js.map +1 -0
- package/dist/background-snapshot-key.d.ts +13 -0
- package/dist/background-snapshot-key.d.ts.map +1 -0
- package/dist/background-snapshot-key.js +194 -0
- package/dist/background-snapshot-key.js.map +1 -0
- package/dist/background-snapshot.d.ts +96 -0
- package/dist/background-snapshot.d.ts.map +1 -0
- package/dist/background-snapshot.js +450 -0
- package/dist/background-snapshot.js.map +1 -0
- package/dist/background-worker-lease.d.ts +39 -0
- package/dist/background-worker-lease.d.ts.map +1 -0
- package/dist/background-worker-lease.js +356 -0
- package/dist/background-worker-lease.js.map +1 -0
- package/dist/background.d.ts +74 -2
- package/dist/background.d.ts.map +1 -1
- package/dist/background.js +815 -73
- package/dist/background.js.map +1 -1
- package/dist/channel-plugins.d.ts +2 -0
- package/dist/channel-plugins.d.ts.map +1 -1
- package/dist/channel-plugins.js +8 -0
- package/dist/channel-plugins.js.map +1 -1
- package/dist/channels.d.ts +10 -0
- package/dist/channels.d.ts.map +1 -1
- package/dist/channels.js +71 -3
- package/dist/channels.js.map +1 -1
- package/dist/cli.d.ts +12 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +341 -63
- package/dist/cli.js.map +1 -1
- package/dist/config-reference.d.ts.map +1 -1
- package/dist/config-reference.js +253 -0
- package/dist/config-reference.js.map +1 -1
- package/dist/configuration-proposal-tool.d.ts +7 -0
- package/dist/configuration-proposal-tool.d.ts.map +1 -1
- package/dist/configuration-proposal-tool.js +55 -6
- package/dist/configuration-proposal-tool.js.map +1 -1
- package/dist/configured-agent.d.ts +4 -0
- package/dist/configured-agent.d.ts.map +1 -1
- package/dist/configured-agent.js +15 -0
- package/dist/configured-agent.js.map +1 -1
- package/dist/continuation-command.d.ts +15 -0
- package/dist/continuation-command.d.ts.map +1 -0
- package/dist/continuation-command.js +170 -0
- package/dist/continuation-command.js.map +1 -0
- package/dist/continuation-config.d.ts +25 -0
- package/dist/continuation-config.d.ts.map +1 -0
- package/dist/continuation-config.js +236 -0
- package/dist/continuation-config.js.map +1 -0
- package/dist/continuation-service.d.ts +99 -0
- package/dist/continuation-service.d.ts.map +1 -0
- package/dist/continuation-service.js +1313 -0
- package/dist/continuation-service.js.map +1 -0
- package/dist/continuation-store.d.ts +104 -0
- package/dist/continuation-store.d.ts.map +1 -0
- package/dist/continuation-store.js +688 -0
- package/dist/continuation-store.js.map +1 -0
- package/dist/continuations.d.ts +167 -0
- package/dist/continuations.d.ts.map +1 -0
- package/dist/continuations.js +71 -0
- package/dist/continuations.js.map +1 -0
- package/dist/doctor.d.ts +2 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +426 -27
- package/dist/doctor.js.map +1 -1
- package/dist/first-run-managed-memory.d.ts.map +1 -1
- package/dist/first-run-managed-memory.js +66 -3
- package/dist/first-run-managed-memory.js.map +1 -1
- package/dist/first-run-readiness.d.ts.map +1 -1
- package/dist/first-run-readiness.js +2 -31
- package/dist/first-run-readiness.js.map +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +7 -0
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +7 -2
- package/dist/init.js.map +1 -1
- package/dist/launchd.d.ts +16 -6
- package/dist/launchd.d.ts.map +1 -1
- package/dist/launchd.js +30 -15
- package/dist/launchd.js.map +1 -1
- package/dist/local-configuration.d.ts +61 -18
- package/dist/local-configuration.d.ts.map +1 -1
- package/dist/local-configuration.js +530 -145
- package/dist/local-configuration.js.map +1 -1
- package/dist/managed-runtime-packages.d.ts +9 -0
- package/dist/managed-runtime-packages.d.ts.map +1 -0
- package/dist/managed-runtime-packages.js +56 -0
- package/dist/managed-runtime-packages.js.map +1 -0
- package/dist/memory-embedding-service.d.ts +33 -0
- package/dist/memory-embedding-service.d.ts.map +1 -0
- package/dist/memory-embedding-service.js +207 -0
- package/dist/memory-embedding-service.js.map +1 -0
- package/dist/memory-recall.d.ts +5 -4
- package/dist/memory-recall.d.ts.map +1 -1
- package/dist/memory-recall.js +21 -8
- package/dist/memory-recall.js.map +1 -1
- package/dist/modules/catalog.d.ts.map +1 -1
- package/dist/modules/catalog.js +91 -9
- package/dist/modules/catalog.js.map +1 -1
- 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/proactive-notify.d.ts +2 -0
- package/dist/proactive-notify.d.ts.map +1 -1
- package/dist/proactive-notify.js +1 -0
- package/dist/proactive-notify.js.map +1 -1
- package/dist/process-incarnation.d.ts +23 -0
- package/dist/process-incarnation.d.ts.map +1 -0
- package/dist/process-incarnation.js +208 -0
- package/dist/process-incarnation.js.map +1 -0
- package/dist/project-skills.d.ts +1 -1
- package/dist/project-skills.js +6 -6
- 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/sandbox-manager.d.ts +17 -0
- package/dist/sandbox-manager.d.ts.map +1 -1
- package/dist/sandbox-manager.js +673 -127
- package/dist/sandbox-manager.js.map +1 -1
- 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/dist/supermemory-plugin.d.ts +5 -3
- package/dist/supermemory-plugin.d.ts.map +1 -1
- package/dist/supermemory-plugin.js +11 -5
- package/dist/supermemory-plugin.js.map +1 -1
- package/dist/tui-command.d.ts +43 -2
- package/dist/tui-command.d.ts.map +1 -1
- package/dist/tui-command.js +261 -27
- package/dist/tui-command.js.map +1 -1
- package/dist/wizard/answers.d.ts +4 -4
- package/dist/wizard/answers.d.ts.map +1 -1
- package/dist/wizard/answers.js +4 -21
- package/dist/wizard/answers.js.map +1 -1
- package/dist/wizard/run.d.ts.map +1 -1
- package/dist/wizard/run.js +162 -5
- package/dist/wizard/run.js.map +1 -1
- package/package.json +15 -15
- package/schema/mono-agent.config.schema.json +206 -3
- package/skills/mono-agent-composer/SKILL.md +4 -4
- package/skills/mono-agent-composer/references/config-blueprint.md +6 -6
- package/skills/mono-agent-composer/references/discovery-questions.md +25 -10
- package/skills/mono-agent-composer/references/feature-coverage.md +7 -7
- package/skills/mono-agent-composer/references/package-map.md +1 -1
- package/skills/mono-agent-composer/references/validation.md +2 -2
|
@@ -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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"}
|
|
@@ -15,6 +15,8 @@ export interface ProactiveNotifyInput {
|
|
|
15
15
|
* destination's harness (e.g. a Slack interactive trigger).
|
|
16
16
|
*/
|
|
17
17
|
readonly verbatim?: boolean;
|
|
18
|
+
/** Stable host delivery identity for adapters with duplicate suppression. */
|
|
19
|
+
readonly deliveryKey?: string;
|
|
18
20
|
/** Currently running channels, keyed by id (the app's live registry). */
|
|
19
21
|
readonly running: ReadonlyMap<ChannelId, Pick<RunningChannel, "notify">>;
|
|
20
22
|
readonly logger?: MonoAgentAppLogger;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proactive-notify.d.ts","sourceRoot":"","sources":["../src/proactive-notify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAInF,YAAY,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAcxE,mHAAmH;AACnH,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAMtF;AAED,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,sFAAsF;IACtF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,
|
|
1
|
+
{"version":3,"file":"proactive-notify.d.ts","sourceRoot":"","sources":["../src/proactive-notify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAInF,YAAY,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAcxE,mHAAmH;AACnH,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAMtF;AAED,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,sFAAsF;IACtF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,6EAA6E;IAC7E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAgC3G"}
|
package/dist/proactive-notify.js
CHANGED
|
@@ -44,6 +44,7 @@ export async function routeProactiveNotification(input) {
|
|
|
44
44
|
conversationId: input.conversationId,
|
|
45
45
|
text: input.text,
|
|
46
46
|
...(input.verbatim === undefined ? {} : { verbatim: input.verbatim }),
|
|
47
|
+
...(input.deliveryKey === undefined ? {} : { deliveryKey: input.deliveryKey }),
|
|
47
48
|
});
|
|
48
49
|
}
|
|
49
50
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proactive-notify.js","sourceRoot":"","sources":["../src/proactive-notify.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,MAAM,sBAAsB,GAAuC;IACjE,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;CACrB,CAAC;AAEF,mHAAmH;AACnH,MAAM,UAAU,wBAAwB,CAAC,cAAsB;IAC7D,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,sBAAsB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAChE,CAAC;
|
|
1
|
+
{"version":3,"file":"proactive-notify.js","sourceRoot":"","sources":["../src/proactive-notify.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,MAAM,sBAAsB,GAAuC;IACjE,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;CACrB,CAAC;AAEF,mHAAmH;AACnH,MAAM,UAAU,wBAAwB,CAAC,cAAsB;IAC7D,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,sBAAsB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAChE,CAAC;AAqBD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,KAA2B;IAC1E,MAAM,SAAS,GAAG,wBAAwB,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACjE,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,2DAA2D,EAAE;YAChF,cAAc,EAAE,KAAK,CAAC,cAAc;SACrC,CAAC,CAAC;QACH,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,yCAAyC,EAAE,CAAC;IACjF,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC7C,IAAI,OAAO,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;QAClC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAClB,kGAAkG,EAClG,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,SAAS,EAAE,CACpD,CAAC;QACF,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,gEAAgE,EAAE,CAAC;IACpH,CAAC;IACD,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,MAAM,CAAC;YAC1B,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;YACrE,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;SAC/E,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/B,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,kEAAkE,EAAE;YACvF,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,SAAS;YACT,MAAM;SACP,CAAC,CAAC;QACH,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACtC,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const PROCESS_INCARNATION_SCHEMA = "mono-agent.process-incarnation.v1";
|
|
2
|
+
/** Stable OS evidence that distinguishes one use of a PID from every later reuse. */
|
|
3
|
+
export interface ProcessIncarnation {
|
|
4
|
+
readonly schema: typeof PROCESS_INCARNATION_SCHEMA;
|
|
5
|
+
readonly bootSessionId: string;
|
|
6
|
+
readonly processStartId: string;
|
|
7
|
+
}
|
|
8
|
+
export type SameProcessIncarnation = (pid: number, expected: ProcessIncarnation) => boolean | Promise<boolean>;
|
|
9
|
+
/** Capture the current process's boot-session and process-birth identity. */
|
|
10
|
+
export declare function currentProcessIncarnation(): Promise<ProcessIncarnation>;
|
|
11
|
+
/**
|
|
12
|
+
* Read one PID incarnation without mistaking `kill(pid, 0)` for owner identity.
|
|
13
|
+
* Linux exposes a boot UUID and per-process start tick directly. Darwin/BSD use
|
|
14
|
+
* the kernel boot time plus `ps`'s stable long-start field. Windows uses native
|
|
15
|
+
* process/OS creation timestamps through PowerShell.
|
|
16
|
+
*/
|
|
17
|
+
export declare function readProcessIncarnation(pid: number): Promise<ProcessIncarnation | undefined>;
|
|
18
|
+
/** True only when PID, boot session, and process birth all still identify the owner. */
|
|
19
|
+
export declare function isSameProcessIncarnation(pid: number, expected: ProcessIncarnation): Promise<boolean>;
|
|
20
|
+
export declare function processIncarnationsEqual(left: ProcessIncarnation, right: ProcessIncarnation): boolean;
|
|
21
|
+
/** Fail-closed parser for persisted lock-owner data. */
|
|
22
|
+
export declare function processIncarnationFromJson(value: unknown): ProcessIncarnation | undefined;
|
|
23
|
+
//# sourceMappingURL=process-incarnation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-incarnation.d.ts","sourceRoot":"","sources":["../src/process-incarnation.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,0BAA0B,sCAAsC,CAAC;AAE9E,qFAAqF;AACrF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,OAAO,0BAA0B,CAAC;IACnD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,MAAM,sBAAsB,GAAG,CACnC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,kBAAkB,KACzB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAIhC,6EAA6E;AAC7E,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAM7E;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAajG;AAED,wFAAwF;AACxF,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,kBAAkB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAGlB;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,kBAAkB,EACxB,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAIT;AAED,wDAAwD;AACxD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,GAAG,SAAS,CAUzF"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import process from "node:process";
|
|
5
|
+
export const PROCESS_INCARNATION_SCHEMA = "mono-agent.process-incarnation.v1";
|
|
6
|
+
let bootSessionIdPromise;
|
|
7
|
+
/** Capture the current process's boot-session and process-birth identity. */
|
|
8
|
+
export async function currentProcessIncarnation() {
|
|
9
|
+
const incarnation = await readProcessIncarnation(process.pid);
|
|
10
|
+
if (incarnation === undefined) {
|
|
11
|
+
throw new Error(`Cannot read process incarnation for current pid ${process.pid}.`);
|
|
12
|
+
}
|
|
13
|
+
return incarnation;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Read one PID incarnation without mistaking `kill(pid, 0)` for owner identity.
|
|
17
|
+
* Linux exposes a boot UUID and per-process start tick directly. Darwin/BSD use
|
|
18
|
+
* the kernel boot time plus `ps`'s stable long-start field. Windows uses native
|
|
19
|
+
* process/OS creation timestamps through PowerShell.
|
|
20
|
+
*/
|
|
21
|
+
export async function readProcessIncarnation(pid) {
|
|
22
|
+
assertPid(pid);
|
|
23
|
+
if (!processExists(pid))
|
|
24
|
+
return undefined;
|
|
25
|
+
const [bootSessionId, processStartId] = await Promise.all([
|
|
26
|
+
currentBootSessionId(),
|
|
27
|
+
processStartIdentifier(pid),
|
|
28
|
+
]);
|
|
29
|
+
if (processStartId === undefined)
|
|
30
|
+
return undefined;
|
|
31
|
+
return {
|
|
32
|
+
schema: PROCESS_INCARNATION_SCHEMA,
|
|
33
|
+
bootSessionId,
|
|
34
|
+
processStartId,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** True only when PID, boot session, and process birth all still identify the owner. */
|
|
38
|
+
export async function isSameProcessIncarnation(pid, expected) {
|
|
39
|
+
const actual = await readProcessIncarnation(pid);
|
|
40
|
+
return actual !== undefined && processIncarnationsEqual(actual, expected);
|
|
41
|
+
}
|
|
42
|
+
export function processIncarnationsEqual(left, right) {
|
|
43
|
+
return left.schema === right.schema
|
|
44
|
+
&& left.bootSessionId === right.bootSessionId
|
|
45
|
+
&& left.processStartId === right.processStartId;
|
|
46
|
+
}
|
|
47
|
+
/** Fail-closed parser for persisted lock-owner data. */
|
|
48
|
+
export function processIncarnationFromJson(value) {
|
|
49
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
50
|
+
return undefined;
|
|
51
|
+
const record = value;
|
|
52
|
+
return record.schema === PROCESS_INCARNATION_SCHEMA
|
|
53
|
+
&& typeof record.bootSessionId === "string"
|
|
54
|
+
&& record.bootSessionId.length > 0
|
|
55
|
+
&& typeof record.processStartId === "string"
|
|
56
|
+
&& record.processStartId.length > 0
|
|
57
|
+
? record
|
|
58
|
+
: undefined;
|
|
59
|
+
}
|
|
60
|
+
async function currentBootSessionId() {
|
|
61
|
+
bootSessionIdPromise ??= readBootSessionId();
|
|
62
|
+
return await bootSessionIdPromise;
|
|
63
|
+
}
|
|
64
|
+
async function readBootSessionId() {
|
|
65
|
+
if (process.platform === "linux") {
|
|
66
|
+
const value = (await readFile("/proc/sys/kernel/random/boot_id", "utf8")).trim();
|
|
67
|
+
if (!/^[a-zA-Z0-9-]+$/u.test(value)) {
|
|
68
|
+
throw new Error("Linux boot session id is malformed.");
|
|
69
|
+
}
|
|
70
|
+
return `linux:${value}`;
|
|
71
|
+
}
|
|
72
|
+
if (process.platform === "darwin") {
|
|
73
|
+
const output = await execFileText("/usr/sbin/sysctl", ["-n", "kern.boottime"], posixEnvironment());
|
|
74
|
+
const match = /sec\s*=\s*(\d+)\s*,\s*usec\s*=\s*(\d+)/u.exec(output);
|
|
75
|
+
if (match?.[1] === undefined || match[2] === undefined) {
|
|
76
|
+
throw new Error("Darwin boot session identity is malformed.");
|
|
77
|
+
}
|
|
78
|
+
return `darwin:${match[1]}:${match[2]}`;
|
|
79
|
+
}
|
|
80
|
+
if (process.platform === "win32") {
|
|
81
|
+
const output = await execFileText(windowsPowerShellPath(), [
|
|
82
|
+
"-NoProfile",
|
|
83
|
+
"-NonInteractive",
|
|
84
|
+
"-Command",
|
|
85
|
+
"(Get-CimInstance Win32_OperatingSystem).LastBootUpTime.ToUniversalTime().Ticks",
|
|
86
|
+
]);
|
|
87
|
+
return `win32:${requiredDecimal(output, "Windows boot session identity")}`;
|
|
88
|
+
}
|
|
89
|
+
// PID 1 is recreated once per POSIX boot, so its birth is a stable fallback
|
|
90
|
+
// on BSD-like platforms that lack Linux's boot UUID and Darwin's sysctl path.
|
|
91
|
+
const pidOneStart = await posixProcessStartIdentifier(1);
|
|
92
|
+
if (pidOneStart === undefined) {
|
|
93
|
+
throw new Error(`Cannot determine the ${process.platform} boot session identity.`);
|
|
94
|
+
}
|
|
95
|
+
return `${process.platform}:pid1:${pidOneStart}`;
|
|
96
|
+
}
|
|
97
|
+
async function processStartIdentifier(pid) {
|
|
98
|
+
if (process.platform === "linux")
|
|
99
|
+
return await linuxProcessStartIdentifier(pid);
|
|
100
|
+
if (process.platform === "win32")
|
|
101
|
+
return await windowsProcessStartIdentifier(pid);
|
|
102
|
+
return await posixProcessStartIdentifier(pid);
|
|
103
|
+
}
|
|
104
|
+
async function linuxProcessStartIdentifier(pid) {
|
|
105
|
+
let stat;
|
|
106
|
+
try {
|
|
107
|
+
stat = await readFile(`/proc/${pid}/stat`, "utf8");
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
if (isErrno(error, "ENOENT") || isErrno(error, "ESRCH"))
|
|
111
|
+
return undefined;
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
// `comm` is parenthesized and may itself contain spaces or `)`, so split only
|
|
115
|
+
// after its final close paren. The remaining token at index 19 is field 22,
|
|
116
|
+
// the kernel start tick since boot.
|
|
117
|
+
const close = stat.lastIndexOf(")");
|
|
118
|
+
if (close < 0)
|
|
119
|
+
throw new Error(`Linux process stat for pid ${pid} is malformed.`);
|
|
120
|
+
const fields = stat.slice(close + 1).trim().split(/\s+/u);
|
|
121
|
+
const startTicks = fields[19];
|
|
122
|
+
if (startTicks === undefined || !/^\d+$/u.test(startTicks)) {
|
|
123
|
+
throw new Error(`Linux process start identity for pid ${pid} is malformed.`);
|
|
124
|
+
}
|
|
125
|
+
return `linux-ticks:${startTicks}`;
|
|
126
|
+
}
|
|
127
|
+
async function posixProcessStartIdentifier(pid) {
|
|
128
|
+
try {
|
|
129
|
+
const output = await execFileText("/bin/ps", ["-p", String(pid), "-o", "lstart="], posixEnvironment());
|
|
130
|
+
const normalized = output.trim().replace(/\s+/gu, " ");
|
|
131
|
+
if (normalized.length === 0) {
|
|
132
|
+
if (!processExists(pid))
|
|
133
|
+
return undefined;
|
|
134
|
+
throw new Error(`POSIX process start identity for pid ${pid} is empty.`);
|
|
135
|
+
}
|
|
136
|
+
return `posix-lstart:${normalized}`;
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
if (!processExists(pid))
|
|
140
|
+
return undefined;
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async function windowsProcessStartIdentifier(pid) {
|
|
145
|
+
try {
|
|
146
|
+
const output = await execFileText(windowsPowerShellPath(), [
|
|
147
|
+
"-NoProfile",
|
|
148
|
+
"-NonInteractive",
|
|
149
|
+
"-Command",
|
|
150
|
+
`$process = Get-Process -Id ${pid} -ErrorAction Stop; $process.StartTime.ToUniversalTime().Ticks`,
|
|
151
|
+
]);
|
|
152
|
+
return `win32-ticks:${requiredDecimal(output, `Windows process start identity for pid ${pid}`)}`;
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
if (!processExists(pid))
|
|
156
|
+
return undefined;
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function processExists(pid) {
|
|
161
|
+
try {
|
|
162
|
+
process.kill(pid, 0);
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
if (isErrno(error, "ESRCH"))
|
|
167
|
+
return false;
|
|
168
|
+
if (isErrno(error, "EPERM"))
|
|
169
|
+
return true;
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
function assertPid(pid) {
|
|
174
|
+
if (!Number.isSafeInteger(pid) || pid <= 0) {
|
|
175
|
+
throw new Error(`Process incarnation pid must be a positive safe integer; received ${String(pid)}.`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function posixEnvironment() {
|
|
179
|
+
return { PATH: "/usr/bin:/bin", LANG: "C", LC_ALL: "C" };
|
|
180
|
+
}
|
|
181
|
+
function windowsPowerShellPath() {
|
|
182
|
+
const systemRoot = process.env.SystemRoot ?? process.env.SYSTEMROOT ?? "C:\\Windows";
|
|
183
|
+
return join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
|
|
184
|
+
}
|
|
185
|
+
function requiredDecimal(output, label) {
|
|
186
|
+
const normalized = output.trim();
|
|
187
|
+
if (!/^\d+$/u.test(normalized))
|
|
188
|
+
throw new Error(`${label} is malformed.`);
|
|
189
|
+
return normalized;
|
|
190
|
+
}
|
|
191
|
+
function execFileText(executable, args, env) {
|
|
192
|
+
return new Promise((resolvePromise, reject) => {
|
|
193
|
+
execFile(executable, [...args], {
|
|
194
|
+
encoding: "utf8",
|
|
195
|
+
windowsHide: true,
|
|
196
|
+
...(env === undefined ? {} : { env }),
|
|
197
|
+
}, (error, stdout) => {
|
|
198
|
+
if (error !== null)
|
|
199
|
+
reject(error);
|
|
200
|
+
else
|
|
201
|
+
resolvePromise(stdout);
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
function isErrno(error, code) {
|
|
206
|
+
return error?.code === code;
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=process-incarnation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-incarnation.js","sourceRoot":"","sources":["../src/process-incarnation.ts"],"names":[],"mappings":"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"}
|
package/dist/project-skills.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { GeneratedFile } from "./modules/types.js";
|
|
2
|
-
export declare const PROJECT_SKILL_VERSION = "1.
|
|
2
|
+
export declare const PROJECT_SKILL_VERSION = "1.1.0";
|
|
3
3
|
export declare const PROJECT_SKILL_MANIFEST_PATH = "skills/.mono-agent-managed.json";
|
|
4
4
|
export declare const PROJECT_SKILL_NAMES: readonly ["mono-agent-configure", "mono-agent-memory"];
|
|
5
5
|
export type ProjectSkillName = (typeof PROJECT_SKILL_NAMES)[number];
|
package/dist/project-skills.js
CHANGED
|
@@ -3,7 +3,7 @@ import { closeSync, constants, fchmodSync, fstatSync, fsyncSync, lstatSync, open
|
|
|
3
3
|
import { lstat, mkdir, readFile, realpath, stat } from "node:fs/promises";
|
|
4
4
|
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { isDeepStrictEqual } from "node:util";
|
|
6
|
-
export const PROJECT_SKILL_VERSION = "1.
|
|
6
|
+
export const PROJECT_SKILL_VERSION = "1.1.0";
|
|
7
7
|
export const PROJECT_SKILL_MANIFEST_PATH = "skills/.mono-agent-managed.json";
|
|
8
8
|
export const PROJECT_SKILL_NAMES = [
|
|
9
9
|
"mono-agent-configure",
|
|
@@ -19,14 +19,14 @@ version: ${PROJECT_SKILL_VERSION}
|
|
|
19
19
|
|
|
20
20
|
Use this skill when the operator asks to configure, tune, or change this agent.
|
|
21
21
|
|
|
22
|
-
1. Treat the current resolved config, IDENTITY.md, and validation output as operational truth. Memory may recall preferences, but never use memory as proof that a change is active.
|
|
23
|
-
2.
|
|
22
|
+
1. Treat the current resolved config, the configured identity document's \`## Role\` (normally \`IDENTITY.md → ## Role\`), and validation output as operational truth. Memory may recall preferences, but never use memory as proof that a change is active.
|
|
23
|
+
2. This is one temporary configuration exchange, separate from ordinary chat. Ask one focused question. After the operator's reply, either make exactly one proposal or clearly say that no changes are proposed. If the reply is an ordinary task, do not execute it with configuration authority; hand it off to the ordinary conversation.
|
|
24
24
|
3. Never ask for API keys, OAuth tokens, passwords, bot tokens, or other secrets in chat. Explain the exact masked mono-agent auth or owner-only .env flow instead.
|
|
25
|
-
4. For a safe local change, call ProposeAgentConfiguration with a short rationale, an RFC 6902 JSON Patch against mono-agent.config.json, and optionally a replacement body for the
|
|
26
|
-
5. Do not claim the proposal was applied. The host validates it, shows an out-of-band
|
|
25
|
+
4. For a safe local change, call ProposeAgentConfiguration once with a short rationale, an RFC 6902 JSON Patch against mono-agent.config.json, and optionally a replacement body for the configured identity document's \`## Role\` (normally \`IDENTITY.md → ## Role\`). A Role-only proposal uses an empty patch.
|
|
26
|
+
5. Do not claim the proposal was applied. The local host validates it, shows an out-of-band review, requires the operator to approve it, commits files atomically, restarts the authoritative background agent, and proves readiness. A failed restart restores the approved files and attempts to restore the previous daemon before reporting recovery instructions.
|
|
27
27
|
6. Keep config proposals to the host's documented low-risk allowlist: public name; effort, turn/session UX; selected project skills and disclosure; memory size or MemoryRecall enablement; and tool-policy tightening. Paths, memory tier/capture behavior, external MCP servers, plugins, channels or cron/proactive jobs, tool/runtime permissions, model-route or provider posture, embeddings/LLM endpoints, exporters, sandboxing, and network exposure require the explicit guided flow named by the host.
|
|
28
28
|
|
|
29
|
-
Keep proposals minimal. Preserve unrelated config, existing knowledge references, and every identity section except the optional Role body.
|
|
29
|
+
Keep proposals minimal. Preserve unrelated config, existing knowledge references, and every identity section except the optional Role body. Configuration mode ends after a no-change reply or after approval/rejection; ordinary chat uses a separate conversation.
|
|
30
30
|
`;
|
|
31
31
|
const MEMORY_SKILL = `---
|
|
32
32
|
name: mono-agent-memory
|
|
@@ -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"}
|