Skip to content
Open
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
22 changes: 22 additions & 0 deletions skills/minimax-docx/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,28 @@ Create, edit, and format DOCX documents via CLI tools or direct C# scripts built

**First operation in session:** `scripts/env_check.sh` — do not proceed if `NOT READY`. (Skip on subsequent operations within the same session.)

The setup helpers restore and build `scripts/dotnet/MiniMaxAIDocx.Cli/MiniMaxAIDocx.Cli.csproj` directly for .NET 8+ compatibility. Do not rely on `dotnet restore scripts/dotnet/` because the repo's `.slnx` file is not supported by older SDKs.

### Restricted network / offline NuGet setup

If `nuget.org` is blocked, set `MINIMAX_DOCX_NUGET_SOURCES` before running setup or `env_check.sh`. Use a semicolon-separated list of reachable NuGet feeds or local package directories:

```bash
export MINIMAX_DOCX_NUGET_SOURCES="https://mirror.example/v3/index.json;/absolute/path/to/local/feed"
bash scripts/setup.sh --minimal
```

```powershell
$env:MINIMAX_DOCX_NUGET_SOURCES = "https://mirror.example/v3/index.json;C:\path\to\local\feed"
powershell -ExecutionPolicy Bypass -File scripts/setup.ps1 -Minimal
```

If you stage offline `.nupkg` files locally, the setup scripts also auto-detect these directories:
- `scripts/dotnet/packages`
- `assets/nuget`

The restore step uses `--ignore-failed-sources`, so a blocked remote feed will not break installation when the required packages are already available from cache or a local mirror.

## Quick Start: Direct C# Path

When the task requires structural document manipulation (custom styles, complex tables, multi-section layouts, headers/footers, TOC, images), write C# directly instead of wrestling with CLI limitations. Use this scaffold:
Expand Down
69 changes: 64 additions & 5 deletions skills/minimax-docx/scripts/env_check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
DOTNET_DIR="$SCRIPT_DIR/dotnet"
CLI_PROJECT="$DOTNET_DIR/MiniMaxAIDocx.Cli/MiniMaxAIDocx.Cli.csproj"
DEFAULT_NUGET_SOURCE="https://api.nuget.org/v3/index.json"

# Force English output for dotnet CLI
export DOTNET_CLI_UI_LANGUAGE=en
Expand All @@ -17,6 +19,59 @@ echo ""
STATUS="READY"
WARNINGS=0

trim() {
local value="$1"
value="${value#"${value%%[![:space:]]*}"}"
value="${value%"${value##*[![:space:]]}"}"
printf '%s' "$value"
}

append_default_restore_sources() {
RESTORE_SOURCE_ARGS+=("--source" "$DEFAULT_NUGET_SOURCE")
RESTORE_SOURCE_LABELS+=("$DEFAULT_NUGET_SOURCE")

local local_feed
for local_feed in "$DOTNET_DIR/packages" "$PROJECT_DIR/assets/nuget"; do
if [ -d "$local_feed" ]; then
RESTORE_SOURCE_ARGS+=("--source" "$local_feed")
RESTORE_SOURCE_LABELS+=("$local_feed")
fi
done
}

collect_restore_sources() {
RESTORE_SOURCE_ARGS=()
RESTORE_SOURCE_LABELS=()

local raw_sources="${MINIMAX_DOCX_NUGET_SOURCES:-}"
local source

if [ -n "$raw_sources" ]; then
local OLDIFS="$IFS"
IFS=';'
read -r -a configured_sources <<< "$raw_sources"
IFS="$OLDIFS"

for source in "${configured_sources[@]}"; do
source="$(trim "$source")"
[ -n "$source" ] || continue
RESTORE_SOURCE_ARGS+=("--source" "$source")
RESTORE_SOURCE_LABELS+=("$source")
done
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same edge case as in setup.sh: if MINIMAX_DOCX_NUGET_SOURCES is set but all entries trim to empty, RESTORE_SOURCE_ARGS ends up empty and the check will silently fall back to default NuGet.Config sources while still treating it as a “custom source(s)” case. Consider validating that at least one source remains after trimming and otherwise failing or falling back to the default + detected local feeds.

Suggested change
done
done
# If MINIMAX_DOCX_NUGET_SOURCES was set but no valid sources remained
# after trimming, fall back to the default + detected local feeds.
if [ ${#RESTORE_SOURCE_ARGS[@]} -eq 0 ]; then
RESTORE_SOURCE_ARGS+=("--source" "$DEFAULT_NUGET_SOURCE")
RESTORE_SOURCE_LABELS+=("$DEFAULT_NUGET_SOURCE")
local local_feed
for local_feed in "$DOTNET_DIR/packages" "$PROJECT_DIR/assets/nuget"; do
if [ -d "$local_feed" ]; then
RESTORE_SOURCE_ARGS+=("--source" "$local_feed")
RESTORE_SOURCE_LABELS+=("$local_feed")
fi
done
fi

Copilot uses AI. Check for mistakes.

if [ "${#RESTORE_SOURCE_ARGS[@]}" -gt 0 ]; then
return
fi
fi

append_default_restore_sources
}

quote_for_display() {
local value="$1"
printf '"%s"' "$value"
}

# --- Detect platform ---
OS="unknown"
case "$(uname -s)" in
Expand Down Expand Up @@ -61,26 +116,30 @@ fi

# --- Critical: NuGet packages ---
if [ -d "$DOTNET_DIR" ]; then
collect_restore_sources
if [ -f "$DOTNET_DIR/MiniMaxAIDocx.Cli/bin/Debug/net10.0/MiniMaxAIDocx.Cli.dll" ] || \
[ -f "$DOTNET_DIR/MiniMaxAIDocx.Cli/bin/Debug/net8.0/MiniMaxAIDocx.Cli.dll" ]; then
printf "[OK] %-14s built\n" "project"
else
# Try restore + build
if dotnet restore "$DOTNET_DIR" --verbosity quiet &>/dev/null; then
if dotnet restore "$CLI_PROJECT" --verbosity quiet --ignore-failed-sources "${RESTORE_SOURCE_ARGS[@]}" &>/dev/null; then
printf "[OK] %-14s packages restored\n" "nuget"
if dotnet build "$DOTNET_DIR" --verbosity quiet --no-restore &>/dev/null; then
if dotnet build "$CLI_PROJECT" --verbosity quiet --no-restore &>/dev/null; then
printf "[OK] %-14s build succeeded\n" "project"
else
printf "[FAIL] %-14s build failed (run: dotnet build %s)\n" "project" "$DOTNET_DIR"
printf "[FAIL] %-14s build failed (run: dotnet build %s)\n" "project" "$(quote_for_display "$CLI_PROJECT")"
STATUS="NOT READY"
fi
else
printf "[FAIL] %-14s restore failed\n" "nuget"
echo ""
echo " Common causes:"
echo " - No internet access (NuGet needs to download packages)"
echo " - Corporate proxy blocking nuget.org"
echo " - No internet access to the configured NuGet source(s)"
echo " - Corporate proxy or sandbox DNS blocking nuget.org"
echo " - Custom/local feed missing required packages"
echo " - SSL certificate issues (try: dotnet nuget list source)"
echo " Source(s): ${RESTORE_SOURCE_LABELS[*]}"
echo " Override sources: export MINIMAX_DOCX_NUGET_SOURCES='https://mirror.example/v3/index.json;/path/to/local/feed'"
echo ""
STATUS="NOT READY"
fi
Expand Down
107 changes: 97 additions & 10 deletions skills/minimax-docx/scripts/setup.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ $ErrorActionPreference = "Stop"
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$ProjectDir = Split-Path -Parent $ScriptDir
$DotnetDir = Join-Path $ScriptDir "dotnet"
$CliProject = Join-Path (Join-Path $DotnetDir "MiniMaxAIDocx.Cli") "MiniMaxAIDocx.Cli.csproj"
$LogFile = Join-Path $ProjectDir ".setup.log"
$DefaultNugetSource = "https://api.nuget.org/v3/index.json"

# --- Output Helpers ---
function Log { Write-Host "[OK] $args" -ForegroundColor Green }
Expand All @@ -22,6 +24,66 @@ function Fail { Write-Host "[FAIL] $args" -ForegroundColor Red }
function Info { Write-Host "[INFO] $args" -ForegroundColor Cyan }
function Step { Write-Host "`n=== $args ===" -ForegroundColor Blue }

function Add-DefaultRestoreSources {
param(
[string[]]$Sources = @()
)

$result = @($Sources)
$result += $DefaultNugetSource

$localFeeds = @(
(Join-Path $DotnetDir "packages"),
(Join-Path $ProjectDir "assets/nuget")
)
foreach ($feed in $localFeeds) {
if (Test-Path $feed) {
$result += $feed
}
}

return $result
}

function Get-RestoreSources {
$sources = @()

if ($env:MINIMAX_DOCX_NUGET_SOURCES) {
foreach ($source in ($env:MINIMAX_DOCX_NUGET_SOURCES -split ';')) {
$trimmed = $source.Trim()
if ($trimmed) {
$sources += $trimmed
}
}
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get-RestoreSources treats any non-empty MINIMAX_DOCX_NUGET_SOURCES as “custom”, but if it’s only whitespace/semicolons the trimmed list can end up empty. That leads to restore using default NuGet sources while output still says it’s using custom sources. Consider validating $sources.Count -gt 0 after trimming and either erroring or falling back to $DefaultNugetSource + detected local feeds.

Suggested change
}
}
if ($sources.Count -eq 0) {
Warn "MINIMAX_DOCX_NUGET_SOURCES contained no valid entries; falling back to default NuGet sources."
$sources += $DefaultNugetSource
$localFeeds = @(
(Join-Path $DotnetDir "packages"),
(Join-Path $ProjectDir "assets/nuget")
)
foreach ($feed in $localFeeds) {
if (Test-Path $feed) {
$sources += $feed
}
}
}

Copilot uses AI. Check for mistakes.

if ($sources.Count -gt 0) {
return [pscustomobject]@{
Mode = "custom"
Sources = $sources
}
}

Warn "MINIMAX_DOCX_NUGET_SOURCES contained no valid entries; falling back to default NuGet sources."
}

return [pscustomobject]@{
Mode = "default"
Sources = (Add-DefaultRestoreSources)
}
}

function Get-RestoreArgs {
param(
[string[]]$Sources
)

$args = @($CliProject, "--verbosity", "quiet", "--ignore-failed-sources")
foreach ($source in $Sources) {
$args += @("--source", $source)
}
return $args
}

if ($Help) {
Write-Host @"
Usage: setup.ps1 [options]
Expand Down Expand Up @@ -152,11 +214,28 @@ if (-not $Minimal) {
Step "Checking NuGet configuration"

$nugetSources = & dotnet nuget list source 2>$null
if ($nugetSources -match "nuget.org") {
Log "nuget.org source is configured"
$restoreSourceConfig = Get-RestoreSources
$restoreSources = $restoreSourceConfig.Sources
if ($restoreSourceConfig.Mode -eq "custom") {
Info "Using custom restore source(s) from MINIMAX_DOCX_NUGET_SOURCES"
foreach ($source in $restoreSources) {
Log "restore source: $source"
}
} else {
Warn "nuget.org not in sources. Adding..."
& dotnet nuget add source "https://api.nuget.org/v3/index.json" --name "nuget.org" 2>>$LogFile
if ($nugetSources -match "nuget.org") {
Log "nuget.org source is configured"
} else {
Warn "nuget.org not in sources. Adding..."
& dotnet nuget add source $DefaultNugetSource --name "nuget.org" 2>>$LogFile
}

foreach ($feed in @((Join-Path $DotnetDir "packages"), (Join-Path $ProjectDir "assets/nuget"))) {
if (Test-Path $feed) {
Log "Detected local NuGet feed: $feed"
}
}

Info "Set MINIMAX_DOCX_NUGET_SOURCES to override restore source(s) in restricted networks"
}

# --- Encoding Check ---
Expand Down Expand Up @@ -200,26 +279,34 @@ if (-not (Test-Path $DotnetDir)) {
Fail "Dotnet project directory not found: $DotnetDir"
exit 1
}
if (-not (Test-Path $CliProject)) {
Fail "CLI project not found: $CliProject"
exit 1
}

Push-Location $DotnetDir

Info "Restoring NuGet packages..."
$restoreResult = & dotnet restore --verbosity quiet 2>&1
$restoreArgs = Get-RestoreArgs -Sources $restoreSources
$restoreResult = & dotnet restore @restoreArgs 2>&1
if ($LASTEXITCODE -ne 0) {
Fail "NuGet restore failed:"
$restoreResult | ForEach-Object { Fail " $_" }
Fail "Common causes:"
Fail " - No internet (NuGet needs to download packages)"
Fail " - No internet access to the configured NuGet source(s)"
Fail " - Corporate proxy/firewall blocking nuget.org"
Fail " - Custom/local feed missing required packages"
Fail " - Insufficient disk space"
Fail "Try: dotnet restore --verbosity detailed"
Fail "Configured source(s): $($restoreSources -join ', ')"
Fail "Try: dotnet restore `"$CliProject`" --verbosity detailed --ignore-failed-sources"
Fail "Restricted network? Set MINIMAX_DOCX_NUGET_SOURCES='https://mirror.example/v3/index.json;C:\path\to\local\feed'"
Pop-Location
exit 1
}
Log "NuGet packages restored"

Info "Building project..."
$buildResult = & dotnet build --verbosity quiet --no-restore 2>&1
$buildResult = & dotnet build $CliProject --verbosity quiet --no-restore 2>&1
if ($LASTEXITCODE -ne 0) {
Fail "Build failed:"
$buildResult | ForEach-Object { Fail " $_" }
Expand All @@ -238,7 +325,7 @@ if (-not $SkipVerify) {

Info "Creating a test document..."
Push-Location $DotnetDir
$testResult = & dotnet run --project MiniMaxAIDocx.Cli -- create --type report --output $testOutput --title "Setup Test" 2>&1
$testResult = & dotnet run --project $CliProject -- create --type report --output $testOutput --title "Setup Test" 2>&1
$testExitCode = $LASTEXITCODE
Pop-Location

Expand Down Expand Up @@ -269,6 +356,6 @@ Write-Host " pandoc: $pandocInfo"
Write-Host " Project: $DotnetDir"
Write-Host ""
Write-Host " Usage:"
Write-Host " dotnet run --project $DotnetDir\MiniMaxAIDocx.Cli -- create --type report --output my_report.docx"
Write-Host " dotnet run --project `"$CliProject`" -- create --type report --output my_report.docx"
Write-Host ""
Write-Host " Log file: $LogFile"
Loading