Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions system_files/shared/usr/share/ublue-os/goose/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Bluefin default Goose configuration.
extensions:
linux-mcp-server:
args: []
bundled: false
cmd: linux-mcp-server
enabled: true
envs: {}
name: linux-mcp-server
timeout: 300
type: stdio
21 changes: 21 additions & 0 deletions system_files/shared/usr/share/ublue-os/just/apps.just
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,27 @@ cncf:
brew bundle --file=/usr/share/ublue-os/homebrew/cncf.Brewfile
[[ -t 0 ]] && ujust --choose || true

# Install Goose and configure the read-only Linux diagnostics MCP server.
[group('Apps')]
install-ai-tools:
#!/usr/bin/env bash
set -euo pipefail
brew bundle --file=/usr/share/ublue-os/homebrew/ai-tools.Brewfile

CONFIG_DIR="${XDG_CONFIG_HOME:-${HOME}/.config}/goose"
CONFIG_FILE="${CONFIG_DIR}/config.yaml"
TEMPLATE="${GOOSE_TEMPLATE:-/usr/share/ublue-os/goose/config.yaml}"
mkdir -p "${CONFIG_DIR}"

if [[ -e "${CONFIG_FILE}" ]]; then
echo "Goose config already exists: ${CONFIG_FILE}"
echo "Review ${TEMPLATE} and merge its linux-mcp-server extension if needed."
exit 0
fi

install -m0644 "${TEMPLATE}" "${CONFIG_FILE}"
echo "Goose configured with read-only Linux diagnostics."

# Install ASUS laptop tools (asusctl daemon + ROG Control Center) | https://gitlab.com/asus-linux/asusctl
[group('Apps')]
install-asus:
Expand Down
117 changes: 117 additions & 0 deletions tests/test_ujust.bats
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,120 @@ EOF
[ "${status}" -ne 0 ]
[ "$(grep -cF "just" "${WORKDIR}/calls.log" || true)" -eq 0 ]
}

# ---------------------------------------------------------------------------
# apps.just: install-ai-tools recipe tests
# ---------------------------------------------------------------------------

APPS_JUST="$BATS_TEST_DIRNAME/../system_files/shared/usr/share/ublue-os/just/apps.just"

_extract_apps_recipe() {
local recipe="$1" out_file="$2"
awk -v recipe="$recipe" '
$0 ~ ("^" recipe "([[:space:]].*)?:$") { in_recipe=1; next }
in_recipe && /^[[:space:]]+#!\/usr\/bin\/env bash/ { found=1; next }
found && /^[^[:space:]]/ { exit }
found { sub(/^[[:space:]]{4}/, ""); print }
' "${APPS_JUST}" > "${out_file}"
}

@test "apps.just: install-ai-tools installs brew bundle and creates goose config on fresh setup" {
local script="${WORKDIR}/install-ai-tools.sh"
_extract_apps_recipe "install-ai-tools" "${script}"

local mock_template="${WORKDIR}/mock-goose-config.yaml"
echo "mock-template-data" > "${mock_template}"

local test_home="${WORKDIR}/test-user-home"
mkdir -p "${test_home}"

run env \
PATH="${WORKDIR}/bin:${PATH}" \
CALLS="${WORKDIR}/calls.log" \
HOME="${test_home}" \
GOOSE_TEMPLATE="${mock_template}" \
bash "${script}"

[ "${status}" -eq 0 ]
grep -qF "brew bundle --file=/usr/share/ublue-os/homebrew/ai-tools.Brewfile" "${WORKDIR}/calls.log"
[ -f "${test_home}/.config/goose/config.yaml" ]
[ "$(< "${test_home}/.config/goose/config.yaml")" = "mock-template-data" ]
[[ "${output}" == *"Goose configured with read-only Linux diagnostics."* ]]
}

@test "apps.just: install-ai-tools respects XDG_CONFIG_HOME on fresh setup" {
local script="${WORKDIR}/install-ai-tools.sh"
_extract_apps_recipe "install-ai-tools" "${script}"

local mock_template="${WORKDIR}/mock-goose-config.yaml"
echo "mock-template-data" > "${mock_template}"

local test_home="${WORKDIR}/test-user-home"
local custom_xdg="${WORKDIR}/custom-xdg"
mkdir -p "${test_home}" "${custom_xdg}"

run env \
PATH="${WORKDIR}/bin:${PATH}" \
CALLS="${WORKDIR}/calls.log" \
HOME="${test_home}" \
XDG_CONFIG_HOME="${custom_xdg}" \
GOOSE_TEMPLATE="${mock_template}" \
bash "${script}"

[ "${status}" -eq 0 ]
[ -f "${custom_xdg}/goose/config.yaml" ]
[ ! -e "${test_home}/.config/goose/config.yaml" ]
[ "$(< "${custom_xdg}/goose/config.yaml")" = "mock-template-data" ]
}

@test "apps.just: install-ai-tools preserves existing goose config and does not overwrite" {
local script="${WORKDIR}/install-ai-tools.sh"
_extract_apps_recipe "install-ai-tools" "${script}"

local mock_template="${WORKDIR}/mock-goose-config.yaml"
echo "mock-template-data" > "${mock_template}"

local test_home="${WORKDIR}/test-user-home"
mkdir -p "${test_home}/.config/goose"
echo "existing-custom-config" > "${test_home}/.config/goose/config.yaml"

run env \
PATH="${WORKDIR}/bin:${PATH}" \
CALLS="${WORKDIR}/calls.log" \
HOME="${test_home}" \
GOOSE_TEMPLATE="${mock_template}" \
bash "${script}"

[ "${status}" -eq 0 ]
grep -qF "brew bundle --file=/usr/share/ublue-os/homebrew/ai-tools.Brewfile" "${WORKDIR}/calls.log"
[ -f "${test_home}/.config/goose/config.yaml" ]
[ "$(< "${test_home}/.config/goose/config.yaml")" = "existing-custom-config" ]
[[ "${output}" == *"Goose config already exists: ${test_home}/.config/goose/config.yaml"* ]]
[[ "${output}" == *"Review "* ]]
[[ "${output}" == *"and merge its linux-mcp-server extension if needed."* ]]
[[ "${output}" != *"Goose configured with read-only Linux diagnostics."* ]]
}

@test "apps.just: install-ai-tools preserves existing config under XDG_CONFIG_HOME" {
local script="${WORKDIR}/install-ai-tools.sh"
_extract_apps_recipe "install-ai-tools" "${script}"

local mock_template="${WORKDIR}/mock-goose-config.yaml"
echo "mock-template-data" > "${mock_template}"

local custom_xdg="${WORKDIR}/custom-xdg"
mkdir -p "${custom_xdg}/goose"
echo "existing-xdg-config" > "${custom_xdg}/goose/config.yaml"

run env \
PATH="${WORKDIR}/bin:${PATH}" \
CALLS="${WORKDIR}/calls.log" \
XDG_CONFIG_HOME="${custom_xdg}" \
GOOSE_TEMPLATE="${mock_template}" \
bash "${script}"

[ "${status}" -eq 0 ]
[ -f "${custom_xdg}/goose/config.yaml" ]
[ "$(< "${custom_xdg}/goose/config.yaml")" = "existing-xdg-config" ]
[[ "${output}" == *"Goose config already exists: ${custom_xdg}/goose/config.yaml"* ]]
}
Loading