Skip to content

Commit 049fd21

Browse files
committed
Merge branch 'main' into mermaid-diagrams-2
2 parents d6713d8 + 3b9331b commit 049fd21

File tree

74 files changed

+4639
-613
lines changed

Some content is hidden

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

74 files changed

+4639
-613
lines changed

.github/workflows/compliance.yaml

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
name: PR Compliance Checks
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened, ready_for_review]
6+
branches: [main]
7+
workflow_dispatch:
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
conventional-commits:
15+
name: Validate Conventional Commits (Warning Only)
16+
runs-on: ubuntu-latest
17+
if: ${{ !github.event.pull_request.draft }}
18+
continue-on-error: true
19+
permissions:
20+
pull-requests: write
21+
issues: write
22+
contents: read
23+
steps:
24+
- name: Checkout code
25+
uses: actions/checkout@v4
26+
with:
27+
fetch-depth: 0
28+
29+
- name: Validate conventional commits
30+
id: commitlint
31+
uses: wagoid/commitlint-github-action@v6
32+
with:
33+
configFile: .commitlintrc.warning.json
34+
continue-on-error: true
35+
36+
- name: Add commit message guidance comment
37+
if: steps.commitlint.outcome == 'failure'
38+
uses: actions/github-script@v7
39+
with:
40+
script: |
41+
const { data: comments } = await github.rest.issues.listComments({
42+
owner: context.repo.owner,
43+
repo: context.repo.repo,
44+
issue_number: context.issue.number,
45+
});
46+
47+
const botComment = comments.find(comment =>
48+
comment.user.type === 'Bot' &&
49+
comment.body.includes('Conventional Commit Format')
50+
);
51+
52+
if (!botComment) {
53+
await github.rest.issues.createComment({
54+
owner: context.repo.owner,
55+
repo: context.repo.repo,
56+
issue_number: context.issue.number,
57+
body: [
58+
"## ⚠️ Conventional Commit Format",
59+
"",
60+
"Your commit messages don't follow the conventional commit format, but **this won't block your PR from being merged**. We recommend downloading [this extension](https://marketplace.visualstudio.com/items?itemName=vivaxy.vscode-conventional-commits) if you are using VS Code.",
61+
"",
62+
"### Expected Format:",
63+
"```",
64+
"<type>[optional scope]: <description>",
65+
"",
66+
"[optional body]",
67+
"",
68+
"[optional footer(s)]",
69+
"```",
70+
"",
71+
"### Examples:",
72+
"- `feat: add changelog generation support`",
73+
"- `fix: resolve login redirect issue`",
74+
"- `docs: update README with new instructions`",
75+
"- `chore: update dependencies`",
76+
"",
77+
"### Valid Types:",
78+
"`feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`",
79+
"",
80+
"This helps with:",
81+
"- 📝 Automatic changelog generation",
82+
"- 🚀 Automated semantic versioning",
83+
"- 📊 Better project history tracking",
84+
"",
85+
"*This is a non-blocking warning - your PR can still be merged without fixing this.*"
86+
].join('\n')
87+
});
88+
}
89+
90+
security-audit:
91+
name: Security Audit
92+
runs-on: ubuntu-latest
93+
if: ${{ !github.event.pull_request.draft }}
94+
permissions:
95+
security-events: write
96+
contents: read
97+
steps:
98+
- name: Checkout code
99+
uses: actions/checkout@v4
100+
101+
- name: Setup Node.js
102+
uses: actions/setup-node@v4
103+
with:
104+
node-version-file: ".nvmrc"
105+
cache: "npm"
106+
107+
- name: Install dependencies
108+
run: npm ci
109+
110+
- name: Fix vulnerabilities
111+
run: npm audit fix
112+
113+
- name: Run npm audit
114+
run: npm audit --audit-level=moderate
115+
116+
- name: Initialize CodeQL
117+
uses: github/codeql-action/init@v3
118+
with:
119+
languages: javascript
120+
121+
- name: Perform CodeQL Analysis
122+
uses: github/codeql-action/analyze@v3
123+
124+
# Use this for any files that we want to be certain exist
125+
# Basically creates a forcing function to discuss were anyone to want to remove them
126+
file-validation:
127+
name: Required Files Check
128+
runs-on: ubuntu-latest
129+
if: ${{ !github.event.pull_request.draft }}
130+
steps:
131+
- name: Checkout code
132+
uses: actions/checkout@v4
133+
134+
- name: Check required files
135+
run: |
136+
required_files=(
137+
"package.json"
138+
"package-lock.json"
139+
"README.md"
140+
"LICENSE"
141+
".gitignore"
142+
"tsconfig.json"
143+
"SECURITY.md"
144+
"CONTRIBUTING.md"
145+
".nvmrc"
146+
".prettierrc"
147+
".prettierignore"
148+
)
149+
150+
missing_files=()
151+
for file in "${required_files[@]}"; do
152+
if [[ ! -f "$file" ]]; then
153+
missing_files+=("$file")
154+
fi
155+
done
156+
157+
if [[ ${#missing_files[@]} -gt 0 ]]; then
158+
echo "❌ Missing required files:"
159+
printf '%s\n' "${missing_files[@]}"
160+
exit 1
161+
else
162+
echo "✅ All required files present"
163+
fi
164+
165+
compliance-summary:
166+
name: Compliance Summary
167+
runs-on: ubuntu-latest
168+
needs: [conventional-commits, security-audit, file-validation]
169+
if: always() && !github.event.pull_request.draft
170+
steps:
171+
- name: Check compliance status
172+
run: |
173+
echo "## 🔍 Compliance Check Results" >> $GITHUB_STEP_SUMMARY
174+
echo "" >> $GITHUB_STEP_SUMMARY
175+
176+
if [[ "${{ needs.conventional-commits.result }}" == "success" ]]; then
177+
echo "✅ Conventional Commits: PASSED" >> $GITHUB_STEP_SUMMARY
178+
elif [[ "${{ needs.conventional-commits.result }}" == "failure" ]]; then
179+
echo "⚠️ Conventional Commits: WARNING (non-blocking)" >> $GITHUB_STEP_SUMMARY
180+
else
181+
echo "❌ Conventional Commits: SKIPPED" >> $GITHUB_STEP_SUMMARY
182+
fi
183+
184+
if [[ "${{ needs.security-audit.result }}" == "success" ]]; then
185+
echo "✅ Security Audit: PASSED" >> $GITHUB_STEP_SUMMARY
186+
else
187+
echo "❌ Security Audit: FAILED" >> $GITHUB_STEP_SUMMARY
188+
fi
189+
190+
if [[ "${{ needs.file-validation.result }}" == "success" ]]; then
191+
echo "✅ File Validation: PASSED" >> $GITHUB_STEP_SUMMARY
192+
else
193+
echo "❌ File Validation: FAILED" >> $GITHUB_STEP_SUMMARY
194+
fi
195+
196+
echo "" >> $GITHUB_STEP_SUMMARY
197+
echo "📊 **Overall Status**: ${{ job.status }}" >> $GITHUB_STEP_SUMMARY

core/config/load.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,13 +643,15 @@ function llmToSerializedModelDescription(llm: ILLM): ModelDescription {
643643
template: llm.template,
644644
completionOptions: llm.completionOptions,
645645
baseAgentSystemMessage: llm.baseAgentSystemMessage,
646+
basePlanSystemMessage: llm.basePlanSystemMessage,
646647
baseChatSystemMessage: llm.baseChatSystemMessage,
647648
requestOptions: llm.requestOptions,
648649
promptTemplates: serializePromptTemplates(llm.promptTemplates),
649650
capabilities: llm.capabilities,
650651
roles: llm.roles,
651652
configurationStatus: llm.getConfigurationStatus(),
652653
apiKeyLocation: llm.apiKeyLocation,
654+
envSecretLocations: llm.envSecretLocations,
653655
};
654656
}
655657

core/config/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,8 @@ declare global {
10041004
type: "stdio";
10051005
command: string;
10061006
args: string[];
1007+
env?: Record<string, string>;
1008+
cwd?: string;
10071009
}
10081010
10091011
interface WebSocketOptions {

core/config/yaml/loadYaml.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ function convertYamlMcpToContinueMcp(
6969
command: server.command,
7070
args: server.args ?? [],
7171
env: server.env,
72+
cwd: server.cwd,
7273
} as any, // TODO: Fix the mcpServers types in config-yaml (discriminated union)
7374
timeout: server.connectionTimeout,
7475
};
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { describe, it, expect } from "vitest";
2+
import {
3+
validateConfigYaml,
4+
AssistantUnrolledNonNullable,
5+
} from "@continuedev/config-yaml";
6+
7+
describe("MCP Server cwd configuration", () => {
8+
describe("YAML schema validation", () => {
9+
it("should accept valid MCP server with cwd", () => {
10+
const config: AssistantUnrolledNonNullable = {
11+
name: "test-assistant",
12+
version: "1.0.0",
13+
mcpServers: [
14+
{
15+
name: "test-server",
16+
command: "node",
17+
args: ["server.js"],
18+
env: { NODE_ENV: "production" },
19+
cwd: "/path/to/project",
20+
connectionTimeout: 5000,
21+
},
22+
],
23+
};
24+
25+
const errors = validateConfigYaml(config);
26+
expect(errors).toHaveLength(0);
27+
});
28+
29+
it("should accept MCP server without cwd", () => {
30+
const config: AssistantUnrolledNonNullable = {
31+
name: "test-assistant",
32+
version: "1.0.0",
33+
mcpServers: [
34+
{
35+
name: "test-server",
36+
command: "python",
37+
args: ["-m", "server"],
38+
},
39+
],
40+
};
41+
42+
const errors = validateConfigYaml(config);
43+
expect(errors).toHaveLength(0);
44+
});
45+
46+
it("should accept relative paths in cwd", () => {
47+
const config: AssistantUnrolledNonNullable = {
48+
name: "test-assistant",
49+
version: "1.0.0",
50+
mcpServers: [
51+
{
52+
name: "test-server",
53+
command: "cargo",
54+
args: ["run"],
55+
cwd: "./rust-project",
56+
},
57+
],
58+
};
59+
60+
const errors = validateConfigYaml(config);
61+
expect(errors).toHaveLength(0);
62+
});
63+
64+
it("should accept empty string cwd", () => {
65+
const config: AssistantUnrolledNonNullable = {
66+
name: "test-assistant",
67+
version: "1.0.0",
68+
mcpServers: [
69+
{
70+
name: "test-server",
71+
command: "deno",
72+
args: ["run", "server.ts"],
73+
cwd: "",
74+
},
75+
],
76+
};
77+
78+
const errors = validateConfigYaml(config);
79+
expect(errors).toHaveLength(0);
80+
});
81+
});
82+
83+
describe("MCP server configuration examples", () => {
84+
it("should support common MCP server patterns with cwd", () => {
85+
const configs = [
86+
{
87+
name: "Local project MCP server",
88+
server: {
89+
name: "project-mcp",
90+
command: "npm",
91+
args: ["run", "mcp-server"],
92+
cwd: "/Users/developer/my-project",
93+
},
94+
},
95+
{
96+
name: "Python MCP with virtual environment",
97+
server: {
98+
name: "python-mcp",
99+
command: "python",
100+
args: ["-m", "my_mcp_server"],
101+
env: { PYTHONPATH: "./src" },
102+
cwd: "/home/user/python-project",
103+
},
104+
},
105+
{
106+
name: "Relative path MCP server",
107+
server: {
108+
name: "relative-mcp",
109+
command: "node",
110+
args: ["index.js"],
111+
cwd: "../mcp-servers/filesystem",
112+
},
113+
},
114+
];
115+
116+
configs.forEach(({ name, server }) => {
117+
const config: AssistantUnrolledNonNullable = {
118+
name: "test-assistant",
119+
version: "1.0.0",
120+
mcpServers: [server],
121+
};
122+
123+
const errors = validateConfigYaml(config);
124+
expect(errors).toHaveLength(0);
125+
});
126+
});
127+
});
128+
});

core/config/yaml/models.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ async function modelConfigToBaseLLM({
6363
template: model.promptTemplates?.chat,
6464
promptTemplates: model.promptTemplates,
6565
baseAgentSystemMessage: model.chatOptions?.baseAgentSystemMessage,
66+
basePlanSystemMessage: model.chatOptions?.basePlanSystemMessage,
6667
baseChatSystemMessage: model.chatOptions?.baseSystemMessage,
6768
capabilities: {
6869
tools: model.capabilities?.includes("tool_use"),
@@ -126,6 +127,12 @@ async function modelConfigToBaseLLM({
126127
if ("profile" in env && typeof env.profile === "string") {
127128
options.profile = env.profile;
128129
}
130+
if ("accessKeyId" in env && typeof env.accessKeyId === "string") {
131+
options.accessKeyId = env.accessKeyId;
132+
}
133+
if ("secretAccessKey" in env && typeof env.secretAccessKey === "string") {
134+
options.secretAccessKey = env.secretAccessKey;
135+
}
129136
if ("modelArn" in env && typeof env.modelArn === "string") {
130137
options.modelArn = env.modelArn;
131138
}

core/context/mcp/MCPConnection.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ class MCPConnection {
329329
command,
330330
args,
331331
env,
332+
cwd: options.transport.cwd,
332333
stderr: "pipe",
333334
});
334335

0 commit comments

Comments
 (0)