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
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Ensure shell scripts always use LF line endings (critical for Docker builds on Windows)
*.sh text eol=lf
docker-entrypoint.sh text eol=lf
21 changes: 19 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ RUN set -eux; \
apk add --no-cache docker-cli; \
fi; \
if [ "$ENABLE_FULL_SKILLS" = "true" ]; then \
apk add --no-cache python3 py3-pip nodejs npm pandoc github-cli; \
apk add --no-cache python3 py3-pip nodejs npm pandoc github-cli poppler-utils bash; \
pip3 install --no-cache-dir --break-system-packages \
pypdf openpyxl pandas python-pptx markitdown defusedxml lxml; \
pypdf openpyxl pandas python-pptx markitdown defusedxml lxml \
pdfplumber pdf2image anthropic; \
npm install -g --cache /tmp/npm-cache docx pptxgenjs; \
rm -rf /tmp/npm-cache /root/.cache /var/cache/apk/*; \
else \
Expand All @@ -77,6 +78,22 @@ COPY --from=builder /out/pkg-helper /app/pkg-helper
COPY --from=builder /src/migrations/ /app/migrations/
COPY --from=builder /src/skills/ /app/bundled-skills/
COPY docker-entrypoint.sh /app/docker-entrypoint.sh

# Fix Windows git clone issues:
# 1. CRLF line endings in shell scripts (Windows git adds \r)
# 2. Broken symlinks: On Windows (core.symlinks=false), git creates text files
# or skips symlinks entirely. Skills like docx/pptx/xlsx need _shared/office
# module in their scripts/ dir (originally symlinked as scripts/office -> ../../_shared/office).
RUN set -eux; \
sed -i 's/\r$//' /app/docker-entrypoint.sh; \
cd /app/bundled-skills; \
for skill in docx pptx xlsx; do \
if [ -d "${skill}/scripts" ] && [ ! -d "${skill}/scripts/office" ]; then \
rm -f "${skill}/scripts/office"; \
cp -r _shared/office "${skill}/scripts/office"; \
fi; \
done

RUN chmod +x /app/docker-entrypoint.sh && \
chmod 755 /app/pkg-helper && chown root:root /app/pkg-helper

Expand Down
15 changes: 15 additions & 0 deletions internal/skills/dep_scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ func scanScriptsDir(scriptsDir string) *SkillManifest {
binaries := make(map[string]bool)
// Track subdirectory names — these are local modules and must never be reported as missing.
localModules := make(map[string]bool)
// The scripts directory itself can be referenced as a module (e.g. "from scripts import utils").
localModules[filepath.Base(scriptsDir)] = true

for _, e := range entries {
if e.IsDir() {
Expand All @@ -53,6 +55,19 @@ func scanScriptsDir(scriptsDir string) *SkillManifest {
}
for _, se := range subEntries {
if se.IsDir() {
// Track nested subdirs as local modules too (e.g. office/helpers, office/validators)
// so intra-package imports like "from helpers import ..." don't get falsely reported.
localModules[se.Name()] = true
// Scan files inside nested subdirs
nestedEntries, err := os.ReadDir(filepath.Join(scriptsDir, e.Name(), se.Name()))
if err != nil {
continue
}
for _, ne := range nestedEntries {
if !ne.IsDir() {
scanFile(filepath.Join(scriptsDir, e.Name(), se.Name(), ne.Name()), pyImports, nodeImports, binaries)
}
}
continue
}
scanFile(filepath.Join(scriptsDir, e.Name(), se.Name()), pyImports, nodeImports, binaries)
Expand Down