dodo_get_project_env tool

Change-Id: I487e68eedffcb65972093458891178b5ebd3359b
diff --git a/dodo_tools/dodo.go b/dodo_tools/dodo.go
index 5913d92..1bc20c5 100644
--- a/dodo_tools/dodo.go
+++ b/dodo_tools/dodo.go
@@ -23,10 +23,10 @@
 	}
 	return &llm.Tool{
 		Name:        "dodo_get_project_config",
-		Description: "A tool for getting current state of the infrastructure configuration of a dodo project",
+		Description: "A tool for getting current state of the infrastructure configuration of a dodo project. You might want to use dodo_get_project_env tool to resolve ingress domains.",
 		InputSchema: llm.EmptySchema(),
 		Run:         tool.Run,
-		EndsTurn:    true,
+		EndsTurn:    false,
 	}
 }
 
@@ -60,6 +60,123 @@
 	return llm.TextContent(string(jsonOutput)), nil
 }
 
+// Env
+
+type GetProjectEnvTool struct {
+	apiBaseAddress string
+	projectId      string
+}
+
+func NewGetProjectEnvTool(apiBaseAddress string, projectId string) *llm.Tool {
+	tool := &GetProjectEnvTool{
+		apiBaseAddress: apiBaseAddress,
+		projectId:      projectId,
+	}
+	return &llm.Tool{
+		Name: "dodo_get_project_env",
+		Description: `A tool for getting GitHub PAT (Personal Access Token) and available networks of the dodo project. Use if you need to:
+1. Interact with GitHub and do not have PAT cached.
+2. Want to resolve network domains of dodo service ingresses.
+3. Access application wide environment variables.
+
+Returns JSON object conforming following schema which you can cache:
+
+{
+  "type": "object",
+  "properties": {
+    "githubToken": {
+      "type": "string",
+      "description": "Github PAT (Personal Access Token)"
+    },
+    "networks": {
+      "type": "array",
+      "description": "List of available networks",
+      "items": {
+        "type": "object",
+        "required": ["name", "domain", "hasAuth"],
+        "properties": {
+          "name": {
+            "type": "string",
+            "description": "The name of the network"
+          },
+          "domain": {
+            "type": "string",
+            "description": "The domain of the network"
+          },
+          "hasAuth": {
+            "type": "boolean",
+            "description": "Represents if services published on this network can use built-in authorization"
+          }
+        }
+      }
+    },
+    "envVars": {
+      "type": "array",
+      "description": "List of application wide environment variables",
+      "items": {
+        "type": "object",
+        "required": ["name", "value"],
+        "properties": {
+          "name": {
+            "type": "string",
+            "description": "The name of the environment variable"
+          },
+          "value": {
+            "type": "string",
+            "description": "The value of the environment variable"
+          }
+        }
+      }
+    }
+  }
+}
+`,
+		InputSchema: llm.EmptySchema(),
+		Run:         tool.Run,
+		EndsTurn:    false,
+	}
+}
+
+type GetProjectEnvInput struct {
+}
+
+type Network struct {
+	Name    string `json:"name"`
+	Domain  string `json:"domain"`
+	HasAuth bool   `json:"hasAuth"`
+}
+
+type GetProjectEnvOutput struct {
+	GithubToken string    `json:"githubToken,omitempty"`
+	Networks    []Network `json:"networks,omitempty"`
+}
+
+func (d *GetProjectEnvTool) Run(ctx context.Context, m json.RawMessage) ([]llm.Content, error) {
+	resp, err := http.Get(fmt.Sprintf("%s/api/project/%s/env", d.apiBaseAddress, d.projectId))
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	body, err := io.ReadAll(resp.Body)
+	if err != nil {
+		return nil, err
+	}
+	if resp.StatusCode != http.StatusOK {
+		return nil, fmt.Errorf("failed to get project env: %s", string(body))
+	}
+	var output GetProjectEnvOutput
+	if err := json.Unmarshal(body, &output); err != nil {
+		return nil, err
+	}
+	jsonOutput, err := json.Marshal(output)
+	if err != nil {
+		return nil, err
+	}
+	return llm.TextContent(string(jsonOutput)), nil
+}
+
+// Validate
+
 type ValidateConfigTool struct {
 	apiBaseAddress string
 }
@@ -88,7 +205,7 @@
 		Description: "A tool for validating the dodo-app configuration",
 		InputSchema: llm.MustSchema(validateConfigSchemaInputSchema),
 		Run:         tool.Run,
-		EndsTurn:    true,
+		EndsTurn:    false,
 	}
 }
 
@@ -209,7 +326,7 @@
 		Description: "A tool for saving the dodo-app configuration",
 		InputSchema: llm.MustSchema(saveProjectSchemaInputSchema),
 		Run:         tool.Run,
-		EndsTurn:    true,
+		EndsTurn:    false,
 	}
 }
 
@@ -255,6 +372,7 @@
 func NewDodoTools(apiBaseAddress string, projectId string) []*llm.Tool {
 	return []*llm.Tool{
 		NewGetProjectConfigTool(apiBaseAddress, projectId),
+		NewGetProjectEnvTool(apiBaseAddress, projectId),
 		NewValidateConfigTool(apiBaseAddress),
 		NewSaveProjectTool(apiBaseAddress, projectId),
 		NewDeployProjectTool(apiBaseAddress, projectId),