mirror of
https://github.com/coder/registry.git
synced 2026-06-02 20:48:14 +00:00
chore: improve Prettier configuration (#392)
This commit is contained in:
@@ -192,8 +192,8 @@ main() {
|
|||||||
|
|
||||||
# Always run formatter to ensure consistent formatting
|
# Always run formatter to ensure consistent formatting
|
||||||
echo "🔧 Running formatter to ensure consistent formatting..."
|
echo "🔧 Running formatter to ensure consistent formatting..."
|
||||||
if command -v bun >/dev/null 2>&1; then
|
if command -v bun > /dev/null 2>&1; then
|
||||||
bun fmt >/dev/null 2>&1 || echo "⚠️ Warning: bun fmt failed, but continuing..."
|
bun fmt > /dev/null 2>&1 || echo "⚠️ Warning: bun fmt failed, but continuing..."
|
||||||
else
|
else
|
||||||
echo "⚠️ Warning: bun not found, skipping formatting"
|
echo "⚠️ Warning: bun not found, skipping formatting"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -21,4 +21,4 @@ jobs:
|
|||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v8
|
uses: golangci/golangci-lint-action@v8
|
||||||
with:
|
with:
|
||||||
version: v2.1
|
version: v2.1
|
||||||
|
|||||||
@@ -11,33 +11,33 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
pull-requests: read
|
pull-requests: read
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Extract tag information
|
- name: Extract tag information
|
||||||
id: tag_info
|
id: tag_info
|
||||||
run: |
|
run: |
|
||||||
TAG=${GITHUB_REF#refs/tags/}
|
TAG=${GITHUB_REF#refs/tags/}
|
||||||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
IFS='/' read -ra PARTS <<< "$TAG"
|
IFS='/' read -ra PARTS <<< "$TAG"
|
||||||
NAMESPACE="${PARTS[1]}"
|
NAMESPACE="${PARTS[1]}"
|
||||||
MODULE="${PARTS[2]}"
|
MODULE="${PARTS[2]}"
|
||||||
VERSION="${PARTS[3]}"
|
VERSION="${PARTS[3]}"
|
||||||
|
|
||||||
echo "namespace=$NAMESPACE" >> $GITHUB_OUTPUT
|
echo "namespace=$NAMESPACE" >> $GITHUB_OUTPUT
|
||||||
echo "module=$MODULE" >> $GITHUB_OUTPUT
|
echo "module=$MODULE" >> $GITHUB_OUTPUT
|
||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
echo "module_path=registry/$NAMESPACE/modules/$MODULE" >> $GITHUB_OUTPUT
|
echo "module_path=registry/$NAMESPACE/modules/$MODULE" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
RELEASE_TITLE="$NAMESPACE/$MODULE $VERSION"
|
RELEASE_TITLE="$NAMESPACE/$MODULE $VERSION"
|
||||||
echo "release_title=$RELEASE_TITLE" >> $GITHUB_OUTPUT
|
echo "release_title=$RELEASE_TITLE" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Find previous tag
|
- name: Find previous tag
|
||||||
id: prev_tag
|
id: prev_tag
|
||||||
env:
|
env:
|
||||||
@@ -46,15 +46,15 @@ jobs:
|
|||||||
CURRENT_TAG: ${{ steps.tag_info.outputs.tag }}
|
CURRENT_TAG: ${{ steps.tag_info.outputs.tag }}
|
||||||
run: |
|
run: |
|
||||||
PREV_TAG=$(git tag -l "release/$NAMESPACE/$MODULE/v*" | sort -V | grep -B1 "$CURRENT_TAG" | head -1)
|
PREV_TAG=$(git tag -l "release/$NAMESPACE/$MODULE/v*" | sort -V | grep -B1 "$CURRENT_TAG" | head -1)
|
||||||
|
|
||||||
if [ -z "$PREV_TAG" ] || [ "$PREV_TAG" = "$CURRENT_TAG" ]; then
|
if [ -z "$PREV_TAG" ] || [ "$PREV_TAG" = "$CURRENT_TAG" ]; then
|
||||||
echo "No previous tag found, using initial commit"
|
echo "No previous tag found, using initial commit"
|
||||||
PREV_TAG=$(git rev-list --max-parents=0 HEAD)
|
PREV_TAG=$(git rev-list --max-parents=0 HEAD)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "prev_tag=$PREV_TAG" >> $GITHUB_OUTPUT
|
echo "prev_tag=$PREV_TAG" >> $GITHUB_OUTPUT
|
||||||
echo "Previous tag: $PREV_TAG"
|
echo "Previous tag: $PREV_TAG"
|
||||||
|
|
||||||
- name: Generate changelog
|
- name: Generate changelog
|
||||||
id: changelog
|
id: changelog
|
||||||
env:
|
env:
|
||||||
@@ -64,15 +64,15 @@ jobs:
|
|||||||
CURRENT_TAG: ${{ steps.tag_info.outputs.tag }}
|
CURRENT_TAG: ${{ steps.tag_info.outputs.tag }}
|
||||||
run: |
|
run: |
|
||||||
echo "Generating changelog for $MODULE_PATH between $PREV_TAG and $CURRENT_TAG"
|
echo "Generating changelog for $MODULE_PATH between $PREV_TAG and $CURRENT_TAG"
|
||||||
|
|
||||||
COMMITS=$(git log --oneline --no-merges "$PREV_TAG..$CURRENT_TAG" -- "$MODULE_PATH")
|
COMMITS=$(git log --oneline --no-merges "$PREV_TAG..$CURRENT_TAG" -- "$MODULE_PATH")
|
||||||
|
|
||||||
if [ -z "$COMMITS" ]; then
|
if [ -z "$COMMITS" ]; then
|
||||||
echo "No commits found for this module"
|
echo "No commits found for this module"
|
||||||
echo "changelog=No changes found for this module." >> $GITHUB_OUTPUT
|
echo "changelog=No changes found for this module." >> $GITHUB_OUTPUT
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$PREV_TAG" == release/* ]]; then
|
if [[ "$PREV_TAG" == release/* ]]; then
|
||||||
FULL_CHANGELOG=$(gh api repos/:owner/:repo/releases/generate-notes \
|
FULL_CHANGELOG=$(gh api repos/:owner/:repo/releases/generate-notes \
|
||||||
--field tag_name="$CURRENT_TAG" \
|
--field tag_name="$CURRENT_TAG" \
|
||||||
@@ -82,11 +82,11 @@ jobs:
|
|||||||
echo "New module detected, skipping GitHub API"
|
echo "New module detected, skipping GitHub API"
|
||||||
FULL_CHANGELOG=""
|
FULL_CHANGELOG=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MODULE_COMMIT_SHAS=$(git log --format="%H" --no-merges "$PREV_TAG..$CURRENT_TAG" -- "$MODULE_PATH")
|
MODULE_COMMIT_SHAS=$(git log --format="%H" --no-merges "$PREV_TAG..$CURRENT_TAG" -- "$MODULE_PATH")
|
||||||
|
|
||||||
FILTERED_CHANGELOG="## What's Changed\n\n"
|
FILTERED_CHANGELOG="## What's Changed\n\n"
|
||||||
|
|
||||||
for sha in $MODULE_COMMIT_SHAS; do
|
for sha in $MODULE_COMMIT_SHAS; do
|
||||||
SHORT_SHA=${sha:0:7}
|
SHORT_SHA=${sha:0:7}
|
||||||
|
|
||||||
@@ -100,11 +100,11 @@ jobs:
|
|||||||
FILTERED_CHANGELOG="${FILTERED_CHANGELOG}* $COMMIT_MSG by @$AUTHOR\n"
|
FILTERED_CHANGELOG="${FILTERED_CHANGELOG}* $COMMIT_MSG by @$AUTHOR\n"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "changelog<<EOF" >> $GITHUB_OUTPUT
|
echo "changelog<<EOF" >> $GITHUB_OUTPUT
|
||||||
echo -e "$FILTERED_CHANGELOG" >> $GITHUB_OUTPUT
|
echo -e "$FILTERED_CHANGELOG" >> $GITHUB_OUTPUT
|
||||||
echo "EOF" >> $GITHUB_OUTPUT
|
echo "EOF" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -114,4 +114,4 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
gh release create "$TAG_NAME" \
|
gh release create "$TAG_NAME" \
|
||||||
--title "$RELEASE_TITLE" \
|
--title "$RELEASE_TITLE" \
|
||||||
--notes "$CHANGELOG"
|
--notes "$CHANGELOG"
|
||||||
|
|||||||
+2
-2
@@ -163,8 +163,8 @@ linters:
|
|||||||
staticcheck:
|
staticcheck:
|
||||||
checks:
|
checks:
|
||||||
- all
|
- all
|
||||||
- SA4006 # Detects redundant assignments
|
- SA4006 # Detects redundant assignments
|
||||||
- SA4009 # Detects redundant variable declarations
|
- SA4009 # Detects redundant variable declarations
|
||||||
- SA1019
|
- SA1019
|
||||||
exclusions:
|
exclusions:
|
||||||
generated: lax
|
generated: lax
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Ignore symlinks to avoid Prettier errors
|
||||||
|
CLAUDE.md
|
||||||
|
.github/copilot-instructions.md
|
||||||
|
|
||||||
|
# Ignore node_modules and dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Ignore Terraform files (formatted by terraform fmt)
|
||||||
|
*.tf
|
||||||
|
*.hcl
|
||||||
|
*.tfvars
|
||||||
|
|
||||||
|
# Ignore generated and temporary files
|
||||||
|
.terraform/
|
||||||
|
*.tfstate
|
||||||
|
*.tfstate.backup
|
||||||
|
*.tfstate.lock.info
|
||||||
|
|
||||||
|
# Ignore other files that shouldn't be formatted
|
||||||
|
bun.lock
|
||||||
|
go.sum
|
||||||
|
go.mod
|
||||||
@@ -4,11 +4,11 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "registry",
|
"name": "registry",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.2.18",
|
"@types/bun": "^1.2.21",
|
||||||
"bun-types": "^1.2.18",
|
"bun-types": "^1.2.21",
|
||||||
"dedent": "^1.6.0",
|
"dedent": "^1.6.0",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"marked": "^16.0.0",
|
"marked": "^16.2.0",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"prettier-plugin-sh": "^0.18.0",
|
"prettier-plugin-sh": "^0.18.0",
|
||||||
"prettier-plugin-terraform-formatter": "^1.2.1",
|
"prettier-plugin-terraform-formatter": "^1.2.1",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
"packages": {
|
"packages": {
|
||||||
"@reteps/dockerfmt": ["@reteps/dockerfmt@0.3.6", "", {}, "sha512-Tb5wIMvBf/nLejTQ61krK644/CEMB/cpiaIFXqGApfGqO3GwcR3qnI0DbmkFVCl2OyEp8LnLX3EkucoL0+tbFg=="],
|
"@reteps/dockerfmt": ["@reteps/dockerfmt@0.3.6", "", {}, "sha512-Tb5wIMvBf/nLejTQ61krK644/CEMB/cpiaIFXqGApfGqO3GwcR3qnI0DbmkFVCl2OyEp8LnLX3EkucoL0+tbFg=="],
|
||||||
|
|
||||||
"@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
|
"@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="],
|
"@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="],
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
"argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
|
"argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
|
||||||
|
|
||||||
"bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
"bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="],
|
||||||
|
|
||||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
"kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="],
|
"kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="],
|
||||||
|
|
||||||
"marked": ["marked@16.0.0", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-MUKMXDjsD/eptB7GPzxo4xcnLS6oo7/RHimUMHEDRhUooPwmN9BEpMl7AEOJv3bmso169wHI2wUF9VQgL7zfmA=="],
|
"marked": ["marked@16.2.0", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-LbbTuye+0dWRz2TS9KJ7wsnD4KAtpj0MVkWc90XvBa6AslXsT0hTBVH5k32pcSyHH1fst9XEFJunXHktVy0zlg=="],
|
||||||
|
|
||||||
"prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="],
|
"prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="],
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -1,18 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "registry",
|
"name": "registry",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"fmt": "bun x prettier --write **/*.sh **/*.ts **/*.md *.md && terraform fmt -recursive -diff",
|
"fmt": "bun x prettier --write . && terraform fmt -recursive -diff",
|
||||||
"fmt:ci": "bun x prettier --check **/*.sh **/*.ts **/*.md *.md && terraform fmt -check -recursive -diff",
|
"fmt:ci": "bun x prettier --check . && terraform fmt -check -recursive -diff",
|
||||||
"terraform-validate": "./scripts/terraform_validate.sh",
|
"terraform-validate": "./scripts/terraform_validate.sh",
|
||||||
"test": "./scripts/terraform_test_all.sh",
|
"test": "./scripts/terraform_test_all.sh",
|
||||||
"update-version": "./update-version.sh"
|
"update-version": "./update-version.sh"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.2.18",
|
"@types/bun": "^1.2.21",
|
||||||
"bun-types": "^1.2.18",
|
"bun-types": "^1.2.21",
|
||||||
"dedent": "^1.6.0",
|
"dedent": "^1.6.0",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"marked": "^16.0.0",
|
"marked": "^16.2.0",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"prettier-plugin-sh": "^0.18.0",
|
"prettier-plugin-sh": "^0.18.0",
|
||||||
"prettier-plugin-terraform-formatter": "^1.2.1"
|
"prettier-plugin-terraform-formatter": "^1.2.1"
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ describe("tmux module", async () => {
|
|||||||
|
|
||||||
// check that the script contains expected lines
|
// check that the script contains expected lines
|
||||||
expect(scriptResource.script).toContain("Installing tmux");
|
expect(scriptResource.script).toContain("Installing tmux");
|
||||||
expect(scriptResource.script).toContain("Installing Tmux Plugin Manager (TPM)");
|
expect(scriptResource.script).toContain(
|
||||||
|
"Installing Tmux Plugin Manager (TPM)",
|
||||||
|
);
|
||||||
expect(scriptResource.script).toContain("tmux configuration created at");
|
expect(scriptResource.script).toContain("tmux configuration created at");
|
||||||
expect(scriptResource.script).toContain("✅ tmux setup complete!");
|
expect(scriptResource.script).toContain("✅ tmux setup complete!");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,75 +8,75 @@ TMUX_CONFIG="${TMUX_CONFIG}"
|
|||||||
|
|
||||||
# Function to install tmux
|
# Function to install tmux
|
||||||
install_tmux() {
|
install_tmux() {
|
||||||
printf "Checking for tmux installation\n"
|
printf "Checking for tmux installation\n"
|
||||||
|
|
||||||
if command -v tmux &> /dev/null; then
|
if command -v tmux &> /dev/null; then
|
||||||
printf "tmux is already installed \n\n"
|
printf "tmux is already installed \n\n"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf "Installing tmux \n\n"
|
printf "Installing tmux \n\n"
|
||||||
|
|
||||||
# Detect package manager and install tmux
|
# Detect package manager and install tmux
|
||||||
if command -v apt-get &> /dev/null; then
|
if command -v apt-get &> /dev/null; then
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y tmux
|
sudo apt-get install -y tmux
|
||||||
elif command -v yum &> /dev/null; then
|
elif command -v yum &> /dev/null; then
|
||||||
sudo yum install -y tmux
|
sudo yum install -y tmux
|
||||||
elif command -v dnf &> /dev/null; then
|
elif command -v dnf &> /dev/null; then
|
||||||
sudo dnf install -y tmux
|
sudo dnf install -y tmux
|
||||||
elif command -v zypper &> /dev/null; then
|
elif command -v zypper &> /dev/null; then
|
||||||
sudo zypper install -y tmux
|
sudo zypper install -y tmux
|
||||||
elif command -v apk &> /dev/null; then
|
elif command -v apk &> /dev/null; then
|
||||||
sudo apk add tmux
|
sudo apk add tmux
|
||||||
elif command -v brew &> /dev/null; then
|
elif command -v brew &> /dev/null; then
|
||||||
brew install tmux
|
brew install tmux
|
||||||
else
|
else
|
||||||
printf "No supported package manager found. Please install tmux manually. \n"
|
printf "No supported package manager found. Please install tmux manually. \n"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf "tmux installed successfully \n"
|
printf "tmux installed successfully \n"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to install Tmux Plugin Manager (TPM)
|
# Function to install Tmux Plugin Manager (TPM)
|
||||||
install_tpm() {
|
install_tpm() {
|
||||||
local tpm_dir="$HOME/.tmux/plugins/tpm"
|
local tpm_dir="$HOME/.tmux/plugins/tpm"
|
||||||
|
|
||||||
if [ -d "$tpm_dir" ]; then
|
if [ -d "$tpm_dir" ]; then
|
||||||
printf "TPM is already installed"
|
printf "TPM is already installed"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf "Installing Tmux Plugin Manager (TPM) \n"
|
printf "Installing Tmux Plugin Manager (TPM) \n"
|
||||||
|
|
||||||
# Create plugins directory
|
# Create plugins directory
|
||||||
mkdir -p "$HOME/.tmux/plugins"
|
mkdir -p "$HOME/.tmux/plugins"
|
||||||
|
|
||||||
# Clone TPM repository
|
# Clone TPM repository
|
||||||
if command -v git &> /dev/null; then
|
if command -v git &> /dev/null; then
|
||||||
git clone https://github.com/tmux-plugins/tpm "$tpm_dir"
|
git clone https://github.com/tmux-plugins/tpm "$tpm_dir"
|
||||||
printf "TPM installed successfully"
|
printf "TPM installed successfully"
|
||||||
else
|
else
|
||||||
printf "Git is not installed. Please install git to use tmux plugins. \n"
|
printf "Git is not installed. Please install git to use tmux plugins. \n"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to create tmux configuration
|
# Function to create tmux configuration
|
||||||
setup_tmux_config() {
|
setup_tmux_config() {
|
||||||
printf "Setting up tmux configuration \n"
|
printf "Setting up tmux configuration \n"
|
||||||
|
|
||||||
local config_dir="$HOME/.tmux"
|
local config_dir="$HOME/.tmux"
|
||||||
local config_file="$HOME/.tmux.conf"
|
local config_file="$HOME/.tmux.conf"
|
||||||
|
|
||||||
mkdir -p "$config_dir"
|
mkdir -p "$config_dir"
|
||||||
|
|
||||||
if [ -n "$TMUX_CONFIG" ]; then
|
if [ -n "$TMUX_CONFIG" ]; then
|
||||||
printf "$TMUX_CONFIG" > "$config_file"
|
printf "$TMUX_CONFIG" > "$config_file"
|
||||||
printf "$${BOLD}Custom tmux configuration applied at {$config_file} \n\n"
|
printf "$${BOLD}Custom tmux configuration applied at {$config_file} \n\n"
|
||||||
else
|
else
|
||||||
cat > "$config_file" << EOF
|
cat > "$config_file" << EOF
|
||||||
# Tmux Configuration File
|
# Tmux Configuration File
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
@@ -106,48 +106,48 @@ bind C-r run-shell "~/.tmux/plugins/tmux-resurrect/scripts/restore.sh"
|
|||||||
# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
|
# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
|
||||||
run '~/.tmux/plugins/tpm/tpm'
|
run '~/.tmux/plugins/tpm/tpm'
|
||||||
EOF
|
EOF
|
||||||
printf "tmux configuration created at {$config_file} \n\n"
|
printf "tmux configuration created at {$config_file} \n\n"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to install tmux plugins
|
# Function to install tmux plugins
|
||||||
install_plugins() {
|
install_plugins() {
|
||||||
printf "Installing tmux plugins"
|
printf "Installing tmux plugins"
|
||||||
|
|
||||||
# Check if TPM is installed
|
# Check if TPM is installed
|
||||||
if [ ! -d "$HOME/.tmux/plugins/tpm" ]; then
|
if [ ! -d "$HOME/.tmux/plugins/tpm" ]; then
|
||||||
printf "TPM is not installed. Cannot install plugins. \n"
|
printf "TPM is not installed. Cannot install plugins. \n"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Install plugins using TPM
|
# Install plugins using TPM
|
||||||
"$HOME/.tmux/plugins/tpm/bin/install_plugins"
|
"$HOME/.tmux/plugins/tpm/bin/install_plugins"
|
||||||
|
|
||||||
printf "tmux plugins installed successfully \n"
|
printf "tmux plugins installed successfully \n"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Main execution
|
# Main execution
|
||||||
main() {
|
main() {
|
||||||
printf "$${BOLD} 🛠️Setting up tmux with session persistence! \n\n"
|
printf "$${BOLD} 🛠️Setting up tmux with session persistence! \n\n"
|
||||||
printf ""
|
printf ""
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
install_tmux
|
install_tmux
|
||||||
install_tpm
|
install_tpm
|
||||||
|
|
||||||
# Setup tmux configuration
|
# Setup tmux configuration
|
||||||
setup_tmux_config
|
setup_tmux_config
|
||||||
|
|
||||||
# Install plugins
|
# Install plugins
|
||||||
install_plugins
|
install_plugins
|
||||||
|
|
||||||
printf "$${BOLD}✅ tmux setup complete! \n\n"
|
printf "$${BOLD}✅ tmux setup complete! \n\n"
|
||||||
|
|
||||||
printf "$${BOLD} Attempting to restore sessions\n"
|
printf "$${BOLD} Attempting to restore sessions\n"
|
||||||
tmux new-session -d \; source-file ~/.tmux.conf \; run-shell '~/.tmux/plugins/tmux-resurrect/scripts/restore.sh'
|
tmux new-session -d \; source-file ~/.tmux.conf \; run-shell '~/.tmux/plugins/tmux-resurrect/scripts/restore.sh'
|
||||||
printf "$${BOLD} Sessions restored: -> %s\n" "$(tmux ls)"
|
printf "$${BOLD} Sessions restored: -> %s\n" "$(tmux ls)"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Run main function
|
# Run main function
|
||||||
main
|
main
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ handle_session() {
|
|||||||
local session_name="$1"
|
local session_name="$1"
|
||||||
|
|
||||||
# Check if the session exists
|
# Check if the session exists
|
||||||
if tmux has-session -t "$session_name" 2>/dev/null; then
|
if tmux has-session -t "$session_name" 2> /dev/null; then
|
||||||
echo "Session '$session_name' exists, attaching to it..."
|
echo "Session '$session_name' exists, attaching to it..."
|
||||||
tmux attach-session -t "$session_name"
|
tmux attach-session -t "$session_name"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -165,9 +165,9 @@ describe("auggie", async () => {
|
|||||||
mcpServers: {
|
mcpServers: {
|
||||||
test: {
|
test: {
|
||||||
command: "test-cmd",
|
command: "test-cmd",
|
||||||
type: "stdio"
|
type: "stdio",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const { id } = await setup({
|
const { id } = await setup({
|
||||||
moduleVariables: {
|
moduleVariables: {
|
||||||
@@ -187,13 +187,16 @@ describe("auggie", async () => {
|
|||||||
const rules = "Always use TypeScript for new files";
|
const rules = "Always use TypeScript for new files";
|
||||||
const { id } = await setup({
|
const { id } = await setup({
|
||||||
moduleVariables: {
|
moduleVariables: {
|
||||||
install_auggie: "false", // Don't need to install auggie to test rules file creation
|
install_auggie: "false", // Don't need to install auggie to test rules file creation
|
||||||
rules: rules,
|
rules: rules,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
|
|
||||||
const rulesFile = await readFileContainer(id, "/home/coder/.augment/rules.md");
|
const rulesFile = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/home/coder/.augment/rules.md",
|
||||||
|
);
|
||||||
expect(rulesFile).toContain(rules);
|
expect(rulesFile).toContain(rules);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -309,12 +312,15 @@ describe("auggie", async () => {
|
|||||||
test("coder-mcp-config-created", async () => {
|
test("coder-mcp-config-created", async () => {
|
||||||
const { id } = await setup({
|
const { id } = await setup({
|
||||||
moduleVariables: {
|
moduleVariables: {
|
||||||
install_auggie: "false", // Don't need to install auggie to test MCP config creation
|
install_auggie: "false", // Don't need to install auggie to test MCP config creation
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
|
|
||||||
const mcpConfig = await readFileContainer(id, "/home/coder/.augment/coder_mcp.json");
|
const mcpConfig = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/home/coder/.augment/coder_mcp.json",
|
||||||
|
);
|
||||||
expect(mcpConfig).toContain("mcpServers");
|
expect(mcpConfig).toContain("mcpServers");
|
||||||
expect(mcpConfig).toContain("coder");
|
expect(mcpConfig).toContain("coder");
|
||||||
expect(mcpConfig).toContain("CODER_MCP_APP_STATUS_SLUG");
|
expect(mcpConfig).toContain("CODER_MCP_APP_STATUS_SLUG");
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ printf "rules: %s\n" "$ARG_AUGGIE_RULES"
|
|||||||
|
|
||||||
echo "--------------------------------"
|
echo "--------------------------------"
|
||||||
|
|
||||||
|
|
||||||
function check_dependencies() {
|
function check_dependencies() {
|
||||||
if ! command_exists node; then
|
if ! command_exists node; then
|
||||||
printf "Error: Node.js is not installed. Please install Node.js manually or use the pre_install_script to install it.\n"
|
printf "Error: Node.js is not installed. Please install Node.js manually or use the pre_install_script to install it.\n"
|
||||||
@@ -51,28 +50,27 @@ function install_auggie() {
|
|||||||
if [ ! -d "$NPM_GLOBAL_PREFIX" ]; then
|
if [ ! -d "$NPM_GLOBAL_PREFIX" ]; then
|
||||||
mkdir -p "$NPM_GLOBAL_PREFIX"
|
mkdir -p "$NPM_GLOBAL_PREFIX"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
npm config set prefix "$NPM_GLOBAL_PREFIX"
|
npm config set prefix "$NPM_GLOBAL_PREFIX"
|
||||||
|
|
||||||
export PATH="$NPM_GLOBAL_PREFIX/bin:$PATH"
|
export PATH="$NPM_GLOBAL_PREFIX/bin:$PATH"
|
||||||
|
|
||||||
if [ -n "$ARG_AUGGIE_VERSION" ]; then
|
if [ -n "$ARG_AUGGIE_VERSION" ]; then
|
||||||
npm install -g "@augmentcode/auggie@$ARG_AUGGIE_VERSION"
|
npm install -g "@augmentcode/auggie@$ARG_AUGGIE_VERSION"
|
||||||
else
|
else
|
||||||
npm install -g "@augmentcode/auggie"
|
npm install -g "@augmentcode/auggie"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! grep -q "export PATH=\"\$HOME/.npm-global/bin:\$PATH\"" "$HOME/.bashrc"; then
|
if ! grep -q "export PATH=\"\$HOME/.npm-global/bin:\$PATH\"" "$HOME/.bashrc"; then
|
||||||
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> "$HOME/.bashrc"
|
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> "$HOME/.bashrc"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf "%s Successfully installed Auggie CLI. Version: %s\n" "${BOLD}" "$(auggie --version)"
|
printf "%s Successfully installed Auggie CLI. Version: %s\n" "${BOLD}" "$(auggie --version)"
|
||||||
else
|
else
|
||||||
printf "Skipping Auggie CLI installation (install_auggie=false)\n"
|
printf "Skipping Auggie CLI installation (install_auggie=false)\n"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function create_coder_mcp() {
|
function create_coder_mcp() {
|
||||||
AUGGIE_CODER_MCP_FILE="$HOME/.augment/coder_mcp.json"
|
AUGGIE_CODER_MCP_FILE="$HOME/.augment/coder_mcp.json"
|
||||||
CODER_MCP=$(
|
CODER_MCP=$(
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ printf "report_tasks: %s\n" "$ARG_REPORT_TASKS"
|
|||||||
|
|
||||||
echo "--------------------------------"
|
echo "--------------------------------"
|
||||||
|
|
||||||
|
|
||||||
function validate_auggie_installation() {
|
function validate_auggie_installation() {
|
||||||
if command_exists auggie; then
|
if command_exists auggie; then
|
||||||
printf "Auggie is installed\n"
|
printf "Auggie is installed\n"
|
||||||
|
|||||||
@@ -124,8 +124,8 @@ describe("codex", async () => {
|
|||||||
});
|
});
|
||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
const resp = await readFileContainer(id, "/home/coder/.codex/config.toml");
|
const resp = await readFileContainer(id, "/home/coder/.codex/config.toml");
|
||||||
expect(resp).toContain("sandbox_mode = \"danger-full-access\"");
|
expect(resp).toContain('sandbox_mode = "danger-full-access"');
|
||||||
expect(resp).toContain("preferred_auth_method = \"apikey\"");
|
expect(resp).toContain('preferred_auth_method = "apikey"');
|
||||||
expect(resp).toContain("[custom_section]");
|
expect(resp).toContain("[custom_section]");
|
||||||
expect(resp).toContain("[mcp_servers.Coder]");
|
expect(resp).toContain("[mcp_servers.Coder]");
|
||||||
});
|
});
|
||||||
@@ -221,7 +221,7 @@ describe("codex", async () => {
|
|||||||
debug = true
|
debug = true
|
||||||
logging_level = "verbose"
|
logging_level = "verbose"
|
||||||
`.trim();
|
`.trim();
|
||||||
|
|
||||||
const additionalMCP = dedent`
|
const additionalMCP = dedent`
|
||||||
[mcp_servers.CustomTool]
|
[mcp_servers.CustomTool]
|
||||||
command = "/usr/local/bin/custom-tool"
|
command = "/usr/local/bin/custom-tool"
|
||||||
@@ -235,7 +235,7 @@ describe("codex", async () => {
|
|||||||
type = "stdio"
|
type = "stdio"
|
||||||
description = "Database query interface"
|
description = "Database query interface"
|
||||||
`.trim();
|
`.trim();
|
||||||
|
|
||||||
const { id } = await setup({
|
const { id } = await setup({
|
||||||
moduleVariables: {
|
moduleVariables: {
|
||||||
base_config_toml: baseConfig,
|
base_config_toml: baseConfig,
|
||||||
@@ -244,14 +244,14 @@ describe("codex", async () => {
|
|||||||
});
|
});
|
||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
const resp = await readFileContainer(id, "/home/coder/.codex/config.toml");
|
const resp = await readFileContainer(id, "/home/coder/.codex/config.toml");
|
||||||
|
|
||||||
// Check base config
|
// Check base config
|
||||||
expect(resp).toContain("sandbox_mode = \"read-only\"");
|
expect(resp).toContain('sandbox_mode = "read-only"');
|
||||||
expect(resp).toContain("preferred_auth_method = \"chatgpt\"");
|
expect(resp).toContain('preferred_auth_method = "chatgpt"');
|
||||||
expect(resp).toContain("custom_setting = \"test-value\"");
|
expect(resp).toContain('custom_setting = "test-value"');
|
||||||
expect(resp).toContain("[advanced_settings]");
|
expect(resp).toContain("[advanced_settings]");
|
||||||
expect(resp).toContain("logging_level = \"verbose\"");
|
expect(resp).toContain('logging_level = "verbose"');
|
||||||
|
|
||||||
// Check MCP servers
|
// Check MCP servers
|
||||||
expect(resp).toContain("[mcp_servers.Coder]");
|
expect(resp).toContain("[mcp_servers.Coder]");
|
||||||
expect(resp).toContain("[mcp_servers.CustomTool]");
|
expect(resp).toContain("[mcp_servers.CustomTool]");
|
||||||
@@ -268,17 +268,17 @@ describe("codex", async () => {
|
|||||||
});
|
});
|
||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
const resp = await readFileContainer(id, "/home/coder/.codex/config.toml");
|
const resp = await readFileContainer(id, "/home/coder/.codex/config.toml");
|
||||||
|
|
||||||
// Check default base config
|
// Check default base config
|
||||||
expect(resp).toContain("sandbox_mode = \"workspace-write\"");
|
expect(resp).toContain('sandbox_mode = "workspace-write"');
|
||||||
expect(resp).toContain("approval_policy = \"never\"");
|
expect(resp).toContain('approval_policy = "never"');
|
||||||
expect(resp).toContain("[sandbox_workspace_write]");
|
expect(resp).toContain("[sandbox_workspace_write]");
|
||||||
expect(resp).toContain("network_access = true");
|
expect(resp).toContain("network_access = true");
|
||||||
|
|
||||||
// Check only Coder MCP server is present
|
// Check only Coder MCP server is present
|
||||||
expect(resp).toContain("[mcp_servers.Coder]");
|
expect(resp).toContain("[mcp_servers.Coder]");
|
||||||
expect(resp).toContain("Report ALL tasks and statuses");
|
expect(resp).toContain("Report ALL tasks and statuses");
|
||||||
|
|
||||||
// Ensure no additional MCP servers
|
// Ensure no additional MCP servers
|
||||||
const mcpServerCount = (resp.match(/\[mcp_servers\./g) || []).length;
|
const mcpServerCount = (resp.match(/\[mcp_servers\./g) || []).length;
|
||||||
expect(mcpServerCount).toBe(1);
|
expect(mcpServerCount).toBe(1);
|
||||||
@@ -328,7 +328,10 @@ describe("codex", async () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
await execModuleScript(id_2);
|
await execModuleScript(id_2);
|
||||||
const resp_2 = await readFileContainer(id_2, "/home/coder/.codex/AGENTS.md");
|
const resp_2 = await readFileContainer(
|
||||||
|
id_2,
|
||||||
|
"/home/coder/.codex/AGENTS.md",
|
||||||
|
);
|
||||||
expect(resp_2).toContain(prompt_1);
|
expect(resp_2).toContain(prompt_1);
|
||||||
const count = (resp_2.match(new RegExp(prompt_1, "g")) || []).length;
|
const count = (resp_2.match(new RegExp(prompt_1, "g")) || []).length;
|
||||||
expect(count).toBe(1);
|
expect(count).toBe(1);
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ function install_codex() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
write_minimal_default_config() {
|
write_minimal_default_config() {
|
||||||
local config_path="$1"
|
local config_path="$1"
|
||||||
cat << EOF > "$config_path"
|
cat << EOF > "$config_path"
|
||||||
# Minimal Default Codex Configuration
|
# Minimal Default Codex Configuration
|
||||||
sandbox_mode = "workspace-write"
|
sandbox_mode = "workspace-write"
|
||||||
approval_policy = "never"
|
approval_policy = "never"
|
||||||
@@ -98,9 +98,9 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
append_mcp_servers_section() {
|
append_mcp_servers_section() {
|
||||||
local config_path="$1"
|
local config_path="$1"
|
||||||
|
|
||||||
cat << EOF >> "$config_path"
|
cat << EOF >> "$config_path"
|
||||||
|
|
||||||
# MCP Servers Configuration
|
# MCP Servers Configuration
|
||||||
[mcp_servers.Coder]
|
[mcp_servers.Coder]
|
||||||
@@ -112,32 +112,32 @@ type = "stdio"
|
|||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
if [ -n "$ARG_ADDITIONAL_MCP_SERVERS" ]; then
|
if [ -n "$ARG_ADDITIONAL_MCP_SERVERS" ]; then
|
||||||
printf "Adding additional MCP servers\n"
|
printf "Adding additional MCP servers\n"
|
||||||
echo "$ARG_ADDITIONAL_MCP_SERVERS" >> "$config_path"
|
echo "$ARG_ADDITIONAL_MCP_SERVERS" >> "$config_path"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function populate_config_toml() {
|
function populate_config_toml() {
|
||||||
CONFIG_PATH="$HOME/.codex/config.toml"
|
CONFIG_PATH="$HOME/.codex/config.toml"
|
||||||
mkdir -p "$(dirname "$CONFIG_PATH")"
|
mkdir -p "$(dirname "$CONFIG_PATH")"
|
||||||
|
|
||||||
if [ -n "$ARG_BASE_CONFIG_TOML" ]; then
|
if [ -n "$ARG_BASE_CONFIG_TOML" ]; then
|
||||||
printf "Using provided base configuration\n"
|
printf "Using provided base configuration\n"
|
||||||
echo "$ARG_BASE_CONFIG_TOML" > "$CONFIG_PATH"
|
echo "$ARG_BASE_CONFIG_TOML" > "$CONFIG_PATH"
|
||||||
else
|
else
|
||||||
printf "Using minimal default configuration\n"
|
printf "Using minimal default configuration\n"
|
||||||
write_minimal_default_config "$CONFIG_PATH"
|
write_minimal_default_config "$CONFIG_PATH"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
append_mcp_servers_section "$CONFIG_PATH"
|
append_mcp_servers_section "$CONFIG_PATH"
|
||||||
}
|
}
|
||||||
|
|
||||||
function add_instruction_prompt_if_exists() {
|
function add_instruction_prompt_if_exists() {
|
||||||
if [ -n "${ARG_CODEX_INSTRUCTION_PROMPT:-}" ]; then
|
if [ -n "${ARG_CODEX_INSTRUCTION_PROMPT:-}" ]; then
|
||||||
AGENTS_PATH="$HOME/.codex/AGENTS.md"
|
AGENTS_PATH="$HOME/.codex/AGENTS.md"
|
||||||
printf "Creating AGENTS.md in .codex directory: %s\\n" "${AGENTS_PATH}"
|
printf "Creating AGENTS.md in .codex directory: %s\\n" "${AGENTS_PATH}"
|
||||||
|
|
||||||
mkdir -p "$HOME/.codex"
|
mkdir -p "$HOME/.codex"
|
||||||
|
|
||||||
if [ -f "${AGENTS_PATH}" ] && grep -Fq "${ARG_CODEX_INSTRUCTION_PROMPT}" "${AGENTS_PATH}"; then
|
if [ -f "${AGENTS_PATH}" ] && grep -Fq "${ARG_CODEX_INSTRUCTION_PROMPT}" "${AGENTS_PATH}"; then
|
||||||
@@ -146,7 +146,7 @@ function add_instruction_prompt_if_exists() {
|
|||||||
printf "Appending instruction prompt to AGENTS.md in .codex directory\n"
|
printf "Appending instruction prompt to AGENTS.md in .codex directory\n"
|
||||||
echo -e "\n${ARG_CODEX_INSTRUCTION_PROMPT}" >> "${AGENTS_PATH}"
|
echo -e "\n${ARG_CODEX_INSTRUCTION_PROMPT}" >> "${AGENTS_PATH}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -d "${ARG_CODEX_START_DIRECTORY}" ]; then
|
if [ ! -d "${ARG_CODEX_START_DIRECTORY}" ]; then
|
||||||
printf "Creating start directory '%s'\\n" "${ARG_CODEX_START_DIRECTORY}"
|
printf "Creating start directory '%s'\\n" "${ARG_CODEX_START_DIRECTORY}"
|
||||||
mkdir -p "${ARG_CODEX_START_DIRECTORY}" || {
|
mkdir -p "${ARG_CODEX_START_DIRECTORY}" || {
|
||||||
|
|||||||
@@ -55,8 +55,6 @@ if [ -n "$ARG_CODEX_MODEL" ]; then
|
|||||||
CODEX_ARGS+=("--model" "$ARG_CODEX_MODEL")
|
CODEX_ARGS+=("--model" "$ARG_CODEX_MODEL")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if [ -n "$ARG_CODEX_TASK_PROMPT" ]; then
|
if [ -n "$ARG_CODEX_TASK_PROMPT" ]; then
|
||||||
printf "Running the task prompt %s\n" "$ARG_CODEX_TASK_PROMPT"
|
printf "Running the task prompt %s\n" "$ARG_CODEX_TASK_PROMPT"
|
||||||
PROMPT="Complete the task at hand in one go. Every step of the way, report your progress using coder_report_task tool with proper summary and statuses. Your task at hand: $ARG_CODEX_TASK_PROMPT"
|
PROMPT="Complete the task at hand in one go. Every step of the way, report your progress using coder_report_task tool with proper summary and statuses. Your task at hand: $ARG_CODEX_TASK_PROMPT"
|
||||||
@@ -65,7 +63,6 @@ else
|
|||||||
printf "No task prompt given.\n"
|
printf "No task prompt given.\n"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Terminal dimensions optimized for Coder Tasks UI sidebar:
|
# Terminal dimensions optimized for Coder Tasks UI sidebar:
|
||||||
# - Width 67: fits comfortably in sidebar
|
# - Width 67: fits comfortably in sidebar
|
||||||
# - Height 1190: adjusted due to Codex terminal height bug
|
# - Height 1190: adjusted due to Codex terminal height bug
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
import { afterEach, beforeAll, describe, expect, setDefaultTimeout, test } from "bun:test";
|
import {
|
||||||
|
afterEach,
|
||||||
|
beforeAll,
|
||||||
|
describe,
|
||||||
|
expect,
|
||||||
|
setDefaultTimeout,
|
||||||
|
test,
|
||||||
|
} from "bun:test";
|
||||||
import { execContainer, runTerraformInit, writeFileContainer } from "~test";
|
import { execContainer, runTerraformInit, writeFileContainer } from "~test";
|
||||||
import {
|
import {
|
||||||
execModuleScript,
|
execModuleScript,
|
||||||
expectAgentAPIStarted,
|
expectAgentAPIStarted,
|
||||||
loadTestFile,
|
loadTestFile,
|
||||||
setup as setupUtil
|
setup as setupUtil,
|
||||||
|
} from "../../../coder/modules/agentapi/test-util";
|
||||||
|
import {
|
||||||
|
setupContainer,
|
||||||
|
writeExecutable,
|
||||||
} from "../../../coder/modules/agentapi/test-util";
|
} from "../../../coder/modules/agentapi/test-util";
|
||||||
import { setupContainer, writeExecutable } from "../../../coder/modules/agentapi/test-util";
|
|
||||||
|
|
||||||
let cleanupFns: (() => Promise<void>)[] = [];
|
let cleanupFns: (() => Promise<void>)[] = [];
|
||||||
const registerCleanup = (fn: () => Promise<void>) => cleanupFns.push(fn);
|
const registerCleanup = (fn: () => Promise<void>) => cleanupFns.push(fn);
|
||||||
@@ -72,11 +82,12 @@ describe("cursor-cli", async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("agentapi-mcp-json", async () => {
|
test("agentapi-mcp-json", async () => {
|
||||||
const mcpJson = '{"mcpServers": {"test": {"command": "test-cmd", "type": "stdio"}}}';
|
const mcpJson =
|
||||||
|
'{"mcpServers": {"test": {"command": "test-cmd", "type": "stdio"}}}';
|
||||||
const { id } = await setup({
|
const { id } = await setup({
|
||||||
moduleVariables: {
|
moduleVariables: {
|
||||||
mcp: mcpJson,
|
mcp: mcpJson,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const resp = await execModuleScript(id);
|
const resp = await execModuleScript(id);
|
||||||
expect(resp.exitCode).toBe(0);
|
expect(resp.exitCode).toBe(0);
|
||||||
@@ -99,7 +110,7 @@ describe("cursor-cli", async () => {
|
|||||||
const { id } = await setup({
|
const { id } = await setup({
|
||||||
moduleVariables: {
|
moduleVariables: {
|
||||||
rules_files: JSON.stringify({ "typescript.md": rulesContent }),
|
rules_files: JSON.stringify({ "typescript.md": rulesContent }),
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const resp = await execModuleScript(id);
|
const resp = await execModuleScript(id);
|
||||||
expect(resp.exitCode).toBe(0);
|
expect(resp.exitCode).toBe(0);
|
||||||
@@ -118,7 +129,7 @@ describe("cursor-cli", async () => {
|
|||||||
const { id } = await setup({
|
const { id } = await setup({
|
||||||
moduleVariables: {
|
moduleVariables: {
|
||||||
api_key: apiKey,
|
api_key: apiKey,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const resp = await execModuleScript(id);
|
const resp = await execModuleScript(id);
|
||||||
expect(resp.exitCode).toBe(0);
|
expect(resp.exitCode).toBe(0);
|
||||||
@@ -138,7 +149,7 @@ describe("cursor-cli", async () => {
|
|||||||
model: model,
|
model: model,
|
||||||
force: "true",
|
force: "true",
|
||||||
ai_prompt: "test prompt",
|
ai_prompt: "test prompt",
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const resp = await execModuleScript(id);
|
const resp = await execModuleScript(id);
|
||||||
expect(resp.exitCode).toBe(0);
|
expect(resp.exitCode).toBe(0);
|
||||||
@@ -158,7 +169,7 @@ describe("cursor-cli", async () => {
|
|||||||
moduleVariables: {
|
moduleVariables: {
|
||||||
pre_install_script: "#!/bin/bash\necho 'cursor-pre-install-script'",
|
pre_install_script: "#!/bin/bash\necho 'cursor-pre-install-script'",
|
||||||
post_install_script: "#!/bin/bash\necho 'cursor-post-install-script'",
|
post_install_script: "#!/bin/bash\necho 'cursor-post-install-script'",
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const resp = await execModuleScript(id);
|
const resp = await execModuleScript(id);
|
||||||
expect(resp.exitCode).toBe(0);
|
expect(resp.exitCode).toBe(0);
|
||||||
@@ -183,7 +194,7 @@ describe("cursor-cli", async () => {
|
|||||||
const { id } = await setup({
|
const { id } = await setup({
|
||||||
moduleVariables: {
|
moduleVariables: {
|
||||||
folder: folder,
|
folder: folder,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const resp = await execModuleScript(id);
|
const resp = await execModuleScript(id);
|
||||||
expect(resp.exitCode).toBe(0);
|
expect(resp.exitCode).toBe(0);
|
||||||
@@ -205,8 +216,5 @@ describe("cursor-cli", async () => {
|
|||||||
expect(resp.exitCode).toBe(0);
|
expect(resp.exitCode).toBe(0);
|
||||||
|
|
||||||
await expectAgentAPIStarted(id);
|
await expectAgentAPIStarted(id);
|
||||||
})
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ fi
|
|||||||
|
|
||||||
if [ -n "$ARG_AI_PROMPT" ]; then
|
if [ -n "$ARG_AI_PROMPT" ]; then
|
||||||
printf "AI prompt provided\n"
|
printf "AI prompt provided\n"
|
||||||
ARGS+=("Complete the task at hand in one go. Every step of the way, report your progress using coder_report_task tool with proper summary and statuses. Your task at hand: $ARG_AI_PROMPT")
|
ARGS+=("Complete the task at hand in one go. Every step of the way, report your progress using coder_report_task tool with proper summary and statuses. Your task at hand: $ARG_AI_PROMPT")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Log and run in background, redirecting all output to the log file
|
# Log and run in background, redirecting all output to the log file
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ fi
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
echo "$(date) - cursor-agent-mock"
|
echo "$(date) - cursor-agent-mock"
|
||||||
sleep 15
|
sleep 15
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -127,7 +127,10 @@ describe("gemini", async () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
const resp = await readFileContainer(id, "/home/coder/.gemini/settings.json");
|
const resp = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/home/coder/.gemini/settings.json",
|
||||||
|
);
|
||||||
expect(resp).toContain("foo");
|
expect(resp).toContain("foo");
|
||||||
expect(resp).toContain("bar");
|
expect(resp).toContain("bar");
|
||||||
});
|
});
|
||||||
@@ -141,7 +144,10 @@ describe("gemini", async () => {
|
|||||||
});
|
});
|
||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
|
|
||||||
const resp = await readFileContainer(id, "/home/coder/.gemini-module/agentapi-start.log");
|
const resp = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/home/coder/.gemini-module/agentapi-start.log",
|
||||||
|
);
|
||||||
expect(resp).toContain("Using direct Gemini API with API key");
|
expect(resp).toContain("Using direct Gemini API with API key");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -153,8 +159,11 @@ describe("gemini", async () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
const resp = await readFileContainer(id, "/home/coder/.gemini-module/agentapi-start.log");
|
const resp = await readFileContainer(
|
||||||
expect(resp).toContain('GOOGLE_GENAI_USE_VERTEXAI=\'true\'');
|
id,
|
||||||
|
"/home/coder/.gemini-module/agentapi-start.log",
|
||||||
|
);
|
||||||
|
expect(resp).toContain("GOOGLE_GENAI_USE_VERTEXAI='true'");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("gemini-model", async () => {
|
test("gemini-model", async () => {
|
||||||
@@ -166,7 +175,10 @@ describe("gemini", async () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
const resp = await readFileContainer(id, "/home/coder/.gemini-module/agentapi-start.log");
|
const resp = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/home/coder/.gemini-module/agentapi-start.log",
|
||||||
|
);
|
||||||
expect(resp).toContain(model);
|
expect(resp).toContain(model);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -178,9 +190,15 @@ describe("gemini", async () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
const preInstallLog = await readFileContainer(id, "/home/coder/.gemini-module/pre_install.log");
|
const preInstallLog = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/home/coder/.gemini-module/pre_install.log",
|
||||||
|
);
|
||||||
expect(preInstallLog).toContain("pre-install-script");
|
expect(preInstallLog).toContain("pre-install-script");
|
||||||
const postInstallLog = await readFileContainer(id, "/home/coder/.gemini-module/post_install.log");
|
const postInstallLog = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/home/coder/.gemini-module/post_install.log",
|
||||||
|
);
|
||||||
expect(postInstallLog).toContain("post-install-script");
|
expect(postInstallLog).toContain("post-install-script");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -193,7 +211,10 @@ describe("gemini", async () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
const resp = await readFileContainer(id, "/home/coder/.gemini-module/agentapi-start.log");
|
const resp = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/home/coder/.gemini-module/agentapi-start.log",
|
||||||
|
);
|
||||||
expect(resp).toContain(folder);
|
expect(resp).toContain(folder);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -205,7 +226,10 @@ describe("gemini", async () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
const resp = await readFileContainer(id, "/home/coder/.gemini/settings.json");
|
const resp = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/home/coder/.gemini/settings.json",
|
||||||
|
);
|
||||||
expect(resp).toContain("custom");
|
expect(resp).toContain("custom");
|
||||||
expect(resp).toContain("enabled");
|
expect(resp).toContain("enabled");
|
||||||
});
|
});
|
||||||
@@ -232,14 +256,21 @@ describe("gemini", async () => {
|
|||||||
await execModuleScript(id, {
|
await execModuleScript(id, {
|
||||||
GEMINI_TASK_PROMPT: taskPrompt,
|
GEMINI_TASK_PROMPT: taskPrompt,
|
||||||
});
|
});
|
||||||
const resp = await readFileContainer(id, "/home/coder/.gemini-module/agentapi-start.log");
|
const resp = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/home/coder/.gemini-module/agentapi-start.log",
|
||||||
|
);
|
||||||
expect(resp).toContain("Running automated task:");
|
expect(resp).toContain("Running automated task:");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("start-without-prompt", async () => {
|
test("start-without-prompt", async () => {
|
||||||
const { id } = await setup();
|
const { id } = await setup();
|
||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
const prompt = await execContainer(id, ["ls", "-l", "/home/coder/GEMINI.md"]);
|
const prompt = await execContainer(id, [
|
||||||
|
"ls",
|
||||||
|
"-l",
|
||||||
|
"/home/coder/GEMINI.md",
|
||||||
|
]);
|
||||||
expect(prompt.exitCode).not.toBe(0);
|
expect(prompt.exitCode).not.toBe(0);
|
||||||
expect(prompt.stderr).toContain("No such file or directory");
|
expect(prompt.stderr).toContain("No such file or directory");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
FROM ubuntu
|
FROM ubuntu
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y \
|
&& apt-get install -y \
|
||||||
curl \
|
curl \
|
||||||
git \
|
git \
|
||||||
golang \
|
golang \
|
||||||
sudo \
|
sudo \
|
||||||
vim \
|
vim \
|
||||||
wget \
|
wget \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
ARG USER=coder
|
ARG USER=coder
|
||||||
RUN useradd --groups sudo --no-create-home --shell /bin/bash ${USER} \
|
RUN useradd --groups sudo --no-create-home --shell /bin/bash ${USER} \
|
||||||
&& echo "${USER} ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/${USER} \
|
&& echo "${USER} ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/${USER} \
|
||||||
&& chmod 0440 /etc/sudoers.d/${USER}
|
&& chmod 0440 /etc/sudoers.d/${USER}
|
||||||
USER ${USER}
|
USER ${USER}
|
||||||
WORKDIR /home/${USER}
|
WORKDIR /home/${USER}
|
||||||
|
|||||||
@@ -164,7 +164,9 @@ describe("agentapi", async () => {
|
|||||||
id,
|
id,
|
||||||
"/home/coder/test-agentapi-start.log",
|
"/home/coder/test-agentapi-start.log",
|
||||||
);
|
);
|
||||||
expect(agentApiStartLog).toContain("Using AGENTAPI_CHAT_BASE_PATH: /@default/default.foo/apps/agentapi-web/chat");
|
expect(agentApiStartLog).toContain(
|
||||||
|
"Using AGENTAPI_CHAT_BASE_PATH: /@default/default.foo/apps/agentapi-web/chat",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("validate-agentapi-version", async () => {
|
test("validate-agentapi-version", async () => {
|
||||||
@@ -186,14 +188,16 @@ describe("agentapi", async () => {
|
|||||||
agentapi_version: "v0.0.1",
|
agentapi_version: "v0.0.1",
|
||||||
agentapi_subdomain: "false",
|
agentapi_subdomain: "false",
|
||||||
},
|
},
|
||||||
shouldThrow: "Running with subdomain = false is only supported by agentapi >= v0.3.3.",
|
shouldThrow:
|
||||||
|
"Running with subdomain = false is only supported by agentapi >= v0.3.3.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleVariables: {
|
moduleVariables: {
|
||||||
agentapi_version: "v0.3.2",
|
agentapi_version: "v0.3.2",
|
||||||
agentapi_subdomain: "false",
|
agentapi_subdomain: "false",
|
||||||
},
|
},
|
||||||
shouldThrow: "Running with subdomain = false is only supported by agentapi >= v0.3.3.",
|
shouldThrow:
|
||||||
|
"Running with subdomain = false is only supported by agentapi >= v0.3.3.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleVariables: {
|
moduleVariables: {
|
||||||
@@ -226,13 +230,17 @@ describe("agentapi", async () => {
|
|||||||
agentapi_version: "arbitrary-string-bypasses-validation",
|
agentapi_version: "arbitrary-string-bypasses-validation",
|
||||||
},
|
},
|
||||||
shouldThrow: "",
|
shouldThrow: "",
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
for (const { moduleVariables, shouldThrow } of cases) {
|
for (const { moduleVariables, shouldThrow } of cases) {
|
||||||
if (shouldThrow) {
|
if (shouldThrow) {
|
||||||
expect(setup({ moduleVariables: moduleVariables as Record<string, string> })).rejects.toThrow(shouldThrow);
|
expect(
|
||||||
|
setup({ moduleVariables: moduleVariables as Record<string, string> }),
|
||||||
|
).rejects.toThrow(shouldThrow);
|
||||||
} else {
|
} else {
|
||||||
expect(setup({ moduleVariables: moduleVariables as Record<string, string> })).resolves.toBeDefined();
|
expect(
|
||||||
|
setup({ moduleVariables: moduleVariables as Record<string, string> }),
|
||||||
|
).resolves.toBeDefined();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,22 +11,22 @@ agentapi_started=false
|
|||||||
|
|
||||||
echo "Waiting for agentapi server to start on port $port..."
|
echo "Waiting for agentapi server to start on port $port..."
|
||||||
for i in $(seq 1 150); do
|
for i in $(seq 1 150); do
|
||||||
for j in $(seq 1 3); do
|
for j in $(seq 1 3); do
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
if curl -fs -o /dev/null "http://localhost:$port/status"; then
|
if curl -fs -o /dev/null "http://localhost:$port/status"; then
|
||||||
echo "agentapi response received ($j/3)"
|
echo "agentapi response received ($j/3)"
|
||||||
else
|
else
|
||||||
echo "agentapi server not responding ($i/15)"
|
echo "agentapi server not responding ($i/15)"
|
||||||
continue 2
|
continue 2
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
agentapi_started=true
|
agentapi_started=true
|
||||||
break
|
break
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$agentapi_started" != "true" ]; then
|
if [ "$agentapi_started" != "true" ]; then
|
||||||
echo "Error: agentapi server did not start on port $port after 15 seconds."
|
echo "Error: agentapi server did not start on port $port after 15 seconds."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "agentapi server started on port $port."
|
echo "agentapi server started on port $port."
|
||||||
|
|||||||
@@ -17,76 +17,76 @@ AGENTAPI_CHAT_BASE_PATH="${ARG_AGENTAPI_CHAT_BASE_PATH:-}"
|
|||||||
set +o nounset
|
set +o nounset
|
||||||
|
|
||||||
command_exists() {
|
command_exists() {
|
||||||
command -v "$1" >/dev/null 2>&1
|
command -v "$1" > /dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
module_path="$HOME/${MODULE_DIR_NAME}"
|
module_path="$HOME/${MODULE_DIR_NAME}"
|
||||||
mkdir -p "$module_path/scripts"
|
mkdir -p "$module_path/scripts"
|
||||||
|
|
||||||
if [ ! -d "${WORKDIR}" ]; then
|
if [ ! -d "${WORKDIR}" ]; then
|
||||||
echo "Warning: The specified folder '${WORKDIR}' does not exist."
|
echo "Warning: The specified folder '${WORKDIR}' does not exist."
|
||||||
echo "Creating the folder..."
|
echo "Creating the folder..."
|
||||||
mkdir -p "${WORKDIR}"
|
mkdir -p "${WORKDIR}"
|
||||||
echo "Folder created successfully."
|
echo "Folder created successfully."
|
||||||
fi
|
fi
|
||||||
if [ -n "${PRE_INSTALL_SCRIPT}" ]; then
|
if [ -n "${PRE_INSTALL_SCRIPT}" ]; then
|
||||||
echo "Running pre-install script..."
|
echo "Running pre-install script..."
|
||||||
echo -n "${PRE_INSTALL_SCRIPT}" >"$module_path/pre_install.sh"
|
echo -n "${PRE_INSTALL_SCRIPT}" > "$module_path/pre_install.sh"
|
||||||
chmod +x "$module_path/pre_install.sh"
|
chmod +x "$module_path/pre_install.sh"
|
||||||
"$module_path/pre_install.sh" 2>&1 | tee "$module_path/pre_install.log"
|
"$module_path/pre_install.sh" 2>&1 | tee "$module_path/pre_install.log"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Running install script..."
|
echo "Running install script..."
|
||||||
echo -n "${INSTALL_SCRIPT}" >"$module_path/install.sh"
|
echo -n "${INSTALL_SCRIPT}" > "$module_path/install.sh"
|
||||||
chmod +x "$module_path/install.sh"
|
chmod +x "$module_path/install.sh"
|
||||||
"$module_path/install.sh" 2>&1 | tee "$module_path/install.log"
|
"$module_path/install.sh" 2>&1 | tee "$module_path/install.log"
|
||||||
|
|
||||||
# Install AgentAPI if enabled
|
# Install AgentAPI if enabled
|
||||||
if [ "${INSTALL_AGENTAPI}" = "true" ]; then
|
if [ "${INSTALL_AGENTAPI}" = "true" ]; then
|
||||||
echo "Installing AgentAPI..."
|
echo "Installing AgentAPI..."
|
||||||
arch=$(uname -m)
|
arch=$(uname -m)
|
||||||
if [ "$arch" = "x86_64" ]; then
|
if [ "$arch" = "x86_64" ]; then
|
||||||
binary_name="agentapi-linux-amd64"
|
binary_name="agentapi-linux-amd64"
|
||||||
elif [ "$arch" = "aarch64" ]; then
|
elif [ "$arch" = "aarch64" ]; then
|
||||||
binary_name="agentapi-linux-arm64"
|
binary_name="agentapi-linux-arm64"
|
||||||
else
|
else
|
||||||
echo "Error: Unsupported architecture: $arch"
|
echo "Error: Unsupported architecture: $arch"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if [ "${AGENTAPI_VERSION}" = "latest" ]; then
|
if [ "${AGENTAPI_VERSION}" = "latest" ]; then
|
||||||
# for the latest release the download URL pattern is different than for tagged releases
|
# for the latest release the download URL pattern is different than for tagged releases
|
||||||
# https://docs.github.com/en/repositories/releasing-projects-on-github/linking-to-releases
|
# https://docs.github.com/en/repositories/releasing-projects-on-github/linking-to-releases
|
||||||
download_url="https://github.com/coder/agentapi/releases/latest/download/$binary_name"
|
download_url="https://github.com/coder/agentapi/releases/latest/download/$binary_name"
|
||||||
else
|
else
|
||||||
download_url="https://github.com/coder/agentapi/releases/download/${AGENTAPI_VERSION}/$binary_name"
|
download_url="https://github.com/coder/agentapi/releases/download/${AGENTAPI_VERSION}/$binary_name"
|
||||||
fi
|
fi
|
||||||
curl \
|
curl \
|
||||||
--retry 5 \
|
--retry 5 \
|
||||||
--retry-delay 5 \
|
--retry-delay 5 \
|
||||||
--fail \
|
--fail \
|
||||||
--retry-all-errors \
|
--retry-all-errors \
|
||||||
-L \
|
-L \
|
||||||
-C - \
|
-C - \
|
||||||
-o agentapi \
|
-o agentapi \
|
||||||
"$download_url"
|
"$download_url"
|
||||||
chmod +x agentapi
|
chmod +x agentapi
|
||||||
sudo mv agentapi /usr/local/bin/agentapi
|
sudo mv agentapi /usr/local/bin/agentapi
|
||||||
fi
|
fi
|
||||||
if ! command_exists agentapi; then
|
if ! command_exists agentapi; then
|
||||||
echo "Error: AgentAPI is not installed. Please enable install_agentapi or install it manually."
|
echo "Error: AgentAPI is not installed. Please enable install_agentapi or install it manually."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n "${START_SCRIPT}" >"$module_path/scripts/agentapi-start.sh"
|
echo -n "${START_SCRIPT}" > "$module_path/scripts/agentapi-start.sh"
|
||||||
echo -n "${WAIT_FOR_START_SCRIPT}" >"$module_path/scripts/agentapi-wait-for-start.sh"
|
echo -n "${WAIT_FOR_START_SCRIPT}" > "$module_path/scripts/agentapi-wait-for-start.sh"
|
||||||
chmod +x "$module_path/scripts/agentapi-start.sh"
|
chmod +x "$module_path/scripts/agentapi-start.sh"
|
||||||
chmod +x "$module_path/scripts/agentapi-wait-for-start.sh"
|
chmod +x "$module_path/scripts/agentapi-wait-for-start.sh"
|
||||||
|
|
||||||
if [ -n "${POST_INSTALL_SCRIPT}" ]; then
|
if [ -n "${POST_INSTALL_SCRIPT}" ]; then
|
||||||
echo "Running post-install script..."
|
echo "Running post-install script..."
|
||||||
echo -n "${POST_INSTALL_SCRIPT}" >"$module_path/post_install.sh"
|
echo -n "${POST_INSTALL_SCRIPT}" > "$module_path/post_install.sh"
|
||||||
chmod +x "$module_path/post_install.sh"
|
chmod +x "$module_path/post_install.sh"
|
||||||
"$module_path/post_install.sh" 2>&1 | tee "$module_path/post_install.log"
|
"$module_path/post_install.sh" 2>&1 | tee "$module_path/post_install.log"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export LANG=en_US.UTF-8
|
export LANG=en_US.UTF-8
|
||||||
@@ -97,5 +97,5 @@ cd "${WORKDIR}"
|
|||||||
export AGENTAPI_CHAT_BASE_PATH="${AGENTAPI_CHAT_BASE_PATH:-}"
|
export AGENTAPI_CHAT_BASE_PATH="${AGENTAPI_CHAT_BASE_PATH:-}"
|
||||||
# Disable host header check since AgentAPI is proxied by Coder (which does its own validation)
|
# Disable host header check since AgentAPI is proxied by Coder (which does its own validation)
|
||||||
export AGENTAPI_ALLOWED_HOSTS="*"
|
export AGENTAPI_ALLOWED_HOSTS="*"
|
||||||
nohup "$module_path/scripts/agentapi-start.sh" true "${AGENTAPI_PORT}" &>"$module_path/agentapi-start.log" &
|
nohup "$module_path/scripts/agentapi-start.sh" true "${AGENTAPI_PORT}" &> "$module_path/agentapi-start.log" &
|
||||||
"$module_path/scripts/agentapi-wait-for-start.sh" "${AGENTAPI_PORT}"
|
"$module_path/scripts/agentapi-wait-for-start.sh" "${AGENTAPI_PORT}"
|
||||||
|
|||||||
@@ -25,14 +25,20 @@ export const setupContainer = async ({
|
|||||||
const coderScript = findResourceInstance(state, "coder_script");
|
const coderScript = findResourceInstance(state, "coder_script");
|
||||||
const id = await runContainer(image ?? "codercom/enterprise-node:latest");
|
const id = await runContainer(image ?? "codercom/enterprise-node:latest");
|
||||||
return {
|
return {
|
||||||
id, coderScript, cleanup: async () => {
|
id,
|
||||||
if (process.env["DEBUG"] === "true" || process.env["DEBUG"] === "1" || process.env["DEBUG"] === "yes") {
|
coderScript,
|
||||||
|
cleanup: async () => {
|
||||||
|
if (
|
||||||
|
process.env["DEBUG"] === "true" ||
|
||||||
|
process.env["DEBUG"] === "1" ||
|
||||||
|
process.env["DEBUG"] === "yes"
|
||||||
|
) {
|
||||||
console.log(`Not removing container ${id} in debug mode`);
|
console.log(`Not removing container ${id} in debug mode`);
|
||||||
console.log(`Run "docker rm -f ${id}" to remove it manually.`);
|
console.log(`Run "docker rm -f ${id}" to remove it manually.`);
|
||||||
} else {
|
} else {
|
||||||
await removeContainer(id);
|
await removeContainer(id);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ const portIdx = args.findIndex((arg) => arg === "--port") + 1;
|
|||||||
const port = portIdx ? args[portIdx] : 3284;
|
const port = portIdx ? args[portIdx] : 3284;
|
||||||
|
|
||||||
console.log(`starting server on port ${port}`);
|
console.log(`starting server on port ${port}`);
|
||||||
fs.writeFileSync("/home/coder/agentapi-mock.log", `AGENTAPI_ALLOWED_HOSTS: ${process.env.AGENTAPI_ALLOWED_HOSTS}`);
|
fs.writeFileSync(
|
||||||
|
"/home/coder/agentapi-mock.log",
|
||||||
|
`AGENTAPI_ALLOWED_HOSTS: ${process.env.AGENTAPI_ALLOWED_HOSTS}`,
|
||||||
|
);
|
||||||
|
|
||||||
http
|
http
|
||||||
.createServer(function (_request, response) {
|
.createServer(function (_request, response) {
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ port=${2:-3284}
|
|||||||
module_path="$HOME/.agentapi-module"
|
module_path="$HOME/.agentapi-module"
|
||||||
log_file_path="$module_path/agentapi.log"
|
log_file_path="$module_path/agentapi.log"
|
||||||
|
|
||||||
echo "using prompt: $use_prompt" >>/home/coder/test-agentapi-start.log
|
echo "using prompt: $use_prompt" >> /home/coder/test-agentapi-start.log
|
||||||
echo "using port: $port" >>/home/coder/test-agentapi-start.log
|
echo "using port: $port" >> /home/coder/test-agentapi-start.log
|
||||||
|
|
||||||
AGENTAPI_CHAT_BASE_PATH="${AGENTAPI_CHAT_BASE_PATH:-}"
|
AGENTAPI_CHAT_BASE_PATH="${AGENTAPI_CHAT_BASE_PATH:-}"
|
||||||
if [ -n "$AGENTAPI_CHAT_BASE_PATH" ]; then
|
if [ -n "$AGENTAPI_CHAT_BASE_PATH" ]; then
|
||||||
echo "Using AGENTAPI_CHAT_BASE_PATH: $AGENTAPI_CHAT_BASE_PATH" >>/home/coder/test-agentapi-start.log
|
echo "Using AGENTAPI_CHAT_BASE_PATH: $AGENTAPI_CHAT_BASE_PATH" >> /home/coder/test-agentapi-start.log
|
||||||
export AGENTAPI_CHAT_BASE_PATH
|
export AGENTAPI_CHAT_BASE_PATH
|
||||||
fi
|
fi
|
||||||
|
|
||||||
agentapi server --port "$port" --term-width 67 --term-height 1190 -- \
|
agentapi server --port "$port" --term-width 67 --term-height 1190 -- \
|
||||||
bash -c aiagent \
|
bash -c aiagent \
|
||||||
>"$log_file_path" 2>&1
|
> "$log_file_path" 2>&1
|
||||||
|
|||||||
@@ -9,33 +9,33 @@ log_file_path="$module_path/agentapi.log"
|
|||||||
|
|
||||||
# if the first argument is not empty, start claude with the prompt
|
# if the first argument is not empty, start claude with the prompt
|
||||||
if [ -n "$1" ]; then
|
if [ -n "$1" ]; then
|
||||||
cp "$module_path/prompt.txt" /tmp/claude-code-prompt
|
cp "$module_path/prompt.txt" /tmp/claude-code-prompt
|
||||||
else
|
else
|
||||||
rm -f /tmp/claude-code-prompt
|
rm -f /tmp/claude-code-prompt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# if the log file already exists, archive it
|
# if the log file already exists, archive it
|
||||||
if [ -f "$log_file_path" ]; then
|
if [ -f "$log_file_path" ]; then
|
||||||
mv "$log_file_path" "$log_file_path"".$(date +%s)"
|
mv "$log_file_path" "$log_file_path"".$(date +%s)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# see the remove-last-session-id.sh script for details
|
# see the remove-last-session-id.sh script for details
|
||||||
# about why we need it
|
# about why we need it
|
||||||
# avoid exiting if the script fails
|
# avoid exiting if the script fails
|
||||||
bash "$scripts_dir/remove-last-session-id.sh" "$(pwd)" 2>/dev/null || true
|
bash "$scripts_dir/remove-last-session-id.sh" "$(pwd)" 2> /dev/null || true
|
||||||
|
|
||||||
# we'll be manually handling errors from this point on
|
# we'll be manually handling errors from this point on
|
||||||
set +o errexit
|
set +o errexit
|
||||||
|
|
||||||
function start_agentapi() {
|
function start_agentapi() {
|
||||||
local continue_flag="$1"
|
local continue_flag="$1"
|
||||||
local prompt_subshell='"$(cat /tmp/claude-code-prompt)"'
|
local prompt_subshell='"$(cat /tmp/claude-code-prompt)"'
|
||||||
|
|
||||||
# use low width to fit in the tasks UI sidebar. height is adjusted so that width x height ~= 80x1000 characters
|
# use low width to fit in the tasks UI sidebar. height is adjusted so that width x height ~= 80x1000 characters
|
||||||
# visible in the terminal screen by default.
|
# visible in the terminal screen by default.
|
||||||
agentapi server --term-width 67 --term-height 1190 -- \
|
agentapi server --term-width 67 --term-height 1190 -- \
|
||||||
bash -c "claude $continue_flag --dangerously-skip-permissions $prompt_subshell" \
|
bash -c "claude $continue_flag --dangerously-skip-permissions $prompt_subshell" \
|
||||||
> "$log_file_path" 2>&1
|
> "$log_file_path" 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "Starting AgentAPI..."
|
echo "Starting AgentAPI..."
|
||||||
@@ -47,15 +47,15 @@ exit_code=$?
|
|||||||
echo "First AgentAPI exit code: $exit_code"
|
echo "First AgentAPI exit code: $exit_code"
|
||||||
|
|
||||||
if [ $exit_code -eq 0 ]; then
|
if [ $exit_code -eq 0 ]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# if there was no conversation to continue, claude exited with an error.
|
# if there was no conversation to continue, claude exited with an error.
|
||||||
# start claude without the --continue flag.
|
# start claude without the --continue flag.
|
||||||
if grep -q "No conversation found to continue" "$log_file_path"; then
|
if grep -q "No conversation found to continue" "$log_file_path"; then
|
||||||
echo "AgentAPI with --continue flag failed, starting claude without it."
|
echo "AgentAPI with --continue flag failed, starting claude without it."
|
||||||
start_agentapi
|
start_agentapi
|
||||||
exit_code=$?
|
exit_code=$?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Second AgentAPI exit code: $exit_code"
|
echo "Second AgentAPI exit code: $exit_code"
|
||||||
|
|||||||
@@ -9,22 +9,22 @@ agentapi_started=false
|
|||||||
|
|
||||||
echo "Waiting for agentapi server to start on port 3284..."
|
echo "Waiting for agentapi server to start on port 3284..."
|
||||||
for i in $(seq 1 150); do
|
for i in $(seq 1 150); do
|
||||||
for j in $(seq 1 3); do
|
for j in $(seq 1 3); do
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
if curl -fs -o /dev/null "http://localhost:3284/status"; then
|
if curl -fs -o /dev/null "http://localhost:3284/status"; then
|
||||||
echo "agentapi response received ($j/3)"
|
echo "agentapi response received ($j/3)"
|
||||||
else
|
else
|
||||||
echo "agentapi server not responding ($i/15)"
|
echo "agentapi server not responding ($i/15)"
|
||||||
continue 2
|
continue 2
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
agentapi_started=true
|
agentapi_started=true
|
||||||
break
|
break
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$agentapi_started" != "true" ]; then
|
if [ "$agentapi_started" != "true" ]; then
|
||||||
echo "Error: agentapi server did not start on port 3284 after 15 seconds."
|
echo "Error: agentapi server did not start on port 3284 after 15 seconds."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "agentapi server started on port 3284."
|
echo "agentapi server started on port 3284."
|
||||||
|
|||||||
@@ -20,7 +20,10 @@ if (
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync("/home/coder/agentapi-mock.log", `AGENTAPI_ALLOWED_HOSTS: ${process.env.AGENTAPI_ALLOWED_HOSTS}`);
|
fs.writeFileSync(
|
||||||
|
"/home/coder/agentapi-mock.log",
|
||||||
|
`AGENTAPI_ALLOWED_HOSTS: ${process.env.AGENTAPI_ALLOWED_HOSTS}`,
|
||||||
|
);
|
||||||
|
|
||||||
console.log(`starting server on port ${port}`);
|
console.log(`starting server on port ${port}`);
|
||||||
|
|
||||||
|
|||||||
@@ -94,12 +94,18 @@ describe("cursor", async () => {
|
|||||||
it("writes ~/.cursor/mcp.json when mcp provided", async () => {
|
it("writes ~/.cursor/mcp.json when mcp provided", async () => {
|
||||||
const id = await runContainer("alpine");
|
const id = await runContainer("alpine");
|
||||||
try {
|
try {
|
||||||
const mcp = JSON.stringify({ servers: { demo: { url: "http://localhost:1234" } } });
|
const mcp = JSON.stringify({
|
||||||
|
servers: { demo: { url: "http://localhost:1234" } },
|
||||||
|
});
|
||||||
const state = await runTerraformApply(import.meta.dir, {
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
agent_id: "foo",
|
agent_id: "foo",
|
||||||
mcp,
|
mcp,
|
||||||
});
|
});
|
||||||
const script = findResourceInstance(state, "coder_script", "cursor_mcp").script;
|
const script = findResourceInstance(
|
||||||
|
state,
|
||||||
|
"coder_script",
|
||||||
|
"cursor_mcp",
|
||||||
|
).script;
|
||||||
const resp = await execContainer(id, ["sh", "-c", script]);
|
const resp = await execContainer(id, ["sh", "-c", script]);
|
||||||
if (resp.exitCode !== 0) {
|
if (resp.exitCode !== 0) {
|
||||||
console.log(resp.stdout);
|
console.log(resp.stdout);
|
||||||
|
|||||||
@@ -7,55 +7,55 @@
|
|||||||
cd "$CODER_SCRIPT_DATA_DIR"
|
cd "$CODER_SCRIPT_DATA_DIR"
|
||||||
|
|
||||||
# If @devcontainers/cli is already installed, we can skip
|
# If @devcontainers/cli is already installed, we can skip
|
||||||
if command -v devcontainer >/dev/null 2>&1; then
|
if command -v devcontainer > /dev/null 2>&1; then
|
||||||
echo "🥳 @devcontainers/cli is already installed into $(which devcontainer)!"
|
echo "🥳 @devcontainers/cli is already installed into $(which devcontainer)!"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if docker is installed
|
# Check if docker is installed
|
||||||
if ! command -v docker >/dev/null 2>&1; then
|
if ! command -v docker > /dev/null 2>&1; then
|
||||||
echo "WARNING: Docker was not found but is required to use @devcontainers/cli, please make sure it is available."
|
echo "WARNING: Docker was not found but is required to use @devcontainers/cli, please make sure it is available."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Determine the package manager to use: npm, pnpm, or yarn
|
# Determine the package manager to use: npm, pnpm, or yarn
|
||||||
if command -v yarn >/dev/null 2>&1; then
|
if command -v yarn > /dev/null 2>&1; then
|
||||||
PACKAGE_MANAGER="yarn"
|
PACKAGE_MANAGER="yarn"
|
||||||
elif command -v npm >/dev/null 2>&1; then
|
elif command -v npm > /dev/null 2>&1; then
|
||||||
PACKAGE_MANAGER="npm"
|
PACKAGE_MANAGER="npm"
|
||||||
elif command -v pnpm >/dev/null 2>&1; then
|
elif command -v pnpm > /dev/null 2>&1; then
|
||||||
PACKAGE_MANAGER="pnpm"
|
PACKAGE_MANAGER="pnpm"
|
||||||
else
|
else
|
||||||
echo "ERROR: No supported package manager (npm, pnpm, yarn) is installed. Please install one first." 1>&2
|
echo "ERROR: No supported package manager (npm, pnpm, yarn) is installed. Please install one first." 1>&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
echo "Installing @devcontainers/cli using $PACKAGE_MANAGER..."
|
echo "Installing @devcontainers/cli using $PACKAGE_MANAGER..."
|
||||||
if [ "$PACKAGE_MANAGER" = "npm" ]; then
|
if [ "$PACKAGE_MANAGER" = "npm" ]; then
|
||||||
npm install -g @devcontainers/cli
|
npm install -g @devcontainers/cli
|
||||||
elif [ "$PACKAGE_MANAGER" = "pnpm" ]; then
|
elif [ "$PACKAGE_MANAGER" = "pnpm" ]; then
|
||||||
# Check if PNPM_HOME is set, if not, set it to the script's bin directory
|
# Check if PNPM_HOME is set, if not, set it to the script's bin directory
|
||||||
# pnpm needs this to be set to install binaries
|
# pnpm needs this to be set to install binaries
|
||||||
# coder agent ensures this part is part of the PATH
|
# coder agent ensures this part is part of the PATH
|
||||||
# so that the devcontainer command is available
|
# so that the devcontainer command is available
|
||||||
if [ -z "$PNPM_HOME" ]; then
|
if [ -z "$PNPM_HOME" ]; then
|
||||||
PNPM_HOME="$CODER_SCRIPT_BIN_DIR"
|
PNPM_HOME="$CODER_SCRIPT_BIN_DIR"
|
||||||
export PNPM_HOME
|
export PNPM_HOME
|
||||||
fi
|
|
||||||
pnpm add -g @devcontainers/cli
|
|
||||||
elif [ "$PACKAGE_MANAGER" = "yarn" ]; then
|
|
||||||
yarn global add @devcontainers/cli --prefix "$(dirname "$CODER_SCRIPT_BIN_DIR")"
|
|
||||||
fi
|
fi
|
||||||
|
pnpm add -g @devcontainers/cli
|
||||||
|
elif [ "$PACKAGE_MANAGER" = "yarn" ]; then
|
||||||
|
yarn global add @devcontainers/cli --prefix "$(dirname "$CODER_SCRIPT_BIN_DIR")"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if ! install; then
|
if ! install; then
|
||||||
echo "Failed to install @devcontainers/cli" >&2
|
echo "Failed to install @devcontainers/cli" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! command -v devcontainer >/dev/null 2>&1; then
|
if ! command -v devcontainer > /dev/null 2>&1; then
|
||||||
echo "Installation completed but 'devcontainer' command not found in PATH" >&2
|
echo "Installation completed but 'devcontainer' command not found in PATH" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "🥳 @devcontainers/cli has been installed into $(which devcontainer)!"
|
echo "🥳 @devcontainers/cli has been installed into $(which devcontainer)!"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ BOLD='\033[[0;1m'
|
|||||||
printf "$${BOLD}Installing filebrowser \n\n"
|
printf "$${BOLD}Installing filebrowser \n\n"
|
||||||
|
|
||||||
# Check if filebrowser is installed
|
# Check if filebrowser is installed
|
||||||
if ! command -v filebrowser &>/dev/null; then
|
if ! command -v filebrowser &> /dev/null; then
|
||||||
curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash
|
curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -34,6 +34,6 @@ printf "👷 Starting filebrowser in background... \n\n"
|
|||||||
|
|
||||||
printf "📂 Serving $${ROOT_DIR} at http://localhost:${PORT} \n\n"
|
printf "📂 Serving $${ROOT_DIR} at http://localhost:${PORT} \n\n"
|
||||||
|
|
||||||
filebrowser >>${LOG_PATH} 2>&1 &
|
filebrowser >> ${LOG_PATH} 2>&1 &
|
||||||
|
|
||||||
printf "📝 Logs at ${LOG_PATH} \n\n"
|
printf "📝 Logs at ${LOG_PATH} \n\n"
|
||||||
|
|||||||
@@ -267,6 +267,8 @@ describe("goose", async () => {
|
|||||||
await execModuleScript(id);
|
await execModuleScript(id);
|
||||||
|
|
||||||
const agentapiMockOutput = await readFileContainer(id, agentapiStartLog);
|
const agentapiMockOutput = await readFileContainer(id, agentapiStartLog);
|
||||||
expect(agentapiMockOutput).toContain("AGENTAPI_CHAT_BASE_PATH=/@default/default.foo/apps/goose/chat");
|
expect(agentapiMockOutput).toContain(
|
||||||
|
"AGENTAPI_CHAT_BASE_PATH=/@default/default.foo/apps/goose/chat",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Function to check if a command exists
|
# Function to check if a command exists
|
||||||
command_exists() {
|
command_exists() {
|
||||||
command -v "$1" >/dev/null 2>&1
|
command -v "$1" > /dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
set -o nounset
|
set -o nounset
|
||||||
@@ -18,40 +18,40 @@ echo "--------------------------------"
|
|||||||
set +o nounset
|
set +o nounset
|
||||||
|
|
||||||
if [ "${ARG_INSTALL}" = "true" ]; then
|
if [ "${ARG_INSTALL}" = "true" ]; then
|
||||||
echo "Installing Goose..."
|
echo "Installing Goose..."
|
||||||
parsed_version="${ARG_GOOSE_VERSION}"
|
parsed_version="${ARG_GOOSE_VERSION}"
|
||||||
if [ "${ARG_GOOSE_VERSION}" = "stable" ]; then
|
if [ "${ARG_GOOSE_VERSION}" = "stable" ]; then
|
||||||
parsed_version=""
|
parsed_version=""
|
||||||
fi
|
fi
|
||||||
curl -fsSL https://github.com/block/goose/releases/download/stable/download_cli.sh | GOOSE_VERSION="${parsed_version}" CONFIGURE=false bash
|
curl -fsSL https://github.com/block/goose/releases/download/stable/download_cli.sh | GOOSE_VERSION="${parsed_version}" CONFIGURE=false bash
|
||||||
echo "Goose installed"
|
echo "Goose installed"
|
||||||
else
|
else
|
||||||
echo "Skipping Goose installation"
|
echo "Skipping Goose installation"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${ARG_GOOSE_CONFIG}" != "" ]; then
|
if [ "${ARG_GOOSE_CONFIG}" != "" ]; then
|
||||||
echo "Configuring Goose..."
|
echo "Configuring Goose..."
|
||||||
mkdir -p "$HOME/.config/goose"
|
mkdir -p "$HOME/.config/goose"
|
||||||
echo "GOOSE_PROVIDER: $ARG_PROVIDER" >"$HOME/.config/goose/config.yaml"
|
echo "GOOSE_PROVIDER: $ARG_PROVIDER" > "$HOME/.config/goose/config.yaml"
|
||||||
echo "GOOSE_MODEL: $ARG_MODEL" >>"$HOME/.config/goose/config.yaml"
|
echo "GOOSE_MODEL: $ARG_MODEL" >> "$HOME/.config/goose/config.yaml"
|
||||||
echo "$ARG_GOOSE_CONFIG" >>"$HOME/.config/goose/config.yaml"
|
echo "$ARG_GOOSE_CONFIG" >> "$HOME/.config/goose/config.yaml"
|
||||||
else
|
else
|
||||||
echo "Skipping Goose configuration"
|
echo "Skipping Goose configuration"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${GOOSE_SYSTEM_PROMPT}" != "" ]; then
|
if [ "${GOOSE_SYSTEM_PROMPT}" != "" ]; then
|
||||||
echo "Setting Goose system prompt..."
|
echo "Setting Goose system prompt..."
|
||||||
mkdir -p "$HOME/.config/goose"
|
mkdir -p "$HOME/.config/goose"
|
||||||
echo "$GOOSE_SYSTEM_PROMPT" >"$HOME/.config/goose/.goosehints"
|
echo "$GOOSE_SYSTEM_PROMPT" > "$HOME/.config/goose/.goosehints"
|
||||||
else
|
else
|
||||||
echo "Goose system prompt not set. use the GOOSE_SYSTEM_PROMPT environment variable to set it."
|
echo "Goose system prompt not set. use the GOOSE_SYSTEM_PROMPT environment variable to set it."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if command_exists goose; then
|
if command_exists goose; then
|
||||||
GOOSE_CMD=goose
|
GOOSE_CMD=goose
|
||||||
elif [ -f "$HOME/.local/bin/goose" ]; then
|
elif [ -f "$HOME/.local/bin/goose" ]; then
|
||||||
GOOSE_CMD="$HOME/.local/bin/goose"
|
GOOSE_CMD="$HOME/.local/bin/goose"
|
||||||
else
|
else
|
||||||
echo "Error: Goose is not installed. Please enable install_goose or install it manually."
|
echo "Error: Goose is not installed. Please enable install_goose or install it manually."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ set -o errexit
|
|||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
command_exists() {
|
command_exists() {
|
||||||
command -v "$1" >/dev/null 2>&1
|
command -v "$1" > /dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
if command_exists goose; then
|
if command_exists goose; then
|
||||||
GOOSE_CMD=goose
|
GOOSE_CMD=goose
|
||||||
elif [ -f "$HOME/.local/bin/goose" ]; then
|
elif [ -f "$HOME/.local/bin/goose" ]; then
|
||||||
GOOSE_CMD="$HOME/.local/bin/goose"
|
GOOSE_CMD="$HOME/.local/bin/goose"
|
||||||
else
|
else
|
||||||
echo "Error: Goose is not installed. Please enable install_goose or install it manually."
|
echo "Error: Goose is not installed. Please enable install_goose or install it manually."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# this must be kept up to date with main.tf
|
# this must be kept up to date with main.tf
|
||||||
@@ -21,15 +21,15 @@ MODULE_DIR="$HOME/.goose-module"
|
|||||||
mkdir -p "$MODULE_DIR"
|
mkdir -p "$MODULE_DIR"
|
||||||
|
|
||||||
if [ ! -z "$GOOSE_TASK_PROMPT" ]; then
|
if [ ! -z "$GOOSE_TASK_PROMPT" ]; then
|
||||||
echo "Starting with a prompt"
|
echo "Starting with a prompt"
|
||||||
PROMPT="Review your goosehints. Every step of the way, report tasks to Coder with proper descriptions and statuses. Your task at hand: $GOOSE_TASK_PROMPT"
|
PROMPT="Review your goosehints. Every step of the way, report tasks to Coder with proper descriptions and statuses. Your task at hand: $GOOSE_TASK_PROMPT"
|
||||||
PROMPT_FILE="$MODULE_DIR/prompt.txt"
|
PROMPT_FILE="$MODULE_DIR/prompt.txt"
|
||||||
echo -n "$PROMPT" >"$PROMPT_FILE"
|
echo -n "$PROMPT" > "$PROMPT_FILE"
|
||||||
GOOSE_ARGS=(run --interactive --instructions "$PROMPT_FILE")
|
GOOSE_ARGS=(run --interactive --instructions "$PROMPT_FILE")
|
||||||
else
|
else
|
||||||
echo "Starting without a prompt"
|
echo "Starting without a prompt"
|
||||||
GOOSE_ARGS=()
|
GOOSE_ARGS=()
|
||||||
fi
|
fi
|
||||||
|
|
||||||
agentapi server --term-width 67 --term-height 1190 -- \
|
agentapi server --term-width 67 --term-height 1190 -- \
|
||||||
bash -c "$(printf '%q ' "$GOOSE_CMD" "${GOOSE_ARGS[@]}")"
|
bash -c "$(printf '%q ' "$GOOSE_CMD" "${GOOSE_ARGS[@]}")"
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
const http = require("http");
|
const http = require("http");
|
||||||
const args = process.argv.slice(2);
|
const args = process.argv.slice(2);
|
||||||
console.log(args);
|
console.log(args);
|
||||||
console.log(`AGENTAPI_CHAT_BASE_PATH=${process.env["AGENTAPI_CHAT_BASE_PATH"]}`);
|
console.log(
|
||||||
|
`AGENTAPI_CHAT_BASE_PATH=${process.env["AGENTAPI_CHAT_BASE_PATH"]}`,
|
||||||
|
);
|
||||||
const port = 3284;
|
const port = 3284;
|
||||||
|
|
||||||
console.log(`starting server on port ${port}`);
|
console.log(`starting server on port ${port}`);
|
||||||
|
|||||||
+2
-2
@@ -3,6 +3,6 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
echo "$(date) - goose-mock"
|
echo "$(date) - goose-mock"
|
||||||
sleep 15
|
sleep 15
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -97,4 +97,4 @@ describe("jetbrains-fleet", async () => {
|
|||||||
expect(coder_app?.instances.length).toBe(1);
|
expect(coder_app?.instances.length).toBe(1);
|
||||||
expect(coder_app?.instances[0].attributes.group).toBe("JetBrains IDEs");
|
expect(coder_app?.instances[0].attributes.group).toBe("JetBrains IDEs");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -115,22 +115,29 @@ describe("jupyterlab", async () => {
|
|||||||
port: 8888,
|
port: 8888,
|
||||||
token: "test-token",
|
token: "test-token",
|
||||||
password: "",
|
password: "",
|
||||||
allow_origin: "*"
|
allow_origin: "*",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
const configJson = JSON.stringify(config);
|
const configJson = JSON.stringify(config);
|
||||||
const state = await runTerraformApply(import.meta.dir, {
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
agent_id: "foo",
|
agent_id: "foo",
|
||||||
config: configJson,
|
config: configJson,
|
||||||
});
|
});
|
||||||
const script = findResourceInstance(state, "coder_script", "jupyterlab_config").script;
|
const script = findResourceInstance(
|
||||||
|
state,
|
||||||
|
"coder_script",
|
||||||
|
"jupyterlab_config",
|
||||||
|
).script;
|
||||||
const resp = await execContainer(id, ["sh", "-c", script]);
|
const resp = await execContainer(id, ["sh", "-c", script]);
|
||||||
if (resp.exitCode !== 0) {
|
if (resp.exitCode !== 0) {
|
||||||
console.log(resp.stdout);
|
console.log(resp.stdout);
|
||||||
console.log(resp.stderr);
|
console.log(resp.stderr);
|
||||||
}
|
}
|
||||||
expect(resp.exitCode).toBe(0);
|
expect(resp.exitCode).toBe(0);
|
||||||
const content = await readFileContainer(id, "/root/.jupyter/jupyter_server_config.json");
|
const content = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/root/.jupyter/jupyter_server_config.json",
|
||||||
|
);
|
||||||
// Parse both JSON strings and compare objects to avoid key ordering issues
|
// Parse both JSON strings and compare objects to avoid key ordering issues
|
||||||
const actualConfig = JSON.parse(content);
|
const actualConfig = JSON.parse(content);
|
||||||
expect(actualConfig).toEqual(config);
|
expect(actualConfig).toEqual(config);
|
||||||
@@ -145,7 +152,7 @@ describe("jupyterlab", async () => {
|
|||||||
config: "{}",
|
config: "{}",
|
||||||
});
|
});
|
||||||
const configScripts = state.resources.filter(
|
const configScripts = state.resources.filter(
|
||||||
(res) => res.type === "coder_script" && res.name === "jupyterlab_config"
|
(res) => res.type === "coder_script" && res.name === "jupyterlab_config",
|
||||||
);
|
);
|
||||||
expect(configScripts.length).toBe(1);
|
expect(configScripts.length).toBe(1);
|
||||||
});
|
});
|
||||||
@@ -155,7 +162,7 @@ describe("jupyterlab", async () => {
|
|||||||
agent_id: "foo",
|
agent_id: "foo",
|
||||||
});
|
});
|
||||||
const configScripts = state.resources.filter(
|
const configScripts = state.resources.filter(
|
||||||
(res) => res.type === "coder_script" && res.name === "jupyterlab_config"
|
(res) => res.type === "coder_script" && res.name === "jupyterlab_config",
|
||||||
);
|
);
|
||||||
expect(configScripts.length).toBe(1);
|
expect(configScripts.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ INSTALLER=""
|
|||||||
check_available_installer() {
|
check_available_installer() {
|
||||||
# check if pipx is installed
|
# check if pipx is installed
|
||||||
echo "Checking for a supported installer"
|
echo "Checking for a supported installer"
|
||||||
if command -v pipx >/dev/null 2>&1; then
|
if command -v pipx > /dev/null 2>&1; then
|
||||||
echo "pipx is installed"
|
echo "pipx is installed"
|
||||||
INSTALLER="pipx"
|
INSTALLER="pipx"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
# check if uv is installed
|
# check if uv is installed
|
||||||
if command -v uv >/dev/null 2>&1; then
|
if command -v uv > /dev/null 2>&1; then
|
||||||
echo "uv is installed"
|
echo "uv is installed"
|
||||||
INSTALLER="uv"
|
INSTALLER="uv"
|
||||||
return
|
return
|
||||||
@@ -26,21 +26,21 @@ fi
|
|||||||
BOLD='\033[0;1m'
|
BOLD='\033[0;1m'
|
||||||
|
|
||||||
# check if jupyterlab is installed
|
# check if jupyterlab is installed
|
||||||
if ! command -v jupyter-lab >/dev/null 2>&1; then
|
if ! command -v jupyter-lab > /dev/null 2>&1; then
|
||||||
# install jupyterlab
|
# install jupyterlab
|
||||||
check_available_installer
|
check_available_installer
|
||||||
printf "$${BOLD}Installing jupyterlab!\n"
|
printf "$${BOLD}Installing jupyterlab!\n"
|
||||||
case $INSTALLER in
|
case $INSTALLER in
|
||||||
uv)
|
uv)
|
||||||
uv pip install -q jupyterlab &&
|
uv pip install -q jupyterlab \
|
||||||
printf "%s\n" "🥳 jupyterlab has been installed"
|
&& printf "%s\n" "🥳 jupyterlab has been installed"
|
||||||
JUPYTER="$HOME/.venv/bin/jupyter-lab"
|
JUPYTER="$HOME/.venv/bin/jupyter-lab"
|
||||||
;;
|
;;
|
||||||
pipx)
|
pipx)
|
||||||
pipx install jupyterlab &&
|
pipx install jupyterlab \
|
||||||
printf "%s\n" "🥳 jupyterlab has been installed"
|
&& printf "%s\n" "🥳 jupyterlab has been installed"
|
||||||
JUPYTER="$HOME/.local/bin/jupyter-lab"
|
JUPYTER="$HOME/.local/bin/jupyter-lab"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
printf "%s\n\n" "🥳 jupyterlab is already installed"
|
printf "%s\n\n" "🥳 jupyterlab is already installed"
|
||||||
@@ -55,4 +55,4 @@ $JUPYTER --no-browser \
|
|||||||
--ServerApp.port="${PORT}" \
|
--ServerApp.port="${PORT}" \
|
||||||
--ServerApp.token='' \
|
--ServerApp.token='' \
|
||||||
--ServerApp.password='' \
|
--ServerApp.password='' \
|
||||||
>"${LOG_PATH}" 2>&1 &
|
> "${LOG_PATH}" 2>&1 &
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Path-Sharing Bounce Page</title>
|
<title>Path-Sharing Bounce Page</title>
|
||||||
@@ -6,40 +6,64 @@
|
|||||||
:root {
|
:root {
|
||||||
color-scheme: light dark;
|
color-scheme: light dark;
|
||||||
--dark: #121212;
|
--dark: #121212;
|
||||||
--header-bg: rgba(127,127,127,0.2);
|
--header-bg: rgba(127, 127, 127, 0.2);
|
||||||
--light: white;
|
--light: white;
|
||||||
--rule-color: light-dark(rgba(0,0,0,0.8), rgba(255,255,255,0.8));
|
--rule-color: light-dark(rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0.8));
|
||||||
background-color: light-dark(var(--light), var(--dark));
|
background-color: light-dark(var(--light), var(--dark));
|
||||||
color: light-dark(var(--dark), var(--light));
|
color: light-dark(var(--dark), var(--light));
|
||||||
}
|
}
|
||||||
body, h1, p {
|
body,
|
||||||
|
h1,
|
||||||
|
p {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin:0; padding:0;
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
body{
|
body {
|
||||||
font-family:Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
font-family:
|
||||||
|
Inter,
|
||||||
|
system-ui,
|
||||||
|
-apple-system,
|
||||||
|
BlinkMacSystemFont,
|
||||||
|
"Segoe UI",
|
||||||
|
Roboto,
|
||||||
|
Oxygen,
|
||||||
|
Ubuntu,
|
||||||
|
Cantarell,
|
||||||
|
"Open Sans",
|
||||||
|
"Helvetica Neue",
|
||||||
|
sans-serif;
|
||||||
}
|
}
|
||||||
h1{
|
h1 {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
letter-spacing: -1.5pt;
|
letter-spacing: -1.5pt;
|
||||||
padding-bottom:10px;
|
padding-bottom: 10px;
|
||||||
border-bottom: 1px solid var(--rule-color);
|
border-bottom: 1px solid var(--rule-color);
|
||||||
background-color: var(--header-bg);
|
background-color: var(--header-bg);
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
padding: 1rem; letter-spacing: -0.5pt;}
|
padding: 1rem;
|
||||||
a.indent { display:inline-block; padding-top:0.5rem; padding-left: 2rem; font-size:0.8rem }
|
letter-spacing: -0.5pt;
|
||||||
</style>
|
}
|
||||||
|
a.indent {
|
||||||
|
display: inline-block;
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
padding-left: 2rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Path-Sharing Bounce Page</h1>
|
<h1>Path-Sharing Bounce Page</h1>
|
||||||
<p>
|
<p>
|
||||||
This application is being served via path sharing.
|
This application is being served via path sharing. If you are not
|
||||||
If you are not redirected, <span id="help">check the
|
redirected,
|
||||||
Javascript console in your browser's developer tools
|
<span id="help"
|
||||||
for more information.</span>
|
>check the Javascript console in your browser's developer tools for more
|
||||||
|
information.</span
|
||||||
|
>
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
<script language="javascript">
|
<script language="javascript">
|
||||||
@@ -58,24 +82,30 @@
|
|||||||
// This apparently doesn't tolerate a leading `/` so we use a
|
// This apparently doesn't tolerate a leading `/` so we use a
|
||||||
// function to tidy that up.
|
// function to tidy that up.
|
||||||
function trimFirstCharIf(str, char) {
|
function trimFirstCharIf(str, char) {
|
||||||
return str.charAt(0) === char ? str.slice(1) : str;
|
return str.charAt(0) === char ? str.slice(1) : str;
|
||||||
}
|
}
|
||||||
function trimLastCharIf(str, char) {
|
function trimLastCharIf(str, char) {
|
||||||
return str.endsWith("/") ? str.slice(0,str.length-1) : str;
|
return str.endsWith("/") ? str.slice(0, str.length - 1) : str;
|
||||||
}
|
}
|
||||||
const newloc = new URL(window.location);
|
const newloc = new URL(window.location);
|
||||||
const h = document.getElementById("help")
|
const h = document.getElementById("help");
|
||||||
|
|
||||||
// Building the websockify path must happen before we append the filename to newloc.pathname
|
// Building the websockify path must happen before we append the filename to newloc.pathname
|
||||||
newloc.searchParams.append("path",
|
newloc.searchParams.append(
|
||||||
trimLastCharIf(trimFirstCharIf(newloc.pathname,"/"),"/")+"/websockify");
|
"path",
|
||||||
newloc.searchParams.append("encrypted", newloc.protocol==="https:"? true : false);
|
trimLastCharIf(trimFirstCharIf(newloc.pathname, "/"), "/") +
|
||||||
|
"/websockify",
|
||||||
|
);
|
||||||
|
newloc.searchParams.append(
|
||||||
|
"encrypted",
|
||||||
|
newloc.protocol === "https:" ? true : false,
|
||||||
|
);
|
||||||
|
|
||||||
newloc.pathname += "vnc.html"
|
newloc.pathname += "vnc.html";
|
||||||
console.log(newloc);
|
console.log(newloc);
|
||||||
|
|
||||||
h.innerHTML = `click <a id="link" href="${newloc.toString()}">here</a> to go to the application.
|
h.innerHTML = `click <a id="link" href="${newloc.toString()}">here</a> to go to the application.
|
||||||
<br/><br/>The rewritten URL is:<br/><a id="link" class="indent" href="${newloc.toString()}">${newloc.toString()}</a>`
|
<br/><br/>The rewritten URL is:<br/><a id="link" class="indent" href="${newloc.toString()}">${newloc.toString()}</a>`;
|
||||||
window.location = newloc.href;
|
window.location = newloc.href;
|
||||||
</script>
|
</script>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
# Exit on error, undefined variables, and pipe failures
|
# Exit on error, undefined variables, and pipe failures
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
error() { printf "💀 ERROR: %s\n" "$@"; exit 1; }
|
error() {
|
||||||
|
printf "💀 ERROR: %s\n" "$@"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
# Function to check if vncserver is already installed
|
# Function to check if vncserver is already installed
|
||||||
check_installed() {
|
check_installed() {
|
||||||
@@ -248,30 +251,30 @@ get_http_dir() {
|
|||||||
echo $httpd_directory
|
echo $httpd_directory
|
||||||
}
|
}
|
||||||
|
|
||||||
fix_server_index_file(){
|
fix_server_index_file() {
|
||||||
local fname=$${FUNCNAME[0]} # gets current function name
|
local fname=$${FUNCNAME[0]} # gets current function name
|
||||||
if [[ $# -ne 1 ]]; then
|
if [[ $# -ne 1 ]]; then
|
||||||
error "$fname requires exactly 1 parameter:\n\tpath to KasmVNC httpd_directory"
|
error "$fname requires exactly 1 parameter:\n\tpath to KasmVNC httpd_directory"
|
||||||
fi
|
fi
|
||||||
local httpdir="$1"
|
local httpdir="$1"
|
||||||
if [[ ! -d "$httpdir" ]]; then
|
if [[ ! -d "$httpdir" ]]; then
|
||||||
error "$fname: $httpdir is not a directory"
|
error "$fname: $httpdir is not a directory"
|
||||||
fi
|
fi
|
||||||
pushd "$httpdir" > /dev/null
|
pushd "$httpdir" > /dev/null
|
||||||
|
|
||||||
cat <<'EOH' > /tmp/path_vnc.html
|
cat << 'EOH' > /tmp/path_vnc.html
|
||||||
${PATH_VNC_HTML}
|
${PATH_VNC_HTML}
|
||||||
EOH
|
EOH
|
||||||
$SUDO mv /tmp/path_vnc.html .
|
$SUDO mv /tmp/path_vnc.html .
|
||||||
# check for the switcheroo
|
# check for the switcheroo
|
||||||
if [[ -f "index.html" && -L "vnc.html" ]]; then
|
if [[ -f "index.html" && -L "vnc.html" ]]; then
|
||||||
$SUDO mv $httpdir/index.html $httpdir/vnc.html
|
$SUDO mv $httpdir/index.html $httpdir/vnc.html
|
||||||
fi
|
fi
|
||||||
$SUDO ln -s -f path_vnc.html index.html
|
$SUDO ln -s -f path_vnc.html index.html
|
||||||
popd > /dev/null
|
popd > /dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
patch_kasm_http_files(){
|
patch_kasm_http_files() {
|
||||||
homedir=$(get_http_dir)
|
homedir=$(get_http_dir)
|
||||||
fix_server_index_file "$homedir"
|
fix_server_index_file "$homedir"
|
||||||
}
|
}
|
||||||
@@ -292,7 +295,7 @@ set -e
|
|||||||
|
|
||||||
if [[ $RETVAL -ne 0 ]]; then
|
if [[ $RETVAL -ne 0 ]]; then
|
||||||
echo "ERROR: Failed to start KasmVNC server. Return code: $RETVAL"
|
echo "ERROR: Failed to start KasmVNC server. Return code: $RETVAL"
|
||||||
if [[ -f "$VNC_LOG" ]]; then
|
if [[ -f "$VNC_LOG" ]]; then
|
||||||
echo "Full logs:"
|
echo "Full logs:"
|
||||||
cat "$VNC_LOG"
|
cat "$VNC_LOG"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ describe("kiro", async () => {
|
|||||||
slug: "kiro-ai",
|
slug: "kiro-ai",
|
||||||
display_name: "Kiro AI IDE",
|
display_name: "Kiro AI IDE",
|
||||||
});
|
});
|
||||||
|
|
||||||
const coder_app = state.resources.find(
|
const coder_app = state.resources.find(
|
||||||
(res) => res.type === "coder_app" && res.name === "kiro",
|
(res) => res.type === "coder_app" && res.name === "kiro",
|
||||||
);
|
);
|
||||||
@@ -70,7 +70,7 @@ describe("kiro", async () => {
|
|||||||
agent_id: "foo",
|
agent_id: "foo",
|
||||||
order: "5",
|
order: "5",
|
||||||
});
|
});
|
||||||
|
|
||||||
const coder_app = state.resources.find(
|
const coder_app = state.resources.find(
|
||||||
(res) => res.type === "coder_app" && res.name === "kiro",
|
(res) => res.type === "coder_app" && res.name === "kiro",
|
||||||
);
|
);
|
||||||
@@ -83,7 +83,7 @@ describe("kiro", async () => {
|
|||||||
agent_id: "foo",
|
agent_id: "foo",
|
||||||
group: "AI IDEs",
|
group: "AI IDEs",
|
||||||
});
|
});
|
||||||
|
|
||||||
const coder_app = state.resources.find(
|
const coder_app = state.resources.find(
|
||||||
(res) => res.type === "coder_app" && res.name === "kiro",
|
(res) => res.type === "coder_app" && res.name === "kiro",
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ CODER_OIDC_ACCESS_TOKEN=${CODER_OIDC_ACCESS_TOKEN}
|
|||||||
fetch() {
|
fetch() {
|
||||||
dest="$1"
|
dest="$1"
|
||||||
url="$2"
|
url="$2"
|
||||||
if command -v curl >/dev/null 2>&1; then
|
if command -v curl > /dev/null 2>&1; then
|
||||||
curl -sSL --fail "$${url}" -o "$${dest}"
|
curl -sSL --fail "$${url}" -o "$${dest}"
|
||||||
elif command -v wget >/dev/null 2>&1; then
|
elif command -v wget > /dev/null 2>&1; then
|
||||||
wget -O "$${dest}" "$${url}"
|
wget -O "$${dest}" "$${url}"
|
||||||
elif command -v busybox >/dev/null 2>&1; then
|
elif command -v busybox > /dev/null 2>&1; then
|
||||||
busybox wget -O "$${dest}" "$${url}"
|
busybox wget -O "$${dest}" "$${url}"
|
||||||
else
|
else
|
||||||
printf "curl, wget, or busybox is not installed. Please install curl or wget in your image.\n"
|
printf "curl, wget, or busybox is not installed. Please install curl or wget in your image.\n"
|
||||||
@@ -22,9 +22,9 @@ fetch() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unzip_safe() {
|
unzip_safe() {
|
||||||
if command -v unzip >/dev/null 2>&1; then
|
if command -v unzip > /dev/null 2>&1; then
|
||||||
command unzip "$@"
|
command unzip "$@"
|
||||||
elif command -v busybox >/dev/null 2>&1; then
|
elif command -v busybox > /dev/null 2>&1; then
|
||||||
busybox unzip "$@"
|
busybox unzip "$@"
|
||||||
else
|
else
|
||||||
printf "unzip or busybox is not installed. Please install unzip in your image.\n"
|
printf "unzip or busybox is not installed. Please install unzip in your image.\n"
|
||||||
@@ -56,7 +56,7 @@ install() {
|
|||||||
|
|
||||||
# Check if the vault CLI is installed and has the correct version
|
# Check if the vault CLI is installed and has the correct version
|
||||||
installation_needed=1
|
installation_needed=1
|
||||||
if command -v vault >/dev/null 2>&1; then
|
if command -v vault > /dev/null 2>&1; then
|
||||||
CURRENT_VERSION=$(vault version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
|
CURRENT_VERSION=$(vault version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
|
||||||
if [ "$${CURRENT_VERSION}" = "$${VAULT_CLI_VERSION}" ]; then
|
if [ "$${CURRENT_VERSION}" = "$${VAULT_CLI_VERSION}" ]; then
|
||||||
printf "Vault version %s is already installed and up-to-date.\n\n" "$${CURRENT_VERSION}"
|
printf "Vault version %s is already installed and up-to-date.\n\n" "$${CURRENT_VERSION}"
|
||||||
@@ -81,7 +81,7 @@ install() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
rm vault.zip
|
rm vault.zip
|
||||||
if sudo mv vault /usr/local/bin/vault 2>/dev/null; then
|
if sudo mv vault /usr/local/bin/vault 2> /dev/null; then
|
||||||
printf "Vault installed successfully!\n\n"
|
printf "Vault installed successfully!\n\n"
|
||||||
else
|
else
|
||||||
mkdir -p ~/.local/bin
|
mkdir -p ~/.local/bin
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const defaultVariables = {
|
|||||||
coder_app_slug: "vscode",
|
coder_app_slug: "vscode",
|
||||||
coder_app_display_name: "VS Code Desktop",
|
coder_app_display_name: "VS Code Desktop",
|
||||||
protocol: "vscode",
|
protocol: "vscode",
|
||||||
}
|
};
|
||||||
|
|
||||||
describe("vscode-desktop-core", async () => {
|
describe("vscode-desktop-core", async () => {
|
||||||
await runTerraformInit(import.meta.dir);
|
await runTerraformInit(import.meta.dir);
|
||||||
@@ -40,7 +40,7 @@ describe("vscode-desktop-core", async () => {
|
|||||||
const state = await runTerraformApply(import.meta.dir, {
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
folder: "/foo/bar",
|
folder: "/foo/bar",
|
||||||
|
|
||||||
...defaultVariables
|
...defaultVariables,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(state.outputs.ide_uri.value).toBe(
|
expect(state.outputs.ide_uri.value).toBe(
|
||||||
@@ -86,7 +86,7 @@ describe("vscode-desktop-core", async () => {
|
|||||||
it("expect order to be set", async () => {
|
it("expect order to be set", async () => {
|
||||||
const state = await runTerraformApply(import.meta.dir, {
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
coder_app_order: "22",
|
coder_app_order: "22",
|
||||||
...defaultVariables
|
...defaultVariables,
|
||||||
});
|
});
|
||||||
|
|
||||||
const coder_app = state.resources.find(
|
const coder_app = state.resources.find(
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ esac
|
|||||||
# Detect the platform
|
# Detect the platform
|
||||||
if [ -n "${PLATFORM}" ]; then
|
if [ -n "${PLATFORM}" ]; then
|
||||||
DETECTED_PLATFORM="${PLATFORM}"
|
DETECTED_PLATFORM="${PLATFORM}"
|
||||||
elif [ -f /etc/alpine-release ] || grep -qi 'ID=alpine' /etc/os-release 2>/dev/null || command -v apk > /dev/null 2>&1; then
|
elif [ -f /etc/alpine-release ] || grep -qi 'ID=alpine' /etc/os-release 2> /dev/null || command -v apk > /dev/null 2>&1; then
|
||||||
DETECTED_PLATFORM="alpine"
|
DETECTED_PLATFORM="alpine"
|
||||||
elif [ "$(uname -s)" = "Darwin" ]; then
|
elif [ "$(uname -s)" = "Darwin" ]; then
|
||||||
DETECTED_PLATFORM="darwin"
|
DETECTED_PLATFORM="darwin"
|
||||||
|
|||||||
@@ -18,27 +18,33 @@ describe("aws-ami-snapshot", async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("missing variable: instance_id", async () => {
|
it("missing variable: instance_id", async () => {
|
||||||
await expect(runTerraformApply(import.meta.dir, {
|
await expect(
|
||||||
default_ami_id: "ami-12345678",
|
runTerraformApply(import.meta.dir, {
|
||||||
template_name: "test-template",
|
default_ami_id: "ami-12345678",
|
||||||
test_mode: true,
|
template_name: "test-template",
|
||||||
})).rejects.toThrow();
|
test_mode: true,
|
||||||
|
}),
|
||||||
|
).rejects.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("missing variable: default_ami_id", async () => {
|
it("missing variable: default_ami_id", async () => {
|
||||||
await expect(runTerraformApply(import.meta.dir, {
|
await expect(
|
||||||
instance_id: "i-1234567890abcdef0",
|
runTerraformApply(import.meta.dir, {
|
||||||
template_name: "test-template",
|
instance_id: "i-1234567890abcdef0",
|
||||||
test_mode: true,
|
template_name: "test-template",
|
||||||
})).rejects.toThrow();
|
test_mode: true,
|
||||||
|
}),
|
||||||
|
).rejects.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("missing variable: template_name", async () => {
|
it("missing variable: template_name", async () => {
|
||||||
await expect(runTerraformApply(import.meta.dir, {
|
await expect(
|
||||||
instance_id: "i-1234567890abcdef0",
|
runTerraformApply(import.meta.dir, {
|
||||||
default_ami_id: "ami-12345678",
|
instance_id: "i-1234567890abcdef0",
|
||||||
test_mode: true,
|
default_ami_id: "ami-12345678",
|
||||||
})).rejects.toThrow();
|
test_mode: true,
|
||||||
|
}),
|
||||||
|
).rejects.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("supports optional variables", async () => {
|
it("supports optional variables", async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user