Skip to content

Commit 7f77d62

Browse files
authored
Static token for DEV env (#251)
* Static token for DEV env * Clean up
1 parent 2dd0ec9 commit 7f77d62

File tree

3 files changed

+93
-90
lines changed

3 files changed

+93
-90
lines changed

internal/app/therapy.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type therapyConfig struct {
2626
sessionID string
2727
locale string
2828
ctx context.Context
29+
token string
2930
}
3031

3132
// Start therapy session
@@ -69,13 +70,19 @@ func relayTherapyMessage(text string, session *Session) {
6970

7071
// Build an HTTP client configured with ID token authentication for therapy session calls
7172
func buildTherapyHTTPClient(ctx context.Context, targetURL string) (*http.Client, error) {
72-
client, err := idtoken.NewClient(ctx, targetURL)
73-
if err != nil {
74-
return nil, fmt.Errorf("failed to create ID token client: %w", err)
75-
}
76-
// Set timeout on the client
77-
client.Timeout = 120 * time.Second
78-
return client, nil
73+
// Local development path: plain HTTP client; per-request header is set using cfg.token
74+
if os.Getenv("CLOUD") == "false" {
75+
return &http.Client{Timeout: 120 * time.Second}, nil
76+
}
77+
78+
// Cloud path (default): use Google ID token auth
79+
client, err := idtoken.NewClient(ctx, targetURL)
80+
if err != nil {
81+
return nil, fmt.Errorf("failed to create ID token client: %w", err)
82+
}
83+
// Set timeout on the client
84+
client.Timeout = 120 * time.Second
85+
return client, nil
7986
}
8087

8188
// Build configuration from environment and session; ensures a session ID exists
@@ -94,13 +101,18 @@ func buildTherapyConfig(session *Session) *therapyConfig {
94101
userID := session.User.ID
95102
sessionID := *session.User.TherapySessionId
96103
locale := session.Locale().String()
104+
var token string
105+
if os.Getenv("CLOUD") == "false" {
106+
token = strings.TrimSpace(os.Getenv("CAPY_AGENT_TOKEN"))
107+
}
97108

98109
return &therapyConfig{
99110
baseURL: baseURL,
100111
userID: userID,
101112
sessionID: sessionID,
102113
locale: locale,
103114
ctx: context.Background(),
115+
token: token,
104116
}
105117
}
106118

@@ -121,6 +133,9 @@ func initTherapySession(client *http.Client, cfg *therapyConfig) bool {
121133
}
122134
// ID token client automatically adds Authorization header
123135
req.Header.Set("Content-Type", "application/json")
136+
if cfg.token != "" {
137+
req.Header.Set("Authorization", "Bearer "+cfg.token)
138+
}
124139

125140
resp, err := client.Do(req)
126141
if err != nil {
@@ -166,6 +181,9 @@ func sendTherapyMessage(client *http.Client, cfg *therapyConfig, text string) *s
166181
return nil
167182
}
168183
req.Header.Set("Content-Type", "application/json")
184+
if cfg.token != "" {
185+
req.Header.Set("Authorization", "Bearer "+cfg.token)
186+
}
169187

170188
resp, err := client.Do(req)
171189
if err != nil {

internal/app/therapy_test.go

Lines changed: 68 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package app
22

33
import (
4-
"context"
5-
"net/http"
6-
"net/http/httptest"
7-
"testing"
8-
"time"
4+
"context"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
"time"
99

10-
"strings"
10+
"strings"
1111

12-
"github.com/capymind/internal/database"
12+
"github.com/capymind/internal/database"
1313
)
1414

1515
func TestStartTherapySession(t *testing.T) {
@@ -54,7 +54,7 @@ func TestEndTherapySession(t *testing.T) {
5454

5555
func TestRelayTherapyMessage(t *testing.T) {
5656
// Create a fake therapy session backend implementing both init and run endpoints
57-
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
57+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
5858
switch {
5959
case r.Method == http.MethodPost && strings.HasPrefix(r.URL.Path, "/apps/capymind_agent/users/u1/sessions/"):
6060
// Session init endpoint
@@ -63,24 +63,24 @@ func TestRelayTherapyMessage(t *testing.T) {
6363
return
6464
case r.Method == http.MethodPost && r.URL.Path == "/run_sse":
6565
// Message sending endpoint
66-
w.Header().Set("Content-Type", "text/event-stream")
67-
w.WriteHeader(http.StatusOK)
68-
_, _ = w.Write([]byte("data: {\"content\":{\"parts\":[{\"text\":\"Hello, I'm here for you.\"}],\"role\":\"model\"}}\n\n"))
66+
w.Header().Set("Content-Type", "text/event-stream")
67+
w.WriteHeader(http.StatusOK)
68+
_, _ = w.Write([]byte("data: {\"content\":{\"parts\":[{\"text\":\"Hello, I'm here for you.\"}],\"role\":\"model\"}}\n\n"))
6969
return
7070
default:
7171
http.NotFound(w, r)
7272
return
7373
}
7474
}))
7575
defer ts.Close()
76-
t.Setenv("CAPY_THERAPY_SESSION_URL", ts.URL)
76+
t.Setenv("CAPY_THERAPY_SESSION_URL", ts.URL)
7777

78-
// Inject simple HTTP client without Google auth for tests
79-
originalBuilder := newTherapyHTTPClient
80-
newTherapyHTTPClient = func(ctx context.Context, targetURL string) (*http.Client, error) {
81-
return &http.Client{Timeout: 5 * time.Second}, nil
82-
}
83-
defer func() { newTherapyHTTPClient = originalBuilder }()
78+
// Inject simple HTTP client without Google auth for tests
79+
originalBuilder := newTherapyHTTPClient
80+
newTherapyHTTPClient = func(ctx context.Context, targetURL string) (*http.Client, error) {
81+
return &http.Client{Timeout: 5 * time.Second}, nil
82+
}
83+
defer func() { newTherapyHTTPClient = originalBuilder }()
8484

8585
ctx := context.Background()
8686
locale := "en"
@@ -89,7 +89,7 @@ func TestRelayTherapyMessage(t *testing.T) {
8989

9090
relayTherapyMessage("hi", session)
9191

92-
if len(session.Job.Output) == 0 {
92+
if len(session.Job.Output) == 0 {
9393
t.Fatalf("expected at least one output")
9494
}
9595
if session.Job.Output[0].TextID != "Hello, I'm here for you." {
@@ -113,30 +113,30 @@ func TestHandleSession_AutoEndWhenExpired(t *testing.T) {
113113

114114
func TestHandleSession_ForwardDuringActive(t *testing.T) {
115115
// Fake backend implementing both init and run endpoints
116-
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
116+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
117117
switch {
118118
case r.Method == http.MethodPost && strings.HasPrefix(r.URL.Path, "/apps/capymind_agent/users/u1/sessions/"):
119119
w.WriteHeader(http.StatusOK)
120120
_, _ = w.Write([]byte(`{"ok":true}`))
121121
return
122122
case r.Method == http.MethodPost && r.URL.Path == "/run_sse":
123-
w.Header().Set("Content-Type", "text/event-stream")
124-
w.WriteHeader(http.StatusOK)
125-
_, _ = w.Write([]byte("data: {\"content\":{\"parts\":[{\"text\":\"Therapist reply\"}],\"role\":\"model\"}}\n\n"))
123+
w.Header().Set("Content-Type", "text/event-stream")
124+
w.WriteHeader(http.StatusOK)
125+
_, _ = w.Write([]byte("data: {\"content\":{\"parts\":[{\"text\":\"Therapist reply\"}],\"role\":\"model\"}}\n\n"))
126126
return
127127
default:
128128
http.NotFound(w, r)
129129
return
130130
}
131131
}))
132132
defer ts.Close()
133-
t.Setenv("CAPY_THERAPY_SESSION_URL", ts.URL)
133+
t.Setenv("CAPY_THERAPY_SESSION_URL", ts.URL)
134134

135-
originalBuilder := newTherapyHTTPClient
136-
newTherapyHTTPClient = func(ctx context.Context, targetURL string) (*http.Client, error) {
137-
return &http.Client{Timeout: 5 * time.Second}, nil
138-
}
139-
defer func() { newTherapyHTTPClient = originalBuilder }()
135+
originalBuilder := newTherapyHTTPClient
136+
newTherapyHTTPClient = func(ctx context.Context, targetURL string) (*http.Client, error) {
137+
return &http.Client{Timeout: 5 * time.Second}, nil
138+
}
139+
defer func() { newTherapyHTTPClient = originalBuilder }()
140140

141141
ctx := context.Background()
142142
future := time.Now().Add(5 * time.Minute)
@@ -154,45 +154,45 @@ func TestHandleSession_ForwardDuringActive(t *testing.T) {
154154
}
155155

156156
func TestRelayTherapyMessage_ExistingSessionContinues(t *testing.T) {
157-
// Fake backend: init returns 400 Session already exists; run_sse returns a reply
158-
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
159-
switch {
160-
case r.Method == http.MethodPost && strings.HasPrefix(r.URL.Path, "/apps/capymind_agent/users/u1/sessions/"):
161-
w.WriteHeader(http.StatusBadRequest)
162-
_, _ = w.Write([]byte(`{"detail":"Session already exists: abc-123"}`))
163-
return
164-
case r.Method == http.MethodPost && r.URL.Path == "/run_sse":
165-
w.Header().Set("Content-Type", "text/event-stream")
166-
w.WriteHeader(http.StatusOK)
167-
_, _ = w.Write([]byte("data: {\"content\":{\"parts\":[{\"text\":\"Hello again\"}],\"role\":\"model\"}}\n\n"))
168-
return
169-
default:
170-
http.NotFound(w, r)
171-
return
172-
}
173-
}))
174-
defer ts.Close()
175-
t.Setenv("CAPY_THERAPY_SESSION_URL", ts.URL)
176-
177-
originalBuilder := newTherapyHTTPClient
178-
newTherapyHTTPClient = func(ctx context.Context, targetURL string) (*http.Client, error) {
179-
return &http.Client{Timeout: 5 * time.Second}, nil
180-
}
181-
defer func() { newTherapyHTTPClient = originalBuilder }()
182-
183-
ctx := context.Background()
184-
locale := "en"
185-
user := &database.User{ID: "u1", Locale: &locale}
186-
session := createSession(&Job{Command: None}, user, nil, &ctx)
187-
188-
relayTherapyMessage("hi", session)
189-
190-
if len(session.Job.Output) == 0 {
191-
t.Fatalf("expected at least one output")
192-
}
193-
if session.Job.Output[0].TextID != "Hello again" {
194-
t.Fatalf("unexpected relay text: %s", session.Job.Output[0].TextID)
195-
}
157+
// Fake backend: init returns 400 Session already exists; run_sse returns a reply
158+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
159+
switch {
160+
case r.Method == http.MethodPost && strings.HasPrefix(r.URL.Path, "/apps/capymind_agent/users/u1/sessions/"):
161+
w.WriteHeader(http.StatusBadRequest)
162+
_, _ = w.Write([]byte(`{"detail":"Session already exists: abc-123"}`))
163+
return
164+
case r.Method == http.MethodPost && r.URL.Path == "/run_sse":
165+
w.Header().Set("Content-Type", "text/event-stream")
166+
w.WriteHeader(http.StatusOK)
167+
_, _ = w.Write([]byte("data: {\"content\":{\"parts\":[{\"text\":\"Hello again\"}],\"role\":\"model\"}}\n\n"))
168+
return
169+
default:
170+
http.NotFound(w, r)
171+
return
172+
}
173+
}))
174+
defer ts.Close()
175+
t.Setenv("CAPY_THERAPY_SESSION_URL", ts.URL)
176+
177+
originalBuilder := newTherapyHTTPClient
178+
newTherapyHTTPClient = func(ctx context.Context, targetURL string) (*http.Client, error) {
179+
return &http.Client{Timeout: 5 * time.Second}, nil
180+
}
181+
defer func() { newTherapyHTTPClient = originalBuilder }()
182+
183+
ctx := context.Background()
184+
locale := "en"
185+
user := &database.User{ID: "u1", Locale: &locale}
186+
session := createSession(&Job{Command: None}, user, nil, &ctx)
187+
188+
relayTherapyMessage("hi", session)
189+
190+
if len(session.Job.Output) == 0 {
191+
t.Fatalf("expected at least one output")
192+
}
193+
if session.Job.Output[0].TextID != "Hello again" {
194+
t.Fatalf("unexpected relay text: %s", session.Job.Output[0].TextID)
195+
}
196196
}
197197

198198
func TestHandleSession_EndOnOtherCommand(t *testing.T) {

scripts/generate_agent_token.sh

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,3 @@
11
#!/bin/bash
22

3-
SERVICE_ACCOUNT=$CAPY_SERVICE_ACCOUNT
4-
PROJECT_ID=$CAPY_PROJECT_ID
5-
6-
gcloud iam service-accounts add-iam-policy-binding $SERVICE_ACCOUNT \
7-
--role=roles/iam.serviceAccountTokenCreator \
8-
--member=serviceAccount:$SERVICE_ACCOUNT \
9-
--project=$PROJECT_ID
10-
11-
gcloud iam service-accounts keys create key.json \
12-
--iam-account=$SERVICE_ACCOUNT
13-
14-
# Activate the service account
15-
gcloud auth activate-service-account --key-file=key.json
16-
17-
# Generate the identity token
183
gcloud auth print-identity-token

0 commit comments

Comments
 (0)