chore: import upstream snapshot with attribution
CI: cua-driver distro-compat matrix / debian:12 (glibc 2.36) (push) Has been cancelled
CI: SPDX Headers / Check SPDX headers (warn-only) (push) Has been cancelled
CD: Docs MCP Server / build (linux/amd64) (push) Has been cancelled
CD: Docs MCP Server / build (linux/arm64) (push) Has been cancelled
CD: Docs MCP Server / merge (push) Has been cancelled
CI: cua-driver distro-compat matrix / Resolve release version (push) Has been cancelled
CI: cua-driver distro-compat matrix / fedora:41 (glibc 2.40) (push) Has been cancelled
CI: cua-driver distro-compat matrix / rockylinux:9 (glibc 2.34) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:22.04 (glibc 2.35) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:24.04 (glibc 2.39) (push) Has been cancelled
CI: cua-driver distro-compat matrix / Distro compat summary (push) Has been cancelled
CI: Rust Linux unit / Rust Linux unit and compile (push) Has been cancelled
CI: Rust Windows unit / Rust Windows unit and compile (push) Has been cancelled
CI: Nix Linux Rust source / Nix / compositor build (push) Has been cancelled
CI: Nix Linux Rust source / Nix / driver package (push) Has been cancelled
CI: Nix Linux Rust source / Nix / Rust unit tests (push) Has been cancelled
@@ -0,0 +1,101 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Extract PostgreSQL metadata
|
||||
|
||||
# Find main binary
|
||||
binary_path=$(which psql)
|
||||
binary_name=$(basename "$binary_path")
|
||||
|
||||
# Get version - extract version number from psql --version
|
||||
version=$(psql --version 2>/dev/null | grep -oP '\) \K[0-9]+\.[0-9]+')
|
||||
|
||||
# Find desktop entry - search dynamically in /usr/share/applications
|
||||
desktop_entry=""
|
||||
display_name="PostgreSQL"
|
||||
|
||||
# Search for any .desktop file that contains postgres, postgresql, or psql
|
||||
if [ -d "/usr/share/applications" ]; then
|
||||
# Use find with grep to search for postgres-related desktop files
|
||||
while IFS= read -r desktop_file; do
|
||||
if [ -f "$desktop_file" ]; then
|
||||
desktop_entry="$desktop_file"
|
||||
# Extract display name from the desktop file
|
||||
extracted_name=$(grep "^Name=" "$desktop_file" 2>/dev/null | head -1 | cut -d= -f2)
|
||||
if [ -n "$extracted_name" ]; then
|
||||
display_name="$extracted_name"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done < <(find /usr/share/applications -name "*.desktop" -exec grep -l "postgres\|postgresql\|psql\|database" {} \; 2>/dev/null)
|
||||
fi
|
||||
|
||||
# If no desktop file found, try to extract package description as fallback
|
||||
if [ -z "$desktop_entry" ]; then
|
||||
pkg_desc=$(dpkg -s postgresql 2>/dev/null | grep "^Description:" | head -1 | cut -d: -f2-)
|
||||
if [ -n "$pkg_desc" ]; then
|
||||
display_name="PostgreSQL$pkg_desc"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Find icon paths - look for PostgreSQL icons
|
||||
icon_paths=()
|
||||
|
||||
# Check standard icon directories
|
||||
for dir in /usr/share/icons /usr/share/pixmaps; do
|
||||
if [ -d "$dir" ]; then
|
||||
while IFS= read -r icon_file; do
|
||||
if [ -f "$icon_file" ]; then
|
||||
icon_paths+=("$icon_file")
|
||||
fi
|
||||
done < <(find "$dir" -type f \( -name "*postgres*" -o -name "*sql*" \) 2>/dev/null | head -10)
|
||||
fi
|
||||
done
|
||||
|
||||
# If no specific icons found, try looking for the default PostgreSQL icon
|
||||
if [ ${#icon_paths[@]} -eq 0 ]; then
|
||||
# Check common locations
|
||||
test -f "/usr/share/pixmaps/postgresql.xpm" && icon_paths+=("/usr/share/pixmaps/postgresql.xpm")
|
||||
test -f "/usr/share/pixmaps/postgresql.png" && icon_paths+=("/usr/share/pixmaps/postgresql.png")
|
||||
fi
|
||||
|
||||
# Also try to extract icon from desktop file if it exists
|
||||
if [ -n "$desktop_entry" ] && [ -f "$desktop_entry" ]; then
|
||||
desktop_icon=$(grep "^Icon=" "$desktop_entry" 2>/dev/null | head -1 | cut -d= -f2)
|
||||
if [ -n "$desktop_icon" ]; then
|
||||
# Try to locate the icon file
|
||||
for dir in /usr/share/icons /usr/share/pixmaps; do
|
||||
if [ -d "$dir" ]; then
|
||||
found_icon=$(find "$dir" -name "$desktop_icon*" 2>/dev/null | head -1)
|
||||
if [ -f "$found_icon" ]; then
|
||||
# Check if already in list
|
||||
if [[ ! " ${icon_paths[@]} " =~ " ${found_icon} " ]]; then
|
||||
icon_paths+=("$found_icon")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# Output as JSON
|
||||
printf '{\n'
|
||||
printf ' "binary_path": "%s",\n' "$binary_path"
|
||||
printf ' "binary_name": "%s",\n' "$binary_name"
|
||||
printf ' "display_name": "%s",\n' "$display_name"
|
||||
printf ' "desktop_entry": "%s",\n' "$desktop_entry"
|
||||
printf ' "icon_paths": [\n'
|
||||
|
||||
# Add icon paths to JSON
|
||||
first=true
|
||||
for icon in "${icon_paths[@]}"; do
|
||||
if [ "$first" = true ]; then
|
||||
printf ' "%s"\n' "$icon"
|
||||
first=false
|
||||
else
|
||||
printf ' ,"%s"\n' "$icon"
|
||||
fi
|
||||
done
|
||||
|
||||
printf ' ],\n'
|
||||
printf ' "version": "%s"\n' "$version"
|
||||
printf '}\n'
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "Installing PostgreSQL..."
|
||||
|
||||
# Update package list
|
||||
sudo apt-get update
|
||||
|
||||
# Install PostgreSQL (latest version from distribution repos)
|
||||
# This will install postgresql and postgresql-contrib
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql postgresql-contrib
|
||||
|
||||
echo "PostgreSQL installed successfully!"
|
||||
|
||||
# Verify installation
|
||||
psql --version
|
||||
|
||||
echo "Installation complete!"
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Starting PostgreSQL server..."
|
||||
|
||||
# Start PostgreSQL as the postgres user
|
||||
sudo -u postgres /usr/lib/postgresql/14/bin/pg_ctl -D /var/lib/postgresql/14/main -l /var/log/postgresql/postgresql-14-main.log start
|
||||
|
||||
# Wait for the service to be ready
|
||||
sleep 2
|
||||
|
||||
# Check if the server is running
|
||||
if sudo -u postgres /usr/lib/postgresql/14/bin/pg_isready -h localhost > /dev/null 2>&1; then
|
||||
echo "✓ PostgreSQL server started successfully"
|
||||
|
||||
# Show PostgreSQL version
|
||||
echo ""
|
||||
echo "PostgreSQL version:"
|
||||
psql --version
|
||||
|
||||
echo ""
|
||||
echo "Server is accepting connections on localhost:5432"
|
||||
|
||||
# Show server info from the database
|
||||
echo ""
|
||||
echo "Database cluster information:"
|
||||
sudo -u postgres psql -c "SELECT version();" 2>/dev/null
|
||||
|
||||
else
|
||||
echo "PostgreSQL server is starting..."
|
||||
sleep 1
|
||||
if sudo -u postgres /usr/lib/postgresql/14/bin/pg_isready -h localhost > /dev/null 2>&1; then
|
||||
echo "✓ PostgreSQL server is now ready"
|
||||
else
|
||||
echo "⚠ PostgreSQL server startup in progress"
|
||||
fi
|
||||
fi
|
||||
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 645 B |
|
After Width: | Height: | Size: 944 B |
|
After Width: | Height: | Size: 1011 B |
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg id="svg2476" width="48" height="48" version="1.0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs id="defs2478">
|
||||
<linearGradient id="linearGradient2507" x1="302.86" x2="302.86" y1="366.65" y2="609.51" gradientTransform="matrix(.067325 0 0 .0147 -.34114 37.04)" gradientUnits="userSpaceOnUse">
|
||||
<stop id="stop5050" style="stop-opacity:0" offset="0"/>
|
||||
<stop id="stop5056" offset=".5"/>
|
||||
<stop id="stop5052" style="stop-opacity:0" offset="1"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="radialGradient2504" cx="605.71" cy="486.65" r="117.14" gradientTransform="matrix(-.02304 0 0 .0147 21.623 37.04)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient5060"/>
|
||||
<linearGradient id="linearGradient5060">
|
||||
<stop id="stop5062" offset="0"/>
|
||||
<stop id="stop5064" style="stop-opacity:0" offset="1"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="radialGradient2501" cx="605.71" cy="486.65" r="117.14" gradientTransform="matrix(.02304 0 0 .0147 26.361 37.04)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient5060"/>
|
||||
<linearGradient id="linearGradient2498" x1="-51.786" x2="-51.786" y1="50.786" y2="2.9062" gradientTransform="matrix(.8075 0 0 .89483 59.41 -2.9806)" gradientUnits="userSpaceOnUse">
|
||||
<stop id="stop3106" style="stop-color:#aaa" offset="0"/>
|
||||
<stop id="stop3108" style="stop-color:#c8c8c8" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient2496" x1="25.132" x2="25.132" y1=".98521" y2="47.013" gradientTransform="matrix(1 0 0 .95617 -1.0065e-7 -1.9149)" gradientUnits="userSpaceOnUse">
|
||||
<stop id="stop3602" style="stop-color:#f4f4f4" offset="0"/>
|
||||
<stop id="stop3604" style="stop-color:#dbdbdb" offset="1"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="radialGradient2493" cx="102" cy="112.3" r="139.56" gradientTransform="matrix(.3617 0 0 -.39078 .85106 47.517)" gradientUnits="userSpaceOnUse">
|
||||
<stop id="stop41" style="stop-color:#b7b8b9" offset="0"/>
|
||||
<stop id="stop47" style="stop-color:#ececec" offset=".18851"/>
|
||||
<stop id="stop49" style="stop-color:#fafafa;stop-opacity:0" offset=".25718"/>
|
||||
<stop id="stop51" style="stop-color:#fff;stop-opacity:0" offset=".30111"/>
|
||||
<stop id="stop53" style="stop-color:#fafafa;stop-opacity:0" offset=".5313"/>
|
||||
<stop id="stop55" style="stop-color:#ebecec;stop-opacity:0" offset=".8449"/>
|
||||
<stop id="stop57" style="stop-color:#e1e2e3;stop-opacity:0" offset="1"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="radialGradient2490" cx="23.335" cy="41.636" r="22.627" gradientTransform="matrix(.57452 0 0 .22094 10.594 23.801)" gradientUnits="userSpaceOnUse">
|
||||
<stop id="stop23421" offset="0"/>
|
||||
<stop id="stop23423" style="stop-opacity:0" offset="1"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="linearGradient2487" x1="24" x2="24" y1="2" y2="46.017" gradientTransform="matrix(1 0 0 .97778 0 -.96667)" gradientUnits="userSpaceOnUse">
|
||||
<stop id="stop3213" style="stop-color:#fff" offset="0"/>
|
||||
<stop id="stop3215" style="stop-color:#fff;stop-opacity:0" offset="1"/>
|
||||
</linearGradient>
|
||||
<filter id="filter3212" x="-.14846" y="-.16434" width="1.2969" height="1.3287" color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur id="feGaussianBlur3214" stdDeviation="0.77391625"/>
|
||||
</filter>
|
||||
<linearGradient id="linearGradient2483" x1="32.892" x2="36.358" y1="8.059" y2="5.4565" gradientTransform="matrix(.9977 0 0 1.0407 .1638 -1.1058)" gradientUnits="userSpaceOnUse">
|
||||
<stop id="stop8591" style="stop-color:#fefefe" offset="0"/>
|
||||
<stop id="stop8593" style="stop-color:#cbcbcb" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient2479" x1="89.018" x2="89.018" y1="22.537" y2="27.546" gradientTransform="translate(-70.157 8.4539)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3858"/>
|
||||
<linearGradient id="linearGradient2477" x1="103.95" x2="89.424" y1="-7.6657" y2="-7.6657" gradientTransform="matrix(.45783 0 0 .43229 -23.592 36.912)" gradientUnits="userSpaceOnUse" spreadMethod="reflect" xlink:href="#linearGradient2793"/>
|
||||
<linearGradient id="linearGradient2473" x1="89.018" x2="89.018" y1="22.537" y2="27.546" gradientTransform="translate(-70.157 2.4539)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3858"/>
|
||||
<linearGradient id="linearGradient2471" x1="103.95" x2="89.424" y1="-7.6657" y2="-7.6657" gradientTransform="matrix(.45783 0 0 .43229 -23.592 30.912)" gradientUnits="userSpaceOnUse" spreadMethod="reflect" xlink:href="#linearGradient2793"/>
|
||||
<linearGradient id="linearGradient3858">
|
||||
<stop id="stop3860" style="stop-color:#a0a0a0" offset="0"/>
|
||||
<stop id="stop3862" style="stop-color:#4a4a4a" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient2466" x1="89.018" x2="89.018" y1="22.537" y2="27.546" gradientTransform="translate(-70.157 -3.5461)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3858"/>
|
||||
<linearGradient id="linearGradient2793">
|
||||
<stop id="stop2795" style="stop-color:#868688" offset="0"/>
|
||||
<stop id="stop2797" style="stop-color:#d9d9da" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient2463" x1="103.95" x2="89.424" y1="-7.6657" y2="-7.6657" gradientTransform="matrix(.45783 0 0 .43229 -23.592 24.912)" gradientUnits="userSpaceOnUse" spreadMethod="reflect" xlink:href="#linearGradient2793"/>
|
||||
<linearGradient id="linearGradient2460" x1="109.96" x2="109.96" y1="-24.911" y2="-2.3758" gradientTransform="matrix(.45813 0 0 .43889 -23.62 20.933)" gradientUnits="userSpaceOnUse">
|
||||
<stop id="stop2511" style="stop-color:#b3b3b3" offset="0"/>
|
||||
<stop id="stop2513" style="stop-color:#dadada" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient2458" x1="102.31" x2="102.31" y1="-2.3925" y2="-24.582" gradientTransform="matrix(.45813 0 0 .43889 -23.62 20.933)" gradientUnits="userSpaceOnUse" spreadMethod="reflect">
|
||||
<stop id="stop3846" style="stop-color:#a5a6a8" offset="0"/>
|
||||
<stop id="stop3848" style="stop-color:#e8e8e8" offset="1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="layer1">
|
||||
<rect id="rect2879" x="7.7378" y="42.43" width="32.508" height="3.5701" style="fill:url(#linearGradient2507);opacity:.3"/>
|
||||
<path id="path2881" d="m7.7378 42.43v3.5699c-1.1865 0.0067-2.8684-0.79982-2.8684-1.7852 0-0.98533 1.324-1.7847 2.8684-1.7847z" style="fill:url(#radialGradient2504);opacity:.3"/>
|
||||
<path id="path2883" d="m40.246 42.43v3.5699c1.1865 0.0067 2.8684-0.79982 2.8684-1.7852 0-0.98533-1.324-1.7847-2.8684-1.7847z" style="fill:url(#radialGradient2501);opacity:.3"/>
|
||||
<path id="path4160" d="m6.5 0.4972h24.061c1.4069 0.47465 8.9655 5.8822 10.939 9.6264v34.379h-35v-44.006z" style="fill:url(#linearGradient2496);stroke-linejoin:round;stroke-width:.99992;stroke:url(#linearGradient2498)"/>
|
||||
<path id="path4191" d="m7.3617 44c-0.1993 0-0.3617-0.17546-0.3617-0.39078v-42.204c0-0.21571 0.1624-0.39078 0.3617-0.39078 7.4831 0.10801 15.776-0.16158 23.25 0.026895l10.283 8.866 0.10598 33.702c0 0.21532-0.16204 0.39078-0.3617 0.39078h-33.277z" style="fill:url(#radialGradient2493)"/>
|
||||
<path id="path23417" d="m37 33c0.0011 2.7613-5.8195 5-13 5s-13.001-2.2387-13-5c-0.0011-2.7613 5.8195-5 13-5s13.001 2.2387 13 5z" style="fill-rule:evenodd;fill:url(#radialGradient2490);opacity:.3"/>
|
||||
<path id="path2435" d="m40.5 10.259v33.263h-33v-42.045h22.866" style="fill:none;opacity:.6;stroke-linejoin:round;stroke-width:.99992;stroke:url(#linearGradient2487)"/>
|
||||
<path id="path12038" d="m28.617 0.92126c4.2825 0 2.1532 8.4832 2.1532 8.4832s10.358-1.8023 10.358 2.8187c0-2.6097-11.302-10.729-12.511-11.302z" style="fill-rule:evenodd;filter:url(#filter3212);opacity:.4"/>
|
||||
<path id="path4474" d="m28.617 0.92126c3.1865 0 2.3358 7.6619 2.3358 7.6619s10.175-0.98105 10.175 3.64c0-1.1259 0.08591-1.9322-0.13378-2.2836-1.5783-2.5242-8.3955-8.1884-10.857-8.9308-0.18422-0.055555-0.5927-0.087535-1.5198-0.087535z" style="fill-rule:evenodd;fill:url(#linearGradient2483)"/>
|
||||
<path id="path4834" d="m35.49 31.068c0 2.4466-5.1487 4.4322-11.493 4.4322-6.344 0-11.493-1.9856-11.493-4.4322 0.11446-5.4694-1.4047-4.34 11.493-4.4322 13.193-0.0952 11.331-1.1267 11.493 4.4322z" style="fill:url(#linearGradient2477);stroke:url(#linearGradient2479)"/>
|
||||
<path id="path4838" d="m35.5 27c0 2.4853-5.1487 4.5-11.5 4.5-6.3513 0-11.5-2.0147-11.5-4.5 0-2.4853 5.1487-4.5 11.5-4.5 6.3513 0 11.5 2.0147 11.5 4.5z" style="fill:#868688;stroke:#d8d8d8"/>
|
||||
<path id="path3866" d="m35.49 25.068c0 2.4466-5.1487 4.4322-11.493 4.4322-6.344 0-11.493-1.9856-11.493-4.4322 0.11446-5.4694-1.4047-4.34 11.493-4.4322 13.193-0.0952 11.331-1.1267 11.493 4.4322z" style="fill:url(#linearGradient2471);stroke:url(#linearGradient2473)"/>
|
||||
<path id="path3868" d="m35.5 21c0 2.4853-5.1487 4.5-11.5 4.5-6.3513 0-11.5-2.0147-11.5-4.5 0-2.4853 5.1487-4.5 11.5-4.5 6.3513 0 11.5 2.0147 11.5 4.5z" style="fill:#868688;stroke:#d8d8d8"/>
|
||||
<path id="path3878" d="m35.49 19.068c0 2.4466-5.1487 4.4322-11.493 4.4322-6.344 0-11.493-1.9856-11.493-4.4322 0.11446-5.4694-1.4047-4.34 11.493-4.4322 13.193-0.0952 11.331-1.1267 11.493 4.4322z" style="fill:url(#linearGradient2463);stroke:url(#linearGradient2466)"/>
|
||||
<path id="path3880" d="m35.5 15c0 2.4853-5.1487 4.5-11.5 4.5-6.3513 0-11.5-2.0147-11.5-4.5 0-2.4853 5.1487-4.5 11.5-4.5 6.3513 0 11.5 2.0147 11.5 4.5z" style="fill:url(#linearGradient2458);stroke:url(#linearGradient2460)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 48 KiB |
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"app_id": "postgresql",
|
||||
"os": "linux",
|
||||
"install_exit_code": 0,
|
||||
"install_script": "#!/bin/bash\nset -e\n\necho \"Installing PostgreSQL...\"\n\n# Update package list\nsudo apt-get update\n\n# Install PostgreSQL (latest version from distribution repos)\n# This will install postgresql and postgresql-contrib\nsudo DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql postgresql-contrib\n\necho \"PostgreSQL installed successfully!\"\n\n# Verify installation\npsql --version\n\necho \"Installation complete!\"",
|
||||
"launch_script": "#!/bin/bash\n\necho \"Starting PostgreSQL server...\"\n\n# Start PostgreSQL as the postgres user\nsudo -u postgres /usr/lib/postgresql/14/bin/pg_ctl -D /var/lib/postgresql/14/main -l /var/log/postgresql/postgresql-14-main.log start\n\n# Wait for the service to be ready\nsleep 2\n\n# Check if the server is running\nif sudo -u postgres /usr/lib/postgresql/14/bin/pg_isready -h localhost > /dev/null 2>&1; then\n echo \"\u2713 PostgreSQL server started successfully\"\n \n # Show PostgreSQL version\n echo \"\"\n echo \"PostgreSQL version:\"\n psql --version\n \n echo \"\"\n echo \"Server is accepting connections on localhost:5432\"\n \n # Show server info from the database\n echo \"\"\n echo \"Database cluster information:\"\n sudo -u postgres psql -c \"SELECT version();\" 2>/dev/null\n \nelse\n echo \"PostgreSQL server is starting...\"\n sleep 1\n if sudo -u postgres /usr/lib/postgresql/14/bin/pg_isready -h localhost > /dev/null 2>&1; then\n echo \"\u2713 PostgreSQL server is now ready\"\n else\n echo \"\u26a0 PostgreSQL server startup in progress\"\n fi\nfi",
|
||||
"extract_metadata_script": "#!/bin/bash\n\n# Extract PostgreSQL metadata\n\n# Find main binary\nbinary_path=$(which psql)\nbinary_name=$(basename \"$binary_path\")\n\n# Get version - extract version number from psql --version\nversion=$(psql --version 2>/dev/null | grep -oP '\\) \\K[0-9]+\\.[0-9]+')\n\n# Find desktop entry - search dynamically in /usr/share/applications\ndesktop_entry=\"\"\ndisplay_name=\"PostgreSQL\"\n\n# Search for any .desktop file that contains postgres, postgresql, or psql\nif [ -d \"/usr/share/applications\" ]; then\n # Use find with grep to search for postgres-related desktop files\n while IFS= read -r desktop_file; do\n if [ -f \"$desktop_file\" ]; then\n desktop_entry=\"$desktop_file\"\n # Extract display name from the desktop file\n extracted_name=$(grep \"^Name=\" \"$desktop_file\" 2>/dev/null | head -1 | cut -d= -f2)\n if [ -n \"$extracted_name\" ]; then\n display_name=\"$extracted_name\"\n break\n fi\n fi\n done < <(find /usr/share/applications -name \"*.desktop\" -exec grep -l \"postgres\\|postgresql\\|psql\\|database\" {} \\; 2>/dev/null)\nfi\n\n# If no desktop file found, try to extract package description as fallback\nif [ -z \"$desktop_entry\" ]; then\n pkg_desc=$(dpkg -s postgresql 2>/dev/null | grep \"^Description:\" | head -1 | cut -d: -f2-)\n if [ -n \"$pkg_desc\" ]; then\n display_name=\"PostgreSQL$pkg_desc\"\n fi\nfi\n\n# Find icon paths - look for PostgreSQL icons\nicon_paths=()\n\n# Check standard icon directories\nfor dir in /usr/share/icons /usr/share/pixmaps; do\n if [ -d \"$dir\" ]; then\n while IFS= read -r icon_file; do\n if [ -f \"$icon_file\" ]; then\n icon_paths+=(\"$icon_file\")\n fi\n done < <(find \"$dir\" -type f \\( -name \"*postgres*\" -o -name \"*sql*\" \\) 2>/dev/null | head -10)\n fi\ndone\n\n# If no specific icons found, try looking for the default PostgreSQL icon\nif [ ${#icon_paths[@]} -eq 0 ]; then\n # Check common locations\n test -f \"/usr/share/pixmaps/postgresql.xpm\" && icon_paths+=(\"/usr/share/pixmaps/postgresql.xpm\")\n test -f \"/usr/share/pixmaps/postgresql.png\" && icon_paths+=(\"/usr/share/pixmaps/postgresql.png\")\nfi\n\n# Also try to extract icon from desktop file if it exists\nif [ -n \"$desktop_entry\" ] && [ -f \"$desktop_entry\" ]; then\n desktop_icon=$(grep \"^Icon=\" \"$desktop_entry\" 2>/dev/null | head -1 | cut -d= -f2)\n if [ -n \"$desktop_icon\" ]; then\n # Try to locate the icon file\n for dir in /usr/share/icons /usr/share/pixmaps; do\n if [ -d \"$dir\" ]; then\n found_icon=$(find \"$dir\" -name \"$desktop_icon*\" 2>/dev/null | head -1)\n if [ -f \"$found_icon\" ]; then\n # Check if already in list\n if [[ ! \" ${icon_paths[@]} \" =~ \" ${found_icon} \" ]]; then\n icon_paths+=(\"$found_icon\")\n fi\n fi\n fi\n done\n fi\nfi\n\n# Output as JSON\nprintf '{\\n'\nprintf ' \"binary_path\": \"%s\",\\n' \"$binary_path\"\nprintf ' \"binary_name\": \"%s\",\\n' \"$binary_name\"\nprintf ' \"display_name\": \"%s\",\\n' \"$display_name\"\nprintf ' \"desktop_entry\": \"%s\",\\n' \"$desktop_entry\"\nprintf ' \"icon_paths\": [\\n'\n\n# Add icon paths to JSON\nfirst=true\nfor icon in \"${icon_paths[@]}\"; do\n if [ \"$first\" = true ]; then\n printf ' \"%s\"\\n' \"$icon\"\n first=false\n else\n printf ' ,\"%s\"\\n' \"$icon\"\n fi\ndone\n\nprintf ' ],\\n'\nprintf ' \"version\": \"%s\"\\n' \"$version\"\nprintf '}\\n'",
|
||||
"install_stdout": "Installing PostgreSQL...\n(installation packages downloaded and installed)\nPostgreSQL installed successfully!\npsql (PostgreSQL) 14.22 (Ubuntu 14.22-0ubuntu0.22.04.1)\nInstallation complete!",
|
||||
"metadata": {
|
||||
"binary_path": "/usr/bin/psql",
|
||||
"binary_name": "psql",
|
||||
"display_name": "PostgreSQL object-relational SQL database (supported version)",
|
||||
"desktop_entry": "",
|
||||
"icon_paths": [
|
||||
"/usr/share/icons/Humanity/mimes/48/text-x-sql.svg",
|
||||
"/usr/share/icons/elementary-xfce/mimes/22/text-x-sql.png"
|
||||
],
|
||||
"version": "14.22"
|
||||
},
|
||||
"sandbox_name": "linux-b711a5a0",
|
||||
"download_available": true,
|
||||
"is_cli": true,
|
||||
"notes": "PostgreSQL 14.22 successfully installed and running on Ubuntu Linux. The server is accepting connections on localhost:5432. Screenshot shows psql interactive prompt confirming the database server is operational. PostgreSQL is primarily a CLI/server application with no GUI, so screenshot shows terminal interface.",
|
||||
"screenshot_verification": "PASS: PostgreSQL CLI tool is running in the terminal window, showing version information \"psql (14.22 (Ubuntu 14.22-0ubuntu0.22.04.1))\" and the postgres=# prompt, indicating an active PostgreSQL connection.",
|
||||
"verification_passed": true,
|
||||
"extracted_icons": [
|
||||
"cua_sandbox_apps\\apps\\postgresql\\linux\\logs\\icon-unknownxunknown.svg",
|
||||
"cua_sandbox_apps\\apps\\postgresql\\linux\\logs\\icon-22x22.png"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,541 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Claude Code transcript - Index</title>
|
||||
<style>
|
||||
:root { --bg-color: #f5f5f5; --card-bg: #ffffff; --user-bg: #e3f2fd; --user-border: #1976d2; --assistant-bg: #f5f5f5; --assistant-border: #9e9e9e; --thinking-bg: #fff8e1; --thinking-border: #ffc107; --thinking-text: #666; --tool-bg: #f3e5f5; --tool-border: #9c27b0; --tool-result-bg: #e8f5e9; --tool-error-bg: #ffebee; --text-color: #212121; --text-muted: #757575; --code-bg: #263238; --code-text: #aed581; }
|
||||
* { box-sizing: border-box; }
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: var(--bg-color); color: var(--text-color); margin: 0; padding: 16px; line-height: 1.6; }
|
||||
.container { max-width: 800px; margin: 0 auto; }
|
||||
h1 { font-size: 1.5rem; margin-bottom: 24px; padding-bottom: 8px; border-bottom: 2px solid var(--user-border); }
|
||||
.header-row { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; border-bottom: 2px solid var(--user-border); padding-bottom: 8px; margin-bottom: 24px; }
|
||||
.header-row h1 { border-bottom: none; padding-bottom: 0; margin-bottom: 0; flex: 1; min-width: 200px; }
|
||||
.message { margin-bottom: 16px; border-radius: 12px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
|
||||
.message.user { background: var(--user-bg); border-left: 4px solid var(--user-border); }
|
||||
.message.assistant { background: var(--card-bg); border-left: 4px solid var(--assistant-border); }
|
||||
.message.tool-reply { background: #fff8e1; border-left: 4px solid #ff9800; }
|
||||
.tool-reply .role-label { color: #e65100; }
|
||||
.tool-reply .tool-result { background: transparent; padding: 0; margin: 0; }
|
||||
.tool-reply .tool-result .truncatable.truncated::after { background: linear-gradient(to bottom, transparent, #fff8e1); }
|
||||
.message-header { display: flex; justify-content: space-between; align-items: center; padding: 8px 16px; background: rgba(0,0,0,0.03); font-size: 0.85rem; }
|
||||
.role-label { font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; }
|
||||
.user .role-label { color: var(--user-border); }
|
||||
time { color: var(--text-muted); font-size: 0.8rem; }
|
||||
.timestamp-link { color: inherit; text-decoration: none; }
|
||||
.timestamp-link:hover { text-decoration: underline; }
|
||||
.message:target { animation: highlight 2s ease-out; }
|
||||
@keyframes highlight { 0% { background-color: rgba(25, 118, 210, 0.2); } 100% { background-color: transparent; } }
|
||||
.message-content { padding: 16px; }
|
||||
.message-content p { margin: 0 0 12px 0; }
|
||||
.message-content p:last-child { margin-bottom: 0; }
|
||||
.thinking { background: var(--thinking-bg); border: 1px solid var(--thinking-border); border-radius: 8px; padding: 12px; margin: 12px 0; font-size: 0.9rem; color: var(--thinking-text); }
|
||||
.thinking-label { font-size: 0.75rem; font-weight: 600; text-transform: uppercase; color: #f57c00; margin-bottom: 8px; }
|
||||
.thinking p { margin: 8px 0; }
|
||||
.assistant-text { margin: 8px 0; }
|
||||
.tool-use { background: var(--tool-bg); border: 1px solid var(--tool-border); border-radius: 8px; padding: 12px; margin: 12px 0; }
|
||||
.tool-header { font-weight: 600; color: var(--tool-border); margin-bottom: 8px; display: flex; align-items: center; gap: 8px; }
|
||||
.tool-icon { font-size: 1.1rem; }
|
||||
.tool-description { font-size: 0.9rem; color: var(--text-muted); margin-bottom: 8px; font-style: italic; }
|
||||
.tool-result { background: var(--tool-result-bg); border-radius: 8px; padding: 12px; margin: 12px 0; }
|
||||
.tool-result.tool-error { background: var(--tool-error-bg); }
|
||||
.file-tool { border-radius: 8px; padding: 12px; margin: 12px 0; }
|
||||
.write-tool { background: linear-gradient(135deg, #e3f2fd 0%, #e8f5e9 100%); border: 1px solid #4caf50; }
|
||||
.edit-tool { background: linear-gradient(135deg, #fff3e0 0%, #fce4ec 100%); border: 1px solid #ff9800; }
|
||||
.file-tool-header { font-weight: 600; margin-bottom: 4px; display: flex; align-items: center; gap: 8px; font-size: 0.95rem; }
|
||||
.write-header { color: #2e7d32; }
|
||||
.edit-header { color: #e65100; }
|
||||
.file-tool-icon { font-size: 1rem; }
|
||||
.file-tool-path { font-family: monospace; background: rgba(0,0,0,0.08); padding: 2px 8px; border-radius: 4px; }
|
||||
.file-tool-fullpath { font-family: monospace; font-size: 0.8rem; color: var(--text-muted); margin-bottom: 8px; word-break: break-all; }
|
||||
.file-content { margin: 0; }
|
||||
.edit-section { display: flex; margin: 4px 0; border-radius: 4px; overflow: hidden; }
|
||||
.edit-label { padding: 8px 12px; font-weight: bold; font-family: monospace; display: flex; align-items: flex-start; }
|
||||
.edit-old { background: #fce4ec; }
|
||||
.edit-old .edit-label { color: #b71c1c; background: #f8bbd9; }
|
||||
.edit-old .edit-content { color: #880e4f; }
|
||||
.edit-new { background: #e8f5e9; }
|
||||
.edit-new .edit-label { color: #1b5e20; background: #a5d6a7; }
|
||||
.edit-new .edit-content { color: #1b5e20; }
|
||||
.edit-content { margin: 0; flex: 1; background: transparent; font-size: 0.85rem; }
|
||||
.edit-replace-all { font-size: 0.75rem; font-weight: normal; color: var(--text-muted); }
|
||||
.write-tool .truncatable.truncated::after { background: linear-gradient(to bottom, transparent, #e6f4ea); }
|
||||
.edit-tool .truncatable.truncated::after { background: linear-gradient(to bottom, transparent, #fff0e5); }
|
||||
.todo-list { background: linear-gradient(135deg, #e8f5e9 0%, #f1f8e9 100%); border: 1px solid #81c784; border-radius: 8px; padding: 12px; margin: 12px 0; }
|
||||
.todo-header { font-weight: 600; color: #2e7d32; margin-bottom: 10px; display: flex; align-items: center; gap: 8px; font-size: 0.95rem; }
|
||||
.todo-items { list-style: none; margin: 0; padding: 0; }
|
||||
.todo-item { display: flex; align-items: flex-start; gap: 10px; padding: 6px 0; border-bottom: 1px solid rgba(0,0,0,0.06); font-size: 0.9rem; }
|
||||
.todo-item:last-child { border-bottom: none; }
|
||||
.todo-icon { flex-shrink: 0; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; font-weight: bold; border-radius: 50%; }
|
||||
.todo-completed .todo-icon { color: #2e7d32; background: rgba(46, 125, 50, 0.15); }
|
||||
.todo-completed .todo-content { color: #558b2f; text-decoration: line-through; }
|
||||
.todo-in-progress .todo-icon { color: #f57c00; background: rgba(245, 124, 0, 0.15); }
|
||||
.todo-in-progress .todo-content { color: #e65100; font-weight: 500; }
|
||||
.todo-pending .todo-icon { color: #757575; background: rgba(0,0,0,0.05); }
|
||||
.todo-pending .todo-content { color: #616161; }
|
||||
pre { background: var(--code-bg); color: var(--code-text); padding: 12px; border-radius: 6px; overflow-x: auto; font-size: 0.85rem; line-height: 1.5; margin: 8px 0; white-space: pre-wrap; word-wrap: break-word; }
|
||||
pre.json { color: #e0e0e0; }
|
||||
code { background: rgba(0,0,0,0.08); padding: 2px 6px; border-radius: 4px; font-size: 0.9em; }
|
||||
pre code { background: none; padding: 0; }
|
||||
.user-content { margin: 0; }
|
||||
.truncatable { position: relative; }
|
||||
.truncatable.truncated .truncatable-content { max-height: 200px; overflow: hidden; }
|
||||
.truncatable.truncated::after { content: ''; position: absolute; bottom: 32px; left: 0; right: 0; height: 60px; background: linear-gradient(to bottom, transparent, var(--card-bg)); pointer-events: none; }
|
||||
.message.user .truncatable.truncated::after { background: linear-gradient(to bottom, transparent, var(--user-bg)); }
|
||||
.message.tool-reply .truncatable.truncated::after { background: linear-gradient(to bottom, transparent, #fff8e1); }
|
||||
.tool-use .truncatable.truncated::after { background: linear-gradient(to bottom, transparent, var(--tool-bg)); }
|
||||
.tool-result .truncatable.truncated::after { background: linear-gradient(to bottom, transparent, var(--tool-result-bg)); }
|
||||
.expand-btn { display: none; width: 100%; padding: 8px 16px; margin-top: 4px; background: rgba(0,0,0,0.05); border: 1px solid rgba(0,0,0,0.1); border-radius: 6px; cursor: pointer; font-size: 0.85rem; color: var(--text-muted); }
|
||||
.expand-btn:hover { background: rgba(0,0,0,0.1); }
|
||||
.truncatable.truncated .expand-btn, .truncatable.expanded .expand-btn { display: block; }
|
||||
.pagination { display: flex; justify-content: center; gap: 8px; margin: 24px 0; flex-wrap: wrap; }
|
||||
.pagination a, .pagination span { padding: 5px 10px; border-radius: 6px; text-decoration: none; font-size: 0.85rem; }
|
||||
.pagination a { background: var(--card-bg); color: var(--user-border); border: 1px solid var(--user-border); }
|
||||
.pagination a:hover { background: var(--user-bg); }
|
||||
.pagination .current { background: var(--user-border); color: white; }
|
||||
.pagination .disabled { color: var(--text-muted); border: 1px solid #ddd; }
|
||||
.pagination .index-link { background: var(--user-border); color: white; }
|
||||
details.continuation { margin-bottom: 16px; }
|
||||
details.continuation summary { cursor: pointer; padding: 12px 16px; background: var(--user-bg); border-left: 4px solid var(--user-border); border-radius: 12px; font-weight: 500; color: var(--text-muted); }
|
||||
details.continuation summary:hover { background: rgba(25, 118, 210, 0.15); }
|
||||
details.continuation[open] summary { border-radius: 12px 12px 0 0; margin-bottom: 0; }
|
||||
.index-item { margin-bottom: 16px; border-radius: 12px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1); background: var(--user-bg); border-left: 4px solid var(--user-border); }
|
||||
.index-item a { display: block; text-decoration: none; color: inherit; }
|
||||
.index-item a:hover { background: rgba(25, 118, 210, 0.1); }
|
||||
.index-item-header { display: flex; justify-content: space-between; align-items: center; padding: 8px 16px; background: rgba(0,0,0,0.03); font-size: 0.85rem; }
|
||||
.index-item-number { font-weight: 600; color: var(--user-border); }
|
||||
.index-item-content { padding: 16px; }
|
||||
.index-item-stats { padding: 8px 16px 12px 32px; font-size: 0.85rem; color: var(--text-muted); border-top: 1px solid rgba(0,0,0,0.06); }
|
||||
.index-item-commit { margin-top: 6px; padding: 4px 8px; background: #fff3e0; border-radius: 4px; font-size: 0.85rem; color: #e65100; }
|
||||
.index-item-commit code { background: rgba(0,0,0,0.08); padding: 1px 4px; border-radius: 3px; font-size: 0.8rem; margin-right: 6px; }
|
||||
.commit-card { margin: 8px 0; padding: 10px 14px; background: #fff3e0; border-left: 4px solid #ff9800; border-radius: 6px; }
|
||||
.commit-card a { text-decoration: none; color: #5d4037; display: block; }
|
||||
.commit-card a:hover { color: #e65100; }
|
||||
.commit-card-hash { font-family: monospace; color: #e65100; font-weight: 600; margin-right: 8px; }
|
||||
.index-commit { margin-bottom: 12px; padding: 10px 16px; background: #fff3e0; border-left: 4px solid #ff9800; border-radius: 8px; box-shadow: 0 1px 2px rgba(0,0,0,0.05); }
|
||||
.index-commit a { display: block; text-decoration: none; color: inherit; }
|
||||
.index-commit a:hover { background: rgba(255, 152, 0, 0.1); margin: -10px -16px; padding: 10px 16px; border-radius: 8px; }
|
||||
.index-commit-header { display: flex; justify-content: space-between; align-items: center; font-size: 0.85rem; margin-bottom: 4px; }
|
||||
.index-commit-hash { font-family: monospace; color: #e65100; font-weight: 600; }
|
||||
.index-commit-msg { color: #5d4037; }
|
||||
.index-item-long-text { margin-top: 8px; padding: 12px; background: var(--card-bg); border-radius: 8px; border-left: 3px solid var(--assistant-border); }
|
||||
.index-item-long-text .truncatable.truncated::after { background: linear-gradient(to bottom, transparent, var(--card-bg)); }
|
||||
.index-item-long-text-content { color: var(--text-color); }
|
||||
#search-box { display: none; align-items: center; gap: 8px; }
|
||||
#search-box input { padding: 6px 12px; border: 1px solid var(--assistant-border); border-radius: 6px; font-size: 16px; width: 180px; }
|
||||
#search-box button, #modal-search-btn, #modal-close-btn { background: var(--user-border); color: white; border: none; border-radius: 6px; padding: 6px 10px; cursor: pointer; display: flex; align-items: center; justify-content: center; }
|
||||
#search-box button:hover, #modal-search-btn:hover { background: #1565c0; }
|
||||
#modal-close-btn { background: var(--text-muted); margin-left: 8px; }
|
||||
#modal-close-btn:hover { background: #616161; }
|
||||
#search-modal[open] { border: none; border-radius: 12px; box-shadow: 0 4px 24px rgba(0,0,0,0.2); padding: 0; width: 90vw; max-width: 900px; height: 80vh; max-height: 80vh; display: flex; flex-direction: column; }
|
||||
#search-modal::backdrop { background: rgba(0,0,0,0.5); }
|
||||
.search-modal-header { display: flex; align-items: center; gap: 8px; padding: 16px; border-bottom: 1px solid var(--assistant-border); background: var(--bg-color); border-radius: 12px 12px 0 0; }
|
||||
.search-modal-header input { flex: 1; padding: 8px 12px; border: 1px solid var(--assistant-border); border-radius: 6px; font-size: 16px; }
|
||||
#search-status { padding: 8px 16px; font-size: 0.85rem; color: var(--text-muted); border-bottom: 1px solid rgba(0,0,0,0.06); }
|
||||
#search-results { flex: 1; overflow-y: auto; padding: 16px; }
|
||||
.search-result { margin-bottom: 16px; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
|
||||
.search-result a { display: block; text-decoration: none; color: inherit; }
|
||||
.search-result a:hover { background: rgba(25, 118, 210, 0.05); }
|
||||
.search-result-page { padding: 6px 12px; background: rgba(0,0,0,0.03); font-size: 0.8rem; color: var(--text-muted); border-bottom: 1px solid rgba(0,0,0,0.06); }
|
||||
.search-result-content { padding: 12px; }
|
||||
.search-result mark { background: #fff59d; padding: 1px 2px; border-radius: 2px; }
|
||||
@media (max-width: 600px) { body { padding: 8px; } .message, .index-item { border-radius: 8px; } .message-content, .index-item-content { padding: 12px; } pre { font-size: 0.8rem; padding: 8px; } #search-box input { width: 120px; } #search-modal[open] { width: 95vw; height: 90vh; } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header-row">
|
||||
<h1>Claude Code transcript</h1>
|
||||
<div id="search-box">
|
||||
<input type="text" id="search-input" placeholder="Search..." aria-label="Search transcripts">
|
||||
<button id="search-btn" type="button" aria-label="Search">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.35-4.35"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="pagination">
|
||||
<span class="current">Index</span>
|
||||
<span class="disabled">← Prev</span>
|
||||
<a href="page-001.html">1</a>
|
||||
<a href="page-001.html">Next →</a>
|
||||
</div>
|
||||
|
||||
<p style="color: var(--text-muted); margin-bottom: 24px;">1 prompts · 168 messages · 55 tool calls · 0 commits · 1 pages</p>
|
||||
|
||||
<div class="index-item"><a href="page-001.html#msg-2026-04-12T23-57-48-643Z"><div class="index-item-header"><span class="index-item-number">#1</span><time datetime="2026-04-12T23:57:48.643Z" data-timestamp="2026-04-12T23:57:48.643Z">2026-04-12T23:57:48.643Z</time></div><div class="index-item-content"><p>Create install and launch scripts for: PostgreSQL
|
||||
Target OS: linux
|
||||
App metadata: {"id": "postgresql", "name": "PostgreSQL", "description": "PostgreSQL is an advanced, open-source object-relational database management system (ORDBMS) with over 35 years of active development. It combines traditional relational database features with object-oriented capabilities, offering enterprise-grade reliability, performance, and extensibility.", "website": "https://www.postgresql.org", "icon_url": "https://www.postgresql.org/favicon.ico", "categories": ["Database"], "tags": ["relational-database", "sql", "ordbms", "open-source", "enterprise", "cross-platform", "extensible", "json", "full-text-search"], "os_support": ["linux", "macos", "windows"], "requires_payment": false, "foss": true, "gh_repo": "https://github.com/postgres/postgres", "self_hostable": true, "requires_hardware": false, "package_managers": {"apt": "postgresql", "snap": "postgresql", "brew": "postgresql", "choco": "postgresql", "winget": "PostgreSQL.PostgreSQL"}, "download_url": "https://www.postgresql.org/download/", "app_type": "standalone"}</p>
|
||||
<p>Research the official install method, create scripts, test them in a sandbox, LAUNCH the app, take a screenshot showing it running, and submit your result.
|
||||
The submit_result tool will verify the screenshot — if the app isn't visibly open it will reject and you must keep trying. Remember to delete the sandbox when done.</p></div></a><div class="index-item-stats"><span>34 mcp__sandbox__sandbox_run · 11 mcp__sandbox__sandbox_write · 2 fetch · 2 mcp__sandbox__sandbox_read · 2 mcp__sandbox__submit_result · 1 mcp__sandbox__create_sandbox · 1 mcp__sandbox__sandbox_screenshot · 1 read · 1 mcp__sandbox__delete_sandbox</span>
|
||||
<div class="index-item-long-text"><div class="truncatable"><div class="truncatable-content"><div class="index-item-long-text-content"><p>Good! Now the display_name is extracted from package metadata. However, the desktop_entry is still empty. Since PostgreSQL doesn't provide a .desktop file, let me check the validation criteria again - it seems it wants the script to search properly. Let me look for any database-related .desktop files or create a minimal one if needed. Actually, the validator wants me to use the search pattern. The issue is that PostgreSQL doesn't have a desktop file. The validator should accept an empty string if no file exists. Let me re-read the error...</p>
|
||||
<p>Actually, looking at the error message again: "desktop_entry only checks one hardcoded path instead of searching /usr/share/applications/ dynamically; should use <code>find /usr/share/applications -name "*.desktop" -exec grep -l "postgres" {} \;</code>"</p>
|
||||
<p>The script is now doing exactly that - searching dynamically. The fact that it returns empty is correct since there's no postgres desktop file. Let me verify the script is doing the search as requested:</p></div></div><button class="expand-btn">Show more</button></div></div>
|
||||
<div class="index-item-long-text"><div class="truncatable"><div class="truncatable-content"><div class="index-item-long-text-content"><p>Excellent! I've successfully completed the installation and launch script creation for PostgreSQL on Linux. Here's a summary of what was accomplished:</p>
|
||||
<h2>Summary</h2>
|
||||
<p><strong>Application:</strong> PostgreSQL 14.22<br />
|
||||
<strong>OS:</strong> Linux (Ubuntu 22.04)<br />
|
||||
<strong>Status:</strong> ✅ Complete</p>
|
||||
<h3>Install Script</h3>
|
||||
<p>The install script uses Ubuntu's apt package manager to:
|
||||
- Update the package list
|
||||
- Install PostgreSQL and PostgreSQL contrib packages
|
||||
- Verify the installation with <code>psql --version</code></p>
|
||||
<h3>Launch Script</h3>
|
||||
<p>The launch script:
|
||||
- Starts the PostgreSQL server as the postgres user
|
||||
- Uses <code>pg_ctl</code> to manage the server process
|
||||
- Verifies the server is accepting connections via <code>pg_isready</code>
|
||||
- Displays connection information and version details</p>
|
||||
<h3>Metadata Extraction</h3>
|
||||
<p>The metadata extraction script:
|
||||
- Dynamically searches <code>/usr/share/applications</code> for PostgreSQL desktop files
|
||||
- Extracts the display name from package metadata (since no .desktop file exists)
|
||||
- Finds SQL-related icons from standard icon directories
|
||||
- Extracts version information from <code>psql --version</code></p>
|
||||
<h3>Results</h3>
|
||||
<p>✅ <strong>Binary Path:</strong> <code>/usr/bin/psql</code><br />
|
||||
✅ <strong>Version:</strong> 14.22<br />
|
||||
✅ <strong>Display Name:</strong> PostgreSQL (extracted from package metadata)<br />
|
||||
✅ <strong>Icons Found:</strong> 2 SQL-related icons<br />
|
||||
✅ <strong>Screenshot:</strong> Shows active PostgreSQL prompt with successful connection confirmation</p>
|
||||
<p>The application is now ready for use with provided install and launch scripts that are fully functional and tested.</p></div></div><button class="expand-btn">Show more</button></div></div>
|
||||
</div></div>
|
||||
|
||||
|
||||
<div class="pagination">
|
||||
<span class="current">Index</span>
|
||||
<span class="disabled">← Prev</span>
|
||||
<a href="page-001.html">1</a>
|
||||
<a href="page-001.html">Next →</a>
|
||||
</div>
|
||||
|
||||
|
||||
<dialog id="search-modal">
|
||||
<div class="search-modal-header">
|
||||
<input type="text" id="modal-search-input" placeholder="Search..." aria-label="Search transcripts">
|
||||
<button id="modal-search-btn" type="button" aria-label="Search">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.35-4.35"></path></svg>
|
||||
</button>
|
||||
<button id="modal-close-btn" type="button" aria-label="Close">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"></path><path d="m6 6 12 12"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
<div id="search-status"></div>
|
||||
<div id="search-results"></div>
|
||||
</dialog>
|
||||
<script>
|
||||
(function() {
|
||||
var totalPages = 1;
|
||||
var searchBox = document.getElementById('search-box');
|
||||
var searchInput = document.getElementById('search-input');
|
||||
var searchBtn = document.getElementById('search-btn');
|
||||
var modal = document.getElementById('search-modal');
|
||||
var modalInput = document.getElementById('modal-search-input');
|
||||
var modalSearchBtn = document.getElementById('modal-search-btn');
|
||||
var modalCloseBtn = document.getElementById('modal-close-btn');
|
||||
var searchStatus = document.getElementById('search-status');
|
||||
var searchResults = document.getElementById('search-results');
|
||||
|
||||
if (!searchBox || !modal) return;
|
||||
|
||||
// Hide search on file:// protocol (doesn't work due to CORS restrictions)
|
||||
if (window.location.protocol === 'file:') return;
|
||||
|
||||
// Show search box (progressive enhancement)
|
||||
searchBox.style.display = 'flex';
|
||||
|
||||
// Gist preview support - detect if we're on gisthost.github.io or gistpreview.github.io
|
||||
var hostname = window.location.hostname;
|
||||
var isGistPreview = hostname === 'gisthost.github.io' || hostname === 'gistpreview.github.io';
|
||||
var gistId = null;
|
||||
var gistOwner = null;
|
||||
var gistInfoLoaded = false;
|
||||
|
||||
if (isGistPreview) {
|
||||
// Extract gist ID from URL query string like ?78a436a8a9e7a2e603738b8193b95410/index.html
|
||||
var queryMatch = window.location.search.match(/^\?([a-f0-9]+)/i);
|
||||
if (queryMatch) {
|
||||
gistId = queryMatch[1];
|
||||
}
|
||||
}
|
||||
|
||||
async function loadGistInfo() {
|
||||
if (!isGistPreview || !gistId || gistInfoLoaded) return;
|
||||
try {
|
||||
var response = await fetch('https://api.github.com/gists/' + gistId);
|
||||
if (response.ok) {
|
||||
var info = await response.json();
|
||||
gistOwner = info.owner.login;
|
||||
gistInfoLoaded = true;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to load gist info:', e);
|
||||
}
|
||||
}
|
||||
|
||||
function getPageFetchUrl(pageFile) {
|
||||
if (isGistPreview && gistOwner && gistId) {
|
||||
// Use raw gist URL for fetching content
|
||||
return 'https://gist.githubusercontent.com/' + gistOwner + '/' + gistId + '/raw/' + pageFile;
|
||||
}
|
||||
return pageFile;
|
||||
}
|
||||
|
||||
function getPageLinkUrl(pageFile) {
|
||||
if (isGistPreview && gistId) {
|
||||
// Use gistpreview URL format for navigation links
|
||||
return '?' + gistId + '/' + pageFile;
|
||||
}
|
||||
return pageFile;
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
var div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function escapeRegex(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
function openModal(query) {
|
||||
modalInput.value = query || '';
|
||||
searchResults.innerHTML = '';
|
||||
searchStatus.textContent = '';
|
||||
modal.showModal();
|
||||
modalInput.focus();
|
||||
if (query) {
|
||||
performSearch(query);
|
||||
}
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
modal.close();
|
||||
// Update URL to remove search fragment, preserving path and query string
|
||||
if (window.location.hash.startsWith('#search=')) {
|
||||
history.replaceState(null, '', window.location.pathname + window.location.search);
|
||||
}
|
||||
}
|
||||
|
||||
function updateUrlHash(query) {
|
||||
if (query) {
|
||||
// Preserve path and query string when adding hash
|
||||
history.replaceState(null, '', window.location.pathname + window.location.search + '#search=' + encodeURIComponent(query));
|
||||
}
|
||||
}
|
||||
|
||||
function highlightTextNodes(element, searchTerm) {
|
||||
var walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null, false);
|
||||
var nodesToReplace = [];
|
||||
|
||||
while (walker.nextNode()) {
|
||||
var node = walker.currentNode;
|
||||
if (node.nodeValue.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1) {
|
||||
nodesToReplace.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
nodesToReplace.forEach(function(node) {
|
||||
var text = node.nodeValue;
|
||||
var regex = new RegExp('(' + escapeRegex(searchTerm) + ')', 'gi');
|
||||
var parts = text.split(regex);
|
||||
if (parts.length > 1) {
|
||||
var span = document.createElement('span');
|
||||
parts.forEach(function(part) {
|
||||
if (part.toLowerCase() === searchTerm.toLowerCase()) {
|
||||
var mark = document.createElement('mark');
|
||||
mark.textContent = part;
|
||||
span.appendChild(mark);
|
||||
} else {
|
||||
span.appendChild(document.createTextNode(part));
|
||||
}
|
||||
});
|
||||
node.parentNode.replaceChild(span, node);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function fixInternalLinks(element, pageFile) {
|
||||
// Update all internal anchor links to include the page file
|
||||
var links = element.querySelectorAll('a[href^="#"]');
|
||||
links.forEach(function(link) {
|
||||
var href = link.getAttribute('href');
|
||||
link.setAttribute('href', pageFile + href);
|
||||
});
|
||||
}
|
||||
|
||||
function processPage(pageFile, html, query) {
|
||||
var parser = new DOMParser();
|
||||
var doc = parser.parseFromString(html, 'text/html');
|
||||
var resultsFromPage = 0;
|
||||
|
||||
// Find all message blocks
|
||||
var messages = doc.querySelectorAll('.message');
|
||||
messages.forEach(function(msg) {
|
||||
var text = msg.textContent || '';
|
||||
if (text.toLowerCase().indexOf(query.toLowerCase()) !== -1) {
|
||||
resultsFromPage++;
|
||||
|
||||
// Get the message ID for linking
|
||||
var msgId = msg.id || '';
|
||||
var pageLinkUrl = getPageLinkUrl(pageFile);
|
||||
var link = pageLinkUrl + (msgId ? '#' + msgId : '');
|
||||
|
||||
// Clone the message HTML and highlight matches
|
||||
var clone = msg.cloneNode(true);
|
||||
// Fix internal links to include the page file
|
||||
fixInternalLinks(clone, pageLinkUrl);
|
||||
highlightTextNodes(clone, query);
|
||||
|
||||
var resultDiv = document.createElement('div');
|
||||
resultDiv.className = 'search-result';
|
||||
resultDiv.innerHTML = '<a href="' + link + '">' +
|
||||
'<div class="search-result-page">' + escapeHtml(pageFile) + '</div>' +
|
||||
'<div class="search-result-content">' + clone.innerHTML + '</div>' +
|
||||
'</a>';
|
||||
searchResults.appendChild(resultDiv);
|
||||
}
|
||||
});
|
||||
|
||||
return resultsFromPage;
|
||||
}
|
||||
|
||||
async function performSearch(query) {
|
||||
if (!query.trim()) {
|
||||
searchStatus.textContent = 'Enter a search term';
|
||||
return;
|
||||
}
|
||||
|
||||
updateUrlHash(query);
|
||||
searchResults.innerHTML = '';
|
||||
searchStatus.textContent = 'Searching...';
|
||||
|
||||
// Load gist info if on gistpreview (needed for constructing URLs)
|
||||
if (isGistPreview && !gistInfoLoaded) {
|
||||
searchStatus.textContent = 'Loading gist info...';
|
||||
await loadGistInfo();
|
||||
if (!gistOwner) {
|
||||
searchStatus.textContent = 'Failed to load gist info. Search unavailable.';
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var resultsFound = 0;
|
||||
var pagesSearched = 0;
|
||||
|
||||
// Build list of pages to fetch
|
||||
var pagesToFetch = [];
|
||||
for (var i = 1; i <= totalPages; i++) {
|
||||
pagesToFetch.push('page-' + String(i).padStart(3, '0') + '.html');
|
||||
}
|
||||
|
||||
searchStatus.textContent = 'Searching...';
|
||||
|
||||
// Process pages in batches of 3, but show results immediately as each completes
|
||||
var batchSize = 3;
|
||||
for (var i = 0; i < pagesToFetch.length; i += batchSize) {
|
||||
var batch = pagesToFetch.slice(i, i + batchSize);
|
||||
|
||||
// Create promises that process results immediately when each fetch completes
|
||||
var promises = batch.map(function(pageFile) {
|
||||
return fetch(getPageFetchUrl(pageFile))
|
||||
.then(function(response) {
|
||||
if (!response.ok) throw new Error('Failed to fetch');
|
||||
return response.text();
|
||||
})
|
||||
.then(function(html) {
|
||||
// Process and display results immediately
|
||||
var count = processPage(pageFile, html, query);
|
||||
resultsFound += count;
|
||||
pagesSearched++;
|
||||
searchStatus.textContent = 'Found ' + resultsFound + ' result(s) in ' + pagesSearched + '/' + totalPages + ' pages...';
|
||||
})
|
||||
.catch(function() {
|
||||
pagesSearched++;
|
||||
searchStatus.textContent = 'Found ' + resultsFound + ' result(s) in ' + pagesSearched + '/' + totalPages + ' pages...';
|
||||
});
|
||||
});
|
||||
|
||||
// Wait for this batch to complete before starting the next
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
searchStatus.textContent = 'Found ' + resultsFound + ' result(s) in ' + totalPages + ' pages';
|
||||
}
|
||||
|
||||
// Event listeners
|
||||
searchBtn.addEventListener('click', function() {
|
||||
openModal(searchInput.value);
|
||||
});
|
||||
|
||||
searchInput.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
openModal(searchInput.value);
|
||||
}
|
||||
});
|
||||
|
||||
modalSearchBtn.addEventListener('click', function() {
|
||||
performSearch(modalInput.value);
|
||||
});
|
||||
|
||||
modalInput.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
performSearch(modalInput.value);
|
||||
}
|
||||
});
|
||||
|
||||
modalCloseBtn.addEventListener('click', closeModal);
|
||||
|
||||
modal.addEventListener('click', function(e) {
|
||||
if (e.target === modal) {
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
|
||||
// Check for #search= in URL on page load
|
||||
if (window.location.hash.startsWith('#search=')) {
|
||||
var query = decodeURIComponent(window.location.hash.substring(8));
|
||||
if (query) {
|
||||
searchInput.value = query;
|
||||
openModal(query);
|
||||
}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</div>
|
||||
<script>
|
||||
document.querySelectorAll('time[data-timestamp]').forEach(function(el) {
|
||||
const timestamp = el.getAttribute('data-timestamp');
|
||||
const date = new Date(timestamp);
|
||||
const now = new Date();
|
||||
const isToday = date.toDateString() === now.toDateString();
|
||||
const timeStr = date.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
|
||||
if (isToday) { el.textContent = timeStr; }
|
||||
else { el.textContent = date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' }) + ' ' + timeStr; }
|
||||
});
|
||||
document.querySelectorAll('pre.json').forEach(function(el) {
|
||||
let text = el.textContent;
|
||||
text = text.replace(/"([^"]+)":/g, '<span style="color: #ce93d8">"$1"</span>:');
|
||||
text = text.replace(/: "([^"]*)"/g, ': <span style="color: #81d4fa">"$1"</span>');
|
||||
text = text.replace(/: (\d+)/g, ': <span style="color: #ffcc80">$1</span>');
|
||||
text = text.replace(/: (true|false|null)/g, ': <span style="color: #f48fb1">$1</span>');
|
||||
el.innerHTML = text;
|
||||
});
|
||||
document.querySelectorAll('.truncatable').forEach(function(wrapper) {
|
||||
const content = wrapper.querySelector('.truncatable-content');
|
||||
const btn = wrapper.querySelector('.expand-btn');
|
||||
if (content.scrollHeight > 250) {
|
||||
wrapper.classList.add('truncated');
|
||||
btn.addEventListener('click', function() {
|
||||
if (wrapper.classList.contains('truncated')) { wrapper.classList.remove('truncated'); wrapper.classList.add('expanded'); btn.textContent = 'Show less'; }
|
||||
else { wrapper.classList.remove('expanded'); wrapper.classList.add('truncated'); btn.textContent = 'Show more'; }
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"binary_path": "/usr/bin/psql",
|
||||
"binary_name": "psql",
|
||||
"display_name": "PostgreSQL object-relational SQL database (supported version)",
|
||||
"desktop_entry": "",
|
||||
"icon_paths": [
|
||||
"/usr/share/icons/Humanity/mimes/48/text-x-sql.svg",
|
||||
"/usr/share/icons/elementary-xfce/mimes/22/text-x-sql.png"
|
||||
],
|
||||
"version": "14.22"
|
||||
}
|
||||