dsh-cloud 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dsh_cloud-0.2.0.dist-info/METADATA +27 -0
- dsh_cloud-0.2.0.dist-info/RECORD +23 -0
- dsh_cloud-0.2.0.dist-info/WHEEL +4 -0
- dsh_cloud-0.2.0.dist-info/entry_points.txt +2 -0
- dsh_cloud-0.2.0.dist-info/licenses/LICENSE +264 -0
- dsh_cloud_cli/__init__.py +1 -0
- dsh_cloud_cli/__main__.py +5 -0
- dsh_cloud_cli/cli.py +367 -0
- dsh_cloud_cli/release-manifest.json +22 -0
- dsh_cloud_cli/templates/Caddyfile +67 -0
- dsh_cloud_cli/templates/compose.build.yml +10 -0
- dsh_cloud_cli/templates/compose.postgres.yml +36 -0
- dsh_cloud_cli/templates/config/i18n/en.json +583 -0
- dsh_cloud_cli/templates/config/i18n/zh.json +583 -0
- dsh_cloud_cli/templates/config/models.curated.txt +37 -0
- dsh_cloud_cli/templates/config/models.json +227 -0
- dsh_cloud_cli/templates/config/pricing.cny.json +96 -0
- dsh_cloud_cli/templates/config/pricing.eur.json +96 -0
- dsh_cloud_cli/templates/config/pricing.gbp.json +96 -0
- dsh_cloud_cli/templates/config/pricing.hkd.json +96 -0
- dsh_cloud_cli/templates/config/pricing.jpy.json +96 -0
- dsh_cloud_cli/templates/config/pricing.usd.json +96 -0
- dsh_cloud_cli/templates/docker-compose.yml +159 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "由 server/scripts/gen_pricing.py 生成,请勿手改。基准 1 USD = 7 CNY = 100 积分;其余币种按对美元汇率折算后取整(日元取整到 100)。三档 $10 / $50 / $100,年付一律 7 折、首月一律 7.5 折(名义值;美元档要取整到整元,$10 的 7.5 折是 $7.5 → $8,实际 8 折。其余币种一律按**美元卡上的实际比例**折算,不重新套名义值,否则同一个促销在不同币种上力度不同)。积分包不再多送——100 积分/美元是公示承诺,包的价值在于不随月清零,同价的包也绝不能比同价套餐给得多,否则最高档被自己的加油包压制。",
|
|
3
|
+
"currency": "JPY",
|
|
4
|
+
"tiers": {
|
|
5
|
+
"free": {
|
|
6
|
+
"name": "Free",
|
|
7
|
+
"monthly_cents": 0,
|
|
8
|
+
"monthly_credits": 0,
|
|
9
|
+
"concurrency": 1,
|
|
10
|
+
"work_minutes": 180,
|
|
11
|
+
"signup_credits": 500
|
|
12
|
+
},
|
|
13
|
+
"plus": {
|
|
14
|
+
"name": "Plus",
|
|
15
|
+
"monthly_cents": 150000,
|
|
16
|
+
"monthly_credits": 1000,
|
|
17
|
+
"concurrency": 2,
|
|
18
|
+
"work_minutes": 6000,
|
|
19
|
+
"yearly_list_cents": 1800000,
|
|
20
|
+
"yearly_cents": 1320000,
|
|
21
|
+
"yearly_per_month_cents": 110000,
|
|
22
|
+
"monthly_intro_cents": 120000
|
|
23
|
+
},
|
|
24
|
+
"pro": {
|
|
25
|
+
"name": "Pro",
|
|
26
|
+
"monthly_cents": 750000,
|
|
27
|
+
"monthly_credits": 5000,
|
|
28
|
+
"concurrency": 5,
|
|
29
|
+
"work_minutes": 21600,
|
|
30
|
+
"yearly_list_cents": 9000000,
|
|
31
|
+
"yearly_cents": 6360000,
|
|
32
|
+
"yearly_per_month_cents": 530000,
|
|
33
|
+
"monthly_intro_cents": 570000
|
|
34
|
+
},
|
|
35
|
+
"max": {
|
|
36
|
+
"name": "Max",
|
|
37
|
+
"monthly_cents": 1500000,
|
|
38
|
+
"monthly_credits": 10000,
|
|
39
|
+
"concurrency": 10,
|
|
40
|
+
"work_minutes": 32400,
|
|
41
|
+
"yearly_list_cents": 18000000,
|
|
42
|
+
"yearly_cents": 12600000,
|
|
43
|
+
"yearly_per_month_cents": 1050000,
|
|
44
|
+
"monthly_intro_cents": 1130000
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"packs": {
|
|
48
|
+
"pack1000": {
|
|
49
|
+
"name": "1,000 credits",
|
|
50
|
+
"cents": 150000,
|
|
51
|
+
"base_credits": 1000,
|
|
52
|
+
"bonus_pct": 0,
|
|
53
|
+
"credits": 1000,
|
|
54
|
+
"valid_days": 365,
|
|
55
|
+
"name_key": "pricing.pack.pack1000"
|
|
56
|
+
},
|
|
57
|
+
"pack5000": {
|
|
58
|
+
"name": "5,000 credits",
|
|
59
|
+
"cents": 750000,
|
|
60
|
+
"base_credits": 5000,
|
|
61
|
+
"bonus_pct": 0,
|
|
62
|
+
"credits": 5000,
|
|
63
|
+
"valid_days": 365,
|
|
64
|
+
"name_key": "pricing.pack.pack5000"
|
|
65
|
+
},
|
|
66
|
+
"pack10000": {
|
|
67
|
+
"name": "10,000 credits",
|
|
68
|
+
"cents": 1500000,
|
|
69
|
+
"base_credits": 10000,
|
|
70
|
+
"bonus_pct": 0,
|
|
71
|
+
"credits": 10000,
|
|
72
|
+
"valid_days": 365,
|
|
73
|
+
"name_key": "pricing.pack.pack10000"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"team": {
|
|
77
|
+
"seat_cents": 380000,
|
|
78
|
+
"min_seats": 3,
|
|
79
|
+
"seat_credits": 2500,
|
|
80
|
+
"seat_minutes": 1200,
|
|
81
|
+
"volume_tiers": [
|
|
82
|
+
[
|
|
83
|
+
10,
|
|
84
|
+
10
|
|
85
|
+
],
|
|
86
|
+
[
|
|
87
|
+
25,
|
|
88
|
+
15
|
|
89
|
+
],
|
|
90
|
+
[
|
|
91
|
+
50,
|
|
92
|
+
20
|
|
93
|
+
]
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "由 server/scripts/gen_pricing.py 生成,请勿手改。基准 1 USD = 7 CNY = 100 积分;其余币种按对美元汇率折算后取整(日元取整到 100)。三档 $10 / $50 / $100,年付一律 7 折、首月一律 7.5 折(名义值;美元档要取整到整元,$10 的 7.5 折是 $7.5 → $8,实际 8 折。其余币种一律按**美元卡上的实际比例**折算,不重新套名义值,否则同一个促销在不同币种上力度不同)。积分包不再多送——100 积分/美元是公示承诺,包的价值在于不随月清零,同价的包也绝不能比同价套餐给得多,否则最高档被自己的加油包压制。",
|
|
3
|
+
"currency": "USD",
|
|
4
|
+
"tiers": {
|
|
5
|
+
"free": {
|
|
6
|
+
"name": "Free",
|
|
7
|
+
"monthly_cents": 0,
|
|
8
|
+
"monthly_credits": 0,
|
|
9
|
+
"concurrency": 1,
|
|
10
|
+
"work_minutes": 180,
|
|
11
|
+
"signup_credits": 500
|
|
12
|
+
},
|
|
13
|
+
"plus": {
|
|
14
|
+
"name": "Plus",
|
|
15
|
+
"monthly_cents": 1000,
|
|
16
|
+
"monthly_credits": 1000,
|
|
17
|
+
"concurrency": 2,
|
|
18
|
+
"work_minutes": 6000,
|
|
19
|
+
"yearly_list_cents": 12000,
|
|
20
|
+
"yearly_cents": 8400,
|
|
21
|
+
"yearly_per_month_cents": 700,
|
|
22
|
+
"monthly_intro_cents": 800
|
|
23
|
+
},
|
|
24
|
+
"pro": {
|
|
25
|
+
"name": "Pro",
|
|
26
|
+
"monthly_cents": 5000,
|
|
27
|
+
"monthly_credits": 5000,
|
|
28
|
+
"concurrency": 5,
|
|
29
|
+
"work_minutes": 21600,
|
|
30
|
+
"yearly_list_cents": 60000,
|
|
31
|
+
"yearly_cents": 42000,
|
|
32
|
+
"yearly_per_month_cents": 3500,
|
|
33
|
+
"monthly_intro_cents": 3800
|
|
34
|
+
},
|
|
35
|
+
"max": {
|
|
36
|
+
"name": "Max",
|
|
37
|
+
"monthly_cents": 10000,
|
|
38
|
+
"monthly_credits": 10000,
|
|
39
|
+
"concurrency": 10,
|
|
40
|
+
"work_minutes": 32400,
|
|
41
|
+
"yearly_list_cents": 120000,
|
|
42
|
+
"yearly_cents": 84000,
|
|
43
|
+
"yearly_per_month_cents": 7000,
|
|
44
|
+
"monthly_intro_cents": 7500
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"packs": {
|
|
48
|
+
"pack1000": {
|
|
49
|
+
"name": "1,000 credits",
|
|
50
|
+
"cents": 1000,
|
|
51
|
+
"base_credits": 1000,
|
|
52
|
+
"bonus_pct": 0,
|
|
53
|
+
"credits": 1000,
|
|
54
|
+
"valid_days": 365,
|
|
55
|
+
"name_key": "pricing.pack.pack1000"
|
|
56
|
+
},
|
|
57
|
+
"pack5000": {
|
|
58
|
+
"name": "5,000 credits",
|
|
59
|
+
"cents": 5000,
|
|
60
|
+
"base_credits": 5000,
|
|
61
|
+
"bonus_pct": 0,
|
|
62
|
+
"credits": 5000,
|
|
63
|
+
"valid_days": 365,
|
|
64
|
+
"name_key": "pricing.pack.pack5000"
|
|
65
|
+
},
|
|
66
|
+
"pack10000": {
|
|
67
|
+
"name": "10,000 credits",
|
|
68
|
+
"cents": 10000,
|
|
69
|
+
"base_credits": 10000,
|
|
70
|
+
"bonus_pct": 0,
|
|
71
|
+
"credits": 10000,
|
|
72
|
+
"valid_days": 365,
|
|
73
|
+
"name_key": "pricing.pack.pack10000"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"team": {
|
|
77
|
+
"seat_cents": 2500,
|
|
78
|
+
"min_seats": 3,
|
|
79
|
+
"seat_credits": 2500,
|
|
80
|
+
"seat_minutes": 1200,
|
|
81
|
+
"volume_tiers": [
|
|
82
|
+
[
|
|
83
|
+
10,
|
|
84
|
+
10
|
|
85
|
+
],
|
|
86
|
+
[
|
|
87
|
+
25,
|
|
88
|
+
15
|
|
89
|
+
],
|
|
90
|
+
[
|
|
91
|
+
50,
|
|
92
|
+
20
|
|
93
|
+
]
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# DSH Cloud (deepseek-harness-cloud) — one-command self-host stack
|
|
3
|
+
# 自部署编排:一条命令起全栈(Caddy + 服务端 + 可选云工作台)
|
|
4
|
+
#
|
|
5
|
+
# cd deploy/selfhost
|
|
6
|
+
# cp .env.example .env && $EDITOR .env # or: scripts/quickstart.sh
|
|
7
|
+
# docker compose --env-file .env up -d
|
|
8
|
+
# # Source build instead of the release image:
|
|
9
|
+
# docker compose --env-file .env -f docker-compose.yml -f compose.build.yml up -d --build
|
|
10
|
+
#
|
|
11
|
+
# What runs here / 本编排包含:
|
|
12
|
+
# dhc-caddy public listener, automatic HTTPS (Let's Encrypt)
|
|
13
|
+
# dhc-server the FastAPI app (accounts, LLM gateway, credits, console)
|
|
14
|
+
# dhc-docker-proxy scoped docker API for cloud workspaces — only started
|
|
15
|
+
# when COMPOSE_PROFILES=work (see .env)
|
|
16
|
+
#
|
|
17
|
+
# The app is never published on a host port: Caddy is the only way in.
|
|
18
|
+
# 应用不暴露宿主端口,唯一入口是 Caddy。
|
|
19
|
+
# =============================================================================
|
|
20
|
+
name: ${COMPOSE_PROJECT_NAME:-dsh-selfhost}
|
|
21
|
+
|
|
22
|
+
x-logging: &logging
|
|
23
|
+
driver: json-file
|
|
24
|
+
options:
|
|
25
|
+
max-size: "10m"
|
|
26
|
+
max-file: "3"
|
|
27
|
+
|
|
28
|
+
services:
|
|
29
|
+
# ---------------------------------------------------------------------------
|
|
30
|
+
# The application. The default path pulls the versioned release image. Source
|
|
31
|
+
# builds are an explicit compose.build.yml overlay so package installs do not
|
|
32
|
+
# require a Git checkout or a repository-root Docker build context.
|
|
33
|
+
# ---------------------------------------------------------------------------
|
|
34
|
+
dhc-server:
|
|
35
|
+
image: ${DHC_SERVER_IMAGE:-ghcr.io/agentsdanceai/dsh-cloud-server:0.2.0}
|
|
36
|
+
pull_policy: missing
|
|
37
|
+
restart: unless-stopped
|
|
38
|
+
env_file:
|
|
39
|
+
- path: .env
|
|
40
|
+
required: false
|
|
41
|
+
environment:
|
|
42
|
+
DHC_DATA_DIR: /app/data
|
|
43
|
+
# Single source of truth for the public origin: whatever Caddy serves is
|
|
44
|
+
# exactly what the app believes it is reachable at (OAuth callbacks,
|
|
45
|
+
# payment return URLs and the workspace gateway URL are derived from it).
|
|
46
|
+
# Set PUBLIC_BASE in .env only when you front this stack with another
|
|
47
|
+
# proxy or use a non-standard port.
|
|
48
|
+
PUBLIC_BASE: ${PUBLIC_BASE:-${SITE_SCHEME:-https}://${DOMAIN:-localhost}}
|
|
49
|
+
volumes:
|
|
50
|
+
# SQLite lives here (/app/data/dhc.db, WAL). Back this volume up.
|
|
51
|
+
# Desktop installers dropped into /app/data/releases are served at
|
|
52
|
+
# /releases/<file> by the app itself.
|
|
53
|
+
- dhc-data:/app/data
|
|
54
|
+
# A source checkout defaults this to ../../server/config. The npm/uv CLIs
|
|
55
|
+
# generate ./config and set DHC_CONFIG_DIR=./config, so the exact same
|
|
56
|
+
# Compose file also works when installed from a package.
|
|
57
|
+
- ${DHC_CONFIG_DIR:-../../server/config}:/srv/dhc/config:ro
|
|
58
|
+
# Legal pages (/legal/terms ...) render "待发布" until you provide your own
|
|
59
|
+
# documents. The drafts in ../../legal name the original operator, so they
|
|
60
|
+
# are NOT mounted by default — write your own, then uncomment:
|
|
61
|
+
# - ../../legal:/srv/legal:ro
|
|
62
|
+
networks:
|
|
63
|
+
- dhc-net
|
|
64
|
+
- dshwork-net # reach per-user dsh containers (readiness probe + /preview)
|
|
65
|
+
expose:
|
|
66
|
+
- "8100"
|
|
67
|
+
healthcheck:
|
|
68
|
+
test: ["CMD", "/usr/local/bin/python3", "-I", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8100/readyz')"]
|
|
69
|
+
interval: 30s
|
|
70
|
+
timeout: 5s
|
|
71
|
+
retries: 3
|
|
72
|
+
start_period: 20s
|
|
73
|
+
security_opt: ["no-new-privileges:true"]
|
|
74
|
+
logging: *logging
|
|
75
|
+
|
|
76
|
+
# ---------------------------------------------------------------------------
|
|
77
|
+
# TLS termination + reverse proxy. Certificates are obtained automatically for
|
|
78
|
+
# any site address that starts with https:// and resolves to this host;
|
|
79
|
+
# http://localhost serves plain HTTP with no certificate at all.
|
|
80
|
+
# ---------------------------------------------------------------------------
|
|
81
|
+
dhc-caddy:
|
|
82
|
+
image: ${CADDY_IMAGE:-caddy:2@sha256:df7f1c2fb114453b951de51a98efc010db1655a92c2e86be6706714e2417a78d}
|
|
83
|
+
restart: unless-stopped
|
|
84
|
+
depends_on: [dhc-server]
|
|
85
|
+
ports:
|
|
86
|
+
# Trial defaults bind only to loopback. Public operators must opt in with
|
|
87
|
+
# BIND_ADDRESS=0.0.0.0 (the checked-in .env.example does this explicitly).
|
|
88
|
+
- "${BIND_ADDRESS:-127.0.0.1}:${HTTP_PORT:-8787}:80"
|
|
89
|
+
- "${BIND_ADDRESS:-127.0.0.1}:${HTTPS_PORT:-8443}:443"
|
|
90
|
+
- "${BIND_ADDRESS:-127.0.0.1}:${HTTPS_PORT:-8443}:443/udp" # HTTP/3
|
|
91
|
+
environment:
|
|
92
|
+
# Internal Caddy listener. PUBLIC_BASE may contain a host-published port
|
|
93
|
+
# (trial uses :8787), while Caddy always listens on container 80/443.
|
|
94
|
+
DSH_SITE: ${DSH_SITE:-${SITE_SCHEME:-https}://${DOMAIN:-localhost}}
|
|
95
|
+
# Cloud-workspace site. Empty WORK_DOMAIN (workspaces off) falls back to
|
|
96
|
+
# work.localhost, which Caddy serves from its internal CA — so a disabled
|
|
97
|
+
# workspace never triggers a certificate request for a domain you do not
|
|
98
|
+
# own. 关闭云工作台时留空 WORK_DOMAIN,不会去申请证书。
|
|
99
|
+
DSH_WORK_SITE: https://${WORK_DOMAIN:-work.localhost}
|
|
100
|
+
volumes:
|
|
101
|
+
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
|
102
|
+
- caddy-data:/data # issued certificates — persist or you will re-issue
|
|
103
|
+
- caddy-config:/config
|
|
104
|
+
networks:
|
|
105
|
+
- dhc-net
|
|
106
|
+
- dshwork-net # reverse_proxy target of the workspace forward_auth
|
|
107
|
+
security_opt: ["no-new-privileges:true"]
|
|
108
|
+
logging: *logging
|
|
109
|
+
|
|
110
|
+
# ---------------------------------------------------------------------------
|
|
111
|
+
# Cloud workspaces only: a scoped view of the docker engine API.
|
|
112
|
+
# Started only when COMPOSE_PROFILES=work — with workspaces off, no container
|
|
113
|
+
# in this stack sees the docker socket at all.
|
|
114
|
+
#
|
|
115
|
+
# SECURITY: do NOT widen these flags. The app must create/start/stop
|
|
116
|
+
# containers and read the image/network/info endpoints. EXEC=0 and VOLUMES=0
|
|
117
|
+
# deny those dedicated API routes, but the proxy does not inspect HostConfig
|
|
118
|
+
# fields in a container-create POST. It therefore does not prevent a
|
|
119
|
+
# compromised control plane from requesting privileged mode, host mounts,
|
|
120
|
+
# devices, or host namespaces. This optional profile is for a trusted,
|
|
121
|
+
# single-operator installation, not a hostile multi-tenant boundary.
|
|
122
|
+
# 这些开关只缩小 API 面,不能过滤容器创建请求体;不要把它当作不可信多租户隔离边界。
|
|
123
|
+
# ---------------------------------------------------------------------------
|
|
124
|
+
dhc-docker-proxy:
|
|
125
|
+
image: ${SOCKET_PROXY_IMAGE:-tecnativa/docker-socket-proxy@sha256:1f5038b54f06c3e18422902cf00ba21803d1c97805aae032e5e6673d532d3459}
|
|
126
|
+
profiles: ["work"]
|
|
127
|
+
restart: unless-stopped
|
|
128
|
+
environment:
|
|
129
|
+
CONTAINERS: 1
|
|
130
|
+
NETWORKS: 1
|
|
131
|
+
IMAGES: 1
|
|
132
|
+
INFO: 1
|
|
133
|
+
POST: 1
|
|
134
|
+
EXEC: 0
|
|
135
|
+
VOLUMES: 0
|
|
136
|
+
volumes:
|
|
137
|
+
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
138
|
+
networks:
|
|
139
|
+
- dhc-net # reachable by the app as http://dhc-docker-proxy:2375
|
|
140
|
+
security_opt: ["no-new-privileges:true"]
|
|
141
|
+
logging: *logging
|
|
142
|
+
|
|
143
|
+
networks:
|
|
144
|
+
# Internal network (app <-> caddy <-> docker proxy); compose names it
|
|
145
|
+
# dsh-selfhost_dhc-net and service names resolve on it.
|
|
146
|
+
dhc-net:
|
|
147
|
+
# The workspace network keeps its literal name on purpose: the app passes
|
|
148
|
+
# WORK_NETWORK to the docker API when it creates a user's container, so the
|
|
149
|
+
# network compose creates and the name the app uses must be the same string.
|
|
150
|
+
dshwork-net:
|
|
151
|
+
name: ${WORK_NETWORK:-dshwork-net}
|
|
152
|
+
|
|
153
|
+
volumes:
|
|
154
|
+
dhc-data:
|
|
155
|
+
name: ${COMPOSE_PROJECT_NAME:-dsh-selfhost}_dhc-data
|
|
156
|
+
caddy-data:
|
|
157
|
+
name: ${COMPOSE_PROJECT_NAME:-dsh-selfhost}_caddy-data
|
|
158
|
+
caddy-config:
|
|
159
|
+
name: ${COMPOSE_PROJECT_NAME:-dsh-selfhost}_caddy-config
|