@vibescope/mcp-server 0.0.1 → 0.1.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 +113 -98
- package/dist/api-client.d.ts +1114 -0
- package/dist/api-client.js +698 -0
- package/dist/cli.d.ts +1 -6
- package/dist/cli.js +39 -240
- package/dist/config/tool-categories.d.ts +31 -0
- package/dist/config/tool-categories.js +253 -0
- package/dist/handlers/blockers.js +57 -58
- package/dist/handlers/bodies-of-work.d.ts +2 -0
- package/dist/handlers/bodies-of-work.js +106 -476
- package/dist/handlers/cost.d.ts +1 -0
- package/dist/handlers/cost.js +35 -113
- package/dist/handlers/decisions.d.ts +2 -0
- package/dist/handlers/decisions.js +28 -27
- package/dist/handlers/deployment.js +112 -828
- package/dist/handlers/discovery.js +31 -0
- package/dist/handlers/fallback.d.ts +2 -0
- package/dist/handlers/fallback.js +39 -134
- package/dist/handlers/findings.js +43 -67
- package/dist/handlers/git-issues.d.ts +9 -13
- package/dist/handlers/git-issues.js +80 -225
- package/dist/handlers/ideas.d.ts +3 -0
- package/dist/handlers/ideas.js +53 -134
- package/dist/handlers/index.d.ts +2 -0
- package/dist/handlers/index.js +6 -0
- package/dist/handlers/milestones.d.ts +2 -0
- package/dist/handlers/milestones.js +51 -98
- package/dist/handlers/organizations.js +79 -275
- package/dist/handlers/progress.d.ts +2 -0
- package/dist/handlers/progress.js +25 -123
- package/dist/handlers/project.js +42 -221
- package/dist/handlers/requests.d.ts +2 -0
- package/dist/handlers/requests.js +23 -83
- package/dist/handlers/session.js +99 -585
- package/dist/handlers/sprints.d.ts +32 -0
- package/dist/handlers/sprints.js +274 -0
- package/dist/handlers/tasks.d.ts +7 -10
- package/dist/handlers/tasks.js +230 -900
- package/dist/handlers/tool-docs.d.ts +8 -0
- package/dist/handlers/tool-docs.js +657 -0
- package/dist/handlers/types.d.ts +11 -3
- package/dist/handlers/validation.d.ts +1 -1
- package/dist/handlers/validation.js +26 -153
- package/dist/index.js +473 -160
- package/dist/knowledge.js +106 -9
- package/dist/tools.js +4 -0
- package/dist/validators.d.ts +21 -0
- package/dist/validators.js +91 -0
- package/package.json +2 -3
- package/src/api-client.ts +1752 -0
- package/src/cli.test.ts +128 -302
- package/src/cli.ts +41 -285
- package/src/handlers/__test-setup__.ts +210 -0
- package/src/handlers/__test-utils__.ts +4 -134
- package/src/handlers/blockers.test.ts +114 -124
- package/src/handlers/blockers.ts +68 -70
- package/src/handlers/bodies-of-work.test.ts +236 -831
- package/src/handlers/bodies-of-work.ts +194 -525
- package/src/handlers/cost.test.ts +149 -113
- package/src/handlers/cost.ts +44 -132
- package/src/handlers/decisions.test.ts +111 -209
- package/src/handlers/decisions.ts +35 -27
- package/src/handlers/deployment.test.ts +193 -239
- package/src/handlers/deployment.ts +140 -895
- package/src/handlers/discovery.test.ts +20 -67
- package/src/handlers/discovery.ts +32 -0
- package/src/handlers/fallback.test.ts +128 -361
- package/src/handlers/fallback.ts +62 -148
- package/src/handlers/findings.test.ts +127 -345
- package/src/handlers/findings.ts +49 -66
- package/src/handlers/git-issues.test.ts +623 -0
- package/src/handlers/git-issues.ts +174 -0
- package/src/handlers/ideas.test.ts +229 -343
- package/src/handlers/ideas.ts +69 -143
- package/src/handlers/index.ts +6 -0
- package/src/handlers/milestones.test.ts +167 -281
- package/src/handlers/milestones.ts +54 -93
- package/src/handlers/organizations.test.ts +275 -467
- package/src/handlers/organizations.ts +84 -294
- package/src/handlers/progress.test.ts +112 -218
- package/src/handlers/progress.ts +29 -142
- package/src/handlers/project.test.ts +203 -226
- package/src/handlers/project.ts +48 -238
- package/src/handlers/requests.test.ts +74 -342
- package/src/handlers/requests.ts +25 -83
- package/src/handlers/session.test.ts +241 -206
- package/src/handlers/session.ts +110 -657
- package/src/handlers/sprints.test.ts +711 -0
- package/src/handlers/sprints.ts +497 -0
- package/src/handlers/tasks.test.ts +608 -353
- package/src/handlers/tasks.ts +248 -1025
- package/src/handlers/types.ts +12 -4
- package/src/handlers/validation.test.ts +189 -572
- package/src/handlers/validation.ts +29 -166
- package/src/index.ts +473 -184
- package/src/knowledge.ts +107 -9
- package/src/tools.ts +2506 -0
- package/src/validators.test.ts +223 -223
- package/src/validators.ts +127 -0
- package/tsconfig.json +1 -1
- package/vitest.config.ts +14 -13
- package/dist/cli.test.d.ts +0 -1
- package/dist/cli.test.js +0 -367
- package/dist/handlers/__test-utils__.d.ts +0 -72
- package/dist/handlers/__test-utils__.js +0 -176
- package/dist/handlers/checkouts.d.ts +0 -37
- package/dist/handlers/checkouts.js +0 -377
- package/dist/handlers/knowledge-query.d.ts +0 -22
- package/dist/handlers/knowledge-query.js +0 -253
- package/dist/handlers/knowledge.d.ts +0 -12
- package/dist/handlers/knowledge.js +0 -108
- package/dist/handlers/roles.d.ts +0 -30
- package/dist/handlers/roles.js +0 -281
- package/dist/handlers/tasks.test.d.ts +0 -1
- package/dist/handlers/tasks.test.js +0 -431
- package/dist/utils.test.d.ts +0 -1
- package/dist/utils.test.js +0 -532
- package/dist/validators.test.d.ts +0 -1
- package/dist/validators.test.js +0 -176
- package/src/tmpclaude-0078-cwd +0 -1
- package/src/tmpclaude-0ee1-cwd +0 -1
- package/src/tmpclaude-2dd5-cwd +0 -1
- package/src/tmpclaude-344c-cwd +0 -1
- package/src/tmpclaude-3860-cwd +0 -1
- package/src/tmpclaude-4b63-cwd +0 -1
- package/src/tmpclaude-5c73-cwd +0 -1
- package/src/tmpclaude-5ee3-cwd +0 -1
- package/src/tmpclaude-6795-cwd +0 -1
- package/src/tmpclaude-709e-cwd +0 -1
- package/src/tmpclaude-9839-cwd +0 -1
- package/src/tmpclaude-d829-cwd +0 -1
- package/src/tmpclaude-e072-cwd +0 -1
- package/src/tmpclaude-f6ee-cwd +0 -1
- package/tmpclaude-0439-cwd +0 -1
- package/tmpclaude-132f-cwd +0 -1
- package/tmpclaude-15bb-cwd +0 -1
- package/tmpclaude-165a-cwd +0 -1
- package/tmpclaude-1ba9-cwd +0 -1
- package/tmpclaude-21a3-cwd +0 -1
- package/tmpclaude-2a38-cwd +0 -1
- package/tmpclaude-2adf-cwd +0 -1
- package/tmpclaude-2f56-cwd +0 -1
- package/tmpclaude-3626-cwd +0 -1
- package/tmpclaude-3727-cwd +0 -1
- package/tmpclaude-40bc-cwd +0 -1
- package/tmpclaude-436f-cwd +0 -1
- package/tmpclaude-4783-cwd +0 -1
- package/tmpclaude-4b6d-cwd +0 -1
- package/tmpclaude-4ba4-cwd +0 -1
- package/tmpclaude-51e6-cwd +0 -1
- package/tmpclaude-5ecf-cwd +0 -1
- package/tmpclaude-6f97-cwd +0 -1
- package/tmpclaude-7fb2-cwd +0 -1
- package/tmpclaude-825c-cwd +0 -1
- package/tmpclaude-8baf-cwd +0 -1
- package/tmpclaude-8d9f-cwd +0 -1
- package/tmpclaude-975c-cwd +0 -1
- package/tmpclaude-9983-cwd +0 -1
- package/tmpclaude-a045-cwd +0 -1
- package/tmpclaude-ac4a-cwd +0 -1
- package/tmpclaude-b593-cwd +0 -1
- package/tmpclaude-b891-cwd +0 -1
- package/tmpclaude-c032-cwd +0 -1
- package/tmpclaude-cf43-cwd +0 -1
- package/tmpclaude-d040-cwd +0 -1
- package/tmpclaude-dcdd-cwd +0 -1
- package/tmpclaude-dcee-cwd +0 -1
- package/tmpclaude-e16b-cwd +0 -1
- package/tmpclaude-ecd2-cwd +0 -1
- package/tmpclaude-f48d-cwd +0 -1
package/src/index.ts
CHANGED
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
ListToolsRequestSchema,
|
|
8
8
|
type Tool,
|
|
9
9
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
10
|
-
import { createClient } from '@supabase/supabase-js';
|
|
11
10
|
import { randomUUID } from 'crypto';
|
|
11
|
+
import { initApiClient, getApiClient } from './api-client.js';
|
|
12
12
|
import {
|
|
13
13
|
ValidationError,
|
|
14
14
|
validateRequired,
|
|
@@ -34,7 +34,6 @@ import {
|
|
|
34
34
|
extractProjectNameFromGitUrl,
|
|
35
35
|
isValidStatusTransition,
|
|
36
36
|
} from './utils.js';
|
|
37
|
-
import { hashApiKey } from './cli.js';
|
|
38
37
|
import { buildHandlerRegistry, type HandlerContext } from './handlers/index.js';
|
|
39
38
|
|
|
40
39
|
// ============================================================================
|
|
@@ -50,6 +49,9 @@ let currentSessionId: string | null = null;
|
|
|
50
49
|
// Assigned persona for this agent instance
|
|
51
50
|
let currentPersona: string | null = null;
|
|
52
51
|
|
|
52
|
+
// Current role for this agent instance
|
|
53
|
+
let currentRole: 'developer' | 'validator' | 'deployer' | 'reviewer' | 'maintainer' | null = null;
|
|
54
|
+
|
|
53
55
|
// Token usage tracking for this session
|
|
54
56
|
interface ModelTokens {
|
|
55
57
|
input: number;
|
|
@@ -589,188 +591,35 @@ interface UserUpdates {
|
|
|
589
591
|
// Configuration
|
|
590
592
|
// ============================================================================
|
|
591
593
|
|
|
592
|
-
// Default Supabase URL for Vibescope production instance
|
|
593
|
-
const DEFAULT_SUPABASE_URL = 'https://uuneucmuubpgswvfijwd.supabase.co';
|
|
594
|
-
|
|
595
|
-
const SUPABASE_URL = process.env.SUPABASE_URL || process.env.PUBLIC_SUPABASE_URL || DEFAULT_SUPABASE_URL;
|
|
596
|
-
const SUPABASE_SERVICE_KEY = process.env.SUPABASE_SERVICE_KEY;
|
|
597
594
|
const API_KEY = process.env.VIBESCOPE_API_KEY;
|
|
598
595
|
|
|
599
|
-
if (!SUPABASE_SERVICE_KEY) {
|
|
600
|
-
console.error('Missing required environment variable: SUPABASE_SERVICE_KEY');
|
|
601
|
-
process.exit(1);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
596
|
if (!API_KEY) {
|
|
605
597
|
console.error('Missing required environment variable: VIBESCOPE_API_KEY');
|
|
606
598
|
process.exit(1);
|
|
607
599
|
}
|
|
608
600
|
|
|
609
|
-
//
|
|
610
|
-
|
|
611
|
-
// ============================================================================
|
|
612
|
-
|
|
613
|
-
// Using untyped client for MCP server - data validation happens at runtime
|
|
614
|
-
const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_KEY);
|
|
601
|
+
// Initialize the API client
|
|
602
|
+
initApiClient({ apiKey: API_KEY });
|
|
615
603
|
|
|
616
604
|
// ============================================================================
|
|
617
605
|
// Authentication
|
|
618
606
|
// ============================================================================
|
|
619
607
|
|
|
620
|
-
async function validateApiKey(
|
|
621
|
-
const
|
|
622
|
-
|
|
623
|
-
const { data, error } = await supabase
|
|
624
|
-
.from('api_keys')
|
|
625
|
-
.select('id, user_id, organization_id, scope, is_valid')
|
|
626
|
-
.eq('key_hash', keyHash)
|
|
627
|
-
.single();
|
|
628
|
-
|
|
629
|
-
if (error || !data) {
|
|
630
|
-
return null;
|
|
631
|
-
}
|
|
608
|
+
async function validateApiKey(): Promise<AuthContext | null> {
|
|
609
|
+
const apiClient = getApiClient();
|
|
610
|
+
const response = await apiClient.validateAuth();
|
|
632
611
|
|
|
633
|
-
|
|
634
|
-
if (data.is_valid === false) {
|
|
612
|
+
if (!response.ok || !response.data?.valid) {
|
|
635
613
|
return null;
|
|
636
614
|
}
|
|
637
615
|
|
|
638
|
-
// For org-scoped keys, verify user is still a member
|
|
639
|
-
if (data.scope === 'organization' && data.organization_id) {
|
|
640
|
-
const { data: member } = await supabase
|
|
641
|
-
.from('organization_members')
|
|
642
|
-
.select('role')
|
|
643
|
-
.eq('organization_id', data.organization_id)
|
|
644
|
-
.eq('user_id', data.user_id)
|
|
645
|
-
.single();
|
|
646
|
-
|
|
647
|
-
if (!member) {
|
|
648
|
-
// User is no longer a member, invalidate the key
|
|
649
|
-
await supabase
|
|
650
|
-
.from('api_keys')
|
|
651
|
-
.update({ is_valid: false })
|
|
652
|
-
.eq('id', data.id);
|
|
653
|
-
return null;
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
// Update last_used_at
|
|
658
|
-
await supabase
|
|
659
|
-
.from('api_keys')
|
|
660
|
-
.update({ last_used_at: new Date().toISOString() })
|
|
661
|
-
.eq('id', data.id);
|
|
662
|
-
|
|
663
616
|
return {
|
|
664
|
-
userId: data.user_id,
|
|
665
|
-
apiKeyId: data.
|
|
666
|
-
|
|
667
|
-
scope: data.scope || 'personal',
|
|
617
|
+
userId: response.data.user_id,
|
|
618
|
+
apiKeyId: response.data.api_key_id,
|
|
619
|
+
scope: 'personal', // API handles authorization, scope not needed locally
|
|
668
620
|
};
|
|
669
621
|
}
|
|
670
622
|
|
|
671
|
-
// ============================================================================
|
|
672
|
-
// Session Status Checking (Multi-Agent Coordination)
|
|
673
|
-
// ============================================================================
|
|
674
|
-
|
|
675
|
-
/**
|
|
676
|
-
* Check if an agent session is active or stale.
|
|
677
|
-
* A session is considered stale if:
|
|
678
|
-
* - It doesn't exist (orphaned reference)
|
|
679
|
-
* - Its status is 'disconnected'
|
|
680
|
-
* - Its last_synced_at is older than 5 minutes
|
|
681
|
-
*/
|
|
682
|
-
async function checkSessionStatus(
|
|
683
|
-
sessionId: string
|
|
684
|
-
): Promise<{ exists: boolean; isActive: boolean; agentName?: string }> {
|
|
685
|
-
const { data: session } = await supabase
|
|
686
|
-
.from('agent_sessions')
|
|
687
|
-
.select('id, status, last_synced_at, agent_name, instance_id')
|
|
688
|
-
.eq('id', sessionId)
|
|
689
|
-
.single();
|
|
690
|
-
|
|
691
|
-
if (!session) {
|
|
692
|
-
return { exists: false, isActive: false };
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
const lastSync = new Date(session.last_synced_at).getTime();
|
|
696
|
-
const fiveMinutesAgo = Date.now() - 5 * 60 * 1000;
|
|
697
|
-
const isActive = session.status !== 'disconnected' && lastSync > fiveMinutesAgo;
|
|
698
|
-
|
|
699
|
-
return {
|
|
700
|
-
exists: true,
|
|
701
|
-
isActive,
|
|
702
|
-
agentName: session.agent_name || `Agent ${session.instance_id?.slice(0, 8) || sessionId.slice(0, 8)}`,
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
// ============================================================================
|
|
707
|
-
// User Updates Tracking
|
|
708
|
-
// ============================================================================
|
|
709
|
-
|
|
710
|
-
async function getUserUpdates(
|
|
711
|
-
auth: AuthContext,
|
|
712
|
-
projectId: string
|
|
713
|
-
): Promise<UserUpdates | undefined> {
|
|
714
|
-
// Get session's last_synced_at - prefer currentSessionId for accuracy
|
|
715
|
-
let lastSyncedAt: string;
|
|
716
|
-
|
|
717
|
-
if (currentSessionId) {
|
|
718
|
-
const { data: session } = await supabase
|
|
719
|
-
.from('agent_sessions')
|
|
720
|
-
.select('last_synced_at')
|
|
721
|
-
.eq('id', currentSessionId)
|
|
722
|
-
.single();
|
|
723
|
-
lastSyncedAt = session?.last_synced_at || new Date(0).toISOString();
|
|
724
|
-
} else {
|
|
725
|
-
const { data: session } = await supabase
|
|
726
|
-
.from('agent_sessions')
|
|
727
|
-
.select('last_synced_at')
|
|
728
|
-
.eq('api_key_id', auth.apiKeyId)
|
|
729
|
-
.eq('project_id', projectId)
|
|
730
|
-
.single();
|
|
731
|
-
lastSyncedAt = session?.last_synced_at || new Date(0).toISOString();
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
// Fetch user-created items since last sync (limit to 5 each for context efficiency)
|
|
735
|
-
const [tasksResult, blockersResult, ideasResult] = await Promise.all([
|
|
736
|
-
supabase
|
|
737
|
-
.from('tasks')
|
|
738
|
-
.select('id, title, created_at')
|
|
739
|
-
.eq('project_id', projectId)
|
|
740
|
-
.eq('created_by', 'user')
|
|
741
|
-
.gt('created_at', lastSyncedAt)
|
|
742
|
-
.order('created_at', { ascending: false })
|
|
743
|
-
.limit(5),
|
|
744
|
-
supabase
|
|
745
|
-
.from('blockers')
|
|
746
|
-
.select('id, description, created_at')
|
|
747
|
-
.eq('project_id', projectId)
|
|
748
|
-
.eq('created_by', 'user')
|
|
749
|
-
.gt('created_at', lastSyncedAt)
|
|
750
|
-
.order('created_at', { ascending: false })
|
|
751
|
-
.limit(5),
|
|
752
|
-
supabase
|
|
753
|
-
.from('ideas')
|
|
754
|
-
.select('id, title, created_at')
|
|
755
|
-
.eq('project_id', projectId)
|
|
756
|
-
.eq('created_by', 'user')
|
|
757
|
-
.gt('created_at', lastSyncedAt)
|
|
758
|
-
.order('created_at', { ascending: false })
|
|
759
|
-
.limit(5),
|
|
760
|
-
]);
|
|
761
|
-
|
|
762
|
-
const tasks = tasksResult.data || [];
|
|
763
|
-
const blockers = blockersResult.data || [];
|
|
764
|
-
const ideas = ideasResult.data || [];
|
|
765
|
-
|
|
766
|
-
// Return undefined if no new updates (saves context window space)
|
|
767
|
-
if (tasks.length === 0 && blockers.length === 0 && ideas.length === 0) {
|
|
768
|
-
return undefined;
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
return { tasks, blockers, ideas };
|
|
772
|
-
}
|
|
773
|
-
|
|
774
623
|
// ============================================================================
|
|
775
624
|
// Tool Definitions
|
|
776
625
|
// ============================================================================
|
|
@@ -812,7 +661,7 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
812
661
|
properties: {
|
|
813
662
|
topic: {
|
|
814
663
|
type: 'string',
|
|
815
|
-
enum: ['getting_started', 'tasks', 'validation', 'deployment', 'git', 'blockers', 'milestones', 'fallback', 'session', 'tokens', 'topics'],
|
|
664
|
+
enum: ['getting_started', 'tasks', 'validation', 'deployment', 'git', 'blockers', 'milestones', 'fallback', 'session', 'tokens', 'sprints', 'topics'],
|
|
816
665
|
description: 'Help topic. Use "topics" to list all available.',
|
|
817
666
|
},
|
|
818
667
|
},
|
|
@@ -1138,6 +987,14 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1138
987
|
type: 'number',
|
|
1139
988
|
description: 'Max number of tasks to return (default 50)',
|
|
1140
989
|
},
|
|
990
|
+
offset: {
|
|
991
|
+
type: 'number',
|
|
992
|
+
description: 'Number of tasks to skip for pagination (default 0)',
|
|
993
|
+
},
|
|
994
|
+
search_query: {
|
|
995
|
+
type: 'string',
|
|
996
|
+
description: 'Search tasks by title',
|
|
997
|
+
},
|
|
1141
998
|
include_subtasks: {
|
|
1142
999
|
type: 'boolean',
|
|
1143
1000
|
description: 'Include subtasks in results (default false). Use get_subtasks for subtasks of a specific task.',
|
|
@@ -1193,6 +1050,11 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1193
1050
|
type: 'boolean',
|
|
1194
1051
|
description: 'When true, this task blocks all other work until complete (used for deployment finalization)',
|
|
1195
1052
|
},
|
|
1053
|
+
task_type: {
|
|
1054
|
+
type: 'string',
|
|
1055
|
+
enum: ['frontend', 'backend', 'database', 'mcp', 'testing', 'docs', 'infra', 'other'],
|
|
1056
|
+
description: 'Task category for visual grouping (frontend, backend, database, mcp, testing, docs, infra, other)',
|
|
1057
|
+
},
|
|
1196
1058
|
},
|
|
1197
1059
|
required: ['project_id', 'title'],
|
|
1198
1060
|
},
|
|
@@ -1237,6 +1099,11 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1237
1099
|
type: 'string',
|
|
1238
1100
|
description: 'Git branch associated with this task',
|
|
1239
1101
|
},
|
|
1102
|
+
task_type: {
|
|
1103
|
+
type: 'string',
|
|
1104
|
+
enum: ['frontend', 'backend', 'database', 'mcp', 'testing', 'docs', 'infra', 'other'],
|
|
1105
|
+
description: 'Task category (frontend, backend, database, mcp, testing, docs, infra, other)',
|
|
1106
|
+
},
|
|
1240
1107
|
},
|
|
1241
1108
|
required: ['task_id'],
|
|
1242
1109
|
},
|
|
@@ -1336,6 +1203,18 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1336
1203
|
enum: ['open', 'resolved'],
|
|
1337
1204
|
description: 'Filter by status (default: open)',
|
|
1338
1205
|
},
|
|
1206
|
+
limit: {
|
|
1207
|
+
type: 'number',
|
|
1208
|
+
description: 'Max number of blockers to return (default 50, max 200)',
|
|
1209
|
+
},
|
|
1210
|
+
offset: {
|
|
1211
|
+
type: 'number',
|
|
1212
|
+
description: 'Number of blockers to skip for pagination (default 0)',
|
|
1213
|
+
},
|
|
1214
|
+
search_query: {
|
|
1215
|
+
type: 'string',
|
|
1216
|
+
description: 'Search blockers by description',
|
|
1217
|
+
},
|
|
1339
1218
|
},
|
|
1340
1219
|
required: ['project_id'],
|
|
1341
1220
|
},
|
|
@@ -1381,6 +1260,18 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1381
1260
|
type: 'string',
|
|
1382
1261
|
description: 'Project UUID',
|
|
1383
1262
|
},
|
|
1263
|
+
limit: {
|
|
1264
|
+
type: 'number',
|
|
1265
|
+
description: 'Max number of decisions to return (default 50, max 200)',
|
|
1266
|
+
},
|
|
1267
|
+
offset: {
|
|
1268
|
+
type: 'number',
|
|
1269
|
+
description: 'Number of decisions to skip for pagination (default 0)',
|
|
1270
|
+
},
|
|
1271
|
+
search_query: {
|
|
1272
|
+
type: 'string',
|
|
1273
|
+
description: 'Search decisions by title or description',
|
|
1274
|
+
},
|
|
1384
1275
|
},
|
|
1385
1276
|
required: ['project_id'],
|
|
1386
1277
|
},
|
|
@@ -1458,6 +1349,18 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1458
1349
|
enum: ['raw', 'exploring', 'planned', 'in_development', 'shipped'],
|
|
1459
1350
|
description: 'Filter by status (optional)',
|
|
1460
1351
|
},
|
|
1352
|
+
limit: {
|
|
1353
|
+
type: 'number',
|
|
1354
|
+
description: 'Max number of ideas to return (default 50, max 100)',
|
|
1355
|
+
},
|
|
1356
|
+
offset: {
|
|
1357
|
+
type: 'number',
|
|
1358
|
+
description: 'Number of ideas to skip for pagination (default 0)',
|
|
1359
|
+
},
|
|
1360
|
+
search_query: {
|
|
1361
|
+
type: 'string',
|
|
1362
|
+
description: 'Search ideas by title or description',
|
|
1363
|
+
},
|
|
1461
1364
|
},
|
|
1462
1365
|
required: ['project_id'],
|
|
1463
1366
|
},
|
|
@@ -1588,7 +1491,9 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1588
1491
|
category: { type: 'string', enum: ['performance', 'security', 'code_quality', 'accessibility', 'documentation', 'architecture', 'testing', 'other'], description: 'Filter by category (optional)' },
|
|
1589
1492
|
severity: { type: 'string', enum: ['info', 'low', 'medium', 'high', 'critical'], description: 'Filter by severity (optional)' },
|
|
1590
1493
|
status: { type: 'string', enum: ['open', 'addressed', 'dismissed', 'wontfix'], description: 'Filter by status (default: all)' },
|
|
1591
|
-
limit: { type: 'number', description: 'Max number of findings to return (default 50)' },
|
|
1494
|
+
limit: { type: 'number', description: 'Max number of findings to return (default 50, max 200)' },
|
|
1495
|
+
offset: { type: 'number', description: 'Number of findings to skip for pagination (default 0)' },
|
|
1496
|
+
search_query: { type: 'string', description: 'Search findings by title or description' },
|
|
1592
1497
|
},
|
|
1593
1498
|
required: ['project_id'],
|
|
1594
1499
|
},
|
|
@@ -1634,6 +1539,119 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1634
1539
|
required: ['blocker_id'],
|
|
1635
1540
|
},
|
|
1636
1541
|
},
|
|
1542
|
+
// Git Issues tools
|
|
1543
|
+
{
|
|
1544
|
+
name: 'add_git_issue',
|
|
1545
|
+
description: `Record a git-related issue (merge conflict, push failure, etc.). Auto-created by claim_validation when conflicts detected.`,
|
|
1546
|
+
inputSchema: {
|
|
1547
|
+
type: 'object',
|
|
1548
|
+
properties: {
|
|
1549
|
+
project_id: {
|
|
1550
|
+
type: 'string',
|
|
1551
|
+
description: 'Project UUID',
|
|
1552
|
+
},
|
|
1553
|
+
issue_type: {
|
|
1554
|
+
type: 'string',
|
|
1555
|
+
enum: ['merge_conflict', 'push_failed', 'rebase_needed', 'branch_diverged', 'pr_not_mergeable'],
|
|
1556
|
+
description: 'Type of git issue',
|
|
1557
|
+
},
|
|
1558
|
+
branch: {
|
|
1559
|
+
type: 'string',
|
|
1560
|
+
description: 'Branch where the issue occurred',
|
|
1561
|
+
},
|
|
1562
|
+
target_branch: {
|
|
1563
|
+
type: 'string',
|
|
1564
|
+
description: 'Target branch for merge/rebase (optional)',
|
|
1565
|
+
},
|
|
1566
|
+
pr_url: {
|
|
1567
|
+
type: 'string',
|
|
1568
|
+
description: 'Pull request URL if applicable (optional)',
|
|
1569
|
+
},
|
|
1570
|
+
conflicting_files: {
|
|
1571
|
+
type: 'array',
|
|
1572
|
+
items: { type: 'string' },
|
|
1573
|
+
description: 'List of files with conflicts (optional)',
|
|
1574
|
+
},
|
|
1575
|
+
error_message: {
|
|
1576
|
+
type: 'string',
|
|
1577
|
+
description: 'Error message from git operation (optional)',
|
|
1578
|
+
},
|
|
1579
|
+
task_id: {
|
|
1580
|
+
type: 'string',
|
|
1581
|
+
description: 'Related task UUID (optional)',
|
|
1582
|
+
},
|
|
1583
|
+
},
|
|
1584
|
+
required: ['project_id', 'issue_type', 'branch'],
|
|
1585
|
+
},
|
|
1586
|
+
},
|
|
1587
|
+
{
|
|
1588
|
+
name: 'resolve_git_issue',
|
|
1589
|
+
description: `Mark a git issue as resolved.`,
|
|
1590
|
+
inputSchema: {
|
|
1591
|
+
type: 'object',
|
|
1592
|
+
properties: {
|
|
1593
|
+
git_issue_id: {
|
|
1594
|
+
type: 'string',
|
|
1595
|
+
description: 'Git issue UUID',
|
|
1596
|
+
},
|
|
1597
|
+
resolution_note: {
|
|
1598
|
+
type: 'string',
|
|
1599
|
+
description: 'How the issue was resolved (optional)',
|
|
1600
|
+
},
|
|
1601
|
+
auto_resolved: {
|
|
1602
|
+
type: 'boolean',
|
|
1603
|
+
description: 'Whether this was auto-resolved (e.g., PR became mergeable)',
|
|
1604
|
+
},
|
|
1605
|
+
},
|
|
1606
|
+
required: ['git_issue_id'],
|
|
1607
|
+
},
|
|
1608
|
+
},
|
|
1609
|
+
{
|
|
1610
|
+
name: 'get_git_issues',
|
|
1611
|
+
description: `Get git issues for a project, optionally filtered by status, type, or branch.`,
|
|
1612
|
+
inputSchema: {
|
|
1613
|
+
type: 'object',
|
|
1614
|
+
properties: {
|
|
1615
|
+
project_id: {
|
|
1616
|
+
type: 'string',
|
|
1617
|
+
description: 'Project UUID',
|
|
1618
|
+
},
|
|
1619
|
+
status: {
|
|
1620
|
+
type: 'string',
|
|
1621
|
+
enum: ['open', 'resolved'],
|
|
1622
|
+
description: 'Filter by status (default: open)',
|
|
1623
|
+
},
|
|
1624
|
+
issue_type: {
|
|
1625
|
+
type: 'string',
|
|
1626
|
+
enum: ['merge_conflict', 'push_failed', 'rebase_needed', 'branch_diverged', 'pr_not_mergeable'],
|
|
1627
|
+
description: 'Filter by issue type (optional)',
|
|
1628
|
+
},
|
|
1629
|
+
branch: {
|
|
1630
|
+
type: 'string',
|
|
1631
|
+
description: 'Filter by branch (optional)',
|
|
1632
|
+
},
|
|
1633
|
+
limit: {
|
|
1634
|
+
type: 'number',
|
|
1635
|
+
description: 'Max issues to return (default: 50)',
|
|
1636
|
+
},
|
|
1637
|
+
},
|
|
1638
|
+
required: ['project_id'],
|
|
1639
|
+
},
|
|
1640
|
+
},
|
|
1641
|
+
{
|
|
1642
|
+
name: 'delete_git_issue',
|
|
1643
|
+
description: `Delete a git issue.`,
|
|
1644
|
+
inputSchema: {
|
|
1645
|
+
type: 'object',
|
|
1646
|
+
properties: {
|
|
1647
|
+
git_issue_id: {
|
|
1648
|
+
type: 'string',
|
|
1649
|
+
description: 'Git issue UUID',
|
|
1650
|
+
},
|
|
1651
|
+
},
|
|
1652
|
+
required: ['git_issue_id'],
|
|
1653
|
+
},
|
|
1654
|
+
},
|
|
1637
1655
|
{
|
|
1638
1656
|
name: 'delete_decision',
|
|
1639
1657
|
description: `Delete a decision.`,
|
|
@@ -2598,6 +2616,18 @@ Bodies of work allow organizing related tasks with optional auto-deployment on c
|
|
|
2598
2616
|
enum: ['draft', 'active', 'completed', 'cancelled'],
|
|
2599
2617
|
description: 'Filter by status (optional)',
|
|
2600
2618
|
},
|
|
2619
|
+
limit: {
|
|
2620
|
+
type: 'number',
|
|
2621
|
+
description: 'Max number of bodies of work to return (default 50, max 100)',
|
|
2622
|
+
},
|
|
2623
|
+
offset: {
|
|
2624
|
+
type: 'number',
|
|
2625
|
+
description: 'Number of items to skip for pagination (default 0)',
|
|
2626
|
+
},
|
|
2627
|
+
search_query: {
|
|
2628
|
+
type: 'string',
|
|
2629
|
+
description: 'Search bodies of work by title or description',
|
|
2630
|
+
},
|
|
2601
2631
|
},
|
|
2602
2632
|
required: ['project_id'],
|
|
2603
2633
|
},
|
|
@@ -2748,6 +2778,273 @@ Only returns tasks where all dependencies are completed.`,
|
|
|
2748
2778
|
},
|
|
2749
2779
|
},
|
|
2750
2780
|
// ============================================================================
|
|
2781
|
+
// Sprint Tools
|
|
2782
|
+
// ============================================================================
|
|
2783
|
+
{
|
|
2784
|
+
name: 'create_sprint',
|
|
2785
|
+
description: `Create a new sprint. Sprints are time-bounded bodies of work with velocity tracking.
|
|
2786
|
+
Sprints start in 'planning' status where tasks can be added with story points.`,
|
|
2787
|
+
inputSchema: {
|
|
2788
|
+
type: 'object',
|
|
2789
|
+
properties: {
|
|
2790
|
+
project_id: {
|
|
2791
|
+
type: 'string',
|
|
2792
|
+
description: 'Project UUID',
|
|
2793
|
+
},
|
|
2794
|
+
title: {
|
|
2795
|
+
type: 'string',
|
|
2796
|
+
description: 'Sprint title (e.g., "Sprint 5" or "Q1 Release")',
|
|
2797
|
+
},
|
|
2798
|
+
goal: {
|
|
2799
|
+
type: 'string',
|
|
2800
|
+
description: 'Sprint goal statement',
|
|
2801
|
+
},
|
|
2802
|
+
start_date: {
|
|
2803
|
+
type: 'string',
|
|
2804
|
+
description: 'Start date (YYYY-MM-DD)',
|
|
2805
|
+
},
|
|
2806
|
+
end_date: {
|
|
2807
|
+
type: 'string',
|
|
2808
|
+
description: 'End date (YYYY-MM-DD)',
|
|
2809
|
+
},
|
|
2810
|
+
auto_deploy_on_completion: {
|
|
2811
|
+
type: 'boolean',
|
|
2812
|
+
description: 'Automatically request deployment when sprint completes (default: false)',
|
|
2813
|
+
},
|
|
2814
|
+
deploy_environment: {
|
|
2815
|
+
type: 'string',
|
|
2816
|
+
enum: ['development', 'staging', 'production'],
|
|
2817
|
+
description: 'Target environment for auto-deploy (default: production)',
|
|
2818
|
+
},
|
|
2819
|
+
deploy_version_bump: {
|
|
2820
|
+
type: 'string',
|
|
2821
|
+
enum: ['patch', 'minor', 'major'],
|
|
2822
|
+
description: 'Version bump for auto-deploy (default: minor)',
|
|
2823
|
+
},
|
|
2824
|
+
},
|
|
2825
|
+
required: ['project_id', 'title', 'start_date', 'end_date'],
|
|
2826
|
+
},
|
|
2827
|
+
},
|
|
2828
|
+
{
|
|
2829
|
+
name: 'update_sprint',
|
|
2830
|
+
description: `Update a sprint's details. Can update title, goal, dates, and deployment settings.`,
|
|
2831
|
+
inputSchema: {
|
|
2832
|
+
type: 'object',
|
|
2833
|
+
properties: {
|
|
2834
|
+
sprint_id: {
|
|
2835
|
+
type: 'string',
|
|
2836
|
+
description: 'Sprint UUID',
|
|
2837
|
+
},
|
|
2838
|
+
title: {
|
|
2839
|
+
type: 'string',
|
|
2840
|
+
description: 'New sprint title',
|
|
2841
|
+
},
|
|
2842
|
+
goal: {
|
|
2843
|
+
type: 'string',
|
|
2844
|
+
description: 'New sprint goal',
|
|
2845
|
+
},
|
|
2846
|
+
start_date: {
|
|
2847
|
+
type: 'string',
|
|
2848
|
+
description: 'New start date (YYYY-MM-DD)',
|
|
2849
|
+
},
|
|
2850
|
+
end_date: {
|
|
2851
|
+
type: 'string',
|
|
2852
|
+
description: 'New end date (YYYY-MM-DD)',
|
|
2853
|
+
},
|
|
2854
|
+
auto_deploy_on_completion: {
|
|
2855
|
+
type: 'boolean',
|
|
2856
|
+
description: 'Auto-deploy setting',
|
|
2857
|
+
},
|
|
2858
|
+
deploy_environment: {
|
|
2859
|
+
type: 'string',
|
|
2860
|
+
enum: ['development', 'staging', 'production'],
|
|
2861
|
+
description: 'Target environment',
|
|
2862
|
+
},
|
|
2863
|
+
deploy_version_bump: {
|
|
2864
|
+
type: 'string',
|
|
2865
|
+
enum: ['patch', 'minor', 'major'],
|
|
2866
|
+
description: 'Version bump type',
|
|
2867
|
+
},
|
|
2868
|
+
},
|
|
2869
|
+
required: ['sprint_id'],
|
|
2870
|
+
},
|
|
2871
|
+
},
|
|
2872
|
+
{
|
|
2873
|
+
name: 'get_sprint',
|
|
2874
|
+
description: `Get a sprint with all its tasks organized by phase (pre/core/post).
|
|
2875
|
+
Includes progress percentage, velocity points, and committed points.`,
|
|
2876
|
+
inputSchema: {
|
|
2877
|
+
type: 'object',
|
|
2878
|
+
properties: {
|
|
2879
|
+
sprint_id: {
|
|
2880
|
+
type: 'string',
|
|
2881
|
+
description: 'Sprint UUID',
|
|
2882
|
+
},
|
|
2883
|
+
},
|
|
2884
|
+
required: ['sprint_id'],
|
|
2885
|
+
},
|
|
2886
|
+
},
|
|
2887
|
+
{
|
|
2888
|
+
name: 'get_sprints',
|
|
2889
|
+
description: `List sprints for a project with velocity metrics.
|
|
2890
|
+
Returns sprints sorted by sprint_number descending (most recent first).`,
|
|
2891
|
+
inputSchema: {
|
|
2892
|
+
type: 'object',
|
|
2893
|
+
properties: {
|
|
2894
|
+
project_id: {
|
|
2895
|
+
type: 'string',
|
|
2896
|
+
description: 'Project UUID',
|
|
2897
|
+
},
|
|
2898
|
+
status: {
|
|
2899
|
+
type: 'string',
|
|
2900
|
+
enum: ['planning', 'active', 'in_review', 'retrospective', 'completed', 'cancelled'],
|
|
2901
|
+
description: 'Filter by sprint status (optional)',
|
|
2902
|
+
},
|
|
2903
|
+
limit: {
|
|
2904
|
+
type: 'number',
|
|
2905
|
+
description: 'Max sprints to return (default: 20, max: 100)',
|
|
2906
|
+
},
|
|
2907
|
+
},
|
|
2908
|
+
required: ['project_id'],
|
|
2909
|
+
},
|
|
2910
|
+
},
|
|
2911
|
+
{
|
|
2912
|
+
name: 'delete_sprint',
|
|
2913
|
+
description: `Delete a sprint. Tasks are preserved but no longer grouped.`,
|
|
2914
|
+
inputSchema: {
|
|
2915
|
+
type: 'object',
|
|
2916
|
+
properties: {
|
|
2917
|
+
sprint_id: {
|
|
2918
|
+
type: 'string',
|
|
2919
|
+
description: 'Sprint UUID',
|
|
2920
|
+
},
|
|
2921
|
+
},
|
|
2922
|
+
required: ['sprint_id'],
|
|
2923
|
+
},
|
|
2924
|
+
},
|
|
2925
|
+
{
|
|
2926
|
+
name: 'start_sprint',
|
|
2927
|
+
description: `Start a sprint. Transitions from 'planning' to 'active' status.
|
|
2928
|
+
Locks the committed_points at the current total story points.`,
|
|
2929
|
+
inputSchema: {
|
|
2930
|
+
type: 'object',
|
|
2931
|
+
properties: {
|
|
2932
|
+
sprint_id: {
|
|
2933
|
+
type: 'string',
|
|
2934
|
+
description: 'Sprint UUID',
|
|
2935
|
+
},
|
|
2936
|
+
},
|
|
2937
|
+
required: ['sprint_id'],
|
|
2938
|
+
},
|
|
2939
|
+
},
|
|
2940
|
+
{
|
|
2941
|
+
name: 'complete_sprint',
|
|
2942
|
+
description: `Complete a sprint. Handles retrospective phase and auto-deployment if configured.
|
|
2943
|
+
Status flow: active → in_review → retrospective → completed`,
|
|
2944
|
+
inputSchema: {
|
|
2945
|
+
type: 'object',
|
|
2946
|
+
properties: {
|
|
2947
|
+
sprint_id: {
|
|
2948
|
+
type: 'string',
|
|
2949
|
+
description: 'Sprint UUID',
|
|
2950
|
+
},
|
|
2951
|
+
retrospective_notes: {
|
|
2952
|
+
type: 'string',
|
|
2953
|
+
description: 'Sprint retrospective notes',
|
|
2954
|
+
},
|
|
2955
|
+
skip_retrospective: {
|
|
2956
|
+
type: 'boolean',
|
|
2957
|
+
description: 'Skip retrospective phase and go directly to completed (default: false)',
|
|
2958
|
+
},
|
|
2959
|
+
},
|
|
2960
|
+
required: ['sprint_id'],
|
|
2961
|
+
},
|
|
2962
|
+
},
|
|
2963
|
+
{
|
|
2964
|
+
name: 'add_task_to_sprint',
|
|
2965
|
+
description: `Add a task to a sprint with optional story points.
|
|
2966
|
+
Tasks can be added during 'planning' status. Story points contribute to committed_points.`,
|
|
2967
|
+
inputSchema: {
|
|
2968
|
+
type: 'object',
|
|
2969
|
+
properties: {
|
|
2970
|
+
sprint_id: {
|
|
2971
|
+
type: 'string',
|
|
2972
|
+
description: 'Sprint UUID',
|
|
2973
|
+
},
|
|
2974
|
+
task_id: {
|
|
2975
|
+
type: 'string',
|
|
2976
|
+
description: 'Task UUID to add',
|
|
2977
|
+
},
|
|
2978
|
+
story_points: {
|
|
2979
|
+
type: 'number',
|
|
2980
|
+
description: 'Story point estimate (optional, must be non-negative integer)',
|
|
2981
|
+
},
|
|
2982
|
+
phase: {
|
|
2983
|
+
type: 'string',
|
|
2984
|
+
enum: ['pre', 'core', 'post'],
|
|
2985
|
+
description: 'Task phase (default: core)',
|
|
2986
|
+
},
|
|
2987
|
+
},
|
|
2988
|
+
required: ['sprint_id', 'task_id'],
|
|
2989
|
+
},
|
|
2990
|
+
},
|
|
2991
|
+
{
|
|
2992
|
+
name: 'remove_task_from_sprint',
|
|
2993
|
+
description: `Remove a task from a sprint. Task is preserved but returns to backlog.`,
|
|
2994
|
+
inputSchema: {
|
|
2995
|
+
type: 'object',
|
|
2996
|
+
properties: {
|
|
2997
|
+
sprint_id: {
|
|
2998
|
+
type: 'string',
|
|
2999
|
+
description: 'Sprint UUID',
|
|
3000
|
+
},
|
|
3001
|
+
task_id: {
|
|
3002
|
+
type: 'string',
|
|
3003
|
+
description: 'Task UUID to remove',
|
|
3004
|
+
},
|
|
3005
|
+
},
|
|
3006
|
+
required: ['sprint_id', 'task_id'],
|
|
3007
|
+
},
|
|
3008
|
+
},
|
|
3009
|
+
{
|
|
3010
|
+
name: 'get_sprint_backlog',
|
|
3011
|
+
description: `Get tasks from backlog/pending that can be added to a sprint.
|
|
3012
|
+
Returns tasks not already assigned to any body of work or sprint.`,
|
|
3013
|
+
inputSchema: {
|
|
3014
|
+
type: 'object',
|
|
3015
|
+
properties: {
|
|
3016
|
+
project_id: {
|
|
3017
|
+
type: 'string',
|
|
3018
|
+
description: 'Project UUID',
|
|
3019
|
+
},
|
|
3020
|
+
sprint_id: {
|
|
3021
|
+
type: 'string',
|
|
3022
|
+
description: 'Sprint UUID to exclude already-added tasks (optional)',
|
|
3023
|
+
},
|
|
3024
|
+
},
|
|
3025
|
+
required: ['project_id'],
|
|
3026
|
+
},
|
|
3027
|
+
},
|
|
3028
|
+
{
|
|
3029
|
+
name: 'get_sprint_velocity',
|
|
3030
|
+
description: `Get velocity metrics for completed sprints.
|
|
3031
|
+
Returns committed vs completed points and average velocity.`,
|
|
3032
|
+
inputSchema: {
|
|
3033
|
+
type: 'object',
|
|
3034
|
+
properties: {
|
|
3035
|
+
project_id: {
|
|
3036
|
+
type: 'string',
|
|
3037
|
+
description: 'Project UUID',
|
|
3038
|
+
},
|
|
3039
|
+
limit: {
|
|
3040
|
+
type: 'number',
|
|
3041
|
+
description: 'Number of sprints to analyze (default: 10, max: 50)',
|
|
3042
|
+
},
|
|
3043
|
+
},
|
|
3044
|
+
required: ['project_id'],
|
|
3045
|
+
},
|
|
3046
|
+
},
|
|
3047
|
+
// ============================================================================
|
|
2751
3048
|
// Organization Tools
|
|
2752
3049
|
// ============================================================================
|
|
2753
3050
|
{
|
|
@@ -3001,24 +3298,15 @@ async function handleTool(
|
|
|
3001
3298
|
name: string,
|
|
3002
3299
|
args: Record<string, unknown>
|
|
3003
3300
|
): Promise<{ result: unknown; user_updates?: UserUpdates; reminder?: string }> {
|
|
3004
|
-
// Update session on every tool call:
|
|
3301
|
+
// Update session on every tool call via API:
|
|
3005
3302
|
// - last_synced_at: keeps session alive and visible as "active" on dashboard
|
|
3006
|
-
// -
|
|
3007
|
-
// - last_tool_at: timestamp of last tool call
|
|
3303
|
+
// - token tracking: synced periodically for cost monitoring
|
|
3008
3304
|
// Skip for start_work_session since it handles its own session setup
|
|
3009
3305
|
if (currentSessionId && name !== 'start_work_session') {
|
|
3010
|
-
const
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
}).then(({ error }) => {
|
|
3015
|
-
// Fallback to direct update if RPC doesn't exist (pre-migration)
|
|
3016
|
-
if (error) {
|
|
3017
|
-
return supabase
|
|
3018
|
-
.from('agent_sessions')
|
|
3019
|
-
.update({ last_synced_at: now })
|
|
3020
|
-
.eq('id', currentSessionId);
|
|
3021
|
-
}
|
|
3306
|
+
const apiClient = getApiClient();
|
|
3307
|
+
// Fire and forget - don't block tool execution on session sync
|
|
3308
|
+
apiClient.syncSession(currentSessionId).catch(() => {
|
|
3309
|
+
// Silently ignore sync errors - session tracking is non-critical
|
|
3022
3310
|
});
|
|
3023
3311
|
}
|
|
3024
3312
|
|
|
@@ -3027,17 +3315,18 @@ async function handleTool(
|
|
|
3027
3315
|
if (handler) {
|
|
3028
3316
|
// Build handler context
|
|
3029
3317
|
const ctx: HandlerContext = {
|
|
3030
|
-
supabase,
|
|
3031
3318
|
auth,
|
|
3032
3319
|
session: {
|
|
3033
3320
|
instanceId: INSTANCE_ID,
|
|
3034
3321
|
currentSessionId,
|
|
3035
3322
|
currentPersona,
|
|
3323
|
+
currentRole,
|
|
3036
3324
|
tokenUsage: sessionTokenUsage,
|
|
3037
3325
|
},
|
|
3038
3326
|
updateSession: (updates) => {
|
|
3039
3327
|
if (updates.currentSessionId !== undefined) currentSessionId = updates.currentSessionId;
|
|
3040
3328
|
if (updates.currentPersona !== undefined) currentPersona = updates.currentPersona;
|
|
3329
|
+
if (updates.currentRole !== undefined) currentRole = updates.currentRole;
|
|
3041
3330
|
if (updates.tokenUsage !== undefined) sessionTokenUsage = updates.tokenUsage;
|
|
3042
3331
|
},
|
|
3043
3332
|
};
|
|
@@ -3054,8 +3343,8 @@ async function handleTool(
|
|
|
3054
3343
|
// ============================================================================
|
|
3055
3344
|
|
|
3056
3345
|
async function main() {
|
|
3057
|
-
// Validate API key on startup
|
|
3058
|
-
const auth = await validateApiKey(
|
|
3346
|
+
// Validate API key on startup via API
|
|
3347
|
+
const auth = await validateApiKey();
|
|
3059
3348
|
if (!auth) {
|
|
3060
3349
|
console.error('Invalid API key');
|
|
3061
3350
|
process.exit(1);
|