Compare commits
5 Commits
v0.1.97-wi
...
v0.2.1-win
| Author | SHA1 | Date | |
|---|---|---|---|
| beae0942a1 | |||
| 6b49981b3a | |||
| b46b392a9a | |||
| 4889dd974f | |||
| b6fd8a557e |
@@ -5,11 +5,13 @@ on:
|
|||||||
branches: [main]
|
branches: [main]
|
||||||
paths:
|
paths:
|
||||||
- "app/**"
|
- "app/**"
|
||||||
|
- "VERSION"
|
||||||
- ".gitea/workflows/build-app.yml"
|
- ".gitea/workflows/build-app.yml"
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
paths:
|
paths:
|
||||||
- "app/**"
|
- "app/**"
|
||||||
|
- "VERSION"
|
||||||
- ".gitea/workflows/build-app.yml"
|
- ".gitea/workflows/build-app.yml"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
@@ -18,10 +20,43 @@ env:
|
|||||||
REPO: ${{ gitea.repository }}
|
REPO: ${{ gitea.repository }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-linux:
|
compute-version:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
version: ${{ steps.version.outputs.VERSION }}
|
version: ${{ steps.version.outputs.VERSION }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Fetch all tags
|
||||||
|
run: git fetch --tags
|
||||||
|
|
||||||
|
- name: Compute version from VERSION file and tags
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
MAJOR_MINOR=$(cat VERSION | tr -d '[:space:]')
|
||||||
|
echo "Major.Minor: ${MAJOR_MINOR}"
|
||||||
|
|
||||||
|
# Find the latest tag matching v{MAJOR_MINOR}.N (exclude -mac, -win suffixes)
|
||||||
|
LATEST_TAG=$(git tag -l "v${MAJOR_MINOR}.*" --sort=-v:refname | grep -E "^v${MAJOR_MINOR}\.[0-9]+$" | head -1)
|
||||||
|
|
||||||
|
if [ -n "$LATEST_TAG" ]; then
|
||||||
|
echo "Latest matching tag: ${LATEST_TAG}"
|
||||||
|
PATCH=$(git rev-list --count "${LATEST_TAG}..HEAD")
|
||||||
|
else
|
||||||
|
echo "No matching tag found for v${MAJOR_MINOR}.*, using total commit count"
|
||||||
|
PATCH=$(git rev-list --count HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION="${MAJOR_MINOR}.${PATCH}"
|
||||||
|
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
echo "Computed version: ${VERSION}"
|
||||||
|
|
||||||
|
build-linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [compute-version]
|
||||||
steps:
|
steps:
|
||||||
- name: Install Node.js 22
|
- name: Install Node.js 22
|
||||||
run: |
|
run: |
|
||||||
@@ -54,17 +89,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Compute version
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
COMMIT_COUNT=$(git rev-list --count HEAD)
|
|
||||||
VERSION="0.1.${COMMIT_COUNT}"
|
|
||||||
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
|
|
||||||
echo "Computed version: ${VERSION}"
|
|
||||||
|
|
||||||
- name: Set app version
|
- name: Set app version
|
||||||
run: |
|
run: |
|
||||||
VERSION="${{ steps.version.outputs.VERSION }}"
|
VERSION="${{ needs.compute-version.outputs.version }}"
|
||||||
sed -i "s/\"version\": \".*\"/\"version\": \"${VERSION}\"/" app/src-tauri/tauri.conf.json
|
sed -i "s/\"version\": \".*\"/\"version\": \"${VERSION}\"/" app/src-tauri/tauri.conf.json
|
||||||
sed -i "s/\"version\": \".*\"/\"version\": \"${VERSION}\"/" app/package.json
|
sed -i "s/\"version\": \".*\"/\"version\": \"${VERSION}\"/" app/package.json
|
||||||
sed -i "s/^version = \".*\"/version = \"${VERSION}\"/" app/src-tauri/Cargo.toml
|
sed -i "s/^version = \".*\"/version = \"${VERSION}\"/" app/src-tauri/Cargo.toml
|
||||||
@@ -133,7 +160,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
TAG="v${{ steps.version.outputs.VERSION }}"
|
TAG="v${{ needs.compute-version.outputs.version }}"
|
||||||
# Create release
|
# Create release
|
||||||
curl -s -X POST \
|
curl -s -X POST \
|
||||||
-H "Authorization: token ${TOKEN}" \
|
-H "Authorization: token ${TOKEN}" \
|
||||||
@@ -156,6 +183,7 @@ jobs:
|
|||||||
|
|
||||||
build-macos:
|
build-macos:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
|
needs: [compute-version]
|
||||||
steps:
|
steps:
|
||||||
- name: Install Node.js 22
|
- name: Install Node.js 22
|
||||||
run: |
|
run: |
|
||||||
@@ -183,17 +211,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Compute version
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
COMMIT_COUNT=$(git rev-list --count HEAD)
|
|
||||||
VERSION="0.1.${COMMIT_COUNT}"
|
|
||||||
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
|
|
||||||
echo "Computed version: ${VERSION}"
|
|
||||||
|
|
||||||
- name: Set app version
|
- name: Set app version
|
||||||
run: |
|
run: |
|
||||||
VERSION="${{ steps.version.outputs.VERSION }}"
|
VERSION="${{ needs.compute-version.outputs.version }}"
|
||||||
sed -i '' "s/\"version\": \".*\"/\"version\": \"${VERSION}\"/" app/src-tauri/tauri.conf.json
|
sed -i '' "s/\"version\": \".*\"/\"version\": \"${VERSION}\"/" app/src-tauri/tauri.conf.json
|
||||||
sed -i '' "s/\"version\": \".*\"/\"version\": \"${VERSION}\"/" app/package.json
|
sed -i '' "s/\"version\": \".*\"/\"version\": \"${VERSION}\"/" app/package.json
|
||||||
sed -i '' "s/^version = \".*\"/version = \"${VERSION}\"/" app/src-tauri/Cargo.toml
|
sed -i '' "s/^version = \".*\"/version = \"${VERSION}\"/" app/src-tauri/Cargo.toml
|
||||||
@@ -243,12 +263,12 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
TAG="v${{ steps.version.outputs.VERSION }}-mac"
|
TAG="v${{ needs.compute-version.outputs.version }}-mac"
|
||||||
# Create release
|
# Create release
|
||||||
curl -s -X POST \
|
curl -s -X POST \
|
||||||
-H "Authorization: token ${TOKEN}" \
|
-H "Authorization: token ${TOKEN}" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "{\"tag_name\": \"${TAG}\", \"name\": \"Triple-C v${{ steps.version.outputs.VERSION }} (macOS)\", \"body\": \"Automated build from commit ${{ gitea.sha }}\"}" \
|
-d "{\"tag_name\": \"${TAG}\", \"name\": \"Triple-C v${{ needs.compute-version.outputs.version }} (macOS)\", \"body\": \"Automated build from commit ${{ gitea.sha }}\"}" \
|
||||||
"${GITEA_URL}/api/v1/repos/${REPO}/releases" > release.json
|
"${GITEA_URL}/api/v1/repos/${REPO}/releases" > release.json
|
||||||
RELEASE_ID=$(cat release.json | grep -o '"id":[0-9]*' | head -1 | grep -o '[0-9]*')
|
RELEASE_ID=$(cat release.json | grep -o '"id":[0-9]*' | head -1 | grep -o '[0-9]*')
|
||||||
echo "Release ID: ${RELEASE_ID}"
|
echo "Release ID: ${RELEASE_ID}"
|
||||||
@@ -266,6 +286,7 @@ jobs:
|
|||||||
|
|
||||||
build-windows:
|
build-windows:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
needs: [compute-version]
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: cmd
|
shell: cmd
|
||||||
@@ -275,18 +296,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Compute version
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
for /f %%i in ('git rev-list --count HEAD') do set "COMMIT_COUNT=%%i"
|
|
||||||
set "VERSION=0.1.%COMMIT_COUNT%"
|
|
||||||
echo VERSION=%VERSION%>> %GITHUB_OUTPUT%
|
|
||||||
echo Computed version: %VERSION%
|
|
||||||
|
|
||||||
- name: Set app version
|
- name: Set app version
|
||||||
shell: powershell
|
shell: powershell
|
||||||
run: |
|
run: |
|
||||||
$version = "${{ steps.version.outputs.VERSION }}"
|
$version = "${{ needs.compute-version.outputs.version }}"
|
||||||
(Get-Content app/src-tauri/tauri.conf.json) -replace '"version": ".*?"', "`"version`": `"$version`"" | Set-Content app/src-tauri/tauri.conf.json
|
(Get-Content app/src-tauri/tauri.conf.json) -replace '"version": ".*?"', "`"version`": `"$version`"" | Set-Content app/src-tauri/tauri.conf.json
|
||||||
(Get-Content app/package.json) -replace '"version": ".*?"', "`"version`": `"$version`"" | Set-Content app/package.json
|
(Get-Content app/package.json) -replace '"version": ".*?"', "`"version`": `"$version`"" | Set-Content app/package.json
|
||||||
(Get-Content app/src-tauri/Cargo.toml) -replace '^version = ".*?"', "version = `"$version`"" | Set-Content app/src-tauri/Cargo.toml
|
(Get-Content app/src-tauri/Cargo.toml) -replace '^version = ".*?"', "version = `"$version`"" | Set-Content app/src-tauri/Cargo.toml
|
||||||
@@ -367,9 +380,9 @@ jobs:
|
|||||||
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
COMMIT_SHA: ${{ gitea.sha }}
|
COMMIT_SHA: ${{ gitea.sha }}
|
||||||
run: |
|
run: |
|
||||||
set "TAG=v${{ steps.version.outputs.VERSION }}-win"
|
set "TAG=v${{ needs.compute-version.outputs.version }}-win"
|
||||||
echo Creating release %TAG%...
|
echo Creating release %TAG%...
|
||||||
curl -s -X POST -H "Authorization: token %TOKEN%" -H "Content-Type: application/json" -d "{\"tag_name\": \"%TAG%\", \"name\": \"Triple-C v${{ steps.version.outputs.VERSION }} (Windows)\", \"body\": \"Automated build from commit %COMMIT_SHA%\"}" "%GITEA_URL%/api/v1/repos/%REPO%/releases" > release.json
|
curl -s -X POST -H "Authorization: token %TOKEN%" -H "Content-Type: application/json" -d "{\"tag_name\": \"%TAG%\", \"name\": \"Triple-C v${{ needs.compute-version.outputs.version }} (Windows)\", \"body\": \"Automated build from commit %COMMIT_SHA%\"}" "%GITEA_URL%/api/v1/repos/%REPO%/releases" > release.json
|
||||||
for /f "tokens=2 delims=:," %%a in ('findstr /c:"\"id\"" release.json') do set "RELEASE_ID=%%a" & goto :found
|
for /f "tokens=2 delims=:," %%a in ('findstr /c:"\"id\"" release.json') do set "RELEASE_ID=%%a" & goto :found
|
||||||
:found
|
:found
|
||||||
echo Release ID: %RELEASE_ID%
|
echo Release ID: %RELEASE_ID%
|
||||||
@@ -378,9 +391,36 @@ jobs:
|
|||||||
curl -s -X POST -H "Authorization: token %TOKEN%" -H "Content-Type: application/octet-stream" --data-binary "@%%f" "%GITEA_URL%/api/v1/repos/%REPO%/releases/%RELEASE_ID%/assets?name=%%~nxf"
|
curl -s -X POST -H "Authorization: token %TOKEN%" -H "Content-Type: application/octet-stream" --data-binary "@%%f" "%GITEA_URL%/api/v1/repos/%REPO%/releases/%RELEASE_ID%/assets?name=%%~nxf"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
create-tag:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [compute-version, build-linux, build-macos, build-windows]
|
||||||
|
if: gitea.event_name == 'push'
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Create version tag
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
run: |
|
||||||
|
VERSION="${{ needs.compute-version.outputs.version }}"
|
||||||
|
TAG="v${VERSION}"
|
||||||
|
echo "Creating tag ${TAG}..."
|
||||||
|
|
||||||
|
# Create annotated tag via Gitea API
|
||||||
|
curl -s -X POST \
|
||||||
|
-H "Authorization: token ${TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"tag_name\": \"${TAG}\", \"target\": \"${{ gitea.sha }}\", \"message\": \"Release ${TAG}\"}" \
|
||||||
|
"${GITEA_URL}/api/v1/repos/${REPO}/tags" || echo "Tag may already exist (created by release)"
|
||||||
|
|
||||||
|
echo "Tag ${TAG} created successfully"
|
||||||
|
|
||||||
sync-to-github:
|
sync-to-github:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [build-linux, build-macos, build-windows]
|
needs: [compute-version, build-linux, build-macos, build-windows]
|
||||||
if: gitea.event_name == 'push'
|
if: gitea.event_name == 'push'
|
||||||
env:
|
env:
|
||||||
GH_PAT: ${{ secrets.GH_PAT }}
|
GH_PAT: ${{ secrets.GH_PAT }}
|
||||||
@@ -389,7 +429,7 @@ jobs:
|
|||||||
- name: Download artifacts from Gitea releases
|
- name: Download artifacts from Gitea releases
|
||||||
env:
|
env:
|
||||||
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
VERSION: ${{ needs.build-linux.outputs.version }}
|
VERSION: ${{ needs.compute-version.outputs.version }}
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
mkdir -p artifacts
|
mkdir -p artifacts
|
||||||
@@ -418,7 +458,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Create GitHub release and upload artifacts
|
- name: Create GitHub release and upload artifacts
|
||||||
env:
|
env:
|
||||||
VERSION: ${{ needs.build-linux.outputs.version }}
|
VERSION: ${{ needs.compute-version.outputs.version }}
|
||||||
COMMIT_SHA: ${{ gitea.sha }}
|
COMMIT_SHA: ${{ gitea.sha }}
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ You need access to Claude Code through one of:
|
|||||||
|
|
||||||
- **Anthropic account** — Sign up at https://claude.ai and use `claude login` (OAuth) inside the terminal
|
- **Anthropic account** — Sign up at https://claude.ai and use `claude login` (OAuth) inside the terminal
|
||||||
- **AWS Bedrock** — An AWS account with Bedrock access and Claude models enabled
|
- **AWS Bedrock** — An AWS account with Bedrock access and Claude models enabled
|
||||||
|
- **Ollama** — A local or remote Ollama server running an Anthropic-compatible model (best-effort support)
|
||||||
|
- **LiteLLM** — A LiteLLM proxy gateway providing access to 100+ model providers (best-effort support)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -88,6 +90,20 @@ Claude Code launches automatically with `--dangerously-skip-permissions` inside
|
|||||||
3. Expand the **Config** panel and fill in your AWS credentials (see [AWS Bedrock Configuration](#aws-bedrock-configuration) below).
|
3. Expand the **Config** panel and fill in your AWS credentials (see [AWS Bedrock Configuration](#aws-bedrock-configuration) below).
|
||||||
4. Start the container again.
|
4. Start the container again.
|
||||||
|
|
||||||
|
**Ollama:**
|
||||||
|
|
||||||
|
1. Stop the container first (settings can only be changed while stopped).
|
||||||
|
2. In the project card, switch the auth mode to **Ollama**.
|
||||||
|
3. Expand the **Config** panel and set the base URL of your Ollama server (defaults to `http://host.docker.internal:11434` for a local instance). Optionally set a model ID.
|
||||||
|
4. Start the container again.
|
||||||
|
|
||||||
|
**LiteLLM:**
|
||||||
|
|
||||||
|
1. Stop the container first (settings can only be changed while stopped).
|
||||||
|
2. In the project card, switch the auth mode to **LiteLLM**.
|
||||||
|
3. Expand the **Config** panel and set the base URL of your LiteLLM proxy (defaults to `http://host.docker.internal:4000`). Optionally set an API key and model ID.
|
||||||
|
4. Start the container again.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## The Interface
|
## The Interface
|
||||||
@@ -372,6 +388,41 @@ Per-project settings always override these global defaults.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Ollama Configuration
|
||||||
|
|
||||||
|
To use Claude Code with a local or remote Ollama server, switch the auth mode to **Ollama** on the project card.
|
||||||
|
|
||||||
|
### Settings
|
||||||
|
|
||||||
|
- **Base URL** — The URL of your Ollama server. Defaults to `http://host.docker.internal:11434`, which reaches a locally running Ollama instance from inside the container. For a remote server, use its IP or hostname (e.g., `http://192.168.1.100:11434`).
|
||||||
|
- **Model ID** — Optional. Override the model to use (e.g., `qwen3.5:27b`).
|
||||||
|
|
||||||
|
### How It Works
|
||||||
|
|
||||||
|
Triple-C sets `ANTHROPIC_BASE_URL` to point Claude Code at your Ollama server instead of Anthropic's API. The `ANTHROPIC_AUTH_TOKEN` is set to `ollama` (required by Claude Code but not used for actual authentication).
|
||||||
|
|
||||||
|
> **Note:** Ollama support is best-effort. Claude Code is designed for Anthropic models, so some features (tool use, extended thinking, prompt caching, etc.) may not work as expected with non-Anthropic models.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## LiteLLM Configuration
|
||||||
|
|
||||||
|
To use Claude Code through a [LiteLLM](https://docs.litellm.ai/) proxy gateway, switch the auth mode to **LiteLLM** on the project card. LiteLLM supports 100+ model providers (OpenAI, Gemini, Anthropic, and more) through a single proxy.
|
||||||
|
|
||||||
|
### Settings
|
||||||
|
|
||||||
|
- **Base URL** — The URL of your LiteLLM proxy. Defaults to `http://host.docker.internal:4000` for a locally running proxy.
|
||||||
|
- **API Key** — Optional. The API key for your LiteLLM proxy, if authentication is required. Stored securely in your OS keychain.
|
||||||
|
- **Model ID** — Optional. Override the model to use.
|
||||||
|
|
||||||
|
### How It Works
|
||||||
|
|
||||||
|
Triple-C sets `ANTHROPIC_BASE_URL` to point Claude Code at your LiteLLM proxy. If an API key is provided, it is set as `ANTHROPIC_AUTH_TOKEN`.
|
||||||
|
|
||||||
|
> **Note:** LiteLLM support is best-effort. Claude Code is designed for Anthropic models, so some features (tool use, extended thinking, prompt caching, etc.) may not work as expected when routing to non-Anthropic models through the proxy.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Settings
|
## Settings
|
||||||
|
|
||||||
Access global settings via the **Settings** tab in the sidebar.
|
Access global settings via the **Settings** tab in the sidebar.
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ Each project can independently use one of:
|
|||||||
|
|
||||||
- **Anthropic** (OAuth): User runs `claude login` inside the terminal on first use. Token persisted in the config volume across restarts and resets.
|
- **Anthropic** (OAuth): User runs `claude login` inside the terminal on first use. Token persisted in the config volume across restarts and resets.
|
||||||
- **AWS Bedrock**: Per-project AWS credentials (static keys, profile, or bearer token). SSO sessions are validated before launching Claude for Profile auth.
|
- **AWS Bedrock**: Per-project AWS credentials (static keys, profile, or bearer token). SSO sessions are validated before launching Claude for Profile auth.
|
||||||
|
- **Ollama**: Connect to a local or remote Ollama server via `ANTHROPIC_BASE_URL` (e.g., `http://host.docker.internal:11434`). Optional model override.
|
||||||
|
- **LiteLLM**: Connect through a LiteLLM proxy gateway via `ANTHROPIC_BASE_URL` + `ANTHROPIC_AUTH_TOKEN` to access 100+ model providers. API key stored securely in OS keychain.
|
||||||
|
|
||||||
|
> **Note:** Ollama and LiteLLM support is best-effort. Claude Code is designed for Anthropic models, so some features (tool use, extended thinking, prompt caching, etc.) may not work as expected with non-Anthropic models behind these backends.
|
||||||
|
|
||||||
### Container Spawning (Sibling Containers)
|
### Container Spawning (Sibling Containers)
|
||||||
|
|
||||||
|
|||||||
68
app/package-lock.json
generated
68
app/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "triple-c",
|
"name": "triple-c",
|
||||||
"version": "0.1.0",
|
"version": "0.2.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "triple-c",
|
"name": "triple-c",
|
||||||
"version": "0.1.0",
|
"version": "0.2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tauri-apps/api": "^2",
|
"@tauri-apps/api": "^2",
|
||||||
"@tauri-apps/plugin-dialog": "^2",
|
"@tauri-apps/plugin-dialog": "^2",
|
||||||
@@ -1643,6 +1643,70 @@
|
|||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||||
|
"version": "1.8.1",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.1.0",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.8.1",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^1.7.1",
|
||||||
|
"@emnapi/runtime": "^1.7.1",
|
||||||
|
"@tybys/wasm-util": "^0.10.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.10.1",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "0BSD",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||||
"version": "4.2.1",
|
"version": "4.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz",
|
||||||
|
|||||||
@@ -1143,11 +1143,6 @@ pub fn any_stdio_docker_mcp(servers: &[McpServer]) -> bool {
|
|||||||
servers.iter().any(|s| s.is_docker() && s.transport_type == McpTransportType::Stdio)
|
servers.iter().any(|s| s.is_docker() && s.transport_type == McpTransportType::Stdio)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if any MCP server uses Docker.
|
|
||||||
pub fn any_docker_mcp(servers: &[McpServer]) -> bool {
|
|
||||||
servers.iter().any(|s| s.is_docker())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find an existing MCP container by its expected name.
|
/// Find an existing MCP container by its expected name.
|
||||||
pub async fn find_mcp_container(server: &McpServer) -> Result<Option<String>, String> {
|
pub async fn find_mcp_container(server: &McpServer) -> Result<Option<String>, String> {
|
||||||
let docker = get_docker()?;
|
let docker = get_docker()?;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ impl ExecSession {
|
|||||||
.map_err(|e| format!("Failed to send input: {}", e))
|
.map_err(|e| format!("Failed to send input: {}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub async fn resize(&self, cols: u16, rows: u16) -> Result<(), String> {
|
pub async fn resize(&self, cols: u16, rows: u16) -> Result<(), String> {
|
||||||
let docker = get_docker()?;
|
let docker = get_docker()?;
|
||||||
docker
|
docker
|
||||||
|
|||||||
@@ -4,8 +4,13 @@ pub mod image;
|
|||||||
pub mod exec;
|
pub mod exec;
|
||||||
pub mod network;
|
pub mod network;
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use client::*;
|
pub use client::*;
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use container::*;
|
pub use container::*;
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use image::*;
|
pub use image::*;
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use exec::*;
|
pub use exec::*;
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use network::*;
|
pub use network::*;
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ pub async fn ensure_project_network(project_id: &str) -> Result<String, String>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Connect a container to the project network.
|
/// Connect a container to the project network.
|
||||||
|
#[allow(dead_code)]
|
||||||
pub async fn connect_container_to_network(
|
pub async fn connect_container_to_network(
|
||||||
container_id: &str,
|
container_id: &str,
|
||||||
network_name: &str,
|
network_name: &str,
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ pub mod secure;
|
|||||||
pub mod settings_store;
|
pub mod settings_store;
|
||||||
pub mod mcp_store;
|
pub mod mcp_store;
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use projects_store::*;
|
pub use projects_store::*;
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use secure::*;
|
pub use secure::*;
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use settings_store::*;
|
pub use settings_store::*;
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use mcp_store::*;
|
pub use mcp_store::*;
|
||||||
|
|||||||
@@ -449,50 +449,18 @@ export default function ProjectCard({ project }: Props) {
|
|||||||
{/* Auth mode selector */}
|
{/* Auth mode selector */}
|
||||||
<div className="flex items-center gap-1 text-xs">
|
<div className="flex items-center gap-1 text-xs">
|
||||||
<span className="text-[var(--text-secondary)] mr-1">Auth:</span>
|
<span className="text-[var(--text-secondary)] mr-1">Auth:</span>
|
||||||
<button
|
<select
|
||||||
onClick={(e) => { e.stopPropagation(); handleAuthModeChange("anthropic"); }}
|
value={project.auth_mode}
|
||||||
|
onChange={(e) => { e.stopPropagation(); handleAuthModeChange(e.target.value as AuthMode); }}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
disabled={!isStopped}
|
disabled={!isStopped}
|
||||||
className={`px-2 py-0.5 rounded transition-colors ${
|
className="px-2 py-0.5 rounded bg-[var(--bg-primary)] border border-[var(--border-color)] text-xs text-[var(--text-primary)] focus:outline-none focus:border-[var(--accent)] disabled:opacity-50"
|
||||||
project.auth_mode === "anthropic"
|
|
||||||
? "bg-[var(--accent)] text-white"
|
|
||||||
: "text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-primary)]"
|
|
||||||
} disabled:opacity-50`}
|
|
||||||
>
|
>
|
||||||
Anthropic
|
<option value="anthropic">Anthropic</option>
|
||||||
</button>
|
<option value="bedrock">Bedrock</option>
|
||||||
<button
|
<option value="ollama">Ollama</option>
|
||||||
onClick={(e) => { e.stopPropagation(); handleAuthModeChange("bedrock"); }}
|
<option value="lit_llm">LiteLLM</option>
|
||||||
disabled={!isStopped}
|
</select>
|
||||||
className={`px-2 py-0.5 rounded transition-colors ${
|
|
||||||
project.auth_mode === "bedrock"
|
|
||||||
? "bg-[var(--accent)] text-white"
|
|
||||||
: "text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-primary)]"
|
|
||||||
} disabled:opacity-50`}
|
|
||||||
>
|
|
||||||
Bedrock
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={(e) => { e.stopPropagation(); handleAuthModeChange("ollama"); }}
|
|
||||||
disabled={!isStopped}
|
|
||||||
className={`px-2 py-0.5 rounded transition-colors ${
|
|
||||||
project.auth_mode === "ollama"
|
|
||||||
? "bg-[var(--accent)] text-white"
|
|
||||||
: "text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-primary)]"
|
|
||||||
} disabled:opacity-50`}
|
|
||||||
>
|
|
||||||
Ollama
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={(e) => { e.stopPropagation(); handleAuthModeChange("lit_llm"); }}
|
|
||||||
disabled={!isStopped}
|
|
||||||
className={`px-2 py-0.5 rounded transition-colors ${
|
|
||||||
project.auth_mode === "lit_llm"
|
|
||||||
? "bg-[var(--accent)] text-white"
|
|
||||||
: "text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-primary)]"
|
|
||||||
} disabled:opacity-50`}
|
|
||||||
>
|
|
||||||
LiteLLM
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Action buttons */}
|
{/* Action buttons */}
|
||||||
@@ -836,20 +804,17 @@ export default function ProjectCard({ project }: Props) {
|
|||||||
{/* Sub-method selector */}
|
{/* Sub-method selector */}
|
||||||
<div className="flex items-center gap-1 text-xs">
|
<div className="flex items-center gap-1 text-xs">
|
||||||
<span className="text-[var(--text-secondary)] mr-1">Method:</span>
|
<span className="text-[var(--text-secondary)] mr-1">Method:</span>
|
||||||
{(["static_credentials", "profile", "bearer_token"] as BedrockAuthMethod[]).map((m) => (
|
<select
|
||||||
<button
|
value={bc.auth_method}
|
||||||
key={m}
|
onChange={(e) => updateBedrockConfig({ auth_method: e.target.value as BedrockAuthMethod })}
|
||||||
onClick={() => updateBedrockConfig({ auth_method: m })}
|
onClick={(e) => e.stopPropagation()}
|
||||||
disabled={!isStopped}
|
disabled={!isStopped}
|
||||||
className={`px-2 py-0.5 rounded transition-colors ${
|
className="px-2 py-0.5 rounded bg-[var(--bg-primary)] border border-[var(--border-color)] text-xs text-[var(--text-primary)] focus:outline-none focus:border-[var(--accent)] disabled:opacity-50"
|
||||||
bc.auth_method === m
|
|
||||||
? "bg-[var(--accent)] text-white"
|
|
||||||
: "text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-primary)]"
|
|
||||||
} disabled:opacity-50`}
|
|
||||||
>
|
>
|
||||||
{m === "static_credentials" ? "Keys" : m === "profile" ? "Profile" : "Token"}
|
<option value="static_credentials">Keys</option>
|
||||||
</button>
|
<option value="profile">Profile</option>
|
||||||
))}
|
<option value="bearer_token">Token</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* AWS Region (always shown) */}
|
{/* AWS Region (always shown) */}
|
||||||
|
|||||||
Reference in New Issue
Block a user