Skip to content

Commit 9d38b90

Browse files
committed
Add Supabase Edge Functions and shared agent utilities
Initial commit of Supabase Edge Functions, including deployment script, agent completion check utilities, agent self-invoke/retry logic, AI provider abstraction, and supporting documentation. Adds core agent, coordinator, portfolio, and rebalance manager functions, shared helpers, and analysis documentation for Alpaca close position endpoint. Enables modular agent workflows and robust error/retry handling.
1 parent b2af68a commit 9d38b90

File tree

140 files changed

+44166
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

140 files changed

+44166
-0
lines changed

supabase/deploy-functions.sh

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/Users/bruzwj/Downloads/.env.local#!/bin/bash
2+
3+
# Deployment script for Supabase Edge Functions
4+
# Run this when Docker is working properly
5+
if [ -f .env.local ]; then
6+
# Load environment variables, handling = signs and quotes properly
7+
set -a
8+
source .env.local
9+
set +a
10+
fi
11+
12+
echo "🚀 Deploying Supabase Edge Functions..."
13+
14+
# Debug: Check if variables are loaded
15+
echo "Debug: SUPABASE_ACCESS_TOKEN is ${#SUPABASE_ACCESS_TOKEN} characters long"
16+
echo "Debug: SUPABASE_PROJECT_REF = $SUPABASE_PROJECT_REF"
17+
18+
# Ensure variables are set
19+
if [ -z "$SUPABASE_ACCESS_TOKEN" ]; then
20+
echo "Error: SUPABASE_ACCESS_TOKEN not found in .env.local"
21+
exit 1
22+
fi
23+
24+
if [ -z "$SUPABASE_PROJECT_REF" ]; then
25+
echo "Error: SUPABASE_PROJECT_REF not found in .env.local"
26+
exit 1
27+
fi
28+
29+
# Deploy functions that require --no-verify-jwt flag
30+
no_verify_jwt_functions=(
31+
"alpaca-batch"
32+
"alpaca-proxy"
33+
"settings-proxy"
34+
"execute-trade"
35+
"analysis-coordinator"
36+
"rebalance-coordinator"
37+
"send-invitation"
38+
"discord-role-sync"
39+
"stripe-webhook"
40+
"create-smart-session"
41+
)
42+
43+
echo "📦 Deploying functions with --no-verify-jwt flag..."
44+
for func in "${no_verify_jwt_functions[@]}"; do
45+
echo " 📦 Deploying $func..."
46+
SUPABASE_ACCESS_TOKEN=$SUPABASE_ACCESS_TOKEN npx supabase functions deploy $func --project-ref $SUPABASE_PROJECT_REF --no-verify-jwt
47+
done
48+
49+
# Deploy functions that use standard JWT verification
50+
standard_functions=(
51+
"process-scheduled-rebalances"
52+
"detect-stale-analysis"
53+
"auto-near-limit-analysis"
54+
)
55+
56+
echo "📦 Deploying functions with standard JWT verification..."
57+
for func in "${standard_functions[@]}"; do
58+
echo " 📦 Deploying $func..."
59+
SUPABASE_ACCESS_TOKEN=$SUPABASE_ACCESS_TOKEN npx supabase functions deploy $func --project-ref $SUPABASE_PROJECT_REF
60+
done
61+
62+
# Deploy all agent functions
63+
agents=(
64+
"agent-macro-analyst"
65+
"agent-market-analyst"
66+
"agent-news-analyst"
67+
"agent-social-media-analyst"
68+
"agent-fundamentals-analyst"
69+
"agent-bull-researcher"
70+
"agent-bear-researcher"
71+
"agent-research-manager"
72+
"agent-trader"
73+
"agent-risky-analyst"
74+
"agent-safe-analyst"
75+
"agent-neutral-analyst"
76+
"agent-risk-manager"
77+
"analysis-portfolio-manager"
78+
"rebalance-portfolio-manager"
79+
"opportunity-agent"
80+
)
81+
82+
echo "📦 Deploying agent functions..."
83+
for agent in "${agents[@]}"; do
84+
echo " 📦 Deploying $agent..."
85+
SUPABASE_ACCESS_TOKEN=$SUPABASE_ACCESS_TOKEN npx supabase functions deploy $agent --project-ref $SUPABASE_PROJECT_REF
86+
done
87+
88+
echo "✅ All functions deployed successfully!"
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
# Alpaca Close Position Endpoint Analysis
2+
3+
## Current Implementation Review
4+
5+
### 1. Current SELL Order Flow
6+
7+
The Trading Goose currently handles position closing through the following mechanism:
8+
9+
1. **Position Management Detection** (`_shared/positionManagement.ts`):
10+
- When a SELL order's dollar amount exceeds the position value OR is within 5% of it
11+
- The system converts the order from dollar-based to share-based
12+
- Sets `shares` to the total shares in the position
13+
- Clears the `dollarAmount` field
14+
15+
2. **Order Submission** (`execute-trade/index.ts`):
16+
- Submits a market SELL order to Alpaca using POST /v2/orders
17+
- Uses either `notional` (dollar amount) or `qty` (shares) parameter
18+
- For full position closures, uses `qty` with all shares
19+
20+
### 2. Alpaca's Close Position Endpoint
21+
22+
Alpaca provides a dedicated endpoint for closing positions:
23+
- **Endpoint**: `DELETE /v2/positions/{symbol_or_asset_id}`
24+
- **Purpose**: Immediately liquidates the entire position
25+
- **Benefits**:
26+
- Guaranteed to close the entire position
27+
- No need to track exact share count
28+
- Handles fractional shares automatically
29+
- Single API call with clear intent
30+
31+
## Pros and Cons Analysis
32+
33+
### Using DELETE /positions Endpoint
34+
35+
**Pros:**
36+
1. **Simplicity**: Single API call that guarantees full position closure
37+
2. **Accuracy**: No risk of leaving fractional shares behind
38+
3. **Clarity**: Explicit intent to close position vs. partial sell
39+
4. **Error Reduction**: No need to calculate or track exact share counts
40+
5. **Consistency**: Works identically for whole and fractional share positions
41+
6. **API Efficiency**: Purpose-built for this exact use case
42+
43+
**Cons:**
44+
1. **Limited Flexibility**: Can only close entire position (no partial capability)
45+
2. **Different Response Format**: Returns position data instead of order data
46+
3. **Tracking Complexity**: Need different handling for order tracking/status
47+
4. **No Order ID**: Doesn't create a traditional order, making tracking harder
48+
5. **Database Schema Impact**: Current system expects alpaca_order metadata
49+
50+
### Current Approach (SELL all shares)
51+
52+
**Pros:**
53+
1. **Unified Handling**: Same flow for partial and full sells
54+
2. **Order Tracking**: Creates standard order with ID for tracking
55+
3. **Status Polling**: Can monitor order status consistently
56+
4. **Database Compatibility**: Fits existing schema without changes
57+
58+
**Cons:**
59+
1. **Fractional Share Risk**: Might leave tiny fractional amounts
60+
2. **Race Conditions**: Share count might change between read and submit
61+
3. **Complexity**: Requires accurate share count tracking
62+
4. **Two-Step Process**: Must fetch position first, then submit order
63+
64+
## Recommendations
65+
66+
### Recommended Approach: Hybrid Solution
67+
68+
Implement a hybrid approach that uses the close position endpoint when appropriate:
69+
70+
```typescript
71+
// Pseudocode for hybrid approach
72+
if (shouldCloseFullPosition && userPreference.useCloseEndpoint) {
73+
// Use DELETE /positions for clean full closure
74+
await closePositionViaDelete(ticker);
75+
// Create synthetic order record for tracking
76+
} else {
77+
// Use existing SELL order flow
78+
await submitSellOrder(shares || dollarAmount);
79+
}
80+
```
81+
82+
### Implementation Strategy
83+
84+
#### Phase 1: Add Close Position Capability (Low Risk)
85+
1. Create new function `closePositionViaAlpaca()` in `_shared/alpacaClient.ts`
86+
2. Add configuration option `use_close_endpoint_for_full_sells` in user settings
87+
3. Modify `execute-trade/index.ts` to check this preference
88+
89+
#### Phase 2: Handle Tracking (Medium Complexity)
90+
1. Create synthetic order record when using close endpoint
91+
2. Store close position response in metadata
92+
3. Mark as immediately "filled" since close is synchronous
93+
94+
#### Phase 3: Improve Position Detection (Enhancement)
95+
1. Enhance `shouldCloseFullPosition()` logic
96+
2. Add explicit "CLOSE_POSITION" action type alongside BUY/SELL/HOLD
97+
3. Allow users to explicitly request position closure
98+
99+
### Migration Plan
100+
101+
```sql
102+
-- Add user preference for close endpoint usage
103+
ALTER TABLE api_settings
104+
ADD COLUMN use_alpaca_close_endpoint BOOLEAN DEFAULT false;
105+
106+
-- Add tracking for close position operations
107+
ALTER TABLE trading_actions
108+
ADD COLUMN close_position_used BOOLEAN DEFAULT false;
109+
```
110+
111+
### Code Changes Required
112+
113+
1. **New File**: `supabase/functions/_shared/alpacaClosePosition.ts`
114+
- Implement close position API call
115+
- Handle response and error cases
116+
- Create synthetic order tracking
117+
118+
2. **Modify**: `supabase/functions/execute-trade/index.ts`
119+
- Check if order should use close endpoint
120+
- Route to appropriate execution path
121+
- Handle different response formats
122+
123+
3. **Update**: `supabase/functions/_shared/positionManagement.ts`
124+
- Add `useCloseEndpoint` flag to validation response
125+
- Enhance detection logic
126+
127+
## Risk Assessment
128+
129+
### Low Risk Items
130+
- Adding new close position function (additive, non-breaking)
131+
- User preference setting (opt-in feature)
132+
- Synthetic order creation (backward compatible)
133+
134+
### Medium Risk Items
135+
- Routing logic in execute-trade (needs careful testing)
136+
- Order status tracking differences (requires adaptation)
137+
- Error handling for new endpoint
138+
139+
### High Risk Items
140+
- None identified - existing flow remains as fallback
141+
142+
## Conclusion
143+
144+
**Recommendation: Implement the hybrid approach in phases**
145+
146+
The close position endpoint offers clear benefits for full position closures, particularly:
147+
- Eliminating fractional share remnants
148+
- Reducing race conditions
149+
- Simplifying the close process
150+
151+
However, maintaining the existing flow as default ensures:
152+
- No breaking changes
153+
- Consistent order tracking
154+
- Gradual adoption via opt-in
155+
156+
The phased implementation allows for:
157+
1. Safe introduction of new capability
158+
2. User testing and feedback
159+
3. Rollback capability if issues arise
160+
4. Gradual migration of users
161+
162+
## Next Steps
163+
164+
1. Create migration file for database changes
165+
2. Implement `alpacaClosePosition.ts` utility
166+
3. Add routing logic to `execute-trade` function
167+
4. Test with paper trading accounts
168+
5. Create user documentation
169+
6. Deploy as opt-in beta feature
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Agent Completion Check Template
2+
3+
This template shows how to add completion checking to prevent duplicate agent execution and save API calls.
4+
5+
## 1. Import the Required Functions
6+
7+
Add this import at the top of your agent file:
8+
9+
```typescript
10+
import { checkAgentCompletion, checkForBlockingOperations } from '../_shared/agentCompletionCheck.ts'
11+
```
12+
13+
## 2. Add Completion Check After Initial Setup
14+
15+
After creating the Supabase client and logging initial status, but BEFORE setting up timeouts or doing any actual work, add:
16+
17+
```typescript
18+
// Check if this agent has already completed for this analysis
19+
const completionStatus = await checkAgentCompletion(
20+
supabase,
21+
analysisId,
22+
'agent-[YOUR-AGENT-NAME]', // e.g., 'agent-fundamentals-analyst'
23+
'[Your Agent Display Name]' // e.g., 'Fundamentals Analyst'
24+
);
25+
26+
if (completionStatus.hasCompleted && completionStatus.status === 'completed') {
27+
console.log(`✅ [Agent Name] already completed for analysis ${analysisId}`);
28+
console.log(` Skipping duplicate execution to save API calls`);
29+
30+
// Clear any timeout that might have been set
31+
if (timeoutId !== null) {
32+
clearAgentTimeout(timeoutId, '[Agent Name]', 'already completed');
33+
}
34+
35+
// Return the existing insights if available
36+
return createSuccessResponse({
37+
agent: '[Agent Name]',
38+
message: 'Agent already completed for this analysis',
39+
alreadyCompleted: true,
40+
existingInsights: completionStatus.existingInsights,
41+
retryInfo: retryStatus
42+
});
43+
}
44+
45+
// Don't check for "already running" - the coordinator handles that before invocation
46+
// The agent will see itself as "running" because the coordinator marks it as such
47+
// Only check for "already completed" to avoid re-doing work
48+
49+
// Check for any blocking operations (canceled analysis, etc.)
50+
const blockingCheck = await checkForBlockingOperations(supabase, analysisId, 'agent-[your-agent-name]');
51+
if (!blockingCheck.canProceed) {
52+
console.log(`🛑 [Agent Name] cannot proceed: ${blockingCheck.reason}`);
53+
return createCanceledResponse(
54+
`[Agent Name] cannot proceed: ${blockingCheck.reason}`,
55+
true
56+
);
57+
}
58+
```
59+
60+
## 3. Complete Example Structure
61+
62+
```typescript
63+
serve(async (req) => {
64+
let timeoutId: number | null = null;
65+
66+
try {
67+
// 1. Validate request method and parameters
68+
if (req.method !== 'POST') {
69+
return createMethodNotAllowedResponse();
70+
}
71+
72+
const request: AgentRequest = await req.json();
73+
// ... parameter validation ...
74+
75+
// 2. Initialize Supabase client
76+
const supabase = createClient(supabaseUrl, supabaseServiceKey);
77+
78+
// 3. Log initial status
79+
console.log(`🎯 [Agent Name] starting for ${ticker}`);
80+
81+
// 4. ⭐ ADD COMPLETION CHECK HERE ⭐
82+
const completionStatus = await checkAgentCompletion(...);
83+
// ... handle completion status as shown above ...
84+
85+
// 5. Setup timeout (AFTER completion check)
86+
timeoutId = setupAgentTimeout(...);
87+
88+
// 6. Check cancellation
89+
const cancellationCheck = await checkAnalysisCancellation(...);
90+
91+
// 7. Do actual work
92+
// ... your agent logic ...
93+
94+
} catch (error) {
95+
// Error handling
96+
}
97+
});
98+
```
99+
100+
## Agent Names Reference
101+
102+
For the `checkAgentCompletion` function, use these exact names:
103+
104+
| Agent Function Name | Display Name |
105+
|-------------------|--------------|
106+
| agent-market-analyst | Market Analyst |
107+
| agent-news-analyst | News Analyst |
108+
| agent-social-media-analyst | Social Media Analyst |
109+
| agent-fundamentals-analyst | Fundamentals Analyst |
110+
| agent-macro-analyst | Macro Analyst |
111+
| agent-bull-researcher | Bull Researcher |
112+
| agent-bear-researcher | Bear Researcher |
113+
| agent-research-manager | Research Manager |
114+
| agent-trader | Trader |
115+
| agent-risky-analyst | Risky Analyst |
116+
| agent-safe-analyst | Safe Analyst |
117+
| agent-neutral-analyst | Neutral Analyst |
118+
| agent-risk-manager | Risk Manager |
119+
120+
## Benefits
121+
122+
1. **Prevents Duplicate Work**: Agents won't re-run if already completed
123+
2. **Saves API Calls**: No unnecessary AI API calls for completed agents
124+
3. **Handles Race Conditions**: Prevents concurrent execution of the same agent
125+
4. **Graceful Recovery**: Allows retry for failed agents while blocking completed ones
126+
5. **Better User Experience**: Faster responses when agents have already run
127+
128+
## Notes
129+
130+
- The check happens BEFORE setting up timeouts to avoid unnecessary timeout handlers
131+
- The check happens BEFORE any actual work (API calls, data fetching, etc.)
132+
- Failed agents (status='error') are allowed to retry
133+
- Running agents are blocked to prevent concurrent execution
134+
- Completed agents return their existing insights if available

0 commit comments

Comments
 (0)