Merge pull request #3891 from SillyTavern/staging Staging
Signed| @@ -3,6 +3,9 @@ module.exports = { | |||
| 3 | extends: [ | 3 | extends: [ |
| 4 | 'eslint:recommended', | 4 | 'eslint:recommended', |
| 5 | ], | 5 | ], |
| 6 | plugins: [ | ||
| 7 | 'jsdoc', | ||
| 8 | ], | ||
| 6 | env: { | 9 | env: { |
| 7 | es6: true, | 10 | es6: true, |
| 8 | }, | 11 | }, |
| @@ -78,6 +81,7 @@ module.exports = { | |||
| 78 | 'public/scripts/extensions/tts/lib/**', | 81 | 'public/scripts/extensions/tts/lib/**', |
| 79 | ], | 82 | ], |
| 80 | rules: { | 83 | rules: { |
| 84 | 'jsdoc/no-undefined-types': ['warn', { disableReporting: true, markVariablesAsUsed: true }], | ||
| 81 | 'no-unused-vars': ['error', { args: 'none' }], | 85 | 'no-unused-vars': ['error', { args: 'none' }], |
| 82 | 'no-control-regex': 'off', | 86 | 'no-control-regex': 'off', |
| 83 | 'no-constant-condition': ['error', { checkLoops: false }], | 87 | 'no-constant-condition': ['error', { checkLoops: false }], |
| @@ -14,7 +14,7 @@ | |||
| 14 | - '(🐧 Linux)' | 14 | - '(🐧 Linux)' |
| 15 | 15 | ||
| 16 | 🦊 Firefox: | 16 | 🦊 Firefox: |
| 17 | - '(firefox|mozilla)' | 17 | - '\b(firefox|mozilla)\b' |
| 18 | 18 | ||
| 19 | 📱 Mobile: | 19 | 📱 Mobile: |
| 20 | - '(iphone|ios|android|📱 Termux)' | 20 | - '\b(iphone|ios|android|📱 Termux)\b' |
| @@ -34,6 +34,9 @@ | |||
| 34 | 🦊 Firefox: | 34 | 🦊 Firefox: |
| 35 | - head-branch: ['\bfirefox\b'] | 35 | - head-branch: ['\bfirefox\b'] |
| 36 | 36 | ||
| 37 | 🧑🤝🧑 Group Chat: | ||
| 38 | - head-branch: ['\bgroups?\b'] | ||
| 39 | |||
| 37 | 🖼️ Image Gen: | 40 | 🖼️ Image Gen: |
| 38 | - head-branch: ['\bimage-gen\b'] | 41 | - head-branch: ['\bimage-gen\b'] |
| 39 | 42 | ||
| @@ -58,6 +61,9 @@ | |||
| 58 | 📜 Prompt: | 61 | 📜 Prompt: |
| 59 | - head-branch: ['\bprompt\b'] | 62 | - head-branch: ['\bprompt\b'] |
| 60 | 63 | ||
| 64 | 🧠 Reasoning: | ||
| 65 | - head-branch: ['\breasoning\b', '\breason\b', '\bthinking\b'] | ||
| 66 | |||
| 61 | 🚚 Refactor: | 67 | 🚚 Refactor: |
| 62 | - head-branch: ['\brefactor(s|ed)?\b'] | 68 | - head-branch: ['\brefactor(s|ed)?\b'] |
| 63 | 69 | ||
| @@ -32,7 +32,7 @@ jobs: | |||
| 32 | with: | 32 | with: |
| 33 | configuration-path: .github/issues-auto-labels.yml | 33 | configuration-path: .github/issues-auto-labels.yml |
| 34 | enable-versioned-regex: 0 | 34 | enable-versioned-regex: 0 |
| 35 | repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 35 | repo-token: ${{ secrets.GITHUB_TOKEN }} |
| 36 | 36 | ||
| 37 | label-on-labels: | 37 | label-on-labels: |
| 38 | name: 🏷️ Label Issues by Labels | 38 | name: 🏷️ Label Issues by Labels |
| @@ -46,7 +46,7 @@ jobs: | |||
| 46 | uses: actions-cool/issues-helper@v3.6.0 | 46 | uses: actions-cool/issues-helper@v3.6.0 |
| 47 | with: | 47 | with: |
| 48 | actions: 'add-labels' | 48 | actions: 'add-labels' |
| 49 | token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 49 | token: ${{ secrets.GITHUB_TOKEN }} |
| 50 | labels: '👍 Approved' | 50 | labels: '👍 Approved' |
| 51 | 51 | ||
| 52 | - name: ❌ Remove progress labels when issue is marked done or stale | 52 | - name: ❌ Remove progress labels when issue is marked done or stale |
| @@ -56,7 +56,7 @@ jobs: | |||
| 56 | uses: actions-cool/issues-helper@v3.6.0 | 56 | uses: actions-cool/issues-helper@v3.6.0 |
| 57 | with: | 57 | with: |
| 58 | actions: 'remove-labels' | 58 | actions: 'remove-labels' |
| 59 | token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 59 | token: ${{ secrets.GITHUB_TOKEN }} |
| 60 | labels: '🧑💻 In Progress,🤔 Unsure,🤔 Under Consideration' | 60 | labels: '🧑💻 In Progress,🤔 Unsure,🤔 Under Consideration' |
| 61 | 61 | ||
| 62 | - name: ❌ Remove temporary labels when confirmed labels are added | 62 | - name: ❌ Remove temporary labels when confirmed labels are added |
| @@ -66,7 +66,7 @@ jobs: | |||
| 66 | uses: actions-cool/issues-helper@v3.6.0 | 66 | uses: actions-cool/issues-helper@v3.6.0 |
| 67 | with: | 67 | with: |
| 68 | actions: 'remove-labels' | 68 | actions: 'remove-labels' |
| 69 | token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 69 | token: ${{ secrets.GITHUB_TOKEN }} |
| 70 | labels: '🤔 Unsure,🤔 Under Consideration' | 70 | labels: '🤔 Unsure,🤔 Under Consideration' |
| 71 | 71 | ||
| 72 | - name: ❌ Remove no bug labels when "🪲 Confirmed" is added | 72 | - name: ❌ Remove no bug labels when "🪲 Confirmed" is added |
| @@ -76,7 +76,7 @@ jobs: | |||
| 76 | uses: actions-cool/issues-helper@v3.6.0 | 76 | uses: actions-cool/issues-helper@v3.6.0 |
| 77 | with: | 77 | with: |
| 78 | actions: 'remove-labels' | 78 | actions: 'remove-labels' |
| 79 | token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 79 | token: ${{ secrets.GITHUB_TOKEN }} |
| 80 | labels: '✖️ Not Reproducible,✖️ Not A Bug' | 80 | labels: '✖️ Not Reproducible,✖️ Not A Bug' |
| 81 | 81 | ||
| 82 | remove-stale-label: | 82 | remove-stale-label: |
| @@ -92,7 +92,7 @@ jobs: | |||
| 92 | uses: actions-cool/issues-helper@v3.6.0 | 92 | uses: actions-cool/issues-helper@v3.6.0 |
| 93 | with: | 93 | with: |
| 94 | actions: 'remove-labels' | 94 | actions: 'remove-labels' |
| 95 | token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 95 | token: ${{ secrets.GITHUB_TOKEN }} |
| 96 | issue-number: ${{ github.event.issue.number }} | 96 | issue-number: ${{ github.event.issue.number }} |
| 97 | labels: '⚰️ Stale,🕸️ Inactive,🚏 Awaiting User Response,🛑 No Response' | 97 | labels: '⚰️ Stale,🕸️ Inactive,🚏 Awaiting User Response,🛑 No Response' |
| 98 | 98 | ||
| @@ -113,4 +113,4 @@ jobs: | |||
| 113 | uses: peaceiris/actions-label-commenter@v1.10.0 | 113 | uses: peaceiris/actions-label-commenter@v1.10.0 |
| 114 | with: | 114 | with: |
| 115 | config_file: .github/issues-auto-comments.yml | 115 | config_file: .github/issues-auto-comments.yml |
| 116 | github_token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 116 | github_token: ${{ secrets.GITHUB_TOKEN }} |
| @@ -31,15 +31,15 @@ jobs: | |||
| 31 | - name: Label Linked Issues | 31 | - name: Label Linked Issues |
| 32 | id: label_linked_issues | 32 | id: label_linked_issues |
| 33 | env: | 33 | env: |
| 34 | GH_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 34 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 35 | run: | | 35 | run: | |
| 36 | for ISSUE in $(echo $issues | jq -r '.[]'); do | 36 | for ISSUE in $(echo $issues | jq -r '.[]'); do |
| 37 | if [ "${{ github.ref }}" == "refs/heads/staging" ]; then | 37 | if [ "${{ github.ref }}" == "refs/heads/staging" ]; then |
| 38 | LABEL="✅ Done (staging)" | 38 | LABEL="✅ Done (staging)" |
| 39 | gh issue edit $ISSUE -R ${{ github.repository }} --add-label "$LABEL" | 39 | gh issue edit $ISSUE -R ${{ github.repository }} --add-label "$LABEL" --remove-label "🧑💻 In Progress" |
| 40 | elif [ "${{ github.ref }}" == "refs/heads/release" ]; then | 40 | elif [ "${{ github.ref }}" == "refs/heads/release" ]; then |
| 41 | LABEL="✅ Done" | 41 | LABEL="✅ Done" |
| 42 | gh issue edit $ISSUE -R ${{ github.repository }} --add-label "$LABEL" | 42 | gh issue edit $ISSUE -R ${{ github.repository }} --add-label "$LABEL" --remove-label "🧑💻 In Progress" |
| 43 | fi | 43 | fi |
| 44 | echo "Added label '$LABEL' to issue #$ISSUE" | 44 | echo "Added label '$LABEL' (and removed '🧑💻 In Progress' if present) in issue #$ISSUE" |
| 45 | done | 45 | done |
| @@ -22,7 +22,7 @@ jobs: | |||
| 22 | # https://github.com/marketplace/actions/close-stale-issues | 22 | # https://github.com/marketplace/actions/close-stale-issues |
| 23 | uses: actions/stale@v9.1.0 | 23 | uses: actions/stale@v9.1.0 |
| 24 | with: | 24 | with: |
| 25 | repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 25 | repo-token: ${{ secrets.GITHUB_TOKEN }} |
| 26 | days-before-stale: 183 | 26 | days-before-stale: 183 |
| 27 | days-before-close: 7 | 27 | days-before-close: 7 |
| 28 | operations-per-run: 30 | 28 | operations-per-run: 30 |
| @@ -56,7 +56,7 @@ jobs: | |||
| 56 | # https://github.com/marketplace/actions/close-stale-issues | 56 | # https://github.com/marketplace/actions/close-stale-issues |
| 57 | uses: actions/stale@v9.1.0 | 57 | uses: actions/stale@v9.1.0 |
| 58 | with: | 58 | with: |
| 59 | repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 59 | repo-token: ${{ secrets.GITHUB_TOKEN }} |
| 60 | days-before-stale: 7 | 60 | days-before-stale: 7 |
| 61 | days-before-close: 7 | 61 | days-before-close: 7 |
| 62 | operations-per-run: 30 | 62 | operations-per-run: 30 |
| @@ -83,7 +83,7 @@ jobs: | |||
| 83 | # https://github.com/marketplace/actions/close-stale-issues | 83 | # https://github.com/marketplace/actions/close-stale-issues |
| 84 | uses: actions/stale@v9.1.0 | 84 | uses: actions/stale@v9.1.0 |
| 85 | with: | 85 | with: |
| 86 | repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 86 | repo-token: ${{ secrets.GITHUB_TOKEN }} |
| 87 | days-before-stale: 7 | 87 | days-before-stale: 7 |
| 88 | days-before-close: 7 | 88 | days-before-close: 7 |
| 89 | operations-per-run: 30 | 89 | operations-per-run: 30 |
| @@ -23,6 +23,6 @@ jobs: | |||
| 23 | uses: actions-cool/issues-helper@v3.6.0 | 23 | uses: actions-cool/issues-helper@v3.6.0 |
| 24 | with: | 24 | with: |
| 25 | actions: remove-labels | 25 | actions: remove-labels |
| 26 | token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 26 | token: ${{ secrets.GITHUB_TOKEN }} |
| 27 | issue-number: ${{ github.event.issue.number || github.event.pull_request.number }} | 27 | issue-number: ${{ github.event.issue.number || github.event.pull_request.number }} |
| 28 | labels: '🚏 Awaiting User Response,🧑💻 In Progress,📌 Keep Open,🚫 Merge Conflicts,🔬 Needs Testing,🔨 Needs Work,⚰️ Stale,⛔ Waiting For External/Upstream' | 28 | labels: '🚏 Awaiting User Response,🧑💻 In Progress,📌 Keep Open,🚫 Merge Conflicts,🔬 Needs Testing,🔨 Needs Work,⚰️ Stale,⛔ Waiting For External/Upstream' |
| @@ -24,6 +24,6 @@ jobs: | |||
| 24 | uses: actions-cool/issues-helper@v3.6.0 | 24 | uses: actions-cool/issues-helper@v3.6.0 |
| 25 | with: | 25 | with: |
| 26 | actions: 'add-labels' | 26 | actions: 'add-labels' |
| 27 | token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 27 | token: ${{ secrets.GITHUB_TOKEN }} |
| 28 | issue-number: ${{ github.event.issue.number || github.event.pull_request.number }} | 28 | issue-number: ${{ github.event.issue.number || github.event.pull_request.number }} |
| 29 | labels: '👷 Maintainer' | 29 | labels: '👷 Maintainer' |
| @@ -1,6 +1,7 @@ | |||
| 1 | name: 🔀 Pull Request Manager | 1 | name: 🔀 Pull Request Manager |
| 2 | 2 | ||
| 3 | on: | 3 | on: |
| 4 | workflow_dispatch: # Allow to manually call this workflow | ||
| 4 | pull_request_target: | 5 | pull_request_target: |
| 5 | types: [opened, synchronize, reopened, edited, labeled, unlabeled, closed] | 6 | types: [opened, synchronize, reopened, edited, labeled, unlabeled, closed] |
| 6 | pull_request_review_comment: | 7 | pull_request_review_comment: |
| @@ -11,9 +12,63 @@ permissions: | |||
| 11 | pull-requests: write | 12 | pull-requests: write |
| 12 | 13 | ||
| 13 | jobs: | 14 | jobs: |
| 15 | run-eslint: | ||
| 16 | name: ✅ Check ESLint on PR | ||
| 17 | runs-on: ubuntu-latest | ||
| 18 | # Only needs to run when code is changed | ||
| 19 | if: github.event.action == 'opened' || github.event.action == 'synchronize' | ||
| 20 | |||
| 21 | # Override permissions, linter likely needs write access to issues | ||
| 22 | permissions: | ||
| 23 | contents: read | ||
| 24 | issues: write | ||
| 25 | pull-requests: write | ||
| 26 | |||
| 27 | steps: | ||
| 28 | - name: Checkout Repository | ||
| 29 | # Checkout | ||
| 30 | # https://github.com/marketplace/actions/checkout | ||
| 31 | uses: actions/checkout@v4.2.2 | ||
| 32 | with: | ||
| 33 | ref: ${{ github.event.pull_request.head.sha }} | ||
| 34 | repository: ${{ github.event.pull_request.head.repo.full_name }} | ||
| 35 | |||
| 36 | - name: Setup Node.js | ||
| 37 | # Setup Node.js environment | ||
| 38 | # https://github.com/marketplace/actions/setup-node-js-environment | ||
| 39 | uses: actions/setup-node@v4.3.0 | ||
| 40 | with: | ||
| 41 | node-version: 20 | ||
| 42 | |||
| 43 | - name: Run npm install | ||
| 44 | run: npm ci | ||
| 45 | |||
| 46 | - name: Run ESLint | ||
| 47 | # Action ESLint | ||
| 48 | # https://github.com/marketplace/actions/action-eslint | ||
| 49 | uses: sibiraj-s/action-eslint@v3.0.1 | ||
| 50 | with: | ||
| 51 | token: ${{ secrets.GITHUB_TOKEN }} | ||
| 52 | eslint-args: '--ignore-path=.gitignore --quiet' | ||
| 53 | extensions: 'js' | ||
| 54 | annotations: true | ||
| 55 | ignore-patterns: | | ||
| 56 | dist/ | ||
| 57 | lib/ | ||
| 58 | |||
| 14 | label-by-size: | 59 | label-by-size: |
| 15 | name: 🏷️ Label PR by Size | 60 | name: 🏷️ Label PR by Size |
| 61 | # This job should run after all others, to prevent possible concurrency issues | ||
| 62 | needs: [label-by-branches, label-by-files, remove-stale-label, check-merge-blocking-labels, write-auto-comments] | ||
| 16 | runs-on: ubuntu-latest | 63 | runs-on: ubuntu-latest |
| 64 | # Only needs to run when code is changed | ||
| 65 | if: always() && (github.event.action == 'opened' || github.event.action == 'synchronize') | ||
| 66 | |||
| 67 | # Override permissions, the labeler needs issues write access | ||
| 68 | permissions: | ||
| 69 | contents: read | ||
| 70 | issues: write | ||
| 71 | pull-requests: write | ||
| 17 | 72 | ||
| 18 | steps: | 73 | steps: |
| 19 | - name: Label PR Size | 74 | - name: Label PR Size |
| @@ -21,7 +76,7 @@ jobs: | |||
| 21 | # https://github.com/marketplace/actions/pull-request-size-labeler | 76 | # https://github.com/marketplace/actions/pull-request-size-labeler |
| 22 | uses: codelytv/pr-size-labeler@v1.10.2 | 77 | uses: codelytv/pr-size-labeler@v1.10.2 |
| 23 | with: | 78 | with: |
| 24 | GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 79 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 25 | xs_label: '🟩 ⬤○○○○' | 80 | xs_label: '🟩 ⬤○○○○' |
| 26 | xs_max_size: '20' | 81 | xs_max_size: '20' |
| 27 | s_label: '🟩 ⬤⬤○○○' | 82 | s_label: '🟩 ⬤⬤○○○' |
| @@ -32,20 +87,15 @@ jobs: | |||
| 32 | l_max_size: '1000' | 87 | l_max_size: '1000' |
| 33 | xl_label: '🟥 ⬤⬤⬤⬤⬤' | 88 | xl_label: '🟥 ⬤⬤⬤⬤⬤' |
| 34 | fail_if_xl: 'false' | 89 | fail_if_xl: 'false' |
| 35 | github_api_url: 'https://api.github.com' | ||
| 36 | files_to_ignore: | | 90 | files_to_ignore: | |
| 37 | "package-lock.json" | 91 | "package-lock.json" |
| 38 | "public/lib/*" | 92 | "public/lib/*" |
| 39 | 93 | ||
| 40 | label-by-branches: | 94 | label-by-branches: |
| 41 | name: 🏷️ Label PR by Branches | 95 | name: 🏷️ Label PR by Branches |
| 42 | needs: [label-by-size] | ||
| 43 | runs-on: ubuntu-latest | 96 | runs-on: ubuntu-latest |
| 44 | # Run, even if the previous jobs were skipped/failed | 97 | # Only label once when PR is created or when base branch is changed, to allow manual label removal |
| 45 | # Only label once when PR is created or branches are changed, to allow manual label removal | 98 | if: github.event.action == 'opened' || (github.event.action == 'synchronize' && github.event.changes.base) |
| 46 | if: | | ||
| 47 | always() | ||
| 48 | && github.event.action == 'opened' || (github.event.action == 'synchronize' && (github.event.changes.base || github.event.changes.head)) | ||
| 49 | 99 | ||
| 50 | steps: | 100 | steps: |
| 51 | - name: Checkout Repository | 101 | - name: Checkout Repository |
| @@ -59,14 +109,13 @@ jobs: | |||
| 59 | uses: actions/labeler@v5.0.0 | 109 | uses: actions/labeler@v5.0.0 |
| 60 | with: | 110 | with: |
| 61 | configuration-path: .github/pr-auto-labels-by-branch.yml | 111 | configuration-path: .github/pr-auto-labels-by-branch.yml |
| 62 | repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 112 | repo-token: ${{ secrets.GITHUB_TOKEN }} |
| 63 | 113 | ||
| 64 | label-by-files: | 114 | label-by-files: |
| 65 | name: 🏷️ Label PR by Files | 115 | name: 🏷️ Label PR by Files |
| 66 | needs: [label-by-branches] | ||
| 67 | runs-on: ubuntu-latest | 116 | runs-on: ubuntu-latest |
| 68 | # Run, even if the previous jobs were skipped/failed | 117 | # Only needs to run when code is changed |
| 69 | if: always() | 118 | if: github.event.action == 'opened' || github.event.action == 'synchronize' |
| 70 | 119 | ||
| 71 | steps: | 120 | steps: |
| 72 | - name: Checkout Repository | 121 | - name: Checkout Repository |
| @@ -80,16 +129,19 @@ jobs: | |||
| 80 | uses: actions/labeler@v5.0.0 | 129 | uses: actions/labeler@v5.0.0 |
| 81 | with: | 130 | with: |
| 82 | configuration-path: .github/pr-auto-labels-by-files.yml | 131 | configuration-path: .github/pr-auto-labels-by-files.yml |
| 83 | repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 132 | repo-token: ${{ secrets.GITHUB_TOKEN }} |
| 84 | 133 | ||
| 85 | remove-stale-label: | 134 | remove-stale-label: |
| 86 | name: 🗑️ Remove Stale Label on Comment | 135 | name: 🗑️ Remove Stale Label on Comment |
| 87 | needs: [label-by-files] | ||
| 88 | runs-on: ubuntu-latest | 136 | runs-on: ubuntu-latest |
| 89 | # Only runs when this is not done by the github actions bot | 137 | # Only runs on comments not done by the github actions bot |
| 90 | if: | | 138 | if: github.event_name == 'pull_request_review_comment' && github.actor != 'github-actions[bot]' |
| 91 | always() | 139 | |
| 92 | && github.event_name == 'pull_request_review_comment' && github.actor != 'github-actions[bot]' | 140 | # Override permissions, issue labeler needs issues write access |
| 141 | permissions: | ||
| 142 | contents: read | ||
| 143 | issues: write | ||
| 144 | pull-requests: write | ||
| 93 | 145 | ||
| 94 | steps: | 146 | steps: |
| 95 | - name: Remove Stale Label | 147 | - name: Remove Stale Label |
| @@ -98,13 +150,13 @@ jobs: | |||
| 98 | uses: actions-cool/issues-helper@v3.6.0 | 150 | uses: actions-cool/issues-helper@v3.6.0 |
| 99 | with: | 151 | with: |
| 100 | actions: 'remove-labels' | 152 | actions: 'remove-labels' |
| 101 | token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 153 | token: ${{ secrets.GITHUB_TOKEN }} |
| 102 | issue-number: ${{ github.event.pull_request.number }} | 154 | issue-number: ${{ github.event.pull_request.number }} |
| 103 | labels: '⚰️ Stale' | 155 | labels: '⚰️ Stale' |
| 104 | 156 | ||
| 105 | check-merge-blocking-labels: | 157 | check-merge-blocking-labels: |
| 106 | name: 🚫 Check Merge Blocking Labels | 158 | name: 🚫 Check Merge Blocking Labels |
| 107 | needs: [label-by-size, label-by-branches, label-by-files, remove-stale-label] | 159 | needs: [label-by-branches, label-by-files] |
| 108 | runs-on: ubuntu-latest | 160 | runs-on: ubuntu-latest |
| 109 | # Run, even if the previous jobs were skipped/failed | 161 | # Run, even if the previous jobs were skipped/failed |
| 110 | if: always() | 162 | if: always() |
| @@ -154,7 +206,7 @@ jobs: | |||
| 154 | 206 | ||
| 155 | write-auto-comments: | 207 | write-auto-comments: |
| 156 | name: 💬 Post PR Comments Based on Labels | 208 | name: 💬 Post PR Comments Based on Labels |
| 157 | needs: [label-by-size, label-by-branches, label-by-files, remove-stale-label] | 209 | needs: [label-by-branches, label-by-files] |
| 158 | runs-on: ubuntu-latest | 210 | runs-on: ubuntu-latest |
| 159 | # Run, even if the previous jobs were skipped/failed | 211 | # Run, even if the previous jobs were skipped/failed |
| 160 | if: always() | 212 | if: always() |
| @@ -171,7 +223,7 @@ jobs: | |||
| 171 | uses: peaceiris/actions-label-commenter@v1.10.0 | 223 | uses: peaceiris/actions-label-commenter@v1.10.0 |
| 172 | with: | 224 | with: |
| 173 | config_file: .github/pr-auto-comments.yml | 225 | config_file: .github/pr-auto-comments.yml |
| 174 | github_token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 226 | github_token: ${{ secrets.GITHUB_TOKEN }} |
| 175 | 227 | ||
| 176 | # This runs on merged PRs to staging, reading the PR body and directly linked issues. Check `issues-updates-on-merge.yml`:`update-linked-issues` for commit-based updates. | 228 | # This runs on merged PRs to staging, reading the PR body and directly linked issues. Check `issues-updates-on-merge.yml`:`update-linked-issues` for commit-based updates. |
| 177 | update-linked-issues: | 229 | update-linked-issues: |
| @@ -179,6 +231,12 @@ jobs: | |||
| 179 | runs-on: ubuntu-latest | 231 | runs-on: ubuntu-latest |
| 180 | if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'staging' | 232 | if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'staging' |
| 181 | 233 | ||
| 234 | # Override permissions, We need to be able to write to issues | ||
| 235 | permissions: | ||
| 236 | contents: read | ||
| 237 | issues: write | ||
| 238 | pull-requests: write | ||
| 239 | |||
| 182 | steps: | 240 | steps: |
| 183 | - name: Extract Linked Issues From PR Description | 241 | - name: Extract Linked Issues From PR Description |
| 184 | id: extract_issues | 242 | id: extract_issues |
| @@ -192,7 +250,7 @@ jobs: | |||
| 192 | PR_NUMBER=${{ github.event.pull_request.number }} | 250 | PR_NUMBER=${{ github.event.pull_request.number }} |
| 193 | REPO=${{ github.repository }} | 251 | REPO=${{ github.repository }} |
| 194 | API_URL="https://api.github.com/repos/$REPO/pulls/$PR_NUMBER/issues" | 252 | API_URL="https://api.github.com/repos/$REPO/pulls/$PR_NUMBER/issues" |
| 195 | ISSUES=$(curl -s -H "Authorization: token ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}" "$API_URL" | jq -r '.[].number' | jq -R -s -c 'split("\n")[:-1]') | 253 | ISSUES=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" "$API_URL" | jq -r '.[].number' | jq -R -s -c 'split("\n")[:-1]') |
| 196 | echo "linked_issues=$ISSUES" >> $GITHUB_ENV | 254 | echo "linked_issues=$ISSUES" >> $GITHUB_ENV |
| 197 | 255 | ||
| 198 | - name: Merge Issue Lists | 256 | - name: Merge Issue Lists |
| @@ -204,9 +262,9 @@ jobs: | |||
| 204 | - name: Label Linked Issues | 262 | - name: Label Linked Issues |
| 205 | id: label_linked_issues | 263 | id: label_linked_issues |
| 206 | env: | 264 | env: |
| 207 | GH_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 265 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 208 | run: | | 266 | run: | |
| 209 | for ISSUE in $(echo $final_issues | jq -r '.[]'); do | 267 | for ISSUE in $(echo $final_issues | jq -r '.[]'); do |
| 210 | gh issue edit $ISSUE -R ${{ github.repository }} --add-label "✅ Done (staging)" | 268 | gh issue edit $ISSUE -R ${{ github.repository }} --add-label "✅ Done (staging)" --remove-label "🧑💻 In Progress" |
| 211 | echo "Added label '✅ Done (staging)' to issue #$ISSUE" | 269 | echo "Added label '✅ Done (staging)' (and removed '🧑💻 In Progress' if present) in issue #$ISSUE" |
| 212 | done | 270 | done |
| @@ -23,6 +23,6 @@ jobs: | |||
| 23 | uses: eps1lon/actions-label-merge-conflict@v3.0.3 | 23 | uses: eps1lon/actions-label-merge-conflict@v3.0.3 |
| 24 | with: | 24 | with: |
| 25 | dirtyLabel: '🚫 Merge Conflicts' | 25 | dirtyLabel: '🚫 Merge Conflicts' |
| 26 | repoToken: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} | 26 | repoToken: ${{ secrets.GITHUB_TOKEN }} |
| 27 | commentOnDirty: > | 27 | commentOnDirty: > |
| 28 | ⚠️ This PR has conflicts that need to be resolved before it can be merged. | 28 | ⚠️ This PR has conflicts that need to be resolved before it can be merged. |
| @@ -114,6 +114,8 @@ backups: | |||
| 114 | chat: | 114 | chat: |
| 115 | # Enable automatic chat backups | 115 | # Enable automatic chat backups |
| 116 | enabled: true | 116 | enabled: true |
| 117 | # Verify integrity of chat files before saving | ||
| 118 | checkIntegrity: true | ||
| 117 | # Maximum number of chat backups to keep per user (starting from the most recent). Set to -1 to keep all backups. | 119 | # Maximum number of chat backups to keep per user (starting from the most recent). Set to -1 to keep all backups. |
| 118 | maxTotalBackups: -1 | 120 | maxTotalBackups: -1 |
| 119 | # Interval in milliseconds to throttle chat backups per user | 121 | # Interval in milliseconds to throttle chat backups per user |
| @@ -140,6 +142,8 @@ performance: | |||
| 140 | lazyLoadCharacters: false | 142 | lazyLoadCharacters: false |
| 141 | # The maximum amount of memory that parsed character cards can use. Set to 0 to disable memory caching. | 143 | # The maximum amount of memory that parsed character cards can use. Set to 0 to disable memory caching. |
| 142 | memoryCacheCapacity: '100mb' | 144 | memoryCacheCapacity: '100mb' |
| 145 | # Enables disk caching for character cards. Improves performances with large card libraries. | ||
| 146 | useDiskCache: true | ||
| 143 | 147 | ||
| 144 | # Allow secret keys exposure via API | 148 | # Allow secret keys exposure via API |
| 145 | allowKeysExposure: false | 149 | allowKeysExposure: false |
| @@ -151,6 +155,7 @@ whitelistImportDomains: | |||
| 151 | - cdn.discordapp.com | 155 | - cdn.discordapp.com |
| 152 | - files.catbox.moe | 156 | - files.catbox.moe |
| 153 | - raw.githubusercontent.com | 157 | - raw.githubusercontent.com |
| 158 | - char-archive.evulid.cc | ||
| 154 | # API request overrides (for KoboldAI and Text Completion APIs) | 159 | # API request overrides (for KoboldAI and Text Completion APIs) |
| 155 | ## Note: host includes the port number if it's not the default (80 or 443) | 160 | ## Note: host includes the port number if it's not the default (80 or 443) |
| 156 | ## Format is an array of objects: | 161 | ## Format is an array of objects: |
| @@ -564,6 +564,10 @@ | |||
| 564 | "type": "context" | 564 | "type": "context" |
| 565 | }, | 565 | }, |
| 566 | { | 566 | { |
| 567 | "filename": "presets/context/Llama 4 Instruct.json", | ||
| 568 | "type": "context" | ||
| 569 | }, | ||
| 570 | { | ||
| 567 | "filename": "presets/context/Phi.json", | 571 | "filename": "presets/context/Phi.json", |
| 568 | "type": "context" | 572 | "type": "context" |
| 569 | }, | 573 | }, |
| @@ -664,6 +668,10 @@ | |||
| 664 | "type": "instruct" | 668 | "type": "instruct" |
| 665 | }, | 669 | }, |
| 666 | { | 670 | { |
| 671 | "filename": "presets/instruct/Llama 4 Instruct.json", | ||
| 672 | "type": "instruct" | ||
| 673 | }, | ||
| 674 | { | ||
| 667 | "filename": "presets/instruct/Phi.json", | 675 | "filename": "presets/instruct/Phi.json", |
| 668 | "type": "instruct" | 676 | "type": "instruct" |
| 669 | }, | 677 | }, |
| @@ -786,5 +794,13 @@ | |||
| 786 | { | 794 | { |
| 787 | "filename": "presets/context/DeepSeek-V2.5.json", | 795 | "filename": "presets/context/DeepSeek-V2.5.json", |
| 788 | "type": "context" | 796 | "type": "context" |
| 797 | }, | ||
| 798 | { | ||
| 799 | "filename": "presets/reasoning/DeepSeek.json", | ||
| 800 | "type": "reasoning" | ||
| 801 | }, | ||
| 802 | { | ||
| 803 | "filename": "presets/reasoning/Blank.json", | ||
| 804 | "type": "reasoning" | ||
| 789 | } | 805 | } |
| 790 | ] | 806 | ] |
| @@ -0,0 +1,11 @@ | |||
| 1 | { | ||
| 2 | "story_string": "<|begin_of_text|><|header_start|>system<|header_end|>\n\n{{#if system}}{{system}}\n{{/if}}{{#if wiBefore}}{{wiBefore}}\n{{/if}}{{#if description}}{{description}}\n{{/if}}{{#if personality}}{{char}}'s personality: {{personality}}\n{{/if}}{{#if scenario}}Scenario: {{scenario}}\n{{/if}}{{#if wiAfter}}{{wiAfter}}\n{{/if}}{{#if persona}}{{persona}}\n{{/if}}{{trim}}<|eot|>", | ||
| 3 | "example_separator": "", | ||
| 4 | "chat_start": "", | ||
| 5 | "use_stop_strings": false, | ||
| 6 | "allow_jailbreak": false, | ||
| 7 | "always_force_name2": true, | ||
| 8 | "trim_sentences": false, | ||
| 9 | "single_line": false, | ||
| 10 | "name": "Llama 4 Instruct" | ||
| 11 | } | ||
| @@ -16,7 +16,7 @@ | |||
| 16 | "input_suffix": "<|eot_id|>", | 16 | "input_suffix": "<|eot_id|>", |
| 17 | "system_suffix": "<|eot_id|>", | 17 | "system_suffix": "<|eot_id|>", |
| 18 | "user_alignment_message": "", | 18 | "user_alignment_message": "", |
| 19 | "system_same_as_user": true, | 19 | "system_same_as_user": false, |
| 20 | "last_system_sequence": "", | 20 | "last_system_sequence": "", |
| 21 | "name": "Llama 3 Instruct" | 21 | "name": "Llama 3 Instruct" |
| 22 | } | 22 | } |
| @@ -0,0 +1,22 @@ | |||
| 1 | { | ||
| 2 | "input_sequence": "<|header_start|>user<|header_end|>\n\n", | ||
| 3 | "output_sequence": "<|header_start|>assistant<|header_end|>\n\n", | ||
| 4 | "last_output_sequence": "", | ||
| 5 | "system_sequence": "<|header_start|>system<|header_end|>\n\n", | ||
| 6 | "stop_sequence": "<|eot|>", | ||
| 7 | "wrap": false, | ||
| 8 | "macro": true, | ||
| 9 | "names_behavior": "always", | ||
| 10 | "activation_regex": "", | ||
| 11 | "system_sequence_prefix": "", | ||
| 12 | "system_sequence_suffix": "", | ||
| 13 | "first_output_sequence": "", | ||
| 14 | "skip_examples": false, | ||
| 15 | "output_suffix": "<|eot|>", | ||
| 16 | "input_suffix": "<|eot|>", | ||
| 17 | "system_suffix": "<|eot|>", | ||
| 18 | "user_alignment_message": "", | ||
| 19 | "system_same_as_user": false, | ||
| 20 | "last_system_sequence": "", | ||
| 21 | "name": "Llama 4 Instruct" | ||
| 22 | } | ||
| @@ -0,0 +1,6 @@ | |||
| 1 | { | ||
| 2 | "name": "Blank", | ||
| 3 | "prefix": "", | ||
| 4 | "suffix": "", | ||
| 5 | "separator": "" | ||
| 6 | } | ||
| @@ -0,0 +1,6 @@ | |||
| 1 | { | ||
| 2 | "name": "DeepSeek", | ||
| 3 | "prefix": "<think>\n", | ||
| 4 | "suffix": "\n</think>", | ||
| 5 | "separator": "\n\n" | ||
| 6 | } | ||
| @@ -2,7 +2,7 @@ | |||
| 2 | "compilerOptions": { | 2 | "compilerOptions": { |
| 3 | "module": "ESNext", | 3 | "module": "ESNext", |
| 4 | "target": "ES2023", | 4 | "target": "ES2023", |
| 5 | "moduleResolution": "Node", | 5 | "moduleResolution": "Bundler", |
| 6 | "strictNullChecks": true, | 6 | "strictNullChecks": true, |
| 7 | "strictFunctionTypes": true, | 7 | "strictFunctionTypes": true, |
| 8 | "checkJs": true, | 8 | "checkJs": true, |
| @@ -1,12 +1,12 @@ | |||
| 1 | { | 1 | { |
| 2 | "name": "sillytavern", | 2 | "name": "sillytavern", |
| 3 | "version": "1.12.13", | 3 | "version": "1.12.14", |
| 4 | "lockfileVersion": 3, | 4 | "lockfileVersion": 3, |
| 5 | "requires": true, | 5 | "requires": true, |
| 6 | "packages": { | 6 | "packages": { |
| 7 | "": { | 7 | "": { |
| 8 | "name": "sillytavern", | 8 | "name": "sillytavern", |
| 9 | "version": "1.12.13", | 9 | "version": "1.12.14", |
| 10 | "hasInstallScript": true, | 10 | "hasInstallScript": true, |
| 11 | "license": "AGPL-3.0", | 11 | "license": "AGPL-3.0", |
| 12 | "dependencies": { | 12 | "dependencies": { |
| @@ -14,6 +14,26 @@ | |||
| 14 | "@agnai/sentencepiece-js": "^1.1.1", | 14 | "@agnai/sentencepiece-js": "^1.1.1", |
| 15 | "@agnai/web-tokenizers": "^0.1.3", | 15 | "@agnai/web-tokenizers": "^0.1.3", |
| 16 | "@iconfu/svg-inject": "^1.2.3", | 16 | "@iconfu/svg-inject": "^1.2.3", |
| 17 | "@jimp/core": "^1.6.0", | ||
| 18 | "@jimp/js-bmp": "^1.6.0", | ||
| 19 | "@jimp/js-gif": "^1.6.0", | ||
| 20 | "@jimp/js-tiff": "^1.6.0", | ||
| 21 | "@jimp/plugin-circle": "^1.6.0", | ||
| 22 | "@jimp/plugin-color": "^1.6.0", | ||
| 23 | "@jimp/plugin-contain": "^1.6.0", | ||
| 24 | "@jimp/plugin-cover": "^1.6.0", | ||
| 25 | "@jimp/plugin-crop": "^1.6.0", | ||
| 26 | "@jimp/plugin-displace": "^1.6.0", | ||
| 27 | "@jimp/plugin-fisheye": "^1.6.0", | ||
| 28 | "@jimp/plugin-flip": "^1.6.0", | ||
| 29 | "@jimp/plugin-mask": "^1.6.0", | ||
| 30 | "@jimp/plugin-quantize": "^1.6.0", | ||
| 31 | "@jimp/plugin-rotate": "^1.6.0", | ||
| 32 | "@jimp/plugin-threshold": "^1.6.0", | ||
| 33 | "@jimp/wasm-avif": "^1.6.0", | ||
| 34 | "@jimp/wasm-jpeg": "^1.6.0", | ||
| 35 | "@jimp/wasm-png": "^1.6.0", | ||
| 36 | "@jimp/wasm-webp": "^1.6.0", | ||
| 17 | "@mozilla/readability": "^0.6.0", | 37 | "@mozilla/readability": "^0.6.0", |
| 18 | "@popperjs/core": "^2.11.8", | 38 | "@popperjs/core": "^2.11.8", |
| 19 | "@zeldafan0225/ai_horde": "^5.2.0", | 39 | "@zeldafan0225/ai_horde": "^5.2.0", |
| @@ -28,6 +48,7 @@ | |||
| 28 | "cookie-parser": "^1.4.6", | 48 | "cookie-parser": "^1.4.6", |
| 29 | "cookie-session": "^2.1.0", | 49 | "cookie-session": "^2.1.0", |
| 30 | "cors": "^2.8.5", | 50 | "cors": "^2.8.5", |
| 51 | "crc": "^4.3.2", | ||
| 31 | "csrf-sync": "^4.0.3", | 52 | "csrf-sync": "^4.0.3", |
| 32 | "diff-match-patch": "^1.0.5", | 53 | "diff-match-patch": "^1.0.5", |
| 33 | "dompurify": "^3.2.4", | 54 | "dompurify": "^3.2.4", |
| @@ -46,7 +67,6 @@ | |||
| 46 | "ip-regex": "^5.0.0", | 67 | "ip-regex": "^5.0.0", |
| 47 | "ipaddr.js": "^2.2.0", | 68 | "ipaddr.js": "^2.2.0", |
| 48 | "is-docker": "^3.0.0", | 69 | "is-docker": "^3.0.0", |
| 49 | "jimp": "^0.22.10", | ||
| 50 | "localforage": "^1.10.0", | 70 | "localforage": "^1.10.0", |
| 51 | "lodash": "^4.17.21", | 71 | "lodash": "^4.17.21", |
| 52 | "mime-types": "^2.1.35", | 72 | "mime-types": "^2.1.35", |
| @@ -57,7 +77,6 @@ | |||
| 57 | "node-persist": "^4.0.4", | 77 | "node-persist": "^4.0.4", |
| 58 | "open": "^8.4.2", | 78 | "open": "^8.4.2", |
| 59 | "png-chunk-text": "^1.0.0", | 79 | "png-chunk-text": "^1.0.0", |
| 60 | "png-chunks-encode": "^1.0.0", | ||
| 61 | "png-chunks-extract": "^1.0.0", | 80 | "png-chunks-extract": "^1.0.0", |
| 62 | "proxy-agent": "^6.5.0", | 81 | "proxy-agent": "^6.5.0", |
| 63 | "rate-limiter-flexible": "^5.0.5", | 82 | "rate-limiter-flexible": "^5.0.5", |
| @@ -102,7 +121,6 @@ | |||
| 102 | "@types/node": "^18.19.80", | 121 | "@types/node": "^18.19.80", |
| 103 | "@types/node-persist": "^3.1.8", | 122 | "@types/node-persist": "^3.1.8", |
| 104 | "@types/png-chunk-text": "^1.0.3", | 123 | "@types/png-chunk-text": "^1.0.3", |
| 105 | "@types/png-chunks-encode": "^1.0.2", | ||
| 106 | "@types/png-chunks-extract": "^1.0.2", | 124 | "@types/png-chunks-extract": "^1.0.2", |
| 107 | "@types/response-time": "^2.3.8", | 125 | "@types/response-time": "^2.3.8", |
| 108 | "@types/select2": "^4.0.63", | 126 | "@types/select2": "^4.0.63", |
| @@ -110,7 +128,8 @@ | |||
| 110 | "@types/write-file-atomic": "^4.0.3", | 128 | "@types/write-file-atomic": "^4.0.3", |
| 111 | "@types/yargs": "^17.0.33", | 129 | "@types/yargs": "^17.0.33", |
| 112 | "@types/yauzl": "^2.10.3", | 130 | "@types/yauzl": "^2.10.3", |
| 113 | "eslint": "^8.57.1" | 131 | "eslint": "^8.57.1", |
| 132 | "eslint-plugin-jsdoc": "^48.10.0" | ||
| 114 | }, | 133 | }, |
| 115 | "engines": { | 134 | "engines": { |
| 116 | "node": ">= 18" | 135 | "node": ">= 18" |
| @@ -147,6 +166,21 @@ | |||
| 147 | "integrity": "sha512-KlmTftToTtmb6aLVdne4NluS+POWputPF5J8v25UN/EQS+K9vahWEIe1NPRSFqBQclObkqHaj7JOnFrmnSm5MA==", | 166 | "integrity": "sha512-KlmTftToTtmb6aLVdne4NluS+POWputPF5J8v25UN/EQS+K9vahWEIe1NPRSFqBQclObkqHaj7JOnFrmnSm5MA==", |
| 148 | "license": "Apache-2.0" | 167 | "license": "Apache-2.0" |
| 149 | }, | 168 | }, |
| 169 | "node_modules/@es-joy/jsdoccomment": { | ||
| 170 | "version": "0.46.0", | ||
| 171 | "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.46.0.tgz", | ||
| 172 | "integrity": "sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==", | ||
| 173 | "dev": true, | ||
| 174 | "license": "MIT", | ||
| 175 | "dependencies": { | ||
| 176 | "comment-parser": "1.4.1", | ||
| 177 | "esquery": "^1.6.0", | ||
| 178 | "jsdoc-type-pratt-parser": "~4.0.0" | ||
| 179 | }, | ||
| 180 | "engines": { | ||
| 181 | "node": ">=16" | ||
| 182 | } | ||
| 183 | }, | ||
| 150 | "node_modules/@eslint-community/eslint-utils": { | 184 | "node_modules/@eslint-community/eslint-utils": { |
| 151 | "version": "4.4.0", | 185 | "version": "4.4.0", |
| 152 | "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", | 186 | "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", |
| @@ -412,7 +446,55 @@ | |||
| 412 | "@jimp/custom": ">=0.3.5" | 446 | "@jimp/custom": ">=0.3.5" |
| 413 | } | 447 | } |
| 414 | }, | 448 | }, |
| 449 | "node_modules/@jimp/bmp/node_modules/@jimp/utils": { | ||
| 450 | "version": "0.22.12", | ||
| 451 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", | ||
| 452 | "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", | ||
| 453 | "license": "MIT", | ||
| 454 | "dependencies": { | ||
| 455 | "regenerator-runtime": "^0.13.3" | ||
| 456 | } | ||
| 457 | }, | ||
| 415 | "node_modules/@jimp/core": { | 458 | "node_modules/@jimp/core": { |
| 459 | "version": "1.6.0", | ||
| 460 | "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.0.tgz", | ||
| 461 | "integrity": "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==", | ||
| 462 | "license": "MIT", | ||
| 463 | "dependencies": { | ||
| 464 | "@jimp/file-ops": "1.6.0", | ||
| 465 | "@jimp/types": "1.6.0", | ||
| 466 | "@jimp/utils": "1.6.0", | ||
| 467 | "await-to-js": "^3.0.0", | ||
| 468 | "exif-parser": "^0.1.12", | ||
| 469 | "file-type": "^16.0.0", | ||
| 470 | "mime": "3" | ||
| 471 | }, | ||
| 472 | "engines": { | ||
| 473 | "node": ">=18" | ||
| 474 | } | ||
| 475 | }, | ||
| 476 | "node_modules/@jimp/core/node_modules/mime": { | ||
| 477 | "version": "3.0.0", | ||
| 478 | "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", | ||
| 479 | "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", | ||
| 480 | "license": "MIT", | ||
| 481 | "bin": { | ||
| 482 | "mime": "cli.js" | ||
| 483 | }, | ||
| 484 | "engines": { | ||
| 485 | "node": ">=10.0.0" | ||
| 486 | } | ||
| 487 | }, | ||
| 488 | "node_modules/@jimp/custom": { | ||
| 489 | "version": "0.22.12", | ||
| 490 | "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.12.tgz", | ||
| 491 | "integrity": "sha512-xcmww1O/JFP2MrlGUMd3Q78S3Qu6W3mYTXYuIqFq33EorgYHV/HqymHfXy9GjiCJ7OI+7lWx6nYFOzU7M4rd1Q==", | ||
| 492 | "license": "MIT", | ||
| 493 | "dependencies": { | ||
| 494 | "@jimp/core": "^0.22.12" | ||
| 495 | } | ||
| 496 | }, | ||
| 497 | "node_modules/@jimp/custom/node_modules/@jimp/core": { | ||
| 416 | "version": "0.22.12", | 498 | "version": "0.22.12", |
| 417 | "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.22.12.tgz", | 499 | "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.22.12.tgz", |
| 418 | "integrity": "sha512-l0RR0dOPyzMKfjUW1uebzueFEDtCOj9fN6pyTYWWOM/VS4BciXQ1VVrJs8pO3kycGYZxncRKhCoygbNr8eEZQA==", | 500 | "integrity": "sha512-l0RR0dOPyzMKfjUW1uebzueFEDtCOj9fN6pyTYWWOM/VS4BciXQ1VVrJs8pO3kycGYZxncRKhCoygbNr8eEZQA==", |
| @@ -428,13 +510,67 @@ | |||
| 428 | "tinycolor2": "^1.6.0" | 510 | "tinycolor2": "^1.6.0" |
| 429 | } | 511 | } |
| 430 | }, | 512 | }, |
| 431 | "node_modules/@jimp/custom": { | 513 | "node_modules/@jimp/custom/node_modules/@jimp/utils": { |
| 432 | "version": "0.22.12", | 514 | "version": "0.22.12", |
| 433 | "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.12.tgz", | 515 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", |
| 434 | "integrity": "sha512-xcmww1O/JFP2MrlGUMd3Q78S3Qu6W3mYTXYuIqFq33EorgYHV/HqymHfXy9GjiCJ7OI+7lWx6nYFOzU7M4rd1Q==", | 516 | "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", |
| 435 | "license": "MIT", | 517 | "license": "MIT", |
| 436 | "dependencies": { | 518 | "dependencies": { |
| 437 | "@jimp/core": "^0.22.12" | 519 | "regenerator-runtime": "^0.13.3" |
| 520 | } | ||
| 521 | }, | ||
| 522 | "node_modules/@jimp/custom/node_modules/buffer": { | ||
| 523 | "version": "5.7.1", | ||
| 524 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", | ||
| 525 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", | ||
| 526 | "funding": [ | ||
| 527 | { | ||
| 528 | "type": "github", | ||
| 529 | "url": "https://github.com/sponsors/feross" | ||
| 530 | }, | ||
| 531 | { | ||
| 532 | "type": "patreon", | ||
| 533 | "url": "https://www.patreon.com/feross" | ||
| 534 | }, | ||
| 535 | { | ||
| 536 | "type": "consulting", | ||
| 537 | "url": "https://feross.org/support" | ||
| 538 | } | ||
| 539 | ], | ||
| 540 | "license": "MIT", | ||
| 541 | "dependencies": { | ||
| 542 | "base64-js": "^1.3.1", | ||
| 543 | "ieee754": "^1.1.13" | ||
| 544 | } | ||
| 545 | }, | ||
| 546 | "node_modules/@jimp/custom/node_modules/pixelmatch": { | ||
| 547 | "version": "4.0.2", | ||
| 548 | "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", | ||
| 549 | "integrity": "sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==", | ||
| 550 | "license": "ISC", | ||
| 551 | "dependencies": { | ||
| 552 | "pngjs": "^3.0.0" | ||
| 553 | }, | ||
| 554 | "bin": { | ||
| 555 | "pixelmatch": "bin/pixelmatch" | ||
| 556 | } | ||
| 557 | }, | ||
| 558 | "node_modules/@jimp/custom/node_modules/pngjs": { | ||
| 559 | "version": "3.4.0", | ||
| 560 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", | ||
| 561 | "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", | ||
| 562 | "license": "MIT", | ||
| 563 | "engines": { | ||
| 564 | "node": ">=4.0.0" | ||
| 565 | } | ||
| 566 | }, | ||
| 567 | "node_modules/@jimp/file-ops": { | ||
| 568 | "version": "1.6.0", | ||
| 569 | "resolved": "https://registry.npmjs.org/@jimp/file-ops/-/file-ops-1.6.0.tgz", | ||
| 570 | "integrity": "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==", | ||
| 571 | "license": "MIT", | ||
| 572 | "engines": { | ||
| 573 | "node": ">=18" | ||
| 438 | } | 574 | } |
| 439 | }, | 575 | }, |
| 440 | "node_modules/@jimp/gif": { | 576 | "node_modules/@jimp/gif": { |
| @@ -451,6 +587,15 @@ | |||
| 451 | "@jimp/custom": ">=0.3.5" | 587 | "@jimp/custom": ">=0.3.5" |
| 452 | } | 588 | } |
| 453 | }, | 589 | }, |
| 590 | "node_modules/@jimp/gif/node_modules/@jimp/utils": { | ||
| 591 | "version": "0.22.12", | ||
| 592 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", | ||
| 593 | "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", | ||
| 594 | "license": "MIT", | ||
| 595 | "dependencies": { | ||
| 596 | "regenerator-runtime": "^0.13.3" | ||
| 597 | } | ||
| 598 | }, | ||
| 454 | "node_modules/@jimp/jpeg": { | 599 | "node_modules/@jimp/jpeg": { |
| 455 | "version": "0.22.12", | 600 | "version": "0.22.12", |
| 456 | "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.22.12.tgz", | 601 | "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.22.12.tgz", |
| @@ -464,10 +609,237 @@ | |||
| 464 | "@jimp/custom": ">=0.3.5" | 609 | "@jimp/custom": ">=0.3.5" |
| 465 | } | 610 | } |
| 466 | }, | 611 | }, |
| 612 | "node_modules/@jimp/jpeg/node_modules/@jimp/utils": { | ||
| 613 | "version": "0.22.12", | ||
| 614 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", | ||
| 615 | "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", | ||
| 616 | "license": "MIT", | ||
| 617 | "dependencies": { | ||
| 618 | "regenerator-runtime": "^0.13.3" | ||
| 619 | } | ||
| 620 | }, | ||
| 621 | "node_modules/@jimp/js-bmp": { | ||
| 622 | "version": "1.6.0", | ||
| 623 | "resolved": "https://registry.npmjs.org/@jimp/js-bmp/-/js-bmp-1.6.0.tgz", | ||
| 624 | "integrity": "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==", | ||
| 625 | "license": "MIT", | ||
| 626 | "dependencies": { | ||
| 627 | "@jimp/core": "1.6.0", | ||
| 628 | "@jimp/types": "1.6.0", | ||
| 629 | "@jimp/utils": "1.6.0", | ||
| 630 | "bmp-ts": "^1.0.9" | ||
| 631 | }, | ||
| 632 | "engines": { | ||
| 633 | "node": ">=18" | ||
| 634 | } | ||
| 635 | }, | ||
| 636 | "node_modules/@jimp/js-gif": { | ||
| 637 | "version": "1.6.0", | ||
| 638 | "resolved": "https://registry.npmjs.org/@jimp/js-gif/-/js-gif-1.6.0.tgz", | ||
| 639 | "integrity": "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==", | ||
| 640 | "license": "MIT", | ||
| 641 | "dependencies": { | ||
| 642 | "@jimp/core": "1.6.0", | ||
| 643 | "@jimp/types": "1.6.0", | ||
| 644 | "gifwrap": "^0.10.1", | ||
| 645 | "omggif": "^1.0.10" | ||
| 646 | }, | ||
| 647 | "engines": { | ||
| 648 | "node": ">=18" | ||
| 649 | } | ||
| 650 | }, | ||
| 651 | "node_modules/@jimp/js-jpeg": { | ||
| 652 | "version": "1.6.0", | ||
| 653 | "resolved": "https://registry.npmjs.org/@jimp/js-jpeg/-/js-jpeg-1.6.0.tgz", | ||
| 654 | "integrity": "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==", | ||
| 655 | "license": "MIT", | ||
| 656 | "dependencies": { | ||
| 657 | "@jimp/core": "1.6.0", | ||
| 658 | "@jimp/types": "1.6.0", | ||
| 659 | "jpeg-js": "^0.4.4" | ||
| 660 | }, | ||
| 661 | "engines": { | ||
| 662 | "node": ">=18" | ||
| 663 | } | ||
| 664 | }, | ||
| 665 | "node_modules/@jimp/js-png": { | ||
| 666 | "version": "1.6.0", | ||
| 667 | "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.0.tgz", | ||
| 668 | "integrity": "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==", | ||
| 669 | "license": "MIT", | ||
| 670 | "dependencies": { | ||
| 671 | "@jimp/core": "1.6.0", | ||
| 672 | "@jimp/types": "1.6.0", | ||
| 673 | "pngjs": "^7.0.0" | ||
| 674 | }, | ||
| 675 | "engines": { | ||
| 676 | "node": ">=18" | ||
| 677 | } | ||
| 678 | }, | ||
| 679 | "node_modules/@jimp/js-tiff": { | ||
| 680 | "version": "1.6.0", | ||
| 681 | "resolved": "https://registry.npmjs.org/@jimp/js-tiff/-/js-tiff-1.6.0.tgz", | ||
| 682 | "integrity": "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==", | ||
| 683 | "license": "MIT", | ||
| 684 | "dependencies": { | ||
| 685 | "@jimp/core": "1.6.0", | ||
| 686 | "@jimp/types": "1.6.0", | ||
| 687 | "utif2": "^4.1.0" | ||
| 688 | }, | ||
| 689 | "engines": { | ||
| 690 | "node": ">=18" | ||
| 691 | } | ||
| 692 | }, | ||
| 467 | "node_modules/@jimp/plugin-blit": { | 693 | "node_modules/@jimp/plugin-blit": { |
| 694 | "version": "1.6.0", | ||
| 695 | "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-1.6.0.tgz", | ||
| 696 | "integrity": "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==", | ||
| 697 | "license": "MIT", | ||
| 698 | "dependencies": { | ||
| 699 | "@jimp/types": "1.6.0", | ||
| 700 | "@jimp/utils": "1.6.0", | ||
| 701 | "zod": "^3.23.8" | ||
| 702 | }, | ||
| 703 | "engines": { | ||
| 704 | "node": ">=18" | ||
| 705 | } | ||
| 706 | }, | ||
| 707 | "node_modules/@jimp/plugin-blur": { | ||
| 708 | "version": "1.6.0", | ||
| 709 | "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-1.6.0.tgz", | ||
| 710 | "integrity": "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==", | ||
| 711 | "license": "MIT", | ||
| 712 | "peer": true, | ||
| 713 | "dependencies": { | ||
| 714 | "@jimp/core": "1.6.0", | ||
| 715 | "@jimp/utils": "1.6.0" | ||
| 716 | }, | ||
| 717 | "engines": { | ||
| 718 | "node": ">=18" | ||
| 719 | } | ||
| 720 | }, | ||
| 721 | "node_modules/@jimp/plugin-circle": { | ||
| 722 | "version": "1.6.0", | ||
| 723 | "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-1.6.0.tgz", | ||
| 724 | "integrity": "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==", | ||
| 725 | "license": "MIT", | ||
| 726 | "dependencies": { | ||
| 727 | "@jimp/types": "1.6.0", | ||
| 728 | "zod": "^3.23.8" | ||
| 729 | }, | ||
| 730 | "engines": { | ||
| 731 | "node": ">=18" | ||
| 732 | } | ||
| 733 | }, | ||
| 734 | "node_modules/@jimp/plugin-color": { | ||
| 735 | "version": "1.6.0", | ||
| 736 | "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-1.6.0.tgz", | ||
| 737 | "integrity": "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==", | ||
| 738 | "license": "MIT", | ||
| 739 | "dependencies": { | ||
| 740 | "@jimp/core": "1.6.0", | ||
| 741 | "@jimp/types": "1.6.0", | ||
| 742 | "@jimp/utils": "1.6.0", | ||
| 743 | "tinycolor2": "^1.6.0", | ||
| 744 | "zod": "^3.23.8" | ||
| 745 | }, | ||
| 746 | "engines": { | ||
| 747 | "node": ">=18" | ||
| 748 | } | ||
| 749 | }, | ||
| 750 | "node_modules/@jimp/plugin-contain": { | ||
| 751 | "version": "1.6.0", | ||
| 752 | "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-1.6.0.tgz", | ||
| 753 | "integrity": "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==", | ||
| 754 | "license": "MIT", | ||
| 755 | "dependencies": { | ||
| 756 | "@jimp/core": "1.6.0", | ||
| 757 | "@jimp/plugin-blit": "1.6.0", | ||
| 758 | "@jimp/plugin-resize": "1.6.0", | ||
| 759 | "@jimp/types": "1.6.0", | ||
| 760 | "@jimp/utils": "1.6.0", | ||
| 761 | "zod": "^3.23.8" | ||
| 762 | }, | ||
| 763 | "engines": { | ||
| 764 | "node": ">=18" | ||
| 765 | } | ||
| 766 | }, | ||
| 767 | "node_modules/@jimp/plugin-cover": { | ||
| 768 | "version": "1.6.0", | ||
| 769 | "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-1.6.0.tgz", | ||
| 770 | "integrity": "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==", | ||
| 771 | "license": "MIT", | ||
| 772 | "dependencies": { | ||
| 773 | "@jimp/core": "1.6.0", | ||
| 774 | "@jimp/plugin-crop": "1.6.0", | ||
| 775 | "@jimp/plugin-resize": "1.6.0", | ||
| 776 | "@jimp/types": "1.6.0", | ||
| 777 | "zod": "^3.23.8" | ||
| 778 | }, | ||
| 779 | "engines": { | ||
| 780 | "node": ">=18" | ||
| 781 | } | ||
| 782 | }, | ||
| 783 | "node_modules/@jimp/plugin-crop": { | ||
| 784 | "version": "1.6.0", | ||
| 785 | "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-1.6.0.tgz", | ||
| 786 | "integrity": "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==", | ||
| 787 | "license": "MIT", | ||
| 788 | "dependencies": { | ||
| 789 | "@jimp/core": "1.6.0", | ||
| 790 | "@jimp/types": "1.6.0", | ||
| 791 | "@jimp/utils": "1.6.0", | ||
| 792 | "zod": "^3.23.8" | ||
| 793 | }, | ||
| 794 | "engines": { | ||
| 795 | "node": ">=18" | ||
| 796 | } | ||
| 797 | }, | ||
| 798 | "node_modules/@jimp/plugin-displace": { | ||
| 799 | "version": "1.6.0", | ||
| 800 | "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-1.6.0.tgz", | ||
| 801 | "integrity": "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==", | ||
| 802 | "license": "MIT", | ||
| 803 | "dependencies": { | ||
| 804 | "@jimp/types": "1.6.0", | ||
| 805 | "@jimp/utils": "1.6.0", | ||
| 806 | "zod": "^3.23.8" | ||
| 807 | }, | ||
| 808 | "engines": { | ||
| 809 | "node": ">=18" | ||
| 810 | } | ||
| 811 | }, | ||
| 812 | "node_modules/@jimp/plugin-fisheye": { | ||
| 813 | "version": "1.6.0", | ||
| 814 | "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-1.6.0.tgz", | ||
| 815 | "integrity": "sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==", | ||
| 816 | "license": "MIT", | ||
| 817 | "dependencies": { | ||
| 818 | "@jimp/types": "1.6.0", | ||
| 819 | "@jimp/utils": "1.6.0", | ||
| 820 | "zod": "^3.23.8" | ||
| 821 | }, | ||
| 822 | "engines": { | ||
| 823 | "node": ">=18" | ||
| 824 | } | ||
| 825 | }, | ||
| 826 | "node_modules/@jimp/plugin-flip": { | ||
| 827 | "version": "1.6.0", | ||
| 828 | "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-1.6.0.tgz", | ||
| 829 | "integrity": "sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==", | ||
| 830 | "license": "MIT", | ||
| 831 | "dependencies": { | ||
| 832 | "@jimp/types": "1.6.0", | ||
| 833 | "zod": "^3.23.8" | ||
| 834 | }, | ||
| 835 | "engines": { | ||
| 836 | "node": ">=18" | ||
| 837 | } | ||
| 838 | }, | ||
| 839 | "node_modules/@jimp/plugin-gaussian": { | ||
| 468 | "version": "0.22.12", | 840 | "version": "0.22.12", |
| 469 | "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.22.12.tgz", | 841 | "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.22.12.tgz", |
| 470 | "integrity": "sha512-xslz2ZoFZOPLY8EZ4dC29m168BtDx95D6K80TzgUi8gqT7LY6CsajWO0FAxDwHz6h0eomHMfyGX0stspBrTKnQ==", | 842 | "integrity": "sha512-sBfbzoOmJ6FczfG2PquiK84NtVGeScw97JsCC3rpQv1PHVWyW+uqWFF53+n3c8Y0P2HWlUjflEla2h/vWShvhg==", |
| 471 | "license": "MIT", | 843 | "license": "MIT", |
| 472 | "dependencies": { | 844 | "dependencies": { |
| 473 | "@jimp/utils": "^0.22.12" | 845 | "@jimp/utils": "^0.22.12" |
| @@ -476,10 +848,40 @@ | |||
| 476 | "@jimp/custom": ">=0.3.5" | 848 | "@jimp/custom": ">=0.3.5" |
| 477 | } | 849 | } |
| 478 | }, | 850 | }, |
| 479 | "node_modules/@jimp/plugin-blur": { | 851 | "node_modules/@jimp/plugin-gaussian/node_modules/@jimp/utils": { |
| 480 | "version": "0.22.12", | 852 | "version": "0.22.12", |
| 481 | "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.22.12.tgz", | 853 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", |
| 482 | "integrity": "sha512-S0vJADTuh1Q9F+cXAwFPlrKWzDj2F9t/9JAbUvaaDuivpyWuImEKXVz5PUZw2NbpuSHjwssbTpOZ8F13iJX4uw==", | 854 | "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", |
| 855 | "license": "MIT", | ||
| 856 | "dependencies": { | ||
| 857 | "regenerator-runtime": "^0.13.3" | ||
| 858 | } | ||
| 859 | }, | ||
| 860 | "node_modules/@jimp/plugin-hash": { | ||
| 861 | "version": "1.6.0", | ||
| 862 | "resolved": "https://registry.npmjs.org/@jimp/plugin-hash/-/plugin-hash-1.6.0.tgz", | ||
| 863 | "integrity": "sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==", | ||
| 864 | "license": "MIT", | ||
| 865 | "dependencies": { | ||
| 866 | "@jimp/core": "1.6.0", | ||
| 867 | "@jimp/js-bmp": "1.6.0", | ||
| 868 | "@jimp/js-jpeg": "1.6.0", | ||
| 869 | "@jimp/js-png": "1.6.0", | ||
| 870 | "@jimp/js-tiff": "1.6.0", | ||
| 871 | "@jimp/plugin-color": "1.6.0", | ||
| 872 | "@jimp/plugin-resize": "1.6.0", | ||
| 873 | "@jimp/types": "1.6.0", | ||
| 874 | "@jimp/utils": "1.6.0", | ||
| 875 | "any-base": "^1.1.0" | ||
| 876 | }, | ||
| 877 | "engines": { | ||
| 878 | "node": ">=18" | ||
| 879 | } | ||
| 880 | }, | ||
| 881 | "node_modules/@jimp/plugin-invert": { | ||
| 882 | "version": "0.22.12", | ||
| 883 | "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.22.12.tgz", | ||
| 884 | "integrity": "sha512-N+6rwxdB+7OCR6PYijaA/iizXXodpxOGvT/smd/lxeXsZ/empHmFFFJ/FaXcYh19Tm04dGDaXcNF/dN5nm6+xQ==", | ||
| 483 | "license": "MIT", | 885 | "license": "MIT", |
| 484 | "dependencies": { | 886 | "dependencies": { |
| 485 | "@jimp/utils": "^0.22.12" | 887 | "@jimp/utils": "^0.22.12" |
| @@ -488,10 +890,32 @@ | |||
| 488 | "@jimp/custom": ">=0.3.5" | 890 | "@jimp/custom": ">=0.3.5" |
| 489 | } | 891 | } |
| 490 | }, | 892 | }, |
| 491 | "node_modules/@jimp/plugin-circle": { | 893 | "node_modules/@jimp/plugin-invert/node_modules/@jimp/utils": { |
| 492 | "version": "0.22.12", | 894 | "version": "0.22.12", |
| 493 | "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.22.12.tgz", | 895 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", |
| 494 | "integrity": "sha512-SWVXx1yiuj5jZtMijqUfvVOJBwOifFn0918ou4ftoHgegc5aHWW5dZbYPjvC9fLpvz7oSlptNl2Sxr1zwofjTg==", | 896 | "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", |
| 897 | "license": "MIT", | ||
| 898 | "dependencies": { | ||
| 899 | "regenerator-runtime": "^0.13.3" | ||
| 900 | } | ||
| 901 | }, | ||
| 902 | "node_modules/@jimp/plugin-mask": { | ||
| 903 | "version": "1.6.0", | ||
| 904 | "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-1.6.0.tgz", | ||
| 905 | "integrity": "sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==", | ||
| 906 | "license": "MIT", | ||
| 907 | "dependencies": { | ||
| 908 | "@jimp/types": "1.6.0", | ||
| 909 | "zod": "^3.23.8" | ||
| 910 | }, | ||
| 911 | "engines": { | ||
| 912 | "node": ">=18" | ||
| 913 | } | ||
| 914 | }, | ||
| 915 | "node_modules/@jimp/plugin-normalize": { | ||
| 916 | "version": "0.22.12", | ||
| 917 | "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.22.12.tgz", | ||
| 918 | "integrity": "sha512-0So0rexQivnWgnhacX4cfkM2223YdExnJTTy6d06WbkfZk5alHUx8MM3yEzwoCN0ErO7oyqEWRnEkGC+As1FtA==", | ||
| 495 | "license": "MIT", | 919 | "license": "MIT", |
| 496 | "dependencies": { | 920 | "dependencies": { |
| 497 | "@jimp/utils": "^0.22.12" | 921 | "@jimp/utils": "^0.22.12" |
| @@ -500,65 +924,158 @@ | |||
| 500 | "@jimp/custom": ">=0.3.5" | 924 | "@jimp/custom": ">=0.3.5" |
| 501 | } | 925 | } |
| 502 | }, | 926 | }, |
| 503 | "node_modules/@jimp/plugin-color": { | 927 | "node_modules/@jimp/plugin-normalize/node_modules/@jimp/utils": { |
| 504 | "version": "0.22.12", | 928 | "version": "0.22.12", |
| 505 | "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.22.12.tgz", | 929 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", |
| 506 | "integrity": "sha512-xImhTE5BpS8xa+mAN6j4sMRWaUgUDLoaGHhJhpC+r7SKKErYDR0WQV4yCE4gP+N0gozD0F3Ka1LUSaMXrn7ZIA==", | 930 | "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", |
| 507 | "license": "MIT", | 931 | "license": "MIT", |
| 508 | "dependencies": { | 932 | "dependencies": { |
| 509 | "@jimp/utils": "^0.22.12", | 933 | "regenerator-runtime": "^0.13.3" |
| 510 | "tinycolor2": "^1.6.0" | 934 | } |
| 935 | }, | ||
| 936 | "node_modules/@jimp/plugin-quantize": { | ||
| 937 | "version": "1.6.0", | ||
| 938 | "resolved": "https://registry.npmjs.org/@jimp/plugin-quantize/-/plugin-quantize-1.6.0.tgz", | ||
| 939 | "integrity": "sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==", | ||
| 940 | "license": "MIT", | ||
| 941 | "dependencies": { | ||
| 942 | "image-q": "^4.0.0", | ||
| 943 | "zod": "^3.23.8" | ||
| 511 | }, | 944 | }, |
| 512 | "peerDependencies": { | 945 | "engines": { |
| 513 | "@jimp/custom": ">=0.3.5" | 946 | "node": ">=18" |
| 514 | } | 947 | } |
| 515 | }, | 948 | }, |
| 516 | "node_modules/@jimp/plugin-contain": { | 949 | "node_modules/@jimp/plugin-resize": { |
| 950 | "version": "1.6.0", | ||
| 951 | "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-1.6.0.tgz", | ||
| 952 | "integrity": "sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==", | ||
| 953 | "license": "MIT", | ||
| 954 | "dependencies": { | ||
| 955 | "@jimp/core": "1.6.0", | ||
| 956 | "@jimp/types": "1.6.0", | ||
| 957 | "zod": "^3.23.8" | ||
| 958 | }, | ||
| 959 | "engines": { | ||
| 960 | "node": ">=18" | ||
| 961 | } | ||
| 962 | }, | ||
| 963 | "node_modules/@jimp/plugin-rotate": { | ||
| 964 | "version": "1.6.0", | ||
| 965 | "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-1.6.0.tgz", | ||
| 966 | "integrity": "sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==", | ||
| 967 | "license": "MIT", | ||
| 968 | "dependencies": { | ||
| 969 | "@jimp/core": "1.6.0", | ||
| 970 | "@jimp/plugin-crop": "1.6.0", | ||
| 971 | "@jimp/plugin-resize": "1.6.0", | ||
| 972 | "@jimp/types": "1.6.0", | ||
| 973 | "@jimp/utils": "1.6.0", | ||
| 974 | "zod": "^3.23.8" | ||
| 975 | }, | ||
| 976 | "engines": { | ||
| 977 | "node": ">=18" | ||
| 978 | } | ||
| 979 | }, | ||
| 980 | "node_modules/@jimp/plugin-scale": { | ||
| 517 | "version": "0.22.12", | 981 | "version": "0.22.12", |
| 518 | "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.22.12.tgz", | 982 | "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.22.12.tgz", |
| 519 | "integrity": "sha512-Eo3DmfixJw3N79lWk8q/0SDYbqmKt1xSTJ69yy8XLYQj9svoBbyRpSnHR+n9hOw5pKXytHwUW6nU4u1wegHNoQ==", | 983 | "integrity": "sha512-dghs92qM6MhHj0HrV2qAwKPMklQtjNpoYgAB94ysYpsXslhRTiPisueSIELRwZGEr0J0VUxpUY7HgJwlSIgGZw==", |
| 520 | "license": "MIT", | 984 | "license": "MIT", |
| 521 | "dependencies": { | 985 | "dependencies": { |
| 522 | "@jimp/utils": "^0.22.12" | 986 | "@jimp/utils": "^0.22.12" |
| 523 | }, | 987 | }, |
| 524 | "peerDependencies": { | 988 | "peerDependencies": { |
| 525 | "@jimp/custom": ">=0.3.5", | 989 | "@jimp/custom": ">=0.3.5", |
| 526 | "@jimp/plugin-blit": ">=0.3.5", | 990 | "@jimp/plugin-resize": ">=0.3.5" |
| 527 | "@jimp/plugin-resize": ">=0.3.5", | ||
| 528 | "@jimp/plugin-scale": ">=0.3.5" | ||
| 529 | } | 991 | } |
| 530 | }, | 992 | }, |
| 531 | "node_modules/@jimp/plugin-cover": { | 993 | "node_modules/@jimp/plugin-scale/node_modules/@jimp/utils": { |
| 532 | "version": "0.22.12", | 994 | "version": "0.22.12", |
| 533 | "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.22.12.tgz", | 995 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", |
| 534 | "integrity": "sha512-z0w/1xH/v/knZkpTNx+E8a7fnasQ2wHG5ze6y5oL2dhH1UufNua8gLQXlv8/W56+4nJ1brhSd233HBJCo01BXA==", | 996 | "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", |
| 997 | "license": "MIT", | ||
| 998 | "dependencies": { | ||
| 999 | "regenerator-runtime": "^0.13.3" | ||
| 1000 | } | ||
| 1001 | }, | ||
| 1002 | "node_modules/@jimp/plugin-shadow": { | ||
| 1003 | "version": "0.22.12", | ||
| 1004 | "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.22.12.tgz", | ||
| 1005 | "integrity": "sha512-FX8mTJuCt7/3zXVoeD/qHlm4YH2bVqBuWQHXSuBK054e7wFRnRnbSLPUqAwSeYP3lWqpuQzJtgiiBxV3+WWwTg==", | ||
| 535 | "license": "MIT", | 1006 | "license": "MIT", |
| 536 | "dependencies": { | 1007 | "dependencies": { |
| 537 | "@jimp/utils": "^0.22.12" | 1008 | "@jimp/utils": "^0.22.12" |
| 538 | }, | 1009 | }, |
| 539 | "peerDependencies": { | 1010 | "peerDependencies": { |
| 540 | "@jimp/custom": ">=0.3.5", | 1011 | "@jimp/custom": ">=0.3.5", |
| 541 | "@jimp/plugin-crop": ">=0.3.5", | 1012 | "@jimp/plugin-blur": ">=0.3.5", |
| 542 | "@jimp/plugin-resize": ">=0.3.5", | 1013 | "@jimp/plugin-resize": ">=0.3.5" |
| 543 | "@jimp/plugin-scale": ">=0.3.5" | ||
| 544 | } | 1014 | } |
| 545 | }, | 1015 | }, |
| 546 | "node_modules/@jimp/plugin-crop": { | 1016 | "node_modules/@jimp/plugin-shadow/node_modules/@jimp/utils": { |
| 547 | "version": "0.22.12", | 1017 | "version": "0.22.12", |
| 548 | "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.22.12.tgz", | 1018 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", |
| 549 | "integrity": "sha512-FNuUN0OVzRCozx8XSgP9MyLGMxNHHJMFt+LJuFjn1mu3k0VQxrzqbN06yIl46TVejhyAhcq5gLzqmSCHvlcBVw==", | 1019 | "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", |
| 550 | "license": "MIT", | 1020 | "license": "MIT", |
| 551 | "dependencies": { | 1021 | "dependencies": { |
| 552 | "@jimp/utils": "^0.22.12" | 1022 | "regenerator-runtime": "^0.13.3" |
| 1023 | } | ||
| 1024 | }, | ||
| 1025 | "node_modules/@jimp/plugin-threshold": { | ||
| 1026 | "version": "1.6.0", | ||
| 1027 | "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz", | ||
| 1028 | "integrity": "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==", | ||
| 1029 | "license": "MIT", | ||
| 1030 | "dependencies": { | ||
| 1031 | "@jimp/core": "1.6.0", | ||
| 1032 | "@jimp/plugin-color": "1.6.0", | ||
| 1033 | "@jimp/plugin-hash": "1.6.0", | ||
| 1034 | "@jimp/types": "1.6.0", | ||
| 1035 | "@jimp/utils": "1.6.0", | ||
| 1036 | "zod": "^3.23.8" | ||
| 1037 | }, | ||
| 1038 | "engines": { | ||
| 1039 | "node": ">=18" | ||
| 1040 | } | ||
| 1041 | }, | ||
| 1042 | "node_modules/@jimp/plugins": { | ||
| 1043 | "version": "0.22.12", | ||
| 1044 | "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.22.12.tgz", | ||
| 1045 | "integrity": "sha512-yBJ8vQrDkBbTgQZLty9k4+KtUQdRjsIDJSPjuI21YdVeqZxYywifHl4/XWILoTZsjTUASQcGoH0TuC0N7xm3ww==", | ||
| 1046 | "license": "MIT", | ||
| 1047 | "dependencies": { | ||
| 1048 | "@jimp/plugin-blit": "^0.22.12", | ||
| 1049 | "@jimp/plugin-blur": "^0.22.12", | ||
| 1050 | "@jimp/plugin-circle": "^0.22.12", | ||
| 1051 | "@jimp/plugin-color": "^0.22.12", | ||
| 1052 | "@jimp/plugin-contain": "^0.22.12", | ||
| 1053 | "@jimp/plugin-cover": "^0.22.12", | ||
| 1054 | "@jimp/plugin-crop": "^0.22.12", | ||
| 1055 | "@jimp/plugin-displace": "^0.22.12", | ||
| 1056 | "@jimp/plugin-dither": "^0.22.12", | ||
| 1057 | "@jimp/plugin-fisheye": "^0.22.12", | ||
| 1058 | "@jimp/plugin-flip": "^0.22.12", | ||
| 1059 | "@jimp/plugin-gaussian": "^0.22.12", | ||
| 1060 | "@jimp/plugin-invert": "^0.22.12", | ||
| 1061 | "@jimp/plugin-mask": "^0.22.12", | ||
| 1062 | "@jimp/plugin-normalize": "^0.22.12", | ||
| 1063 | "@jimp/plugin-print": "^0.22.12", | ||
| 1064 | "@jimp/plugin-resize": "^0.22.12", | ||
| 1065 | "@jimp/plugin-rotate": "^0.22.12", | ||
| 1066 | "@jimp/plugin-scale": "^0.22.12", | ||
| 1067 | "@jimp/plugin-shadow": "^0.22.12", | ||
| 1068 | "@jimp/plugin-threshold": "^0.22.12", | ||
| 1069 | "timm": "^1.6.1" | ||
| 553 | }, | 1070 | }, |
| 554 | "peerDependencies": { | 1071 | "peerDependencies": { |
| 555 | "@jimp/custom": ">=0.3.5" | 1072 | "@jimp/custom": ">=0.3.5" |
| 556 | } | 1073 | } |
| 557 | }, | 1074 | }, |
| 558 | "node_modules/@jimp/plugin-displace": { | 1075 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-blit": { |
| 559 | "version": "0.22.12", | 1076 | "version": "0.22.12", |
| 560 | "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.22.12.tgz", | 1077 | "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.22.12.tgz", |
| 561 | "integrity": "sha512-qpRM8JRicxfK6aPPqKZA6+GzBwUIitiHaZw0QrJ64Ygd3+AsTc7BXr+37k2x7QcyCvmKXY4haUrSIsBug4S3CA==", | 1078 | "integrity": "sha512-xslz2ZoFZOPLY8EZ4dC29m168BtDx95D6K80TzgUi8gqT7LY6CsajWO0FAxDwHz6h0eomHMfyGX0stspBrTKnQ==", |
| 562 | "license": "MIT", | 1079 | "license": "MIT", |
| 563 | "dependencies": { | 1080 | "dependencies": { |
| 564 | "@jimp/utils": "^0.22.12" | 1081 | "@jimp/utils": "^0.22.12" |
| @@ -567,10 +1084,10 @@ | |||
| 567 | "@jimp/custom": ">=0.3.5" | 1084 | "@jimp/custom": ">=0.3.5" |
| 568 | } | 1085 | } |
| 569 | }, | 1086 | }, |
| 570 | "node_modules/@jimp/plugin-dither": { | 1087 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-blur": { |
| 571 | "version": "0.22.12", | 1088 | "version": "0.22.12", |
| 572 | "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.22.12.tgz", | 1089 | "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.22.12.tgz", |
| 573 | "integrity": "sha512-jYgGdSdSKl1UUEanX8A85v4+QUm+PE8vHFwlamaKk89s+PXQe7eVE3eNeSZX4inCq63EHL7cX580dMqkoC3ZLw==", | 1090 | "integrity": "sha512-S0vJADTuh1Q9F+cXAwFPlrKWzDj2F9t/9JAbUvaaDuivpyWuImEKXVz5PUZw2NbpuSHjwssbTpOZ8F13iJX4uw==", |
| 574 | "license": "MIT", | 1091 | "license": "MIT", |
| 575 | "dependencies": { | 1092 | "dependencies": { |
| 576 | "@jimp/utils": "^0.22.12" | 1093 | "@jimp/utils": "^0.22.12" |
| @@ -579,10 +1096,10 @@ | |||
| 579 | "@jimp/custom": ">=0.3.5" | 1096 | "@jimp/custom": ">=0.3.5" |
| 580 | } | 1097 | } |
| 581 | }, | 1098 | }, |
| 582 | "node_modules/@jimp/plugin-fisheye": { | 1099 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-circle": { |
| 583 | "version": "0.22.12", | 1100 | "version": "0.22.12", |
| 584 | "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.22.12.tgz", | 1101 | "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.22.12.tgz", |
| 585 | "integrity": "sha512-LGuUTsFg+fOp6KBKrmLkX4LfyCy8IIsROwoUvsUPKzutSqMJnsm3JGDW2eOmWIS/jJpPaeaishjlxvczjgII+Q==", | 1102 | "integrity": "sha512-SWVXx1yiuj5jZtMijqUfvVOJBwOifFn0918ou4ftoHgegc5aHWW5dZbYPjvC9fLpvz7oSlptNl2Sxr1zwofjTg==", |
| 586 | "license": "MIT", | 1103 | "license": "MIT", |
| 587 | "dependencies": { | 1104 | "dependencies": { |
| 588 | "@jimp/utils": "^0.22.12" | 1105 | "@jimp/utils": "^0.22.12" |
| @@ -591,23 +1108,53 @@ | |||
| 591 | "@jimp/custom": ">=0.3.5" | 1108 | "@jimp/custom": ">=0.3.5" |
| 592 | } | 1109 | } |
| 593 | }, | 1110 | }, |
| 594 | "node_modules/@jimp/plugin-flip": { | 1111 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-color": { |
| 595 | "version": "0.22.12", | 1112 | "version": "0.22.12", |
| 596 | "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.22.12.tgz", | 1113 | "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.22.12.tgz", |
| 597 | "integrity": "sha512-m251Rop7GN8W0Yo/rF9LWk6kNclngyjIJs/VXHToGQ6EGveOSTSQaX2Isi9f9lCDLxt+inBIb7nlaLLxnvHX8Q==", | 1114 | "integrity": "sha512-xImhTE5BpS8xa+mAN6j4sMRWaUgUDLoaGHhJhpC+r7SKKErYDR0WQV4yCE4gP+N0gozD0F3Ka1LUSaMXrn7ZIA==", |
| 1115 | "license": "MIT", | ||
| 1116 | "dependencies": { | ||
| 1117 | "@jimp/utils": "^0.22.12", | ||
| 1118 | "tinycolor2": "^1.6.0" | ||
| 1119 | }, | ||
| 1120 | "peerDependencies": { | ||
| 1121 | "@jimp/custom": ">=0.3.5" | ||
| 1122 | } | ||
| 1123 | }, | ||
| 1124 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-contain": { | ||
| 1125 | "version": "0.22.12", | ||
| 1126 | "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.22.12.tgz", | ||
| 1127 | "integrity": "sha512-Eo3DmfixJw3N79lWk8q/0SDYbqmKt1xSTJ69yy8XLYQj9svoBbyRpSnHR+n9hOw5pKXytHwUW6nU4u1wegHNoQ==", | ||
| 598 | "license": "MIT", | 1128 | "license": "MIT", |
| 599 | "dependencies": { | 1129 | "dependencies": { |
| 600 | "@jimp/utils": "^0.22.12" | 1130 | "@jimp/utils": "^0.22.12" |
| 601 | }, | 1131 | }, |
| 602 | "peerDependencies": { | 1132 | "peerDependencies": { |
| 603 | "@jimp/custom": ">=0.3.5", | 1133 | "@jimp/custom": ">=0.3.5", |
| 604 | "@jimp/plugin-rotate": ">=0.3.5" | 1134 | "@jimp/plugin-blit": ">=0.3.5", |
| 1135 | "@jimp/plugin-resize": ">=0.3.5", | ||
| 1136 | "@jimp/plugin-scale": ">=0.3.5" | ||
| 605 | } | 1137 | } |
| 606 | }, | 1138 | }, |
| 607 | "node_modules/@jimp/plugin-gaussian": { | 1139 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-cover": { |
| 608 | "version": "0.22.12", | 1140 | "version": "0.22.12", |
| 609 | "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.22.12.tgz", | 1141 | "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.22.12.tgz", |
| 610 | "integrity": "sha512-sBfbzoOmJ6FczfG2PquiK84NtVGeScw97JsCC3rpQv1PHVWyW+uqWFF53+n3c8Y0P2HWlUjflEla2h/vWShvhg==", | 1142 | "integrity": "sha512-z0w/1xH/v/knZkpTNx+E8a7fnasQ2wHG5ze6y5oL2dhH1UufNua8gLQXlv8/W56+4nJ1brhSd233HBJCo01BXA==", |
| 1143 | "license": "MIT", | ||
| 1144 | "dependencies": { | ||
| 1145 | "@jimp/utils": "^0.22.12" | ||
| 1146 | }, | ||
| 1147 | "peerDependencies": { | ||
| 1148 | "@jimp/custom": ">=0.3.5", | ||
| 1149 | "@jimp/plugin-crop": ">=0.3.5", | ||
| 1150 | "@jimp/plugin-resize": ">=0.3.5", | ||
| 1151 | "@jimp/plugin-scale": ">=0.3.5" | ||
| 1152 | } | ||
| 1153 | }, | ||
| 1154 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-crop": { | ||
| 1155 | "version": "0.22.12", | ||
| 1156 | "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.22.12.tgz", | ||
| 1157 | "integrity": "sha512-FNuUN0OVzRCozx8XSgP9MyLGMxNHHJMFt+LJuFjn1mu3k0VQxrzqbN06yIl46TVejhyAhcq5gLzqmSCHvlcBVw==", | ||
| 611 | "license": "MIT", | 1158 | "license": "MIT", |
| 612 | "dependencies": { | 1159 | "dependencies": { |
| 613 | "@jimp/utils": "^0.22.12" | 1160 | "@jimp/utils": "^0.22.12" |
| @@ -616,10 +1163,10 @@ | |||
| 616 | "@jimp/custom": ">=0.3.5" | 1163 | "@jimp/custom": ">=0.3.5" |
| 617 | } | 1164 | } |
| 618 | }, | 1165 | }, |
| 619 | "node_modules/@jimp/plugin-invert": { | 1166 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-displace": { |
| 620 | "version": "0.22.12", | 1167 | "version": "0.22.12", |
| 621 | "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.22.12.tgz", | 1168 | "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.22.12.tgz", |
| 622 | "integrity": "sha512-N+6rwxdB+7OCR6PYijaA/iizXXodpxOGvT/smd/lxeXsZ/empHmFFFJ/FaXcYh19Tm04dGDaXcNF/dN5nm6+xQ==", | 1169 | "integrity": "sha512-qpRM8JRicxfK6aPPqKZA6+GzBwUIitiHaZw0QrJ64Ygd3+AsTc7BXr+37k2x7QcyCvmKXY4haUrSIsBug4S3CA==", |
| 623 | "license": "MIT", | 1170 | "license": "MIT", |
| 624 | "dependencies": { | 1171 | "dependencies": { |
| 625 | "@jimp/utils": "^0.22.12" | 1172 | "@jimp/utils": "^0.22.12" |
| @@ -628,10 +1175,10 @@ | |||
| 628 | "@jimp/custom": ">=0.3.5" | 1175 | "@jimp/custom": ">=0.3.5" |
| 629 | } | 1176 | } |
| 630 | }, | 1177 | }, |
| 631 | "node_modules/@jimp/plugin-mask": { | 1178 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-dither": { |
| 632 | "version": "0.22.12", | 1179 | "version": "0.22.12", |
| 633 | "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.22.12.tgz", | 1180 | "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.22.12.tgz", |
| 634 | "integrity": "sha512-4AWZg+DomtpUA099jRV8IEZUfn1wLv6+nem4NRJC7L/82vxzLCgXKTxvNvBcNmJjT9yS1LAAmiJGdWKXG63/NA==", | 1181 | "integrity": "sha512-jYgGdSdSKl1UUEanX8A85v4+QUm+PE8vHFwlamaKk89s+PXQe7eVE3eNeSZX4inCq63EHL7cX580dMqkoC3ZLw==", |
| 635 | "license": "MIT", | 1182 | "license": "MIT", |
| 636 | "dependencies": { | 1183 | "dependencies": { |
| 637 | "@jimp/utils": "^0.22.12" | 1184 | "@jimp/utils": "^0.22.12" |
| @@ -640,10 +1187,10 @@ | |||
| 640 | "@jimp/custom": ">=0.3.5" | 1187 | "@jimp/custom": ">=0.3.5" |
| 641 | } | 1188 | } |
| 642 | }, | 1189 | }, |
| 643 | "node_modules/@jimp/plugin-normalize": { | 1190 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-fisheye": { |
| 644 | "version": "0.22.12", | 1191 | "version": "0.22.12", |
| 645 | "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.22.12.tgz", | 1192 | "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.22.12.tgz", |
| 646 | "integrity": "sha512-0So0rexQivnWgnhacX4cfkM2223YdExnJTTy6d06WbkfZk5alHUx8MM3yEzwoCN0ErO7oyqEWRnEkGC+As1FtA==", | 1193 | "integrity": "sha512-LGuUTsFg+fOp6KBKrmLkX4LfyCy8IIsROwoUvsUPKzutSqMJnsm3JGDW2eOmWIS/jJpPaeaishjlxvczjgII+Q==", |
| 647 | "license": "MIT", | 1194 | "license": "MIT", |
| 648 | "dependencies": { | 1195 | "dependencies": { |
| 649 | "@jimp/utils": "^0.22.12" | 1196 | "@jimp/utils": "^0.22.12" |
| @@ -652,24 +1199,23 @@ | |||
| 652 | "@jimp/custom": ">=0.3.5" | 1199 | "@jimp/custom": ">=0.3.5" |
| 653 | } | 1200 | } |
| 654 | }, | 1201 | }, |
| 655 | "node_modules/@jimp/plugin-print": { | 1202 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-flip": { |
| 656 | "version": "0.22.12", | 1203 | "version": "0.22.12", |
| 657 | "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.22.12.tgz", | 1204 | "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.22.12.tgz", |
| 658 | "integrity": "sha512-c7TnhHlxm87DJeSnwr/XOLjJU/whoiKYY7r21SbuJ5nuH+7a78EW1teOaj5gEr2wYEd7QtkFqGlmyGXY/YclyQ==", | 1205 | "integrity": "sha512-m251Rop7GN8W0Yo/rF9LWk6kNclngyjIJs/VXHToGQ6EGveOSTSQaX2Isi9f9lCDLxt+inBIb7nlaLLxnvHX8Q==", |
| 659 | "license": "MIT", | 1206 | "license": "MIT", |
| 660 | "dependencies": { | 1207 | "dependencies": { |
| 661 | "@jimp/utils": "^0.22.12", | 1208 | "@jimp/utils": "^0.22.12" |
| 662 | "load-bmfont": "^1.4.1" | ||
| 663 | }, | 1209 | }, |
| 664 | "peerDependencies": { | 1210 | "peerDependencies": { |
| 665 | "@jimp/custom": ">=0.3.5", | 1211 | "@jimp/custom": ">=0.3.5", |
| 666 | "@jimp/plugin-blit": ">=0.3.5" | 1212 | "@jimp/plugin-rotate": ">=0.3.5" |
| 667 | } | 1213 | } |
| 668 | }, | 1214 | }, |
| 669 | "node_modules/@jimp/plugin-resize": { | 1215 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-mask": { |
| 670 | "version": "0.22.12", | 1216 | "version": "0.22.12", |
| 671 | "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.22.12.tgz", | 1217 | "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.22.12.tgz", |
| 672 | "integrity": "sha512-3NyTPlPbTnGKDIbaBgQ3HbE6wXbAlFfxHVERmrbqAi8R3r6fQPxpCauA8UVDnieg5eo04D0T8nnnNIX//i/sXg==", | 1218 | "integrity": "sha512-4AWZg+DomtpUA099jRV8IEZUfn1wLv6+nem4NRJC7L/82vxzLCgXKTxvNvBcNmJjT9yS1LAAmiJGdWKXG63/NA==", |
| 673 | "license": "MIT", | 1219 | "license": "MIT", |
| 674 | "dependencies": { | 1220 | "dependencies": { |
| 675 | "@jimp/utils": "^0.22.12" | 1221 | "@jimp/utils": "^0.22.12" |
| @@ -678,49 +1224,48 @@ | |||
| 678 | "@jimp/custom": ">=0.3.5" | 1224 | "@jimp/custom": ">=0.3.5" |
| 679 | } | 1225 | } |
| 680 | }, | 1226 | }, |
| 681 | "node_modules/@jimp/plugin-rotate": { | 1227 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-print": { |
| 682 | "version": "0.22.12", | 1228 | "version": "0.22.12", |
| 683 | "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.22.12.tgz", | 1229 | "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.22.12.tgz", |
| 684 | "integrity": "sha512-9YNEt7BPAFfTls2FGfKBVgwwLUuKqy+E8bDGGEsOqHtbuhbshVGxN2WMZaD4gh5IDWvR+emmmPPWGgaYNYt1gA==", | 1230 | "integrity": "sha512-c7TnhHlxm87DJeSnwr/XOLjJU/whoiKYY7r21SbuJ5nuH+7a78EW1teOaj5gEr2wYEd7QtkFqGlmyGXY/YclyQ==", |
| 685 | "license": "MIT", | 1231 | "license": "MIT", |
| 686 | "dependencies": { | 1232 | "dependencies": { |
| 687 | "@jimp/utils": "^0.22.12" | 1233 | "@jimp/utils": "^0.22.12", |
| 1234 | "load-bmfont": "^1.4.1" | ||
| 688 | }, | 1235 | }, |
| 689 | "peerDependencies": { | 1236 | "peerDependencies": { |
| 690 | "@jimp/custom": ">=0.3.5", | 1237 | "@jimp/custom": ">=0.3.5", |
| 691 | "@jimp/plugin-blit": ">=0.3.5", | 1238 | "@jimp/plugin-blit": ">=0.3.5" |
| 692 | "@jimp/plugin-crop": ">=0.3.5", | ||
| 693 | "@jimp/plugin-resize": ">=0.3.5" | ||
| 694 | } | 1239 | } |
| 695 | }, | 1240 | }, |
| 696 | "node_modules/@jimp/plugin-scale": { | 1241 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-resize": { |
| 697 | "version": "0.22.12", | 1242 | "version": "0.22.12", |
| 698 | "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.22.12.tgz", | 1243 | "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.22.12.tgz", |
| 699 | "integrity": "sha512-dghs92qM6MhHj0HrV2qAwKPMklQtjNpoYgAB94ysYpsXslhRTiPisueSIELRwZGEr0J0VUxpUY7HgJwlSIgGZw==", | 1244 | "integrity": "sha512-3NyTPlPbTnGKDIbaBgQ3HbE6wXbAlFfxHVERmrbqAi8R3r6fQPxpCauA8UVDnieg5eo04D0T8nnnNIX//i/sXg==", |
| 700 | "license": "MIT", | 1245 | "license": "MIT", |
| 701 | "dependencies": { | 1246 | "dependencies": { |
| 702 | "@jimp/utils": "^0.22.12" | 1247 | "@jimp/utils": "^0.22.12" |
| 703 | }, | 1248 | }, |
| 704 | "peerDependencies": { | 1249 | "peerDependencies": { |
| 705 | "@jimp/custom": ">=0.3.5", | 1250 | "@jimp/custom": ">=0.3.5" |
| 706 | "@jimp/plugin-resize": ">=0.3.5" | ||
| 707 | } | 1251 | } |
| 708 | }, | 1252 | }, |
| 709 | "node_modules/@jimp/plugin-shadow": { | 1253 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-rotate": { |
| 710 | "version": "0.22.12", | 1254 | "version": "0.22.12", |
| 711 | "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.22.12.tgz", | 1255 | "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.22.12.tgz", |
| 712 | "integrity": "sha512-FX8mTJuCt7/3zXVoeD/qHlm4YH2bVqBuWQHXSuBK054e7wFRnRnbSLPUqAwSeYP3lWqpuQzJtgiiBxV3+WWwTg==", | 1256 | "integrity": "sha512-9YNEt7BPAFfTls2FGfKBVgwwLUuKqy+E8bDGGEsOqHtbuhbshVGxN2WMZaD4gh5IDWvR+emmmPPWGgaYNYt1gA==", |
| 713 | "license": "MIT", | 1257 | "license": "MIT", |
| 714 | "dependencies": { | 1258 | "dependencies": { |
| 715 | "@jimp/utils": "^0.22.12" | 1259 | "@jimp/utils": "^0.22.12" |
| 716 | }, | 1260 | }, |
| 717 | "peerDependencies": { | 1261 | "peerDependencies": { |
| 718 | "@jimp/custom": ">=0.3.5", | 1262 | "@jimp/custom": ">=0.3.5", |
| 719 | "@jimp/plugin-blur": ">=0.3.5", | 1263 | "@jimp/plugin-blit": ">=0.3.5", |
| 1264 | "@jimp/plugin-crop": ">=0.3.5", | ||
| 720 | "@jimp/plugin-resize": ">=0.3.5" | 1265 | "@jimp/plugin-resize": ">=0.3.5" |
| 721 | } | 1266 | } |
| 722 | }, | 1267 | }, |
| 723 | "node_modules/@jimp/plugin-threshold": { | 1268 | "node_modules/@jimp/plugins/node_modules/@jimp/plugin-threshold": { |
| 724 | "version": "0.22.12", | 1269 | "version": "0.22.12", |
| 725 | "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.22.12.tgz", | 1270 | "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.22.12.tgz", |
| 726 | "integrity": "sha512-4x5GrQr1a/9L0paBC/MZZJjjgjxLYrqSmWd+e+QfAEPvmRxdRoQ5uKEuNgXnm9/weHQBTnQBQsOY2iFja+XGAw==", | 1271 | "integrity": "sha512-4x5GrQr1a/9L0paBC/MZZJjjgjxLYrqSmWd+e+QfAEPvmRxdRoQ5uKEuNgXnm9/weHQBTnQBQsOY2iFja+XGAw==", |
| @@ -734,37 +1279,13 @@ | |||
| 734 | "@jimp/plugin-resize": ">=0.8.0" | 1279 | "@jimp/plugin-resize": ">=0.8.0" |
| 735 | } | 1280 | } |
| 736 | }, | 1281 | }, |
| 737 | "node_modules/@jimp/plugins": { | 1282 | "node_modules/@jimp/plugins/node_modules/@jimp/utils": { |
| 738 | "version": "0.22.12", | 1283 | "version": "0.22.12", |
| 739 | "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.22.12.tgz", | 1284 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", |
| 740 | "integrity": "sha512-yBJ8vQrDkBbTgQZLty9k4+KtUQdRjsIDJSPjuI21YdVeqZxYywifHl4/XWILoTZsjTUASQcGoH0TuC0N7xm3ww==", | 1285 | "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", |
| 741 | "license": "MIT", | 1286 | "license": "MIT", |
| 742 | "dependencies": { | 1287 | "dependencies": { |
| 743 | "@jimp/plugin-blit": "^0.22.12", | 1288 | "regenerator-runtime": "^0.13.3" |
| 744 | "@jimp/plugin-blur": "^0.22.12", | ||
| 745 | "@jimp/plugin-circle": "^0.22.12", | ||
| 746 | "@jimp/plugin-color": "^0.22.12", | ||
| 747 | "@jimp/plugin-contain": "^0.22.12", | ||
| 748 | "@jimp/plugin-cover": "^0.22.12", | ||
| 749 | "@jimp/plugin-crop": "^0.22.12", | ||
| 750 | "@jimp/plugin-displace": "^0.22.12", | ||
| 751 | "@jimp/plugin-dither": "^0.22.12", | ||
| 752 | "@jimp/plugin-fisheye": "^0.22.12", | ||
| 753 | "@jimp/plugin-flip": "^0.22.12", | ||
| 754 | "@jimp/plugin-gaussian": "^0.22.12", | ||
| 755 | "@jimp/plugin-invert": "^0.22.12", | ||
| 756 | "@jimp/plugin-mask": "^0.22.12", | ||
| 757 | "@jimp/plugin-normalize": "^0.22.12", | ||
| 758 | "@jimp/plugin-print": "^0.22.12", | ||
| 759 | "@jimp/plugin-resize": "^0.22.12", | ||
| 760 | "@jimp/plugin-rotate": "^0.22.12", | ||
| 761 | "@jimp/plugin-scale": "^0.22.12", | ||
| 762 | "@jimp/plugin-shadow": "^0.22.12", | ||
| 763 | "@jimp/plugin-threshold": "^0.22.12", | ||
| 764 | "timm": "^1.6.1" | ||
| 765 | }, | ||
| 766 | "peerDependencies": { | ||
| 767 | "@jimp/custom": ">=0.3.5" | ||
| 768 | } | 1289 | } |
| 769 | }, | 1290 | }, |
| 770 | "node_modules/@jimp/png": { | 1291 | "node_modules/@jimp/png": { |
| @@ -780,6 +1301,24 @@ | |||
| 780 | "@jimp/custom": ">=0.3.5" | 1301 | "@jimp/custom": ">=0.3.5" |
| 781 | } | 1302 | } |
| 782 | }, | 1303 | }, |
| 1304 | "node_modules/@jimp/png/node_modules/@jimp/utils": { | ||
| 1305 | "version": "0.22.12", | ||
| 1306 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", | ||
| 1307 | "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", | ||
| 1308 | "license": "MIT", | ||
| 1309 | "dependencies": { | ||
| 1310 | "regenerator-runtime": "^0.13.3" | ||
| 1311 | } | ||
| 1312 | }, | ||
| 1313 | "node_modules/@jimp/png/node_modules/pngjs": { | ||
| 1314 | "version": "6.0.0", | ||
| 1315 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", | ||
| 1316 | "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", | ||
| 1317 | "license": "MIT", | ||
| 1318 | "engines": { | ||
| 1319 | "node": ">=12.13.0" | ||
| 1320 | } | ||
| 1321 | }, | ||
| 783 | "node_modules/@jimp/tiff": { | 1322 | "node_modules/@jimp/tiff": { |
| 784 | "version": "0.22.12", | 1323 | "version": "0.22.12", |
| 785 | "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.22.12.tgz", | 1324 | "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.22.12.tgz", |
| @@ -793,29 +1332,81 @@ | |||
| 793 | } | 1332 | } |
| 794 | }, | 1333 | }, |
| 795 | "node_modules/@jimp/types": { | 1334 | "node_modules/@jimp/types": { |
| 796 | "version": "0.22.12", | 1335 | "version": "1.6.0", |
| 797 | "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.22.12.tgz", | 1336 | "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.0.tgz", |
| 798 | "integrity": "sha512-wwKYzRdElE1MBXFREvCto5s699izFHNVvALUv79GXNbsOVqlwlOxlWJ8DuyOGIXoLP4JW/m30YyuTtfUJgMRMA==", | 1337 | "integrity": "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==", |
| 799 | "license": "MIT", | 1338 | "license": "MIT", |
| 800 | "dependencies": { | 1339 | "dependencies": { |
| 801 | "@jimp/bmp": "^0.22.12", | 1340 | "zod": "^3.23.8" |
| 802 | "@jimp/gif": "^0.22.12", | ||
| 803 | "@jimp/jpeg": "^0.22.12", | ||
| 804 | "@jimp/png": "^0.22.12", | ||
| 805 | "@jimp/tiff": "^0.22.12", | ||
| 806 | "timm": "^1.6.1" | ||
| 807 | }, | 1341 | }, |
| 808 | "peerDependencies": { | 1342 | "engines": { |
| 809 | "@jimp/custom": ">=0.3.5" | 1343 | "node": ">=18" |
| 810 | } | 1344 | } |
| 811 | }, | 1345 | }, |
| 812 | "node_modules/@jimp/utils": { | 1346 | "node_modules/@jimp/utils": { |
| 813 | "version": "0.22.12", | 1347 | "version": "1.6.0", |
| 814 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.12.tgz", | 1348 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.0.tgz", |
| 815 | "integrity": "sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q==", | 1349 | "integrity": "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==", |
| 816 | "license": "MIT", | 1350 | "license": "MIT", |
| 817 | "dependencies": { | 1351 | "dependencies": { |
| 818 | "regenerator-runtime": "^0.13.3" | 1352 | "@jimp/types": "1.6.0", |
| 1353 | "tinycolor2": "^1.6.0" | ||
| 1354 | }, | ||
| 1355 | "engines": { | ||
| 1356 | "node": ">=18" | ||
| 1357 | } | ||
| 1358 | }, | ||
| 1359 | "node_modules/@jimp/wasm-avif": { | ||
| 1360 | "version": "1.6.0", | ||
| 1361 | "resolved": "https://registry.npmjs.org/@jimp/wasm-avif/-/wasm-avif-1.6.0.tgz", | ||
| 1362 | "integrity": "sha512-OjiqqtD71MTLVQgB/oUOZ8PD+nxLQtl/Lyf/P/hhL56L6iCJbcciA3xO0Y9OJept7+R34ORY4f7RwWwt535DHg==", | ||
| 1363 | "license": "MIT", | ||
| 1364 | "dependencies": { | ||
| 1365 | "@jsquash/avif": "^1.3.0", | ||
| 1366 | "zod": "^3.23.8" | ||
| 1367 | }, | ||
| 1368 | "engines": { | ||
| 1369 | "node": ">=18" | ||
| 1370 | } | ||
| 1371 | }, | ||
| 1372 | "node_modules/@jimp/wasm-jpeg": { | ||
| 1373 | "version": "1.6.0", | ||
| 1374 | "resolved": "https://registry.npmjs.org/@jimp/wasm-jpeg/-/wasm-jpeg-1.6.0.tgz", | ||
| 1375 | "integrity": "sha512-zURjiESa79XXpMHzvvLMD3RC+wzFevS8lcTgyoZq4/y7qE5WrrUTWUBhr1UMFDueQ4gmOUf6EZ8L3/jkS/6nKQ==", | ||
| 1376 | "license": "MIT", | ||
| 1377 | "dependencies": { | ||
| 1378 | "@jsquash/jpeg": "^1.4.0", | ||
| 1379 | "zod": "^3.23.8" | ||
| 1380 | }, | ||
| 1381 | "engines": { | ||
| 1382 | "node": ">=18" | ||
| 1383 | } | ||
| 1384 | }, | ||
| 1385 | "node_modules/@jimp/wasm-png": { | ||
| 1386 | "version": "1.6.0", | ||
| 1387 | "resolved": "https://registry.npmjs.org/@jimp/wasm-png/-/wasm-png-1.6.0.tgz", | ||
| 1388 | "integrity": "sha512-D1xTVXpErApFH4YiOWZDoF8S8B6I3PgoCe38WsnTxDLfple8KGZMBdNjv3UO7vczsdlg5rATwWMBbNwxK03jNQ==", | ||
| 1389 | "license": "MIT", | ||
| 1390 | "dependencies": { | ||
| 1391 | "@jsquash/oxipng": "^2.3.0", | ||
| 1392 | "@jsquash/png": "^3.0.1", | ||
| 1393 | "zod": "^3.23.8" | ||
| 1394 | }, | ||
| 1395 | "engines": { | ||
| 1396 | "node": ">=18" | ||
| 1397 | } | ||
| 1398 | }, | ||
| 1399 | "node_modules/@jimp/wasm-webp": { | ||
| 1400 | "version": "1.6.0", | ||
| 1401 | "resolved": "https://registry.npmjs.org/@jimp/wasm-webp/-/wasm-webp-1.6.0.tgz", | ||
| 1402 | "integrity": "sha512-P0zUpK6n2XIAn8bt0F6rhSn1+FgteBTrL+TBb6Oqw8v5qEDJoNYkd6LlfZYN8YwtRBTBdZ8GFnWsg2Sar+qOkA==", | ||
| 1403 | "license": "MIT", | ||
| 1404 | "dependencies": { | ||
| 1405 | "@jsquash/webp": "^1.4.0", | ||
| 1406 | "zod": "^3.23.8" | ||
| 1407 | }, | ||
| 1408 | "engines": { | ||
| 1409 | "node": ">=18" | ||
| 819 | } | 1410 | } |
| 820 | }, | 1411 | }, |
| 821 | "node_modules/@jridgewell/gen-mapping": { | 1412 | "node_modules/@jridgewell/gen-mapping": { |
| @@ -876,6 +1467,45 @@ | |||
| 876 | "@jridgewell/sourcemap-codec": "^1.4.14" | 1467 | "@jridgewell/sourcemap-codec": "^1.4.14" |
| 877 | } | 1468 | } |
| 878 | }, | 1469 | }, |
| 1470 | "node_modules/@jsquash/avif": { | ||
| 1471 | "version": "1.3.0", | ||
| 1472 | "resolved": "https://registry.npmjs.org/@jsquash/avif/-/avif-1.3.0.tgz", | ||
| 1473 | "integrity": "sha512-N6zH27O/AioCPNGxaf33PYnUEQZmAjUz0JwwAf9eMHRdYItn+CxwxlsHSSOkFmZKW+v9uVX6c7ZPQ4RTXArL7A==", | ||
| 1474 | "license": "Apache-2.0", | ||
| 1475 | "dependencies": { | ||
| 1476 | "wasm-feature-detect": "^1.2.11" | ||
| 1477 | } | ||
| 1478 | }, | ||
| 1479 | "node_modules/@jsquash/jpeg": { | ||
| 1480 | "version": "1.5.0", | ||
| 1481 | "resolved": "https://registry.npmjs.org/@jsquash/jpeg/-/jpeg-1.5.0.tgz", | ||
| 1482 | "integrity": "sha512-Jam3X9BhbP1f+d58TfYobV/ZpYhCnawBF7YMS0Vt5Gi1v5Rk+xUdqYiZarAn0PwAzy2Zm2pPU/VzXHsLhwT9QQ==", | ||
| 1483 | "license": "Apache-2.0" | ||
| 1484 | }, | ||
| 1485 | "node_modules/@jsquash/oxipng": { | ||
| 1486 | "version": "2.3.0", | ||
| 1487 | "resolved": "https://registry.npmjs.org/@jsquash/oxipng/-/oxipng-2.3.0.tgz", | ||
| 1488 | "integrity": "sha512-aQ8wiEp6ztlTMXc+RMt/CG8crU3mEHDU+h+JYkIi6ctMhlh8+Ltj5XwQFfBuyzKYrp8NxaFW80Dp824bqjr+zA==", | ||
| 1489 | "license": "Apache-2.0", | ||
| 1490 | "dependencies": { | ||
| 1491 | "wasm-feature-detect": "^1.2.11" | ||
| 1492 | } | ||
| 1493 | }, | ||
| 1494 | "node_modules/@jsquash/png": { | ||
| 1495 | "version": "3.0.1", | ||
| 1496 | "resolved": "https://registry.npmjs.org/@jsquash/png/-/png-3.0.1.tgz", | ||
| 1497 | "integrity": "sha512-Bnvv93Y5LL92cuk2r2gpV+9JKuDo2/w7bOODw1iPxk8VARknky0sS1tSDgMosUdhNb4CdMlcCm3TMzTaqa3zZw==", | ||
| 1498 | "license": "Apache-2.0" | ||
| 1499 | }, | ||
| 1500 | "node_modules/@jsquash/webp": { | ||
| 1501 | "version": "1.4.0", | ||
| 1502 | "resolved": "https://registry.npmjs.org/@jsquash/webp/-/webp-1.4.0.tgz", | ||
| 1503 | "integrity": "sha512-yKJb6Hilq+qV/4C4qTDEalBobNwJO09LeHHtilmWg5mYHFUDwMunfeAap/r3cL5KsHkGOoI0IjY2nKbTaHq9Bw==", | ||
| 1504 | "license": "Apache-2.0", | ||
| 1505 | "dependencies": { | ||
| 1506 | "wasm-feature-detect": "^1.2.11" | ||
| 1507 | } | ||
| 1508 | }, | ||
| 879 | "node_modules/@kwsites/file-exists": { | 1509 | "node_modules/@kwsites/file-exists": { |
| 880 | "version": "1.1.1", | 1510 | "version": "1.1.1", |
| 881 | "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", | 1511 | "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", |
| @@ -970,6 +1600,19 @@ | |||
| 970 | "node": ">=14" | 1600 | "node": ">=14" |
| 971 | } | 1601 | } |
| 972 | }, | 1602 | }, |
| 1603 | "node_modules/@pkgr/core": { | ||
| 1604 | "version": "0.1.1", | ||
| 1605 | "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", | ||
| 1606 | "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", | ||
| 1607 | "dev": true, | ||
| 1608 | "license": "MIT", | ||
| 1609 | "engines": { | ||
| 1610 | "node": "^12.20.0 || ^14.18.0 || >=16.0.0" | ||
| 1611 | }, | ||
| 1612 | "funding": { | ||
| 1613 | "url": "https://opencollective.com/unts" | ||
| 1614 | } | ||
| 1615 | }, | ||
| 973 | "node_modules/@popperjs/core": { | 1616 | "node_modules/@popperjs/core": { |
| 974 | "version": "2.11.8", | 1617 | "version": "2.11.8", |
| 975 | "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", | 1618 | "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", |
| @@ -1389,13 +2032,6 @@ | |||
| 1389 | "dev": true, | 2032 | "dev": true, |
| 1390 | "license": "MIT" | 2033 | "license": "MIT" |
| 1391 | }, | 2034 | }, |
| 1392 | "node_modules/@types/png-chunks-encode": { | ||
| 1393 | "version": "1.0.2", | ||
| 1394 | "resolved": "https://registry.npmjs.org/@types/png-chunks-encode/-/png-chunks-encode-1.0.2.tgz", | ||
| 1395 | "integrity": "sha512-Dxn0aXEcSg1wVeHjvNlygm/+fKBDzWMCdxJYhjGUTeefFW/jYxWcrg+W7ppLBfH44iJMqeVBHtHBwtYQUeYvgw==", | ||
| 1396 | "dev": true, | ||
| 1397 | "license": "MIT" | ||
| 1398 | }, | ||
| 1399 | "node_modules/@types/png-chunks-extract": { | 2035 | "node_modules/@types/png-chunks-extract": { |
| 1400 | "version": "1.0.2", | 2036 | "version": "1.0.2", |
| 1401 | "resolved": "https://registry.npmjs.org/@types/png-chunks-extract/-/png-chunks-extract-1.0.2.tgz", | 2037 | "resolved": "https://registry.npmjs.org/@types/png-chunks-extract/-/png-chunks-extract-1.0.2.tgz", |
| @@ -1926,29 +2562,6 @@ | |||
| 1926 | "balanced-match": "^1.0.0" | 2562 | "balanced-match": "^1.0.0" |
| 1927 | } | 2563 | } |
| 1928 | }, | 2564 | }, |
| 1929 | "node_modules/archiver-utils/node_modules/buffer": { | ||
| 1930 | "version": "6.0.3", | ||
| 1931 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", | ||
| 1932 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", | ||
| 1933 | "funding": [ | ||
| 1934 | { | ||
| 1935 | "type": "github", | ||
| 1936 | "url": "https://github.com/sponsors/feross" | ||
| 1937 | }, | ||
| 1938 | { | ||
| 1939 | "type": "patreon", | ||
| 1940 | "url": "https://www.patreon.com/feross" | ||
| 1941 | }, | ||
| 1942 | { | ||
| 1943 | "type": "consulting", | ||
| 1944 | "url": "https://feross.org/support" | ||
| 1945 | } | ||
| 1946 | ], | ||
| 1947 | "dependencies": { | ||
| 1948 | "base64-js": "^1.3.1", | ||
| 1949 | "ieee754": "^1.2.1" | ||
| 1950 | } | ||
| 1951 | }, | ||
| 1952 | "node_modules/archiver-utils/node_modules/glob": { | 2565 | "node_modules/archiver-utils/node_modules/glob": { |
| 1953 | "version": "10.3.12", | 2566 | "version": "10.3.12", |
| 1954 | "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", | 2567 | "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", |
| @@ -2026,29 +2639,6 @@ | |||
| 2026 | "safe-buffer": "~5.2.0" | 2639 | "safe-buffer": "~5.2.0" |
| 2027 | } | 2640 | } |
| 2028 | }, | 2641 | }, |
| 2029 | "node_modules/archiver/node_modules/buffer": { | ||
| 2030 | "version": "6.0.3", | ||
| 2031 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", | ||
| 2032 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", | ||
| 2033 | "funding": [ | ||
| 2034 | { | ||
| 2035 | "type": "github", | ||
| 2036 | "url": "https://github.com/sponsors/feross" | ||
| 2037 | }, | ||
| 2038 | { | ||
| 2039 | "type": "patreon", | ||
| 2040 | "url": "https://www.patreon.com/feross" | ||
| 2041 | }, | ||
| 2042 | { | ||
| 2043 | "type": "consulting", | ||
| 2044 | "url": "https://feross.org/support" | ||
| 2045 | } | ||
| 2046 | ], | ||
| 2047 | "dependencies": { | ||
| 2048 | "base64-js": "^1.3.1", | ||
| 2049 | "ieee754": "^1.2.1" | ||
| 2050 | } | ||
| 2051 | }, | ||
| 2052 | "node_modules/archiver/node_modules/buffer-crc32": { | 2642 | "node_modules/archiver/node_modules/buffer-crc32": { |
| 2053 | "version": "1.0.0", | 2643 | "version": "1.0.0", |
| 2054 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", | 2644 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", |
| @@ -2099,6 +2689,16 @@ | |||
| 2099 | "safe-buffer": "~5.2.0" | 2689 | "safe-buffer": "~5.2.0" |
| 2100 | } | 2690 | } |
| 2101 | }, | 2691 | }, |
| 2692 | "node_modules/are-docs-informative": { | ||
| 2693 | "version": "0.0.2", | ||
| 2694 | "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", | ||
| 2695 | "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", | ||
| 2696 | "dev": true, | ||
| 2697 | "license": "MIT", | ||
| 2698 | "engines": { | ||
| 2699 | "node": ">=14" | ||
| 2700 | } | ||
| 2701 | }, | ||
| 2102 | "node_modules/argparse": { | 2702 | "node_modules/argparse": { |
| 2103 | "version": "2.0.1", | 2703 | "version": "2.0.1", |
| 2104 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", | 2704 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", |
| @@ -2135,6 +2735,15 @@ | |||
| 2135 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", | 2735 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", |
| 2136 | "license": "MIT" | 2736 | "license": "MIT" |
| 2137 | }, | 2737 | }, |
| 2738 | "node_modules/await-to-js": { | ||
| 2739 | "version": "3.0.0", | ||
| 2740 | "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz", | ||
| 2741 | "integrity": "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==", | ||
| 2742 | "license": "MIT", | ||
| 2743 | "engines": { | ||
| 2744 | "node": ">=6.0.0" | ||
| 2745 | } | ||
| 2746 | }, | ||
| 2138 | "node_modules/axios": { | 2747 | "node_modules/axios": { |
| 2139 | "version": "1.8.3", | 2748 | "version": "1.8.3", |
| 2140 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", | 2749 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", |
| @@ -2212,6 +2821,12 @@ | |||
| 2212 | "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==", | 2821 | "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==", |
| 2213 | "license": "MIT" | 2822 | "license": "MIT" |
| 2214 | }, | 2823 | }, |
| 2824 | "node_modules/bmp-ts": { | ||
| 2825 | "version": "1.0.9", | ||
| 2826 | "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz", | ||
| 2827 | "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==", | ||
| 2828 | "license": "MIT" | ||
| 2829 | }, | ||
| 2215 | "node_modules/body-parser": { | 2830 | "node_modules/body-parser": { |
| 2216 | "version": "1.20.3", | 2831 | "version": "1.20.3", |
| 2217 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", | 2832 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", |
| @@ -2304,9 +2919,9 @@ | |||
| 2304 | } | 2919 | } |
| 2305 | }, | 2920 | }, |
| 2306 | "node_modules/buffer": { | 2921 | "node_modules/buffer": { |
| 2307 | "version": "5.7.1", | 2922 | "version": "6.0.3", |
| 2308 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", | 2923 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", |
| 2309 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", | 2924 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", |
| 2310 | "funding": [ | 2925 | "funding": [ |
| 2311 | { | 2926 | { |
| 2312 | "type": "github", | 2927 | "type": "github", |
| @@ -2324,7 +2939,7 @@ | |||
| 2324 | "license": "MIT", | 2939 | "license": "MIT", |
| 2325 | "dependencies": { | 2940 | "dependencies": { |
| 2326 | "base64-js": "^1.3.1", | 2941 | "base64-js": "^1.3.1", |
| 2327 | "ieee754": "^1.1.13" | 2942 | "ieee754": "^1.2.1" |
| 2328 | } | 2943 | } |
| 2329 | }, | 2944 | }, |
| 2330 | "node_modules/buffer-crc32": { | 2945 | "node_modules/buffer-crc32": { |
| @@ -2614,6 +3229,16 @@ | |||
| 2614 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", | 3229 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", |
| 2615 | "license": "MIT" | 3230 | "license": "MIT" |
| 2616 | }, | 3231 | }, |
| 3232 | "node_modules/comment-parser": { | ||
| 3233 | "version": "1.4.1", | ||
| 3234 | "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", | ||
| 3235 | "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", | ||
| 3236 | "dev": true, | ||
| 3237 | "license": "MIT", | ||
| 3238 | "engines": { | ||
| 3239 | "node": ">= 12.0.0" | ||
| 3240 | } | ||
| 3241 | }, | ||
| 2617 | "node_modules/compress-commons": { | 3242 | "node_modules/compress-commons": { |
| 2618 | "version": "6.0.2", | 3243 | "version": "6.0.2", |
| 2619 | "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", | 3244 | "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", |
| @@ -2629,29 +3254,6 @@ | |||
| 2629 | "node": ">= 14" | 3254 | "node": ">= 14" |
| 2630 | } | 3255 | } |
| 2631 | }, | 3256 | }, |
| 2632 | "node_modules/compress-commons/node_modules/buffer": { | ||
| 2633 | "version": "6.0.3", | ||
| 2634 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", | ||
| 2635 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", | ||
| 2636 | "funding": [ | ||
| 2637 | { | ||
| 2638 | "type": "github", | ||
| 2639 | "url": "https://github.com/sponsors/feross" | ||
| 2640 | }, | ||
| 2641 | { | ||
| 2642 | "type": "patreon", | ||
| 2643 | "url": "https://www.patreon.com/feross" | ||
| 2644 | }, | ||
| 2645 | { | ||
| 2646 | "type": "consulting", | ||
| 2647 | "url": "https://feross.org/support" | ||
| 2648 | } | ||
| 2649 | ], | ||
| 2650 | "dependencies": { | ||
| 2651 | "base64-js": "^1.3.1", | ||
| 2652 | "ieee754": "^1.2.1" | ||
| 2653 | } | ||
| 2654 | }, | ||
| 2655 | "node_modules/compress-commons/node_modules/crc-32": { | 3257 | "node_modules/compress-commons/node_modules/crc-32": { |
| 2656 | "version": "1.2.2", | 3258 | "version": "1.2.2", |
| 2657 | "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", | 3259 | "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", |
| @@ -2928,8 +3530,25 @@ | |||
| 2928 | "object-assign": "^4", | 3530 | "object-assign": "^4", |
| 2929 | "vary": "^1" | 3531 | "vary": "^1" |
| 2930 | }, | 3532 | }, |
| 2931 | "engines": { | 3533 | "engines": { |
| 2932 | "node": ">= 0.10" | 3534 | "node": ">= 0.10" |
| 3535 | } | ||
| 3536 | }, | ||
| 3537 | "node_modules/crc": { | ||
| 3538 | "version": "4.3.2", | ||
| 3539 | "resolved": "https://registry.npmjs.org/crc/-/crc-4.3.2.tgz", | ||
| 3540 | "integrity": "sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A==", | ||
| 3541 | "license": "MIT", | ||
| 3542 | "engines": { | ||
| 3543 | "node": ">=12" | ||
| 3544 | }, | ||
| 3545 | "peerDependencies": { | ||
| 3546 | "buffer": ">=6.0.3" | ||
| 3547 | }, | ||
| 3548 | "peerDependenciesMeta": { | ||
| 3549 | "buffer": { | ||
| 3550 | "optional": true | ||
| 3551 | } | ||
| 2933 | } | 3552 | } |
| 2934 | }, | 3553 | }, |
| 2935 | "node_modules/crc-32": { | 3554 | "node_modules/crc-32": { |
| @@ -2953,29 +3572,6 @@ | |||
| 2953 | "node": ">= 14" | 3572 | "node": ">= 14" |
| 2954 | } | 3573 | } |
| 2955 | }, | 3574 | }, |
| 2956 | "node_modules/crc32-stream/node_modules/buffer": { | ||
| 2957 | "version": "6.0.3", | ||
| 2958 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", | ||
| 2959 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", | ||
| 2960 | "funding": [ | ||
| 2961 | { | ||
| 2962 | "type": "github", | ||
| 2963 | "url": "https://github.com/sponsors/feross" | ||
| 2964 | }, | ||
| 2965 | { | ||
| 2966 | "type": "patreon", | ||
| 2967 | "url": "https://www.patreon.com/feross" | ||
| 2968 | }, | ||
| 2969 | { | ||
| 2970 | "type": "consulting", | ||
| 2971 | "url": "https://feross.org/support" | ||
| 2972 | } | ||
| 2973 | ], | ||
| 2974 | "dependencies": { | ||
| 2975 | "base64-js": "^1.3.1", | ||
| 2976 | "ieee754": "^1.2.1" | ||
| 2977 | } | ||
| 2978 | }, | ||
| 2979 | "node_modules/crc32-stream/node_modules/crc-32": { | 3575 | "node_modules/crc32-stream/node_modules/crc-32": { |
| 2980 | "version": "1.2.2", | 3576 | "version": "1.2.2", |
| 2981 | "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", | 3577 | "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", |
| @@ -3560,6 +4156,69 @@ | |||
| 3560 | "url": "https://opencollective.com/eslint" | 4156 | "url": "https://opencollective.com/eslint" |
| 3561 | } | 4157 | } |
| 3562 | }, | 4158 | }, |
| 4159 | "node_modules/eslint-plugin-jsdoc": { | ||
| 4160 | "version": "48.10.0", | ||
| 4161 | "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.10.0.tgz", | ||
| 4162 | "integrity": "sha512-BEli0k8E0dzhJairAllwlkGnyYDZVKNn4WDmyKy+v6J5qGNuofjzxwNUi+55BOGmyO9mKBhqaidwGy+dxndn/Q==", | ||
| 4163 | "dev": true, | ||
| 4164 | "license": "BSD-3-Clause", | ||
| 4165 | "dependencies": { | ||
| 4166 | "@es-joy/jsdoccomment": "~0.46.0", | ||
| 4167 | "are-docs-informative": "^0.0.2", | ||
| 4168 | "comment-parser": "1.4.1", | ||
| 4169 | "debug": "^4.3.5", | ||
| 4170 | "escape-string-regexp": "^4.0.0", | ||
| 4171 | "esquery": "^1.6.0", | ||
| 4172 | "parse-imports": "^2.1.1", | ||
| 4173 | "semver": "^7.6.3", | ||
| 4174 | "spdx-expression-parse": "^4.0.0", | ||
| 4175 | "synckit": "^0.9.1" | ||
| 4176 | }, | ||
| 4177 | "engines": { | ||
| 4178 | "node": ">=18" | ||
| 4179 | }, | ||
| 4180 | "peerDependencies": { | ||
| 4181 | "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" | ||
| 4182 | } | ||
| 4183 | }, | ||
| 4184 | "node_modules/eslint-plugin-jsdoc/node_modules/debug": { | ||
| 4185 | "version": "4.4.0", | ||
| 4186 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", | ||
| 4187 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", | ||
| 4188 | "dev": true, | ||
| 4189 | "license": "MIT", | ||
| 4190 | "dependencies": { | ||
| 4191 | "ms": "^2.1.3" | ||
| 4192 | }, | ||
| 4193 | "engines": { | ||
| 4194 | "node": ">=6.0" | ||
| 4195 | }, | ||
| 4196 | "peerDependenciesMeta": { | ||
| 4197 | "supports-color": { | ||
| 4198 | "optional": true | ||
| 4199 | } | ||
| 4200 | } | ||
| 4201 | }, | ||
| 4202 | "node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": { | ||
| 4203 | "version": "4.0.0", | ||
| 4204 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", | ||
| 4205 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", | ||
| 4206 | "dev": true, | ||
| 4207 | "license": "MIT", | ||
| 4208 | "engines": { | ||
| 4209 | "node": ">=10" | ||
| 4210 | }, | ||
| 4211 | "funding": { | ||
| 4212 | "url": "https://github.com/sponsors/sindresorhus" | ||
| 4213 | } | ||
| 4214 | }, | ||
| 4215 | "node_modules/eslint-plugin-jsdoc/node_modules/ms": { | ||
| 4216 | "version": "2.1.3", | ||
| 4217 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", | ||
| 4218 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", | ||
| 4219 | "dev": true, | ||
| 4220 | "license": "MIT" | ||
| 4221 | }, | ||
| 3563 | "node_modules/eslint-scope": { | 4222 | "node_modules/eslint-scope": { |
| 3564 | "version": "7.2.2", | 4223 | "version": "7.2.2", |
| 3565 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", | 4224 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", |
| @@ -3690,9 +4349,9 @@ | |||
| 3690 | } | 4349 | } |
| 3691 | }, | 4350 | }, |
| 3692 | "node_modules/esquery": { | 4351 | "node_modules/esquery": { |
| 3693 | "version": "1.5.0", | 4352 | "version": "1.6.0", |
| 3694 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", | 4353 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", |
| 3695 | "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", | 4354 | "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", |
| 3696 | "dev": true, | 4355 | "dev": true, |
| 3697 | "license": "BSD-3-Clause", | 4356 | "license": "BSD-3-Clause", |
| 3698 | "dependencies": { | 4357 | "dependencies": { |
| @@ -4978,18 +5637,6 @@ | |||
| 4978 | "url": "https://github.com/chalk/supports-color?sponsor=1" | 5637 | "url": "https://github.com/chalk/supports-color?sponsor=1" |
| 4979 | } | 5638 | } |
| 4980 | }, | 5639 | }, |
| 4981 | "node_modules/jimp": { | ||
| 4982 | "version": "0.22.12", | ||
| 4983 | "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.22.12.tgz", | ||
| 4984 | "integrity": "sha512-R5jZaYDnfkxKJy1dwLpj/7cvyjxiclxU3F4TrI/J4j2rS0niq6YDUMoPn5hs8GDpO+OZGo7Ky057CRtWesyhfg==", | ||
| 4985 | "license": "MIT", | ||
| 4986 | "dependencies": { | ||
| 4987 | "@jimp/custom": "^0.22.12", | ||
| 4988 | "@jimp/plugins": "^0.22.12", | ||
| 4989 | "@jimp/types": "^0.22.12", | ||
| 4990 | "regenerator-runtime": "^0.13.3" | ||
| 4991 | } | ||
| 4992 | }, | ||
| 4993 | "node_modules/jpeg-js": { | 5640 | "node_modules/jpeg-js": { |
| 4994 | "version": "0.4.4", | 5641 | "version": "0.4.4", |
| 4995 | "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", | 5642 | "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", |
| @@ -5015,6 +5662,16 @@ | |||
| 5015 | "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", | 5662 | "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", |
| 5016 | "license": "MIT" | 5663 | "license": "MIT" |
| 5017 | }, | 5664 | }, |
| 5665 | "node_modules/jsdoc-type-pratt-parser": { | ||
| 5666 | "version": "4.0.0", | ||
| 5667 | "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", | ||
| 5668 | "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", | ||
| 5669 | "dev": true, | ||
| 5670 | "license": "MIT", | ||
| 5671 | "engines": { | ||
| 5672 | "node": ">=12.0.0" | ||
| 5673 | } | ||
| 5674 | }, | ||
| 5018 | "node_modules/json-buffer": { | 5675 | "node_modules/json-buffer": { |
| 5019 | "version": "3.0.1", | 5676 | "version": "3.0.1", |
| 5020 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", | 5677 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", |
| @@ -5886,11 +6543,25 @@ | |||
| 5886 | } | 6543 | } |
| 5887 | }, | 6544 | }, |
| 5888 | "node_modules/parse-headers": { | 6545 | "node_modules/parse-headers": { |
| 5889 | "version": "2.0.5", | 6546 | "version": "2.0.6", |
| 5890 | "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", | 6547 | "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.6.tgz", |
| 5891 | "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==", | 6548 | "integrity": "sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==", |
| 5892 | "license": "MIT" | 6549 | "license": "MIT" |
| 5893 | }, | 6550 | }, |
| 6551 | "node_modules/parse-imports": { | ||
| 6552 | "version": "2.2.1", | ||
| 6553 | "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", | ||
| 6554 | "integrity": "sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==", | ||
| 6555 | "dev": true, | ||
| 6556 | "license": "Apache-2.0 AND MIT", | ||
| 6557 | "dependencies": { | ||
| 6558 | "es-module-lexer": "^1.5.3", | ||
| 6559 | "slashes": "^3.0.12" | ||
| 6560 | }, | ||
| 6561 | "engines": { | ||
| 6562 | "node": ">= 18" | ||
| 6563 | } | ||
| 6564 | }, | ||
| 5894 | "node_modules/parse5": { | 6565 | "node_modules/parse5": { |
| 5895 | "version": "7.1.2", | 6566 | "version": "7.1.2", |
| 5896 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", | 6567 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", |
| @@ -6012,27 +6683,6 @@ | |||
| 6012 | "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", | 6683 | "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", |
| 6013 | "license": "ISC" | 6684 | "license": "ISC" |
| 6014 | }, | 6685 | }, |
| 6015 | "node_modules/pixelmatch": { | ||
| 6016 | "version": "4.0.2", | ||
| 6017 | "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", | ||
| 6018 | "integrity": "sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==", | ||
| 6019 | "license": "ISC", | ||
| 6020 | "dependencies": { | ||
| 6021 | "pngjs": "^3.0.0" | ||
| 6022 | }, | ||
| 6023 | "bin": { | ||
| 6024 | "pixelmatch": "bin/pixelmatch" | ||
| 6025 | } | ||
| 6026 | }, | ||
| 6027 | "node_modules/pixelmatch/node_modules/pngjs": { | ||
| 6028 | "version": "3.4.0", | ||
| 6029 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", | ||
| 6030 | "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", | ||
| 6031 | "license": "MIT", | ||
| 6032 | "engines": { | ||
| 6033 | "node": ">=4.0.0" | ||
| 6034 | } | ||
| 6035 | }, | ||
| 6036 | "node_modules/platform": { | 6686 | "node_modules/platform": { |
| 6037 | "version": "1.3.6", | 6687 | "version": "1.3.6", |
| 6038 | "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", | 6688 | "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", |
| @@ -6045,16 +6695,6 @@ | |||
| 6045 | "integrity": "sha512-DEROKU3SkkLGWNMzru3xPVgxyd48UGuMSZvioErCure6yhOc/pRH2ZV+SEn7nmaf7WNf3NdIpH+UTrRdKyq9Lw==", | 6695 | "integrity": "sha512-DEROKU3SkkLGWNMzru3xPVgxyd48UGuMSZvioErCure6yhOc/pRH2ZV+SEn7nmaf7WNf3NdIpH+UTrRdKyq9Lw==", |
| 6046 | "license": "MIT" | 6696 | "license": "MIT" |
| 6047 | }, | 6697 | }, |
| 6048 | "node_modules/png-chunks-encode": { | ||
| 6049 | "version": "1.0.0", | ||
| 6050 | "resolved": "https://registry.npmjs.org/png-chunks-encode/-/png-chunks-encode-1.0.0.tgz", | ||
| 6051 | "integrity": "sha512-J1jcHgbQRsIIgx5wxW9UmCymV3wwn4qCCJl6KYgEU/yHCh/L2Mwq/nMOkRPtmV79TLxRZj5w3tH69pvygFkDqA==", | ||
| 6052 | "license": "MIT", | ||
| 6053 | "dependencies": { | ||
| 6054 | "crc-32": "^0.3.0", | ||
| 6055 | "sliced": "^1.0.1" | ||
| 6056 | } | ||
| 6057 | }, | ||
| 6058 | "node_modules/png-chunks-extract": { | 6698 | "node_modules/png-chunks-extract": { |
| 6059 | "version": "1.0.0", | 6699 | "version": "1.0.0", |
| 6060 | "resolved": "https://registry.npmjs.org/png-chunks-extract/-/png-chunks-extract-1.0.0.tgz", | 6700 | "resolved": "https://registry.npmjs.org/png-chunks-extract/-/png-chunks-extract-1.0.0.tgz", |
| @@ -6065,12 +6705,12 @@ | |||
| 6065 | } | 6705 | } |
| 6066 | }, | 6706 | }, |
| 6067 | "node_modules/pngjs": { | 6707 | "node_modules/pngjs": { |
| 6068 | "version": "6.0.0", | 6708 | "version": "7.0.0", |
| 6069 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", | 6709 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", |
| 6070 | "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", | 6710 | "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", |
| 6071 | "license": "MIT", | 6711 | "license": "MIT", |
| 6072 | "engines": { | 6712 | "engines": { |
| 6073 | "node": ">=12.13.0" | 6713 | "node": ">=14.19.0" |
| 6074 | } | 6714 | } |
| 6075 | }, | 6715 | }, |
| 6076 | "node_modules/prelude-ls": { | 6716 | "node_modules/prelude-ls": { |
| @@ -6342,12 +6982,12 @@ | |||
| 6342 | } | 6982 | } |
| 6343 | }, | 6983 | }, |
| 6344 | "node_modules/readable-web-to-node-stream": { | 6984 | "node_modules/readable-web-to-node-stream": { |
| 6345 | "version": "3.0.2", | 6985 | "version": "3.0.4", |
| 6346 | "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", | 6986 | "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz", |
| 6347 | "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", | 6987 | "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==", |
| 6348 | "license": "MIT", | 6988 | "license": "MIT", |
| 6349 | "dependencies": { | 6989 | "dependencies": { |
| 6350 | "readable-stream": "^3.6.0" | 6990 | "readable-stream": "^4.7.0" |
| 6351 | }, | 6991 | }, |
| 6352 | "engines": { | 6992 | "engines": { |
| 6353 | "node": ">=8" | 6993 | "node": ">=8" |
| @@ -6358,17 +6998,48 @@ | |||
| 6358 | } | 6998 | } |
| 6359 | }, | 6999 | }, |
| 6360 | "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { | 7000 | "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { |
| 6361 | "version": "3.6.2", | 7001 | "version": "4.7.0", |
| 6362 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", | 7002 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", |
| 6363 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", | 7003 | "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", |
| 6364 | "license": "MIT", | 7004 | "license": "MIT", |
| 6365 | "dependencies": { | 7005 | "dependencies": { |
| 6366 | "inherits": "^2.0.3", | 7006 | "abort-controller": "^3.0.0", |
| 6367 | "string_decoder": "^1.1.1", | 7007 | "buffer": "^6.0.3", |
| 6368 | "util-deprecate": "^1.0.1" | 7008 | "events": "^3.3.0", |
| 7009 | "process": "^0.11.10", | ||
| 7010 | "string_decoder": "^1.3.0" | ||
| 6369 | }, | 7011 | }, |
| 6370 | "engines": { | 7012 | "engines": { |
| 6371 | "node": ">= 6" | 7013 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" |
| 7014 | } | ||
| 7015 | }, | ||
| 7016 | "node_modules/readable-web-to-node-stream/node_modules/safe-buffer": { | ||
| 7017 | "version": "5.2.1", | ||
| 7018 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", | ||
| 7019 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", | ||
| 7020 | "funding": [ | ||
| 7021 | { | ||
| 7022 | "type": "github", | ||
| 7023 | "url": "https://github.com/sponsors/feross" | ||
| 7024 | }, | ||
| 7025 | { | ||
| 7026 | "type": "patreon", | ||
| 7027 | "url": "https://www.patreon.com/feross" | ||
| 7028 | }, | ||
| 7029 | { | ||
| 7030 | "type": "consulting", | ||
| 7031 | "url": "https://feross.org/support" | ||
| 7032 | } | ||
| 7033 | ], | ||
| 7034 | "license": "MIT" | ||
| 7035 | }, | ||
| 7036 | "node_modules/readable-web-to-node-stream/node_modules/string_decoder": { | ||
| 7037 | "version": "1.3.0", | ||
| 7038 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", | ||
| 7039 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", | ||
| 7040 | "license": "MIT", | ||
| 7041 | "dependencies": { | ||
| 7042 | "safe-buffer": "~5.2.0" | ||
| 6372 | } | 7043 | } |
| 6373 | }, | 7044 | }, |
| 6374 | "node_modules/readdir-glob": { | 7045 | "node_modules/readdir-glob": { |
| @@ -6600,6 +7271,19 @@ | |||
| 6600 | "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", | 7271 | "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", |
| 6601 | "license": "MIT" | 7272 | "license": "MIT" |
| 6602 | }, | 7273 | }, |
| 7274 | "node_modules/semver": { | ||
| 7275 | "version": "7.7.1", | ||
| 7276 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", | ||
| 7277 | "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", | ||
| 7278 | "dev": true, | ||
| 7279 | "license": "ISC", | ||
| 7280 | "bin": { | ||
| 7281 | "semver": "bin/semver.js" | ||
| 7282 | }, | ||
| 7283 | "engines": { | ||
| 7284 | "node": ">=10" | ||
| 7285 | } | ||
| 7286 | }, | ||
| 6603 | "node_modules/send": { | 7287 | "node_modules/send": { |
| 6604 | "version": "0.19.0", | 7288 | "version": "0.19.0", |
| 6605 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", | 7289 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", |
| @@ -6773,6 +7457,35 @@ | |||
| 6773 | "onnxruntime-web": "1.14.0" | 7457 | "onnxruntime-web": "1.14.0" |
| 6774 | } | 7458 | } |
| 6775 | }, | 7459 | }, |
| 7460 | "node_modules/sillytavern-transformers/node_modules/@jimp/types": { | ||
| 7461 | "version": "0.22.12", | ||
| 7462 | "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.22.12.tgz", | ||
| 7463 | "integrity": "sha512-wwKYzRdElE1MBXFREvCto5s699izFHNVvALUv79GXNbsOVqlwlOxlWJ8DuyOGIXoLP4JW/m30YyuTtfUJgMRMA==", | ||
| 7464 | "license": "MIT", | ||
| 7465 | "dependencies": { | ||
| 7466 | "@jimp/bmp": "^0.22.12", | ||
| 7467 | "@jimp/gif": "^0.22.12", | ||
| 7468 | "@jimp/jpeg": "^0.22.12", | ||
| 7469 | "@jimp/png": "^0.22.12", | ||
| 7470 | "@jimp/tiff": "^0.22.12", | ||
| 7471 | "timm": "^1.6.1" | ||
| 7472 | }, | ||
| 7473 | "peerDependencies": { | ||
| 7474 | "@jimp/custom": ">=0.3.5" | ||
| 7475 | } | ||
| 7476 | }, | ||
| 7477 | "node_modules/sillytavern-transformers/node_modules/jimp": { | ||
| 7478 | "version": "0.22.12", | ||
| 7479 | "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.22.12.tgz", | ||
| 7480 | "integrity": "sha512-R5jZaYDnfkxKJy1dwLpj/7cvyjxiclxU3F4TrI/J4j2rS0niq6YDUMoPn5hs8GDpO+OZGo7Ky057CRtWesyhfg==", | ||
| 7481 | "license": "MIT", | ||
| 7482 | "dependencies": { | ||
| 7483 | "@jimp/custom": "^0.22.12", | ||
| 7484 | "@jimp/plugins": "^0.22.12", | ||
| 7485 | "@jimp/types": "^0.22.12", | ||
| 7486 | "regenerator-runtime": "^0.13.3" | ||
| 7487 | } | ||
| 7488 | }, | ||
| 6776 | "node_modules/simple-git": { | 7489 | "node_modules/simple-git": { |
| 6777 | "version": "3.27.0", | 7490 | "version": "3.27.0", |
| 6778 | "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.27.0.tgz", | 7491 | "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.27.0.tgz", |
| @@ -6811,11 +7524,12 @@ | |||
| 6811 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", | 7524 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", |
| 6812 | "license": "MIT" | 7525 | "license": "MIT" |
| 6813 | }, | 7526 | }, |
| 6814 | "node_modules/sliced": { | 7527 | "node_modules/slashes": { |
| 6815 | "version": "1.0.1", | 7528 | "version": "3.0.12", |
| 6816 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", | 7529 | "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", |
| 6817 | "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==", | 7530 | "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", |
| 6818 | "license": "MIT" | 7531 | "dev": true, |
| 7532 | "license": "ISC" | ||
| 6819 | }, | 7533 | }, |
| 6820 | "node_modules/slidetoggle": { | 7534 | "node_modules/slidetoggle": { |
| 6821 | "version": "4.0.0", | 7535 | "version": "4.0.0", |
| @@ -6903,6 +7617,31 @@ | |||
| 6903 | "source-map": "^0.6.0" | 7617 | "source-map": "^0.6.0" |
| 6904 | } | 7618 | } |
| 6905 | }, | 7619 | }, |
| 7620 | "node_modules/spdx-exceptions": { | ||
| 7621 | "version": "2.5.0", | ||
| 7622 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", | ||
| 7623 | "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", | ||
| 7624 | "dev": true, | ||
| 7625 | "license": "CC-BY-3.0" | ||
| 7626 | }, | ||
| 7627 | "node_modules/spdx-expression-parse": { | ||
| 7628 | "version": "4.0.0", | ||
| 7629 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", | ||
| 7630 | "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", | ||
| 7631 | "dev": true, | ||
| 7632 | "license": "MIT", | ||
| 7633 | "dependencies": { | ||
| 7634 | "spdx-exceptions": "^2.1.0", | ||
| 7635 | "spdx-license-ids": "^3.0.0" | ||
| 7636 | } | ||
| 7637 | }, | ||
| 7638 | "node_modules/spdx-license-ids": { | ||
| 7639 | "version": "3.0.21", | ||
| 7640 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", | ||
| 7641 | "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", | ||
| 7642 | "dev": true, | ||
| 7643 | "license": "CC0-1.0" | ||
| 7644 | }, | ||
| 6906 | "node_modules/sprintf-js": { | 7645 | "node_modules/sprintf-js": { |
| 6907 | "version": "1.1.3", | 7646 | "version": "1.1.3", |
| 6908 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", | 7647 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", |
| @@ -7042,6 +7781,23 @@ | |||
| 7042 | "node": ">=8" | 7781 | "node": ">=8" |
| 7043 | } | 7782 | } |
| 7044 | }, | 7783 | }, |
| 7784 | "node_modules/synckit": { | ||
| 7785 | "version": "0.9.2", | ||
| 7786 | "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", | ||
| 7787 | "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", | ||
| 7788 | "dev": true, | ||
| 7789 | "license": "MIT", | ||
| 7790 | "dependencies": { | ||
| 7791 | "@pkgr/core": "^0.1.0", | ||
| 7792 | "tslib": "^2.6.2" | ||
| 7793 | }, | ||
| 7794 | "engines": { | ||
| 7795 | "node": "^14.18.0 || >=16.0.0" | ||
| 7796 | }, | ||
| 7797 | "funding": { | ||
| 7798 | "url": "https://opencollective.com/unts" | ||
| 7799 | } | ||
| 7800 | }, | ||
| 7045 | "node_modules/tapable": { | 7801 | "node_modules/tapable": { |
| 7046 | "version": "2.2.1", | 7802 | "version": "2.2.1", |
| 7047 | "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", | 7803 | "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", |
| @@ -7391,6 +8147,12 @@ | |||
| 7391 | "vectra": "bin/vectra.js" | 8147 | "vectra": "bin/vectra.js" |
| 7392 | } | 8148 | } |
| 7393 | }, | 8149 | }, |
| 8150 | "node_modules/wasm-feature-detect": { | ||
| 8151 | "version": "1.8.0", | ||
| 8152 | "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz", | ||
| 8153 | "integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==", | ||
| 8154 | "license": "Apache-2.0" | ||
| 8155 | }, | ||
| 7394 | "node_modules/watchpack": { | 8156 | "node_modules/watchpack": { |
| 7395 | "version": "2.4.2", | 8157 | "version": "2.4.2", |
| 7396 | "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", | 8158 | "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", |
| @@ -7757,29 +8519,6 @@ | |||
| 7757 | "node": ">= 14" | 8519 | "node": ">= 14" |
| 7758 | } | 8520 | } |
| 7759 | }, | 8521 | }, |
| 7760 | "node_modules/zip-stream/node_modules/buffer": { | ||
| 7761 | "version": "6.0.3", | ||
| 7762 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", | ||
| 7763 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", | ||
| 7764 | "funding": [ | ||
| 7765 | { | ||
| 7766 | "type": "github", | ||
| 7767 | "url": "https://github.com/sponsors/feross" | ||
| 7768 | }, | ||
| 7769 | { | ||
| 7770 | "type": "patreon", | ||
| 7771 | "url": "https://www.patreon.com/feross" | ||
| 7772 | }, | ||
| 7773 | { | ||
| 7774 | "type": "consulting", | ||
| 7775 | "url": "https://feross.org/support" | ||
| 7776 | } | ||
| 7777 | ], | ||
| 7778 | "dependencies": { | ||
| 7779 | "base64-js": "^1.3.1", | ||
| 7780 | "ieee754": "^1.2.1" | ||
| 7781 | } | ||
| 7782 | }, | ||
| 7783 | "node_modules/zip-stream/node_modules/readable-stream": { | 8522 | "node_modules/zip-stream/node_modules/readable-stream": { |
| 7784 | "version": "4.5.2", | 8523 | "version": "4.5.2", |
| 7785 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", | 8524 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", |
| @@ -7821,6 +8560,15 @@ | |||
| 7821 | "dependencies": { | 8560 | "dependencies": { |
| 7822 | "safe-buffer": "~5.2.0" | 8561 | "safe-buffer": "~5.2.0" |
| 7823 | } | 8562 | } |
| 8563 | }, | ||
| 8564 | "node_modules/zod": { | ||
| 8565 | "version": "3.24.2", | ||
| 8566 | "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", | ||
| 8567 | "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", | ||
| 8568 | "license": "MIT", | ||
| 8569 | "funding": { | ||
| 8570 | "url": "https://github.com/sponsors/colinhacks" | ||
| 8571 | } | ||
| 7824 | } | 8572 | } |
| 7825 | } | 8573 | } |
| 7826 | } | 8574 | } |
| @@ -4,6 +4,26 @@ | |||
| 4 | "@agnai/sentencepiece-js": "^1.1.1", | 4 | "@agnai/sentencepiece-js": "^1.1.1", |
| 5 | "@agnai/web-tokenizers": "^0.1.3", | 5 | "@agnai/web-tokenizers": "^0.1.3", |
| 6 | "@iconfu/svg-inject": "^1.2.3", | 6 | "@iconfu/svg-inject": "^1.2.3", |
| 7 | "@jimp/core": "^1.6.0", | ||
| 8 | "@jimp/js-bmp": "^1.6.0", | ||
| 9 | "@jimp/js-gif": "^1.6.0", | ||
| 10 | "@jimp/js-tiff": "^1.6.0", | ||
| 11 | "@jimp/plugin-circle": "^1.6.0", | ||
| 12 | "@jimp/plugin-color": "^1.6.0", | ||
| 13 | "@jimp/plugin-contain": "^1.6.0", | ||
| 14 | "@jimp/plugin-cover": "^1.6.0", | ||
| 15 | "@jimp/plugin-crop": "^1.6.0", | ||
| 16 | "@jimp/plugin-displace": "^1.6.0", | ||
| 17 | "@jimp/plugin-fisheye": "^1.6.0", | ||
| 18 | "@jimp/plugin-flip": "^1.6.0", | ||
| 19 | "@jimp/plugin-mask": "^1.6.0", | ||
| 20 | "@jimp/plugin-quantize": "^1.6.0", | ||
| 21 | "@jimp/plugin-rotate": "^1.6.0", | ||
| 22 | "@jimp/plugin-threshold": "^1.6.0", | ||
| 23 | "@jimp/wasm-avif": "^1.6.0", | ||
| 24 | "@jimp/wasm-jpeg": "^1.6.0", | ||
| 25 | "@jimp/wasm-png": "^1.6.0", | ||
| 26 | "@jimp/wasm-webp": "^1.6.0", | ||
| 7 | "@mozilla/readability": "^0.6.0", | 27 | "@mozilla/readability": "^0.6.0", |
| 8 | "@popperjs/core": "^2.11.8", | 28 | "@popperjs/core": "^2.11.8", |
| 9 | "@zeldafan0225/ai_horde": "^5.2.0", | 29 | "@zeldafan0225/ai_horde": "^5.2.0", |
| @@ -18,6 +38,7 @@ | |||
| 18 | "cookie-parser": "^1.4.6", | 38 | "cookie-parser": "^1.4.6", |
| 19 | "cookie-session": "^2.1.0", | 39 | "cookie-session": "^2.1.0", |
| 20 | "cors": "^2.8.5", | 40 | "cors": "^2.8.5", |
| 41 | "crc": "^4.3.2", | ||
| 21 | "csrf-sync": "^4.0.3", | 42 | "csrf-sync": "^4.0.3", |
| 22 | "diff-match-patch": "^1.0.5", | 43 | "diff-match-patch": "^1.0.5", |
| 23 | "dompurify": "^3.2.4", | 44 | "dompurify": "^3.2.4", |
| @@ -36,7 +57,6 @@ | |||
| 36 | "ip-regex": "^5.0.0", | 57 | "ip-regex": "^5.0.0", |
| 37 | "ipaddr.js": "^2.2.0", | 58 | "ipaddr.js": "^2.2.0", |
| 38 | "is-docker": "^3.0.0", | 59 | "is-docker": "^3.0.0", |
| 39 | "jimp": "^0.22.10", | ||
| 40 | "localforage": "^1.10.0", | 60 | "localforage": "^1.10.0", |
| 41 | "lodash": "^4.17.21", | 61 | "lodash": "^4.17.21", |
| 42 | "mime-types": "^2.1.35", | 62 | "mime-types": "^2.1.35", |
| @@ -47,7 +67,6 @@ | |||
| 47 | "node-persist": "^4.0.4", | 67 | "node-persist": "^4.0.4", |
| 48 | "open": "^8.4.2", | 68 | "open": "^8.4.2", |
| 49 | "png-chunk-text": "^1.0.0", | 69 | "png-chunk-text": "^1.0.0", |
| 50 | "png-chunks-encode": "^1.0.0", | ||
| 51 | "png-chunks-extract": "^1.0.0", | 70 | "png-chunks-extract": "^1.0.0", |
| 52 | "proxy-agent": "^6.5.0", | 71 | "proxy-agent": "^6.5.0", |
| 53 | "rate-limiter-flexible": "^5.0.5", | 72 | "rate-limiter-flexible": "^5.0.5", |
| @@ -90,7 +109,7 @@ | |||
| 90 | "type": "git", | 109 | "type": "git", |
| 91 | "url": "https://github.com/SillyTavern/SillyTavern.git" | 110 | "url": "https://github.com/SillyTavern/SillyTavern.git" |
| 92 | }, | 111 | }, |
| 93 | "version": "1.12.13", | 112 | "version": "1.12.14", |
| 94 | "scripts": { | 113 | "scripts": { |
| 95 | "start": "node server.js", | 114 | "start": "node server.js", |
| 96 | "debug": "node --inspect server.js", | 115 | "debug": "node --inspect server.js", |
| @@ -132,7 +151,6 @@ | |||
| 132 | "@types/node": "^18.19.80", | 151 | "@types/node": "^18.19.80", |
| 133 | "@types/node-persist": "^3.1.8", | 152 | "@types/node-persist": "^3.1.8", |
| 134 | "@types/png-chunk-text": "^1.0.3", | 153 | "@types/png-chunk-text": "^1.0.3", |
| 135 | "@types/png-chunks-encode": "^1.0.2", | ||
| 136 | "@types/png-chunks-extract": "^1.0.2", | 154 | "@types/png-chunks-extract": "^1.0.2", |
| 137 | "@types/response-time": "^2.3.8", | 155 | "@types/response-time": "^2.3.8", |
| 138 | "@types/select2": "^4.0.63", | 156 | "@types/select2": "^4.0.63", |
| @@ -140,6 +158,7 @@ | |||
| 140 | "@types/write-file-atomic": "^4.0.3", | 158 | "@types/write-file-atomic": "^4.0.3", |
| 141 | "@types/yargs": "^17.0.33", | 159 | "@types/yargs": "^17.0.33", |
| 142 | "@types/yauzl": "^2.10.3", | 160 | "@types/yauzl": "^2.10.3", |
| 143 | "eslint": "^8.57.1" | 161 | "eslint": "^8.57.1", |
| 162 | "eslint-plugin-jsdoc": "^48.10.0" | ||
| 144 | } | 163 | } |
| 145 | } | 164 | } |
| @@ -101,15 +101,12 @@ const keyMigrationMap = [ | |||
| 101 | newKey: 'performance.memoryCacheCapacity', | 101 | newKey: 'performance.memoryCacheCapacity', |
| 102 | migrate: (value) => `${value}mb`, | 102 | migrate: (value) => `${value}mb`, |
| 103 | }, | 103 | }, |
| 104 | // uncomment one release after 1.12.13 | ||
| 105 | /* | ||
| 106 | { | 104 | { |
| 107 | oldKey: 'cookieSecret', | 105 | oldKey: 'cookieSecret', |
| 108 | newKey: 'cookieSecret', | 106 | newKey: 'cookieSecret', |
| 109 | migrate: () => void 0, | 107 | migrate: () => void 0, |
| 110 | remove: true, | 108 | remove: true, |
| 111 | }, | 109 | }, |
| 112 | */ | ||
| 113 | ]; | 110 | ]; |
| 114 | 111 | ||
| 115 | /** | 112 | /** |
| @@ -146,3 +146,15 @@ input.extension_missing[type="checkbox"] { | |||
| 146 | .extensions_info .extension_actions { | 146 | .extensions_info .extension_actions { |
| 147 | flex-wrap: nowrap; | 147 | flex-wrap: nowrap; |
| 148 | } | 148 | } |
| 149 | |||
| 150 | .extensions_toolbar { | ||
| 151 | top: 0; | ||
| 152 | position: sticky; | ||
| 153 | display: flex; | ||
| 154 | flex-direction: row; | ||
| 155 | background-color: var(--SmartThemeBlurTintColor); | ||
| 156 | gap: 5px; | ||
| 157 | z-index: 1; | ||
| 158 | margin-bottom: 10px; | ||
| 159 | padding: 5px; | ||
| 160 | } | ||
| @@ -13,6 +13,7 @@ | |||
| 13 | backdrop-filter: blur(calc(var(--SmartThemeBlurStrength)*2)); | 13 | backdrop-filter: blur(calc(var(--SmartThemeBlurStrength)*2)); |
| 14 | color: var(--SmartThemeBodyColor); | 14 | color: var(--SmartThemeBodyColor); |
| 15 | z-index: 40000; | 15 | z-index: 40000; |
| 16 | user-select: none; | ||
| 16 | } | 17 | } |
| 17 | 18 | ||
| 18 | .select2-container .select2-selection .select2-selection__clear { | 19 | .select2-container .select2-selection .select2-selection__clear { |
| @@ -1,7 +1,11 @@ | |||
| 1 | import libs from './lib'; | 1 | import libs from './lib'; |
| 2 | import getContext from './scripts/st-context'; | 2 | import getContext from './scripts/st-context'; |
| 3 | import { power_user } from './scripts/power-user'; | ||
| 3 | 4 | ||
| 4 | declare global { | 5 | declare global { |
| 6 | // Custom types | ||
| 7 | declare type InstructSettings = typeof power_user.instruct; | ||
| 8 | |||
| 5 | // Global namespace modules | 9 | // Global namespace modules |
| 6 | interface Window { | 10 | interface Window { |
| 7 | ai: any; | 11 | ai: any; |
| @@ -0,0 +1,46 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 2 | <!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> | ||
| 3 | |||
| 4 | <svg | ||
| 5 | version="1.1" | ||
| 6 | id="katman_1" | ||
| 7 | x="0px" | ||
| 8 | y="0px" | ||
| 9 | viewBox="0 0 438.67001 481.44999" | ||
| 10 | xml:space="preserve" | ||
| 11 | sodipodi:docname="XAI_Logo.svg" | ||
| 12 | width="438.67001" | ||
| 13 | height="481.45001" | ||
| 14 | inkscape:version="1.3 (0e150ed, 2023-07-21)" | ||
| 15 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||
| 16 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||
| 17 | xmlns="http://www.w3.org/2000/svg" | ||
| 18 | xmlns:svg="http://www.w3.org/2000/svg"><defs | ||
| 19 | id="defs4" /><sodipodi:namedview | ||
| 20 | id="namedview4" | ||
| 21 | pagecolor="#ffffff" | ||
| 22 | bordercolor="#000000" | ||
| 23 | borderopacity="0.25" | ||
| 24 | inkscape:showpageshadow="2" | ||
| 25 | inkscape:pageopacity="0.0" | ||
| 26 | inkscape:pagecheckerboard="0" | ||
| 27 | inkscape:deskcolor="#d1d1d1" | ||
| 28 | inkscape:zoom="0.39645207" | ||
| 29 | inkscape:cx="219.44645" | ||
| 30 | inkscape:cy="238.36425" | ||
| 31 | inkscape:window-width="1512" | ||
| 32 | inkscape:window-height="856" | ||
| 33 | inkscape:window-x="0" | ||
| 34 | inkscape:window-y="38" | ||
| 35 | inkscape:window-maximized="1" | ||
| 36 | inkscape:current-layer="katman_1" /> <g | ||
| 37 | id="g4" | ||
| 38 | transform="translate(-201.61,-56.91)"> <polygon | ||
| 39 | points="631.96,538.36 640.28,93.18 557.09,211.99 565.4,538.36 " | ||
| 40 | id="polygon1" /> <polygon | ||
| 41 | points="379.35,284.53 430.13,357.05 640.28,56.91 538.72,56.91 " | ||
| 42 | id="polygon2" /> <polygon | ||
| 43 | points="353.96,465.84 303.17,393.31 201.61,538.36 303.17,538.36 " | ||
| 44 | id="polygon3" /> <polygon | ||
| 45 | points="531.69,538.36 303.17,211.99 201.61,211.99 430.13,538.36 " | ||
| 46 | id="polygon4" /> </g> </svg> | ||
| @@ -197,6 +197,9 @@ | |||
| 197 | <div id="update_oai_preset" class="menu_button menu_button_icon" title="Update current preset" data-i18n="[title]Update current preset"> | 197 | <div id="update_oai_preset" class="menu_button menu_button_icon" title="Update current preset" data-i18n="[title]Update current preset"> |
| 198 | <i class="fa-fw fa-solid fa-save"></i> | 198 | <i class="fa-fw fa-solid fa-save"></i> |
| 199 | </div> | 199 | </div> |
| 200 | <div data-preset-manager-rename="openai" class="menu_button menu_button_icon" title="Rename current preset" data-i18n="[title]Rename current preset"> | ||
| 201 | <i class="fa-fw fa-solid fa-pencil"></i> | ||
| 202 | </div> | ||
| 200 | <div id="new_oai_preset" class="menu_button menu_button_icon" title="Save preset as" data-i18n="[title]Save preset as"> | 203 | <div id="new_oai_preset" class="menu_button menu_button_icon" title="Save preset as" data-i18n="[title]Save preset as"> |
| 201 | <i class="fa-fw fa-solid fa-file-circle-plus"></i> | 204 | <i class="fa-fw fa-solid fa-file-circle-plus"></i> |
| 202 | </div> | 205 | </div> |
| @@ -643,7 +646,7 @@ | |||
| 643 | <input type="number" id="openai_max_tokens" name="openai_max_tokens" class="text_pole" min="1" max="65536"> | 646 | <input type="number" id="openai_max_tokens" name="openai_max_tokens" class="text_pole" min="1" max="65536"> |
| 644 | </div> | 647 | </div> |
| 645 | </div> | 648 | </div> |
| 646 | <div class="range-block" data-source="openai,custom"> | 649 | <div class="range-block" data-source="openai,custom,xai"> |
| 647 | <div class="range-block-title" data-i18n="Multiple swipes per generation"> | 650 | <div class="range-block-title" data-i18n="Multiple swipes per generation"> |
| 648 | Multiple swipes per generation | 651 | Multiple swipes per generation |
| 649 | </div> | 652 | </div> |
| @@ -682,7 +685,7 @@ | |||
| 682 | </span> | 685 | </span> |
| 683 | </div> | 686 | </div> |
| 684 | </div> | 687 | </div> |
| 685 | <div class="range-block" data-source="openai,claude,windowai,openrouter,ai21,scale,makersuite,mistralai,custom,cohere,perplexity,groq,01ai,nanogpt,deepseek"> | 688 | <div class="range-block" data-source="openai,claude,windowai,openrouter,ai21,scale,makersuite,mistralai,custom,cohere,perplexity,groq,01ai,nanogpt,deepseek,xai"> |
| 686 | <div class="range-block-title" data-i18n="Temperature"> | 689 | <div class="range-block-title" data-i18n="Temperature"> |
| 687 | Temperature | 690 | Temperature |
| 688 | </div> | 691 | </div> |
| @@ -695,7 +698,7 @@ | |||
| 695 | </div> | 698 | </div> |
| 696 | </div> | 699 | </div> |
| 697 | </div> | 700 | </div> |
| 698 | <div class="range-block" data-source="openai,openrouter,custom,cohere,perplexity,groq,mistralai,nanogpt,deepseek"> | 701 | <div class="range-block" data-source="openai,openrouter,custom,cohere,perplexity,groq,mistralai,nanogpt,deepseek,xai"> |
| 699 | <div class="range-block-title" data-i18n="Frequency Penalty"> | 702 | <div class="range-block-title" data-i18n="Frequency Penalty"> |
| 700 | Frequency Penalty | 703 | Frequency Penalty |
| 701 | </div> | 704 | </div> |
| @@ -708,7 +711,7 @@ | |||
| 708 | </div> | 711 | </div> |
| 709 | </div> | 712 | </div> |
| 710 | </div> | 713 | </div> |
| 711 | <div class="range-block" data-source="openai,openrouter,custom,cohere,perplexity,groq,mistralai,nanogpt,deepseek"> | 714 | <div class="range-block" data-source="openai,openrouter,custom,cohere,perplexity,groq,mistralai,nanogpt,deepseek,xai"> |
| 712 | <div class="range-block-title" data-i18n="Presence Penalty"> | 715 | <div class="range-block-title" data-i18n="Presence Penalty"> |
| 713 | Presence Penalty | 716 | Presence Penalty |
| 714 | </div> | 717 | </div> |
| @@ -734,7 +737,7 @@ | |||
| 734 | </div> | 737 | </div> |
| 735 | </div> | 738 | </div> |
| 736 | </div> | 739 | </div> |
| 737 | <div class="range-block" data-source="openai,claude,openrouter,ai21,scale,makersuite,mistralai,custom,cohere,perplexity,groq,01ai,nanogpt,deepseek"> | 740 | <div class="range-block" data-source="openai,claude,openrouter,ai21,scale,makersuite,mistralai,custom,cohere,perplexity,groq,01ai,nanogpt,deepseek,xai"> |
| 738 | <div class="range-block-title" data-i18n="Top P"> | 741 | <div class="range-block-title" data-i18n="Top P"> |
| 739 | Top P | 742 | Top P |
| 740 | </div> | 743 | </div> |
| @@ -971,7 +974,7 @@ | |||
| 971 | </div> | 974 | </div> |
| 972 | </div> | 975 | </div> |
| 973 | </div> | 976 | </div> |
| 974 | <div class="range-block" data-source="openai,openrouter,mistralai,custom,cohere,groq,nanogpt"> | 977 | <div class="range-block" data-source="openai,openrouter,mistralai,custom,cohere,groq,nanogpt,xai"> |
| 975 | <div class="range-block-title justifyLeft" data-i18n="Seed"> | 978 | <div class="range-block-title justifyLeft" data-i18n="Seed"> |
| 976 | Seed | 979 | Seed |
| 977 | </div> | 980 | </div> |
| @@ -1416,7 +1419,7 @@ | |||
| 1416 | </div> | 1419 | </div> |
| 1417 | </div> | 1420 | </div> |
| 1418 | 1421 | ||
| 1419 | <div data-tg-type="aphrodite, ooba, koboldcpp, tabby, llamacpp" id="dryBlock" class="wide100p"> | 1422 | <div data-tg-type="aphrodite, ooba, koboldcpp, tabby, llamacpp, dreamgen" id="dryBlock" class="wide100p"> |
| 1420 | <h4 class="wide100p textAlignCenter" title="DRY penalizes tokens that would extend the end of the input into a sequence that has previously occurred in the input. Set multiplier to 0 to disable." data-i18n="[title]DRY_Repetition_Penalty_desc"> | 1423 | <h4 class="wide100p textAlignCenter" title="DRY penalizes tokens that would extend the end of the input into a sequence that has previously occurred in the input. Set multiplier to 0 to disable." data-i18n="[title]DRY_Repetition_Penalty_desc"> |
| 1421 | <label data-i18n="DRY Repetition Penalty">DRY Repetition Penalty</label> | 1424 | <label data-i18n="DRY Repetition Penalty">DRY Repetition Penalty</label> |
| 1422 | <a href="https://github.com/oobabooga/text-generation-webui/pull/5677" target="_blank"> | 1425 | <a href="https://github.com/oobabooga/text-generation-webui/pull/5677" target="_blank"> |
| @@ -1571,7 +1574,7 @@ | |||
| 1571 | <div class="fa-solid fa-circle-info opacity50p " data-i18n="[title]Add the bos_token to the beginning of prompts. Disabling this can make the replies more creative" title="Add the bos_token to the beginning of prompts. Disabling this can make the replies more creative."></div> | 1574 | <div class="fa-solid fa-circle-info opacity50p " data-i18n="[title]Add the bos_token to the beginning of prompts. Disabling this can make the replies more creative" title="Add the bos_token to the beginning of prompts. Disabling this can make the replies more creative."></div> |
| 1572 | </label> | 1575 | </label> |
| 1573 | </label> | 1576 | </label> |
| 1574 | <label data-tg-type="ooba, llamacpp, tabby, koboldcpp" class="checkbox_label flexGrow flexShrink" for="ban_eos_token_textgenerationwebui"> | 1577 | <label data-tg-type="ooba, llamacpp, tabby, koboldcpp, dreamgen" class="checkbox_label flexGrow flexShrink" for="ban_eos_token_textgenerationwebui"> |
| 1575 | <input type="checkbox" id="ban_eos_token_textgenerationwebui" /> | 1578 | <input type="checkbox" id="ban_eos_token_textgenerationwebui" /> |
| 1576 | <label> | 1579 | <label> |
| 1577 | <small data-i18n="Ban EOS Token">Ban EOS Token</small> | 1580 | <small data-i18n="Ban EOS Token">Ban EOS Token</small> |
| @@ -1957,12 +1960,15 @@ | |||
| 1957 | <span data-i18n="Enable web search">Enable web search</span> | 1960 | <span data-i18n="Enable web search">Enable web search</span> |
| 1958 | </label> | 1961 | </label> |
| 1959 | <div class="flexBasis100p toggle-description justifyLeft"> | 1962 | <div class="flexBasis100p toggle-description justifyLeft"> |
| 1960 | <span> | 1963 | <span data-i18n="Use search capabilities provided by the backend."> |
| 1961 | Use search capabilities provided by the backend. | 1964 | Use search capabilities provided by the backend. |
| 1962 | </span> | 1965 | </span> |
| 1966 | <b data-source="openrouter" data-i18n="openrouter_web_search_fee"> | ||
| 1967 | Not free, adds a $0.02 fee to each prompt. | ||
| 1968 | </b> | ||
| 1963 | </div> | 1969 | </div> |
| 1964 | </div> | 1970 | </div> |
| 1965 | <div class="range-block" data-source="openai,cohere,mistralai,custom,claude,openrouter,groq,deepseek,makersuite,ai21"> | 1971 | <div class="range-block" data-source="openai,cohere,mistralai,custom,claude,openrouter,groq,deepseek,makersuite,ai21,xai"> |
| 1966 | <label for="openai_function_calling" class="checkbox_label flexWrap widthFreeExpand"> | 1972 | <label for="openai_function_calling" class="checkbox_label flexWrap widthFreeExpand"> |
| 1967 | <input id="openai_function_calling" type="checkbox" /> | 1973 | <input id="openai_function_calling" type="checkbox" /> |
| 1968 | <span data-i18n="Enable function calling">Enable function calling</span> | 1974 | <span data-i18n="Enable function calling">Enable function calling</span> |
| @@ -1972,7 +1978,7 @@ | |||
| 1972 | <span data-i18n="enable_functions_desc_3">Can be utilized by various extensions to provide additional functionality.</span> | 1978 | <span data-i18n="enable_functions_desc_3">Can be utilized by various extensions to provide additional functionality.</span> |
| 1973 | </div> | 1979 | </div> |
| 1974 | </div> | 1980 | </div> |
| 1975 | <div class="range-block" data-source="openai,openrouter,makersuite,claude,custom,01ai"> | 1981 | <div class="range-block" data-source="openai,openrouter,mistralai,makersuite,claude,custom,01ai,xai"> |
| 1976 | <label for="openai_image_inlining" class="checkbox_label flexWrap widthFreeExpand"> | 1982 | <label for="openai_image_inlining" class="checkbox_label flexWrap widthFreeExpand"> |
| 1977 | <input id="openai_image_inlining" type="checkbox" /> | 1983 | <input id="openai_image_inlining" type="checkbox" /> |
| 1978 | <span data-i18n="Send inline images">Send inline images</span> | 1984 | <span data-i18n="Send inline images">Send inline images</span> |
| @@ -1984,7 +1990,7 @@ | |||
| 1984 | <code><i class="fa-solid fa-wand-magic-sparkles"></i></code> | 1990 | <code><i class="fa-solid fa-wand-magic-sparkles"></i></code> |
| 1985 | <span data-i18n="image_inlining_hint_3">menu to attach an image file to the chat.</span> | 1991 | <span data-i18n="image_inlining_hint_3">menu to attach an image file to the chat.</span> |
| 1986 | </div> | 1992 | </div> |
| 1987 | <div class="flex-container flexFlowColumn wide100p textAlignCenter marginTop10" data-source="openai,custom"> | 1993 | <div class="flex-container flexFlowColumn wide100p textAlignCenter marginTop10" data-source="openai,custom,xai"> |
| 1988 | <div class="flex-container oneline-dropdown"> | 1994 | <div class="flex-container oneline-dropdown"> |
| 1989 | <label for="openai_inline_image_quality" data-i18n="Inline Image Quality"> | 1995 | <label for="openai_inline_image_quality" data-i18n="Inline Image Quality"> |
| 1990 | Inline Image Quality | 1996 | Inline Image Quality |
| @@ -2028,7 +2034,7 @@ | |||
| 2028 | </span> | 2034 | </span> |
| 2029 | </div> | 2035 | </div> |
| 2030 | </div> | 2036 | </div> |
| 2031 | <div class="range-block" data-source="deepseek,openrouter,custom,claude"> | 2037 | <div class="range-block" data-source="deepseek,openrouter,custom,claude,xai"> |
| 2032 | <label for="openai_show_thoughts" class="checkbox_label widthFreeExpand"> | 2038 | <label for="openai_show_thoughts" class="checkbox_label widthFreeExpand"> |
| 2033 | <input id="openai_show_thoughts" type="checkbox" /> | 2039 | <input id="openai_show_thoughts" type="checkbox" /> |
| 2034 | <span> | 2040 | <span> |
| @@ -2042,7 +2048,7 @@ | |||
| 2042 | </span> | 2048 | </span> |
| 2043 | </div> | 2049 | </div> |
| 2044 | </div> | 2050 | </div> |
| 2045 | <div class="flex-container flexFlowColumn wide100p textAlignCenter marginTop10" data-source="openai,custom,claude"> | 2051 | <div class="flex-container flexFlowColumn wide100p textAlignCenter marginTop10" data-source="openai,custom,claude,xai"> |
| 2046 | <div class="flex-container oneline-dropdown" title="Constrains effort on reasoning for reasoning models. Currently supported values are low, medium, and high. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response." data-i18n="[title]Constrains effort on reasoning for reasoning models."> | 2052 | <div class="flex-container oneline-dropdown" title="Constrains effort on reasoning for reasoning models. Currently supported values are low, medium, and high. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response." data-i18n="[title]Constrains effort on reasoning for reasoning models."> |
| 2047 | <label for="openai_reasoning_effort"> | 2053 | <label for="openai_reasoning_effort"> |
| 2048 | <span data-i18n="Reasoning Effort">Reasoning Effort</span> | 2054 | <span data-i18n="Reasoning Effort">Reasoning Effort</span> |
| @@ -2188,7 +2194,7 @@ | |||
| 2188 | <input id="horde_trusted_workers_only" type="checkbox" /> | 2194 | <input id="horde_trusted_workers_only" type="checkbox" /> |
| 2189 | <span data-i18n="Trusted workers only">Trusted workers only</span> | 2195 | <span data-i18n="Trusted workers only">Trusted workers only</span> |
| 2190 | </label> | 2196 | </label> |
| 2191 | <small id="adjustedHordeParams">Context: --, Response: --</small> | 2197 | <small id="adjustedHordeParams"><span data-i18n="Context">Context</span>: --, <span data-i18n="Response">Response</span>: --</small> |
| 2192 | <h4 data-i18n="API key">API key</h4> | 2198 | <h4 data-i18n="API key">API key</h4> |
| 2193 | <small> | 2199 | <small> |
| 2194 | <span data-i18n="Get it here:">Get it here: </span> <a target="_blank" href="https://aihorde.net/register" data-i18n="Register">Register</a> (<a id="horde_kudos" href="javascript:void(0);" data-i18n="View my Kudos">View my Kudos</a>)<br> | 2200 | <span data-i18n="Get it here:">Get it here: </span> <a target="_blank" href="https://aihorde.net/register" data-i18n="Register">Register</a> (<a id="horde_kudos" href="javascript:void(0);" data-i18n="View my Kudos">View my Kudos</a>)<br> |
| @@ -2429,7 +2435,7 @@ | |||
| 2429 | </div> | 2435 | </div> |
| 2430 | <div class="flex1"> | 2436 | <div class="flex1"> |
| 2431 | <h4 data-i18n="Server url">Server URL</h4> | 2437 | <h4 data-i18n="Server url">Server URL</h4> |
| 2432 | <small data-i18n="Example: 127.0.0.1:5000">Example: http://127.0.0.1:5000</small> | 2438 | <small data-i18n="Example: http://127.0.0.1:5000">Example: http://127.0.0.1:5000</small> |
| 2433 | <input id="generic_api_url_text" name="generic_api_url" class="text_pole wide100p" value="" autocomplete="off" data-server-history="generic"> | 2439 | <input id="generic_api_url_text" name="generic_api_url" class="text_pole wide100p" value="" autocomplete="off" data-server-history="generic"> |
| 2434 | </div> | 2440 | </div> |
| 2435 | <datalist id="generic_model_fill"></datalist> | 2441 | <datalist id="generic_model_fill"></datalist> |
| @@ -2458,7 +2464,7 @@ | |||
| 2458 | </div> | 2464 | </div> |
| 2459 | <div class="flex1"> | 2465 | <div class="flex1"> |
| 2460 | <h4 data-i18n="Server url">Server URL</h4> | 2466 | <h4 data-i18n="Server url">Server URL</h4> |
| 2461 | <small data-i18n="Example: 127.0.0.1:5000">Example: http://127.0.0.1:5000</small> | 2467 | <small data-i18n="Example: http://127.0.0.1:5000">Example: http://127.0.0.1:5000</small> |
| 2462 | <input id="textgenerationwebui_api_url_text" name="textgenerationwebui_api_url" class="text_pole wide100p" value="" autocomplete="off" data-server-history="ooba_blocking"> | 2468 | <input id="textgenerationwebui_api_url_text" name="textgenerationwebui_api_url" class="text_pole wide100p" value="" autocomplete="off" data-server-history="ooba_blocking"> |
| 2463 | </div> | 2469 | </div> |
| 2464 | <input id="custom_model_textgenerationwebui" class="text_pole wide100p" placeholder="Custom model (optional)" data-i18n="[placeholder]Custom model (optional)" type="text"> | 2470 | <input id="custom_model_textgenerationwebui" class="text_pole wide100p" placeholder="Custom model (optional)" data-i18n="[placeholder]Custom model (optional)" type="text"> |
| @@ -2531,7 +2537,7 @@ | |||
| 2531 | </div> | 2537 | </div> |
| 2532 | <div class="flex1"> | 2538 | <div class="flex1"> |
| 2533 | <h4 data-i18n="API url">API URL</h4> | 2539 | <h4 data-i18n="API url">API URL</h4> |
| 2534 | <small data-i18n="Example: 127.0.0.1:8000">Example: http://127.0.0.1:8000</small> | 2540 | <small data-i18n="Example: http://127.0.0.1:8000">Example: http://127.0.0.1:8000</small> |
| 2535 | <input id="vllm_api_url_text" class="text_pole wide100p" value="" autocomplete="off" data-server-history="vllm"> | 2541 | <input id="vllm_api_url_text" class="text_pole wide100p" value="" autocomplete="off" data-server-history="vllm"> |
| 2536 | </div> | 2542 | </div> |
| 2537 | <div> | 2543 | <div> |
| @@ -2577,7 +2583,7 @@ | |||
| 2577 | </div> | 2583 | </div> |
| 2578 | <div class="flex1"> | 2584 | <div class="flex1"> |
| 2579 | <h4 data-i18n="API url">API URL</h4> | 2585 | <h4 data-i18n="API url">API URL</h4> |
| 2580 | <small data-i18n="Example: 127.0.0.1:5000">Example: http://127.0.0.1:5000</small> | 2586 | <small data-i18n="Example: http://127.0.0.1:5000">Example: http://127.0.0.1:5000</small> |
| 2581 | <input id="aphrodite_api_url_text" class="text_pole wide100p" value="" autocomplete="off" data-server-history="aphrodite"> | 2587 | <input id="aphrodite_api_url_text" class="text_pole wide100p" value="" autocomplete="off" data-server-history="aphrodite"> |
| 2582 | </div> | 2588 | </div> |
| 2583 | <div> | 2589 | <div> |
| @@ -2606,7 +2612,7 @@ | |||
| 2606 | </div> | 2612 | </div> |
| 2607 | <div class="flex1"> | 2613 | <div class="flex1"> |
| 2608 | <h4 data-i18n="API url">API URL</h4> | 2614 | <h4 data-i18n="API url">API URL</h4> |
| 2609 | <small data-i18n="Example: 127.0.0.1:8080">Example: http://127.0.0.1:8080</small> | 2615 | <small data-i18n="Example: http://127.0.0.1:8080">Example: http://127.0.0.1:8080</small> |
| 2610 | <input id="llamacpp_api_url_text" class="text_pole wide100p" value="" autocomplete="off" data-server-history="llamacpp"> | 2616 | <input id="llamacpp_api_url_text" class="text_pole wide100p" value="" autocomplete="off" data-server-history="llamacpp"> |
| 2611 | </div> | 2617 | </div> |
| 2612 | </div> | 2618 | </div> |
| @@ -2618,7 +2624,7 @@ | |||
| 2618 | </div> | 2624 | </div> |
| 2619 | <div class="flex1"> | 2625 | <div class="flex1"> |
| 2620 | <h4 data-i18n="API url">API URL</h4> | 2626 | <h4 data-i18n="API url">API URL</h4> |
| 2621 | <small data-i18n="Example: 127.0.0.1:11434">Example: http://127.0.0.1:11434</small> | 2627 | <small data-i18n="Example: http://127.0.0.1:11434">Example: http://127.0.0.1:11434</small> |
| 2622 | <input id="ollama_api_url_text" class="text_pole wide100p" value="" autocomplete="off" data-server-history="ollama"> | 2628 | <input id="ollama_api_url_text" class="text_pole wide100p" value="" autocomplete="off" data-server-history="ollama"> |
| 2623 | </div> | 2629 | </div> |
| 2624 | <div class="flex1"> | 2630 | <div class="flex1"> |
| @@ -2653,7 +2659,7 @@ | |||
| 2653 | </div> | 2659 | </div> |
| 2654 | <div class="flex1"> | 2660 | <div class="flex1"> |
| 2655 | <h4 data-i18n="API url">API URL</h4> | 2661 | <h4 data-i18n="API url">API URL</h4> |
| 2656 | <small data-i18n="Example: 127.0.0.1:5000">Example: http://127.0.0.1:5000</small> | 2662 | <small data-i18n="Example: http://127.0.0.1:5000">Example: http://127.0.0.1:5000</small> |
| 2657 | <input id="tabby_api_url_text" class="text_pole wide100p" value="" autocomplete="off" data-server-history="tabby"> | 2663 | <input id="tabby_api_url_text" class="text_pole wide100p" value="" autocomplete="off" data-server-history="tabby"> |
| 2658 | </div> | 2664 | </div> |
| 2659 | <div class="flex1"> | 2665 | <div class="flex1"> |
| @@ -2705,7 +2711,7 @@ | |||
| 2705 | </div> | 2711 | </div> |
| 2706 | <div class="flex1"> | 2712 | <div class="flex1"> |
| 2707 | <h4 data-i18n="API url">API URL</h4> | 2713 | <h4 data-i18n="API url">API URL</h4> |
| 2708 | <small data-i18n="Example: 127.0.0.1:5001">Example: http://127.0.0.1:5001</small> | 2714 | <small data-i18n="Example: http://127.0.0.1:5001">Example: http://127.0.0.1:5001</small> |
| 2709 | <input id="koboldcpp_api_url_text" class="text_pole wide100p" value="" autocomplete="off" data-server-history="koboldcpp"> | 2715 | <input id="koboldcpp_api_url_text" class="text_pole wide100p" value="" autocomplete="off" data-server-history="koboldcpp"> |
| 2710 | </div> | 2716 | </div> |
| 2711 | </div> | 2717 | </div> |
| @@ -2742,7 +2748,6 @@ | |||
| 2742 | <optgroup> | 2748 | <optgroup> |
| 2743 | <option value="01ai">01.AI (Yi)</option> | 2749 | <option value="01ai">01.AI (Yi)</option> |
| 2744 | <option value="ai21">AI21</option> | 2750 | <option value="ai21">AI21</option> |
| 2745 | <option value="blockentropy">Block Entropy</option> | ||
| 2746 | <option value="claude">Claude</option> | 2751 | <option value="claude">Claude</option> |
| 2747 | <option value="cohere">Cohere</option> | 2752 | <option value="cohere">Cohere</option> |
| 2748 | <option value="deepseek">DeepSeek</option> | 2753 | <option value="deepseek">DeepSeek</option> |
| @@ -2754,9 +2759,10 @@ | |||
| 2754 | <option value="perplexity">Perplexity</option> | 2759 | <option value="perplexity">Perplexity</option> |
| 2755 | <option value="scale">Scale</option> | 2760 | <option value="scale">Scale</option> |
| 2756 | <option value="windowai">Window AI</option> | 2761 | <option value="windowai">Window AI</option> |
| 2762 | <option value="xai">xAI (Grok)</option> | ||
| 2757 | </optgroup> | 2763 | </optgroup> |
| 2758 | </select> | 2764 | </select> |
| 2759 | <div class="inline-drawer wide100p" data-source="openai,claude,mistralai,makersuite,deepseek"> | 2765 | <div class="inline-drawer wide100p" data-source="openai,claude,mistralai,makersuite,deepseek,xai"> |
| 2760 | <div class="inline-drawer-toggle inline-drawer-header"> | 2766 | <div class="inline-drawer-toggle inline-drawer-header"> |
| 2761 | <b data-i18n="Reverse Proxy">Reverse Proxy</b> | 2767 | <b data-i18n="Reverse Proxy">Reverse Proxy</b> |
| 2762 | <div class="fa-solid fa-circle-chevron-down inline-drawer-icon down"></div> | 2768 | <div class="fa-solid fa-circle-chevron-down inline-drawer-icon down"></div> |
| @@ -2819,7 +2825,7 @@ | |||
| 2819 | </div> | 2825 | </div> |
| 2820 | </div> | 2826 | </div> |
| 2821 | </div> | 2827 | </div> |
| 2822 | <div id="ReverseProxyWarningMessage" data-source="openai,claude,mistralai,makersuite,deepseek"> | 2828 | <div id="ReverseProxyWarningMessage" data-source="openai,claude,mistralai,makersuite,deepseek,xai"> |
| 2823 | <div class="reverse_proxy_warning"> | 2829 | <div class="reverse_proxy_warning"> |
| 2824 | <b> | 2830 | <b> |
| 2825 | <div data-i18n="Using a proxy that you're not running yourself is a risk to your data privacy."> | 2831 | <div data-i18n="Using a proxy that you're not running yourself is a risk to your data privacy."> |
| @@ -2883,7 +2889,15 @@ | |||
| 2883 | <option value="gpt-4o-2024-05-13">gpt-4o-2024-05-13</option> | 2889 | <option value="gpt-4o-2024-05-13">gpt-4o-2024-05-13</option> |
| 2884 | <option value="chatgpt-4o-latest">chatgpt-4o-latest</option> | 2890 | <option value="chatgpt-4o-latest">chatgpt-4o-latest</option> |
| 2885 | </optgroup> | 2891 | </optgroup> |
| 2886 | <optgroup label="o1 and o1-mini"> | 2892 | <optgroup label="GPT-4.1"> |
| 2893 | <option value="gpt-4.1">gpt-4.1</option> | ||
| 2894 | <option value="gpt-4.1-2025-04-14">gpt-4.1-2025-04-14</option> | ||
| 2895 | <option value="gpt-4.1-mini">gpt-4.1-mini</option> | ||
| 2896 | <option value="gpt-4.1-mini-2025-04-14">gpt-4.1-mini-2025-04-14</option> | ||
| 2897 | <option value="gpt-4.1-nano">gpt-4.1-nano</option> | ||
| 2898 | <option value="gpt-4.1-nano-2025-04-14">gpt-4.1-nano-2025-04-14</option> | ||
| 2899 | </optgroup> | ||
| 2900 | <optgroup label="o1"> | ||
| 2887 | <option value="o1">o1</option> | 2901 | <option value="o1">o1</option> |
| 2888 | <option value="o1-2024-12-17">o1-2024-12-17</option> | 2902 | <option value="o1-2024-12-17">o1-2024-12-17</option> |
| 2889 | <option value="o1-mini">o1-mini</option> | 2903 | <option value="o1-mini">o1-mini</option> |
| @@ -2892,9 +2906,15 @@ | |||
| 2892 | <option value="o1-preview-2024-09-12">o1-preview-2024-09-12</option> | 2906 | <option value="o1-preview-2024-09-12">o1-preview-2024-09-12</option> |
| 2893 | </optgroup> | 2907 | </optgroup> |
| 2894 | <optgroup label="o3"> | 2908 | <optgroup label="o3"> |
| 2909 | <option value="o3">o3</option> | ||
| 2910 | <option value="o3-2025-04-16">o3-2025-04-16</option> | ||
| 2895 | <option value="o3-mini">o3-mini</option> | 2911 | <option value="o3-mini">o3-mini</option> |
| 2896 | <option value="o3-mini-2025-01-31">o3-mini-2025-01-31</option> | 2912 | <option value="o3-mini-2025-01-31">o3-mini-2025-01-31</option> |
| 2897 | </optgroup> | 2913 | </optgroup> |
| 2914 | <optgroup label="o4"> | ||
| 2915 | <option value="o4-mini">o4-mini</option> | ||
| 2916 | <option value="o4-mini-2025-04-16">o4-mini-2025-04-16</option> | ||
| 2917 | </optgroup> | ||
| 2898 | <optgroup label="GPT-4.5"> | 2918 | <optgroup label="GPT-4.5"> |
| 2899 | <option value="gpt-4.5-preview">gpt-4.5-preview</option> | 2919 | <option value="gpt-4.5-preview">gpt-4.5-preview</option> |
| 2900 | <option value="gpt-4.5-preview-2025-02-27">gpt-4.5-preview-2025-02-27</option> | 2920 | <option value="gpt-4.5-preview-2025-02-27">gpt-4.5-preview-2025-02-27</option> |
| @@ -3138,8 +3158,11 @@ | |||
| 3138 | <option value="gemma-3-27b-it">Gemma 3 27B</option> | 3158 | <option value="gemma-3-27b-it">Gemma 3 27B</option> |
| 3139 | </optgroup> | 3159 | </optgroup> |
| 3140 | <optgroup label="Subversions"> | 3160 | <optgroup label="Subversions"> |
| 3161 | <option value="gemini-2.5-pro-preview-03-25">Gemini 2.5 Pro Preview 2025-03-25</option> | ||
| 3162 | <option value="gemini-2.5-pro-exp-03-25">Gemini 2.5 Pro Experimental 2025-03-25</option> | ||
| 3141 | <option value="gemini-2.0-pro-exp">Gemini 2.0 Pro Experimental</option> | 3163 | <option value="gemini-2.0-pro-exp">Gemini 2.0 Pro Experimental</option> |
| 3142 | <option value="gemini-2.0-pro-exp-02-05">Gemini 2.0 Pro Experimental 2025-02-05</option> | 3164 | <option value="gemini-2.0-pro-exp-02-05">Gemini 2.0 Pro Experimental 2025-02-05</option> |
| 3165 | <option value="gemini-2.5-flash-preview-04-17">Gemini 2.5 Flash Preview 2025-04-17</option> | ||
| 3143 | <option value="gemini-2.0-flash-lite-preview">Gemini 2.0 Flash-Lite Preview</option> | 3166 | <option value="gemini-2.0-flash-lite-preview">Gemini 2.0 Flash-Lite Preview</option> |
| 3144 | <option value="gemini-2.0-flash-lite-preview-02-05">Gemini 2.0 Flash-Lite Preview 2025-02-05</option> | 3167 | <option value="gemini-2.0-flash-lite-preview-02-05">Gemini 2.0 Flash-Lite Preview 2025-02-05</option> |
| 3145 | <option value="gemini-2.0-flash-001">Gemini 2.0 Flash [001]</option> | 3168 | <option value="gemini-2.0-flash-001">Gemini 2.0 Flash [001]</option> |
| @@ -3193,6 +3216,7 @@ | |||
| 3193 | <option value="mistral-small-latest">mistral-small-latest</option> | 3216 | <option value="mistral-small-latest">mistral-small-latest</option> |
| 3194 | <option value="mistral-medium-latest">mistral-medium-latest</option> | 3217 | <option value="mistral-medium-latest">mistral-medium-latest</option> |
| 3195 | <option value="mistral-large-latest">mistral-large-latest</option> | 3218 | <option value="mistral-large-latest">mistral-large-latest</option> |
| 3219 | <option value="mistral-saba-latest">mistral-saba-latest</option> | ||
| 3196 | <option value="codestral-latest">codestral-latest</option> | 3220 | <option value="codestral-latest">codestral-latest</option> |
| 3197 | <option value="codestral-mamba-latest">codestral-mamba-latest</option> | 3221 | <option value="codestral-mamba-latest">codestral-mamba-latest</option> |
| 3198 | <option value="pixtral-12b-latest">pixtral-12b-latest</option> | 3222 | <option value="pixtral-12b-latest">pixtral-12b-latest</option> |
| @@ -3208,13 +3232,20 @@ | |||
| 3208 | <option value="mistral-small-2312">mistral-small-2312</option> | 3232 | <option value="mistral-small-2312">mistral-small-2312</option> |
| 3209 | <option value="mistral-small-2402">mistral-small-2402</option> | 3233 | <option value="mistral-small-2402">mistral-small-2402</option> |
| 3210 | <option value="mistral-small-2409">mistral-small-2409</option> | 3234 | <option value="mistral-small-2409">mistral-small-2409</option> |
| 3235 | <option value="mistral-small-2501">mistral-small-2501</option> | ||
| 3236 | <option value="mistral-small-2503">mistral-small-2503</option> | ||
| 3211 | <option value="mistral-medium-2312">mistral-medium-2312</option> | 3237 | <option value="mistral-medium-2312">mistral-medium-2312</option> |
| 3212 | <option value="mistral-large-2402">mistral-large-2402</option> | 3238 | <option value="mistral-large-2402">mistral-large-2402</option> |
| 3213 | <option value="mistral-large-2407">mistral-large-2407</option> | 3239 | <option value="mistral-large-2407">mistral-large-2407</option> |
| 3214 | <option value="mistral-large-2411">mistral-large-2411</option> | 3240 | <option value="mistral-large-2411">mistral-large-2411</option> |
| 3241 | <option value="mistral-large-pixtral-2411">mistral-large-pixtral-2411</option> | ||
| 3242 | <option value="mistral-saba-2502">mistral-saba-2502</option> | ||
| 3215 | <option value="codestral-2405">codestral-2405</option> | 3243 | <option value="codestral-2405">codestral-2405</option> |
| 3216 | <option value="codestral-2405-blue">codestral-2405-blue</option> | 3244 | <option value="codestral-2405-blue">codestral-2405-blue</option> |
| 3217 | <option value="codestral-mamba-2407">codestral-mamba-2407</option> | 3245 | <option value="codestral-mamba-2407">codestral-mamba-2407</option> |
| 3246 | <option value="codestral-2411-rc5">codestral-2411-rc5</option> | ||
| 3247 | <option value="codestral-2412">codestral-2412</option> | ||
| 3248 | <option value="codestral-2501">codestral-2501</option> | ||
| 3218 | <option value="pixtral-12b-2409">pixtral-12b-2409</option> | 3249 | <option value="pixtral-12b-2409">pixtral-12b-2409</option> |
| 3219 | <option value="pixtral-large-2411">pixtral-large-2411</option> | 3250 | <option value="pixtral-large-2411">pixtral-large-2411</option> |
| 3220 | </optgroup> | 3251 | </optgroup> |
| @@ -3237,28 +3268,29 @@ | |||
| 3237 | <option value="qwen-2.5-32b">qwen-2.5-32b</option> | 3268 | <option value="qwen-2.5-32b">qwen-2.5-32b</option> |
| 3238 | <option value="qwen-2.5-coder-32b">qwen-2.5-coder-32b</option> | 3269 | <option value="qwen-2.5-coder-32b">qwen-2.5-coder-32b</option> |
| 3239 | </optgroup> | 3270 | </optgroup> |
| 3240 | <optgroup label="DeepSeek / Alibaba Cloud"> | 3271 | <optgroup label="DeepSeek"> |
| 3241 | <option value="deepseek-r1-distill-qwen-32b">deepseek-r1-distill-qwen-32b</option> | 3272 | <option value="deepseek-r1-distill-qwen-32b">deepseek-r1-distill-qwen-32b</option> |
| 3242 | </optgroup> | ||
| 3243 | <optgroup label="DeepSeek / Meta"> | ||
| 3244 | <option value="deepseek-r1-distill-llama-70b">deepseek-r1-distill-llama-70b</option> | 3273 | <option value="deepseek-r1-distill-llama-70b">deepseek-r1-distill-llama-70b</option> |
| 3245 | </optgroup> | 3274 | </optgroup> |
| 3246 | <optgroup label="Google"> | 3275 | <optgroup label="Google"> |
| 3247 | <option value="gemma2-9b-it">gemma2-9b-it</option> | 3276 | <option value="gemma2-9b-it">gemma2-9b-it</option> |
| 3248 | </optgroup> | 3277 | </optgroup> |
| 3249 | <optgroup label="Meta"> | 3278 | <optgroup label="Meta"> |
| 3250 | <option value="llama-3.1-8b-instant">llama-3.1-8b-instant </option> | 3279 | <option value="meta-llama/llama-4-scout-17b-16e-instruct">meta-llama/llama-4-scout-17b-16e-instruct</option> |
| 3280 | <option value="meta-llama/llama-4-maverick-17b-128e-instruct">meta-llama/llama-4-maverick-17b-128e-instruct</option> | ||
| 3281 | <option value="llama-3.1-8b-instant">llama-3.1-8b-instant</option> | ||
| 3251 | <option value="llama-3.2-11b-vision-preview">llama-3.2-11b-vision-preview </option> | 3282 | <option value="llama-3.2-11b-vision-preview">llama-3.2-11b-vision-preview </option> |
| 3252 | <option value="llama-3.2-1b-preview">llama-3.2-1b-preview </option> | 3283 | <option value="llama-3.2-1b-preview">llama-3.2-1b-preview </option> |
| 3253 | <option value="llama-3.2-3b-preview">llama-3.2-3b-preview </option> | 3284 | <option value="llama-3.2-3b-preview">llama-3.2-3b-preview </option> |
| 3254 | <option value="llama-3.2-90b-vision-preview">llama-3.2-90b-vision-preview </option> | 3285 | <option value="llama-3.2-90b-vision-preview">llama-3.2-90b-vision-preview </option> |
| 3255 | <option value="llama-3.3-70b-specdec">llama-3.3-70b-specdec </option> | 3286 | <option value="llama-3.3-70b-specdec">llama-3.3-70b-specdec</option> |
| 3256 | <option value="llama-3.3-70b-versatile">llama-3.3-70b-versatile </option> | 3287 | <option value="llama-3.3-70b-versatile">llama-3.3-70b-versatile </option> |
| 3257 | <option value="llama-guard-3-8b">llama-guard-3-8b </option> | 3288 | <option value="llama-guard-3-8b">llama-guard-3-8b</option> |
| 3258 | <option value="llama3-70b-8192">llama3-70b-8192 </option> | 3289 | <option value="llama3-70b-8192">llama3-70b-8192</option> |
| 3259 | <option value="llama3-8b-8192">llama3-8b-8192 </option> | 3290 | <option value="llama3-8b-8192">llama3-8b-8192</option> |
| 3260 | </optgroup> | 3291 | </optgroup> |
| 3261 | <optgroup label="Mistral AI"> | 3292 | <optgroup label="Mistral AI"> |
| 3293 | <option value="mistral-saba-24b">mistral-saba-24b</option> | ||
| 3262 | <option value="mixtral-8x7b-32768">mixtral-8x7b-32768</option> | 3294 | <option value="mixtral-8x7b-32768">mixtral-8x7b-32768</option> |
| 3263 | </optgroup> | 3295 | </optgroup> |
| 3264 | </select> | 3296 | </select> |
| @@ -3363,20 +3395,6 @@ | |||
| 3363 | </select> | 3395 | </select> |
| 3364 | </div> | 3396 | </div> |
| 3365 | </form> | 3397 | </form> |
| 3366 | <form id="blockentropy_form" data-source="blockentropy"> | ||
| 3367 | <h4 data-i18n="Block Entropy API Key">Block Entropy API Key</h4> | ||
| 3368 | <div class="flex-container"> | ||
| 3369 | <input id="api_key_blockentropy" name="api_key_blockentropy" class="text_pole flex1" value="" type="text" autocomplete="off"> | ||
| 3370 | <div title="Clear your API key" data-i18n="[title]Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_blockentropy"></div> | ||
| 3371 | </div> | ||
| 3372 | <div data-for="api_key_blockentropy" class="neutral_warning" data-i18n="For privacy reasons, your API key will be hidden after you reload the page."> | ||
| 3373 | For privacy reasons, your API key will be hidden after you reload the page. | ||
| 3374 | </div> | ||
| 3375 | <h4 data-i18n="Select a Model">Select a Model</h4> | ||
| 3376 | <div class="flex-container"> | ||
| 3377 | <select id="model_blockentropy_select" class="text_pole"></select> | ||
| 3378 | </div> | ||
| 3379 | </form> | ||
| 3380 | <form id="custom_form" data-source="custom"> | 3398 | <form id="custom_form" data-source="custom"> |
| 3381 | <h4 data-i18n="Custom Endpoint (Base URL)">Custom Endpoint (Base URL)</h4> | 3399 | <h4 data-i18n="Custom Endpoint (Base URL)">Custom Endpoint (Base URL)</h4> |
| 3382 | <div class="flex-container"> | 3400 | <div class="flex-container"> |
| @@ -3407,17 +3425,10 @@ | |||
| 3407 | <div class="flex-container"> | 3425 | <div class="flex-container"> |
| 3408 | <select id="model_custom_select" class="text_pole model_custom_select"></select> | 3426 | <select id="model_custom_select" class="text_pole model_custom_select"></select> |
| 3409 | </div> | 3427 | </div> |
| 3410 | <h4 data-i18n="Prompt Post-Processing">Prompt Post-Processing</h4> | ||
| 3411 | <select id="custom_prompt_post_processing" class="text_pole" title="Applies additional processing to the prompt before sending it to the API." data-i18n="[title]Applies additional processing to the prompt before sending it to the API."> | ||
| 3412 | <option data-i18n="prompt_post_processing_none" value="">None</option> | ||
| 3413 | <option data-i18n="prompt_post_processing_merge" value="merge">Merge consecutive roles</option> | ||
| 3414 | <option data-i18n="prompt_post_processing_semi" value="semi">Semi-strict (alternating roles)</option> | ||
| 3415 | <option data-i18n="prompt_post_processing_strict" value="strict">Strict (user first, alternating roles)</option> | ||
| 3416 | </select> | ||
| 3417 | </form> | 3428 | </form> |
| 3418 | <div id="01ai_form" data-source="01ai"> | 3429 | <div id="01ai_form" data-source="01ai"> |
| 3419 | <h4> | 3430 | <h4> |
| 3420 | <a data-i18n="01.AI API Key" href="https://platform.01.ai/" target="_blank" rel="noopener noreferrer"> | 3431 | <a data-i18n="01.AI API Key" href="https://platform.lingyiwanwu.com/" target="_blank" rel="noopener noreferrer"> |
| 3421 | 01.AI API Key | 3432 | 01.AI API Key |
| 3422 | </a> | 3433 | </a> |
| 3423 | </h4> | 3434 | </h4> |
| @@ -3432,6 +3443,40 @@ | |||
| 3432 | <select id="model_01ai_select"> | 3443 | <select id="model_01ai_select"> |
| 3433 | </select> | 3444 | </select> |
| 3434 | </div> | 3445 | </div> |
| 3446 | <div id="xai_form" data-source="xai"> | ||
| 3447 | <h4> | ||
| 3448 | <a data-i18n="xAI API Key" href="https://console.x.ai/" target="_blank" rel="noopener noreferrer"> | ||
| 3449 | xAI API Key | ||
| 3450 | </a> | ||
| 3451 | </h4> | ||
| 3452 | <div class="flex-container"> | ||
| 3453 | <input id="api_key_xai" name="api_key_xai" class="text_pole flex1" value="" type="text" autocomplete="off"> | ||
| 3454 | <div title="Clear your API key" data-i18n="[title]Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_xai"></div> | ||
| 3455 | </div> | ||
| 3456 | <div data-for="api_key_xai" class="neutral_warning" data-i18n="For privacy reasons, your API key will be hidden after you reload the page."> | ||
| 3457 | For privacy reasons, your API key will be hidden after you reload the page. | ||
| 3458 | </div> | ||
| 3459 | <h4 data-i18n="xAI Model">xAI Model</h4> | ||
| 3460 | <select id="model_xai_select"> | ||
| 3461 | <option value="grok-3-beta">grok-3-beta</option> | ||
| 3462 | <option value="grok-3-fast-beta">grok-3-fast-beta</option> | ||
| 3463 | <option value="grok-3-mini-beta">grok-3-mini-beta</option> | ||
| 3464 | <option value="grok-3-mini-fast-beta">grok-3-mini-fast-beta</option> | ||
| 3465 | <option value="grok-2-vision-1212">grok-2-vision-1212</option> | ||
| 3466 | <option value="grok-2-1212">grok-2-1212</option> | ||
| 3467 | <option value="grok-vision-beta">grok-vision-beta</option> | ||
| 3468 | <option value="grok-beta">grok-beta</option> | ||
| 3469 | </select> | ||
| 3470 | </div> | ||
| 3471 | <div id="prompt_post_porcessing_form" data-source="custom,openrouter"> | ||
| 3472 | <h4 data-i18n="Prompt Post-Processing">Prompt Post-Processing</h4> | ||
| 3473 | <select id="custom_prompt_post_processing" class="text_pole" title="Applies additional processing to the prompt before sending it to the API." data-i18n="[title]Applies additional processing to the prompt before sending it to the API."> | ||
| 3474 | <option data-i18n="prompt_post_processing_none" value="">None</option> | ||
| 3475 | <option data-i18n="prompt_post_processing_merge" value="merge">Merge consecutive roles</option> | ||
| 3476 | <option data-i18n="prompt_post_processing_semi" value="semi">Semi-strict (alternating roles)</option> | ||
| 3477 | <option data-i18n="prompt_post_processing_strict" value="strict">Strict (user first, alternating roles)</option> | ||
| 3478 | </select> | ||
| 3479 | </div> | ||
| 3435 | <div class="flex-container flex"> | 3480 | <div class="flex-container flex"> |
| 3436 | <div id="api_button_openai" class="api_button menu_button menu_button_icon" type="submit" data-i18n="Connect">Connect</div> | 3481 | <div id="api_button_openai" class="api_button menu_button menu_button_icon" type="submit" data-i18n="Connect">Connect</div> |
| 3437 | <div class="api_loading menu_button menu_button_icon" data-i18n="Cancel">Cancel</div> | 3482 | <div class="api_loading menu_button menu_button_icon" data-i18n="Cancel">Cancel</div> |
| @@ -3917,6 +3962,19 @@ | |||
| 3917 | <summary data-i18n="Reasoning Formatting"> | 3962 | <summary data-i18n="Reasoning Formatting"> |
| 3918 | Reasoning Formatting | 3963 | Reasoning Formatting |
| 3919 | </summary> | 3964 | </summary> |
| 3965 | <div class="flex-container" title="Select your current Reasoning Template" data-i18n="[title]Select your current Reasoning Template"> | ||
| 3966 | <select id="reasoning_select" data-preset-manager-for="reasoning" class="flex1 text_pole"></select> | ||
| 3967 | <div class="flex-container margin0 justifyCenter gap3px"> | ||
| 3968 | <input type="file" hidden data-preset-manager-file="reasoning" accept=".json, .settings"> | ||
| 3969 | <i data-preset-manager-update="reasoning" class="menu_button fa-solid fa-save" title="Update current template" data-i18n="[title]Update current template"></i> | ||
| 3970 | <i data-preset-manager-rename="reasoning" class="menu_button fa-pencil fa-solid" title="Rename current template" data-i18n="[title]Rename current template"></i> | ||
| 3971 | <i data-preset-manager-new="reasoning" class="menu_button fa-solid fa-file-circle-plus" title="Save template as" data-i18n="[title]Save template as"></i> | ||
| 3972 | <i data-preset-manager-import="reasoning" class="displayNone menu_button fa-solid fa-file-import" title="Import template" data-i18n="[title]Import template"></i> | ||
| 3973 | <i data-preset-manager-export="reasoning" class="displayNone menu_button fa-solid fa-file-export" title="Export template" data-i18n="[title]Export template"></i> | ||
| 3974 | <i data-preset-manager-restore="reasoning" class="menu_button fa-solid fa-recycle" title="Restore current template" data-i18n="[title]Restore current template"></i> | ||
| 3975 | <i data-preset-manager-delete="reasoning" class="menu_button fa-solid fa-trash-can" title="Delete template" data-i18n="[title]Delete template"></i> | ||
| 3976 | </div> | ||
| 3977 | </div> | ||
| 3920 | <div class="flex-container"> | 3978 | <div class="flex-container"> |
| 3921 | <div class="flex1" title="Inserted before the reasoning content." data-i18n="[title]reasoning_prefix"> | 3979 | <div class="flex1" title="Inserted before the reasoning content." data-i18n="[title]reasoning_prefix"> |
| 3922 | <small data-i18n="Prefix">Prefix</small> | 3980 | <small data-i18n="Prefix">Prefix</small> |
| @@ -5099,7 +5157,7 @@ | |||
| 5099 | <div id="persona_depth_position_settings" class="flex-container"> | 5157 | <div id="persona_depth_position_settings" class="flex-container"> |
| 5100 | <div class="flex1"> | 5158 | <div class="flex1"> |
| 5101 | <label for="persona_depth_value" data-i18n="Depth:">Depth:</label> | 5159 | <label for="persona_depth_value" data-i18n="Depth:">Depth:</label> |
| 5102 | <input id="persona_depth_value" class="text_pole" type="number" min="0" max="999" step="1"> | 5160 | <input id="persona_depth_value" class="text_pole" type="number" min="0" max="9999" step="1"> |
| 5103 | </div> | 5161 | </div> |
| 5104 | <div class="flex1"> | 5162 | <div class="flex1"> |
| 5105 | <label for="persona_depth_role" data-i18n="Role:">Role:</label> | 5163 | <label for="persona_depth_role" data-i18n="Role:">Role:</label> |
| @@ -5752,7 +5810,7 @@ | |||
| 5752 | @ Depth | 5810 | @ Depth |
| 5753 | </span> | 5811 | </span> |
| 5754 | </h4> | 5812 | </h4> |
| 5755 | <input id="depth_prompt_depth" name="depth_prompt_depth" class="text_pole textarea_compact m-t-0" type="number" min="0" max="999" value="4" form="form_create" /> | 5813 | <input id="depth_prompt_depth" name="depth_prompt_depth" class="text_pole textarea_compact m-t-0" type="number" min="0" max="9999" value="4" form="form_create" /> |
| 5756 | <h4> | 5814 | <h4> |
| 5757 | <span data-i18n="Role"> | 5815 | <span data-i18n="Role"> |
| 5758 | Role | 5816 | Role |
| @@ -5973,11 +6031,11 @@ | |||
| 5973 | </div> | 6031 | </div> |
| 5974 | <div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap"> | 6032 | <div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap"> |
| 5975 | <label for="depth" class="WIEntryHeaderTitleMobile" data-i18n="Depth:">Depth:</label> | 6033 | <label for="depth" class="WIEntryHeaderTitleMobile" data-i18n="Depth:">Depth:</label> |
| 5976 | <input title="Depth" class="text_pole wideMax100px margin0" type="number" name="depth" data-i18n="[title]Depth" placeholder="" min="0" max="999" /> | 6034 | <input title="Depth" class="text_pole wideMax100px margin0" type="number" name="depth" data-i18n="[title]Depth" placeholder="" min="0" max="9999" /> |
| 5977 | </div> | 6035 | </div> |
| 5978 | <div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap"> | 6036 | <div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap"> |
| 5979 | <label for="order" class="WIEntryHeaderTitleMobile" data-i18n="Order:">Order:</label> | 6037 | <label for="order" class="WIEntryHeaderTitleMobile" data-i18n="Order:">Order:</label> |
| 5980 | <input title="Order" data-i18n="[title]Order" class="text_pole wideMax100px margin0" type="number" name="order" placeholder="" min="0" max="999" /> | 6038 | <input title="Order" data-i18n="[title]Order" class="text_pole wideMax100px margin0" type="number" name="order" placeholder="" min="0" max="9999" /> |
| 5981 | </div> | 6039 | </div> |
| 5982 | <div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap probabilityContainer"> | 6040 | <div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap probabilityContainer"> |
| 5983 | <label for="order" class="WIEntryHeaderTitleMobile" data-i18n="Trigger %:">Trigger %:</label> | 6041 | <label for="order" class="WIEntryHeaderTitleMobile" data-i18n="Trigger %:">Trigger %:</label> |
| @@ -5986,6 +6044,7 @@ | |||
| 5986 | </div> | 6044 | </div> |
| 5987 | </div> | 6045 | </div> |
| 5988 | </div> | 6046 | </div> |
| 6047 | <i class="menu_button move_entry_button fa-solid fa-right-left" title="Move Entry to Another Lorebook" data-i18n="[title]Move Entry to Another Lorebook"></i> | ||
| 5989 | <i class="menu_button duplicate_entry_button fa-solid fa-paste" title="Duplicate world info entry" data-i18n="[title]Duplicate world info entry" type="submit" value=""></i> | 6048 | <i class="menu_button duplicate_entry_button fa-solid fa-paste" title="Duplicate world info entry" data-i18n="[title]Duplicate world info entry" type="submit" value=""></i> |
| 5990 | <i class="menu_button delete_entry_button fa-solid fa-trash-can" title="Delete world info entry" data-i18n="[title]Delete world info entry" type="submit" value=""></i> | 6049 | <i class="menu_button delete_entry_button fa-solid fa-trash-can" title="Delete world info entry" data-i18n="[title]Delete world info entry" type="submit" value=""></i> |
| 5991 | </div> | 6050 | </div> |
| @@ -6074,8 +6133,11 @@ | |||
| 6074 | <label for="content "> | 6133 | <label for="content "> |
| 6075 | <small> | 6134 | <small> |
| 6076 | <span class="alignitemscenter flex-container flexnowrap wide100p justifySpaceBetween"> | 6135 | <span class="alignitemscenter flex-container flexnowrap wide100p justifySpaceBetween"> |
| 6077 | <span data-i18n="Content" class="alignitemscenter flex-container flexNoGap mdhotkey_location"> | 6136 | <span class="alignitemscenter flex-container"> |
| 6078 | Content | 6137 | <span data-i18n="Content" class="mdhotkey_location"> |
| 6138 | Content | ||
| 6139 | </span> | ||
| 6140 | <i class="editor_maximize fa-solid fa-maximize right_menu_button" title="Expand the editor" data-i18n="[title]Expand the editor"></i> | ||
| 6079 | </span> | 6141 | </span> |
| 6080 | <span> | 6142 | <span> |
| 6081 | (<span data-i18n="extension_token_counter">Tokens:</span> <span class="world_entry_form_token_counter" data-first-run="true">counting...</span>) | 6143 | (<span data-i18n="extension_token_counter">Tokens:</span> <span class="world_entry_form_token_counter" data-first-run="true">counting...</span>) |
| @@ -6335,7 +6397,7 @@ | |||
| 6335 | <span data-i18n="prompt_manager_depth">Depth</span> | 6397 | <span data-i18n="prompt_manager_depth">Depth</span> |
| 6336 | </label> | 6398 | </label> |
| 6337 | <div class="text_muted" data-i18n="Injection depth. 0 = after the last message, 1 = before the last message, etc.">Injection depth. 0 = after the last message, 1 = before the last message, etc.</div> | 6399 | <div class="text_muted" data-i18n="Injection depth. 0 = after the last message, 1 = before the last message, etc.">Injection depth. 0 = after the last message, 1 = before the last message, etc.</div> |
| 6338 | <input id="completion_prompt_manager_popup_entry_form_injection_depth" class="text_pole" type="number" name="injection_depth" min="0" max="999" value="4" /> | 6400 | <input id="completion_prompt_manager_popup_entry_form_injection_depth" class="text_pole" type="number" name="injection_depth" min="0" max="9999" value="4" /> |
| 6339 | </div> | 6401 | </div> |
| 6340 | </div> | 6402 | </div> |
| 6341 | <div class="completion_prompt_manager_popup_entry_form_control"> | 6403 | <div class="completion_prompt_manager_popup_entry_form_control"> |
| @@ -6434,7 +6496,7 @@ | |||
| 6434 | <div class="mes_text"></div> | 6496 | <div class="mes_text"></div> |
| 6435 | <div class="mes_img_container"> | 6497 | <div class="mes_img_container"> |
| 6436 | <div class="mes_img_controls"> | 6498 | <div class="mes_img_controls"> |
| 6437 | <div title="Enlarge" class="right_menu_button fa-lg fa-solid fa-magnifying-glass mes_img_enlarge" data-i18n="[title]Enlarge"></div> | 6499 | <div title="Expand and zoom" class="right_menu_button fa-lg fa-solid fa-magnifying-glass mes_img_enlarge" data-i18n="[title]Expand and zoom"></div> |
| 6438 | <div title="Caption" class="right_menu_button fa-lg fa-solid fa-envelope-open-text mes_img_caption" data-i18n="[title]Caption"></div> | 6500 | <div title="Caption" class="right_menu_button fa-lg fa-solid fa-envelope-open-text mes_img_caption" data-i18n="[title]Caption"></div> |
| 6439 | <div title="Delete" class="right_menu_button fa-lg fa-solid fa-trash-can mes_img_delete" data-i18n="[title]Delete"></div> | 6501 | <div title="Delete" class="right_menu_button fa-lg fa-solid fa-trash-can mes_img_delete" data-i18n="[title]Delete"></div> |
| 6440 | </div> | 6502 | </div> |
| @@ -6563,7 +6625,7 @@ | |||
| 6563 | <div class="ch_name"></div> | 6625 | <div class="ch_name"></div> |
| 6564 | <small class="ch_additional_info group_select_counter"></small> | 6626 | <small class="ch_additional_info group_select_counter"></small> |
| 6565 | </div> | 6627 | </div> |
| 6566 | <small class="character_name_block_sub_line">in this group</small> | 6628 | <small class="character_name_block_sub_line" data-i18n="in this group">in this group</small> |
| 6567 | <i class='group_fav_icon fa-solid fa-star'></i> | 6629 | <i class='group_fav_icon fa-solid fa-star'></i> |
| 6568 | <input class="ch_fav" value="" hidden /> | 6630 | <input class="ch_fav" value="" hidden /> |
| 6569 | <div class="group_select_block_list ch_description"></div> | 6631 | <div class="group_select_block_list ch_description"></div> |
| @@ -6695,7 +6757,7 @@ | |||
| 6695 | <label class="checkbox_label alignItemsCenter" for="extension_floating_position_depth"> | 6757 | <label class="checkbox_label alignItemsCenter" for="extension_floating_position_depth"> |
| 6696 | <input type="radio" id="extension_floating_position_depth" name="extension_floating_position" value="1" /> | 6758 | <input type="radio" id="extension_floating_position_depth" name="extension_floating_position" value="1" /> |
| 6697 | <span data-i18n="In-chat @ Depth">In-chat @ Depth</span> | 6759 | <span data-i18n="In-chat @ Depth">In-chat @ Depth</span> |
| 6698 | <input id="extension_floating_depth" class="text_pole textarea_compact widthNatural" type="number" min="0" max="999" /> | 6760 | <input id="extension_floating_depth" class="text_pole textarea_compact widthNatural" type="number" min="0" max="9999" /> |
| 6699 | <span data-i18n="as">as</span> | 6761 | <span data-i18n="as">as</span> |
| 6700 | <select id="extension_floating_role" class="text_pole widthNatural"> | 6762 | <select id="extension_floating_role" class="text_pole widthNatural"> |
| 6701 | <option data-i18n="System" value="0">System</option> | 6763 | <option data-i18n="System" value="0">System</option> |
| @@ -6710,7 +6772,7 @@ | |||
| 6710 | <span data-i18n="Insertion Frequency">Insertion Frequency</span> | 6772 | <span data-i18n="Insertion Frequency">Insertion Frequency</span> |
| 6711 | <small data-i18n="(0 = Disable, 1 = Always)">(0 = Disable, 1 = Always)</small> | 6773 | <small data-i18n="(0 = Disable, 1 = Always)">(0 = Disable, 1 = Always)</small> |
| 6712 | </label> | 6774 | </label> |
| 6713 | <input id="extension_floating_interval" class="text_pole widthUnset" type="number" min="0" max="999" /> | 6775 | <input id="extension_floating_interval" class="text_pole widthUnset" type="number" min="0" max="9999" /> |
| 6714 | </div> | 6776 | </div> |
| 6715 | <br> | 6777 | <br> |
| 6716 | <span><span data-i18n="User inputs until next insertion:">User inputs until next insertion:</span> <span id="extension_floating_counter">(disabled)</span></span> | 6778 | <span><span data-i18n="User inputs until next insertion:">User inputs until next insertion:</span> <span id="extension_floating_counter">(disabled)</span></span> |
| @@ -6780,7 +6842,7 @@ | |||
| 6780 | <label class="checkbox_label alignItemsCenter" for="extension_default_position_depth"> | 6842 | <label class="checkbox_label alignItemsCenter" for="extension_default_position_depth"> |
| 6781 | <input type="radio" id="extension_default_position_depth" name="extension_default_position" value="1" /> | 6843 | <input type="radio" id="extension_default_position_depth" name="extension_default_position" value="1" /> |
| 6782 | <span data-i18n="In-chat @ Depth">In-chat @ Depth</span> | 6844 | <span data-i18n="In-chat @ Depth">In-chat @ Depth</span> |
| 6783 | <input id="extension_default_depth" class="text_pole textarea_compact widthNatural" type="number" min="0" max="999" /> | 6845 | <input id="extension_default_depth" class="text_pole textarea_compact widthNatural" type="number" min="0" max="9999" /> |
| 6784 | <span data-i18n="as">as</span> | 6846 | <span data-i18n="as">as</span> |
| 6785 | <select id="extension_default_role" class="text_pole widthNatural"> | 6847 | <select id="extension_default_role" class="text_pole widthNatural"> |
| 6786 | <option data-i18n="System" value="0">System</option> | 6848 | <option data-i18n="System" value="0">System</option> |
| @@ -6794,7 +6856,7 @@ | |||
| 6794 | <span data-i18n="Insertion Frequency">Insertion Frequency</span> | 6856 | <span data-i18n="Insertion Frequency">Insertion Frequency</span> |
| 6795 | <small data-i18n="(0 = Disable, 1 = Always)">(0 = Disable, 1 = Always)</small> | 6857 | <small data-i18n="(0 = Disable, 1 = Always)">(0 = Disable, 1 = Always)</small> |
| 6796 | </label> | 6858 | </label> |
| 6797 | <input id="extension_default_interval" class="text_pole widthUnset" type="number" min="0" max="999" /> | 6859 | <input id="extension_default_interval" class="text_pole widthUnset" type="number" min="0" max="9999" /> |
| 6798 | </div> | 6860 | </div> |
| 6799 | </div> | 6861 | </div> |
| 6800 | </div> | 6862 | </div> |
| @@ -318,23 +318,23 @@ | |||
| 318 | "flag": "وضع علامة", | 318 | "flag": "وضع علامة", |
| 319 | "API key (optional)": "مفتاح API (اختياري)", | 319 | "API key (optional)": "مفتاح API (اختياري)", |
| 320 | "Server url": "رابط الخادم", | 320 | "Server url": "رابط الخادم", |
| 321 | "Example: 127.0.0.1:5000": "مثال: 127.0.0.1:5000", | 321 | "Example: http://127.0.0.1:5000": "مثال: http://127.0.0.1:5000", |
| 322 | "Custom model (optional)": "نموذج مخصص (اختياري)", | 322 | "Custom model (optional)": "نموذج مخصص (اختياري)", |
| 323 | "vllm-project/vllm": "vllm-project/vllm (وضع غلاف OpenAI API)", | 323 | "vllm-project/vllm": "vllm-project/vllm (وضع غلاف OpenAI API)", |
| 324 | "vLLM API key": "مفتاح واجهة برمجة التطبيقات vLLM", | 324 | "vLLM API key": "مفتاح واجهة برمجة التطبيقات vLLM", |
| 325 | "Example: 127.0.0.1:8000": "مثال: http://127.0.0.1:8000", | 325 | "Example: http://127.0.0.1:8000": "مثال: http://127.0.0.1:8000", |
| 326 | "vLLM Model": "نموذج vLLM", | 326 | "vLLM Model": "نموذج vLLM", |
| 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (وضع التغليف لواجهة برمجة التطبيقات OpenAI)", | 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (وضع التغليف لواجهة برمجة التطبيقات OpenAI)", |
| 328 | "Aphrodite API key": "مفتاح واجهة برمجة التطبيقات Aphrodite", | 328 | "Aphrodite API key": "مفتاح واجهة برمجة التطبيقات Aphrodite", |
| 329 | "Aphrodite Model": "نموذج أفروديت", | 329 | "Aphrodite Model": "نموذج أفروديت", |
| 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (خادم إخراج)", | 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (خادم إخراج)", |
| 331 | "Example: 127.0.0.1:8080": "مثال: 127.0.0.1:8080", | 331 | "Example: http://127.0.0.1:8080": "مثال: http://127.0.0.1:8080", |
| 332 | "Example: 127.0.0.1:11434": "مثال: 127.0.0.1:11434", | 332 | "Example: http://127.0.0.1:11434": "مثال: http://127.0.0.1:11434", |
| 333 | "Ollama Model": "نموذج Ollama", | 333 | "Ollama Model": "نموذج Ollama", |
| 334 | "Download": "تحميل", | 334 | "Download": "تحميل", |
| 335 | "Tabby API key": "مفتاح API لـ Tabby", | 335 | "Tabby API key": "مفتاح API لـ Tabby", |
| 336 | "koboldcpp API key (optional)": "مفتاح koboldcpp API (اختياري)", | 336 | "koboldcpp API key (optional)": "مفتاح koboldcpp API (اختياري)", |
| 337 | "Example: 127.0.0.1:5001": "مثال: 127.0.0.1:5001", | 337 | "Example: http://127.0.0.1:5001": "مثال: http://127.0.0.1:5001", |
| 338 | "Authorize": "تفويض", | 338 | "Authorize": "تفويض", |
| 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "احصل على رمز واجهة برمجة التطبيقات الخاص بك لموزع الاتصالات باستخدام تدفق OAuth. سيتم توجيهك إلى openrouter.ai", | 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "احصل على رمز واجهة برمجة التطبيقات الخاص بك لموزع الاتصالات باستخدام تدفق OAuth. سيتم توجيهك إلى openrouter.ai", |
| 340 | "Bypass status check": "تجاوز فحص الحالة", | 340 | "Bypass status check": "تجاوز فحص الحالة", |
| @@ -318,23 +318,23 @@ | |||
| 318 | "flag": "Flagge", | 318 | "flag": "Flagge", |
| 319 | "API key (optional)": "API-Schlüssel (optional)", | 319 | "API key (optional)": "API-Schlüssel (optional)", |
| 320 | "Server url": "Server-URL", | 320 | "Server url": "Server-URL", |
| 321 | "Example: 127.0.0.1:5000": "Beispiel: 127.0.0.1:5000", | 321 | "Example: http://127.0.0.1:5000": "Beispiel: http://127.0.0.1:5000", |
| 322 | "Custom model (optional)": "Benutzerdefiniertes Modell (optional)", | 322 | "Custom model (optional)": "Benutzerdefiniertes Modell (optional)", |
| 323 | "vllm-project/vllm": "vllm-project/vllm (OpenAI API-Wrappermodus)", | 323 | "vllm-project/vllm": "vllm-project/vllm (OpenAI API-Wrappermodus)", |
| 324 | "vLLM API key": "vLLM-API-Schlüssel", | 324 | "vLLM API key": "vLLM-API-Schlüssel", |
| 325 | "Example: 127.0.0.1:8000": "Beispiel: http://127.0.0.1:8000", | 325 | "Example: http://127.0.0.1:8000": "Beispiel: http://127.0.0.1:8000", |
| 326 | "vLLM Model": "vLLM-Modell", | 326 | "vLLM Model": "vLLM-Modell", |
| 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (Wrappermodus für OpenAI API)", | 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (Wrappermodus für OpenAI API)", |
| 328 | "Aphrodite API key": "Aphrodite API-Schlüssel", | 328 | "Aphrodite API key": "Aphrodite API-Schlüssel", |
| 329 | "Aphrodite Model": "Aphrodite-Modell", | 329 | "Aphrodite Model": "Aphrodite-Modell", |
| 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (Output-Server)", | 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (Output-Server)", |
| 331 | "Example: 127.0.0.1:8080": "Beispiel: 127.0.0.1:8080", | 331 | "Example: http://127.0.0.1:8080": "Beispiel: http://127.0.0.1:8080", |
| 332 | "Example: 127.0.0.1:11434": "Beispiel: 127.0.0.1:11434", | 332 | "Example: http://127.0.0.1:11434": "Beispiel: http://127.0.0.1:11434", |
| 333 | "Ollama Model": "Ollama-Modell", | 333 | "Ollama Model": "Ollama-Modell", |
| 334 | "Download": "Herunterladen", | 334 | "Download": "Herunterladen", |
| 335 | "Tabby API key": "Tabby API-Schlüssel", | 335 | "Tabby API key": "Tabby API-Schlüssel", |
| 336 | "koboldcpp API key (optional)": "koboldcpp API-Schlüssel (optional)", | 336 | "koboldcpp API key (optional)": "koboldcpp API-Schlüssel (optional)", |
| 337 | "Example: 127.0.0.1:5001": "Beispiel: 127.0.0.1:5001", | 337 | "Example: http://127.0.0.1:5001": "Beispiel: http://127.0.0.1:5001", |
| 338 | "Authorize": "Autorisieren", | 338 | "Authorize": "Autorisieren", |
| 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Hole dein OpenRouter-API-Token mit OAuth-Fluss. Du wirst zu openrouter.ai weitergeleitet", | 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Hole dein OpenRouter-API-Token mit OAuth-Fluss. Du wirst zu openrouter.ai weitergeleitet", |
| 340 | "Bypass status check": "Umgehe Statusüberprüfung", | 340 | "Bypass status check": "Umgehe Statusüberprüfung", |
| @@ -318,23 +318,23 @@ | |||
| 318 | "flag": "bandera", | 318 | "flag": "bandera", |
| 319 | "API key (optional)": "Clave API (opcional)", | 319 | "API key (optional)": "Clave API (opcional)", |
| 320 | "Server url": "URL del servidor", | 320 | "Server url": "URL del servidor", |
| 321 | "Example: 127.0.0.1:5000": "Ejemplo: 127.0.0.1:5000", | 321 | "Example: http://127.0.0.1:5000": "Ejemplo: http://127.0.0.1:5000", |
| 322 | "Custom model (optional)": "Modelo personalizado (opcional)", | 322 | "Custom model (optional)": "Modelo personalizado (opcional)", |
| 323 | "vllm-project/vllm": "vllm-project/vllm (modo contenedor de API OpenAI)", | 323 | "vllm-project/vllm": "vllm-project/vllm (modo contenedor de API OpenAI)", |
| 324 | "vLLM API key": "Clave API vLLM", | 324 | "vLLM API key": "Clave API vLLM", |
| 325 | "Example: 127.0.0.1:8000": "Ejemplo: http://127.0.0.1:8000", | 325 | "Example: http://127.0.0.1:8000": "Ejemplo: http://127.0.0.1:8000", |
| 326 | "vLLM Model": "Modelo vLLM", | 326 | "vLLM Model": "Modelo vLLM", |
| 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (Modo envolvente para API de OpenAI)", | 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (Modo envolvente para API de OpenAI)", |
| 328 | "Aphrodite API key": "Clave de API de Aphrodite", | 328 | "Aphrodite API key": "Clave de API de Aphrodite", |
| 329 | "Aphrodite Model": "Modelo Afrodita", | 329 | "Aphrodite Model": "Modelo Afrodita", |
| 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (Servidor de salida)", | 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (Servidor de salida)", |
| 331 | "Example: 127.0.0.1:8080": "Ejemplo: 127.0.0.1:8080", | 331 | "Example: http://127.0.0.1:8080": "Ejemplo: http://127.0.0.1:8080", |
| 332 | "Example: 127.0.0.1:11434": "Ejemplo: 127.0.0.1:11434", | 332 | "Example: http://127.0.0.1:11434": "Ejemplo: http://127.0.0.1:11434", |
| 333 | "Ollama Model": "Modelo Ollama", | 333 | "Ollama Model": "Modelo Ollama", |
| 334 | "Download": "Descargar", | 334 | "Download": "Descargar", |
| 335 | "Tabby API key": "Clave API de Tabby", | 335 | "Tabby API key": "Clave API de Tabby", |
| 336 | "koboldcpp API key (optional)": "Clave API de koboldcpp (opcional)", | 336 | "koboldcpp API key (optional)": "Clave API de koboldcpp (opcional)", |
| 337 | "Example: 127.0.0.1:5001": "Ejemplo: 127.0.0.1:5001", | 337 | "Example: http://127.0.0.1:5001": "Ejemplo: http://127.0.0.1:5001", |
| 338 | "Authorize": "Autorizar", | 338 | "Authorize": "Autorizar", |
| 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Obtenga su token de API de OpenRouter utilizando el flujo OAuth. Será redirigido a openrouter.ai", | 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Obtenga su token de API de OpenRouter utilizando el flujo OAuth. Será redirigido a openrouter.ai", |
| 340 | "Bypass status check": "Saltar la verificación del estado", | 340 | "Bypass status check": "Saltar la verificación del estado", |
| @@ -301,23 +301,23 @@ | |||
| 301 | "flag": "fanion", | 301 | "flag": "fanion", |
| 302 | "API key (optional)": "Clé API (optionnelle)", | 302 | "API key (optional)": "Clé API (optionnelle)", |
| 303 | "Server url": "URL du serveur", | 303 | "Server url": "URL du serveur", |
| 304 | "Example: 127.0.0.1:5000": "Exemple : 127.0.0.1:5000", | 304 | "Example: http://127.0.0.1:5000": "Exemple : http://127.0.0.1:5000", |
| 305 | "Custom model (optional)": "Modèle personnalisé (optionnel)", | 305 | "Custom model (optional)": "Modèle personnalisé (optionnel)", |
| 306 | "vllm-project/vllm": "vllm-project/vllm (mode wrapper de l'API OpenAI)", | 306 | "vllm-project/vllm": "vllm-project/vllm (mode wrapper de l'API OpenAI)", |
| 307 | "vLLM API key": "Clé API vLLM", | 307 | "vLLM API key": "Clé API vLLM", |
| 308 | "Example: 127.0.0.1:8000": "Exemple : http://127.0.0.1:8000", | 308 | "Example: http://127.0.0.1:8000": "Exemple : http://127.0.0.1:8000", |
| 309 | "vLLM Model": "Modèle vLLM", | 309 | "vLLM Model": "Modèle vLLM", |
| 310 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (mode wrapper pour l'API OpenAI)", | 310 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (mode wrapper pour l'API OpenAI)", |
| 311 | "Aphrodite API key": "Clé API Aphrodite", | 311 | "Aphrodite API key": "Clé API Aphrodite", |
| 312 | "Aphrodite Model": "Modèle Aphrodite", | 312 | "Aphrodite Model": "Modèle Aphrodite", |
| 313 | "ggerganov/llama.cpp": "ggerganov/llama.cpp", | 313 | "ggerganov/llama.cpp": "ggerganov/llama.cpp", |
| 314 | "Example: 127.0.0.1:8080": "Exemple : 127.0.0.1:8080", | 314 | "Example: http://127.0.0.1:8080": "Exemple : http://127.0.0.1:8080", |
| 315 | "Example: 127.0.0.1:11434": "Exemple : 127.0.0.1:11434", | 315 | "Example: http://127.0.0.1:11434": "Exemple : http://127.0.0.1:11434", |
| 316 | "Ollama Model": "Modèle Ollama", | 316 | "Ollama Model": "Modèle Ollama", |
| 317 | "Download": "Télécharger", | 317 | "Download": "Télécharger", |
| 318 | "Tabby API key": "Clé API de Tabby", | 318 | "Tabby API key": "Clé API de Tabby", |
| 319 | "koboldcpp API key (optional)": "Clé API koboldcpp (facultatif)", | 319 | "koboldcpp API key (optional)": "Clé API koboldcpp (facultatif)", |
| 320 | "Example: 127.0.0.1:5001": "Exemple : 127.0.0.1:5001", | 320 | "Example: http://127.0.0.1:5001": "Exemple : http://127.0.0.1:5001", |
| 321 | "Authorize": "Autoriser", | 321 | "Authorize": "Autoriser", |
| 322 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Obtenez votre jeton API OpenRouter en utilisant le flux OAuth. Vous serez redirigé vers openrouter.ai", | 322 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Obtenez votre jeton API OpenRouter en utilisant le flux OAuth. Vous serez redirigé vers openrouter.ai", |
| 323 | "Bypass status check": "Contourner la vérification de l'état", | 323 | "Bypass status check": "Contourner la vérification de l'état", |
| @@ -318,23 +318,23 @@ | |||
| 318 | "flag": "merki", | 318 | "flag": "merki", |
| 319 | "API key (optional)": "API lykill (valkvæmt)", | 319 | "API key (optional)": "API lykill (valkvæmt)", |
| 320 | "Server url": "URL þjóns", | 320 | "Server url": "URL þjóns", |
| 321 | "Example: 127.0.0.1:5000": "Dæmi: 127.0.0.1:5000", | 321 | "Example: http://127.0.0.1:5000": "Dæmi: http://127.0.0.1:5000", |
| 322 | "Custom model (optional)": "Sérsniðið módel (valkvæmt)", | 322 | "Custom model (optional)": "Sérsniðið módel (valkvæmt)", |
| 323 | "vllm-project/vllm": "vllm-project/vllm (OpenAI API umbúðastilling)", | 323 | "vllm-project/vllm": "vllm-project/vllm (OpenAI API umbúðastilling)", |
| 324 | "vLLM API key": "vLLM API lykill", | 324 | "vLLM API key": "vLLM API lykill", |
| 325 | "Example: 127.0.0.1:8000": "Dæmi: http://127.0.0.1:8000", | 325 | "Example: http://127.0.0.1:8000": "Dæmi: http://127.0.0.1:8000", |
| 326 | "vLLM Model": "vLLM líkan", | 326 | "vLLM Model": "vLLM líkan", |
| 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (OpenAI forritunargrensl)", | 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (OpenAI forritunargrensl)", |
| 328 | "Aphrodite API key": "Aphrodite API lykill", | 328 | "Aphrodite API key": "Aphrodite API lykill", |
| 329 | "Aphrodite Model": "Afródíta fyrirmynd", | 329 | "Aphrodite Model": "Afródíta fyrirmynd", |
| 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (úttak þjónn)", | 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (úttak þjónn)", |
| 331 | "Example: 127.0.0.1:8080": "Dæmi: 127.0.0.1:8080", | 331 | "Example: http://127.0.0.1:8080": "Dæmi: http://127.0.0.1:8080", |
| 332 | "Example: 127.0.0.1:11434": "Dæmi: 127.0.0.1:11434", | 332 | "Example: http://127.0.0.1:11434": "Dæmi: http://127.0.0.1:11434", |
| 333 | "Ollama Model": "Ollama módel", | 333 | "Ollama Model": "Ollama módel", |
| 334 | "Download": "Niðurhal", | 334 | "Download": "Niðurhal", |
| 335 | "Tabby API key": "Tabby API lykill", | 335 | "Tabby API key": "Tabby API lykill", |
| 336 | "koboldcpp API key (optional)": "koboldcpp API lykill (valfrjálst)", | 336 | "koboldcpp API key (optional)": "koboldcpp API lykill (valfrjálst)", |
| 337 | "Example: 127.0.0.1:5001": "Dæmi: 127.0.0.1:5001", | 337 | "Example: http://127.0.0.1:5001": "Dæmi: http://127.0.0.1:5001", |
| 338 | "Authorize": "Heimild", | 338 | "Authorize": "Heimild", |
| 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Fáðu API lykilinn þinn fyrir OpenRouter með því að nota OAuth strauminn. Þú verður endurvísað(ð/ur) á openrouter.ai", | 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Fáðu API lykilinn þinn fyrir OpenRouter með því að nota OAuth strauminn. Þú verður endurvísað(ð/ur) á openrouter.ai", |
| 340 | "Bypass status check": "Hlaupa framhjá stöðutík", | 340 | "Bypass status check": "Hlaupa framhjá stöðutík", |
| @@ -318,23 +318,23 @@ | |||
| 318 | "flag": "bandiera", | 318 | "flag": "bandiera", |
| 319 | "API key (optional)": "Chiave API (opzionale)", | 319 | "API key (optional)": "Chiave API (opzionale)", |
| 320 | "Server url": "URL del server", | 320 | "Server url": "URL del server", |
| 321 | "Example: 127.0.0.1:5000": "Esempio: 127.0.0.1:5000", | 321 | "Example: http://127.0.0.1:5000": "Esempio: http://127.0.0.1:5000", |
| 322 | "Custom model (optional)": "Modello personalizzato (opzionale)", | 322 | "Custom model (optional)": "Modello personalizzato (opzionale)", |
| 323 | "vllm-project/vllm": "vllm-project/vllm (modalità wrapper API OpenAI)", | 323 | "vllm-project/vllm": "vllm-project/vllm (modalità wrapper API OpenAI)", |
| 324 | "vLLM API key": "Chiave API vLLM", | 324 | "vLLM API key": "Chiave API vLLM", |
| 325 | "Example: 127.0.0.1:8000": "Esempio: http://127.0.0.1:8000", | 325 | "Example: http://127.0.0.1:8000": "Esempio: http://127.0.0.1:8000", |
| 326 | "vLLM Model": "Modello vLLM", | 326 | "vLLM Model": "Modello vLLM", |
| 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (Modalità wrapper per l'API OpenAI)", | 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (Modalità wrapper per l'API OpenAI)", |
| 328 | "Aphrodite API key": "Chiave API di Aphrodite", | 328 | "Aphrodite API key": "Chiave API di Aphrodite", |
| 329 | "Aphrodite Model": "Modello di Afrodite", | 329 | "Aphrodite Model": "Modello di Afrodite", |
| 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (Server di output)", | 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (Server di output)", |
| 331 | "Example: 127.0.0.1:8080": "Esempio: 127.0.0.1:8080", | 331 | "Example: http://127.0.0.1:8080": "Esempio: http://127.0.0.1:8080", |
| 332 | "Example: 127.0.0.1:11434": "Esempio: 127.0.0.1:11434", | 332 | "Example: http://127.0.0.1:11434": "Esempio: http://127.0.0.1:11434", |
| 333 | "Ollama Model": "Modello Ollama", | 333 | "Ollama Model": "Modello Ollama", |
| 334 | "Download": "Scarica", | 334 | "Download": "Scarica", |
| 335 | "Tabby API key": "Chiave API di Tabby", | 335 | "Tabby API key": "Chiave API di Tabby", |
| 336 | "koboldcpp API key (optional)": "Chiave API koboldcpp (opzionale)", | 336 | "koboldcpp API key (optional)": "Chiave API koboldcpp (opzionale)", |
| 337 | "Example: 127.0.0.1:5001": "Esempio: 127.0.0.1:5001", | 337 | "Example: http://127.0.0.1:5001": "Esempio: http://127.0.0.1:5001", |
| 338 | "Authorize": "Autorizzare", | 338 | "Authorize": "Autorizzare", |
| 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Ottieni il tuo token API di OpenRouter utilizzando il flusso OAuth. Sarai reindirizzato su openrouter.ai", | 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Ottieni il tuo token API di OpenRouter utilizzando il flusso OAuth. Sarai reindirizzato su openrouter.ai", |
| 340 | "Bypass status check": "Ignora controllo stato", | 340 | "Bypass status check": "Ignora controllo stato", |
| @@ -318,23 +318,23 @@ | |||
| 318 | "flag": "フラグ", | 318 | "flag": "フラグ", |
| 319 | "API key (optional)": "APIキー(オプション)", | 319 | "API key (optional)": "APIキー(オプション)", |
| 320 | "Server url": "サーバーURL", | 320 | "Server url": "サーバーURL", |
| 321 | "Example: 127.0.0.1:5000": "例: 127.0.0.1:5000", | 321 | "Example: http://127.0.0.1:5000": "例: http://127.0.0.1:5000", |
| 322 | "Custom model (optional)": "カスタムモデル(オプション)", | 322 | "Custom model (optional)": "カスタムモデル(オプション)", |
| 323 | "vllm-project/vllm": "vllm-project/vllm (OpenAI API ラッパーモード)", | 323 | "vllm-project/vllm": "vllm-project/vllm (OpenAI API ラッパーモード)", |
| 324 | "vLLM API key": "vLLM API キー", | 324 | "vLLM API key": "vLLM API キー", |
| 325 | "Example: 127.0.0.1:8000": "例: http://127.0.0.1:8000", | 325 | "Example: http://127.0.0.1:8000": "例: http://127.0.0.1:8000", |
| 326 | "vLLM Model": "vLLM モデル", | 326 | "vLLM Model": "vLLM モデル", |
| 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine(OpenAI APIエンドポイントのパッケージングモード)", | 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine(OpenAI APIエンドポイントのパッケージングモード)", |
| 328 | "Aphrodite API key": "アフロディーテAPIキー", | 328 | "Aphrodite API key": "アフロディーテAPIキー", |
| 329 | "Aphrodite Model": "アフロディーテモデル", | 329 | "Aphrodite Model": "アフロディーテモデル", |
| 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp(出力サーバー)", | 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp(出力サーバー)", |
| 331 | "Example: 127.0.0.1:8080": "例: 127.0.0.1:8080", | 331 | "Example: http://127.0.0.1:8080": "例: http://127.0.0.1:8080", |
| 332 | "Example: 127.0.0.1:11434": "例: 127.0.0.1:11434", | 332 | "Example: http://127.0.0.1:11434": "例: http://127.0.0.1:11434", |
| 333 | "Ollama Model": "Ollamaモデル", | 333 | "Ollama Model": "Ollamaモデル", |
| 334 | "Download": "ダウンロード", | 334 | "Download": "ダウンロード", |
| 335 | "Tabby API key": "TabbyのAPIキー", | 335 | "Tabby API key": "TabbyのAPIキー", |
| 336 | "koboldcpp API key (optional)": "koboldcpp API キー (オプション)", | 336 | "koboldcpp API key (optional)": "koboldcpp API キー (オプション)", |
| 337 | "Example: 127.0.0.1:5001": "例: 127.0.0.1:5001", | 337 | "Example: http://127.0.0.1:5001": "例: http://127.0.0.1:5001", |
| 338 | "Authorize": "承認", | 338 | "Authorize": "承認", |
| 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "OAuthフローを使用してOpenRouter APIトークンを取得します。 openrouter.aiにリダイレクトされます", | 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "OAuthフローを使用してOpenRouter APIトークンを取得します。 openrouter.aiにリダイレクトされます", |
| 340 | "Bypass status check": "ステータスのチェックをバイパスする", | 340 | "Bypass status check": "ステータスのチェックをバイパスする", |
| @@ -320,23 +320,23 @@ | |||
| 320 | "flag": "깃발", | 320 | "flag": "깃발", |
| 321 | "API key (optional)": "API 키 (선택 사항)", | 321 | "API key (optional)": "API 키 (선택 사항)", |
| 322 | "Server url": "서버 URL", | 322 | "Server url": "서버 URL", |
| 323 | "Example: 127.0.0.1:5000": "예시: 127.0.0.1:5000", | 323 | "Example: http://127.0.0.1:5000": "예시: http://127.0.0.1:5000", |
| 324 | "Custom model (optional)": "사용자 정의 모델 (선택 사항)", | 324 | "Custom model (optional)": "사용자 정의 모델 (선택 사항)", |
| 325 | "vllm-project/vllm": "vllm-project/vllm(OpenAI API 래퍼 모드)", | 325 | "vllm-project/vllm": "vllm-project/vllm(OpenAI API 래퍼 모드)", |
| 326 | "vLLM API key": "vLLM API 키", | 326 | "vLLM API key": "vLLM API 키", |
| 327 | "Example: 127.0.0.1:8000": "예: http://127.0.0.1:8000", | 327 | "Example: http://127.0.0.1:8000": "예: http://127.0.0.1:8000", |
| 328 | "vLLM Model": "vLLM 모델", | 328 | "vLLM Model": "vLLM 모델", |
| 329 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (OpenAI API의 래퍼 모드)", | 329 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (OpenAI API의 래퍼 모드)", |
| 330 | "Aphrodite API key": "Aphrodite API 키", | 330 | "Aphrodite API key": "Aphrodite API 키", |
| 331 | "Aphrodite Model": "Aphrodite 모델", | 331 | "Aphrodite Model": "Aphrodite 모델", |
| 332 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (출력 서버)", | 332 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (출력 서버)", |
| 333 | "Example: 127.0.0.1:8080": "예: 127.0.0.1:8080", | 333 | "Example: http://127.0.0.1:8080": "예: http://127.0.0.1:8080", |
| 334 | "Example: 127.0.0.1:11434": "예: 127.0.0.1:11434", | 334 | "Example: http://127.0.0.1:11434": "예: http://127.0.0.1:11434", |
| 335 | "Ollama Model": "Ollama 모델", | 335 | "Ollama Model": "Ollama 모델", |
| 336 | "Download": "다운로드", | 336 | "Download": "다운로드", |
| 337 | "Tabby API key": "Tabby API 키", | 337 | "Tabby API key": "Tabby API 키", |
| 338 | "koboldcpp API key (optional)": "koboldcpp API 키(선택사항)", | 338 | "koboldcpp API key (optional)": "koboldcpp API 키(선택사항)", |
| 339 | "Example: 127.0.0.1:5001": "예: 127.0.0.1:5001", | 339 | "Example: http://127.0.0.1:5001": "예: http://127.0.0.1:5001", |
| 340 | "Authorize": "승인하기", | 340 | "Authorize": "승인하기", |
| 341 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "OAuth 플로우를 사용하여 OpenRouter API 토큰을 가져옵니다. openrouter.ai로 리디렉션됩니다.", | 341 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "OAuth 플로우를 사용하여 OpenRouter API 토큰을 가져옵니다. openrouter.ai로 리디렉션됩니다.", |
| 342 | "Legacy API (pre-OAI, no streaming)": "레거시 API (OAI 이전, 스트리밍 없음)", | 342 | "Legacy API (pre-OAI, no streaming)": "레거시 API (OAI 이전, 스트리밍 없음)", |
| @@ -318,23 +318,23 @@ | |||
| 318 | "flag": "vlag", | 318 | "flag": "vlag", |
| 319 | "API key (optional)": "API-sleutel (optioneel)", | 319 | "API key (optional)": "API-sleutel (optioneel)", |
| 320 | "Server url": "Server-URL", | 320 | "Server url": "Server-URL", |
| 321 | "Example: 127.0.0.1:5000": "Voorbeeld: 127.0.0.1:5000", | 321 | "Example: http://127.0.0.1:5000": "Voorbeeld: http://127.0.0.1:5000", |
| 322 | "Custom model (optional)": "Aangepast model (optioneel)", | 322 | "Custom model (optional)": "Aangepast model (optioneel)", |
| 323 | "vllm-project/vllm": "vllm-project/vllm (OpenAI API-wrappermodus)", | 323 | "vllm-project/vllm": "vllm-project/vllm (OpenAI API-wrappermodus)", |
| 324 | "vLLM API key": "vLLM API-sleutel", | 324 | "vLLM API key": "vLLM API-sleutel", |
| 325 | "Example: 127.0.0.1:8000": "Voorbeeld: http://127.0.0.1:8000", | 325 | "Example: http://127.0.0.1:8000": "Voorbeeld: http://127.0.0.1:8000", |
| 326 | "vLLM Model": "vLLM-model", | 326 | "vLLM Model": "vLLM-model", |
| 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (Wrappermodus voor OpenAI API)", | 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (Wrappermodus voor OpenAI API)", |
| 328 | "Aphrodite API key": "Aphrodite API-sleutel", | 328 | "Aphrodite API key": "Aphrodite API-sleutel", |
| 329 | "Aphrodite Model": "Aphrodite-model", | 329 | "Aphrodite Model": "Aphrodite-model", |
| 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (Output-server)", | 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (Output-server)", |
| 331 | "Example: 127.0.0.1:8080": "Voorbeeld: 127.0.0.1:8080", | 331 | "Example: http://127.0.0.1:8080": "Voorbeeld: http://127.0.0.1:8080", |
| 332 | "Example: 127.0.0.1:11434": "Voorbeeld: 127.0.0.1:11434", | 332 | "Example: http://127.0.0.1:11434": "Voorbeeld: http://127.0.0.1:11434", |
| 333 | "Ollama Model": "Ollama-model", | 333 | "Ollama Model": "Ollama-model", |
| 334 | "Download": "Downloaden", | 334 | "Download": "Downloaden", |
| 335 | "Tabby API key": "Tabby API-sleutel", | 335 | "Tabby API key": "Tabby API-sleutel", |
| 336 | "koboldcpp API key (optional)": "koboldcpp API-sleutel (optioneel)", | 336 | "koboldcpp API key (optional)": "koboldcpp API-sleutel (optioneel)", |
| 337 | "Example: 127.0.0.1:5001": "Voorbeeld: 127.0.0.1:5001", | 337 | "Example: http://127.0.0.1:5001": "Voorbeeld: http://127.0.0.1:5001", |
| 338 | "Authorize": "Toestemming geven", | 338 | "Authorize": "Toestemming geven", |
| 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Haal uw OpenRouter API-token op met behulp van OAuth-flow. U wordt doorgestuurd naar openrouter.ai", | 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Haal uw OpenRouter API-token op met behulp van OAuth-flow. U wordt doorgestuurd naar openrouter.ai", |
| 340 | "Bypass status check": "Omzeil statuscontrole", | 340 | "Bypass status check": "Omzeil statuscontrole", |
| @@ -318,23 +318,23 @@ | |||
| 318 | "flag": "bandeira", | 318 | "flag": "bandeira", |
| 319 | "API key (optional)": "Chave da API (opcional)", | 319 | "API key (optional)": "Chave da API (opcional)", |
| 320 | "Server url": "URL do servidor", | 320 | "Server url": "URL do servidor", |
| 321 | "Example: 127.0.0.1:5000": "Exemplo: 127.0.0.1:5000", | 321 | "Example: http://127.0.0.1:5000": "Exemplo: http://127.0.0.1:5000", |
| 322 | "Custom model (optional)": "Modelo personalizado (opcional)", | 322 | "Custom model (optional)": "Modelo personalizado (opcional)", |
| 323 | "vllm-project/vllm": "vllm-project/vllm (modo wrapper da API OpenAI)", | 323 | "vllm-project/vllm": "vllm-project/vllm (modo wrapper da API OpenAI)", |
| 324 | "vLLM API key": "Chave de API vLLM", | 324 | "vLLM API key": "Chave de API vLLM", |
| 325 | "Example: 127.0.0.1:8000": "Exemplo: http://127.0.0.1:8000", | 325 | "Example: http://127.0.0.1:8000": "Exemplo: http://127.0.0.1:8000", |
| 326 | "vLLM Model": "Modelo vLLM", | 326 | "vLLM Model": "Modelo vLLM", |
| 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (Modo Wrapper para API OpenAI)", | 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (Modo Wrapper para API OpenAI)", |
| 328 | "Aphrodite API key": "Chave da API Aphrodite", | 328 | "Aphrodite API key": "Chave da API Aphrodite", |
| 329 | "Aphrodite Model": "Modelo Afrodite", | 329 | "Aphrodite Model": "Modelo Afrodite", |
| 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (Servidor de Saída)", | 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (Servidor de Saída)", |
| 331 | "Example: 127.0.0.1:8080": "Exemplo: 127.0.0.1:8080", | 331 | "Example: http://127.0.0.1:8080": "Exemplo: http://127.0.0.1:8080", |
| 332 | "Example: 127.0.0.1:11434": "Exemplo: 127.0.0.1:11434", | 332 | "Example: http://127.0.0.1:11434": "Exemplo: http://127.0.0.1:11434", |
| 333 | "Ollama Model": "Modelo Ollama", | 333 | "Ollama Model": "Modelo Ollama", |
| 334 | "Download": "Baixar", | 334 | "Download": "Baixar", |
| 335 | "Tabby API key": "Chave da API do Tabby", | 335 | "Tabby API key": "Chave da API do Tabby", |
| 336 | "koboldcpp API key (optional)": "Chave API koboldcpp (opcional)", | 336 | "koboldcpp API key (optional)": "Chave API koboldcpp (opcional)", |
| 337 | "Example: 127.0.0.1:5001": "Exemplo: 127.0.0.1:5001", | 337 | "Example: http://127.0.0.1:5001": "Exemplo: http://127.0.0.1:5001", |
| 338 | "Authorize": "Autorizar", | 338 | "Authorize": "Autorizar", |
| 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Obtenha seu token da API do OpenRouter usando o fluxo OAuth. Você será redirecionado para openrouter.ai", | 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Obtenha seu token da API do OpenRouter usando o fluxo OAuth. Você será redirecionado para openrouter.ai", |
| 340 | "Bypass status check": "Ignorar verificação de status", | 340 | "Bypass status check": "Ignorar verificação de status", |
| @@ -23,9 +23,8 @@ | |||
| 23 | "Mirostat Mode": "Режим", | 23 | "Mirostat Mode": "Режим", |
| 24 | "Mirostat Tau": "Tau", | 24 | "Mirostat Tau": "Tau", |
| 25 | "Mirostat Eta": "Eta", | 25 | "Mirostat Eta": "Eta", |
| 26 | "Variability parameter for Mirostat outputs": "Параметр изменчивости для выходных данных Mirostat.", | 26 | "Variability parameter for Mirostat outputs": "Вариативность для выходных данных Mirostat.", |
| 27 | "Learning rate of Mirostat": "Скорость обучения Mirostat.", | 27 | "Learning rate of Mirostat": "Скорость обучения Mirostat.", |
| 28 | "Strength of the Contrastive Search regularization term. Set to 0 to disable CS": "Сила условия регуляризации контрастивного поиска. Установите значение 0, чтобы отключить CS.", | ||
| 29 | "Temperature Last": "Температура последней", | 28 | "Temperature Last": "Температура последней", |
| 30 | "LLaMA / Mistral / Yi models only": "Только для моделей LLaMA / Mistral / Yi. Перед этим обязательно выберите подходящий токенизатор.\nПоследовательности, которых не должно быть на выходе.\nОдна на строку. Текст или [идентификаторы токенов].\nМногие токены имеют пробел впереди. Используйте счетчик токенов, если не уверены.", | 29 | "LLaMA / Mistral / Yi models only": "Только для моделей LLaMA / Mistral / Yi. Перед этим обязательно выберите подходящий токенизатор.\nПоследовательности, которых не должно быть на выходе.\nОдна на строку. Текст или [идентификаторы токенов].\nМногие токены имеют пробел впереди. Используйте счетчик токенов, если не уверены.", |
| 31 | "Example: some text [42, 69, 1337]": "Пример:\nкакой-то текст\n[42, 69, 1337]", | 30 | "Example: some text [42, 69, 1337]": "Пример:\nкакой-то текст\n[42, 69, 1337]", |
| @@ -60,13 +59,11 @@ | |||
| 60 | "Add BOS Token": "Добавлять BOS-токен", | 59 | "Add BOS Token": "Добавлять BOS-токен", |
| 61 | "Add the bos_token to the beginning of prompts. Disabling this can make the replies more creative": "Добавлять BOS-токен в начале промпта. Если выключить, ответы могут стать более креативными.", | 60 | "Add the bos_token to the beginning of prompts. Disabling this can make the replies more creative": "Добавлять BOS-токен в начале промпта. Если выключить, ответы могут стать более креативными.", |
| 62 | "Ban EOS Token": "Запретить EOS-токен", | 61 | "Ban EOS Token": "Запретить EOS-токен", |
| 63 | "Ban the eos_token. This forces the model to never end the generation prematurely": "Запрет EOS-токена не позволит модели завершить генерацию преждевременно", | 62 | "Ban the eos_token. This forces the model to never end the generation prematurely": "Запрет EOS-токена не позволит модели завершить генерацию самостоятельно (только при достижении лимита токенов)", |
| 64 | "Skip Special Tokens": "Пропускать спец. токены", | 63 | "Skip Special Tokens": "Пропускать спец. токены", |
| 65 | "Beam search": "Поиск Beam", | 64 | "Beam search": "Beam Search", |
| 66 | "Number of Beams": "Количество Beam", | ||
| 67 | "Length Penalty": "Штраф за длину", | 65 | "Length Penalty": "Штраф за длину", |
| 68 | "Early Stopping": "Преждевременная остановка", | 66 | "Early Stopping": "Прекращать сразу", |
| 69 | "Contrastive search": "Контрастный поиск", | ||
| 70 | "Penalty Alpha": "Penalty Alpha", | 67 | "Penalty Alpha": "Penalty Alpha", |
| 71 | "Seed": "Зерно", | 68 | "Seed": "Зерно", |
| 72 | "Epsilon Cutoff": "Epsilon Cutoff", | 69 | "Epsilon Cutoff": "Epsilon Cutoff", |
| @@ -89,7 +86,7 @@ | |||
| 89 | "Text Completion presets": "Пресеты для Text Completion", | 86 | "Text Completion presets": "Пресеты для Text Completion", |
| 90 | "Documentation on sampling parameters": "Документация по параметрам сэмплеров", | 87 | "Documentation on sampling parameters": "Документация по параметрам сэмплеров", |
| 91 | "Set all samplers to their neutral/disabled state.": "Установить все сэмплеры в нейтральное/отключенное состояние.", | 88 | "Set all samplers to their neutral/disabled state.": "Установить все сэмплеры в нейтральное/отключенное состояние.", |
| 92 | "Only enable this if your model supports context sizes greater than 8192 tokens": "Включайте эту опцию, только если ваша модель поддерживает размер контекста более 8192 токенов.\nУвеличивайте только если вы знаете, что делаете.", | 89 | "Only enable this if your model supports context sizes greater than 8192 tokens": "Включайте эту опцию, только если ваша модель поддерживает размер контекста более 8192 токенов.\nУвеличивайте только если вы понимаете, что делаете.", |
| 93 | "Wrap in Quotes": "Заключать в кавычки", | 90 | "Wrap in Quotes": "Заключать в кавычки", |
| 94 | "Wrap entire user message in quotes before sending.": "Перед отправкой заключать всё сообщение пользователя в кавычки.", | 91 | "Wrap entire user message in quotes before sending.": "Перед отправкой заключать всё сообщение пользователя в кавычки.", |
| 95 | "Leave off if you use quotes manually for speech.": "Оставьте выключенным, если вручную выставляете кавычки для прямой речи.", | 92 | "Leave off if you use quotes manually for speech.": "Оставьте выключенным, если вручную выставляете кавычки для прямой речи.", |
| @@ -109,13 +106,13 @@ | |||
| 109 | "Adjust response length to worker capabilities": "Подстраивать длину ответа под возможности рабочих машин", | 106 | "Adjust response length to worker capabilities": "Подстраивать длину ответа под возможности рабочих машин", |
| 110 | "API key": "API-ключ", | 107 | "API key": "API-ключ", |
| 111 | "Tabby API key": "Tabby API-ключ", | 108 | "Tabby API key": "Tabby API-ключ", |
| 112 | "Get it here:": "Получить здесь:", | 109 | "Get it here:": "Получите здесь:", |
| 113 | "Register": "Зарегистрироваться", | 110 | "Register": "Зарегистрироваться", |
| 114 | "TogetherAI Model": "Модель TogetherAI", | 111 | "TogetherAI Model": "Модель TogetherAI", |
| 115 | "Example: 127.0.0.1:5001": "Пример: http://127.0.0.1:5001", | 112 | "Example: http://127.0.0.1:5001": "Пример: http://127.0.0.1:5001", |
| 116 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (сервер вывода)", | 113 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (сервер вывода)", |
| 117 | "Example: 127.0.0.1:8080": "Пример: http://127.0.0.1:8080", | 114 | "Example: http://127.0.0.1:8080": "Пример: http://127.0.0.1:8080", |
| 118 | "Example: 127.0.0.1:11434": "Пример: http://127.0.0.1:11434", | 115 | "Example: http://127.0.0.1:11434": "Пример: http://127.0.0.1:11434", |
| 119 | "Ollama Model": "Модель Ollama", | 116 | "Ollama Model": "Модель Ollama", |
| 120 | "Download": "Скачать", | 117 | "Download": "Скачать", |
| 121 | "TogetherAI API Key": "TogetherAI API-ключ", | 118 | "TogetherAI API Key": "TogetherAI API-ключ", |
| @@ -136,7 +133,7 @@ | |||
| 136 | "Server url": "URL-адрес сервера", | 133 | "Server url": "URL-адрес сервера", |
| 137 | "Custom model (optional)": "Пользовательская модель (необязательно)", | 134 | "Custom model (optional)": "Пользовательская модель (необязательно)", |
| 138 | "Bypass API status check": "Обход проверки статуса API", | 135 | "Bypass API status check": "Обход проверки статуса API", |
| 139 | "Example: 127.0.0.1:5000": "Пример: http://127.0.0.1:5000", | 136 | "Example: http://127.0.0.1:5000": "Пример: http://127.0.0.1:5000", |
| 140 | "Bypass status check": "Обход проверки статуса", | 137 | "Bypass status check": "Обход проверки статуса", |
| 141 | "Mancer API key": "Ключ от Mancer API", | 138 | "Mancer API key": "Ключ от Mancer API", |
| 142 | "to get your OpenAI API key.": "для получения ключа от API OpenAI", | 139 | "to get your OpenAI API key.": "для получения ключа от API OpenAI", |
| @@ -289,10 +286,10 @@ | |||
| 289 | "Author's Note": "Заметки автора", | 286 | "Author's Note": "Заметки автора", |
| 290 | "Replace empty message": "Заменять пустые сообщения", | 287 | "Replace empty message": "Заменять пустые сообщения", |
| 291 | "Send this text instead of nothing when the text box is empty.": "Этот текст будет отправлен в случае отсутствия текста на отправку.", | 288 | "Send this text instead of nothing when the text box is empty.": "Этот текст будет отправлен в случае отсутствия текста на отправку.", |
| 292 | "Unrestricted maximum value for the context slider": "Убрать потолок для ползунка контекста. Включайте только если точно знаете, что делаете", | 289 | "Unrestricted maximum value for the context slider": "Убрать потолок для ползунка контекста. Включайте только если точно понимаете, что делаете", |
| 293 | "Chat Completion Source": "Источник для Chat Completion", | 290 | "Chat Completion Source": "Источник для Chat Completion", |
| 294 | "Avoid sending sensitive information to the Horde.": "Избегайте отправки личной информации Horde", | 291 | "Avoid sending sensitive information to the Horde.": "Избегайте отправки личной информации Horde.", |
| 295 | "Review the Privacy statement": "Ознакомиться с заявлением о конфиденциальности", | 292 | "Review the Privacy statement": "Ознакомьтесь с заявлением о конфиденциальности", |
| 296 | "Trusted workers only": "Только доверенные рабочие машины", | 293 | "Trusted workers only": "Только доверенные рабочие машины", |
| 297 | "For privacy reasons, your API key will be hidden after you reload the page.": "Из соображений безопасности ваш API-ключ будет скрыт после перезагрузки страницы.", | 294 | "For privacy reasons, your API key will be hidden after you reload the page.": "Из соображений безопасности ваш API-ключ будет скрыт после перезагрузки страницы.", |
| 298 | "-- Horde models not loaded --": "--Модель Horde не загружена--", | 295 | "-- Horde models not loaded --": "--Модель Horde не загружена--", |
| @@ -699,7 +696,7 @@ | |||
| 699 | "Aggressive": "Агрессивный", | 696 | "Aggressive": "Агрессивный", |
| 700 | "Very aggressive": "Очень агрессивный", | 697 | "Very aggressive": "Очень агрессивный", |
| 701 | "Eta_Cutoff_desc": "Eta cutoff - основной параметр специальной техники сэмплинга под названием Eta Sampling. В единицах 1e-4; разумное значение - 3. Установите в 0, чтобы отключить. См. статью Truncation Sampling as Language Model Desmoothing от Хьюитт и др. (2022) для получения подробной информации.", | 698 | "Eta_Cutoff_desc": "Eta cutoff - основной параметр специальной техники сэмплинга под названием Eta Sampling. В единицах 1e-4; разумное значение - 3. Установите в 0, чтобы отключить. См. статью Truncation Sampling as Language Model Desmoothing от Хьюитт и др. (2022) для получения подробной информации.", |
| 702 | "Learn how to contribute your idle GPU cycles to the Horde": "Узнайте, как внести свой вклад в свои свободные GPU-циклы в орду", | 699 | "Learn how to contribute your idle GPU cycles to the Horde": "Узнайте, как использовать время простоя вашего GPU для помощи Horde", |
| 703 | "Use the appropriate tokenizer for Google models via their API. Slower prompt processing, but offers much more accurate token counting.": "Используйте соответствующий токенизатор для моделей Google через их API. Медленная обработка подсказок, но предлагает намного более точный подсчет токенов.", | 700 | "Use the appropriate tokenizer for Google models via their API. Slower prompt processing, but offers much more accurate token counting.": "Используйте соответствующий токенизатор для моделей Google через их API. Медленная обработка подсказок, но предлагает намного более точный подсчет токенов.", |
| 704 | "Load koboldcpp order": "Загрузить порядок из koboldcpp", | 701 | "Load koboldcpp order": "Загрузить порядок из koboldcpp", |
| 705 | "Use Google Tokenizer": "Использовать токенизатор Google", | 702 | "Use Google Tokenizer": "Использовать токенизатор Google", |
| @@ -744,7 +741,7 @@ | |||
| 744 | "Last Assistant Prefix": "Последний префикс ассистента", | 741 | "Last Assistant Prefix": "Последний префикс ассистента", |
| 745 | "System Instruction Prefix": "Префикс системной инструкции", | 742 | "System Instruction Prefix": "Префикс системной инструкции", |
| 746 | "User Filler Message": "Принудительное сообщение пользователя", | 743 | "User Filler Message": "Принудительное сообщение пользователя", |
| 747 | "Permanent": "перманентных", | 744 | "Permanent": "постоянных", |
| 748 | "Alt. Greetings": "Др. варианты", | 745 | "Alt. Greetings": "Др. варианты", |
| 749 | "Smooth Streaming": "Плавный стриминг", | 746 | "Smooth Streaming": "Плавный стриминг", |
| 750 | "Save checkpoint": "Сохранить чекпоинт", | 747 | "Save checkpoint": "Сохранить чекпоинт", |
| @@ -1227,7 +1224,6 @@ | |||
| 1227 | "JSON-serialized array of strings.": "Список строк в формате JSON.", | 1224 | "JSON-serialized array of strings.": "Список строк в формате JSON.", |
| 1228 | "Mirostat_desc": "Mirostat - своего рода термометр, измеряющий перплексию для выводимого текста.\nMirostat подгоняет перплексию генерируемого текста к перплексии входного текста, что позволяет избежать повторов.\n(когда по мере генерации текста авторегрессионным инференсом, перплексия всё больше приближается к нулю)\n а также ловушки перплексии (когда перплексия начинает уходить в сторону)\nБолее подробное описание в статье Mirostat: A Neural Text Decoding Algorithm that Directly Controls Perplexity by Basu et al. (2020).\nРежим выбирает версию Mirostat. 0=отключить, 1=Mirostat 1.0 (только llama.cpp), 2=Mirostat 2.0.", | 1225 | "Mirostat_desc": "Mirostat - своего рода термометр, измеряющий перплексию для выводимого текста.\nMirostat подгоняет перплексию генерируемого текста к перплексии входного текста, что позволяет избежать повторов.\n(когда по мере генерации текста авторегрессионным инференсом, перплексия всё больше приближается к нулю)\n а также ловушки перплексии (когда перплексия начинает уходить в сторону)\nБолее подробное описание в статье Mirostat: A Neural Text Decoding Algorithm that Directly Controls Perplexity by Basu et al. (2020).\nРежим выбирает версию Mirostat. 0=отключить, 1=Mirostat 1.0 (только llama.cpp), 2=Mirostat 2.0.", |
| 1229 | "Helpful tip coming soon.": "Подсказку скоро добавим.", | 1226 | "Helpful tip coming soon.": "Подсказку скоро добавим.", |
| 1230 | "Temperature_Last_desc": "Использовать Temperature сэмплер в последнюю очередь. Это почти всегда разумно.\nПри включении: сначала выборка набора правдоподобных токенов, затем применение Temperature для корректировки их относительных вероятностей (технически, логитов).\nПри отключении: сначала применение Temperature для корректировки относительных вероятностей ВСЕХ токенов, затем выборка правдоподобных токенов из этого.\nОтключение Temperature Last увеличивает вероятности в хвосте распределения, что увеличивает шансы получить несогласованный ответ.", | ||
| 1231 | "Speculative Ngram": "Speculative Ngram", | 1227 | "Speculative Ngram": "Speculative Ngram", |
| 1232 | "Use a different speculative decoding method without a draft model": "Use a different speculative decoding method without a draft model.\rUsing a draft model is preferred. Speculative ngram is not as effective.", | 1228 | "Use a different speculative decoding method without a draft model": "Use a different speculative decoding method without a draft model.\rUsing a draft model is preferred. Speculative ngram is not as effective.", |
| 1233 | "Spaces Between Special Tokens": "Spaces Between Special Tokens", | 1229 | "Spaces Between Special Tokens": "Spaces Between Special Tokens", |
| @@ -1256,7 +1252,6 @@ | |||
| 1256 | "DreamGen Model": "Модель DreamGen", | 1252 | "DreamGen Model": "Модель DreamGen", |
| 1257 | "vllm-project/vllm": "vllm-project/vllm (режим враппера OpenAI API)", | 1253 | "vllm-project/vllm": "vllm-project/vllm (режим враппера OpenAI API)", |
| 1258 | "vLLM API key": "Ключ от API vLLM", | 1254 | "vLLM API key": "Ключ от API vLLM", |
| 1259 | "Example: 127.0.0.1:8000": "Example: http://127.0.0.1:8000", | ||
| 1260 | "vLLM Model": "Модель vLLM", | 1255 | "vLLM Model": "Модель vLLM", |
| 1261 | "Aphrodite Model": "Модель Aphrodite", | 1256 | "Aphrodite Model": "Модель Aphrodite", |
| 1262 | "Peek a password": "Посмотреть пароль", | 1257 | "Peek a password": "Посмотреть пароль", |
| @@ -1734,7 +1729,7 @@ | |||
| 1734 | "markdown_hotkeys_desc": "Включить горячие клавиши для вставки символов разметки в некоторых полях ввода. См. '/help hotkeys'.", | 1729 | "markdown_hotkeys_desc": "Включить горячие клавиши для вставки символов разметки в некоторых полях ввода. См. '/help hotkeys'.", |
| 1735 | "Save and Update": "Сохранить и обновить", | 1730 | "Save and Update": "Сохранить и обновить", |
| 1736 | "Profile name:": "Название профиля:", | 1731 | "Profile name:": "Название профиля:", |
| 1737 | "API returned an error": "API вернуло ошибку", | 1732 | "API returned an error": "API ответило ошибкой", |
| 1738 | "Failed to save preset": "Не удалось сохранить пресет", | 1733 | "Failed to save preset": "Не удалось сохранить пресет", |
| 1739 | "Preset name should be unique.": "Название пресета должно быть уникальным.", | 1734 | "Preset name should be unique.": "Название пресета должно быть уникальным.", |
| 1740 | "Invalid file": "Невалидный файл", | 1735 | "Invalid file": "Невалидный файл", |
| @@ -1756,8 +1751,7 @@ | |||
| 1756 | "dot quota_error": "имеется достаточно кредитов.", | 1751 | "dot quota_error": "имеется достаточно кредитов.", |
| 1757 | "If you have sufficient credits, please try again later.": "Если кредитов достаточно, то повторите попытку позднее.", | 1752 | "If you have sufficient credits, please try again later.": "Если кредитов достаточно, то повторите попытку позднее.", |
| 1758 | "Proxy preset '${0}' not found": "Пресет '${0}' не найден", | 1753 | "Proxy preset '${0}' not found": "Пресет '${0}' не найден", |
| 1759 | "Window.ai returned an error": "Window.ai вернул ошибку", | 1754 | "Window.ai returned an error": "Window.ai ответил ошибкой", |
| 1760 | "Get it here:": "Загрузите здесь:", | ||
| 1761 | "Extension is not installed": "Расширение не установлено", | 1755 | "Extension is not installed": "Расширение не установлено", |
| 1762 | "Update or remove your reverse proxy settings.": "Измените или удалите ваши настройки прокси.", | 1756 | "Update or remove your reverse proxy settings.": "Измените или удалите ваши настройки прокси.", |
| 1763 | "An error occurred while importing prompts. More info available in console.": "В процессе импорта произошла ошибка. Подробную информацию см. в консоли.", | 1757 | "An error occurred while importing prompts. More info available in console.": "В процессе импорта произошла ошибка. Подробную информацию см. в консоли.", |
| @@ -1866,7 +1860,7 @@ | |||
| 1866 | "Group Chat could not be saved": "Не удалось сохранить групповой чат", | 1860 | "Group Chat could not be saved": "Не удалось сохранить групповой чат", |
| 1867 | "Deleted group member swiped. To get a reply, add them back to the group.": "Вы пытаетесь свайпнуть удалённого члена группы. Чтобы получить ответ, добавьте этого персонажа обратно в группу.", | 1861 | "Deleted group member swiped. To get a reply, add them back to the group.": "Вы пытаетесь свайпнуть удалённого члена группы. Чтобы получить ответ, добавьте этого персонажа обратно в группу.", |
| 1868 | "Currently no group selected.": "В данный момент не выбрано ни одной группы.", | 1862 | "Currently no group selected.": "В данный момент не выбрано ни одной группы.", |
| 1869 | "Not so fast! Wait for the characters to stop typing before deleting the group.": "Чуть помедленнее! Перед удалением группы дождитесь, пока персонаж закончит печатать.", | 1863 | "Not so fast! Wait for the characters to stop typing before deleting the group.": "Чуть помедленнее! Перед удалением группы дождитесь, пока персонажи закончат печатать.", |
| 1870 | "Delete the group?": "Удалить группу?", | 1864 | "Delete the group?": "Удалить группу?", |
| 1871 | "This will also delete all your chats with that group. If you want to delete a single conversation, select a \"View past chats\" option in the lower left menu.": "Вместе с ней будут удалены и все её чаты. Если требуется удалить только один чат, воспользуйтесь кнопкой \"Все чаты\" в меню в левом нижнем углу.", | 1865 | "This will also delete all your chats with that group. If you want to delete a single conversation, select a \"View past chats\" option in the lower left menu.": "Вместе с ней будут удалены и все её чаты. Если требуется удалить только один чат, воспользуйтесь кнопкой \"Все чаты\" в меню в левом нижнем углу.", |
| 1872 | "Can't peek a character while group reply is being generated": "Невозможно открыть карточку персонажа во время генерации ответа", | 1866 | "Can't peek a character while group reply is being generated": "Невозможно открыть карточку персонажа во время генерации ответа", |
| @@ -1997,7 +1991,7 @@ | |||
| 1997 | "Default persona deleted": "Удалена персона по умолчанию", | 1991 | "Default persona deleted": "Удалена персона по умолчанию", |
| 1998 | "The locked persona was deleted. You will need to set a new persona for this chat.": "Удалена привязанная к чату персона. Вам будет необходимо выбрать новую фиксированную персону для этого чата.", | 1992 | "The locked persona was deleted. You will need to set a new persona for this chat.": "Удалена привязанная к чату персона. Вам будет необходимо выбрать новую фиксированную персону для этого чата.", |
| 1999 | "Persona deleted": "Персона удалена", | 1993 | "Persona deleted": "Персона удалена", |
| 2000 | "You must bind a name to this persona before you can set it as the default.": "Прежде чем установить эту персону в качестве персоны по умолчанию, ей необходимо задать имя.", | 1994 | "You must bind a name to this persona before you can set it as the default.": "Прежде чем установить эту персону в качестве персоны по умолчанию, ей необходимо присвоить имя.", |
| 2001 | "Persona name not set": "У персоны отсутствует имя", | 1995 | "Persona name not set": "У персоны отсутствует имя", |
| 2002 | "Are you sure you want to remove the default persona?": "Вы точно хотите снять статус персоны по умолчанию?", | 1996 | "Are you sure you want to remove the default persona?": "Вы точно хотите снять статус персоны по умолчанию?", |
| 2003 | "This persona will no longer be used by default when you open a new chat.": "Эта персона больше не будет автоматически выбираться при старте нового чата", | 1997 | "This persona will no longer be used by default when you open a new chat.": "Эта персона больше не будет автоматически выбираться при старте нового чата", |
| @@ -2038,7 +2032,7 @@ | |||
| 2038 | "[Currently loaded]": "[Загруженная сейчас]", | 2032 | "[Currently loaded]": "[Загруженная сейчас]", |
| 2039 | "Search providers...": "Искать по провайдерам...", | 2033 | "Search providers...": "Искать по провайдерам...", |
| 2040 | "Automatically chooses an alternative provider if chosen providers can't serve your request.": "Автоматически переключаться на другого провайдера, если текущий не может обслужить запрос.", | 2034 | "Automatically chooses an alternative provider if chosen providers can't serve your request.": "Автоматически переключаться на другого провайдера, если текущий не может обслужить запрос.", |
| 2041 | "Example: 127.0.0.1:8000": "Пример: 127.0.0.1:8000", | 2035 | "Example: http://127.0.0.1:8000": "Пример: http://127.0.0.1:8000", |
| 2042 | "Edit a connection profile": "Редактировать профиль соединения", | 2036 | "Edit a connection profile": "Редактировать профиль соединения", |
| 2043 | "System Prompt Name": "Название системного промпта", | 2037 | "System Prompt Name": "Название системного промпта", |
| 2044 | "Use System Prompt": "Использовать системный промпт", | 2038 | "Use System Prompt": "Использовать системный промпт", |
| @@ -2203,5 +2197,146 @@ | |||
| 2203 | "Input:": "Входные данные:", | 2197 | "Input:": "Входные данные:", |
| 2204 | "Tokenized text:": "Токенизированный текст:", | 2198 | "Tokenized text:": "Токенизированный текст:", |
| 2205 | "Token IDs:": "Идентификаторы токенов:", | 2199 | "Token IDs:": "Идентификаторы токенов:", |
| 2206 | "Tokens:": "Токенов:" | 2200 | "Tokens:": "Токенов:", |
| 2201 | "Max prompt cost:": "Макс. стоимость промпта:", | ||
| 2202 | "Reset custom sampler selection": "Сбросить подборку семплеров", | ||
| 2203 | "Here you can toggle the display of individual samplers. (WIP)": "Здесь можно включить или выключить отображение каждого из сэмплеров отдельно. (WIP)", | ||
| 2204 | "Request Model Reasoning": "Запрашивать цепочку рассуждений", | ||
| 2205 | "Reasoning": "Рассуждения / Reasoning", | ||
| 2206 | "Auto-Parse": "Авто-парсинг", | ||
| 2207 | "reasoning_auto_parse": "Автоматически считывать блоки рассуждений, расположенные между префиксом и суффиксом рассуждений. Для работы должно быть указано и то, и другое.", | ||
| 2208 | "Auto-Expand": "Разворачивать", | ||
| 2209 | "reasoning_auto_expand": "Автоматически разворачивать блоки рассуждений.", | ||
| 2210 | "Show Hidden": "Показывать время", | ||
| 2211 | "reasoning_show_hidden": "Отображать затраченное на рассуждения время для моделей со скрытой цепочкой рассуждений", | ||
| 2212 | "Add to Prompts": "Добавлять в промпт", | ||
| 2213 | "reasoning_add_to_prompts": "Добавлять существующие блоки рассуждений в промпт. Для добавления новых используйте меню редактирования сообщений.", | ||
| 2214 | "reasoning_max_additions": "Макс. кол-во блоков рассуждений в промпте, считается от последнего сообщения", | ||
| 2215 | "Max": "Макс.", | ||
| 2216 | "Reasoning Formatting": "Форматирование рассуждений", | ||
| 2217 | "Prefix": "Префикс", | ||
| 2218 | "Suffix": "Постфикс", | ||
| 2219 | "Separator": "Разделитель", | ||
| 2220 | "reasoning_separator": "Вставляется между рассуждениями и содержанием самого сообщения.", | ||
| 2221 | "reasoning_prefix": "Вставляется перед рассуждениями.", | ||
| 2222 | "reasoning_suffix": "Вставляется после рассуждений.", | ||
| 2223 | "Seed_desc": "Фиксированное значение зерна позволяет получать предсказуемые, одинаковые результаты на одинаковых настройках. Поставьте -1 для рандомного зерна.", | ||
| 2224 | "# of Beams": "Кол-во лучей", | ||
| 2225 | "The number of sequences generated at each step with Beam Search.": "Кол-во вариантов, генерируемых Beam Search на каждом шаге работы.", | ||
| 2226 | "Penalize sequences based on their length.": "Штрафует строки в зависимости от длины", | ||
| 2227 | "Controls the stopping condition for beam search. If checked, the generation stops as soon as there are '# of Beams' sequences. If not checked, a heuristic is applied and the generation is stopped when it's very unlikely to find better candidates.": "Определяет, когда останавливать работу Beam Search. Поставив галочку, вы укажете поиску остановиться тогда, когда будет достигнуто кол-во лучей из соответствующего поля. Если галочку не отмечать, то генерация остановится тогда, когда сочтёт, что дальше найти лучших кандидатов слишком маловероятно.", | ||
| 2228 | "A greedy, brute-force algorithm used in LLM sampling to find the most likely sequence of words or tokens. It expands multiple candidate sequences at once, maintaining a fixed number (beam width) of top sequences at each step.": "Жадный алгоритм LLM-сэмплинга, подбирающий наиболее вероятную последовательность слов или токенов путём исследования и расширения сразу нескольких вариантов. На каждом шаге он удерживает фиксированное кол-во самых подходящих вариантов (ширина луча).", | ||
| 2229 | "Smooth_Sampling_desc": "Изменяет распределение с помощью квадратичных и кубических преобразований. Снижение Коэффициента сглаживания даёт более креативные ответы, обычно идеальное значение находится в диапазоне 0.2-0.3 (при кривой сглаживания=1.0). Повышение значения Кривой сглаживания сделает кривую круче, что приведёт к более агрессивной фильтрации маловероятных вариантов. Установив Кривую сглаживания = 1.0, вы фактически нейтрализуете этот параметр и будете работать только с Коэффициентом", | ||
| 2230 | "Temperature_Last_desc": "Применять сэмплер Температуры в последнюю очередь. Почти всегда оправдано.\nПри включении: сначала все токены семплируются, и затем температура регулирует распределение у оставшихся (технически, у оставшихся логитов).\nПри выключении: сначала температура настраивает распределение ВСЕХ токенов, и потом они семплируются уже с этим обновлённым распределением.\nПри отключении этой опции токены в хвосте получают больше шансов попасть в итоговую последовательность, что может привести к менее связным и логичным ответам.", | ||
| 2231 | "Swipe # for All Messages": "Номер свайпа на всех сообщениях", | ||
| 2232 | "Display swipe numbers for all messages, not just the last.": "Отображать номер свайпа для всех сообщений, а не только для последнего.", | ||
| 2233 | "Penalty Range": "Окно для штрафа", | ||
| 2234 | "Never": "Никогда", | ||
| 2235 | "Groups and Past Personas": "Для групп и прошлых персон", | ||
| 2236 | "Always": "Всегда", | ||
| 2237 | "Request model reasoning": "Запрашивать рассуждения", | ||
| 2238 | "Allows the model to return its thinking process.": "Позволяет модели высылать в ответе свою цепочку рассуждений.", | ||
| 2239 | "Rename Persona": "Переименовать персону", | ||
| 2240 | "Change Persona Image": "Изменить изображение персоны", | ||
| 2241 | "Duplicate Persona": "Клонировать персону", | ||
| 2242 | "Delete Persona": "Удалить персону", | ||
| 2243 | "Enter a new name for this persona:": "Введите новое имя персоны:", | ||
| 2244 | "Connections": "Связи", | ||
| 2245 | "Click to select this as default persona for the new chats. Click again to remove it.": "Нажмите, чтобы установить эту персону стандартной для всех новых чатов. Нажмите ещё раз, чтобы отключить.", | ||
| 2246 | "Character": "Персонаж", | ||
| 2247 | "Click to lock your selected persona to the current character. Click again to remove the lock.": "Нажмите, чтобы закрепить эту персону для текущего персонажа. Нажмите ещё раз, чтобы открепить.", | ||
| 2248 | "Chat": "Чат", | ||
| 2249 | "[No character connections. Click one of the buttons above to connect this persona.]": "[Связи отсутствуют. Нажмите на одну из кнопок выше, чтобы создать.]", | ||
| 2250 | "Global Settings": "Общие настройки", | ||
| 2251 | "Allow multiple persona connections per character": "Разрешить привязывать несколько персон к одному персонажу", | ||
| 2252 | "When multiple personas are connected to a character, a popup will appear to select which one to use": "При связывании нескольких персон с персонажем, будет появляться окошко с предложением выбрать нужную.", | ||
| 2253 | "Auto-lock a chosen persona to the chat": "Автоматически привязывать выбранную персону к чату", | ||
| 2254 | "Whenever a persona is selected, it will be locked to the current chat and automatically selected when the chat is opened.": "При выборе новой персоны она автоматически будет привязана к текущему чату, и будет выбираться при его открытии.", | ||
| 2255 | "Current Persona": "Текущая персона", | ||
| 2256 | "The chat has been successfully converted!": "Чат успешно преобразован!", | ||
| 2257 | "Manual": "Когда вы скажете", | ||
| 2258 | "Auto Mode delay": "Задержка авто-режима", | ||
| 2259 | "Use tag as folder": "Тег-папка", | ||
| 2260 | "All connections to ${0} have been removed.": "Все связи с персонажем ${0} были удалены.", | ||
| 2261 | "Personas Unlocked": "Персоны отвязаны", | ||
| 2262 | "Remove All Connections": "Удалить все связи", | ||
| 2263 | "Persona ${0} selected and auto-locked to current chat": "Персона ${0} выбрана и автоматически закреплена за этим чатом", | ||
| 2264 | "This persona is only temporarily chosen. Click for more info.": "Данная персона выбрана лишь временно. Нажмите, чтобы узнать больше.", | ||
| 2265 | "Temporary Persona": "Временная персона", | ||
| 2266 | "A different persona is locked to this chat, or you have a different default persona set. The currently selected persona will only be temporary, and resets on reload. Consider locking this persona to the chat if you want to permanently use it.": "К этому чату уже привязана иная персона, либо у вас выбрана иная персона по-умолчанию. Выбранная в данный момент персона будет временной, и сбросится после перезагрузки. Если хотите всегда использовать её в этом чате, советуем её прикрепить.", | ||
| 2267 | "Current Persona: ${0}": "Выбранная персона: ${0}", | ||
| 2268 | "Chat persona: ${0}": "Персона для этого чата: ${0}", | ||
| 2269 | "Default persona: ${0}": "Персона по умолчанию (стандартная): ${0}", | ||
| 2270 | "Persona ${0} is now unlocked from this chat.": "Персона ${0} отвязана от этого чата.", | ||
| 2271 | "Persona Unlocked": "Персона отвязана", | ||
| 2272 | "Persona ${0} is now unlocked from character ${1}.": "Персона ${0} отвязана от персонажа ${1}.", | ||
| 2273 | "Persona Not Found": "Персона не найдена", | ||
| 2274 | "Persona Locked": "Персона закреплена", | ||
| 2275 | "User persona ${0} is locked to character ${1}${2}": "Персона ${0} прикреплена к персонажу ${1}${2}", | ||
| 2276 | "Persona Name Not Set": "У персоны отсутствует имя", | ||
| 2277 | "You must bind a name to this persona before you can set a lorebook.": "Перед привязкой лорбука персоне необходимо присвоить имя.", | ||
| 2278 | "Default Persona Removed": "Персона по умолчанию снята", | ||
| 2279 | "Persona is locked to the current character": "Персона закреплена за этим персонажем", | ||
| 2280 | "Persona is locked to the current chat": "Персона закреплена за этим чатом", | ||
| 2281 | "characters": "перс.", | ||
| 2282 | "character": "персонаж", | ||
| 2283 | "in this group": "в группе", | ||
| 2284 | "Chatting Since": "Первая беседа", | ||
| 2285 | "Context": "Контекст", | ||
| 2286 | "Response": "Ответ", | ||
| 2287 | "Connected": "Подключено", | ||
| 2288 | "Enter new background name:": "Введите новое название для фона:", | ||
| 2289 | "AI Horde Website": "Сайт AI Horde", | ||
| 2290 | "Enable web search": "Включить поиск в Интернете", | ||
| 2291 | "Use search capabilities provided by the backend.": "Разрешить использование предоставляемых бэкендом функций поиска.", | ||
| 2292 | "Request inline images": "Запрашивать inline-изображения", | ||
| 2293 | "Allows the model to return image attachments.": "Разрешить модели отправлять вложения в виде картинок.", | ||
| 2294 | "Request inline images_desc_2": "Не совместимо со следующим функционалом: вызов функций, поиск в Интернете, системный промпт.", | ||
| 2295 | "Connected Personas": "Связанные персоны", | ||
| 2296 | "[Currently no personas connected]": "[Связанных персон нет]", | ||
| 2297 | "The following personas are connected to the current character.\n\nClick on a persona to select it for the current character.\nShift + Click to unlink the persona from the character.": "С этим персонажем связаны следующие персоны.\n\nНажмите на персону, чтобы выбрать её для данного персонажа.\nShift + ЛКМ, чтобы её отвязать.", | ||
| 2298 | "Persona Connections": "Связи с персонами", | ||
| 2299 | "Pooled order": "Если уже давно не отвечали", | ||
| 2300 | "Attach a File": "Приложить файл", | ||
| 2301 | "Attach a file or image to a current chat.": "Приложить файл или изображение к текущему чату", | ||
| 2302 | "Remove the file": "Удалить файл", | ||
| 2303 | "Delete the Chat File?": "Удалить чат?", | ||
| 2304 | "Forbidden": "Доступ запрещён", | ||
| 2305 | "To view your API keys here, set the value of allowKeysExposure to true in config.yaml file and restart the SillyTavern server.": "Чтобы видеть здесь ваши API-ключи, установите параметр allowKeysExposure в config.yaml в положение true, после чего перезапустите сервер SillyTavern.", | ||
| 2306 | "Invalid endpoint URL. Requests may fail.": "Некорректный адрес эндпоинта. Запросы могут не проходить.", | ||
| 2307 | "How to install extensions?": "Как устанавливать расширения?", | ||
| 2308 | "Click the flashing button to install extensions.": "Чтобы их установить, нажмите на мигающую кнопку.", | ||
| 2309 | "ext_regex_reasoning_desc": "Содержимое блоков рассуждений. При отмеченной галочке \"Только промпт\" будут также обработаны добавленные в промпт рассуждения.", | ||
| 2310 | "Macro in Find Regex": "Макросы в рег. выражении", | ||
| 2311 | "Don't substitute": "Не заменять", | ||
| 2312 | "Substitute (raw)": "Заменять в \"чистом\" виде", | ||
| 2313 | "Substitute (escaped)": "Заменять после экранирования", | ||
| 2314 | "ext_regex_other_options_desc": "По умолчанию, расширение вносит изменения в сам файл чата.\nПри включении одной из опций (или обеих), файл чата останется нетронутым, при этом сами изменения по-прежнему будут действовать.", | ||
| 2315 | "ext_regex_flags_help": "Нажмите, чтобы узнать больше о флагах в рег. выражениях.", | ||
| 2316 | "Applies to all matches": "Заменяет все вхождения", | ||
| 2317 | "Applies to the first match": "Заменяет первое вхождение", | ||
| 2318 | "Case insensitive": "Не чувствительно к регистру", | ||
| 2319 | "Case sensitive": "Чувствительно к регистру", | ||
| 2320 | "Find Regex is empty": "Рег. выражение не указано", | ||
| 2321 | "Click the button to save it as a file.": "Нажмите на кнопку справа, чтобы сохранить его в файл.", | ||
| 2322 | "Export as JSONL": "Экспорт в формате JSONL", | ||
| 2323 | "Thought for some time": "Какое-то время заняли размышления", | ||
| 2324 | "Thinking...": "В раздумьях...", | ||
| 2325 | "Thought for ${0}": "Размышления заняли ${0}", | ||
| 2326 | "Hidden reasoning - Add reasoning block": "Рассуждения скрыты - Добавить блок рассуждений", | ||
| 2327 | "Add reasoning block": "Добавить блок рассуждений", | ||
| 2328 | "Edit reasoning": "Редактировать рассуждения", | ||
| 2329 | "Copy reasoning": "Скопировать рассуждения", | ||
| 2330 | "Confirm Edit": "Подтвердить", | ||
| 2331 | "Remove reasoning": "Удалить рассуждения", | ||
| 2332 | "Cancel edit": "Отменить редактирование", | ||
| 2333 | "Remove Reasoning": "Удалить рассуждения", | ||
| 2334 | "Are you sure you want to clear the reasoning?<br />Visible message contents will stay intact.": "Вы точно хотите удалить блок рассуждений?<br />Основное сообщение останется на месте.", | ||
| 2335 | "Reasoning Parse": "Парсинг рассуждений", | ||
| 2336 | "Both prefix and suffix must be set in the Reasoning Formatting settings.": "В настройках форматирования рассуждений должны быть заданы префикс и суффикс.", | ||
| 2337 | "Invalid return type '${0}', defaulting to 'reasoning'.": "Некорректный возвращаемый тип, используем стандартный 'reasoning'.", | ||
| 2338 | "Reasoning already exists.": "Рассуждения уже присутствуют.", | ||
| 2339 | "Edit Message": "Редактирование", | ||
| 2340 | "Status check bypassed": "Проверка статуса отключена", | ||
| 2341 | "Valid": "Работает" | ||
| 2207 | } | 2342 | } |
| @@ -318,23 +318,23 @@ | |||
| 318 | "flag": "прапорцем", | 318 | "flag": "прапорцем", |
| 319 | "API key (optional)": "Ключ API (необов'язково)", | 319 | "API key (optional)": "Ключ API (необов'язково)", |
| 320 | "Server url": "URL-адреса сервера", | 320 | "Server url": "URL-адреса сервера", |
| 321 | "Example: 127.0.0.1:5000": "Приклад: 127.0.0.1:5000", | 321 | "Example: http://127.0.0.1:5000": "Приклад: http://127.0.0.1:5000", |
| 322 | "Custom model (optional)": "Власна модель (необов'язково)", | 322 | "Custom model (optional)": "Власна модель (необов'язково)", |
| 323 | "vllm-project/vllm": "vllm-project/vllm (режим оболонки OpenAI API)", | 323 | "vllm-project/vllm": "vllm-project/vllm (режим оболонки OpenAI API)", |
| 324 | "vLLM API key": "Ключ API vLLM", | 324 | "vLLM API key": "Ключ API vLLM", |
| 325 | "Example: 127.0.0.1:8000": "Приклад: http://127.0.0.1:8000", | 325 | "Example: http://127.0.0.1:8000": "Приклад: http://127.0.0.1:8000", |
| 326 | "vLLM Model": "Модель vLLM", | 326 | "vLLM Model": "Модель vLLM", |
| 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (режим OpenAI API)", | 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (режим OpenAI API)", |
| 328 | "Aphrodite API key": "Ключ API для Aphrodite", | 328 | "Aphrodite API key": "Ключ API для Aphrodite", |
| 329 | "Aphrodite Model": "Модель Афродіта", | 329 | "Aphrodite Model": "Модель Афродіта", |
| 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (сервер виведення)", | 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp (сервер виведення)", |
| 331 | "Example: 127.0.0.1:8080": "Приклад: 127.0.0.1:8080", | 331 | "Example: http://127.0.0.1:8080": "Приклад: http://127.0.0.1:8080", |
| 332 | "Example: 127.0.0.1:11434": "Приклад: 127.0.0.1:11434", | 332 | "Example: http://127.0.0.1:11434": "Приклад: http://127.0.0.1:11434", |
| 333 | "Ollama Model": "Модель Ollama", | 333 | "Ollama Model": "Модель Ollama", |
| 334 | "Download": "Завантажити", | 334 | "Download": "Завантажити", |
| 335 | "Tabby API key": "Ключ API для Tabby", | 335 | "Tabby API key": "Ключ API для Tabby", |
| 336 | "koboldcpp API key (optional)": "API-ключ koboldcpp (необов’язково)", | 336 | "koboldcpp API key (optional)": "API-ключ koboldcpp (необов’язково)", |
| 337 | "Example: 127.0.0.1:5001": "Приклад: 127.0.0.1:5001", | 337 | "Example: http://127.0.0.1:5001": "Приклад: http://127.0.0.1:5001", |
| 338 | "Authorize": "Авторизувати", | 338 | "Authorize": "Авторизувати", |
| 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Отримайте свій токен API OpenRouter за допомогою OAuth. Вас буде перенаправлено на openrouter.ai", | 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Отримайте свій токен API OpenRouter за допомогою OAuth. Вас буде перенаправлено на openrouter.ai", |
| 340 | "Bypass status check": "Обійти перевірку статусу", | 340 | "Bypass status check": "Обійти перевірку статусу", |
| @@ -318,23 +318,23 @@ | |||
| 318 | "flag": "cờ", | 318 | "flag": "cờ", |
| 319 | "API key (optional)": "Key API (tùy chọn)", | 319 | "API key (optional)": "Key API (tùy chọn)", |
| 320 | "Server url": "URL máy chủ", | 320 | "Server url": "URL máy chủ", |
| 321 | "Example: 127.0.0.1:5000": "Ví dụ: 127.0.0.1:5000", | 321 | "Example: http://127.0.0.1:5000": "Ví dụ: http://127.0.0.1:5000", |
| 322 | "Custom model (optional)": "Model tùy chỉnh (tùy chọn)", | 322 | "Custom model (optional)": "Model tùy chỉnh (tùy chọn)", |
| 323 | "vllm-project/vllm": "vllm-project/vllm (Chế độ trình bao bọc API OpenAI)", | 323 | "vllm-project/vllm": "vllm-project/vllm (Chế độ trình bao bọc API OpenAI)", |
| 324 | "vLLM API key": "Key API vLLM", | 324 | "vLLM API key": "Key API vLLM", |
| 325 | "Example: 127.0.0.1:8000": "Ví dụ: http://127.0.0.1:8000", | 325 | "Example: http://127.0.0.1:8000": "Ví dụ: http://127.0.0.1:8000", |
| 326 | "vLLM Model": "Model vLLM", | 326 | "vLLM Model": "Model vLLM", |
| 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (Chế độ đóng gói cho Giao diện lập trình ứng dụng OpenAI)", | 327 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite-engine (Chế độ đóng gói cho Giao diện lập trình ứng dụng OpenAI)", |
| 328 | "Aphrodite API key": "Key API Aphrodite", | 328 | "Aphrodite API key": "Key API Aphrodite", |
| 329 | "Aphrodite Model": "Moddel cho Aphrodite", | 329 | "Aphrodite Model": "Moddel cho Aphrodite", |
| 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp", | 330 | "ggerganov/llama.cpp": "ggerganov/llama.cpp", |
| 331 | "Example: 127.0.0.1:8080": "Ví dụ: 127.0.0.1:8080", | 331 | "Example: http://127.0.0.1:8080": "Ví dụ: http://127.0.0.1:8080", |
| 332 | "Example: 127.0.0.1:11434": "Ví dụ: 127.0.0.1:11434", | 332 | "Example: http://127.0.0.1:11434": "Ví dụ: http://127.0.0.1:11434", |
| 333 | "Ollama Model": "Model Ollama", | 333 | "Ollama Model": "Model Ollama", |
| 334 | "Download": "Tải xuống", | 334 | "Download": "Tải xuống", |
| 335 | "Tabby API key": "Key API Tabby", | 335 | "Tabby API key": "Key API Tabby", |
| 336 | "koboldcpp API key (optional)": "Key API koboldcpp (tùy chọn)", | 336 | "koboldcpp API key (optional)": "Key API koboldcpp (tùy chọn)", |
| 337 | "Example: 127.0.0.1:5001": "Ví dụ: 127.0.0.1:5001", | 337 | "Example: http://127.0.0.1:5001": "Ví dụ: http://127.0.0.1:5001", |
| 338 | "Cho phép": "Ủy quyền", | 338 | "Cho phép": "Ủy quyền", |
| 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Nhận mã thông báo API OpenRouter của bạn bằng cách sử dụng luồng OAuth. Bạn sẽ được chuyển hướng đến openrouter.ai", | 339 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Nhận mã thông báo API OpenRouter của bạn bằng cách sử dụng luồng OAuth. Bạn sẽ được chuyển hướng đến openrouter.ai", |
| 340 | "Bypass status check": "Bỏ qua check trạng thái", | 340 | "Bypass status check": "Bỏ qua check trạng thái", |
| @@ -347,7 +347,7 @@ | |||
| 347 | "Mancer Model": "Mancer 模型", | 347 | "Mancer Model": "Mancer 模型", |
| 348 | "API key (optional)": "API密钥(可选)", | 348 | "API key (optional)": "API密钥(可选)", |
| 349 | "Server url": "服务器URL", | 349 | "Server url": "服务器URL", |
| 350 | "Example: 127.0.0.1:5000": "示例:127.0.0.1:5000", | 350 | "Example: http://127.0.0.1:5000": "示例:http://127.0.0.1:5000", |
| 351 | "Model ID (optional)": "模型 ID(可选)", | 351 | "Model ID (optional)": "模型 ID(可选)", |
| 352 | "Make sure you run it with": "确保您在运行时加上", | 352 | "Make sure you run it with": "确保您在运行时加上", |
| 353 | "flag": "标志", | 353 | "flag": "标志", |
| @@ -364,7 +364,7 @@ | |||
| 364 | "No model description": "[无描述]", | 364 | "No model description": "[无描述]", |
| 365 | "vllm-project/vllm": "vllm-project/vllm(OpenAI API 包装器模式)", | 365 | "vllm-project/vllm": "vllm-project/vllm(OpenAI API 包装器模式)", |
| 366 | "vLLM API key": "vLLM API 密钥", | 366 | "vLLM API key": "vLLM API 密钥", |
| 367 | "Example: 127.0.0.1:8000": "示例:http://127.0.0.1:8000", | 367 | "Example: http://127.0.0.1:8000": "示例:http://127.0.0.1:8000", |
| 368 | "vLLM Model": "vLLM 模型", | 368 | "vLLM Model": "vLLM 模型", |
| 369 | "HuggingFace Token": "HuggingFace 代币", | 369 | "HuggingFace Token": "HuggingFace 代币", |
| 370 | "Endpoint URL": "端点 URL", | 370 | "Endpoint URL": "端点 URL", |
| @@ -373,8 +373,8 @@ | |||
| 373 | "Aphrodite API key": "Aphrodite API 密钥", | 373 | "Aphrodite API key": "Aphrodite API 密钥", |
| 374 | "Aphrodite Model": "Aphrodite 模型", | 374 | "Aphrodite Model": "Aphrodite 模型", |
| 375 | "ggerganov/llama.cpp": "ggerganov/llama.cpp", | 375 | "ggerganov/llama.cpp": "ggerganov/llama.cpp", |
| 376 | "Example: 127.0.0.1:8080": "示例:127.0.0.1:8080", | 376 | "Example: http://127.0.0.1:8080": "示例:http://127.0.0.1:8080", |
| 377 | "Example: 127.0.0.1:11434": "示例:127.0.0.1:11434", | 377 | "Example: http://127.0.0.1:11434": "示例:http://127.0.0.1:11434", |
| 378 | "Ollama Model": "Ollama 模型", | 378 | "Ollama Model": "Ollama 模型", |
| 379 | "Download": "下载", | 379 | "Download": "下载", |
| 380 | "Tabby API key": "Tabby API 密钥", | 380 | "Tabby API key": "Tabby API 密钥", |
| @@ -382,7 +382,7 @@ | |||
| 382 | "must be set in Tabby's config.yml to switch models.": "必须在Tabby的config.yml内设置以切换模型", | 382 | "must be set in Tabby's config.yml to switch models.": "必须在Tabby的config.yml内设置以切换模型", |
| 383 | "Use an admin API key.": "使用管理员API密钥。", | 383 | "Use an admin API key.": "使用管理员API密钥。", |
| 384 | "koboldcpp API key (optional)": "koboldcpp API 密钥(可选)", | 384 | "koboldcpp API key (optional)": "koboldcpp API 密钥(可选)", |
| 385 | "Example: 127.0.0.1:5001": "示例:127.0.0.1:5001", | 385 | "Example: http://127.0.0.1:5001": "示例:http://127.0.0.1:5001", |
| 386 | "Bypass status check": "跳过状态检查", | 386 | "Bypass status check": "跳过状态检查", |
| 387 | "Derive context size from backend": "从后端获取上下文长度", | 387 | "Derive context size from backend": "从后端获取上下文长度", |
| 388 | "Authorize": "授权", | 388 | "Authorize": "授权", |
| @@ -319,23 +319,23 @@ | |||
| 319 | "flag": "旗標", | 319 | "flag": "旗標", |
| 320 | "API key (optional)": "API 金鑰(可選)", | 320 | "API key (optional)": "API 金鑰(可選)", |
| 321 | "Server url": "伺服器 URL", | 321 | "Server url": "伺服器 URL", |
| 322 | "Example: 127.0.0.1:5000": "範例:127.0.0.1:5000", | 322 | "Example: http://127.0.0.1:5000": "範例:http://127.0.0.1:5000", |
| 323 | "Custom model (optional)": "自訂模型(選填)", | 323 | "Custom model (optional)": "自訂模型(選填)", |
| 324 | "vllm-project/vllm": "vllm-project/vllm", | 324 | "vllm-project/vllm": "vllm-project/vllm", |
| 325 | "vLLM API key": "vLLM API 金鑰", | 325 | "vLLM API key": "vLLM API 金鑰", |
| 326 | "Example: 127.0.0.1:8000": "範例:127.0.0.1:8000", | 326 | "Example: http://127.0.0.1:8000": "範例:http://127.0.0.1:8000", |
| 327 | "vLLM Model": "vLLM 模型", | 327 | "vLLM Model": "vLLM 模型", |
| 328 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite 引擎", | 328 | "PygmalionAI/aphrodite-engine": "PygmalionAI/aphrodite 引擎", |
| 329 | "Aphrodite API key": "Aphrodite API 金鑰", | 329 | "Aphrodite API key": "Aphrodite API 金鑰", |
| 330 | "Aphrodite Model": "Aphrodite 模型", | 330 | "Aphrodite Model": "Aphrodite 模型", |
| 331 | "ggerganov/llama.cpp": "ggerganov/llama.cpp", | 331 | "ggerganov/llama.cpp": "ggerganov/llama.cpp", |
| 332 | "Example: 127.0.0.1:8080": "範例:127.0.0.1:8080", | 332 | "Example: http://127.0.0.1:8080": "範例:http://127.0.0.1:8080", |
| 333 | "Example: 127.0.0.1:11434": "範例:127.0.0.1:11434", | 333 | "Example: http://127.0.0.1:11434": "範例:http://127.0.0.1:11434", |
| 334 | "Ollama Model": "Ollama 模型", | 334 | "Ollama Model": "Ollama 模型", |
| 335 | "Download": "下載", | 335 | "Download": "下載", |
| 336 | "Tabby API key": "Tabby API 金鑰", | 336 | "Tabby API key": "Tabby API 金鑰", |
| 337 | "koboldcpp API key (optional)": "KoboldCpp API 金鑰(可選)", | 337 | "koboldcpp API key (optional)": "KoboldCpp API 金鑰(可選)", |
| 338 | "Example: 127.0.0.1:5001": "範例:127.0.0.1:5001", | 338 | "Example: http://127.0.0.1:5001": "範例:http://127.0.0.1:5001", |
| 339 | "Authorize": "授權", | 339 | "Authorize": "授權", |
| 340 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "使用 OAuth 流程取得您的 OpenRouter API 符元。您將被重新導向到 openrouter.ai", | 340 | "Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "使用 OAuth 流程取得您的 OpenRouter API 符元。您將被重新導向到 openrouter.ai", |
| 341 | "Bypass status check": "繞過狀態檢查", | 341 | "Bypass status check": "繞過狀態檢查", |
| @@ -172,8 +172,10 @@ import { | |||
| 172 | copyText, | 172 | copyText, |
| 173 | escapeHtml, | 173 | escapeHtml, |
| 174 | saveBase64AsFile, | 174 | saveBase64AsFile, |
| 175 | uuidv4, | ||
| 176 | equalsIgnoreCaseAndAccents, | ||
| 175 | } from './scripts/utils.js'; | 177 | } from './scripts/utils.js'; |
| 176 | import { debounce_timeout } from './scripts/constants.js'; | 178 | import { debounce_timeout, IGNORE_SYMBOL } from './scripts/constants.js'; |
| 177 | 179 | ||
| 178 | import { doDailyExtensionUpdatesCheck, extension_settings, initExtensions, loadExtensionSettings, runGenerationInterceptors, saveMetadataDebounced } from './scripts/extensions.js'; | 180 | import { doDailyExtensionUpdatesCheck, extension_settings, initExtensions, loadExtensionSettings, runGenerationInterceptors, saveMetadataDebounced } from './scripts/extensions.js'; |
| 179 | import { COMMENT_NAME_DEFAULT, executeSlashCommandsOnChatInput, getSlashCommandsHelp, initDefaultSlashCommands, isExecutingCommandsFromChatInput, pauseScriptExecution, processChatSlashCommands, stopScriptExecution } from './scripts/slash-commands.js'; | 181 | import { COMMENT_NAME_DEFAULT, executeSlashCommandsOnChatInput, getSlashCommandsHelp, initDefaultSlashCommands, isExecutingCommandsFromChatInput, pauseScriptExecution, processChatSlashCommands, stopScriptExecution } from './scripts/slash-commands.js'; |
| @@ -494,6 +496,8 @@ export const event_types = { | |||
| 494 | GENERATE_AFTER_COMBINE_PROMPTS: 'generate_after_combine_prompts', | 496 | GENERATE_AFTER_COMBINE_PROMPTS: 'generate_after_combine_prompts', |
| 495 | GENERATE_AFTER_DATA: 'generate_after_data', | 497 | GENERATE_AFTER_DATA: 'generate_after_data', |
| 496 | GROUP_MEMBER_DRAFTED: 'group_member_drafted', | 498 | GROUP_MEMBER_DRAFTED: 'group_member_drafted', |
| 499 | GROUP_WRAPPER_STARTED: 'group_wrapper_started', | ||
| 500 | GROUP_WRAPPER_FINISHED: 'group_wrapper_finished', | ||
| 497 | WORLD_INFO_ACTIVATED: 'world_info_activated', | 501 | WORLD_INFO_ACTIVATED: 'world_info_activated', |
| 498 | TEXT_COMPLETION_SETTINGS_READY: 'text_completion_settings_ready', | 502 | TEXT_COMPLETION_SETTINGS_READY: 'text_completion_settings_ready', |
| 499 | CHAT_COMPLETION_SETTINGS_READY: 'chat_completion_settings_ready', | 503 | CHAT_COMPLETION_SETTINGS_READY: 'chat_completion_settings_ready', |
| @@ -514,6 +518,9 @@ export const event_types = { | |||
| 514 | ONLINE_STATUS_CHANGED: 'online_status_changed', | 518 | ONLINE_STATUS_CHANGED: 'online_status_changed', |
| 515 | IMAGE_SWIPED: 'image_swiped', | 519 | IMAGE_SWIPED: 'image_swiped', |
| 516 | CONNECTION_PROFILE_LOADED: 'connection_profile_loaded', | 520 | CONNECTION_PROFILE_LOADED: 'connection_profile_loaded', |
| 521 | CONNECTION_PROFILE_CREATED: 'connection_profile_created', | ||
| 522 | CONNECTION_PROFILE_DELETED: 'connection_profile_deleted', | ||
| 523 | CONNECTION_PROFILE_UPDATED: 'connection_profile_updated', | ||
| 517 | TOOL_CALLS_PERFORMED: 'tool_calls_performed', | 524 | TOOL_CALLS_PERFORMED: 'tool_calls_performed', |
| 518 | TOOL_CALLS_RENDERED: 'tool_calls_rendered', | 525 | TOOL_CALLS_RENDERED: 'tool_calls_rendered', |
| 519 | }; | 526 | }; |
| @@ -589,7 +596,7 @@ let is_delete_mode = false; | |||
| 589 | let fav_ch_checked = false; | 596 | let fav_ch_checked = false; |
| 590 | let scrollLock = false; | 597 | let scrollLock = false; |
| 591 | export let abortStatusCheck = new AbortController(); | 598 | export let abortStatusCheck = new AbortController(); |
| 592 | let charDragDropHandler = null; | 599 | export let charDragDropHandler = null; |
| 593 | 600 | ||
| 594 | /** @type {debounce_timeout} The debounce timeout used for chat/settings save. debounce_timeout.long: 1.000 ms */ | 601 | /** @type {debounce_timeout} The debounce timeout used for chat/settings save. debounce_timeout.long: 1.000 ms */ |
| 595 | export const DEFAULT_SAVE_EDIT_TIMEOUT = debounce_timeout.relaxed; | 602 | export const DEFAULT_SAVE_EDIT_TIMEOUT = debounce_timeout.relaxed; |
| @@ -644,7 +651,7 @@ export const extension_prompt_roles = { | |||
| 644 | ASSISTANT: 2, | 651 | ASSISTANT: 2, |
| 645 | }; | 652 | }; |
| 646 | 653 | ||
| 647 | export const MAX_INJECTION_DEPTH = 1000; | 654 | export const MAX_INJECTION_DEPTH = 10000; |
| 648 | 655 | ||
| 649 | const SAFETY_CHAT = [ | 656 | const SAFETY_CHAT = [ |
| 650 | { | 657 | { |
| @@ -1140,7 +1147,7 @@ export async function clearItemizedPrompts() { | |||
| 1140 | async function getStatusHorde() { | 1147 | async function getStatusHorde() { |
| 1141 | try { | 1148 | try { |
| 1142 | const hordeStatus = await checkHordeStatus(); | 1149 | const hordeStatus = await checkHordeStatus(); |
| 1143 | setOnlineStatus(hordeStatus ? 'Connected' : 'no_connection'); | 1150 | setOnlineStatus(hordeStatus ? t`Connected` : 'no_connection'); |
| 1144 | } | 1151 | } |
| 1145 | catch { | 1152 | catch { |
| 1146 | setOnlineStatus('no_connection'); | 1153 | setOnlineStatus('no_connection'); |
| @@ -1207,7 +1214,7 @@ async function getStatusTextgen() { | |||
| 1207 | } | 1214 | } |
| 1208 | 1215 | ||
| 1209 | if ([textgen_types.GENERIC, textgen_types.OOBA].includes(textgen_settings.type) && textgen_settings.bypass_status_check) { | 1216 | if ([textgen_types.GENERIC, textgen_types.OOBA].includes(textgen_settings.type) && textgen_settings.bypass_status_check) { |
| 1210 | setOnlineStatus('Status check bypassed'); | 1217 | setOnlineStatus(t`Status check bypassed`); |
| 1211 | return resultCheckStatus(); | 1218 | return resultCheckStatus(); |
| 1212 | } | 1219 | } |
| 1213 | 1220 | ||
| @@ -1232,7 +1239,7 @@ async function getStatusTextgen() { | |||
| 1232 | setOnlineStatus(textgen_settings.togetherai_model); | 1239 | setOnlineStatus(textgen_settings.togetherai_model); |
| 1233 | } else if (textgen_settings.type === textgen_types.OLLAMA) { | 1240 | } else if (textgen_settings.type === textgen_types.OLLAMA) { |
| 1234 | loadOllamaModels(data?.data); | 1241 | loadOllamaModels(data?.data); |
| 1235 | setOnlineStatus(textgen_settings.ollama_model || 'Connected'); | 1242 | setOnlineStatus(textgen_settings.ollama_model || t`Connected`); |
| 1236 | } else if (textgen_settings.type === textgen_types.INFERMATICAI) { | 1243 | } else if (textgen_settings.type === textgen_types.INFERMATICAI) { |
| 1237 | loadInfermaticAIModels(data?.data); | 1244 | loadInfermaticAIModels(data?.data); |
| 1238 | setOnlineStatus(textgen_settings.infermaticai_model); | 1245 | setOnlineStatus(textgen_settings.infermaticai_model); |
| @@ -1256,7 +1263,7 @@ async function getStatusTextgen() { | |||
| 1256 | setOnlineStatus(textgen_settings.tabby_model || data?.result); | 1263 | setOnlineStatus(textgen_settings.tabby_model || data?.result); |
| 1257 | } else if (textgen_settings.type === textgen_types.GENERIC) { | 1264 | } else if (textgen_settings.type === textgen_types.GENERIC) { |
| 1258 | loadGenericModels(data?.data); | 1265 | loadGenericModels(data?.data); |
| 1259 | setOnlineStatus(textgen_settings.generic_model || data?.result || 'Connected'); | 1266 | setOnlineStatus(textgen_settings.generic_model || data?.result || t`Connected`); |
| 1260 | } else { | 1267 | } else { |
| 1261 | setOnlineStatus(data?.result); | 1268 | setOnlineStatus(data?.result); |
| 1262 | } | 1269 | } |
| @@ -1370,8 +1377,11 @@ export function resultCheckStatus() { | |||
| 1370 | * If the character ID doesn't exist, if the chat is being saved, or if a group is being generated, this function does nothing. | 1377 | * If the character ID doesn't exist, if the chat is being saved, or if a group is being generated, this function does nothing. |
| 1371 | * If the character is different from the currently selected one, it will clear the chat and reset any selected character or group. | 1378 | * If the character is different from the currently selected one, it will clear the chat and reset any selected character or group. |
| 1372 | * @param {number} id The ID of the character to switch to. | 1379 | * @param {number} id The ID of the character to switch to. |
| 1380 | * @param {object} [options] Options for the switch. | ||
| 1381 | * @param {boolean} [options.switchMenu=true] Whether to switch the right menu to the character edit menu if the character is already selected. | ||
| 1382 | * @returns {Promise<void>} A promise that resolves when the character is switched. | ||
| 1373 | */ | 1383 | */ |
| 1374 | export async function selectCharacterById(id) { | 1384 | export async function selectCharacterById(id, { switchMenu = true } = {}) { |
| 1375 | if (characters[id] === undefined) { | 1385 | if (characters[id] === undefined) { |
| 1376 | return; | 1386 | return; |
| 1377 | } | 1387 | } |
| @@ -1400,9 +1410,9 @@ export async function selectCharacterById(id) { | |||
| 1400 | } | 1410 | } |
| 1401 | } else { | 1411 | } else { |
| 1402 | //if clicked on character that was already selected | 1412 | //if clicked on character that was already selected |
| 1403 | selected_button = 'character_edit'; | 1413 | switchMenu && (selected_button = 'character_edit'); |
| 1404 | await unshallowCharacter(this_chid); | 1414 | await unshallowCharacter(this_chid); |
| 1405 | select_selected_character(this_chid); | 1415 | select_selected_character(this_chid, { switchMenu }); |
| 1406 | } | 1416 | } |
| 1407 | } | 1417 | } |
| 1408 | 1418 | ||
| @@ -1787,6 +1797,7 @@ export async function getCharacters() { | |||
| 1787 | body: JSON.stringify({}), | 1797 | body: JSON.stringify({}), |
| 1788 | }); | 1798 | }); |
| 1789 | if (response.ok === true) { | 1799 | if (response.ok === true) { |
| 1800 | const previousAvatar = this_chid !== undefined ? characters[this_chid]?.avatar : null; | ||
| 1790 | characters.splice(0, characters.length); | 1801 | characters.splice(0, characters.length); |
| 1791 | const getData = await response.json(); | 1802 | const getData = await response.json(); |
| 1792 | for (let i = 0; i < getData.length; i++) { | 1803 | for (let i = 0; i < getData.length; i++) { |
| @@ -1800,8 +1811,16 @@ export async function getCharacters() { | |||
| 1800 | 1811 | ||
| 1801 | characters[i]['chat'] = String(characters[i]['chat']); | 1812 | characters[i]['chat'] = String(characters[i]['chat']); |
| 1802 | } | 1813 | } |
| 1803 | if (this_chid !== undefined) { | 1814 | |
| 1804 | $('#avatar_url_pole').val(characters[this_chid].avatar); | 1815 | if (previousAvatar) { |
| 1816 | const newCharacterId = characters.findIndex(x => x.avatar === previousAvatar); | ||
| 1817 | if (newCharacterId >= 0) { | ||
| 1818 | setCharacterId(newCharacterId); | ||
| 1819 | await selectCharacterById(newCharacterId, { switchMenu: false }); | ||
| 1820 | } else { | ||
| 1821 | await Popup.show.text(t`ERROR: The active character is no longer available.`, t`The page will be refreshed to prevent data loss. Press "OK" to continue.`); | ||
| 1822 | return location.reload(); | ||
| 1823 | } | ||
| 1805 | } | 1824 | } |
| 1806 | 1825 | ||
| 1807 | await getGroups(); | 1826 | await getGroups(); |
| @@ -2051,8 +2070,9 @@ export function messageFormatting(mes, ch_name, isSystem, isUser, messageId, san | |||
| 2051 | } | 2070 | } |
| 2052 | 2071 | ||
| 2053 | // Prompt bias replacement should be applied on the raw message | 2072 | // Prompt bias replacement should be applied on the raw message |
| 2054 | if (!power_user.show_user_prompt_bias && ch_name && !isUser && !isSystem) { | 2073 | const replacedPromptBias = power_user.user_prompt_bias && substituteParams(power_user.user_prompt_bias); |
| 2055 | mes = mes.replaceAll(substituteParams(power_user.user_prompt_bias), ''); | 2074 | if (!power_user.show_user_prompt_bias && ch_name && !isUser && !isSystem && replacedPromptBias && mes.startsWith(replacedPromptBias)) { |
| 2075 | mes = mes.slice(replacedPromptBias.length); | ||
| 2056 | } | 2076 | } |
| 2057 | 2077 | ||
| 2058 | if (!isSystem) { | 2078 | if (!isSystem) { |
| @@ -2114,7 +2134,7 @@ export function messageFormatting(mes, ch_name, isSystem, isUser, messageId, san | |||
| 2114 | } | 2134 | } |
| 2115 | 2135 | ||
| 2116 | mes = mes.replace( | 2136 | mes = mes.replace( |
| 2117 | /```[\s\S]*?```|``[\s\S]*?``|`[\s\S]*?`|(".*?")|(\u201C.*?\u201D)|(\u00AB.*?\u00BB)|(\u300C.*?\u300D)|(\u300E.*?\u300F)|(\uFF02.*?\uFF02)/gm, | 2137 | /<style>[\s\S]*?<\/style>|```[\s\S]*?```|~~~[\s\S]*?~~~|``[\s\S]*?``|`[\s\S]*?`|(".*?")|(\u201C.*?\u201D)|(\u00AB.*?\u00BB)|(\u300C.*?\u300D)|(\u300E.*?\u300F)|(\uFF02.*?\uFF02)/gim, |
| 2118 | function (match, p1, p2, p3, p4, p5, p6) { | 2138 | function (match, p1, p2, p3, p4, p5, p6) { |
| 2119 | if (p1) { | 2139 | if (p1) { |
| 2120 | // English double quotes | 2140 | // English double quotes |
| @@ -2730,6 +2750,7 @@ export function substituteParams(content, _name1, _name2, _original, _group, _re | |||
| 2730 | environment.mesExamplesRaw = fields.mesExamples || ''; | 2750 | environment.mesExamplesRaw = fields.mesExamples || ''; |
| 2731 | environment.charVersion = fields.version || ''; | 2751 | environment.charVersion = fields.version || ''; |
| 2732 | environment.char_version = fields.version || ''; | 2752 | environment.char_version = fields.version || ''; |
| 2753 | environment.charDepthPrompt = fields.charDepthPrompt || ''; | ||
| 2733 | } | 2754 | } |
| 2734 | 2755 | ||
| 2735 | // Must be substituted last so that they're replaced inside {{description}} | 2756 | // Must be substituted last so that they're replaced inside {{description}} |
| @@ -3026,6 +3047,20 @@ export async function getExtensionPromptByName(moduleName) { | |||
| 3026 | } | 3047 | } |
| 3027 | 3048 | ||
| 3028 | /** | 3049 | /** |
| 3050 | * Gets the maximum depth of extension prompts. | ||
| 3051 | * @returns {number} Maximum depth of extension prompts | ||
| 3052 | */ | ||
| 3053 | export function getExtensionPromptMaxDepth() { | ||
| 3054 | return MAX_INJECTION_DEPTH; | ||
| 3055 | /* | ||
| 3056 | const prompts = Object.values(extension_prompts); | ||
| 3057 | const maxDepth = Math.max(...prompts.map(x => x.depth ?? 0)); | ||
| 3058 | // Clamp to 1 <= depth <= MAX_INJECTION_DEPTH | ||
| 3059 | return Math.max(Math.min(maxDepth, MAX_INJECTION_DEPTH), 1); | ||
| 3060 | */ | ||
| 3061 | } | ||
| 3062 | |||
| 3063 | /** | ||
| 3029 | * Returns the extension prompt for the given position, depth, and role. | 3064 | * Returns the extension prompt for the given position, depth, and role. |
| 3030 | * If multiple prompts are found, they are joined with a separator. | 3065 | * If multiple prompts are found, they are joined with a separator. |
| 3031 | * @param {number} [position] Position of the prompt | 3066 | * @param {number} [position] Position of the prompt |
| @@ -3081,13 +3116,38 @@ export function baseChatReplace(value, name1, name2) { | |||
| 3081 | 3116 | ||
| 3082 | /** | 3117 | /** |
| 3083 | * Returns the character card fields for the current character. | 3118 | * Returns the character card fields for the current character. |
| 3084 | * @returns {{system: string, mesExamples: string, description: string, personality: string, persona: string, scenario: string, jailbreak: string, version: string}} | 3119 | * @param {object} [options] |
| 3120 | * @param {number} [options.chid] Optional character index | ||
| 3121 | * | ||
| 3122 | * @typedef {object} CharacterCardFields | ||
| 3123 | * @property {string} system System prompt | ||
| 3124 | * @property {string} mesExamples Message examples | ||
| 3125 | * @property {string} description Description | ||
| 3126 | * @property {string} personality Personality | ||
| 3127 | * @property {string} persona Persona | ||
| 3128 | * @property {string} scenario Scenario | ||
| 3129 | * @property {string} jailbreak Jailbreak instructions | ||
| 3130 | * @property {string} version Character version | ||
| 3131 | * @property {string} charDepthPrompt Character depth note | ||
| 3132 | * @returns {CharacterCardFields} Character card fields | ||
| 3085 | */ | 3133 | */ |
| 3086 | export function getCharacterCardFields() { | 3134 | export function getCharacterCardFields({ chid = null } = {}) { |
| 3087 | const result = { system: '', mesExamples: '', description: '', personality: '', persona: '', scenario: '', jailbreak: '', version: '' }; | 3135 | const currentChid = chid ?? this_chid; |
| 3136 | |||
| 3137 | const result = { | ||
| 3138 | system: '', | ||
| 3139 | mesExamples: '', | ||
| 3140 | description: '', | ||
| 3141 | personality: '', | ||
| 3142 | persona: '', | ||
| 3143 | scenario: '', | ||
| 3144 | jailbreak: '', | ||
| 3145 | version: '', | ||
| 3146 | charDepthPrompt: '', | ||
| 3147 | }; | ||
| 3088 | result.persona = baseChatReplace(power_user.persona_description?.trim(), name1, name2); | 3148 | result.persona = baseChatReplace(power_user.persona_description?.trim(), name1, name2); |
| 3089 | 3149 | ||
| 3090 | const character = characters[this_chid]; | 3150 | const character = characters[currentChid]; |
| 3091 | 3151 | ||
| 3092 | if (!character) { | 3152 | if (!character) { |
| 3093 | return result; | 3153 | return result; |
| @@ -3101,9 +3161,10 @@ export function getCharacterCardFields() { | |||
| 3101 | result.system = power_user.prefer_character_prompt ? baseChatReplace(character.data?.system_prompt?.trim(), name1, name2) : ''; | 3161 | result.system = power_user.prefer_character_prompt ? baseChatReplace(character.data?.system_prompt?.trim(), name1, name2) : ''; |
| 3102 | result.jailbreak = power_user.prefer_character_jailbreak ? baseChatReplace(character.data?.post_history_instructions?.trim(), name1, name2) : ''; | 3162 | result.jailbreak = power_user.prefer_character_jailbreak ? baseChatReplace(character.data?.post_history_instructions?.trim(), name1, name2) : ''; |
| 3103 | result.version = character.data?.character_version ?? ''; | 3163 | result.version = character.data?.character_version ?? ''; |
| 3164 | result.charDepthPrompt = baseChatReplace(character.data?.extensions?.depth_prompt?.prompt?.trim(), name1, name2); | ||
| 3104 | 3165 | ||
| 3105 | if (selected_group) { | 3166 | if (selected_group) { |
| 3106 | const groupCards = getGroupCharacterCards(selected_group, Number(this_chid)); | 3167 | const groupCards = getGroupCharacterCards(selected_group, Number(currentChid)); |
| 3107 | 3168 | ||
| 3108 | if (groupCards) { | 3169 | if (groupCards) { |
| 3109 | result.description = groupCards.description; | 3170 | result.description = groupCards.description; |
| @@ -3269,13 +3330,25 @@ class StreamingProcessor { | |||
| 3269 | 3330 | ||
| 3270 | if (!isImpersonate && !isContinue && Array.isArray(this.swipes) && this.swipes.length > 0) { | 3331 | if (!isImpersonate && !isContinue && Array.isArray(this.swipes) && this.swipes.length > 0) { |
| 3271 | for (let i = 0; i < this.swipes.length; i++) { | 3332 | for (let i = 0; i < this.swipes.length; i++) { |
| 3272 | this.swipes[i] = cleanUpMessage(this.swipes[i], false, false, true, this.stoppingStrings); | 3333 | this.swipes[i] = cleanUpMessage({ |
| 3334 | getMessage: this.swipes[i], | ||
| 3335 | isImpersonate: false, | ||
| 3336 | isContinue: false, | ||
| 3337 | displayIncompleteSentences: true, | ||
| 3338 | stoppingStrings: this.stoppingStrings, | ||
| 3339 | }); | ||
| 3273 | } | 3340 | } |
| 3274 | } | 3341 | } |
| 3275 | 3342 | ||
| 3276 | let processedText = cleanUpMessage(text, isImpersonate, isContinue, !isFinal, this.stoppingStrings); | 3343 | let processedText = cleanUpMessage({ |
| 3344 | getMessage: text, | ||
| 3345 | isImpersonate: isImpersonate, | ||
| 3346 | isContinue: isContinue, | ||
| 3347 | displayIncompleteSentences: !isFinal, | ||
| 3348 | stoppingStrings: this.stoppingStrings, | ||
| 3349 | }); | ||
| 3277 | 3350 | ||
| 3278 | const charsToBalance = ['*', '"', '```']; | 3351 | const charsToBalance = ['*', '"', '```', '~~~']; |
| 3279 | for (const char of charsToBalance) { | 3352 | for (const char of charsToBalance) { |
| 3280 | if (!isFinal && isOdd(countOccurrences(processedText, char))) { | 3353 | if (!isFinal && isOdd(countOccurrences(processedText, char))) { |
| 3281 | const separator = char.length > 1 ? '\n' : ''; | 3354 | const separator = char.length > 1 ? '\n' : ''; |
| @@ -3505,9 +3578,10 @@ class StreamingProcessor { | |||
| 3505 | * @param {boolean} quietToLoud true to generate a message in system mode, false to generate a message in character mode | 3578 | * @param {boolean} quietToLoud true to generate a message in system mode, false to generate a message in character mode |
| 3506 | * @param {string} [systemPrompt] System prompt to use. Only Instruct mode or OpenAI. | 3579 | * @param {string} [systemPrompt] System prompt to use. Only Instruct mode or OpenAI. |
| 3507 | * @param {number} [responseLength] Maximum response length. If unset, the global default value is used. | 3580 | * @param {number} [responseLength] Maximum response length. If unset, the global default value is used. |
| 3581 | * @param {boolean} [trimNames] Whether to allow trimming "{{user}}:" and "{{char}}:" from the response. | ||
| 3508 | * @returns {Promise<string>} Generated message | 3582 | * @returns {Promise<string>} Generated message |
| 3509 | */ | 3583 | */ |
| 3510 | export async function generateRaw(prompt, api, instructOverride, quietToLoud, systemPrompt, responseLength) { | 3584 | export async function generateRaw(prompt, api, instructOverride, quietToLoud, systemPrompt, responseLength, trimNames = true) { |
| 3511 | if (!api) { | 3585 | if (!api) { |
| 3512 | api = main_api; | 3586 | api = main_api; |
| 3513 | } | 3587 | } |
| @@ -3596,7 +3670,16 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy | |||
| 3596 | throw new Error(data.response); | 3670 | throw new Error(data.response); |
| 3597 | } | 3671 | } |
| 3598 | 3672 | ||
| 3599 | const message = cleanUpMessage(extractMessageFromData(data), false, false, true); | 3673 | // format result, exclude user prompt bias |
| 3674 | const message = cleanUpMessage({ | ||
| 3675 | getMessage: extractMessageFromData(data), | ||
| 3676 | isImpersonate: false, | ||
| 3677 | isContinue: false, | ||
| 3678 | displayIncompleteSentences: true, | ||
| 3679 | includeUserPromptBias: false, | ||
| 3680 | trimNames: trimNames, | ||
| 3681 | trimWrongNames: trimNames, | ||
| 3682 | }); | ||
| 3600 | 3683 | ||
| 3601 | if (!message) { | 3684 | if (!message) { |
| 3602 | throw new Error('No message generated'); | 3685 | throw new Error('No message generated'); |
| @@ -3905,6 +3988,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 3905 | mesExamples, | 3988 | mesExamples, |
| 3906 | system, | 3989 | system, |
| 3907 | jailbreak, | 3990 | jailbreak, |
| 3991 | charDepthPrompt, | ||
| 3908 | } = getCharacterCardFields(); | 3992 | } = getCharacterCardFields(); |
| 3909 | 3993 | ||
| 3910 | if (main_api !== 'openai') { | 3994 | if (main_api !== 'openai') { |
| @@ -3927,7 +4011,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 3927 | setExtensionPrompt('DEPTH_PROMPT_' + index, value.text, extension_prompt_types.IN_CHAT, value.depth, extension_settings.note.allowWIScan, role); | 4011 | setExtensionPrompt('DEPTH_PROMPT_' + index, value.text, extension_prompt_types.IN_CHAT, value.depth, extension_settings.note.allowWIScan, role); |
| 3928 | }); | 4012 | }); |
| 3929 | } else { | 4013 | } else { |
| 3930 | const depthPromptText = baseChatReplace(characters[this_chid]?.data?.extensions?.depth_prompt?.prompt?.trim(), name1, name2) || ''; | 4014 | const depthPromptText = charDepthPrompt || ''; |
| 3931 | const depthPromptDepth = characters[this_chid]?.data?.extensions?.depth_prompt?.depth ?? depth_prompt_depth_default; | 4015 | const depthPromptDepth = characters[this_chid]?.data?.extensions?.depth_prompt?.depth ?? depth_prompt_depth_default; |
| 3932 | const depthPromptRole = getExtensionPromptRoleByName(characters[this_chid]?.data?.extensions?.depth_prompt?.role ?? depth_prompt_role_default); | 4016 | const depthPromptRole = getExtensionPromptRoleByName(characters[this_chid]?.data?.extensions?.depth_prompt?.role ?? depth_prompt_role_default); |
| 3933 | setExtensionPrompt('DEPTH_PROMPT', depthPromptText, extension_prompt_types.IN_CHAT, depthPromptDepth, extension_settings.note.allowWIScan, depthPromptRole); | 4017 | setExtensionPrompt('DEPTH_PROMPT', depthPromptText, extension_prompt_types.IN_CHAT, depthPromptDepth, extension_settings.note.allowWIScan, depthPromptRole); |
| @@ -4796,7 +4880,12 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4796 | 4880 | ||
| 4797 | hideSwipeButtons(); | 4881 | hideSwipeButtons(); |
| 4798 | let getMessage = await streamingProcessor.generate(); | 4882 | let getMessage = await streamingProcessor.generate(); |
| 4799 | let messageChunk = cleanUpMessage(getMessage, isImpersonate, isContinue, false); | 4883 | let messageChunk = cleanUpMessage({ |
| 4884 | getMessage: getMessage, | ||
| 4885 | isImpersonate: isImpersonate, | ||
| 4886 | isContinue: isContinue, | ||
| 4887 | displayIncompleteSentences: false, | ||
| 4888 | }); | ||
| 4800 | 4889 | ||
| 4801 | if (isContinue) { | 4890 | if (isContinue) { |
| 4802 | getMessage = continue_mag + getMessage; | 4891 | getMessage = continue_mag + getMessage; |
| @@ -4880,7 +4969,14 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4880 | 4969 | ||
| 4881 | const swipes = extractMultiSwipes(data, type); | 4970 | const swipes = extractMultiSwipes(data, type); |
| 4882 | 4971 | ||
| 4883 | messageChunk = cleanUpMessage(getMessage, isImpersonate, isContinue, false); | 4972 | messageChunk = cleanUpMessage({ |
| 4973 | getMessage: getMessage, | ||
| 4974 | isImpersonate: isImpersonate, | ||
| 4975 | isContinue: isContinue, | ||
| 4976 | displayIncompleteSentences: false, | ||
| 4977 | }); | ||
| 4978 | |||
| 4979 | |||
| 4884 | reasoning = getRegexedString(reasoning, regex_placement.REASONING); | 4980 | reasoning = getRegexedString(reasoning, regex_placement.REASONING); |
| 4885 | 4981 | ||
| 4886 | if (power_user.trim_spaces) { | 4982 | if (power_user.trim_spaces) { |
| @@ -4894,7 +4990,12 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4894 | 4990 | ||
| 4895 | //Formating | 4991 | //Formating |
| 4896 | const displayIncomplete = type === 'quiet' && !quietToLoud; | 4992 | const displayIncomplete = type === 'quiet' && !quietToLoud; |
| 4897 | getMessage = cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncomplete); | 4993 | getMessage = cleanUpMessage({ |
| 4994 | getMessage: getMessage, | ||
| 4995 | isImpersonate: isImpersonate, | ||
| 4996 | isContinue: isContinue, | ||
| 4997 | displayIncompleteSentences: displayIncomplete, | ||
| 4998 | }); | ||
| 4898 | 4999 | ||
| 4899 | if (isImpersonate) { | 5000 | if (isImpersonate) { |
| 4900 | $('#send_textarea').val(getMessage)[0].dispatchEvent(new Event('input', { bubbles: true })); | 5001 | $('#send_textarea').val(getMessage)[0].dispatchEvent(new Event('input', { bubbles: true })); |
| @@ -5012,7 +5113,8 @@ async function doChatInject(messages, isContinue) { | |||
| 5012 | let totalInsertedMessages = 0; | 5113 | let totalInsertedMessages = 0; |
| 5013 | messages.reverse(); | 5114 | messages.reverse(); |
| 5014 | 5115 | ||
| 5015 | for (let i = 0; i <= MAX_INJECTION_DEPTH; i++) { | 5116 | const maxDepth = getExtensionPromptMaxDepth(); |
| 5117 | for (let i = 0; i <= maxDepth; i++) { | ||
| 5016 | // Order of priority (most important go lower) | 5118 | // Order of priority (most important go lower) |
| 5017 | const roles = [extension_prompt_roles.SYSTEM, extension_prompt_roles.USER, extension_prompt_roles.ASSISTANT]; | 5119 | const roles = [extension_prompt_roles.SYSTEM, extension_prompt_roles.USER, extension_prompt_roles.ASSISTANT]; |
| 5018 | const names = { | 5120 | const names = { |
| @@ -5215,6 +5317,12 @@ function formatMessageHistoryItem(chatItem, isInstruct, forceOutputSequence) { | |||
| 5215 | const itemName = chatItem.is_user ? chatItem['name'] : characterName; | 5317 | const itemName = chatItem.is_user ? chatItem['name'] : characterName; |
| 5216 | const shouldPrependName = !isNarratorType; | 5318 | const shouldPrependName = !isNarratorType; |
| 5217 | 5319 | ||
| 5320 | // If this symbol flag is set, completely ignore the message. | ||
| 5321 | // This can be used to hide messages without affecting the number of messages in the chat. | ||
| 5322 | if (chatItem.extra?.[IGNORE_SYMBOL]) { | ||
| 5323 | return ''; | ||
| 5324 | } | ||
| 5325 | |||
| 5218 | // Don't include a name if it's empty | 5326 | // Don't include a name if it's empty |
| 5219 | let textResult = chatItem?.name && shouldPrependName ? `${itemName}: ${chatItem.mes}\n` : `${chatItem.mes}\n`; | 5327 | let textResult = chatItem?.name && shouldPrependName ? `${itemName}: ${chatItem.mes}\n` : `${chatItem.mes}\n`; |
| 5220 | 5328 | ||
| @@ -5860,7 +5968,13 @@ function extractMultiSwipes(data, type) { | |||
| 5860 | 5968 | ||
| 5861 | for (let i = 1; i < data.choices.length; i++) { | 5969 | for (let i = 1; i < data.choices.length; i++) { |
| 5862 | const text = data?.choices[i]?.message?.content ?? data?.choices[i]?.text ?? ''; | 5970 | const text = data?.choices[i]?.message?.content ?? data?.choices[i]?.text ?? ''; |
| 5863 | const cleanedText = cleanUpMessage(text, false, false, false); | 5971 | const cleanedText = cleanUpMessage({ |
| 5972 | getMessage: text, | ||
| 5973 | isImpersonate: false, | ||
| 5974 | isContinue: false, | ||
| 5975 | displayIncompleteSentences: false, | ||
| 5976 | }); | ||
| 5977 | |||
| 5864 | swipes.push(cleanedText); | 5978 | swipes.push(cleanedText); |
| 5865 | } | 5979 | } |
| 5866 | } | 5980 | } |
| @@ -5868,13 +5982,33 @@ function extractMultiSwipes(data, type) { | |||
| 5868 | return swipes; | 5982 | return swipes; |
| 5869 | } | 5983 | } |
| 5870 | 5984 | ||
| 5871 | export function cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncompleteSentences = false, stoppingStrings = null) { | 5985 | /** |
| 5986 | * Formats a message according to user settings | ||
| 5987 | * @param {object} [options] - Additional options. | ||
| 5988 | * @param {string} [options.getMessage] The message to clean up | ||
| 5989 | * @param {boolean} [options.isImpersonate] Whether this is an impersonated message | ||
| 5990 | * @param {boolean} [options.isContinue] Whether this is a continued message | ||
| 5991 | * @param {boolean} [options.displayIncompleteSentences] Whether to keep incomplete sentences at the end. | ||
| 5992 | * @param {array} [options.stoppingStrings] Array of stopping strings. | ||
| 5993 | * @param {boolean} [options.includeUserPromptBias] Whether to permit prepending the user prompt bias at the beginning. | ||
| 5994 | * @param {boolean} [options.trimNames] Whether to allow trimming "{{char}}:" or "{{user}}:" from the beginning. | ||
| 5995 | * @param {boolean} [options.trimWrongNames] Whether to allow deleting responses prefixed by the incorrect name, depending on isImpersonate | ||
| 5996 | * | ||
| 5997 | * @returns {string} The formatted message | ||
| 5998 | */ | ||
| 5999 | export function cleanUpMessage({ getMessage, isImpersonate, isContinue, displayIncompleteSentences = false, stoppingStrings = null, includeUserPromptBias = true, trimNames = true, trimWrongNames = true } = {}) { | ||
| 6000 | if (arguments.length > 0 && typeof arguments[0] !== 'object') { | ||
| 6001 | console.trace('cleanUpMessage called with positional arguments. Please use an object instead.'); | ||
| 6002 | [getMessage, isImpersonate, isContinue, displayIncompleteSentences, stoppingStrings, includeUserPromptBias, trimNames, trimWrongNames] = arguments; | ||
| 6003 | } | ||
| 6004 | |||
| 5872 | if (!getMessage) { | 6005 | if (!getMessage) { |
| 5873 | return ''; | 6006 | return ''; |
| 5874 | } | 6007 | } |
| 5875 | 6008 | ||
| 5876 | // Add the prompt bias before anything else | 6009 | // Add the prompt bias before anything else |
| 5877 | if ( | 6010 | if ( |
| 6011 | includeUserPromptBias && | ||
| 5878 | power_user.user_prompt_bias && | 6012 | power_user.user_prompt_bias && |
| 5879 | !isImpersonate && | 6013 | !isImpersonate && |
| 5880 | !isContinue && | 6014 | !isContinue && |
| @@ -5912,21 +6046,32 @@ export function cleanUpMessage(getMessage, isImpersonate, isContinue, displayInc | |||
| 5912 | // "trailing whitespace on newlines\nevery line of the string\nsample text" | 6046 | // "trailing whitespace on newlines\nevery line of the string\nsample text" |
| 5913 | getMessage = getMessage.replace(/[^\S\r\n]+$/gm, ''); | 6047 | getMessage = getMessage.replace(/[^\S\r\n]+$/gm, ''); |
| 5914 | 6048 | ||
| 5915 | let nameToTrim = isImpersonate ? name2 : name1; | 6049 | if (trimWrongNames) { |
| 6050 | // If this is an impersonation, delete the entire response if it starts with "{{char}}:" | ||
| 6051 | // If this isn't an impersonation, delete the entire response if it starts with "{{user}}:" | ||
| 6052 | // Also delete any trailing text that starts with the wrong name. | ||
| 6053 | // This only occurs if the corresponding "power_user.allow_nameX_display" is false. | ||
| 5916 | 6054 | ||
| 5917 | if (isImpersonate) { | 6055 | let wrongName = isImpersonate |
| 5918 | nameToTrim = power_user.allow_name2_display ? '' : name2; | 6056 | ? (!power_user.allow_name2_display ? name2 : '') // char |
| 5919 | } | 6057 | : (!power_user.allow_name1_display ? name1 : ''); // user |
| 5920 | else { | ||
| 5921 | nameToTrim = power_user.allow_name1_display ? '' : name1; | ||
| 5922 | } | ||
| 5923 | 6058 | ||
| 5924 | if (nameToTrim && getMessage.indexOf(`${nameToTrim}:`) == 0) { | 6059 | if (wrongName) { |
| 5925 | getMessage = getMessage.substring(0, getMessage.indexOf(`${nameToTrim}:`)); | 6060 | // If the message starts with the wrong name, delete the entire response |
| 5926 | } | 6061 | let startIndex = getMessage.indexOf(`${wrongName}:`); |
| 5927 | if (nameToTrim && getMessage.indexOf(`\n${nameToTrim}:`) >= 0) { | 6062 | if (startIndex === 0) { |
| 5928 | getMessage = getMessage.substring(0, getMessage.indexOf(`\n${nameToTrim}:`)); | 6063 | getMessage = ''; |
| 6064 | console.debug(`Message started with the wrong name: "${wrongName}" - response was deleted.`); | ||
| 6065 | } | ||
| 6066 | |||
| 6067 | // If there is trailing text starting with the wrong name, trim it off. | ||
| 6068 | startIndex = getMessage.indexOf(`\n${wrongName}:`); | ||
| 6069 | if (startIndex >= 0) { | ||
| 6070 | getMessage = getMessage.substring(0, startIndex); | ||
| 6071 | } | ||
| 6072 | } | ||
| 5929 | } | 6073 | } |
| 6074 | |||
| 5930 | if (getMessage.indexOf('<|endoftext|>') != -1) { | 6075 | if (getMessage.indexOf('<|endoftext|>') != -1) { |
| 5931 | getMessage = getMessage.substring(0, getMessage.indexOf('<|endoftext|>')); | 6076 | getMessage = getMessage.substring(0, getMessage.indexOf('<|endoftext|>')); |
| 5932 | } | 6077 | } |
| @@ -5986,13 +6131,18 @@ export function cleanUpMessage(getMessage, isImpersonate, isContinue, displayInc | |||
| 5986 | getMessage = fixMarkdown(getMessage, false); | 6131 | getMessage = fixMarkdown(getMessage, false); |
| 5987 | } | 6132 | } |
| 5988 | 6133 | ||
| 5989 | const nameToTrim2 = isImpersonate | 6134 | if (trimNames) { |
| 5990 | ? (!power_user.allow_name1_display ? name1 : '') | 6135 | // If this is an impersonation, trim "{{user}}:" from the beginning |
| 5991 | : (!power_user.allow_name2_display ? name2 : ''); | 6136 | // If this isn't an impersonation, trim "{{char}}:" from the beginning. |
| 6137 | // Only applied when the corresponding "power_user.allow_nameX_display" is false. | ||
| 6138 | const nameToTrim2 = isImpersonate | ||
| 6139 | ? (!power_user.allow_name1_display ? name1 : '') // user | ||
| 6140 | : (!power_user.allow_name2_display ? name2 : ''); // char | ||
| 5992 | 6141 | ||
| 5993 | if (nameToTrim2 && getMessage.startsWith(nameToTrim2 + ':')) { | 6142 | if (nameToTrim2 && getMessage.startsWith(nameToTrim2 + ':')) { |
| 5994 | getMessage = getMessage.replace(nameToTrim2 + ':', ''); | 6143 | getMessage = getMessage.replace(nameToTrim2 + ':', ''); |
| 5995 | getMessage = getMessage.trimStart(); | 6144 | getMessage = getMessage.trimStart(); |
| 6145 | } | ||
| 5996 | } | 6146 | } |
| 5997 | 6147 | ||
| 5998 | if (isImpersonate) { | 6148 | if (isImpersonate) { |
| @@ -6588,6 +6738,8 @@ export async function renameCharacter(name = null, { silent = false, renameChats | |||
| 6588 | 6738 | ||
| 6589 | await eventSource.emit(event_types.CHARACTER_RENAMED, oldAvatar, newAvatar); | 6739 | await eventSource.emit(event_types.CHARACTER_RENAMED, oldAvatar, newAvatar); |
| 6590 | 6740 | ||
| 6741 | // Unload current character | ||
| 6742 | setCharacterId(undefined); | ||
| 6591 | // Reload characters list | 6743 | // Reload characters list |
| 6592 | await getCharacters(); | 6744 | await getCharacters(); |
| 6593 | 6745 | ||
| @@ -6596,7 +6748,6 @@ export async function renameCharacter(name = null, { silent = false, renameChats | |||
| 6596 | 6748 | ||
| 6597 | if (newChId !== -1) { | 6749 | if (newChId !== -1) { |
| 6598 | // Select the character after the renaming | 6750 | // Select the character after the renaming |
| 6599 | setCharacterId(undefined); | ||
| 6600 | await selectCharacterById(newChId); | 6751 | await selectCharacterById(newChId); |
| 6601 | 6752 | ||
| 6602 | // Async delay to update UI | 6753 | // Async delay to update UI |
| @@ -6729,7 +6880,22 @@ export function saveChatDebounced() { | |||
| 6729 | }, DEFAULT_SAVE_EDIT_TIMEOUT); | 6880 | }, DEFAULT_SAVE_EDIT_TIMEOUT); |
| 6730 | } | 6881 | } |
| 6731 | 6882 | ||
| 6732 | export async function saveChat(chatName, withMetadata, mesId) { | 6883 | /** |
| 6884 | * Saves the chat to the server. | ||
| 6885 | * @param {object} [options] - Additional options. | ||
| 6886 | * @param {string} [options.chatName] The name of the chat file to save to | ||
| 6887 | * @param {object} [options.withMetadata] Additional metadata to save with the chat | ||
| 6888 | * @param {number} [options.mesId] The message ID to save the chat up to | ||
| 6889 | * @param {boolean} [options.force] Force the saving despire the integrity check result | ||
| 6890 | * | ||
| 6891 | * @returns {Promise<void>} | ||
| 6892 | */ | ||
| 6893 | export async function saveChat({ chatName, withMetadata, mesId, force = false } = {}) { | ||
| 6894 | if (arguments.length > 0 && typeof arguments[0] !== 'object') { | ||
| 6895 | console.trace('saveChat called with positional arguments. Please use an object instead.'); | ||
| 6896 | [chatName, withMetadata, mesId, force] = arguments; | ||
| 6897 | } | ||
| 6898 | |||
| 6733 | const metadata = { ...chat_metadata, ...(withMetadata || {}) }; | 6899 | const metadata = { ...chat_metadata, ...(withMetadata || {}) }; |
| 6734 | const fileName = chatName ?? characters[this_chid]?.chat; | 6900 | const fileName = chatName ?? characters[this_chid]?.chat; |
| 6735 | 6901 | ||
| @@ -6749,53 +6915,59 @@ export async function saveChat(chatName, withMetadata, mesId) { | |||
| 6749 | toastr.error(t`Trying to save group chat with regular saveChat function. Aborting to prevent corruption.`); | 6915 | toastr.error(t`Trying to save group chat with regular saveChat function. Aborting to prevent corruption.`); |
| 6750 | throw new Error('Group chat saved from saveChat'); | 6916 | throw new Error('Group chat saved from saveChat'); |
| 6751 | } | 6917 | } |
| 6752 | /* | ||
| 6753 | if (item.is_user) { | ||
| 6754 | //var str = item.mes.replace(`${name1}:`, `${name1}:`); | ||
| 6755 | //chat[i].mes = str; | ||
| 6756 | //chat[i].name = name1; | ||
| 6757 | } else if (i !== chat.length - 1 && chat[i].swipe_id !== undefined) { | ||
| 6758 | // delete chat[i].swipes; | ||
| 6759 | // delete chat[i].swipe_id; | ||
| 6760 | } | ||
| 6761 | */ | ||
| 6762 | }); | 6918 | }); |
| 6763 | 6919 | ||
| 6764 | const trimmed_chat = (mesId !== undefined && mesId >= 0 && mesId < chat.length) | 6920 | const trimmedChat = (mesId !== undefined && mesId >= 0 && mesId < chat.length) |
| 6765 | ? chat.slice(0, parseInt(mesId) + 1) | 6921 | ? chat.slice(0, Number(mesId) + 1) |
| 6766 | : chat; | 6922 | : chat.slice(); |
| 6767 | 6923 | ||
| 6768 | var save_chat = [ | 6924 | const chatToSave = [ |
| 6769 | { | 6925 | { |
| 6770 | user_name: name1, | 6926 | user_name: name1, |
| 6771 | character_name: name2, | 6927 | character_name: name2, |
| 6772 | create_date: chat_create_date, | 6928 | create_date: chat_create_date, |
| 6773 | chat_metadata: metadata, | 6929 | chat_metadata: metadata, |
| 6774 | }, | 6930 | }, |
| 6775 | ...trimmed_chat, | 6931 | ...trimmedChat, |
| 6776 | ]; | 6932 | ]; |
| 6777 | return jQuery.ajax({ | ||
| 6778 | type: 'POST', | ||
| 6779 | url: '/api/chats/save', | ||
| 6780 | data: JSON.stringify({ | ||
| 6781 | ch_name: characters[this_chid].name, | ||
| 6782 | file_name: fileName, | ||
| 6783 | chat: save_chat, | ||
| 6784 | avatar_url: characters[this_chid].avatar, | ||
| 6785 | }), | ||
| 6786 | beforeSend: function () { | ||
| 6787 | 6933 | ||
| 6788 | }, | 6934 | try { |
| 6789 | cache: false, | 6935 | const result = await fetch('/api/chats/save', { |
| 6790 | dataType: 'json', | 6936 | method: 'POST', |
| 6791 | contentType: 'application/json', | 6937 | cache: 'no-cache', |
| 6792 | success: function (data) { }, | 6938 | headers: getRequestHeaders(), |
| 6793 | error: function (jqXHR, exception) { | 6939 | body: JSON.stringify({ |
| 6794 | toastr.error(t`Check the server connection and reload the page to prevent data loss.`, t`Chat could not be saved`); | 6940 | ch_name: characters[this_chid].name, |
| 6795 | console.log(exception); | 6941 | file_name: fileName, |
| 6796 | console.log(jqXHR); | 6942 | chat: chatToSave, |
| 6797 | }, | 6943 | avatar_url: characters[this_chid].avatar, |
| 6798 | }); | 6944 | force: force, |
| 6945 | }), | ||
| 6946 | }); | ||
| 6947 | |||
| 6948 | if (result.ok) { | ||
| 6949 | return; | ||
| 6950 | } | ||
| 6951 | |||
| 6952 | const errorData = await result.json(); | ||
| 6953 | const isIntegrityError = errorData?.error === 'integrity' && !force; | ||
| 6954 | if (!isIntegrityError) { | ||
| 6955 | throw new Error(result.statusText); | ||
| 6956 | } | ||
| 6957 | |||
| 6958 | const forceSaveConfirmed = await Popup.show.confirm( | ||
| 6959 | t`ERROR: Chat integrity check failed.`, | ||
| 6960 | t`Continuing the operation may result in data loss. Would you like to overwrite the chat file anyway? Pressing "NO" will cancel the save operation.`, | ||
| 6961 | { okButton: t`Yes, overwrite`, cancelButton: t`No, cancel` }, | ||
| 6962 | ) === POPUP_RESULT.AFFIRMATIVE; | ||
| 6963 | |||
| 6964 | if (forceSaveConfirmed) { | ||
| 6965 | await saveChat({ chatName, withMetadata, mesId, force: true }); | ||
| 6966 | } | ||
| 6967 | } catch (error) { | ||
| 6968 | console.error(error); | ||
| 6969 | toastr.error(t`Check the server connection and reload the page to prevent data loss.`, t`Chat could not be saved`); | ||
| 6970 | } | ||
| 6799 | } | 6971 | } |
| 6800 | 6972 | ||
| 6801 | async function read_avatar_load(input) { | 6973 | async function read_avatar_load(input) { |
| @@ -6972,6 +7144,9 @@ export async function getChat() { | |||
| 6972 | } else { | 7144 | } else { |
| 6973 | chat_create_date = humanizedDateTime(); | 7145 | chat_create_date = humanizedDateTime(); |
| 6974 | } | 7146 | } |
| 7147 | if (!chat_metadata['integrity']) { | ||
| 7148 | chat_metadata['integrity'] = uuidv4(); | ||
| 7149 | } | ||
| 6975 | await getChatResult(); | 7150 | await getChatResult(); |
| 6976 | eventSource.emit('chatLoaded', { detail: { id: this_chid, character: characters[this_chid] } }); | 7151 | eventSource.emit('chatLoaded', { detail: { id: this_chid, character: characters[this_chid] } }); |
| 6977 | 7152 | ||
| @@ -7943,14 +8118,19 @@ export function select_rm_info(type, charId, previousCharId = null) { | |||
| 7943 | } | 8118 | } |
| 7944 | } | 8119 | } |
| 7945 | 8120 | ||
| 7946 | export function select_selected_character(chid) { | 8121 | /** |
| 8122 | * Selects the right menu for displaying the character editor. | ||
| 8123 | * @param {number|string} chid Character array index | ||
| 8124 | * @param {object} [param1] Options for the switch | ||
| 8125 | * @param {boolean} [param1.switchMenu=true] Whether to switch the menu | ||
| 8126 | */ | ||
| 8127 | export function select_selected_character(chid, { switchMenu = true } = {}) { | ||
| 7947 | //character select | 8128 | //character select |
| 7948 | //console.log('select_selected_character() -- starting with input of -- ' + chid + ' (name:' + characters[chid].name + ')'); | 8129 | //console.log('select_selected_character() -- starting with input of -- ' + chid + ' (name:' + characters[chid].name + ')'); |
| 7949 | select_rm_create(); | 8130 | select_rm_create({ switchMenu }); |
| 7950 | setMenuType('character_edit'); | 8131 | switchMenu && setMenuType('character_edit'); |
| 7951 | $('#delete_button').css('display', 'flex'); | 8132 | $('#delete_button').css('display', 'flex'); |
| 7952 | $('#export_button').css('display', 'flex'); | 8133 | $('#export_button').css('display', 'flex'); |
| 7953 | var display_name = characters[chid].name; | ||
| 7954 | 8134 | ||
| 7955 | //create text poles | 8135 | //create text poles |
| 7956 | $('#rm_button_back').css('display', 'none'); | 8136 | $('#rm_button_back').css('display', 'none'); |
| @@ -7965,7 +8145,7 @@ export function select_selected_character(chid) { | |||
| 7965 | 8145 | ||
| 7966 | // Don't update the navbar name if we're peeking the group member defs | 8146 | // Don't update the navbar name if we're peeking the group member defs |
| 7967 | if (!selected_group) { | 8147 | if (!selected_group) { |
| 7968 | $('#rm_button_selected_ch').children('h2').text(display_name); | 8148 | $('#rm_button_selected_ch').children('h2').text(characters[chid].name); |
| 7969 | } | 8149 | } |
| 7970 | 8150 | ||
| 7971 | $('#add_avatar_button').val(''); | 8151 | $('#add_avatar_button').val(''); |
| @@ -7996,22 +8176,20 @@ export function select_selected_character(chid) { | |||
| 7996 | $('#chat_import_avatar_url').val(characters[chid].avatar); | 8176 | $('#chat_import_avatar_url').val(characters[chid].avatar); |
| 7997 | $('#chat_import_character_name').val(characters[chid].name); | 8177 | $('#chat_import_character_name').val(characters[chid].name); |
| 7998 | $('#character_json_data').val(characters[chid].json_data); | 8178 | $('#character_json_data').val(characters[chid].json_data); |
| 7999 | let this_avatar = default_avatar; | ||
| 8000 | if (characters[chid].avatar != 'none') { | ||
| 8001 | this_avatar = getThumbnailUrl('avatar', characters[chid].avatar); | ||
| 8002 | } | ||
| 8003 | 8179 | ||
| 8004 | updateFavButtonState(characters[chid].fav || characters[chid].fav == 'true'); | 8180 | updateFavButtonState(characters[chid].fav || characters[chid].fav == 'true'); |
| 8005 | 8181 | ||
| 8006 | $('#avatar_load_preview').attr('src', this_avatar); | 8182 | const avatarUrl = characters[chid].avatar != 'none' ? getThumbnailUrl('avatar', characters[chid].avatar) : default_avatar; |
| 8007 | $('#name_div').removeClass('displayBlock'); | 8183 | $('#avatar_load_preview').attr('src', avatarUrl); |
| 8008 | $('#name_div').addClass('displayNone'); | ||
| 8009 | $('#renameCharButton').css('display', ''); | ||
| 8010 | $('.open_alternate_greetings').data('chid', chid); | 8184 | $('.open_alternate_greetings').data('chid', chid); |
| 8011 | $('#set_character_world').data('chid', chid); | 8185 | $('#set_character_world').data('chid', chid); |
| 8012 | setWorldInfoButtonClass(chid); | 8186 | setWorldInfoButtonClass(chid); |
| 8013 | checkEmbeddedWorld(chid); | 8187 | checkEmbeddedWorld(chid); |
| 8014 | 8188 | ||
| 8189 | $('#name_div').removeClass('displayBlock'); | ||
| 8190 | $('#name_div').addClass('displayNone'); | ||
| 8191 | $('#renameCharButton').css('display', ''); | ||
| 8192 | |||
| 8015 | $('#form_create').attr('actiontype', 'editcharacter'); | 8193 | $('#form_create').attr('actiontype', 'editcharacter'); |
| 8016 | $('.form_create_bottom_buttons_block .chat_lorebook_button').show(); | 8194 | $('.form_create_bottom_buttons_block .chat_lorebook_button').show(); |
| 8017 | 8195 | ||
| @@ -8023,8 +8201,13 @@ export function select_selected_character(chid) { | |||
| 8023 | saveSettingsDebounced(); | 8201 | saveSettingsDebounced(); |
| 8024 | } | 8202 | } |
| 8025 | 8203 | ||
| 8026 | function select_rm_create() { | 8204 | /** |
| 8027 | setMenuType('create'); | 8205 | * Selects the right menu for creating a new character. |
| 8206 | * @param {object} [options] Options for the switch | ||
| 8207 | * @param {boolean} [options.switchMenu=true] Whether to switch the menu | ||
| 8208 | */ | ||
| 8209 | function select_rm_create({ switchMenu = true } = {}) { | ||
| 8210 | switchMenu && setMenuType('create'); | ||
| 8028 | 8211 | ||
| 8029 | //console.log('select_rm_Create() -- selected button: '+selected_button); | 8212 | //console.log('select_rm_Create() -- selected button: '+selected_button); |
| 8030 | if (selected_button == 'create') { | 8213 | if (selected_button == 'create') { |
| @@ -8034,7 +8217,7 @@ function select_rm_create() { | |||
| 8034 | } | 8217 | } |
| 8035 | } | 8218 | } |
| 8036 | 8219 | ||
| 8037 | selectRightMenuWithAnimation('rm_ch_create_block'); | 8220 | switchMenu && selectRightMenuWithAnimation('rm_ch_create_block'); |
| 8038 | 8221 | ||
| 8039 | $('#set_chat_scenario').hide(); | 8222 | $('#set_chat_scenario').hide(); |
| 8040 | $('#delete_button_div').css('display', 'none'); | 8223 | $('#delete_button_div').css('display', 'none'); |
| @@ -9256,6 +9439,17 @@ function swipe_right(_event, { source, repeated } = {}) { | |||
| 9256 | } | 9439 | } |
| 9257 | } | 9440 | } |
| 9258 | 9441 | ||
| 9442 | /** | ||
| 9443 | * @typedef {object} ConnectAPIMap | ||
| 9444 | * @property {string} selected - API name (e.g. "textgenerationwebui", "openai") | ||
| 9445 | * @property {string?} [button] - CSS selector for the API button | ||
| 9446 | * @property {string?} [type] - API type, mostly used by text completion. (e.g. "openrouter") | ||
| 9447 | * @property {string?} [source] - API source, mostly used by chat completion. (e.g. "openai") | ||
| 9448 | */ | ||
| 9449 | |||
| 9450 | /** | ||
| 9451 | * @type {Record<string, ConnectAPIMap>} | ||
| 9452 | */ | ||
| 9259 | export const CONNECT_API_MAP = { | 9453 | export const CONNECT_API_MAP = { |
| 9260 | // Default APIs not contined inside text gen / chat gen | 9454 | // Default APIs not contined inside text gen / chat gen |
| 9261 | 'kobold': { | 9455 | 'kobold': { |
| @@ -9700,6 +9894,15 @@ export async function renameChat(oldFileName, newName) { | |||
| 9700 | renamed_file: `${newName.trim()}.jsonl`, | 9894 | renamed_file: `${newName.trim()}.jsonl`, |
| 9701 | }; | 9895 | }; |
| 9702 | 9896 | ||
| 9897 | if (body.original_file === body.renamed_file) { | ||
| 9898 | console.debug('Chat rename cancelled, old and new names are the same'); | ||
| 9899 | return; | ||
| 9900 | } | ||
| 9901 | if (equalsIgnoreCaseAndAccents(body.original_file, body.renamed_file)) { | ||
| 9902 | toastr.warning(t`Name not accepted, as it is the same as before (ignoring case and accents).`, t`Rename Chat`); | ||
| 9903 | return; | ||
| 9904 | } | ||
| 9905 | |||
| 9703 | try { | 9906 | try { |
| 9704 | showLoader(); | 9907 | showLoader(); |
| 9705 | const response = await fetch('/api/chats/rename', { | 9908 | const response = await fetch('/api/chats/rename', { |
| @@ -10477,7 +10680,7 @@ jQuery(async function () { | |||
| 10477 | e.stopPropagation(); | 10680 | e.stopPropagation(); |
| 10478 | chat_file_for_del = $(this).attr('file_name'); | 10681 | chat_file_for_del = $(this).attr('file_name'); |
| 10479 | console.debug('detected cross click for' + chat_file_for_del); | 10682 | console.debug('detected cross click for' + chat_file_for_del); |
| 10480 | callPopup('<h3>Delete the Chat File?</h3>', 'del_chat'); | 10683 | callPopup('<h3>' + t`Delete the Chat File?` + '</h3>', 'del_chat'); |
| 10481 | }); | 10684 | }); |
| 10482 | 10685 | ||
| 10483 | $('#advanced_div').click(function () { | 10686 | $('#advanced_div').click(function () { |
| @@ -11644,8 +11847,8 @@ jQuery(async function () { | |||
| 11644 | return; | 11847 | return; |
| 11645 | } | 11848 | } |
| 11646 | const drawer = $(this).closest('.inline-drawer'); | 11849 | const drawer = $(this).closest('.inline-drawer'); |
| 11647 | const icon = drawer.find('.inline-drawer-icon'); | 11850 | const icon = drawer.find('>.inline-drawer-header .inline-drawer-icon'); |
| 11648 | const drawerContent = drawer.find('.inline-drawer-content'); | 11851 | const drawerContent = drawer.find('>.inline-drawer-content'); |
| 11649 | icon.toggleClass('down up'); | 11852 | icon.toggleClass('down up'); |
| 11650 | icon.toggleClass('fa-circle-chevron-down fa-circle-chevron-up'); | 11853 | icon.toggleClass('fa-circle-chevron-down fa-circle-chevron-up'); |
| 11651 | drawerContent.stop().slideToggle({ | 11854 | drawerContent.stop().slideToggle({ |
| @@ -12031,4 +12234,11 @@ jQuery(async function () { | |||
| 12031 | }); | 12234 | }); |
| 12032 | 12235 | ||
| 12033 | initCustomSelectedSamplers(); | 12236 | initCustomSelectedSamplers(); |
| 12237 | |||
| 12238 | window.addEventListener('beforeunload', (e) => { | ||
| 12239 | if (isChatSaving) { | ||
| 12240 | e.preventDefault(); | ||
| 12241 | e.returnValue = true; | ||
| 12242 | } | ||
| 12243 | }); | ||
| 12034 | }); | 12244 | }); |
| @@ -1,10 +1,10 @@ | |||
| 1 | 'use strict'; | 1 | 'use strict'; |
| 2 | 2 | ||
| 3 | import { DOMPurify, Popper } from '../lib.js'; | 3 | import { DOMPurify } from '../lib.js'; |
| 4 | 4 | ||
| 5 | import { event_types, eventSource, is_send_press, main_api, substituteParams } from '../script.js'; | 5 | import { event_types, eventSource, is_send_press, main_api, substituteParams } from '../script.js'; |
| 6 | import { is_group_generating } from './group-chats.js'; | 6 | import { is_group_generating } from './group-chats.js'; |
| 7 | import { Message, TokenHandler } from './openai.js'; | 7 | import { Message, MessageCollection, TokenHandler } from './openai.js'; |
| 8 | import { power_user } from './power-user.js'; | 8 | import { power_user } from './power-user.js'; |
| 9 | import { debounce, waitUntilCondition, escapeHtml } from './utils.js'; | 9 | import { debounce, waitUntilCondition, escapeHtml } from './utils.js'; |
| 10 | import { debounce_timeout } from './constants.js'; | 10 | import { debounce_timeout } from './constants.js'; |
| @@ -1440,36 +1440,8 @@ class PromptManager { | |||
| 1440 | footerDiv.querySelector('select').selectedIndex = selectedPromptIndex; | 1440 | footerDiv.querySelector('select').selectedIndex = selectedPromptIndex; |
| 1441 | 1441 | ||
| 1442 | // Add prompt export dialogue and options | 1442 | // Add prompt export dialogue and options |
| 1443 | |||
| 1444 | const exportForCharacter = await renderTemplateAsync('promptManagerExportForCharacter'); | ||
| 1445 | const exportPopup = await renderTemplateAsync('promptManagerExportPopup', { isGlobalStrategy: 'global' === this.configuration.promptOrder.strategy, exportForCharacter }); | ||
| 1446 | rangeBlockDiv.insertAdjacentHTML('beforeend', exportPopup); | ||
| 1447 | |||
| 1448 | // Destroy previous popper instance if it exists | ||
| 1449 | if (this.exportPopper) { | ||
| 1450 | this.exportPopper.destroy(); | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | this.exportPopper = Popper.createPopper( | ||
| 1454 | document.getElementById('prompt-manager-export'), | ||
| 1455 | document.getElementById('prompt-manager-export-format-popup'), | ||
| 1456 | { placement: 'bottom' }, | ||
| 1457 | ); | ||
| 1458 | |||
| 1459 | const showExportSelection = () => { | ||
| 1460 | const popup = document.getElementById('prompt-manager-export-format-popup'); | ||
| 1461 | const show = popup.hasAttribute('data-show'); | ||
| 1462 | |||
| 1463 | if (show) popup.removeAttribute('data-show'); | ||
| 1464 | else popup.setAttribute('data-show', ''); | ||
| 1465 | |||
| 1466 | this.exportPopper.update(); | ||
| 1467 | }; | ||
| 1468 | |||
| 1469 | footerDiv.querySelector('#prompt-manager-import').addEventListener('click', this.handleImport); | 1443 | footerDiv.querySelector('#prompt-manager-import').addEventListener('click', this.handleImport); |
| 1470 | footerDiv.querySelector('#prompt-manager-export').addEventListener('click', showExportSelection); | 1444 | footerDiv.querySelector('#prompt-manager-export').addEventListener('click', this.handleFullExport); |
| 1471 | rangeBlockDiv.querySelector('.export-promptmanager-prompts-full').addEventListener('click', this.handleFullExport); | ||
| 1472 | rangeBlockDiv.querySelector('.export-promptmanager-prompts-character')?.addEventListener('click', this.handleCharacterExport); | ||
| 1473 | } | 1445 | } |
| 1474 | } | 1446 | } |
| 1475 | 1447 | ||
| @@ -407,9 +407,9 @@ function RA_autoconnect(PrevApi) { | |||
| 407 | || (secret_state[SECRET_KEYS.PERPLEXITY] && oai_settings.chat_completion_source == chat_completion_sources.PERPLEXITY) | 407 | || (secret_state[SECRET_KEYS.PERPLEXITY] && oai_settings.chat_completion_source == chat_completion_sources.PERPLEXITY) |
| 408 | || (secret_state[SECRET_KEYS.GROQ] && oai_settings.chat_completion_source == chat_completion_sources.GROQ) | 408 | || (secret_state[SECRET_KEYS.GROQ] && oai_settings.chat_completion_source == chat_completion_sources.GROQ) |
| 409 | || (secret_state[SECRET_KEYS.ZEROONEAI] && oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI) | 409 | || (secret_state[SECRET_KEYS.ZEROONEAI] && oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI) |
| 410 | || (secret_state[SECRET_KEYS.BLOCKENTROPY] && oai_settings.chat_completion_source == chat_completion_sources.BLOCKENTROPY) | ||
| 411 | || (secret_state[SECRET_KEYS.NANOGPT] && oai_settings.chat_completion_source == chat_completion_sources.NANOGPT) | 410 | || (secret_state[SECRET_KEYS.NANOGPT] && oai_settings.chat_completion_source == chat_completion_sources.NANOGPT) |
| 412 | || (secret_state[SECRET_KEYS.DEEPSEEK] && oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) | 411 | || (secret_state[SECRET_KEYS.DEEPSEEK] && oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) |
| 412 | || (secret_state[SECRET_KEYS.XAI] && oai_settings.chat_completion_source == chat_completion_sources.XAI) | ||
| 413 | || (isValidUrl(oai_settings.custom_url) && oai_settings.chat_completion_source == chat_completion_sources.CUSTOM) | 413 | || (isValidUrl(oai_settings.custom_url) && oai_settings.chat_completion_source == chat_completion_sources.CUSTOM) |
| 414 | ) { | 414 | ) { |
| 415 | $('#api_button_openai').trigger('click'); | 415 | $('#api_button_openai').trigger('click'); |
| @@ -17,6 +17,7 @@ import { SlashCommand } from './slash-commands/SlashCommand.js'; | |||
| 17 | import { ARGUMENT_TYPE, SlashCommandArgument } from './slash-commands/SlashCommandArgument.js'; | 17 | import { ARGUMENT_TYPE, SlashCommandArgument } from './slash-commands/SlashCommandArgument.js'; |
| 18 | export { MODULE_NAME as NOTE_MODULE_NAME }; | 18 | export { MODULE_NAME as NOTE_MODULE_NAME }; |
| 19 | import { t } from './i18n.js'; | 19 | import { t } from './i18n.js'; |
| 20 | import { MacrosParser } from './macros.js'; | ||
| 20 | 21 | ||
| 21 | const MODULE_NAME = '2_floating_prompt'; // <= Deliberate, for sorting lower than memory | 22 | const MODULE_NAME = '2_floating_prompt'; // <= Deliberate, for sorting lower than memory |
| 22 | 23 | ||
| @@ -576,4 +577,8 @@ export function initAuthorsNote() { | |||
| 576 | `, | 577 | `, |
| 577 | })); | 578 | })); |
| 578 | eventSource.on(event_types.CHAT_CHANGED, onChatChanged); | 579 | eventSource.on(event_types.CHAT_CHANGED, onChatChanged); |
| 580 | |||
| 581 | MacrosParser.registerMacro('authorsNote', () => chat_metadata[metadata_keys.prompt] ?? '', t`The contents of the Author's Note`); | ||
| 582 | MacrosParser.registerMacro('charAuthorsNote', () => this_chid !== undefined ? (extension_settings.note.chara.find((e) => e.name === getCharaFilename())?.prompt ?? '') : '', t`The contents of the Character Author's Note`); | ||
| 583 | MacrosParser.registerMacro('defaultAuthorsNote', () => extension_settings.note.default ?? '', t`The contents of the Default Author's Note`); | ||
| 579 | } | 584 | } |
| @@ -3,10 +3,8 @@ import { debounce, escapeRegex } from '../utils.js'; | |||
| 3 | import { AutoCompleteOption } from './AutoCompleteOption.js'; | 3 | import { AutoCompleteOption } from './AutoCompleteOption.js'; |
| 4 | import { AutoCompleteFuzzyScore } from './AutoCompleteFuzzyScore.js'; | 4 | import { AutoCompleteFuzzyScore } from './AutoCompleteFuzzyScore.js'; |
| 5 | import { BlankAutoCompleteOption } from './BlankAutoCompleteOption.js'; | 5 | import { BlankAutoCompleteOption } from './BlankAutoCompleteOption.js'; |
| 6 | // eslint-disable-next-line no-unused-vars | ||
| 7 | import { AutoCompleteNameResult } from './AutoCompleteNameResult.js'; | 6 | import { AutoCompleteNameResult } from './AutoCompleteNameResult.js'; |
| 8 | import { AutoCompleteSecondaryNameResult } from './AutoCompleteSecondaryNameResult.js'; | 7 | import { AutoCompleteSecondaryNameResult } from './AutoCompleteSecondaryNameResult.js'; |
| 9 | import { Popup, getTopmostModalLayer } from '../popup.js'; | ||
| 10 | 8 | ||
| 11 | /**@readonly*/ | 9 | /**@readonly*/ |
| 12 | /**@enum {Number}*/ | 10 | /**@enum {Number}*/ |
| @@ -1,4 +1,3 @@ | |||
| 1 | import { SlashCommandNamedArgumentAutoCompleteOption } from '../slash-commands/SlashCommandNamedArgumentAutoCompleteOption.js'; | ||
| 2 | import { AutoCompleteOption } from './AutoCompleteOption.js'; | 1 | import { AutoCompleteOption } from './AutoCompleteOption.js'; |
| 3 | 2 | ||
| 4 | 3 | ||
| @@ -1,19 +1,18 @@ | |||
| 1 | import { SlashCommand } from '../slash-commands/SlashCommand.js'; | ||
| 2 | import { AutoCompleteFuzzyScore } from './AutoCompleteFuzzyScore.js'; | 1 | import { AutoCompleteFuzzyScore } from './AutoCompleteFuzzyScore.js'; |
| 3 | 2 | ||
| 4 | 3 | ||
| 5 | 4 | ||
| 6 | export class AutoCompleteOption { | 5 | export class AutoCompleteOption { |
| 7 | /**@type {string}*/ name; | 6 | /** @type {string} */ name; |
| 8 | /**@type {string}*/ typeIcon; | 7 | /** @type {string} */ typeIcon; |
| 9 | /**@type {string}*/ type; | 8 | /** @type {string} */ type; |
| 10 | /**@type {number}*/ nameOffset = 0; | 9 | /** @type {number} */ nameOffset = 0; |
| 11 | /**@type {AutoCompleteFuzzyScore}*/ score; | 10 | /** @type {AutoCompleteFuzzyScore} */ score; |
| 12 | /**@type {string}*/ replacer; | 11 | /** @type {string} */ replacer; |
| 13 | /**@type {HTMLElement}*/ dom; | 12 | /** @type {HTMLElement} */ dom; |
| 14 | /**@type {(input:string)=>boolean}*/ matchProvider; | 13 | /** @type {(input:string)=>boolean} */ matchProvider; |
| 15 | /**@type {(input:string)=>string}*/ valueProvider; | 14 | /** @type {(input:string)=>string} */ valueProvider; |
| 16 | /**@type {boolean}*/ makeSelectable = false; | 15 | /** @type {boolean} */ makeSelectable = false; |
| 17 | 16 | ||
| 18 | 17 | ||
| 19 | /** | 18 | /** |
| @@ -5,6 +5,7 @@ import { saveMetadataDebounced } from './extensions.js'; | |||
| 5 | import { SlashCommand } from './slash-commands/SlashCommand.js'; | 5 | import { SlashCommand } from './slash-commands/SlashCommand.js'; |
| 6 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; | 6 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; |
| 7 | import { flashHighlight, stringFormat } from './utils.js'; | 7 | import { flashHighlight, stringFormat } from './utils.js'; |
| 8 | import { t } from './i18n.js'; | ||
| 8 | 9 | ||
| 9 | const BG_METADATA_KEY = 'custom_background'; | 10 | const BG_METADATA_KEY = 'custom_background'; |
| 10 | const LIST_METADATA_KEY = 'chat_backgrounds'; | 11 | const LIST_METADATA_KEY = 'chat_backgrounds'; |
| @@ -243,7 +244,7 @@ async function getNewBackgroundName(referenceElement) { | |||
| 243 | const fileExtension = oldBg.split('.').pop(); | 244 | const fileExtension = oldBg.split('.').pop(); |
| 244 | const fileNameBase = isCustom ? oldBg.split('/').pop() : oldBg; | 245 | const fileNameBase = isCustom ? oldBg.split('/').pop() : oldBg; |
| 245 | const oldBgExtensionless = fileNameBase.replace(`.${fileExtension}`, ''); | 246 | const oldBgExtensionless = fileNameBase.replace(`.${fileExtension}`, ''); |
| 246 | const newBgExtensionless = await callPopup('<h3>Enter new background name:</h3>', 'input', oldBgExtensionless); | 247 | const newBgExtensionless = await callPopup('<h3>' + t`Enter new background name:` + '</h3>', 'input', oldBgExtensionless); |
| 247 | 248 | ||
| 248 | if (!newBgExtensionless) { | 249 | if (!newBgExtensionless) { |
| 249 | console.debug('no new_bg_extensionless'); | 250 | console.debug('no new_bg_extensionless'); |
| @@ -1,7 +1,6 @@ | |||
| 1 | import { | 1 | import { |
| 2 | characters, | 2 | characters, |
| 3 | saveChat, | 3 | saveChat, |
| 4 | system_messages, | ||
| 5 | system_message_types, | 4 | system_message_types, |
| 6 | this_chid, | 5 | this_chid, |
| 7 | openCharacterChat, | 6 | openCharacterChat, |
| @@ -13,7 +12,7 @@ import { | |||
| 13 | saveChatConditional, | 12 | saveChatConditional, |
| 14 | saveItemizedPrompts, | 13 | saveItemizedPrompts, |
| 15 | } from '../script.js'; | 14 | } from '../script.js'; |
| 16 | import { humanizedDateTime, getMessageTimeStamp } from './RossAscends-mods.js'; | 15 | import { humanizedDateTime } from './RossAscends-mods.js'; |
| 17 | import { | 16 | import { |
| 18 | getGroupPastChats, | 17 | getGroupPastChats, |
| 19 | group_activation_strategy, | 18 | group_activation_strategy, |
| @@ -156,7 +155,7 @@ export async function createBranch(mesId) { | |||
| 156 | if (selected_group) { | 155 | if (selected_group) { |
| 157 | await saveGroupBookmarkChat(selected_group, name, newMetadata, mesId); | 156 | await saveGroupBookmarkChat(selected_group, name, newMetadata, mesId); |
| 158 | } else { | 157 | } else { |
| 159 | await saveChat(name, newMetadata, mesId); | 158 | await saveChat({ chatName: name, withMetadata: newMetadata, mesId }); |
| 160 | } | 159 | } |
| 161 | // append to branches list if it exists | 160 | // append to branches list if it exists |
| 162 | // otherwise create it | 161 | // otherwise create it |
| @@ -212,7 +211,7 @@ export async function createNewBookmark(mesId, { forceName = null } = {}) { | |||
| 212 | if (selected_group) { | 211 | if (selected_group) { |
| 213 | await saveGroupBookmarkChat(selected_group, name, newMetadata, mesId); | 212 | await saveGroupBookmarkChat(selected_group, name, newMetadata, mesId); |
| 214 | } else { | 213 | } else { |
| 215 | await saveChat(name, newMetadata, mesId); | 214 | await saveChat({ chatName: name, withMetadata: newMetadata, mesId }); |
| 216 | } | 215 | } |
| 217 | 216 | ||
| 218 | lastMes.extra['bookmark_link'] = name; | 217 | lastMes.extra['bookmark_link'] = name; |
| @@ -358,7 +357,7 @@ export async function convertSoloToGroupChat() { | |||
| 358 | // Click on the freshly selected group to open it | 357 | // Click on the freshly selected group to open it |
| 359 | await openGroupById(group.id); | 358 | await openGroupById(group.id); |
| 360 | 359 | ||
| 361 | toastr.success('The chat has been successfully converted!'); | 360 | toastr.success(t`The chat has been successfully converted!`); |
| 362 | } | 361 | } |
| 363 | 362 | ||
| 364 | /** | 363 | /** |
| @@ -459,7 +459,7 @@ export async function appendFileContent(message, messageText) { | |||
| 459 | * @copyright https://github.com/kwaroran/risuAI | 459 | * @copyright https://github.com/kwaroran/risuAI |
| 460 | */ | 460 | */ |
| 461 | export function encodeStyleTags(text) { | 461 | export function encodeStyleTags(text) { |
| 462 | const styleRegex = /<style>(.+?)<\/style>/gms; | 462 | const styleRegex = /<style>(.+?)<\/style>/gims; |
| 463 | return text.replaceAll(styleRegex, (_, match) => { | 463 | return text.replaceAll(styleRegex, (_, match) => { |
| 464 | return `<custom-style>${escape(match)}</custom-style>`; | 464 | return `<custom-style>${escape(match)}</custom-style>`; |
| 465 | }); | 465 | }); |
| @@ -575,8 +575,8 @@ export function isExternalMediaAllowed() { | |||
| 575 | return !power_user.forbid_external_media; | 575 | return !power_user.forbid_external_media; |
| 576 | } | 576 | } |
| 577 | 577 | ||
| 578 | async function enlargeMessageImage() { | 578 | function expandMessageImage(event) { |
| 579 | const mesBlock = $(this).closest('.mes'); | 579 | const mesBlock = $(event.currentTarget).closest('.mes'); |
| 580 | const mesId = mesBlock.attr('mesid'); | 580 | const mesId = mesBlock.attr('mesid'); |
| 581 | const message = chat[mesId]; | 581 | const message = chat[mesId]; |
| 582 | const imgSrc = message?.extra?.image; | 582 | const imgSrc = message?.extra?.image; |
| @@ -620,7 +620,12 @@ async function enlargeMessageImage() { | |||
| 620 | popup.completeCancelled(); | 620 | popup.completeCancelled(); |
| 621 | }); | 621 | }); |
| 622 | 622 | ||
| 623 | await popup.show(); | 623 | popup.show(); |
| 624 | return img; | ||
| 625 | } | ||
| 626 | |||
| 627 | function expandAndZoomMessageImage(event) { | ||
| 628 | expandMessageImage(event).click(); | ||
| 624 | } | 629 | } |
| 625 | 630 | ||
| 626 | async function deleteMessageImage() { | 631 | async function deleteMessageImage() { |
| @@ -1603,7 +1608,8 @@ jQuery(function () { | |||
| 1603 | reloadCurrentChat(); | 1608 | reloadCurrentChat(); |
| 1604 | }); | 1609 | }); |
| 1605 | 1610 | ||
| 1606 | $(document).on('click', '.mes_img_enlarge', enlargeMessageImage); | 1611 | $(document).on('click', '.mes_img', expandMessageImage); |
| 1612 | $(document).on('click', '.mes_img_enlarge', expandAndZoomMessageImage); | ||
| 1607 | $(document).on('click', '.mes_img_delete', deleteMessageImage); | 1613 | $(document).on('click', '.mes_img_delete', deleteMessageImage); |
| 1608 | 1614 | ||
| 1609 | $('#file_form_input').on('change', async () => { | 1615 | $('#file_form_input').on('change', async () => { |
| @@ -14,3 +14,11 @@ export const debounce_timeout = { | |||
| 14 | /** [5 sec] For delayed tasks, like auto-saving or completing batch operations that need a significant pause. */ | 14 | /** [5 sec] For delayed tasks, like auto-saving or completing batch operations that need a significant pause. */ |
| 15 | extended: 5000, | 15 | extended: 5000, |
| 16 | }; | 16 | }; |
| 17 | |||
| 18 | /** | ||
| 19 | * Used as an ephemeral key in message extra metadata. | ||
| 20 | * When set, the message will be excluded from generation | ||
| 21 | * prompts without affecting the number of chat messages, | ||
| 22 | * which is needed to preserve world info timed effects. | ||
| 23 | */ | ||
| 24 | export const IGNORE_SYMBOL = Symbol.for('ignore'); | ||
| @@ -1,22 +1,26 @@ | |||
| 1 | import { getPresetManager } from './preset-manager.js'; | 1 | import { getPresetManager } from './preset-manager.js'; |
| 2 | import { extractMessageFromData, getGenerateUrl, getRequestHeaders } from '../script.js'; | 2 | import { extractMessageFromData, getGenerateUrl, getRequestHeaders } from '../script.js'; |
| 3 | import { getTextGenServer } from './textgen-settings.js'; | 3 | import { getTextGenServer } from './textgen-settings.js'; |
| 4 | import { extractReasoningFromData } from './reasoning.js'; | ||
| 5 | import { formatInstructModeChat, formatInstructModePrompt, getInstructStoppingSequences, names_behavior_types } from './instruct-mode.js'; | ||
| 6 | import { getStreamingReply, tryParseStreamingError } from './openai.js'; | ||
| 7 | import EventSourceStream from './sse-stream.js'; | ||
| 4 | 8 | ||
| 5 | // #region Type Definitions | 9 | // #region Type Definitions |
| 6 | /** | 10 | /** |
| 7 | * @typedef {Object} TextCompletionRequestBase | 11 | * @typedef {Object} TextCompletionRequestBase |
| 8 | * @property {string} prompt - The text prompt for completion | 12 | * @property {boolean?} [stream=false] - Whether to stream the response |
| 9 | * @property {number} max_tokens - Maximum number of tokens to generate | 13 | * @property {number} max_tokens - Maximum number of tokens to generate |
| 10 | * @property {string} [model] - Optional model name | 14 | * @property {string} [model] - Optional model name |
| 11 | * @property {string} api_type - Type of API to use | 15 | * @property {string} api_type - Type of API to use |
| 12 | * @property {string} [api_server] - Optional API server URL | 16 | * @property {string} [api_server] - Optional API server URL |
| 13 | * @property {number} [temperature] - Optional temperature parameter | 17 | * @property {number} [temperature] - Optional temperature parameter |
| 18 | * @property {number} [min_p] - Optional min_p parameter | ||
| 14 | */ | 19 | */ |
| 15 | 20 | ||
| 16 | /** @typedef {Record<string, any> & TextCompletionRequestBase} TextCompletionRequest */ | ||
| 17 | |||
| 18 | /** | 21 | /** |
| 19 | * @typedef {Object} TextCompletionPayloadBase | 22 | * @typedef {Object} TextCompletionPayloadBase |
| 23 | * @property {boolean?} [stream=false] - Whether to stream the response | ||
| 20 | * @property {string} prompt - The text prompt for completion | 24 | * @property {string} prompt - The text prompt for completion |
| 21 | * @property {number} max_tokens - Maximum number of tokens to generate | 25 | * @property {number} max_tokens - Maximum number of tokens to generate |
| 22 | * @property {number} max_new_tokens - Alias for max_tokens | 26 | * @property {number} max_new_tokens - Alias for max_tokens |
| @@ -36,29 +40,49 @@ import { getTextGenServer } from './textgen-settings.js'; | |||
| 36 | 40 | ||
| 37 | /** | 41 | /** |
| 38 | * @typedef {Object} ChatCompletionPayloadBase | 42 | * @typedef {Object} ChatCompletionPayloadBase |
| 43 | * @property {boolean?} [stream=false] - Whether to stream the response | ||
| 39 | * @property {ChatCompletionMessage[]} messages - Array of chat messages | 44 | * @property {ChatCompletionMessage[]} messages - Array of chat messages |
| 40 | * @property {string} [model] - Optional model name to use for completion | 45 | * @property {string} [model] - Optional model name to use for completion |
| 41 | * @property {string} chat_completion_source - Source provider for chat completion | 46 | * @property {string} chat_completion_source - Source provider |
| 42 | * @property {number} max_tokens - Maximum number of tokens to generate | 47 | * @property {number} max_tokens - Maximum number of tokens to generate |
| 43 | * @property {number} [temperature] - Optional temperature parameter for response randomness | 48 | * @property {number} [temperature] - Optional temperature parameter for response randomness |
| 49 | * @property {string} [custom_url] - Optional custom URL | ||
| 50 | * @property {string} [reverse_proxy] - Optional reverse proxy URL | ||
| 51 | * @property {string} [proxy_password] - Optional proxy password | ||
| 44 | */ | 52 | */ |
| 45 | 53 | ||
| 46 | /** @typedef {Record<string, any> & ChatCompletionPayloadBase} ChatCompletionPayload */ | 54 | /** @typedef {Record<string, any> & ChatCompletionPayloadBase} ChatCompletionPayload */ |
| 55 | |||
| 56 | /** | ||
| 57 | * @typedef {Object} ExtractedData | ||
| 58 | * @property {string} content - Extracted content. | ||
| 59 | * @property {string} reasoning - Extracted reasoning. | ||
| 60 | */ | ||
| 61 | |||
| 62 | /** | ||
| 63 | * @typedef {Object} StreamResponse | ||
| 64 | * @property {string} text - Generated text. | ||
| 65 | * @property {string[]} swipes - Generated swipes | ||
| 66 | * @property {Object} state - Generated state | ||
| 67 | * @property {string?} [state.reasoning] - Generated reasoning | ||
| 68 | * @property {string?} [state.image] - Generated image | ||
| 69 | */ | ||
| 70 | |||
| 47 | // #endregion | 71 | // #endregion |
| 48 | 72 | ||
| 49 | /** | 73 | /** |
| 50 | * Creates & sends a text completion request. Streaming is not supported. | 74 | * Creates & sends a text completion request. |
| 51 | */ | 75 | */ |
| 52 | export class TextCompletionService { | 76 | export class TextCompletionService { |
| 53 | static TYPE = 'textgenerationwebui'; | 77 | static TYPE = 'textgenerationwebui'; |
| 54 | 78 | ||
| 55 | /** | 79 | /** |
| 56 | * @param {TextCompletionRequest} custom | 80 | * @param {Record<string, any> & TextCompletionRequestBase & {prompt: string}} custom |
| 57 | * @returns {TextCompletionPayload} | 81 | * @returns {TextCompletionPayload} |
| 58 | */ | 82 | */ |
| 59 | static createRequestData({ prompt, max_tokens, model, api_type, api_server, temperature, ...props }) { | 83 | static createRequestData({ stream = false, prompt, max_tokens, model, api_type, api_server, temperature, min_p, ...props }) { |
| 60 | return { | 84 | const payload = { |
| 61 | ...props, | 85 | stream, |
| 62 | prompt, | 86 | prompt, |
| 63 | max_tokens, | 87 | max_tokens, |
| 64 | max_new_tokens: max_tokens, | 88 | max_new_tokens: max_tokens, |
| @@ -66,60 +90,297 @@ export class TextCompletionService { | |||
| 66 | api_type, | 90 | api_type, |
| 67 | api_server: api_server ?? getTextGenServer(api_type), | 91 | api_server: api_server ?? getTextGenServer(api_type), |
| 68 | temperature, | 92 | temperature, |
| 69 | stream: false, | 93 | min_p, |
| 94 | ...props, | ||
| 70 | }; | 95 | }; |
| 96 | |||
| 97 | // Remove undefined values to avoid API errors | ||
| 98 | Object.keys(payload).forEach(key => { | ||
| 99 | if (payload[key] === undefined) { | ||
| 100 | delete payload[key]; | ||
| 101 | } | ||
| 102 | }); | ||
| 103 | |||
| 104 | return payload; | ||
| 71 | } | 105 | } |
| 72 | 106 | ||
| 73 | /** | 107 | /** |
| 74 | * Sends a text completion request to the specified server | 108 | * Sends a text completion request to the specified server |
| 75 | * @param {TextCompletionPayload} data Request data | 109 | * @param {TextCompletionPayload} data Request data |
| 76 | * @param {boolean?} extractData Extract message from the response. Default true | 110 | * @param {boolean?} extractData Extract message from the response. Default true |
| 77 | * @returns {Promise<string | any>} Extracted data or the raw response | 111 | * @param {AbortSignal?} signal |
| 112 | * @returns {Promise<ExtractedData | (() => AsyncGenerator<StreamResponse>)>} If not streaming, returns extracted data; if streaming, returns a function that creates an AsyncGenerator | ||
| 78 | * @throws {Error} | 113 | * @throws {Error} |
| 79 | */ | 114 | */ |
| 80 | static async sendRequest(data, extractData = true) { | 115 | static async sendRequest(data, extractData = true, signal = null) { |
| 81 | const response = await fetch(getGenerateUrl(this.TYPE), { | 116 | if (!data.stream) { |
| 117 | const response = await fetch(getGenerateUrl(this.TYPE), { | ||
| 118 | method: 'POST', | ||
| 119 | headers: getRequestHeaders(), | ||
| 120 | cache: 'no-cache', | ||
| 121 | body: JSON.stringify(data), | ||
| 122 | signal: signal ?? new AbortController().signal, | ||
| 123 | }); | ||
| 124 | |||
| 125 | const json = await response.json(); | ||
| 126 | if (!response.ok || json.error) { | ||
| 127 | throw json; | ||
| 128 | } | ||
| 129 | |||
| 130 | if (!extractData) { | ||
| 131 | return json; | ||
| 132 | } | ||
| 133 | |||
| 134 | return { | ||
| 135 | content: extractMessageFromData(json, this.TYPE), | ||
| 136 | reasoning: extractReasoningFromData(json, { | ||
| 137 | mainApi: this.TYPE, | ||
| 138 | textGenType: data.api_type, | ||
| 139 | ignoreShowThoughts: true, | ||
| 140 | }), | ||
| 141 | }; | ||
| 142 | } | ||
| 143 | |||
| 144 | const response = await fetch('/api/backends/text-completions/generate', { | ||
| 82 | method: 'POST', | 145 | method: 'POST', |
| 83 | headers: getRequestHeaders(), | 146 | headers: getRequestHeaders(), |
| 84 | cache: 'no-cache', | 147 | cache: 'no-cache', |
| 85 | body: JSON.stringify(data), | 148 | body: JSON.stringify(data), |
| 86 | signal: new AbortController().signal, | 149 | signal: signal ?? new AbortController().signal, |
| 87 | }); | 150 | }); |
| 88 | 151 | ||
| 89 | const json = await response.json(); | 152 | if (!response.ok) { |
| 90 | if (!response.ok || json.error) { | 153 | const text = await response.text(); |
| 91 | throw json; | 154 | tryParseStreamingError(response, text, { quiet: true }); |
| 155 | |||
| 156 | throw new Error(`Got response status ${response.status}`); | ||
| 92 | } | 157 | } |
| 93 | 158 | ||
| 94 | return extractData ? extractMessageFromData(json, this.TYPE) : json; | 159 | const eventStream = new EventSourceStream(); |
| 160 | response.body.pipeThrough(eventStream); | ||
| 161 | const reader = eventStream.readable.getReader(); | ||
| 162 | return async function* streamData() { | ||
| 163 | let text = ''; | ||
| 164 | const swipes = []; | ||
| 165 | const state = { reasoning: '' }; | ||
| 166 | while (true) { | ||
| 167 | const { done, value } = await reader.read(); | ||
| 168 | if (done) return; | ||
| 169 | if (value.data === '[DONE]') return; | ||
| 170 | |||
| 171 | tryParseStreamingError(response, value.data, { quiet: true }); | ||
| 172 | |||
| 173 | let data = JSON.parse(value.data); | ||
| 174 | |||
| 175 | if (data?.choices?.[0]?.index > 0) { | ||
| 176 | const swipeIndex = data.choices[0].index - 1; | ||
| 177 | swipes[swipeIndex] = (swipes[swipeIndex] || '') + data.choices[0].text; | ||
| 178 | } else { | ||
| 179 | const newText = data?.choices?.[0]?.text || data?.content || ''; | ||
| 180 | text += newText; | ||
| 181 | state.reasoning += data?.choices?.[0]?.reasoning ?? ''; | ||
| 182 | } | ||
| 183 | |||
| 184 | yield { text, swipes, state }; | ||
| 185 | } | ||
| 186 | }; | ||
| 95 | } | 187 | } |
| 96 | 188 | ||
| 97 | /** | 189 | /** |
| 98 | * @param {string} presetName | 190 | * Process and send a text completion request with optional preset & instruct |
| 99 | * @param {TextCompletionRequest} custom | 191 | * @param {Record<string, any> & TextCompletionRequestBase & {prompt: (ChatCompletionMessage & {ignoreInstruct?: boolean})[] |string}} custom |
| 100 | * @param {boolean?} extractData Extract message from the response. Default true | 192 | * @param {Object} options - Configuration options |
| 101 | * @returns {Promise<string | any>} Extracted data or the raw response | 193 | * @param {string?} [options.presetName] - Name of the preset to use for generation settings |
| 194 | * @param {string?} [options.instructName] - Name of instruct preset for message formatting | ||
| 195 | * @param {Partial<InstructSettings>?} [options.instructSettings] - Override instruct settings | ||
| 196 | * @param {boolean} extractData - Whether to extract structured data from response | ||
| 197 | * @param {AbortSignal?} [signal] | ||
| 198 | * @returns {Promise<ExtractedData | (() => AsyncGenerator<StreamResponse>)>} If not streaming, returns extracted data; if streaming, returns a function that creates an AsyncGenerator | ||
| 102 | * @throws {Error} | 199 | * @throws {Error} |
| 103 | */ | 200 | */ |
| 104 | static async sendRequestWithPreset(presetName, custom, extractData = true) { | 201 | static async processRequest( |
| 105 | const presetManager = getPresetManager(this.TYPE); | 202 | custom, |
| 106 | if (!presetManager) { | 203 | options = {}, |
| 107 | throw new Error('Preset manager not found'); | 204 | extractData = true, |
| 205 | signal = null, | ||
| 206 | ) { | ||
| 207 | const { presetName, instructName } = options; | ||
| 208 | let requestData = { ...custom }; | ||
| 209 | const prompt = custom.prompt; | ||
| 210 | |||
| 211 | // Apply generation preset if specified | ||
| 212 | if (presetName) { | ||
| 213 | const presetManager = getPresetManager(this.TYPE); | ||
| 214 | if (presetManager) { | ||
| 215 | const preset = presetManager.getCompletionPresetByName(presetName); | ||
| 216 | if (preset) { | ||
| 217 | // Convert preset to payload and merge with custom parameters | ||
| 218 | const presetPayload = this.presetToGeneratePayload(preset, {}); | ||
| 219 | requestData = { ...presetPayload, ...requestData }; | ||
| 220 | } else { | ||
| 221 | console.warn(`Preset "${presetName}" not found, continuing with default settings`); | ||
| 222 | } | ||
| 223 | } else { | ||
| 224 | console.warn('Preset manager not found, continuing with default settings'); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | |||
| 229 | /** @type {InstructSettings | undefined} */ | ||
| 230 | let instructPreset; | ||
| 231 | // Handle instruct formatting if requested | ||
| 232 | if (Array.isArray(prompt) && instructName) { | ||
| 233 | const instructPresetManager = getPresetManager('instruct'); | ||
| 234 | instructPreset = instructPresetManager?.getCompletionPresetByName(instructName); | ||
| 235 | if (instructPreset) { | ||
| 236 | // Clone the preset to avoid modifying the original | ||
| 237 | instructPreset = structuredClone(instructPreset); | ||
| 238 | instructPreset.names_behavior = names_behavior_types.NONE; | ||
| 239 | if (options.instructSettings) { | ||
| 240 | Object.assign(instructPreset, options.instructSettings); | ||
| 241 | } | ||
| 242 | |||
| 243 | // Format messages using instruct formatting | ||
| 244 | const formattedMessages = []; | ||
| 245 | for (const message of prompt) { | ||
| 246 | let messageContent = message.content; | ||
| 247 | if (!message.ignoreInstruct) { | ||
| 248 | messageContent = formatInstructModeChat( | ||
| 249 | message.role, | ||
| 250 | message.content, | ||
| 251 | message.role === 'user', | ||
| 252 | false, | ||
| 253 | undefined, | ||
| 254 | undefined, | ||
| 255 | undefined, | ||
| 256 | undefined, | ||
| 257 | instructPreset, | ||
| 258 | ); | ||
| 259 | |||
| 260 | // Add prompt formatting for the last message | ||
| 261 | if (message === prompt[prompt.length - 1]) { | ||
| 262 | messageContent += formatInstructModePrompt( | ||
| 263 | undefined, | ||
| 264 | false, | ||
| 265 | undefined, | ||
| 266 | undefined, | ||
| 267 | undefined, | ||
| 268 | false, | ||
| 269 | false, | ||
| 270 | instructPreset, | ||
| 271 | ); | ||
| 272 | } | ||
| 273 | } | ||
| 274 | formattedMessages.push(messageContent); | ||
| 275 | } | ||
| 276 | requestData.prompt = formattedMessages.join(''); | ||
| 277 | const stoppingStrings = getInstructStoppingSequences({ customInstruct: instructPreset, useStopStrings: false }); | ||
| 278 | requestData.stop = stoppingStrings; | ||
| 279 | requestData.stopping_strings = stoppingStrings; | ||
| 280 | } else { | ||
| 281 | console.warn(`Instruct preset "${instructName}" not found, using basic formatting`); | ||
| 282 | requestData.prompt = prompt.map(x => x.content).join('\n\n'); | ||
| 283 | } | ||
| 284 | } else if (typeof prompt === 'string') { | ||
| 285 | requestData.prompt = prompt; | ||
| 286 | } else { | ||
| 287 | requestData.prompt = prompt.map(x => x.content).join('\n\n'); | ||
| 288 | } | ||
| 289 | |||
| 290 | // @ts-ignore | ||
| 291 | const data = this.createRequestData(requestData); | ||
| 292 | |||
| 293 | const response = await this.sendRequest(data, extractData, signal); | ||
| 294 | // Remove stopping strings from the end | ||
| 295 | if (!data.stream && extractData) { | ||
| 296 | /** @type {ExtractedData} */ | ||
| 297 | // @ts-ignore | ||
| 298 | const extractedData = response; | ||
| 299 | |||
| 300 | let message = extractedData.content; | ||
| 301 | |||
| 302 | message = message.replace(/[^\S\r\n]+$/gm, ''); | ||
| 303 | |||
| 304 | if (requestData.stopping_strings) { | ||
| 305 | for (const stoppingString of requestData.stopping_strings) { | ||
| 306 | if (stoppingString.length) { | ||
| 307 | for (let j = stoppingString.length; j > 0; j--) { | ||
| 308 | if (message.slice(-j) === stoppingString.slice(0, j)) { | ||
| 309 | message = message.slice(0, -j); | ||
| 310 | break; | ||
| 311 | } | ||
| 312 | } | ||
| 313 | } | ||
| 314 | } | ||
| 315 | } | ||
| 316 | |||
| 317 | if (instructPreset) { | ||
| 318 | [ | ||
| 319 | instructPreset.stop_sequence, | ||
| 320 | instructPreset.input_sequence, | ||
| 321 | ].forEach(sequence => { | ||
| 322 | if (sequence?.trim()) { | ||
| 323 | const index = message.indexOf(sequence); | ||
| 324 | if (index !== -1) { | ||
| 325 | message = message.substring(0, index); | ||
| 326 | } | ||
| 327 | } | ||
| 328 | }); | ||
| 329 | |||
| 330 | [ | ||
| 331 | instructPreset.output_sequence, | ||
| 332 | instructPreset.last_output_sequence, | ||
| 333 | ].forEach(sequences => { | ||
| 334 | if (sequences) { | ||
| 335 | sequences.split('\n') | ||
| 336 | .filter(line => line.trim() !== '') | ||
| 337 | .forEach(line => { | ||
| 338 | message = message.replaceAll(line, ''); | ||
| 339 | }); | ||
| 340 | } | ||
| 341 | }); | ||
| 342 | } | ||
| 343 | |||
| 344 | extractedData.content = message; | ||
| 108 | } | 345 | } |
| 109 | 346 | ||
| 110 | const preset = presetManager.getCompletionPresetByName(presetName); | 347 | return response; |
| 111 | if (!preset) { | 348 | } |
| 112 | throw new Error('Preset not found'); | 349 | |
| 350 | /** | ||
| 351 | * Converts a preset to a valid text completion payload. | ||
| 352 | * Only supports temperature. | ||
| 353 | * @param {Object} preset - The preset configuration | ||
| 354 | * @param {Object} customPreset - Additional parameters to override preset values | ||
| 355 | * @returns {Object} - Formatted payload for text completion API | ||
| 356 | */ | ||
| 357 | static presetToGeneratePayload(preset, customPreset = {}) { | ||
| 358 | if (!preset || typeof preset !== 'object') { | ||
| 359 | throw new Error('Invalid preset: must be an object'); | ||
| 113 | } | 360 | } |
| 114 | 361 | ||
| 115 | const data = this.createRequestData({ ...preset, ...custom }); | 362 | // Merge preset with custom parameters |
| 363 | const settings = { ...preset, ...customPreset }; | ||
| 116 | 364 | ||
| 117 | return await this.sendRequest(data, extractData); | 365 | // Initialize base payload with common parameters |
| 366 | let payload = { | ||
| 367 | 'temperature': settings.temp ? Number(settings.temp) : undefined, | ||
| 368 | 'min_p': settings.min_p ? Number(settings.min_p) : undefined, | ||
| 369 | }; | ||
| 370 | |||
| 371 | // Remove undefined values to avoid API errors | ||
| 372 | Object.keys(payload).forEach(key => { | ||
| 373 | if (payload[key] === undefined) { | ||
| 374 | delete payload[key]; | ||
| 375 | } | ||
| 376 | }); | ||
| 377 | |||
| 378 | return payload; | ||
| 118 | } | 379 | } |
| 119 | } | 380 | } |
| 120 | 381 | ||
| 121 | /** | 382 | /** |
| 122 | * Creates & sends a chat completion request. Streaming is not supported. | 383 | * Creates & sends a chat completion request. |
| 123 | */ | 384 | */ |
| 124 | export class ChatCompletionService { | 385 | export class ChatCompletionService { |
| 125 | static TYPE = 'openai'; | 386 | static TYPE = 'openai'; |
| @@ -128,62 +389,170 @@ export class ChatCompletionService { | |||
| 128 | * @param {ChatCompletionPayload} custom | 389 | * @param {ChatCompletionPayload} custom |
| 129 | * @returns {ChatCompletionPayload} | 390 | * @returns {ChatCompletionPayload} |
| 130 | */ | 391 | */ |
| 131 | static createRequestData({ messages, model, chat_completion_source, max_tokens, temperature, ...props }) { | 392 | static createRequestData({ stream = false, messages, model, chat_completion_source, max_tokens, temperature, custom_url, reverse_proxy, proxy_password, ...props }) { |
| 132 | return { | 393 | const payload = { |
| 133 | ...props, | 394 | stream, |
| 134 | messages, | 395 | messages, |
| 135 | model, | 396 | model, |
| 136 | chat_completion_source, | 397 | chat_completion_source, |
| 137 | max_tokens, | 398 | max_tokens, |
| 138 | temperature, | 399 | temperature, |
| 139 | stream: false, | 400 | custom_url, |
| 401 | reverse_proxy, | ||
| 402 | proxy_password, | ||
| 403 | use_makersuite_sysprompt: true, | ||
| 404 | claude_use_sysprompt: true, | ||
| 405 | ...props, | ||
| 140 | }; | 406 | }; |
| 407 | |||
| 408 | // Remove undefined values to avoid API errors | ||
| 409 | Object.keys(payload).forEach(key => { | ||
| 410 | if (payload[key] === undefined) { | ||
| 411 | delete payload[key]; | ||
| 412 | } | ||
| 413 | }); | ||
| 414 | |||
| 415 | return payload; | ||
| 141 | } | 416 | } |
| 142 | 417 | ||
| 143 | /** | 418 | /** |
| 144 | * Sends a chat completion request | 419 | * Sends a chat completion request |
| 145 | * @param {ChatCompletionPayload} data Request data | 420 | * @param {ChatCompletionPayload} data Request data |
| 146 | * @param {boolean?} extractData Extract message from the response. Default true | 421 | * @param {boolean?} extractData Extract message from the response. Default true |
| 147 | * @returns {Promise<string | any>} Extracted data or the raw response | 422 | * @param {AbortSignal?} signal Abort signal |
| 423 | * @returns {Promise<ExtractedData | (() => AsyncGenerator<StreamResponse>)>} If not streaming, returns extracted data; if streaming, returns a function that creates an AsyncGenerator | ||
| 148 | * @throws {Error} | 424 | * @throws {Error} |
| 149 | */ | 425 | */ |
| 150 | static async sendRequest(data, extractData = true) { | 426 | static async sendRequest(data, extractData = true, signal = null) { |
| 151 | const response = await fetch('/api/backends/chat-completions/generate', { | 427 | const response = await fetch('/api/backends/chat-completions/generate', { |
| 152 | method: 'POST', | 428 | method: 'POST', |
| 153 | headers: getRequestHeaders(), | 429 | headers: getRequestHeaders(), |
| 154 | cache: 'no-cache', | 430 | cache: 'no-cache', |
| 155 | body: JSON.stringify(data), | 431 | body: JSON.stringify(data), |
| 156 | signal: new AbortController().signal, | 432 | signal: signal ?? new AbortController().signal, |
| 157 | }); | 433 | }); |
| 158 | 434 | ||
| 159 | const json = await response.json(); | 435 | if (!data.stream) { |
| 160 | if (!response.ok || json.error) { | 436 | const json = await response.json(); |
| 161 | throw json; | 437 | if (!response.ok || json.error) { |
| 438 | throw json; | ||
| 439 | } | ||
| 440 | |||
| 441 | if (!extractData) { | ||
| 442 | return json; | ||
| 443 | } | ||
| 444 | |||
| 445 | return { | ||
| 446 | content: extractMessageFromData(json, this.TYPE), | ||
| 447 | reasoning: extractReasoningFromData(json, { | ||
| 448 | mainApi: this.TYPE, | ||
| 449 | textGenType: data.chat_completion_source, | ||
| 450 | ignoreShowThoughts: true, | ||
| 451 | }), | ||
| 452 | }; | ||
| 453 | } | ||
| 454 | |||
| 455 | if (!response.ok) { | ||
| 456 | const text = await response.text(); | ||
| 457 | tryParseStreamingError(response, text, { quiet: true }); | ||
| 458 | |||
| 459 | throw new Error(`Got response status ${response.status}`); | ||
| 162 | } | 460 | } |
| 163 | 461 | ||
| 164 | return extractData ? extractMessageFromData(json, this.TYPE) : json; | 462 | const eventStream = new EventSourceStream(); |
| 463 | response.body.pipeThrough(eventStream); | ||
| 464 | const reader = eventStream.readable.getReader(); | ||
| 465 | return async function* streamData() { | ||
| 466 | let text = ''; | ||
| 467 | const swipes = []; | ||
| 468 | const state = { reasoning: '', image: '' }; | ||
| 469 | while (true) { | ||
| 470 | const { done, value } = await reader.read(); | ||
| 471 | if (done) return; | ||
| 472 | const rawData = value.data; | ||
| 473 | if (rawData === '[DONE]') return; | ||
| 474 | tryParseStreamingError(response, rawData, { quiet: true }); | ||
| 475 | const parsed = JSON.parse(rawData); | ||
| 476 | |||
| 477 | const reply = getStreamingReply(parsed, state, { | ||
| 478 | chatCompletionSource: data.chat_completion_source, | ||
| 479 | overrideShowThoughts: true, | ||
| 480 | }); | ||
| 481 | if (Array.isArray(parsed?.choices) && parsed?.choices?.[0]?.index > 0) { | ||
| 482 | const swipeIndex = parsed.choices[0].index - 1; | ||
| 483 | swipes[swipeIndex] = (swipes[swipeIndex] || '') + reply; | ||
| 484 | } else { | ||
| 485 | text += reply; | ||
| 486 | } | ||
| 487 | |||
| 488 | yield { text, swipes: swipes, state }; | ||
| 489 | } | ||
| 490 | }; | ||
| 165 | } | 491 | } |
| 166 | 492 | ||
| 167 | /** | 493 | /** |
| 168 | * @param {string} presetName | 494 | * Process and send a chat completion request with optional preset |
| 169 | * @param {ChatCompletionPayload} custom | 495 | * @param {ChatCompletionPayload} custom |
| 170 | * @param {boolean} extractData Extract message from the response. Default true | 496 | * @param {Object} options - Configuration options |
| 171 | * @returns {Promise<string | any>} Extracted data or the raw response | 497 | * @param {string?} [options.presetName] - Name of the preset to use for generation settings |
| 498 | * @param {boolean} [extractData=true] - Whether to extract structured data from response | ||
| 499 | * @param {AbortSignal?} [signal] - Abort signal | ||
| 500 | * @returns {Promise<ExtractedData | (() => AsyncGenerator<StreamResponse>)>} If not streaming, returns extracted data; if streaming, returns a function that creates an AsyncGenerator | ||
| 172 | * @throws {Error} | 501 | * @throws {Error} |
| 173 | */ | 502 | */ |
| 174 | static async sendRequestWithPreset(presetName, custom, extractData = true) { | 503 | static async processRequest(custom, options, extractData = true, signal = null) { |
| 175 | const presetManager = getPresetManager(this.TYPE); | 504 | const { presetName } = options; |
| 176 | if (!presetManager) { | 505 | let requestData = { ...custom }; |
| 177 | throw new Error('Preset manager not found'); | 506 | |
| 507 | // Apply generation preset if specified | ||
| 508 | if (presetName) { | ||
| 509 | const presetManager = getPresetManager(this.TYPE); | ||
| 510 | if (presetManager) { | ||
| 511 | const preset = presetManager.getCompletionPresetByName(presetName); | ||
| 512 | if (preset) { | ||
| 513 | // Convert preset to payload and merge with custom parameters | ||
| 514 | const presetPayload = this.presetToGeneratePayload(preset, {}); | ||
| 515 | requestData = { ...presetPayload, ...requestData }; | ||
| 516 | } else { | ||
| 517 | console.warn(`Preset "${presetName}" not found, continuing with default settings`); | ||
| 518 | } | ||
| 519 | } else { | ||
| 520 | console.warn('Preset manager not found, continuing with default settings'); | ||
| 521 | } | ||
| 178 | } | 522 | } |
| 179 | 523 | ||
| 180 | const preset = presetManager.getCompletionPresetByName(presetName); | 524 | const data = this.createRequestData(requestData); |
| 181 | if (!preset) { | 525 | |
| 182 | throw new Error('Preset not found'); | 526 | return await this.sendRequest(data, extractData, signal); |
| 527 | } | ||
| 528 | |||
| 529 | /** | ||
| 530 | * Converts a preset to a valid chat completion payload | ||
| 531 | * Only supports temperature. | ||
| 532 | * @param {Object} preset - The preset configuration | ||
| 533 | * @param {Object} customParams - Additional parameters to override preset values | ||
| 534 | * @returns {Object} - Formatted payload for chat completion API | ||
| 535 | */ | ||
| 536 | static presetToGeneratePayload(preset, customParams = {}) { | ||
| 537 | if (!preset || typeof preset !== 'object') { | ||
| 538 | throw new Error('Invalid preset: must be an object'); | ||
| 183 | } | 539 | } |
| 184 | 540 | ||
| 185 | const data = this.createRequestData({ ...preset, ...custom }); | 541 | // Merge preset with custom parameters |
| 542 | const settings = { ...preset, ...customParams }; | ||
| 543 | |||
| 544 | // Initialize base payload with common parameters | ||
| 545 | const payload = { | ||
| 546 | temperature: settings.temperature ? Number(settings.temperature) : undefined, | ||
| 547 | }; | ||
| 548 | |||
| 549 | // Remove undefined values to avoid API errors | ||
| 550 | Object.keys(payload).forEach(key => { | ||
| 551 | if (payload[key] === undefined) { | ||
| 552 | delete payload[key]; | ||
| 553 | } | ||
| 554 | }); | ||
| 186 | 555 | ||
| 187 | return await this.sendRequest(data, extractData); | 556 | return payload; |
| 188 | } | 557 | } |
| 189 | } | 558 | } |
| @@ -783,25 +783,41 @@ async function showExtensionsDetails() { | |||
| 783 | .append(htmlExternal) | 783 | .append(htmlExternal) |
| 784 | .append(getModuleInformation()); | 784 | .append(getModuleInformation()); |
| 785 | 785 | ||
| 786 | /** @type {import('./popup.js').CustomPopupButton} */ | 786 | { |
| 787 | const updateAllButton = { | 787 | const updateAction = async (force) => { |
| 788 | text: t`Update all`, | ||
| 789 | action: async () => { | ||
| 790 | requiresReload = true; | 788 | requiresReload = true; |
| 791 | await autoUpdateExtensions(true); | 789 | await autoUpdateExtensions(force); |
| 792 | await popup.complete(POPUP_RESULT.AFFIRMATIVE); | 790 | await popup.complete(POPUP_RESULT.AFFIRMATIVE); |
| 793 | }, | 791 | }; |
| 794 | }; | 792 | |
| 793 | const toolbar = document.createElement('div'); | ||
| 794 | toolbar.classList.add('extensions_toolbar'); | ||
| 795 | |||
| 796 | const updateAllButton = document.createElement('button'); | ||
| 797 | updateAllButton.classList.add('menu_button', 'menu_button_icon'); | ||
| 798 | updateAllButton.textContent = t`Update all`; | ||
| 799 | updateAllButton.addEventListener('click', () => updateAction(true)); | ||
| 795 | 800 | ||
| 796 | /** @type {import('./popup.js').CustomPopupButton} */ | 801 | const updateEnabledOnlyButton = document.createElement('button'); |
| 797 | const sortOrderButton = { | 802 | updateEnabledOnlyButton.classList.add('menu_button', 'menu_button_icon'); |
| 798 | text: sortByName ? t`Sort: Display Name` : t`Sort: Loading Order`, | 803 | updateEnabledOnlyButton.textContent = t`Update enabled`; |
| 799 | action: async () => { | 804 | updateEnabledOnlyButton.addEventListener('click', () => updateAction(false)); |
| 805 | |||
| 806 | const flexExpander = document.createElement('div'); | ||
| 807 | flexExpander.classList.add('expander'); | ||
| 808 | |||
| 809 | const sortOrderButton = document.createElement('button'); | ||
| 810 | sortOrderButton.classList.add('menu_button', 'menu_button_icon'); | ||
| 811 | sortOrderButton.textContent = sortByName ? t`Sort: Display Name` : t`Sort: Loading Order`; | ||
| 812 | sortOrderButton.addEventListener('click', async () => { | ||
| 800 | abortController.abort(); | 813 | abortController.abort(); |
| 801 | accountStorage.setItem(sortOrderKey, sortByName ? 'false' : 'true'); | 814 | accountStorage.setItem(sortOrderKey, sortByName ? 'false' : 'true'); |
| 802 | await showExtensionsDetails(); | 815 | await showExtensionsDetails(); |
| 803 | }, | 816 | }); |
| 804 | }; | 817 | |
| 818 | toolbar.append(updateAllButton, updateEnabledOnlyButton, flexExpander, sortOrderButton); | ||
| 819 | html.prepend(toolbar); | ||
| 820 | } | ||
| 805 | 821 | ||
| 806 | let waitingForSave = false; | 822 | let waitingForSave = false; |
| 807 | 823 | ||
| @@ -809,7 +825,7 @@ async function showExtensionsDetails() { | |||
| 809 | okButton: t`Close`, | 825 | okButton: t`Close`, |
| 810 | wide: true, | 826 | wide: true, |
| 811 | large: true, | 827 | large: true, |
| 812 | customButtons: [sortOrderButton, updateAllButton], | 828 | customButtons: [], |
| 813 | allowVerticalScrolling: true, | 829 | allowVerticalScrolling: true, |
| 814 | onClosing: async () => { | 830 | onClosing: async () => { |
| 815 | if (waitingForSave) { | 831 | if (waitingForSave) { |
| @@ -1196,7 +1212,7 @@ async function checkForUpdatesManual(sortFn, abortSignal) { | |||
| 1196 | } | 1212 | } |
| 1197 | 1213 | ||
| 1198 | /** | 1214 | /** |
| 1199 | * Checks if there are updates available for 3rd-party extensions. | 1215 | * Checks if there are updates available for enabled 3rd-party extensions. |
| 1200 | * @param {boolean} force Skip nag check | 1216 | * @param {boolean} force Skip nag check |
| 1201 | * @returns {Promise<any>} | 1217 | * @returns {Promise<any>} |
| 1202 | */ | 1218 | */ |
| @@ -1218,6 +1234,11 @@ async function checkForExtensionUpdates(force) { | |||
| 1218 | const promises = []; | 1234 | const promises = []; |
| 1219 | 1235 | ||
| 1220 | for (const [id, manifest] of Object.entries(manifests)) { | 1236 | for (const [id, manifest] of Object.entries(manifests)) { |
| 1237 | const isDisabled = extension_settings.disabledExtensions.includes(id); | ||
| 1238 | if (isDisabled) { | ||
| 1239 | console.debug(`Skipping extension: ${manifest.display_name} (${id}) for non-admin user`); | ||
| 1240 | continue; | ||
| 1241 | } | ||
| 1221 | const isGlobal = getExtensionType(id) === 'global'; | 1242 | const isGlobal = getExtensionType(id) === 'global'; |
| 1222 | if (isGlobal && !isCurrentUserAdmin) { | 1243 | if (isGlobal && !isCurrentUserAdmin) { |
| 1223 | console.debug(`Skipping global extension: ${manifest.display_name} (${id}) for non-admin user`); | 1244 | console.debug(`Skipping global extension: ${manifest.display_name} (${id}) for non-admin user`); |
| @@ -1247,8 +1268,8 @@ async function checkForExtensionUpdates(force) { | |||
| 1247 | } | 1268 | } |
| 1248 | 1269 | ||
| 1249 | /** | 1270 | /** |
| 1250 | * Updates all 3rd-party extensions that have auto-update enabled. | 1271 | * Updates all enabled 3rd-party extensions that have auto-update enabled. |
| 1251 | * @param {boolean} forceAll Force update all even if not auto-updating | 1272 | * @param {boolean} forceAll Include disabled and not auto-updating |
| 1252 | * @returns {Promise<void>} | 1273 | * @returns {Promise<void>} |
| 1253 | */ | 1274 | */ |
| 1254 | async function autoUpdateExtensions(forceAll) { | 1275 | async function autoUpdateExtensions(forceAll) { |
| @@ -1260,6 +1281,11 @@ async function autoUpdateExtensions(forceAll) { | |||
| 1260 | const isCurrentUserAdmin = isAdmin(); | 1281 | const isCurrentUserAdmin = isAdmin(); |
| 1261 | const promises = []; | 1282 | const promises = []; |
| 1262 | for (const [id, manifest] of Object.entries(manifests)) { | 1283 | for (const [id, manifest] of Object.entries(manifests)) { |
| 1284 | const isDisabled = extension_settings.disabledExtensions.includes(id); | ||
| 1285 | if (!forceAll && isDisabled) { | ||
| 1286 | console.debug(`Skipping extension: ${manifest.display_name} (${id}) for non-admin user`); | ||
| 1287 | continue; | ||
| 1288 | } | ||
| 1263 | const isGlobal = getExtensionType(id) === 'global'; | 1289 | const isGlobal = getExtensionType(id) === 'global'; |
| 1264 | if (isGlobal && !isCurrentUserAdmin) { | 1290 | if (isGlobal && !isCurrentUserAdmin) { |
| 1265 | console.debug(`Skipping global extension: ${manifest.display_name} (${id}) for non-admin user`); | 1291 | console.debug(`Skipping global extension: ${manifest.display_name} (${id}) for non-admin user`); |
| @@ -424,7 +424,7 @@ jQuery(async () => { | |||
| 424 | installHintButton.on('click', async function () { | 424 | installHintButton.on('click', async function () { |
| 425 | const installButton = $('#third_party_extension_button'); | 425 | const installButton = $('#third_party_extension_button'); |
| 426 | flashHighlight(installButton, 5000); | 426 | flashHighlight(installButton, 5000); |
| 427 | toastr.info('Click the flashing button to install extensions.', 'How to install extensions?'); | 427 | toastr.info(t`Click the flashing button to install extensions.`, t`How to install extensions?`); |
| 428 | }); | 428 | }); |
| 429 | 429 | ||
| 430 | const connectButton = windowHtml.find('#assets-connect-button'); | 430 | const connectButton = windowHtml.find('#assets-connect-button'); |
| @@ -39,7 +39,7 @@ To install a single 3rd party extension, use the "Install Extensions" | |||
| 39 | <span data-i18n="Characters">Characters</span> | 39 | <span data-i18n="Characters">Characters</span> |
| 40 | </div> | 40 | </div> |
| 41 | </div> | 41 | </div> |
| 42 | <div class="inline-drawer-content" id="assets_menu"> | 42 | <div id="assets_menu"> |
| 43 | </div> | 43 | </div> |
| 44 | </div> | 44 | </div> |
| 45 | </div> | 45 | </div> |
| @@ -1,4 +1,4 @@ | |||
| 1 | <div id="attachFile" class="list-group-item flex-container flexGap5" title="Attach a file or image to a current chat."> | 1 | <div id="attachFile" class="list-group-item flex-container flexGap5" data-i18n="[title]Attach a file or image to a current chat." title="Attach a file or image to a current chat."> |
| 2 | <div class="fa-fw fa-solid fa-paperclip extensionsMenuExtensionButton"></div> | 2 | <div class="fa-fw fa-solid fa-paperclip extensionsMenuExtensionButton"></div> |
| 3 | <span data-i18n="Attach a File">Attach a File</span> | 3 | <span data-i18n="Attach a File">Attach a File</span> |
| 4 | </div> | 4 | </div> |
| @@ -428,6 +428,7 @@ jQuery(async function () { | |||
| 428 | 'zerooneai': SECRET_KEYS.ZEROONEAI, | 428 | 'zerooneai': SECRET_KEYS.ZEROONEAI, |
| 429 | 'groq': SECRET_KEYS.GROQ, | 429 | 'groq': SECRET_KEYS.GROQ, |
| 430 | 'cohere': SECRET_KEYS.COHERE, | 430 | 'cohere': SECRET_KEYS.COHERE, |
| 431 | 'xai': SECRET_KEYS.XAI, | ||
| 431 | }; | 432 | }; |
| 432 | 433 | ||
| 433 | if (chatCompletionApis[api] && secret_state[chatCompletionApis[api]]) { | 434 | if (chatCompletionApis[api] && secret_state[chatCompletionApis[api]]) { |
| @@ -31,6 +31,7 @@ | |||
| 31 | <option value="openrouter">OpenRouter</option> | 31 | <option value="openrouter">OpenRouter</option> |
| 32 | <option value="ooba" data-i18n="Text Generation WebUI (oobabooga)">Text Generation WebUI (oobabooga)</option> | 32 | <option value="ooba" data-i18n="Text Generation WebUI (oobabooga)">Text Generation WebUI (oobabooga)</option> |
| 33 | <option value="vllm">vLLM</option> | 33 | <option value="vllm">vLLM</option> |
| 34 | <option value="xai">xAI (Grok)</option> | ||
| 34 | </select> | 35 | </select> |
| 35 | </div> | 36 | </div> |
| 36 | <div class="flex1 flex-container flexFlowColumn flexNoGap"> | 37 | <div class="flex1 flex-container flexFlowColumn flexNoGap"> |
| @@ -42,7 +43,16 @@ | |||
| 42 | <option data-type="mistral" value="pixtral-12b-2409">pixtral-12b-2409</option> | 43 | <option data-type="mistral" value="pixtral-12b-2409">pixtral-12b-2409</option> |
| 43 | <option data-type="mistral" value="pixtral-large-latest">pixtral-large-latest</option> | 44 | <option data-type="mistral" value="pixtral-large-latest">pixtral-large-latest</option> |
| 44 | <option data-type="mistral" value="pixtral-large-2411">pixtral-large-2411</option> | 45 | <option data-type="mistral" value="pixtral-large-2411">pixtral-large-2411</option> |
| 46 | <option data-type="mistral" value="mistral-large-pixtral-2411">mistral-large-pixtral-2411</option> | ||
| 47 | <option data-type="mistral" value="mistral-small-2503">mistral-small-2503</option> | ||
| 48 | <option data-type="mistral" value="mistral-small-latest">mistral-small-latest</option> | ||
| 45 | <option data-type="zerooneai" value="yi-vision">yi-vision</option> | 49 | <option data-type="zerooneai" value="yi-vision">yi-vision</option> |
| 50 | <option data-type="openai" value="gpt-4.1">gpt-4.1</option> | ||
| 51 | <option data-type="openai" value="gpt-4.1-2025-04-14">gpt-4.1-2025-04-14</option> | ||
| 52 | <option data-type="openai" value="gpt-4.1-mini">gpt-4.1-mini</option> | ||
| 53 | <option data-type="openai" value="gpt-4.1-mini-2025-04-14">gpt-4.1-mini-2025-04-14</option> | ||
| 54 | <option data-type="openai" value="gpt-4.1-nano">gpt-4.1-nano</option> | ||
| 55 | <option data-type="openai" value="gpt-4.1-nano-2025-04-14">gpt-4.1-nano-2025-04-14</option> | ||
| 46 | <option data-type="openai" value="gpt-4-vision-preview">gpt-4-vision-preview</option> | 56 | <option data-type="openai" value="gpt-4-vision-preview">gpt-4-vision-preview</option> |
| 47 | <option data-type="openai" value="gpt-4-turbo">gpt-4-turbo</option> | 57 | <option data-type="openai" value="gpt-4-turbo">gpt-4-turbo</option> |
| 48 | <option data-type="openai" value="gpt-4o">gpt-4o</option> | 58 | <option data-type="openai" value="gpt-4o">gpt-4o</option> |
| @@ -50,6 +60,10 @@ | |||
| 50 | <option data-type="openai" value="chatgpt-4o-latest">chatgpt-4o-latest</option> | 60 | <option data-type="openai" value="chatgpt-4o-latest">chatgpt-4o-latest</option> |
| 51 | <option data-type="openai" value="o1">o1</option> | 61 | <option data-type="openai" value="o1">o1</option> |
| 52 | <option data-type="openai" value="o1-2024-12-17">o1-2024-12-17</option> | 62 | <option data-type="openai" value="o1-2024-12-17">o1-2024-12-17</option> |
| 63 | <option data-type="openai" value="o3">o3</option> | ||
| 64 | <option data-type="openai" value="o3-2025-04-16">o3-2025-04-16</option> | ||
| 65 | <option data-type="openai" value="o4-mini">o4-mini</option> | ||
| 66 | <option data-type="openai" value="o4-mini-2025-04-16">o4-mini-2025-04-16</option> | ||
| 53 | <option data-type="openai" value="gpt-4.5-preview">gpt-4.5-preview</option> | 67 | <option data-type="openai" value="gpt-4.5-preview">gpt-4.5-preview</option> |
| 54 | <option data-type="openai" value="gpt-4.5-preview-2025-02-27">gpt-4.5-preview-2025-02-27</option> | 68 | <option data-type="openai" value="gpt-4.5-preview-2025-02-27">gpt-4.5-preview-2025-02-27</option> |
| 55 | <option data-type="anthropic" value="claude-3-7-sonnet-latest">claude-3-7-sonnet-latest</option> | 69 | <option data-type="anthropic" value="claude-3-7-sonnet-latest">claude-3-7-sonnet-latest</option> |
| @@ -62,8 +76,11 @@ | |||
| 62 | <option data-type="anthropic" value="claude-3-opus-20240229">claude-3-opus-20240229</option> | 76 | <option data-type="anthropic" value="claude-3-opus-20240229">claude-3-opus-20240229</option> |
| 63 | <option data-type="anthropic" value="claude-3-sonnet-20240229">claude-3-sonnet-20240229</option> | 77 | <option data-type="anthropic" value="claude-3-sonnet-20240229">claude-3-sonnet-20240229</option> |
| 64 | <option data-type="anthropic" value="claude-3-haiku-20240307">claude-3-haiku-20240307</option> | 78 | <option data-type="anthropic" value="claude-3-haiku-20240307">claude-3-haiku-20240307</option> |
| 79 | <option data-type="google" value="gemini-2.5-pro-preview-03-25">gemini-2.5-pro-preview-03-25</option> | ||
| 80 | <option data-type="google" value="gemini-2.5-pro-exp-03-25">gemini-2.5-pro-exp-03-25</option> | ||
| 65 | <option data-type="google" value="gemini-2.0-pro-exp">gemini-2.0-pro-exp</option> | 81 | <option data-type="google" value="gemini-2.0-pro-exp">gemini-2.0-pro-exp</option> |
| 66 | <option data-type="google" value="gemini-2.0-pro-exp-02-05">gemini-2.0-pro-exp-02-05</option> | 82 | <option data-type="google" value="gemini-2.0-pro-exp-02-05">gemini-2.0-pro-exp-02-05</option> |
| 83 | <option data-type="google" value="gemini-2.5-flash-preview-04-17">gemini-2.5-flash-preview-04-17</option> | ||
| 67 | <option data-type="google" value="gemini-2.0-flash-lite-preview">gemini-2.0-flash-lite-preview</option> | 84 | <option data-type="google" value="gemini-2.0-flash-lite-preview">gemini-2.0-flash-lite-preview</option> |
| 68 | <option data-type="google" value="gemini-2.0-flash-lite-preview-02-05">gemini-2.0-flash-lite-preview-02-05</option> | 85 | <option data-type="google" value="gemini-2.0-flash-lite-preview-02-05">gemini-2.0-flash-lite-preview-02-05</option> |
| 69 | <option data-type="google" value="gemini-2.0-flash">gemini-2.0-flash</option> | 86 | <option data-type="google" value="gemini-2.0-flash">gemini-2.0-flash</option> |
| @@ -129,6 +146,8 @@ | |||
| 129 | <option data-type="koboldcpp" value="koboldcpp_current" data-i18n="currently_loaded">[Currently loaded]</option> | 146 | <option data-type="koboldcpp" value="koboldcpp_current" data-i18n="currently_loaded">[Currently loaded]</option> |
| 130 | <option data-type="vllm" value="vllm_current" data-i18n="currently_selected">[Currently selected]</option> | 147 | <option data-type="vllm" value="vllm_current" data-i18n="currently_selected">[Currently selected]</option> |
| 131 | <option data-type="custom" value="custom_current" data-i18n="currently_selected">[Currently selected]</option> | 148 | <option data-type="custom" value="custom_current" data-i18n="currently_selected">[Currently selected]</option> |
| 149 | <option data-type="xai" value="grok-2-vision-1212">grok-2-vision-1212</option> | ||
| 150 | <option data-type="xai" value="grok-vision-beta">grok-vision-beta</option> | ||
| 132 | </select> | 151 | </select> |
| 133 | </div> | 152 | </div> |
| 134 | <div data-type="ollama"> | 153 | <div data-type="ollama"> |
| @@ -1,4 +1,4 @@ | |||
| 1 | import { Fuse } from '../../../lib.js'; | 1 | import { DOMPurify, Fuse } from '../../../lib.js'; |
| 2 | 2 | ||
| 3 | import { event_types, eventSource, main_api, saveSettingsDebounced } from '../../../script.js'; | 3 | import { event_types, eventSource, main_api, saveSettingsDebounced } from '../../../script.js'; |
| 4 | import { extension_settings, renderExtensionTemplateAsync } from '../../extensions.js'; | 4 | import { extension_settings, renderExtensionTemplateAsync } from '../../extensions.js'; |
| @@ -39,6 +39,7 @@ const CC_COMMANDS = [ | |||
| 39 | 'proxy', | 39 | 'proxy', |
| 40 | 'stop-strings', | 40 | 'stop-strings', |
| 41 | 'start-reply-with', | 41 | 'start-reply-with', |
| 42 | 'reasoning-template', | ||
| 42 | ]; | 43 | ]; |
| 43 | 44 | ||
| 44 | const TC_COMMANDS = [ | 45 | const TC_COMMANDS = [ |
| @@ -54,6 +55,7 @@ const TC_COMMANDS = [ | |||
| 54 | 'tokenizer', | 55 | 'tokenizer', |
| 55 | 'stop-strings', | 56 | 'stop-strings', |
| 56 | 'start-reply-with', | 57 | 'start-reply-with', |
| 58 | 'reasoning-template', | ||
| 57 | ]; | 59 | ]; |
| 58 | 60 | ||
| 59 | const FANCY_NAMES = { | 61 | const FANCY_NAMES = { |
| @@ -70,6 +72,7 @@ const FANCY_NAMES = { | |||
| 70 | 'tokenizer': 'Tokenizer', | 72 | 'tokenizer': 'Tokenizer', |
| 71 | 'stop-strings': 'Custom Stopping Strings', | 73 | 'stop-strings': 'Custom Stopping Strings', |
| 72 | 'start-reply-with': 'Start Reply With', | 74 | 'start-reply-with': 'Start Reply With', |
| 75 | 'reasoning-template': 'Reasoning Template', | ||
| 73 | }; | 76 | }; |
| 74 | 77 | ||
| 75 | /** | 78 | /** |
| @@ -154,6 +157,7 @@ const profilesProvider = () => [ | |||
| 154 | * @property {string} [tokenizer] Tokenizer | 157 | * @property {string} [tokenizer] Tokenizer |
| 155 | * @property {string} [stop-strings] Custom Stopping Strings | 158 | * @property {string} [stop-strings] Custom Stopping Strings |
| 156 | * @property {string} [start-reply-with] Start Reply With | 159 | * @property {string} [start-reply-with] Start Reply With |
| 160 | * @property {string} [reasoning-template] Reasoning Template | ||
| 157 | * @property {string[]} [exclude] Commands to exclude | 161 | * @property {string[]} [exclude] Commands to exclude |
| 158 | */ | 162 | */ |
| 159 | 163 | ||
| @@ -267,9 +271,14 @@ async function createConnectionProfile(forceName = null) { | |||
| 267 | }); | 271 | }); |
| 268 | const isNameTaken = (n) => extension_settings.connectionManager.profiles.some(p => p.name === n); | 272 | const isNameTaken = (n) => extension_settings.connectionManager.profiles.some(p => p.name === n); |
| 269 | const suggestedName = getUniqueName(collapseSpaces(`${profile.api ?? ''} ${profile.model ?? ''} - ${profile.preset ?? ''}`), isNameTaken); | 273 | const suggestedName = getUniqueName(collapseSpaces(`${profile.api ?? ''} ${profile.model ?? ''} - ${profile.preset ?? ''}`), isNameTaken); |
| 270 | const name = forceName ?? await callGenericPopup(template, POPUP_TYPE.INPUT, suggestedName, { rows: 2 }); | 274 | let name = forceName ?? await callGenericPopup(template, POPUP_TYPE.INPUT, suggestedName, { rows: 2 }); |
| 271 | 275 | // If it's cancelled, it will be false | |
| 276 | if (!name) { | ||
| 277 | return null; | ||
| 278 | } | ||
| 279 | name = DOMPurify.sanitize(String(name)); | ||
| 272 | if (!name) { | 280 | if (!name) { |
| 281 | toastr.error('Name cannot be empty.'); | ||
| 273 | return null; | 282 | return null; |
| 274 | } | 283 | } |
| 275 | 284 | ||
| @@ -303,7 +312,8 @@ async function deleteConnectionProfile() { | |||
| 303 | return; | 312 | return; |
| 304 | } | 313 | } |
| 305 | 314 | ||
| 306 | const name = extension_settings.connectionManager.profiles[index].name; | 315 | const profile = extension_settings.connectionManager.profiles[index]; |
| 316 | const name = profile.name; | ||
| 307 | const confirm = await Popup.show.confirm(t`Are you sure you want to delete the selected profile?`, name); | 317 | const confirm = await Popup.show.confirm(t`Are you sure you want to delete the selected profile?`, name); |
| 308 | 318 | ||
| 309 | if (!confirm) { | 319 | if (!confirm) { |
| @@ -313,6 +323,8 @@ async function deleteConnectionProfile() { | |||
| 313 | extension_settings.connectionManager.profiles.splice(index, 1); | 323 | extension_settings.connectionManager.profiles.splice(index, 1); |
| 314 | extension_settings.connectionManager.selectedProfile = null; | 324 | extension_settings.connectionManager.selectedProfile = null; |
| 315 | saveSettingsDebounced(); | 325 | saveSettingsDebounced(); |
| 326 | |||
| 327 | await eventSource.emit(event_types.CONNECTION_PROFILE_DELETED, profile); | ||
| 316 | } | 328 | } |
| 317 | 329 | ||
| 318 | /** | 330 | /** |
| @@ -512,6 +524,7 @@ async function renderDetailsContent(detailsContent) { | |||
| 512 | saveSettingsDebounced(); | 524 | saveSettingsDebounced(); |
| 513 | renderConnectionProfiles(profiles); | 525 | renderConnectionProfiles(profiles); |
| 514 | await renderDetailsContent(detailsContent); | 526 | await renderDetailsContent(detailsContent); |
| 527 | await eventSource.emit(event_types.CONNECTION_PROFILE_CREATED, profile); | ||
| 515 | await eventSource.emit(event_types.CONNECTION_PROFILE_LOADED, profile.name); | 528 | await eventSource.emit(event_types.CONNECTION_PROFILE_LOADED, profile.name); |
| 516 | }); | 529 | }); |
| 517 | 530 | ||
| @@ -523,9 +536,11 @@ async function renderDetailsContent(detailsContent) { | |||
| 523 | console.log('No profile selected'); | 536 | console.log('No profile selected'); |
| 524 | return; | 537 | return; |
| 525 | } | 538 | } |
| 539 | const oldProfile = structuredClone(profile); | ||
| 526 | await updateConnectionProfile(profile); | 540 | await updateConnectionProfile(profile); |
| 527 | await renderDetailsContent(detailsContent); | 541 | await renderDetailsContent(detailsContent); |
| 528 | saveSettingsDebounced(); | 542 | saveSettingsDebounced(); |
| 543 | await eventSource.emit(event_types.CONNECTION_PROFILE_UPDATED, oldProfile, profile); | ||
| 529 | await eventSource.emit(event_types.CONNECTION_PROFILE_LOADED, profile.name); | 544 | await eventSource.emit(event_types.CONNECTION_PROFILE_LOADED, profile.name); |
| 530 | toastr.success('Connection profile updated', '', { timeOut: 1500 }); | 545 | toastr.success('Connection profile updated', '', { timeOut: 1500 }); |
| 531 | }); | 546 | }); |
| @@ -559,7 +574,7 @@ async function renderDetailsContent(detailsContent) { | |||
| 559 | return acc; | 574 | return acc; |
| 560 | }, {}); | 575 | }, {}); |
| 561 | const template = $(await renderExtensionTemplateAsync(MODULE_NAME, 'edit', { name: profile.name, settings })); | 576 | const template = $(await renderExtensionTemplateAsync(MODULE_NAME, 'edit', { name: profile.name, settings })); |
| 562 | const newName = await callGenericPopup(template, POPUP_TYPE.INPUT, profile.name, { | 577 | let newName = await callGenericPopup(template, POPUP_TYPE.INPUT, profile.name, { |
| 563 | rows: 2, | 578 | rows: 2, |
| 564 | customButtons: [{ | 579 | customButtons: [{ |
| 565 | text: t`Save and Update`, | 580 | text: t`Save and Update`, |
| @@ -571,7 +586,13 @@ async function renderDetailsContent(detailsContent) { | |||
| 571 | }], | 586 | }], |
| 572 | }); | 587 | }); |
| 573 | 588 | ||
| 589 | // If it's cancelled, it will be false | ||
| 590 | if (!newName) { | ||
| 591 | return; | ||
| 592 | } | ||
| 593 | newName = DOMPurify.sanitize(String(newName)); | ||
| 574 | if (!newName) { | 594 | if (!newName) { |
| 595 | toastr.error('Name cannot be empty.'); | ||
| 575 | return; | 596 | return; |
| 576 | } | 597 | } |
| 577 | 598 | ||
| @@ -584,6 +605,7 @@ async function renderDetailsContent(detailsContent) { | |||
| 584 | return Object.entries(FANCY_NAMES).find(x => x[1] === String($(this).val()))?.[0]; | 605 | return Object.entries(FANCY_NAMES).find(x => x[1] === String($(this).val()))?.[0]; |
| 585 | }).get(); | 606 | }).get(); |
| 586 | 607 | ||
| 608 | const oldProfile = structuredClone(profile); | ||
| 587 | if (newExcludeList.length !== profile.exclude.length || !newExcludeList.every(e => profile.exclude.includes(e))) { | 609 | if (newExcludeList.length !== profile.exclude.length || !newExcludeList.every(e => profile.exclude.includes(e))) { |
| 588 | profile.exclude = newExcludeList; | 610 | profile.exclude = newExcludeList; |
| 589 | for (const command of newExcludeList) { | 611 | for (const command of newExcludeList) { |
| @@ -598,10 +620,11 @@ async function renderDetailsContent(detailsContent) { | |||
| 598 | 620 | ||
| 599 | if (profile.name !== newName) { | 621 | if (profile.name !== newName) { |
| 600 | toastr.success('Connection profile renamed.'); | 622 | toastr.success('Connection profile renamed.'); |
| 601 | profile.name = String(newName); | 623 | profile.name = newName; |
| 602 | } | 624 | } |
| 603 | 625 | ||
| 604 | saveSettingsDebounced(); | 626 | saveSettingsDebounced(); |
| 627 | await eventSource.emit(event_types.CONNECTION_PROFILE_UPDATED, oldProfile, profile); | ||
| 605 | renderConnectionProfiles(profiles); | 628 | renderConnectionProfiles(profiles); |
| 606 | await renderDetailsContent(detailsContent); | 629 | await renderDetailsContent(detailsContent); |
| 607 | }); | 630 | }); |
| @@ -704,6 +727,7 @@ async function renderDetailsContent(detailsContent) { | |||
| 704 | saveSettingsDebounced(); | 727 | saveSettingsDebounced(); |
| 705 | renderConnectionProfiles(profiles); | 728 | renderConnectionProfiles(profiles); |
| 706 | await renderDetailsContent(detailsContent); | 729 | await renderDetailsContent(detailsContent); |
| 730 | await eventSource.emit(event_types.CONNECTION_PROFILE_CREATED, profile); | ||
| 707 | return profile.name; | 731 | return profile.name; |
| 708 | }, | 732 | }, |
| 709 | })); | 733 | })); |
| @@ -718,9 +742,11 @@ async function renderDetailsContent(detailsContent) { | |||
| 718 | toastr.warning('No profile selected.'); | 742 | toastr.warning('No profile selected.'); |
| 719 | return ''; | 743 | return ''; |
| 720 | } | 744 | } |
| 745 | const oldProfile = structuredClone(profile); | ||
| 721 | await updateConnectionProfile(profile); | 746 | await updateConnectionProfile(profile); |
| 722 | await renderDetailsContent(detailsContent); | 747 | await renderDetailsContent(detailsContent); |
| 723 | saveSettingsDebounced(); | 748 | saveSettingsDebounced(); |
| 749 | await eventSource.emit(event_types.CONNECTION_PROFILE_UPDATED, oldProfile, profile); | ||
| 724 | return profile.name; | 750 | return profile.name; |
| 725 | }, | 751 | }, |
| 726 | })); | 752 | })); |
| @@ -4,7 +4,7 @@ import { characters, eventSource, event_types, generateRaw, getRequestHeaders, m | |||
| 4 | import { dragElement, isMobile } from '../../RossAscends-mods.js'; | 4 | import { dragElement, isMobile } from '../../RossAscends-mods.js'; |
| 5 | import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch, renderExtensionTemplateAsync } from '../../extensions.js'; | 5 | import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch, renderExtensionTemplateAsync } from '../../extensions.js'; |
| 6 | import { loadMovingUIState, performFuzzySearch, power_user } from '../../power-user.js'; | 6 | import { loadMovingUIState, performFuzzySearch, power_user } from '../../power-user.js'; |
| 7 | import { onlyUnique, debounce, getCharaFilename, trimToEndSentence, trimToStartSentence, waitUntilCondition, findChar } from '../../utils.js'; | 7 | import { onlyUnique, debounce, getCharaFilename, trimToEndSentence, trimToStartSentence, waitUntilCondition, findChar, isFalseBoolean } from '../../utils.js'; |
| 8 | import { hideMutedSprites, selected_group } from '../../group-chats.js'; | 8 | import { hideMutedSprites, selected_group } from '../../group-chats.js'; |
| 9 | import { isJsonSchemaSupported } from '../../textgen-settings.js'; | 9 | import { isJsonSchemaSupported } from '../../textgen-settings.js'; |
| 10 | import { debounce_timeout } from '../../constants.js'; | 10 | import { debounce_timeout } from '../../constants.js'; |
| @@ -17,6 +17,7 @@ import { slashCommandReturnHelper } from '../../slash-commands/SlashCommandRetur | |||
| 17 | import { generateWebLlmChatPrompt, isWebLlmSupported } from '../shared.js'; | 17 | import { generateWebLlmChatPrompt, isWebLlmSupported } from '../shared.js'; |
| 18 | import { Popup, POPUP_RESULT } from '../../popup.js'; | 18 | import { Popup, POPUP_RESULT } from '../../popup.js'; |
| 19 | import { t } from '../../i18n.js'; | 19 | import { t } from '../../i18n.js'; |
| 20 | import { removeReasoningFromString } from '../../reasoning.js'; | ||
| 20 | export { MODULE_NAME }; | 21 | export { MODULE_NAME }; |
| 21 | 22 | ||
| 22 | /** | 23 | /** |
| @@ -82,6 +83,7 @@ const EXPRESSION_API = { | |||
| 82 | extras: 1, | 83 | extras: 1, |
| 83 | llm: 2, | 84 | llm: 2, |
| 84 | webllm: 3, | 85 | webllm: 3, |
| 86 | none: 99, | ||
| 85 | }; | 87 | }; |
| 86 | 88 | ||
| 87 | let expressionsList = null; | 89 | let expressionsList = null; |
| @@ -273,7 +275,7 @@ async function getLastMessageSprite(avatar) { | |||
| 273 | return null; | 275 | return null; |
| 274 | } | 276 | } |
| 275 | 277 | ||
| 276 | async function visualNovelUpdateLayers(container) { | 278 | export async function visualNovelUpdateLayers(container) { |
| 277 | const context = getContext(); | 279 | const context = getContext(); |
| 278 | const group = context.groups.find(x => x.id == context.groupId); | 280 | const group = context.groups.find(x => x.id == context.groupId); |
| 279 | const recentMessages = context.chat.map(x => x.original_avatar).filter(x => x).reverse().filter(onlyUnique); | 281 | const recentMessages = context.chat.map(x => x.original_avatar).filter(x => x).reverse().filter(onlyUnique); |
| @@ -678,7 +680,7 @@ async function setSpriteFolderCommand(_, folder) { | |||
| 678 | return ''; | 680 | return ''; |
| 679 | } | 681 | } |
| 680 | 682 | ||
| 681 | async function classifyCallback(/** @type {{api: string?, prompt: string?}} */ { api = null, prompt = null }, text) { | 683 | async function classifyCallback(/** @type {{api: string?, filter: string?, prompt: string?}} */ { api = null, filter = null, prompt = null }, text) { |
| 682 | if (!text) { | 684 | if (!text) { |
| 683 | toastr.error('No text provided'); | 685 | toastr.error('No text provided'); |
| 684 | return ''; | 686 | return ''; |
| @@ -689,13 +691,19 @@ async function classifyCallback(/** @type {{api: string?, prompt: string?}} */ { | |||
| 689 | } | 691 | } |
| 690 | 692 | ||
| 691 | const expressionApi = EXPRESSION_API[api] || extension_settings.expressions.api; | 693 | const expressionApi = EXPRESSION_API[api] || extension_settings.expressions.api; |
| 694 | const filterAvailable = !isFalseBoolean(filter); | ||
| 695 | |||
| 696 | if (expressionApi === EXPRESSION_API.none) { | ||
| 697 | toastr.warning('No classifier API selected'); | ||
| 698 | return ''; | ||
| 699 | } | ||
| 692 | 700 | ||
| 693 | if (!modules.includes('classify') && expressionApi == EXPRESSION_API.extras) { | 701 | if (!modules.includes('classify') && expressionApi == EXPRESSION_API.extras) { |
| 694 | toastr.warning('Text classification is disabled or not available'); | 702 | toastr.warning('Text classification is disabled or not available'); |
| 695 | return ''; | 703 | return ''; |
| 696 | } | 704 | } |
| 697 | 705 | ||
| 698 | const label = await getExpressionLabel(text, expressionApi, { customPrompt: prompt }); | 706 | const label = await getExpressionLabel(text, expressionApi, { filterAvailable: filterAvailable, customPrompt: prompt }); |
| 699 | console.debug(`Classification result for "${text}": ${label}`); | 707 | console.debug(`Classification result for "${text}": ${label}`); |
| 700 | return label; | 708 | return label; |
| 701 | } | 709 | } |
| @@ -928,6 +936,9 @@ function parseLlmResponse(emotionResponse, labels) { | |||
| 928 | 936 | ||
| 929 | return response; | 937 | return response; |
| 930 | } catch { | 938 | } catch { |
| 939 | // Clean possible reasoning from response | ||
| 940 | emotionResponse = removeReasoningFromString(emotionResponse); | ||
| 941 | |||
| 931 | const fuse = new Fuse(labels, { includeScore: true }); | 942 | const fuse = new Fuse(labels, { includeScore: true }); |
| 932 | console.debug('Using fuzzy search in labels:', labels); | 943 | console.debug('Using fuzzy search in labels:', labels); |
| 933 | const result = fuse.search(emotionResponse); | 944 | const result = fuse.search(emotionResponse); |
| @@ -988,10 +999,11 @@ function onTextGenSettingsReady(args) { | |||
| 988 | * @param {string} text - The text to classify and retrieve the expression label for. | 999 | * @param {string} text - The text to classify and retrieve the expression label for. |
| 989 | * @param {EXPRESSION_API} [expressionsApi=extension_settings.expressions.api] - The expressions API to use for classification. | 1000 | * @param {EXPRESSION_API} [expressionsApi=extension_settings.expressions.api] - The expressions API to use for classification. |
| 990 | * @param {object} [options={}] - Optional arguments. | 1001 | * @param {object} [options={}] - Optional arguments. |
| 1002 | * @param {boolean?} [options.filterAvailable=null] - Whether to filter available expressions. If not specified, uses the extension setting. | ||
| 991 | * @param {string?} [options.customPrompt=null] - The custom prompt to use for classification. | 1003 | * @param {string?} [options.customPrompt=null] - The custom prompt to use for classification. |
| 992 | * @returns {Promise<string?>} - The label of the expression. | 1004 | * @returns {Promise<string?>} - The label of the expression. |
| 993 | */ | 1005 | */ |
| 994 | export async function getExpressionLabel(text, expressionsApi = extension_settings.expressions.api, { customPrompt = null } = {}) { | 1006 | export async function getExpressionLabel(text, expressionsApi = extension_settings.expressions.api, { filterAvailable = null, customPrompt = null } = {}) { |
| 995 | // Return if text is undefined, saving a costly fetch request | 1007 | // Return if text is undefined, saving a costly fetch request |
| 996 | if ((!modules.includes('classify') && expressionsApi == EXPRESSION_API.extras) || !text) { | 1008 | if ((!modules.includes('classify') && expressionsApi == EXPRESSION_API.extras) || !text) { |
| 997 | return extension_settings.expressions.fallback_expression; | 1009 | return extension_settings.expressions.fallback_expression; |
| @@ -1003,6 +1015,11 @@ export async function getExpressionLabel(text, expressionsApi = extension_settin | |||
| 1003 | 1015 | ||
| 1004 | text = sampleClassifyText(text); | 1016 | text = sampleClassifyText(text); |
| 1005 | 1017 | ||
| 1018 | filterAvailable ??= extension_settings.expressions.filterAvailable; | ||
| 1019 | if (filterAvailable && ![EXPRESSION_API.llm, EXPRESSION_API.webllm].includes(expressionsApi)) { | ||
| 1020 | console.debug('Filter available is only supported for LLM and WebLLM expressions'); | ||
| 1021 | } | ||
| 1022 | |||
| 1006 | try { | 1023 | try { |
| 1007 | switch (expressionsApi) { | 1024 | switch (expressionsApi) { |
| 1008 | // Local BERT pipeline | 1025 | // Local BERT pipeline |
| @@ -1027,7 +1044,7 @@ export async function getExpressionLabel(text, expressionsApi = extension_settin | |||
| 1027 | return extension_settings.expressions.fallback_expression; | 1044 | return extension_settings.expressions.fallback_expression; |
| 1028 | } | 1045 | } |
| 1029 | 1046 | ||
| 1030 | const expressionsList = await getExpressionsList(); | 1047 | const expressionsList = await getExpressionsList({ filterAvailable: filterAvailable }); |
| 1031 | const prompt = substituteParamsExtended(customPrompt, { labels: expressionsList }) || await getLlmPrompt(expressionsList); | 1048 | const prompt = substituteParamsExtended(customPrompt, { labels: expressionsList }) || await getLlmPrompt(expressionsList); |
| 1032 | eventSource.once(event_types.TEXT_COMPLETION_SETTINGS_READY, onTextGenSettingsReady); | 1049 | eventSource.once(event_types.TEXT_COMPLETION_SETTINGS_READY, onTextGenSettingsReady); |
| 1033 | const emotionResponse = await generateRaw(text, main_api, false, false, prompt); | 1050 | const emotionResponse = await generateRaw(text, main_api, false, false, prompt); |
| @@ -1040,7 +1057,7 @@ export async function getExpressionLabel(text, expressionsApi = extension_settin | |||
| 1040 | return extension_settings.expressions.fallback_expression; | 1057 | return extension_settings.expressions.fallback_expression; |
| 1041 | } | 1058 | } |
| 1042 | 1059 | ||
| 1043 | const expressionsList = await getExpressionsList(); | 1060 | const expressionsList = await getExpressionsList({ filterAvailable: filterAvailable }); |
| 1044 | const prompt = substituteParamsExtended(customPrompt, { labels: expressionsList }) || await getLlmPrompt(expressionsList); | 1061 | const prompt = substituteParamsExtended(customPrompt, { labels: expressionsList }) || await getLlmPrompt(expressionsList); |
| 1045 | const messages = [ | 1062 | const messages = [ |
| 1046 | { role: 'user', content: text + '\n\n' + prompt }, | 1063 | { role: 'user', content: text + '\n\n' + prompt }, |
| @@ -1050,7 +1067,7 @@ export async function getExpressionLabel(text, expressionsApi = extension_settin | |||
| 1050 | return parseLlmResponse(emotionResponse, expressionsList); | 1067 | return parseLlmResponse(emotionResponse, expressionsList); |
| 1051 | } | 1068 | } |
| 1052 | // Extras | 1069 | // Extras |
| 1053 | default: { | 1070 | case EXPRESSION_API.extras: { |
| 1054 | const url = new URL(getApiUrl()); | 1071 | const url = new URL(getApiUrl()); |
| 1055 | url.pathname = '/api/classify'; | 1072 | url.pathname = '/api/classify'; |
| 1056 | 1073 | ||
| @@ -1068,6 +1085,15 @@ export async function getExpressionLabel(text, expressionsApi = extension_settin | |||
| 1068 | return data.classification[0].label; | 1085 | return data.classification[0].label; |
| 1069 | } | 1086 | } |
| 1070 | } break; | 1087 | } break; |
| 1088 | // None | ||
| 1089 | case EXPRESSION_API.none: { | ||
| 1090 | // Return empty, the fallback expression will be used | ||
| 1091 | return ''; | ||
| 1092 | } | ||
| 1093 | default: { | ||
| 1094 | toastr.error('Invalid API selected'); | ||
| 1095 | return ''; | ||
| 1096 | } | ||
| 1071 | } | 1097 | } |
| 1072 | } catch (error) { | 1098 | } catch (error) { |
| 1073 | toastr.error('Could not classify expression. Check the console or your backend for more information.'); | 1099 | toastr.error('Could not classify expression. Check the console or your backend for more information.'); |
| @@ -1320,12 +1346,28 @@ function getCachedExpressions() { | |||
| 1320 | return [...expressionsList, ...extension_settings.expressions.custom].filter(onlyUnique); | 1346 | return [...expressionsList, ...extension_settings.expressions.custom].filter(onlyUnique); |
| 1321 | } | 1347 | } |
| 1322 | 1348 | ||
| 1323 | export async function getExpressionsList() { | 1349 | export async function getExpressionsList({ filterAvailable = false } = {}) { |
| 1324 | // Return cached list if available | 1350 | // If there is no cached list, load and cache it |
| 1325 | if (Array.isArray(expressionsList)) { | 1351 | if (!Array.isArray(expressionsList)) { |
| 1326 | return getCachedExpressions(); | 1352 | expressionsList = await resolveExpressionsList(); |
| 1353 | } | ||
| 1354 | |||
| 1355 | const expressions = getCachedExpressions(); | ||
| 1356 | |||
| 1357 | // Filtering is only available for llm and webllm APIs | ||
| 1358 | if (!filterAvailable || ![EXPRESSION_API.llm, EXPRESSION_API.webllm].includes(extension_settings.expressions.api)) { | ||
| 1359 | return expressions; | ||
| 1327 | } | 1360 | } |
| 1328 | 1361 | ||
| 1362 | // Get expressions with available sprites | ||
| 1363 | const currentLastMessage = selected_group ? getLastCharacterMessage() : null; | ||
| 1364 | const spriteFolderName = getSpriteFolderName(currentLastMessage, currentLastMessage?.name); | ||
| 1365 | |||
| 1366 | return expressions.filter(label => { | ||
| 1367 | const expression = spriteCache[spriteFolderName]?.find(x => x.label === label); | ||
| 1368 | return (expression?.files.length ?? 0) > 0; | ||
| 1369 | }); | ||
| 1370 | |||
| 1329 | /** | 1371 | /** |
| 1330 | * Returns the list of expressions from the API or fallback in offline mode. | 1372 | * Returns the list of expressions from the API or fallback in offline mode. |
| 1331 | * @returns {Promise<string[]>} | 1373 | * @returns {Promise<string[]>} |
| @@ -1372,9 +1414,6 @@ export async function getExpressionsList() { | |||
| 1372 | expressionsList = DEFAULT_EXPRESSIONS.slice(); | 1414 | expressionsList = DEFAULT_EXPRESSIONS.slice(); |
| 1373 | return expressionsList; | 1415 | return expressionsList; |
| 1374 | } | 1416 | } |
| 1375 | |||
| 1376 | const result = await resolveExpressionsList(); | ||
| 1377 | return [...result, ...extension_settings.expressions.custom].filter(onlyUnique); | ||
| 1378 | } | 1417 | } |
| 1379 | 1418 | ||
| 1380 | /** | 1419 | /** |
| @@ -2036,7 +2075,7 @@ async function fetchImagesNoCache() { | |||
| 2036 | 2075 | ||
| 2037 | function migrateSettings() { | 2076 | function migrateSettings() { |
| 2038 | if (extension_settings.expressions.api === undefined) { | 2077 | if (extension_settings.expressions.api === undefined) { |
| 2039 | extension_settings.expressions.api = EXPRESSION_API.extras; | 2078 | extension_settings.expressions.api = EXPRESSION_API.none; |
| 2040 | saveSettingsDebounced(); | 2079 | saveSettingsDebounced(); |
| 2041 | } | 2080 | } |
| 2042 | 2081 | ||
| @@ -2102,6 +2141,10 @@ function migrateSettings() { | |||
| 2102 | extension_settings.expressions.rerollIfSame = !!$(this).prop('checked'); | 2141 | extension_settings.expressions.rerollIfSame = !!$(this).prop('checked'); |
| 2103 | saveSettingsDebounced(); | 2142 | saveSettingsDebounced(); |
| 2104 | }); | 2143 | }); |
| 2144 | $('#expressions_filter_available').prop('checked', extension_settings.expressions.filterAvailable).on('input', function () { | ||
| 2145 | extension_settings.expressions.filterAvailable = !!$(this).prop('checked'); | ||
| 2146 | saveSettingsDebounced(); | ||
| 2147 | }); | ||
| 2105 | $('#expression_override_cleanup_button').on('click', onClickExpressionOverrideRemoveAllButton); | 2148 | $('#expression_override_cleanup_button').on('click', onClickExpressionOverrideRemoveAllButton); |
| 2106 | $(document).on('dragstart', '.expression', (e) => { | 2149 | $(document).on('dragstart', '.expression', (e) => { |
| 2107 | e.preventDefault(); | 2150 | e.preventDefault(); |
| @@ -2114,7 +2157,7 @@ function migrateSettings() { | |||
| 2114 | $('#open_chat_expressions').hide(); | 2157 | $('#open_chat_expressions').hide(); |
| 2115 | 2158 | ||
| 2116 | await renderAdditionalExpressionSettings(); | 2159 | await renderAdditionalExpressionSettings(); |
| 2117 | $('#expression_api').val(extension_settings.expressions.api ?? EXPRESSION_API.extras); | 2160 | $('#expression_api').val(extension_settings.expressions.api ?? EXPRESSION_API.none); |
| 2118 | $('.expression_llm_prompt_block').toggle([EXPRESSION_API.llm, EXPRESSION_API.webllm].includes(extension_settings.expressions.api)); | 2161 | $('.expression_llm_prompt_block').toggle([EXPRESSION_API.llm, EXPRESSION_API.webllm].includes(extension_settings.expressions.api)); |
| 2119 | $('#expression_llm_prompt').val(extension_settings.expressions.llmPrompt ?? ''); | 2162 | $('#expression_llm_prompt').val(extension_settings.expressions.llmPrompt ?? ''); |
| 2120 | $('#expression_llm_prompt').on('input', function () { | 2163 | $('#expression_llm_prompt').on('input', function () { |
| @@ -2154,7 +2197,7 @@ function migrateSettings() { | |||
| 2154 | imgElement.src = ''; | 2197 | imgElement.src = ''; |
| 2155 | } | 2198 | } |
| 2156 | 2199 | ||
| 2157 | setExpressionOverrideHtml(); | 2200 | setExpressionOverrideHtml(true); // force-clear, as the character might not have an override defined |
| 2158 | 2201 | ||
| 2159 | if (isVisualNovelMode()) { | 2202 | if (isVisualNovelMode()) { |
| 2160 | $('#visual-novel-wrapper').empty(); | 2203 | $('#visual-novel-wrapper').empty(); |
| @@ -2279,13 +2322,13 @@ function migrateSettings() { | |||
| 2279 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | 2322 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| 2280 | name: 'expression-list', | 2323 | name: 'expression-list', |
| 2281 | aliases: ['expressions'], | 2324 | aliases: ['expressions'], |
| 2282 | /** @type {(args: {return: string}) => Promise<string>} */ | 2325 | /** @type {(args: {return: string, filter: string}) => Promise<string>} */ |
| 2283 | callback: async (args) => { | 2326 | callback: async (args) => { |
| 2284 | let returnType = | 2327 | let returnType = |
| 2285 | /** @type {import('../../slash-commands/SlashCommandReturnHelper.js').SlashCommandReturnType} */ | 2328 | /** @type {import('../../slash-commands/SlashCommandReturnHelper.js').SlashCommandReturnType} */ |
| 2286 | (args.return); | 2329 | (args.return); |
| 2287 | 2330 | ||
| 2288 | const list = await getExpressionsList(); | 2331 | const list = await getExpressionsList({ filterAvailable: !isFalseBoolean(args.filter) }); |
| 2289 | 2332 | ||
| 2290 | return await slashCommandReturnHelper.doReturn(returnType ?? 'pipe', list, { objectToStringFunc: list => list.join(', ') }); | 2333 | return await slashCommandReturnHelper.doReturn(returnType ?? 'pipe', list, { objectToStringFunc: list => list.join(', ') }); |
| 2291 | }, | 2334 | }, |
| @@ -2298,6 +2341,13 @@ function migrateSettings() { | |||
| 2298 | enumList: slashCommandReturnHelper.enumList({ allowObject: true }), | 2341 | enumList: slashCommandReturnHelper.enumList({ allowObject: true }), |
| 2299 | forceEnum: true, | 2342 | forceEnum: true, |
| 2300 | }), | 2343 | }), |
| 2344 | SlashCommandNamedArgument.fromProps({ | ||
| 2345 | name: 'filter', | ||
| 2346 | description: 'Filter the list to only include expressions that have available sprites for the current character.', | ||
| 2347 | typeList: [ARGUMENT_TYPE.BOOLEAN], | ||
| 2348 | enumList: commonEnumProviders.boolean('trueFalse')(), | ||
| 2349 | defaultValue: 'true', | ||
| 2350 | }), | ||
| 2301 | ], | 2351 | ], |
| 2302 | returns: 'The comma-separated list of available expressions, including custom expressions.', | 2352 | returns: 'The comma-separated list of available expressions, including custom expressions.', |
| 2303 | helpString: 'Returns a list of available expressions, including custom expressions.', | 2353 | helpString: 'Returns a list of available expressions, including custom expressions.', |
| @@ -2314,6 +2364,13 @@ function migrateSettings() { | |||
| 2314 | enumList: Object.keys(EXPRESSION_API).map(api => new SlashCommandEnumValue(api, null, enumTypes.enum)), | 2364 | enumList: Object.keys(EXPRESSION_API).map(api => new SlashCommandEnumValue(api, null, enumTypes.enum)), |
| 2315 | }), | 2365 | }), |
| 2316 | SlashCommandNamedArgument.fromProps({ | 2366 | SlashCommandNamedArgument.fromProps({ |
| 2367 | name: 'filter', | ||
| 2368 | description: 'Filter the list to only include expressions that have available sprites for the current character.', | ||
| 2369 | typeList: [ARGUMENT_TYPE.BOOLEAN], | ||
| 2370 | enumList: commonEnumProviders.boolean('trueFalse')(), | ||
| 2371 | defaultValue: 'true', | ||
| 2372 | }), | ||
| 2373 | SlashCommandNamedArgument.fromProps({ | ||
| 2317 | name: 'prompt', | 2374 | name: 'prompt', |
| 2318 | description: 'Custom prompt for classification. Only relevant if Classifier API is set to LLM.', | 2375 | description: 'Custom prompt for classification. Only relevant if Classifier API is set to LLM.', |
| 2319 | typeList: [ARGUMENT_TYPE.STRING], | 2376 | typeList: [ARGUMENT_TYPE.STRING], |
| @@ -22,6 +22,7 @@ | |||
| 22 | <label for="expression_api" data-i18n="Classifier API">Classifier API</label> | 22 | <label for="expression_api" data-i18n="Classifier API">Classifier API</label> |
| 23 | <small data-i18n="Select the API for classifying expressions.">Select the API for classifying expressions.</small> | 23 | <small data-i18n="Select the API for classifying expressions.">Select the API for classifying expressions.</small> |
| 24 | <select id="expression_api" class="flex1 margin0"> | 24 | <select id="expression_api" class="flex1 margin0"> |
| 25 | <option value="99" data-i18n="[ None ]">[ None ]</option> | ||
| 25 | <option value="0" data-i18n="Local">Local</option> | 26 | <option value="0" data-i18n="Local">Local</option> |
| 26 | <option value="1" data-i18n="Extras">Extras (deprecated)</option> | 27 | <option value="1" data-i18n="Extras">Extras (deprecated)</option> |
| 27 | <option value="2" data-i18n="Main API">Main API</option> | 28 | <option value="2" data-i18n="Main API">Main API</option> |
| @@ -29,7 +30,11 @@ | |||
| 29 | </select> | 30 | </select> |
| 30 | </div> | 31 | </div> |
| 31 | <div class="expression_llm_prompt_block m-b-1 m-t-1"> | 32 | <div class="expression_llm_prompt_block m-b-1 m-t-1"> |
| 32 | <label for="expression_llm_prompt" class="title_restorable"> | 33 | <label class="checkbox_label" for="expressions_filter_available" title="When using LLM or WebLLM classifier, only show and use expressions that have sprites assigned to them." data-i18n="[title]When using LLM or WebLLM classifier, only show and use expressions that have sprites assigned to them."> |
| 34 | <input id="expressions_filter_available" type="checkbox"> | ||
| 35 | <span data-i18n="Filter expressions for available sprites">Filter expressions for available sprites</span> | ||
| 36 | </label> | ||
| 37 | <label for="expression_llm_prompt" class="title_restorable m-t-1"> | ||
| 33 | <span data-i18n="LLM Prompt">LLM Prompt</span> | 38 | <span data-i18n="LLM Prompt">LLM Prompt</span> |
| 34 | <div id="expression_llm_prompt_restore" title="Restore default value" class="right_menu_button"> | 39 | <div id="expression_llm_prompt_restore" title="Restore default value" class="right_menu_button"> |
| 35 | <i class="fa-solid fa-clock-rotate-left fa-sm"></i> | 40 | <i class="fa-solid fa-clock-rotate-left fa-sm"></i> |
| @@ -132,7 +132,7 @@ | |||
| 132 | </label> | 132 | </label> |
| 133 | <label class="flex-container alignItemsCenter" title="How many messages before the current end of the chat." data-i18n="[title]How many messages before the current end of the chat."> | 133 | <label class="flex-container alignItemsCenter" title="How many messages before the current end of the chat." data-i18n="[title]How many messages before the current end of the chat."> |
| 134 | <input type="radio" name="memory_position" value="1" /> | 134 | <input type="radio" name="memory_position" value="1" /> |
| 135 | <span data-i18n="In-chat @ Depth">In-chat @ Depth</span> <input id="memory_depth" class="text_pole widthUnset" type="number" min="0" max="999" /> | 135 | <span data-i18n="In-chat @ Depth">In-chat @ Depth</span> <input id="memory_depth" class="text_pole widthUnset" type="number" min="0" max="9999" /> |
| 136 | <span data-i18n="as">as</span> | 136 | <span data-i18n="as">as</span> |
| 137 | <select id="memory_role" class="text_pole widthNatural"> | 137 | <select id="memory_role" class="text_pole widthNatural"> |
| 138 | <option value="0" data-i18n="System">System</option> | 138 | <option value="0" data-i18n="System">System</option> |
| @@ -1,21 +1,18 @@ | |||
| 1 | // eslint-disable-next-line no-unused-vars | ||
| 2 | import { QuickReply } from '../src/QuickReply.js'; | 1 | import { QuickReply } from '../src/QuickReply.js'; |
| 3 | import { QuickReplyContextLink } from '../src/QuickReplyContextLink.js'; | 2 | import { QuickReplyContextLink } from '../src/QuickReplyContextLink.js'; |
| 4 | import { QuickReplySet } from '../src/QuickReplySet.js'; | 3 | import { QuickReplySet } from '../src/QuickReplySet.js'; |
| 5 | // eslint-disable-next-line no-unused-vars | ||
| 6 | import { QuickReplySettings } from '../src/QuickReplySettings.js'; | 4 | import { QuickReplySettings } from '../src/QuickReplySettings.js'; |
| 7 | // eslint-disable-next-line no-unused-vars | ||
| 8 | import { SettingsUi } from '../src/ui/SettingsUi.js'; | 5 | import { SettingsUi } from '../src/ui/SettingsUi.js'; |
| 9 | import { onlyUnique } from '../../../utils.js'; | 6 | import { onlyUnique } from '../../../utils.js'; |
| 10 | 7 | ||
| 11 | export class QuickReplyApi { | 8 | export class QuickReplyApi { |
| 12 | /**@type {QuickReplySettings}*/ settings; | 9 | /** @type {QuickReplySettings} */ settings; |
| 13 | /**@type {SettingsUi}*/ settingsUi; | 10 | /** @type {SettingsUi} */ settingsUi; |
| 14 | 11 | ||
| 15 | 12 | ||
| 16 | 13 | ||
| 17 | 14 | ||
| 18 | constructor(/**@type {QuickReplySettings}*/settings, /**@type {SettingsUi}*/settingsUi) { | 15 | constructor(/** @type {QuickReplySettings} */settings, /** @type {SettingsUi} */settingsUi) { |
| 19 | this.settings = settings; | 16 | this.settings = settings; |
| 20 | this.settingsUi = settingsUi; | 17 | this.settingsUi = settingsUi; |
| 21 | } | 18 | } |
| @@ -1,18 +1,16 @@ | |||
| 1 | import { warn } from '../index.js'; | 1 | import { warn } from '../index.js'; |
| 2 | // eslint-disable-next-line no-unused-vars | ||
| 3 | import { QuickReply } from './QuickReply.js'; | 2 | import { QuickReply } from './QuickReply.js'; |
| 4 | // eslint-disable-next-line no-unused-vars | ||
| 5 | import { QuickReplySettings } from './QuickReplySettings.js'; | 3 | import { QuickReplySettings } from './QuickReplySettings.js'; |
| 6 | 4 | ||
| 7 | export class AutoExecuteHandler { | 5 | export class AutoExecuteHandler { |
| 8 | /**@type {QuickReplySettings}*/ settings; | 6 | /** @type {QuickReplySettings} */ settings; |
| 9 | 7 | ||
| 10 | /**@type {Boolean[]}*/ preventAutoExecuteStack = []; | 8 | /** @type {Boolean[]}*/ preventAutoExecuteStack = []; |
| 11 | 9 | ||
| 12 | 10 | ||
| 13 | 11 | ||
| 14 | 12 | ||
| 15 | constructor(/**@type {QuickReplySettings}*/settings) { | 13 | constructor(/** @type {QuickReplySettings} */settings) { |
| 16 | this.settings = settings; | 14 | this.settings = settings; |
| 17 | } | 15 | } |
| 18 | 16 | ||
| @@ -24,7 +22,7 @@ export class AutoExecuteHandler { | |||
| 24 | 22 | ||
| 25 | 23 | ||
| 26 | 24 | ||
| 27 | async performAutoExecute(/**@type {QuickReply[]}*/qrList) { | 25 | async performAutoExecute(/** @type {QuickReply[]} */qrList) { |
| 28 | for (const qr of qrList) { | 26 | for (const qr of qrList) { |
| 29 | this.preventAutoExecuteStack.push(qr.preventAutoExecute); | 27 | this.preventAutoExecuteStack.push(qr.preventAutoExecute); |
| 30 | try { | 28 | try { |
| @@ -49,7 +49,7 @@ export class QuickReply { | |||
| 49 | /**@type {string}*/ automationId = ''; | 49 | /**@type {string}*/ automationId = ''; |
| 50 | 50 | ||
| 51 | /**@type {function}*/ onExecute; | 51 | /**@type {function}*/ onExecute; |
| 52 | /**@type {(qr:QuickReply)=>AsyncGenerator<SlashCommandClosureResult|{closure:SlashCommandClosure, executor:SlashCommandExecutor|SlashCommandClosureResult}, SlashCommandClosureResult, boolean>}*/ onDebug; | 52 | /** @type {(qr:QuickReply)=>AsyncGenerator<SlashCommandClosureResult|{closure:SlashCommandClosure, executor:SlashCommandExecutor|SlashCommandClosureResult}, SlashCommandClosureResult, boolean>} */ onDebug; |
| 53 | /**@type {function}*/ onDelete; | 53 | /**@type {function}*/ onDelete; |
| 54 | /**@type {function}*/ onUpdate; | 54 | /**@type {function}*/ onUpdate; |
| 55 | /**@type {function}*/ onInsertBefore; | 55 | /**@type {function}*/ onInsertBefore; |
| @@ -635,7 +635,6 @@ export class QuickReply { | |||
| 635 | }, { passive:true }); | 635 | }, { passive:true }); |
| 636 | const getLineStart = ()=>{ | 636 | const getLineStart = ()=>{ |
| 637 | const start = message.selectionStart; | 637 | const start = message.selectionStart; |
| 638 | const end = message.selectionEnd; | ||
| 639 | let lineStart; | 638 | let lineStart; |
| 640 | if (start == 0 || message.value[start - 1] == '\n') { | 639 | if (start == 0 || message.value[start - 1] == '\n') { |
| 641 | // cursor is already at beginning of line | 640 | // cursor is already at beginning of line |
| @@ -701,7 +700,6 @@ export class QuickReply { | |||
| 701 | } else if (evt.key == 'Enter' && !evt.ctrlKey && !evt.shiftKey && !evt.altKey && !(ac.isReplaceable && ac.isActive)) { | 700 | } else if (evt.key == 'Enter' && !evt.ctrlKey && !evt.shiftKey && !evt.altKey && !(ac.isReplaceable && ac.isActive)) { |
| 702 | // new line, keep indent | 701 | // new line, keep indent |
| 703 | const start = message.selectionStart; | 702 | const start = message.selectionStart; |
| 704 | const end = message.selectionEnd; | ||
| 705 | let lineStart = getLineStart(); | 703 | let lineStart = getLineStart(); |
| 706 | const indent = /^([^\S\n]*)/.exec(message.value.slice(lineStart))[1] ?? ''; | 704 | const indent = /^([^\S\n]*)/.exec(message.value.slice(lineStart))[1] ?? ''; |
| 707 | if (indent.length) { | 705 | if (indent.length) { |
| @@ -8,18 +8,17 @@ import { SlashCommandEnumValue, enumTypes } from '../../../slash-commands/SlashC | |||
| 8 | import { SlashCommandParser } from '../../../slash-commands/SlashCommandParser.js'; | 8 | import { SlashCommandParser } from '../../../slash-commands/SlashCommandParser.js'; |
| 9 | import { SlashCommandScope } from '../../../slash-commands/SlashCommandScope.js'; | 9 | import { SlashCommandScope } from '../../../slash-commands/SlashCommandScope.js'; |
| 10 | import { isTrueBoolean } from '../../../utils.js'; | 10 | import { isTrueBoolean } from '../../../utils.js'; |
| 11 | // eslint-disable-next-line no-unused-vars | ||
| 12 | import { QuickReplyApi } from '../api/QuickReplyApi.js'; | 11 | import { QuickReplyApi } from '../api/QuickReplyApi.js'; |
| 13 | import { QuickReply } from './QuickReply.js'; | 12 | import { QuickReply } from './QuickReply.js'; |
| 14 | import { QuickReplySet } from './QuickReplySet.js'; | 13 | import { QuickReplySet } from './QuickReplySet.js'; |
| 15 | 14 | ||
| 16 | export class SlashCommandHandler { | 15 | export class SlashCommandHandler { |
| 17 | /**@type {QuickReplyApi}*/ api; | 16 | /** @type {QuickReplyApi} */ api; |
| 18 | 17 | ||
| 19 | 18 | ||
| 20 | 19 | ||
| 21 | 20 | ||
| 22 | constructor(/**@type {QuickReplyApi}*/api) { | 21 | constructor(/** @type {QuickReplyApi} */api) { |
| 23 | this.api = api; | 22 | this.api = api; |
| 24 | } | 23 | } |
| 25 | 24 | ||
| @@ -27,7 +26,7 @@ export class SlashCommandHandler { | |||
| 27 | 26 | ||
| 28 | 27 | ||
| 29 | init() { | 28 | init() { |
| 30 | function getExecutionIcons(/**@type {QuickReply} */ qr) { | 29 | function getExecutionIcons(/** @type {QuickReply} */ qr) { |
| 31 | let icons = ''; | 30 | let icons = ''; |
| 32 | if (qr.preventAutoExecute) icons += '🚫'; | 31 | if (qr.preventAutoExecute) icons += '🚫'; |
| 33 | if (qr.isHidden) icons += '👁️'; | 32 | if (qr.isHidden) icons += '👁️'; |
| @@ -1,11 +1,10 @@ | |||
| 1 | import { animation_duration } from '../../../../../script.js'; | 1 | import { animation_duration } from '../../../../../script.js'; |
| 2 | import { dragElement } from '../../../../RossAscends-mods.js'; | 2 | import { dragElement } from '../../../../RossAscends-mods.js'; |
| 3 | import { loadMovingUIState } from '../../../../power-user.js'; | 3 | import { loadMovingUIState } from '../../../../power-user.js'; |
| 4 | // eslint-disable-next-line no-unused-vars | ||
| 5 | import { QuickReplySettings } from '../QuickReplySettings.js'; | 4 | import { QuickReplySettings } from '../QuickReplySettings.js'; |
| 6 | 5 | ||
| 7 | export class ButtonUi { | 6 | export class ButtonUi { |
| 8 | /**@type {QuickReplySettings}*/ settings; | 7 | /** @type {QuickReplySettings} */ settings; |
| 9 | 8 | ||
| 10 | /**@type {HTMLElement}*/ dom; | 9 | /**@type {HTMLElement}*/ dom; |
| 11 | /**@type {HTMLElement}*/ popoutDom; | 10 | /**@type {HTMLElement}*/ popoutDom; |
| @@ -3,14 +3,13 @@ import { getSortableDelay } from '../../../../utils.js'; | |||
| 3 | import { log, warn } from '../../index.js'; | 3 | import { log, warn } from '../../index.js'; |
| 4 | import { QuickReply } from '../QuickReply.js'; | 4 | import { QuickReply } from '../QuickReply.js'; |
| 5 | import { QuickReplySet } from '../QuickReplySet.js'; | 5 | import { QuickReplySet } from '../QuickReplySet.js'; |
| 6 | // eslint-disable-next-line no-unused-vars | ||
| 7 | import { QuickReplySettings } from '../QuickReplySettings.js'; | 6 | import { QuickReplySettings } from '../QuickReplySettings.js'; |
| 8 | 7 | ||
| 9 | export class SettingsUi { | 8 | export class SettingsUi { |
| 10 | /**@type {QuickReplySettings}*/ settings; | 9 | /** @type {QuickReplySettings} */ settings; |
| 11 | 10 | ||
| 12 | /**@type {HTMLElement}*/ template; | 11 | /** @type {HTMLElement} */ template; |
| 13 | /**@type {HTMLElement}*/ dom; | 12 | /** @type {HTMLElement} */ dom; |
| 14 | 13 | ||
| 15 | /**@type {HTMLInputElement}*/ isEnabled; | 14 | /**@type {HTMLInputElement}*/ isEnabled; |
| 16 | /**@type {HTMLInputElement}*/ isCombined; | 15 | /**@type {HTMLInputElement}*/ isCombined; |
| @@ -1,5 +1,4 @@ | |||
| 1 | import { QuickReply } from '../../QuickReply.js'; | 1 | import { QuickReply } from '../../QuickReply.js'; |
| 2 | // eslint-disable-next-line no-unused-vars | ||
| 3 | import { QuickReplySet } from '../../QuickReplySet.js'; | 2 | import { QuickReplySet } from '../../QuickReplySet.js'; |
| 4 | import { MenuHeader } from './MenuHeader.js'; | 3 | import { MenuHeader } from './MenuHeader.js'; |
| 5 | import { MenuItem } from './MenuItem.js'; | 4 | import { MenuItem } from './MenuItem.js'; |
| @@ -18,9 +18,8 @@ | |||
| 18 | 18 | ||
| 19 | <div id="regex_info_block_wrapper"> | 19 | <div id="regex_info_block_wrapper"> |
| 20 | <div id="regex_info_block" class="info-block"></div> | 20 | <div id="regex_info_block" class="info-block"></div> |
| 21 | <!-- TODO replace 3rd-party link with our own docs when it's done --> | 21 | <a id="regex_info_block_flags_hint" href="https://docs.sillytavern.app/extensions/regex/#flags" target="_blank" rel="noopener noreferrer"> |
| 22 | <a id="regex_info_block_flags_hint" href="http://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#advanced_searching_with_flags" target="_blank" rel="noopener noreferrer"> | 22 | <i class="fa-solid fa-circle-info" data-i18n="[title]ext_regex_flags_help" title="Click here to learn more about regex flags."></i> |
| 23 | <i class="fa-solid fa-circle-info" title="Click here to learn more about regex flags."></i> | ||
| 24 | </a> | 23 | </a> |
| 25 | </div> | 24 | </div> |
| 26 | 25 | ||
| @@ -114,14 +113,14 @@ | |||
| 114 | <span data-i18n="Min Depth">Min Depth</span> | 113 | <span data-i18n="Min Depth">Min Depth</span> |
| 115 | <span class="fa-solid fa-circle-question note-link-span"></span> | 114 | <span class="fa-solid fa-circle-question note-link-span"></span> |
| 116 | </small> | 115 | </small> |
| 117 | <input name="min_depth" class="text_pole textarea_compact" type="number" min="-1" max="999" data-i18n="[placeholder]ext_regex_min_depth_placeholder" placeholder="Unlimited" /> | 116 | <input name="min_depth" class="text_pole textarea_compact" type="number" min="-1" max="9999" data-i18n="[placeholder]ext_regex_min_depth_placeholder" placeholder="Unlimited" /> |
| 118 | </div> | 117 | </div> |
| 119 | <div class="flex1 flex-container flexNoGap"> | 118 | <div class="flex1 flex-container flexNoGap"> |
| 120 | <small data-i18n="[title]ext_regex_max_depth_desc" title="When applied to prompts or display, only affect messages no more than N levels deep. 0 = last message, 1 = penultimate message, etc. System prompt and utility prompts are not affected. Max must be greater than Min for regex to apply."> | 119 | <small data-i18n="[title]ext_regex_max_depth_desc" title="When applied to prompts or display, only affect messages no more than N levels deep. 0 = last message, 1 = penultimate message, etc. System prompt and utility prompts are not affected. Max must be greater than Min for regex to apply."> |
| 121 | <span data-i18n="Max Depth">Max Depth</span> | 120 | <span data-i18n="Max Depth">Max Depth</span> |
| 122 | <span class="fa-solid fa-circle-question note-link-span"></span> | 121 | <span class="fa-solid fa-circle-question note-link-span"></span> |
| 123 | </small> | 122 | </small> |
| 124 | <input name="max_depth" class="text_pole textarea_compact" type="number" min="0" max="999" data-i18n="[placeholder]ext_regex_min_depth_placeholder" placeholder="Unlimited" /> | 123 | <input name="max_depth" class="text_pole textarea_compact" type="number" min="0" max="9999" data-i18n="[placeholder]ext_regex_min_depth_placeholder" placeholder="Unlimited" /> |
| 125 | </div> | 124 | </div> |
| 126 | </div> | 125 | </div> |
| 127 | </div> | 126 | </div> |
| @@ -148,7 +147,7 @@ | |||
| 148 | </label> | 147 | </label> |
| 149 | <span> | 148 | <span> |
| 150 | <small data-i18n="ext_regex_other_options" data-i18n="Ephemerality">Ephemerality</small> | 149 | <small data-i18n="ext_regex_other_options" data-i18n="Ephemerality">Ephemerality</small> |
| 151 | <span class="fa-solid fa-circle-question note-link-span" title="By default, regex scripts alter the chat file directly and irreversibly. Enabling either (or both) of the options below will prevent chat file alteration, while still altering the specified item(s)."></span> | 150 | <span class="fa-solid fa-circle-question note-link-span" data-i18n="[title]ext_regex_other_options_desc" title="By default, regex scripts alter the chat file directly and irreversibly. Enabling either (or both) of the options below will prevent chat file alteration, while still altering the specified item(s)."></span> |
| 152 | </span> | 151 | </span> |
| 153 | <label class="checkbox flex-container" data-i18n="[title]ext_regex_only_format_visual_desc" title="Chat history file contents won't change, but regex will be applied to the messages displayed in the Chat UI."> | 152 | <label class="checkbox flex-container" data-i18n="[title]ext_regex_only_format_visual_desc" title="Chat history file contents won't change, but regex will be applied to the messages displayed in the Chat UI."> |
| 154 | <input type="checkbox" name="only_format_display" /> | 153 | <input type="checkbox" name="only_format_display" /> |
| @@ -398,7 +398,7 @@ function runRegexCallback(args, value) { | |||
| 398 | for (const script of scripts) { | 398 | for (const script of scripts) { |
| 399 | if (script.scriptName.toLowerCase() === scriptName.toLowerCase()) { | 399 | if (script.scriptName.toLowerCase() === scriptName.toLowerCase()) { |
| 400 | if (script.disabled) { | 400 | if (script.disabled) { |
| 401 | toastr.warning(`Regex script "${scriptName}" is disabled.`); | 401 | toastr.warning(t`Regex script "${scriptName}" is disabled.`); |
| 402 | return value; | 402 | return value; |
| 403 | } | 403 | } |
| 404 | 404 | ||
| @@ -1,6 +1,7 @@ | |||
| 1 | import { getRequestHeaders } from '../../script.js'; | 1 | import { CONNECT_API_MAP, getRequestHeaders } from '../../script.js'; |
| 2 | import { extension_settings, openThirdPartyExtensionMenu } from '../extensions.js'; | 2 | import { extension_settings, openThirdPartyExtensionMenu } from '../extensions.js'; |
| 3 | import { oai_settings } from '../openai.js'; | 3 | import { t } from '../i18n.js'; |
| 4 | import { oai_settings, proxies } from '../openai.js'; | ||
| 4 | import { SECRET_KEYS, secret_state } from '../secrets.js'; | 5 | import { SECRET_KEYS, secret_state } from '../secrets.js'; |
| 5 | import { textgen_types, textgenerationwebui_settings } from '../textgen-settings.js'; | 6 | import { textgen_types, textgenerationwebui_settings } from '../textgen-settings.js'; |
| 6 | import { getTokenCountAsync } from '../tokenizers.js'; | 7 | import { getTokenCountAsync } from '../tokenizers.js'; |
| @@ -152,6 +153,10 @@ function throwIfInvalidModel(useReverseProxy) { | |||
| 152 | throw new Error('Cohere API key is not set.'); | 153 | throw new Error('Cohere API key is not set.'); |
| 153 | } | 154 | } |
| 154 | 155 | ||
| 156 | if (extension_settings.caption.multimodal_api === 'xai' && !secret_state[SECRET_KEYS.XAI]) { | ||
| 157 | throw new Error('xAI API key is not set.'); | ||
| 158 | } | ||
| 159 | |||
| 155 | if (extension_settings.caption.multimodal_api === 'ollama' && !textgenerationwebui_settings.server_urls[textgen_types.OLLAMA]) { | 160 | if (extension_settings.caption.multimodal_api === 'ollama' && !textgenerationwebui_settings.server_urls[textgen_types.OLLAMA]) { |
| 156 | throw new Error('Ollama server URL is not set.'); | 161 | throw new Error('Ollama server URL is not set.'); |
| 157 | } | 162 | } |
| @@ -273,3 +278,329 @@ export async function getWebLlmContextSize() { | |||
| 273 | const model = await engine.getCurrentModelInfo(); | 278 | const model = await engine.getCurrentModelInfo(); |
| 274 | return model?.context_size; | 279 | return model?.context_size; |
| 275 | } | 280 | } |
| 281 | |||
| 282 | /** | ||
| 283 | * It uses the profiles to send a generate request to the API. | ||
| 284 | */ | ||
| 285 | export class ConnectionManagerRequestService { | ||
| 286 | static defaultSendRequestParams = { | ||
| 287 | stream: false, | ||
| 288 | signal: null, | ||
| 289 | extractData: true, | ||
| 290 | includePreset: true, | ||
| 291 | includeInstruct: true, | ||
| 292 | instructSettings: {}, | ||
| 293 | }; | ||
| 294 | |||
| 295 | static getAllowedTypes() { | ||
| 296 | return { | ||
| 297 | openai: t`Chat Completion`, | ||
| 298 | textgenerationwebui: t`Text Completion`, | ||
| 299 | }; | ||
| 300 | } | ||
| 301 | |||
| 302 | /** | ||
| 303 | * @param {string} profileId | ||
| 304 | * @param {string | (import('../custom-request.js').ChatCompletionMessage & {ignoreInstruct?: boolean})[]} prompt | ||
| 305 | * @param {number} maxTokens | ||
| 306 | * @param {Object} custom | ||
| 307 | * @param {boolean?} [custom.stream=false] | ||
| 308 | * @param {AbortSignal?} [custom.signal] | ||
| 309 | * @param {boolean?} [custom.extractData=true] | ||
| 310 | * @param {boolean?} [custom.includePreset=true] | ||
| 311 | * @param {boolean?} [custom.includeInstruct=true] | ||
| 312 | * @param {Partial<InstructSettings>?} [custom.instructSettings] Override instruct settings | ||
| 313 | * @param {Record<string, any>} [overridePayload] - Override payload for the request | ||
| 314 | * @returns {Promise<import('../custom-request.js').ExtractedData | (() => AsyncGenerator<import('../custom-request.js').StreamResponse>)>} If not streaming, returns extracted data; if streaming, returns a function that creates an AsyncGenerator | ||
| 315 | */ | ||
| 316 | static async sendRequest(profileId, prompt, maxTokens, custom = this.defaultSendRequestParams, overridePayload = {}) { | ||
| 317 | const { stream, signal, extractData, includePreset, includeInstruct, instructSettings } = { ...this.defaultSendRequestParams, ...custom }; | ||
| 318 | |||
| 319 | const context = SillyTavern.getContext(); | ||
| 320 | if (context.extensionSettings.disabledExtensions.includes('connection-manager')) { | ||
| 321 | throw new Error('Connection Manager is not available'); | ||
| 322 | } | ||
| 323 | |||
| 324 | const profile = context.extensionSettings.connectionManager.profiles.find((p) => p.id === profileId); | ||
| 325 | const selectedApiMap = this.validateProfile(profile); | ||
| 326 | |||
| 327 | try { | ||
| 328 | switch (selectedApiMap.selected) { | ||
| 329 | case 'openai': { | ||
| 330 | if (!selectedApiMap.source) { | ||
| 331 | throw new Error(`API type ${selectedApiMap.selected} does not support chat completions`); | ||
| 332 | } | ||
| 333 | |||
| 334 | const proxyPreset = proxies.find((p) => p.name === profile.proxy); | ||
| 335 | |||
| 336 | const messages = Array.isArray(prompt) ? prompt : [{ role: 'user', content: prompt }]; | ||
| 337 | return await context.ChatCompletionService.processRequest({ | ||
| 338 | stream, | ||
| 339 | messages, | ||
| 340 | max_tokens: maxTokens, | ||
| 341 | model: profile.model, | ||
| 342 | chat_completion_source: selectedApiMap.source, | ||
| 343 | custom_url: profile['api-url'], | ||
| 344 | reverse_proxy: proxyPreset?.url, | ||
| 345 | proxy_password: proxyPreset?.password, | ||
| 346 | ...overridePayload, | ||
| 347 | }, { | ||
| 348 | presetName: includePreset ? profile.preset : undefined, | ||
| 349 | }, extractData, signal); | ||
| 350 | } | ||
| 351 | case 'textgenerationwebui': { | ||
| 352 | if (!selectedApiMap.type) { | ||
| 353 | throw new Error(`API type ${selectedApiMap.selected} does not support text completions`); | ||
| 354 | } | ||
| 355 | |||
| 356 | return await context.TextCompletionService.processRequest({ | ||
| 357 | stream, | ||
| 358 | prompt, | ||
| 359 | max_tokens: maxTokens, | ||
| 360 | model: profile.model, | ||
| 361 | api_type: selectedApiMap.type, | ||
| 362 | api_server: profile['api-url'], | ||
| 363 | ...overridePayload, | ||
| 364 | }, { | ||
| 365 | instructName: includeInstruct ? profile.instruct : undefined, | ||
| 366 | presetName: includePreset ? profile.preset : undefined, | ||
| 367 | instructSettings: includeInstruct ? instructSettings : undefined, | ||
| 368 | }, extractData, signal); | ||
| 369 | } | ||
| 370 | default: { | ||
| 371 | throw new Error(`Unknown API type ${selectedApiMap.selected}`); | ||
| 372 | } | ||
| 373 | } | ||
| 374 | } catch (error) { | ||
| 375 | throw new Error('API request failed', { cause: error }); | ||
| 376 | } | ||
| 377 | } | ||
| 378 | |||
| 379 | /** | ||
| 380 | * Respects allowed types. | ||
| 381 | * @returns {import('./connection-manager/index.js').ConnectionProfile[]} | ||
| 382 | */ | ||
| 383 | static getSupportedProfiles() { | ||
| 384 | const context = SillyTavern.getContext(); | ||
| 385 | if (context.extensionSettings.disabledExtensions.includes('connection-manager')) { | ||
| 386 | throw new Error('Connection Manager is not available'); | ||
| 387 | } | ||
| 388 | |||
| 389 | const profiles = context.extensionSettings.connectionManager.profiles; | ||
| 390 | return profiles.filter((p) => this.isProfileSupported(p)); | ||
| 391 | } | ||
| 392 | |||
| 393 | /** | ||
| 394 | * @param {import('./connection-manager/index.js').ConnectionProfile?} [profile] | ||
| 395 | * @returns {boolean} | ||
| 396 | */ | ||
| 397 | static isProfileSupported(profile) { | ||
| 398 | if (!profile || !profile.api) { | ||
| 399 | return false; | ||
| 400 | } | ||
| 401 | |||
| 402 | const apiMap = CONNECT_API_MAP[profile.api]; | ||
| 403 | if (!Object.hasOwn(this.getAllowedTypes(), apiMap.selected)) { | ||
| 404 | return false; | ||
| 405 | } | ||
| 406 | |||
| 407 | // Some providers not need model, like koboldcpp. But I don't want to check by provider. | ||
| 408 | switch (apiMap.selected) { | ||
| 409 | case 'openai': | ||
| 410 | return !!apiMap.source; | ||
| 411 | case 'textgenerationwebui': | ||
| 412 | return !!apiMap.type; | ||
| 413 | } | ||
| 414 | |||
| 415 | return false; | ||
| 416 | } | ||
| 417 | |||
| 418 | /** | ||
| 419 | * @param {import('./connection-manager/index.js').ConnectionProfile?} [profile] | ||
| 420 | * @return {import('../../script.js').ConnectAPIMap} | ||
| 421 | * @throws {Error} | ||
| 422 | */ | ||
| 423 | static validateProfile(profile) { | ||
| 424 | if (!profile) { | ||
| 425 | throw new Error('Could not find profile.'); | ||
| 426 | } | ||
| 427 | if (!profile.api) { | ||
| 428 | throw new Error('Select a connection profile that has an API'); | ||
| 429 | } | ||
| 430 | |||
| 431 | const context = SillyTavern.getContext(); | ||
| 432 | const selectedApiMap = context.CONNECT_API_MAP[profile.api]; | ||
| 433 | if (!selectedApiMap) { | ||
| 434 | throw new Error(`Unknown API type ${profile.api}`); | ||
| 435 | } | ||
| 436 | if (!Object.hasOwn(this.getAllowedTypes(), selectedApiMap.selected)) { | ||
| 437 | throw new Error(`API type ${selectedApiMap.selected} is not supported. Supported types: ${Object.values(this.getAllowedTypes()).join(', ')}`); | ||
| 438 | } | ||
| 439 | |||
| 440 | return selectedApiMap; | ||
| 441 | } | ||
| 442 | |||
| 443 | /** | ||
| 444 | * Create profiles dropdown and updates select element accordingly. Use onChange, onCreate, unUpdate, onDelete callbacks for custom behaviour. e.g updating extension settings. | ||
| 445 | * @param {string} selector | ||
| 446 | * @param {string} initialSelectedProfileId | ||
| 447 | * @param {(profile?: import('./connection-manager/index.js').ConnectionProfile) => Promise<void> | void} onChange - 3 cases. 1- When user selects new profile. 2- When user deletes selected profile. 3- When user updates selected profile. | ||
| 448 | * @param {(profile: import('./connection-manager/index.js').ConnectionProfile) => Promise<void> | void} onCreate | ||
| 449 | * @param {(oldProfile: import('./connection-manager/index.js').ConnectionProfile, newProfile: import('./connection-manager/index.js').ConnectionProfile) => Promise<void> | void} unUpdate | ||
| 450 | * @param {(profile: import('./connection-manager/index.js').ConnectionProfile) => Promise<void> | void} onDelete | ||
| 451 | */ | ||
| 452 | static handleDropdown( | ||
| 453 | selector, | ||
| 454 | initialSelectedProfileId, | ||
| 455 | onChange = () => { }, | ||
| 456 | onCreate = () => { }, | ||
| 457 | unUpdate = () => { }, | ||
| 458 | onDelete = () => { }, | ||
| 459 | ) { | ||
| 460 | const context = SillyTavern.getContext(); | ||
| 461 | if (context.extensionSettings.disabledExtensions.includes('connection-manager')) { | ||
| 462 | throw new Error('Connection Manager is not available'); | ||
| 463 | } | ||
| 464 | |||
| 465 | /** | ||
| 466 | * @type {JQuery<HTMLSelectElement>} | ||
| 467 | */ | ||
| 468 | const dropdown = $(selector); | ||
| 469 | |||
| 470 | if (!dropdown || !dropdown.length) { | ||
| 471 | throw new Error(`Could not find dropdown with selector ${selector}`); | ||
| 472 | } | ||
| 473 | |||
| 474 | dropdown.empty(); | ||
| 475 | |||
| 476 | // Create default option using document.createElement | ||
| 477 | const defaultOption = document.createElement('option'); | ||
| 478 | defaultOption.value = ''; | ||
| 479 | defaultOption.textContent = 'Select a Connection Profile'; | ||
| 480 | defaultOption.dataset.i18n = 'Select a Connection Profile'; | ||
| 481 | dropdown.append(defaultOption); | ||
| 482 | |||
| 483 | const profiles = context.extensionSettings.connectionManager.profiles; | ||
| 484 | |||
| 485 | // Create optgroups using document.createElement | ||
| 486 | const groups = {}; | ||
| 487 | for (const [apiType, groupLabel] of Object.entries(this.getAllowedTypes())) { | ||
| 488 | const optgroup = document.createElement('optgroup'); | ||
| 489 | optgroup.label = groupLabel; | ||
| 490 | groups[apiType] = optgroup; | ||
| 491 | } | ||
| 492 | |||
| 493 | const sortedProfilesByGroup = {}; | ||
| 494 | for (const apiType of Object.keys(this.getAllowedTypes())) { | ||
| 495 | sortedProfilesByGroup[apiType] = []; | ||
| 496 | } | ||
| 497 | |||
| 498 | for (const profile of profiles) { | ||
| 499 | if (this.isProfileSupported(profile)) { | ||
| 500 | const apiMap = CONNECT_API_MAP[profile.api]; | ||
| 501 | if (sortedProfilesByGroup[apiMap.selected]) { | ||
| 502 | sortedProfilesByGroup[apiMap.selected].push(profile); | ||
| 503 | } | ||
| 504 | } | ||
| 505 | } | ||
| 506 | |||
| 507 | // Sort each group alphabetically and add to dropdown | ||
| 508 | for (const [apiType, groupProfiles] of Object.entries(sortedProfilesByGroup)) { | ||
| 509 | if (groupProfiles.length === 0) continue; | ||
| 510 | |||
| 511 | groupProfiles.sort((a, b) => a.name.localeCompare(b.name)); | ||
| 512 | |||
| 513 | const group = groups[apiType]; | ||
| 514 | for (const profile of groupProfiles) { | ||
| 515 | const option = document.createElement('option'); | ||
| 516 | option.value = profile.id; | ||
| 517 | option.textContent = profile.name; | ||
| 518 | group.appendChild(option); | ||
| 519 | } | ||
| 520 | } | ||
| 521 | |||
| 522 | for (const group of Object.values(groups)) { | ||
| 523 | if (group.children.length > 0) { | ||
| 524 | dropdown.append(group); | ||
| 525 | } | ||
| 526 | } | ||
| 527 | |||
| 528 | const selectedProfile = profiles.find((p) => p.id === initialSelectedProfileId); | ||
| 529 | if (selectedProfile) { | ||
| 530 | dropdown.val(selectedProfile.id); | ||
| 531 | } | ||
| 532 | |||
| 533 | context.eventSource.on(context.eventTypes.CONNECTION_PROFILE_CREATED, async (profile) => { | ||
| 534 | const isSupported = this.isProfileSupported(profile); | ||
| 535 | if (!isSupported) { | ||
| 536 | return; | ||
| 537 | } | ||
| 538 | |||
| 539 | const group = groups[CONNECT_API_MAP[profile.api].selected]; | ||
| 540 | const option = document.createElement('option'); | ||
| 541 | option.value = profile.id; | ||
| 542 | option.textContent = profile.name; | ||
| 543 | group.appendChild(option); | ||
| 544 | |||
| 545 | await onCreate(profile); | ||
| 546 | }); | ||
| 547 | |||
| 548 | context.eventSource.on(context.eventTypes.CONNECTION_PROFILE_UPDATED, async (oldProfile, newProfile) => { | ||
| 549 | const currentSelected = dropdown.val(); | ||
| 550 | const isSelectedProfile = currentSelected === oldProfile.id; | ||
| 551 | await unUpdate(oldProfile, newProfile); | ||
| 552 | |||
| 553 | if (!this.isProfileSupported(newProfile)) { | ||
| 554 | if (isSelectedProfile) { | ||
| 555 | dropdown.val(''); | ||
| 556 | dropdown.trigger('change'); | ||
| 557 | } | ||
| 558 | return; | ||
| 559 | } | ||
| 560 | |||
| 561 | const group = groups[CONNECT_API_MAP[newProfile.api].selected]; | ||
| 562 | const oldOption = group.querySelector(`option[value="${oldProfile.id}"]`); | ||
| 563 | if (oldOption) { | ||
| 564 | oldOption.remove(); | ||
| 565 | } | ||
| 566 | |||
| 567 | const option = document.createElement('option'); | ||
| 568 | option.value = newProfile.id; | ||
| 569 | option.textContent = newProfile.name; | ||
| 570 | group.appendChild(option); | ||
| 571 | |||
| 572 | if (isSelectedProfile) { | ||
| 573 | // Ackchyually, we don't need to reselect but what if id changes? It is not possible for now I couldn't stop myself. | ||
| 574 | dropdown.val(newProfile.id); | ||
| 575 | dropdown.trigger('change'); | ||
| 576 | } | ||
| 577 | }); | ||
| 578 | |||
| 579 | context.eventSource.on(context.eventTypes.CONNECTION_PROFILE_DELETED, async (profile) => { | ||
| 580 | const currentSelected = dropdown.val(); | ||
| 581 | const isSelectedProfile = currentSelected === profile.id; | ||
| 582 | if (!this.isProfileSupported(profile)) { | ||
| 583 | return; | ||
| 584 | } | ||
| 585 | |||
| 586 | const group = groups[CONNECT_API_MAP[profile.api].selected]; | ||
| 587 | const optionToRemove = group.querySelector(`option[value="${profile.id}"]`); | ||
| 588 | if (optionToRemove) { | ||
| 589 | optionToRemove.remove(); | ||
| 590 | } | ||
| 591 | |||
| 592 | if (isSelectedProfile) { | ||
| 593 | dropdown.val(''); | ||
| 594 | dropdown.trigger('change'); | ||
| 595 | } | ||
| 596 | |||
| 597 | await onDelete(profile); | ||
| 598 | }); | ||
| 599 | |||
| 600 | dropdown.on('change', async () => { | ||
| 601 | const profileId = dropdown.val(); | ||
| 602 | const profile = context.extensionSettings.connectionManager.profiles.find((p) => p.id === profileId); | ||
| 603 | await onChange(profile); | ||
| 604 | }); | ||
| 605 | } | ||
| 606 | } | ||
| @@ -77,11 +77,11 @@ const sources = { | |||
| 77 | drawthings: 'drawthings', | 77 | drawthings: 'drawthings', |
| 78 | pollinations: 'pollinations', | 78 | pollinations: 'pollinations', |
| 79 | stability: 'stability', | 79 | stability: 'stability', |
| 80 | blockentropy: 'blockentropy', | ||
| 81 | huggingface: 'huggingface', | 80 | huggingface: 'huggingface', |
| 82 | nanogpt: 'nanogpt', | 81 | nanogpt: 'nanogpt', |
| 83 | bfl: 'bfl', | 82 | bfl: 'bfl', |
| 84 | falai: 'falai', | 83 | falai: 'falai', |
| 84 | xai: 'xai', | ||
| 85 | }; | 85 | }; |
| 86 | 86 | ||
| 87 | const initiators = { | 87 | const initiators = { |
| @@ -1300,11 +1300,11 @@ async function onModelChange() { | |||
| 1300 | sources.togetherai, | 1300 | sources.togetherai, |
| 1301 | sources.pollinations, | 1301 | sources.pollinations, |
| 1302 | sources.stability, | 1302 | sources.stability, |
| 1303 | sources.blockentropy, | ||
| 1304 | sources.huggingface, | 1303 | sources.huggingface, |
| 1305 | sources.nanogpt, | 1304 | sources.nanogpt, |
| 1306 | sources.bfl, | 1305 | sources.bfl, |
| 1307 | sources.falai, | 1306 | sources.falai, |
| 1307 | sources.xai, | ||
| 1308 | ]; | 1308 | ]; |
| 1309 | 1309 | ||
| 1310 | if (cloudSources.includes(extension_settings.sd.source)) { | 1310 | if (cloudSources.includes(extension_settings.sd.source)) { |
| @@ -1511,9 +1511,6 @@ async function loadSamplers() { | |||
| 1511 | case sources.stability: | 1511 | case sources.stability: |
| 1512 | samplers = ['N/A']; | 1512 | samplers = ['N/A']; |
| 1513 | break; | 1513 | break; |
| 1514 | case sources.blockentropy: | ||
| 1515 | samplers = ['N/A']; | ||
| 1516 | break; | ||
| 1517 | case sources.huggingface: | 1514 | case sources.huggingface: |
| 1518 | samplers = ['N/A']; | 1515 | samplers = ['N/A']; |
| 1519 | break; | 1516 | break; |
| @@ -1523,6 +1520,9 @@ async function loadSamplers() { | |||
| 1523 | case sources.bfl: | 1520 | case sources.bfl: |
| 1524 | samplers = ['N/A']; | 1521 | samplers = ['N/A']; |
| 1525 | break; | 1522 | break; |
| 1523 | case sources.xai: | ||
| 1524 | samplers = ['N/A']; | ||
| 1525 | break; | ||
| 1526 | } | 1526 | } |
| 1527 | 1527 | ||
| 1528 | for (const sampler of samplers) { | 1528 | for (const sampler of samplers) { |
| @@ -1701,9 +1701,6 @@ async function loadModels() { | |||
| 1701 | case sources.stability: | 1701 | case sources.stability: |
| 1702 | models = await loadStabilityModels(); | 1702 | models = await loadStabilityModels(); |
| 1703 | break; | 1703 | break; |
| 1704 | case sources.blockentropy: | ||
| 1705 | models = await loadBlockEntropyModels(); | ||
| 1706 | break; | ||
| 1707 | case sources.huggingface: | 1704 | case sources.huggingface: |
| 1708 | models = [{ value: '', text: '<Enter Model ID above>' }]; | 1705 | models = [{ value: '', text: '<Enter Model ID above>' }]; |
| 1709 | break; | 1706 | break; |
| @@ -1716,6 +1713,9 @@ async function loadModels() { | |||
| 1716 | case sources.falai: | 1713 | case sources.falai: |
| 1717 | models = await loadFalaiModels(); | 1714 | models = await loadFalaiModels(); |
| 1718 | break; | 1715 | break; |
| 1716 | case sources.xai: | ||
| 1717 | models = await loadXAIModels(); | ||
| 1718 | break; | ||
| 1719 | } | 1719 | } |
| 1720 | 1720 | ||
| 1721 | for (const model of models) { | 1721 | for (const model of models) { |
| @@ -1768,6 +1768,12 @@ async function loadFalaiModels() { | |||
| 1768 | return []; | 1768 | return []; |
| 1769 | } | 1769 | } |
| 1770 | 1770 | ||
| 1771 | async function loadXAIModels() { | ||
| 1772 | return [ | ||
| 1773 | { value: 'grok-2-image-1212', text: 'grok-2-image-1212' }, | ||
| 1774 | ]; | ||
| 1775 | } | ||
| 1776 | |||
| 1771 | async function loadPollinationsModels() { | 1777 | async function loadPollinationsModels() { |
| 1772 | const result = await fetch('/api/sd/pollinations/models', { | 1778 | const result = await fetch('/api/sd/pollinations/models', { |
| 1773 | method: 'POST', | 1779 | method: 'POST', |
| @@ -1799,26 +1805,6 @@ async function loadTogetherAIModels() { | |||
| 1799 | return []; | 1805 | return []; |
| 1800 | } | 1806 | } |
| 1801 | 1807 | ||
| 1802 | async function loadBlockEntropyModels() { | ||
| 1803 | if (!secret_state[SECRET_KEYS.BLOCKENTROPY]) { | ||
| 1804 | console.debug('Block Entropy API key is not set.'); | ||
| 1805 | return []; | ||
| 1806 | } | ||
| 1807 | |||
| 1808 | const result = await fetch('/api/sd/blockentropy/models', { | ||
| 1809 | method: 'POST', | ||
| 1810 | headers: getRequestHeaders(), | ||
| 1811 | }); | ||
| 1812 | console.log(result); | ||
| 1813 | if (result.ok) { | ||
| 1814 | const data = await result.json(); | ||
| 1815 | console.log(data); | ||
| 1816 | return data; | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | return []; | ||
| 1820 | } | ||
| 1821 | |||
| 1822 | async function loadNanoGPTModels() { | 1808 | async function loadNanoGPTModels() { |
| 1823 | if (!secret_state[SECRET_KEYS.NANOGPT]) { | 1809 | if (!secret_state[SECRET_KEYS.NANOGPT]) { |
| 1824 | console.debug('NanoGPT API key is not set.'); | 1810 | console.debug('NanoGPT API key is not set.'); |
| @@ -2097,9 +2083,6 @@ async function loadSchedulers() { | |||
| 2097 | case sources.stability: | 2083 | case sources.stability: |
| 2098 | schedulers = ['N/A']; | 2084 | schedulers = ['N/A']; |
| 2099 | break; | 2085 | break; |
| 2100 | case sources.blockentropy: | ||
| 2101 | schedulers = ['N/A']; | ||
| 2102 | break; | ||
| 2103 | case sources.huggingface: | 2086 | case sources.huggingface: |
| 2104 | schedulers = ['N/A']; | 2087 | schedulers = ['N/A']; |
| 2105 | break; | 2088 | break; |
| @@ -2112,6 +2095,9 @@ async function loadSchedulers() { | |||
| 2112 | case sources.falai: | 2095 | case sources.falai: |
| 2113 | schedulers = ['N/A']; | 2096 | schedulers = ['N/A']; |
| 2114 | break; | 2097 | break; |
| 2098 | case sources.xai: | ||
| 2099 | schedulers = ['N/A']; | ||
| 2100 | break; | ||
| 2115 | } | 2101 | } |
| 2116 | 2102 | ||
| 2117 | for (const scheduler of schedulers) { | 2103 | for (const scheduler of schedulers) { |
| @@ -2188,9 +2174,6 @@ async function loadVaes() { | |||
| 2188 | case sources.stability: | 2174 | case sources.stability: |
| 2189 | vaes = ['N/A']; | 2175 | vaes = ['N/A']; |
| 2190 | break; | 2176 | break; |
| 2191 | case sources.blockentropy: | ||
| 2192 | vaes = ['N/A']; | ||
| 2193 | break; | ||
| 2194 | case sources.huggingface: | 2177 | case sources.huggingface: |
| 2195 | vaes = ['N/A']; | 2178 | vaes = ['N/A']; |
| 2196 | break; | 2179 | break; |
| @@ -2200,6 +2183,12 @@ async function loadVaes() { | |||
| 2200 | case sources.bfl: | 2183 | case sources.bfl: |
| 2201 | vaes = ['N/A']; | 2184 | vaes = ['N/A']; |
| 2202 | break; | 2185 | break; |
| 2186 | case sources.falai: | ||
| 2187 | vaes = ['N/A']; | ||
| 2188 | break; | ||
| 2189 | case sources.xai: | ||
| 2190 | vaes = ['N/A']; | ||
| 2191 | break; | ||
| 2203 | } | 2192 | } |
| 2204 | 2193 | ||
| 2205 | for (const vae of vaes) { | 2194 | for (const vae of vaes) { |
| @@ -2337,10 +2326,10 @@ function processReply(str) { | |||
| 2337 | str = str.replaceAll('“', ''); | 2326 | str = str.replaceAll('“', ''); |
| 2338 | str = str.replaceAll('\n', ', '); | 2327 | str = str.replaceAll('\n', ', '); |
| 2339 | str = str.normalize('NFD'); | 2328 | str = str.normalize('NFD'); |
| 2340 | 2329 | ||
| 2341 | // Strip out non-alphanumeric characters barring model syntax exceptions | 2330 | // Strip out non-alphanumeric characters barring model syntax exceptions |
| 2342 | str = str.replace(/[^a-zA-Z0-9.,:_(){}<>[\]\-'|#]+/g, ' '); | 2331 | str = str.replace(/[^a-zA-Z0-9.,:_(){}<>[\]\-'|#]+/g, ' '); |
| 2343 | 2332 | ||
| 2344 | str = str.replace(/\s+/g, ' '); // Collapse multiple whitespaces into one | 2333 | str = str.replace(/\s+/g, ' '); // Collapse multiple whitespaces into one |
| 2345 | str = str.trim(); | 2334 | str = str.trim(); |
| 2346 | 2335 | ||
| @@ -2757,9 +2746,6 @@ async function sendGenerationRequest(generationType, prompt, additionalNegativeP | |||
| 2757 | case sources.stability: | 2746 | case sources.stability: |
| 2758 | result = await generateStabilityImage(prefixedPrompt, negativePrompt, signal); | 2747 | result = await generateStabilityImage(prefixedPrompt, negativePrompt, signal); |
| 2759 | break; | 2748 | break; |
| 2760 | case sources.blockentropy: | ||
| 2761 | result = await generateBlockEntropyImage(prefixedPrompt, negativePrompt, signal); | ||
| 2762 | break; | ||
| 2763 | case sources.huggingface: | 2749 | case sources.huggingface: |
| 2764 | result = await generateHuggingFaceImage(prefixedPrompt, signal); | 2750 | result = await generateHuggingFaceImage(prefixedPrompt, signal); |
| 2765 | break; | 2751 | break; |
| @@ -2772,6 +2758,9 @@ async function sendGenerationRequest(generationType, prompt, additionalNegativeP | |||
| 2772 | case sources.falai: | 2758 | case sources.falai: |
| 2773 | result = await generateFalaiImage(prefixedPrompt, negativePrompt, signal); | 2759 | result = await generateFalaiImage(prefixedPrompt, negativePrompt, signal); |
| 2774 | break; | 2760 | break; |
| 2761 | case sources.xai: | ||
| 2762 | result = await generateXAIImage(prefixedPrompt, negativePrompt, signal); | ||
| 2763 | break; | ||
| 2775 | } | 2764 | } |
| 2776 | 2765 | ||
| 2777 | if (!result.data) { | 2766 | if (!result.data) { |
| @@ -2828,40 +2817,6 @@ async function generateTogetherAIImage(prompt, negativePrompt, signal) { | |||
| 2828 | } | 2817 | } |
| 2829 | } | 2818 | } |
| 2830 | 2819 | ||
| 2831 | async function generateBlockEntropyImage(prompt, negativePrompt, signal) { | ||
| 2832 | const result = await fetch('/api/sd/blockentropy/generate', { | ||
| 2833 | method: 'POST', | ||
| 2834 | headers: getRequestHeaders(), | ||
| 2835 | signal: signal, | ||
| 2836 | body: JSON.stringify({ | ||
| 2837 | prompt: prompt, | ||
| 2838 | negative_prompt: negativePrompt, | ||
| 2839 | model: extension_settings.sd.model, | ||
| 2840 | steps: extension_settings.sd.steps, | ||
| 2841 | width: extension_settings.sd.width, | ||
| 2842 | height: extension_settings.sd.height, | ||
| 2843 | seed: extension_settings.sd.seed >= 0 ? extension_settings.sd.seed : undefined, | ||
| 2844 | }), | ||
| 2845 | }); | ||
| 2846 | |||
| 2847 | if (result.ok) { | ||
| 2848 | const data = await result.json(); | ||
| 2849 | |||
| 2850 | // Default format is 'jpg' | ||
| 2851 | let format = 'jpg'; | ||
| 2852 | |||
| 2853 | // Check if a format is specified in the result | ||
| 2854 | if (data.format) { | ||
| 2855 | format = data.format.toLowerCase(); | ||
| 2856 | } | ||
| 2857 | |||
| 2858 | return { format: format, data: data.images[0] }; | ||
| 2859 | } else { | ||
| 2860 | const text = await result.text(); | ||
| 2861 | throw new Error(text); | ||
| 2862 | } | ||
| 2863 | } | ||
| 2864 | |||
| 2865 | /** | 2820 | /** |
| 2866 | * Generates an image using the Pollinations API. | 2821 | * Generates an image using the Pollinations API. |
| 2867 | * @param {string} prompt - The main instruction used to guide the image generation. | 2822 | * @param {string} prompt - The main instruction used to guide the image generation. |
| @@ -3234,7 +3189,7 @@ function getNovelParams() { | |||
| 3234 | extension_settings.sd.scheduler = 'karras'; | 3189 | extension_settings.sd.scheduler = 'karras'; |
| 3235 | } | 3190 | } |
| 3236 | 3191 | ||
| 3237 | if (extension_settings.sd.sampler === 'ddim' || | 3192 | if (extension_settings.sd.sampler === 'ddim' || |
| 3238 | ['nai-diffusion-4-curated-preview', 'nai-diffusion-4-full'].includes(extension_settings.sd.model)) { | 3193 | ['nai-diffusion-4-curated-preview', 'nai-diffusion-4-full'].includes(extension_settings.sd.model)) { |
| 3239 | sm = false; | 3194 | sm = false; |
| 3240 | sm_dyn = false; | 3195 | sm_dyn = false; |
| @@ -3535,6 +3490,33 @@ async function generateBflImage(prompt, signal) { | |||
| 3535 | } | 3490 | } |
| 3536 | 3491 | ||
| 3537 | /** | 3492 | /** |
| 3493 | * Generates an image using the xAI API. | ||
| 3494 | * @param {string} prompt The main instruction used to guide the image generation. | ||
| 3495 | * @param {string} _negativePrompt Negative prompt is not used in this API | ||
| 3496 | * @param {AbortSignal} signal An AbortSignal object that can be used to cancel the request. | ||
| 3497 | * @returns {Promise<{format: string, data: string}>} A promise that resolves when the image generation and processing are complete. | ||
| 3498 | */ | ||
| 3499 | async function generateXAIImage(prompt, _negativePrompt, signal) { | ||
| 3500 | const result = await fetch('/api/sd/xai/generate', { | ||
| 3501 | method: 'POST', | ||
| 3502 | headers: getRequestHeaders(), | ||
| 3503 | signal: signal, | ||
| 3504 | body: JSON.stringify({ | ||
| 3505 | prompt: prompt, | ||
| 3506 | model: extension_settings.sd.model, | ||
| 3507 | }), | ||
| 3508 | }); | ||
| 3509 | |||
| 3510 | if (result.ok) { | ||
| 3511 | const data = await result.json(); | ||
| 3512 | return { format: 'jpg', data: data.image }; | ||
| 3513 | } else { | ||
| 3514 | const text = await result.text(); | ||
| 3515 | throw new Error(text); | ||
| 3516 | } | ||
| 3517 | } | ||
| 3518 | |||
| 3519 | /** | ||
| 3538 | * Generates an image using the FAL.AI API. | 3520 | * Generates an image using the FAL.AI API. |
| 3539 | * @param {string} prompt - The main instruction used to guide the image generation. | 3521 | * @param {string} prompt - The main instruction used to guide the image generation. |
| 3540 | * @param {string} negativePrompt - The negative prompt used to guide the image generation. | 3522 | * @param {string} negativePrompt - The negative prompt used to guide the image generation. |
| @@ -3772,7 +3754,6 @@ async function addSDGenButtons() { | |||
| 3772 | $('#sd_wand_container').append(buttonHtml); | 3754 | $('#sd_wand_container').append(buttonHtml); |
| 3773 | $(document.body).append(dropdownHtml); | 3755 | $(document.body).append(dropdownHtml); |
| 3774 | 3756 | ||
| 3775 | const messageButton = $('.sd_message_gen'); | ||
| 3776 | const button = $('#sd_gen'); | 3757 | const button = $('#sd_gen'); |
| 3777 | const dropdown = $('#sd_dropdown'); | 3758 | const dropdown = $('#sd_dropdown'); |
| 3778 | dropdown.hide(); | 3759 | dropdown.hide(); |
| @@ -3846,8 +3827,6 @@ function isValidState() { | |||
| 3846 | return true; | 3827 | return true; |
| 3847 | case sources.stability: | 3828 | case sources.stability: |
| 3848 | return secret_state[SECRET_KEYS.STABILITY]; | 3829 | return secret_state[SECRET_KEYS.STABILITY]; |
| 3849 | case sources.blockentropy: | ||
| 3850 | return secret_state[SECRET_KEYS.BLOCKENTROPY]; | ||
| 3851 | case sources.huggingface: | 3830 | case sources.huggingface: |
| 3852 | return secret_state[SECRET_KEYS.HUGGINGFACE]; | 3831 | return secret_state[SECRET_KEYS.HUGGINGFACE]; |
| 3853 | case sources.nanogpt: | 3832 | case sources.nanogpt: |
| @@ -3856,6 +3835,8 @@ function isValidState() { | |||
| 3856 | return secret_state[SECRET_KEYS.BFL]; | 3835 | return secret_state[SECRET_KEYS.BFL]; |
| 3857 | case sources.falai: | 3836 | case sources.falai: |
| 3858 | return secret_state[SECRET_KEYS.FALAI]; | 3837 | return secret_state[SECRET_KEYS.FALAI]; |
| 3838 | case sources.xai: | ||
| 3839 | return secret_state[SECRET_KEYS.XAI]; | ||
| 3859 | } | 3840 | } |
| 3860 | } | 3841 | } |
| 3861 | 3842 | ||
| @@ -38,7 +38,6 @@ | |||
| 38 | <label for="sd_source" data-i18n="Source">Source</label> | 38 | <label for="sd_source" data-i18n="Source">Source</label> |
| 39 | <select id="sd_source"> | 39 | <select id="sd_source"> |
| 40 | <option value="bfl">BFL (Black Forest Labs)</option> | 40 | <option value="bfl">BFL (Black Forest Labs)</option> |
| 41 | <option value="blockentropy">Block Entropy</option> | ||
| 42 | <option value="comfy">ComfyUI</option> | 41 | <option value="comfy">ComfyUI</option> |
| 43 | <option value="drawthings">DrawThings HTTP API</option> | 42 | <option value="drawthings">DrawThings HTTP API</option> |
| 44 | <option value="extras">Extras API (deprecated)</option> | 43 | <option value="extras">Extras API (deprecated)</option> |
| @@ -53,6 +52,7 @@ | |||
| 53 | <option value="auto">Stable Diffusion Web UI (AUTOMATIC1111)</option> | 52 | <option value="auto">Stable Diffusion Web UI (AUTOMATIC1111)</option> |
| 54 | <option value="horde">Stable Horde</option> | 53 | <option value="horde">Stable Horde</option> |
| 55 | <option value="togetherai">TogetherAI</option> | 54 | <option value="togetherai">TogetherAI</option> |
| 55 | <option value="xai">xAI (Grok)</option> | ||
| 56 | </select> | 56 | </select> |
| 57 | <div data-sd-source="auto"> | 57 | <div data-sd-source="auto"> |
| 58 | <label for="sd_auto_url">SD Web UI URL</label> | 58 | <label for="sd_auto_url">SD Web UI URL</label> |
| @@ -422,7 +422,7 @@ | |||
| 422 | </label> | 422 | </label> |
| 423 | </div> | 423 | </div> |
| 424 | 424 | ||
| 425 | <div data-sd-source="novel,togetherai,pollinations,comfy,drawthings,vlad,auto,horde,extras,stability,blockentropy,bfl" class="marginTop5"> | 425 | <div data-sd-source="novel,togetherai,pollinations,comfy,drawthings,vlad,auto,horde,extras,stability,bfl" class="marginTop5"> |
| 426 | <label for="sd_seed"> | 426 | <label for="sd_seed"> |
| 427 | <span data-i18n="Seed">Seed</span> | 427 | <span data-i18n="Seed">Seed</span> |
| 428 | <small data-i18n="(-1 for random)">(-1 for random)</small> | 428 | <small data-i18n="(-1 for random)">(-1 for random)</small> |
| @@ -24,7 +24,7 @@ $('button').click(function () { | |||
| 24 | 24 | ||
| 25 | async function doTokenCounter() { | 25 | async function doTokenCounter() { |
| 26 | const { tokenizerName, tokenizerId } = getFriendlyTokenizerName(main_api); | 26 | const { tokenizerName, tokenizerId } = getFriendlyTokenizerName(main_api); |
| 27 | const html = await renderExtensionTemplateAsync('token-counter', 'window', {tokenizerName}); | 27 | const html = await renderExtensionTemplateAsync('token-counter', 'window', { tokenizerName }); |
| 28 | 28 | ||
| 29 | const dialog = $(html); | 29 | const dialog = $(html); |
| 30 | const countDebounced = debounce(async () => { | 30 | const countDebounced = debounce(async () => { |
| @@ -183,8 +183,6 @@ class GptSovitsV2Provider { | |||
| 183 | 183 | ||
| 184 | let prompt_text = replaceSpeaker(voiceId); | 184 | let prompt_text = replaceSpeaker(voiceId); |
| 185 | 185 | ||
| 186 | const streaming = this.settings.streaming; | ||
| 187 | |||
| 188 | const params = { | 186 | const params = { |
| 189 | text: inputText, | 187 | text: inputText, |
| 190 | prompt_text: prompt_text, | 188 | prompt_text: prompt_text, |
| @@ -1,5 +1,5 @@ | |||
| 1 | import { cancelTtsPlay, eventSource, event_types, getCurrentChatId, isStreamingEnabled, name2, saveSettingsDebounced, substituteParams } from '../../../script.js'; | 1 | import { cancelTtsPlay, eventSource, event_types, getCurrentChatId, isStreamingEnabled, name2, saveSettingsDebounced, substituteParams } from '../../../script.js'; |
| 2 | import { ModuleWorkerWrapper, doExtrasFetch, extension_settings, getApiUrl, getContext, modules, renderExtensionTemplateAsync } from '../../extensions.js'; | 2 | import { ModuleWorkerWrapper, extension_settings, getContext, renderExtensionTemplateAsync } from '../../extensions.js'; |
| 3 | import { delay, escapeRegex, getBase64Async, getStringHash, onlyUnique } from '../../utils.js'; | 3 | import { delay, escapeRegex, getBase64Async, getStringHash, onlyUnique } from '../../utils.js'; |
| 4 | import { EdgeTtsProvider } from './edge.js'; | 4 | import { EdgeTtsProvider } from './edge.js'; |
| 5 | import { ElevenLabsTtsProvider } from './elevenlabs.js'; | 5 | import { ElevenLabsTtsProvider } from './elevenlabs.js'; |
| @@ -471,6 +471,7 @@ async function processTtsQueue() { | |||
| 471 | if (extension_settings.tts.skip_codeblocks) { | 471 | if (extension_settings.tts.skip_codeblocks) { |
| 472 | text = text.replace(/^\s{4}.*$/gm, '').trim(); | 472 | text = text.replace(/^\s{4}.*$/gm, '').trim(); |
| 473 | text = text.replace(/```.*?```/gs, '').trim(); | 473 | text = text.replace(/```.*?```/gs, '').trim(); |
| 474 | text = text.replace(/~~~.*?~~~/gs, '').trim(); | ||
| 474 | } | 475 | } |
| 475 | 476 | ||
| 476 | if (extension_settings.tts.skip_tags) { | 477 | if (extension_settings.tts.skip_tags) { |
| @@ -76,7 +76,7 @@ | |||
| 76 | <div id="tts_voicemap_block"> | 76 | <div id="tts_voicemap_block"> |
| 77 | </div> | 77 | </div> |
| 78 | <hr> | 78 | <hr> |
| 79 | <form id="tts_provider_settings" class="inline-drawer-content"> | 79 | <form id="tts_provider_settings"> |
| 80 | </form> | 80 | </form> |
| 81 | <div class="tts_buttons"> | 81 | <div class="tts_buttons"> |
| 82 | <input id="tts_voices" class="menu_button" type="submit" value="Available voices" /> | 82 | <input id="tts_voices" class="menu_button" type="submit" value="Available voices" /> |
| @@ -79,6 +79,10 @@ class SystemTtsProvider { | |||
| 79 | // Config // | 79 | // Config // |
| 80 | //########// | 80 | //########// |
| 81 | 81 | ||
| 82 | // Static constants for the simulated default voice | ||
| 83 | static BROWSER_DEFAULT_VOICE_ID = '__browser_default__'; | ||
| 84 | static BROWSER_DEFAULT_VOICE_NAME = 'System Default Voice'; | ||
| 85 | |||
| 82 | settings; | 86 | settings; |
| 83 | ready = false; | 87 | ready = false; |
| 84 | voices = []; | 88 | voices = []; |
| @@ -168,51 +172,97 @@ class SystemTtsProvider { | |||
| 168 | //#################// | 172 | //#################// |
| 169 | fetchTtsVoiceObjects() { | 173 | fetchTtsVoiceObjects() { |
| 170 | if (!('speechSynthesis' in window)) { | 174 | if (!('speechSynthesis' in window)) { |
| 171 | return []; | 175 | return Promise.resolve([]); |
| 172 | } | 176 | } |
| 173 | 177 | ||
| 174 | return new Promise((resolve) => { | 178 | return new Promise((resolve) => { |
| 175 | setTimeout(() => { | 179 | setTimeout(() => { |
| 176 | const voices = speechSynthesis | 180 | let voices = speechSynthesis.getVoices(); |
| 177 | .getVoices() | 181 | |
| 178 | .sort((a, b) => a.lang.localeCompare(b.lang) || a.name.localeCompare(b.name)) | 182 | if (voices.length === 0) { |
| 179 | .map(x => ({ name: x.name, voice_id: x.voiceURI, preview_url: false, lang: x.lang })); | 183 | // Edge compat: Provide default when voices empty |
| 180 | 184 | console.warn('SystemTTS: getVoices() returned empty list. Providing browser default option.'); | |
| 181 | resolve(voices); | 185 | const defaultVoice = { |
| 182 | }, 1); | 186 | name: SystemTtsProvider.BROWSER_DEFAULT_VOICE_NAME, |
| 187 | voice_id: SystemTtsProvider.BROWSER_DEFAULT_VOICE_ID, | ||
| 188 | preview_url: false, | ||
| 189 | lang: navigator.language || 'en-US', | ||
| 190 | }; | ||
| 191 | resolve([defaultVoice]); | ||
| 192 | } else { | ||
| 193 | const mappedVoices = voices | ||
| 194 | .sort((a, b) => a.lang.localeCompare(b.lang) || a.name.localeCompare(b.name)) | ||
| 195 | .map(x => ({ name: x.name, voice_id: x.voiceURI, preview_url: false, lang: x.lang })); | ||
| 196 | resolve(mappedVoices); | ||
| 197 | } | ||
| 198 | }, 50); | ||
| 183 | }); | 199 | }); |
| 184 | } | 200 | } |
| 185 | 201 | ||
| 186 | previewTtsVoice(voiceId) { | 202 | previewTtsVoice(voiceId) { |
| 187 | if (!('speechSynthesis' in window)) { | 203 | if (!('speechSynthesis' in window)) { |
| 188 | throw 'Speech synthesis API is not supported'; | 204 | throw new Error('Speech synthesis API is not supported'); |
| 189 | } | 205 | } |
| 190 | 206 | ||
| 191 | const voice = speechSynthesis.getVoices().find(x => x.voiceURI === voiceId); | 207 | let voice = null; |
| 208 | if (voiceId !== SystemTtsProvider.BROWSER_DEFAULT_VOICE_ID) { | ||
| 209 | const voices = speechSynthesis.getVoices(); | ||
| 210 | voice = voices.find(x => x.voiceURI === voiceId); | ||
| 192 | 211 | ||
| 193 | if (!voice) { | 212 | if (!voice && voices.length > 0) { |
| 194 | throw `TTS Voice id ${voiceId} not found`; | 213 | console.warn(`SystemTTS Preview: Voice ID "${voiceId}" not found among available voices. Using browser default.`); |
| 214 | } else if (!voice && voices.length === 0) { | ||
| 215 | console.warn('SystemTTS Preview: Voice list is empty. Using browser default.'); | ||
| 216 | } | ||
| 217 | } else { | ||
| 218 | console.log('SystemTTS Preview: Using browser default voice as requested.'); | ||
| 195 | } | 219 | } |
| 196 | 220 | ||
| 197 | speechSynthesis.cancel(); | 221 | speechSynthesis.cancel(); |
| 198 | const text = getPreviewString(voice.lang); | 222 | const langForPreview = voice ? voice.lang : (navigator.language || 'en-US'); |
| 223 | const text = getPreviewString(langForPreview); | ||
| 199 | const utterance = new SpeechSynthesisUtterance(text); | 224 | const utterance = new SpeechSynthesisUtterance(text); |
| 200 | utterance.voice = voice; | 225 | |
| 226 | if (voice) { | ||
| 227 | utterance.voice = voice; | ||
| 228 | } | ||
| 229 | |||
| 201 | utterance.rate = this.settings.rate || 1; | 230 | utterance.rate = this.settings.rate || 1; |
| 202 | utterance.pitch = this.settings.pitch || 1; | 231 | utterance.pitch = this.settings.pitch || 1; |
| 232 | |||
| 233 | utterance.onerror = (event) => { | ||
| 234 | console.error(`SystemTTS Preview Error: ${event.error}`, event); | ||
| 235 | }; | ||
| 236 | |||
| 203 | speechSynthesis.speak(utterance); | 237 | speechSynthesis.speak(utterance); |
| 204 | } | 238 | } |
| 205 | 239 | ||
| 206 | async getVoice(voiceName) { | 240 | async getVoice(voiceName) { |
| 207 | if (!('speechSynthesis' in window)) { | 241 | if (!('speechSynthesis' in window)) { |
| 208 | return { voice_id: null }; | 242 | return { voice_id: null, name: 'API Not Supported' }; |
| 243 | } | ||
| 244 | |||
| 245 | if (voiceName === SystemTtsProvider.BROWSER_DEFAULT_VOICE_NAME) { | ||
| 246 | return { | ||
| 247 | voice_id: SystemTtsProvider.BROWSER_DEFAULT_VOICE_ID, | ||
| 248 | name: SystemTtsProvider.BROWSER_DEFAULT_VOICE_NAME, | ||
| 249 | }; | ||
| 209 | } | 250 | } |
| 210 | 251 | ||
| 211 | const voices = speechSynthesis.getVoices(); | 252 | const voices = speechSynthesis.getVoices(); |
| 253 | |||
| 254 | if (voices.length === 0) { | ||
| 255 | console.warn('SystemTTS: Empty voice list, using default fallback'); | ||
| 256 | return { | ||
| 257 | voice_id: SystemTtsProvider.BROWSER_DEFAULT_VOICE_ID, | ||
| 258 | name: SystemTtsProvider.BROWSER_DEFAULT_VOICE_NAME, | ||
| 259 | }; | ||
| 260 | } | ||
| 261 | |||
| 212 | const match = voices.find(x => x.name == voiceName); | 262 | const match = voices.find(x => x.name == voiceName); |
| 213 | 263 | ||
| 214 | if (!match) { | 264 | if (!match) { |
| 215 | throw `TTS Voice name ${voiceName} not found`; | 265 | throw new Error(`SystemTTS getVoice: TTS Voice name "${voiceName}" not found`); |
| 216 | } | 266 | } |
| 217 | 267 | ||
| 218 | return { voice_id: match.voiceURI, name: match.name }; | 268 | return { voice_id: match.voiceURI, name: match.name }; |
| @@ -237,7 +287,6 @@ class SystemTtsProvider { | |||
| 237 | speechUtteranceChunker(utterance, { | 287 | speechUtteranceChunker(utterance, { |
| 238 | chunkLength: 200, | 288 | chunkLength: 200, |
| 239 | }, function () { | 289 | }, function () { |
| 240 | //some code to execute when done | ||
| 241 | resolve(silence); | 290 | resolve(silence); |
| 242 | console.log('System TTS done'); | 291 | console.log('System TTS done'); |
| 243 | }); | 292 | }); |
| @@ -55,6 +55,8 @@ const getBatchSize = () => ['transformers', 'palm', 'ollama'].includes(settings. | |||
| 55 | const settings = { | 55 | const settings = { |
| 56 | // For both | 56 | // For both |
| 57 | source: 'transformers', | 57 | source: 'transformers', |
| 58 | alt_endpoint_url: '', | ||
| 59 | use_alt_endpoint: false, | ||
| 58 | include_wi: false, | 60 | include_wi: false, |
| 59 | togetherai_model: 'togethercomputer/m2-bert-80M-32k-retrieval', | 61 | togetherai_model: 'togethercomputer/m2-bert-80M-32k-retrieval', |
| 60 | openai_model: 'text-embedding-ada-002', | 62 | openai_model: 'text-embedding-ada-002', |
| @@ -63,6 +65,7 @@ const settings = { | |||
| 63 | ollama_keep: false, | 65 | ollama_keep: false, |
| 64 | vllm_model: '', | 66 | vllm_model: '', |
| 65 | webllm_model: '', | 67 | webllm_model: '', |
| 68 | google_model: 'text-embedding-004', | ||
| 66 | summarize: false, | 69 | summarize: false, |
| 67 | summarize_sent: false, | 70 | summarize_sent: false, |
| 68 | summary_source: 'main', | 71 | summary_source: 'main', |
| @@ -108,6 +111,7 @@ const settings = { | |||
| 108 | const moduleWorker = new ModuleWorkerWrapper(synchronizeChat); | 111 | const moduleWorker = new ModuleWorkerWrapper(synchronizeChat); |
| 109 | const webllmProvider = new WebLlmVectorProvider(); | 112 | const webllmProvider = new WebLlmVectorProvider(); |
| 110 | const cachedSummaries = new Map(); | 113 | const cachedSummaries = new Map(); |
| 114 | const vectorApiRequiresUrl = ['llamacpp', 'vllm', 'ollama', 'koboldcpp']; | ||
| 111 | 115 | ||
| 112 | /** | 116 | /** |
| 113 | * Gets the Collection ID for a file embedded in the chat. | 117 | * Gets the Collection ID for a file embedded in the chat. |
| @@ -565,6 +569,8 @@ async function retrieveFileChunks(queryText, collectionId) { | |||
| 565 | * @returns {Promise<boolean>} True if successful, false if not | 569 | * @returns {Promise<boolean>} True if successful, false if not |
| 566 | */ | 570 | */ |
| 567 | async function vectorizeFile(fileText, fileName, collectionId, chunkSize, overlapPercent) { | 571 | async function vectorizeFile(fileText, fileName, collectionId, chunkSize, overlapPercent) { |
| 572 | let toast = jQuery(); | ||
| 573 | |||
| 568 | try { | 574 | try { |
| 569 | if (settings.translate_files && typeof globalThis.translate === 'function') { | 575 | if (settings.translate_files && typeof globalThis.translate === 'function') { |
| 570 | console.log(`Vectors: Translating file ${fileName} to English...`); | 576 | console.log(`Vectors: Translating file ${fileName} to English...`); |
| @@ -574,7 +580,7 @@ async function vectorizeFile(fileText, fileName, collectionId, chunkSize, overla | |||
| 574 | 580 | ||
| 575 | const batchSize = getBatchSize(); | 581 | const batchSize = getBatchSize(); |
| 576 | const toastBody = $('<span>').text('This may take a while. Please wait...'); | 582 | const toastBody = $('<span>').text('This may take a while. Please wait...'); |
| 577 | const toast = toastr.info(toastBody, `Ingesting file ${escapeHtml(fileName)}`, { closeButton: false, escapeHtml: false, timeOut: 0, extendedTimeOut: 0 }); | 583 | toast = toastr.info(toastBody, `Ingesting file ${escapeHtml(fileName)}`, { closeButton: false, escapeHtml: false, timeOut: 0, extendedTimeOut: 0 }); |
| 578 | const overlapSize = Math.round(chunkSize * overlapPercent / 100); | 584 | const overlapSize = Math.round(chunkSize * overlapPercent / 100); |
| 579 | const delimiters = getChunkDelimiters(); | 585 | const delimiters = getChunkDelimiters(); |
| 580 | // Overlap should not be included in chunk size. It will be later compensated by overlapChunks | 586 | // Overlap should not be included in chunk size. It will be later compensated by overlapChunks |
| @@ -596,6 +602,7 @@ async function vectorizeFile(fileText, fileName, collectionId, chunkSize, overla | |||
| 596 | console.log(`Vectors: Inserted ${chunks.length} vector items for file ${fileName} into ${collectionId}`); | 602 | console.log(`Vectors: Inserted ${chunks.length} vector items for file ${fileName} into ${collectionId}`); |
| 597 | return true; | 603 | return true; |
| 598 | } catch (error) { | 604 | } catch (error) { |
| 605 | toastr.clear(toast); | ||
| 599 | toastr.error(String(error), 'Failed to vectorize file', { preventDuplicates: true }); | 606 | toastr.error(String(error), 'Failed to vectorize file', { preventDuplicates: true }); |
| 600 | console.error('Vectors: Failed to vectorize file', error); | 607 | console.error('Vectors: Failed to vectorize file', error); |
| 601 | return false; | 608 | return false; |
| @@ -773,19 +780,22 @@ function getVectorsRequestBody(args = {}) { | |||
| 773 | break; | 780 | break; |
| 774 | case 'ollama': | 781 | case 'ollama': |
| 775 | body.model = extension_settings.vectors.ollama_model; | 782 | body.model = extension_settings.vectors.ollama_model; |
| 776 | body.apiUrl = textgenerationwebui_settings.server_urls[textgen_types.OLLAMA]; | 783 | body.apiUrl = settings.use_alt_endpoint ? settings.alt_endpoint_url : textgenerationwebui_settings.server_urls[textgen_types.OLLAMA]; |
| 777 | body.keep = !!extension_settings.vectors.ollama_keep; | 784 | body.keep = !!extension_settings.vectors.ollama_keep; |
| 778 | break; | 785 | break; |
| 779 | case 'llamacpp': | 786 | case 'llamacpp': |
| 780 | body.apiUrl = textgenerationwebui_settings.server_urls[textgen_types.LLAMACPP]; | 787 | body.apiUrl = settings.use_alt_endpoint ? settings.alt_endpoint_url : textgenerationwebui_settings.server_urls[textgen_types.LLAMACPP]; |
| 781 | break; | 788 | break; |
| 782 | case 'vllm': | 789 | case 'vllm': |
| 783 | body.apiUrl = textgenerationwebui_settings.server_urls[textgen_types.VLLM]; | 790 | body.apiUrl = settings.use_alt_endpoint ? settings.alt_endpoint_url : textgenerationwebui_settings.server_urls[textgen_types.VLLM]; |
| 784 | body.model = extension_settings.vectors.vllm_model; | 791 | body.model = extension_settings.vectors.vllm_model; |
| 785 | break; | 792 | break; |
| 786 | case 'webllm': | 793 | case 'webllm': |
| 787 | body.model = extension_settings.vectors.webllm_model; | 794 | body.model = extension_settings.vectors.webllm_model; |
| 788 | break; | 795 | break; |
| 796 | case 'palm': | ||
| 797 | body.model = extension_settings.vectors.google_model; | ||
| 798 | break; | ||
| 789 | default: | 799 | default: |
| 790 | break; | 800 | break; |
| 791 | } | 801 | } |
| @@ -803,6 +813,12 @@ async function getAdditionalArgs(items) { | |||
| 803 | case 'webllm': | 813 | case 'webllm': |
| 804 | args.embeddings = await createWebLlmEmbeddings(items); | 814 | args.embeddings = await createWebLlmEmbeddings(items); |
| 805 | break; | 815 | break; |
| 816 | case 'koboldcpp': { | ||
| 817 | const { embeddings, model } = await createKoboldCppEmbeddings(items); | ||
| 818 | args.embeddings = embeddings; | ||
| 819 | args.model = model; | ||
| 820 | break; | ||
| 821 | } | ||
| 806 | } | 822 | } |
| 807 | return args; | 823 | return args; |
| 808 | } | 824 | } |
| @@ -870,10 +886,18 @@ function throwIfSourceInvalid() { | |||
| 870 | throw new Error('Vectors: API key missing', { cause: 'api_key_missing' }); | 886 | throw new Error('Vectors: API key missing', { cause: 'api_key_missing' }); |
| 871 | } | 887 | } |
| 872 | 888 | ||
| 873 | if (settings.source === 'ollama' && !textgenerationwebui_settings.server_urls[textgen_types.OLLAMA] || | 889 | if (vectorApiRequiresUrl.includes(settings.source) && settings.use_alt_endpoint) { |
| 874 | settings.source === 'vllm' && !textgenerationwebui_settings.server_urls[textgen_types.VLLM] || | 890 | if (!settings.alt_endpoint_url) { |
| 875 | settings.source === 'llamacpp' && !textgenerationwebui_settings.server_urls[textgen_types.LLAMACPP]) { | 891 | throw new Error('Vectors: API URL missing', { cause: 'api_url_missing' }); |
| 876 | throw new Error('Vectors: API URL missing', { cause: 'api_url_missing' }); | 892 | } |
| 893 | } | ||
| 894 | else { | ||
| 895 | if (settings.source === 'ollama' && !textgenerationwebui_settings.server_urls[textgen_types.OLLAMA] || | ||
| 896 | settings.source === 'vllm' && !textgenerationwebui_settings.server_urls[textgen_types.VLLM] || | ||
| 897 | settings.source === 'koboldcpp' && !textgenerationwebui_settings.server_urls[textgen_types.KOBOLDCPP] || | ||
| 898 | settings.source === 'llamacpp' && !textgenerationwebui_settings.server_urls[textgen_types.LLAMACPP]) { | ||
| 899 | throw new Error('Vectors: API URL missing', { cause: 'api_url_missing' }); | ||
| 900 | } | ||
| 877 | } | 901 | } |
| 878 | 902 | ||
| 879 | if (settings.source === 'ollama' && !settings.ollama_model || settings.source === 'vllm' && !settings.vllm_model) { | 903 | if (settings.source === 'ollama' && !settings.ollama_model || settings.source === 'vllm' && !settings.vllm_model) { |
| @@ -1071,6 +1095,9 @@ function toggleSettings() { | |||
| 1071 | $('#vllm_vectorsModel').toggle(settings.source === 'vllm'); | 1095 | $('#vllm_vectorsModel').toggle(settings.source === 'vllm'); |
| 1072 | $('#nomicai_apiKey').toggle(settings.source === 'nomicai'); | 1096 | $('#nomicai_apiKey').toggle(settings.source === 'nomicai'); |
| 1073 | $('#webllm_vectorsModel').toggle(settings.source === 'webllm'); | 1097 | $('#webllm_vectorsModel').toggle(settings.source === 'webllm'); |
| 1098 | $('#koboldcpp_vectorsModel').toggle(settings.source === 'koboldcpp'); | ||
| 1099 | $('#google_vectorsModel').toggle(settings.source === 'palm'); | ||
| 1100 | $('#vector_altEndpointUrl').toggle(vectorApiRequiresUrl.includes(settings.source)); | ||
| 1074 | if (settings.source === 'webllm') { | 1101 | if (settings.source === 'webllm') { |
| 1075 | loadWebLlmModels(); | 1102 | loadWebLlmModels(); |
| 1076 | } | 1103 | } |
| @@ -1138,6 +1165,45 @@ async function createWebLlmEmbeddings(items) { | |||
| 1138 | }); | 1165 | }); |
| 1139 | } | 1166 | } |
| 1140 | 1167 | ||
| 1168 | /** | ||
| 1169 | * Creates KoboldCpp embeddings for a list of items. | ||
| 1170 | * @param {string[]} items Items to embed | ||
| 1171 | * @returns {Promise<{embeddings: Record<string, number[]>, model: string}>} Calculated embeddings | ||
| 1172 | */ | ||
| 1173 | async function createKoboldCppEmbeddings(items) { | ||
| 1174 | const response = await fetch('/api/backends/kobold/embed', { | ||
| 1175 | method: 'POST', | ||
| 1176 | headers: getRequestHeaders(), | ||
| 1177 | body: JSON.stringify({ | ||
| 1178 | items: items, | ||
| 1179 | server: settings.use_alt_endpoint ? settings.alt_endpoint_url : textgenerationwebui_settings.server_urls[textgen_types.KOBOLDCPP], | ||
| 1180 | }), | ||
| 1181 | }); | ||
| 1182 | |||
| 1183 | if (!response.ok) { | ||
| 1184 | throw new Error('Failed to get KoboldCpp embeddings'); | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | const data = await response.json(); | ||
| 1188 | if (!Array.isArray(data.embeddings) || !data.model || data.embeddings.length !== items.length) { | ||
| 1189 | throw new Error('Invalid response from KoboldCpp embeddings'); | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | const embeddings = /** @type {Record<string, number[]>} */ ({}); | ||
| 1193 | for (let i = 0; i < data.embeddings.length; i++) { | ||
| 1194 | if (!Array.isArray(data.embeddings[i]) || data.embeddings[i].length === 0) { | ||
| 1195 | throw new Error('KoboldCpp returned an empty embedding. Reduce the chunk size and/or size threshold and try again.'); | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | embeddings[items[i]] = data.embeddings[i]; | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | return { | ||
| 1202 | embeddings: embeddings, | ||
| 1203 | model: data.model, | ||
| 1204 | }; | ||
| 1205 | } | ||
| 1206 | |||
| 1141 | async function onPurgeClick() { | 1207 | async function onPurgeClick() { |
| 1142 | const chatId = getCurrentChatId(); | 1208 | const chatId = getCurrentChatId(); |
| 1143 | if (!chatId) { | 1209 | if (!chatId) { |
| @@ -1412,6 +1478,16 @@ jQuery(async () => { | |||
| 1412 | saveSettingsDebounced(); | 1478 | saveSettingsDebounced(); |
| 1413 | toggleSettings(); | 1479 | toggleSettings(); |
| 1414 | }); | 1480 | }); |
| 1481 | $('#vector_altEndpointUrl_enabled').prop('checked', settings.use_alt_endpoint).on('input', () => { | ||
| 1482 | settings.use_alt_endpoint = $('#vector_altEndpointUrl_enabled').prop('checked'); | ||
| 1483 | Object.assign(extension_settings.vectors, settings); | ||
| 1484 | saveSettingsDebounced(); | ||
| 1485 | }); | ||
| 1486 | $('#vector_altEndpoint_address').val(settings.alt_endpoint_url).on('change', () => { | ||
| 1487 | settings.alt_endpoint_url = String($('#vector_altEndpoint_address').val()); | ||
| 1488 | Object.assign(extension_settings.vectors, settings); | ||
| 1489 | saveSettingsDebounced(); | ||
| 1490 | }); | ||
| 1415 | $('#api_key_nomicai').on('click', async () => { | 1491 | $('#api_key_nomicai').on('click', async () => { |
| 1416 | const popupText = 'NomicAI API Key:'; | 1492 | const popupText = 'NomicAI API Key:'; |
| 1417 | const key = await callGenericPopup(popupText, POPUP_TYPE.INPUT, '', { | 1493 | const key = await callGenericPopup(popupText, POPUP_TYPE.INPUT, '', { |
| @@ -1688,6 +1764,12 @@ jQuery(async () => { | |||
| 1688 | toastr.success('WebLLM model loaded'); | 1764 | toastr.success('WebLLM model loaded'); |
| 1689 | }); | 1765 | }); |
| 1690 | 1766 | ||
| 1767 | $('#vectors_google_model').val(settings.google_model).on('input', () => { | ||
| 1768 | settings.google_model = String($('#vectors_google_model').val()); | ||
| 1769 | Object.assign(extension_settings.vectors, settings); | ||
| 1770 | saveSettingsDebounced(); | ||
| 1771 | }); | ||
| 1772 | |||
| 1691 | $('#api_key_nomicai').toggleClass('success', !!secret_state[SECRET_KEYS.NOMICAI]); | 1773 | $('#api_key_nomicai').toggleClass('success', !!secret_state[SECRET_KEYS.NOMICAI]); |
| 1692 | 1774 | ||
| 1693 | toggleSettings(); | 1775 | toggleSettings(); |
| @@ -13,6 +13,7 @@ | |||
| 13 | <option value="cohere">Cohere</option> | 13 | <option value="cohere">Cohere</option> |
| 14 | <option value="extras">Extras (deprecated)</option> | 14 | <option value="extras">Extras (deprecated)</option> |
| 15 | <option value="palm">Google AI Studio</option> | 15 | <option value="palm">Google AI Studio</option> |
| 16 | <option value="koboldcpp">KoboldCpp</option> | ||
| 16 | <option value="llamacpp">llama.cpp</option> | 17 | <option value="llamacpp">llama.cpp</option> |
| 17 | <option value="transformers" data-i18n="Local (Transformers)">Local (Transformers)</option> | 18 | <option value="transformers" data-i18n="Local (Transformers)">Local (Transformers)</option> |
| 18 | <option value="mistral">MistralAI</option> | 19 | <option value="mistral">MistralAI</option> |
| @@ -24,6 +25,16 @@ | |||
| 24 | <option value="webllm" data-i18n="WebLLM Extension">WebLLM Extension</option> | 25 | <option value="webllm" data-i18n="WebLLM Extension">WebLLM Extension</option> |
| 25 | </select> | 26 | </select> |
| 26 | </div> | 27 | </div> |
| 28 | <div class="flex-container flexFlowColumn" id="vector_altEndpointUrl"> | ||
| 29 | <label class="checkbox_label" for="vector_altEndpointUrl_enabled" title="Enable secondary endpoint URL usage, instead of the main one."> | ||
| 30 | <input id="vector_altEndpointUrl_enabled" type="checkbox" class="checkbox"> | ||
| 31 | <span data-i18n="Use secondary URL">Use secondary URL</span> | ||
| 32 | </label> | ||
| 33 | <label for="vector_altEndpoint_address" data-i18n="Secondary Embedding endpoint URL"> | ||
| 34 | Secondary Embedding endpoint URL | ||
| 35 | </label> | ||
| 36 | <input id="vector_altEndpoint_address" class="text_pole" type="text" placeholder="e.g. http://localhost:5001" /> | ||
| 37 | </div> | ||
| 27 | <div class="flex-container flexFlowColumn" id="webllm_vectorsModel"> | 38 | <div class="flex-container flexFlowColumn" id="webllm_vectorsModel"> |
| 28 | <label for="vectors_webllm_model" data-i18n="Vectorization Model"> | 39 | <label for="vectors_webllm_model" data-i18n="Vectorization Model"> |
| 29 | Vectorization Model | 40 | Vectorization Model |
| @@ -55,6 +66,14 @@ | |||
| 55 | Hint: Set the URL in the API connection settings. | 66 | Hint: Set the URL in the API connection settings. |
| 56 | </i> | 67 | </i> |
| 57 | </div> | 68 | </div> |
| 69 | <div class="flex-container flexFlowColumn" id="koboldcpp_vectorsModel"> | ||
| 70 | <span> | ||
| 71 | Set the KoboldCpp URL in the Text Completion API connection settings. | ||
| 72 | </span> | ||
| 73 | <span> | ||
| 74 | Must use version 1.87 or higher and have an embedding model loaded. | ||
| 75 | </span> | ||
| 76 | </div> | ||
| 58 | <div class="flex-container flexFlowColumn" id="llamacpp_vectorsModel"> | 77 | <div class="flex-container flexFlowColumn" id="llamacpp_vectorsModel"> |
| 59 | <span data-i18n="The server MUST be started with the --embedding flag to use this feature!"> | 78 | <span data-i18n="The server MUST be started with the --embedding flag to use this feature!"> |
| 60 | The server MUST be started with the <code>--embedding</code> flag to use this feature! | 79 | The server MUST be started with the <code>--embedding</code> flag to use this feature! |
| @@ -111,7 +130,16 @@ | |||
| 111 | Hint: Set the URL in the API connection settings. | 130 | Hint: Set the URL in the API connection settings. |
| 112 | </i> | 131 | </i> |
| 113 | </div> | 132 | </div> |
| 114 | 133 | <div class="flex-container flexFlowColumn" id="google_vectorsModel"> | |
| 134 | <label for="vectors_google_model" data-i18n="Vectorization Model"> | ||
| 135 | Vectorization Model | ||
| 136 | </label> | ||
| 137 | <select id="vectors_google_model" class="text_pole"> | ||
| 138 | <option value="gemini-embedding-exp-03-07">gemini-embedding-exp-03-07</option> | ||
| 139 | <option value="text-embedding-004">text-embedding-004</option> | ||
| 140 | <option value="embedding-001">embedding-001</option> | ||
| 141 | </select> | ||
| 142 | </div> | ||
| 115 | <div class="flex-container alignItemsCenter" id="nomicai_apiKey"> | 143 | <div class="flex-container alignItemsCenter" id="nomicai_apiKey"> |
| 116 | <label for="api_key_nomicai" class="flex1"> | 144 | <label for="api_key_nomicai" class="flex1"> |
| 117 | <span data-i18n="NomicAI API Key">NomicAI API Key</span> | 145 | <span data-i18n="NomicAI API Key">NomicAI API Key</span> |
| @@ -292,7 +320,7 @@ | |||
| 292 | <label for="vectors_file_depth_db" title="How many messages before the current end of the chat." data-i18n="[title]How many messages before the current end of the chat."> | 320 | <label for="vectors_file_depth_db" title="How many messages before the current end of the chat." data-i18n="[title]How many messages before the current end of the chat."> |
| 293 | <input type="radio" name="vectors_file_position_db" value="1" /> | 321 | <input type="radio" name="vectors_file_position_db" value="1" /> |
| 294 | <span data-i18n="In-chat @ Depth">In-chat @ Depth</span> | 322 | <span data-i18n="In-chat @ Depth">In-chat @ Depth</span> |
| 295 | <input id="vectors_file_depth_db" class="text_pole widthUnset" type="number" min="0" max="999" /> | 323 | <input id="vectors_file_depth_db" class="text_pole widthUnset" type="number" min="0" max="9999" /> |
| 296 | <span>as</span> | 324 | <span>as</span> |
| 297 | <select id="vectors_file_depth_role_db" class="text_pole widthNatural"> | 325 | <select id="vectors_file_depth_role_db" class="text_pole widthNatural"> |
| 298 | <option value="0" data-i18n="System">System</option> | 326 | <option value="0" data-i18n="System">System</option> |
| @@ -344,7 +372,7 @@ | |||
| 344 | <label for="vectors_depth" title="How many messages before the current end of the chat." data-i18n="[title]How many messages before the current end of the chat."> | 372 | <label for="vectors_depth" title="How many messages before the current end of the chat." data-i18n="[title]How many messages before the current end of the chat."> |
| 345 | <input type="radio" name="vectors_position" value="1" /> | 373 | <input type="radio" name="vectors_position" value="1" /> |
| 346 | <span data-i18n="In-chat @ Depth">In-chat @ Depth </span> | 374 | <span data-i18n="In-chat @ Depth">In-chat @ Depth </span> |
| 347 | <input id="vectors_depth" class="text_pole widthUnset" type="number" min="0" max="999" /> | 375 | <input id="vectors_depth" class="text_pole widthUnset" type="number" min="0" max="9999" /> |
| 348 | </label> | 376 | </label> |
| 349 | </div> | 377 | </div> |
| 350 | <div class="flex-container"> | 378 | <div class="flex-container"> |
| @@ -46,7 +46,6 @@ import { | |||
| 46 | hideSwipeButtons, | 46 | hideSwipeButtons, |
| 47 | chat_metadata, | 47 | chat_metadata, |
| 48 | updateChatMetadata, | 48 | updateChatMetadata, |
| 49 | isStreamingEnabled, | ||
| 50 | getThumbnailUrl, | 49 | getThumbnailUrl, |
| 51 | getRequestHeaders, | 50 | getRequestHeaders, |
| 52 | setMenuType, | 51 | setMenuType, |
| @@ -435,16 +434,18 @@ export function getGroupCharacterCards(groupId, characterId) { | |||
| 435 | * @param {string} value Value to replace | 434 | * @param {string} value Value to replace |
| 436 | * @param {string} fieldName Name of the field | 435 | * @param {string} fieldName Name of the field |
| 437 | * @param {string} characterName Name of the character | 436 | * @param {string} characterName Name of the character |
| 437 | * @param {boolean} trim Whether to trim the value | ||
| 438 | * @returns {string} Replaced text | 438 | * @returns {string} Replaced text |
| 439 | * */ | 439 | * */ |
| 440 | function customBaseChatReplace(value, fieldName, characterName) { | 440 | function customBaseChatReplace(value, fieldName, characterName, trim) { |
| 441 | if (!value) { | 441 | if (!value) { |
| 442 | return ''; | 442 | return ''; |
| 443 | } | 443 | } |
| 444 | 444 | ||
| 445 | // We should do the custom field name replacement first, and then run it through the normal macro engine with provided names | 445 | // We should do the custom field name replacement first, and then run it through the normal macro engine with provided names |
| 446 | value = value.replace(/<FIELDNAME>/gi, fieldName); | 446 | value = value.replace(/<FIELDNAME>/gi, fieldName); |
| 447 | return baseChatReplace(value.trim(), name1, characterName); | 447 | value = trim ? value.trim() : value; |
| 448 | return baseChatReplace(value, name1, characterName); | ||
| 448 | } | 449 | } |
| 449 | 450 | ||
| 450 | /** | 451 | /** |
| @@ -467,13 +468,12 @@ export function getGroupCharacterCards(groupId, characterId) { | |||
| 467 | } | 468 | } |
| 468 | 469 | ||
| 469 | // Prepare and replace prefixes | 470 | // Prepare and replace prefixes |
| 470 | const prefix = customBaseChatReplace(group.generation_mode_join_prefix, fieldName, characterName); | 471 | const prefix = customBaseChatReplace(group.generation_mode_join_prefix, fieldName, characterName, false); |
| 471 | const suffix = customBaseChatReplace(group.generation_mode_join_suffix, fieldName, characterName); | 472 | const suffix = customBaseChatReplace(group.generation_mode_join_suffix, fieldName, characterName, false); |
| 472 | const separator = power_user.instruct.wrap ? '\n' : ''; | ||
| 473 | // Also run the macro replacement on the actual content | 473 | // Also run the macro replacement on the actual content |
| 474 | value = customBaseChatReplace(value, fieldName, characterName); | 474 | value = customBaseChatReplace(value, fieldName, characterName, true); |
| 475 | 475 | ||
| 476 | return `${prefix ? prefix + separator : ''}${value}${suffix ? separator + suffix : ''}`; | 476 | return `${prefix}${value}${suffix}`; |
| 477 | } | 477 | } |
| 478 | 478 | ||
| 479 | const scenarioOverride = chat_metadata['scenario']; | 479 | const scenarioOverride = chat_metadata['scenario']; |
| @@ -696,7 +696,7 @@ export function getGroupBlock(group) { | |||
| 696 | template.find('.group_fav_icon').css('display', 'none'); | 696 | template.find('.group_fav_icon').css('display', 'none'); |
| 697 | template.addClass(group.fav ? 'is_fav' : ''); | 697 | template.addClass(group.fav ? 'is_fav' : ''); |
| 698 | template.find('.ch_fav').val(group.fav); | 698 | template.find('.ch_fav').val(group.fav); |
| 699 | template.find('.group_select_counter').text(`${count} ${count != 1 ? 'characters' : 'character'}`); | 699 | template.find('.group_select_counter').text(count + ' ' + (count != 1 ? t`characters` : t`character`)); |
| 700 | template.find('.group_select_block_list').text(namesList.join(', ')); | 700 | template.find('.group_select_block_list').text(namesList.join(', ')); |
| 701 | 701 | ||
| 702 | // Display inline tags | 702 | // Display inline tags |
| @@ -882,7 +882,7 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { | |||
| 882 | activatedMembers = activateListOrder(enabledMembers); | 882 | activatedMembers = activateListOrder(enabledMembers); |
| 883 | } | 883 | } |
| 884 | else if (activationStrategy === group_activation_strategy.POOLED) { | 884 | else if (activationStrategy === group_activation_strategy.POOLED) { |
| 885 | activatedMembers = activatePooledOrder(enabledMembers, lastMessage); | 885 | activatedMembers = activatePooledOrder(enabledMembers, lastMessage, isUserInput); |
| 886 | } | 886 | } |
| 887 | else if (activationStrategy === group_activation_strategy.MANUAL && !isUserInput) { | 887 | else if (activationStrategy === group_activation_strategy.MANUAL && !isUserInput) { |
| 888 | activatedMembers = shuffle(enabledMembers).slice(0, 1).map(x => characters.findIndex(y => y.avatar === x)).filter(x => x !== -1); | 888 | activatedMembers = shuffle(enabledMembers).slice(0, 1).map(x => characters.findIndex(y => y.avatar === x)).filter(x => x !== -1); |
| @@ -904,6 +904,7 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { | |||
| 904 | groupChatQueueOrder.set(characters[activatedMembers[i]].avatar, i + 1); | 904 | groupChatQueueOrder.set(characters[activatedMembers[i]].avatar, i + 1); |
| 905 | } | 905 | } |
| 906 | } | 906 | } |
| 907 | await eventSource.emit(event_types.GROUP_WRAPPER_STARTED, { selected_group, type }); | ||
| 907 | // now the real generation begins: cycle through every activated character | 908 | // now the real generation begins: cycle through every activated character |
| 908 | for (const chId of activatedMembers) { | 909 | for (const chId of activatedMembers) { |
| 909 | throwIfAborted(); | 910 | throwIfAborted(); |
| @@ -942,6 +943,7 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { | |||
| 942 | setCharacterName(''); | 943 | setCharacterName(''); |
| 943 | activateSendButtons(); | 944 | activateSendButtons(); |
| 944 | showSwipeButtons(); | 945 | showSwipeButtons(); |
| 946 | await eventSource.emit(event_types.GROUP_WRAPPER_FINISHED, { selected_group, type }); | ||
| 945 | } | 947 | } |
| 946 | 948 | ||
| 947 | return Promise.resolve(textResult); | 949 | return Promise.resolve(textResult); |
| @@ -1028,16 +1030,17 @@ function activateListOrder(members) { | |||
| 1028 | * Activate group members based on the last message. | 1030 | * Activate group members based on the last message. |
| 1029 | * @param {string[]} members List of member avatars | 1031 | * @param {string[]} members List of member avatars |
| 1030 | * @param {Object} lastMessage Last message | 1032 | * @param {Object} lastMessage Last message |
| 1033 | * @param {boolean} isUserInput Whether the user has input text | ||
| 1031 | * @returns {number[]} List of character ids | 1034 | * @returns {number[]} List of character ids |
| 1032 | */ | 1035 | */ |
| 1033 | function activatePooledOrder(members, lastMessage) { | 1036 | function activatePooledOrder(members, lastMessage, isUserInput) { |
| 1034 | /** @type {string} */ | 1037 | /** @type {string} */ |
| 1035 | let activatedMember = null; | 1038 | let activatedMember = null; |
| 1036 | /** @type {string[]} */ | 1039 | /** @type {string[]} */ |
| 1037 | const spokenSinceUser = []; | 1040 | const spokenSinceUser = []; |
| 1038 | 1041 | ||
| 1039 | for (const message of chat.slice().reverse()) { | 1042 | for (const message of chat.slice().reverse()) { |
| 1040 | if (message.is_user) { | 1043 | if (message.is_user || isUserInput) { |
| 1041 | break; | 1044 | break; |
| 1042 | } | 1045 | } |
| 1043 | 1046 | ||
| @@ -10,6 +10,7 @@ import { SECRET_KEYS, writeSecret } from './secrets.js'; | |||
| 10 | import { delay } from './utils.js'; | 10 | import { delay } from './utils.js'; |
| 11 | import { isMobile } from './RossAscends-mods.js'; | 11 | import { isMobile } from './RossAscends-mods.js'; |
| 12 | import { autoSelectInstructPreset } from './instruct-mode.js'; | 12 | import { autoSelectInstructPreset } from './instruct-mode.js'; |
| 13 | import { t } from './i18n.js'; | ||
| 13 | 14 | ||
| 14 | export { | 15 | export { |
| 15 | horde_settings, | 16 | horde_settings, |
| @@ -169,7 +170,7 @@ async function adjustHordeGenerationParams(max_context_length, max_length) { | |||
| 169 | } | 170 | } |
| 170 | } | 171 | } |
| 171 | console.log(maxContextLength, maxLength); | 172 | console.log(maxContextLength, maxLength); |
| 172 | $('#adjustedHordeParams').text(`Context: ${maxContextLength}, Response: ${maxLength}`); | 173 | $('#adjustedHordeParams').text(t`Context` + `: ${maxContextLength}, ` + t`Response` + `: ${maxLength}`); |
| 173 | return { maxContextLength, maxLength }; | 174 | return { maxContextLength, maxLength }; |
| 174 | } | 175 | } |
| 175 | 176 | ||
| @@ -177,7 +178,7 @@ function setContextSizePreview() { | |||
| 177 | if (horde_settings.models.length) { | 178 | if (horde_settings.models.length) { |
| 178 | adjustHordeGenerationParams(max_context, amount_gen); | 179 | adjustHordeGenerationParams(max_context, amount_gen); |
| 179 | } else { | 180 | } else { |
| 180 | $('#adjustedHordeParams').text('Context: --, Response: --'); | 181 | $('#adjustedHordeParams').text(t`Context` + ': --, ' + t`Response` + ': --'); |
| 181 | } | 182 | } |
| 182 | } | 183 | } |
| 183 | 184 | ||
| @@ -404,7 +405,7 @@ jQuery(function () { | |||
| 404 | if (horde_settings.models.length) { | 405 | if (horde_settings.models.length) { |
| 405 | adjustHordeGenerationParams(max_context, amount_gen); | 406 | adjustHordeGenerationParams(max_context, amount_gen); |
| 406 | } else { | 407 | } else { |
| 407 | $('#adjustedHordeParams').text('Context: --, Response: --'); | 408 | $('#adjustedHordeParams').text(t`Context` + ': --, ' + t`Response` + ': --'); |
| 408 | } | 409 | } |
| 409 | 410 | ||
| 410 | saveSettingsDebounced(); | 411 | saveSettingsDebounced(); |
| @@ -243,9 +243,14 @@ export function autoSelectInstructPreset(modelId) { | |||
| 243 | 243 | ||
| 244 | /** | 244 | /** |
| 245 | * Converts instruct mode sequences to an array of stopping strings. | 245 | * Converts instruct mode sequences to an array of stopping strings. |
| 246 | * @param {Object} options | ||
| 247 | * @param {InstructSettings?} [options.customInstruct=null] - Custom instruct settings. | ||
| 248 | * @param {boolean?} [options.useStopStrings] - Decides whether to use "Chat Start" and "Example Separator" | ||
| 246 | * @returns {string[]} Array of instruct mode stopping strings. | 249 | * @returns {string[]} Array of instruct mode stopping strings. |
| 247 | */ | 250 | */ |
| 248 | export function getInstructStoppingSequences() { | 251 | export function getInstructStoppingSequences({ customInstruct = null, useStopStrings = null } = {}) { |
| 252 | const instruct = structuredClone(customInstruct ?? power_user.instruct); | ||
| 253 | |||
| 249 | /** | 254 | /** |
| 250 | * Adds instruct mode sequence to the result array. | 255 | * Adds instruct mode sequence to the result array. |
| 251 | * @param {string} sequence Sequence string. | 256 | * @param {string} sequence Sequence string. |
| @@ -254,7 +259,7 @@ export function getInstructStoppingSequences() { | |||
| 254 | function addInstructSequence(sequence) { | 259 | function addInstructSequence(sequence) { |
| 255 | // Cohee: oobabooga's textgen always appends newline before the sequence as a stopping string | 260 | // Cohee: oobabooga's textgen always appends newline before the sequence as a stopping string |
| 256 | // But it's a problem for Metharme which doesn't use newlines to separate them. | 261 | // But it's a problem for Metharme which doesn't use newlines to separate them. |
| 257 | const wrap = (s) => power_user.instruct.wrap ? '\n' + s : s; | 262 | const wrap = (s) => instruct.wrap ? '\n' + s : s; |
| 258 | // Sequence must be a non-empty string | 263 | // Sequence must be a non-empty string |
| 259 | if (typeof sequence === 'string' && sequence.length > 0) { | 264 | if (typeof sequence === 'string' && sequence.length > 0) { |
| 260 | // If sequence is just a whitespace or newline - we don't want to make it a stopping string | 265 | // If sequence is just a whitespace or newline - we don't want to make it a stopping string |
| @@ -262,7 +267,7 @@ export function getInstructStoppingSequences() { | |||
| 262 | if (sequence.trim().length > 0) { | 267 | if (sequence.trim().length > 0) { |
| 263 | const wrappedSequence = wrap(sequence); | 268 | const wrappedSequence = wrap(sequence); |
| 264 | // Need to respect "insert macro" setting | 269 | // Need to respect "insert macro" setting |
| 265 | const stopString = power_user.instruct.macro ? substituteParams(wrappedSequence) : wrappedSequence; | 270 | const stopString = instruct.macro ? substituteParams(wrappedSequence) : wrappedSequence; |
| 266 | result.push(stopString); | 271 | result.push(stopString); |
| 267 | } | 272 | } |
| 268 | } | 273 | } |
| @@ -270,14 +275,15 @@ export function getInstructStoppingSequences() { | |||
| 270 | 275 | ||
| 271 | const result = []; | 276 | const result = []; |
| 272 | 277 | ||
| 273 | if (power_user.instruct.enabled) { | 278 | // Since preset's don't have "enabled", we assume it's always enabled |
| 274 | const stop_sequence = power_user.instruct.stop_sequence || ''; | 279 | if (customInstruct ?? instruct.enabled) { |
| 275 | const input_sequence = power_user.instruct.input_sequence?.replace(/{{name}}/gi, name1) || ''; | 280 | const stop_sequence = instruct.stop_sequence || ''; |
| 276 | const output_sequence = power_user.instruct.output_sequence?.replace(/{{name}}/gi, name2) || ''; | 281 | const input_sequence = instruct.input_sequence?.replace(/{{name}}/gi, name1) || ''; |
| 277 | const first_output_sequence = power_user.instruct.first_output_sequence?.replace(/{{name}}/gi, name2) || ''; | 282 | const output_sequence = instruct.output_sequence?.replace(/{{name}}/gi, name2) || ''; |
| 278 | const last_output_sequence = power_user.instruct.last_output_sequence?.replace(/{{name}}/gi, name2) || ''; | 283 | const first_output_sequence = instruct.first_output_sequence?.replace(/{{name}}/gi, name2) || ''; |
| 279 | const system_sequence = power_user.instruct.system_sequence?.replace(/{{name}}/gi, 'System') || ''; | 284 | const last_output_sequence = instruct.last_output_sequence?.replace(/{{name}}/gi, name2) || ''; |
| 280 | const last_system_sequence = power_user.instruct.last_system_sequence?.replace(/{{name}}/gi, 'System') || ''; | 285 | const system_sequence = instruct.system_sequence?.replace(/{{name}}/gi, 'System') || ''; |
| 286 | const last_system_sequence = instruct.last_system_sequence?.replace(/{{name}}/gi, 'System') || ''; | ||
| 281 | 287 | ||
| 282 | const combined_sequence = [ | 288 | const combined_sequence = [ |
| 283 | stop_sequence, | 289 | stop_sequence, |
| @@ -292,7 +298,7 @@ export function getInstructStoppingSequences() { | |||
| 292 | combined_sequence.split('\n').filter((line, index, self) => self.indexOf(line) === index).forEach(addInstructSequence); | 298 | combined_sequence.split('\n').filter((line, index, self) => self.indexOf(line) === index).forEach(addInstructSequence); |
| 293 | } | 299 | } |
| 294 | 300 | ||
| 295 | if (power_user.context.use_stop_strings) { | 301 | if (useStopStrings ?? power_user.context.use_stop_strings) { |
| 296 | if (power_user.context.chat_start) { | 302 | if (power_user.context.chat_start) { |
| 297 | result.push(`\n${substituteParams(power_user.context.chat_start)}`); | 303 | result.push(`\n${substituteParams(power_user.context.chat_start)}`); |
| 298 | } | 304 | } |
| @@ -320,59 +326,61 @@ export const force_output_sequence = { | |||
| 320 | * @param {string} name1 User name. | 326 | * @param {string} name1 User name. |
| 321 | * @param {string} name2 Character name. | 327 | * @param {string} name2 Character name. |
| 322 | * @param {boolean|number} forceOutputSequence Force to use first/last output sequence (if configured). | 328 | * @param {boolean|number} forceOutputSequence Force to use first/last output sequence (if configured). |
| 329 | * @param {InstructSettings} customInstruct Custom instruct mode settings. | ||
| 323 | * @returns {string} Formatted instruct mode chat message. | 330 | * @returns {string} Formatted instruct mode chat message. |
| 324 | */ | 331 | */ |
| 325 | export function formatInstructModeChat(name, mes, isUser, isNarrator, forceAvatar, name1, name2, forceOutputSequence) { | 332 | export function formatInstructModeChat(name, mes, isUser, isNarrator, forceAvatar, name1, name2, forceOutputSequence, customInstruct = null) { |
| 326 | let includeNames = isNarrator ? false : power_user.instruct.names_behavior === names_behavior_types.ALWAYS; | 333 | const instruct = structuredClone(customInstruct ?? power_user.instruct); |
| 334 | let includeNames = isNarrator ? false : instruct.names_behavior === names_behavior_types.ALWAYS; | ||
| 327 | 335 | ||
| 328 | if (!isNarrator && power_user.instruct.names_behavior === names_behavior_types.FORCE && ((selected_group && name !== name1) || (forceAvatar && name !== name1))) { | 336 | if (!isNarrator && instruct.names_behavior === names_behavior_types.FORCE && ((selected_group && name !== name1) || (forceAvatar && name !== name1))) { |
| 329 | includeNames = true; | 337 | includeNames = true; |
| 330 | } | 338 | } |
| 331 | 339 | ||
| 332 | function getPrefix() { | 340 | function getPrefix() { |
| 333 | if (isNarrator) { | 341 | if (isNarrator) { |
| 334 | return power_user.instruct.system_same_as_user ? power_user.instruct.input_sequence : power_user.instruct.system_sequence; | 342 | return instruct.system_same_as_user ? instruct.input_sequence : instruct.system_sequence; |
| 335 | } | 343 | } |
| 336 | 344 | ||
| 337 | if (isUser) { | 345 | if (isUser) { |
| 338 | if (forceOutputSequence === force_output_sequence.FIRST) { | 346 | if (forceOutputSequence === force_output_sequence.FIRST) { |
| 339 | return power_user.instruct.first_input_sequence || power_user.instruct.input_sequence; | 347 | return instruct.first_input_sequence || instruct.input_sequence; |
| 340 | } | 348 | } |
| 341 | 349 | ||
| 342 | if (forceOutputSequence === force_output_sequence.LAST) { | 350 | if (forceOutputSequence === force_output_sequence.LAST) { |
| 343 | return power_user.instruct.last_input_sequence || power_user.instruct.input_sequence; | 351 | return instruct.last_input_sequence || instruct.input_sequence; |
| 344 | } | 352 | } |
| 345 | 353 | ||
| 346 | return power_user.instruct.input_sequence; | 354 | return instruct.input_sequence; |
| 347 | } | 355 | } |
| 348 | 356 | ||
| 349 | if (forceOutputSequence === force_output_sequence.FIRST) { | 357 | if (forceOutputSequence === force_output_sequence.FIRST) { |
| 350 | return power_user.instruct.first_output_sequence || power_user.instruct.output_sequence; | 358 | return instruct.first_output_sequence || instruct.output_sequence; |
| 351 | } | 359 | } |
| 352 | 360 | ||
| 353 | if (forceOutputSequence === force_output_sequence.LAST) { | 361 | if (forceOutputSequence === force_output_sequence.LAST) { |
| 354 | return power_user.instruct.last_output_sequence || power_user.instruct.output_sequence; | 362 | return instruct.last_output_sequence || instruct.output_sequence; |
| 355 | } | 363 | } |
| 356 | 364 | ||
| 357 | return power_user.instruct.output_sequence; | 365 | return instruct.output_sequence; |
| 358 | } | 366 | } |
| 359 | 367 | ||
| 360 | function getSuffix() { | 368 | function getSuffix() { |
| 361 | if (isNarrator) { | 369 | if (isNarrator) { |
| 362 | return power_user.instruct.system_same_as_user ? power_user.instruct.input_suffix : power_user.instruct.system_suffix; | 370 | return instruct.system_same_as_user ? instruct.input_suffix : instruct.system_suffix; |
| 363 | } | 371 | } |
| 364 | 372 | ||
| 365 | if (isUser) { | 373 | if (isUser) { |
| 366 | return power_user.instruct.input_suffix; | 374 | return instruct.input_suffix; |
| 367 | } | 375 | } |
| 368 | 376 | ||
| 369 | return power_user.instruct.output_suffix; | 377 | return instruct.output_suffix; |
| 370 | } | 378 | } |
| 371 | 379 | ||
| 372 | let prefix = getPrefix() || ''; | 380 | let prefix = getPrefix() || ''; |
| 373 | let suffix = getSuffix() || ''; | 381 | let suffix = getSuffix() || ''; |
| 374 | 382 | ||
| 375 | if (power_user.instruct.macro) { | 383 | if (instruct.macro) { |
| 376 | prefix = substituteParams(prefix, name1, name2); | 384 | prefix = substituteParams(prefix, name1, name2); |
| 377 | prefix = prefix.replace(/{{name}}/gi, name || 'System'); | 385 | prefix = prefix.replace(/{{name}}/gi, name || 'System'); |
| 378 | 386 | ||
| @@ -380,11 +388,11 @@ export function formatInstructModeChat(name, mes, isUser, isNarrator, forceAvata | |||
| 380 | suffix = suffix.replace(/{{name}}/gi, name || 'System'); | 388 | suffix = suffix.replace(/{{name}}/gi, name || 'System'); |
| 381 | } | 389 | } |
| 382 | 390 | ||
| 383 | if (!suffix && power_user.instruct.wrap) { | 391 | if (!suffix && instruct.wrap) { |
| 384 | suffix = '\n'; | 392 | suffix = '\n'; |
| 385 | } | 393 | } |
| 386 | 394 | ||
| 387 | const separator = power_user.instruct.wrap ? '\n' : ''; | 395 | const separator = instruct.wrap ? '\n' : ''; |
| 388 | 396 | ||
| 389 | // Don't include the name if it's empty | 397 | // Don't include the name if it's empty |
| 390 | const textArray = includeNames && name ? [prefix, `${name}: ${mes}` + suffix] : [prefix, mes + suffix]; | 398 | const textArray = includeNames && name ? [prefix, `${name}: ${mes}` + suffix] : [prefix, mes + suffix]; |
| @@ -396,23 +404,26 @@ export function formatInstructModeChat(name, mes, isUser, isNarrator, forceAvata | |||
| 396 | /** | 404 | /** |
| 397 | * Formats instruct mode system prompt. | 405 | * Formats instruct mode system prompt. |
| 398 | * @param {string} systemPrompt System prompt string. | 406 | * @param {string} systemPrompt System prompt string. |
| 407 | * @param {InstructSettings} customInstruct Custom instruct mode settings. | ||
| 399 | * @returns {string} Formatted instruct mode system prompt. | 408 | * @returns {string} Formatted instruct mode system prompt. |
| 400 | */ | 409 | */ |
| 401 | export function formatInstructModeSystemPrompt(systemPrompt) { | 410 | export function formatInstructModeSystemPrompt(systemPrompt, customInstruct = null) { |
| 402 | if (!systemPrompt) { | 411 | if (!systemPrompt) { |
| 403 | return ''; | 412 | return ''; |
| 404 | } | 413 | } |
| 405 | 414 | ||
| 406 | const separator = power_user.instruct.wrap ? '\n' : ''; | 415 | const instruct = structuredClone(customInstruct ?? power_user.instruct); |
| 407 | 416 | ||
| 408 | if (power_user.instruct.system_sequence_prefix) { | 417 | const separator = instruct.wrap ? '\n' : ''; |
| 418 | |||
| 419 | if (instruct.system_sequence_prefix) { | ||
| 409 | // TODO: Replace with a proper 'System' prompt entity name input | 420 | // TODO: Replace with a proper 'System' prompt entity name input |
| 410 | const prefix = power_user.instruct.system_sequence_prefix.replace(/{{name}}/gi, 'System'); | 421 | const prefix = instruct.system_sequence_prefix.replace(/{{name}}/gi, 'System'); |
| 411 | systemPrompt = prefix + separator + systemPrompt; | 422 | systemPrompt = prefix + separator + systemPrompt; |
| 412 | } | 423 | } |
| 413 | 424 | ||
| 414 | if (power_user.instruct.system_sequence_suffix) { | 425 | if (instruct.system_sequence_suffix) { |
| 415 | systemPrompt = systemPrompt + separator + power_user.instruct.system_sequence_suffix; | 426 | systemPrompt = systemPrompt + separator + instruct.system_sequence_suffix; |
| 416 | } | 427 | } |
| 417 | 428 | ||
| 418 | return systemPrompt; | 429 | return systemPrompt; |
| @@ -504,30 +515,32 @@ export function formatInstructModeExamples(mesExamplesArray, name1, name2) { | |||
| 504 | * @param {string} name2 Character name. | 515 | * @param {string} name2 Character name. |
| 505 | * @param {boolean} isQuiet Is quiet mode generation. | 516 | * @param {boolean} isQuiet Is quiet mode generation. |
| 506 | * @param {boolean} isQuietToLoud Is quiet to loud generation. | 517 | * @param {boolean} isQuietToLoud Is quiet to loud generation. |
| 518 | * @param {InstructSettings} customInstruct Custom instruct settings. | ||
| 507 | * @returns {string} Formatted instruct mode last prompt line. | 519 | * @returns {string} Formatted instruct mode last prompt line. |
| 508 | */ | 520 | */ |
| 509 | export function formatInstructModePrompt(name, isImpersonate, promptBias, name1, name2, isQuiet, isQuietToLoud) { | 521 | export function formatInstructModePrompt(name, isImpersonate, promptBias, name1, name2, isQuiet, isQuietToLoud, customInstruct = null) { |
| 510 | const includeNames = name && (power_user.instruct.names_behavior === names_behavior_types.ALWAYS || (!!selected_group && power_user.instruct.names_behavior === names_behavior_types.FORCE)) && !(isQuiet && !isQuietToLoud); | 522 | const instruct = structuredClone(customInstruct ?? power_user.instruct); |
| 523 | const includeNames = name && (instruct.names_behavior === names_behavior_types.ALWAYS || (!!selected_group && instruct.names_behavior === names_behavior_types.FORCE)) && !(isQuiet && !isQuietToLoud); | ||
| 511 | 524 | ||
| 512 | function getSequence() { | 525 | function getSequence() { |
| 513 | // User impersonation prompt | 526 | // User impersonation prompt |
| 514 | if (isImpersonate) { | 527 | if (isImpersonate) { |
| 515 | return power_user.instruct.input_sequence; | 528 | return instruct.input_sequence; |
| 516 | } | 529 | } |
| 517 | 530 | ||
| 518 | // Neutral / system / quiet prompt | 531 | // Neutral / system / quiet prompt |
| 519 | // Use a special quiet instruct sequence if defined, or assistant's output sequence otherwise | 532 | // Use a special quiet instruct sequence if defined, or assistant's output sequence otherwise |
| 520 | if (isQuiet && !isQuietToLoud) { | 533 | if (isQuiet && !isQuietToLoud) { |
| 521 | return power_user.instruct.last_system_sequence || power_user.instruct.output_sequence; | 534 | return instruct.last_system_sequence || instruct.output_sequence; |
| 522 | } | 535 | } |
| 523 | 536 | ||
| 524 | // Quiet in-character prompt | 537 | // Quiet in-character prompt |
| 525 | if (isQuiet && isQuietToLoud) { | 538 | if (isQuiet && isQuietToLoud) { |
| 526 | return power_user.instruct.last_output_sequence || power_user.instruct.output_sequence; | 539 | return instruct.last_output_sequence || instruct.output_sequence; |
| 527 | } | 540 | } |
| 528 | 541 | ||
| 529 | // Default AI response | 542 | // Default AI response |
| 530 | return power_user.instruct.last_output_sequence || power_user.instruct.output_sequence; | 543 | return instruct.last_output_sequence || instruct.output_sequence; |
| 531 | } | 544 | } |
| 532 | 545 | ||
| 533 | let sequence = getSequence() || ''; | 546 | let sequence = getSequence() || ''; |
| @@ -536,21 +549,21 @@ export function formatInstructModePrompt(name, isImpersonate, promptBias, name1, | |||
| 536 | // A hack for Mistral's formatting that has a normal output sequence ending with a space | 549 | // A hack for Mistral's formatting that has a normal output sequence ending with a space |
| 537 | if ( | 550 | if ( |
| 538 | includeNames && | 551 | includeNames && |
| 539 | power_user.instruct.last_output_sequence && | 552 | instruct.last_output_sequence && |
| 540 | power_user.instruct.output_sequence && | 553 | instruct.output_sequence && |
| 541 | sequence === power_user.instruct.last_output_sequence && | 554 | sequence === instruct.last_output_sequence && |
| 542 | /\s$/.test(power_user.instruct.output_sequence) && | 555 | /\s$/.test(instruct.output_sequence) && |
| 543 | !/\s$/.test(power_user.instruct.last_output_sequence) | 556 | !/\s$/.test(instruct.last_output_sequence) |
| 544 | ) { | 557 | ) { |
| 545 | nameFiller = power_user.instruct.output_sequence.slice(-1); | 558 | nameFiller = instruct.output_sequence.slice(-1); |
| 546 | } | 559 | } |
| 547 | 560 | ||
| 548 | if (power_user.instruct.macro) { | 561 | if (instruct.macro) { |
| 549 | sequence = substituteParams(sequence, name1, name2); | 562 | sequence = substituteParams(sequence, name1, name2); |
| 550 | sequence = sequence.replace(/{{name}}/gi, name || 'System'); | 563 | sequence = sequence.replace(/{{name}}/gi, name || 'System'); |
| 551 | } | 564 | } |
| 552 | 565 | ||
| 553 | const separator = power_user.instruct.wrap ? '\n' : ''; | 566 | const separator = instruct.wrap ? '\n' : ''; |
| 554 | let text = includeNames ? (separator + sequence + separator + nameFiller + `${name}:`) : (separator + sequence); | 567 | let text = includeNames ? (separator + sequence + separator + nameFiller + `${name}:`) : (separator + sequence); |
| 555 | 568 | ||
| 556 | // Quiet prompt already has a newline at the end | 569 | // Quiet prompt already has a newline at the end |
| @@ -562,7 +575,7 @@ export function formatInstructModePrompt(name, isImpersonate, promptBias, name1, | |||
| 562 | text += (includeNames ? promptBias : (separator + promptBias.trimStart())); | 575 | text += (includeNames ? promptBias : (separator + promptBias.trimStart())); |
| 563 | } | 576 | } |
| 564 | 577 | ||
| 565 | return (power_user.instruct.wrap ? text.trimEnd() : text) + (includeNames ? '' : separator); | 578 | return (instruct.wrap ? text.trimEnd() : text) + (includeNames ? '' : separator); |
| 566 | } | 579 | } |
| 567 | 580 | ||
| 568 | /** | 581 | /** |
| @@ -180,13 +180,18 @@ function displayError(message) { | |||
| 180 | * Preserves the query string. | 180 | * Preserves the query string. |
| 181 | */ | 181 | */ |
| 182 | function redirectToHome() { | 182 | function redirectToHome() { |
| 183 | // After a login theres no need to preserve the | 183 | // Create a URL object based on the current location |
| 184 | // noauto (if present) | 184 | const currentUrl = new URL(window.location.href); |
| 185 | const urlParams = new URLSearchParams(window.location.search); | ||
| 186 | 185 | ||
| 187 | urlParams.delete('noauto'); | 186 | // After a login there's no need to preserve the |
| 187 | // noauto parameter (if present) | ||
| 188 | currentUrl.searchParams.delete('noauto'); | ||
| 188 | 189 | ||
| 189 | window.location.href = '/' + urlParams.toString(); | 190 | // Set the pathname to root and keep the updated query string |
| 191 | currentUrl.pathname = '/'; | ||
| 192 | |||
| 193 | // Redirect to the new URL | ||
| 194 | window.location.href = currentUrl.toString(); | ||
| 190 | } | 195 | } |
| 191 | 196 | ||
| 192 | /** | 197 | /** |
| @@ -368,7 +368,12 @@ function onToggleLogprobsPanel() { | |||
| 368 | function createSwipe(messageId, prompt) { | 368 | function createSwipe(messageId, prompt) { |
| 369 | // need to call `cleanUpMessage` on our new prompt, because we were working | 369 | // need to call `cleanUpMessage` on our new prompt, because we were working |
| 370 | // with raw model output and our new prompt is missing trimming/macro replacements | 370 | // with raw model output and our new prompt is missing trimming/macro replacements |
| 371 | const cleanedPrompt = cleanUpMessage(prompt, false, false, true); | 371 | const cleanedPrompt = cleanUpMessage({ |
| 372 | getMessage: prompt, | ||
| 373 | isImpersonate: false, | ||
| 374 | isContinue: false, | ||
| 375 | displayIncompleteSentences: true, | ||
| 376 | }); | ||
| 372 | 377 | ||
| 373 | const msg = chat[messageId]; | 378 | const msg = chat[messageId]; |
| 374 | const newSwipeInfo = { | 379 | const newSwipeInfo = { |
| @@ -795,6 +795,7 @@ export function parseNovelAILogprobs(data) { | |||
| 795 | 795 | ||
| 796 | // Add the chosen token to `merged` if it's not already there. This can | 796 | // Add the chosen token to `merged` if it's not already there. This can |
| 797 | // happen if the chosen token was not among the top 10 most likely ones. | 797 | // happen if the chosen token was not among the top 10 most likely ones. |
| 798 | // eslint-disable-next-line no-unused-vars | ||
| 798 | const [[chosenId], [_, chosenAfter]] = data.chosen[0]; | 799 | const [[chosenId], [_, chosenAfter]] = data.chosen[0]; |
| 799 | if (!merged.some(([id]) => id === chosenId)) { | 800 | if (!merged.some(([id]) => id === chosenId)) { |
| 800 | merged.push([chosenId, chosenAfter]); | 801 | merged.push([chosenId, chosenAfter]); |
| @@ -15,12 +15,12 @@ import { | |||
| 15 | extension_prompt_types, | 15 | extension_prompt_types, |
| 16 | Generate, | 16 | Generate, |
| 17 | getExtensionPrompt, | 17 | getExtensionPrompt, |
| 18 | getExtensionPromptMaxDepth, | ||
| 18 | getNextMessageId, | 19 | getNextMessageId, |
| 19 | getRequestHeaders, | 20 | getRequestHeaders, |
| 20 | getStoppingStrings, | 21 | getStoppingStrings, |
| 21 | is_send_press, | 22 | is_send_press, |
| 22 | main_api, | 23 | main_api, |
| 23 | MAX_INJECTION_DEPTH, | ||
| 24 | name1, | 24 | name1, |
| 25 | name2, | 25 | name2, |
| 26 | replaceItemizedPromptText, | 26 | replaceItemizedPromptText, |
| @@ -75,6 +75,7 @@ import { Popup, POPUP_RESULT } from './popup.js'; | |||
| 75 | import { t } from './i18n.js'; | 75 | import { t } from './i18n.js'; |
| 76 | import { ToolManager } from './tool-calling.js'; | 76 | import { ToolManager } from './tool-calling.js'; |
| 77 | import { accountStorage } from './util/AccountStorage.js'; | 77 | import { accountStorage } from './util/AccountStorage.js'; |
| 78 | import { IGNORE_SYMBOL } from './constants.js'; | ||
| 78 | 79 | ||
| 79 | export { | 80 | export { |
| 80 | openai_messages_count, | 81 | openai_messages_count, |
| @@ -119,7 +120,6 @@ const default_bias_presets = { | |||
| 119 | const max_2k = 2047; | 120 | const max_2k = 2047; |
| 120 | const max_4k = 4095; | 121 | const max_4k = 4095; |
| 121 | const max_8k = 8191; | 122 | const max_8k = 8191; |
| 122 | const max_12k = 12287; | ||
| 123 | const max_16k = 16383; | 123 | const max_16k = 16383; |
| 124 | const max_32k = 32767; | 124 | const max_32k = 32767; |
| 125 | const max_64k = 65535; | 125 | const max_64k = 65535; |
| @@ -182,9 +182,9 @@ export const chat_completion_sources = { | |||
| 182 | PERPLEXITY: 'perplexity', | 182 | PERPLEXITY: 'perplexity', |
| 183 | GROQ: 'groq', | 183 | GROQ: 'groq', |
| 184 | ZEROONEAI: '01ai', | 184 | ZEROONEAI: '01ai', |
| 185 | BLOCKENTROPY: 'blockentropy', | ||
| 186 | NANOGPT: 'nanogpt', | 185 | NANOGPT: 'nanogpt', |
| 187 | DEEPSEEK: 'deepseek', | 186 | DEEPSEEK: 'deepseek', |
| 187 | XAI: 'xai', | ||
| 188 | }; | 188 | }; |
| 189 | 189 | ||
| 190 | const character_names_behavior = { | 190 | const character_names_behavior = { |
| @@ -258,7 +258,7 @@ export const settingsToUpdate = { | |||
| 258 | nanogpt_model: ['#model_nanogpt_select', 'nanogpt_model', false], | 258 | nanogpt_model: ['#model_nanogpt_select', 'nanogpt_model', false], |
| 259 | deepseek_model: ['#model_deepseek_select', 'deepseek_model', false], | 259 | deepseek_model: ['#model_deepseek_select', 'deepseek_model', false], |
| 260 | zerooneai_model: ['#model_01ai_select', 'zerooneai_model', false], | 260 | zerooneai_model: ['#model_01ai_select', 'zerooneai_model', false], |
| 261 | blockentropy_model: ['#model_blockentropy_select', 'blockentropy_model', false], | 261 | xai_model: ['#model_xai_select', 'xai_model', false], |
| 262 | custom_model: ['#custom_model_id', 'custom_model', false], | 262 | custom_model: ['#custom_model_id', 'custom_model', false], |
| 263 | custom_url: ['#custom_api_url_text', 'custom_url', false], | 263 | custom_url: ['#custom_api_url_text', 'custom_url', false], |
| 264 | custom_include_body: ['#custom_include_body', 'custom_include_body', false], | 264 | custom_include_body: ['#custom_include_body', 'custom_include_body', false], |
| @@ -346,8 +346,8 @@ const default_settings = { | |||
| 346 | groq_model: 'llama-3.3-70b-versatile', | 346 | groq_model: 'llama-3.3-70b-versatile', |
| 347 | nanogpt_model: 'gpt-4o-mini', | 347 | nanogpt_model: 'gpt-4o-mini', |
| 348 | zerooneai_model: 'yi-large', | 348 | zerooneai_model: 'yi-large', |
| 349 | blockentropy_model: 'be-70b-base-llama3.1', | ||
| 350 | deepseek_model: 'deepseek-chat', | 349 | deepseek_model: 'deepseek-chat', |
| 350 | xai_model: 'grok-3-beta', | ||
| 351 | custom_model: '', | 351 | custom_model: '', |
| 352 | custom_url: '', | 352 | custom_url: '', |
| 353 | custom_include_body: '', | 353 | custom_include_body: '', |
| @@ -427,8 +427,8 @@ const oai_settings = { | |||
| 427 | groq_model: 'llama-3.1-70b-versatile', | 427 | groq_model: 'llama-3.1-70b-versatile', |
| 428 | nanogpt_model: 'gpt-4o-mini', | 428 | nanogpt_model: 'gpt-4o-mini', |
| 429 | zerooneai_model: 'yi-large', | 429 | zerooneai_model: 'yi-large', |
| 430 | blockentropy_model: 'be-70b-base-llama3.1', | ||
| 431 | deepseek_model: 'deepseek-chat', | 430 | deepseek_model: 'deepseek-chat', |
| 431 | xai_model: 'grok-3-beta', | ||
| 432 | custom_model: '', | 432 | custom_model: '', |
| 433 | custom_url: '', | 433 | custom_url: '', |
| 434 | custom_include_body: '', | 434 | custom_include_body: '', |
| @@ -527,6 +527,13 @@ function setOpenAIMessages(chat) { | |||
| 527 | let role = chat[j]['is_user'] ? 'user' : 'assistant'; | 527 | let role = chat[j]['is_user'] ? 'user' : 'assistant'; |
| 528 | let content = chat[j]['mes']; | 528 | let content = chat[j]['mes']; |
| 529 | 529 | ||
| 530 | // If this symbol flag is set, completely ignore the message. | ||
| 531 | // This can be used to hide messages without affecting the number of messages in the chat. | ||
| 532 | if (chat[j].extra?.[IGNORE_SYMBOL]) { | ||
| 533 | j++; | ||
| 534 | continue; | ||
| 535 | } | ||
| 536 | |||
| 530 | // 100% legal way to send a message as system | 537 | // 100% legal way to send a message as system |
| 531 | if (chat[j].extra?.type === system_message_types.NARRATOR) { | 538 | if (chat[j].extra?.type === system_message_types.NARRATOR) { |
| 532 | role = 'system'; | 539 | role = 'system'; |
| @@ -705,16 +712,18 @@ export function parseExampleIntoIndividual(messageExampleString, appendNamesForG | |||
| 705 | return result; | 712 | return result; |
| 706 | } | 713 | } |
| 707 | 714 | ||
| 708 | function formatWorldInfo(value) { | 715 | export function formatWorldInfo(value, { wiFormat = null } = {}) { |
| 709 | if (!value) { | 716 | if (!value) { |
| 710 | return ''; | 717 | return ''; |
| 711 | } | 718 | } |
| 712 | 719 | ||
| 713 | if (!oai_settings.wi_format.trim()) { | 720 | const format = wiFormat ?? oai_settings.wi_format; |
| 721 | |||
| 722 | if (!format.trim()) { | ||
| 714 | return value; | 723 | return value; |
| 715 | } | 724 | } |
| 716 | 725 | ||
| 717 | return stringFormat(oai_settings.wi_format, value); | 726 | return stringFormat(format, value); |
| 718 | } | 727 | } |
| 719 | 728 | ||
| 720 | /** | 729 | /** |
| @@ -733,7 +742,8 @@ async function populationInjectionPrompts(prompts, messages) { | |||
| 733 | 'assistant': extension_prompt_roles.ASSISTANT, | 742 | 'assistant': extension_prompt_roles.ASSISTANT, |
| 734 | }; | 743 | }; |
| 735 | 744 | ||
| 736 | for (let i = 0; i <= MAX_INJECTION_DEPTH; i++) { | 745 | const maxDepth = getExtensionPromptMaxDepth(); |
| 746 | for (let i = 0; i <= maxDepth; i++) { | ||
| 737 | // Get prompts for current depth | 747 | // Get prompts for current depth |
| 738 | const depthPrompts = prompts.filter(prompt => prompt.injection_depth === i && prompt.content); | 748 | const depthPrompts = prompts.filter(prompt => prompt.injection_depth === i && prompt.content); |
| 739 | 749 | ||
| @@ -952,7 +962,7 @@ async function populateDialogueExamples(prompts, chatCompletion, messageExamples | |||
| 952 | * @param {number} position - Prompt position in the extensions object. | 962 | * @param {number} position - Prompt position in the extensions object. |
| 953 | * @returns {string|false} - The prompt position for prompt collection. | 963 | * @returns {string|false} - The prompt position for prompt collection. |
| 954 | */ | 964 | */ |
| 955 | function getPromptPosition(position) { | 965 | export function getPromptPosition(position) { |
| 956 | if (position == extension_prompt_types.BEFORE_PROMPT) { | 966 | if (position == extension_prompt_types.BEFORE_PROMPT) { |
| 957 | return 'start'; | 967 | return 'start'; |
| 958 | } | 968 | } |
| @@ -969,7 +979,7 @@ function getPromptPosition(position) { | |||
| 969 | * @param {number} role Role of the prompt. | 979 | * @param {number} role Role of the prompt. |
| 970 | * @returns {string} Mapped role. | 980 | * @returns {string} Mapped role. |
| 971 | */ | 981 | */ |
| 972 | function getPromptRole(role) { | 982 | export function getPromptRole(role) { |
| 973 | switch (role) { | 983 | switch (role) { |
| 974 | case extension_prompt_roles.SYSTEM: | 984 | case extension_prompt_roles.SYSTEM: |
| 975 | return 'system'; | 985 | return 'system'; |
| @@ -1402,9 +1412,9 @@ export async function prepareOpenAIMessages({ | |||
| 1402 | await populateChatCompletion(prompts, chatCompletion, { bias, quietPrompt, quietImage, type, cyclePrompt, messages, messageExamples }); | 1412 | await populateChatCompletion(prompts, chatCompletion, { bias, quietPrompt, quietImage, type, cyclePrompt, messages, messageExamples }); |
| 1403 | } catch (error) { | 1413 | } catch (error) { |
| 1404 | if (error instanceof TokenBudgetExceededError) { | 1414 | if (error instanceof TokenBudgetExceededError) { |
| 1405 | toastr.error(t`An error occurred while counting tokens: Token budget exceeded.`); | 1415 | toastr.error(t`Mandatory prompts exceed the context size.`); |
| 1406 | chatCompletion.log('Token budget exceeded.'); | 1416 | chatCompletion.log('Mandatory prompts exceed the context size.'); |
| 1407 | promptManager.error = t`Not enough free tokens for mandatory prompts. Raise your token Limit or disable custom prompts.`; | 1417 | promptManager.error = t`Not enough free tokens for mandatory prompts. Raise your token limit or disable custom prompts.`; |
| 1408 | } else if (error instanceof InvalidCharacterNameError) { | 1418 | } else if (error instanceof InvalidCharacterNameError) { |
| 1409 | toastr.warning(t`An error occurred while counting tokens: Invalid character name`); | 1419 | toastr.warning(t`An error occurred while counting tokens: Invalid character name`); |
| 1410 | chatCompletion.log('Invalid character name'); | 1420 | chatCompletion.log('Invalid character name'); |
| @@ -1442,8 +1452,10 @@ export async function prepareOpenAIMessages({ | |||
| 1442 | * Handles errors during streaming requests. | 1452 | * Handles errors during streaming requests. |
| 1443 | * @param {Response} response | 1453 | * @param {Response} response |
| 1444 | * @param {string} decoded - response text or decoded stream data | 1454 | * @param {string} decoded - response text or decoded stream data |
| 1455 | * @param {object} [options] | ||
| 1456 | * @param {boolean?} [options.quiet=false] Suppress toast messages | ||
| 1445 | */ | 1457 | */ |
| 1446 | function tryParseStreamingError(response, decoded) { | 1458 | export function tryParseStreamingError(response, decoded, { quiet = false } = {}) { |
| 1447 | try { | 1459 | try { |
| 1448 | const data = JSON.parse(decoded); | 1460 | const data = JSON.parse(decoded); |
| 1449 | 1461 | ||
| @@ -1451,19 +1463,19 @@ function tryParseStreamingError(response, decoded) { | |||
| 1451 | return; | 1463 | return; |
| 1452 | } | 1464 | } |
| 1453 | 1465 | ||
| 1454 | checkQuotaError(data); | 1466 | checkQuotaError(data, { quiet }); |
| 1455 | checkModerationError(data); | 1467 | checkModerationError(data, { quiet }); |
| 1456 | 1468 | ||
| 1457 | // these do not throw correctly (equiv to Error("[object Object]")) | 1469 | // these do not throw correctly (equiv to Error("[object Object]")) |
| 1458 | // if trying to fix "[object Object]" displayed to users, start here | 1470 | // if trying to fix "[object Object]" displayed to users, start here |
| 1459 | 1471 | ||
| 1460 | if (data.error) { | 1472 | if (data.error) { |
| 1461 | toastr.error(data.error.message || response.statusText, 'Chat Completion API'); | 1473 | !quiet && toastr.error(data.error.message || response.statusText, 'Chat Completion API'); |
| 1462 | throw new Error(data); | 1474 | throw new Error(data); |
| 1463 | } | 1475 | } |
| 1464 | 1476 | ||
| 1465 | if (data.message) { | 1477 | if (data.message) { |
| 1466 | toastr.error(data.message, 'Chat Completion API'); | 1478 | !quiet && toastr.error(data.message, 'Chat Completion API'); |
| 1467 | throw new Error(data); | 1479 | throw new Error(data); |
| 1468 | } | 1480 | } |
| 1469 | } | 1481 | } |
| @@ -1475,16 +1487,18 @@ function tryParseStreamingError(response, decoded) { | |||
| 1475 | /** | 1487 | /** |
| 1476 | * Checks if the response contains a quota error and displays a popup if it does. | 1488 | * Checks if the response contains a quota error and displays a popup if it does. |
| 1477 | * @param data | 1489 | * @param data |
| 1490 | * @param {object} [options] | ||
| 1491 | * @param {boolean?} [options.quiet=false] Suppress toast messages | ||
| 1478 | * @returns {void} | 1492 | * @returns {void} |
| 1479 | * @throws {object} - response JSON | 1493 | * @throws {object} - response JSON |
| 1480 | */ | 1494 | */ |
| 1481 | function checkQuotaError(data) { | 1495 | function checkQuotaError(data, { quiet = false } = {}) { |
| 1482 | if (!data) { | 1496 | if (!data) { |
| 1483 | return; | 1497 | return; |
| 1484 | } | 1498 | } |
| 1485 | 1499 | ||
| 1486 | if (data.quota_error) { | 1500 | if (data.quota_error) { |
| 1487 | renderTemplateAsync('quotaError').then((html) => Popup.show.text('Quota Error', html)); | 1501 | !quiet && renderTemplateAsync('quotaError').then((html) => Popup.show.text('Quota Error', html)); |
| 1488 | 1502 | ||
| 1489 | // this does not throw correctly (equiv to Error("[object Object]")) | 1503 | // this does not throw correctly (equiv to Error("[object Object]")) |
| 1490 | // if trying to fix "[object Object]" displayed to users, start here | 1504 | // if trying to fix "[object Object]" displayed to users, start here |
| @@ -1492,9 +1506,14 @@ function checkQuotaError(data) { | |||
| 1492 | } | 1506 | } |
| 1493 | } | 1507 | } |
| 1494 | 1508 | ||
| 1495 | function checkModerationError(data) { | 1509 | /** |
| 1510 | * @param {any} data | ||
| 1511 | * @param {object} [options] | ||
| 1512 | * @param {boolean?} [options.quiet=false] Suppress toast messages | ||
| 1513 | */ | ||
| 1514 | function checkModerationError(data, { quiet = false } = {}) { | ||
| 1496 | const moderationError = data?.error?.message?.includes('requires moderation'); | 1515 | const moderationError = data?.error?.message?.includes('requires moderation'); |
| 1497 | if (moderationError) { | 1516 | if (moderationError && !quiet) { |
| 1498 | const moderationReason = `Reasons: ${data?.error?.metadata?.reasons?.join(', ') ?? '(N/A)'}`; | 1517 | const moderationReason = `Reasons: ${data?.error?.metadata?.reasons?.join(', ') ?? '(N/A)'}`; |
| 1499 | const flaggedText = data?.error?.metadata?.flagged_input ?? '(N/A)'; | 1518 | const flaggedText = data?.error?.metadata?.flagged_input ?? '(N/A)'; |
| 1500 | toastr.info(flaggedText, moderationReason, { timeOut: 10000 }); | 1519 | toastr.info(flaggedText, moderationReason, { timeOut: 10000 }); |
| @@ -1626,12 +1645,12 @@ export function getChatCompletionModel(source = null) { | |||
| 1626 | return oai_settings.groq_model; | 1645 | return oai_settings.groq_model; |
| 1627 | case chat_completion_sources.ZEROONEAI: | 1646 | case chat_completion_sources.ZEROONEAI: |
| 1628 | return oai_settings.zerooneai_model; | 1647 | return oai_settings.zerooneai_model; |
| 1629 | case chat_completion_sources.BLOCKENTROPY: | ||
| 1630 | return oai_settings.blockentropy_model; | ||
| 1631 | case chat_completion_sources.NANOGPT: | 1648 | case chat_completion_sources.NANOGPT: |
| 1632 | return oai_settings.nanogpt_model; | 1649 | return oai_settings.nanogpt_model; |
| 1633 | case chat_completion_sources.DEEPSEEK: | 1650 | case chat_completion_sources.DEEPSEEK: |
| 1634 | return oai_settings.deepseek_model; | 1651 | return oai_settings.deepseek_model; |
| 1652 | case chat_completion_sources.XAI: | ||
| 1653 | return oai_settings.xai_model; | ||
| 1635 | default: | 1654 | default: |
| 1636 | throw new Error(`Unknown chat completion source: ${activeSource}`); | 1655 | throw new Error(`Unknown chat completion source: ${activeSource}`); |
| 1637 | } | 1656 | } |
| @@ -1675,6 +1694,11 @@ function calculateOpenRouterCost() { | |||
| 1675 | } | 1694 | } |
| 1676 | } | 1695 | } |
| 1677 | 1696 | ||
| 1697 | if (oai_settings.enable_web_search) { | ||
| 1698 | const webSearchCost = (0.02).toFixed(2); | ||
| 1699 | cost = t`${cost} + $${webSearchCost}`; | ||
| 1700 | } | ||
| 1701 | |||
| 1678 | $('#openrouter_max_prompt_cost').text(cost); | 1702 | $('#openrouter_max_prompt_cost').text(cost); |
| 1679 | } | 1703 | } |
| 1680 | 1704 | ||
| @@ -1746,23 +1770,6 @@ function saveModelList(data) { | |||
| 1746 | $('#model_01ai_select').val(oai_settings.zerooneai_model).trigger('change'); | 1770 | $('#model_01ai_select').val(oai_settings.zerooneai_model).trigger('change'); |
| 1747 | } | 1771 | } |
| 1748 | 1772 | ||
| 1749 | if (oai_settings.chat_completion_source == chat_completion_sources.BLOCKENTROPY) { | ||
| 1750 | $('#model_blockentropy_select').empty(); | ||
| 1751 | model_list.forEach((model) => { | ||
| 1752 | $('#model_blockentropy_select').append( | ||
| 1753 | $('<option>', { | ||
| 1754 | value: model.id, | ||
| 1755 | text: model.id, | ||
| 1756 | })); | ||
| 1757 | }); | ||
| 1758 | |||
| 1759 | if (!oai_settings.blockentropy_model && model_list.length > 0) { | ||
| 1760 | oai_settings.blockentropy_model = model_list[0].id; | ||
| 1761 | } | ||
| 1762 | |||
| 1763 | $('#model_blockentropy_select').val(oai_settings.blockentropy_model).trigger('change'); | ||
| 1764 | } | ||
| 1765 | |||
| 1766 | if (oai_settings.chat_completion_source == chat_completion_sources.MISTRALAI) { | 1773 | if (oai_settings.chat_completion_source == chat_completion_sources.MISTRALAI) { |
| 1767 | /** @type {HTMLSelectElement} */ | 1774 | /** @type {HTMLSelectElement} */ |
| 1768 | const mistralModelSelect = document.querySelector('#model_mistralai_select'); | 1775 | const mistralModelSelect = document.querySelector('#model_mistralai_select'); |
| @@ -1966,13 +1973,14 @@ async function sendOpenAIRequest(type, messages, signal) { | |||
| 1966 | const is01AI = oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI; | 1973 | const is01AI = oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI; |
| 1967 | const isNano = oai_settings.chat_completion_source == chat_completion_sources.NANOGPT; | 1974 | const isNano = oai_settings.chat_completion_source == chat_completion_sources.NANOGPT; |
| 1968 | const isDeepSeek = oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK; | 1975 | const isDeepSeek = oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK; |
| 1976 | const isXAI = oai_settings.chat_completion_source == chat_completion_sources.XAI; | ||
| 1969 | const isTextCompletion = isOAI && textCompletionModels.includes(oai_settings.openai_model); | 1977 | const isTextCompletion = isOAI && textCompletionModels.includes(oai_settings.openai_model); |
| 1970 | const isQuiet = type === 'quiet'; | 1978 | const isQuiet = type === 'quiet'; |
| 1971 | const isImpersonate = type === 'impersonate'; | 1979 | const isImpersonate = type === 'impersonate'; |
| 1972 | const isContinue = type === 'continue'; | 1980 | const isContinue = type === 'continue'; |
| 1973 | const stream = oai_settings.stream_openai && !isQuiet && !isScale && !(isOAI && ['o1-2024-12-17', 'o1'].includes(oai_settings.openai_model)); | 1981 | const stream = oai_settings.stream_openai && !isQuiet && !isScale && !(isOAI && ['o1-2024-12-17', 'o1'].includes(oai_settings.openai_model)); |
| 1974 | const useLogprobs = !!power_user.request_token_probabilities; | 1982 | const useLogprobs = !!power_user.request_token_probabilities; |
| 1975 | const canMultiSwipe = oai_settings.n > 1 && !isContinue && !isImpersonate && !isQuiet && (isOAI || isCustom); | 1983 | const canMultiSwipe = oai_settings.n > 1 && !isContinue && !isImpersonate && !isQuiet && (isOAI || isCustom || isXAI); |
| 1976 | 1984 | ||
| 1977 | // If we're using the window.ai extension, use that instead | 1985 | // If we're using the window.ai extension, use that instead |
| 1978 | // Doesn't support logit bias yet | 1986 | // Doesn't support logit bias yet |
| @@ -2018,6 +2026,7 @@ async function sendOpenAIRequest(type, messages, signal) { | |||
| 2018 | 'reasoning_effort': String(oai_settings.reasoning_effort), | 2026 | 'reasoning_effort': String(oai_settings.reasoning_effort), |
| 2019 | 'enable_web_search': Boolean(oai_settings.enable_web_search), | 2027 | 'enable_web_search': Boolean(oai_settings.enable_web_search), |
| 2020 | 'request_images': Boolean(oai_settings.request_images), | 2028 | 'request_images': Boolean(oai_settings.request_images), |
| 2029 | 'custom_prompt_post_processing': oai_settings.custom_prompt_post_processing, | ||
| 2021 | }; | 2030 | }; |
| 2022 | 2031 | ||
| 2023 | if (!canMultiSwipe && ToolManager.canPerformToolCalls(type)) { | 2032 | if (!canMultiSwipe && ToolManager.canPerformToolCalls(type)) { |
| @@ -2030,14 +2039,14 @@ async function sendOpenAIRequest(type, messages, signal) { | |||
| 2030 | } | 2039 | } |
| 2031 | 2040 | ||
| 2032 | // Proxy is only supported for Claude, OpenAI, Mistral, and Google MakerSuite | 2041 | // Proxy is only supported for Claude, OpenAI, Mistral, and Google MakerSuite |
| 2033 | if (oai_settings.reverse_proxy && [chat_completion_sources.CLAUDE, chat_completion_sources.OPENAI, chat_completion_sources.MISTRALAI, chat_completion_sources.MAKERSUITE, chat_completion_sources.DEEPSEEK].includes(oai_settings.chat_completion_source)) { | 2042 | if (oai_settings.reverse_proxy && [chat_completion_sources.CLAUDE, chat_completion_sources.OPENAI, chat_completion_sources.MISTRALAI, chat_completion_sources.MAKERSUITE, chat_completion_sources.DEEPSEEK, chat_completion_sources.XAI].includes(oai_settings.chat_completion_source)) { |
| 2034 | await validateReverseProxy(); | 2043 | await validateReverseProxy(); |
| 2035 | generate_data['reverse_proxy'] = oai_settings.reverse_proxy; | 2044 | generate_data['reverse_proxy'] = oai_settings.reverse_proxy; |
| 2036 | generate_data['proxy_password'] = oai_settings.proxy_password; | 2045 | generate_data['proxy_password'] = oai_settings.proxy_password; |
| 2037 | } | 2046 | } |
| 2038 | 2047 | ||
| 2039 | // Add logprobs request (currently OpenAI only, max 5 on their side) | 2048 | // Add logprobs request (currently OpenAI only, max 5 on their side) |
| 2040 | if (useLogprobs && (isOAI || isCustom || isDeepSeek)) { | 2049 | if (useLogprobs && (isOAI || isCustom || isDeepSeek || isXAI)) { |
| 2041 | generate_data['logprobs'] = 5; | 2050 | generate_data['logprobs'] = 5; |
| 2042 | } | 2051 | } |
| 2043 | 2052 | ||
| @@ -2048,7 +2057,7 @@ async function sendOpenAIRequest(type, messages, signal) { | |||
| 2048 | delete generate_data.stop; | 2057 | delete generate_data.stop; |
| 2049 | delete generate_data.logprobs; | 2058 | delete generate_data.logprobs; |
| 2050 | } | 2059 | } |
| 2051 | if (isOAI && oai_settings.openai_model.includes('gpt-4.5-preview') || isOpenRouter && oai_settings.openrouter_model.includes('gpt-4.5-preview')) { | 2060 | if (isOAI && oai_settings.openai_model.includes('gpt-4.5') || isOpenRouter && oai_settings.openrouter_model.includes('gpt-4.5')) { |
| 2052 | delete generate_data.logprobs; | 2061 | delete generate_data.logprobs; |
| 2053 | } | 2062 | } |
| 2054 | 2063 | ||
| @@ -2098,7 +2107,6 @@ async function sendOpenAIRequest(type, messages, signal) { | |||
| 2098 | generate_data['custom_include_body'] = oai_settings.custom_include_body; | 2107 | generate_data['custom_include_body'] = oai_settings.custom_include_body; |
| 2099 | generate_data['custom_exclude_body'] = oai_settings.custom_exclude_body; | 2108 | generate_data['custom_exclude_body'] = oai_settings.custom_exclude_body; |
| 2100 | generate_data['custom_include_headers'] = oai_settings.custom_include_headers; | 2109 | generate_data['custom_include_headers'] = oai_settings.custom_include_headers; |
| 2101 | generate_data['custom_prompt_post_processing'] = oai_settings.custom_prompt_post_processing; | ||
| 2102 | } | 2110 | } |
| 2103 | 2111 | ||
| 2104 | if (isCohere) { | 2112 | if (isCohere) { |
| @@ -2157,29 +2165,42 @@ async function sendOpenAIRequest(type, messages, signal) { | |||
| 2157 | } | 2165 | } |
| 2158 | } | 2166 | } |
| 2159 | 2167 | ||
| 2160 | if ((isOAI || isOpenRouter || isMistral || isCustom || isCohere || isNano) && oai_settings.seed >= 0) { | 2168 | if (isXAI) { |
| 2169 | if (generate_data.model.includes('grok-3-mini')) { | ||
| 2170 | delete generate_data.presence_penalty; | ||
| 2171 | delete generate_data.frequency_penalty; | ||
| 2172 | } | ||
| 2173 | if (generate_data.model.includes('grok-vision')) { | ||
| 2174 | delete generate_data.tools; | ||
| 2175 | delete generate_data.tool_choice; | ||
| 2176 | } | ||
| 2177 | } | ||
| 2178 | |||
| 2179 | if ((isOAI || isOpenRouter || isMistral || isCustom || isCohere || isNano || isXAI) && oai_settings.seed >= 0) { | ||
| 2161 | generate_data['seed'] = oai_settings.seed; | 2180 | generate_data['seed'] = oai_settings.seed; |
| 2162 | } | 2181 | } |
| 2163 | 2182 | ||
| 2164 | if (isOAI && (oai_settings.openai_model.startsWith('o1') || oai_settings.openai_model.startsWith('o3'))) { | 2183 | if (isOAI && /^(o1|o3|o4)/.test(oai_settings.openai_model)) { |
| 2165 | generate_data.messages.forEach((msg) => { | ||
| 2166 | if (msg.role === 'system') { | ||
| 2167 | msg.role = 'user'; | ||
| 2168 | } | ||
| 2169 | }); | ||
| 2170 | generate_data.max_completion_tokens = generate_data.max_tokens; | 2184 | generate_data.max_completion_tokens = generate_data.max_tokens; |
| 2171 | delete generate_data.max_tokens; | 2185 | delete generate_data.max_tokens; |
| 2172 | delete generate_data.logprobs; | 2186 | delete generate_data.logprobs; |
| 2173 | delete generate_data.top_logprobs; | 2187 | delete generate_data.top_logprobs; |
| 2174 | delete generate_data.n; | 2188 | delete generate_data.stop; |
| 2189 | delete generate_data.logit_bias; | ||
| 2175 | delete generate_data.temperature; | 2190 | delete generate_data.temperature; |
| 2176 | delete generate_data.top_p; | 2191 | delete generate_data.top_p; |
| 2177 | delete generate_data.frequency_penalty; | 2192 | delete generate_data.frequency_penalty; |
| 2178 | delete generate_data.presence_penalty; | 2193 | delete generate_data.presence_penalty; |
| 2179 | delete generate_data.tools; | 2194 | if (oai_settings.openai_model.startsWith('o1')) { |
| 2180 | delete generate_data.tool_choice; | 2195 | generate_data.messages.forEach((msg) => { |
| 2181 | delete generate_data.stop; | 2196 | if (msg.role === 'system') { |
| 2182 | delete generate_data.logit_bias; | 2197 | msg.role = 'user'; |
| 2198 | } | ||
| 2199 | }); | ||
| 2200 | delete generate_data.n; | ||
| 2201 | delete generate_data.tools; | ||
| 2202 | delete generate_data.tool_choice; | ||
| 2203 | } | ||
| 2183 | } | 2204 | } |
| 2184 | 2205 | ||
| 2185 | await eventSource.emit(event_types.CHAT_COMPLETION_SETTINGS_READY, generate_data); | 2206 | await eventSource.emit(event_types.CHAT_COMPLETION_SETTINGS_READY, generate_data); |
| @@ -2215,7 +2236,8 @@ async function sendOpenAIRequest(type, messages, signal) { | |||
| 2215 | 2236 | ||
| 2216 | if (Array.isArray(parsed?.choices) && parsed?.choices?.[0]?.index > 0) { | 2237 | if (Array.isArray(parsed?.choices) && parsed?.choices?.[0]?.index > 0) { |
| 2217 | const swipeIndex = parsed.choices[0].index - 1; | 2238 | const swipeIndex = parsed.choices[0].index - 1; |
| 2218 | swipes[swipeIndex] = (swipes[swipeIndex] || '') + getStreamingReply(parsed, state); | 2239 | // FIXME: state.reasoning should be an array to support multi-swipe |
| 2240 | swipes[swipeIndex] = (swipes[swipeIndex] || '') + getStreamingReply(parsed, state, { overrideShowThoughts: false }); | ||
| 2219 | } else { | 2241 | } else { |
| 2220 | text += getStreamingReply(parsed, state); | 2242 | text += getStreamingReply(parsed, state); |
| 2221 | } | 2243 | } |
| @@ -2253,37 +2275,48 @@ async function sendOpenAIRequest(type, messages, signal) { | |||
| 2253 | * Extracts the reply from the response data from a chat completions-like source | 2275 | * Extracts the reply from the response data from a chat completions-like source |
| 2254 | * @param {object} data Response data from the chat completions-like source | 2276 | * @param {object} data Response data from the chat completions-like source |
| 2255 | * @param {object} state Additional state to keep track of | 2277 | * @param {object} state Additional state to keep track of |
| 2278 | * @param {object} [options] Additional options | ||
| 2279 | * @param {string?} [options.chatCompletionSource] Chat completion source | ||
| 2280 | * @param {boolean?} [options.overrideShowThoughts] Override show thoughts | ||
| 2256 | * @returns {string} The reply extracted from the response data | 2281 | * @returns {string} The reply extracted from the response data |
| 2257 | */ | 2282 | */ |
| 2258 | function getStreamingReply(data, state) { | 2283 | export function getStreamingReply(data, state, { chatCompletionSource = null, overrideShowThoughts = null } = {}) { |
| 2259 | if (oai_settings.chat_completion_source === chat_completion_sources.CLAUDE) { | 2284 | const chat_completion_source = chatCompletionSource ?? oai_settings.chat_completion_source; |
| 2260 | if (oai_settings.show_thoughts) { | 2285 | const show_thoughts = overrideShowThoughts ?? oai_settings.show_thoughts; |
| 2286 | |||
| 2287 | if (chat_completion_source === chat_completion_sources.CLAUDE) { | ||
| 2288 | if (show_thoughts) { | ||
| 2261 | state.reasoning += data?.delta?.thinking || ''; | 2289 | state.reasoning += data?.delta?.thinking || ''; |
| 2262 | } | 2290 | } |
| 2263 | return data?.delta?.text || ''; | 2291 | return data?.delta?.text || ''; |
| 2264 | } else if (oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE) { | 2292 | } else if (chat_completion_source === chat_completion_sources.MAKERSUITE) { |
| 2265 | const inlineData = data?.candidates?.[0]?.content?.parts?.find(x => x.inlineData)?.inlineData; | 2293 | const inlineData = data?.candidates?.[0]?.content?.parts?.find(x => x.inlineData)?.inlineData; |
| 2266 | if (inlineData) { | 2294 | if (inlineData) { |
| 2267 | state.image = `data:${inlineData.mimeType};base64,${inlineData.data}`; | 2295 | state.image = `data:${inlineData.mimeType};base64,${inlineData.data}`; |
| 2268 | } | 2296 | } |
| 2269 | if (oai_settings.show_thoughts) { | 2297 | if (show_thoughts) { |
| 2270 | state.reasoning += (data?.candidates?.[0]?.content?.parts?.filter(x => x.thought)?.map(x => x.text)?.[0] || ''); | 2298 | state.reasoning += (data?.candidates?.[0]?.content?.parts?.filter(x => x.thought)?.map(x => x.text)?.[0] || ''); |
| 2271 | } | 2299 | } |
| 2272 | return data?.candidates?.[0]?.content?.parts?.filter(x => !x.thought)?.map(x => x.text)?.[0] || ''; | 2300 | return data?.candidates?.[0]?.content?.parts?.filter(x => !x.thought)?.map(x => x.text)?.[0] || ''; |
| 2273 | } else if (oai_settings.chat_completion_source === chat_completion_sources.COHERE) { | 2301 | } else if (chat_completion_source === chat_completion_sources.COHERE) { |
| 2274 | return data?.delta?.message?.content?.text || data?.delta?.message?.tool_plan || ''; | 2302 | return data?.delta?.message?.content?.text || data?.delta?.message?.tool_plan || ''; |
| 2275 | } else if (oai_settings.chat_completion_source === chat_completion_sources.DEEPSEEK) { | 2303 | } else if (chat_completion_source === chat_completion_sources.DEEPSEEK) { |
| 2276 | if (oai_settings.show_thoughts) { | 2304 | if (show_thoughts) { |
| 2277 | state.reasoning += (data.choices?.filter(x => x?.delta?.reasoning_content)?.[0]?.delta?.reasoning_content || ''); | 2305 | state.reasoning += (data.choices?.filter(x => x?.delta?.reasoning_content)?.[0]?.delta?.reasoning_content || ''); |
| 2278 | } | 2306 | } |
| 2279 | return data.choices?.[0]?.delta?.content || ''; | 2307 | return data.choices?.[0]?.delta?.content || ''; |
| 2280 | } else if (oai_settings.chat_completion_source === chat_completion_sources.OPENROUTER) { | 2308 | } else if (chat_completion_source === chat_completion_sources.XAI) { |
| 2281 | if (oai_settings.show_thoughts) { | 2309 | if (show_thoughts) { |
| 2310 | state.reasoning += (data.choices?.filter(x => x?.delta?.reasoning_content)?.[0]?.delta?.reasoning_content || ''); | ||
| 2311 | } | ||
| 2312 | return data.choices?.[0]?.delta?.content || ''; | ||
| 2313 | } else if (chat_completion_source === chat_completion_sources.OPENROUTER) { | ||
| 2314 | if (show_thoughts) { | ||
| 2282 | state.reasoning += (data.choices?.filter(x => x?.delta?.reasoning)?.[0]?.delta?.reasoning || ''); | 2315 | state.reasoning += (data.choices?.filter(x => x?.delta?.reasoning)?.[0]?.delta?.reasoning || ''); |
| 2283 | } | 2316 | } |
| 2284 | return data.choices?.[0]?.delta?.content ?? data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? ''; | 2317 | return data.choices?.[0]?.delta?.content ?? data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? ''; |
| 2285 | } else if (oai_settings.chat_completion_source === chat_completion_sources.CUSTOM) { | 2318 | } else if (chat_completion_source === chat_completion_sources.CUSTOM) { |
| 2286 | if (oai_settings.show_thoughts) { | 2319 | if (show_thoughts) { |
| 2287 | state.reasoning += | 2320 | state.reasoning += |
| 2288 | data.choices?.filter(x => x?.delta?.reasoning_content)?.[0]?.delta?.reasoning_content ?? | 2321 | data.choices?.filter(x => x?.delta?.reasoning_content)?.[0]?.delta?.reasoning_content ?? |
| 2289 | data.choices?.filter(x => x?.delta?.reasoning)?.[0]?.delta?.reasoning ?? | 2322 | data.choices?.filter(x => x?.delta?.reasoning)?.[0]?.delta?.reasoning ?? |
| @@ -2309,6 +2342,7 @@ function parseChatCompletionLogprobs(data) { | |||
| 2309 | switch (oai_settings.chat_completion_source) { | 2342 | switch (oai_settings.chat_completion_source) { |
| 2310 | case chat_completion_sources.OPENAI: | 2343 | case chat_completion_sources.OPENAI: |
| 2311 | case chat_completion_sources.DEEPSEEK: | 2344 | case chat_completion_sources.DEEPSEEK: |
| 2345 | case chat_completion_sources.XAI: | ||
| 2312 | case chat_completion_sources.CUSTOM: | 2346 | case chat_completion_sources.CUSTOM: |
| 2313 | if (!data.choices?.length) { | 2347 | if (!data.choices?.length) { |
| 2314 | return null; | 2348 | return null; |
| @@ -3229,8 +3263,8 @@ function loadOpenAISettings(data, settings) { | |||
| 3229 | oai_settings.groq_model = settings.groq_model ?? default_settings.groq_model; | 3263 | oai_settings.groq_model = settings.groq_model ?? default_settings.groq_model; |
| 3230 | oai_settings.nanogpt_model = settings.nanogpt_model ?? default_settings.nanogpt_model; | 3264 | oai_settings.nanogpt_model = settings.nanogpt_model ?? default_settings.nanogpt_model; |
| 3231 | oai_settings.deepseek_model = settings.deepseek_model ?? default_settings.deepseek_model; | 3265 | oai_settings.deepseek_model = settings.deepseek_model ?? default_settings.deepseek_model; |
| 3232 | oai_settings.blockentropy_model = settings.blockentropy_model ?? default_settings.blockentropy_model; | ||
| 3233 | oai_settings.zerooneai_model = settings.zerooneai_model ?? default_settings.zerooneai_model; | 3266 | oai_settings.zerooneai_model = settings.zerooneai_model ?? default_settings.zerooneai_model; |
| 3267 | oai_settings.xai_model = settings.xai_model ?? default_settings.xai_model; | ||
| 3234 | oai_settings.custom_model = settings.custom_model ?? default_settings.custom_model; | 3268 | oai_settings.custom_model = settings.custom_model ?? default_settings.custom_model; |
| 3235 | oai_settings.custom_url = settings.custom_url ?? default_settings.custom_url; | 3269 | oai_settings.custom_url = settings.custom_url ?? default_settings.custom_url; |
| 3236 | oai_settings.custom_include_body = settings.custom_include_body ?? default_settings.custom_include_body; | 3270 | oai_settings.custom_include_body = settings.custom_include_body ?? default_settings.custom_include_body; |
| @@ -3316,7 +3350,8 @@ function loadOpenAISettings(data, settings) { | |||
| 3316 | $('#model_deepseek_select').val(oai_settings.deepseek_model); | 3350 | $('#model_deepseek_select').val(oai_settings.deepseek_model); |
| 3317 | $(`#model_deepseek_select option[value="${oai_settings.deepseek_model}"`).prop('selected', true); | 3351 | $(`#model_deepseek_select option[value="${oai_settings.deepseek_model}"`).prop('selected', true); |
| 3318 | $('#model_01ai_select').val(oai_settings.zerooneai_model); | 3352 | $('#model_01ai_select').val(oai_settings.zerooneai_model); |
| 3319 | $('#model_blockentropy_select').val(oai_settings.blockentropy_model); | 3353 | $('#model_xai_select').val(oai_settings.xai_model); |
| 3354 | $(`#model_xai_select option[value="${oai_settings.xai_model}"`).attr('selected', true); | ||
| 3320 | $('#custom_model_id').val(oai_settings.custom_model); | 3355 | $('#custom_model_id').val(oai_settings.custom_model); |
| 3321 | $('#custom_api_url_text').val(oai_settings.custom_url); | 3356 | $('#custom_api_url_text').val(oai_settings.custom_url); |
| 3322 | $('#openai_max_context').val(oai_settings.openai_max_context); | 3357 | $('#openai_max_context').val(oai_settings.openai_max_context); |
| @@ -3476,7 +3511,7 @@ async function getStatusOpen() { | |||
| 3476 | let status; | 3511 | let status; |
| 3477 | 3512 | ||
| 3478 | if ('ai' in window) { | 3513 | if ('ai' in window) { |
| 3479 | status = 'Valid'; | 3514 | status = t`Valid`; |
| 3480 | } | 3515 | } |
| 3481 | else { | 3516 | else { |
| 3482 | showWindowExtensionError(); | 3517 | showWindowExtensionError(); |
| @@ -3513,7 +3548,7 @@ async function getStatusOpen() { | |||
| 3513 | chat_completion_source: oai_settings.chat_completion_source, | 3548 | chat_completion_source: oai_settings.chat_completion_source, |
| 3514 | }; | 3549 | }; |
| 3515 | 3550 | ||
| 3516 | if (oai_settings.reverse_proxy && [chat_completion_sources.CLAUDE, chat_completion_sources.OPENAI, chat_completion_sources.MISTRALAI, chat_completion_sources.MAKERSUITE, chat_completion_sources.DEEPSEEK].includes(oai_settings.chat_completion_source)) { | 3551 | if (oai_settings.reverse_proxy && [chat_completion_sources.CLAUDE, chat_completion_sources.OPENAI, chat_completion_sources.MISTRALAI, chat_completion_sources.MAKERSUITE, chat_completion_sources.DEEPSEEK, chat_completion_sources.XAI].includes(oai_settings.chat_completion_source)) { |
| 3517 | await validateReverseProxy(); | 3552 | await validateReverseProxy(); |
| 3518 | } | 3553 | } |
| 3519 | 3554 | ||
| @@ -3525,7 +3560,7 @@ async function getStatusOpen() { | |||
| 3525 | 3560 | ||
| 3526 | const canBypass = (oai_settings.chat_completion_source === chat_completion_sources.OPENAI && oai_settings.bypass_status_check) || oai_settings.chat_completion_source === chat_completion_sources.CUSTOM; | 3561 | const canBypass = (oai_settings.chat_completion_source === chat_completion_sources.OPENAI && oai_settings.bypass_status_check) || oai_settings.chat_completion_source === chat_completion_sources.CUSTOM; |
| 3527 | if (canBypass) { | 3562 | if (canBypass) { |
| 3528 | setOnlineStatus('Status check bypassed'); | 3563 | setOnlineStatus(t`Status check bypassed`); |
| 3529 | } | 3564 | } |
| 3530 | 3565 | ||
| 3531 | try { | 3566 | try { |
| @@ -3547,7 +3582,7 @@ async function getStatusOpen() { | |||
| 3547 | saveModelList(responseData.data); | 3582 | saveModelList(responseData.data); |
| 3548 | } | 3583 | } |
| 3549 | if (!('error' in responseData)) { | 3584 | if (!('error' in responseData)) { |
| 3550 | setOnlineStatus('Valid'); | 3585 | setOnlineStatus(t`Valid`); |
| 3551 | } | 3586 | } |
| 3552 | } catch (error) { | 3587 | } catch (error) { |
| 3553 | console.error(error); | 3588 | console.error(error); |
| @@ -3596,7 +3631,6 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) { | |||
| 3596 | perplexity_model: settings.perplexity_model, | 3631 | perplexity_model: settings.perplexity_model, |
| 3597 | groq_model: settings.groq_model, | 3632 | groq_model: settings.groq_model, |
| 3598 | zerooneai_model: settings.zerooneai_model, | 3633 | zerooneai_model: settings.zerooneai_model, |
| 3599 | blockentropy_model: settings.blockentropy_model, | ||
| 3600 | custom_model: settings.custom_model, | 3634 | custom_model: settings.custom_model, |
| 3601 | custom_url: settings.custom_url, | 3635 | custom_url: settings.custom_url, |
| 3602 | custom_include_body: settings.custom_include_body, | 3636 | custom_include_body: settings.custom_include_body, |
| @@ -4094,9 +4128,15 @@ function getMaxContextOpenAI(value) { | |||
| 4094 | if (oai_settings.max_context_unlocked) { | 4128 | if (oai_settings.max_context_unlocked) { |
| 4095 | return unlocked_max; | 4129 | return unlocked_max; |
| 4096 | } | 4130 | } |
| 4097 | else if (value.startsWith('o1') || value.startsWith('o3')) { | 4131 | else if (value.includes('gpt-4.1')) { |
| 4132 | return max_1mil; | ||
| 4133 | } | ||
| 4134 | else if (value.startsWith('o1')) { | ||
| 4098 | return max_128k; | 4135 | return max_128k; |
| 4099 | } | 4136 | } |
| 4137 | else if (value.startsWith('o4') || value.startsWith('o3')) { | ||
| 4138 | return max_200k; | ||
| 4139 | } | ||
| 4100 | else if (value.includes('chatgpt-4o-latest') || value.includes('gpt-4-turbo') || value.includes('gpt-4o') || value.includes('gpt-4-1106') || value.includes('gpt-4-0125') || value.includes('gpt-4-vision')) { | 4140 | else if (value.includes('chatgpt-4o-latest') || value.includes('gpt-4-turbo') || value.includes('gpt-4o') || value.includes('gpt-4-1106') || value.includes('gpt-4-0125') || value.includes('gpt-4-vision')) { |
| 4101 | return max_128k; | 4141 | return max_128k; |
| 4102 | } | 4142 | } |
| @@ -4168,6 +4208,80 @@ function getMaxContextWindowAI(value) { | |||
| 4168 | } | 4208 | } |
| 4169 | 4209 | ||
| 4170 | /** | 4210 | /** |
| 4211 | * Get the maximum context size for the Mistral model | ||
| 4212 | * @param {string} model Model identifier | ||
| 4213 | * @param {boolean} isUnlocked Whether context limits are unlocked | ||
| 4214 | * @returns {number} Maximum context size in tokens | ||
| 4215 | */ | ||
| 4216 | function getMistralMaxContext(model, isUnlocked) { | ||
| 4217 | if (isUnlocked) { | ||
| 4218 | return unlocked_max; | ||
| 4219 | } | ||
| 4220 | |||
| 4221 | if (Array.isArray(model_list) && model_list.length > 0) { | ||
| 4222 | const contextLength = model_list.find((record) => record.id === model)?.max_context_length; | ||
| 4223 | if (contextLength) { | ||
| 4224 | return contextLength; | ||
| 4225 | } | ||
| 4226 | } | ||
| 4227 | |||
| 4228 | const contextMap = { | ||
| 4229 | 'codestral-2411-rc5': 262144, | ||
| 4230 | 'codestral-2412': 262144, | ||
| 4231 | 'codestral-2501': 262144, | ||
| 4232 | 'codestral-latest': 262144, | ||
| 4233 | 'codestral-mamba-2407': 262144, | ||
| 4234 | 'codestral-mamba-latest': 262144, | ||
| 4235 | 'open-codestral-mamba': 262144, | ||
| 4236 | 'ministral-3b-2410': 131072, | ||
| 4237 | 'ministral-3b-latest': 131072, | ||
| 4238 | 'ministral-8b-2410': 131072, | ||
| 4239 | 'ministral-8b-latest': 131072, | ||
| 4240 | 'mistral-large-2407': 131072, | ||
| 4241 | 'mistral-large-2411': 131072, | ||
| 4242 | 'mistral-large-latest': 131072, | ||
| 4243 | 'mistral-large-pixtral-2411': 131072, | ||
| 4244 | 'mistral-tiny-2407': 131072, | ||
| 4245 | 'mistral-tiny-latest': 131072, | ||
| 4246 | 'open-mistral-nemo': 131072, | ||
| 4247 | 'open-mistral-nemo-2407': 131072, | ||
| 4248 | 'pixtral-12b': 131072, | ||
| 4249 | 'pixtral-12b-2409': 131072, | ||
| 4250 | 'pixtral-12b-latest': 131072, | ||
| 4251 | 'pixtral-large-2411': 131072, | ||
| 4252 | 'pixtral-large-latest': 131072, | ||
| 4253 | 'open-mixtral-8x22b': 65536, | ||
| 4254 | 'open-mixtral-8x22b-2404': 65536, | ||
| 4255 | 'codestral-2405': 32768, | ||
| 4256 | 'mistral-embed': 32768, | ||
| 4257 | 'mistral-large-2402': 32768, | ||
| 4258 | 'mistral-medium': 32768, | ||
| 4259 | 'mistral-medium-2312': 32768, | ||
| 4260 | 'mistral-medium-latest': 32768, | ||
| 4261 | 'mistral-moderation-2411': 32768, | ||
| 4262 | 'mistral-moderation-latest': 32768, | ||
| 4263 | 'mistral-ocr-2503': 32768, | ||
| 4264 | 'mistral-ocr-latest': 32768, | ||
| 4265 | 'mistral-saba-2502': 32768, | ||
| 4266 | 'mistral-saba-latest': 32768, | ||
| 4267 | 'mistral-small': 32768, | ||
| 4268 | 'mistral-small-2312': 32768, | ||
| 4269 | 'mistral-small-2402': 32768, | ||
| 4270 | 'mistral-small-2409': 32768, | ||
| 4271 | 'mistral-small-2501': 32768, | ||
| 4272 | 'mistral-small-2503': 32768, | ||
| 4273 | 'mistral-small-latest': 32768, | ||
| 4274 | 'mistral-tiny': 32768, | ||
| 4275 | 'mistral-tiny-2312': 32768, | ||
| 4276 | 'open-mistral-7b': 32768, | ||
| 4277 | 'open-mixtral-8x7b': 32768, | ||
| 4278 | }; | ||
| 4279 | |||
| 4280 | // Return context size if model found, otherwise default to 32k | ||
| 4281 | return Object.entries(contextMap).find(([key]) => model.includes(key))?.[1] || 32768; | ||
| 4282 | } | ||
| 4283 | |||
| 4284 | /** | ||
| 4171 | * Get the maximum context size for the Groq model | 4285 | * Get the maximum context size for the Groq model |
| 4172 | * @param {string} model Model identifier | 4286 | * @param {string} model Model identifier |
| 4173 | * @param {boolean} isUnlocked Whether context limits are unlocked | 4287 | * @param {boolean} isUnlocked Whether context limits are unlocked |
| @@ -4195,6 +4309,9 @@ function getGroqMaxContext(model, isUnlocked) { | |||
| 4195 | 'qwen-2.5-32b': max_128k, | 4309 | 'qwen-2.5-32b': max_128k, |
| 4196 | 'deepseek-r1-distill-qwen-32b': max_128k, | 4310 | 'deepseek-r1-distill-qwen-32b': max_128k, |
| 4197 | 'deepseek-r1-distill-llama-70b-specdec': max_128k, | 4311 | 'deepseek-r1-distill-llama-70b-specdec': max_128k, |
| 4312 | 'mistral-saba-24b': max_32k, | ||
| 4313 | 'meta-llama/llama-4-scout-17b-16e-instruct': max_128k, | ||
| 4314 | 'meta-llama/llama-4-maverick-17b-128e-instruct': max_128k, | ||
| 4198 | }; | 4315 | }; |
| 4199 | 4316 | ||
| 4200 | // Return context size if model found, otherwise default to 128k | 4317 | // Return context size if model found, otherwise default to 128k |
| @@ -4305,18 +4422,17 @@ async function onModelChange() { | |||
| 4305 | oai_settings.zerooneai_model = value; | 4422 | oai_settings.zerooneai_model = value; |
| 4306 | } | 4423 | } |
| 4307 | 4424 | ||
| 4308 | if (value && $(this).is('#model_blockentropy_select')) { | ||
| 4309 | console.log('Block Entropy model changed to', value); | ||
| 4310 | oai_settings.blockentropy_model = value; | ||
| 4311 | $('#blockentropy_model_id').val(value).trigger('input'); | ||
| 4312 | } | ||
| 4313 | |||
| 4314 | if (value && $(this).is('#model_custom_select')) { | 4425 | if (value && $(this).is('#model_custom_select')) { |
| 4315 | console.log('Custom model changed to', value); | 4426 | console.log('Custom model changed to', value); |
| 4316 | oai_settings.custom_model = value; | 4427 | oai_settings.custom_model = value; |
| 4317 | $('#custom_model_id').val(value).trigger('input'); | 4428 | $('#custom_model_id').val(value).trigger('input'); |
| 4318 | } | 4429 | } |
| 4319 | 4430 | ||
| 4431 | if ($(this).is('#model_xai_select')) { | ||
| 4432 | console.log('XAI model changed to', value); | ||
| 4433 | oai_settings.xai_model = value; | ||
| 4434 | } | ||
| 4435 | |||
| 4320 | if (oai_settings.chat_completion_source == chat_completion_sources.SCALE) { | 4436 | if (oai_settings.chat_completion_source == chat_completion_sources.SCALE) { |
| 4321 | if (oai_settings.max_context_unlocked) { | 4437 | if (oai_settings.max_context_unlocked) { |
| 4322 | $('#openai_max_context').attr('max', unlocked_max); | 4438 | $('#openai_max_context').attr('max', unlocked_max); |
| @@ -4335,7 +4451,7 @@ async function onModelChange() { | |||
| 4335 | $('#openai_max_context').attr('max', max_32k); | 4451 | $('#openai_max_context').attr('max', max_32k); |
| 4336 | } else if (value.includes('gemini-1.5-pro') || value.includes('gemini-exp-1206') || value.includes('gemini-2.0-pro')) { | 4452 | } else if (value.includes('gemini-1.5-pro') || value.includes('gemini-exp-1206') || value.includes('gemini-2.0-pro')) { |
| 4337 | $('#openai_max_context').attr('max', max_2mil); | 4453 | $('#openai_max_context').attr('max', max_2mil); |
| 4338 | } else if (value.includes('gemini-1.5-flash') || value.includes('gemini-2.0-flash')) { | 4454 | } else if (value.includes('gemini-1.5-flash') || value.includes('gemini-2.0-flash') || value.includes('gemini-2.5-flash-preview-04-17') || value.includes('gemini-2.5-pro-exp-03-25') || value.includes('gemini-2.5-pro-preview-03-25')) { |
| 4339 | $('#openai_max_context').attr('max', max_1mil); | 4455 | $('#openai_max_context').attr('max', max_1mil); |
| 4340 | } else if (value.includes('gemini-1.0-pro') || value === 'gemini-pro') { | 4456 | } else if (value.includes('gemini-1.0-pro') || value === 'gemini-pro') { |
| 4341 | $('#openai_max_context').attr('max', max_32k); | 4457 | $('#openai_max_context').attr('max', max_32k); |
| @@ -4433,27 +4549,10 @@ async function onModelChange() { | |||
| 4433 | } | 4549 | } |
| 4434 | 4550 | ||
| 4435 | if (oai_settings.chat_completion_source === chat_completion_sources.MISTRALAI) { | 4551 | if (oai_settings.chat_completion_source === chat_completion_sources.MISTRALAI) { |
| 4436 | if (oai_settings.max_context_unlocked) { | 4552 | const maxContext = getMistralMaxContext(oai_settings.mistralai_model, oai_settings.max_context_unlocked); |
| 4437 | $('#openai_max_context').attr('max', unlocked_max); | 4553 | $('#openai_max_context').attr('max', maxContext); |
| 4438 | } else if (oai_settings.mistralai_model.includes('codestral-mamba')) { | ||
| 4439 | $('#openai_max_context').attr('max', max_256k); | ||
| 4440 | } else if (['mistral-large-2407', 'mistral-large-2411', 'mistral-large-latest'].includes(oai_settings.mistralai_model)) { | ||
| 4441 | $('#openai_max_context').attr('max', max_128k); | ||
| 4442 | } else if (oai_settings.mistralai_model.includes('mistral-nemo')) { | ||
| 4443 | $('#openai_max_context').attr('max', max_128k); | ||
| 4444 | } else if (oai_settings.mistralai_model.includes('mixtral-8x22b')) { | ||
| 4445 | $('#openai_max_context').attr('max', max_64k); | ||
| 4446 | } else if (oai_settings.mistralai_model.includes('pixtral')) { | ||
| 4447 | $('#openai_max_context').attr('max', max_128k); | ||
| 4448 | } else if (oai_settings.mistralai_model.includes('ministral')) { | ||
| 4449 | $('#openai_max_context').attr('max', max_32k); | ||
| 4450 | } else { | ||
| 4451 | $('#openai_max_context').attr('max', max_32k); | ||
| 4452 | } | ||
| 4453 | oai_settings.openai_max_context = Math.min(oai_settings.openai_max_context, Number($('#openai_max_context').attr('max'))); | 4554 | oai_settings.openai_max_context = Math.min(oai_settings.openai_max_context, Number($('#openai_max_context').attr('max'))); |
| 4454 | $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input'); | 4555 | $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input'); |
| 4455 | |||
| 4456 | //mistral also caps temp at 1.0 | ||
| 4457 | oai_settings.temp_openai = Math.min(claude_max_temp, oai_settings.temp_openai); | 4556 | oai_settings.temp_openai = Math.min(claude_max_temp, oai_settings.temp_openai); |
| 4458 | $('#temp_openai').attr('max', claude_max_temp).val(oai_settings.temp_openai).trigger('input'); | 4557 | $('#temp_openai').attr('max', claude_max_temp).val(oai_settings.temp_openai).trigger('input'); |
| 4459 | } | 4558 | } |
| @@ -4560,29 +4659,6 @@ async function onModelChange() { | |||
| 4560 | oai_settings.temp_openai = Math.min(oai_max_temp, oai_settings.temp_openai); | 4659 | oai_settings.temp_openai = Math.min(oai_max_temp, oai_settings.temp_openai); |
| 4561 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); | 4660 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); |
| 4562 | } | 4661 | } |
| 4563 | if (oai_settings.chat_completion_source === chat_completion_sources.BLOCKENTROPY) { | ||
| 4564 | if (oai_settings.max_context_unlocked) { | ||
| 4565 | $('#openai_max_context').attr('max', unlocked_max); | ||
| 4566 | } | ||
| 4567 | else if (oai_settings.blockentropy_model.includes('llama3.1')) { | ||
| 4568 | $('#openai_max_context').attr('max', max_16k); | ||
| 4569 | } | ||
| 4570 | else if (oai_settings.blockentropy_model.includes('72b')) { | ||
| 4571 | $('#openai_max_context').attr('max', max_16k); | ||
| 4572 | } | ||
| 4573 | else if (oai_settings.blockentropy_model.includes('120b')) { | ||
| 4574 | $('#openai_max_context').attr('max', max_12k); | ||
| 4575 | } | ||
| 4576 | else { | ||
| 4577 | $('#openai_max_context').attr('max', max_8k); | ||
| 4578 | } | ||
| 4579 | |||
| 4580 | oai_settings.openai_max_context = Math.min(oai_settings.openai_max_context, Number($('#openai_max_context').attr('max'))); | ||
| 4581 | $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input'); | ||
| 4582 | |||
| 4583 | oai_settings.temp_openai = Math.min(oai_max_temp, oai_settings.temp_openai); | ||
| 4584 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); | ||
| 4585 | } | ||
| 4586 | 4662 | ||
| 4587 | if (oai_settings.chat_completion_source === chat_completion_sources.NANOGPT) { | 4663 | if (oai_settings.chat_completion_source === chat_completion_sources.NANOGPT) { |
| 4588 | if (oai_settings.max_context_unlocked) { | 4664 | if (oai_settings.max_context_unlocked) { |
| @@ -4612,6 +4688,22 @@ async function onModelChange() { | |||
| 4612 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); | 4688 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); |
| 4613 | } | 4689 | } |
| 4614 | 4690 | ||
| 4691 | if (oai_settings.chat_completion_source === chat_completion_sources.XAI) { | ||
| 4692 | if (oai_settings.max_context_unlocked) { | ||
| 4693 | $('#openai_max_context').attr('max', unlocked_max); | ||
| 4694 | } else if (oai_settings.xai_model.includes('grok-2-vision')) { | ||
| 4695 | $('#openai_max_context').attr('max', max_32k); | ||
| 4696 | } else if (oai_settings.xai_model.includes('grok-vision')) { | ||
| 4697 | $('#openai_max_context').attr('max', max_8k); | ||
| 4698 | } else { | ||
| 4699 | $('#openai_max_context').attr('max', max_128k); | ||
| 4700 | } | ||
| 4701 | |||
| 4702 | oai_settings.openai_max_context = Math.min(Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context); | ||
| 4703 | $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input'); | ||
| 4704 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); | ||
| 4705 | } | ||
| 4706 | |||
| 4615 | if (oai_settings.chat_completion_source === chat_completion_sources.COHERE) { | 4707 | if (oai_settings.chat_completion_source === chat_completion_sources.COHERE) { |
| 4616 | oai_settings.pres_pen_openai = Math.min(Math.max(0, oai_settings.pres_pen_openai), 1); | 4708 | oai_settings.pres_pen_openai = Math.min(Math.max(0, oai_settings.pres_pen_openai), 1); |
| 4617 | $('#pres_pen_openai').attr('max', 1).attr('min', 0).val(oai_settings.pres_pen_openai).trigger('input'); | 4709 | $('#pres_pen_openai').attr('max', 1).attr('min', 0).val(oai_settings.pres_pen_openai).trigger('input'); |
| @@ -4849,15 +4941,16 @@ async function onConnectButtonClick(e) { | |||
| 4849 | return; | 4941 | return; |
| 4850 | } | 4942 | } |
| 4851 | } | 4943 | } |
| 4852 | if (oai_settings.chat_completion_source == chat_completion_sources.BLOCKENTROPY) { | ||
| 4853 | const api_key_blockentropy = String($('#api_key_blockentropy').val()).trim(); | ||
| 4854 | 4944 | ||
| 4855 | if (api_key_blockentropy.length) { | 4945 | if (oai_settings.chat_completion_source === chat_completion_sources.XAI) { |
| 4856 | await writeSecret(SECRET_KEYS.BLOCKENTROPY, api_key_blockentropy); | 4946 | const api_key_xai = String($('#api_key_xai').val()).trim(); |
| 4947 | |||
| 4948 | if (api_key_xai.length) { | ||
| 4949 | await writeSecret(SECRET_KEYS.XAI, api_key_xai); | ||
| 4857 | } | 4950 | } |
| 4858 | 4951 | ||
| 4859 | if (!secret_state[SECRET_KEYS.BLOCKENTROPY]) { | 4952 | if (!secret_state[SECRET_KEYS.XAI] && !oai_settings.reverse_proxy) { |
| 4860 | console.log('No secret key saved for Block Entropy'); | 4953 | console.log('No secret key saved for XAI'); |
| 4861 | return; | 4954 | return; |
| 4862 | } | 4955 | } |
| 4863 | } | 4956 | } |
| @@ -4915,12 +5008,12 @@ function toggleChatCompletionForms() { | |||
| 4915 | else if (oai_settings.chat_completion_source == chat_completion_sources.CUSTOM) { | 5008 | else if (oai_settings.chat_completion_source == chat_completion_sources.CUSTOM) { |
| 4916 | $('#model_custom_select').trigger('change'); | 5009 | $('#model_custom_select').trigger('change'); |
| 4917 | } | 5010 | } |
| 4918 | else if (oai_settings.chat_completion_source == chat_completion_sources.BLOCKENTROPY) { | ||
| 4919 | $('#model_blockentropy_select').trigger('change'); | ||
| 4920 | } | ||
| 4921 | else if (oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) { | 5011 | else if (oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) { |
| 4922 | $('#model_deepseek_select').trigger('change'); | 5012 | $('#model_deepseek_select').trigger('change'); |
| 4923 | } | 5013 | } |
| 5014 | else if (oai_settings.chat_completion_source == chat_completion_sources.XAI) { | ||
| 5015 | $('#model_xai_select').trigger('change'); | ||
| 5016 | } | ||
| 4924 | $('[data-source]').each(function () { | 5017 | $('[data-source]').each(function () { |
| 4925 | const validSources = $(this).data('source').split(','); | 5018 | const validSources = $(this).data('source').split(','); |
| 4926 | $(this).toggle(validSources.includes(oai_settings.chat_completion_source)); | 5019 | $(this).toggle(validSources.includes(oai_settings.chat_completion_source)); |
| @@ -5006,8 +5099,11 @@ export function isImageInliningSupported() { | |||
| 5006 | // gultra just isn't being offered as multimodal, thanks google. | 5099 | // gultra just isn't being offered as multimodal, thanks google. |
| 5007 | const visionSupportedModels = [ | 5100 | const visionSupportedModels = [ |
| 5008 | 'gpt-4-vision', | 5101 | 'gpt-4-vision', |
| 5102 | 'gemini-2.5-pro-exp-03-25', | ||
| 5103 | 'gemini-2.5-pro-preview-03-25', | ||
| 5009 | 'gemini-2.0-pro-exp', | 5104 | 'gemini-2.0-pro-exp', |
| 5010 | 'gemini-2.0-pro-exp-02-05', | 5105 | 'gemini-2.0-pro-exp-02-05', |
| 5106 | 'gemini-2.5-flash-preview-04-17', | ||
| 5011 | 'gemini-2.0-flash-lite-preview', | 5107 | 'gemini-2.0-flash-lite-preview', |
| 5012 | 'gemini-2.0-flash-lite-preview-02-05', | 5108 | 'gemini-2.0-flash-lite-preview-02-05', |
| 5013 | 'gemini-2.0-flash', | 5109 | 'gemini-2.0-flash', |
| @@ -5047,7 +5143,9 @@ export function isImageInliningSupported() { | |||
| 5047 | 'o1-2024-12-17', | 5143 | 'o1-2024-12-17', |
| 5048 | 'chatgpt-4o-latest', | 5144 | 'chatgpt-4o-latest', |
| 5049 | 'yi-vision', | 5145 | 'yi-vision', |
| 5050 | 'pixtral-latest', | 5146 | 'mistral-large-pixtral-2411', |
| 5147 | 'mistral-small-2503', | ||
| 5148 | 'mistral-small-latest', | ||
| 5051 | 'pixtral-12b-latest', | 5149 | 'pixtral-12b-latest', |
| 5052 | 'pixtral-12b', | 5150 | 'pixtral-12b', |
| 5053 | 'pixtral-12b-2409', | 5151 | 'pixtral-12b-2409', |
| @@ -5055,11 +5153,18 @@ export function isImageInliningSupported() { | |||
| 5055 | 'pixtral-large-2411', | 5153 | 'pixtral-large-2411', |
| 5056 | 'c4ai-aya-vision-8b', | 5154 | 'c4ai-aya-vision-8b', |
| 5057 | 'c4ai-aya-vision-32b', | 5155 | 'c4ai-aya-vision-32b', |
| 5156 | 'grok-2-vision', | ||
| 5157 | 'grok-vision', | ||
| 5158 | 'gpt-4.1', | ||
| 5159 | 'o3', | ||
| 5160 | 'o3-2025-04-16', | ||
| 5161 | 'o4-mini', | ||
| 5162 | 'o4-mini-2025-04-16', | ||
| 5058 | ]; | 5163 | ]; |
| 5059 | 5164 | ||
| 5060 | switch (oai_settings.chat_completion_source) { | 5165 | switch (oai_settings.chat_completion_source) { |
| 5061 | case chat_completion_sources.OPENAI: | 5166 | case chat_completion_sources.OPENAI: |
| 5062 | return visionSupportedModels.some(model => oai_settings.openai_model.includes(model) && !oai_settings.openai_model.includes('gpt-4-turbo-preview')); | 5167 | return visionSupportedModels.some(model => oai_settings.openai_model.includes(model) && !oai_settings.openai_model.includes('gpt-4-turbo-preview') && !oai_settings.openai_model.includes('o3-mini')); |
| 5063 | case chat_completion_sources.MAKERSUITE: | 5168 | case chat_completion_sources.MAKERSUITE: |
| 5064 | return visionSupportedModels.some(model => oai_settings.google_model.includes(model)); | 5169 | return visionSupportedModels.some(model => oai_settings.google_model.includes(model)); |
| 5065 | case chat_completion_sources.CLAUDE: | 5170 | case chat_completion_sources.CLAUDE: |
| @@ -5074,6 +5179,8 @@ export function isImageInliningSupported() { | |||
| 5074 | return visionSupportedModels.some(model => oai_settings.mistralai_model.includes(model)); | 5179 | return visionSupportedModels.some(model => oai_settings.mistralai_model.includes(model)); |
| 5075 | case chat_completion_sources.COHERE: | 5180 | case chat_completion_sources.COHERE: |
| 5076 | return visionSupportedModels.some(model => oai_settings.cohere_model.includes(model)); | 5181 | return visionSupportedModels.some(model => oai_settings.cohere_model.includes(model)); |
| 5182 | case chat_completion_sources.XAI: | ||
| 5183 | return visionSupportedModels.some(model => oai_settings.xai_model.includes(model)); | ||
| 5077 | default: | 5184 | default: |
| 5078 | return false; | 5185 | return false; |
| 5079 | } | 5186 | } |
| @@ -5614,6 +5721,7 @@ export function initOpenAI() { | |||
| 5614 | 5721 | ||
| 5615 | $('#openai_enable_web_search').on('input', function () { | 5722 | $('#openai_enable_web_search').on('input', function () { |
| 5616 | oai_settings.enable_web_search = !!$(this).prop('checked'); | 5723 | oai_settings.enable_web_search = !!$(this).prop('checked'); |
| 5724 | calculateOpenRouterCost(); | ||
| 5617 | saveSettingsDebounced(); | 5725 | saveSettingsDebounced(); |
| 5618 | }); | 5726 | }); |
| 5619 | 5727 | ||
| @@ -5669,8 +5777,8 @@ export function initOpenAI() { | |||
| 5669 | $('#model_nanogpt_select').on('change', onModelChange); | 5777 | $('#model_nanogpt_select').on('change', onModelChange); |
| 5670 | $('#model_deepseek_select').on('change', onModelChange); | 5778 | $('#model_deepseek_select').on('change', onModelChange); |
| 5671 | $('#model_01ai_select').on('change', onModelChange); | 5779 | $('#model_01ai_select').on('change', onModelChange); |
| 5672 | $('#model_blockentropy_select').on('change', onModelChange); | ||
| 5673 | $('#model_custom_select').on('change', onModelChange); | 5780 | $('#model_custom_select').on('change', onModelChange); |
| 5781 | $('#model_xai_select').on('change', onModelChange); | ||
| 5674 | $('#settings_preset_openai').on('change', onSettingsPresetChange); | 5782 | $('#settings_preset_openai').on('change', onSettingsPresetChange); |
| 5675 | $('#new_oai_preset').on('click', onNewPresetClick); | 5783 | $('#new_oai_preset').on('click', onNewPresetClick); |
| 5676 | $('#delete_oai_preset').on('click', onDeletePresetClick); | 5784 | $('#delete_oai_preset').on('click', onDeletePresetClick); |
| @@ -111,6 +111,7 @@ export function setUserAvatar(imgfile, { toastPersonaNameChange = true, navigate | |||
| 111 | reloadUserAvatar(); | 111 | reloadUserAvatar(); |
| 112 | updatePersonaUIStates({ navigateToCurrent: navigateToCurrent }); | 112 | updatePersonaUIStates({ navigateToCurrent: navigateToCurrent }); |
| 113 | selectCurrentPersona({ toastPersonaNameChange: toastPersonaNameChange }); | 113 | selectCurrentPersona({ toastPersonaNameChange: toastPersonaNameChange }); |
| 114 | retriggerFirstMessageOnEmptyChat(); | ||
| 114 | saveSettingsDebounced(); | 115 | saveSettingsDebounced(); |
| 115 | $('.zoomed_avatar[forchar]').remove(); | 116 | $('.zoomed_avatar[forchar]').remove(); |
| 116 | } | 117 | } |
| @@ -465,7 +466,7 @@ export function initPersona(avatarId, personaName, personaDescription) { | |||
| 465 | * @returns {Promise<boolean>} A promise that resolves to true if the character was converted, false otherwise. | 466 | * @returns {Promise<boolean>} A promise that resolves to true if the character was converted, false otherwise. |
| 466 | */ | 467 | */ |
| 467 | export async function convertCharacterToPersona(characterId = null) { | 468 | export async function convertCharacterToPersona(characterId = null) { |
| 468 | if (null === characterId) characterId = this_chid; | 469 | if (null === characterId) characterId = Number(this_chid); |
| 469 | 470 | ||
| 470 | const avatarUrl = characters[characterId]?.avatar; | 471 | const avatarUrl = characters[characterId]?.avatar; |
| 471 | if (!avatarUrl) { | 472 | if (!avatarUrl) { |
| @@ -800,7 +801,7 @@ async function selectCurrentPersona({ toastPersonaNameChange = true } = {}) { | |||
| 800 | chat_metadata['persona'] = user_avatar; | 801 | chat_metadata['persona'] = user_avatar; |
| 801 | console.log(`Auto locked persona to ${user_avatar}`); | 802 | console.log(`Auto locked persona to ${user_avatar}`); |
| 802 | if (toastPersonaNameChange && power_user.persona_show_notifications) { | 803 | if (toastPersonaNameChange && power_user.persona_show_notifications) { |
| 803 | toastr.success(`Persona ${personaName} selected and auto-locked to current chat`, t`Persona Selected`); | 804 | toastr.success(t`Persona ${personaName} selected and auto-locked to current chat`, t`Persona Selected`); |
| 804 | } | 805 | } |
| 805 | saveMetadataDebounced(); | 806 | saveMetadataDebounced(); |
| 806 | updatePersonaUIStates(); | 807 | updatePersonaUIStates(); |
| @@ -1243,7 +1244,7 @@ function getPersonaStates(avatarId) { | |||
| 1243 | /** @type {PersonaConnection[]} */ | 1244 | /** @type {PersonaConnection[]} */ |
| 1244 | const connections = power_user.persona_descriptions[avatarId]?.connections; | 1245 | const connections = power_user.persona_descriptions[avatarId]?.connections; |
| 1245 | const hasCharLock = !!connections?.some(c => | 1246 | const hasCharLock = !!connections?.some(c => |
| 1246 | (!selected_group && c.type === 'character' && c.id === characters[this_chid]?.avatar) | 1247 | (!selected_group && c.type === 'character' && c.id === characters[Number(this_chid)]?.avatar) |
| 1247 | || (selected_group && c.type === 'group' && c.id === selected_group)); | 1248 | || (selected_group && c.type === 'group' && c.id === selected_group)); |
| 1248 | 1249 | ||
| 1249 | return { | 1250 | return { |
| @@ -1481,7 +1482,7 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) { | |||
| 1481 | * @returns {string[]} - An array of persona keys that are connected to the given character key | 1482 | * @returns {string[]} - An array of persona keys that are connected to the given character key |
| 1482 | */ | 1483 | */ |
| 1483 | export function getConnectedPersonas(characterKey = undefined) { | 1484 | export function getConnectedPersonas(characterKey = undefined) { |
| 1484 | characterKey ??= selected_group || characters[this_chid]?.avatar; | 1485 | characterKey ??= selected_group || characters[Number(this_chid)]?.avatar; |
| 1485 | const connectedPersonas = Object.entries(power_user.persona_descriptions) | 1486 | const connectedPersonas = Object.entries(power_user.persona_descriptions) |
| 1486 | .filter(([_, desc]) => desc.connections?.some(conn => conn.type === 'character' && conn.id === characterKey)) | 1487 | .filter(([_, desc]) => desc.connections?.some(conn => conn.type === 'character' && conn.id === characterKey)) |
| 1487 | .map(([key, _]) => key); | 1488 | .map(([key, _]) => key); |
| @@ -1513,7 +1514,7 @@ export async function showCharConnections() { | |||
| 1513 | console.log(`Unlocking persona ${personaId} from current character ${name2}`); | 1514 | console.log(`Unlocking persona ${personaId} from current character ${name2}`); |
| 1514 | power_user.persona_descriptions[personaId].connections = connections.filter(c => { | 1515 | power_user.persona_descriptions[personaId].connections = connections.filter(c => { |
| 1515 | if (menu_type == 'group_edit' && c.type == 'group' && c.id == selected_group) return false; | 1516 | if (menu_type == 'group_edit' && c.type == 'group' && c.id == selected_group) return false; |
| 1516 | else if (c.type == 'character' && c.id == characters[this_chid]?.avatar) return false; | 1517 | else if (c.type == 'character' && c.id == characters[Number(this_chid)]?.avatar) return false; |
| 1517 | return true; | 1518 | return true; |
| 1518 | }); | 1519 | }); |
| 1519 | saveSettingsDebounced(); | 1520 | saveSettingsDebounced(); |
| @@ -1545,8 +1546,8 @@ export async function showCharConnections() { | |||
| 1545 | export function getCurrentConnectionObj() { | 1546 | export function getCurrentConnectionObj() { |
| 1546 | if (selected_group) | 1547 | if (selected_group) |
| 1547 | return { type: 'group', id: selected_group }; | 1548 | return { type: 'group', id: selected_group }; |
| 1548 | if (characters[this_chid]?.avatar) | 1549 | if (characters[Number(this_chid)]?.avatar) |
| 1549 | return { type: 'character', id: characters[this_chid]?.avatar }; | 1550 | return { type: 'character', id: characters[Number(this_chid)]?.avatar }; |
| 1550 | return null; | 1551 | return null; |
| 1551 | } | 1552 | } |
| 1552 | 1553 | ||
| @@ -1664,7 +1665,7 @@ async function syncUserNameToPersona() { | |||
| 1664 | * Only works if only the first message is present, and not in group mode. | 1665 | * Only works if only the first message is present, and not in group mode. |
| 1665 | */ | 1666 | */ |
| 1666 | export function retriggerFirstMessageOnEmptyChat() { | 1667 | export function retriggerFirstMessageOnEmptyChat() { |
| 1667 | if (this_chid >= 0 && !selected_group && chat.length === 1) { | 1668 | if (Number(this_chid) >= 0 && !selected_group && chat.length === 1) { |
| 1668 | $('#firstmessage_textarea').trigger('input'); | 1669 | $('#firstmessage_textarea').trigger('input'); |
| 1669 | } | 1670 | } |
| 1670 | } | 1671 | } |
| @@ -1782,7 +1783,6 @@ function setNameCallback({ mode = 'all' }, name) { | |||
| 1782 | if (!persona) persona = Object.entries(power_user.personas).find(([_, personaName]) => personaName.toLowerCase() === name.toLowerCase())?.[1]; | 1783 | if (!persona) persona = Object.entries(power_user.personas).find(([_, personaName]) => personaName.toLowerCase() === name.toLowerCase())?.[1]; |
| 1783 | if (persona) { | 1784 | if (persona) { |
| 1784 | autoSelectPersona(persona); | 1785 | autoSelectPersona(persona); |
| 1785 | retriggerFirstMessageOnEmptyChat(); | ||
| 1786 | return ''; | 1786 | return ''; |
| 1787 | } else if (mode === 'lookup') { | 1787 | } else if (mode === 'lookup') { |
| 1788 | toastr.warning(`Persona ${name} not found`); | 1788 | toastr.warning(`Persona ${name} not found`); |
| @@ -1793,7 +1793,6 @@ function setNameCallback({ mode = 'all' }, name) { | |||
| 1793 | if (['temp', 'all'].includes(mode)) { | 1793 | if (['temp', 'all'].includes(mode)) { |
| 1794 | // Otherwise, set just the name | 1794 | // Otherwise, set just the name |
| 1795 | setUserName(name); //this prevented quickReply usage | 1795 | setUserName(name); //this prevented quickReply usage |
| 1796 | retriggerFirstMessageOnEmptyChat(); | ||
| 1797 | } | 1796 | } |
| 1798 | 1797 | ||
| 1799 | return ''; | 1798 | return ''; |
| @@ -1944,9 +1943,6 @@ export async function initPersonas() { | |||
| 1944 | $(document).on('click', '#user_avatar_block .avatar-container', function () { | 1943 | $(document).on('click', '#user_avatar_block .avatar-container', function () { |
| 1945 | const imgfile = $(this).attr('data-avatar-id'); | 1944 | const imgfile = $(this).attr('data-avatar-id'); |
| 1946 | setUserAvatar(imgfile); | 1945 | setUserAvatar(imgfile); |
| 1947 | |||
| 1948 | // force firstMes {{user}} update on persona switch | ||
| 1949 | retriggerFirstMessageOnEmptyChat(); | ||
| 1950 | }); | 1946 | }); |
| 1951 | 1947 | ||
| 1952 | $('#persona_rename_button').on('click', () => renamePersona(user_avatar)); | 1948 | $('#persona_rename_button').on('click', () => renamePersona(user_avatar)); |
| @@ -1979,4 +1975,3 @@ export async function initPersonas() { | |||
| 1979 | eventSource.on(event_types.CHAT_CHANGED, loadPersonaForCurrentChat); | 1975 | eventSource.on(event_types.CHAT_CHANGED, loadPersonaForCurrentChat); |
| 1980 | switchPersonaGridView(); | 1976 | switchPersonaGridView(); |
| 1981 | } | 1977 | } |
| 1982 | |||
| @@ -55,6 +55,7 @@ import { POPUP_TYPE, callGenericPopup } from './popup.js'; | |||
| 55 | import { loadSystemPrompts } from './sysprompt.js'; | 55 | import { loadSystemPrompts } from './sysprompt.js'; |
| 56 | import { fuzzySearchCategories } from './filters.js'; | 56 | import { fuzzySearchCategories } from './filters.js'; |
| 57 | import { accountStorage } from './util/AccountStorage.js'; | 57 | import { accountStorage } from './util/AccountStorage.js'; |
| 58 | import { DEFAULT_REASONING_TEMPLATE, loadReasoningTemplates } from './reasoning.js'; | ||
| 58 | 59 | ||
| 59 | export { | 60 | export { |
| 60 | loadPowerUserSettings, | 61 | loadPowerUserSettings, |
| @@ -70,8 +71,8 @@ export { | |||
| 70 | 71 | ||
| 71 | export const MAX_CONTEXT_DEFAULT = 8192; | 72 | export const MAX_CONTEXT_DEFAULT = 8192; |
| 72 | export const MAX_RESPONSE_DEFAULT = 2048; | 73 | export const MAX_RESPONSE_DEFAULT = 2048; |
| 73 | const MAX_CONTEXT_UNLOCKED = 200 * 1024; | 74 | const MAX_CONTEXT_UNLOCKED = 512 * 1024; |
| 74 | const MAX_RESPONSE_UNLOCKED = 32 * 1024; | 75 | const MAX_RESPONSE_UNLOCKED = 64 * 1024; |
| 75 | const unlockedMaxContextStep = 512; | 76 | const unlockedMaxContextStep = 512; |
| 76 | const maxContextMin = 512; | 77 | const maxContextMin = 512; |
| 77 | const maxContextStep = 64; | 78 | const maxContextStep = 64; |
| @@ -218,7 +219,9 @@ let power_user = { | |||
| 218 | system_sequence: '', | 219 | system_sequence: '', |
| 219 | system_suffix: '', | 220 | system_suffix: '', |
| 220 | last_system_sequence: '', | 221 | last_system_sequence: '', |
| 222 | first_input_sequence: '', | ||
| 221 | first_output_sequence: '', | 223 | first_output_sequence: '', |
| 224 | last_input_sequence: '', | ||
| 222 | last_output_sequence: '', | 225 | last_output_sequence: '', |
| 223 | system_sequence_prefix: '', | 226 | system_sequence_prefix: '', |
| 224 | system_sequence_suffix: '', | 227 | system_sequence_suffix: '', |
| @@ -255,6 +258,7 @@ let power_user = { | |||
| 255 | }, | 258 | }, |
| 256 | 259 | ||
| 257 | reasoning: { | 260 | reasoning: { |
| 261 | name: DEFAULT_REASONING_TEMPLATE, | ||
| 258 | auto_parse: false, | 262 | auto_parse: false, |
| 259 | add_to_prompts: false, | 263 | add_to_prompts: false, |
| 260 | auto_expand: false, | 264 | auto_expand: false, |
| @@ -1622,6 +1626,7 @@ async function loadPowerUserSettings(settings, data) { | |||
| 1622 | await loadInstructMode(data); | 1626 | await loadInstructMode(data); |
| 1623 | await loadContextSettings(); | 1627 | await loadContextSettings(); |
| 1624 | await loadSystemPrompts(data); | 1628 | await loadSystemPrompts(data); |
| 1629 | await loadReasoningTemplates(data); | ||
| 1625 | loadMaxContextUnlocked(); | 1630 | loadMaxContextUnlocked(); |
| 1626 | switchWaifuMode(); | 1631 | switchWaifuMode(); |
| 1627 | switchSpoilerMode(); | 1632 | switchSpoilerMode(); |
| @@ -1983,15 +1988,21 @@ export function fuzzySearchGroups(searchValue, fuzzySearchCaches = null) { | |||
| 1983 | /** | 1988 | /** |
| 1984 | * Renders a story string template with the given parameters. | 1989 | * Renders a story string template with the given parameters. |
| 1985 | * @param {object} params Template parameters. | 1990 | * @param {object} params Template parameters. |
| 1991 | * @param {object} [options] Additional options. | ||
| 1992 | * @param {string} [options.customStoryString] Custom story string template. | ||
| 1993 | * @param {InstructSettings} [options.customInstructSettings] Custom instruct settings. | ||
| 1986 | * @returns {string} The rendered story string. | 1994 | * @returns {string} The rendered story string. |
| 1987 | */ | 1995 | */ |
| 1988 | export function renderStoryString(params) { | 1996 | export function renderStoryString(params, { customStoryString = null, customInstructSettings = null } = {}) { |
| 1989 | try { | 1997 | try { |
| 1998 | const storyString = customStoryString ?? power_user.context.story_string; | ||
| 1999 | const instructSettings = structuredClone(customInstructSettings ?? power_user.instruct); | ||
| 2000 | |||
| 1990 | // Validate and log possible warnings/errors | 2001 | // Validate and log possible warnings/errors |
| 1991 | validateStoryString(power_user.context.story_string, params); | 2002 | validateStoryString(storyString, params); |
| 1992 | 2003 | ||
| 1993 | // compile the story string template into a function, with no HTML escaping | 2004 | // compile the story string template into a function, with no HTML escaping |
| 1994 | const compiledTemplate = Handlebars.compile(power_user.context.story_string, { noEscape: true }); | 2005 | const compiledTemplate = Handlebars.compile(storyString, { noEscape: true }); |
| 1995 | 2006 | ||
| 1996 | // render the story string template with the given params | 2007 | // render the story string template with the given params |
| 1997 | let output = compiledTemplate(params); | 2008 | let output = compiledTemplate(params); |
| @@ -2004,7 +2015,7 @@ export function renderStoryString(params) { | |||
| 2004 | 2015 | ||
| 2005 | // add a newline to the end of the story string if it doesn't have one | 2016 | // add a newline to the end of the story string if it doesn't have one |
| 2006 | if (output.length > 0 && !output.endsWith('\n')) { | 2017 | if (output.length > 0 && !output.endsWith('\n')) { |
| 2007 | if (!power_user.instruct.enabled || power_user.instruct.wrap) { | 2018 | if (!instructSettings.enabled || instructSettings.wrap) { |
| 2008 | output += '\n'; | 2019 | output += '\n'; |
| 2009 | } | 2020 | } |
| 2010 | } | 2021 | } |
| @@ -21,7 +21,7 @@ import { groups, selected_group } from './group-chats.js'; | |||
| 21 | import { instruct_presets } from './instruct-mode.js'; | 21 | import { instruct_presets } from './instruct-mode.js'; |
| 22 | import { kai_settings } from './kai-settings.js'; | 22 | import { kai_settings } from './kai-settings.js'; |
| 23 | import { convertNovelPreset } from './nai-settings.js'; | 23 | import { convertNovelPreset } from './nai-settings.js'; |
| 24 | import { openai_settings, openai_setting_names, oai_settings } from './openai.js'; | 24 | import { openai_settings, openai_setting_names } from './openai.js'; |
| 25 | import { Popup, POPUP_RESULT, POPUP_TYPE } from './popup.js'; | 25 | import { Popup, POPUP_RESULT, POPUP_TYPE } from './popup.js'; |
| 26 | import { context_presets, getContextSettings, power_user } from './power-user.js'; | 26 | import { context_presets, getContextSettings, power_user } from './power-user.js'; |
| 27 | import { SlashCommand } from './slash-commands/SlashCommand.js'; | 27 | import { SlashCommand } from './slash-commands/SlashCommand.js'; |
| @@ -36,8 +36,9 @@ import { | |||
| 36 | textgenerationwebui_presets, | 36 | textgenerationwebui_presets, |
| 37 | textgenerationwebui_settings as textgen_settings, | 37 | textgenerationwebui_settings as textgen_settings, |
| 38 | } from './textgen-settings.js'; | 38 | } from './textgen-settings.js'; |
| 39 | import { download, parseJsonFile, waitUntilCondition } from './utils.js'; | 39 | import { download, equalsIgnoreCaseAndAccents, parseJsonFile, waitUntilCondition } from './utils.js'; |
| 40 | import { t } from './i18n.js'; | 40 | import { t } from './i18n.js'; |
| 41 | import { reasoning_templates } from './reasoning.js'; | ||
| 41 | 42 | ||
| 42 | const presetManagers = {}; | 43 | const presetManagers = {}; |
| 43 | 44 | ||
| @@ -168,6 +169,20 @@ class PresetManager { | |||
| 168 | }, | 169 | }, |
| 169 | isValid: (data) => PresetManager.isPossiblyTextCompletionData(data), | 170 | isValid: (data) => PresetManager.isPossiblyTextCompletionData(data), |
| 170 | }, | 171 | }, |
| 172 | 'reasoning': { | ||
| 173 | name: 'Reasoning Formatting', | ||
| 174 | getData: () => { | ||
| 175 | const manager = getPresetManager('reasoning'); | ||
| 176 | const name = manager.getSelectedPresetName(); | ||
| 177 | return manager.getPresetSettings(name); | ||
| 178 | }, | ||
| 179 | setData: (data) => { | ||
| 180 | const manager = getPresetManager('reasoning'); | ||
| 181 | const name = data.name; | ||
| 182 | return manager.savePreset(name, data); | ||
| 183 | }, | ||
| 184 | isValid: (data) => PresetManager.isPossiblyReasoningData(data), | ||
| 185 | }, | ||
| 171 | }; | 186 | }; |
| 172 | 187 | ||
| 173 | static isPossiblyInstructData(data) { | 188 | static isPossiblyInstructData(data) { |
| @@ -190,6 +205,11 @@ class PresetManager { | |||
| 190 | return data && textCompletionProps.every(prop => Object.keys(data).includes(prop)); | 205 | return data && textCompletionProps.every(prop => Object.keys(data).includes(prop)); |
| 191 | } | 206 | } |
| 192 | 207 | ||
| 208 | static isPossiblyReasoningData(data) { | ||
| 209 | const reasoningProps = ['name', 'prefix', 'suffix', 'separator']; | ||
| 210 | return data && reasoningProps.every(prop => Object.keys(data).includes(prop)); | ||
| 211 | } | ||
| 212 | |||
| 193 | /** | 213 | /** |
| 194 | * Imports master settings from JSON data. | 214 | * Imports master settings from JSON data. |
| 195 | * @param {object} data Data to import | 215 | * @param {object} data Data to import |
| @@ -227,6 +247,12 @@ class PresetManager { | |||
| 227 | return await getPresetManager('textgenerationwebui').savePreset(fileName, data); | 247 | return await getPresetManager('textgenerationwebui').savePreset(fileName, data); |
| 228 | } | 248 | } |
| 229 | 249 | ||
| 250 | // 5. Reasoning Template | ||
| 251 | if (this.isPossiblyReasoningData(data)) { | ||
| 252 | toastr.info(t`Importing as reasoning template...`, t`Reasoning template detected`); | ||
| 253 | return await getPresetManager('reasoning').savePreset(data.name, data); | ||
| 254 | } | ||
| 255 | |||
| 230 | const validSections = []; | 256 | const validSections = []; |
| 231 | for (const [key, section] of Object.entries(this.masterSections)) { | 257 | for (const [key, section] of Object.entries(this.masterSections)) { |
| 232 | if (key in data && section.isValid(data[key])) { | 258 | if (key in data && section.isValid(data[key])) { |
| @@ -428,6 +454,9 @@ class PresetManager { | |||
| 428 | 454 | ||
| 429 | async renamePreset(newName) { | 455 | async renamePreset(newName) { |
| 430 | const oldName = this.getSelectedPresetName(); | 456 | const oldName = this.getSelectedPresetName(); |
| 457 | if (equalsIgnoreCaseAndAccents(oldName, newName)) { | ||
| 458 | throw new Error('New name must be different from old name'); | ||
| 459 | } | ||
| 431 | try { | 460 | try { |
| 432 | await this.savePreset(newName); | 461 | await this.savePreset(newName); |
| 433 | await this.deletePreset(oldName); | 462 | await this.deletePreset(oldName); |
| @@ -478,6 +507,10 @@ class PresetManager { | |||
| 478 | presets = system_prompts; | 507 | presets = system_prompts; |
| 479 | preset_names = system_prompts.map(x => x.name); | 508 | preset_names = system_prompts.map(x => x.name); |
| 480 | break; | 509 | break; |
| 510 | case 'reasoning': | ||
| 511 | presets = reasoning_templates; | ||
| 512 | preset_names = reasoning_templates.map(x => x.name); | ||
| 513 | break; | ||
| 481 | default: | 514 | default: |
| 482 | console.warn(`Unknown API ID ${api}`); | 515 | console.warn(`Unknown API ID ${api}`); |
| 483 | } | 516 | } |
| @@ -490,7 +523,7 @@ class PresetManager { | |||
| 490 | } | 523 | } |
| 491 | 524 | ||
| 492 | isAdvancedFormatting() { | 525 | isAdvancedFormatting() { |
| 493 | return this.apiId == 'context' || this.apiId == 'instruct' || this.apiId == 'sysprompt'; | 526 | return ['context', 'instruct', 'sysprompt', 'reasoning'].includes(this.apiId); |
| 494 | } | 527 | } |
| 495 | 528 | ||
| 496 | updateList(name, preset) { | 529 | updateList(name, preset) { |
| @@ -553,6 +586,11 @@ class PresetManager { | |||
| 553 | sysprompt_preset['name'] = name || power_user.sysprompt.preset; | 586 | sysprompt_preset['name'] = name || power_user.sysprompt.preset; |
| 554 | return sysprompt_preset; | 587 | return sysprompt_preset; |
| 555 | } | 588 | } |
| 589 | case 'reasoning': { | ||
| 590 | const reasoning_preset = structuredClone(power_user.reasoning); | ||
| 591 | reasoning_preset['name'] = name || power_user.reasoning.preset; | ||
| 592 | return reasoning_preset; | ||
| 593 | } | ||
| 556 | default: | 594 | default: |
| 557 | console.warn(`Unknown API ID ${apiId}`); | 595 | console.warn(`Unknown API ID ${apiId}`); |
| 558 | return {}; | 596 | return {}; |
| @@ -599,6 +637,13 @@ class PresetManager { | |||
| 599 | 'include_reasoning', | 637 | 'include_reasoning', |
| 600 | 'global_banned_tokens', | 638 | 'global_banned_tokens', |
| 601 | 'send_banned_tokens', | 639 | 'send_banned_tokens', |
| 640 | |||
| 641 | // Reasoning exclusions | ||
| 642 | 'auto_parse', | ||
| 643 | 'add_to_prompts', | ||
| 644 | 'auto_expand', | ||
| 645 | 'show_hidden', | ||
| 646 | 'max_additions', | ||
| 602 | ]; | 647 | ]; |
| 603 | const settings = Object.assign({}, getSettingsByApiId(this.apiId)); | 648 | const settings = Object.assign({}, getSettingsByApiId(this.apiId)); |
| 604 | 649 | ||
| @@ -850,9 +895,19 @@ export async function initPresetManager() { | |||
| 850 | console.debug(!presetManager.isAdvancedFormatting() ? 'Preset rename cancelled' : 'Template rename cancelled'); | 895 | console.debug(!presetManager.isAdvancedFormatting() ? 'Preset rename cancelled' : 'Template rename cancelled'); |
| 851 | return; | 896 | return; |
| 852 | } | 897 | } |
| 898 | if (equalsIgnoreCaseAndAccents(oldName, newName)) { | ||
| 899 | toastr.warning(t`Name not accepted, as it is the same as before (ignoring case and accents).`, t`Rename Preset`); | ||
| 900 | return; | ||
| 901 | } | ||
| 853 | 902 | ||
| 854 | await presetManager.renamePreset(newName); | 903 | await presetManager.renamePreset(newName); |
| 855 | 904 | ||
| 905 | if (apiId === 'openai') { | ||
| 906 | // This is a horrible mess, but prevents the renamed preset from being corrupted. | ||
| 907 | $('#update_oai_preset').trigger('click'); | ||
| 908 | return; | ||
| 909 | } | ||
| 910 | |||
| 856 | const successToast = !presetManager.isAdvancedFormatting() ? t`Preset renamed` : t`Template renamed`; | 911 | const successToast = !presetManager.isAdvancedFormatting() ? t`Preset renamed` : t`Template renamed`; |
| 857 | toastr.success(successToast); | 912 | toastr.success(successToast); |
| 858 | }); | 913 | }); |
| @@ -7,14 +7,46 @@ import { getCurrentLocale, t, translate } from './i18n.js'; | |||
| 7 | import { MacrosParser } from './macros.js'; | 7 | import { MacrosParser } from './macros.js'; |
| 8 | import { chat_completion_sources, getChatCompletionModel, oai_settings } from './openai.js'; | 8 | import { chat_completion_sources, getChatCompletionModel, oai_settings } from './openai.js'; |
| 9 | import { Popup } from './popup.js'; | 9 | import { Popup } from './popup.js'; |
| 10 | import { power_user } from './power-user.js'; | 10 | import { performFuzzySearch, power_user } from './power-user.js'; |
| 11 | import { getPresetManager } from './preset-manager.js'; | ||
| 11 | import { SlashCommand } from './slash-commands/SlashCommand.js'; | 12 | import { SlashCommand } from './slash-commands/SlashCommand.js'; |
| 12 | import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js'; | 13 | import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js'; |
| 13 | import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js'; | 14 | import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js'; |
| 14 | import { enumTypes, SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js'; | 15 | import { enumTypes, SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js'; |
| 15 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; | 16 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; |
| 16 | import { textgen_types, textgenerationwebui_settings } from './textgen-settings.js'; | 17 | import { textgen_types, textgenerationwebui_settings } from './textgen-settings.js'; |
| 17 | import { copyText, escapeRegex, isFalseBoolean, setDatasetProperty, trimSpaces } from './utils.js'; | 18 | import { copyText, escapeRegex, isFalseBoolean, isTrueBoolean, setDatasetProperty, trimSpaces } from './utils.js'; |
| 19 | |||
| 20 | /** | ||
| 21 | * @typedef {object} ReasoningTemplate | ||
| 22 | * @property {string} name - The name of the template | ||
| 23 | * @property {string} prefix - Reasoning prefix | ||
| 24 | * @property {string} suffix - Reasoning suffix | ||
| 25 | * @property {string} separator - Reasoning separator | ||
| 26 | */ | ||
| 27 | |||
| 28 | /** | ||
| 29 | * @type {ReasoningTemplate[]} List of reasoning templates | ||
| 30 | */ | ||
| 31 | export const reasoning_templates = []; | ||
| 32 | |||
| 33 | export const DEFAULT_REASONING_TEMPLATE = 'DeepSeek'; | ||
| 34 | |||
| 35 | /** | ||
| 36 | * @type {Record<string, JQuery<HTMLElement>>} List of UI elements for reasoning settings | ||
| 37 | * @readonly | ||
| 38 | */ | ||
| 39 | const UI = { | ||
| 40 | $select: $('#reasoning_select'), | ||
| 41 | $suffix: $('#reasoning_suffix'), | ||
| 42 | $prefix: $('#reasoning_prefix'), | ||
| 43 | $separator: $('#reasoning_separator'), | ||
| 44 | $autoParse: $('#reasoning_auto_parse'), | ||
| 45 | $autoExpand: $('#reasoning_auto_expand'), | ||
| 46 | $showHidden: $('#reasoning_show_hidden'), | ||
| 47 | $addToPrompts: $('#reasoning_add_to_prompts'), | ||
| 48 | $maxAdditions: $('#reasoning_max_additions'), | ||
| 49 | }; | ||
| 18 | 50 | ||
| 19 | /** | 51 | /** |
| 20 | * Enum representing the type of the reasoning for a message (where it came from) | 52 | * Enum representing the type of the reasoning for a message (where it came from) |
| @@ -57,21 +89,28 @@ function toggleReasoningAutoExpand() { | |||
| 57 | * @param {object} data Response data | 89 | * @param {object} data Response data |
| 58 | * @returns {string} Extracted reasoning | 90 | * @returns {string} Extracted reasoning |
| 59 | */ | 91 | */ |
| 60 | export function extractReasoningFromData(data) { | 92 | export function extractReasoningFromData(data, { |
| 61 | switch (main_api) { | 93 | mainApi = null, |
| 94 | ignoreShowThoughts = false, | ||
| 95 | textGenType = null, | ||
| 96 | chatCompletionSource = null, | ||
| 97 | } = {}) { | ||
| 98 | switch (mainApi ?? main_api) { | ||
| 62 | case 'textgenerationwebui': | 99 | case 'textgenerationwebui': |
| 63 | switch (textgenerationwebui_settings.type) { | 100 | switch (textGenType ?? textgenerationwebui_settings.type) { |
| 64 | case textgen_types.OPENROUTER: | 101 | case textgen_types.OPENROUTER: |
| 65 | return data?.choices?.[0]?.reasoning ?? ''; | 102 | return data?.choices?.[0]?.reasoning ?? ''; |
| 66 | } | 103 | } |
| 67 | break; | 104 | break; |
| 68 | 105 | ||
| 69 | case 'openai': | 106 | case 'openai': |
| 70 | if (!oai_settings.show_thoughts) break; | 107 | if (!ignoreShowThoughts && !oai_settings.show_thoughts) break; |
| 71 | 108 | ||
| 72 | switch (oai_settings.chat_completion_source) { | 109 | switch (chatCompletionSource ?? oai_settings.chat_completion_source) { |
| 73 | case chat_completion_sources.DEEPSEEK: | 110 | case chat_completion_sources.DEEPSEEK: |
| 74 | return data?.choices?.[0]?.message?.reasoning_content ?? ''; | 111 | return data?.choices?.[0]?.message?.reasoning_content ?? ''; |
| 112 | case chat_completion_sources.XAI: | ||
| 113 | return data?.choices?.[0]?.message?.reasoning_content ?? ''; | ||
| 75 | case chat_completion_sources.OPENROUTER: | 114 | case chat_completion_sources.OPENROUTER: |
| 76 | return data?.choices?.[0]?.message?.reasoning ?? ''; | 115 | return data?.choices?.[0]?.message?.reasoning ?? ''; |
| 77 | case chat_completion_sources.MAKERSUITE: | 116 | case chat_completion_sources.MAKERSUITE: |
| @@ -664,57 +703,102 @@ export class PromptReasoning { | |||
| 664 | } | 703 | } |
| 665 | 704 | ||
| 666 | function loadReasoningSettings() { | 705 | function loadReasoningSettings() { |
| 667 | $('#reasoning_add_to_prompts').prop('checked', power_user.reasoning.add_to_prompts); | 706 | UI.$addToPrompts.prop('checked', power_user.reasoning.add_to_prompts); |
| 668 | $('#reasoning_add_to_prompts').on('change', function () { | 707 | UI.$addToPrompts.on('change', function () { |
| 669 | power_user.reasoning.add_to_prompts = !!$(this).prop('checked'); | 708 | power_user.reasoning.add_to_prompts = !!$(this).prop('checked'); |
| 670 | saveSettingsDebounced(); | 709 | saveSettingsDebounced(); |
| 671 | }); | 710 | }); |
| 672 | 711 | ||
| 673 | $('#reasoning_prefix').val(power_user.reasoning.prefix); | 712 | UI.$prefix.val(power_user.reasoning.prefix); |
| 674 | $('#reasoning_prefix').on('input', function () { | 713 | UI.$prefix.on('input', function () { |
| 675 | power_user.reasoning.prefix = String($(this).val()); | 714 | power_user.reasoning.prefix = String($(this).val()); |
| 676 | saveSettingsDebounced(); | 715 | saveSettingsDebounced(); |
| 677 | }); | 716 | }); |
| 678 | 717 | ||
| 679 | $('#reasoning_suffix').val(power_user.reasoning.suffix); | 718 | UI.$suffix.val(power_user.reasoning.suffix); |
| 680 | $('#reasoning_suffix').on('input', function () { | 719 | UI.$suffix.on('input', function () { |
| 681 | power_user.reasoning.suffix = String($(this).val()); | 720 | power_user.reasoning.suffix = String($(this).val()); |
| 682 | saveSettingsDebounced(); | 721 | saveSettingsDebounced(); |
| 683 | }); | 722 | }); |
| 684 | 723 | ||
| 685 | $('#reasoning_separator').val(power_user.reasoning.separator); | 724 | UI.$separator.val(power_user.reasoning.separator); |
| 686 | $('#reasoning_separator').on('input', function () { | 725 | UI.$separator.on('input', function () { |
| 687 | power_user.reasoning.separator = String($(this).val()); | 726 | power_user.reasoning.separator = String($(this).val()); |
| 688 | saveSettingsDebounced(); | 727 | saveSettingsDebounced(); |
| 689 | }); | 728 | }); |
| 690 | 729 | ||
| 691 | $('#reasoning_max_additions').val(power_user.reasoning.max_additions); | 730 | UI.$maxAdditions.val(power_user.reasoning.max_additions); |
| 692 | $('#reasoning_max_additions').on('input', function () { | 731 | UI.$maxAdditions.on('input', function () { |
| 693 | power_user.reasoning.max_additions = Number($(this).val()); | 732 | power_user.reasoning.max_additions = Number($(this).val()); |
| 694 | saveSettingsDebounced(); | 733 | saveSettingsDebounced(); |
| 695 | }); | 734 | }); |
| 696 | 735 | ||
| 697 | $('#reasoning_auto_parse').prop('checked', power_user.reasoning.auto_parse); | 736 | UI.$autoParse.prop('checked', power_user.reasoning.auto_parse); |
| 698 | $('#reasoning_auto_parse').on('change', function () { | 737 | UI.$autoParse.on('change', function () { |
| 699 | power_user.reasoning.auto_parse = !!$(this).prop('checked'); | 738 | power_user.reasoning.auto_parse = !!$(this).prop('checked'); |
| 700 | saveSettingsDebounced(); | 739 | saveSettingsDebounced(); |
| 701 | }); | 740 | }); |
| 702 | 741 | ||
| 703 | $('#reasoning_auto_expand').prop('checked', power_user.reasoning.auto_expand); | 742 | UI.$autoExpand.prop('checked', power_user.reasoning.auto_expand); |
| 704 | $('#reasoning_auto_expand').on('change', function () { | 743 | UI.$autoExpand.on('change', function () { |
| 705 | power_user.reasoning.auto_expand = !!$(this).prop('checked'); | 744 | power_user.reasoning.auto_expand = !!$(this).prop('checked'); |
| 706 | toggleReasoningAutoExpand(); | 745 | toggleReasoningAutoExpand(); |
| 707 | saveSettingsDebounced(); | 746 | saveSettingsDebounced(); |
| 708 | }); | 747 | }); |
| 709 | toggleReasoningAutoExpand(); | 748 | toggleReasoningAutoExpand(); |
| 710 | 749 | ||
| 711 | $('#reasoning_show_hidden').prop('checked', power_user.reasoning.show_hidden); | 750 | UI.$showHidden.prop('checked', power_user.reasoning.show_hidden); |
| 712 | $('#reasoning_show_hidden').on('change', function () { | 751 | UI.$showHidden.on('change', function () { |
| 713 | power_user.reasoning.show_hidden = !!$(this).prop('checked'); | 752 | power_user.reasoning.show_hidden = !!$(this).prop('checked'); |
| 714 | $('#chat').attr('data-show-hidden-reasoning', power_user.reasoning.show_hidden ? 'true' : null); | 753 | $('#chat').attr('data-show-hidden-reasoning', power_user.reasoning.show_hidden ? 'true' : null); |
| 715 | saveSettingsDebounced(); | 754 | saveSettingsDebounced(); |
| 716 | }); | 755 | }); |
| 717 | $('#chat').attr('data-show-hidden-reasoning', power_user.reasoning.show_hidden ? 'true' : null); | 756 | $('#chat').attr('data-show-hidden-reasoning', power_user.reasoning.show_hidden ? 'true' : null); |
| 757 | |||
| 758 | UI.$select.on('change', async function () { | ||
| 759 | const name = String($(this).val()); | ||
| 760 | const template = reasoning_templates.find(p => p.name === name); | ||
| 761 | if (!template) { | ||
| 762 | return; | ||
| 763 | } | ||
| 764 | |||
| 765 | UI.$prefix.val(template.prefix); | ||
| 766 | UI.$suffix.val(template.suffix); | ||
| 767 | UI.$separator.val(template.separator); | ||
| 768 | |||
| 769 | power_user.reasoning.name = name; | ||
| 770 | power_user.reasoning.prefix = template.prefix; | ||
| 771 | power_user.reasoning.suffix = template.suffix; | ||
| 772 | power_user.reasoning.separator = template.separator; | ||
| 773 | |||
| 774 | saveSettingsDebounced(); | ||
| 775 | }); | ||
| 776 | } | ||
| 777 | |||
| 778 | function selectReasoningTemplateCallback(args, name) { | ||
| 779 | if (!name) { | ||
| 780 | return power_user.reasoning.name ?? ''; | ||
| 781 | } | ||
| 782 | |||
| 783 | const quiet = isTrueBoolean(args?.quiet); | ||
| 784 | const templateNames = reasoning_templates.map(preset => preset.name); | ||
| 785 | let foundName = templateNames.find(x => x.toLowerCase() === name.toLowerCase()); | ||
| 786 | |||
| 787 | if (!foundName) { | ||
| 788 | const result = performFuzzySearch('reasoning-templates', templateNames, [], name); | ||
| 789 | |||
| 790 | if (result.length === 0) { | ||
| 791 | !quiet && toastr.warning(`Reasoning template "${name}" not found`); | ||
| 792 | return ''; | ||
| 793 | } | ||
| 794 | |||
| 795 | foundName = result[0].item; | ||
| 796 | } | ||
| 797 | |||
| 798 | UI.$select.val(foundName).trigger('change'); | ||
| 799 | !quiet && toastr.success(`Reasoning template "${foundName}" selected`); | ||
| 800 | return foundName; | ||
| 801 | |||
| 718 | } | 802 | } |
| 719 | 803 | ||
| 720 | function registerReasoningSlashCommands() { | 804 | function registerReasoningSlashCommands() { |
| @@ -750,6 +834,12 @@ function registerReasoningSlashCommands() { | |||
| 750 | typeList: ARGUMENT_TYPE.NUMBER, | 834 | typeList: ARGUMENT_TYPE.NUMBER, |
| 751 | enumProvider: commonEnumProviders.messages(), | 835 | enumProvider: commonEnumProviders.messages(), |
| 752 | }), | 836 | }), |
| 837 | SlashCommandNamedArgument.fromProps({ | ||
| 838 | name: 'collapse', | ||
| 839 | description: 'Whether to collapse the reasoning block. (If not provided, uses the default expand setting)', | ||
| 840 | typeList: [ARGUMENT_TYPE.BOOLEAN], | ||
| 841 | enumList: commonEnumProviders.boolean('trueFalse')(), | ||
| 842 | }), | ||
| 753 | ], | 843 | ], |
| 754 | unnamedArgumentList: [ | 844 | unnamedArgumentList: [ |
| 755 | SlashCommandArgument.fromProps({ | 845 | SlashCommandArgument.fromProps({ |
| @@ -774,6 +864,9 @@ function registerReasoningSlashCommands() { | |||
| 774 | 864 | ||
| 775 | closeMessageEditor('reasoning'); | 865 | closeMessageEditor('reasoning'); |
| 776 | updateMessageBlock(messageId, message); | 866 | updateMessageBlock(messageId, message); |
| 867 | |||
| 868 | if (isTrueBoolean(String(args.collapse))) $(`#chat [mesid="${messageId}"] .mes_reasoning_details`).removeAttr('open'); | ||
| 869 | if (isFalseBoolean(String(args.collapse))) $(`#chat [mesid="${messageId}"] .mes_reasoning_details`).attr('open', ''); | ||
| 777 | return message.extra.reasoning; | 870 | return message.extra.reasoning; |
| 778 | }, | 871 | }, |
| 779 | })); | 872 | })); |
| @@ -848,6 +941,42 @@ function registerReasoningSlashCommands() { | |||
| 848 | : parsedReasoning.reasoning; | 941 | : parsedReasoning.reasoning; |
| 849 | }, | 942 | }, |
| 850 | })); | 943 | })); |
| 944 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | ||
| 945 | name: 'reasoning-template', | ||
| 946 | aliases: ['reasoning-formatting', 'reasoning-preset'], | ||
| 947 | callback: selectReasoningTemplateCallback, | ||
| 948 | returns: 'template name', | ||
| 949 | namedArgumentList: [ | ||
| 950 | SlashCommandNamedArgument.fromProps({ | ||
| 951 | name: 'quiet', | ||
| 952 | description: 'Suppress the toast message on template change', | ||
| 953 | typeList: [ARGUMENT_TYPE.BOOLEAN], | ||
| 954 | defaultValue: 'false', | ||
| 955 | enumList: commonEnumProviders.boolean('trueFalse')(), | ||
| 956 | }), | ||
| 957 | ], | ||
| 958 | unnamedArgumentList: [ | ||
| 959 | SlashCommandArgument.fromProps({ | ||
| 960 | description: 'reasoning template name', | ||
| 961 | typeList: [ARGUMENT_TYPE.STRING], | ||
| 962 | enumProvider: () => reasoning_templates.map(x => new SlashCommandEnumValue(x.name, null, enumTypes.enum, enumIcons.preset)), | ||
| 963 | }), | ||
| 964 | ], | ||
| 965 | helpString: ` | ||
| 966 | <div> | ||
| 967 | Selects a reasoning template by name, using fuzzy search to find the closest match. | ||
| 968 | Gets the current template if no name is provided. | ||
| 969 | </div> | ||
| 970 | <div> | ||
| 971 | <strong>Example:</strong> | ||
| 972 | <ul> | ||
| 973 | <li> | ||
| 974 | <pre><code class="language-stscript">/reasoning-template DeepSeek</code></pre> | ||
| 975 | </li> | ||
| 976 | </ul> | ||
| 977 | </div> | ||
| 978 | `, | ||
| 979 | })); | ||
| 851 | } | 980 | } |
| 852 | 981 | ||
| 853 | function registerReasoningMacros() { | 982 | function registerReasoningMacros() { |
| @@ -1207,6 +1336,53 @@ function registerReasoningAppEvents() { | |||
| 1207 | } | 1336 | } |
| 1208 | } | 1337 | } |
| 1209 | 1338 | ||
| 1339 | /** | ||
| 1340 | * Loads reasoning templates from the settings data. | ||
| 1341 | * @param {object} data Settings data | ||
| 1342 | * @param {ReasoningTemplate[]} data.reasoning Reasoning templates | ||
| 1343 | * @returns {Promise<void>} | ||
| 1344 | */ | ||
| 1345 | export async function loadReasoningTemplates(data) { | ||
| 1346 | if (data.reasoning !== undefined) { | ||
| 1347 | reasoning_templates.splice(0, reasoning_templates.length, ...data.reasoning); | ||
| 1348 | } | ||
| 1349 | |||
| 1350 | for (const template of reasoning_templates) { | ||
| 1351 | $('<option>').val(template.name).text(template.name).appendTo(UI.$select); | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | // No template name, need to migrate | ||
| 1355 | if (power_user.reasoning.name === undefined) { | ||
| 1356 | const defaultTemplate = reasoning_templates.find(p => p.name === DEFAULT_REASONING_TEMPLATE); | ||
| 1357 | if (defaultTemplate) { | ||
| 1358 | // If the reasoning settings were modified - migrate them to a custom template | ||
| 1359 | if (power_user.reasoning.prefix !== defaultTemplate.prefix || power_user.reasoning.suffix !== defaultTemplate.suffix || power_user.reasoning.separator !== defaultTemplate.separator) { | ||
| 1360 | /** @type {ReasoningTemplate} */ | ||
| 1361 | const data = { | ||
| 1362 | name: '[Migrated] Custom', | ||
| 1363 | prefix: power_user.reasoning.prefix, | ||
| 1364 | suffix: power_user.reasoning.suffix, | ||
| 1365 | separator: power_user.reasoning.separator, | ||
| 1366 | }; | ||
| 1367 | await getPresetManager('reasoning')?.savePreset(data.name, data); | ||
| 1368 | power_user.reasoning.name = data.name; | ||
| 1369 | } else { | ||
| 1370 | power_user.reasoning.name = defaultTemplate.name; | ||
| 1371 | } | ||
| 1372 | } else { | ||
| 1373 | // Template not found (deleted or content check skipped - leave blank) | ||
| 1374 | power_user.reasoning.name = ''; | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | saveSettingsDebounced(); | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | UI.$select.val(power_user.reasoning.name); | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | /** | ||
| 1384 | * Initializes reasoning settings and event handlers. | ||
| 1385 | */ | ||
| 1210 | export function initReasoning() { | 1386 | export function initReasoning() { |
| 1211 | loadReasoningSettings(); | 1387 | loadReasoningSettings(); |
| 1212 | setReasoningEventHandlers(); | 1388 | setReasoningEventHandlers(); |
| @@ -9,6 +9,7 @@ import { power_user } from './power-user.js'; | |||
| 9 | //import { getSortableDelay, onlyUnique } from './utils.js'; | 9 | //import { getSortableDelay, onlyUnique } from './utils.js'; |
| 10 | //import { getCfgPrompt } from './cfg-scale.js'; | 10 | //import { getCfgPrompt } from './cfg-scale.js'; |
| 11 | import { setting_names } from './textgen-settings.js'; | 11 | import { setting_names } from './textgen-settings.js'; |
| 12 | import { renderTemplateAsync } from './templates.js'; | ||
| 12 | 13 | ||
| 13 | 14 | ||
| 14 | const TGsamplerNames = setting_names; | 15 | const TGsamplerNames = setting_names; |
| @@ -25,25 +26,7 @@ async function showSamplerSelectPopup() { | |||
| 25 | const html = $(document.createElement('div')); | 26 | const html = $(document.createElement('div')); |
| 26 | html.attr('id', 'sampler_view_list') | 27 | html.attr('id', 'sampler_view_list') |
| 27 | .addClass('flex-container flexFlowColumn'); | 28 | .addClass('flex-container flexFlowColumn'); |
| 28 | html.append(` | 29 | html.append(await renderTemplateAsync('samplerSelector')); |
| 29 | <div class="title_restorable flexFlowColumn alignItemsBaseline"> | ||
| 30 | <div class="flex-container justifyCenter"> | ||
| 31 | <h3>Sampler Select</h3> | ||
| 32 | <div class="flex-container alignItemsBaseline"> | ||
| 33 | <div id="resetSelectedSamplers" class="menu_button menu_button_icon" title="Reset custom sampler selection"> | ||
| 34 | <i class="fa-solid fa-recycle"></i> | ||
| 35 | </div> | ||
| 36 | </div> | ||
| 37 | <!--<div class="flex-container alignItemsBaseline"> | ||
| 38 | <div class="menu_button menu_button_icon" title="Create a new sampler"> | ||
| 39 | <i class="fa-solid fa-plus"></i> | ||
| 40 | <span data-i18n="Create">Create</span> | ||
| 41 | </div> | ||
| 42 | </div>--> | ||
| 43 | </div> | ||
| 44 | <small>Here you can toggle the display of individual samplers. (WIP)</small> | ||
| 45 | </div> | ||
| 46 | <hr>`); | ||
| 47 | 30 | ||
| 48 | const listContainer = $('<div id="apiSamplersList" class="flex-container flexNoGap"></div>'); | 31 | const listContainer = $('<div id="apiSamplersList" class="flex-container flexNoGap"></div>'); |
| 49 | const APISamplers = await listSamplers(main_api); | 32 | const APISamplers = await listSamplers(main_api); |
| @@ -1,5 +1,6 @@ | |||
| 1 | import { DOMPurify } from '../lib.js'; | 1 | import { DOMPurify } from '../lib.js'; |
| 2 | import { callPopup, getRequestHeaders } from '../script.js'; | 2 | import { callPopup, getRequestHeaders } from '../script.js'; |
| 3 | import { t } from './i18n.js'; | ||
| 3 | 4 | ||
| 4 | export const SECRET_KEYS = { | 5 | export const SECRET_KEYS = { |
| 5 | HORDE: 'api_key_horde', | 6 | HORDE: 'api_key_horde', |
| @@ -33,7 +34,6 @@ export const SECRET_KEYS = { | |||
| 33 | ZEROONEAI: 'api_key_01ai', | 34 | ZEROONEAI: 'api_key_01ai', |
| 34 | HUGGINGFACE: 'api_key_huggingface', | 35 | HUGGINGFACE: 'api_key_huggingface', |
| 35 | STABILITY: 'api_key_stability', | 36 | STABILITY: 'api_key_stability', |
| 36 | BLOCKENTROPY: 'api_key_blockentropy', | ||
| 37 | CUSTOM_OPENAI_TTS: 'api_key_custom_openai_tts', | 37 | CUSTOM_OPENAI_TTS: 'api_key_custom_openai_tts', |
| 38 | NANOGPT: 'api_key_nanogpt', | 38 | NANOGPT: 'api_key_nanogpt', |
| 39 | TAVILY: 'api_key_tavily', | 39 | TAVILY: 'api_key_tavily', |
| @@ -42,6 +42,7 @@ export const SECRET_KEYS = { | |||
| 42 | DEEPSEEK: 'api_key_deepseek', | 42 | DEEPSEEK: 'api_key_deepseek', |
| 43 | SERPER: 'api_key_serper', | 43 | SERPER: 'api_key_serper', |
| 44 | FALAI: 'api_key_falai', | 44 | FALAI: 'api_key_falai', |
| 45 | XAI: 'api_key_xai', | ||
| 45 | }; | 46 | }; |
| 46 | 47 | ||
| 47 | const INPUT_MAP = { | 48 | const INPUT_MAP = { |
| @@ -73,10 +74,10 @@ const INPUT_MAP = { | |||
| 73 | [SECRET_KEYS.FEATHERLESS]: '#api_key_featherless', | 74 | [SECRET_KEYS.FEATHERLESS]: '#api_key_featherless', |
| 74 | [SECRET_KEYS.ZEROONEAI]: '#api_key_01ai', | 75 | [SECRET_KEYS.ZEROONEAI]: '#api_key_01ai', |
| 75 | [SECRET_KEYS.HUGGINGFACE]: '#api_key_huggingface', | 76 | [SECRET_KEYS.HUGGINGFACE]: '#api_key_huggingface', |
| 76 | [SECRET_KEYS.BLOCKENTROPY]: '#api_key_blockentropy', | ||
| 77 | [SECRET_KEYS.NANOGPT]: '#api_key_nanogpt', | 77 | [SECRET_KEYS.NANOGPT]: '#api_key_nanogpt', |
| 78 | [SECRET_KEYS.GENERIC]: '#api_key_generic', | 78 | [SECRET_KEYS.GENERIC]: '#api_key_generic', |
| 79 | [SECRET_KEYS.DEEPSEEK]: '#api_key_deepseek', | 79 | [SECRET_KEYS.DEEPSEEK]: '#api_key_deepseek', |
| 80 | [SECRET_KEYS.XAI]: '#api_key_xai', | ||
| 80 | }; | 81 | }; |
| 81 | 82 | ||
| 82 | async function clearSecret() { | 83 | async function clearSecret() { |
| @@ -104,7 +105,7 @@ async function viewSecrets() { | |||
| 104 | }); | 105 | }); |
| 105 | 106 | ||
| 106 | if (response.status == 403) { | 107 | if (response.status == 403) { |
| 107 | callPopup('<h3>Forbidden</h3><p>To view your API keys here, set the value of allowKeysExposure to true in config.yaml file and restart the SillyTavern server.</p>', 'text'); | 108 | callPopup('<h3>' + t`Forbidden` + '</h3><p>' + t`To view your API keys here, set the value of allowKeysExposure to true in config.yaml file and restart the SillyTavern server.` + '</p>', 'text'); |
| 108 | return; | 109 | return; |
| 109 | } | 110 | } |
| 110 | 111 | ||
| @@ -188,14 +189,17 @@ export async function findSecret(key) { | |||
| 188 | } | 189 | } |
| 189 | 190 | ||
| 190 | function authorizeOpenRouter() { | 191 | function authorizeOpenRouter() { |
| 191 | const openRouterUrl = `https://openrouter.ai/auth?callback_url=${encodeURIComponent(location.origin)}`; | 192 | const redirectUrl = new URL('/callback/openrouter', window.location.origin); |
| 193 | const openRouterUrl = `https://openrouter.ai/auth?callback_url=${encodeURIComponent(redirectUrl.toString())}`; | ||
| 192 | location.href = openRouterUrl; | 194 | location.href = openRouterUrl; |
| 193 | } | 195 | } |
| 194 | 196 | ||
| 195 | async function checkOpenRouterAuth() { | 197 | async function checkOpenRouterAuth() { |
| 196 | const params = new URLSearchParams(location.search); | 198 | const params = new URLSearchParams(location.search); |
| 197 | if (params.has('code')) { | 199 | const source = params.get('source'); |
| 198 | const code = params.get('code'); | 200 | if (source === 'openrouter') { |
| 201 | const query = new URLSearchParams(params.get('query')); | ||
| 202 | const code = query.get('code'); | ||
| 199 | try { | 203 | try { |
| 200 | const response = await fetch('https://openrouter.ai/api/v1/auth/keys', { | 204 | const response = await fetch('https://openrouter.ai/api/v1/auth/keys', { |
| 201 | method: 'POST', | 205 | method: 'POST', |
| @@ -8,10 +8,10 @@ export const markdownUnderscoreExt = () => { | |||
| 8 | 8 | ||
| 9 | return [{ | 9 | return [{ |
| 10 | type: 'output', | 10 | type: 'output', |
| 11 | regex: new RegExp('(<code(?:\\s+[^>]*)?>[\\s\\S]*?<\\/code>)|\\b(?<!_)_(?!_)(.*?)(?<!_)_(?!_)\\b', 'g'), | 11 | regex: new RegExp('(<code(?:\\s+[^>]*)?>[\\s\\S]*?<\\/code>|<style(?:\\s+[^>]*)?>[\\s\\S]*?<\\/style>)|\\b(?<!_)_(?!_)(.*?)(?<!_)_(?!_)\\b', 'gi'), |
| 12 | replace: function(match, codeContent, italicContent) { | 12 | replace: function(match, tagContent, italicContent) { |
| 13 | if (codeContent) { | 13 | if (tagContent) { |
| 14 | // If it's inside <code> tags, return unchanged | 14 | // If it's inside <code> or <style> tags, return unchanged |
| 15 | return match; | 15 | return match; |
| 16 | } else if (italicContent) { | 16 | } else if (italicContent) { |
| 17 | // If it's an italic group, apply the replacement | 17 | // If it's an italic group, apply the replacement |
| @@ -75,6 +75,9 @@ import { SlashCommandBreakController } from './slash-commands/SlashCommandBreakC | |||
| 75 | import { SlashCommandExecutionError } from './slash-commands/SlashCommandExecutionError.js'; | 75 | import { SlashCommandExecutionError } from './slash-commands/SlashCommandExecutionError.js'; |
| 76 | import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHelper.js'; | 76 | import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHelper.js'; |
| 77 | import { accountStorage } from './util/AccountStorage.js'; | 77 | import { accountStorage } from './util/AccountStorage.js'; |
| 78 | import { SlashCommandDebugController } from './slash-commands/SlashCommandDebugController.js'; | ||
| 79 | import { SlashCommandScope } from './slash-commands/SlashCommandScope.js'; | ||
| 80 | import { t } from './i18n.js'; | ||
| 78 | export { | 81 | export { |
| 79 | executeSlashCommands, executeSlashCommandsWithOptions, getSlashCommandsHelp, registerSlashCommand, | 82 | executeSlashCommands, executeSlashCommandsWithOptions, getSlashCommandsHelp, registerSlashCommand, |
| 80 | }; | 83 | }; |
| @@ -224,6 +227,7 @@ export function initDefaultSlashCommands() { | |||
| 224 | })); | 227 | })); |
| 225 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | 228 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| 226 | name: 'sendas', | 229 | name: 'sendas', |
| 230 | rawQuotes: true, | ||
| 227 | callback: sendMessageAs, | 231 | callback: sendMessageAs, |
| 228 | returns: 'Optionally the text of the sent message, if specified in the "return" argument', | 232 | returns: 'Optionally the text of the sent message, if specified in the "return" argument', |
| 229 | namedArgumentList: [ | 233 | namedArgumentList: [ |
| @@ -290,6 +294,7 @@ export function initDefaultSlashCommands() { | |||
| 290 | })); | 294 | })); |
| 291 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | 295 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| 292 | name: 'sys', | 296 | name: 'sys', |
| 297 | rawQuotes: true, | ||
| 293 | callback: sendNarratorMessage, | 298 | callback: sendNarratorMessage, |
| 294 | aliases: ['nar'], | 299 | aliases: ['nar'], |
| 295 | returns: 'Optionally the text of the sent message, if specified in the "return" argument', | 300 | returns: 'Optionally the text of the sent message, if specified in the "return" argument', |
| @@ -354,6 +359,7 @@ export function initDefaultSlashCommands() { | |||
| 354 | })); | 359 | })); |
| 355 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | 360 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| 356 | name: 'comment', | 361 | name: 'comment', |
| 362 | rawQuotes: true, | ||
| 357 | callback: sendCommentMessage, | 363 | callback: sendCommentMessage, |
| 358 | returns: 'Optionally the text of the sent message, if specified in the "return" argument', | 364 | returns: 'Optionally the text of the sent message, if specified in the "return" argument', |
| 359 | namedArgumentList: [ | 365 | namedArgumentList: [ |
| @@ -571,6 +577,7 @@ export function initDefaultSlashCommands() { | |||
| 571 | })); | 577 | })); |
| 572 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | 578 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| 573 | name: 'send', | 579 | name: 'send', |
| 580 | rawQuotes: true, | ||
| 574 | callback: sendUserMessageCallback, | 581 | callback: sendUserMessageCallback, |
| 575 | returns: 'Optionally the text of the sent message, if specified in the "return" argument', | 582 | returns: 'Optionally the text of the sent message, if specified in the "return" argument', |
| 576 | namedArgumentList: [ | 583 | namedArgumentList: [ |
| @@ -933,6 +940,7 @@ export function initDefaultSlashCommands() { | |||
| 933 | })); | 940 | })); |
| 934 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | 941 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| 935 | name: 'echo', | 942 | name: 'echo', |
| 943 | rawQuotes: true, | ||
| 936 | callback: echoCallback, | 944 | callback: echoCallback, |
| 937 | returns: 'the text', | 945 | returns: 'the text', |
| 938 | namedArgumentList: [ | 946 | namedArgumentList: [ |
| @@ -1554,16 +1562,28 @@ export function initDefaultSlashCommands() { | |||
| 1554 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | 1562 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| 1555 | name: 'buttons', | 1563 | name: 'buttons', |
| 1556 | callback: buttonsCallback, | 1564 | callback: buttonsCallback, |
| 1557 | returns: 'clicked button label', | 1565 | returns: 'clicked button label (or array of labels if multiple is enabled)', |
| 1558 | namedArgumentList: [ | 1566 | namedArgumentList: [ |
| 1559 | new SlashCommandNamedArgument( | 1567 | SlashCommandNamedArgument.fromProps({ |
| 1560 | 'labels', 'button labels', [ARGUMENT_TYPE.LIST], true, | 1568 | name: 'labels', |
| 1561 | ), | 1569 | description: 'button labels', |
| 1570 | typeList: [ARGUMENT_TYPE.LIST], | ||
| 1571 | isRequired: true, | ||
| 1572 | }), | ||
| 1573 | SlashCommandNamedArgument.fromProps({ | ||
| 1574 | name: 'multiple', | ||
| 1575 | description: 'if enabled multiple buttons can be clicked/toggled, and all clicked buttons are returned as an array', | ||
| 1576 | typeList: [ARGUMENT_TYPE.BOOLEAN], | ||
| 1577 | enumList: commonEnumProviders.boolean('trueFalse')(), | ||
| 1578 | defaultValue: 'false', | ||
| 1579 | }), | ||
| 1562 | ], | 1580 | ], |
| 1563 | unnamedArgumentList: [ | 1581 | unnamedArgumentList: [ |
| 1564 | new SlashCommandArgument( | 1582 | SlashCommandArgument.fromProps({ |
| 1565 | 'text', [ARGUMENT_TYPE.STRING], true, | 1583 | description: 'text', |
| 1566 | ), | 1584 | typeList: [ARGUMENT_TYPE.STRING], |
| 1585 | isRequired: true, | ||
| 1586 | }), | ||
| 1567 | ], | 1587 | ], |
| 1568 | helpString: ` | 1588 | helpString: ` |
| 1569 | <div> | 1589 | <div> |
| @@ -2375,6 +2395,18 @@ async function trimTokensCallback(arg, value) { | |||
| 2375 | } | 2395 | } |
| 2376 | } | 2396 | } |
| 2377 | 2397 | ||
| 2398 | /** | ||
| 2399 | * Displays a popup with buttons based on provided labels and handles button interactions. | ||
| 2400 | * | ||
| 2401 | * @param {object} args - Named arguments for the command | ||
| 2402 | * @param {string} args.labels - JSON string of an array of button labels | ||
| 2403 | * @param {string} [args.multiple=false] - Flag indicating if multiple buttons can be toggled | ||
| 2404 | * @param {string} text - The text content to be displayed within the popup | ||
| 2405 | * | ||
| 2406 | * @returns {Promise<string>} - A promise that resolves to a string of the button labels selected | ||
| 2407 | * If 'multiple' is true, returns a JSON string array of labels. | ||
| 2408 | * If 'multiple' is false, returns a single label string. | ||
| 2409 | */ | ||
| 2378 | async function buttonsCallback(args, text) { | 2410 | async function buttonsCallback(args, text) { |
| 2379 | try { | 2411 | try { |
| 2380 | /** @type {string[]} */ | 2412 | /** @type {string[]} */ |
| @@ -2385,6 +2417,10 @@ async function buttonsCallback(args, text) { | |||
| 2385 | return ''; | 2417 | return ''; |
| 2386 | } | 2418 | } |
| 2387 | 2419 | ||
| 2420 | /** @type {Set<number>} */ | ||
| 2421 | const multipleToggledState = new Set(); | ||
| 2422 | const multiple = isTrueBoolean(args?.multiple); | ||
| 2423 | |||
| 2388 | // Map custom buttons to results. Start at 2 because 1 and 0 are reserved for ok and cancel | 2424 | // Map custom buttons to results. Start at 2 because 1 and 0 are reserved for ok and cancel |
| 2389 | const resultToButtonMap = new Map(buttons.map((button, index) => [index + 2, button])); | 2425 | const resultToButtonMap = new Map(buttons.map((button, index) => [index + 2, button])); |
| 2390 | 2426 | ||
| @@ -2402,11 +2438,24 @@ async function buttonsCallback(args, text) { | |||
| 2402 | 2438 | ||
| 2403 | for (const [result, button] of resultToButtonMap) { | 2439 | for (const [result, button] of resultToButtonMap) { |
| 2404 | const buttonElement = document.createElement('div'); | 2440 | const buttonElement = document.createElement('div'); |
| 2405 | buttonElement.classList.add('menu_button', 'result-control', 'wide100p'); | 2441 | buttonElement.classList.add('menu_button', 'wide100p'); |
| 2406 | buttonElement.dataset.result = String(result); | 2442 | |
| 2407 | buttonElement.addEventListener('click', async () => { | 2443 | if (multiple) { |
| 2408 | await popup.complete(result); | 2444 | buttonElement.classList.add('toggleable'); |
| 2409 | }); | 2445 | buttonElement.dataset.toggleValue = String(result); |
| 2446 | buttonElement.addEventListener('click', async () => { | ||
| 2447 | buttonElement.classList.toggle('toggled'); | ||
| 2448 | if (buttonElement.classList.contains('toggled')) { | ||
| 2449 | multipleToggledState.add(result); | ||
| 2450 | } else { | ||
| 2451 | multipleToggledState.delete(result); | ||
| 2452 | } | ||
| 2453 | }); | ||
| 2454 | } else { | ||
| 2455 | buttonElement.classList.add('result-control'); | ||
| 2456 | buttonElement.dataset.result = String(result); | ||
| 2457 | } | ||
| 2458 | |||
| 2410 | buttonElement.innerText = button; | 2459 | buttonElement.innerText = button; |
| 2411 | buttonContainer.appendChild(buttonElement); | 2460 | buttonContainer.appendChild(buttonElement); |
| 2412 | } | 2461 | } |
| @@ -2422,10 +2471,19 @@ async function buttonsCallback(args, text) { | |||
| 2422 | popupContainer.style.flexDirection = 'column'; | 2471 | popupContainer.style.flexDirection = 'column'; |
| 2423 | popupContainer.style.maxHeight = '80vh'; // Limit the overall height of the popup | 2472 | popupContainer.style.maxHeight = '80vh'; // Limit the overall height of the popup |
| 2424 | 2473 | ||
| 2425 | popup = new Popup(popupContainer, POPUP_TYPE.TEXT, '', { okButton: 'Cancel', allowVerticalScrolling: true }); | 2474 | popup = new Popup(popupContainer, POPUP_TYPE.TEXT, '', { okButton: multiple ? t`Ok` : t`Cancel`, allowVerticalScrolling: true }); |
| 2426 | popup.show() | 2475 | popup.show() |
| 2427 | .then((result => resolve(typeof result === 'number' ? resultToButtonMap.get(result) ?? '' : ''))) | 2476 | .then((result => resolve(getResult(result)))) |
| 2428 | .catch(() => resolve('')); | 2477 | .catch(() => resolve('')); |
| 2478 | |||
| 2479 | /** @returns {string} @param {string|number|boolean} result */ | ||
| 2480 | function getResult(result) { | ||
| 2481 | if (multiple) { | ||
| 2482 | const array = result === POPUP_RESULT.AFFIRMATIVE ? Array.from(multipleToggledState).map(r => resultToButtonMap.get(r) ?? '') : []; | ||
| 2483 | return JSON.stringify(array); | ||
| 2484 | } | ||
| 2485 | return typeof result === 'number' ? resultToButtonMap.get(result) ?? '' : ''; | ||
| 2486 | } | ||
| 2429 | }); | 2487 | }); |
| 2430 | } catch { | 2488 | } catch { |
| 2431 | return ''; | 2489 | return ''; |
| @@ -3883,8 +3941,8 @@ function getModelOptions(quiet) { | |||
| 3883 | { id: 'model_groq_select', api: 'openai', type: chat_completion_sources.GROQ }, | 3941 | { id: 'model_groq_select', api: 'openai', type: chat_completion_sources.GROQ }, |
| 3884 | { id: 'model_nanogpt_select', api: 'openai', type: chat_completion_sources.NANOGPT }, | 3942 | { id: 'model_nanogpt_select', api: 'openai', type: chat_completion_sources.NANOGPT }, |
| 3885 | { id: 'model_01ai_select', api: 'openai', type: chat_completion_sources.ZEROONEAI }, | 3943 | { id: 'model_01ai_select', api: 'openai', type: chat_completion_sources.ZEROONEAI }, |
| 3886 | { id: 'model_blockentropy_select', api: 'openai', type: chat_completion_sources.BLOCKENTROPY }, | ||
| 3887 | { id: 'model_deepseek_select', api: 'openai', type: chat_completion_sources.DEEPSEEK }, | 3944 | { id: 'model_deepseek_select', api: 'openai', type: chat_completion_sources.DEEPSEEK }, |
| 3945 | { id: 'model_xai_select', api: 'openai', type: chat_completion_sources.XAI }, | ||
| 3888 | { id: 'model_novel_select', api: 'novel', type: null }, | 3946 | { id: 'model_novel_select', api: 'novel', type: null }, |
| 3889 | { id: 'horde_model', api: 'koboldhorde', type: null }, | 3947 | { id: 'horde_model', api: 'koboldhorde', type: null }, |
| 3890 | ]; | 3948 | ]; |
| @@ -4345,7 +4403,7 @@ const clearCommandProgressDebounced = debounce(clearCommandProgress); | |||
| 4345 | * @prop {boolean} [handleParserErrors] (true) Whether to handle parser errors (show toast on error) or throw. | 4403 | * @prop {boolean} [handleParserErrors] (true) Whether to handle parser errors (show toast on error) or throw. |
| 4346 | * @prop {SlashCommandScope} [scope] (null) The scope to be used when executing the commands. | 4404 | * @prop {SlashCommandScope} [scope] (null) The scope to be used when executing the commands. |
| 4347 | * @prop {boolean} [handleExecutionErrors] (false) Whether to handle execution errors (show toast on error) or throw | 4405 | * @prop {boolean} [handleExecutionErrors] (false) Whether to handle execution errors (show toast on error) or throw |
| 4348 | * @prop {{[id:PARSER_FLAG]:boolean}} [parserFlags] (null) Parser flags to apply | 4406 | * @prop {import('./slash-commands/SlashCommandParser.js').ParserFlags} [parserFlags] (null) Parser flags to apply |
| 4349 | * @prop {SlashCommandAbortController} [abortController] (null) Controller used to abort or pause command execution | 4407 | * @prop {SlashCommandAbortController} [abortController] (null) Controller used to abort or pause command execution |
| 4350 | * @prop {SlashCommandDebugController} [debugController] (null) Controller used to control debug execution | 4408 | * @prop {SlashCommandDebugController} [debugController] (null) Controller used to control debug execution |
| 4351 | * @prop {(done:number, total:number)=>void} [onProgress] (null) Callback to handle progress events | 4409 | * @prop {(done:number, total:number)=>void} [onProgress] (null) Callback to handle progress events |
| @@ -4355,7 +4413,7 @@ const clearCommandProgressDebounced = debounce(clearCommandProgress); | |||
| 4355 | /** | 4413 | /** |
| 4356 | * @typedef ExecuteSlashCommandsOnChatInputOptions | 4414 | * @typedef ExecuteSlashCommandsOnChatInputOptions |
| 4357 | * @prop {SlashCommandScope} [scope] (null) The scope to be used when executing the commands. | 4415 | * @prop {SlashCommandScope} [scope] (null) The scope to be used when executing the commands. |
| 4358 | * @prop {{[id:PARSER_FLAG]:boolean}} [parserFlags] (null) Parser flags to apply | 4416 | * @prop {import('./slash-commands/SlashCommandParser.js').ParserFlags} [parserFlags] (null) Parser flags to apply |
| 4359 | * @prop {boolean} [clearChatInput] (false) Whether to clear the chat input textarea | 4417 | * @prop {boolean} [clearChatInput] (false) Whether to clear the chat input textarea |
| 4360 | * @prop {string} [source] (null) String indicating where the code come from (e.g., QR name) | 4418 | * @prop {string} [source] (null) String indicating where the code come from (e.g., QR name) |
| 4361 | */ | 4419 | */ |
| @@ -1,18 +1,15 @@ | |||
| 1 | import { hljs } from '../../lib.js'; | 1 | import { hljs } from '../../lib.js'; |
| 2 | import { t } from '../i18n.js'; | ||
| 2 | import { SlashCommandAbortController } from './SlashCommandAbortController.js'; | 3 | import { SlashCommandAbortController } from './SlashCommandAbortController.js'; |
| 3 | import { SlashCommandArgument, SlashCommandNamedArgument } from './SlashCommandArgument.js'; | 4 | import { SlashCommandArgument, SlashCommandNamedArgument } from './SlashCommandArgument.js'; |
| 4 | import { SlashCommandClosure } from './SlashCommandClosure.js'; | 5 | import { SlashCommandClosure } from './SlashCommandClosure.js'; |
| 5 | import { SlashCommandDebugController } from './SlashCommandDebugController.js'; | 6 | import { SlashCommandDebugController } from './SlashCommandDebugController.js'; |
| 6 | import { PARSER_FLAG } from './SlashCommandParser.js'; | ||
| 7 | import { SlashCommandScope } from './SlashCommandScope.js'; | 7 | import { SlashCommandScope } from './SlashCommandScope.js'; |
| 8 | 8 | ||
| 9 | |||
| 10 | |||
| 11 | |||
| 12 | /** | 9 | /** |
| 13 | * @typedef {{ | 10 | * @typedef {{ |
| 14 | * _scope:SlashCommandScope, | 11 | * _scope:SlashCommandScope, |
| 15 | * _parserFlags:{[id:PARSER_FLAG]:boolean}, | 12 | * _parserFlags:import('./SlashCommandParser.js').ParserFlags, |
| 16 | * _abortController:SlashCommandAbortController, | 13 | * _abortController:SlashCommandAbortController, |
| 17 | * _debugController:SlashCommandDebugController, | 14 | * _debugController:SlashCommandDebugController, |
| 18 | * _hasUnnamedArgument:boolean, | 15 | * _hasUnnamedArgument:boolean, |
| @@ -40,6 +37,7 @@ export class SlashCommand { | |||
| 40 | * @param {string} [props.helpString] | 37 | * @param {string} [props.helpString] |
| 41 | * @param {boolean} [props.splitUnnamedArgument] | 38 | * @param {boolean} [props.splitUnnamedArgument] |
| 42 | * @param {Number} [props.splitUnnamedArgumentCount] | 39 | * @param {Number} [props.splitUnnamedArgumentCount] |
| 40 | * @param {boolean} [props.rawQuotes] If set to true, does not remove wrapping quotes from the unnamed argument. | ||
| 43 | * @param {string[]} [props.aliases] | 41 | * @param {string[]} [props.aliases] |
| 44 | * @param {string} [props.returns] | 42 | * @param {string} [props.returns] |
| 45 | * @param {SlashCommandNamedArgument[]} [props.namedArgumentList] | 43 | * @param {SlashCommandNamedArgument[]} [props.namedArgumentList] |
| @@ -58,6 +56,7 @@ export class SlashCommand { | |||
| 58 | /**@type {string}*/ helpString; | 56 | /**@type {string}*/ helpString; |
| 59 | /**@type {boolean}*/ splitUnnamedArgument = false; | 57 | /**@type {boolean}*/ splitUnnamedArgument = false; |
| 60 | /**@type {Number}*/ splitUnnamedArgumentCount; | 58 | /**@type {Number}*/ splitUnnamedArgumentCount; |
| 59 | /** @type {boolean} */ rawQuotes = false; | ||
| 61 | /**@type {string[]}*/ aliases = []; | 60 | /**@type {string[]}*/ aliases = []; |
| 62 | /**@type {string}*/ returns; | 61 | /**@type {string}*/ returns; |
| 63 | /**@type {SlashCommandNamedArgument[]}*/ namedArgumentList = []; | 62 | /**@type {SlashCommandNamedArgument[]}*/ namedArgumentList = []; |
| @@ -262,6 +261,15 @@ export class SlashCommand { | |||
| 262 | ].filter(it=>it).join('\n'); | 261 | ].filter(it=>it).join('\n'); |
| 263 | head.append(src); | 262 | head.append(src); |
| 264 | } | 263 | } |
| 264 | if (this.rawQuotes) { | ||
| 265 | const rawQuotes = document.createElement('div'); { | ||
| 266 | rawQuotes.classList.add('rawQuotes'); | ||
| 267 | rawQuotes.classList.add('fa-solid'); | ||
| 268 | rawQuotes.classList.add('fa-quote-left'); | ||
| 269 | rawQuotes.title = t`Does not alter quoted literal unnamed arguments`; | ||
| 270 | head.append(rawQuotes); | ||
| 271 | } | ||
| 272 | } | ||
| 265 | specs.append(head); | 273 | specs.append(head); |
| 266 | } | 274 | } |
| 267 | const body = document.createElement('div'); { | 275 | const body = document.createElement('div'); { |
| @@ -1,9 +1,6 @@ | |||
| 1 | import { AutoCompleteNameResult } from '../autocomplete/AutoCompleteNameResult.js'; | 1 | import { AutoCompleteNameResult } from '../autocomplete/AutoCompleteNameResult.js'; |
| 2 | import { AutoCompleteOption } from '../autocomplete/AutoCompleteOption.js'; | ||
| 3 | import { AutoCompleteSecondaryNameResult } from '../autocomplete/AutoCompleteSecondaryNameResult.js'; | 2 | import { AutoCompleteSecondaryNameResult } from '../autocomplete/AutoCompleteSecondaryNameResult.js'; |
| 4 | import { SlashCommand } from './SlashCommand.js'; | 3 | import { SlashCommand } from './SlashCommand.js'; |
| 5 | import { SlashCommandNamedArgument } from './SlashCommandArgument.js'; | ||
| 6 | import { SlashCommandClosure } from './SlashCommandClosure.js'; | ||
| 7 | import { SlashCommandCommandAutoCompleteOption } from './SlashCommandCommandAutoCompleteOption.js'; | 4 | import { SlashCommandCommandAutoCompleteOption } from './SlashCommandCommandAutoCompleteOption.js'; |
| 8 | import { SlashCommandEnumAutoCompleteOption } from './SlashCommandEnumAutoCompleteOption.js'; | 5 | import { SlashCommandEnumAutoCompleteOption } from './SlashCommandEnumAutoCompleteOption.js'; |
| 9 | import { SlashCommandExecutor } from './SlashCommandExecutor.js'; | 6 | import { SlashCommandExecutor } from './SlashCommandExecutor.js'; |
| @@ -2,7 +2,6 @@ import { substituteParams } from '../../script.js'; | |||
| 2 | import { delay, escapeRegex, uuidv4 } from '../utils.js'; | 2 | import { delay, escapeRegex, uuidv4 } from '../utils.js'; |
| 3 | import { SlashCommand } from './SlashCommand.js'; | 3 | import { SlashCommand } from './SlashCommand.js'; |
| 4 | import { SlashCommandAbortController } from './SlashCommandAbortController.js'; | 4 | import { SlashCommandAbortController } from './SlashCommandAbortController.js'; |
| 5 | import { SlashCommandNamedArgument } from './SlashCommandArgument.js'; | ||
| 6 | import { SlashCommandBreak } from './SlashCommandBreak.js'; | 5 | import { SlashCommandBreak } from './SlashCommandBreak.js'; |
| 7 | import { SlashCommandBreakController } from './SlashCommandBreakController.js'; | 6 | import { SlashCommandBreakController } from './SlashCommandBreakController.js'; |
| 8 | import { SlashCommandBreakPoint } from './SlashCommandBreakPoint.js'; | 7 | import { SlashCommandBreakPoint } from './SlashCommandBreakPoint.js'; |
| @@ -14,21 +13,19 @@ import { SlashCommandNamedArgumentAssignment } from './SlashCommandNamedArgument | |||
| 14 | import { SlashCommandScope } from './SlashCommandScope.js'; | 13 | import { SlashCommandScope } from './SlashCommandScope.js'; |
| 15 | 14 | ||
| 16 | export class SlashCommandClosure { | 15 | export class SlashCommandClosure { |
| 17 | /**@type {SlashCommandScope}*/ scope; | 16 | /** @type {SlashCommandScope} */ scope; |
| 18 | /**@type {boolean}*/ executeNow = false; | 17 | /** @type {boolean} */ executeNow = false; |
| 19 | // @ts-ignore | 18 | /** @type {SlashCommandNamedArgumentAssignment[]} */ argumentList = []; |
| 20 | /**@type {SlashCommandNamedArgumentAssignment[]}*/ argumentList = []; | 19 | /** @type {SlashCommandNamedArgumentAssignment[]} */ providedArgumentList = []; |
| 21 | // @ts-ignore | 20 | /** @type {SlashCommandExecutor[]} */ executorList = []; |
| 22 | /**@type {SlashCommandNamedArgumentAssignment[]}*/ providedArgumentList = []; | 21 | /** @type {SlashCommandAbortController} */ abortController; |
| 23 | /**@type {SlashCommandExecutor[]}*/ executorList = []; | 22 | /** @type {SlashCommandBreakController} */ breakController; |
| 24 | /**@type {SlashCommandAbortController}*/ abortController; | 23 | /** @type {SlashCommandDebugController} */ debugController; |
| 25 | /**@type {SlashCommandBreakController}*/ breakController; | 24 | /** @type {(done:number, total:number)=>void} */ onProgress; |
| 26 | /**@type {SlashCommandDebugController}*/ debugController; | 25 | /** @type {string} */ rawText; |
| 27 | /**@type {(done:number, total:number)=>void}*/ onProgress; | 26 | /** @type {string} */ fullText; |
| 28 | /**@type {string}*/ rawText; | 27 | /** @type {string} */ parserContext; |
| 29 | /**@type {string}*/ fullText; | 28 | /** @type {string} */ #source = uuidv4(); |
| 30 | /**@type {string}*/ parserContext; | ||
| 31 | /**@type {string}*/ #source = uuidv4(); | ||
| 32 | get source() { return this.#source; } | 29 | get source() { return this.#source; } |
| 33 | set source(value) { | 30 | set source(value) { |
| 34 | this.#source = value; | 31 | this.#source = value; |
| @@ -2,20 +2,20 @@ import { SlashCommandClosure } from './SlashCommandClosure.js'; | |||
| 2 | import { SlashCommandExecutor } from './SlashCommandExecutor.js'; | 2 | import { SlashCommandExecutor } from './SlashCommandExecutor.js'; |
| 3 | 3 | ||
| 4 | export class SlashCommandDebugController { | 4 | export class SlashCommandDebugController { |
| 5 | /**@type {SlashCommandClosure[]} */ stack = []; | 5 | /** @type {SlashCommandClosure[]} */ stack = []; |
| 6 | /**@type {SlashCommandExecutor[]} */ cmdStack = []; | 6 | /** @type {SlashCommandExecutor[]} */ cmdStack = []; |
| 7 | /**@type {boolean[]} */ stepStack = []; | 7 | /** @type {boolean[]} */ stepStack = []; |
| 8 | /**@type {boolean} */ isStepping = false; | 8 | /** @type {boolean} */ isStepping = false; |
| 9 | /**@type {boolean} */ isSteppingInto = false; | 9 | /** @type {boolean} */ isSteppingInto = false; |
| 10 | /**@type {boolean} */ isSteppingOut = false; | 10 | /** @type {boolean} */ isSteppingOut = false; |
| 11 | 11 | ||
| 12 | /**@type {object} */ namedArguments; | 12 | /** @type {object} */ namedArguments; |
| 13 | /**@type {string|SlashCommandClosure|(string|SlashCommandClosure)[]} */ unnamedArguments; | 13 | /** @type {string|SlashCommandClosure|(string|SlashCommandClosure)[]} */ unnamedArguments; |
| 14 | 14 | ||
| 15 | /**@type {Promise<boolean>} */ continuePromise; | 15 | /** @type {Promise<boolean>} */ continuePromise; |
| 16 | /**@type {(boolean)=>void} */ continueResolver; | 16 | /** @type {(boolean)=>void} */ continueResolver; |
| 17 | 17 | ||
| 18 | /**@type {(closure:SlashCommandClosure, executor:SlashCommandExecutor)=>Promise<boolean>} */ onBreakPoint; | 18 | /** @type {(closure:SlashCommandClosure, executor:SlashCommandExecutor)=>Promise<boolean>} */ onBreakPoint; |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | 21 | ||
| @@ -1,7 +1,3 @@ | |||
| 1 | import { SlashCommandExecutor } from './SlashCommandExecutor.js'; | ||
| 2 | import { SlashCommandScope } from './SlashCommandScope.js'; | ||
| 3 | |||
| 4 | |||
| 5 | /** | 1 | /** |
| 6 | * @typedef {'enum' | 'command' | 'namedArgument' | 'variable' | 'qr' | 'macro' | 'number' | 'name'} EnumType | 2 | * @typedef {'enum' | 'command' | 'namedArgument' | 'variable' | 'qr' | 'macro' | 'number' | 'name'} EnumType |
| 7 | */ | 3 | */ |
| @@ -1,11 +1,7 @@ | |||
| 1 | // eslint-disable-next-line no-unused-vars | ||
| 2 | import { uuidv4 } from '../utils.js'; | 1 | import { uuidv4 } from '../utils.js'; |
| 3 | import { SlashCommand } from './SlashCommand.js'; | 2 | import { SlashCommand } from './SlashCommand.js'; |
| 4 | // eslint-disable-next-line no-unused-vars | ||
| 5 | import { SlashCommandClosure } from './SlashCommandClosure.js'; | 3 | import { SlashCommandClosure } from './SlashCommandClosure.js'; |
| 6 | import { SlashCommandNamedArgumentAssignment } from './SlashCommandNamedArgumentAssignment.js'; | 4 | import { SlashCommandNamedArgumentAssignment } from './SlashCommandNamedArgumentAssignment.js'; |
| 7 | // eslint-disable-next-line no-unused-vars | ||
| 8 | import { PARSER_FLAG } from './SlashCommandParser.js'; | ||
| 9 | import { SlashCommandUnnamedArgumentAssignment } from './SlashCommandUnnamedArgumentAssignment.js'; | 5 | import { SlashCommandUnnamedArgumentAssignment } from './SlashCommandUnnamedArgumentAssignment.js'; |
| 10 | 6 | ||
| 11 | export class SlashCommandExecutor { | 7 | export class SlashCommandExecutor { |
| @@ -28,11 +24,10 @@ export class SlashCommandExecutor { | |||
| 28 | arg.value.source = value; | 24 | arg.value.source = value; |
| 29 | } | 25 | } |
| 30 | } | 26 | } |
| 31 | /**@type {SlashCommand}*/ command; | 27 | /** @type {SlashCommand} */ command; |
| 32 | // @ts-ignore | 28 | /** @type {SlashCommandNamedArgumentAssignment[]} */ namedArgumentList = []; |
| 33 | /**@type {SlashCommandNamedArgumentAssignment[]}*/ namedArgumentList = []; | 29 | /** @type {SlashCommandUnnamedArgumentAssignment[]} */ unnamedArgumentList = []; |
| 34 | /**@type {SlashCommandUnnamedArgumentAssignment[]}*/ unnamedArgumentList = []; | 30 | /** @type {import('./SlashCommandParser.js').ParserFlags} */ parserFlags; |
| 35 | /**@type {{[id:PARSER_FLAG]:boolean}} */ parserFlags; | ||
| 36 | 31 | ||
| 37 | get commandCount() { | 32 | get commandCount() { |
| 38 | return 1 | 33 | return 1 |
| @@ -1,10 +1,10 @@ | |||
| 1 | import { SlashCommandClosure } from './SlashCommandClosure.js'; | 1 | import { SlashCommandClosure } from './SlashCommandClosure.js'; |
| 2 | 2 | ||
| 3 | export class SlashCommandNamedArgumentAssignment { | 3 | export class SlashCommandNamedArgumentAssignment { |
| 4 | /**@type {number}*/ start; | 4 | /** @type {number} */ start; |
| 5 | /**@type {number}*/ end; | 5 | /** @type {number} */ end; |
| 6 | /**@type {string}*/ name; | 6 | /** @type {string} */ name; |
| 7 | /**@type {string|SlashCommandClosure}*/ value; | 7 | /** @type {string|SlashCommandClosure} */ value; |
| 8 | 8 | ||
| 9 | 9 | ||
| 10 | constructor() { | 10 | constructor() { |
| @@ -1,11 +1,10 @@ | |||
| 1 | import { AutoCompleteOption } from '../autocomplete/AutoCompleteOption.js'; | 1 | import { AutoCompleteOption } from '../autocomplete/AutoCompleteOption.js'; |
| 2 | import { SlashCommand } from './SlashCommand.js'; | 2 | import { SlashCommand } from './SlashCommand.js'; |
| 3 | import { SlashCommandNamedArgument } from './SlashCommandArgument.js'; | 3 | import { SlashCommandNamedArgument } from './SlashCommandArgument.js'; |
| 4 | import { SlashCommandNamedArgumentAssignment } from './SlashCommandNamedArgumentAssignment.js'; | ||
| 5 | 4 | ||
| 6 | export class SlashCommandNamedArgumentAutoCompleteOption extends AutoCompleteOption { | 5 | export class SlashCommandNamedArgumentAutoCompleteOption extends AutoCompleteOption { |
| 7 | /**@type {SlashCommandNamedArgument}*/ arg; | 6 | /** @type {SlashCommandNamedArgument} */ arg; |
| 8 | /**@type {SlashCommand}*/ cmd; | 7 | /** @type {SlashCommand} */ cmd; |
| 9 | 8 | ||
| 10 | /** | 9 | /** |
| 11 | * @param {SlashCommandNamedArgument} arg | 10 | * @param {SlashCommandNamedArgument} arg |
| @@ -8,11 +8,9 @@ import { SlashCommandExecutor } from './SlashCommandExecutor.js'; | |||
| 8 | import { SlashCommandParserError } from './SlashCommandParserError.js'; | 8 | import { SlashCommandParserError } from './SlashCommandParserError.js'; |
| 9 | import { AutoCompleteNameResult } from '../autocomplete/AutoCompleteNameResult.js'; | 9 | import { AutoCompleteNameResult } from '../autocomplete/AutoCompleteNameResult.js'; |
| 10 | import { SlashCommandQuickReplyAutoCompleteOption } from './SlashCommandQuickReplyAutoCompleteOption.js'; | 10 | import { SlashCommandQuickReplyAutoCompleteOption } from './SlashCommandQuickReplyAutoCompleteOption.js'; |
| 11 | // eslint-disable-next-line no-unused-vars | ||
| 12 | import { SlashCommandScope } from './SlashCommandScope.js'; | 11 | import { SlashCommandScope } from './SlashCommandScope.js'; |
| 13 | import { SlashCommandVariableAutoCompleteOption } from './SlashCommandVariableAutoCompleteOption.js'; | 12 | import { SlashCommandVariableAutoCompleteOption } from './SlashCommandVariableAutoCompleteOption.js'; |
| 14 | import { SlashCommandNamedArgumentAssignment } from './SlashCommandNamedArgumentAssignment.js'; | 13 | import { SlashCommandNamedArgumentAssignment } from './SlashCommandNamedArgumentAssignment.js'; |
| 15 | // eslint-disable-next-line no-unused-vars | ||
| 16 | import { SlashCommandAbortController } from './SlashCommandAbortController.js'; | 14 | import { SlashCommandAbortController } from './SlashCommandAbortController.js'; |
| 17 | import { SlashCommandAutoCompleteNameResult } from './SlashCommandAutoCompleteNameResult.js'; | 15 | import { SlashCommandAutoCompleteNameResult } from './SlashCommandAutoCompleteNameResult.js'; |
| 18 | import { SlashCommandUnnamedArgumentAssignment } from './SlashCommandUnnamedArgumentAssignment.js'; | 16 | import { SlashCommandUnnamedArgumentAssignment } from './SlashCommandUnnamedArgumentAssignment.js'; |
| @@ -28,16 +26,18 @@ import { t } from '../i18n.js'; | |||
| 28 | /** @typedef {import('./SlashCommand.js').NamedArgumentsCapture} NamedArgumentsCapture */ | 26 | /** @typedef {import('./SlashCommand.js').NamedArgumentsCapture} NamedArgumentsCapture */ |
| 29 | /** @typedef {import('./SlashCommand.js').NamedArguments} NamedArguments */ | 27 | /** @typedef {import('./SlashCommand.js').NamedArguments} NamedArguments */ |
| 30 | 28 | ||
| 31 | /**@readonly*/ | 29 | /** |
| 32 | /**@enum {Number}*/ | 30 | * @enum {Number} |
| 31 | * @readonly | ||
| 32 | * @typedef {{[id:PARSER_FLAG]:boolean}} ParserFlags | ||
| 33 | */ | ||
| 33 | export const PARSER_FLAG = { | 34 | export const PARSER_FLAG = { |
| 34 | 'STRICT_ESCAPING': 1, | 35 | 'STRICT_ESCAPING': 1, |
| 35 | 'REPLACE_GETVAR': 2, | 36 | 'REPLACE_GETVAR': 2, |
| 36 | }; | 37 | }; |
| 37 | 38 | ||
| 38 | export class SlashCommandParser { | 39 | export class SlashCommandParser { |
| 39 | // @ts-ignore | 40 | /** @type {Object.<string, SlashCommand>} */ static commands = {}; |
| 40 | /**@type {Object.<string, SlashCommand>}*/ static commands = {}; | ||
| 41 | 41 | ||
| 42 | /** | 42 | /** |
| 43 | * @deprecated Use SlashCommandParser.addCommandObject() instead. | 43 | * @deprecated Use SlashCommandParser.addCommandObject() instead. |
| @@ -101,26 +101,25 @@ export class SlashCommandParser { | |||
| 101 | get commands() { | 101 | get commands() { |
| 102 | return SlashCommandParser.commands; | 102 | return SlashCommandParser.commands; |
| 103 | } | 103 | } |
| 104 | // @ts-ignore | 104 | /** @type {Object.<string, string>} */ helpStrings = {}; |
| 105 | /**@type {Object.<string, string>}*/ helpStrings = {}; | 105 | /** @type {boolean} */ verifyCommandNames = true; |
| 106 | /**@type {boolean}*/ verifyCommandNames = true; | 106 | /** @type {string} */ text; |
| 107 | /**@type {string}*/ text; | 107 | /** @type {number} */ index; |
| 108 | /**@type {number}*/ index; | 108 | /** @type {SlashCommandAbortController} */ abortController; |
| 109 | /**@type {SlashCommandAbortController}*/ abortController; | 109 | /** @type {SlashCommandDebugController} */ debugController; |
| 110 | /**@type {SlashCommandDebugController}*/ debugController; | 110 | /** @type {SlashCommandScope} */ scope; |
| 111 | /**@type {SlashCommandScope}*/ scope; | 111 | /** @type {SlashCommandClosure} */ closure; |
| 112 | /**@type {SlashCommandClosure}*/ closure; | ||
| 113 | 112 | ||
| 114 | /**@type {Object.<PARSER_FLAG,boolean>}*/ flags = {}; | 113 | /** @type {Object.<PARSER_FLAG,boolean>} */ flags = {}; |
| 115 | 114 | ||
| 116 | /**@type {boolean}*/ jumpedEscapeSequence = false; | 115 | /** @type {boolean} */ jumpedEscapeSequence = false; |
| 117 | 116 | ||
| 118 | /**@type {{start:number, end:number}[]}*/ closureIndex; | 117 | /** @type {{start:number, end:number}[]} */ closureIndex; |
| 119 | /**@type {{start:number, end:number, name:string}[]}*/ macroIndex; | 118 | /** @type {{start:number, end:number, name:string}[]} */ macroIndex; |
| 120 | /**@type {SlashCommandExecutor[]}*/ commandIndex; | 119 | /** @type {SlashCommandExecutor[]} */ commandIndex; |
| 121 | /**@type {SlashCommandScope[]}*/ scopeIndex; | 120 | /** @type {SlashCommandScope[]} */ scopeIndex; |
| 122 | 121 | ||
| 123 | /**@type {string}*/ parserContext; | 122 | /** @type {string} */ parserContext; |
| 124 | 123 | ||
| 125 | get userIndex() { return this.index; } | 124 | get userIndex() { return this.index; } |
| 126 | 125 | ||
| @@ -976,7 +975,7 @@ export class SlashCommandParser { | |||
| 976 | cmd.startUnnamedArgs = this.index - (/\s(\s*)$/s.exec(this.behind)?.[1]?.length ?? 0); | 975 | cmd.startUnnamedArgs = this.index - (/\s(\s*)$/s.exec(this.behind)?.[1]?.length ?? 0); |
| 977 | cmd.endUnnamedArgs = this.index; | 976 | cmd.endUnnamedArgs = this.index; |
| 978 | if (this.testUnnamedArgument()) { | 977 | if (this.testUnnamedArgument()) { |
| 979 | cmd.unnamedArgumentList = this.parseUnnamedArgument(cmd.command?.unnamedArgumentList?.length && cmd?.command?.splitUnnamedArgument, cmd?.command?.splitUnnamedArgumentCount); | 978 | cmd.unnamedArgumentList = this.parseUnnamedArgument(cmd.command?.unnamedArgumentList?.length && cmd?.command?.splitUnnamedArgument, cmd?.command?.splitUnnamedArgumentCount, cmd?.command?.rawQuotes); |
| 980 | cmd.endUnnamedArgs = this.index; | 979 | cmd.endUnnamedArgs = this.index; |
| 981 | if (cmd.name == 'let') { | 980 | if (cmd.name == 'let') { |
| 982 | const keyArg = cmd.namedArgumentList.find(it=>it.name == 'key'); | 981 | const keyArg = cmd.namedArgumentList.find(it=>it.name == 'key'); |
| @@ -1036,7 +1035,7 @@ export class SlashCommandParser { | |||
| 1036 | testUnnamedArgumentEnd() { | 1035 | testUnnamedArgumentEnd() { |
| 1037 | return this.testCommandEnd(); | 1036 | return this.testCommandEnd(); |
| 1038 | } | 1037 | } |
| 1039 | parseUnnamedArgument(split, splitCount = null) { | 1038 | parseUnnamedArgument(split, splitCount = null, rawQuotes = false) { |
| 1040 | const wasSplit = split; | 1039 | const wasSplit = split; |
| 1041 | /**@type {SlashCommandClosure|String}*/ | 1040 | /**@type {SlashCommandClosure|String}*/ |
| 1042 | let value = this.jumpedEscapeSequence ? this.take() : ''; // take the first, already tested, char if it is an escaped one | 1041 | let value = this.jumpedEscapeSequence ? this.take() : ''; // take the first, already tested, char if it is an escaped one |
| @@ -1046,7 +1045,7 @@ export class SlashCommandParser { | |||
| 1046 | /**@type {SlashCommandUnnamedArgumentAssignment}*/ | 1045 | /**@type {SlashCommandUnnamedArgumentAssignment}*/ |
| 1047 | let assignment = new SlashCommandUnnamedArgumentAssignment(); | 1046 | let assignment = new SlashCommandUnnamedArgumentAssignment(); |
| 1048 | assignment.start = this.index; | 1047 | assignment.start = this.index; |
| 1049 | if (!split && this.testQuotedValue()) { | 1048 | if (!split && !rawQuotes && this.testQuotedValue()) { |
| 1050 | // if the next bit is a quoted value, take the whole value and gather contents as a list | 1049 | // if the next bit is a quoted value, take the whole value and gather contents as a list |
| 1051 | assignment.value = this.parseQuotedValue(); | 1050 | assignment.value = this.parseQuotedValue(); |
| 1052 | assignment.end = this.index; | 1051 | assignment.end = this.index; |
| @@ -2,21 +2,21 @@ import { SlashCommandClosure } from './SlashCommandClosure.js'; | |||
| 2 | import { convertValueType } from '../utils.js'; | 2 | import { convertValueType } from '../utils.js'; |
| 3 | 3 | ||
| 4 | export class SlashCommandScope { | 4 | export class SlashCommandScope { |
| 5 | /**@type {string[]}*/ variableNames = []; | 5 | /** @type {string[]} */ variableNames = []; |
| 6 | get allVariableNames() { | 6 | get allVariableNames() { |
| 7 | const names = [...this.variableNames, ...(this.parent?.allVariableNames ?? [])]; | 7 | const names = [...this.variableNames, ...(this.parent?.allVariableNames ?? [])]; |
| 8 | return names.filter((it,idx)=>idx == names.indexOf(it)); | 8 | return names.filter((it,idx)=>idx == names.indexOf(it)); |
| 9 | } | 9 | } |
| 10 | // @ts-ignore | 10 | // @ts-ignore |
| 11 | /**@type {object.<string, string|SlashCommandClosure>}*/ variables = {}; | 11 | /** @type {object.<string, string|SlashCommandClosure>} */ variables = {}; |
| 12 | // @ts-ignore | 12 | // @ts-ignore |
| 13 | /**@type {object.<string, string|SlashCommandClosure>}*/ macros = {}; | 13 | /** @type {object.<string, string|SlashCommandClosure>} */ macros = {}; |
| 14 | /**@type {{key:string, value:string|SlashCommandClosure}[]} */ | 14 | /** @type {{key:string, value:string|SlashCommandClosure}[]} */ |
| 15 | get macroList() { | 15 | get macroList() { |
| 16 | return [...Object.keys(this.macros).map(key=>({ key, value:this.macros[key] })), ...(this.parent?.macroList ?? [])]; | 16 | return [...Object.keys(this.macros).map(key=>({ key, value:this.macros[key] })), ...(this.parent?.macroList ?? [])]; |
| 17 | } | 17 | } |
| 18 | /**@type {SlashCommandScope}*/ parent; | 18 | /** @type {SlashCommandScope} */ parent; |
| 19 | /**@type {string}*/ #pipe; | 19 | /** @type {string} */ #pipe; |
| 20 | get pipe() { | 20 | get pipe() { |
| 21 | return this.#pipe ?? this.parent?.pipe; | 21 | return this.#pipe ?? this.parent?.pipe; |
| 22 | } | 22 | } |
| @@ -1,9 +1,9 @@ | |||
| 1 | import { SlashCommandClosure } from './SlashCommandClosure.js'; | 1 | import { SlashCommandClosure } from './SlashCommandClosure.js'; |
| 2 | 2 | ||
| 3 | export class SlashCommandUnnamedArgumentAssignment { | 3 | export class SlashCommandUnnamedArgumentAssignment { |
| 4 | /**@type {number}*/ start; | 4 | /** @type {number} */ start; |
| 5 | /**@type {number}*/ end; | 5 | /** @type {number} */ end; |
| 6 | /**@type {string|SlashCommandClosure}*/ value; | 6 | /** @type {string|SlashCommandClosure} */ value; |
| 7 | 7 | ||
| 8 | 8 | ||
| 9 | constructor() { | 9 | constructor() { |
| @@ -49,6 +49,7 @@ import { | |||
| 49 | clearChat, | 49 | clearChat, |
| 50 | unshallowCharacter, | 50 | unshallowCharacter, |
| 51 | deleteLastMessage, | 51 | deleteLastMessage, |
| 52 | getCharacterCardFields, | ||
| 52 | } from '../script.js'; | 53 | } from '../script.js'; |
| 53 | import { | 54 | import { |
| 54 | extension_settings, | 55 | extension_settings, |
| @@ -78,9 +79,11 @@ import { ToolManager } from './tool-calling.js'; | |||
| 78 | import { accountStorage } from './util/AccountStorage.js'; | 79 | import { accountStorage } from './util/AccountStorage.js'; |
| 79 | import { timestampToMoment, uuidv4 } from './utils.js'; | 80 | import { timestampToMoment, uuidv4 } from './utils.js'; |
| 80 | import { getGlobalVariable, getLocalVariable, setGlobalVariable, setLocalVariable } from './variables.js'; | 81 | import { getGlobalVariable, getLocalVariable, setGlobalVariable, setLocalVariable } from './variables.js'; |
| 81 | import { convertCharacterBook, loadWorldInfo, saveWorldInfo, updateWorldInfoList } from './world-info.js'; | 82 | import { convertCharacterBook, getWorldInfoPrompt, loadWorldInfo, reloadEditor, saveWorldInfo, updateWorldInfoList } from './world-info.js'; |
| 82 | import { ChatCompletionService, TextCompletionService } from './custom-request.js'; | 83 | import { ChatCompletionService, TextCompletionService } from './custom-request.js'; |
| 84 | import { ConnectionManagerRequestService } from './extensions/shared.js'; | ||
| 83 | import { updateReasoningUI, parseReasoningFromString } from './reasoning.js'; | 85 | import { updateReasoningUI, parseReasoningFromString } from './reasoning.js'; |
| 86 | import { IGNORE_SYMBOL } from './constants.js'; | ||
| 84 | 87 | ||
| 85 | export function getContext() { | 88 | export function getContext() { |
| 86 | return { | 89 | return { |
| @@ -188,6 +191,7 @@ export function getContext() { | |||
| 188 | textCompletionSettings: textgenerationwebui_settings, | 191 | textCompletionSettings: textgenerationwebui_settings, |
| 189 | powerUserSettings: power_user, | 192 | powerUserSettings: power_user, |
| 190 | getCharacters, | 193 | getCharacters, |
| 194 | getCharacterCardFields, | ||
| 191 | uuidv4, | 195 | uuidv4, |
| 192 | humanizedDateTime, | 196 | humanizedDateTime, |
| 193 | updateMessageBlock, | 197 | updateMessageBlock, |
| @@ -204,8 +208,10 @@ export function getContext() { | |||
| 204 | }, | 208 | }, |
| 205 | loadWorldInfo, | 209 | loadWorldInfo, |
| 206 | saveWorldInfo, | 210 | saveWorldInfo, |
| 211 | reloadWorldInfoEditor: reloadEditor, | ||
| 207 | updateWorldInfoList, | 212 | updateWorldInfoList, |
| 208 | convertCharacterBook, | 213 | convertCharacterBook, |
| 214 | getWorldInfoPrompt, | ||
| 209 | CONNECT_API_MAP, | 215 | CONNECT_API_MAP, |
| 210 | getTextGenServer, | 216 | getTextGenServer, |
| 211 | extractMessageFromData, | 217 | extractMessageFromData, |
| @@ -215,10 +221,14 @@ export function getContext() { | |||
| 215 | clearChat, | 221 | clearChat, |
| 216 | ChatCompletionService, | 222 | ChatCompletionService, |
| 217 | TextCompletionService, | 223 | TextCompletionService, |
| 224 | ConnectionManagerRequestService, | ||
| 218 | updateReasoningUI, | 225 | updateReasoningUI, |
| 219 | parseReasoningFromString, | 226 | parseReasoningFromString, |
| 220 | unshallowCharacter, | 227 | unshallowCharacter, |
| 221 | unshallowGroupMembers, | 228 | unshallowGroupMembers, |
| 229 | symbols: { | ||
| 230 | ignore: IGNORE_SYMBOL, | ||
| 231 | }, | ||
| 222 | }; | 232 | }; |
| 223 | } | 233 | } |
| 224 | 234 | ||
| @@ -13,7 +13,6 @@ import { | |||
| 13 | DEFAULT_PRINT_TIMEOUT, | 13 | DEFAULT_PRINT_TIMEOUT, |
| 14 | printCharacters, | 14 | printCharacters, |
| 15 | } from '../script.js'; | 15 | } from '../script.js'; |
| 16 | // eslint-disable-next-line no-unused-vars | ||
| 17 | import { FILTER_TYPES, FILTER_STATES, DEFAULT_FILTER_STATE, isFilterState, FilterHelper } from './filters.js'; | 16 | import { FILTER_TYPES, FILTER_STATES, DEFAULT_FILTER_STATE, isFilterState, FilterHelper } from './filters.js'; |
| 18 | 17 | ||
| 19 | import { groupCandidatesFilter, groups, selected_group } from './group-chats.js'; | 18 | import { groupCandidatesFilter, groups, selected_group } from './group-chats.js'; |
| @@ -1,9 +1,9 @@ | |||
| 1 | <div data-type="assistant_note"> | 1 | <div data-type="assistant_note"> |
| 2 | <div> | 2 | <div> |
| 3 | <b data-i18n="Note:">Note:</b> <span data-i18n="this chat is temporary and will be deleted as soon as you leave it.">this chat is temporary and will be deleted as soon as you leave it.</span> | 3 | <b data-i18n="Note:">Note:</b> <span data-i18n="this chat is temporary and will be deleted as soon as you leave it.">this chat is temporary and will be deleted as soon as you leave it.</span> |
| 4 | <span>Click the button to save it as a file.</span> | 4 | <span data-i18n="Click the button to save it as a file.">Click the button to save it as a file.</span> |
| 5 | </div> | 5 | </div> |
| 6 | <div class="assistant_note_export menu_button menu_button_icon" title="Export as JSONL"> | 6 | <div class="assistant_note_export menu_button menu_button_icon" data-i18n="[title]Export as JSONL" title="Export as JSONL"> |
| 7 | <i class="fa-solid fa-file-export"></i> | 7 | <i class="fa-solid fa-file-export"></i> |
| 8 | </div> | 8 | </div> |
| 9 | </div> | 9 | </div> |
| @@ -20,7 +20,8 @@ | |||
| 20 | <li><tt>{{summary}}</tt> – <span data-i18n="help_macros_summary">the latest chat summary generated by the "Summarize" extension (if available).</span></li> | 20 | <li><tt>{{summary}}</tt> – <span data-i18n="help_macros_summary">the latest chat summary generated by the "Summarize" extension (if available).</span></li> |
| 21 | <li><tt>{{user}}</tt> – <span data-i18n="help_macros_15">your current Persona username</span></li> | 21 | <li><tt>{{user}}</tt> – <span data-i18n="help_macros_15">your current Persona username</span></li> |
| 22 | <li><tt>{{char}}</tt> – <span data-i18n="help_macros_16">the Character's name</span></li> | 22 | <li><tt>{{char}}</tt> – <span data-i18n="help_macros_16">the Character's name</span></li> |
| 23 | <li><tt>{{char_version}}</tt> – <span data-i18n="help_macros_17">the Character's version number</span></li> | 23 | <li><tt>{{version}}</tt> – <span data-i18n="help_macros_17">the Character's version number</span></li> |
| 24 | <li><tt>{{charDepthPrompt}}</tt> – <span data-i18n="help_macros_charDepthPrompt">the Character's @ Depth Note</span></li> | ||
| 24 | <li><tt>{{group}}</tt> – <span data-i18n="help_macros_18">a comma-separated list of group member names (including muted) or the character name in solo chats. Alias: {{charIfNotGroup}}</span></li> | 25 | <li><tt>{{group}}</tt> – <span data-i18n="help_macros_18">a comma-separated list of group member names (including muted) or the character name in solo chats. Alias: {{charIfNotGroup}}</span></li> |
| 25 | <li><tt>{{groupNotMuted}}</tt> – <span data-i18n="help_groupNotMuted">the same as {{group}}, but excludes muted members</span></li> | 26 | <li><tt>{{groupNotMuted}}</tt> – <span data-i18n="help_groupNotMuted">the same as {{group}}, but excludes muted members</span></li> |
| 26 | <li><tt>{{model}}</tt> – <span data-i18n="help_macros_19">a text generation model name for the currently selected API. </span><b data-i18n="Can be inaccurate!">Can be inaccurate!</b></li> | 27 | <li><tt>{{model}}</tt> – <span data-i18n="help_macros_19">a text generation model name for the currently selected API. </span><b data-i18n="Can be inaccurate!">Can be inaccurate!</b></li> |
| @@ -1,4 +0,0 @@ | |||
| 1 | <div class="row"> | ||
| 2 | <a class="export-promptmanager-prompts-character list-group-item" data-i18n="Export for character">Export for character</a> | ||
| 3 | <span class="tooltip fa-solid fa-info-circle" data-i18n="[title]Export prompts for this character, including their order." title="Export prompts for this character, including their order."></span> | ||
| 4 | </div> | ||
| @@ -1,12 +0,0 @@ | |||
| 1 | <div id="prompt-manager-export-format-popup" class="list-group"> | ||
| 2 | <div class="prompt-manager-export-format-popup-flex"> | ||
| 3 | <div class="row"> | ||
| 4 | <a class="export-promptmanager-prompts-full list-group-item" data-i18n="Export all">Export all</a> | ||
| 5 | <span class="tooltip fa-solid fa-info-circle" data-i18n="[title]Export all your prompts to a file" title="Export all your prompts to a file"></span> | ||
| 6 | </div> | ||
| 7 | {{#if isGlobalStrategy}} | ||
| 8 | {{else}} | ||
| 9 | {{{exportForCharacter}}} | ||
| 10 | {{/if}} | ||
| 11 | </div> | ||
| 12 | </div> | ||
| @@ -0,0 +1,18 @@ | |||
| 1 | <div class="title_restorable flexFlowColumn alignItemsBaseline"> | ||
| 2 | <div class="flex-container justifyCenter"> | ||
| 3 | <h3 data-i18n="Sampler Select">Sampler Select</h3> | ||
| 4 | <div class="flex-container alignItemsBaseline"> | ||
| 5 | <div id="resetSelectedSamplers" class="menu_button menu_button_icon" data-i18n="[title]Reset custom sampler selection" title="Reset custom sampler selection"> | ||
| 6 | <i class="fa-solid fa-recycle"></i> | ||
| 7 | </div> | ||
| 8 | </div> | ||
| 9 | <!--<div class="flex-container alignItemsBaseline"> | ||
| 10 | <div class="menu_button menu_button_icon" title="Create a new sampler"> | ||
| 11 | <i class="fa-solid fa-plus"></i> | ||
| 12 | <span data-i18n="Create">Create</span> | ||
| 13 | </div> | ||
| 14 | </div>--> | ||
| 15 | </div> | ||
| 16 | <small data-i18n="Here you can toggle the display of individual samplers. (WIP)">Here you can toggle the display of individual samplers. (WIP)</small> | ||
| 17 | </div> | ||
| 18 | <hr> | ||
| \ No newline at end of file | 18 | \ No newline at end of file | |
| @@ -1,4 +1,4 @@ | |||
| 1 | <div id="WIEntryHeaderTitlesPC" class="flex-container wide100p spaceBetween justifyCenter textAlignCenter" style="padding:0 4.5em;"> | 1 | <div id="WIEntryHeaderTitlesPC" class="flex-container wide100p spaceBetween justifyCenter textAlignCenter" style="padding:0 7.0em;"> |
| 2 | <small class="flex1" data-i18n="Title/Memo">Title/Memo</small> | 2 | <small class="flex1" data-i18n="Title/Memo">Title/Memo</small> |
| 3 | <small style="width: calc(3.5em + 10px)" data-i18n="Strategy">Strategy</small> | 3 | <small style="width: calc(3.5em + 10px)" data-i18n="Strategy">Strategy</small> |
| 4 | <small style="width: calc(3.5em + 20px)" data-i18n="Position">Position</small> | 4 | <small style="width: calc(3.5em + 20px)" data-i18n="Position">Position</small> |
| @@ -58,6 +58,8 @@ const OPENROUTER_PROVIDERS = [ | |||
| 58 | 'Minimax', | 58 | 'Minimax', |
| 59 | 'Nineteen', | 59 | 'Nineteen', |
| 60 | 'Liquid', | 60 | 'Liquid', |
| 61 | 'Stealth', | ||
| 62 | 'NCompass', | ||
| 61 | 'InferenceNet', | 63 | 'InferenceNet', |
| 62 | 'Friendli', | 64 | 'Friendli', |
| 63 | 'AionLabs', | 65 | 'AionLabs', |
| @@ -69,6 +71,9 @@ const OPENROUTER_PROVIDERS = [ | |||
| 69 | 'Targon', | 71 | 'Targon', |
| 70 | 'Ubicloud', | 72 | 'Ubicloud', |
| 71 | 'Parasail', | 73 | 'Parasail', |
| 74 | 'Phala', | ||
| 75 | 'Cent-ML', | ||
| 76 | 'Venice', | ||
| 72 | '01.AI', | 77 | '01.AI', |
| 73 | 'HuggingFace', | 78 | 'HuggingFace', |
| 74 | 'Mancer', | 79 | 'Mancer', |
| @@ -923,6 +928,10 @@ export function getCurrentDreamGenModelTokenizer() { | |||
| 923 | return tokenizers.YI; | 928 | return tokenizers.YI; |
| 924 | } else if (model.id.startsWith('opus-v1-xl')) { | 929 | } else if (model.id.startsWith('opus-v1-xl')) { |
| 925 | return tokenizers.LLAMA; | 930 | return tokenizers.LLAMA; |
| 931 | } else if (model.id.startsWith('lucid-v1-medium')) { | ||
| 932 | return tokenizers.NEMO; | ||
| 933 | } else if (model.id.startsWith('lucid-v1-extra-large')) { | ||
| 934 | return tokenizers.LLAMA3; | ||
| 926 | } else { | 935 | } else { |
| 927 | return tokenizers.MISTRAL; | 936 | return tokenizers.MISTRAL; |
| 928 | } | 937 | } |
| @@ -86,7 +86,7 @@ const OOBA_DEFAULT_ORDER = [ | |||
| 86 | 'encoder_repetition_penalty', | 86 | 'encoder_repetition_penalty', |
| 87 | 'no_repeat_ngram', | 87 | 'no_repeat_ngram', |
| 88 | ]; | 88 | ]; |
| 89 | const APHRODITE_DEFAULT_ORDER = [ | 89 | export const APHRODITE_DEFAULT_ORDER = [ |
| 90 | 'dry', | 90 | 'dry', |
| 91 | 'penalties', | 91 | 'penalties', |
| 92 | 'no_repeat_ngram', | 92 | 'no_repeat_ngram', |
| @@ -729,15 +729,6 @@ export function getTokenizerModel() { | |||
| 729 | return yiTokenizer; | 729 | return yiTokenizer; |
| 730 | } | 730 | } |
| 731 | 731 | ||
| 732 | if (oai_settings.chat_completion_source === chat_completion_sources.BLOCKENTROPY) { | ||
| 733 | if (oai_settings.blockentropy_model.includes('llama3')) { | ||
| 734 | return llama3Tokenizer; | ||
| 735 | } | ||
| 736 | if (oai_settings.blockentropy_model.includes('miqu') || oai_settings.blockentropy_model.includes('mixtral')) { | ||
| 737 | return mistralTokenizer; | ||
| 738 | } | ||
| 739 | } | ||
| 740 | |||
| 741 | // Default to Turbo 3.5 | 732 | // Default to Turbo 3.5 |
| 742 | return turboTokenizer; | 733 | return turboTokenizer; |
| 743 | } | 734 | } |
| @@ -586,6 +586,7 @@ export class ToolManager { | |||
| 586 | chat_completion_sources.DEEPSEEK, | 586 | chat_completion_sources.DEEPSEEK, |
| 587 | chat_completion_sources.MAKERSUITE, | 587 | chat_completion_sources.MAKERSUITE, |
| 588 | chat_completion_sources.AI21, | 588 | chat_completion_sources.AI21, |
| 589 | chat_completion_sources.XAI, | ||
| 589 | ]; | 590 | ]; |
| 590 | return supportedSources.includes(oai_settings.chat_completion_source); | 591 | return supportedSources.includes(oai_settings.chat_completion_source); |
| 591 | } | 592 | } |
| @@ -9,8 +9,8 @@ import { ensureImageFormatSupported, getBase64Async, humanFileSize } from './uti | |||
| 9 | export let currentUser = null; | 9 | export let currentUser = null; |
| 10 | export let accountsEnabled = false; | 10 | export let accountsEnabled = false; |
| 11 | 11 | ||
| 12 | // Extend the session every 30 minutes | 12 | // Extend the session every 10 minutes |
| 13 | const SESSION_EXTEND_INTERVAL = 30 * 60 * 1000; | 13 | const SESSION_EXTEND_INTERVAL = 10 * 60 * 1000; |
| 14 | 14 | ||
| 15 | /** | 15 | /** |
| 16 | * Enable or disable user account controls in the UI. | 16 | * Enable or disable user account controls in the UI. |
| @@ -1437,6 +1437,8 @@ export async function ensureImageFormatSupported(file) { | |||
| 1437 | 'image/tiff', | 1437 | 'image/tiff', |
| 1438 | 'image/gif', | 1438 | 'image/gif', |
| 1439 | 'image/apng', | 1439 | 'image/apng', |
| 1440 | 'image/webp', | ||
| 1441 | 'image/avif', | ||
| 1440 | ]; | 1442 | ]; |
| 1441 | 1443 | ||
| 1442 | if (supportedTypes.includes(file.type) || !file.type.startsWith('image/')) { | 1444 | if (supportedTypes.includes(file.type) || !file.type.startsWith('image/')) { |
| @@ -9,7 +9,7 @@ import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js'; | |||
| 9 | import { SlashCommandClosureResult } from './slash-commands/SlashCommandClosureResult.js'; | 9 | import { SlashCommandClosureResult } from './slash-commands/SlashCommandClosureResult.js'; |
| 10 | import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js'; | 10 | import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js'; |
| 11 | import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js'; | 11 | import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js'; |
| 12 | import { PARSER_FLAG, SlashCommandParser } from './slash-commands/SlashCommandParser.js'; | 12 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; |
| 13 | import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHelper.js'; | 13 | import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHelper.js'; |
| 14 | import { SlashCommandScope } from './slash-commands/SlashCommandScope.js'; | 14 | import { SlashCommandScope } from './slash-commands/SlashCommandScope.js'; |
| 15 | import { isFalseBoolean, convertValueType, isTrueBoolean } from './utils.js'; | 15 | import { isFalseBoolean, convertValueType, isTrueBoolean } from './utils.js'; |
| @@ -583,7 +583,7 @@ export function evalBoolean(rule, a, b) { | |||
| 583 | * Executes a slash command from a string (may be enclosed in quotes) and returns the result. | 583 | * Executes a slash command from a string (may be enclosed in quotes) and returns the result. |
| 584 | * @param {string} command Command to execute. May contain escaped macro and batch separators. | 584 | * @param {string} command Command to execute. May contain escaped macro and batch separators. |
| 585 | * @param {SlashCommandScope} [scope] The scope to use. | 585 | * @param {SlashCommandScope} [scope] The scope to use. |
| 586 | * @param {{[id:PARSER_FLAG]:boolean}} [parserFlags] The parser flags to use. | 586 | * @param {import('./slash-commands/SlashCommandParser.js').ParserFlags} [parserFlags] The parser flags to use. |
| 587 | * @param {SlashCommandAbortController} [abortController] The abort controller to use. | 587 | * @param {SlashCommandAbortController} [abortController] The abort controller to use. |
| 588 | * @returns {Promise<SlashCommandClosureResult>} Closure execution result | 588 | * @returns {Promise<SlashCommandClosureResult>} Closure execution result |
| 589 | */ | 589 | */ |
| @@ -1,7 +1,7 @@ | |||
| 1 | import { Fuse } from '../lib.js'; | 1 | import { Fuse } from '../lib.js'; |
| 2 | 2 | ||
| 3 | import { saveSettings, callPopup, substituteParams, getRequestHeaders, chat_metadata, this_chid, characters, saveCharacterDebounced, menu_type, eventSource, event_types, getExtensionPromptByName, saveMetadata, getCurrentChatId, extension_prompt_roles } from '../script.js'; | 3 | import { saveSettings, substituteParams, getRequestHeaders, chat_metadata, this_chid, characters, saveCharacterDebounced, menu_type, eventSource, event_types, getExtensionPromptByName, saveMetadata, getCurrentChatId, extension_prompt_roles } from '../script.js'; |
| 4 | import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option, waitUntilCondition, isTrueBoolean, setValueByPath, flashHighlight, select2ModifyOptions, getSelect2OptionId, dynamicSelect2DataViaAjax, highlightRegex, select2ChoiceClickSubscribe, isFalseBoolean, getSanitizedFilename, checkOverwriteExistingData, getStringHash, parseStringArray, cancelDebounce, findChar, onlyUnique } from './utils.js'; | 4 | import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option, waitUntilCondition, isTrueBoolean, setValueByPath, flashHighlight, select2ModifyOptions, getSelect2OptionId, dynamicSelect2DataViaAjax, highlightRegex, select2ChoiceClickSubscribe, isFalseBoolean, getSanitizedFilename, checkOverwriteExistingData, getStringHash, parseStringArray, cancelDebounce, findChar, onlyUnique, equalsIgnoreCaseAndAccents } from './utils.js'; |
| 5 | import { extension_settings, getContext } from './extensions.js'; | 5 | import { extension_settings, getContext } from './extensions.js'; |
| 6 | import { NOTE_MODULE_NAME, metadata_keys, shouldWIAddPrompt } from './authors-note.js'; | 6 | import { NOTE_MODULE_NAME, metadata_keys, shouldWIAddPrompt } from './authors-note.js'; |
| 7 | import { isMobile } from './RossAscends-mods.js'; | 7 | import { isMobile } from './RossAscends-mods.js'; |
| @@ -753,10 +753,17 @@ export const worldInfoCache = new StructuredCloneMap({ cloneOnGet: true, cloneOn | |||
| 753 | 753 | ||
| 754 | /** | 754 | /** |
| 755 | * Gets the world info based on chat messages. | 755 | * Gets the world info based on chat messages. |
| 756 | * @param {string[]} chat The chat messages to scan, in reverse order. | 756 | * @param {string[]} chat - The chat messages to scan, in reverse order. |
| 757 | * @param {number} maxContext The maximum context size of the generation. | 757 | * @param {number} maxContext - The maximum context size of the generation. |
| 758 | * @param {boolean} isDryRun If true, the function will not emit any events. | 758 | * @param {boolean} isDryRun - If true, the function will not emit any events. |
| 759 | * @typedef {{worldInfoString: string, worldInfoBefore: string, worldInfoAfter: string, worldInfoExamples: any[], worldInfoDepth: any[]}} WIPromptResult | 759 | * @typedef {object} WIPromptResult |
| 760 | * @property {string} worldInfoString - Complete world info string | ||
| 761 | * @property {string} worldInfoBefore - World info that goes before the prompt | ||
| 762 | * @property {string} worldInfoAfter - World info that goes after the prompt | ||
| 763 | * @property {Array} worldInfoExamples - Array of example entries | ||
| 764 | * @property {Array} worldInfoDepth - Array of depth entries | ||
| 765 | * @property {Array} anBefore - Array of entries before Author's Note | ||
| 766 | * @property {Array} anAfter - Array of entries after Author's Note | ||
| 760 | * @returns {Promise<WIPromptResult>} The world info string and depth. | 767 | * @returns {Promise<WIPromptResult>} The world info string and depth. |
| 761 | */ | 768 | */ |
| 762 | export async function getWorldInfoPrompt(chat, maxContext, isDryRun) { | 769 | export async function getWorldInfoPrompt(chat, maxContext, isDryRun) { |
| @@ -778,6 +785,8 @@ export async function getWorldInfoPrompt(chat, maxContext, isDryRun) { | |||
| 778 | worldInfoAfter, | 785 | worldInfoAfter, |
| 779 | worldInfoExamples: activatedWorldInfo.EMEntries ?? [], | 786 | worldInfoExamples: activatedWorldInfo.EMEntries ?? [], |
| 780 | worldInfoDepth: activatedWorldInfo.WIDepthEntries ?? [], | 787 | worldInfoDepth: activatedWorldInfo.WIDepthEntries ?? [], |
| 788 | anBefore: activatedWorldInfo.ANBeforeEntries ?? [], | ||
| 789 | anAfter: activatedWorldInfo.ANAfterEntries ?? [], | ||
| 781 | }; | 790 | }; |
| 782 | } | 791 | } |
| 783 | 792 | ||
| @@ -899,20 +908,20 @@ export function setWorldInfoSettings(settings, data) { | |||
| 899 | registerWorldInfoSlashCommands(); | 908 | registerWorldInfoSlashCommands(); |
| 900 | } | 909 | } |
| 901 | 910 | ||
| 902 | function registerWorldInfoSlashCommands() { | 911 | /** |
| 903 | /** | 912 | * Reloads the editor with the specified world info file |
| 904 | * Reloads the editor with the specified world info file | 913 | * @param {string} file - The file to load in the editor |
| 905 | * @param {string} file - The file to load in the editor | 914 | * @param {boolean} [loadIfNotSelected=false] - Indicates whether to load the file even if it's not currently selected |
| 906 | * @param {boolean} [loadIfNotSelected=false] - Indicates whether to load the file even if it's not currently selected | 915 | */ |
| 907 | */ | 916 | export function reloadEditor(file, loadIfNotSelected = false) { |
| 908 | function reloadEditor(file, loadIfNotSelected = false) { | 917 | const currentIndex = Number($('#world_editor_select').val()); |
| 909 | const currentIndex = Number($('#world_editor_select').val()); | 918 | const selectedIndex = world_names.indexOf(file); |
| 910 | const selectedIndex = world_names.indexOf(file); | 919 | if (selectedIndex !== -1 && (loadIfNotSelected || currentIndex === selectedIndex)) { |
| 911 | if (selectedIndex !== -1 && (loadIfNotSelected || currentIndex === selectedIndex)) { | 920 | $('#world_editor_select').val(selectedIndex).trigger('change'); |
| 912 | $('#world_editor_select').val(selectedIndex).trigger('change'); | ||
| 913 | } | ||
| 914 | } | 921 | } |
| 922 | } | ||
| 915 | 923 | ||
| 924 | function registerWorldInfoSlashCommands() { | ||
| 916 | /** | 925 | /** |
| 917 | * Gets a *rough* approximation of the current chat context. | 926 | * Gets a *rough* approximation of the current chat context. |
| 918 | * Normally, it is provided externally by the prompt builder. | 927 | * Normally, it is provided externally by the prompt builder. |
| @@ -1329,6 +1338,18 @@ function registerWorldInfoSlashCommands() { | |||
| 1329 | } | 1338 | } |
| 1330 | } | 1339 | } |
| 1331 | 1340 | ||
| 1341 | async function getGlobalBooksCallback() { | ||
| 1342 | if (!selected_world_info?.length) { | ||
| 1343 | return JSON.stringify([]); | ||
| 1344 | } | ||
| 1345 | |||
| 1346 | let entries = selected_world_info.slice(); | ||
| 1347 | |||
| 1348 | console.debug(`[WI] Selected global world info has ${entries.length} entries`, selected_world_info); | ||
| 1349 | |||
| 1350 | return JSON.stringify(entries); | ||
| 1351 | } | ||
| 1352 | |||
| 1332 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | 1353 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| 1333 | name: 'world', | 1354 | name: 'world', |
| 1334 | callback: onWorldInfoChange, | 1355 | callback: onWorldInfoChange, |
| @@ -1371,6 +1392,13 @@ function registerWorldInfoSlashCommands() { | |||
| 1371 | aliases: ['getchatlore', 'getchatwi'], | 1392 | aliases: ['getchatlore', 'getchatwi'], |
| 1372 | })); | 1393 | })); |
| 1373 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | 1394 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| 1395 | name: 'getglobalbooks', | ||
| 1396 | callback: getGlobalBooksCallback, | ||
| 1397 | returns: 'list of selected lorebook names', | ||
| 1398 | helpString: 'Get a list of names of the selected global lorebooks and pass it down the pipe.', | ||
| 1399 | aliases: ['getgloballore', 'getglobalwi'], | ||
| 1400 | })); | ||
| 1401 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | ||
| 1374 | name: 'getpersonabook', | 1402 | name: 'getpersonabook', |
| 1375 | callback: getPersonaBookCallback, | 1403 | callback: getPersonaBookCallback, |
| 1376 | returns: 'lorebook name', | 1404 | returns: 'lorebook name', |
| @@ -2199,7 +2227,7 @@ function verifyWorldInfoSearchSortRule() { | |||
| 2199 | * Use `originalWIDataKeyMap` to find the correct value to be set. | 2227 | * Use `originalWIDataKeyMap` to find the correct value to be set. |
| 2200 | * | 2228 | * |
| 2201 | * @param {object} data - The data object containing the original data entries. | 2229 | * @param {object} data - The data object containing the original data entries. |
| 2202 | * @param {string} uid - The unique identifier of the data entry. | 2230 | * @param {number} uid - The unique identifier of the data entry. |
| 2203 | * @param {string} key - The key of the value to be set. | 2231 | * @param {string} key - The key of the value to be set. |
| 2204 | * @param {any} value - The value to be set. | 2232 | * @param {any} value - The value to be set. |
| 2205 | */ | 2233 | */ |
| @@ -2223,7 +2251,9 @@ export function setWIOriginalDataValue(data, uid, key, value) { | |||
| 2223 | */ | 2251 | */ |
| 2224 | export function deleteWIOriginalDataValue(data, uid) { | 2252 | export function deleteWIOriginalDataValue(data, uid) { |
| 2225 | if (data.originalData && Array.isArray(data.originalData.entries)) { | 2253 | if (data.originalData && Array.isArray(data.originalData.entries)) { |
| 2226 | const originalIndex = data.originalData.entries.findIndex(x => x.uid === uid); | 2254 | // Non-strict equality is used here to allow for both string and number comparisons |
| 2255 | // @eslint-disable-next-line eqeqeq | ||
| 2256 | const originalIndex = data.originalData.entries.findIndex(x => x.uid == uid); | ||
| 2227 | 2257 | ||
| 2228 | if (originalIndex >= 0) { | 2258 | if (originalIndex >= 0) { |
| 2229 | data.originalData.entries.splice(originalIndex, 1); | 2259 | data.originalData.entries.splice(originalIndex, 1); |
| @@ -2671,8 +2701,10 @@ export async function getWorldEntry(name, data, entry) { | |||
| 2671 | $(counter).text(numberOfTokens); | 2701 | $(counter).text(numberOfTokens); |
| 2672 | }, debounce_timeout.relaxed); | 2702 | }, debounce_timeout.relaxed); |
| 2673 | 2703 | ||
| 2704 | const contentInputId = `world_entry_content_${entry.uid}`; | ||
| 2674 | const contentInput = template.find('textarea[name="content"]'); | 2705 | const contentInput = template.find('textarea[name="content"]'); |
| 2675 | contentInput.data('uid', entry.uid); | 2706 | contentInput.data('uid', entry.uid); |
| 2707 | contentInput.attr('id', contentInputId); | ||
| 2676 | contentInput.on('input', async function (_, { skipCount } = {}) { | 2708 | contentInput.on('input', async function (_, { skipCount } = {}) { |
| 2677 | const uid = $(this).data('uid'); | 2709 | const uid = $(this).data('uid'); |
| 2678 | const value = $(this).val(); | 2710 | const value = $(this).val(); |
| @@ -2689,7 +2721,9 @@ export async function getWorldEntry(name, data, entry) { | |||
| 2689 | countTokensDebounced(counter, value); | 2721 | countTokensDebounced(counter, value); |
| 2690 | }); | 2722 | }); |
| 2691 | contentInput.val(entry.content).trigger('input', { skipCount: true }); | 2723 | contentInput.val(entry.content).trigger('input', { skipCount: true }); |
| 2692 | //initScrollHeight(contentInput); | 2724 | |
| 2725 | const contentExpandButton = template.find('.editor_maximize'); | ||
| 2726 | contentExpandButton.attr('data-for', contentInputId); | ||
| 2693 | 2727 | ||
| 2694 | template.find('.inline-drawer-toggle').on('click', function () { | 2728 | template.find('.inline-drawer-toggle').on('click', function () { |
| 2695 | if (counter.data('first-run')) { | 2729 | if (counter.data('first-run')) { |
| @@ -3130,6 +3164,84 @@ export async function getWorldEntry(name, data, entry) { | |||
| 3130 | updateEditor(navigation_option.previous); | 3164 | updateEditor(navigation_option.previous); |
| 3131 | }); | 3165 | }); |
| 3132 | 3166 | ||
| 3167 | // move button | ||
| 3168 | const moveButton = template.find('.move_entry_button'); | ||
| 3169 | moveButton.attr('data-uid', entry.uid); | ||
| 3170 | moveButton.attr('data-current-world', name); | ||
| 3171 | moveButton.on('click', async function (e) { | ||
| 3172 | e.stopPropagation(); | ||
| 3173 | const sourceUid = $(this).attr('data-uid'); | ||
| 3174 | const sourceWorld = $(this).attr('data-current-world'); | ||
| 3175 | const sourceWorldInfo = await loadWorldInfo(sourceWorld); | ||
| 3176 | if (!sourceWorldInfo) { | ||
| 3177 | return; | ||
| 3178 | } | ||
| 3179 | const sourceName = sourceWorldInfo.entries[sourceUid]?.comment; | ||
| 3180 | if (sourceName === undefined) { | ||
| 3181 | return; | ||
| 3182 | } | ||
| 3183 | |||
| 3184 | const select = document.createElement('select'); | ||
| 3185 | select.id = 'move_entry_target_select'; | ||
| 3186 | select.classList.add('text_pole', 'wide100p', 'marginTop10'); | ||
| 3187 | |||
| 3188 | const defaultOption = document.createElement('option'); | ||
| 3189 | defaultOption.value = ''; | ||
| 3190 | defaultOption.textContent = `-- ${t`Select Target Lorebook`} --`; | ||
| 3191 | select.appendChild(defaultOption); | ||
| 3192 | |||
| 3193 | let selectableWorldCount = 0; | ||
| 3194 | world_names.forEach(worldName => { | ||
| 3195 | if (worldName !== sourceWorld) { // Exclude current world | ||
| 3196 | const option = document.createElement('option'); | ||
| 3197 | option.value = world_names.indexOf(worldName).toString(); | ||
| 3198 | option.textContent = worldName; | ||
| 3199 | select.appendChild(option); | ||
| 3200 | selectableWorldCount++; | ||
| 3201 | } | ||
| 3202 | }); | ||
| 3203 | |||
| 3204 | if (selectableWorldCount === 0) { | ||
Diff truncated