@dobbyai/mcp-external 1.0.4 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -14
- package/dist/__tests__/agent-mail-tools.test.d.ts +8 -0
- package/dist/__tests__/agent-mail-tools.test.d.ts.map +1 -0
- package/dist/__tests__/agent-mail-tools.test.js +255 -0
- package/dist/__tests__/agent-mail-tools.test.js.map +1 -0
- package/dist/__tests__/annotations.test.d.ts +8 -0
- package/dist/__tests__/annotations.test.d.ts.map +1 -0
- package/dist/__tests__/annotations.test.js +108 -0
- package/dist/__tests__/annotations.test.js.map +1 -0
- package/dist/__tests__/auth.test.d.ts +7 -0
- package/dist/__tests__/auth.test.d.ts.map +1 -0
- package/dist/__tests__/auth.test.js +161 -0
- package/dist/__tests__/auth.test.js.map +1 -0
- package/dist/__tests__/doctor.test.d.ts +16 -0
- package/dist/__tests__/doctor.test.d.ts.map +1 -0
- package/dist/__tests__/doctor.test.js +258 -0
- package/dist/__tests__/doctor.test.js.map +1 -0
- package/dist/__tests__/external-agents-tools.test.d.ts +11 -0
- package/dist/__tests__/external-agents-tools.test.d.ts.map +1 -0
- package/dist/__tests__/external-agents-tools.test.js +619 -0
- package/dist/__tests__/external-agents-tools.test.js.map +1 -0
- package/dist/__tests__/gateway-bearer.test.d.ts +12 -0
- package/dist/__tests__/gateway-bearer.test.d.ts.map +1 -0
- package/dist/__tests__/gateway-bearer.test.js +112 -0
- package/dist/__tests__/gateway-bearer.test.js.map +1 -0
- package/dist/__tests__/gateway-key-resolver.test.d.ts +10 -0
- package/dist/__tests__/gateway-key-resolver.test.d.ts.map +1 -0
- package/dist/__tests__/gateway-key-resolver.test.js +125 -0
- package/dist/__tests__/gateway-key-resolver.test.js.map +1 -0
- package/dist/__tests__/http-concurrency.test.d.ts +20 -0
- package/dist/__tests__/http-concurrency.test.d.ts.map +1 -0
- package/dist/__tests__/http-concurrency.test.js +254 -0
- package/dist/__tests__/http-concurrency.test.js.map +1 -0
- package/dist/__tests__/integration/protocol.test.d.ts +8 -0
- package/dist/__tests__/integration/protocol.test.d.ts.map +1 -0
- package/dist/__tests__/integration/protocol.test.js +110 -0
- package/dist/__tests__/integration/protocol.test.js.map +1 -0
- package/dist/__tests__/mcp-integrations.test.d.ts +8 -0
- package/dist/__tests__/mcp-integrations.test.d.ts.map +1 -0
- package/dist/__tests__/mcp-integrations.test.js +365 -0
- package/dist/__tests__/mcp-integrations.test.js.map +1 -0
- package/dist/__tests__/memory-graph-tools.test.d.ts +8 -0
- package/dist/__tests__/memory-graph-tools.test.d.ts.map +1 -0
- package/dist/__tests__/memory-graph-tools.test.js +254 -0
- package/dist/__tests__/memory-graph-tools.test.js.map +1 -0
- package/dist/__tests__/registry-dispatch.test.d.ts +11 -0
- package/dist/__tests__/registry-dispatch.test.d.ts.map +1 -0
- package/dist/__tests__/registry-dispatch.test.js +30 -0
- package/dist/__tests__/registry-dispatch.test.js.map +1 -0
- package/dist/__tests__/registry-listing-parity.test.d.ts +2 -0
- package/dist/__tests__/registry-listing-parity.test.d.ts.map +1 -0
- package/dist/__tests__/registry-listing-parity.test.js +89 -0
- package/dist/__tests__/registry-listing-parity.test.js.map +1 -0
- package/dist/__tests__/role-cap.test.d.ts +2 -0
- package/dist/__tests__/role-cap.test.d.ts.map +1 -0
- package/dist/__tests__/role-cap.test.js +113 -0
- package/dist/__tests__/role-cap.test.js.map +1 -0
- package/dist/__tests__/schedule-tools.test.d.ts +8 -0
- package/dist/__tests__/schedule-tools.test.d.ts.map +1 -0
- package/dist/__tests__/schedule-tools.test.js +285 -0
- package/dist/__tests__/schedule-tools.test.js.map +1 -0
- package/dist/__tests__/server-gateway-key.test.d.ts +18 -0
- package/dist/__tests__/server-gateway-key.test.d.ts.map +1 -0
- package/dist/__tests__/server-gateway-key.test.js +148 -0
- package/dist/__tests__/server-gateway-key.test.js.map +1 -0
- package/dist/__tests__/server-user-scoped.test.d.ts +34 -0
- package/dist/__tests__/server-user-scoped.test.d.ts.map +1 -0
- package/dist/__tests__/server-user-scoped.test.js +577 -0
- package/dist/__tests__/server-user-scoped.test.js.map +1 -0
- package/dist/__tests__/task-id-pattern.test.d.ts +12 -0
- package/dist/__tests__/task-id-pattern.test.d.ts.map +1 -0
- package/dist/__tests__/task-id-pattern.test.js +43 -0
- package/dist/__tests__/task-id-pattern.test.js.map +1 -0
- package/dist/__tests__/tiers.test.d.ts +7 -0
- package/dist/__tests__/tiers.test.d.ts.map +1 -0
- package/dist/__tests__/tiers.test.js +199 -0
- package/dist/__tests__/tiers.test.js.map +1 -0
- package/dist/__tests__/tools/hosted-agents.test.d.ts +9 -0
- package/dist/__tests__/tools/hosted-agents.test.d.ts.map +1 -0
- package/dist/__tests__/tools/hosted-agents.test.js +301 -0
- package/dist/__tests__/tools/hosted-agents.test.js.map +1 -0
- package/dist/__tests__/tools/llm-providers.test.d.ts +10 -0
- package/dist/__tests__/tools/llm-providers.test.d.ts.map +1 -0
- package/dist/__tests__/tools/llm-providers.test.js +105 -0
- package/dist/__tests__/tools/llm-providers.test.js.map +1 -0
- package/dist/__tests__/tools/services.test.js +139 -98
- package/dist/__tests__/tools/services.test.js.map +1 -1
- package/dist/__tests__/tools.test.d.ts +7 -0
- package/dist/__tests__/tools.test.d.ts.map +1 -0
- package/dist/__tests__/tools.test.js +152 -0
- package/dist/__tests__/tools.test.js.map +1 -0
- package/dist/__tests__/transport.test.d.ts +7 -0
- package/dist/__tests__/transport.test.d.ts.map +1 -0
- package/dist/__tests__/transport.test.js +397 -0
- package/dist/__tests__/transport.test.js.map +1 -0
- package/dist/__tests__/validate-credentials.test.d.ts +9 -0
- package/dist/__tests__/validate-credentials.test.d.ts.map +1 -0
- package/dist/__tests__/validate-credentials.test.js +172 -0
- package/dist/__tests__/validate-credentials.test.js.map +1 -0
- package/dist/__tests__/web-eval-tools.test.d.ts +8 -0
- package/dist/__tests__/web-eval-tools.test.d.ts.map +1 -0
- package/dist/__tests__/web-eval-tools.test.js +241 -0
- package/dist/__tests__/web-eval-tools.test.js.map +1 -0
- package/dist/__tests__/whoami.test.d.ts +11 -0
- package/dist/__tests__/whoami.test.d.ts.map +1 -0
- package/dist/__tests__/whoami.test.js +194 -0
- package/dist/__tests__/whoami.test.js.map +1 -0
- package/dist/__tests__/workflow-tools.test.d.ts +8 -0
- package/dist/__tests__/workflow-tools.test.d.ts.map +1 -0
- package/dist/__tests__/workflow-tools.test.js +261 -0
- package/dist/__tests__/workflow-tools.test.js.map +1 -0
- package/dist/__tests__/workloads.test.d.ts +9 -0
- package/dist/__tests__/workloads.test.d.ts.map +1 -0
- package/dist/__tests__/workloads.test.js +169 -0
- package/dist/__tests__/workloads.test.js.map +1 -0
- package/dist/auth/oauth-provider.d.ts +34 -0
- package/dist/auth/oauth-provider.d.ts.map +1 -0
- package/dist/auth/oauth-provider.js +75 -0
- package/dist/auth/oauth-provider.js.map +1 -0
- package/dist/auth/token-verifier.d.ts +45 -0
- package/dist/auth/token-verifier.d.ts.map +1 -0
- package/dist/auth/token-verifier.js +160 -0
- package/dist/auth/token-verifier.js.map +1 -0
- package/dist/connectors/claude-desktop.d.ts.map +1 -1
- package/dist/connectors/claude-desktop.js +3 -2
- package/dist/connectors/claude-desktop.js.map +1 -1
- package/dist/connectors/cursor.d.ts.map +1 -1
- package/dist/connectors/cursor.js +3 -2
- package/dist/connectors/cursor.js.map +1 -1
- package/dist/connectors/setup.d.ts.map +1 -1
- package/dist/connectors/setup.js +2 -1
- package/dist/connectors/setup.js.map +1 -1
- package/dist/connectors/vscode.d.ts.map +1 -1
- package/dist/connectors/vscode.js +3 -2
- package/dist/connectors/vscode.js.map +1 -1
- package/dist/connectors/windsurf.d.ts.map +1 -1
- package/dist/connectors/windsurf.js +3 -2
- package/dist/connectors/windsurf.js.map +1 -1
- package/dist/doctor.d.ts +34 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +134 -0
- package/dist/doctor.js.map +1 -0
- package/dist/http-server.d.ts +56 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +455 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +96 -171
- package/dist/index.js.map +1 -1
- package/dist/lib/consts.d.ts +21 -0
- package/dist/lib/consts.d.ts.map +1 -0
- package/dist/lib/consts.js +30 -0
- package/dist/lib/consts.js.map +1 -0
- package/dist/lib/dobby-client.d.ts +60 -3
- package/dist/lib/dobby-client.d.ts.map +1 -1
- package/dist/lib/dobby-client.js +145 -44
- package/dist/lib/dobby-client.js.map +1 -1
- package/dist/lib/gateway-key-resolver.d.ts +38 -0
- package/dist/lib/gateway-key-resolver.d.ts.map +1 -0
- package/dist/lib/gateway-key-resolver.js +59 -0
- package/dist/lib/gateway-key-resolver.js.map +1 -0
- package/dist/lib/log.d.ts +25 -0
- package/dist/lib/log.d.ts.map +1 -0
- package/dist/lib/log.js +36 -0
- package/dist/lib/log.js.map +1 -0
- package/dist/server.d.ts +175 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1017 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/agent-mail.d.ts +112 -0
- package/dist/tools/agent-mail.d.ts.map +1 -0
- package/dist/tools/agent-mail.js +118 -0
- package/dist/tools/agent-mail.js.map +1 -0
- package/dist/tools/agent-versions.d.ts +93 -0
- package/dist/tools/agent-versions.d.ts.map +1 -0
- package/dist/tools/agent-versions.js +99 -0
- package/dist/tools/agent-versions.js.map +1 -0
- package/dist/tools/approvals.d.ts +24 -34
- package/dist/tools/approvals.d.ts.map +1 -1
- package/dist/tools/approvals.js +24 -81
- package/dist/tools/approvals.js.map +1 -1
- package/dist/tools/claude-code-sync.d.ts +40 -0
- package/dist/tools/claude-code-sync.d.ts.map +1 -0
- package/dist/tools/claude-code-sync.js +52 -0
- package/dist/tools/claude-code-sync.js.map +1 -0
- package/dist/tools/control-plane.d.ts +118 -0
- package/dist/tools/control-plane.d.ts.map +1 -0
- package/dist/tools/control-plane.js +135 -0
- package/dist/tools/control-plane.js.map +1 -0
- package/dist/tools/crew-builder.d.ts +24 -66
- package/dist/tools/crew-builder.d.ts.map +1 -1
- package/dist/tools/crew-builder.js +24 -185
- package/dist/tools/crew-builder.js.map +1 -1
- package/dist/tools/crewai.d.ts +24 -63
- package/dist/tools/crewai.d.ts.map +1 -1
- package/dist/tools/crewai.js +24 -145
- package/dist/tools/crewai.js.map +1 -1
- package/dist/tools/exa.d.ts +126 -0
- package/dist/tools/exa.d.ts.map +1 -0
- package/dist/tools/exa.js +125 -0
- package/dist/tools/exa.js.map +1 -0
- package/dist/tools/external-agents.d.ts +440 -0
- package/dist/tools/external-agents.d.ts.map +1 -0
- package/dist/tools/external-agents.js +386 -0
- package/dist/tools/external-agents.js.map +1 -0
- package/dist/tools/github-mcp.d.ts +228 -0
- package/dist/tools/github-mcp.d.ts.map +1 -0
- package/dist/tools/github-mcp.js +235 -0
- package/dist/tools/github-mcp.js.map +1 -0
- package/dist/tools/governance.d.ts +273 -0
- package/dist/tools/governance.d.ts.map +1 -0
- package/dist/tools/governance.js +286 -0
- package/dist/tools/governance.js.map +1 -0
- package/dist/tools/hosted-agents.d.ts +216 -0
- package/dist/tools/hosted-agents.d.ts.map +1 -0
- package/dist/tools/hosted-agents.js +214 -0
- package/dist/tools/hosted-agents.js.map +1 -0
- package/dist/tools/index.d.ts +6335 -191
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +441 -172
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/jira.d.ts +60 -176
- package/dist/tools/jira.d.ts.map +1 -1
- package/dist/tools/jira.js +60 -365
- package/dist/tools/jira.js.map +1 -1
- package/dist/tools/llm-providers.d.ts +50 -0
- package/dist/tools/llm-providers.d.ts.map +1 -0
- package/dist/tools/llm-providers.js +41 -0
- package/dist/tools/llm-providers.js.map +1 -0
- package/dist/tools/mcp-metrics.d.ts +47 -0
- package/dist/tools/mcp-metrics.d.ts.map +1 -0
- package/dist/tools/mcp-metrics.js +53 -0
- package/dist/tools/mcp-metrics.js.map +1 -0
- package/dist/tools/mcp-tools.d.ts +12 -29
- package/dist/tools/mcp-tools.d.ts.map +1 -1
- package/dist/tools/mcp-tools.js +12 -131
- package/dist/tools/mcp-tools.js.map +1 -1
- package/dist/tools/mem0.d.ts +127 -0
- package/dist/tools/mem0.d.ts.map +1 -0
- package/dist/tools/mem0.js +155 -0
- package/dist/tools/mem0.js.map +1 -0
- package/dist/tools/memory-graph.d.ts +151 -0
- package/dist/tools/memory-graph.d.ts.map +1 -0
- package/dist/tools/memory-graph.js +159 -0
- package/dist/tools/memory-graph.js.map +1 -0
- package/dist/tools/memory-stores.d.ts +141 -0
- package/dist/tools/memory-stores.d.ts.map +1 -0
- package/dist/tools/memory-stores.js +147 -0
- package/dist/tools/memory-stores.js.map +1 -0
- package/dist/tools/messages.d.ts +12 -20
- package/dist/tools/messages.d.ts.map +1 -1
- package/dist/tools/messages.js +12 -49
- package/dist/tools/messages.js.map +1 -1
- package/dist/tools/moltbook.d.ts +328 -0
- package/dist/tools/moltbook.d.ts.map +1 -0
- package/dist/tools/moltbook.js +334 -0
- package/dist/tools/moltbook.js.map +1 -0
- package/dist/tools/monitoring-attribution.d.ts +71 -0
- package/dist/tools/monitoring-attribution.d.ts.map +1 -0
- package/dist/tools/monitoring-attribution.js +74 -0
- package/dist/tools/monitoring-attribution.js.map +1 -0
- package/dist/tools/ops.d.ts +139 -0
- package/dist/tools/ops.d.ts.map +1 -0
- package/dist/tools/ops.js +151 -0
- package/dist/tools/ops.js.map +1 -0
- package/dist/tools/orchestrations.d.ts +109 -0
- package/dist/tools/orchestrations.d.ts.map +1 -0
- package/dist/tools/orchestrations.js +115 -0
- package/dist/tools/orchestrations.js.map +1 -0
- package/dist/tools/outcomes.d.ts +138 -0
- package/dist/tools/outcomes.d.ts.map +1 -0
- package/dist/tools/outcomes.js +136 -0
- package/dist/tools/outcomes.js.map +1 -0
- package/dist/tools/schedules.d.ts +149 -0
- package/dist/tools/schedules.d.ts.map +1 -0
- package/dist/tools/schedules.js +155 -0
- package/dist/tools/schedules.js.map +1 -0
- package/dist/tools/services.d.ts +6 -16
- package/dist/tools/services.d.ts.map +1 -1
- package/dist/tools/services.js +6 -135
- package/dist/tools/services.js.map +1 -1
- package/dist/tools/sessions.d.ts +124 -0
- package/dist/tools/sessions.d.ts.map +1 -0
- package/dist/tools/sessions.js +130 -0
- package/dist/tools/sessions.js.map +1 -0
- package/dist/tools/setup-status.d.ts +29 -0
- package/dist/tools/setup-status.d.ts.map +1 -0
- package/dist/tools/setup-status.js +35 -0
- package/dist/tools/setup-status.js.map +1 -0
- package/dist/tools/tasks.d.ts +44 -56
- package/dist/tools/tasks.d.ts.map +1 -1
- package/dist/tools/tasks.js +48 -212
- package/dist/tools/tasks.js.map +1 -1
- package/dist/tools/tiers.d.ts +55 -0
- package/dist/tools/tiers.d.ts.map +1 -0
- package/dist/tools/tiers.js +239 -0
- package/dist/tools/tiers.js.map +1 -0
- package/dist/tools/unified-agents.d.ts +43 -0
- package/dist/tools/unified-agents.d.ts.map +1 -0
- package/dist/tools/unified-agents.js +46 -0
- package/dist/tools/unified-agents.js.map +1 -0
- package/dist/tools/web-eval.d.ts +129 -0
- package/dist/tools/web-eval.d.ts.map +1 -0
- package/dist/tools/web-eval.js +136 -0
- package/dist/tools/web-eval.js.map +1 -0
- package/dist/tools/workflow.d.ts +105 -0
- package/dist/tools/workflow.d.ts.map +1 -0
- package/dist/tools/workflow.js +111 -0
- package/dist/tools/workflow.js.map +1 -0
- package/dist/tools/workloads.d.ts +81 -0
- package/dist/tools/workloads.d.ts.map +1 -0
- package/dist/tools/workloads.js +81 -0
- package/dist/tools/workloads.js.map +1 -0
- package/package.json +13 -7
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schedule MCP Tools Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for scheduled agent task execution:
|
|
5
|
+
* create_schedule, list_schedules, pause_schedule, delete_schedule
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
8
|
+
import { createRegistry, toMcpResult } from '@dobbyai/capability-core';
|
|
9
|
+
// Mock DobbyClient
|
|
10
|
+
const mockClient = {
|
|
11
|
+
apiUrl: 'http://localhost:3000',
|
|
12
|
+
apiKey: 'test-api-key',
|
|
13
|
+
createSchedule: vi.fn(),
|
|
14
|
+
listSchedules: vi.fn(),
|
|
15
|
+
pauseSchedule: vi.fn(),
|
|
16
|
+
deleteSchedule: vi.fn(),
|
|
17
|
+
};
|
|
18
|
+
// ADR-019: the legacy handle* functions are gone — dispatch goes through the
|
|
19
|
+
// capability registry (handlers are verbatim copies; MCP output byte-identical).
|
|
20
|
+
const registry = createRegistry();
|
|
21
|
+
const callCap = async (id, client, args) => toMcpResult(await registry.get(id).handler({ client: client }, args));
|
|
22
|
+
// ============================================
|
|
23
|
+
// Create Schedule
|
|
24
|
+
// ============================================
|
|
25
|
+
describe('Schedule: Create Schedule', () => {
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
vi.resetAllMocks();
|
|
28
|
+
});
|
|
29
|
+
it('creates a daily recurring schedule', async () => {
|
|
30
|
+
mockClient.createSchedule.mockResolvedValueOnce({
|
|
31
|
+
schedule: {
|
|
32
|
+
id: 'sched_abc123',
|
|
33
|
+
name: 'Daily code review',
|
|
34
|
+
scheduleType: 'recurring',
|
|
35
|
+
scheduleDescription: 'Daily at 09:00',
|
|
36
|
+
nextRunAt: '2026-03-06T09:00:00.000Z',
|
|
37
|
+
overlapPolicy: 'skip',
|
|
38
|
+
taskTitle: 'Review pending PRs',
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
const result = await callCap('create_schedule', mockClient, {
|
|
42
|
+
name: 'Daily code review',
|
|
43
|
+
task_title: 'Review pending PRs',
|
|
44
|
+
task_description: 'Review all open pull requests and provide feedback',
|
|
45
|
+
schedule_type: 'recurring',
|
|
46
|
+
frequency: 'daily',
|
|
47
|
+
time: '09:00',
|
|
48
|
+
timezone: 'Asia/Jerusalem',
|
|
49
|
+
});
|
|
50
|
+
expect(mockClient.createSchedule).toHaveBeenCalledOnce();
|
|
51
|
+
expect(result.content[0].text).toContain('Schedule created successfully');
|
|
52
|
+
expect(result.content[0].text).toContain('sched_abc123');
|
|
53
|
+
expect(result.content[0].text).toContain('Daily at 09:00');
|
|
54
|
+
});
|
|
55
|
+
it('creates a weekly recurring schedule', async () => {
|
|
56
|
+
mockClient.createSchedule.mockResolvedValueOnce({
|
|
57
|
+
schedule: {
|
|
58
|
+
id: 'sched_def456',
|
|
59
|
+
name: 'Weekly security scan',
|
|
60
|
+
scheduleType: 'recurring',
|
|
61
|
+
scheduleDescription: 'Every Monday at 08:00',
|
|
62
|
+
nextRunAt: '2026-03-10T08:00:00.000Z',
|
|
63
|
+
overlapPolicy: 'skip',
|
|
64
|
+
taskTitle: 'Security vulnerability scan',
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
const result = await callCap('create_schedule', mockClient, {
|
|
68
|
+
name: 'Weekly security scan',
|
|
69
|
+
task_title: 'Security vulnerability scan',
|
|
70
|
+
task_description: 'Run security scan on the entire codebase',
|
|
71
|
+
schedule_type: 'recurring',
|
|
72
|
+
frequency: 'weekly',
|
|
73
|
+
time: '08:00',
|
|
74
|
+
timezone: 'Asia/Jerusalem',
|
|
75
|
+
day_of_week: 1,
|
|
76
|
+
});
|
|
77
|
+
expect(mockClient.createSchedule).toHaveBeenCalledOnce();
|
|
78
|
+
const callArgs = mockClient.createSchedule.mock.calls[0][0];
|
|
79
|
+
expect(callArgs.schedule_config.frequency).toBe('weekly');
|
|
80
|
+
expect(callArgs.schedule_config.dayOfWeek).toBe(1);
|
|
81
|
+
expect(result.content[0].text).toContain('sched_def456');
|
|
82
|
+
});
|
|
83
|
+
it('creates a one-time schedule', async () => {
|
|
84
|
+
mockClient.createSchedule.mockResolvedValueOnce({
|
|
85
|
+
schedule: {
|
|
86
|
+
id: 'sched_onetime1',
|
|
87
|
+
name: 'Release day deploy check',
|
|
88
|
+
scheduleType: 'one_time',
|
|
89
|
+
scheduleDescription: null,
|
|
90
|
+
nextRunAt: '2026-03-15T14:00:00.000Z',
|
|
91
|
+
overlapPolicy: 'allow',
|
|
92
|
+
taskTitle: 'Pre-deployment checklist',
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
const result = await callCap('create_schedule', mockClient, {
|
|
96
|
+
name: 'Release day deploy check',
|
|
97
|
+
task_title: 'Pre-deployment checklist',
|
|
98
|
+
task_description: 'Verify all systems before v2.0 deployment',
|
|
99
|
+
schedule_type: 'one_time',
|
|
100
|
+
schedule_at: '2026-03-15T14:00:00.000Z',
|
|
101
|
+
overlap_policy: 'allow',
|
|
102
|
+
});
|
|
103
|
+
expect(mockClient.createSchedule).toHaveBeenCalledOnce();
|
|
104
|
+
const callArgs = mockClient.createSchedule.mock.calls[0][0];
|
|
105
|
+
expect(callArgs.schedule_type).toBe('one_time');
|
|
106
|
+
expect(callArgs.schedule_at).toBe('2026-03-15T14:00:00.000Z');
|
|
107
|
+
expect(callArgs.overlap_policy).toBe('allow');
|
|
108
|
+
expect(result.content[0].text).toContain('sched_onetime1');
|
|
109
|
+
});
|
|
110
|
+
it('uses default values when optional params omitted', async () => {
|
|
111
|
+
mockClient.createSchedule.mockResolvedValueOnce({
|
|
112
|
+
schedule: {
|
|
113
|
+
id: 'sched_default1',
|
|
114
|
+
name: 'Test schedule',
|
|
115
|
+
scheduleType: 'recurring',
|
|
116
|
+
scheduleDescription: 'Daily at 09:00',
|
|
117
|
+
nextRunAt: '2026-03-06T09:00:00.000Z',
|
|
118
|
+
overlapPolicy: 'skip',
|
|
119
|
+
taskTitle: 'Test task',
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
const result = await callCap('create_schedule', mockClient, {
|
|
123
|
+
name: 'Test schedule',
|
|
124
|
+
task_title: 'Test task',
|
|
125
|
+
task_description: 'A test description',
|
|
126
|
+
schedule_type: 'recurring',
|
|
127
|
+
});
|
|
128
|
+
const callArgs = mockClient.createSchedule.mock.calls[0][0];
|
|
129
|
+
expect(callArgs.task_priority).toBe('medium');
|
|
130
|
+
expect(callArgs.overlap_policy).toBe('skip');
|
|
131
|
+
expect(callArgs.schedule_config.frequency).toBe('daily');
|
|
132
|
+
expect(callArgs.schedule_config.time).toBe('09:00');
|
|
133
|
+
expect(callArgs.schedule_config.timezone).toBe('Asia/Jerusalem');
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
// ============================================
|
|
137
|
+
// List Schedules
|
|
138
|
+
// ============================================
|
|
139
|
+
describe('Schedule: List Schedules', () => {
|
|
140
|
+
beforeEach(() => {
|
|
141
|
+
vi.resetAllMocks();
|
|
142
|
+
});
|
|
143
|
+
it('lists schedules with status and run info', async () => {
|
|
144
|
+
mockClient.listSchedules.mockResolvedValueOnce({
|
|
145
|
+
schedules: [
|
|
146
|
+
{
|
|
147
|
+
id: 'sched_abc123',
|
|
148
|
+
name: 'Daily code review',
|
|
149
|
+
enabled: true,
|
|
150
|
+
paused: false,
|
|
151
|
+
scheduleDescription: 'Daily at 09:00',
|
|
152
|
+
nextRunAt: '2026-03-06T09:00:00.000Z',
|
|
153
|
+
lastRunAt: '2026-03-05T09:00:00.000Z',
|
|
154
|
+
lastRunStatus: 'success',
|
|
155
|
+
totalRuns: 42,
|
|
156
|
+
totalSuccesses: 41,
|
|
157
|
+
totalFailures: 1,
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: 'sched_def456',
|
|
161
|
+
name: 'Weekly security scan',
|
|
162
|
+
enabled: true,
|
|
163
|
+
paused: true,
|
|
164
|
+
scheduleDescription: 'Every Monday at 08:00',
|
|
165
|
+
nextRunAt: null,
|
|
166
|
+
lastRunAt: '2026-03-03T08:00:00.000Z',
|
|
167
|
+
lastRunStatus: 'failed',
|
|
168
|
+
totalRuns: 10,
|
|
169
|
+
totalSuccesses: 8,
|
|
170
|
+
totalFailures: 2,
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
});
|
|
174
|
+
const result = await callCap('list_schedules', mockClient, {});
|
|
175
|
+
expect(mockClient.listSchedules).toHaveBeenCalledOnce();
|
|
176
|
+
expect(result.content[0].text).toContain('Agent Schedules (2)');
|
|
177
|
+
expect(result.content[0].text).toContain('Daily code review');
|
|
178
|
+
expect(result.content[0].text).toContain('Weekly security scan');
|
|
179
|
+
expect(result.content[0].text).toContain('Active');
|
|
180
|
+
expect(result.content[0].text).toContain('Paused');
|
|
181
|
+
});
|
|
182
|
+
it('shows empty state when no schedules', async () => {
|
|
183
|
+
mockClient.listSchedules.mockResolvedValueOnce({
|
|
184
|
+
schedules: [],
|
|
185
|
+
});
|
|
186
|
+
const result = await callCap('list_schedules', mockClient, {});
|
|
187
|
+
expect(result.content[0].text).toContain('No agent schedules found');
|
|
188
|
+
});
|
|
189
|
+
it('passes filter options to client', async () => {
|
|
190
|
+
mockClient.listSchedules.mockResolvedValueOnce({ schedules: [] });
|
|
191
|
+
await callCap('list_schedules', mockClient, {
|
|
192
|
+
enabled_only: true,
|
|
193
|
+
limit: 5,
|
|
194
|
+
});
|
|
195
|
+
expect(mockClient.listSchedules).toHaveBeenCalledWith({
|
|
196
|
+
enabled_only: true,
|
|
197
|
+
limit: 5,
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
// ============================================
|
|
202
|
+
// Pause Schedule
|
|
203
|
+
// ============================================
|
|
204
|
+
describe('Schedule: Pause/Resume', () => {
|
|
205
|
+
beforeEach(() => {
|
|
206
|
+
vi.resetAllMocks();
|
|
207
|
+
});
|
|
208
|
+
it('pauses a schedule with reason', async () => {
|
|
209
|
+
mockClient.pauseSchedule.mockResolvedValueOnce({ success: true });
|
|
210
|
+
const result = await callCap('pause_schedule', mockClient, {
|
|
211
|
+
schedule_id: 'sched_abc123',
|
|
212
|
+
action: 'pause',
|
|
213
|
+
reason: 'Holiday freeze',
|
|
214
|
+
});
|
|
215
|
+
expect(mockClient.pauseSchedule).toHaveBeenCalledWith({
|
|
216
|
+
schedule_id: 'sched_abc123',
|
|
217
|
+
action: 'pause',
|
|
218
|
+
reason: 'Holiday freeze',
|
|
219
|
+
});
|
|
220
|
+
expect(result.content[0].text).toContain('paused');
|
|
221
|
+
expect(result.content[0].text).toContain('Holiday freeze');
|
|
222
|
+
});
|
|
223
|
+
it('resumes a paused schedule', async () => {
|
|
224
|
+
mockClient.pauseSchedule.mockResolvedValueOnce({ success: true });
|
|
225
|
+
const result = await callCap('pause_schedule', mockClient, {
|
|
226
|
+
schedule_id: 'sched_abc123',
|
|
227
|
+
action: 'resume',
|
|
228
|
+
});
|
|
229
|
+
expect(mockClient.pauseSchedule).toHaveBeenCalledWith({
|
|
230
|
+
schedule_id: 'sched_abc123',
|
|
231
|
+
action: 'resume',
|
|
232
|
+
reason: undefined,
|
|
233
|
+
});
|
|
234
|
+
expect(result.content[0].text).toContain('resumed');
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
// ============================================
|
|
238
|
+
// Delete Schedule
|
|
239
|
+
// ============================================
|
|
240
|
+
describe('Schedule: Delete', () => {
|
|
241
|
+
beforeEach(() => {
|
|
242
|
+
vi.resetAllMocks();
|
|
243
|
+
});
|
|
244
|
+
it('deletes a schedule by ID', async () => {
|
|
245
|
+
mockClient.deleteSchedule.mockResolvedValueOnce({ success: true });
|
|
246
|
+
const result = await callCap('delete_schedule', mockClient, {
|
|
247
|
+
schedule_id: 'sched_abc123',
|
|
248
|
+
});
|
|
249
|
+
expect(mockClient.deleteSchedule).toHaveBeenCalledWith('sched_abc123');
|
|
250
|
+
expect(result.content[0].text).toContain('deleted');
|
|
251
|
+
expect(result.content[0].text).toContain('sched_abc123');
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
// ============================================
|
|
255
|
+
// Tool Definitions
|
|
256
|
+
// ============================================
|
|
257
|
+
describe('Schedule: Tool Definitions', () => {
|
|
258
|
+
it('exports all 4 schedule tools', async () => {
|
|
259
|
+
const { scheduleTools } = await import('../tools/schedules.js');
|
|
260
|
+
expect(scheduleTools.create_schedule).toBeDefined();
|
|
261
|
+
expect(scheduleTools.list_schedules).toBeDefined();
|
|
262
|
+
expect(scheduleTools.pause_schedule).toBeDefined();
|
|
263
|
+
expect(scheduleTools.delete_schedule).toBeDefined();
|
|
264
|
+
});
|
|
265
|
+
it('create_schedule has correct required fields', async () => {
|
|
266
|
+
const { scheduleTools } = await import('../tools/schedules.js');
|
|
267
|
+
const schema = scheduleTools.create_schedule.inputSchema;
|
|
268
|
+
expect(schema.required).toContain('name');
|
|
269
|
+
expect(schema.required).toContain('task_title');
|
|
270
|
+
expect(schema.required).toContain('task_description');
|
|
271
|
+
expect(schema.required).toContain('schedule_type');
|
|
272
|
+
});
|
|
273
|
+
it('pause_schedule requires schedule_id and action', async () => {
|
|
274
|
+
const { scheduleTools } = await import('../tools/schedules.js');
|
|
275
|
+
const schema = scheduleTools.pause_schedule.inputSchema;
|
|
276
|
+
expect(schema.required).toContain('schedule_id');
|
|
277
|
+
expect(schema.required).toContain('action');
|
|
278
|
+
});
|
|
279
|
+
it('delete_schedule requires schedule_id', async () => {
|
|
280
|
+
const { scheduleTools } = await import('../tools/schedules.js');
|
|
281
|
+
const schema = scheduleTools.delete_schedule.inputSchema;
|
|
282
|
+
expect(schema.required).toContain('schedule_id');
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
//# sourceMappingURL=schedule-tools.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-tools.test.js","sourceRoot":"","sources":["../../src/__tests__/schedule-tools.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvE,mBAAmB;AACnB,MAAM,UAAU,GAAG;IACjB,MAAM,EAAE,uBAAuB;IAC/B,MAAM,EAAE,cAAc;IACtB,cAAc,EAAE,EAAE,CAAC,EAAE,EAAE;IACvB,aAAa,EAAE,EAAE,CAAC,EAAE,EAAE;IACtB,aAAa,EAAE,EAAE,CAAC,EAAE,EAAE;IACtB,cAAc,EAAE,EAAE,CAAC,EAAE,EAAE;CACjB,CAAC;AAET,6EAA6E;AAC7E,iFAAiF;AACjF,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;AAClC,MAAM,OAAO,GAAG,KAAK,EAAE,EAAU,EAAE,MAAe,EAAE,IAA6B,EAAE,EAAE,CACnF,WAAW,CAAC,MAAM,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAa,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;AAEhF,+CAA+C;AAC/C,kBAAkB;AAClB,+CAA+C;AAE/C,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,UAAU,CAAC,cAAc,CAAC,qBAAqB,CAAC;YAC9C,QAAQ,EAAE;gBACR,EAAE,EAAE,cAAc;gBAClB,IAAI,EAAE,mBAAmB;gBACzB,YAAY,EAAE,WAAW;gBACzB,mBAAmB,EAAE,gBAAgB;gBACrC,SAAS,EAAE,0BAA0B;gBACrC,aAAa,EAAE,MAAM;gBACrB,SAAS,EAAE,oBAAoB;aAChC;SACF,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,iBAAiB,EAAE,UAAU,EAAE;YAC1D,IAAI,EAAE,mBAAmB;YACzB,UAAU,EAAE,oBAAoB;YAChC,gBAAgB,EAAE,oDAAoD;YACtE,aAAa,EAAE,WAAW;YAC1B,SAAS,EAAE,OAAO;YAClB,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,gBAAgB;SAC3B,CAAC,CAAC;QAEH,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,oBAAoB,EAAE,CAAC;QACzD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,+BAA+B,CAAC,CAAC;QAC1E,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QACzD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,UAAU,CAAC,cAAc,CAAC,qBAAqB,CAAC;YAC9C,QAAQ,EAAE;gBACR,EAAE,EAAE,cAAc;gBAClB,IAAI,EAAE,sBAAsB;gBAC5B,YAAY,EAAE,WAAW;gBACzB,mBAAmB,EAAE,uBAAuB;gBAC5C,SAAS,EAAE,0BAA0B;gBACrC,aAAa,EAAE,MAAM;gBACrB,SAAS,EAAE,6BAA6B;aACzC;SACF,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,iBAAiB,EAAE,UAAU,EAAE;YAC1D,IAAI,EAAE,sBAAsB;YAC5B,UAAU,EAAE,6BAA6B;YACzC,gBAAgB,EAAE,0CAA0C;YAC5D,aAAa,EAAE,WAAW;YAC1B,SAAS,EAAE,QAAQ;YACnB,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,gBAAgB;YAC1B,WAAW,EAAE,CAAC;SACf,CAAC,CAAC;QAEH,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,oBAAoB,EAAE,CAAC;QACzD,MAAM,QAAQ,GAAG,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1D,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;QAC3C,UAAU,CAAC,cAAc,CAAC,qBAAqB,CAAC;YAC9C,QAAQ,EAAE;gBACR,EAAE,EAAE,gBAAgB;gBACpB,IAAI,EAAE,0BAA0B;gBAChC,YAAY,EAAE,UAAU;gBACxB,mBAAmB,EAAE,IAAI;gBACzB,SAAS,EAAE,0BAA0B;gBACrC,aAAa,EAAE,OAAO;gBACtB,SAAS,EAAE,0BAA0B;aACtC;SACF,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,iBAAiB,EAAE,UAAU,EAAE;YAC1D,IAAI,EAAE,0BAA0B;YAChC,UAAU,EAAE,0BAA0B;YACtC,gBAAgB,EAAE,2CAA2C;YAC7D,aAAa,EAAE,UAAU;YACzB,WAAW,EAAE,0BAA0B;YACvC,cAAc,EAAE,OAAO;SACxB,CAAC,CAAC;QAEH,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,oBAAoB,EAAE,CAAC;QACzD,MAAM,QAAQ,GAAG,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChD,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC9D,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,UAAU,CAAC,cAAc,CAAC,qBAAqB,CAAC;YAC9C,QAAQ,EAAE;gBACR,EAAE,EAAE,gBAAgB;gBACpB,IAAI,EAAE,eAAe;gBACrB,YAAY,EAAE,WAAW;gBACzB,mBAAmB,EAAE,gBAAgB;gBACrC,SAAS,EAAE,0BAA0B;gBACrC,aAAa,EAAE,MAAM;gBACrB,SAAS,EAAE,WAAW;aACvB;SACF,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,iBAAiB,EAAE,UAAU,EAAE;YAC1D,IAAI,EAAE,eAAe;YACrB,UAAU,EAAE,WAAW;YACvB,gBAAgB,EAAE,oBAAoB;YACtC,aAAa,EAAE,WAAW;SAC3B,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpD,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,+CAA+C;AAC/C,iBAAiB;AACjB,+CAA+C;AAE/C,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,UAAU,CAAC,aAAa,CAAC,qBAAqB,CAAC;YAC7C,SAAS,EAAE;gBACT;oBACE,EAAE,EAAE,cAAc;oBAClB,IAAI,EAAE,mBAAmB;oBACzB,OAAO,EAAE,IAAI;oBACb,MAAM,EAAE,KAAK;oBACb,mBAAmB,EAAE,gBAAgB;oBACrC,SAAS,EAAE,0BAA0B;oBACrC,SAAS,EAAE,0BAA0B;oBACrC,aAAa,EAAE,SAAS;oBACxB,SAAS,EAAE,EAAE;oBACb,cAAc,EAAE,EAAE;oBAClB,aAAa,EAAE,CAAC;iBACjB;gBACD;oBACE,EAAE,EAAE,cAAc;oBAClB,IAAI,EAAE,sBAAsB;oBAC5B,OAAO,EAAE,IAAI;oBACb,MAAM,EAAE,IAAI;oBACZ,mBAAmB,EAAE,uBAAuB;oBAC5C,SAAS,EAAE,IAAI;oBACf,SAAS,EAAE,0BAA0B;oBACrC,aAAa,EAAE,QAAQ;oBACvB,SAAS,EAAE,EAAE;oBACb,cAAc,EAAE,CAAC;oBACjB,aAAa,EAAE,CAAC;iBACjB;aACF;SACF,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,gBAAgB,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QAE/D,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,oBAAoB,EAAE,CAAC;QACxD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAChE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAC9D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QACjE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,UAAU,CAAC,aAAa,CAAC,qBAAqB,CAAC;YAC7C,SAAS,EAAE,EAAE;SACd,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,gBAAgB,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QAE/D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,UAAU,CAAC,aAAa,CAAC,qBAAqB,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;QAElE,MAAM,OAAO,CAAC,gBAAgB,EAAE,UAAU,EAAE;YAC1C,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,CAAC;SACT,CAAC,CAAC;QAEH,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,oBAAoB,CAAC;YACpD,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,CAAC;SACT,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,+CAA+C;AAC/C,iBAAiB;AACjB,+CAA+C;AAE/C,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,UAAU,CAAC,aAAa,CAAC,qBAAqB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAElE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,gBAAgB,EAAE,UAAU,EAAE;YACzD,WAAW,EAAE,cAAc;YAC3B,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,gBAAgB;SACzB,CAAC,CAAC;QAEH,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,oBAAoB,CAAC;YACpD,WAAW,EAAE,cAAc;YAC3B,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,gBAAgB;SACzB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;QACzC,UAAU,CAAC,aAAa,CAAC,qBAAqB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAElE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,gBAAgB,EAAE,UAAU,EAAE;YACzD,WAAW,EAAE,cAAc;YAC3B,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAC;QAEH,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,oBAAoB,CAAC;YACpD,WAAW,EAAE,cAAc;YAC3B,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,+CAA+C;AAC/C,kBAAkB;AAClB,+CAA+C;AAE/C,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;QACxC,UAAU,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAEnE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,iBAAiB,EAAE,UAAU,EAAE;YAC1D,WAAW,EAAE,cAAc;SAC5B,CAAC,CAAC;QAEH,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAAC;QACvE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,+CAA+C;AAC/C,mBAAmB;AACnB,+CAA+C;AAE/C,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAEhE,MAAM,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE,CAAC;QACpD,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,WAAW,EAAE,CAAC;QACnD,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,WAAW,EAAE,CAAC;QACnD,MAAM,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAEhE,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,CAAC,WAAW,CAAC;QACzD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;QACtD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAEhE,MAAM,MAAM,GAAG,aAAa,CAAC,cAAc,CAAC,WAAW,CAAC;QACxD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAEhE,MAAM,MAAM,GAAG,aAAa,CAAC,eAAe,CAAC,WAAW,CAAC;QACzD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server HTTP-mode Gateway Key Tests
|
|
3
|
+
*
|
|
4
|
+
* The CallTool handler must split the session families:
|
|
5
|
+
* - gk_* Bearer session → context.gatewayKey = the token (restores the
|
|
6
|
+
* checkGatewayAuth pre-check + gateway metering that commit 157db598b
|
|
7
|
+
* disabled for ALL families).
|
|
8
|
+
* - dobby_at_ / sk_live_ session → context.gatewayKey stays undefined (the
|
|
9
|
+
* pre-check short-circuits to allowed) and the per-request DobbyClient
|
|
10
|
+
* carries a LAZY, session-memoized provider that exchanges the token for a
|
|
11
|
+
* gk_tmp_* via the web app's internal endpoint.
|
|
12
|
+
*
|
|
13
|
+
* Drives the REAL server factory (server.ts) over real Streamable HTTP with a
|
|
14
|
+
* stub introspection issuer — only tools/index.handleToolCall is spied, so we
|
|
15
|
+
* can inspect the exact ToolContext the handler builds.
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=server-gateway-key.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-gateway-key.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/server-gateway-key.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server HTTP-mode Gateway Key Tests
|
|
3
|
+
*
|
|
4
|
+
* The CallTool handler must split the session families:
|
|
5
|
+
* - gk_* Bearer session → context.gatewayKey = the token (restores the
|
|
6
|
+
* checkGatewayAuth pre-check + gateway metering that commit 157db598b
|
|
7
|
+
* disabled for ALL families).
|
|
8
|
+
* - dobby_at_ / sk_live_ session → context.gatewayKey stays undefined (the
|
|
9
|
+
* pre-check short-circuits to allowed) and the per-request DobbyClient
|
|
10
|
+
* carries a LAZY, session-memoized provider that exchanges the token for a
|
|
11
|
+
* gk_tmp_* via the web app's internal endpoint.
|
|
12
|
+
*
|
|
13
|
+
* Drives the REAL server factory (server.ts) over real Streamable HTTP with a
|
|
14
|
+
* stub introspection issuer — only tools/index.handleToolCall is spied, so we
|
|
15
|
+
* can inspect the exact ToolContext the handler builds.
|
|
16
|
+
*/
|
|
17
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
18
|
+
const { handleToolCallSpy } = vi.hoisted(() => ({
|
|
19
|
+
handleToolCallSpy: vi.fn(),
|
|
20
|
+
}));
|
|
21
|
+
vi.mock('../tools/index.js', async (importOriginal) => {
|
|
22
|
+
const actual = await importOriginal();
|
|
23
|
+
return {
|
|
24
|
+
...actual,
|
|
25
|
+
handleToolCall: handleToolCallSpy,
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* Spin up a stub issuer + the real HTTP server, run initialize → tools/call
|
|
30
|
+
* with the given bearer, and return the ToolContext handleToolCall received.
|
|
31
|
+
*/
|
|
32
|
+
async function callToolOverHttp(bearer) {
|
|
33
|
+
const express = (await import('express')).default;
|
|
34
|
+
const { startHttpServer } = await import('../http-server.js');
|
|
35
|
+
const { createServer } = await import('../server.js');
|
|
36
|
+
const issuer = express();
|
|
37
|
+
issuer.use(express.json());
|
|
38
|
+
issuer.post('/oauth/token/introspect', (_req, res) => {
|
|
39
|
+
res.json({
|
|
40
|
+
active: true,
|
|
41
|
+
user_id: 'pu_gw',
|
|
42
|
+
org_id: 'org_gw',
|
|
43
|
+
tenant_id: 'tenant_gw',
|
|
44
|
+
scope: 'mcp:execute mcp:*',
|
|
45
|
+
client_id: 'key_gw',
|
|
46
|
+
exp: Math.floor(Date.now() / 1000) + 3600,
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
const issuerServer = issuer.listen(0);
|
|
50
|
+
const issuerPort = issuerServer.address().port;
|
|
51
|
+
const { server, tokenVerifier } = await startHttpServer({
|
|
52
|
+
port: 0,
|
|
53
|
+
issuerUrl: `http://127.0.0.1:${issuerPort}`,
|
|
54
|
+
mcpPublicUrl: 'http://127.0.0.1:0',
|
|
55
|
+
createMcpServer: () => createServer({ mode: 'http' }),
|
|
56
|
+
});
|
|
57
|
+
const mcpPort = server.address().port;
|
|
58
|
+
const mcpUrl = `http://127.0.0.1:${mcpPort}/mcp`;
|
|
59
|
+
const headers = {
|
|
60
|
+
Authorization: `Bearer ${bearer}`,
|
|
61
|
+
'Content-Type': 'application/json',
|
|
62
|
+
Accept: 'application/json, text/event-stream',
|
|
63
|
+
};
|
|
64
|
+
try {
|
|
65
|
+
const initRes = await fetch(mcpUrl, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers,
|
|
68
|
+
body: JSON.stringify({
|
|
69
|
+
jsonrpc: '2.0',
|
|
70
|
+
id: 1,
|
|
71
|
+
method: 'initialize',
|
|
72
|
+
params: {
|
|
73
|
+
protocolVersion: '2025-03-26',
|
|
74
|
+
capabilities: {},
|
|
75
|
+
clientInfo: { name: 'gw-probe', version: '0' },
|
|
76
|
+
},
|
|
77
|
+
}),
|
|
78
|
+
});
|
|
79
|
+
expect(initRes.status).toBe(200);
|
|
80
|
+
const sessionId = initRes.headers.get('mcp-session-id');
|
|
81
|
+
const callRes = await fetch(mcpUrl, {
|
|
82
|
+
method: 'POST',
|
|
83
|
+
headers: { ...headers, 'Mcp-Session-Id': sessionId },
|
|
84
|
+
body: JSON.stringify({
|
|
85
|
+
jsonrpc: '2.0',
|
|
86
|
+
id: 2,
|
|
87
|
+
method: 'tools/call',
|
|
88
|
+
params: { name: 'create_task', arguments: { title: 'probe' } },
|
|
89
|
+
}),
|
|
90
|
+
});
|
|
91
|
+
expect(callRes.status).toBe(200);
|
|
92
|
+
await callRes.text();
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
tokenVerifier.clearCache();
|
|
96
|
+
server.close();
|
|
97
|
+
issuerServer.close();
|
|
98
|
+
}
|
|
99
|
+
expect(handleToolCallSpy).toHaveBeenCalledTimes(1);
|
|
100
|
+
return handleToolCallSpy.mock.calls[0][2];
|
|
101
|
+
}
|
|
102
|
+
describe('CallTool handler — gateway key by session family (HTTP mode)', () => {
|
|
103
|
+
beforeEach(() => {
|
|
104
|
+
handleToolCallSpy.mockReset().mockResolvedValue({
|
|
105
|
+
content: [{ type: 'text', text: 'ok' }],
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
afterEach(() => {
|
|
109
|
+
vi.unstubAllGlobals();
|
|
110
|
+
vi.unstubAllEnvs();
|
|
111
|
+
});
|
|
112
|
+
it('gk_ Bearer session: context.gatewayKey = the token (pre-check + metering restored)', async () => {
|
|
113
|
+
const context = await callToolOverHttp('gk_user_test_abc');
|
|
114
|
+
expect(context.gatewayKey).toBe('gk_user_test_abc');
|
|
115
|
+
expect(context.client.apiKey).toBe('gk_user_test_abc');
|
|
116
|
+
// gatewayBearer falls back to the apiKey — which IS the gateway key
|
|
117
|
+
expect(await context.client.gatewayBearer()).toBe('gk_user_test_abc');
|
|
118
|
+
});
|
|
119
|
+
it('dobby_at_ (OAuth) session: context.gatewayKey stays undefined', async () => {
|
|
120
|
+
const context = await callToolOverHttp('dobby_at_test_token');
|
|
121
|
+
expect(context.gatewayKey).toBeUndefined();
|
|
122
|
+
expect(context.client.apiKey).toBe('dobby_at_test_token');
|
|
123
|
+
});
|
|
124
|
+
it('dobby_at_ session client lazily resolves a gk_tmp_ via the internal endpoint — memoized', async () => {
|
|
125
|
+
const context = await callToolOverHttp('dobby_at_test_token2');
|
|
126
|
+
// The provider was NOT invoked during the tool call (lazy)
|
|
127
|
+
// — now stub the exchange and resolve it explicitly.
|
|
128
|
+
vi.stubEnv('INTERNAL_SERVICE_SECRET', 'it-secret');
|
|
129
|
+
const fetchMock = vi.fn().mockResolvedValue({
|
|
130
|
+
ok: true,
|
|
131
|
+
json: () => Promise.resolve({
|
|
132
|
+
success: true,
|
|
133
|
+
data: { gateway_key: 'gk_tmp_from_web' },
|
|
134
|
+
}),
|
|
135
|
+
});
|
|
136
|
+
vi.stubGlobal('fetch', fetchMock);
|
|
137
|
+
expect(await context.client.gatewayBearer()).toBe('gk_tmp_from_web');
|
|
138
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
139
|
+
const [url, init] = fetchMock.mock.calls[0];
|
|
140
|
+
expect(String(url)).toContain('/api/v1/internal/mcp/gateway-key');
|
|
141
|
+
expect(init.headers['x-internal-secret']).toBe('it-secret');
|
|
142
|
+
expect(init.headers.Authorization).toBe('Bearer dobby_at_test_token2');
|
|
143
|
+
// Session-memoized: a second resolution reuses the same promise
|
|
144
|
+
expect(await context.client.gatewayBearer()).toBe('gk_tmp_from_web');
|
|
145
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
//# sourceMappingURL=server-gateway-key.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-gateway-key.test.js","sourceRoot":"","sources":["../../src/__tests__/server-gateway-key.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server HTTP-mode User-Scoped PAT Routing Tests (ADR-020 W1b/W1c/W2)
|
|
3
|
+
*
|
|
4
|
+
* A user-scoped PAT (`dobby_pat_*`) carries NO tenant/org pin — the introspect
|
|
5
|
+
* endpoint returns `user_scoped: true` with `tenant_id: null` / `org_id: null`
|
|
6
|
+
* and the AGGREGATE (max) role. The CallTool handler must therefore resolve the
|
|
7
|
+
* per-call target from the tool ARGUMENTS, not from the token:
|
|
8
|
+
*
|
|
9
|
+
* - ORG_CLIENT_TOOLS (memory_store_*, rubric_*, orchestration_config_list) →
|
|
10
|
+
* require an `org_id` arg, which becomes client.organizationId + ctx.orgId;
|
|
11
|
+
* tenantId stays undefined. Missing → helpful error, handleToolCall NOT run.
|
|
12
|
+
* - ORG_ARG_TOOLS (export_policies, validate_policies, apply_guardrail,
|
|
13
|
+
* import_policies) → carry their own `organization_id`; the branch must NOT
|
|
14
|
+
* demand a tenant_id.
|
|
15
|
+
* - everything else is tenant-scoped → require a `tenant_id` arg → ctx.tenantId,
|
|
16
|
+
* plus a per-TENANT-memoized gk_tmp_ provider on the client. Missing → error.
|
|
17
|
+
* - ListTools for a user-scoped session appends the two synthetic discovery
|
|
18
|
+
* tools (list_my_tenants + list_my_orgs); a tenant-pinned session gets neither.
|
|
19
|
+
*
|
|
20
|
+
* Drives the REAL server factory (server.ts) over real Streamable HTTP with a
|
|
21
|
+
* stub introspection issuer — only tools/index.handleToolCall is spied, so we
|
|
22
|
+
* inspect the exact ToolContext the handler built, and we also return the parsed
|
|
23
|
+
* tools/call JSON-RPC result so the "missing arg" branches can assert isError.
|
|
24
|
+
*
|
|
25
|
+
* Fixture note — `tenant_role: 'tenant_owner'` (NOT the plain `'owner'` shown in
|
|
26
|
+
* the ADR-020 ticket example): introspection emits roles in the capability-core
|
|
27
|
+
* vocabulary (web `aggregate-roles.ts` maps DB `owner` → `tenant_owner`), and the
|
|
28
|
+
* MCP role-cap (capability-core `roleCapAllows`) only recognizes `tenant_owner`
|
|
29
|
+
* — `'owner'` is an unknown role and fails the cap (verified), which would make
|
|
30
|
+
* every call hit a role denial before handleToolCall. `tenant_owner` is the real
|
|
31
|
+
* in-band value and satisfies the spec's intent (calls reach handleToolCall).
|
|
32
|
+
*/
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=server-user-scoped.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-user-scoped.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/server-user-scoped.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG"}
|