Compare commits
299 Commits
refactor-d
...
feat/vscod
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32c085cf7d | ||
|
|
d4a0e84508 | ||
|
|
1806390421 | ||
|
|
5c6ed070de | ||
|
|
883c6d878c | ||
|
|
b9a2cc7bdf | ||
|
|
4cbb57a793 | ||
|
|
9280739a85 | ||
|
|
b6128ef2d2 | ||
|
|
f7ef720e3b | ||
|
|
0e6ebe85e4 | ||
|
|
3138aa1fe3 | ||
|
|
0f2f1faee5 | ||
|
|
641dd03689 | ||
|
|
44fef93399 | ||
|
|
b073b2db79 | ||
|
|
ccc6192164 | ||
|
|
a5f8c66c35 | ||
|
|
c8d18591b0 | ||
|
|
e9036daa8d | ||
|
|
8e29cc88f9 | ||
|
|
61ce586117 | ||
|
|
90fc4c33f0 | ||
|
|
389d8dd9c4 | ||
|
|
4590138a1e | ||
|
|
0ac191e2db | ||
|
|
9e392b3035 | ||
|
|
65796e2799 | ||
|
|
8fdcd53f53 | ||
|
|
693a58d517 | ||
|
|
c7f4c462f4 | ||
|
|
c94708e448 | ||
|
|
0b854e494f | ||
|
|
f6f4b24356 | ||
|
|
bc5dd87eb4 | ||
|
|
f8aeb06823 | ||
|
|
bca288e742 | ||
|
|
5841370b1a | ||
|
|
0d90d5c118 | ||
|
|
cc0d688c8b | ||
|
|
4eb7aa5448 | ||
|
|
9978fe107b | ||
|
|
b95bb2cd95 | ||
|
|
e895c49f5c | ||
|
|
3191cf73b3 | ||
|
|
f5306339f6 | ||
|
|
026fd468b1 | ||
|
|
d25af87eaf | ||
|
|
a5039d15bf | ||
|
|
3ff916a5f1 | ||
|
|
7bb9bc1e5e | ||
|
|
8b29dd130e | ||
|
|
d0be8b43d7 | ||
|
|
3095442eb3 | ||
|
|
2ceecab503 | ||
|
|
e5ed0334ab | ||
|
|
2b62b1e8bc | ||
|
|
89be6edb5e | ||
|
|
d812c9dcf2 | ||
|
|
d754767e73 | ||
|
|
bb8447edd7 | ||
|
|
02234f5434 | ||
|
|
25261ab88d | ||
|
|
60a58ad8e5 | ||
|
|
c20df192a8 | ||
|
|
b34894c8ea | ||
|
|
ba3b576906 | ||
|
|
b67ee32481 | ||
|
|
5b8ce440ea | ||
|
|
58d3a9c253 | ||
|
|
d06a6d7ef9 | ||
|
|
ae9753a326 | ||
|
|
a02c4b2765 | ||
|
|
0055399cba | ||
|
|
5f78909040 | ||
|
|
5ef3d32f16 | ||
|
|
49c032492a | ||
|
|
4345b9370e | ||
|
|
d2e2a07327 | ||
|
|
5b74422be6 | ||
|
|
06c398a015 | ||
|
|
aec5d6463a | ||
|
|
29032d2c6a | ||
|
|
e91ea3ac1a | ||
|
|
f2a74c74b6 | ||
|
|
21651410c8 | ||
|
|
09cefbcf67 | ||
|
|
5fddcd509c | ||
|
|
d7b9466516 | ||
|
|
fcd4bb9c03 | ||
|
|
828b760820 | ||
|
|
ef3d7b92d0 | ||
|
|
58b9e477bc | ||
|
|
f4edcc5cd2 | ||
|
|
7adb9ed7ff | ||
|
|
f146f062cb | ||
|
|
111234eb24 | ||
|
|
dd7f9ed489 | ||
|
|
5fa87e6fbb | ||
|
|
a6a572336c | ||
|
|
96cd685b1b | ||
|
|
e8b4ee111c | ||
|
|
ac0d5206ba | ||
|
|
e5e1e6a3da | ||
|
|
6269415e7b | ||
|
|
efccd44cb4 | ||
|
|
0a8281f2dd | ||
|
|
efbf50554d | ||
|
|
63e4794633 | ||
|
|
be71976a1f | ||
|
|
e47263f7c9 | ||
|
|
51b4de0c23 | ||
|
|
67eee14ca9 | ||
|
|
ed44520e51 | ||
|
|
7cd26f728d | ||
|
|
ad79b9bcab | ||
|
|
ad301963a6 | ||
|
|
e538a3d1bf | ||
|
|
413c143004 | ||
|
|
b4be2c6c7f | ||
|
|
8b5b8d2b90 | ||
|
|
6e826b815e | ||
|
|
86b166bb1d | ||
|
|
57a684ad97 | ||
|
|
bf6abf7752 | ||
|
|
541d0b22e5 | ||
|
|
96b275a756 | ||
|
|
ab228c682f | ||
|
|
22943b888d | ||
|
|
96d458fa8c | ||
|
|
0e9255b122 | ||
|
|
3ed0a34b5e | ||
|
|
2949b33a4e | ||
|
|
c218048551 | ||
|
|
be44e7af56 | ||
|
|
ac9cb3a6d3 | ||
|
|
13aa4b03c7 | ||
|
|
75fd2a5dcc | ||
|
|
811b332bc3 | ||
|
|
bf4673b00b | ||
|
|
645a5b181a | ||
|
|
2957058521 | ||
|
|
e7b92622ce | ||
|
|
82f97fe56d | ||
|
|
2c1a836f18 | ||
|
|
3a7b1159ae | ||
|
|
3e2a2255ee | ||
|
|
46478e5dd3 | ||
|
|
64de3520b3 | ||
|
|
322ce80e2c | ||
|
|
c6f5a4585e | ||
|
|
b1a439e38f | ||
|
|
a6467e7f9b | ||
|
|
5ed60348d6 | ||
|
|
0851ab572d | ||
|
|
a58d3f7aaf | ||
|
|
8203f6582f | ||
|
|
2d844d11df | ||
|
|
aacc4b43ff | ||
|
|
57b519db9a | ||
|
|
43f23f8ce5 | ||
|
|
427c69ba07 | ||
|
|
1c45ef563d | ||
|
|
0630908e0c | ||
|
|
c18fed574f | ||
|
|
51b9281774 | ||
|
|
839a1d9d8c | ||
|
|
56f61bc0b8 | ||
|
|
b1d848f935 | ||
|
|
81c8b3eaec | ||
|
|
50e3a6ee0a | ||
|
|
3056f8a63d | ||
|
|
ae7d6af717 | ||
|
|
8035be6f8d | ||
|
|
249b141f19 | ||
|
|
56957a687b | ||
|
|
638b7bb466 | ||
|
|
d76341b8d8 | ||
|
|
769a438fa4 | ||
|
|
49dc84ac0e | ||
|
|
ac6aecb622 | ||
|
|
ad9ba914e1 | ||
|
|
d76cdf1076 | ||
|
|
e1ffaec499 | ||
|
|
5b2f3e285c | ||
|
|
4145f45c7c | ||
|
|
d56923b657 | ||
|
|
32258f2f04 | ||
|
|
5dec3e653c | ||
|
|
3053e6c41f | ||
|
|
86cd06ef43 | ||
|
|
7270983821 | ||
|
|
b1901f103f | ||
|
|
5701a3c897 | ||
|
|
2145b28f8b | ||
|
|
e3c456a430 | ||
|
|
35f98723ca | ||
|
|
b9b3b6d62e | ||
|
|
cec6b8691a | ||
|
|
05f5189bb4 | ||
|
|
c6299bf135 | ||
|
|
2e449f4d45 | ||
|
|
90fc53a9df | ||
|
|
ed0d5f67db | ||
|
|
1b37d729cb | ||
|
|
1acc24bc17 | ||
|
|
b1e74e5732 | ||
|
|
82205034cc | ||
|
|
c038745897 | ||
|
|
6885138cf0 | ||
|
|
9ae45c01a6 | ||
|
|
5ce40085d5 | ||
|
|
627f5fb43a | ||
|
|
9cc48f12da | ||
|
|
dc340daf8b | ||
|
|
f78b1eff93 | ||
|
|
8bc9bea5a1 | ||
|
|
b986692f94 | ||
|
|
4f63d92bb1 | ||
|
|
3c09ad46ca | ||
|
|
d5ede56e62 | ||
|
|
530039c517 | ||
|
|
0cbf95d6b3 | ||
|
|
579772197a | ||
|
|
934365c41f | ||
|
|
f623bfbb34 | ||
|
|
f503eb2520 | ||
|
|
3cf22c065f | ||
|
|
a1ec1227cc | ||
|
|
36af718616 | ||
|
|
795e7fa2c5 | ||
|
|
b6914c6b33 | ||
|
|
f11d054a47 | ||
|
|
4ad377b0d8 | ||
|
|
b7f9acf0ff | ||
|
|
4dfbdcddca | ||
|
|
826516581b | ||
|
|
4f964b5281 | ||
|
|
de8ea0678d | ||
|
|
c4bcd178a4 | ||
|
|
e5729b0420 | ||
|
|
aceb857436 | ||
|
|
e15dd2f5c9 | ||
|
|
8ac38aad92 | ||
|
|
38fd303b07 | ||
|
|
9899d872a2 | ||
|
|
36a96a7b5c | ||
|
|
951f6b2829 | ||
|
|
eff01819a8 | ||
|
|
31f8ca07b6 | ||
|
|
39adaaff11 | ||
|
|
fd2e5b0933 | ||
|
|
49a2be195d | ||
|
|
ce07fb2b3f | ||
|
|
e2beecb9c4 | ||
|
|
ecc6e22002 | ||
|
|
99f93b457c | ||
|
|
748ad8f4dd | ||
|
|
a33187ed7a | ||
|
|
088c766c22 | ||
|
|
b82ef5b73f | ||
|
|
328924f578 | ||
|
|
1eedd36542 | ||
|
|
9ba99177b9 | ||
|
|
7d2411e72f | ||
|
|
5a9f5e3432 | ||
|
|
95b67bbebd | ||
|
|
492c56a780 | ||
|
|
06a8580361 | ||
|
|
dcc10eb0a9 | ||
|
|
805e5f92c1 | ||
|
|
8cb7ea0d3d | ||
|
|
b534bd2b18 | ||
|
|
6286b8b6e8 | ||
|
|
e81255e589 | ||
|
|
018990b7f6 | ||
|
|
bc2b503e8d | ||
|
|
454cbfdde4 | ||
|
|
04dfad7ab5 | ||
|
|
e02866d06f | ||
|
|
9fcdd3fa77 | ||
|
|
754ae30939 | ||
|
|
0577fe6f36 | ||
|
|
732220e651 | ||
|
|
729a3d0ab3 | ||
|
|
0e3759fbd2 | ||
|
|
f8db157a5d | ||
|
|
f827aadd76 | ||
|
|
39426be9a1 | ||
|
|
f95f6e63bb | ||
|
|
91af599823 | ||
|
|
ad8d7aae8a | ||
|
|
d22d07a840 | ||
|
|
28892996b3 | ||
|
|
eeeb1d490a | ||
|
|
247c237647 | ||
|
|
c423e12aa7 | ||
|
|
dc40995e70 | ||
|
|
1123b9f0fc |
237
.github/workflows/release-sdk.yml
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
name: 'Release SDK'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'The version to release (e.g., v0.1.11). Required for manual patch releases.'
|
||||
required: false
|
||||
type: 'string'
|
||||
ref:
|
||||
description: 'The branch or ref (full git sha) to release from.'
|
||||
required: true
|
||||
type: 'string'
|
||||
default: 'main'
|
||||
dry_run:
|
||||
description: 'Run a dry-run of the release process; no branches, npm packages or GitHub releases will be created.'
|
||||
required: true
|
||||
type: 'boolean'
|
||||
default: true
|
||||
create_nightly_release:
|
||||
description: 'Auto apply the nightly release tag, input version is ignored.'
|
||||
required: false
|
||||
type: 'boolean'
|
||||
default: false
|
||||
create_preview_release:
|
||||
description: 'Auto apply the preview release tag, input version is ignored.'
|
||||
required: false
|
||||
type: 'boolean'
|
||||
default: false
|
||||
force_skip_tests:
|
||||
description: 'Select to skip the "Run Tests" step in testing. Prod releases should run tests'
|
||||
required: false
|
||||
type: 'boolean'
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
release-sdk:
|
||||
runs-on: 'ubuntu-latest'
|
||||
environment:
|
||||
name: 'production-release'
|
||||
url: '${{ github.server_url }}/${{ github.repository }}/releases/tag/sdk-typescript-${{ steps.version.outputs.RELEASE_TAG }}'
|
||||
if: |-
|
||||
${{ github.repository == 'QwenLM/qwen-code' }}
|
||||
permissions:
|
||||
contents: 'write'
|
||||
packages: 'write'
|
||||
id-token: 'write'
|
||||
issues: 'write'
|
||||
outputs:
|
||||
RELEASE_TAG: '${{ steps.version.outputs.RELEASE_TAG }}'
|
||||
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
with:
|
||||
ref: '${{ github.event.inputs.ref || github.sha }}'
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 'Set booleans for simplified logic'
|
||||
env:
|
||||
CREATE_NIGHTLY_RELEASE: '${{ github.event.inputs.create_nightly_release }}'
|
||||
CREATE_PREVIEW_RELEASE: '${{ github.event.inputs.create_preview_release }}'
|
||||
DRY_RUN_INPUT: '${{ github.event.inputs.dry_run }}'
|
||||
id: 'vars'
|
||||
run: |-
|
||||
is_nightly="false"
|
||||
if [[ "${CREATE_NIGHTLY_RELEASE}" == "true" ]]; then
|
||||
is_nightly="true"
|
||||
fi
|
||||
echo "is_nightly=${is_nightly}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
is_preview="false"
|
||||
if [[ "${CREATE_PREVIEW_RELEASE}" == "true" ]]; then
|
||||
is_preview="true"
|
||||
fi
|
||||
echo "is_preview=${is_preview}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
is_dry_run="false"
|
||||
if [[ "${DRY_RUN_INPUT}" == "true" ]]; then
|
||||
is_dry_run="true"
|
||||
fi
|
||||
echo "is_dry_run=${is_dry_run}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: 'Setup Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install Dependencies'
|
||||
run: |-
|
||||
npm ci
|
||||
|
||||
- name: 'Get the version'
|
||||
id: 'version'
|
||||
run: |
|
||||
VERSION_ARGS=()
|
||||
if [[ "${IS_NIGHTLY}" == "true" ]]; then
|
||||
VERSION_ARGS+=(--type=nightly)
|
||||
elif [[ "${IS_PREVIEW}" == "true" ]]; then
|
||||
VERSION_ARGS+=(--type=preview)
|
||||
if [[ -n "${MANUAL_VERSION}" ]]; then
|
||||
VERSION_ARGS+=("--preview_version_override=${MANUAL_VERSION}")
|
||||
fi
|
||||
else
|
||||
VERSION_ARGS+=(--type=stable)
|
||||
if [[ -n "${MANUAL_VERSION}" ]]; then
|
||||
VERSION_ARGS+=("--stable_version_override=${MANUAL_VERSION}")
|
||||
fi
|
||||
fi
|
||||
|
||||
VERSION_JSON=$(node packages/sdk-typescript/scripts/get-release-version.js "${VERSION_ARGS[@]}")
|
||||
echo "RELEASE_TAG=$(echo "$VERSION_JSON" | jq -r .releaseTag)" >> "$GITHUB_OUTPUT"
|
||||
echo "RELEASE_VERSION=$(echo "$VERSION_JSON" | jq -r .releaseVersion)" >> "$GITHUB_OUTPUT"
|
||||
echo "NPM_TAG=$(echo "$VERSION_JSON" | jq -r .npmTag)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
echo "PREVIOUS_RELEASE_TAG=$(echo "$VERSION_JSON" | jq -r .previousReleaseTag)" >> "$GITHUB_OUTPUT"
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
IS_NIGHTLY: '${{ steps.vars.outputs.is_nightly }}'
|
||||
IS_PREVIEW: '${{ steps.vars.outputs.is_preview }}'
|
||||
MANUAL_VERSION: '${{ inputs.version }}'
|
||||
|
||||
- name: 'Run Tests'
|
||||
if: |-
|
||||
${{ github.event.inputs.force_skip_tests != 'true' }}
|
||||
working-directory: 'packages/sdk-typescript'
|
||||
run: |
|
||||
npm run test:ci
|
||||
env:
|
||||
OPENAI_API_KEY: '${{ secrets.OPENAI_API_KEY }}'
|
||||
OPENAI_BASE_URL: '${{ secrets.OPENAI_BASE_URL }}'
|
||||
OPENAI_MODEL: '${{ secrets.OPENAI_MODEL }}'
|
||||
|
||||
- name: 'Build CLI for Integration Tests'
|
||||
if: |-
|
||||
${{ github.event.inputs.force_skip_tests != 'true' }}
|
||||
run: |
|
||||
npm run build
|
||||
npm run bundle
|
||||
|
||||
- name: 'Run SDK Integration Tests'
|
||||
if: |-
|
||||
${{ github.event.inputs.force_skip_tests != 'true' }}
|
||||
run: |
|
||||
npm run test:integration:sdk:sandbox:none
|
||||
npm run test:integration:sdk:sandbox:docker
|
||||
env:
|
||||
OPENAI_API_KEY: '${{ secrets.OPENAI_API_KEY }}'
|
||||
OPENAI_BASE_URL: '${{ secrets.OPENAI_BASE_URL }}'
|
||||
OPENAI_MODEL: '${{ secrets.OPENAI_MODEL }}'
|
||||
|
||||
- name: 'Configure Git User'
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: 'Create and switch to a release branch'
|
||||
id: 'release_branch'
|
||||
env:
|
||||
RELEASE_TAG: '${{ steps.version.outputs.RELEASE_TAG }}'
|
||||
run: |-
|
||||
BRANCH_NAME="release/sdk-typescript/${RELEASE_TAG}"
|
||||
git switch -c "${BRANCH_NAME}"
|
||||
echo "BRANCH_NAME=${BRANCH_NAME}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: 'Update package version'
|
||||
working-directory: 'packages/sdk-typescript'
|
||||
env:
|
||||
RELEASE_VERSION: '${{ steps.version.outputs.RELEASE_VERSION }}'
|
||||
run: |-
|
||||
npm version "${RELEASE_VERSION}" --no-git-tag-version --allow-same-version
|
||||
|
||||
- name: 'Commit and Conditionally Push package version'
|
||||
env:
|
||||
BRANCH_NAME: '${{ steps.release_branch.outputs.BRANCH_NAME }}'
|
||||
IS_DRY_RUN: '${{ steps.vars.outputs.is_dry_run }}'
|
||||
RELEASE_TAG: '${{ steps.version.outputs.RELEASE_TAG }}'
|
||||
run: |-
|
||||
git add packages/sdk-typescript/package.json
|
||||
if git diff --staged --quiet; then
|
||||
echo "No version changes to commit"
|
||||
else
|
||||
git commit -m "chore(release): sdk-typescript ${RELEASE_TAG}"
|
||||
fi
|
||||
if [[ "${IS_DRY_RUN}" == "false" ]]; then
|
||||
echo "Pushing release branch to remote..."
|
||||
git push --set-upstream origin "${BRANCH_NAME}" --follow-tags
|
||||
else
|
||||
echo "Dry run enabled. Skipping push."
|
||||
fi
|
||||
|
||||
- name: 'Build SDK'
|
||||
working-directory: 'packages/sdk-typescript'
|
||||
run: |-
|
||||
npm run build
|
||||
|
||||
- name: 'Configure npm for publishing'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
scope: '@qwen-code'
|
||||
|
||||
- name: 'Publish @qwen-code/sdk'
|
||||
working-directory: 'packages/sdk-typescript'
|
||||
run: |-
|
||||
npm publish --access public --tag=${{ steps.version.outputs.NPM_TAG }} ${{ steps.vars.outputs.is_dry_run == 'true' && '--dry-run' || '' }}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ secrets.NPM_TOKEN }}'
|
||||
|
||||
- name: 'Create GitHub Release and Tag'
|
||||
if: |-
|
||||
${{ steps.vars.outputs.is_dry_run == 'false' }}
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
RELEASE_BRANCH: '${{ steps.release_branch.outputs.BRANCH_NAME }}'
|
||||
RELEASE_TAG: '${{ steps.version.outputs.RELEASE_TAG }}'
|
||||
PREVIOUS_RELEASE_TAG: '${{ steps.version.outputs.PREVIOUS_RELEASE_TAG }}'
|
||||
run: |-
|
||||
gh release create "sdk-typescript-${RELEASE_TAG}" \
|
||||
--target "$RELEASE_BRANCH" \
|
||||
--title "SDK TypeScript Release ${RELEASE_TAG}" \
|
||||
--notes-start-tag "sdk-typescript-${PREVIOUS_RELEASE_TAG}" \
|
||||
--generate-notes
|
||||
|
||||
- name: 'Create Issue on Failure'
|
||||
if: |-
|
||||
${{ failure() }}
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
RELEASE_TAG: "${{ steps.version.outputs.RELEASE_TAG || 'N/A' }}"
|
||||
DETAILS_URL: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||
run: |-
|
||||
gh issue create \
|
||||
--title "SDK Release Failed for ${RELEASE_TAG} on $(date +'%Y-%m-%d')" \
|
||||
--body "The SDK release workflow failed. See the full run for details: ${DETAILS_URL}"
|
||||
3
.vscode/launch.json
vendored
@@ -27,7 +27,7 @@
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/packages/vscode-ide-companion/dist/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "npm: build: vscode-ide-companion"
|
||||
"preLaunchTask": "launch: vscode-ide-companion (copy+build)"
|
||||
},
|
||||
{
|
||||
"name": "Attach",
|
||||
@@ -79,7 +79,6 @@
|
||||
"--",
|
||||
"-p",
|
||||
"${input:prompt}",
|
||||
"-y",
|
||||
"--output-format",
|
||||
"stream-json"
|
||||
],
|
||||
|
||||
16
.vscode/tasks.json
vendored
@@ -20,6 +20,22 @@
|
||||
"problemMatcher": [],
|
||||
"label": "npm: build: vscode-ide-companion",
|
||||
"detail": "npm run build -w packages/vscode-ide-companion"
|
||||
},
|
||||
{
|
||||
"label": "copy: bundled-cli (dev)",
|
||||
"type": "shell",
|
||||
"command": "node",
|
||||
"args": ["packages/vscode-ide-companion/scripts/copy-bundled-cli.js"],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "launch: vscode-ide-companion (copy+build)",
|
||||
"dependsOrder": "sequence",
|
||||
"dependsOn": [
|
||||
"copy: bundled-cli (dev)",
|
||||
"npm: build: vscode-ide-companion"
|
||||
],
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -88,6 +88,12 @@ npm install -g .
|
||||
brew install qwen-code
|
||||
```
|
||||
|
||||
## VS Code Extension
|
||||
|
||||
In addition to the CLI tool, Qwen Code also provides a **VS Code extension** that brings AI-powered coding assistance directly into your editor with features like file system operations, native diffing, interactive chat, and more.
|
||||
|
||||
> 📦 The extension is currently in development. For installation, features, and development guide, see the [VS Code Extension README](./packages/vscode-ide-companion/README.md).
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
export default {
|
||||
index: {
|
||||
type: 'page',
|
||||
display: 'hidden',
|
||||
},
|
||||
users: {
|
||||
type: 'page',
|
||||
title: 'User Guide',
|
||||
},
|
||||
developers: {
|
||||
type: 'page',
|
||||
title: 'Developer Guide',
|
||||
},
|
||||
index: 'Welcome to Qwen Code',
|
||||
cli: 'CLI',
|
||||
core: 'Core',
|
||||
tools: 'Tools',
|
||||
features: 'Features',
|
||||
'ide-integration': 'IDE Integration',
|
||||
development: 'Development',
|
||||
support: 'Support',
|
||||
};
|
||||
|
||||
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 350 KiB After Width: | Height: | Size: 350 KiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 381 KiB After Width: | Height: | Size: 381 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 259 KiB After Width: | Height: | Size: 259 KiB |
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
@@ -5,7 +5,12 @@ export default {
|
||||
commands: 'Commands',
|
||||
configuration: 'Configuration',
|
||||
'configuration-v1': 'Configuration (v1)',
|
||||
themes: 'Themes',
|
||||
tutorials: 'Tutorials',
|
||||
'keyboard-shortcuts': 'Keyboard Shortcuts',
|
||||
'trusted-folders': 'Trusted Folders',
|
||||
'qwen-ignore': 'Ignoring Files',
|
||||
Uninstall: 'Uninstall',
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -145,16 +145,6 @@ Slash commands provide meta-level control over the CLI itself.
|
||||
- **`nodesc`** or **`nodescriptions`**:
|
||||
- **Description:** Hide tool descriptions, showing only the tool names.
|
||||
|
||||
- **`/quit-confirm`**
|
||||
- **Description:** Show a confirmation dialog before exiting Qwen Code, allowing you to choose how to handle your current session.
|
||||
- **Usage:** `/quit-confirm`
|
||||
- **Features:**
|
||||
- **Quit immediately:** Exit without saving anything (equivalent to `/quit`)
|
||||
- **Generate summary and quit:** Create a project summary using `/summary` before exiting
|
||||
- **Save conversation and quit:** Save the current conversation with an auto-generated tag before exiting
|
||||
- **Keyboard shortcut:** Press **Ctrl+C** twice to trigger the quit confirmation dialog
|
||||
- **Note:** This command is automatically triggered when you press Ctrl+C once, providing a safety mechanism to prevent accidental exits.
|
||||
|
||||
- **`/quit`** (or **`/exit`**)
|
||||
- **Description:** Exit Qwen Code immediately without any confirmation dialog.
|
||||
|
||||
@@ -671,4 +671,4 @@ Note: When usage statistics are enabled, events are sent to an Alibaba Cloud RUM
|
||||
- **Category:** UI
|
||||
- **Requires Restart:** No
|
||||
- **Example:** `"enableWelcomeBack": false`
|
||||
- **Details:** When enabled, Qwen Code will automatically detect if you're returning to a project with a previously generated project summary (`.qwen/PROJECT_SUMMARY.md`) and show a dialog allowing you to continue your previous conversation or start fresh. This feature integrates with the `/summary` command and quit confirmation dialog. See the [Welcome Back documentation](./welcome-back.md) for more details.
|
||||
- **Details:** When enabled, Qwen Code will automatically detect if you're returning to a project with a previously generated project summary (`.qwen/PROJECT_SUMMARY.md`) and show a dialog allowing you to continue your previous conversation or start fresh. This feature integrates with the `/summary` command. See the [Welcome Back documentation](./welcome-back.md) for more details.
|
||||
@@ -10,19 +10,21 @@ The `/language` command allows you to customize the language settings for both t
|
||||
To change the UI language of Qwen Code, use the `ui` subcommand:
|
||||
|
||||
```
|
||||
/language ui [zh-CN|en-US]
|
||||
/language ui [zh-CN|en-US|ru-RU]
|
||||
```
|
||||
|
||||
### Available UI Languages
|
||||
|
||||
- **zh-CN**: Simplified Chinese (简体中文)
|
||||
- **en-US**: English
|
||||
- **ru-RU**: Russian (Русский)
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
/language ui zh-CN # Set UI language to Simplified Chinese
|
||||
/language ui en-US # Set UI language to English
|
||||
/language ui ru-RU # Set UI language to Russian
|
||||
```
|
||||
|
||||
### UI Language Subcommands
|
||||
@@ -31,6 +33,7 @@ You can also use direct subcommands for convenience:
|
||||
|
||||
- `/language ui zh-CN` or `/language ui zh` or `/language ui 中文`
|
||||
- `/language ui en-US` or `/language ui en` or `/language ui english`
|
||||
- `/language ui ru-RU` or `/language ui ru` or `/language ui русский`
|
||||
|
||||
## LLM Output Language Settings
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
export default {
|
||||
'Contribute to Qwen Code': {
|
||||
title: 'Contribute to Qwen Code',
|
||||
type: 'separator',
|
||||
},
|
||||
architecture: 'Architecture',
|
||||
contributing: 'Contributing Guide',
|
||||
roadmap: 'Roadmap',
|
||||
'Qwen Code SDK': {
|
||||
title: 'Qwen Code SDK',
|
||||
type: 'separator',
|
||||
},
|
||||
'Dive Into Qwen Code': {
|
||||
title: 'Dive Into Qwen Code',
|
||||
type: 'separator',
|
||||
},
|
||||
cli: {
|
||||
display: 'hidden',
|
||||
},
|
||||
core: 'Core',
|
||||
tools: 'Tools',
|
||||
// development: 'Development',
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
# Qwen Code RoadMap
|
||||
@@ -1,5 +1,7 @@
|
||||
export default {
|
||||
architecture: 'Architecture',
|
||||
npm: 'NPM',
|
||||
deployment: 'Deployment',
|
||||
telemetry: 'Telemetry',
|
||||
'integration-tests': 'Integration Tests',
|
||||
'issue-and-pr-automation': 'Issue and PR Automation',
|
||||
8
docs/features/_meta.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export default {
|
||||
subagents: 'Subagents',
|
||||
checkpointing: 'Checkpointing',
|
||||
sandbox: 'Sandbox Support',
|
||||
headless: 'Headless Mode',
|
||||
'welcome-back': 'Welcome Back',
|
||||
'token-caching': 'Token Caching',
|
||||
};
|
||||
@@ -81,14 +81,6 @@ The Welcome Back feature works seamlessly with the `/summary` command:
|
||||
2. **Automatic Detection:** Next time you start Qwen Code in this project, Welcome Back will detect the summary
|
||||
3. **Resume Work:** Choose to continue and the summary will be loaded as context
|
||||
|
||||
### Quit Confirmation
|
||||
|
||||
When exiting with `/quit-confirm` and choosing "Generate summary and quit":
|
||||
|
||||
1. A project summary is automatically created
|
||||
2. Next session will trigger the Welcome Back dialog
|
||||
3. You can seamlessly continue your work
|
||||
|
||||
## File Structure
|
||||
|
||||
The Welcome Back feature creates and uses:
|
||||
344
docs/index.md
@@ -0,0 +1,344 @@
|
||||
# Welcome to Qwen Code documentation
|
||||
|
||||
Qwen Code is a powerful command-line AI workflow tool adapted from [**Gemini CLI**](https://github.com/google-gemini/gemini-cli) ([details](./README.gemini.md)), specifically optimized for [Qwen3-Coder](https://github.com/QwenLM/Qwen3-Coder) models. It enhances your development workflow with advanced code understanding, automated tasks, and intelligent assistance.
|
||||
|
||||
## 🚀 Why Choose Qwen Code?
|
||||
|
||||
- 🎯 **Free Tier:** Up to 60 requests/min and 2,000 requests/day with your [QwenChat](https://chat.qwen.ai/) account.
|
||||
- 🧠 **Advanced Model:** Specially optimized for [Qwen3-Coder](https://github.com/QwenLM/Qwen3-Coder) for superior code understanding and assistance.
|
||||
- 🏆 **Comprehensive Features:** Includes subagents, Plan Mode, TodoWrite, vision model support, and full OpenAI API compatibility—all seamlessly integrated.
|
||||
- 🔧 **Built-in & Extensible Tools:** Includes file system operations, shell command execution, web fetch/search, and more—all easily extended via the Model Context Protocol (MCP) for custom integrations.
|
||||
- 💻 **Developer-Centric:** Built for terminal-first workflows—perfect for command-line enthusiasts.
|
||||
- 🛡️ **Open Source:** Apache 2.0 licensed for maximum freedom and transparency.
|
||||
|
||||
## Installation
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Ensure you have [Node.js version 20](https://nodejs.org/en/download) or higher installed.
|
||||
|
||||
```bash
|
||||
curl -qL https://www.npmjs.com/install.sh | sh
|
||||
```
|
||||
|
||||
### Install from npm
|
||||
|
||||
```bash
|
||||
npm install -g @qwen-code/qwen-code@latest
|
||||
qwen --version
|
||||
```
|
||||
|
||||
### Install from source
|
||||
|
||||
```bash
|
||||
git clone https://github.com/QwenLM/qwen-code.git
|
||||
cd qwen-code
|
||||
npm install
|
||||
npm install -g .
|
||||
```
|
||||
|
||||
### Install globally with Homebrew (macOS/Linux)
|
||||
|
||||
```bash
|
||||
brew install qwen-code
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Start Qwen Code
|
||||
qwen
|
||||
|
||||
# Example commands
|
||||
> Explain this codebase structure
|
||||
> Help me refactor this function
|
||||
> Generate unit tests for this module
|
||||
```
|
||||
|
||||
### Session Management
|
||||
|
||||
Control your token usage with configurable session limits to optimize costs and performance.
|
||||
|
||||
#### Configure Session Token Limit
|
||||
|
||||
Create or edit `.qwen/settings.json` in your home directory:
|
||||
|
||||
```json
|
||||
{
|
||||
"sessionTokenLimit": 32000
|
||||
}
|
||||
```
|
||||
|
||||
#### Session Commands
|
||||
|
||||
- **`/compress`** - Compress conversation history to continue within token limits
|
||||
- **`/clear`** (aliases: `/reset`, `/new`) - Clear conversation history, start a fresh session, and free up context
|
||||
- **`/stats`** - Check current token usage and limits
|
||||
|
||||
> 📝 **Note**: Session token limit applies to a single conversation, not cumulative API calls.
|
||||
|
||||
### Vision Model Configuration
|
||||
|
||||
Qwen Code includes intelligent vision model auto-switching that detects images in your input and can automatically switch to vision-capable models for multimodal analysis. **This feature is enabled by default** - when you include images in your queries, you'll see a dialog asking how you'd like to handle the vision model switch.
|
||||
|
||||
#### Skip the Switch Dialog (Optional)
|
||||
|
||||
If you don't want to see the interactive dialog each time, configure the default behavior in your `.qwen/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"experimental": {
|
||||
"vlmSwitchMode": "once"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Available modes:**
|
||||
|
||||
- **`"once"`** - Switch to vision model for this query only, then revert
|
||||
- **`"session"`** - Switch to vision model for the entire session
|
||||
- **`"persist"`** - Continue with current model (no switching)
|
||||
- **Not set** - Show interactive dialog each time (default)
|
||||
|
||||
#### Command Line Override
|
||||
|
||||
You can also set the behavior via command line:
|
||||
|
||||
```bash
|
||||
# Switch once per query
|
||||
qwen --vlm-switch-mode once
|
||||
|
||||
# Switch for entire session
|
||||
qwen --vlm-switch-mode session
|
||||
|
||||
# Never switch automatically
|
||||
qwen --vlm-switch-mode persist
|
||||
```
|
||||
|
||||
#### Disable Vision Models (Optional)
|
||||
|
||||
To completely disable vision model support, add to your `.qwen/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"experimental": {
|
||||
"visionModelPreview": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 💡 **Tip**: In YOLO mode (`--yolo`), vision switching happens automatically without prompts when images are detected.
|
||||
|
||||
### Authorization
|
||||
|
||||
Choose your preferred authentication method based on your needs:
|
||||
|
||||
#### 1. Qwen OAuth (🚀 Recommended - Start in 30 seconds)
|
||||
|
||||
The easiest way to get started - completely free with generous quotas:
|
||||
|
||||
```bash
|
||||
# Just run this command and follow the browser authentication
|
||||
qwen
|
||||
```
|
||||
|
||||
**What happens:**
|
||||
|
||||
1. **Instant Setup**: CLI opens your browser automatically
|
||||
2. **One-Click Login**: Authenticate with your qwen.ai account
|
||||
3. **Automatic Management**: Credentials cached locally for future use
|
||||
4. **No Configuration**: Zero setup required - just start coding!
|
||||
|
||||
**Free Tier Benefits:**
|
||||
|
||||
- ✅ **2,000 requests/day** (no token counting needed)
|
||||
- ✅ **60 requests/minute** rate limit
|
||||
- ✅ **Automatic credential refresh**
|
||||
- ✅ **Zero cost** for individual users
|
||||
- ℹ️ **Note**: Model fallback may occur to maintain service quality
|
||||
|
||||
#### 2. OpenAI-Compatible API
|
||||
|
||||
Use API keys for OpenAI or other compatible providers:
|
||||
|
||||
**Configuration Methods:**
|
||||
|
||||
1. **Environment Variables**
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY="your_api_key_here"
|
||||
export OPENAI_BASE_URL="your_api_endpoint"
|
||||
export OPENAI_MODEL="your_model_choice"
|
||||
```
|
||||
|
||||
2. **Project `.env` File**
|
||||
Create a `.env` file in your project root:
|
||||
```env
|
||||
OPENAI_API_KEY=your_api_key_here
|
||||
OPENAI_BASE_URL=your_api_endpoint
|
||||
OPENAI_MODEL=your_model_choice
|
||||
```
|
||||
|
||||
**API Provider Options**
|
||||
|
||||
> ⚠️ **Regional Notice:**
|
||||
>
|
||||
> - **Mainland China**: Use Alibaba Cloud Bailian or ModelScope
|
||||
> - **International**: Use Alibaba Cloud ModelStudio or OpenRouter
|
||||
|
||||
<details>
|
||||
<summary><b>🇨🇳 For Users in Mainland China</b></summary>
|
||||
|
||||
**Option 1: Alibaba Cloud Bailian** ([Apply for API Key](https://bailian.console.aliyun.com/))
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY="your_api_key_here"
|
||||
export OPENAI_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1"
|
||||
export OPENAI_MODEL="qwen3-coder-plus"
|
||||
```
|
||||
|
||||
**Option 2: ModelScope (Free Tier)** ([Apply for API Key](https://modelscope.cn/docs/model-service/API-Inference/intro))
|
||||
|
||||
- ✅ **2,000 free API calls per day**
|
||||
- ⚠️ Connect your Aliyun account to avoid authentication errors
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY="your_api_key_here"
|
||||
export OPENAI_BASE_URL="https://api-inference.modelscope.cn/v1"
|
||||
export OPENAI_MODEL="Qwen/Qwen3-Coder-480B-A35B-Instruct"
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>🌍 For International Users</b></summary>
|
||||
|
||||
**Option 1: Alibaba Cloud ModelStudio** ([Apply for API Key](https://modelstudio.console.alibabacloud.com/))
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY="your_api_key_here"
|
||||
export OPENAI_BASE_URL="https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
|
||||
export OPENAI_MODEL="qwen3-coder-plus"
|
||||
```
|
||||
|
||||
**Option 2: OpenRouter (Free Tier Available)** ([Apply for API Key](https://openrouter.ai/))
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY="your_api_key_here"
|
||||
export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
|
||||
export OPENAI_MODEL="qwen/qwen3-coder:free"
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### 🔍 Explore Codebases
|
||||
|
||||
```bash
|
||||
cd your-project/
|
||||
qwen
|
||||
|
||||
# Architecture analysis
|
||||
> Describe the main pieces of this system's architecture
|
||||
> What are the key dependencies and how do they interact?
|
||||
> Find all API endpoints and their authentication methods
|
||||
```
|
||||
|
||||
### 💻 Code Development
|
||||
|
||||
```bash
|
||||
# Refactoring
|
||||
> Refactor this function to improve readability and performance
|
||||
> Convert this class to use dependency injection
|
||||
> Split this large module into smaller, focused components
|
||||
|
||||
# Code generation
|
||||
> Create a REST API endpoint for user management
|
||||
> Generate unit tests for the authentication module
|
||||
> Add error handling to all database operations
|
||||
```
|
||||
|
||||
### 🔄 Automate Workflows
|
||||
|
||||
```bash
|
||||
# Git automation
|
||||
> Analyze git commits from the last 7 days, grouped by feature
|
||||
> Create a changelog from recent commits
|
||||
> Find all TODO comments and create GitHub issues
|
||||
|
||||
# File operations
|
||||
> Convert all images in this directory to PNG format
|
||||
> Rename all test files to follow the *.test.ts pattern
|
||||
> Find and remove all console.log statements
|
||||
```
|
||||
|
||||
### 🐛 Debugging & Analysis
|
||||
|
||||
```bash
|
||||
# Performance analysis
|
||||
> Identify performance bottlenecks in this React component
|
||||
> Find all N+1 query problems in the codebase
|
||||
|
||||
# Security audit
|
||||
> Check for potential SQL injection vulnerabilities
|
||||
> Find all hardcoded credentials or API keys
|
||||
```
|
||||
|
||||
## Popular Tasks
|
||||
|
||||
### 📚 Understand New Codebases
|
||||
|
||||
```text
|
||||
> What are the core business logic components?
|
||||
> What security mechanisms are in place?
|
||||
> How does the data flow through the system?
|
||||
> What are the main design patterns used?
|
||||
> Generate a dependency graph for this module
|
||||
```
|
||||
|
||||
### 🔨 Code Refactoring & Optimization
|
||||
|
||||
```text
|
||||
> What parts of this module can be optimized?
|
||||
> Help me refactor this class to follow SOLID principles
|
||||
> Add proper error handling and logging
|
||||
> Convert callbacks to async/await pattern
|
||||
> Implement caching for expensive operations
|
||||
```
|
||||
|
||||
### 📝 Documentation & Testing
|
||||
|
||||
```text
|
||||
> Generate comprehensive JSDoc comments for all public APIs
|
||||
> Write unit tests with edge cases for this component
|
||||
> Create API documentation in OpenAPI format
|
||||
> Add inline comments explaining complex algorithms
|
||||
> Generate a README for this module
|
||||
```
|
||||
|
||||
### 🚀 Development Acceleration
|
||||
|
||||
```text
|
||||
> Set up a new Express server with authentication
|
||||
> Create a React component with TypeScript and tests
|
||||
> Implement a rate limiter middleware
|
||||
> Add database migrations for new schema
|
||||
> Configure CI/CD pipeline for this project
|
||||
```
|
||||
|
||||
## Commands & Shortcuts
|
||||
|
||||
### Session Commands
|
||||
|
||||
- `/help` - Display available commands
|
||||
- `/clear` (aliases: `/reset`, `/new`) - Clear conversation history and start a fresh session
|
||||
- `/compress` - Compress history to save tokens
|
||||
- `/stats` - Show current session information
|
||||
- `/exit` or `/quit` - Exit Qwen Code
|
||||
|
||||
### Keyboard Shortcuts
|
||||
|
||||
- `Ctrl+C` - Cancel current operation
|
||||
- `Ctrl+D` - Exit (on empty line)
|
||||
- `Up/Down` - Navigate command history
|
||||
|
||||
534
docs/mcp-example-configs.md
Normal file
@@ -0,0 +1,534 @@
|
||||
# MCP Example Configurations
|
||||
|
||||
Ready-to-use MCP server configurations for common scenarios.
|
||||
|
||||
## 📁 Local Development
|
||||
|
||||
### Basic Setup
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"workspace": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
|
||||
"trust": true,
|
||||
"description": "Full workspace access"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Multi-Directory Project
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"frontend": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"./src",
|
||||
"./public",
|
||||
"./tests"
|
||||
],
|
||||
"trust": true,
|
||||
"description": "Frontend development files"
|
||||
},
|
||||
"config": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"./config",
|
||||
"./.env.example"
|
||||
],
|
||||
"trust": true,
|
||||
"includeTools": ["read_file", "list_directory"],
|
||||
"description": "Configuration files (read-only)"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧠 Memory & Context
|
||||
|
||||
### Persistent Memory
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"project-memory": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"trust": true,
|
||||
"description": "Remember project context across sessions"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Combined with Filesystem
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"files": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
|
||||
"trust": true
|
||||
},
|
||||
"memory": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"trust": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🌐 Remote Servers (HTTP/SSE)
|
||||
|
||||
### HTTP MCP Server
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"remote-api": {
|
||||
"httpUrl": "https://api.example.com/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer ${API_TOKEN}",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"timeout": 30000,
|
||||
"description": "Remote MCP API"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### SSE Server with OAuth
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"sse-service": {
|
||||
"url": "https://mcp.example.com/sse",
|
||||
"oauth": {
|
||||
"enabled": true,
|
||||
"scopes": ["read", "write"]
|
||||
},
|
||||
"timeout": 60000,
|
||||
"description": "SSE server with OAuth"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🐍 Python MCP Servers
|
||||
|
||||
### Simple Python Server
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"python-tools": {
|
||||
"command": "python",
|
||||
"args": ["-m", "my_mcp_server"],
|
||||
"env": {
|
||||
"PYTHONPATH": "${PWD}",
|
||||
"DEBUG": "false"
|
||||
},
|
||||
"description": "Custom Python MCP tools"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Python with Virtual Environment
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"python-venv": {
|
||||
"command": "./venv/bin/python",
|
||||
"args": ["-m", "mcp_server"],
|
||||
"cwd": "./",
|
||||
"env": {
|
||||
"VIRTUAL_ENV": "${PWD}/venv"
|
||||
},
|
||||
"description": "Python server in virtual environment"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🐳 Docker Containers
|
||||
|
||||
### Basic Docker Server
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"docker-mcp": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
"-i",
|
||||
"--rm",
|
||||
"my-mcp-server:latest"
|
||||
],
|
||||
"timeout": 45000,
|
||||
"description": "MCP server in Docker"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Docker with Volume Mounts
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"docker-workspace": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
"-i",
|
||||
"--rm",
|
||||
"-v",
|
||||
"${PWD}:/workspace",
|
||||
"-w",
|
||||
"/workspace",
|
||||
"-e",
|
||||
"API_KEY",
|
||||
"mcp-tools:latest"
|
||||
],
|
||||
"env": {
|
||||
"API_KEY": "${MY_API_KEY}"
|
||||
},
|
||||
"description": "Docker MCP with workspace access"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🛡️ Security-Focused Configs
|
||||
|
||||
### Read-Only Filesystem
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"readonly-docs": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"./docs",
|
||||
"./README.md"
|
||||
],
|
||||
"includeTools": ["read_file", "list_directory", "search_files"],
|
||||
"excludeTools": [
|
||||
"write_file",
|
||||
"create_directory",
|
||||
"move_file",
|
||||
"delete_file"
|
||||
],
|
||||
"trust": true,
|
||||
"description": "Read-only documentation access"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Untrusted External Server
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"external-api": {
|
||||
"httpUrl": "https://external-mcp.example.com/api",
|
||||
"trust": false,
|
||||
"timeout": 15000,
|
||||
"includeTools": ["search", "analyze"],
|
||||
"description": "External API (requires confirmation)"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 Database Access
|
||||
|
||||
### PostgreSQL MCP Server
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"postgres": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-postgres",
|
||||
"${DATABASE_URL}"
|
||||
],
|
||||
"env": {
|
||||
"DATABASE_URL": "$POSTGRES_CONNECTION_STRING"
|
||||
},
|
||||
"timeout": 30000,
|
||||
"trust": false,
|
||||
"description": "PostgreSQL database access"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 Testing & Development
|
||||
|
||||
### Test Environment
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"test-files": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"./tests",
|
||||
"./fixtures"
|
||||
],
|
||||
"trust": true,
|
||||
"description": "Test files and fixtures"
|
||||
},
|
||||
"test-memory": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"trust": true,
|
||||
"description": "Test session memory"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Debug Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"debug-server": {
|
||||
"command": "node",
|
||||
"args": ["--inspect", "mcp-server.js"],
|
||||
"env": {
|
||||
"DEBUG": "*",
|
||||
"LOG_LEVEL": "verbose"
|
||||
},
|
||||
"timeout": 60000,
|
||||
"description": "MCP server with debugging enabled"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 CI/CD Integration
|
||||
|
||||
### GitHub Actions Environment
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"ci-workspace": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"${GITHUB_WORKSPACE}"
|
||||
],
|
||||
"env": {
|
||||
"GITHUB_TOKEN": "$GITHUB_TOKEN",
|
||||
"CI": "true"
|
||||
},
|
||||
"trust": true,
|
||||
"description": "CI/CD workspace access"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🌟 Advanced Patterns
|
||||
|
||||
### Multiple Servers Same Type
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"project-a": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "../project-a"],
|
||||
"description": "Project A files"
|
||||
},
|
||||
"project-b": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "../project-b"],
|
||||
"description": "Project B files"
|
||||
},
|
||||
"shared-memory": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"description": "Shared knowledge across projects"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Conditional Server Selection
|
||||
|
||||
User-level config (`~/.qwen/settings.json`):
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"global-memory": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"trust": true,
|
||||
"description": "Global memory across all projects"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Project-level config (`.qwen/settings.json`):
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"project-files": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
|
||||
"trust": true,
|
||||
"description": "Project-specific files"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📝 Configuration Validation
|
||||
|
||||
### Check Your Config
|
||||
|
||||
```bash
|
||||
# List configured servers
|
||||
qwen mcp list
|
||||
|
||||
# Show server details and schemas
|
||||
qwen mcp list --schema
|
||||
|
||||
# Test connection
|
||||
qwen mcp list --descriptions
|
||||
```
|
||||
|
||||
### Common Mistakes
|
||||
|
||||
❌ **Wrong:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"server": {
|
||||
"command": "mcp-server", // Not in PATH
|
||||
"args": ["./"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
✅ **Correct:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"server": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
|
||||
"description": "Uses npx to ensure server is available"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 Best Practices
|
||||
|
||||
1. **Use descriptive names** - Make server purposes clear
|
||||
2. **Set appropriate timeouts** - Match your server's response time
|
||||
3. **Trust local servers** - Skip confirmation for your own tools
|
||||
4. **Filter tools** - Use `includeTools`/`excludeTools` for security
|
||||
5. **Document configs** - Add descriptions for team members
|
||||
6. **Environment variables** - Keep secrets out of configs
|
||||
7. **Test independently** - Verify servers work before configuring
|
||||
|
||||
## 🔗 Quick Copy-Paste Configs
|
||||
|
||||
### Starter Pack
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"files": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
|
||||
"trust": true
|
||||
},
|
||||
"memory": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"trust": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Documentation Project
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"docs": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./docs"],
|
||||
"includeTools": ["read_file", "list_directory"],
|
||||
"trust": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Full-Stack Development
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"frontend": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./frontend"],
|
||||
"trust": true
|
||||
},
|
||||
"backend": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./backend"],
|
||||
"trust": true
|
||||
},
|
||||
"shared": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./shared"],
|
||||
"trust": true
|
||||
},
|
||||
"memory": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"trust": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Need help?** Check `qwen mcp --help` or refer to the [complete MCP documentation](./tools/mcp-server.md).
|
||||
418
docs/mcp-quick-start.md
Normal file
@@ -0,0 +1,418 @@
|
||||
# MCP Quick Start Guide - Practical Examples
|
||||
|
||||
This guide provides real-world examples to get you started with Model Context Protocol (MCP) servers in Qwen Code.
|
||||
|
||||
## 🚀 Getting Started in 5 Minutes
|
||||
|
||||
### Step 1: Install MCP Servers
|
||||
|
||||
Install official MCP servers from Anthropic:
|
||||
|
||||
```bash
|
||||
# Filesystem access
|
||||
npm install -g @modelcontextprotocol/server-filesystem
|
||||
|
||||
# Memory & Knowledge Graph
|
||||
npm install -g @modelcontextprotocol/server-memory
|
||||
|
||||
# Sequential thinking
|
||||
npm install -g @modelcontextprotocol/server-sequential-thinking
|
||||
```
|
||||
|
||||
### Step 2: Configure Your First MCP Server
|
||||
|
||||
Create or edit `.qwen/settings.json` in your project:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"filesystem": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
|
||||
"description": "Access project files"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Verify Connection
|
||||
|
||||
```bash
|
||||
qwen mcp list
|
||||
```
|
||||
|
||||
You should see:
|
||||
```
|
||||
✓ filesystem: npx -y @modelcontextprotocol/server-filesystem ./ (stdio) - Connected
|
||||
```
|
||||
|
||||
## 📚 Practical Examples
|
||||
|
||||
### Example 1: Local Development Assistant
|
||||
|
||||
**Use Case:** Work on a Node.js project with file access and memory.
|
||||
|
||||
**Configuration (`.qwen/settings.json`):**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"project-files": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"./src",
|
||||
"./tests",
|
||||
"./docs"
|
||||
],
|
||||
"description": "Access source code, tests, and documentation",
|
||||
"trust": true
|
||||
},
|
||||
"project-memory": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"description": "Remember project decisions and context",
|
||||
"trust": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
qwen
|
||||
|
||||
> Remember: This project uses React 18 with TypeScript and follows Airbnb style guide
|
||||
> List all files in the src directory
|
||||
> Read src/App.tsx and suggest improvements
|
||||
```
|
||||
|
||||
### Example 2: Multi-Repository Development
|
||||
|
||||
**Use Case:** Working across multiple codebases simultaneously.
|
||||
|
||||
**Configuration:**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"frontend": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"../frontend-app"
|
||||
],
|
||||
"description": "Frontend repository access"
|
||||
},
|
||||
"backend": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"../backend-api"
|
||||
],
|
||||
"description": "Backend repository access"
|
||||
},
|
||||
"shared-memory": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"description": "Shared knowledge across repositories"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Example 3: Documentation-Only Access
|
||||
|
||||
**Use Case:** Safe access to documentation without risking code changes.
|
||||
|
||||
**Configuration:**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"docs": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"./docs",
|
||||
"./README.md"
|
||||
],
|
||||
"description": "Read-only documentation access",
|
||||
"trust": true,
|
||||
"includeTools": ["read_file", "list_directory"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Example 4: Custom Python MCP Server
|
||||
|
||||
**Use Case:** Integrate custom Python tools via MCP.
|
||||
|
||||
**Server File (`mcp_server.py`):**
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
from mcp.server.stdio import stdio_server
|
||||
from mcp.server import Server
|
||||
from mcp.types import Tool, TextContent
|
||||
|
||||
server = Server("custom-tools")
|
||||
|
||||
@server.list_tools()
|
||||
async def list_tools() -> list[Tool]:
|
||||
return [
|
||||
Tool(
|
||||
name="analyze_python_code",
|
||||
description="Static analysis of Python code",
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {"type": "string"}
|
||||
},
|
||||
"required": ["file_path"]
|
||||
}
|
||||
)
|
||||
]
|
||||
|
||||
@server.call_tool()
|
||||
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
|
||||
if name == "analyze_python_code":
|
||||
# Your custom logic here
|
||||
return [TextContent(type="text", text=f"Analysis of {arguments['file_path']}")]
|
||||
|
||||
async def main():
|
||||
async with stdio_server() as (read_stream, write_stream):
|
||||
await server.run(read_stream, write_stream, server.create_initialization_options())
|
||||
|
||||
if __name__ == "__main__":
|
||||
import asyncio
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
**Configuration:**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"python-tools": {
|
||||
"command": "python",
|
||||
"args": ["mcp_server.py"],
|
||||
"env": {
|
||||
"PYTHONPATH": "${PWD}"
|
||||
},
|
||||
"description": "Custom Python analysis tools"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Example 5: Docker-Based MCP Server
|
||||
|
||||
**Use Case:** Run MCP servers in isolated containers.
|
||||
|
||||
**Configuration:**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"containerized-tools": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
"-i",
|
||||
"--rm",
|
||||
"-v",
|
||||
"${PWD}:/workspace",
|
||||
"-w",
|
||||
"/workspace",
|
||||
"my-mcp-server:latest"
|
||||
],
|
||||
"description": "MCP tools running in Docker"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 Configuration Tips
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Use environment variables for sensitive data:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"api-server": {
|
||||
"command": "node",
|
||||
"args": ["api-server.js"],
|
||||
"env": {
|
||||
"API_KEY": "${MY_API_KEY}",
|
||||
"DATABASE_URL": "$DB_CONNECTION"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Trust Settings
|
||||
|
||||
Trust servers you control to skip confirmation dialogs:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"trusted-server": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
|
||||
"trust": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Tool Filtering
|
||||
|
||||
Limit which tools are available:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"filesystem": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
|
||||
"includeTools": ["read_file", "list_directory"],
|
||||
"excludeTools": ["write_file", "move_file"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 Common Use Cases
|
||||
|
||||
### Code Review Assistant
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"codebase": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
|
||||
"description": "Full codebase access for reviews"
|
||||
},
|
||||
"review-memory": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"description": "Remember review comments and patterns"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
qwen
|
||||
|
||||
> Review the changes in src/components/
|
||||
> Remember: We follow the single responsibility principle
|
||||
> Check if all new components have tests
|
||||
```
|
||||
|
||||
### Documentation Generator
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"source": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./src"],
|
||||
"includeTools": ["read_file", "list_directory"]
|
||||
},
|
||||
"docs-writer": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./docs"],
|
||||
"includeTools": ["write_file", "create_directory"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Learning Assistant
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"tutorials": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"./tutorials",
|
||||
"./examples"
|
||||
],
|
||||
"trust": true
|
||||
},
|
||||
"learning-progress": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"description": "Track learning progress and concepts"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🛠️ Troubleshooting
|
||||
|
||||
### Server Won't Connect
|
||||
|
||||
1. **Check the command is accessible:**
|
||||
```bash
|
||||
npx -y @modelcontextprotocol/server-filesystem ./
|
||||
```
|
||||
|
||||
2. **Verify directory permissions:**
|
||||
```bash
|
||||
ls -la ./
|
||||
```
|
||||
|
||||
3. **Check logs:**
|
||||
```bash
|
||||
qwen --debug
|
||||
```
|
||||
|
||||
### No Tools Discovered
|
||||
|
||||
Ensure the server actually provides tools:
|
||||
```bash
|
||||
qwen mcp list --schema
|
||||
```
|
||||
|
||||
### Tools Not Executing
|
||||
|
||||
- Check parameter schemas match
|
||||
- Verify timeout settings (increase if needed)
|
||||
- Test the server independently first
|
||||
|
||||
## 📖 Further Reading
|
||||
|
||||
- [MCP Server Documentation](./tools/mcp-server.md) - Complete reference
|
||||
- [Official MCP Specification](https://modelcontextprotocol.io/) - Protocol details
|
||||
- [MCP Server Examples](https://github.com/modelcontextprotocol/servers) - Community servers
|
||||
|
||||
## 🎓 Next Steps
|
||||
|
||||
1. ✅ Configure your first MCP server
|
||||
2. ✅ Verify connection with `qwen mcp list`
|
||||
3. ✅ Try basic file operations
|
||||
4. ✅ Add memory for persistent context
|
||||
5. ✅ Explore community MCP servers
|
||||
6. ✅ Build your own custom server
|
||||
|
||||
---
|
||||
|
||||
**Pro Tip:** Start with trusted local servers (`trust: true`) for faster iteration, then add confirmation for production use.
|
||||
382
docs/mcp-testing-validation.md
Normal file
@@ -0,0 +1,382 @@
|
||||
# MCP Testing & Validation Guide
|
||||
|
||||
This guide helps you test and validate your MCP server configurations.
|
||||
|
||||
## ✅ Quick Validation Checklist
|
||||
|
||||
### 1. Check MCP Servers Are Configured
|
||||
|
||||
```bash
|
||||
qwen mcp list
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
Configured MCP servers:
|
||||
|
||||
✓ filesystem: npx -y @modelcontextprotocol/server-filesystem ./ (stdio) - Connected
|
||||
✓ memory: npx -y @modelcontextprotocol/server-memory (stdio) - Connected
|
||||
```
|
||||
|
||||
**Status indicators:**
|
||||
- ✓ (green) - Connected successfully
|
||||
- ✗ (red) - Connection failed or not connected
|
||||
|
||||
### 2. Verify Server Is Installed
|
||||
|
||||
Test the server command directly:
|
||||
|
||||
```bash
|
||||
# Filesystem server
|
||||
npx -y @modelcontextprotocol/server-filesystem --help
|
||||
|
||||
# Memory server
|
||||
npx -y @modelcontextprotocol/server-memory --help
|
||||
|
||||
# Custom server
|
||||
python mcp_server.py --help
|
||||
```
|
||||
|
||||
### 3. Check Configuration File Syntax
|
||||
|
||||
Validate your JSON configuration:
|
||||
|
||||
```bash
|
||||
# Linux/macOS
|
||||
cat .qwen/settings.json | jq .
|
||||
|
||||
# Windows PowerShell
|
||||
Get-Content .qwen/settings.json | ConvertFrom-Json | ConvertTo-Json
|
||||
```
|
||||
|
||||
### 4. Test Within Qwen Code Session
|
||||
|
||||
Start an interactive session and check MCP status:
|
||||
|
||||
```bash
|
||||
qwen
|
||||
|
||||
# Inside the session:
|
||||
/mcp # Show all MCP servers and tools
|
||||
/mcp desc # Show tool descriptions
|
||||
/mcp schema # Show tool parameter schemas
|
||||
```
|
||||
|
||||
## 🧪 Test Cases
|
||||
|
||||
### Test Case 1: Filesystem Server
|
||||
|
||||
**Configuration:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"test-fs": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
|
||||
"trust": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Validation:**
|
||||
1. List files: Start `qwen` and ask "List all files in this directory"
|
||||
2. Read file: "Read the README.md file"
|
||||
3. Verify output contains actual file contents
|
||||
|
||||
**Expected Tools:**
|
||||
- `read_file` - Read file contents
|
||||
- `write_file` - Write to files
|
||||
- `list_directory` - List directory contents
|
||||
- `create_directory` - Create directories
|
||||
- `move_file` - Move/rename files
|
||||
- `search_files` - Search for files
|
||||
- `get_file_info` - Get file metadata
|
||||
|
||||
### Test Case 2: Memory Server
|
||||
|
||||
**Configuration:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"test-memory": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"trust": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Validation:**
|
||||
1. Store information: "Remember that this project uses React 18"
|
||||
2. Query: "What JavaScript framework does this project use?"
|
||||
3. Verify it recalls the information from step 1
|
||||
|
||||
**Expected Tools:**
|
||||
- `create_entities` - Create knowledge entities
|
||||
- `create_relations` - Create relationships between entities
|
||||
- `add_observations` - Add observations to entities
|
||||
- `delete_entities` - Remove entities
|
||||
- `delete_observations` - Remove observations
|
||||
- `delete_relations` - Remove relationships
|
||||
- `read_graph` - Read entire knowledge graph
|
||||
- `search_nodes` - Search for specific nodes
|
||||
- `open_nodes` - Open specific nodes by name
|
||||
|
||||
### Test Case 3: Multiple Servers
|
||||
|
||||
**Configuration:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"files": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
|
||||
"trust": true
|
||||
},
|
||||
"memory": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"trust": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Validation:**
|
||||
1. Check both servers are connected: `qwen mcp list`
|
||||
2. Use filesystem tool: "List all JavaScript files"
|
||||
3. Use memory tool: "Remember that we prefer TypeScript"
|
||||
4. Verify both tools work simultaneously
|
||||
|
||||
### Test Case 4: Tool Filtering
|
||||
|
||||
**Configuration:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"readonly-fs": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
|
||||
"includeTools": ["read_file", "list_directory"],
|
||||
"trust": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Validation:**
|
||||
1. Start qwen session
|
||||
2. Run `/mcp desc` to list available tools
|
||||
3. Verify only `read_file` and `list_directory` are present
|
||||
4. Verify `write_file`, `create_directory`, etc. are NOT available
|
||||
|
||||
### Test Case 5: Untrusted Server Confirmation
|
||||
|
||||
**Configuration:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"untrusted": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
|
||||
"trust": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Validation:**
|
||||
1. Ask qwen to read a file
|
||||
2. Confirmation dialog should appear before execution
|
||||
3. Options should include:
|
||||
- Proceed once
|
||||
- Always allow this tool
|
||||
- Always allow this server
|
||||
- Cancel
|
||||
|
||||
## 🔍 Debugging Failed Connections
|
||||
|
||||
### Issue: Server Shows "Disconnected"
|
||||
|
||||
**Diagnostic steps:**
|
||||
|
||||
1. **Test command manually:**
|
||||
```bash
|
||||
npx -y @modelcontextprotocol/server-filesystem ./
|
||||
```
|
||||
|
||||
2. **Check for errors:**
|
||||
```bash
|
||||
qwen --debug
|
||||
```
|
||||
|
||||
3. **Verify paths are correct:**
|
||||
```bash
|
||||
# Check if directory exists
|
||||
ls ./
|
||||
|
||||
# Check if command is in PATH
|
||||
which npx # Linux/macOS
|
||||
where npx # Windows
|
||||
```
|
||||
|
||||
4. **Check permissions:**
|
||||
```bash
|
||||
# Verify read/execute permissions
|
||||
ls -la ./
|
||||
```
|
||||
|
||||
5. **Review environment variables:**
|
||||
```bash
|
||||
echo $PATH
|
||||
echo $PYTHONPATH # For Python servers
|
||||
```
|
||||
|
||||
### Issue: No Tools Discovered
|
||||
|
||||
**Diagnostic steps:**
|
||||
|
||||
1. **Verify server implements MCP protocol:**
|
||||
```bash
|
||||
# For stdio servers, test input/output manually
|
||||
echo '{"jsonrpc": "2.0", "method": "initialize", "id": 1}' | npx -y @modelcontextprotocol/server-filesystem ./
|
||||
```
|
||||
|
||||
2. **Check server logs:**
|
||||
```bash
|
||||
# Some servers log to stderr
|
||||
qwen --debug 2>&1 | grep MCP
|
||||
```
|
||||
|
||||
3. **Verify server version:**
|
||||
```bash
|
||||
npm list -g @modelcontextprotocol/server-filesystem
|
||||
```
|
||||
|
||||
### Issue: Tools Fail to Execute
|
||||
|
||||
**Diagnostic steps:**
|
||||
|
||||
1. **Check parameter format:**
|
||||
- Ensure parameters match the expected schema
|
||||
- Verify JSON encoding is correct
|
||||
|
||||
2. **Increase timeout:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"slow-server": {
|
||||
"command": "...",
|
||||
"timeout": 60000
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **Check server implementation:**
|
||||
- Verify the server actually implements the tool
|
||||
- Test the tool independently if possible
|
||||
|
||||
## 📊 Validation Results
|
||||
|
||||
### Expected Server Connection Times
|
||||
|
||||
| Server Type | Typical Connection Time | Timeout Recommendation |
|
||||
|-------------|------------------------|------------------------|
|
||||
| Filesystem | < 1 second | 10-30 seconds |
|
||||
| Memory | < 1 second | 10-30 seconds |
|
||||
| HTTP/SSE | 1-3 seconds | 30-60 seconds |
|
||||
| Custom Python | 2-5 seconds | 30-60 seconds |
|
||||
| Docker | 5-10 seconds | 60-120 seconds |
|
||||
|
||||
### Tool Execution Times
|
||||
|
||||
| Tool Type | Typical Duration | Timeout Recommendation |
|
||||
|-------------------|-----------------|------------------------|
|
||||
| Read file | < 100ms | 5-10 seconds |
|
||||
| List directory | < 500ms | 10-15 seconds |
|
||||
| Search files | 1-5 seconds | 30-60 seconds |
|
||||
| Memory operations | < 1 second | 10-30 seconds |
|
||||
| API calls | 1-10 seconds | 30-120 seconds |
|
||||
|
||||
## 🎯 Success Criteria
|
||||
|
||||
Your MCP configuration is working correctly if:
|
||||
|
||||
✅ `qwen mcp list` shows all servers as "Connected"
|
||||
✅ `/mcp` command in qwen session displays tools
|
||||
✅ Tool executions complete without errors
|
||||
✅ Confirmation dialogs appear for untrusted servers (if `trust: false`)
|
||||
✅ Tool filtering works as expected (include/exclude)
|
||||
✅ Environment variables are properly substituted
|
||||
✅ Timeouts are appropriate for your server's response time
|
||||
|
||||
## 🚀 Performance Tips
|
||||
|
||||
1. **Use `trust: true` for local servers** to skip confirmation dialogs
|
||||
2. **Set appropriate timeouts** - too low causes failures, too high slows down errors
|
||||
3. **Filter tools** - Only enable tools you actually need
|
||||
4. **Test servers independently** before configuring in qwen
|
||||
5. **Use `--debug` flag** during initial setup
|
||||
6. **Monitor resource usage** for long-running or resource-intensive servers
|
||||
|
||||
## 📝 Validation Script Example
|
||||
|
||||
Create a test script to automate validation:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# validate-mcp.sh
|
||||
|
||||
echo "Testing MCP configuration..."
|
||||
|
||||
# Test 1: Check config file exists
|
||||
if [ ! -f .qwen/settings.json ]; then
|
||||
echo "❌ Missing .qwen/settings.json"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ Config file exists"
|
||||
|
||||
# Test 2: Validate JSON syntax
|
||||
if ! cat .qwen/settings.json | jq . > /dev/null 2>&1; then
|
||||
echo "❌ Invalid JSON in settings.json"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ Valid JSON syntax"
|
||||
|
||||
# Test 3: Check servers are configured
|
||||
SERVER_COUNT=$(cat .qwen/settings.json | jq '.mcpServers | length')
|
||||
if [ "$SERVER_COUNT" -eq 0 ]; then
|
||||
echo "❌ No MCP servers configured"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ $SERVER_COUNT MCP server(s) configured"
|
||||
|
||||
# Test 4: Check connection status
|
||||
qwen mcp list | grep -q "Connected"
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ At least one server is connected"
|
||||
else
|
||||
echo "❌ No servers connected"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✅ All validation checks passed!"
|
||||
```
|
||||
|
||||
## 📚 Next Steps
|
||||
|
||||
After validation:
|
||||
|
||||
1. **Start using MCP tools** in your workflow
|
||||
2. **Document your custom configurations** for team members
|
||||
3. **Share your successful configs** with the community
|
||||
4. **Monitor performance** and adjust timeouts as needed
|
||||
5. **Explore more MCP servers** from the community
|
||||
|
||||
---
|
||||
|
||||
**Having issues?** Check the [MCP troubleshooting guide](./tools/mcp-server.md#troubleshooting) or open an issue on GitHub.
|
||||
68
docs/sidebar.json
Normal file
@@ -0,0 +1,68 @@
|
||||
[
|
||||
{
|
||||
"label": "Overview",
|
||||
"items": [
|
||||
{ "label": "Welcome", "slug": "docs" },
|
||||
{ "label": "Execution and Deployment", "slug": "docs/deployment" },
|
||||
{ "label": "Architecture Overview", "slug": "docs/architecture" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "CLI",
|
||||
"items": [
|
||||
{ "label": "Introduction", "slug": "docs/cli" },
|
||||
{ "label": "Authentication", "slug": "docs/cli/authentication" },
|
||||
{ "label": "Commands", "slug": "docs/cli/commands" },
|
||||
{ "label": "Configuration", "slug": "docs/cli/configuration" },
|
||||
{ "label": "Checkpointing", "slug": "docs/checkpointing" },
|
||||
{ "label": "Extensions", "slug": "docs/extension" },
|
||||
{ "label": "Headless Mode", "slug": "docs/headless" },
|
||||
{ "label": "IDE Integration", "slug": "docs/ide-integration" },
|
||||
{
|
||||
"label": "IDE Companion Spec",
|
||||
"slug": "docs/ide-companion-spec"
|
||||
},
|
||||
{ "label": "Telemetry", "slug": "docs/telemetry" },
|
||||
{ "label": "Themes", "slug": "docs/cli/themes" },
|
||||
{ "label": "Token Caching", "slug": "docs/cli/token-caching" },
|
||||
{ "label": "Trusted Folders", "slug": "docs/trusted-folders" },
|
||||
{ "label": "Tutorials", "slug": "docs/cli/tutorials" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Core",
|
||||
"items": [
|
||||
{ "label": "Introduction", "slug": "docs/core" },
|
||||
{ "label": "Tools API", "slug": "docs/core/tools-api" },
|
||||
{ "label": "Memory Import Processor", "slug": "docs/core/memport" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Tools",
|
||||
"items": [
|
||||
{ "label": "Overview", "slug": "docs/tools" },
|
||||
{ "label": "File System", "slug": "docs/tools/file-system" },
|
||||
{ "label": "Multi-File Read", "slug": "docs/tools/multi-file" },
|
||||
{ "label": "Shell", "slug": "docs/tools/shell" },
|
||||
{ "label": "Web Fetch", "slug": "docs/tools/web-fetch" },
|
||||
{ "label": "Web Search", "slug": "docs/tools/web-search" },
|
||||
{ "label": "Memory", "slug": "docs/tools/memory" },
|
||||
{ "label": "MCP Servers", "slug": "docs/tools/mcp-server" },
|
||||
{ "label": "Sandboxing", "slug": "docs/sandbox" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Development",
|
||||
"items": [
|
||||
{ "label": "NPM", "slug": "docs/npm" },
|
||||
{ "label": "Releases", "slug": "docs/releases" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Support",
|
||||
"items": [
|
||||
{ "label": "Troubleshooting", "slug": "docs/troubleshooting" },
|
||||
{ "label": "Terms of Service", "slug": "docs/tos-privacy" }
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,6 +1,4 @@
|
||||
export default {
|
||||
troubleshooting: 'Troubleshooting',
|
||||
'tos-privacy': 'Terms of Service',
|
||||
|
||||
Uninstall: 'Uninstall',
|
||||
};
|
||||
@@ -54,3 +54,7 @@ Qwen Code's built-in tools can be broadly categorized as follows:
|
||||
Additionally, these tools incorporate:
|
||||
|
||||
- **[MCP servers](./mcp-server.md)**: MCP servers act as a bridge between the model and your local environment or other services like APIs.
|
||||
- **[MCP Quick Start Guide](../mcp-quick-start.md)**: Get started with MCP in 5 minutes with practical examples
|
||||
- **[MCP Example Configurations](../mcp-example-configs.md)**: Ready-to-use configurations for common scenarios
|
||||
- **[MCP Testing & Validation](../mcp-testing-validation.md)**: Test and validate your MCP server setups
|
||||
- **[Sandboxing](../sandbox.md)**: Sandboxing isolates the model and its changes from your environment to reduce potential risk.
|
||||
@@ -1,28 +0,0 @@
|
||||
export default {
|
||||
'Getting started': {
|
||||
type: 'separator',
|
||||
title: 'Getting started', // Title is optional
|
||||
},
|
||||
overview: 'Overview',
|
||||
'quick-start': 'QuickStart',
|
||||
'common-workflow': 'Command Workflows',
|
||||
'Outside of the terminal': {
|
||||
type: 'separator',
|
||||
title: 'Outside of the terminal', // Title is optional
|
||||
},
|
||||
'integration-github-action': 'Github Action',
|
||||
'integration-vscode': 'VSCode Extension',
|
||||
'integration-zed': 'Zed IDE',
|
||||
'Code with Qwen Code': {
|
||||
type: 'separator',
|
||||
title: 'Code with Qwen Code', // Title is optional
|
||||
},
|
||||
features: 'Features',
|
||||
configuration: 'Configuration',
|
||||
reference: 'Reference',
|
||||
support: 'Support',
|
||||
// need refine
|
||||
'ide-integration': {
|
||||
display: 'hidden',
|
||||
},
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
export default {
|
||||
settings: 'Settings File',
|
||||
memory: 'Memory Management',
|
||||
'trusted-folders': 'Trusted Folders',
|
||||
'qwen-ignore': 'Ignoring Files',
|
||||
themes: 'Themes',
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
export default {
|
||||
subagents: 'Subagents',
|
||||
'sub-commands': 'Sub Commands',
|
||||
checkpointing: {
|
||||
display: 'hidden',
|
||||
},
|
||||
headless: 'Headless Mode',
|
||||
'welcome-back': {
|
||||
display: 'hidden',
|
||||
},
|
||||
'approval-mode': 'Approval Mode',
|
||||
'token-caching': 'Token Caching',
|
||||
mcp: 'MCP',
|
||||
sandbox: 'Sandboxing',
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
export default {
|
||||
'keyboard-shortcuts': 'Keyboard Shortcuts',
|
||||
};
|
||||
@@ -22,6 +22,7 @@ export default tseslint.config(
|
||||
'bundle/**',
|
||||
'package/bundle/**',
|
||||
'.integration-tests/**',
|
||||
'packages/**/.integration-test/**',
|
||||
'dist/**',
|
||||
],
|
||||
},
|
||||
@@ -74,6 +75,8 @@ export default tseslint.config(
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// We use TypeScript for React components; prop-types are unnecessary
|
||||
'react/prop-types': 'off',
|
||||
// General Best Practice Rules (subset adapted for flat config)
|
||||
'@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
|
||||
'arrow-body-style': ['error', 'as-needed'],
|
||||
@@ -110,10 +113,14 @@ export default tseslint.config(
|
||||
{
|
||||
allow: [
|
||||
'react-dom/test-utils',
|
||||
'react-dom/client',
|
||||
'memfs/lib/volume.js',
|
||||
'yargs/**',
|
||||
'msw/node',
|
||||
'**/generated/**'
|
||||
'**/generated/**',
|
||||
'./styles/tailwind.css',
|
||||
'./styles/App.css',
|
||||
'./styles/style.css'
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -150,7 +157,7 @@ export default tseslint.config(
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['packages/*/src/**/*.test.{ts,tsx}'],
|
||||
files: ['packages/*/src/**/*.test.{ts,tsx}', 'packages/**/test/**/*.test.{ts,tsx}'],
|
||||
plugins: {
|
||||
vitest,
|
||||
},
|
||||
@@ -158,11 +165,19 @@ export default tseslint.config(
|
||||
...vitest.configs.recommended.rules,
|
||||
'vitest/expect-expect': 'off',
|
||||
'vitest/no-commented-out-tests': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
caughtErrorsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
// extra settings for scripts that we run directly with node
|
||||
{
|
||||
files: ['./scripts/**/*.js', 'esbuild.config.js'],
|
||||
files: ['./scripts/**/*.js', 'esbuild.config.js', 'packages/*/scripts/**/*.js'],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
@@ -229,7 +244,7 @@ export default tseslint.config(
|
||||
prettierConfig,
|
||||
// extra settings for scripts that we run directly with node
|
||||
{
|
||||
files: ['./integration-tests/**/*.js'],
|
||||
files: ['./integration-tests/**/*.{js,ts,tsx}'],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
|
||||
@@ -13,8 +13,6 @@ import { TestRig } from './test-helper.js';
|
||||
|
||||
const REQUEST_TIMEOUT_MS = 60_000;
|
||||
const INITIAL_PROMPT = 'Create a quick note (smoke test).';
|
||||
const RESUME_PROMPT = 'Continue the note after reload.';
|
||||
const LIST_SIZE = 5;
|
||||
const IS_SANDBOX =
|
||||
process.env['GEMINI_SANDBOX'] &&
|
||||
process.env['GEMINI_SANDBOX']!.toLowerCase() !== 'false';
|
||||
@@ -25,6 +23,14 @@ type PendingRequest = {
|
||||
timeout: NodeJS.Timeout;
|
||||
};
|
||||
|
||||
type UsageMetadata = {
|
||||
promptTokens?: number | null;
|
||||
completionTokens?: number | null;
|
||||
thoughtsTokens?: number | null;
|
||||
totalTokens?: number | null;
|
||||
cachedTokens?: number | null;
|
||||
};
|
||||
|
||||
type SessionUpdateNotification = {
|
||||
sessionId?: string;
|
||||
update?: {
|
||||
@@ -39,6 +45,9 @@ type SessionUpdateNotification = {
|
||||
text?: string;
|
||||
};
|
||||
modeId?: string;
|
||||
_meta?: {
|
||||
usage?: UsageMetadata;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -86,10 +95,14 @@ function setupAcpTest(
|
||||
const permissionHandler =
|
||||
options?.permissionHandler ?? (() => ({ optionId: 'proceed_once' }));
|
||||
|
||||
const agent = spawn('node', [rig.bundlePath, '--experimental-acp'], {
|
||||
cwd: rig.testDir!,
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
});
|
||||
const agent = spawn(
|
||||
'node',
|
||||
[rig.bundlePath, '--experimental-acp', '--no-chat-recording'],
|
||||
{
|
||||
cwd: rig.testDir!,
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
},
|
||||
);
|
||||
|
||||
agent.stderr?.on('data', (chunk) => {
|
||||
stderr.push(chunk.toString());
|
||||
@@ -253,11 +266,11 @@ function setupAcpTest(
|
||||
}
|
||||
|
||||
(IS_SANDBOX ? describe.skip : describe)('acp integration', () => {
|
||||
it('creates, lists, loads, and resumes a session', async () => {
|
||||
it('basic smoke test', async () => {
|
||||
const rig = new TestRig();
|
||||
rig.setup('acp load session');
|
||||
|
||||
const { sendRequest, cleanup, stderr, sessionUpdates } = setupAcpTest(rig);
|
||||
const { sendRequest, cleanup, stderr } = setupAcpTest(rig);
|
||||
|
||||
try {
|
||||
const initResult = await sendRequest('initialize', {
|
||||
@@ -283,34 +296,6 @@ function setupAcpTest(
|
||||
prompt: [{ type: 'text', text: INITIAL_PROMPT }],
|
||||
});
|
||||
expect(promptResult).toBeDefined();
|
||||
|
||||
await delay(500);
|
||||
|
||||
const listResult = (await sendRequest('session/list', {
|
||||
cwd: rig.testDir!,
|
||||
size: LIST_SIZE,
|
||||
})) as { items?: Array<{ sessionId: string }> };
|
||||
|
||||
expect(Array.isArray(listResult.items)).toBe(true);
|
||||
expect(listResult.items?.length ?? 0).toBeGreaterThan(0);
|
||||
|
||||
const sessionToLoad = listResult.items![0].sessionId;
|
||||
await sendRequest('session/load', {
|
||||
cwd: rig.testDir!,
|
||||
sessionId: sessionToLoad,
|
||||
mcpServers: [],
|
||||
});
|
||||
|
||||
const resumeResult = await sendRequest('session/prompt', {
|
||||
sessionId: sessionToLoad,
|
||||
prompt: [{ type: 'text', text: RESUME_PROMPT }],
|
||||
});
|
||||
expect(resumeResult).toBeDefined();
|
||||
|
||||
const sessionsWithUpdates = sessionUpdates
|
||||
.map((update) => update.sessionId)
|
||||
.filter(Boolean);
|
||||
expect(sessionsWithUpdates).toContain(sessionToLoad);
|
||||
} catch (e) {
|
||||
if (stderr.length) {
|
||||
console.error('Agent stderr:', stderr.join(''));
|
||||
@@ -587,4 +572,52 @@ function setupAcpTest(
|
||||
await cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
it('receives usage metadata in agent_message_chunk updates', async () => {
|
||||
const rig = new TestRig();
|
||||
rig.setup('acp usage metadata');
|
||||
|
||||
const { sendRequest, cleanup, stderr, sessionUpdates } = setupAcpTest(rig);
|
||||
|
||||
try {
|
||||
await sendRequest('initialize', {
|
||||
protocolVersion: 1,
|
||||
clientCapabilities: { fs: { readTextFile: true, writeTextFile: true } },
|
||||
});
|
||||
await sendRequest('authenticate', { methodId: 'openai' });
|
||||
|
||||
const newSession = (await sendRequest('session/new', {
|
||||
cwd: rig.testDir!,
|
||||
mcpServers: [],
|
||||
})) as { sessionId: string };
|
||||
|
||||
await sendRequest('session/prompt', {
|
||||
sessionId: newSession.sessionId,
|
||||
prompt: [{ type: 'text', text: 'Say "hello".' }],
|
||||
});
|
||||
|
||||
await delay(500);
|
||||
|
||||
// Find updates with usage metadata
|
||||
const updatesWithUsage = sessionUpdates.filter(
|
||||
(u) =>
|
||||
u.update?.sessionUpdate === 'agent_message_chunk' &&
|
||||
u.update?._meta?.usage,
|
||||
);
|
||||
|
||||
expect(updatesWithUsage.length).toBeGreaterThan(0);
|
||||
|
||||
const usage = updatesWithUsage[0].update?._meta?.usage;
|
||||
expect(usage).toBeDefined();
|
||||
expect(
|
||||
typeof usage?.promptTokens === 'number' ||
|
||||
typeof usage?.totalTokens === 'number',
|
||||
).toBe(true);
|
||||
} catch (e) {
|
||||
if (stderr.length) console.error('Agent stderr:', stderr.join(''));
|
||||
throw e;
|
||||
} finally {
|
||||
await cleanup();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||