@besales/mcp 0.1.0 → 0.12.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.
Files changed (94) hide show
  1. package/README.md +272 -17
  2. package/dist/auth/connection-store.d.ts +58 -0
  3. package/dist/auth/connection-store.js +208 -0
  4. package/dist/auth/connection-store.js.map +1 -0
  5. package/dist/auth/oauth-client.d.ts +27 -2
  6. package/dist/auth/oauth-client.js +62 -11
  7. package/dist/auth/oauth-client.js.map +1 -1
  8. package/dist/auth/session-workspace.d.ts +2 -0
  9. package/dist/auth/session-workspace.js +20 -0
  10. package/dist/auth/session-workspace.js.map +1 -0
  11. package/dist/auth/token-storage.d.ts +19 -5
  12. package/dist/auth/token-storage.js +11 -6
  13. package/dist/auth/token-storage.js.map +1 -1
  14. package/dist/cli.d.ts +2 -7
  15. package/dist/cli.js +111 -33
  16. package/dist/cli.js.map +1 -1
  17. package/dist/http/api-client.d.ts +4 -13
  18. package/dist/http/api-client.js +18 -18
  19. package/dist/http/api-client.js.map +1 -1
  20. package/dist/index.d.ts +8 -6
  21. package/dist/index.js +3 -2
  22. package/dist/index.js.map +1 -1
  23. package/dist/instructions/server-instructions.d.ts +15 -0
  24. package/dist/instructions/server-instructions.js +245 -0
  25. package/dist/instructions/server-instructions.js.map +1 -0
  26. package/dist/package-metadata.js +7 -1
  27. package/dist/package-metadata.js.map +1 -1
  28. package/dist/resources/concepts/feedback-sheets.md +77 -0
  29. package/dist/resources/concepts/sandbox.md +13 -0
  30. package/dist/resources/concepts/workbook-classification.md +241 -0
  31. package/dist/resources/docs/agent-behavior.md +393 -0
  32. package/dist/resources/docs/crm-integration.md +535 -0
  33. package/dist/resources/docs/files-and-uploads.md +295 -0
  34. package/dist/resources/docs/knowledge-base.md +521 -0
  35. package/dist/resources/docs/pipeline-builder.md +221 -0
  36. package/dist/resources/docs/pipeline-settings-deep.md +221 -0
  37. package/dist/resources/docs/platforms.md +513 -0
  38. package/dist/resources/docs/prompt-anatomy.md +298 -0
  39. package/dist/resources/docs/prompt-principles.md +390 -0
  40. package/dist/resources/registry.js +34 -12
  41. package/dist/resources/registry.js.map +1 -1
  42. package/dist/resources/workflows/compare-models.md +46 -0
  43. package/dist/resources/workflows/connect-crm-from-scratch.md +89 -0
  44. package/dist/resources/workflows/connect-datasource-from-scratch.md +92 -0
  45. package/dist/resources/workflows/extract-from-document.md +36 -0
  46. package/dist/resources/workflows/iterate-with-sandbox.md +31 -0
  47. package/dist/resources/workflows/platform-setup-from-scratch.md +113 -0
  48. package/dist/resources/workflows/production-readiness-check.md +41 -0
  49. package/dist/schemas/mcp-tools.json +2638 -184
  50. package/dist/server.js +2 -0
  51. package/dist/server.js.map +1 -1
  52. package/dist/tools/definitions/agent-design.d.ts +215 -0
  53. package/dist/tools/definitions/agent-design.js +644 -0
  54. package/dist/tools/definitions/agent-design.js.map +1 -0
  55. package/dist/tools/definitions/crm-platform.d.ts +211 -0
  56. package/dist/tools/definitions/crm-platform.js +1070 -0
  57. package/dist/tools/definitions/crm-platform.js.map +1 -0
  58. package/dist/tools/definitions/datasource.d.ts +40 -0
  59. package/dist/tools/definitions/datasource.js +196 -0
  60. package/dist/tools/definitions/datasource.js.map +1 -0
  61. package/dist/tools/definitions/knowledge.d.ts +215 -0
  62. package/dist/tools/definitions/knowledge.js +782 -0
  63. package/dist/tools/definitions/knowledge.js.map +1 -0
  64. package/dist/tools/definitions/model-comparison.d.ts +25 -0
  65. package/dist/tools/definitions/model-comparison.js +101 -0
  66. package/dist/tools/definitions/model-comparison.js.map +1 -0
  67. package/dist/tools/definitions/platform-setup.d.ts +412 -0
  68. package/dist/tools/definitions/platform-setup.js +741 -0
  69. package/dist/tools/definitions/platform-setup.js.map +1 -0
  70. package/dist/tools/definitions/session.d.ts +11 -0
  71. package/dist/tools/definitions/session.js +86 -0
  72. package/dist/tools/definitions/session.js.map +1 -0
  73. package/dist/tools/definitions/shared.d.ts +742 -0
  74. package/dist/tools/definitions/shared.js +773 -0
  75. package/dist/tools/definitions/shared.js.map +1 -0
  76. package/dist/tools/definitions.d.ts +873 -88
  77. package/dist/tools/definitions.js +14 -856
  78. package/dist/tools/definitions.js.map +1 -1
  79. package/dist/tools/registry.d.ts +3 -1
  80. package/dist/tools/registry.js +90 -11
  81. package/dist/tools/registry.js.map +1 -1
  82. package/dist/tools/result.d.ts +1 -1
  83. package/dist/tools/result.js +12 -4
  84. package/dist/tools/result.js.map +1 -1
  85. package/dist/utils/logger.js +2 -1
  86. package/dist/utils/logger.js.map +1 -1
  87. package/docs/host-setup.md +34 -15
  88. package/package.json +2 -2
  89. package/scripts/install-claude-desktop.js +89 -11
  90. package/scripts/mock-api-server.js +1 -1
  91. package/scripts/mock-credentials.js +49 -6
  92. package/dist/types/api-contract.gen.d.ts +0 -6975
  93. package/dist/types/api-contract.gen.js +0 -6
  94. package/dist/types/api-contract.gen.js.map +0 -1
@@ -0,0 +1,644 @@
1
+ import { z } from 'zod';
2
+ import { analysisModeSchema, anyObjectSchema, buildListQuery, compactMetadata, compactObject, defineTool, generatedScenarioSchema, icpAnalysisPersonaSchema, icpAnalysisSegmentSchema, optionalAnyObjectSchema, outcomeSchema, promptAnalysisStageOutputSchema, promptGenerationStageOutputSchema, sandboxFindingSchema, simulationFindingSchema, uuidSchema, withInstructions, } from './shared.js';
3
+ export const agentDesignTools = [
4
+ defineTool({
5
+ name: 'besales_icp_create',
6
+ requiredFields: ['name'],
7
+ defaultWorkspaceId: true,
8
+ schema: z.object({
9
+ workspace_id: uuidSchema.optional(),
10
+ name: z.string(),
11
+ description: z.string().optional(),
12
+ source: z
13
+ .enum(['from_dialogues', 'from_files', 'from_scratch'])
14
+ .default('from_scratch'),
15
+ }),
16
+ createRequest: (input) => ({
17
+ path: `/workspaces/${input.workspace_id}/icp`,
18
+ body: compactObject({
19
+ name: input.name,
20
+ description: input.description,
21
+ source: { type: input.source },
22
+ }),
23
+ }),
24
+ }),
25
+ defineTool({
26
+ name: 'besales_icp_import_dialogues',
27
+ requiredFields: ['icp_id'],
28
+ schema: z
29
+ .object({
30
+ icp_id: uuidSchema,
31
+ /**
32
+ * mode='text' (default) — импорт сохранённых текстовых диалогов из CRM history.
33
+ * mode='audio' — batch audio path через transcription-service: тянем call recordings
34
+ * из источника (amocrm_leads / xlsx_upload / onlinepbx_direct), прогоняем через
35
+ * Yandex SpeechKit STT, создаём IcpDialogueSample из транскрипта.
36
+ */
37
+ mode: z.enum(['text', 'audio']).default('text'),
38
+ // --- Text mode (legacy CRM history) ---
39
+ crm_connection_id: uuidSchema.optional(),
40
+ outcome_filter: z.array(outcomeSchema).default(['won', 'lost']),
41
+ days_ago: z.number().int().min(1).max(730).default(180),
42
+ anonymize: z.boolean().default(true),
43
+ gdpr_confirmed: z.boolean().optional(),
44
+ // --- Audio mode (Phase 4 + Track B onlinePBX) ---
45
+ audio_source_type: z
46
+ .enum(['amocrm_leads', 'xlsx_upload', 'onlinepbx_direct', 'bitrix_openlines'])
47
+ .optional(),
48
+ /**
49
+ * Конфиг источника аудио — shape зависит от audio_source_type:
50
+ * - amocrm_leads: { crmConnectionId, leadIds[], defaultOutcome? }
51
+ * - xlsx_upload: { storedFileId, crmConnectionId } (xlsx загрузи через POST /v2/files)
52
+ * - onlinepbx_direct: { startDate, endDate, minDurationSec?=60, direction?='all',
53
+ * matchToCrm?=true, crmConnectionId?, defaultOutcome?='unknown',
54
+ * dryRun?=false, trunkId? } — звонки из onlinePBX за период,
55
+ * опц. матчинг к AmoCRM по телефону → outcome. dryRun=true →
56
+ * только подсчёт (status=DRY_RUN, totalRefs=count) без запуска STT.
57
+ * - bitrix_openlines: { crmConnectionId, startDate, endDate, categoryId?, dryRun? } —
58
+ * ТЕКСТОВЫЕ диалоги из Bitrix open-lines (сделки за период), без STT.
59
+ * NB: xlsx_drive (Google Drive) НЕ поддерживается бэкендом (MVP) — backend → 400.
60
+ */
61
+ audio_source_config: optionalAnyObjectSchema,
62
+ language: z.enum(['ru-RU', 'uz-UZ', 'kk-KZ', 'auto']).optional(),
63
+ })
64
+ .superRefine((value, ctx) => {
65
+ if (value.mode === 'audio') {
66
+ if (!value.audio_source_type || !value.audio_source_config) {
67
+ ctx.addIssue({
68
+ code: z.ZodIssueCode.custom,
69
+ message: 'audio_source_type и audio_source_config обязательны при mode=audio',
70
+ path: ['audio_source_type'],
71
+ });
72
+ }
73
+ }
74
+ else {
75
+ if (!value.crm_connection_id || value.gdpr_confirmed !== true) {
76
+ ctx.addIssue({
77
+ code: z.ZodIssueCode.custom,
78
+ message: 'crm_connection_id и gdpr_confirmed обязательны при mode=text',
79
+ path: ['crm_connection_id'],
80
+ });
81
+ }
82
+ }
83
+ }),
84
+ createRequest: (input) => {
85
+ if (input.mode === 'audio') {
86
+ return {
87
+ method: 'POST',
88
+ path: `/icp/audio-import-runs`,
89
+ body: compactObject({
90
+ icpProfileId: input.icp_id,
91
+ sourceType: input.audio_source_type,
92
+ sourceConfig: input.audio_source_config,
93
+ language: input.language,
94
+ }),
95
+ };
96
+ }
97
+ return {
98
+ path: `/icp/${input.icp_id}/samples/import-from-crm`,
99
+ body: {
100
+ crmConnectionId: input.crm_connection_id,
101
+ outcomeFilter: input.outcome_filter,
102
+ ageFilter: { daysAgo: input.days_ago },
103
+ anonymize: input.anonymize,
104
+ gdprConfirmed: input.gdpr_confirmed,
105
+ },
106
+ };
107
+ },
108
+ enhanceResponse: (response, input) => {
109
+ if (input.mode === 'audio') {
110
+ return withInstructions(response, [
111
+ 'Audio import — асинхронный. Получи runId из response.',
112
+ 'onlinepbx_direct + dryRun=true → response.status=DRY_RUN, totalRefs=число звонков ' +
113
+ 'после фильтра (Run НЕ создан). Подтверди объём и повтори с dryRun=false для импорта.',
114
+ 'Опрашивай статус через besales_icp_import_status каждые 30-60 сек.',
115
+ 'Терминальные статусы: COMPLETED, PARTIAL, FAILED.',
116
+ 'При PARTIAL — часть items expired/failed, но успешные диалоги уже в IcpDialogueSample.',
117
+ ]);
118
+ }
119
+ return response;
120
+ },
121
+ }),
122
+ defineTool({
123
+ name: 'besales_icp_import_status',
124
+ requiredFields: ['run_id'],
125
+ schema: z.object({
126
+ run_id: uuidSchema,
127
+ }),
128
+ createRequest: (input) => ({
129
+ method: 'GET',
130
+ path: `/icp/audio-import-runs/${input.run_id}`,
131
+ }),
132
+ }),
133
+ defineTool({
134
+ name: 'besales_icp_analysis_get_instructions',
135
+ requiredFields: ['icp_profile_id'],
136
+ defaultWorkspaceId: true,
137
+ schema: z.object({
138
+ workspace_id: uuidSchema.optional(),
139
+ icp_profile_id: uuidSchema,
140
+ business_context: optionalAnyObjectSchema,
141
+ }),
142
+ createRequest: (input) => ({
143
+ path: `/workspaces/${input.workspace_id}/icp/instructions`,
144
+ body: compactObject({
145
+ icpProfileId: input.icp_profile_id,
146
+ businessContext: input.business_context,
147
+ }),
148
+ }),
149
+ enhanceResponse: (response) => withInstructions(response, [
150
+ 'Выполни 3 stages ICP analysis локально: segment_clustering, classification, persona_generation.',
151
+ 'Используй returned schemas для structured output и не меняй operationId.',
152
+ 'Для каждого нового segment укажи валидный UUID id; persona.segment_id должен точно совпадать с существующим segment id или UUID из segments[].id.',
153
+ 'После всех stages вызови besales_icp_analysis_submit с segments и personas.',
154
+ ]),
155
+ }),
156
+ defineTool({
157
+ name: 'besales_icp_analysis_submit',
158
+ requiredFields: ['operation_id', 'icp_profile_id', 'segments', 'personas'],
159
+ defaultWorkspaceId: true,
160
+ schema: z.object({
161
+ workspace_id: uuidSchema.optional(),
162
+ operation_id: uuidSchema,
163
+ icp_profile_id: uuidSchema,
164
+ segments: z.array(icpAnalysisSegmentSchema),
165
+ personas: z.array(icpAnalysisPersonaSchema),
166
+ }),
167
+ createRequest: (input) => ({
168
+ path: `/workspaces/${input.workspace_id}/icp/external-submit`,
169
+ body: {
170
+ operationId: input.operation_id,
171
+ icpProfileId: input.icp_profile_id,
172
+ segments: input.segments.map((segment) => compactObject({
173
+ id: segment.id,
174
+ name: segment.name,
175
+ description: segment.description,
176
+ demographics: segment.demographics,
177
+ pains: segment.pains,
178
+ motivations: segment.motivations,
179
+ languageStyle: segment.language_style,
180
+ })),
181
+ personas: input.personas.map((persona) => compactObject({
182
+ name: persona.name,
183
+ segmentId: persona.segment_id,
184
+ description: persona.description,
185
+ painPoints: persona.pain_points,
186
+ goals: persona.goals,
187
+ objections: persona.objections,
188
+ messagingHints: persona.messaging_hints,
189
+ })),
190
+ },
191
+ }),
192
+ restartToolName: 'besales_icp_analysis_get_instructions',
193
+ }),
194
+ defineTool({
195
+ name: 'besales_icp_list',
196
+ requiredFields: [],
197
+ defaultWorkspaceId: true,
198
+ schema: z.object({
199
+ workspace_id: uuidSchema.optional(),
200
+ limit: z.number().int().min(1).max(100).optional(),
201
+ cursor: z.string().optional(),
202
+ }),
203
+ createRequest: (input) => ({
204
+ method: 'GET',
205
+ path: `/workspaces/${input.workspace_id}/icp${buildListQuery({ limit: input.limit, cursor: input.cursor })}`,
206
+ }),
207
+ }),
208
+ defineTool({
209
+ name: 'besales_icp_get',
210
+ requiredFields: ['icp_id'],
211
+ schema: z.object({
212
+ icp_id: uuidSchema,
213
+ }),
214
+ createRequest: (input) => ({
215
+ method: 'GET',
216
+ path: `/icp/${input.icp_id}`,
217
+ }),
218
+ }),
219
+ defineTool({
220
+ name: 'besales_icp_scenarios_list',
221
+ requiredFields: ['icp_id'],
222
+ schema: z.object({
223
+ icp_id: uuidSchema,
224
+ }),
225
+ createRequest: (input) => ({
226
+ method: 'GET',
227
+ path: `/icp/${input.icp_id}/scenarios`,
228
+ }),
229
+ }),
230
+ defineTool({
231
+ name: 'besales_icp_sample_messages',
232
+ requiredFields: ['sample_id'],
233
+ schema: z.object({
234
+ sample_id: uuidSchema,
235
+ }),
236
+ createRequest: (input) => ({
237
+ method: 'GET',
238
+ path: `/samples/${input.sample_id}/messages`,
239
+ }),
240
+ }),
241
+ defineTool({
242
+ name: 'besales_prompt_generate_get_instructions',
243
+ requiredFields: ['agent_id'],
244
+ schema: z.object({
245
+ agent_id: uuidSchema,
246
+ icp_profile_id: uuidSchema.optional(),
247
+ business_context: optionalAnyObjectSchema,
248
+ style_hints: z
249
+ .object({
250
+ formality: z.enum(['formal', 'casual', 'friendly']).optional(),
251
+ verbosity: z.enum(['concise', 'balanced', 'detailed']).optional(),
252
+ // Язык РАССУЖДЕНИЯ стадий генерации (ru/en) — НЕ язык итогового промпта.
253
+ // Язык промпта = то, что ты пишешь в final_content (узбекский и т.д.).
254
+ language: z.enum(['ru', 'en']).default('ru'),
255
+ message_direction: z.enum(['INBOUND', 'OUTBOUND']).optional(),
256
+ })
257
+ .optional(),
258
+ }),
259
+ createRequest: (input) => ({
260
+ path: `/agents/${input.agent_id}/prompt/generate/instructions`,
261
+ body: compactObject({
262
+ sourceType: input.icp_profile_id ? 'icp_full' : 'business_context_only',
263
+ icpProfileId: input.icp_profile_id,
264
+ businessContext: input.business_context,
265
+ styleHints: input.style_hints
266
+ ? compactObject({
267
+ formality: input.style_hints.formality,
268
+ verbosity: input.style_hints.verbosity,
269
+ language: input.style_hints.language,
270
+ messageDirection: input.style_hints.message_direction,
271
+ })
272
+ : undefined,
273
+ }),
274
+ }),
275
+ enhanceResponse: (response) => withInstructions(response, [
276
+ 'Выполни 4 stages prompt generation локально: structure_builder, industry_validator, prompt_tester, finalizer.',
277
+ 'Каждая stage должна вернуть JSON по своей schema. Финальный compiled prompt положи в final_content.',
278
+ 'Язык итогового промпта = содержимое final_content: пиши его на языке бота (узбекский, казахский и т.д.). style_hints.language (ru/en) задаёт лишь язык рассуждения стадий, не язык промпта.',
279
+ 'После stages вызови besales_prompt_generate_submit с stages, final_content и metadata.',
280
+ ]),
281
+ }),
282
+ defineTool({
283
+ name: 'besales_prompt_generate_submit',
284
+ requiredFields: ['agent_id', 'operation_id', 'stages', 'final_content'],
285
+ schema: z.object({
286
+ agent_id: uuidSchema,
287
+ operation_id: uuidSchema,
288
+ stages: z.array(promptGenerationStageOutputSchema).min(4),
289
+ final_content: z.string(),
290
+ metadata: z
291
+ .object({
292
+ total_tokens: z.number().int().optional(),
293
+ models: z.record(z.string(), z.string()).optional(),
294
+ })
295
+ .optional(),
296
+ }),
297
+ createRequest: (input) => ({
298
+ path: `/agents/${input.agent_id}/prompt/generate/${input.operation_id}/submit`,
299
+ body: compactObject({
300
+ stages: input.stages,
301
+ finalContent: input.final_content,
302
+ metadata: compactMetadata(input.metadata),
303
+ }),
304
+ }),
305
+ restartToolName: 'besales_prompt_generate_get_instructions',
306
+ }),
307
+ defineTool({
308
+ name: 'besales_prompt_analyze_get_instructions',
309
+ requiredFields: ['agent_id', 'version_id'],
310
+ schema: z.object({
311
+ agent_id: uuidSchema,
312
+ version_id: uuidSchema,
313
+ modes: z.array(analysisModeSchema).default(['grammar', 'structure', 'contradictions']),
314
+ }),
315
+ createRequest: (input) => ({
316
+ path: `/agents/${input.agent_id}/prompt/analyze/instructions`,
317
+ body: {
318
+ versionId: input.version_id,
319
+ modes: input.modes,
320
+ },
321
+ }),
322
+ enhanceResponse: (response) => withInstructions(response, [
323
+ 'Выполни static analysis stages локально: grammar, industry, structure, aggregation.',
324
+ 'Собери итоговый список issues без дублей и с severity.',
325
+ 'После анализа вызови besales_prompt_analyze_submit с aggregated_issues.',
326
+ ]),
327
+ }),
328
+ defineTool({
329
+ name: 'besales_prompt_analyze_submit',
330
+ requiredFields: ['agent_id', 'operation_id', 'stages', 'aggregated_issues'],
331
+ schema: z.object({
332
+ agent_id: uuidSchema,
333
+ operation_id: uuidSchema,
334
+ stages: z.array(promptAnalysisStageOutputSchema).min(4),
335
+ aggregated_issues: z.array(anyObjectSchema),
336
+ }),
337
+ createRequest: (input) => ({
338
+ path: `/agents/${input.agent_id}/prompt/analyze/${input.operation_id}/submit`,
339
+ body: {
340
+ stages: input.stages,
341
+ aggregatedIssues: input.aggregated_issues,
342
+ },
343
+ }),
344
+ restartToolName: 'besales_prompt_analyze_get_instructions',
345
+ }),
346
+ defineTool({
347
+ name: 'besales_prompt_finalize',
348
+ requiredFields: ['agent_id', 'draft_version_id'],
349
+ schema: z.object({
350
+ agent_id: uuidSchema,
351
+ draft_version_id: uuidSchema,
352
+ changelog_note: z.string().optional(),
353
+ }),
354
+ createRequest: (input) => ({
355
+ path: `/agents/${input.agent_id}/prompt/approve`,
356
+ body: compactObject({
357
+ draftVersionId: input.draft_version_id,
358
+ changelogNote: input.changelog_note,
359
+ }),
360
+ }),
361
+ enhanceResponse: (response) => withInstructions(response, [
362
+ 'Промпт активирован. Перед запуском проверь 3 вещи: 1) greeting — besales_behavior_update.greeting, замени дефолтный «Привет!/Hello» на язык аудитории текстом, БЕЗ кнопок (greeting_buttons — лишь по явному запросу); для INBOUND именно оно открывает диалог; 2) knowledge привязан к каналу; 3) прогон besales_sandbox_run_start.',
363
+ ]),
364
+ }),
365
+ defineTool({
366
+ name: 'besales_sandbox_run_start',
367
+ requiredFields: ['agent_id'],
368
+ schema: z.object({
369
+ agent_id: uuidSchema,
370
+ scenario_ids: z.array(uuidSchema).optional(),
371
+ options: z
372
+ .object({
373
+ mode: z.enum(['single_agent', 'workflow']).default('single_agent'),
374
+ client_mode: z.enum(['scripted', 'simulated']).default('scripted'),
375
+ simulation: z
376
+ .object({
377
+ max_turns: z.number().int().min(1).max(30).optional(),
378
+ })
379
+ .optional(),
380
+ check_routing: z.boolean().default(false),
381
+ check_pipeline_transitions: z.boolean().default(false),
382
+ check_agent_actions: z.boolean().default(false),
383
+ run_rag_golden_tests: z.boolean().default(false),
384
+ turns_per_scenario: z.number().int().min(1).max(50).default(10),
385
+ })
386
+ .optional(),
387
+ }),
388
+ createRequest: (input) => ({
389
+ path: `/agents/${input.agent_id}/sandbox-runs`,
390
+ body: compactObject({
391
+ scenarioIds: input.scenario_ids,
392
+ options: input.options
393
+ ? {
394
+ mode: input.options.mode,
395
+ clientMode: input.options.client_mode,
396
+ simulation: input.options.simulation
397
+ ? { maxTurns: input.options.simulation.max_turns }
398
+ : undefined,
399
+ checkRouting: input.options.check_routing,
400
+ checkPipelineTransitions: input.options.check_pipeline_transitions,
401
+ checkAgentActions: input.options.check_agent_actions,
402
+ runRagGoldenTests: input.options.run_rag_golden_tests,
403
+ turnsPerScenario: input.options.turns_per_scenario,
404
+ }
405
+ : undefined,
406
+ }),
407
+ }),
408
+ }),
409
+ defineTool({
410
+ name: 'besales_sandbox_findings_get_instructions',
411
+ requiredFields: ['agent_id', 'run_id'],
412
+ schema: z.object({
413
+ agent_id: uuidSchema,
414
+ run_id: uuidSchema,
415
+ }),
416
+ createRequest: (input) => ({
417
+ path: `/agents/${input.agent_id}/sandbox/runs/${input.run_id}/findings/instructions`,
418
+ }),
419
+ enhanceResponse: (response) => withInstructions(response, [
420
+ 'Проанализируй sandbox report локально и выдели structured findings.',
421
+ 'Сгруппируй проблемы по scenario/turn/category/severity и предложи actionable fix.',
422
+ 'Если клиент в simulated-прогоне ушёл с outcome "refused" или endReason "gave_up" — ' +
423
+ 'это не обязательно ошибка агента; оцени по тексту диалога, отработал ли агент корректно.',
424
+ 'После анализа вызови besales_sandbox_findings_submit.',
425
+ ]),
426
+ }),
427
+ defineTool({
428
+ name: 'besales_sandbox_findings_submit',
429
+ requiredFields: ['agent_id', 'run_id', 'operation_id', 'findings'],
430
+ schema: z.object({
431
+ agent_id: uuidSchema,
432
+ run_id: uuidSchema,
433
+ operation_id: uuidSchema,
434
+ findings: z.array(sandboxFindingSchema),
435
+ }),
436
+ createRequest: (input) => ({
437
+ path: `/agents/${input.agent_id}/sandbox/runs/${input.run_id}/findings/${input.operation_id}/submit`,
438
+ body: {
439
+ findings: input.findings.map((finding) => compactObject({
440
+ scenarioId: finding.scenario_id,
441
+ category: finding.category,
442
+ severity: finding.severity,
443
+ message: finding.message,
444
+ suggestion: finding.suggestion,
445
+ turnIndex: finding.turn_index,
446
+ })),
447
+ },
448
+ }),
449
+ restartToolName: 'besales_sandbox_findings_get_instructions',
450
+ }),
451
+ defineTool({
452
+ name: 'besales_simulation_findings_get_instructions',
453
+ requiredFields: ['agent_id', 'simulation_id'],
454
+ schema: z.object({
455
+ agent_id: uuidSchema,
456
+ simulation_id: uuidSchema,
457
+ }),
458
+ createRequest: (input) => ({
459
+ path: `/agents/${input.agent_id}/prompt/simulate-findings/instructions`,
460
+ body: {
461
+ simulationId: input.simulation_id,
462
+ },
463
+ }),
464
+ enhanceResponse: (response) => withInstructions(response, [
465
+ 'Проанализируй simulation dialogues локально и найди hallucination, tone, off-topic и action issues.',
466
+ 'Не отправляй raw simulation_id в submit body: он используется только для выбора route/context.',
467
+ 'После анализа вызови besales_simulation_findings_submit.',
468
+ ]),
469
+ }),
470
+ defineTool({
471
+ name: 'besales_simulation_findings_submit',
472
+ requiredFields: ['agent_id', 'operation_id', 'findings'],
473
+ schema: z.object({
474
+ agent_id: uuidSchema,
475
+ // Принимается для непрерывности flow, но НЕ обязателен и не отправляется:
476
+ // backend восстанавливает simulationId из operation.referenceId по operation_id.
477
+ simulation_id: uuidSchema.optional(),
478
+ operation_id: uuidSchema,
479
+ findings: z.array(simulationFindingSchema),
480
+ }),
481
+ createRequest: (input) => ({
482
+ path: `/agents/${input.agent_id}/prompt/simulate-findings/${input.operation_id}/submit`,
483
+ body: {
484
+ findings: input.findings.map((finding) => compactObject({
485
+ dialogueId: finding.dialogue_id,
486
+ category: finding.category,
487
+ severity: finding.severity,
488
+ message: finding.message,
489
+ suggestion: finding.suggestion,
490
+ referenceMessageIndex: finding.reference_message_index,
491
+ })),
492
+ },
493
+ }),
494
+ restartToolName: 'besales_simulation_findings_get_instructions',
495
+ }),
496
+ defineTool({
497
+ name: 'besales_qa_generation_get_instructions',
498
+ requiredFields: ['agent_id'],
499
+ schema: z.object({
500
+ agent_id: uuidSchema,
501
+ namespace_context: z.string().optional(),
502
+ company_context: z.string().optional(),
503
+ icp_profile_id: uuidSchema.optional(),
504
+ target_count: z.number().int().min(5).max(100).default(30),
505
+ }),
506
+ createRequest: (input) => ({
507
+ path: `/agents/${input.agent_id}/knowledge/qa-generation/instructions`,
508
+ body: compactObject({
509
+ namespaceContext: input.namespace_context,
510
+ companyContext: input.company_context,
511
+ icpProfileId: input.icp_profile_id,
512
+ targetCount: input.target_count,
513
+ }),
514
+ }),
515
+ enhanceResponse: (response) => withInstructions(response, [
516
+ 'Сгенерируй Q&A pairs локально по returned schema и company/namespace context.',
517
+ 'Каждая пара должна быть пригодна для knowledge base: короткий вопрос, точный ответ, optional tags.',
518
+ 'После генерации вызови besales_qa_generation_submit с qa_pairs.',
519
+ ]),
520
+ }),
521
+ defineTool({
522
+ name: 'besales_qa_generation_submit',
523
+ requiredFields: ['agent_id', 'operation_id', 'qa_pairs'],
524
+ schema: z.object({
525
+ agent_id: uuidSchema,
526
+ operation_id: uuidSchema,
527
+ knowledge_space_id: uuidSchema.optional(),
528
+ qa_pairs: z.array(z.object({
529
+ question: z.string(),
530
+ answer: z.string(),
531
+ tags: z.array(z.string()).optional(),
532
+ })),
533
+ }),
534
+ createRequest: (input) => ({
535
+ path: `/agents/${input.agent_id}/knowledge/qa-generation/${input.operation_id}/submit`,
536
+ body: compactObject({
537
+ knowledgeSpaceId: input.knowledge_space_id,
538
+ qaPairs: input.qa_pairs,
539
+ }),
540
+ }),
541
+ restartToolName: 'besales_qa_generation_get_instructions',
542
+ }),
543
+ defineTool({
544
+ name: 'besales_test_scenario_generate_get_instructions',
545
+ requiredFields: ['icp_profile_id'],
546
+ defaultWorkspaceId: true,
547
+ schema: z.object({
548
+ workspace_id: uuidSchema.optional(),
549
+ icp_profile_id: uuidSchema,
550
+ count: z.number().int().min(1).max(20).default(5),
551
+ business_context: optionalAnyObjectSchema,
552
+ }),
553
+ createRequest: (input) => ({
554
+ path: `/workspaces/${input.workspace_id}/test-scenarios/instructions`,
555
+ body: compactObject({
556
+ icpProfileId: input.icp_profile_id,
557
+ count: input.count,
558
+ businessContext: input.business_context,
559
+ }),
560
+ }),
561
+ enhanceResponse: (response) => withInstructions(response, [
562
+ 'Выполни stage scenario_builder локально и верни структурированный JSON.',
563
+ 'Уточни у пользователя целевой режим sandbox: изолированный агент (single_agent) или полный workflow с роутером (workflow). Для workflow добавь сценарии, провоцирующие смену агента — сдвиг темы/intent в ходе диалога.',
564
+ 'Каждый scenario — короткий sandbox-готовый диалог: 1-4 turns, начинать ОБЯЗАТЕЛЬНО с role="client".',
565
+ 'segment_ids должны ссылаться только на icpContext.segments[].id; не выдумывай UUID.',
566
+ 'Покрой разные кейсы: happy path, возражение, edge case (раздражение / спешка / сомнение).',
567
+ 'После генерации вызови besales_test_scenario_generate_submit с массивом scenarios.',
568
+ ]),
569
+ }),
570
+ defineTool({
571
+ name: 'besales_test_scenario_generate_submit',
572
+ requiredFields: ['operation_id', 'icp_profile_id', 'scenarios'],
573
+ defaultWorkspaceId: true,
574
+ schema: z.object({
575
+ workspace_id: uuidSchema.optional(),
576
+ operation_id: uuidSchema,
577
+ icp_profile_id: uuidSchema,
578
+ scenarios: z.array(generatedScenarioSchema).min(1).max(20),
579
+ }),
580
+ createRequest: (input) => ({
581
+ path: `/workspaces/${input.workspace_id}/test-scenarios/external-submit`,
582
+ body: {
583
+ operationId: input.operation_id,
584
+ icpProfileId: input.icp_profile_id,
585
+ scenarios: input.scenarios.map((scenario) => compactObject({
586
+ name: scenario.name,
587
+ description: scenario.description,
588
+ segmentIds: scenario.segment_ids,
589
+ situations: scenario.situations.map((situation) => ({
590
+ role: situation.role,
591
+ text: situation.text,
592
+ })),
593
+ })),
594
+ },
595
+ }),
596
+ restartToolName: 'besales_test_scenario_generate_get_instructions',
597
+ }),
598
+ defineTool({
599
+ name: 'besales_dialog_script_get',
600
+ requiredFields: ['agent_id'],
601
+ schema: z.object({
602
+ agent_id: uuidSchema,
603
+ }),
604
+ createRequest: (input) => ({
605
+ method: 'GET',
606
+ path: `/agents/${input.agent_id}/prompt/script`,
607
+ }),
608
+ }),
609
+ defineTool({
610
+ name: 'besales_dialog_script_update',
611
+ requiredFields: ['agent_id', 'graph'],
612
+ schema: z.object({
613
+ agent_id: uuidSchema,
614
+ preamble: z.string().optional(),
615
+ graph: z.object({
616
+ stages: z.array(z.object({ id: z.string(), name: z.string() })),
617
+ nodes: z.array(z.object({
618
+ id: z.string(),
619
+ stageId: z.string(),
620
+ title: z.string(),
621
+ instruction: z.string(),
622
+ leadStateTag: z.string().nullable().optional(),
623
+ branchId: z.string(),
624
+ })),
625
+ edges: z.array(z.object({
626
+ from: z.string(),
627
+ to: z.string(),
628
+ condition: z.string().nullable().optional(),
629
+ })),
630
+ }),
631
+ }),
632
+ createRequest: (input) => ({
633
+ method: 'PUT',
634
+ path: `/agents/${input.agent_id}/prompt/dialog-script`,
635
+ body: compactObject({ preamble: input.preamble, graph: input.graph }),
636
+ }),
637
+ enhanceResponse: (response) => withInstructions(response, [
638
+ 'Скрипт-summary сохранён. §6 промпта НЕ обновляется автоматически (она независима и богаче). ' +
639
+ 'Чтобы §6 отразила скрипт — пропиши её на его основе через besales_prompt_patch_* или ' +
640
+ 'перегенерируй промпт (besales_prompt_generate_get_instructions → submit → besales_prompt_finalize).',
641
+ ]),
642
+ }),
643
+ ];
644
+ //# sourceMappingURL=agent-design.js.map