@hailer/mcp 1.1.11 → 1.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +18 -5
- package/dist/bot/bot-config.d.ts +12 -1
- package/dist/bot/bot-config.js +98 -14
- package/dist/bot/bot-manager.d.ts +13 -3
- package/dist/bot/bot-manager.js +80 -25
- package/dist/bot/bot.d.ts +46 -0
- package/dist/bot/bot.js +542 -166
- package/dist/bot/services/message-classifier.js +17 -0
- package/dist/bot/services/permission-guard.d.ts +52 -0
- package/dist/bot/services/permission-guard.js +149 -0
- package/dist/bot/services/types.d.ts +5 -0
- package/dist/bot/services/typing-indicator.d.ts +6 -1
- package/dist/bot/services/typing-indicator.js +19 -3
- package/dist/config.d.ts +6 -1
- package/dist/config.js +43 -0
- package/dist/core.js +3 -6
- package/dist/mcp/UserContextCache.d.ts +5 -0
- package/dist/mcp/UserContextCache.js +51 -19
- package/dist/mcp/hailer-clients.d.ts +19 -1
- package/dist/mcp/hailer-clients.js +157 -20
- package/dist/mcp/session-store.d.ts +68 -0
- package/dist/mcp/session-store.js +169 -0
- package/dist/mcp/signal-handler.js +12 -12
- package/dist/mcp/tool-registry.d.ts +17 -4
- package/dist/mcp/tool-registry.js +37 -7
- package/dist/mcp/tools/activity.js +99 -7
- package/dist/mcp/tools/app-scaffold.js +304 -336
- package/dist/mcp/tools/company.d.ts +9 -0
- package/dist/mcp/tools/company.js +88 -0
- package/dist/mcp/tools/discussion.js +68 -0
- package/dist/mcp/tools/workflow-permissions.d.ts +15 -0
- package/dist/mcp/tools/workflow-permissions.js +204 -0
- package/dist/mcp/tools/workflow.js +57 -18
- package/dist/mcp/utils/index.d.ts +2 -0
- package/dist/mcp/utils/index.js +12 -1
- package/dist/mcp/utils/role-utils.d.ts +74 -0
- package/dist/mcp/utils/role-utils.js +151 -0
- package/dist/mcp/utils/types.d.ts +43 -1
- package/dist/mcp/utils/types.js +14 -0
- package/dist/mcp/webhook-handler.d.ts +6 -0
- package/dist/mcp/webhook-handler.js +11 -0
- package/dist/mcp-server.d.ts +23 -2
- package/dist/mcp-server.js +639 -111
- package/dist/plugins/vipunen/client.d.ts +150 -0
- package/dist/plugins/vipunen/client.js +535 -0
- package/dist/plugins/vipunen/config/schema-config.json +19 -0
- package/dist/plugins/vipunen/config/schema-doc.json +22 -0
- package/dist/plugins/vipunen/index.d.ts +41 -0
- package/dist/plugins/vipunen/index.js +88 -0
- package/dist/plugins/vipunen/tools.d.ts +26 -0
- package/dist/plugins/vipunen/tools.js +501 -0
- package/package.json +2 -1
- package/.claude/.context-watchdog.json +0 -1
- package/.claude/.session-checked +0 -1
- package/.claude/CLAUDE.md +0 -370
- package/.claude/agents/agent-ada-skill-builder.md +0 -94
- package/.claude/agents/agent-alejandro-function-fields.md +0 -342
- package/.claude/agents/agent-bjorn-config-audit.md +0 -103
- package/.claude/agents/agent-builder-agent-creator.md +0 -130
- package/.claude/agents/agent-code-simplifier.md +0 -53
- package/.claude/agents/agent-dmitri-activity-crud.md +0 -159
- package/.claude/agents/agent-giuseppe-app-builder.md +0 -247
- package/.claude/agents/agent-gunther-mcp-tools.md +0 -39
- package/.claude/agents/agent-helga-workflow-config.md +0 -204
- package/.claude/agents/agent-igor-activity-mover-automation.md +0 -125
- package/.claude/agents/agent-ingrid-doc-templates.md +0 -261
- package/.claude/agents/agent-ivan-monolith.md +0 -154
- package/.claude/agents/agent-kenji-data-reader.md +0 -86
- package/.claude/agents/agent-lars-code-inspector.md +0 -102
- package/.claude/agents/agent-marco-mockup-builder.md +0 -110
- package/.claude/agents/agent-marcus-api-documenter.md +0 -323
- package/.claude/agents/agent-marketplace-publisher.md +0 -280
- package/.claude/agents/agent-marketplace-reviewer.md +0 -309
- package/.claude/agents/agent-permissions-handler.md +0 -208
- package/.claude/agents/agent-simple-writer.md +0 -48
- package/.claude/agents/agent-svetlana-code-review.md +0 -171
- package/.claude/agents/agent-tanya-test-runner.md +0 -333
- package/.claude/agents/agent-ui-designer.md +0 -100
- package/.claude/agents/agent-viktor-sql-insights.md +0 -212
- package/.claude/agents/agent-web-search.md +0 -55
- package/.claude/agents/agent-yevgeni-discussions.md +0 -45
- package/.claude/agents/agent-zara-zapier.md +0 -159
- package/.claude/commands/app-squad.md +0 -135
- package/.claude/commands/audit-squad.md +0 -158
- package/.claude/commands/autoplan.md +0 -563
- package/.claude/commands/cleanup-squad.md +0 -98
- package/.claude/commands/config-squad.md +0 -106
- package/.claude/commands/crud-squad.md +0 -87
- package/.claude/commands/data-squad.md +0 -97
- package/.claude/commands/debug-squad.md +0 -303
- package/.claude/commands/doc-squad.md +0 -65
- package/.claude/commands/handoff.md +0 -137
- package/.claude/commands/health.md +0 -49
- package/.claude/commands/help.md +0 -29
- package/.claude/commands/help:agents.md +0 -151
- package/.claude/commands/help:commands.md +0 -78
- package/.claude/commands/help:faq.md +0 -79
- package/.claude/commands/help:plugins.md +0 -50
- package/.claude/commands/help:skills.md +0 -93
- package/.claude/commands/help:tools.md +0 -75
- package/.claude/commands/hotfix-squad.md +0 -112
- package/.claude/commands/integration-squad.md +0 -82
- package/.claude/commands/janitor-squad.md +0 -167
- package/.claude/commands/learn-auto.md +0 -120
- package/.claude/commands/learn.md +0 -120
- package/.claude/commands/mcp-list.md +0 -27
- package/.claude/commands/onboard-squad.md +0 -140
- package/.claude/commands/plan-workspace.md +0 -732
- package/.claude/commands/prd.md +0 -130
- package/.claude/commands/project-status.md +0 -82
- package/.claude/commands/publish.md +0 -138
- package/.claude/commands/recap.md +0 -69
- package/.claude/commands/restore.md +0 -64
- package/.claude/commands/review-squad.md +0 -152
- package/.claude/commands/save.md +0 -24
- package/.claude/commands/stats.md +0 -19
- package/.claude/commands/swarm.md +0 -210
- package/.claude/commands/tool-builder.md +0 -39
- package/.claude/commands/ws-pull.md +0 -44
- package/.claude/hooks/_shared-memory.cjs +0 -305
- package/.claude/hooks/_utils.cjs +0 -108
- package/.claude/hooks/agent-failure-detector.cjs +0 -383
- package/.claude/hooks/agent-usage-logger.cjs +0 -204
- package/.claude/hooks/app-edit-guard.cjs +0 -494
- package/.claude/hooks/auto-learn.cjs +0 -304
- package/.claude/hooks/bash-guard.cjs +0 -272
- package/.claude/hooks/builder-mode-manager.cjs +0 -354
- package/.claude/hooks/bulk-activity-guard.cjs +0 -271
- package/.claude/hooks/context-watchdog.cjs +0 -230
- package/.claude/hooks/delegation-reminder.cjs +0 -465
- package/.claude/hooks/design-system-lint.cjs +0 -271
- package/.claude/hooks/post-scaffold-hook.cjs +0 -181
- package/.claude/hooks/prompt-guard.cjs +0 -354
- package/.claude/hooks/publish-template-guard.cjs +0 -147
- package/.claude/hooks/session-start.cjs +0 -35
- package/.claude/hooks/shared-memory-writer.cjs +0 -147
- package/.claude/hooks/skill-injector.cjs +0 -140
- package/.claude/hooks/skill-usage-logger.cjs +0 -258
- package/.claude/hooks/src-edit-guard.cjs +0 -240
- package/.claude/hooks/sync-marketplace-agents.cjs +0 -346
- package/.claude/settings.json +0 -257
- package/.claude/skills/SDK-activity-patterns/SKILL.md +0 -428
- package/.claude/skills/SDK-document-templates/SKILL.md +0 -1033
- package/.claude/skills/SDK-function-fields/SKILL.md +0 -542
- package/.claude/skills/SDK-generate-skill/SKILL.md +0 -92
- package/.claude/skills/SDK-init-skill/SKILL.md +0 -127
- package/.claude/skills/SDK-insight-queries/SKILL.md +0 -787
- package/.claude/skills/SDK-ws-config-skill/SKILL.md +0 -1139
- package/.claude/skills/agent-structure/SKILL.md +0 -98
- package/.claude/skills/api-documentation-patterns/SKILL.md +0 -474
- package/.claude/skills/chrome-mcp-reference/SKILL.md +0 -370
- package/.claude/skills/delegation-routing/SKILL.md +0 -202
- package/.claude/skills/frontend-design/SKILL.md +0 -254
- package/.claude/skills/hailer-activity-mover/SKILL.md +0 -213
- package/.claude/skills/hailer-api-client/SKILL.md +0 -518
- package/.claude/skills/hailer-app-builder/SKILL.md +0 -1434
- package/.claude/skills/hailer-apps-pictures/SKILL.md +0 -269
- package/.claude/skills/hailer-design-system/SKILL.md +0 -235
- package/.claude/skills/hailer-monolith-automations/SKILL.md +0 -686
- package/.claude/skills/hailer-permissions-system/SKILL.md +0 -121
- package/.claude/skills/hailer-project-protocol/SKILL.md +0 -488
- package/.claude/skills/hailer-rest-api/SKILL.md +0 -61
- package/.claude/skills/hailer-rest-api/hailer-activities.md +0 -184
- package/.claude/skills/hailer-rest-api/hailer-admin.md +0 -473
- package/.claude/skills/hailer-rest-api/hailer-calendar.md +0 -256
- package/.claude/skills/hailer-rest-api/hailer-feed.md +0 -249
- package/.claude/skills/hailer-rest-api/hailer-insights.md +0 -195
- package/.claude/skills/hailer-rest-api/hailer-messaging.md +0 -276
- package/.claude/skills/hailer-rest-api/hailer-workflows.md +0 -283
- package/.claude/skills/insight-join-patterns/SKILL.md +0 -174
- package/.claude/skills/integration-patterns/SKILL.md +0 -421
- package/.claude/skills/json-only-output/SKILL.md +0 -72
- package/.claude/skills/lsp-setup/SKILL.md +0 -160
- package/.claude/skills/mcp-direct-tools/SKILL.md +0 -153
- package/.claude/skills/optional-parameters/SKILL.md +0 -72
- package/.claude/skills/publish-hailer-app/SKILL.md +0 -244
- package/.claude/skills/testing-patterns/SKILL.md +0 -630
- package/.claude/skills/tool-builder/SKILL.md +0 -250
- package/.claude/skills/tool-parameter-usage/SKILL.md +0 -126
- package/.claude/skills/tool-response-verification/SKILL.md +0 -92
- package/.claude/skills/zapier-hailer-patterns/SKILL.md +0 -581
- package/.hailer-mcp-port +0 -1
- package/.mcp.json +0 -13
- package/.opencode/agent/agent-ada-skill-builder.md +0 -35
- package/.opencode/agent/agent-alejandro-function-fields.md +0 -39
- package/.opencode/agent/agent-bjorn-config-audit.md +0 -36
- package/.opencode/agent/agent-builder-agent-creator.md +0 -39
- package/.opencode/agent/agent-code-simplifier.md +0 -31
- package/.opencode/agent/agent-dmitri-activity-crud.md +0 -40
- package/.opencode/agent/agent-giuseppe-app-builder.md +0 -37
- package/.opencode/agent/agent-gunther-mcp-tools.md +0 -39
- package/.opencode/agent/agent-helga-workflow-config.md +0 -204
- package/.opencode/agent/agent-igor-activity-mover-automation.md +0 -46
- package/.opencode/agent/agent-ingrid-doc-templates.md +0 -39
- package/.opencode/agent/agent-ivan-monolith.md +0 -46
- package/.opencode/agent/agent-kenji-data-reader.md +0 -53
- package/.opencode/agent/agent-lars-code-inspector.md +0 -28
- package/.opencode/agent/agent-marco-mockup-builder.md +0 -42
- package/.opencode/agent/agent-marcus-api-documenter.md +0 -53
- package/.opencode/agent/agent-marketplace-publisher.md +0 -44
- package/.opencode/agent/agent-marketplace-reviewer.md +0 -42
- package/.opencode/agent/agent-permissions-handler.md +0 -50
- package/.opencode/agent/agent-simple-writer.md +0 -45
- package/.opencode/agent/agent-svetlana-code-review.md +0 -39
- package/.opencode/agent/agent-tanya-test-runner.md +0 -57
- package/.opencode/agent/agent-ui-designer.md +0 -56
- package/.opencode/agent/agent-viktor-sql-insights.md +0 -34
- package/.opencode/agent/agent-web-search.md +0 -42
- package/.opencode/agent/agent-yevgeni-discussions.md +0 -37
- package/.opencode/agent/agent-zara-zapier.md +0 -53
- package/.opencode/commands/app-squad.md +0 -135
- package/.opencode/commands/audit-squad.md +0 -158
- package/.opencode/commands/autoplan.md +0 -563
- package/.opencode/commands/cleanup-squad.md +0 -98
- package/.opencode/commands/config-squad.md +0 -106
- package/.opencode/commands/crud-squad.md +0 -87
- package/.opencode/commands/data-squad.md +0 -97
- package/.opencode/commands/debug-squad.md +0 -303
- package/.opencode/commands/doc-squad.md +0 -65
- package/.opencode/commands/handoff.md +0 -137
- package/.opencode/commands/health.md +0 -49
- package/.opencode/commands/help-agents.md +0 -151
- package/.opencode/commands/help-commands.md +0 -32
- package/.opencode/commands/help-faq.md +0 -29
- package/.opencode/commands/help-plugins.md +0 -28
- package/.opencode/commands/help-skills.md +0 -7
- package/.opencode/commands/help-tools.md +0 -40
- package/.opencode/commands/help.md +0 -28
- package/.opencode/commands/hotfix-squad.md +0 -112
- package/.opencode/commands/integration-squad.md +0 -82
- package/.opencode/commands/janitor-squad.md +0 -167
- package/.opencode/commands/learn-auto.md +0 -120
- package/.opencode/commands/learn.md +0 -120
- package/.opencode/commands/mcp-list.md +0 -27
- package/.opencode/commands/onboard-squad.md +0 -140
- package/.opencode/commands/plan-workspace.md +0 -732
- package/.opencode/commands/prd.md +0 -131
- package/.opencode/commands/project-status.md +0 -82
- package/.opencode/commands/publish.md +0 -138
- package/.opencode/commands/recap.md +0 -69
- package/.opencode/commands/restore.md +0 -64
- package/.opencode/commands/review-squad.md +0 -152
- package/.opencode/commands/save.md +0 -24
- package/.opencode/commands/stats.md +0 -19
- package/.opencode/commands/swarm.md +0 -210
- package/.opencode/commands/tool-builder.md +0 -39
- package/.opencode/commands/ws-pull.md +0 -44
- package/.opencode/opencode.json +0 -21
- package/inbox/failures.log +0 -1
- package/inbox/usage.jsonl +0 -4
- package/scripts/postinstall.cjs +0 -64
- package/scripts/test-hal-tools.ts +0 -154
package/dist/app.js
CHANGED
|
@@ -8,9 +8,13 @@ const file_1 = require("./mcp/tools/file");
|
|
|
8
8
|
const activity_1 = require("./mcp/tools/activity");
|
|
9
9
|
const discussion_1 = require("./mcp/tools/discussion");
|
|
10
10
|
const user_1 = require("./mcp/tools/user");
|
|
11
|
+
const company_1 = require("./mcp/tools/company");
|
|
11
12
|
const workflow_1 = require("./mcp/tools/workflow");
|
|
12
13
|
const insight_1 = require("./mcp/tools/insight");
|
|
14
|
+
const workflow_permissions_1 = require("./mcp/tools/workflow-permissions");
|
|
13
15
|
const app_1 = require("./mcp/tools/app");
|
|
16
|
+
// Vipunen plugin — Weaviate RAG knowledge base (conditional on WEAVIATE_HOST)
|
|
17
|
+
const vipunen_1 = require("./plugins/vipunen");
|
|
14
18
|
// Bot config and bug-fixer tools are dynamically imported only when MCP_CLIENT_ENABLED=true
|
|
15
19
|
// This allows the npm package to work without these modules
|
|
16
20
|
const core = new core_1.Core();
|
|
@@ -22,9 +26,6 @@ core.addTool(activity_1.listActivitiesTool);
|
|
|
22
26
|
core.addTool(activity_1.showActivityByIdTool);
|
|
23
27
|
core.addTool(activity_1.createActivityTool);
|
|
24
28
|
core.addTool(activity_1.updateActivityTool);
|
|
25
|
-
// core.addTool(searchActivitiesTool);
|
|
26
|
-
// core.addTool(filterActivitiesTool);
|
|
27
|
-
// core.addTool(activityToolsGuideTool);
|
|
28
29
|
core.addTool(discussion_1.listMyDiscussionsTool);
|
|
29
30
|
core.addTool(discussion_1.fetchDiscussionMessagesTool);
|
|
30
31
|
core.addTool(discussion_1.fetchPreviousDiscussionMessagesTool);
|
|
@@ -35,8 +36,7 @@ core.addTool(discussion_1.inviteDiscussionMembersTool);
|
|
|
35
36
|
core.addTool(discussion_1.getActivityFromDiscussionTool);
|
|
36
37
|
core.addTool(user_1.searchWorkspaceUsersTool);
|
|
37
38
|
core.addTool(user_1.getWorkspaceBalanceTool);
|
|
38
|
-
|
|
39
|
-
// core.addTool(validateUserIdTool);
|
|
39
|
+
core.addTool(company_1.setUserRoleTool);
|
|
40
40
|
core.addTool(workflow_1.getWorkflowSchemaTool);
|
|
41
41
|
core.addTool(workflow_1.listWorkflowPhasesTool);
|
|
42
42
|
core.addTool(workflow_1.listWorkflowsTool);
|
|
@@ -50,6 +50,10 @@ core.addTool(workflow_1.testFunctionFieldTool);
|
|
|
50
50
|
core.addTool(workflow_1.listWorkflowsMinimalTool);
|
|
51
51
|
core.addTool(workflow_1.countActivitiesTool);
|
|
52
52
|
core.addTool(workflow_1.coreInitTool);
|
|
53
|
+
core.addTool(workflow_permissions_1.listWorkflowPermissionsTool);
|
|
54
|
+
core.addTool(workflow_permissions_1.grantWorkflowPermissionTool);
|
|
55
|
+
core.addTool(workflow_permissions_1.revokeWorkflowPermissionTool);
|
|
56
|
+
core.addTool(workflow_permissions_1.checkUserPermissionsTool);
|
|
53
57
|
core.addTool(insight_1.createInsightTool);
|
|
54
58
|
core.addTool(insight_1.previewInsightTool);
|
|
55
59
|
core.addTool(insight_1.getInsightDataTool);
|
|
@@ -79,6 +83,15 @@ core.addTool(app_1.getProductManifestTool);
|
|
|
79
83
|
// Marketplace app tools
|
|
80
84
|
core.addTool(app_1.publishAppTool);
|
|
81
85
|
core.addTool(app_1.installMarketplaceAppTool);
|
|
86
|
+
// Vipunen tools (Weaviate RAG) — only registered when WEAVIATE_HOST is set
|
|
87
|
+
const vipunenTools = (0, vipunen_1.registerVipunenTools)({
|
|
88
|
+
weaviateHost: config_1.environment.WEAVIATE_HOST,
|
|
89
|
+
weaviateApiKey: config_1.environment.WEAVIATE_API_KEY,
|
|
90
|
+
vipunenApiKeys: config_1.environment.VIPUNEN_API_KEYS,
|
|
91
|
+
});
|
|
92
|
+
for (const tool of vipunenTools) {
|
|
93
|
+
core.addTool(tool);
|
|
94
|
+
}
|
|
82
95
|
// Bot-internal tools - dynamically imported only when MCP_CLIENT_ENABLED=true
|
|
83
96
|
// Wrapped in try/catch so global installs work (bot-config excluded from npm package)
|
|
84
97
|
if (config_1.environment.MCP_CLIENT_ENABLED) {
|
package/dist/bot/bot-config.d.ts
CHANGED
|
@@ -4,18 +4,29 @@
|
|
|
4
4
|
* Simple config reader for .bot-config/*.json files.
|
|
5
5
|
* Extracts orchestrator credentials into a flat BotConfig interface.
|
|
6
6
|
*/
|
|
7
|
+
import { ResponseMode } from './services/types';
|
|
8
|
+
/** Who can talk to this bot */
|
|
9
|
+
export type BotAccessLevel = 'all' | 'admin' | 'owner';
|
|
7
10
|
export interface BotConfig {
|
|
11
|
+
activityId: string;
|
|
8
12
|
workspaceId: string;
|
|
9
13
|
workspaceName: string;
|
|
10
14
|
email: string;
|
|
11
15
|
password: string;
|
|
12
16
|
displayName?: string;
|
|
17
|
+
systemPrompt?: string;
|
|
13
18
|
enabled: boolean;
|
|
14
19
|
apiHost: string;
|
|
20
|
+
/** Who can talk to this bot: 'all' (default), 'admin', or 'owner' */
|
|
21
|
+
accessLevel?: BotAccessLevel;
|
|
22
|
+
/** Workflow IDs the bot is allowed to access. Empty/undefined = all workflows. */
|
|
23
|
+
allowedWorkflows?: string[];
|
|
24
|
+
/** When the bot responds: 'always' (default), 'mention_only', 'reply_only', 'mention_or_reply' */
|
|
25
|
+
responseMode?: ResponseMode;
|
|
15
26
|
}
|
|
16
27
|
/**
|
|
17
28
|
* Load all bot configs from .bot-config/*.json files.
|
|
18
|
-
*
|
|
29
|
+
* Falls back to BOT_EMAIL/BOT_PASSWORD or BOT_ACCOUNTS env vars.
|
|
19
30
|
*/
|
|
20
31
|
export declare function loadBotConfigs(): BotConfig[];
|
|
21
32
|
/**
|
package/dist/bot/bot-config.js
CHANGED
|
@@ -52,15 +52,66 @@ function getApiHost() {
|
|
|
52
52
|
function getConfigDir() {
|
|
53
53
|
return path.join(process.cwd(), '.bot-config');
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Load bot configs from env vars (BOT_EMAIL/BOT_PASSWORD or BOT_ACCOUNTS).
|
|
57
|
+
* Returns empty array if no env vars are set.
|
|
58
|
+
*/
|
|
59
|
+
function loadEnvBotConfigs() {
|
|
60
|
+
// Multi-bot: BOT_ACCOUNTS JSON array
|
|
61
|
+
const botAccountsStr = process.env.BOT_ACCOUNTS;
|
|
62
|
+
if (botAccountsStr) {
|
|
63
|
+
try {
|
|
64
|
+
const accounts = JSON.parse(botAccountsStr);
|
|
65
|
+
const configs = accounts
|
|
66
|
+
.filter(a => a.email && a.password)
|
|
67
|
+
.map(a => ({
|
|
68
|
+
activityId: '',
|
|
69
|
+
workspaceId: 'env',
|
|
70
|
+
workspaceName: 'env',
|
|
71
|
+
email: a.email,
|
|
72
|
+
password: a.password,
|
|
73
|
+
displayName: a.displayName || process.env.BOT_DISPLAY_NAME || 'Dev AI',
|
|
74
|
+
enabled: true,
|
|
75
|
+
apiHost: getApiHost(),
|
|
76
|
+
}));
|
|
77
|
+
if (configs.length > 0) {
|
|
78
|
+
logger.info('Loaded bot configs from BOT_ACCOUNTS env', { count: configs.length });
|
|
79
|
+
return configs;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
logger.warn('Failed to parse BOT_ACCOUNTS env var', {
|
|
84
|
+
error: error instanceof Error ? error.message : String(error),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Single bot: BOT_EMAIL + BOT_PASSWORD
|
|
89
|
+
const email = process.env.BOT_EMAIL;
|
|
90
|
+
const password = process.env.BOT_PASSWORD;
|
|
91
|
+
if (email && password) {
|
|
92
|
+
logger.info('Loaded bot config from BOT_EMAIL/BOT_PASSWORD env');
|
|
93
|
+
return [{
|
|
94
|
+
activityId: '',
|
|
95
|
+
workspaceId: 'env',
|
|
96
|
+
workspaceName: 'env',
|
|
97
|
+
email,
|
|
98
|
+
password,
|
|
99
|
+
displayName: process.env.BOT_DISPLAY_NAME || 'Dev AI',
|
|
100
|
+
enabled: true,
|
|
101
|
+
apiHost: getApiHost(),
|
|
102
|
+
}];
|
|
103
|
+
}
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
55
106
|
/**
|
|
56
107
|
* Load all bot configs from .bot-config/*.json files.
|
|
57
|
-
*
|
|
108
|
+
* Falls back to BOT_EMAIL/BOT_PASSWORD or BOT_ACCOUNTS env vars.
|
|
58
109
|
*/
|
|
59
110
|
function loadBotConfigs() {
|
|
60
111
|
const configDir = getConfigDir();
|
|
61
112
|
if (!fs.existsSync(configDir)) {
|
|
62
|
-
logger.
|
|
63
|
-
return
|
|
113
|
+
logger.debug('No .bot-config directory found, checking env vars');
|
|
114
|
+
return loadEnvBotConfigs();
|
|
64
115
|
}
|
|
65
116
|
const files = fs.readdirSync(configDir).filter(f => f.endsWith('.json'));
|
|
66
117
|
const configs = [];
|
|
@@ -68,21 +119,46 @@ function loadBotConfigs() {
|
|
|
68
119
|
try {
|
|
69
120
|
const filePath = path.join(configDir, file);
|
|
70
121
|
const raw = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
122
|
+
// Load orchestrator
|
|
71
123
|
const orch = raw.orchestrator;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
124
|
+
if (orch?.email && orch?.password) {
|
|
125
|
+
configs.push({
|
|
126
|
+
activityId: orch.activityId || '',
|
|
127
|
+
workspaceId: raw.workspaceId,
|
|
128
|
+
workspaceName: raw.workspaceName,
|
|
129
|
+
email: orch.email,
|
|
130
|
+
password: orch.password,
|
|
131
|
+
displayName: orch.displayName,
|
|
132
|
+
systemPrompt: orch.systemPrompt,
|
|
133
|
+
enabled: true,
|
|
134
|
+
apiHost: getApiHost(),
|
|
135
|
+
accessLevel: orch.accessLevel,
|
|
136
|
+
allowedWorkflows: orch.allowedWorkflows,
|
|
137
|
+
responseMode: orch.responseMode,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
// Load specialists
|
|
141
|
+
if (Array.isArray(raw.specialists)) {
|
|
142
|
+
for (const spec of raw.specialists) {
|
|
143
|
+
if (spec?.email && spec?.password && spec?.enabled !== false) {
|
|
144
|
+
configs.push({
|
|
145
|
+
activityId: spec.activityId || '',
|
|
146
|
+
workspaceId: raw.workspaceId,
|
|
147
|
+
workspaceName: raw.workspaceName,
|
|
148
|
+
email: spec.email,
|
|
149
|
+
password: spec.password,
|
|
150
|
+
displayName: spec.displayName,
|
|
151
|
+
systemPrompt: spec.systemPrompt,
|
|
152
|
+
enabled: true,
|
|
153
|
+
apiHost: getApiHost(),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
82
158
|
logger.debug('Loaded bot config', {
|
|
83
159
|
workspaceId: raw.workspaceId,
|
|
84
160
|
workspaceName: raw.workspaceName,
|
|
85
|
-
|
|
161
|
+
botCount: configs.filter(c => c.workspaceId === raw.workspaceId).length,
|
|
86
162
|
});
|
|
87
163
|
}
|
|
88
164
|
catch (error) {
|
|
@@ -92,6 +168,11 @@ function loadBotConfigs() {
|
|
|
92
168
|
});
|
|
93
169
|
}
|
|
94
170
|
}
|
|
171
|
+
// If no configs from files, fall back to env vars
|
|
172
|
+
if (configs.length === 0) {
|
|
173
|
+
logger.debug('No bot configs from files, checking env vars');
|
|
174
|
+
return loadEnvBotConfigs();
|
|
175
|
+
}
|
|
95
176
|
logger.debug('Bot configs loaded', { total: configs.length });
|
|
96
177
|
return configs;
|
|
97
178
|
}
|
|
@@ -124,6 +205,9 @@ function saveBotConfig(config) {
|
|
|
124
205
|
email: config.email,
|
|
125
206
|
password: config.password,
|
|
126
207
|
displayName: config.displayName,
|
|
208
|
+
systemPrompt: config.systemPrompt,
|
|
209
|
+
accessLevel: config.accessLevel,
|
|
210
|
+
allowedWorkflows: config.allowedWorkflows,
|
|
127
211
|
} : null,
|
|
128
212
|
specialists: existing.specialists ?? [],
|
|
129
213
|
lastSynced: new Date().toISOString(),
|
|
@@ -7,23 +7,33 @@
|
|
|
7
7
|
import { ToolRegistry } from '../mcp/tool-registry';
|
|
8
8
|
import { BotConfig } from './bot-config';
|
|
9
9
|
interface BotUpdateEntry {
|
|
10
|
+
activityId: string;
|
|
10
11
|
email: string;
|
|
11
12
|
password: string;
|
|
12
13
|
botType: string;
|
|
13
14
|
enabled: boolean;
|
|
14
15
|
displayName?: string;
|
|
16
|
+
systemPrompt?: string;
|
|
17
|
+
accessLevel?: string;
|
|
18
|
+
responseMode?: string;
|
|
15
19
|
}
|
|
16
20
|
export declare class BotManager {
|
|
17
21
|
private toolRegistry;
|
|
18
22
|
private anthropicApiKey;
|
|
23
|
+
/** Key: activityId → Bot instance */
|
|
19
24
|
private bots;
|
|
25
|
+
/** Key: workspaceId → Set of activityIds (for cross-bot awareness) */
|
|
26
|
+
private workspaceBots;
|
|
20
27
|
private apiHost;
|
|
21
28
|
constructor(toolRegistry: ToolRegistry, anthropicApiKey: string);
|
|
29
|
+
/** Get all bot userIds in a workspace (for self-message guard) */
|
|
30
|
+
getBotUserIdsForWorkspace(workspaceId: string): Set<string>;
|
|
22
31
|
startAll(): Promise<void>;
|
|
23
32
|
startBot(config: BotConfig): Promise<void>;
|
|
24
|
-
stopBot(
|
|
33
|
+
stopBot(botKey: string, workspaceId?: string): Promise<void>;
|
|
25
34
|
stopAll(): Promise<void>;
|
|
26
35
|
getStatus(): Array<{
|
|
36
|
+
activityId: string;
|
|
27
37
|
workspaceId: string;
|
|
28
38
|
connected: boolean;
|
|
29
39
|
displayName: string;
|
|
@@ -31,8 +41,8 @@ export declare class BotManager {
|
|
|
31
41
|
getBotCount(): number;
|
|
32
42
|
/**
|
|
33
43
|
* Handle hot reload from webhook updates.
|
|
34
|
-
*
|
|
35
|
-
*
|
|
44
|
+
* Supports all bot types. Routes by activityId so multiple bots
|
|
45
|
+
* can run in the same workspace independently.
|
|
36
46
|
*/
|
|
37
47
|
handleBotUpdate(workspaceId: string, bot: BotUpdateEntry, action: 'add' | 'update' | 'remove'): Promise<void>;
|
|
38
48
|
}
|
package/dist/bot/bot-manager.js
CHANGED
|
@@ -14,13 +14,29 @@ const logger = (0, logger_1.createLogger)({ component: 'bot-manager' });
|
|
|
14
14
|
class BotManager {
|
|
15
15
|
toolRegistry;
|
|
16
16
|
anthropicApiKey;
|
|
17
|
+
/** Key: activityId → Bot instance */
|
|
17
18
|
bots = new Map();
|
|
19
|
+
/** Key: workspaceId → Set of activityIds (for cross-bot awareness) */
|
|
20
|
+
workspaceBots = new Map();
|
|
18
21
|
apiHost;
|
|
19
22
|
constructor(toolRegistry, anthropicApiKey) {
|
|
20
23
|
this.toolRegistry = toolRegistry;
|
|
21
24
|
this.anthropicApiKey = anthropicApiKey;
|
|
22
25
|
this.apiHost = process.env.BOT_API_BASE_URL || 'https://api.hailer.com';
|
|
23
26
|
}
|
|
27
|
+
/** Get all bot userIds in a workspace (for self-message guard) */
|
|
28
|
+
getBotUserIdsForWorkspace(workspaceId) {
|
|
29
|
+
const ids = new Set();
|
|
30
|
+
const activityIds = this.workspaceBots.get(workspaceId);
|
|
31
|
+
if (activityIds) {
|
|
32
|
+
for (const actId of activityIds) {
|
|
33
|
+
const bot = this.bots.get(actId);
|
|
34
|
+
if (bot?.botUserId)
|
|
35
|
+
ids.add(bot.botUserId);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return ids;
|
|
39
|
+
}
|
|
24
40
|
async startAll() {
|
|
25
41
|
const configs = (0, bot_config_1.loadBotConfigs)();
|
|
26
42
|
const enabled = configs.filter(c => c.enabled);
|
|
@@ -37,11 +53,13 @@ class BotManager {
|
|
|
37
53
|
logger.debug('Bot startup complete', { succeeded, failed });
|
|
38
54
|
}
|
|
39
55
|
async startBot(config) {
|
|
40
|
-
|
|
41
|
-
|
|
56
|
+
const botKey = config.activityId || config.workspaceId; // fallback for legacy configs
|
|
57
|
+
if (this.bots.has(botKey)) {
|
|
58
|
+
logger.warn('Bot already running', { activityId: botKey, workspaceId: config.workspaceId });
|
|
42
59
|
return;
|
|
43
60
|
}
|
|
44
61
|
logger.debug('Starting bot', {
|
|
62
|
+
activityId: botKey,
|
|
45
63
|
workspaceId: config.workspaceId,
|
|
46
64
|
workspace: config.workspaceName,
|
|
47
65
|
});
|
|
@@ -52,32 +70,53 @@ class BotManager {
|
|
|
52
70
|
anthropicApiKey: this.anthropicApiKey,
|
|
53
71
|
toolRegistry: this.toolRegistry,
|
|
54
72
|
workspaceId: config.workspaceId,
|
|
73
|
+
systemPrompt: config.systemPrompt,
|
|
74
|
+
responseMode: config.responseMode,
|
|
75
|
+
botManager: this,
|
|
76
|
+
accessLevel: config.accessLevel,
|
|
77
|
+
allowedWorkflows: config.allowedWorkflows,
|
|
55
78
|
});
|
|
56
79
|
await bot.start();
|
|
57
|
-
this.bots.set(
|
|
58
|
-
|
|
80
|
+
this.bots.set(botKey, bot);
|
|
81
|
+
// Track in workspace lookup
|
|
82
|
+
if (!this.workspaceBots.has(config.workspaceId)) {
|
|
83
|
+
this.workspaceBots.set(config.workspaceId, new Set());
|
|
84
|
+
}
|
|
85
|
+
this.workspaceBots.get(config.workspaceId).add(botKey);
|
|
86
|
+
logger.debug('Bot started', { activityId: botKey, workspaceId: config.workspaceId });
|
|
59
87
|
}
|
|
60
|
-
async stopBot(workspaceId) {
|
|
61
|
-
const bot = this.bots.get(
|
|
88
|
+
async stopBot(botKey, workspaceId) {
|
|
89
|
+
const bot = this.bots.get(botKey);
|
|
62
90
|
if (!bot)
|
|
63
91
|
return;
|
|
64
92
|
await bot.stop();
|
|
65
|
-
this.bots.delete(
|
|
66
|
-
|
|
93
|
+
this.bots.delete(botKey);
|
|
94
|
+
// Clean up workspace tracking
|
|
95
|
+
if (workspaceId) {
|
|
96
|
+
const wsSet = this.workspaceBots.get(workspaceId);
|
|
97
|
+
if (wsSet) {
|
|
98
|
+
wsSet.delete(botKey);
|
|
99
|
+
if (wsSet.size === 0)
|
|
100
|
+
this.workspaceBots.delete(workspaceId);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
logger.debug('Bot stopped', { activityId: botKey, workspaceId });
|
|
67
104
|
}
|
|
68
105
|
async stopAll() {
|
|
69
106
|
logger.debug('Stopping all bots', { count: this.bots.size });
|
|
70
|
-
await Promise.allSettled(Array.from(this.bots.entries()).map(async ([
|
|
107
|
+
await Promise.allSettled(Array.from(this.bots.entries()).map(async ([botKey, bot]) => {
|
|
71
108
|
await bot.stop();
|
|
72
|
-
logger.debug('Bot stopped', {
|
|
109
|
+
logger.debug('Bot stopped', { activityId: botKey });
|
|
73
110
|
}));
|
|
74
111
|
this.bots.clear();
|
|
112
|
+
this.workspaceBots.clear();
|
|
75
113
|
}
|
|
76
114
|
getStatus() {
|
|
77
|
-
return Array.from(this.bots.entries()).map(([
|
|
78
|
-
|
|
115
|
+
return Array.from(this.bots.entries()).map(([botKey, bot]) => ({
|
|
116
|
+
activityId: botKey,
|
|
117
|
+
workspaceId: bot.workspaceId || botKey,
|
|
79
118
|
connected: bot.connected,
|
|
80
|
-
displayName:
|
|
119
|
+
displayName: bot.workspaceId || botKey,
|
|
81
120
|
}));
|
|
82
121
|
}
|
|
83
122
|
getBotCount() {
|
|
@@ -85,48 +124,64 @@ class BotManager {
|
|
|
85
124
|
}
|
|
86
125
|
/**
|
|
87
126
|
* Handle hot reload from webhook updates.
|
|
88
|
-
*
|
|
89
|
-
*
|
|
127
|
+
* Supports all bot types. Routes by activityId so multiple bots
|
|
128
|
+
* can run in the same workspace independently.
|
|
90
129
|
*/
|
|
91
130
|
async handleBotUpdate(workspaceId, bot, action) {
|
|
92
|
-
|
|
93
|
-
|
|
131
|
+
const botKey = bot.activityId;
|
|
132
|
+
if (!botKey) {
|
|
133
|
+
logger.warn('Bot update missing activityId, skipping', { workspaceId });
|
|
94
134
|
return;
|
|
95
135
|
}
|
|
96
|
-
const running = this.bots.has(
|
|
136
|
+
const running = this.bots.has(botKey);
|
|
97
137
|
if (action === 'remove' || !bot.enabled) {
|
|
98
138
|
if (running) {
|
|
99
|
-
logger.info('Stopping bot (disabled via webhook)', { workspaceId });
|
|
100
|
-
await this.stopBot(workspaceId);
|
|
139
|
+
logger.info('Stopping bot (disabled via webhook)', { activityId: botKey, workspaceId });
|
|
140
|
+
await this.stopBot(botKey, workspaceId);
|
|
101
141
|
}
|
|
102
142
|
return;
|
|
103
143
|
}
|
|
104
144
|
// Validate credentials before proceeding
|
|
105
145
|
if (!/.+@.+\..+/.test(bot.email) || !bot.password || bot.password.length < 6) {
|
|
106
|
-
logger.warn('Invalid bot credentials, skipping', { workspaceId });
|
|
146
|
+
logger.warn('Invalid bot credentials, skipping', { activityId: botKey, workspaceId });
|
|
107
147
|
return;
|
|
108
148
|
}
|
|
109
149
|
// action is 'add' or 'update' with enabled=true
|
|
110
150
|
if (running) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
151
|
+
const runningBot = this.bots.get(botKey);
|
|
152
|
+
// If only the system prompt changed, update it live — no restart needed
|
|
153
|
+
const credentialsChanged = runningBot.email !== bot.email || runningBot.password !== bot.password;
|
|
154
|
+
const accessLevelChanged = bot.accessLevel !== undefined && runningBot.accessLevel !== bot.accessLevel;
|
|
155
|
+
if (!credentialsChanged && !accessLevelChanged) {
|
|
156
|
+
logger.info('Updating bot config live (no restart needed)', { activityId: botKey, workspaceId });
|
|
157
|
+
runningBot.updateSystemPrompt(bot.systemPrompt);
|
|
158
|
+
runningBot.updateResponseMode(bot.responseMode);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// Credentials changed — full restart required
|
|
162
|
+
logger.info('Restarting bot (credentials updated via webhook)', { activityId: botKey, workspaceId });
|
|
163
|
+
await this.stopBot(botKey, workspaceId);
|
|
114
164
|
}
|
|
115
165
|
const config = {
|
|
166
|
+
activityId: botKey,
|
|
116
167
|
workspaceId,
|
|
117
168
|
workspaceName: workspaceId,
|
|
118
169
|
email: bot.email,
|
|
119
170
|
password: bot.password,
|
|
120
171
|
displayName: bot.displayName,
|
|
172
|
+
systemPrompt: bot.systemPrompt,
|
|
121
173
|
enabled: true,
|
|
122
174
|
apiHost: this.apiHost,
|
|
175
|
+
accessLevel: bot.accessLevel,
|
|
176
|
+
responseMode: bot.responseMode,
|
|
123
177
|
};
|
|
124
178
|
try {
|
|
125
179
|
await this.startBot(config);
|
|
126
|
-
logger.info('Bot started via webhook', { workspaceId, displayName: bot.displayName });
|
|
180
|
+
logger.info('Bot started via webhook', { activityId: botKey, workspaceId, displayName: bot.displayName });
|
|
127
181
|
}
|
|
128
182
|
catch (error) {
|
|
129
183
|
logger.error('Failed to start bot via webhook', {
|
|
184
|
+
activityId: botKey,
|
|
130
185
|
workspaceId,
|
|
131
186
|
error: error instanceof Error ? error.message : String(error),
|
|
132
187
|
});
|
package/dist/bot/bot.d.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* and posts responses back to discussions.
|
|
7
7
|
*/
|
|
8
8
|
import { ToolRegistry } from '../mcp/tool-registry';
|
|
9
|
+
import { ResponseMode } from './services/types';
|
|
10
|
+
import { BotAccessLevel } from './bot-config';
|
|
9
11
|
export declare class Bot {
|
|
10
12
|
private logger;
|
|
11
13
|
private clientManager;
|
|
@@ -18,12 +20,17 @@ export declare class Bot {
|
|
|
18
20
|
private workspaceOverview;
|
|
19
21
|
private userId;
|
|
20
22
|
private _workspaceId;
|
|
23
|
+
private _systemPrompt;
|
|
24
|
+
private _responseMode;
|
|
21
25
|
private conversationManager;
|
|
22
26
|
private messageClassifier;
|
|
23
27
|
private messageFormatter;
|
|
24
28
|
private typingIndicator;
|
|
25
29
|
private tokenBilling;
|
|
26
30
|
private sessionLogger;
|
|
31
|
+
private hailerApi;
|
|
32
|
+
/** Cache of insightId → Set<workflowId> for permission checks on ID-based insight tools */
|
|
33
|
+
private insightWorkflowCache;
|
|
27
34
|
private opLogger;
|
|
28
35
|
private discussionStates;
|
|
29
36
|
private processingDiscussions;
|
|
@@ -44,7 +51,10 @@ export declare class Bot {
|
|
|
44
51
|
private permissionIndex;
|
|
45
52
|
private adminUserIds;
|
|
46
53
|
private ownerUserIds;
|
|
54
|
+
private workspaceMemberIds;
|
|
55
|
+
private membersLoaded;
|
|
47
56
|
private config;
|
|
57
|
+
private botManager;
|
|
48
58
|
constructor(config: {
|
|
49
59
|
email: string;
|
|
50
60
|
password: string;
|
|
@@ -53,11 +63,28 @@ export declare class Bot {
|
|
|
53
63
|
model?: string;
|
|
54
64
|
toolRegistry: ToolRegistry;
|
|
55
65
|
workspaceId?: string;
|
|
66
|
+
systemPrompt?: string;
|
|
67
|
+
responseMode?: ResponseMode;
|
|
68
|
+
botManager?: any;
|
|
69
|
+
accessLevel?: BotAccessLevel;
|
|
70
|
+
allowedWorkflows?: string[];
|
|
56
71
|
});
|
|
72
|
+
get email(): string;
|
|
73
|
+
get password(): string;
|
|
74
|
+
get accessLevel(): string;
|
|
75
|
+
/**
|
|
76
|
+
* Hot-update the system prompt without restarting the bot.
|
|
77
|
+
* Takes effect on the next message processed.
|
|
78
|
+
*/
|
|
79
|
+
updateSystemPrompt(prompt: string | undefined): void;
|
|
80
|
+
updateResponseMode(mode: ResponseMode | undefined): void;
|
|
57
81
|
get connected(): boolean;
|
|
58
82
|
get workspaceId(): string | undefined;
|
|
83
|
+
/** Exposed for BotManager cross-bot awareness */
|
|
84
|
+
get botUserId(): string;
|
|
59
85
|
start(): Promise<void>;
|
|
60
86
|
stop(): Promise<void>;
|
|
87
|
+
private checkTriggerCondition;
|
|
61
88
|
private handleSignal;
|
|
62
89
|
private processDiscussion;
|
|
63
90
|
/**
|
|
@@ -91,6 +118,11 @@ export declare class Bot {
|
|
|
91
118
|
*/
|
|
92
119
|
private cleanupIncompleteExchange;
|
|
93
120
|
private formatIncomingMessage;
|
|
121
|
+
/**
|
|
122
|
+
* Download image attachments and return Anthropic image content blocks.
|
|
123
|
+
* Falls back silently on errors — the text note still tells the LLM about the file.
|
|
124
|
+
*/
|
|
125
|
+
private resolveImageAttachments;
|
|
94
126
|
private formatOutgoingMessage;
|
|
95
127
|
/**
|
|
96
128
|
* Find bare 24-char hex IDs in text that aren't already inside hailerTags
|
|
@@ -99,6 +131,8 @@ export declare class Bot {
|
|
|
99
131
|
private resolveBareIds;
|
|
100
132
|
private getBotDisplayName;
|
|
101
133
|
private buildSystemPrompt;
|
|
134
|
+
private static TOOL_STATUS_LABELS;
|
|
135
|
+
private getToolStatus;
|
|
102
136
|
private getAnthropicTools;
|
|
103
137
|
private sendMessage;
|
|
104
138
|
/**
|
|
@@ -113,10 +147,22 @@ export declare class Bot {
|
|
|
113
147
|
* Called when process.updated, workspace.updated, or cache.invalidate signals fire.
|
|
114
148
|
*/
|
|
115
149
|
private refreshWorkspaceData;
|
|
150
|
+
/**
|
|
151
|
+
* Backfill workspaceCache.usersById with entries from network.members
|
|
152
|
+
* that are missing from init.users (which is only a partial user list).
|
|
153
|
+
*/
|
|
154
|
+
private backfillWorkspaceCacheMembers;
|
|
116
155
|
private buildPermissionIndex;
|
|
117
156
|
private getOrCreateDiscussionState;
|
|
118
157
|
private getUserContext;
|
|
119
158
|
private getDefaultTeamId;
|
|
159
|
+
/** Get the current permission context for checkWorkflowAccess calls */
|
|
160
|
+
private getPermissionContext;
|
|
161
|
+
/**
|
|
162
|
+
* Post-filter list-type tool results to remove items the user can't access.
|
|
163
|
+
* Handles list_workflows, list_workflows_minimal, and list_insights.
|
|
164
|
+
*/
|
|
165
|
+
private postFilterListResults;
|
|
120
166
|
/**
|
|
121
167
|
* Extract workflow ID from tool result for post-execution permission checks.
|
|
122
168
|
* Returns the workflow ID if found, or undefined if extraction fails.
|