@amirdaraee/namewise 0.5.3 → 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +60 -60
- package/dist/index.js +0 -0
- package/dist/services/claude-service.d.ts.map +1 -1
- package/dist/services/claude-service.js +3 -0
- package/dist/services/claude-service.js.map +1 -1
- package/dist/services/lmstudio-service.d.ts +1 -0
- package/dist/services/lmstudio-service.d.ts.map +1 -1
- package/dist/services/lmstudio-service.js +16 -1
- package/dist/services/lmstudio-service.js.map +1 -1
- package/dist/services/ollama-service.d.ts +1 -0
- package/dist/services/ollama-service.d.ts.map +1 -1
- package/dist/services/ollama-service.js +16 -1
- package/dist/services/ollama-service.js.map +1 -1
- package/dist/services/openai-service.d.ts.map +1 -1
- package/dist/services/openai-service.js +3 -0
- package/dist/services/openai-service.js.map +1 -1
- package/package.json +8 -8
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -82
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -61
- package/.github/workflows/auto-release.yml +0 -81
- package/.github/workflows/build.yml +0 -55
- package/.github/workflows/publish.yml +0 -134
- package/.github/workflows/test.yml +0 -45
- package/eng.traineddata +0 -0
- package/src/cli/commands.ts +0 -64
- package/src/cli/rename.ts +0 -171
- package/src/index.ts +0 -54
- package/src/parsers/excel-parser.ts +0 -66
- package/src/parsers/factory.ts +0 -38
- package/src/parsers/pdf-parser.ts +0 -99
- package/src/parsers/text-parser.ts +0 -43
- package/src/parsers/word-parser.ts +0 -50
- package/src/services/ai-factory.ts +0 -39
- package/src/services/claude-service.ts +0 -119
- package/src/services/file-renamer.ts +0 -141
- package/src/services/lmstudio-service.ts +0 -161
- package/src/services/ollama-service.ts +0 -191
- package/src/services/openai-service.ts +0 -117
- package/src/types/index.ts +0 -76
- package/src/types/pdf-extraction.d.ts +0 -7
- package/src/utils/ai-prompts.ts +0 -76
- package/src/utils/file-templates.ts +0 -275
- package/src/utils/naming-conventions.ts +0 -67
- package/src/utils/pdf-to-image.ts +0 -137
- package/tests/data/console-test-1.txt +0 -1
- package/tests/data/console-test-2.txt +0 -1
- package/tests/data/console-test-long-filename-for-display-testing.txt +0 -1
- package/tests/data/empty-file.txt +0 -0
- package/tests/data/failure.txt +0 -1
- package/tests/data/file1.txt +0 -1
- package/tests/data/file2.txt +0 -1
- package/tests/data/much-longer-filename-to-test-clearing.txt +0 -1
- package/tests/data/sample-markdown.md +0 -9
- package/tests/data/sample-pdf.pdf +0 -0
- package/tests/data/sample-text.txt +0 -25
- package/tests/data/short.txt +0 -1
- package/tests/data/single-file.txt +0 -1
- package/tests/data/success.txt +0 -1
- package/tests/data/this-is-a-very-long-filename-that-should-be-truncated-for-better-display-purposes.txt +0 -1
- package/tests/data/very-long-filename-that-should-be-cleared-properly.txt +0 -1
- package/tests/data/x.txt +0 -1
- package/tests/integration/ai-prompting.test.ts +0 -386
- package/tests/integration/end-to-end.test.ts +0 -209
- package/tests/integration/person-name-extraction.test.ts +0 -440
- package/tests/integration/workflow.test.ts +0 -336
- package/tests/mocks/mock-ai-service.ts +0 -58
- package/tests/unit/cli/commands.test.ts +0 -169
- package/tests/unit/parsers/factory.test.ts +0 -100
- package/tests/unit/parsers/pdf-parser.test.ts +0 -63
- package/tests/unit/parsers/text-parser.test.ts +0 -85
- package/tests/unit/services/ai-factory.test.ts +0 -85
- package/tests/unit/services/claude-service.test.ts +0 -188
- package/tests/unit/services/file-renamer.test.ts +0 -514
- package/tests/unit/services/lmstudio-service.test.ts +0 -326
- package/tests/unit/services/ollama-service.test.ts +0 -264
- package/tests/unit/services/openai-service.test.ts +0 -196
- package/tests/unit/utils/ai-prompts.test.ts +0 -213
- package/tests/unit/utils/file-templates.test.ts +0 -199
- package/tests/unit/utils/naming-conventions.test.ts +0 -88
- package/tests/unit/utils/pdf-to-image.test.ts +0 -127
- package/tsconfig.json +0 -20
- package/vitest.config.ts +0 -30
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
name: Feature Request
|
|
2
|
-
description: Suggest an idea for this project
|
|
3
|
-
title: "[Feature]: "
|
|
4
|
-
labels: ["enhancement", "feature-request"]
|
|
5
|
-
body:
|
|
6
|
-
- type: markdown
|
|
7
|
-
attributes:
|
|
8
|
-
value: |
|
|
9
|
-
Thanks for suggesting a new feature!
|
|
10
|
-
|
|
11
|
-
- type: textarea
|
|
12
|
-
id: problem
|
|
13
|
-
attributes:
|
|
14
|
-
label: Problem Description
|
|
15
|
-
description: Is your feature request related to a problem? Please describe.
|
|
16
|
-
placeholder: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
17
|
-
|
|
18
|
-
- type: textarea
|
|
19
|
-
id: solution
|
|
20
|
-
attributes:
|
|
21
|
-
label: Proposed Solution
|
|
22
|
-
description: Describe the solution you'd like
|
|
23
|
-
placeholder: A clear and concise description of what you want to happen.
|
|
24
|
-
validations:
|
|
25
|
-
required: true
|
|
26
|
-
|
|
27
|
-
- type: textarea
|
|
28
|
-
id: alternatives
|
|
29
|
-
attributes:
|
|
30
|
-
label: Alternative Solutions
|
|
31
|
-
description: Describe alternatives you've considered
|
|
32
|
-
placeholder: A clear and concise description of any alternative solutions or features you've considered.
|
|
33
|
-
|
|
34
|
-
- type: dropdown
|
|
35
|
-
id: priority
|
|
36
|
-
attributes:
|
|
37
|
-
label: Priority
|
|
38
|
-
description: How important is this feature to you?
|
|
39
|
-
options:
|
|
40
|
-
- Low
|
|
41
|
-
- Medium
|
|
42
|
-
- High
|
|
43
|
-
- Critical
|
|
44
|
-
validations:
|
|
45
|
-
required: true
|
|
46
|
-
|
|
47
|
-
- type: checkboxes
|
|
48
|
-
id: implementation
|
|
49
|
-
attributes:
|
|
50
|
-
label: Implementation
|
|
51
|
-
description: Would you be willing to help implement this feature?
|
|
52
|
-
options:
|
|
53
|
-
- label: I would like to implement this feature
|
|
54
|
-
- label: I need help implementing this feature
|
|
55
|
-
- label: I can provide feedback during implementation
|
|
56
|
-
|
|
57
|
-
- type: textarea
|
|
58
|
-
id: additional
|
|
59
|
-
attributes:
|
|
60
|
-
label: Additional Context
|
|
61
|
-
description: Add any other context, screenshots, or examples about the feature request here.
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
name: Auto Release
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_run:
|
|
5
|
-
workflows: ["Build Pipeline"]
|
|
6
|
-
types:
|
|
7
|
-
- completed
|
|
8
|
-
branches: [ main ]
|
|
9
|
-
|
|
10
|
-
jobs:
|
|
11
|
-
check-version:
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
# Only run if the build workflow succeeded
|
|
14
|
-
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
|
15
|
-
outputs:
|
|
16
|
-
should-release: ${{ steps.version-check.outputs.should-release }}
|
|
17
|
-
new-version: ${{ steps.version-check.outputs.new-version }}
|
|
18
|
-
|
|
19
|
-
steps:
|
|
20
|
-
- name: Checkout code
|
|
21
|
-
uses: actions/checkout@v4
|
|
22
|
-
with:
|
|
23
|
-
fetch-depth: 0
|
|
24
|
-
|
|
25
|
-
- name: Check if version changed
|
|
26
|
-
id: version-check
|
|
27
|
-
run: |
|
|
28
|
-
# Get current version from package.json
|
|
29
|
-
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
30
|
-
echo "Current version: $CURRENT_VERSION"
|
|
31
|
-
|
|
32
|
-
# Check if tag already exists
|
|
33
|
-
if git tag --list | grep -q "^v$CURRENT_VERSION$"; then
|
|
34
|
-
echo "should-release=false" >> $GITHUB_OUTPUT
|
|
35
|
-
echo "Tag v$CURRENT_VERSION already exists"
|
|
36
|
-
else
|
|
37
|
-
echo "should-release=true" >> $GITHUB_OUTPUT
|
|
38
|
-
echo "new-version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
|
39
|
-
echo "New version detected: $CURRENT_VERSION"
|
|
40
|
-
fi
|
|
41
|
-
|
|
42
|
-
auto-release:
|
|
43
|
-
needs: check-version
|
|
44
|
-
runs-on: ubuntu-latest
|
|
45
|
-
if: needs.check-version.outputs.should-release == 'true'
|
|
46
|
-
permissions:
|
|
47
|
-
contents: write
|
|
48
|
-
|
|
49
|
-
steps:
|
|
50
|
-
- name: Checkout code
|
|
51
|
-
uses: actions/checkout@v4
|
|
52
|
-
|
|
53
|
-
- name: Setup Node.js
|
|
54
|
-
uses: actions/setup-node@v4
|
|
55
|
-
with:
|
|
56
|
-
node-version: '20.x'
|
|
57
|
-
cache: 'npm'
|
|
58
|
-
registry-url: 'https://registry.npmjs.org'
|
|
59
|
-
|
|
60
|
-
- name: Install dependencies
|
|
61
|
-
run: npm ci
|
|
62
|
-
|
|
63
|
-
- name: Run tests
|
|
64
|
-
run: npm run test:run
|
|
65
|
-
|
|
66
|
-
- name: Build project
|
|
67
|
-
run: npm run build
|
|
68
|
-
|
|
69
|
-
- name: Create and push tag
|
|
70
|
-
run: |
|
|
71
|
-
git config --local user.email "action@github.com"
|
|
72
|
-
git config --local user.name "GitHub Action"
|
|
73
|
-
git tag -a "v${{ needs.check-version.outputs.new-version }}" -m "Release v${{ needs.check-version.outputs.new-version }}"
|
|
74
|
-
git push origin "v${{ needs.check-version.outputs.new-version }}"
|
|
75
|
-
env:
|
|
76
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
77
|
-
|
|
78
|
-
- name: Publish to npm
|
|
79
|
-
run: npm publish
|
|
80
|
-
env:
|
|
81
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
name: Build Pipeline
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch: # Allows manual triggering
|
|
5
|
-
push:
|
|
6
|
-
branches: [ main ]
|
|
7
|
-
workflow_call: # Allows this workflow to be called by other workflows
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
test:
|
|
11
|
-
name: Run Tests Before Build
|
|
12
|
-
uses: ./.github/workflows/test.yml
|
|
13
|
-
|
|
14
|
-
build:
|
|
15
|
-
name: Build Project
|
|
16
|
-
runs-on: ubuntu-latest
|
|
17
|
-
needs: [test]
|
|
18
|
-
if: ${{ needs.test.result == 'success' }}
|
|
19
|
-
|
|
20
|
-
steps:
|
|
21
|
-
- name: Checkout code
|
|
22
|
-
uses: actions/checkout@v4
|
|
23
|
-
|
|
24
|
-
- name: Setup Node.js
|
|
25
|
-
uses: actions/setup-node@v4
|
|
26
|
-
with:
|
|
27
|
-
node-version: '22'
|
|
28
|
-
cache: 'npm'
|
|
29
|
-
|
|
30
|
-
- name: Install dependencies
|
|
31
|
-
run: npm ci
|
|
32
|
-
|
|
33
|
-
- name: Build project
|
|
34
|
-
run: npm run build
|
|
35
|
-
|
|
36
|
-
- name: Test CLI build
|
|
37
|
-
run: |
|
|
38
|
-
node dist/index.js --help
|
|
39
|
-
node dist/index.js --version
|
|
40
|
-
|
|
41
|
-
- name: Upload build artifacts
|
|
42
|
-
uses: actions/upload-artifact@v4
|
|
43
|
-
with:
|
|
44
|
-
name: build-artifacts-${{ github.sha }}
|
|
45
|
-
path: |
|
|
46
|
-
dist/
|
|
47
|
-
package.json
|
|
48
|
-
package-lock.json
|
|
49
|
-
README.md
|
|
50
|
-
LICENSE
|
|
51
|
-
CHANGELOG.md
|
|
52
|
-
retention-days: 30
|
|
53
|
-
|
|
54
|
-
- name: Build success notification
|
|
55
|
-
run: echo "✅ Build completed successfully for commit ${{ github.sha }}"
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
name: Publish Pipeline
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch: # Allows manual triggering
|
|
5
|
-
inputs:
|
|
6
|
-
use_artifact:
|
|
7
|
-
description: 'Use build artifact (provide artifact name or "latest")'
|
|
8
|
-
required: false
|
|
9
|
-
default: ''
|
|
10
|
-
release:
|
|
11
|
-
types: [published]
|
|
12
|
-
|
|
13
|
-
jobs:
|
|
14
|
-
build:
|
|
15
|
-
name: Build for Publishing
|
|
16
|
-
uses: ./.github/workflows/build.yml
|
|
17
|
-
if: ${{ github.event.inputs.use_artifact == '' }}
|
|
18
|
-
|
|
19
|
-
publish:
|
|
20
|
-
name: Publish Package
|
|
21
|
-
runs-on: ubuntu-latest
|
|
22
|
-
needs: [build]
|
|
23
|
-
if: ${{ always() && (needs.build.result == 'success' || github.event.inputs.use_artifact != '') }}
|
|
24
|
-
environment: production # Requires environment approval for production
|
|
25
|
-
|
|
26
|
-
steps:
|
|
27
|
-
- name: Checkout code
|
|
28
|
-
uses: actions/checkout@v4
|
|
29
|
-
|
|
30
|
-
- name: Setup Node.js
|
|
31
|
-
uses: actions/setup-node@v4
|
|
32
|
-
with:
|
|
33
|
-
node-version: '22'
|
|
34
|
-
registry-url: 'https://registry.npmjs.org'
|
|
35
|
-
cache: 'npm'
|
|
36
|
-
|
|
37
|
-
- name: Download build artifacts (from current run)
|
|
38
|
-
if: ${{ github.event.inputs.use_artifact == '' }}
|
|
39
|
-
uses: actions/download-artifact@v4
|
|
40
|
-
with:
|
|
41
|
-
name: build-artifacts-${{ github.sha }}
|
|
42
|
-
path: ./
|
|
43
|
-
|
|
44
|
-
- name: Download build artifacts (from specific run)
|
|
45
|
-
if: ${{ github.event.inputs.use_artifact != '' && github.event.inputs.use_artifact != 'latest' }}
|
|
46
|
-
uses: actions/download-artifact@v4
|
|
47
|
-
with:
|
|
48
|
-
name: ${{ github.event.inputs.use_artifact }}
|
|
49
|
-
path: ./
|
|
50
|
-
|
|
51
|
-
- name: Download latest build artifacts
|
|
52
|
-
if: ${{ github.event.inputs.use_artifact == 'latest' }}
|
|
53
|
-
run: |
|
|
54
|
-
echo "Downloading latest build artifacts..."
|
|
55
|
-
gh run download --name "build-artifacts-*" --limit 1
|
|
56
|
-
env:
|
|
57
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
58
|
-
|
|
59
|
-
- name: Install dependencies (only for package.json)
|
|
60
|
-
run: npm ci --production
|
|
61
|
-
|
|
62
|
-
- name: Publish to NPM
|
|
63
|
-
run: npm publish
|
|
64
|
-
env:
|
|
65
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
66
|
-
|
|
67
|
-
- name: Publish success notification
|
|
68
|
-
run: echo "✅ Package published to NPM successfully"
|
|
69
|
-
|
|
70
|
-
publish-github:
|
|
71
|
-
name: Publish to GitHub Packages
|
|
72
|
-
runs-on: ubuntu-latest
|
|
73
|
-
needs: [build, publish]
|
|
74
|
-
if: ${{ always() && needs.publish.result == 'success' }}
|
|
75
|
-
permissions:
|
|
76
|
-
contents: read
|
|
77
|
-
packages: write
|
|
78
|
-
|
|
79
|
-
steps:
|
|
80
|
-
- name: Checkout code
|
|
81
|
-
uses: actions/checkout@v4
|
|
82
|
-
|
|
83
|
-
- name: Setup Node.js
|
|
84
|
-
uses: actions/setup-node@v4
|
|
85
|
-
with:
|
|
86
|
-
node-version: '22'
|
|
87
|
-
registry-url: 'https://npm.pkg.github.com'
|
|
88
|
-
cache: 'npm'
|
|
89
|
-
|
|
90
|
-
- name: Download build artifacts (reuse from publish job)
|
|
91
|
-
if: ${{ github.event.inputs.use_artifact == '' }}
|
|
92
|
-
uses: actions/download-artifact@v4
|
|
93
|
-
with:
|
|
94
|
-
name: build-artifacts-${{ github.sha }}
|
|
95
|
-
path: ./
|
|
96
|
-
|
|
97
|
-
- name: Download build artifacts (from specific run)
|
|
98
|
-
if: ${{ github.event.inputs.use_artifact != '' && github.event.inputs.use_artifact != 'latest' }}
|
|
99
|
-
uses: actions/download-artifact@v4
|
|
100
|
-
with:
|
|
101
|
-
name: ${{ github.event.inputs.use_artifact }}
|
|
102
|
-
path: ./
|
|
103
|
-
|
|
104
|
-
- name: Download latest build artifacts
|
|
105
|
-
if: ${{ github.event.inputs.use_artifact == 'latest' }}
|
|
106
|
-
run: |
|
|
107
|
-
echo "Downloading latest build artifacts..."
|
|
108
|
-
gh run download --name "build-artifacts-*" --limit 1
|
|
109
|
-
env:
|
|
110
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
111
|
-
|
|
112
|
-
- name: Install dependencies (only for package.json)
|
|
113
|
-
run: npm ci --production
|
|
114
|
-
|
|
115
|
-
- name: Configure package for GitHub Packages
|
|
116
|
-
run: |
|
|
117
|
-
cp package.json package.json.backup
|
|
118
|
-
node -e "
|
|
119
|
-
const pkg = require('./package.json');
|
|
120
|
-
pkg.name = '@${{ github.repository_owner }}/' + pkg.name.split('/').pop();
|
|
121
|
-
require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2));
|
|
122
|
-
"
|
|
123
|
-
|
|
124
|
-
- name: Publish to GitHub Packages
|
|
125
|
-
run: npm publish
|
|
126
|
-
env:
|
|
127
|
-
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
128
|
-
|
|
129
|
-
- name: Restore original package.json
|
|
130
|
-
run: mv package.json.backup package.json
|
|
131
|
-
if: always()
|
|
132
|
-
|
|
133
|
-
- name: GitHub Packages success notification
|
|
134
|
-
run: echo "✅ Package published to GitHub Packages successfully"
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
name: Test Pipeline
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch: # Allows manual triggering
|
|
5
|
-
workflow_call: # Allows this workflow to be called by other workflows
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [ main ]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
test:
|
|
11
|
-
name: Run Tests
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
|
|
14
|
-
strategy:
|
|
15
|
-
matrix:
|
|
16
|
-
node-version: [18, 20, 22]
|
|
17
|
-
|
|
18
|
-
steps:
|
|
19
|
-
- name: Checkout code
|
|
20
|
-
uses: actions/checkout@v4
|
|
21
|
-
|
|
22
|
-
- name: Setup Node.js ${{ matrix.node-version }}
|
|
23
|
-
uses: actions/setup-node@v4
|
|
24
|
-
with:
|
|
25
|
-
node-version: ${{ matrix.node-version }}
|
|
26
|
-
cache: 'npm'
|
|
27
|
-
|
|
28
|
-
- name: Install dependencies
|
|
29
|
-
run: npm ci
|
|
30
|
-
|
|
31
|
-
- name: Run linter (if available)
|
|
32
|
-
run: npm run lint --if-present
|
|
33
|
-
|
|
34
|
-
- name: Run tests
|
|
35
|
-
run: npm run test:run
|
|
36
|
-
|
|
37
|
-
- name: Generate coverage report
|
|
38
|
-
run: npm run test:coverage
|
|
39
|
-
if: matrix.node-version == '22'
|
|
40
|
-
|
|
41
|
-
- name: Upload coverage reports
|
|
42
|
-
uses: codecov/codecov-action@v3
|
|
43
|
-
if: matrix.node-version == '22'
|
|
44
|
-
with:
|
|
45
|
-
fail_ci_if_error: false
|
package/eng.traineddata
DELETED
|
Binary file
|
package/src/cli/commands.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { renameFiles } from './rename.js';
|
|
3
|
-
|
|
4
|
-
export function setupCommands(program: Command): void {
|
|
5
|
-
program
|
|
6
|
-
.command('rename')
|
|
7
|
-
.description('🚀 Rename files in a directory based on their content using AI analysis')
|
|
8
|
-
.argument('[directory]', 'Directory containing files to rename (default: current directory)', '.')
|
|
9
|
-
.option('-p, --provider <provider>', 'AI provider (claude|openai|ollama|lmstudio)', 'claude')
|
|
10
|
-
.option('-k, --api-key <key>', 'API key for cloud providers (or set CLAUDE_API_KEY/OPENAI_API_KEY)')
|
|
11
|
-
.option('-c, --case <convention>', 'Naming convention (kebab-case|snake_case|camelCase|PascalCase|lowercase|UPPERCASE)', 'kebab-case')
|
|
12
|
-
.option('-t, --template <category>', 'File category template (document|movie|music|series|photo|book|general|auto)', 'general')
|
|
13
|
-
.option('-n, --name <personalName>', 'Personal name to include in filenames (for document/photo templates)')
|
|
14
|
-
.option('-d, --date <format>', 'Date format to include (YYYY-MM-DD|YYYY|YYYYMMDD|none)', 'none')
|
|
15
|
-
.option('--dry-run', 'Preview changes without actually renaming files (RECOMMENDED first!)', false)
|
|
16
|
-
.option('--max-size <size>', 'Maximum file size in MB to process', '10')
|
|
17
|
-
.option('--base-url <url>', 'Base URL for local LLM providers (default: ollama=http://localhost:11434, lmstudio=http://localhost:1234)')
|
|
18
|
-
.option('--model <name>', 'Model name for local LLM providers (default: ollama=llama3.1, lmstudio=local-model)')
|
|
19
|
-
.addHelpText('after', `
|
|
20
|
-
|
|
21
|
-
🔍 How it works:
|
|
22
|
-
1. Scans directory for supported files (PDF, DOCX, XLSX, TXT, MD, RTF)
|
|
23
|
-
2. Extracts content and metadata from each file
|
|
24
|
-
3. For scanned PDFs with no text, converts to image for AI vision analysis
|
|
25
|
-
4. Uses AI to analyze content and generate descriptive names
|
|
26
|
-
5. Applies your chosen template and naming convention
|
|
27
|
-
6. Renames files (or shows preview with --dry-run)
|
|
28
|
-
|
|
29
|
-
💡 Pro Tips:
|
|
30
|
-
• Always use --dry-run first to preview changes
|
|
31
|
-
• Use 'auto' template for smart file type detection
|
|
32
|
-
• Personal templates work great for documents and photos
|
|
33
|
-
• Scanned PDFs are automatically handled via AI vision (Claude/OpenAI/Ollama)
|
|
34
|
-
• Set API keys as environment variables for cloud providers
|
|
35
|
-
• Local LLMs (Ollama/LMStudio) require running servers first
|
|
36
|
-
|
|
37
|
-
🖥️ Local LLM Setup:
|
|
38
|
-
• Ollama: Start with 'ollama serve' (default: http://localhost:11434)
|
|
39
|
-
• LMStudio: Enable local server mode (default: http://localhost:1234)
|
|
40
|
-
|
|
41
|
-
📝 Examples:
|
|
42
|
-
# Current directory (no directory argument needed)
|
|
43
|
-
namewise rename --dry-run
|
|
44
|
-
namewise rename --provider claude --template document --name "alice"
|
|
45
|
-
|
|
46
|
-
# Specific directory
|
|
47
|
-
namewise rename ./documents --dry-run
|
|
48
|
-
|
|
49
|
-
# Cloud providers (require API keys)
|
|
50
|
-
namewise rename ./docs --provider claude --template document --name "alice"
|
|
51
|
-
namewise rename ./media --provider openai --template auto
|
|
52
|
-
|
|
53
|
-
# Local LLMs (no API key needed)
|
|
54
|
-
namewise rename --provider ollama --model llama3.1 --dry-run
|
|
55
|
-
namewise rename ./documents --provider ollama --model llama3.1
|
|
56
|
-
namewise rename ./contracts --provider lmstudio --base-url http://localhost:1234
|
|
57
|
-
|
|
58
|
-
# Custom Ollama setup
|
|
59
|
-
namewise rename ./files --provider ollama --base-url http://192.168.1.100:11434 --model codellama
|
|
60
|
-
`)
|
|
61
|
-
.action(async (directory, options) => {
|
|
62
|
-
await renameFiles(directory, options);
|
|
63
|
-
});
|
|
64
|
-
}
|
package/src/cli/rename.ts
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import inquirer from 'inquirer';
|
|
4
|
-
import { FileInfo, Config, RenameResult, FileCategory, DateFormat } from '../types/index.js';
|
|
5
|
-
import { DocumentParserFactory } from '../parsers/factory.js';
|
|
6
|
-
import { AIServiceFactory } from '../services/ai-factory.js';
|
|
7
|
-
import { FileRenamer } from '../services/file-renamer.js';
|
|
8
|
-
|
|
9
|
-
export async function renameFiles(directory: string, options: any): Promise<void> {
|
|
10
|
-
try {
|
|
11
|
-
// Validate directory exists
|
|
12
|
-
const stats = await fs.stat(directory);
|
|
13
|
-
if (!stats.isDirectory()) {
|
|
14
|
-
throw new Error(`${directory} is not a directory`);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Get API key for cloud providers only
|
|
18
|
-
let apiKey = options.apiKey;
|
|
19
|
-
const requiresApiKey = ['claude', 'openai'].includes(options.provider);
|
|
20
|
-
|
|
21
|
-
if (requiresApiKey && !apiKey) {
|
|
22
|
-
// Check environment variables first
|
|
23
|
-
if (options.provider === 'claude' && process.env.CLAUDE_API_KEY) {
|
|
24
|
-
apiKey = process.env.CLAUDE_API_KEY;
|
|
25
|
-
} else if (options.provider === 'openai' && process.env.OPENAI_API_KEY) {
|
|
26
|
-
apiKey = process.env.OPENAI_API_KEY;
|
|
27
|
-
} else {
|
|
28
|
-
const keyPrompt = await inquirer.prompt([
|
|
29
|
-
{
|
|
30
|
-
type: 'password',
|
|
31
|
-
name: 'apiKey',
|
|
32
|
-
message: `Enter your ${options.provider} API key:`,
|
|
33
|
-
mask: '*'
|
|
34
|
-
}
|
|
35
|
-
]);
|
|
36
|
-
apiKey = keyPrompt.apiKey;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Create config
|
|
41
|
-
const config: Config = {
|
|
42
|
-
aiProvider: options.provider,
|
|
43
|
-
apiKey,
|
|
44
|
-
maxFileSize: parseInt(options.maxSize) * 1024 * 1024, // Convert MB to bytes
|
|
45
|
-
supportedExtensions: ['.pdf', '.docx', '.doc', '.xlsx', '.xls', '.txt'],
|
|
46
|
-
dryRun: options.dryRun,
|
|
47
|
-
namingConvention: options.case,
|
|
48
|
-
templateOptions: {
|
|
49
|
-
category: options.template as FileCategory,
|
|
50
|
-
personalName: options.name,
|
|
51
|
-
dateFormat: options.date as DateFormat
|
|
52
|
-
},
|
|
53
|
-
// Local LLM specific configuration
|
|
54
|
-
localLLMConfig: {
|
|
55
|
-
baseUrl: options.baseUrl,
|
|
56
|
-
model: options.model
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
// Initialize services
|
|
61
|
-
const parserFactory = new DocumentParserFactory(config);
|
|
62
|
-
const aiService = AIServiceFactory.create(config.aiProvider, apiKey, config.localLLMConfig);
|
|
63
|
-
const fileRenamer = new FileRenamer(parserFactory, aiService, config);
|
|
64
|
-
|
|
65
|
-
// Get files to process
|
|
66
|
-
const files = await getFilesToProcess(directory, config.supportedExtensions);
|
|
67
|
-
|
|
68
|
-
if (files.length === 0) {
|
|
69
|
-
console.log('No supported files found in the directory.');
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
console.log(`Found ${files.length} files to process:`);
|
|
74
|
-
files.forEach(file => console.log(` - ${file.name}`));
|
|
75
|
-
|
|
76
|
-
// Confirm before processing
|
|
77
|
-
if (!config.dryRun) {
|
|
78
|
-
const confirm = await inquirer.prompt([
|
|
79
|
-
{
|
|
80
|
-
type: 'confirm',
|
|
81
|
-
name: 'proceed',
|
|
82
|
-
message: 'Do you want to proceed with renaming these files?',
|
|
83
|
-
default: false
|
|
84
|
-
}
|
|
85
|
-
]);
|
|
86
|
-
|
|
87
|
-
if (!confirm.proceed) {
|
|
88
|
-
console.log('Operation cancelled.');
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Process files
|
|
94
|
-
console.log('\nProcessing files...');
|
|
95
|
-
const results = await fileRenamer.renameFiles(files);
|
|
96
|
-
|
|
97
|
-
// Display results
|
|
98
|
-
displayResults(results, config.dryRun);
|
|
99
|
-
|
|
100
|
-
} catch (error) {
|
|
101
|
-
console.error('Error:', error instanceof Error ? error.message : 'Unknown error');
|
|
102
|
-
process.exit(1);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async function getFilesToProcess(directory: string, supportedExtensions: string[]): Promise<FileInfo[]> {
|
|
107
|
-
const files: FileInfo[] = [];
|
|
108
|
-
const entries = await fs.readdir(directory, { withFileTypes: true });
|
|
109
|
-
|
|
110
|
-
for (const entry of entries) {
|
|
111
|
-
if (entry.isFile()) {
|
|
112
|
-
const filePath = path.join(directory, entry.name);
|
|
113
|
-
const extension = path.extname(entry.name).toLowerCase();
|
|
114
|
-
|
|
115
|
-
if (supportedExtensions.includes(extension)) {
|
|
116
|
-
const stats = await fs.stat(filePath);
|
|
117
|
-
|
|
118
|
-
// Extract folder context
|
|
119
|
-
const parentFolder = path.basename(directory);
|
|
120
|
-
const fullPath = path.resolve(filePath);
|
|
121
|
-
const folderPath = path.dirname(fullPath).split(path.sep).filter(p => p);
|
|
122
|
-
|
|
123
|
-
files.push({
|
|
124
|
-
path: filePath,
|
|
125
|
-
name: entry.name,
|
|
126
|
-
extension,
|
|
127
|
-
size: stats.size,
|
|
128
|
-
// File system metadata
|
|
129
|
-
createdAt: stats.birthtime,
|
|
130
|
-
modifiedAt: stats.mtime,
|
|
131
|
-
accessedAt: stats.atime,
|
|
132
|
-
// Context metadata
|
|
133
|
-
parentFolder,
|
|
134
|
-
folderPath: folderPath.slice(-3), // Last 3 folder levels for context
|
|
135
|
-
// Document metadata will be populated by parsers
|
|
136
|
-
documentMetadata: undefined
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return files;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function displayResults(results: RenameResult[], dryRun: boolean): void {
|
|
146
|
-
const successful = results.filter(r => r.success);
|
|
147
|
-
const failed = results.filter(r => !r.success);
|
|
148
|
-
|
|
149
|
-
console.log(`\n${dryRun ? 'Preview' : 'Results'}:`);
|
|
150
|
-
console.log(`✅ ${successful.length} files ${dryRun ? 'would be' : 'successfully'} renamed`);
|
|
151
|
-
|
|
152
|
-
if (failed.length > 0) {
|
|
153
|
-
console.log(`❌ ${failed.length} files failed`);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
console.log('\nDetails:');
|
|
157
|
-
results.forEach(result => {
|
|
158
|
-
const status = result.success ? '✅' : '❌';
|
|
159
|
-
const originalName = path.basename(result.originalPath);
|
|
160
|
-
const newName = path.basename(result.newPath);
|
|
161
|
-
|
|
162
|
-
if (result.success) {
|
|
163
|
-
console.log(`${status} ${originalName} → ${newName}`);
|
|
164
|
-
} else {
|
|
165
|
-
console.log(`${status} ${originalName} (failed)`);
|
|
166
|
-
if (result.error) {
|
|
167
|
-
console.log(` Error: ${result.error}`);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { program } from 'commander';
|
|
4
|
-
import { setupCommands } from './cli/commands.js';
|
|
5
|
-
|
|
6
|
-
async function main() {
|
|
7
|
-
program
|
|
8
|
-
.name('namewise')
|
|
9
|
-
.description('🤖 AI-powered CLI tool that intelligently renames files based on their content using Claude or OpenAI')
|
|
10
|
-
.version('0.3.1')
|
|
11
|
-
.addHelpText('after', `
|
|
12
|
-
|
|
13
|
-
📋 Supported File Types:
|
|
14
|
-
PDF, DOCX/DOC, XLSX/XLS, TXT, MD, RTF
|
|
15
|
-
|
|
16
|
-
🎯 File Templates:
|
|
17
|
-
• general - Simple descriptive names (default)
|
|
18
|
-
• document - Personal docs with name/date: contract-john-20241205.pdf
|
|
19
|
-
• movie - Movies with year: the-matrix-1999.mkv
|
|
20
|
-
• series - TV shows: breaking-bad-s01e01.mkv
|
|
21
|
-
• music - Music with artist: the-beatles-hey-jude.mp3
|
|
22
|
-
• photo - Photos with context: vacation-paris-john-20241205.jpg
|
|
23
|
-
• book - Books with author: george-orwell-1984.pdf
|
|
24
|
-
• auto - AI auto-detects best template
|
|
25
|
-
|
|
26
|
-
🔧 Naming Conventions:
|
|
27
|
-
kebab-case, snake_case, camelCase, PascalCase, lowercase, UPPERCASE
|
|
28
|
-
|
|
29
|
-
💡 Quick Examples:
|
|
30
|
-
# Basic usage (dry run first - recommended!)
|
|
31
|
-
namewise rename ./documents --dry-run
|
|
32
|
-
|
|
33
|
-
# With Claude AI and specific template
|
|
34
|
-
namewise rename ./documents --provider claude --template document --name "john"
|
|
35
|
-
|
|
36
|
-
# Movies with auto-detection
|
|
37
|
-
namewise rename ./movies --template auto --case kebab-case
|
|
38
|
-
|
|
39
|
-
# OpenAI with custom settings
|
|
40
|
-
namewise rename ./files --provider openai --api-key your-key --max-size 20
|
|
41
|
-
|
|
42
|
-
🔑 API Keys:
|
|
43
|
-
Set environment variables: CLAUDE_API_KEY or OPENAI_API_KEY
|
|
44
|
-
Or provide via --api-key flag
|
|
45
|
-
|
|
46
|
-
📖 More info: https://github.com/amirdaraee/namewise#readme
|
|
47
|
-
`);
|
|
48
|
-
|
|
49
|
-
setupCommands(program);
|
|
50
|
-
|
|
51
|
-
await program.parseAsync(process.argv);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
main().catch(console.error);
|