@deadragdoll/tellymcp 0.0.9 → 0.0.11
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 +42 -50
- package/.env.example.gateway +49 -61
- package/CHANGELOG.md +3 -3
- package/README-ru.md +205 -384
- package/README.md +195 -1194
- package/TOOLS.md +294 -377
- package/VERSION.md +36 -10
- package/config/codex/plugins/telly-workflows/.codex-plugin/plugin.json +18 -0
- package/config/codex/plugins/telly-workflows/references/invariants.md +10 -0
- package/config/codex/plugins/telly-workflows/skills/telly-browser-screenshot/SKILL.md +27 -0
- package/config/codex/plugins/telly-workflows/skills/telly-collab-artifact/SKILL.md +22 -0
- package/config/codex/plugins/telly-workflows/skills/telly-human-telegram/SKILL.md +31 -0
- package/config/codex/plugins/telly-workflows/skills/telly-partner-note/SKILL.md +36 -0
- package/config/templates/env.both.template +40 -20
- package/config/templates/env.client.template +34 -18
- package/config/templates/env.gateway.template +38 -22
- package/dist/cli.js +322 -75
- package/dist/codexPluginInstaller.js +215 -0
- package/dist/lib/mixins/session.errors.js +34 -1
- package/dist/lib/pinoTargets.js +2 -2
- package/dist/moleculer.config.js +7 -5
- package/dist/services/features/telegram-mcp/approval.service.js +1 -1
- package/dist/services/features/telegram-mcp/browser.service.js +95 -2
- package/dist/services/features/telegram-mcp/collaboration.service.js +41 -4
- package/dist/services/features/telegram-mcp/ensuredb.service.js +145 -26
- package/dist/services/features/telegram-mcp/gateway-delivery.service.js +285 -103
- package/dist/services/features/telegram-mcp/gateway-rmq.service.js +3 -2
- package/dist/services/features/telegram-mcp/gateway-socket.service.js +905 -87
- package/dist/services/features/telegram-mcp/gateway.service.js +876 -81
- package/dist/services/features/telegram-mcp/mcp-http.service.js +9 -1
- package/dist/services/features/telegram-mcp/mcp-server.service.js +17 -26
- package/dist/services/features/telegram-mcp/notify.service.js +128 -2
- package/dist/services/features/telegram-mcp/runtime.service.js +27 -7
- package/dist/services/features/telegram-mcp/session-context.service.js +29 -2
- package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +133 -10
- package/dist/services/features/telegram-mcp/src/app/config/env.js +161 -51
- package/dist/services/features/telegram-mcp/src/app/http.js +375 -42
- package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +386 -58
- package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +3 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/terminal.js +12 -0
- package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +116 -104
- package/dist/services/features/telegram-mcp/src/entities/xchange/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/features/ask-user/model/askUserTelegram.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +249 -19
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/gatewaySessionsService.js +71 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/listGatewaySessionsTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +93 -82
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +47 -5
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayClientAccess.js +82 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +22 -14
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +649 -75
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/remoteConsoleActionClient.js +76 -0
- package/dist/services/features/telegram-mcp/src/features/embedded-runtime/model/embeddedRuntimeBroker.js +92 -0
- package/dist/services/features/telegram-mcp/src/features/foreground-terminal/model/foregroundTerminalRuntime.js +192 -0
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +382 -3
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/notify/model/sendFileToTelegramTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +42 -200
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/terminal-buffer/model/terminalBufferService.js +96 -0
- package/dist/services/features/telegram-mcp/src/features/terminal-input/model/terminalInputService.js +97 -0
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +107 -58
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/xchange/model/getXchangeRecordTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/xchange/model/listXchangeRecordsTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/xchange/model/markXchangeRecordReadTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/xchange/model/xchangeService.js +169 -0
- package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +5 -4
- package/dist/services/features/telegram-mcp/src/shared/i18n/index.js +46 -0
- package/dist/services/features/telegram-mcp/src/shared/i18n/resources/en.js +652 -0
- package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +652 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/memory/processLocalSessionStore.js +27 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +11 -8
- package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +51 -71
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +21 -22
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +411 -6524
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportAttachmentStore.js +93 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportBroadcastActions.js +385 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConsoleRegistry.js +143 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConstructorWiring.js +633 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContent.js +84 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContext.js +78 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportDocumentActions.js +36 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportEventActions.js +292 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFileHandoffActions.js +352 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFormatting.js +75 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportGatewayActions.js +44 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLifecycleActions.js +161 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLive.js +56 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLiveActions.js +77 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuCallbacks.js +254 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFactories.js +538 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFingerprints.js +93 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFlow.js +344 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuShell.js +62 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuState.js +408 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuText.js +216 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMessageFlow.js +452 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportOutputActions.js +189 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPartnerActions.js +286 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPayloadState.js +101 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectActions.js +463 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEntryActions.js +202 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEvents.js +99 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectMenus.js +138 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectState.js +308 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectView.js +426 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportRequestFlow.js +278 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportSessionActions.js +143 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalActions.js +468 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalRuntime.js +171 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTypes.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportUtils.js +330 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportXchangeState.js +107 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/client.js +255 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/ptyRegistry.js +543 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/xchange/sqliteRecordStore.js +223 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/gatewayScope.js +24 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +6 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +147 -76
- package/dist/services/features/telegram-mcp/src/shared/lib/telegramXchangeRecords.js +72 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/terminalPromptDetection.js +237 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +129 -1
- package/dist/services/features/telegram-mcp/src/shared/lib/xchangeRecordHints.js +98 -0
- package/dist/services/features/telegram-mcp/standalone-http.service.js +13 -1
- package/dist/services/features/telegram-mcp/terminal-buffer.service.js +42 -0
- package/dist/services/features/telegram-mcp/terminal-input.service.js +41 -0
- package/dist/services/features/telegram-mcp/tools-sync.service.js +16 -2
- package/dist/services/features/telegram-mcp/xchange.service.js +123 -0
- package/docs/STANDALONE-ru.md +172 -0
- package/docs/STANDALONE.md +172 -0
- package/package.json +11 -5
- package/scripts/build-package-artifact.sh +27 -0
- package/scripts/deploy-gateway.sh +64 -0
- package/scripts/deploy-onebot-branch.sh +27 -0
- package/scripts/postinstall.js +11 -36
- package/STANDALONE-ru.md +0 -274
- package/STANDALONE.md +0 -274
- package/dist/services/features/telegram-mcp/inbox.service.js +0 -33
- package/dist/services/features/telegram-mcp/pair.service.js +0 -33
- package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +0 -10
- package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +0 -77
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +0 -202
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +0 -363
|
@@ -5,8 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.LocalCollaborationBackend = void 0;
|
|
7
7
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
-
const
|
|
9
|
-
const client_1 = require("../../../shared/integrations/
|
|
8
|
+
const xchangeRecordHints_1 = require("../../../shared/lib/xchangeRecordHints");
|
|
9
|
+
const client_1 = require("../../../shared/integrations/terminal/client");
|
|
10
|
+
const sqliteRecordStore_1 = require("../../../shared/integrations/xchange/sqliteRecordStore");
|
|
10
11
|
function slugify(input) {
|
|
11
12
|
return input
|
|
12
13
|
.trim()
|
|
@@ -49,7 +50,6 @@ const SOURCE_ARTIFACT_EXTENSIONS = new Set([
|
|
|
49
50
|
".xml",
|
|
50
51
|
".zsh",
|
|
51
52
|
]);
|
|
52
|
-
const PARTNER_INDEX_FILE_NAME = "SHARED_INDEX.md";
|
|
53
53
|
function trimOptional(value) {
|
|
54
54
|
const trimmed = value?.trim();
|
|
55
55
|
return trimmed ? trimmed : undefined;
|
|
@@ -78,35 +78,6 @@ function renderYamlArray(values) {
|
|
|
78
78
|
}
|
|
79
79
|
return `\n${values.map((value) => ` - ${JSON.stringify(value)}`).join("\n")}`;
|
|
80
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
81
|
function buildNoteContent(input) {
|
|
111
82
|
const lines = ["---"];
|
|
112
83
|
lines.push(`kind: ${JSON.stringify(input.kind)}`);
|
|
@@ -129,38 +100,26 @@ function buildNoteContent(input) {
|
|
|
129
100
|
lines.push("", "# Expected Reply", input.expectedReply.trim());
|
|
130
101
|
}
|
|
131
102
|
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=\"Подробный ответ\"", ")");
|
|
103
|
+
lines.push("", "# Action Required", "You must send a reply via send_partner_note.", "Do not stop after reading, listing files, or explaining what you found.", "Your task is not complete until send_partner_note succeeds.", "Do not stop after local analysis or a chat explanation.", "Only after send_partner_note succeeds may you mark the record as read or say the work is done.", "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
104
|
}
|
|
134
105
|
if (input.copiedArtifacts.length > 0) {
|
|
135
106
|
lines.push("", "# Artifacts", ...input.copiedArtifacts.map((artifact) => `- ${artifact}`));
|
|
136
107
|
}
|
|
137
108
|
return `${lines.join("\n")}\n`;
|
|
138
109
|
}
|
|
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
110
|
class LocalCollaborationBackend {
|
|
150
111
|
config;
|
|
151
112
|
sessionStore;
|
|
152
113
|
bindingStore;
|
|
153
|
-
inboxStore;
|
|
154
114
|
xchangeFileMetaStore;
|
|
155
115
|
objectStore;
|
|
156
116
|
telegramTransport;
|
|
157
117
|
logger;
|
|
158
118
|
textEncoder = new TextEncoder();
|
|
159
|
-
constructor(config, sessionStore, bindingStore,
|
|
119
|
+
constructor(config, sessionStore, bindingStore, xchangeFileMetaStore, objectStore, telegramTransport, logger) {
|
|
160
120
|
this.config = config;
|
|
161
121
|
this.sessionStore = sessionStore;
|
|
162
122
|
this.bindingStore = bindingStore;
|
|
163
|
-
this.inboxStore = inboxStore;
|
|
164
123
|
this.xchangeFileMetaStore = xchangeFileMetaStore;
|
|
165
124
|
this.objectStore = objectStore;
|
|
166
125
|
this.telegramTransport = telegramTransport;
|
|
@@ -169,11 +128,11 @@ class LocalCollaborationBackend {
|
|
|
169
128
|
async sendPartnerNote(input, resolved) {
|
|
170
129
|
const sourceSession = await this.sessionStore.getSession(resolved.sessionId);
|
|
171
130
|
if (!sourceSession) {
|
|
172
|
-
throw new Error(`Session ${resolved.sessionId} was not found
|
|
131
|
+
throw new Error(`Session ${resolved.sessionId} was not found.`);
|
|
173
132
|
}
|
|
174
|
-
const targetSessionId = trimOptional(input.target_session_id)
|
|
133
|
+
const targetSessionId = trimOptional(input.target_session_id);
|
|
175
134
|
if (!targetSessionId) {
|
|
176
|
-
throw new Error("
|
|
135
|
+
throw new Error("target_session_id is required for send_partner_note.");
|
|
177
136
|
}
|
|
178
137
|
const targetSession = await this.sessionStore.getSession(targetSessionId);
|
|
179
138
|
if (!targetSession) {
|
|
@@ -181,7 +140,7 @@ class LocalCollaborationBackend {
|
|
|
181
140
|
}
|
|
182
141
|
const targetBinding = await this.bindingStore.getBinding(targetSession.sessionId);
|
|
183
142
|
if (!targetBinding) {
|
|
184
|
-
throw new Error(`
|
|
143
|
+
throw new Error(`Target session ${targetSession.sessionId} has no active Telegram route.`);
|
|
185
144
|
}
|
|
186
145
|
const now = new Date();
|
|
187
146
|
const createdAt = now.toISOString();
|
|
@@ -210,7 +169,7 @@ class LocalCollaborationBackend {
|
|
|
210
169
|
message: input.message,
|
|
211
170
|
...(expectedReply ? { expectedReply } : {}),
|
|
212
171
|
});
|
|
213
|
-
const notePath = await (0, client_1.writeXchangeRelativeFile)(this.config.
|
|
172
|
+
const notePath = await (0, client_1.writeXchangeRelativeFile)(this.config.terminal, targetWorkspaceDir, this.config.exchange.dir, relativeNotePath, this.textEncoder.encode(noteContent));
|
|
214
173
|
await this.xchangeFileMetaStore.setXchangeFileMeta({
|
|
215
174
|
sessionId: targetSession.sessionId,
|
|
216
175
|
filePath: notePath,
|
|
@@ -220,32 +179,81 @@ class LocalCollaborationBackend {
|
|
|
220
179
|
mimeType: "text/markdown",
|
|
221
180
|
sizeBytes: this.textEncoder.encode(noteContent).byteLength,
|
|
222
181
|
});
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
182
|
+
const targetActionDesc = (0, xchangeRecordHints_1.buildIncomingPartnerActionDesc)(input.kind, requiresReply);
|
|
183
|
+
const targetTools = (0, xchangeRecordHints_1.buildIncomingPartnerTools)(input.kind, requiresReply);
|
|
184
|
+
await (0, sqliteRecordStore_1.upsertXchangeRecord)(this.config.terminal, targetWorkspaceDir, this.config.exchange.dir, {
|
|
185
|
+
record_id: shareId,
|
|
186
|
+
session_id: targetSession.sessionId,
|
|
187
|
+
category: "partner_note",
|
|
188
|
+
direction: "incoming",
|
|
189
|
+
status: "new",
|
|
227
190
|
kind: input.kind,
|
|
228
191
|
summary: input.summary.trim(),
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
192
|
+
body_text: noteContent,
|
|
193
|
+
action_desc: targetActionDesc,
|
|
194
|
+
tools: targetTools,
|
|
195
|
+
note_path: notePath,
|
|
196
|
+
note_relative_path: relativeNotePath,
|
|
197
|
+
source_session_id: sourceSession.sessionId,
|
|
198
|
+
source_label: sourceLabel,
|
|
199
|
+
target_session_id: targetSession.sessionId,
|
|
200
|
+
target_label: targetLabel,
|
|
201
|
+
requires_reply: requiresReply,
|
|
202
|
+
...(inReplyTo ? { in_reply_to: inReplyTo } : {}),
|
|
203
|
+
...(expectedReply ? { expected_reply: expectedReply } : {}),
|
|
204
|
+
attachments: [
|
|
205
|
+
{
|
|
206
|
+
file_path: notePath,
|
|
207
|
+
relative_path: relativeNotePath,
|
|
208
|
+
original_name: node_path_1.default.basename(relativeNotePath),
|
|
209
|
+
mime_type: "text/markdown",
|
|
210
|
+
size_bytes: this.textEncoder.encode(noteContent).byteLength,
|
|
211
|
+
},
|
|
212
|
+
...copiedArtifacts.map((filePath) => ({
|
|
213
|
+
file_path: filePath,
|
|
214
|
+
})),
|
|
215
|
+
],
|
|
216
|
+
tags: [
|
|
217
|
+
"partner",
|
|
218
|
+
input.kind,
|
|
219
|
+
...(requiresReply ? ["requires-reply"] : []),
|
|
220
|
+
],
|
|
221
|
+
created_at: createdAt,
|
|
222
|
+
updated_at: createdAt,
|
|
223
|
+
});
|
|
224
|
+
await (0, sqliteRecordStore_1.upsertXchangeRecord)(this.config.terminal, sourceWorkspaceDir, this.config.exchange.dir, {
|
|
225
|
+
record_id: shareId,
|
|
226
|
+
session_id: sourceSession.sessionId,
|
|
227
|
+
category: "partner_note",
|
|
228
|
+
direction: "outgoing",
|
|
229
|
+
status: "read",
|
|
230
|
+
kind: input.kind,
|
|
231
|
+
summary: input.summary.trim(),
|
|
232
|
+
body_text: noteContent,
|
|
233
|
+
action_desc: (0, xchangeRecordHints_1.buildOutgoingPartnerActionDesc)(input.kind, requiresReply),
|
|
234
|
+
tools: (0, xchangeRecordHints_1.buildOutgoingPartnerTools)(input.kind, requiresReply),
|
|
235
|
+
note_path: notePath,
|
|
236
|
+
note_relative_path: relativeNotePath,
|
|
237
|
+
source_session_id: sourceSession.sessionId,
|
|
238
|
+
source_label: sourceLabel,
|
|
239
|
+
target_session_id: targetSession.sessionId,
|
|
240
|
+
target_label: targetLabel,
|
|
241
|
+
requires_reply: requiresReply,
|
|
242
|
+
...(inReplyTo ? { in_reply_to: inReplyTo } : {}),
|
|
243
|
+
...(expectedReply ? { expected_reply: expectedReply } : {}),
|
|
244
|
+
attachments: copiedArtifacts.map((filePath) => ({
|
|
245
|
+
file_path: filePath,
|
|
246
|
+
})),
|
|
247
|
+
tags: [
|
|
248
|
+
"partner",
|
|
249
|
+
"outgoing",
|
|
250
|
+
input.kind,
|
|
251
|
+
...(requiresReply ? ["awaiting-reply"] : []),
|
|
252
|
+
],
|
|
253
|
+
created_at: createdAt,
|
|
254
|
+
updated_at: createdAt,
|
|
255
|
+
read_at: createdAt,
|
|
256
|
+
});
|
|
249
257
|
await this.telegramTransport.sendNotification({
|
|
250
258
|
sessionId: targetSession.sessionId,
|
|
251
259
|
sessionLabel: sourceLabel,
|
|
@@ -280,10 +288,13 @@ class LocalCollaborationBackend {
|
|
|
280
288
|
].join("\n"),
|
|
281
289
|
});
|
|
282
290
|
try {
|
|
283
|
-
await this.telegramTransport.nudgeSessionPartnerNote(targetSession.sessionId
|
|
291
|
+
await this.telegramTransport.nudgeSessionPartnerNote(targetSession.sessionId, {
|
|
292
|
+
kind: input.kind,
|
|
293
|
+
requiresReply,
|
|
294
|
+
});
|
|
284
295
|
}
|
|
285
296
|
catch (error) {
|
|
286
|
-
this.logger.warn("
|
|
297
|
+
this.logger.warn("terminal nudge failed after local partner delivery", {
|
|
287
298
|
sessionId: targetSession.sessionId,
|
|
288
299
|
partnerSessionId: sourceSession.sessionId,
|
|
289
300
|
shareId,
|
|
@@ -307,9 +318,9 @@ class LocalCollaborationBackend {
|
|
|
307
318
|
share_id: shareId,
|
|
308
319
|
delivery_status: "delivered",
|
|
309
320
|
note_path: notePath,
|
|
310
|
-
|
|
321
|
+
xchange_record_id: shareId,
|
|
311
322
|
copied_artifacts: copiedArtifacts,
|
|
312
|
-
inbox_message_id:
|
|
323
|
+
inbox_message_id: shareId,
|
|
313
324
|
requires_reply: requiresReply,
|
|
314
325
|
};
|
|
315
326
|
}
|
|
@@ -318,7 +329,7 @@ class LocalCollaborationBackend {
|
|
|
318
329
|
if (workspaceDir) {
|
|
319
330
|
return workspaceDir;
|
|
320
331
|
}
|
|
321
|
-
|
|
332
|
+
throw new Error(`Workspace cwd is not registered for console '${session.sessionId}'.`);
|
|
322
333
|
}
|
|
323
334
|
async copyArtifactsToPartner(sourceSession, targetSession, sourceWorkspaceDir, targetWorkspaceDir, shareId, uploadedAt, artifacts) {
|
|
324
335
|
const copied = [];
|
|
@@ -351,8 +362,8 @@ class LocalCollaborationBackend {
|
|
|
351
362
|
source: sourceMeta.source,
|
|
352
363
|
})
|
|
353
364
|
: artifactPath;
|
|
354
|
-
const content = await (0, client_1.readWorkspaceFile)(this.config.
|
|
355
|
-
const materializedArtifactPath = await (0, client_1.writeXchangeRelativeFile)(this.config.
|
|
365
|
+
const content = await (0, client_1.readWorkspaceFile)(this.config.terminal, sourceWorkspaceDir, ensuredArtifactPath);
|
|
366
|
+
const materializedArtifactPath = await (0, client_1.writeXchangeRelativeFile)(this.config.terminal, targetWorkspaceDir, this.config.exchange.dir, relativeArtifactPath, content);
|
|
356
367
|
await this.xchangeFileMetaStore.setXchangeFileMeta({
|
|
357
368
|
sessionId: targetSession.sessionId,
|
|
358
369
|
filePath: materializedArtifactPath,
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.SendPartnerFileService = void 0;
|
|
7
7
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
8
|
const mime_types_1 = require("mime-types");
|
|
9
|
-
const client_1 = require("../../../shared/integrations/
|
|
9
|
+
const client_1 = require("../../../shared/integrations/terminal/client");
|
|
10
10
|
function resolveWorkspaceDir(input) {
|
|
11
11
|
if (input.inputCwd?.trim()) {
|
|
12
12
|
return node_path_1.default.resolve(input.inputCwd.trim());
|
|
@@ -36,33 +36,53 @@ function normalizeWorkspaceRelativePath(workspaceDir, filePath) {
|
|
|
36
36
|
class SendPartnerFileService {
|
|
37
37
|
config;
|
|
38
38
|
sessionStore;
|
|
39
|
+
maintenanceStore;
|
|
39
40
|
logger;
|
|
40
41
|
projectIdentityResolver;
|
|
41
42
|
collaborationService;
|
|
42
|
-
|
|
43
|
+
remoteConsoleInvoker;
|
|
44
|
+
constructor(config, sessionStore, maintenanceStore, logger, projectIdentityResolver, collaborationService, remoteConsoleInvoker) {
|
|
43
45
|
this.config = config;
|
|
44
46
|
this.sessionStore = sessionStore;
|
|
47
|
+
this.maintenanceStore = maintenanceStore;
|
|
45
48
|
this.logger = logger;
|
|
46
49
|
this.projectIdentityResolver = projectIdentityResolver;
|
|
47
50
|
this.collaborationService = collaborationService;
|
|
51
|
+
this.remoteConsoleInvoker = remoteConsoleInvoker;
|
|
48
52
|
}
|
|
49
53
|
async send(input) {
|
|
50
54
|
const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
|
|
51
|
-
const
|
|
55
|
+
const sessionId = await this.normalizeSessionIdForWorkspace(resolved.sessionId);
|
|
56
|
+
const remote = this.config.distributed.mode !== "client"
|
|
57
|
+
? await this.remoteConsoleInvoker?.invokeForRelaySession(sessionId, "telegramMcp.collaboration.sendPartnerFileRemote", {
|
|
58
|
+
...input,
|
|
59
|
+
session_id: sessionId,
|
|
60
|
+
})
|
|
61
|
+
: null;
|
|
62
|
+
if (remote) {
|
|
63
|
+
return remote;
|
|
64
|
+
}
|
|
65
|
+
const session = await this.sessionStore.getSession(sessionId);
|
|
52
66
|
const workspaceDir = resolveWorkspaceDir({
|
|
53
67
|
inputCwd: input.cwd,
|
|
54
68
|
sessionCwd: session?.cwd,
|
|
55
69
|
resolvedCwd: resolved.cwd,
|
|
56
70
|
});
|
|
57
71
|
const relativeFilePath = normalizeWorkspaceRelativePath(workspaceDir, input.file_path);
|
|
58
|
-
const fileContent = await (0, client_1.readWorkspaceFile)(this.config.
|
|
72
|
+
const fileContent = await (0, client_1.readWorkspaceFile)(this.config.terminal, workspaceDir, relativeFilePath);
|
|
59
73
|
const originalName = node_path_1.default.basename(relativeFilePath);
|
|
60
74
|
const mimeType = (0, mime_types_1.lookup)(originalName) || "application/octet-stream";
|
|
61
75
|
const output = await this.collaborationService.sendPartnerNote({
|
|
62
|
-
session_id:
|
|
76
|
+
session_id: sessionId,
|
|
63
77
|
...(input.target_session_id?.trim()
|
|
64
78
|
? { target_session_id: input.target_session_id.trim() }
|
|
65
79
|
: {}),
|
|
80
|
+
...(input.target_client_uuid?.trim()
|
|
81
|
+
? { target_client_uuid: input.target_client_uuid.trim() }
|
|
82
|
+
: {}),
|
|
83
|
+
...(input.target_local_session_id?.trim()
|
|
84
|
+
? { target_local_session_id: input.target_local_session_id.trim() }
|
|
85
|
+
: {}),
|
|
66
86
|
...(input.project_uuid?.trim()
|
|
67
87
|
? { project_uuid: input.project_uuid.trim() }
|
|
68
88
|
: {}),
|
|
@@ -98,5 +118,27 @@ class SendPartnerFileService {
|
|
|
98
118
|
});
|
|
99
119
|
return output;
|
|
100
120
|
}
|
|
121
|
+
async normalizeSessionIdForWorkspace(sessionId) {
|
|
122
|
+
const trimmed = sessionId.trim();
|
|
123
|
+
if (!trimmed) {
|
|
124
|
+
return trimmed;
|
|
125
|
+
}
|
|
126
|
+
const direct = await this.sessionStore.getSession(trimmed);
|
|
127
|
+
if (direct) {
|
|
128
|
+
return trimmed;
|
|
129
|
+
}
|
|
130
|
+
const separatorIndex = trimmed.indexOf(":");
|
|
131
|
+
if (separatorIndex <= 0) {
|
|
132
|
+
return trimmed;
|
|
133
|
+
}
|
|
134
|
+
const localClientUuid = await this.maintenanceStore.getGatewayClientUuid();
|
|
135
|
+
const clientUuid = trimmed.slice(0, separatorIndex).trim();
|
|
136
|
+
const localSessionId = trimmed.slice(separatorIndex + 1).trim();
|
|
137
|
+
if (!localClientUuid || clientUuid !== localClientUuid || !localSessionId) {
|
|
138
|
+
return trimmed;
|
|
139
|
+
}
|
|
140
|
+
const localSession = await this.sessionStore.getSession(localSessionId);
|
|
141
|
+
return localSession ? localSessionId : trimmed;
|
|
142
|
+
}
|
|
101
143
|
}
|
|
102
144
|
exports.SendPartnerFileService = SendPartnerFileService;
|
package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js
CHANGED
|
@@ -18,7 +18,7 @@ class SendPartnerFileTool {
|
|
|
18
18
|
register(server) {
|
|
19
19
|
server.registerTool("send_partner_file", {
|
|
20
20
|
title: "Send Partner File",
|
|
21
|
-
description: "Use this when the result must include a real local workspace file for another
|
|
21
|
+
description: "Use this when the result must include a real local workspace file for another console. Prefer this over send_partner_note when you already have an existing file path such as sample.txt, report.pdf, or screenshot.png. For project/collab routing, use target_session_id. For direct gateway-wide routing outside a single collab project, first call list_gateway_sessions and then pass target_client_uuid plus target_local_session_id. The tool reads the file from the current console workspace, attaches it as an artifact, and sends the partner note in one step.",
|
|
22
22
|
inputSchema: schema_1.sendPartnerFileInputSchema,
|
|
23
23
|
outputSchema: schema_1.sendPartnerNoteOutputSchema,
|
|
24
24
|
}, async (args) => {
|
package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js
CHANGED
|
@@ -18,7 +18,7 @@ class SendPartnerNoteTool {
|
|
|
18
18
|
register(server) {
|
|
19
19
|
server.registerTool("send_partner_note", {
|
|
20
20
|
title: "Send Partner Note",
|
|
21
|
-
description: "Use this for agent-to-agent collaboration: ask another
|
|
21
|
+
description: "Use this for agent-to-agent collaboration: ask another console to do work, send a reply, or share results. The canonical gateway-facing console id is session_id in the format client_uuid:local_session_id. For direct routing outside a collab project, pass that canonical console id in target_session_id. Only use target_client_uuid plus target_local_session_id when you already have those exact direct fields separately. For project/collab routing, use target_session_id equal to the project 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
22
|
inputSchema: schema_1.sendPartnerNoteInputSchema,
|
|
23
23
|
outputSchema: schema_1.sendPartnerNoteOutputSchema,
|
|
24
24
|
}, async (args) => {
|
|
@@ -0,0 +1,82 @@
|
|
|
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.normalizeGatewayBaseUrl = normalizeGatewayBaseUrl;
|
|
7
|
+
exports.callGatewayJson = callGatewayJson;
|
|
8
|
+
exports.ensureGatewayClientUuid = ensureGatewayClientUuid;
|
|
9
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
10
|
+
function normalizeGatewayBaseUrl(value) {
|
|
11
|
+
const url = new URL(value);
|
|
12
|
+
url.pathname = url.pathname.replace(/\/+$/u, "");
|
|
13
|
+
if (!url.pathname.endsWith("/gateway")) {
|
|
14
|
+
url.pathname = `${url.pathname}/gateway`.replace(/\/{2,}/gu, "/");
|
|
15
|
+
}
|
|
16
|
+
return url;
|
|
17
|
+
}
|
|
18
|
+
async function callGatewayJson(input) {
|
|
19
|
+
const url = normalizeGatewayBaseUrl(input.gatewayPublicUrl);
|
|
20
|
+
url.pathname = `${url.pathname}${input.endpointPath}`.replace(/\/{2,}/gu, "/");
|
|
21
|
+
const response = await fetch(url, {
|
|
22
|
+
method: "POST",
|
|
23
|
+
headers: {
|
|
24
|
+
"content-type": "application/json",
|
|
25
|
+
...(input.gatewayAuthToken
|
|
26
|
+
? { authorization: `Bearer ${input.gatewayAuthToken}` }
|
|
27
|
+
: {}),
|
|
28
|
+
},
|
|
29
|
+
body: JSON.stringify(input.body),
|
|
30
|
+
});
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
const message = await response.text();
|
|
33
|
+
throw new Error(`Gateway request failed with status ${response.status}: ${message || response.statusText}`);
|
|
34
|
+
}
|
|
35
|
+
return (await response.json());
|
|
36
|
+
}
|
|
37
|
+
async function ensureGatewayClientUuid(input) {
|
|
38
|
+
const namespace = input.namespace || process.env.NAMESPACE || undefined;
|
|
39
|
+
const nodeId = input.nodeId || process.env.NODE_ID || undefined;
|
|
40
|
+
const systemUsername = input.systemUsername ||
|
|
41
|
+
process.env.USER ||
|
|
42
|
+
process.env.LOGNAME ||
|
|
43
|
+
(() => {
|
|
44
|
+
try {
|
|
45
|
+
return node_os_1.default.userInfo().username;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
})();
|
|
51
|
+
const existing = await input.maintenanceStore.getGatewayClientUuid();
|
|
52
|
+
if (!input.gatewayPublicUrl) {
|
|
53
|
+
throw new Error("Gateway client registration requires GATEWAY_PUBLIC_URL.");
|
|
54
|
+
}
|
|
55
|
+
const response = await callGatewayJson({
|
|
56
|
+
gatewayPublicUrl: input.gatewayPublicUrl,
|
|
57
|
+
...(input.gatewayAuthToken
|
|
58
|
+
? { gatewayAuthToken: input.gatewayAuthToken }
|
|
59
|
+
: {}),
|
|
60
|
+
endpointPath: "/client/register",
|
|
61
|
+
body: {
|
|
62
|
+
...(existing ? { client_uuid: existing } : {}),
|
|
63
|
+
client_label: input.projectName ||
|
|
64
|
+
[namespace, nodeId].filter(Boolean).join("/") ||
|
|
65
|
+
input.botUsername ||
|
|
66
|
+
"tellymcp client",
|
|
67
|
+
...(input.botUsername ? { bot_username: input.botUsername } : {}),
|
|
68
|
+
...(input.gatewayToken ? { gateway_token: input.gatewayToken } : {}),
|
|
69
|
+
...(input.gatewayUserUuid ? { owner_user_uuid: input.gatewayUserUuid } : {}),
|
|
70
|
+
meta: {
|
|
71
|
+
...(namespace ? { namespace } : {}),
|
|
72
|
+
...(nodeId ? { node_id: nodeId } : {}),
|
|
73
|
+
...(systemUsername ? { system_username: systemUsername } : {}),
|
|
74
|
+
...(input.gatewayUserUuid
|
|
75
|
+
? { gateway_user_uuid: input.gatewayUserUuid }
|
|
76
|
+
: {}),
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
await input.maintenanceStore.setGatewayClientUuid(response.client_uuid);
|
|
81
|
+
return response.client_uuid;
|
|
82
|
+
}
|
|
@@ -1,35 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GatewayCollaborationBackend = void 0;
|
|
4
|
-
|
|
5
|
-
const url = new URL(value);
|
|
6
|
-
url.pathname = url.pathname.replace(/\/+$/u, "");
|
|
7
|
-
if (!url.pathname.endsWith("/gateway")) {
|
|
8
|
-
url.pathname = `${url.pathname}/gateway`.replace(/\/{2,}/gu, "/");
|
|
9
|
-
}
|
|
10
|
-
return url;
|
|
11
|
-
}
|
|
4
|
+
const gatewayClientAccess_1 = require("./gatewayClientAccess");
|
|
12
5
|
class GatewayCollaborationBackend {
|
|
13
6
|
logger;
|
|
14
7
|
maintenanceStore;
|
|
15
8
|
gatewayPublicUrl;
|
|
16
9
|
gatewayAuthToken;
|
|
17
|
-
|
|
10
|
+
gatewayToken;
|
|
11
|
+
gatewayUserUuid;
|
|
12
|
+
projectName;
|
|
13
|
+
botUsername;
|
|
14
|
+
constructor(logger, maintenanceStore, gatewayPublicUrl, gatewayAuthToken, gatewayToken, gatewayUserUuid, projectName, botUsername) {
|
|
18
15
|
this.logger = logger;
|
|
19
16
|
this.maintenanceStore = maintenanceStore;
|
|
20
17
|
this.gatewayPublicUrl = gatewayPublicUrl;
|
|
21
18
|
this.gatewayAuthToken = gatewayAuthToken;
|
|
19
|
+
this.gatewayToken = gatewayToken;
|
|
20
|
+
this.gatewayUserUuid = gatewayUserUuid;
|
|
21
|
+
this.projectName = projectName;
|
|
22
|
+
this.botUsername = botUsername;
|
|
22
23
|
}
|
|
23
24
|
async sendPartnerNote(input, resolved) {
|
|
24
25
|
if (!this.gatewayPublicUrl) {
|
|
25
26
|
throw new Error("Gateway collaboration backend requires GATEWAY_PUBLIC_URL.");
|
|
26
27
|
}
|
|
27
|
-
const url = normalizeGatewayBaseUrl(this.gatewayPublicUrl);
|
|
28
|
+
const url = (0, gatewayClientAccess_1.normalizeGatewayBaseUrl)(this.gatewayPublicUrl);
|
|
28
29
|
url.pathname = `${url.pathname}/partner-note`.replace(/\/{2,}/gu, "/");
|
|
29
|
-
const clientUuid = await
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
const clientUuid = await (0, gatewayClientAccess_1.ensureGatewayClientUuid)({
|
|
31
|
+
maintenanceStore: this.maintenanceStore,
|
|
32
|
+
gatewayPublicUrl: this.gatewayPublicUrl,
|
|
33
|
+
...(this.gatewayAuthToken
|
|
34
|
+
? { gatewayAuthToken: this.gatewayAuthToken }
|
|
35
|
+
: {}),
|
|
36
|
+
...(this.gatewayToken ? { gatewayToken: this.gatewayToken } : {}),
|
|
37
|
+
...(this.gatewayUserUuid ? { gatewayUserUuid: this.gatewayUserUuid } : {}),
|
|
38
|
+
...(this.projectName ? { projectName: this.projectName } : {}),
|
|
39
|
+
...(this.botUsername ? { botUsername: this.botUsername } : {}),
|
|
40
|
+
});
|
|
33
41
|
const response = await fetch(url, {
|
|
34
42
|
method: "POST",
|
|
35
43
|
headers: {
|