Skip to content
This repository was archived by the owner on Jun 5, 2025. It is now read-only.

Commit 36c1c43

Browse files
committed
Merge branch 'adds-codegate-helm' of github.com:stacklok/codegate into adds-codegate-helm
2 parents 2f7b756 + cc3fa12 commit 36c1c43

File tree

17 files changed

+301
-40
lines changed

17 files changed

+301
-40
lines changed

.github/workflows/feature-launcher.yml

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,51 @@ jobs:
1212
- name: Send Feature Release Notification to Discord
1313
env:
1414
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
15+
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
1516
ISSUE_TITLE: ${{ github.event.issue.title }}
1617
ISSUE_BODY: ${{ github.event.issue.body }}
1718
ISSUE_URL: ${{ github.event.issue.html_url }}
1819
run: |
19-
curl -H "Content-Type: application/json" \
20-
-X POST \
21-
-d '{
22-
"content": "**🚀 New Feature Launched!**\n\n🎉 *${{ env.ISSUE_TITLE }}* is now available to try!\n📖 Description: ${{ env.ISSUE_BODY }}\n🔗 [Check it out here](${{ env.ISSUE_URL }})"
23-
}' \
24-
$DISCORD_WEBHOOK
20+
node -e '
21+
const https = require("https");
22+
const discordWebhook = new URL(process.env.DISCORD_WEBHOOK);
23+
const slackWebhook = new URL(process.env.SLACK_WEBHOOK);
24+
25+
const issueTitle = process.env.ISSUE_TITLE;
26+
const issueBody = process.env.ISSUE_BODY;
27+
const issueUrl = process.env.ISSUE_URL;
28+
29+
// Discord Payload
30+
const discordPayload = {
31+
content: [
32+
"**🚀 " +issueTitle + " has been released!**",
33+
"",
34+
"**🌟 Whats new in CodeGate:**",
35+
issueBody,
36+
"",
37+
"We would 🤍 your feedback! 🔗 [Here’s the GitHub issue](" + issueUrl + ")"
38+
].join("\n")
39+
};
40+
41+
// Slack Payload
42+
const slackPayload = {
43+
text: `🚀 *${issueTitle}* has been released!\n\n 🔗 <${issueUrl}|Here’s the GitHub issue>`,
44+
};
45+
46+
function sendNotification(webhookUrl, payload) {
47+
const url = new URL(webhookUrl);
48+
const req = https.request(url, {
49+
method: "POST",
50+
headers: {
51+
"Content-Type": "application/json",
52+
}
53+
});
54+
55+
req.on("error", (error) => {
56+
console.error("Error:", error);
57+
process.exit(1);
58+
});
59+
60+
req.write(JSON.stringify(payload));
61+
req.end();
62+
}

api/openapi.json

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,55 @@
989989
}
990990
}
991991
},
992+
"/api/v1/workspaces/{provider_id}": {
993+
"get": {
994+
"tags": [
995+
"CodeGate API",
996+
"Workspaces"
997+
],
998+
"summary": "List Workspaces By Provider",
999+
"description": "List workspaces by provider ID.",
1000+
"operationId": "v1_list_workspaces_by_provider",
1001+
"parameters": [
1002+
{
1003+
"name": "provider_id",
1004+
"in": "path",
1005+
"required": true,
1006+
"schema": {
1007+
"type": "string",
1008+
"format": "uuid",
1009+
"title": "Provider Id"
1010+
}
1011+
}
1012+
],
1013+
"responses": {
1014+
"200": {
1015+
"description": "Successful Response",
1016+
"content": {
1017+
"application/json": {
1018+
"schema": {
1019+
"type": "array",
1020+
"items": {
1021+
"$ref": "#/components/schemas/WorkspaceWithModel"
1022+
},
1023+
"title": "Response V1 List Workspaces By Provider"
1024+
}
1025+
}
1026+
}
1027+
},
1028+
"422": {
1029+
"description": "Validation Error",
1030+
"content": {
1031+
"application/json": {
1032+
"schema": {
1033+
"$ref": "#/components/schemas/HTTPValidationError"
1034+
}
1035+
}
1036+
}
1037+
}
1038+
}
1039+
}
1040+
},
9921041
"/api/v1/alerts_notification": {
9931042
"get": {
9941043
"tags": [
@@ -1478,6 +1527,16 @@
14781527
"type": "string",
14791528
"title": "Name"
14801529
},
1530+
"config": {
1531+
"anyOf": [
1532+
{
1533+
"$ref": "#/components/schemas/WorkspaceConfig"
1534+
},
1535+
{
1536+
"type": "null"
1537+
}
1538+
]
1539+
},
14811540
"rename_to": {
14821541
"anyOf": [
14831542
{
@@ -1590,6 +1649,17 @@
15901649
},
15911650
"MuxRule": {
15921651
"properties": {
1652+
"provider_name": {
1653+
"anyOf": [
1654+
{
1655+
"type": "string"
1656+
},
1657+
{
1658+
"type": "null"
1659+
}
1660+
],
1661+
"title": "Provider Name"
1662+
},
15931663
"provider_id": {
15941664
"type": "string",
15951665
"title": "Provider Id"
@@ -1842,6 +1912,52 @@
18421912
"is_active"
18431913
],
18441914
"title": "Workspace"
1915+
},
1916+
"WorkspaceConfig": {
1917+
"properties": {
1918+
"system_prompt": {
1919+
"type": "string",
1920+
"title": "System Prompt"
1921+
},
1922+
"muxing_rules": {
1923+
"items": {
1924+
"$ref": "#/components/schemas/MuxRule"
1925+
},
1926+
"type": "array",
1927+
"title": "Muxing Rules"
1928+
}
1929+
},
1930+
"type": "object",
1931+
"required": [
1932+
"system_prompt",
1933+
"muxing_rules"
1934+
],
1935+
"title": "WorkspaceConfig"
1936+
},
1937+
"WorkspaceWithModel": {
1938+
"properties": {
1939+
"id": {
1940+
"type": "string",
1941+
"title": "Id"
1942+
},
1943+
"name": {
1944+
"type": "string",
1945+
"pattern": "^[a-zA-Z0-9_-]+$",
1946+
"title": "Name"
1947+
},
1948+
"provider_model_name": {
1949+
"type": "string",
1950+
"title": "Provider Model Name"
1951+
}
1952+
},
1953+
"type": "object",
1954+
"required": [
1955+
"id",
1956+
"name",
1957+
"provider_model_name"
1958+
],
1959+
"title": "WorkspaceWithModel",
1960+
"description": "Returns a workspace ID with model name"
18451961
}
18461962
}
18471963
}

docs/development.md

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ from potential AI-related security risks. Key features include:
2626
deployment)
2727
- [Visual Studio Code](https://code.visualstudio.com/download) (recommended IDE)
2828

29+
Note that if you are using pyenv on macOS, you will need a Python build linked
30+
against sqlite installed from Homebrew. macOS ships with sqlite, but it lacks
31+
some required functionality needed in the project. This can be accomplished with:
32+
33+
```
34+
# substitute for your version of choice
35+
PYTHON_VERSION=3.12.9
36+
brew install sqlite
37+
LDFLAGS="-L$(brew --prefix sqlite)/lib" CPPFLAGS="-I$(brew --prefix sqlite)/include" PYTHON_CONFIGURE_OPTS="--enable-loadable-sqlite-extensions" pyenv install -v $PYTHON_VERSION
38+
poetry env use $PYTHON_VERSION
39+
```
40+
2941
### Initial setup
3042

3143
1. Clone the repository:
@@ -59,19 +71,6 @@ To install all dependencies for your local development environment, run
5971
npm install
6072
```
6173

62-
Note that if you are running some processes (specifically the package import
63-
script) on macOS, you will need a Python build linked against sqlite installed
64-
from Homebrew. macOS ships with sqlite, but it lacks some required
65-
functionality. This can be accomplished with:
66-
67-
```
68-
# substitute for your version of choice
69-
PYTHON_VERSION=3.12.9
70-
brew install sqlite
71-
LDFLAGS="-L$(brew --prefix sqlite)/lib" CPPFLAGS="-I$(brew --prefix sqlite)/include" PYTHON_CONFIGURE_OPTS="--enable-loadable-sqlite-extensions" pyenv install -v $PYTHON_VERSION
72-
poetry env use $PYTHON_VERSION
73-
```
74-
7574
### Running the development server
7675

7776
Run the development server using:

poetry.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pytest = "==8.3.4"
4646
pytest-cov = "==6.0.0"
4747
black = "==25.1.0"
4848
ruff = "==0.9.6"
49-
bandit = "==1.8.2"
49+
bandit = "==1.8.3"
5050
build = "==1.2.2.post1"
5151
wheel = "==0.45.1"
5252
litellm = "==1.61.6"

src/codegate/api/v1.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from codegate import __version__
1313
from codegate.api import v1_models, v1_processing
1414
from codegate.db.connection import AlreadyExistsError, DbReader
15-
from codegate.db.models import AlertSeverity
15+
from codegate.db.models import AlertSeverity, WorkspaceWithModel
1616
from codegate.providers import crud as provendcrud
1717
from codegate.workspaces import crud
1818

@@ -532,6 +532,22 @@ async def set_workspace_muxes(
532532
return Response(status_code=204)
533533

534534

535+
@v1.get(
536+
"/workspaces/{provider_id}",
537+
tags=["Workspaces"],
538+
generate_unique_id_function=uniq_name,
539+
)
540+
async def list_workspaces_by_provider(
541+
provider_id: UUID,
542+
) -> List[WorkspaceWithModel]:
543+
"""List workspaces by provider ID."""
544+
try:
545+
return await wscrud.workspaces_by_provider(provider_id)
546+
547+
except Exception as e:
548+
raise HTTPException(status_code=500, detail=str(e))
549+
550+
535551
@v1.get("/alerts_notification", tags=["Dashboard"], generate_unique_id_function=uniq_name)
536552
async def stream_sse():
537553
"""

src/codegate/api/v1_models.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import pydantic
77

8+
import codegate.muxing.models as mux_models
89
from codegate.db import models as db_models
910
from codegate.extract_snippets.message_extractor import CodeSnippet
1011
from codegate.providers.base import BaseProvider
@@ -59,9 +60,19 @@ def from_db_workspaces(
5960
)
6061

6162

62-
class CreateOrRenameWorkspaceRequest(pydantic.BaseModel):
63+
class WorkspaceConfig(pydantic.BaseModel):
64+
system_prompt: str
65+
66+
muxing_rules: List[mux_models.MuxRule]
67+
68+
69+
class FullWorkspace(pydantic.BaseModel):
6370
name: str
6471

72+
config: Optional[WorkspaceConfig] = None
73+
74+
75+
class CreateOrRenameWorkspaceRequest(FullWorkspace):
6576
# If set, rename the workspace to this name. Note that
6677
# the 'name' field is still required and the workspace
6778
# workspace must exist.

src/codegate/db/connection.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
ProviderModel,
2929
Session,
3030
WorkspaceRow,
31+
WorkspaceWithModel,
3132
WorkspaceWithSessionInfo,
3233
)
3334
from codegate.db.token_usage import TokenUsageParser
@@ -129,6 +130,7 @@ async def record_request(self, prompt_params: Optional[Prompt] = None) -> Option
129130
active_workspace = await DbReader().get_active_workspace()
130131
workspace_id = active_workspace.id if active_workspace else "1"
131132
prompt_params.workspace_id = workspace_id
133+
132134
sql = text(
133135
"""
134136
INSERT INTO prompts (id, timestamp, provider, request, type, workspace_id)
@@ -302,7 +304,7 @@ async def record_context(self, context: Optional[PipelineContext]) -> None:
302304
await self.record_outputs(context.output_responses, initial_id)
303305
await self.record_alerts(context.alerts_raised, initial_id)
304306
logger.info(
305-
f"Recorded context in DB. Output chunks: {len(context.output_responses)}. "
307+
f"Updated context in DB. Output chunks: {len(context.output_responses)}. "
306308
f"Alerts: {len(context.alerts_raised)}."
307309
)
308310
except Exception as e:
@@ -720,6 +722,23 @@ async def get_workspace_by_name(self, name: str) -> Optional[WorkspaceRow]:
720722
)
721723
return workspaces[0] if workspaces else None
722724

725+
async def get_workspaces_by_provider(self, provider_id: str) -> List[WorkspaceWithModel]:
726+
sql = text(
727+
"""
728+
SELECT
729+
w.id, w.name, m.provider_model_name
730+
FROM workspaces w
731+
JOIN muxes m ON w.id = m.workspace_id
732+
WHERE m.provider_endpoint_id = :provider_id
733+
AND w.deleted_at IS NULL
734+
"""
735+
)
736+
conditions = {"provider_id": provider_id}
737+
workspaces = await self._exec_select_conditions_to_pydantic(
738+
WorkspaceWithModel, sql, conditions, should_raise=True
739+
)
740+
return workspaces
741+
723742
async def get_archived_workspace_by_name(self, name: str) -> Optional[WorkspaceRow]:
724743
sql = text(
725744
"""

src/codegate/db/models.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,14 @@ class WorkspaceWithSessionInfo(BaseModel):
189189
session_id: Optional[str]
190190

191191

192+
class WorkspaceWithModel(BaseModel):
193+
"""Returns a workspace ID with model name"""
194+
195+
id: str
196+
name: WorkspaceNameStr
197+
provider_model_name: str
198+
199+
192200
class ActiveWorkspace(BaseModel):
193201
"""Returns a full active workspace object with the
194202
with the session information.

0 commit comments

Comments
 (0)