@deadragdoll/tellymcp 0.0.1
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/.env.example.client +93 -0
- package/.env.example.gateway +120 -0
- package/CHANGELOG.md +155 -0
- package/LICENSE +21 -0
- package/README-ru.md +338 -0
- package/README.md +1262 -0
- package/STANDALONE-ru.md +266 -0
- package/STANDALONE.md +266 -0
- package/TOOLS.md +1296 -0
- package/config/templates/env.both.template +83 -0
- package/config/templates/env.client.template +60 -0
- package/config/templates/env.gateway.template +82 -0
- package/dist/cli.js +636 -0
- package/dist/index.js +17 -0
- package/dist/lib/logfeed/store.js +52 -0
- package/dist/lib/middlewares/tracer.js +172 -0
- package/dist/lib/mixins/db.js +267 -0
- package/dist/lib/mixins/logfeed.js +34 -0
- package/dist/lib/mixins/session.errors.js +142 -0
- package/dist/lib/moleculer.js +2 -0
- package/dist/lib/trace.js +147 -0
- package/dist/lib/traceContext.js +116 -0
- package/dist/moleculer.config.js +274 -0
- package/dist/services/features/telegram-mcp/approval.service.js +33 -0
- package/dist/services/features/telegram-mcp/browser.service.js +42 -0
- package/dist/services/features/telegram-mcp/collaboration.service.js +53 -0
- package/dist/services/features/telegram-mcp/ensuredb.service.js +337 -0
- package/dist/services/features/telegram-mcp/gateway-delivery.service.js +378 -0
- package/dist/services/features/telegram-mcp/gateway-loopback.js +10 -0
- package/dist/services/features/telegram-mcp/gateway-rmq.service.js +294 -0
- package/dist/services/features/telegram-mcp/gateway-socket.service.js +1463 -0
- package/dist/services/features/telegram-mcp/gateway.service.js +1141 -0
- package/dist/services/features/telegram-mcp/inbox.service.js +33 -0
- package/dist/services/features/telegram-mcp/mcp-http.service.js +76 -0
- package/dist/services/features/telegram-mcp/mcp-server.service.js +127 -0
- package/dist/services/features/telegram-mcp/notify.service.js +33 -0
- package/dist/services/features/telegram-mcp/pair.service.js +33 -0
- package/dist/services/features/telegram-mcp/runtime.service.js +36 -0
- package/dist/services/features/telegram-mcp/session-context.service.js +33 -0
- package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +103 -0
- package/dist/services/features/telegram-mcp/src/app/config/env.js +317 -0
- package/dist/services/features/telegram-mcp/src/app/http.js +774 -0
- package/dist/services/features/telegram-mcp/src/app/index.js +2 -0
- package/dist/services/features/telegram-mcp/src/app/providers/mcp/server.js +13 -0
- package/dist/services/features/telegram-mcp/src/app/providers/redis/client.js +18 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +740 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +267 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/relay.js +69 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +9 -0
- package/dist/services/features/telegram-mcp/src/entities/auth/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/browser/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/collaboration/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/inbox/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +545 -0
- package/dist/services/features/telegram-mcp/src/entities/request/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/session/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/features/ask-user/model/askUserTelegram.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserClearLogsTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserClickTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserCloseTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserComputedStyleTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserConsoleTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserDomTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserErrorsTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserFillTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserNetworkFailuresTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserOpenTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserPressTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserReloadTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +689 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserWaitForTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserWaitForUrlTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/backend.js +2 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/collaborationService.js +26 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +390 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +102 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +69 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +657 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayReplyResolution.js +17 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +77 -0
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +93 -0
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +202 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +409 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +123 -0
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +243 -0
- package/dist/services/features/telegram-mcp/src/shared/api/storage/contract.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/api/tool-registry/registry.js +8 -0
- package/dist/services/features/telegram-mcp/src/shared/api/tool-registry/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/api/transport/contract.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +86 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +436 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/collabSemantics.js +21 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/collabUi.js +87 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/messageFormat.js +60 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +46 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +6534 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +280 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/ids/ids.js +34 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +68 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +223 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/redact-secrets/redactSecrets.js +22 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/truncate/truncate.js +12 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +124 -0
- package/dist/services/features/telegram-mcp/src/shared/types/common.js +2 -0
- package/dist/services/features/telegram-mcp/standalone-http.service.js +113 -0
- package/dist/services/features/telegram-mcp/tools-sync.service.js +33 -0
- package/package.json +110 -0
- package/scripts/postinstall.js +60 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BrowserWaitForTool = void 0;
|
|
4
|
+
const schema_1 = require("../../../entities/request/model/schema");
|
|
5
|
+
function createContent(output) {
|
|
6
|
+
return [{ type: "text", text: JSON.stringify(output, null, 2) }];
|
|
7
|
+
}
|
|
8
|
+
class BrowserWaitForTool {
|
|
9
|
+
browserService;
|
|
10
|
+
constructor(browserService) {
|
|
11
|
+
this.browserService = browserService;
|
|
12
|
+
}
|
|
13
|
+
register(server) {
|
|
14
|
+
server.registerTool("browser_wait_for", {
|
|
15
|
+
title: "Browser Wait For",
|
|
16
|
+
description: "Wait for an element in the session browser page to reach the requested state by CSS selector or visible text.",
|
|
17
|
+
inputSchema: schema_1.browserWaitForInputSchema,
|
|
18
|
+
outputSchema: schema_1.browserWaitForOutputSchema,
|
|
19
|
+
}, async (args) => {
|
|
20
|
+
const output = await this.browserService.waitFor(args);
|
|
21
|
+
return {
|
|
22
|
+
content: createContent(output),
|
|
23
|
+
structuredContent: output,
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.BrowserWaitForTool = BrowserWaitForTool;
|
package/dist/services/features/telegram-mcp/src/features/browser/model/browserWaitForUrlTool.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BrowserWaitForUrlTool = void 0;
|
|
4
|
+
const schema_1 = require("../../../entities/request/model/schema");
|
|
5
|
+
function createContent(output) {
|
|
6
|
+
return [{ type: "text", text: JSON.stringify(output, null, 2) }];
|
|
7
|
+
}
|
|
8
|
+
class BrowserWaitForUrlTool {
|
|
9
|
+
browserService;
|
|
10
|
+
constructor(browserService) {
|
|
11
|
+
this.browserService = browserService;
|
|
12
|
+
}
|
|
13
|
+
register(server) {
|
|
14
|
+
server.registerTool("browser_wait_for_url", {
|
|
15
|
+
title: "Browser Wait For URL",
|
|
16
|
+
description: "Wait for the session browser page to reach an exact URL or contain a URL fragment after navigation.",
|
|
17
|
+
inputSchema: schema_1.browserWaitForUrlInputSchema,
|
|
18
|
+
outputSchema: schema_1.browserWaitForUrlOutputSchema,
|
|
19
|
+
}, async (args) => {
|
|
20
|
+
const output = await this.browserService.waitForUrl(args);
|
|
21
|
+
return {
|
|
22
|
+
content: createContent(output),
|
|
23
|
+
structuredContent: output,
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.BrowserWaitForUrlTool = BrowserWaitForUrlTool;
|
package/dist/services/features/telegram-mcp/src/features/collaboration/model/collaborationService.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CollaborationService = void 0;
|
|
4
|
+
class CollaborationService {
|
|
5
|
+
backend;
|
|
6
|
+
logger;
|
|
7
|
+
projectIdentityResolver;
|
|
8
|
+
constructor(backend, logger, projectIdentityResolver) {
|
|
9
|
+
this.backend = backend;
|
|
10
|
+
this.logger = logger;
|
|
11
|
+
this.projectIdentityResolver = projectIdentityResolver;
|
|
12
|
+
}
|
|
13
|
+
async sendPartnerNote(input) {
|
|
14
|
+
const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
|
|
15
|
+
const output = await this.backend.sendPartnerNote(input, resolved);
|
|
16
|
+
this.logger.info("Partner note processed by collaboration service", {
|
|
17
|
+
sessionId: output.session_id,
|
|
18
|
+
partnerSessionId: output.partner_session_id,
|
|
19
|
+
shareId: output.share_id,
|
|
20
|
+
kind: output.kind,
|
|
21
|
+
sessionIdDerived: resolved.sessionIdDerived,
|
|
22
|
+
});
|
|
23
|
+
return output;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.CollaborationService = CollaborationService;
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.LocalCollaborationBackend = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const ids_1 = require("../../../shared/lib/ids/ids");
|
|
9
|
+
const client_1 = require("../../../shared/integrations/tmux/client");
|
|
10
|
+
function slugify(input) {
|
|
11
|
+
return input
|
|
12
|
+
.trim()
|
|
13
|
+
.toLowerCase()
|
|
14
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
15
|
+
.replace(/^-+|-+$/g, "")
|
|
16
|
+
.replace(/-{2,}/g, "-")
|
|
17
|
+
.slice(0, 48);
|
|
18
|
+
}
|
|
19
|
+
const SOURCE_ARTIFACT_EXTENSIONS = new Set([
|
|
20
|
+
".c",
|
|
21
|
+
".cc",
|
|
22
|
+
".cpp",
|
|
23
|
+
".cs",
|
|
24
|
+
".css",
|
|
25
|
+
".go",
|
|
26
|
+
".h",
|
|
27
|
+
".hpp",
|
|
28
|
+
".html",
|
|
29
|
+
".java",
|
|
30
|
+
".js",
|
|
31
|
+
".jsx",
|
|
32
|
+
".kt",
|
|
33
|
+
".less",
|
|
34
|
+
".mjs",
|
|
35
|
+
".php",
|
|
36
|
+
".py",
|
|
37
|
+
".rb",
|
|
38
|
+
".rs",
|
|
39
|
+
".sass",
|
|
40
|
+
".scala",
|
|
41
|
+
".scss",
|
|
42
|
+
".sh",
|
|
43
|
+
".sql",
|
|
44
|
+
".svelte",
|
|
45
|
+
".swift",
|
|
46
|
+
".ts",
|
|
47
|
+
".tsx",
|
|
48
|
+
".vue",
|
|
49
|
+
".xml",
|
|
50
|
+
".zsh",
|
|
51
|
+
]);
|
|
52
|
+
const PARTNER_INDEX_FILE_NAME = "SHARED_INDEX.md";
|
|
53
|
+
function trimOptional(value) {
|
|
54
|
+
const trimmed = value?.trim();
|
|
55
|
+
return trimmed ? trimmed : undefined;
|
|
56
|
+
}
|
|
57
|
+
function isReplyRequired(kind, input) {
|
|
58
|
+
if (typeof input.requires_reply === "boolean") {
|
|
59
|
+
return input.requires_reply;
|
|
60
|
+
}
|
|
61
|
+
return kind === "question" || kind === "request";
|
|
62
|
+
}
|
|
63
|
+
function isSourceArtifactPath(filePath) {
|
|
64
|
+
return SOURCE_ARTIFACT_EXTENSIONS.has(node_path_1.default.extname(filePath).toLowerCase());
|
|
65
|
+
}
|
|
66
|
+
function buildShareId(kind, sourceLabel, summary, now) {
|
|
67
|
+
const timestamp = now.toISOString().replace(/[:.]/gu, "-");
|
|
68
|
+
return [
|
|
69
|
+
timestamp,
|
|
70
|
+
slugify(sourceLabel) || "session",
|
|
71
|
+
kind,
|
|
72
|
+
slugify(summary) || "note",
|
|
73
|
+
].join("-");
|
|
74
|
+
}
|
|
75
|
+
function renderYamlArray(values) {
|
|
76
|
+
if (values.length === 0) {
|
|
77
|
+
return "[]";
|
|
78
|
+
}
|
|
79
|
+
return `\n${values.map((value) => ` - ${JSON.stringify(value)}`).join("\n")}`;
|
|
80
|
+
}
|
|
81
|
+
function buildPartnerInboxText(input) {
|
|
82
|
+
const kindTitle = input.kind === "question"
|
|
83
|
+
? "Partner question received."
|
|
84
|
+
: input.kind === "reply"
|
|
85
|
+
? "Partner reply received."
|
|
86
|
+
: input.kind === "request"
|
|
87
|
+
? "Partner request received."
|
|
88
|
+
: input.kind === "handoff"
|
|
89
|
+
? "Partner handoff received."
|
|
90
|
+
: "Partner update received.";
|
|
91
|
+
return [
|
|
92
|
+
kindTitle,
|
|
93
|
+
`From: ${input.fromLabel}`,
|
|
94
|
+
`Summary: ${input.summary}`,
|
|
95
|
+
"",
|
|
96
|
+
`Immediate action: read ${PARTNER_INDEX_FILE_NAME} and then open the note below.`,
|
|
97
|
+
`Note: ${input.notePath}`,
|
|
98
|
+
...(input.copiedArtifacts.length > 0
|
|
99
|
+
? ["", "Artifacts:", ...input.copiedArtifacts.map((item) => `- ${item}`)]
|
|
100
|
+
: []),
|
|
101
|
+
...(input.requiresReply
|
|
102
|
+
? [
|
|
103
|
+
"",
|
|
104
|
+
"Reply through send_partner_note after you finish the requested work.",
|
|
105
|
+
"The task is not complete until send_partner_note succeeds.",
|
|
106
|
+
]
|
|
107
|
+
: []),
|
|
108
|
+
].join("\n");
|
|
109
|
+
}
|
|
110
|
+
function buildNoteContent(input) {
|
|
111
|
+
const lines = ["---"];
|
|
112
|
+
lines.push(`kind: ${JSON.stringify(input.kind)}`);
|
|
113
|
+
lines.push(`from_session_id: ${JSON.stringify(input.sourceSessionId)}`);
|
|
114
|
+
lines.push(`from_label: ${JSON.stringify(input.sourceLabel)}`);
|
|
115
|
+
lines.push(`to_session_id: ${JSON.stringify(input.targetSessionId)}`);
|
|
116
|
+
lines.push(`to_label: ${JSON.stringify(input.targetLabel)}`);
|
|
117
|
+
lines.push(`created_at: ${JSON.stringify(input.createdAt)}`);
|
|
118
|
+
if (input.requiresReply) {
|
|
119
|
+
lines.push("requires_reply: true");
|
|
120
|
+
}
|
|
121
|
+
if (input.inReplyTo) {
|
|
122
|
+
lines.push(`in_reply_to: ${JSON.stringify(input.inReplyTo)}`);
|
|
123
|
+
}
|
|
124
|
+
if (input.copiedArtifacts.length > 0) {
|
|
125
|
+
lines.push(`artifacts:${renderYamlArray(input.copiedArtifacts)}`);
|
|
126
|
+
}
|
|
127
|
+
lines.push("---", "", "# Summary", input.summary.trim(), "", "# Message", input.message.trim());
|
|
128
|
+
if (input.expectedReply?.trim()) {
|
|
129
|
+
lines.push("", "# Expected Reply", input.expectedReply.trim());
|
|
130
|
+
}
|
|
131
|
+
if (input.requiresReply) {
|
|
132
|
+
lines.push("", "# Action Required", "You must send a reply via send_partner_note.", "Your task is not complete until send_partner_note succeeds.", "Do not stop after local analysis or a chat explanation.", "Use the current partner route for the reply.", "Only after the tool succeeds may you say that the reply was sent.", "", "# Reply Tool Call Example", "send_partner_note(", ` session_id=${JSON.stringify(input.targetSessionId)},`, ` kind=${JSON.stringify("reply")},`, " summary=\"Короткий итог\",", " message=\"Подробный ответ\"", ")");
|
|
133
|
+
}
|
|
134
|
+
if (input.copiedArtifacts.length > 0) {
|
|
135
|
+
lines.push("", "# Artifacts", ...input.copiedArtifacts.map((artifact) => `- ${artifact}`));
|
|
136
|
+
}
|
|
137
|
+
return `${lines.join("\n")}\n`;
|
|
138
|
+
}
|
|
139
|
+
function buildShareIndexLine(input) {
|
|
140
|
+
return [
|
|
141
|
+
"-",
|
|
142
|
+
`[${input.createdAt}]`,
|
|
143
|
+
`${input.sourceLabel} → ${input.targetLabel}`,
|
|
144
|
+
`| ${input.kind} |`,
|
|
145
|
+
`${input.summary}`,
|
|
146
|
+
`| \`${input.relativeNotePath}\``,
|
|
147
|
+
].join(" ");
|
|
148
|
+
}
|
|
149
|
+
class LocalCollaborationBackend {
|
|
150
|
+
config;
|
|
151
|
+
sessionStore;
|
|
152
|
+
bindingStore;
|
|
153
|
+
inboxStore;
|
|
154
|
+
xchangeFileMetaStore;
|
|
155
|
+
objectStore;
|
|
156
|
+
telegramTransport;
|
|
157
|
+
logger;
|
|
158
|
+
textEncoder = new TextEncoder();
|
|
159
|
+
constructor(config, sessionStore, bindingStore, inboxStore, xchangeFileMetaStore, objectStore, telegramTransport, logger) {
|
|
160
|
+
this.config = config;
|
|
161
|
+
this.sessionStore = sessionStore;
|
|
162
|
+
this.bindingStore = bindingStore;
|
|
163
|
+
this.inboxStore = inboxStore;
|
|
164
|
+
this.xchangeFileMetaStore = xchangeFileMetaStore;
|
|
165
|
+
this.objectStore = objectStore;
|
|
166
|
+
this.telegramTransport = telegramTransport;
|
|
167
|
+
this.logger = logger;
|
|
168
|
+
}
|
|
169
|
+
async sendPartnerNote(input, resolved) {
|
|
170
|
+
const sourceSession = await this.sessionStore.getSession(resolved.sessionId);
|
|
171
|
+
if (!sourceSession) {
|
|
172
|
+
throw new Error(`Session ${resolved.sessionId} was not found. Pair the session before collaborating.`);
|
|
173
|
+
}
|
|
174
|
+
const targetSessionId = trimOptional(input.target_session_id) ?? sourceSession.linkedSessionId;
|
|
175
|
+
if (!targetSessionId) {
|
|
176
|
+
throw new Error("This session has no linked partner. Link another session in Telegram first.");
|
|
177
|
+
}
|
|
178
|
+
const targetSession = await this.sessionStore.getSession(targetSessionId);
|
|
179
|
+
if (!targetSession) {
|
|
180
|
+
throw new Error(`Target partner session ${targetSessionId} was not found.`);
|
|
181
|
+
}
|
|
182
|
+
const targetBinding = await this.bindingStore.getBinding(targetSession.sessionId);
|
|
183
|
+
if (!targetBinding) {
|
|
184
|
+
throw new Error(`Linked partner session ${targetSession.sessionId} is not paired with Telegram.`);
|
|
185
|
+
}
|
|
186
|
+
const now = new Date();
|
|
187
|
+
const createdAt = now.toISOString();
|
|
188
|
+
const sourceLabel = sourceSession.label ?? sourceSession.sessionId;
|
|
189
|
+
const targetLabel = targetSession.label ?? targetSession.sessionId;
|
|
190
|
+
const shareId = buildShareId(input.kind, sourceLabel, input.summary, now);
|
|
191
|
+
const sourceWorkspaceDir = this.resolveWorkspaceDir(sourceSession, resolved.sessionId);
|
|
192
|
+
const targetWorkspaceDir = this.resolveWorkspaceDir(targetSession, targetSession.sessionId);
|
|
193
|
+
const relativeNotePath = `shares/${shareId}.md`;
|
|
194
|
+
const requiresReply = isReplyRequired(input.kind, input);
|
|
195
|
+
const copiedArtifacts = await this.copyArtifactsToPartner(sourceSession, targetSession, sourceWorkspaceDir, targetWorkspaceDir, shareId, createdAt, input.artifacts ?? []);
|
|
196
|
+
const inReplyTo = trimOptional(input.in_reply_to);
|
|
197
|
+
const expectedReply = trimOptional(input.expected_reply);
|
|
198
|
+
const noteContent = buildNoteContent({
|
|
199
|
+
shareId,
|
|
200
|
+
kind: input.kind,
|
|
201
|
+
sourceSessionId: sourceSession.sessionId,
|
|
202
|
+
sourceLabel,
|
|
203
|
+
targetSessionId: targetSession.sessionId,
|
|
204
|
+
targetLabel,
|
|
205
|
+
createdAt,
|
|
206
|
+
requiresReply,
|
|
207
|
+
...(inReplyTo ? { inReplyTo } : {}),
|
|
208
|
+
copiedArtifacts,
|
|
209
|
+
summary: input.summary,
|
|
210
|
+
message: input.message,
|
|
211
|
+
...(expectedReply ? { expectedReply } : {}),
|
|
212
|
+
});
|
|
213
|
+
const notePath = await (0, client_1.writeXchangeRelativeFile)(this.config.tmux, targetWorkspaceDir, this.config.exchange.dir, relativeNotePath, this.textEncoder.encode(noteContent));
|
|
214
|
+
await this.xchangeFileMetaStore.setXchangeFileMeta({
|
|
215
|
+
sessionId: targetSession.sessionId,
|
|
216
|
+
filePath: notePath,
|
|
217
|
+
relativePath: relativeNotePath,
|
|
218
|
+
source: "partner-artifact",
|
|
219
|
+
uploadedAt: createdAt,
|
|
220
|
+
mimeType: "text/markdown",
|
|
221
|
+
sizeBytes: this.textEncoder.encode(noteContent).byteLength,
|
|
222
|
+
});
|
|
223
|
+
const shareIndexPath = await (0, client_1.writeXchangeRelativeFile)(this.config.tmux, targetWorkspaceDir, this.config.exchange.dir, PARTNER_INDEX_FILE_NAME, this.textEncoder.encode(`${buildShareIndexLine({
|
|
224
|
+
createdAt,
|
|
225
|
+
sourceLabel,
|
|
226
|
+
targetLabel,
|
|
227
|
+
kind: input.kind,
|
|
228
|
+
summary: input.summary.trim(),
|
|
229
|
+
relativeNotePath,
|
|
230
|
+
})}\n`), { append: true });
|
|
231
|
+
const inboxMessage = {
|
|
232
|
+
id: (0, ids_1.createInboxMessageId)(now),
|
|
233
|
+
sessionId: targetSession.sessionId,
|
|
234
|
+
telegramChatId: targetBinding.telegramChatId,
|
|
235
|
+
telegramUserId: targetBinding.telegramUserId,
|
|
236
|
+
sourceTelegramMessageId: now.getTime(),
|
|
237
|
+
text: buildPartnerInboxText({
|
|
238
|
+
kind: input.kind,
|
|
239
|
+
fromLabel: sourceLabel,
|
|
240
|
+
summary: input.summary.trim(),
|
|
241
|
+
notePath,
|
|
242
|
+
requiresReply,
|
|
243
|
+
copiedArtifacts,
|
|
244
|
+
}),
|
|
245
|
+
attachments: [notePath, ...copiedArtifacts],
|
|
246
|
+
receivedAt: createdAt,
|
|
247
|
+
};
|
|
248
|
+
await this.inboxStore.createInboxMessage(inboxMessage);
|
|
249
|
+
await this.telegramTransport.sendNotification({
|
|
250
|
+
sessionId: targetSession.sessionId,
|
|
251
|
+
...(targetSession.label ? { sessionLabel: targetSession.label } : {}),
|
|
252
|
+
recipient: {
|
|
253
|
+
telegramChatId: targetBinding.telegramChatId,
|
|
254
|
+
telegramUserId: targetBinding.telegramUserId,
|
|
255
|
+
},
|
|
256
|
+
message: [
|
|
257
|
+
input.kind === "question"
|
|
258
|
+
? `Получен вопрос от ${sourceLabel}.`
|
|
259
|
+
: input.kind === "reply"
|
|
260
|
+
? `Получен ответ от ${sourceLabel}.`
|
|
261
|
+
: input.kind === "request"
|
|
262
|
+
? `Получен запрос от ${sourceLabel}.`
|
|
263
|
+
: input.kind === "handoff"
|
|
264
|
+
? copiedArtifacts.length > 0
|
|
265
|
+
? `Получен файл от ${sourceLabel}.`
|
|
266
|
+
: `Получен handoff от ${sourceLabel}.`
|
|
267
|
+
: `Получено обновление от ${sourceLabel}.`,
|
|
268
|
+
`Сессия: ${sourceLabel} -> ${targetLabel}`,
|
|
269
|
+
`Тип: ${input.kind}`,
|
|
270
|
+
`Кратко: ${input.summary.trim()}`,
|
|
271
|
+
...(copiedArtifacts.length > 0
|
|
272
|
+
? [
|
|
273
|
+
"",
|
|
274
|
+
`Файлы: ${copiedArtifacts.length}`,
|
|
275
|
+
...copiedArtifacts.map((item) => `- ${node_path_1.default.basename(item)}`),
|
|
276
|
+
]
|
|
277
|
+
: []),
|
|
278
|
+
"",
|
|
279
|
+
`Note: ${notePath}`,
|
|
280
|
+
].join("\n"),
|
|
281
|
+
});
|
|
282
|
+
try {
|
|
283
|
+
await this.telegramTransport.nudgeSessionPartnerNote(targetSession.sessionId);
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
this.logger.warn("tmux nudge failed after local partner delivery", {
|
|
287
|
+
sessionId: targetSession.sessionId,
|
|
288
|
+
partnerSessionId: sourceSession.sessionId,
|
|
289
|
+
shareId,
|
|
290
|
+
error: error instanceof Error ? (error.stack ?? error.message) : String(error),
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
this.logger.info("Partner note delivered through local backend", {
|
|
294
|
+
sessionId: sourceSession.sessionId,
|
|
295
|
+
partnerSessionId: targetSession.sessionId,
|
|
296
|
+
shareId,
|
|
297
|
+
kind: input.kind,
|
|
298
|
+
notePath,
|
|
299
|
+
copiedArtifacts,
|
|
300
|
+
requiresReply,
|
|
301
|
+
sessionIdDerived: resolved.sessionIdDerived,
|
|
302
|
+
});
|
|
303
|
+
return {
|
|
304
|
+
session_id: sourceSession.sessionId,
|
|
305
|
+
partner_session_id: targetSession.sessionId,
|
|
306
|
+
kind: input.kind,
|
|
307
|
+
share_id: shareId,
|
|
308
|
+
delivery_status: "delivered",
|
|
309
|
+
note_path: notePath,
|
|
310
|
+
share_index_path: shareIndexPath,
|
|
311
|
+
copied_artifacts: copiedArtifacts,
|
|
312
|
+
inbox_message_id: inboxMessage.id,
|
|
313
|
+
requires_reply: requiresReply,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
resolveWorkspaceDir(session, _sessionId) {
|
|
317
|
+
const workspaceDir = session.cwd?.trim();
|
|
318
|
+
if (workspaceDir) {
|
|
319
|
+
return workspaceDir;
|
|
320
|
+
}
|
|
321
|
+
return process.cwd();
|
|
322
|
+
}
|
|
323
|
+
async copyArtifactsToPartner(sourceSession, targetSession, sourceWorkspaceDir, targetWorkspaceDir, shareId, uploadedAt, artifacts) {
|
|
324
|
+
const copied = [];
|
|
325
|
+
const usedArtifactNames = new Set();
|
|
326
|
+
for (const artifactPath of artifacts) {
|
|
327
|
+
if (isSourceArtifactPath(artifactPath)) {
|
|
328
|
+
throw new Error(`Source file artifacts are not allowed for partner exchange: ${artifactPath}. Share summaries, API specs, logs, screenshots, or other derived artifacts instead.`);
|
|
329
|
+
}
|
|
330
|
+
const sourceMeta = await this.xchangeFileMetaStore.getXchangeFileMeta(sourceSession.sessionId, artifactPath);
|
|
331
|
+
const preferredArtifactName = sourceMeta?.originalName ||
|
|
332
|
+
(sourceMeta?.relativePath
|
|
333
|
+
? node_path_1.default.basename(sourceMeta.relativePath)
|
|
334
|
+
: undefined) ||
|
|
335
|
+
node_path_1.default.basename(artifactPath) ||
|
|
336
|
+
"artifact.bin";
|
|
337
|
+
const artifactName = this.allocatePartnerArtifactName(preferredArtifactName, usedArtifactNames);
|
|
338
|
+
const relativeArtifactPath = [
|
|
339
|
+
"shares",
|
|
340
|
+
"files",
|
|
341
|
+
shareId,
|
|
342
|
+
artifactName,
|
|
343
|
+
].join("/");
|
|
344
|
+
const ensuredArtifactPath = sourceMeta
|
|
345
|
+
? await this.objectStore.ensureLocalFile({
|
|
346
|
+
sessionId: sourceSession.sessionId,
|
|
347
|
+
session: sourceSession,
|
|
348
|
+
filePath: artifactPath,
|
|
349
|
+
relativePath: sourceMeta.relativePath,
|
|
350
|
+
storageRef: sourceMeta.storageRef,
|
|
351
|
+
source: sourceMeta.source,
|
|
352
|
+
})
|
|
353
|
+
: artifactPath;
|
|
354
|
+
const content = await (0, client_1.readWorkspaceFile)(this.config.tmux, sourceWorkspaceDir, ensuredArtifactPath);
|
|
355
|
+
const materializedArtifactPath = await (0, client_1.writeXchangeRelativeFile)(this.config.tmux, targetWorkspaceDir, this.config.exchange.dir, relativeArtifactPath, content);
|
|
356
|
+
await this.xchangeFileMetaStore.setXchangeFileMeta({
|
|
357
|
+
sessionId: targetSession.sessionId,
|
|
358
|
+
filePath: materializedArtifactPath,
|
|
359
|
+
relativePath: relativeArtifactPath,
|
|
360
|
+
source: "partner-artifact",
|
|
361
|
+
uploadedAt,
|
|
362
|
+
...(sourceMeta?.originalName
|
|
363
|
+
? { originalName: sourceMeta.originalName }
|
|
364
|
+
: {}),
|
|
365
|
+
...(sourceMeta?.caption ? { caption: sourceMeta.caption } : {}),
|
|
366
|
+
...(sourceMeta?.mimeType ? { mimeType: sourceMeta.mimeType } : {}),
|
|
367
|
+
...(typeof sourceMeta?.sizeBytes === "number"
|
|
368
|
+
? { sizeBytes: sourceMeta.sizeBytes }
|
|
369
|
+
: {}),
|
|
370
|
+
});
|
|
371
|
+
copied.push(materializedArtifactPath);
|
|
372
|
+
}
|
|
373
|
+
return copied;
|
|
374
|
+
}
|
|
375
|
+
allocatePartnerArtifactName(fileName, usedArtifactNames) {
|
|
376
|
+
const baseName = node_path_1.default.basename(fileName).trim() || "artifact.bin";
|
|
377
|
+
const extension = node_path_1.default.extname(baseName);
|
|
378
|
+
const stem = node_path_1.default.basename(baseName, extension) || "artifact";
|
|
379
|
+
for (let attempt = 0; attempt < 1000; attempt += 1) {
|
|
380
|
+
const candidate = attempt === 0 ? baseName : `${stem}--${attempt}${extension}`;
|
|
381
|
+
if (usedArtifactNames.has(candidate)) {
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
usedArtifactNames.add(candidate);
|
|
385
|
+
return candidate;
|
|
386
|
+
}
|
|
387
|
+
throw new Error("Could not allocate a unique partner artifact name.");
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
exports.LocalCollaborationBackend = LocalCollaborationBackend;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SendPartnerFileService = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const mime_types_1 = require("mime-types");
|
|
9
|
+
const client_1 = require("../../../shared/integrations/tmux/client");
|
|
10
|
+
function resolveWorkspaceDir(input) {
|
|
11
|
+
if (input.inputCwd?.trim()) {
|
|
12
|
+
return node_path_1.default.resolve(input.inputCwd.trim());
|
|
13
|
+
}
|
|
14
|
+
if (input.sessionCwd?.trim()) {
|
|
15
|
+
return node_path_1.default.resolve(input.sessionCwd.trim());
|
|
16
|
+
}
|
|
17
|
+
return node_path_1.default.resolve(input.resolvedCwd);
|
|
18
|
+
}
|
|
19
|
+
function normalizeWorkspaceRelativePath(workspaceDir, filePath) {
|
|
20
|
+
const trimmed = filePath.trim();
|
|
21
|
+
if (!trimmed) {
|
|
22
|
+
throw new Error("file_path is required.");
|
|
23
|
+
}
|
|
24
|
+
const resolvedWorkspaceDir = node_path_1.default.resolve(workspaceDir);
|
|
25
|
+
const resolvedFilePath = node_path_1.default.isAbsolute(trimmed)
|
|
26
|
+
? node_path_1.default.resolve(trimmed)
|
|
27
|
+
: node_path_1.default.resolve(resolvedWorkspaceDir, trimmed);
|
|
28
|
+
const relative = node_path_1.default.relative(resolvedWorkspaceDir, resolvedFilePath);
|
|
29
|
+
if (relative.startsWith("..") ||
|
|
30
|
+
node_path_1.default.isAbsolute(relative) ||
|
|
31
|
+
relative.trim() === "") {
|
|
32
|
+
throw new Error("File path is outside the workspace directory.");
|
|
33
|
+
}
|
|
34
|
+
return relative.split(node_path_1.default.sep).join("/");
|
|
35
|
+
}
|
|
36
|
+
class SendPartnerFileService {
|
|
37
|
+
config;
|
|
38
|
+
sessionStore;
|
|
39
|
+
logger;
|
|
40
|
+
projectIdentityResolver;
|
|
41
|
+
collaborationService;
|
|
42
|
+
constructor(config, sessionStore, logger, projectIdentityResolver, collaborationService) {
|
|
43
|
+
this.config = config;
|
|
44
|
+
this.sessionStore = sessionStore;
|
|
45
|
+
this.logger = logger;
|
|
46
|
+
this.projectIdentityResolver = projectIdentityResolver;
|
|
47
|
+
this.collaborationService = collaborationService;
|
|
48
|
+
}
|
|
49
|
+
async send(input) {
|
|
50
|
+
const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
|
|
51
|
+
const session = await this.sessionStore.getSession(resolved.sessionId);
|
|
52
|
+
const workspaceDir = resolveWorkspaceDir({
|
|
53
|
+
inputCwd: input.cwd,
|
|
54
|
+
sessionCwd: session?.cwd,
|
|
55
|
+
resolvedCwd: resolved.cwd,
|
|
56
|
+
});
|
|
57
|
+
const relativeFilePath = normalizeWorkspaceRelativePath(workspaceDir, input.file_path);
|
|
58
|
+
const fileContent = await (0, client_1.readWorkspaceFile)(this.config.tmux, workspaceDir, relativeFilePath);
|
|
59
|
+
const originalName = node_path_1.default.basename(relativeFilePath);
|
|
60
|
+
const mimeType = (0, mime_types_1.lookup)(originalName) || "application/octet-stream";
|
|
61
|
+
const output = await this.collaborationService.sendPartnerNote({
|
|
62
|
+
session_id: resolved.sessionId,
|
|
63
|
+
...(input.target_session_id?.trim()
|
|
64
|
+
? { target_session_id: input.target_session_id.trim() }
|
|
65
|
+
: {}),
|
|
66
|
+
...(input.project_uuid?.trim()
|
|
67
|
+
? { project_uuid: input.project_uuid.trim() }
|
|
68
|
+
: {}),
|
|
69
|
+
kind: input.kind ?? "handoff",
|
|
70
|
+
summary: input.summary?.trim() || `Передача файла: ${originalName}`,
|
|
71
|
+
message: input.message?.trim() || `Передаю файл \`${originalName}\`.`,
|
|
72
|
+
...(input.expected_reply?.trim()
|
|
73
|
+
? { expected_reply: input.expected_reply.trim() }
|
|
74
|
+
: {}),
|
|
75
|
+
...(typeof input.requires_reply === "boolean"
|
|
76
|
+
? { requires_reply: input.requires_reply }
|
|
77
|
+
: {}),
|
|
78
|
+
...(input.in_reply_to?.trim()
|
|
79
|
+
? { in_reply_to: input.in_reply_to.trim() }
|
|
80
|
+
: {}),
|
|
81
|
+
artifacts: [relativeFilePath],
|
|
82
|
+
artifact_refs: [
|
|
83
|
+
{
|
|
84
|
+
file_path: relativeFilePath,
|
|
85
|
+
original_name: originalName,
|
|
86
|
+
mime_type: mimeType,
|
|
87
|
+
size_bytes: fileContent.byteLength,
|
|
88
|
+
content_base64: Buffer.from(fileContent).toString("base64"),
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
});
|
|
92
|
+
this.logger.info("Partner file sent through send_partner_file", {
|
|
93
|
+
sessionId: output.session_id,
|
|
94
|
+
partnerSessionId: output.partner_session_id,
|
|
95
|
+
filePath: relativeFilePath,
|
|
96
|
+
kind: output.kind,
|
|
97
|
+
shareId: output.share_id,
|
|
98
|
+
});
|
|
99
|
+
return output;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.SendPartnerFileService = SendPartnerFileService;
|
package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SendPartnerFileTool = void 0;
|
|
4
|
+
const schema_1 = require("../../../entities/request/model/schema");
|
|
5
|
+
function createContent(output) {
|
|
6
|
+
return [
|
|
7
|
+
{
|
|
8
|
+
type: "text",
|
|
9
|
+
text: JSON.stringify(output, null, 2),
|
|
10
|
+
},
|
|
11
|
+
];
|
|
12
|
+
}
|
|
13
|
+
class SendPartnerFileTool {
|
|
14
|
+
sendPartnerFileService;
|
|
15
|
+
constructor(sendPartnerFileService) {
|
|
16
|
+
this.sendPartnerFileService = sendPartnerFileService;
|
|
17
|
+
}
|
|
18
|
+
register(server) {
|
|
19
|
+
server.registerTool("send_partner_file", {
|
|
20
|
+
title: "Send Partner File",
|
|
21
|
+
description: "Use this when the result must include a real local workspace file for another session. Prefer this over send_partner_note when you already have an existing file path such as sample.txt, report.pdf, or screenshot.png. The tool reads the file from the current session workspace, attaches it as an artifact, and sends the partner note in one step.",
|
|
22
|
+
inputSchema: schema_1.sendPartnerFileInputSchema,
|
|
23
|
+
outputSchema: schema_1.sendPartnerNoteOutputSchema,
|
|
24
|
+
}, async (args) => {
|
|
25
|
+
const output = await this.sendPartnerFileService.send(args);
|
|
26
|
+
return {
|
|
27
|
+
content: createContent(output),
|
|
28
|
+
structuredContent: output,
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.SendPartnerFileTool = SendPartnerFileTool;
|
package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SendPartnerNoteTool = void 0;
|
|
4
|
+
const schema_1 = require("../../../entities/request/model/schema");
|
|
5
|
+
function createContent(output) {
|
|
6
|
+
return [
|
|
7
|
+
{
|
|
8
|
+
type: "text",
|
|
9
|
+
text: JSON.stringify(output, null, 2),
|
|
10
|
+
},
|
|
11
|
+
];
|
|
12
|
+
}
|
|
13
|
+
class SendPartnerNoteTool {
|
|
14
|
+
collaborationService;
|
|
15
|
+
constructor(collaborationService) {
|
|
16
|
+
this.collaborationService = collaborationService;
|
|
17
|
+
}
|
|
18
|
+
register(server) {
|
|
19
|
+
server.registerTool("send_partner_note", {
|
|
20
|
+
title: "Send Partner Note",
|
|
21
|
+
description: "Use this for agent-to-agent collaboration: ask another session to do work, send a reply, or share results. Resolve the target explicitly for project/collab work with target_session_id and, if available, project_uuid. If the result includes an existing local file, prefer send_partner_file; mentioning the filename in message text is not enough. For required replies, the task is not complete until this tool succeeds.",
|
|
22
|
+
inputSchema: schema_1.sendPartnerNoteInputSchema,
|
|
23
|
+
outputSchema: schema_1.sendPartnerNoteOutputSchema,
|
|
24
|
+
}, async (args) => {
|
|
25
|
+
const output = await this.collaborationService.sendPartnerNote(args);
|
|
26
|
+
return {
|
|
27
|
+
content: createContent(output),
|
|
28
|
+
structuredContent: output,
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.SendPartnerNoteTool = SendPartnerNoteTool;
|