@cat-factory/app 0.46.7 → 0.46.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/components/providers/PersonalCredentialModal.vue +2 -2
- package/app/components/providers/PersonalSubscriptionSection.vue +68 -57
- package/i18n/locales/en.json +52 -0
- package/i18n/locales/es.json +49 -0
- package/i18n/locales/fr.json +49 -0
- package/i18n/locales/pl.json +49 -0
- package/i18n/locales/uk.json +49 -0
- package/package.json +8 -8
|
@@ -60,7 +60,7 @@ const title = computed(() => {
|
|
|
60
60
|
})
|
|
61
61
|
|
|
62
62
|
async function submit() {
|
|
63
|
-
if (!pending.value || password.value.length <
|
|
63
|
+
if (!pending.value || password.value.length < 6) return
|
|
64
64
|
busy.value = true
|
|
65
65
|
try {
|
|
66
66
|
await pending.value.retry(password.value)
|
|
@@ -117,7 +117,7 @@ function goConnect() {
|
|
|
117
117
|
</UFormField>
|
|
118
118
|
<div class="flex justify-end gap-2">
|
|
119
119
|
<UButton color="neutral" variant="ghost" @click="open = false">Cancel</UButton>
|
|
120
|
-
<UButton :loading="busy" :disabled="password.length <
|
|
120
|
+
<UButton :loading="busy" :disabled="password.length < 6" @click="submit()">
|
|
121
121
|
Unlock & run
|
|
122
122
|
</UButton>
|
|
123
123
|
</div>
|
|
@@ -9,52 +9,61 @@ import type { SubscriptionVendor } from '~/types/domain'
|
|
|
9
9
|
|
|
10
10
|
const personal = usePersonalSubscriptionsStore()
|
|
11
11
|
const toast = useToast()
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
const { t, d } = useI18n()
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Per-vendor metadata driving the connect form + connected-row labels. Reactive to the
|
|
16
|
+
* locale (rebuilds on switch). The token placeholders for `claude`/`codex` are literal
|
|
17
|
+
* format examples (and the Codex one contains `{ }`, which are vue-i18n interpolation
|
|
18
|
+
* metacharacters), so they stay inline rather than in the message catalog; only the GLM
|
|
19
|
+
* placeholder is prose and lives in i18n.
|
|
20
|
+
*/
|
|
21
|
+
const PERSONAL_VENDORS = computed<
|
|
22
|
+
{
|
|
23
|
+
value: SubscriptionVendor
|
|
24
|
+
label: string
|
|
25
|
+
tokenLabel: string
|
|
26
|
+
tokenPlaceholder: string
|
|
27
|
+
steps: string[]
|
|
28
|
+
}[]
|
|
29
|
+
>(() => [
|
|
21
30
|
{
|
|
22
31
|
value: 'claude',
|
|
23
|
-
label: '
|
|
24
|
-
tokenLabel: '
|
|
32
|
+
label: t('personalSubscriptions.vendors.claude.label'),
|
|
33
|
+
tokenLabel: t('personalSubscriptions.vendors.claude.tokenLabel'),
|
|
25
34
|
tokenPlaceholder: 'sk-ant-oat01-…',
|
|
26
35
|
steps: [
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
36
|
+
t('personalSubscriptions.vendors.claude.step1'),
|
|
37
|
+
t('personalSubscriptions.vendors.claude.step2'),
|
|
38
|
+
t('personalSubscriptions.vendors.claude.step3'),
|
|
30
39
|
],
|
|
31
40
|
},
|
|
32
41
|
{
|
|
33
42
|
value: 'glm',
|
|
34
|
-
label: '
|
|
35
|
-
tokenLabel: '
|
|
36
|
-
tokenPlaceholder: '
|
|
43
|
+
label: t('personalSubscriptions.vendors.glm.label'),
|
|
44
|
+
tokenLabel: t('personalSubscriptions.vendors.glm.tokenLabel'),
|
|
45
|
+
tokenPlaceholder: t('personalSubscriptions.vendors.glm.tokenPlaceholder'),
|
|
37
46
|
steps: [
|
|
38
|
-
'
|
|
39
|
-
'
|
|
40
|
-
'
|
|
47
|
+
t('personalSubscriptions.vendors.glm.step1'),
|
|
48
|
+
t('personalSubscriptions.vendors.glm.step2'),
|
|
49
|
+
t('personalSubscriptions.vendors.glm.step3'),
|
|
41
50
|
],
|
|
42
51
|
},
|
|
43
52
|
{
|
|
44
53
|
value: 'codex',
|
|
45
|
-
label: '
|
|
46
|
-
tokenLabel: '
|
|
54
|
+
label: t('personalSubscriptions.vendors.codex.label'),
|
|
55
|
+
tokenLabel: t('personalSubscriptions.vendors.codex.tokenLabel'),
|
|
47
56
|
tokenPlaceholder: '{ "auth_mode": "chatgpt", "tokens": { … } }',
|
|
48
57
|
steps: [
|
|
49
|
-
'
|
|
50
|
-
'
|
|
51
|
-
'
|
|
58
|
+
t('personalSubscriptions.vendors.codex.step1'),
|
|
59
|
+
t('personalSubscriptions.vendors.codex.step2'),
|
|
60
|
+
t('personalSubscriptions.vendors.codex.step3'),
|
|
52
61
|
],
|
|
53
62
|
},
|
|
54
|
-
]
|
|
63
|
+
])
|
|
55
64
|
|
|
56
65
|
function vendorMeta(v: SubscriptionVendor) {
|
|
57
|
-
return PERSONAL_VENDORS.find((m) => m.value === v)
|
|
66
|
+
return PERSONAL_VENDORS.value.find((m) => m.value === v)
|
|
58
67
|
}
|
|
59
68
|
|
|
60
69
|
function vendorLabel(v: SubscriptionVendor): string {
|
|
@@ -70,7 +79,7 @@ const busy = ref(false)
|
|
|
70
79
|
|
|
71
80
|
onMounted(() => void personal.load())
|
|
72
81
|
|
|
73
|
-
const selectedMeta = computed(() => vendorMeta(vendor.value) ?? PERSONAL_VENDORS[0]!)
|
|
82
|
+
const selectedMeta = computed(() => vendorMeta(vendor.value) ?? PERSONAL_VENDORS.value[0]!)
|
|
74
83
|
const existing = computed(() => personal.subscriptions.find((s) => s.vendor === vendor.value))
|
|
75
84
|
|
|
76
85
|
/** Renewal nudges for any connected subscription that's near or past expiry. */
|
|
@@ -78,20 +87,23 @@ const renewals = computed(() =>
|
|
|
78
87
|
personal.subscriptions
|
|
79
88
|
.filter((s) => s.expiresAt !== null && (s.expired || s.renewSoon))
|
|
80
89
|
.map((s) => {
|
|
81
|
-
const
|
|
90
|
+
const vendorName = vendorLabel(s.vendor)
|
|
82
91
|
if (s.expired)
|
|
83
|
-
return
|
|
84
|
-
|
|
92
|
+
return t('personalSubscriptions.renewal.expired', { vendor: vendorName })
|
|
93
|
+
const days = s.expiresInDays ?? 0
|
|
94
|
+
return t('personalSubscriptions.renewal.soon', { vendor: vendorName, count: days }, days)
|
|
85
95
|
}),
|
|
86
96
|
)
|
|
87
97
|
|
|
88
98
|
async function connect() {
|
|
89
|
-
if (!token.value.trim() || password.value.length <
|
|
99
|
+
if (!token.value.trim() || password.value.length < 6) return
|
|
90
100
|
busy.value = true
|
|
91
101
|
try {
|
|
92
102
|
await personal.store({
|
|
93
103
|
vendor: vendor.value,
|
|
94
|
-
label:
|
|
104
|
+
label:
|
|
105
|
+
label.value.trim() ||
|
|
106
|
+
t('personalSubscriptions.defaultLabel', { vendor: selectedMeta.value.label }),
|
|
95
107
|
token: token.value.trim(),
|
|
96
108
|
password: password.value,
|
|
97
109
|
expiresAt: expiresOn.value ? new Date(`${expiresOn.value}T00:00:00Z`).getTime() : null,
|
|
@@ -101,13 +113,13 @@ async function connect() {
|
|
|
101
113
|
label.value = ''
|
|
102
114
|
expiresOn.value = ''
|
|
103
115
|
toast.add({
|
|
104
|
-
title:
|
|
116
|
+
title: t('personalSubscriptions.toast.connected', { vendor: selectedMeta.value.label }),
|
|
105
117
|
icon: 'i-lucide-check',
|
|
106
118
|
color: 'success',
|
|
107
119
|
})
|
|
108
120
|
} catch (e) {
|
|
109
121
|
toast.add({
|
|
110
|
-
title: '
|
|
122
|
+
title: t('personalSubscriptions.toast.connectFailed'),
|
|
111
123
|
description: e instanceof Error ? e.message : String(e),
|
|
112
124
|
color: 'error',
|
|
113
125
|
})
|
|
@@ -119,10 +131,10 @@ async function connect() {
|
|
|
119
131
|
async function disconnect(v: SubscriptionVendor) {
|
|
120
132
|
try {
|
|
121
133
|
await personal.remove(v)
|
|
122
|
-
toast.add({ title: '
|
|
134
|
+
toast.add({ title: t('personalSubscriptions.toast.disconnected'), icon: 'i-lucide-check' })
|
|
123
135
|
} catch (e) {
|
|
124
136
|
toast.add({
|
|
125
|
-
title: '
|
|
137
|
+
title: t('personalSubscriptions.toast.disconnectFailed'),
|
|
126
138
|
description: e instanceof Error ? e.message : String(e),
|
|
127
139
|
color: 'error',
|
|
128
140
|
})
|
|
@@ -134,17 +146,9 @@ async function disconnect(v: SubscriptionVendor) {
|
|
|
134
146
|
<div class="space-y-3">
|
|
135
147
|
<div>
|
|
136
148
|
<h4 class="text-xs font-semibold uppercase tracking-wide text-slate-500">
|
|
137
|
-
|
|
149
|
+
{{ t('personalSubscriptions.heading') }}
|
|
138
150
|
</h4>
|
|
139
|
-
<p class="mt-1 text-sm text-slate-400">
|
|
140
|
-
Claude (Pro/Max), GLM (Z.ai Coding Plan) and ChatGPT (Codex) are each licensed to you as an
|
|
141
|
-
individual, so they’re stored <strong>just for you</strong> and only your runs use them.
|
|
142
|
-
Each token is encrypted under a personal password (never stored) that you enter when you
|
|
143
|
-
start such a run — it’s cached in this browser for a while so it stays out of your way. The
|
|
144
|
-
password is a low-friction convenience and a transparency signal that the system won’t
|
|
145
|
-
silently share your credential — it is <strong>not</strong> a wall against a system-key
|
|
146
|
-
holder. These models can’t be used on recurring schedules.
|
|
147
|
-
</p>
|
|
151
|
+
<p class="mt-1 text-sm text-slate-400">{{ t('personalSubscriptions.intro') }}</p>
|
|
148
152
|
</div>
|
|
149
153
|
|
|
150
154
|
<!-- connected subscriptions -->
|
|
@@ -158,9 +162,9 @@ async function disconnect(v: SubscriptionVendor) {
|
|
|
158
162
|
<span class="ml-2 text-xs text-slate-500">{{ vendorLabel(sub.vendor) }}</span>
|
|
159
163
|
<div class="text-[11px] text-slate-500">
|
|
160
164
|
<template v-if="sub.expiresAt">
|
|
161
|
-
|
|
165
|
+
{{ t('personalSubscriptions.expires', { date: d(new Date(sub.expiresAt), 'short') }) }}
|
|
162
166
|
</template>
|
|
163
|
-
<template v-else>
|
|
167
|
+
<template v-else>{{ t('personalSubscriptions.noExpiry') }}</template>
|
|
164
168
|
</div>
|
|
165
169
|
</div>
|
|
166
170
|
<UButton
|
|
@@ -175,7 +179,7 @@ async function disconnect(v: SubscriptionVendor) {
|
|
|
175
179
|
<p v-for="(line, i) in renewals" :key="i" class="text-sm text-amber-400/90">{{ line }}</p>
|
|
176
180
|
|
|
177
181
|
<!-- vendor picker -->
|
|
178
|
-
<UFormField label="
|
|
182
|
+
<UFormField :label="t('personalSubscriptions.vendorField')">
|
|
179
183
|
<USelect
|
|
180
184
|
v-model="vendor"
|
|
181
185
|
:items="PERSONAL_VENDORS.map((m) => ({ label: m.label, value: m.value }))"
|
|
@@ -191,8 +195,11 @@ async function disconnect(v: SubscriptionVendor) {
|
|
|
191
195
|
</ol>
|
|
192
196
|
|
|
193
197
|
<div class="space-y-2">
|
|
194
|
-
<UFormField label="
|
|
195
|
-
<UInput
|
|
198
|
+
<UFormField :label="t('personalSubscriptions.labelField')">
|
|
199
|
+
<UInput
|
|
200
|
+
v-model="label"
|
|
201
|
+
:placeholder="t('personalSubscriptions.labelPlaceholder', { vendor: selectedMeta.label })"
|
|
202
|
+
/>
|
|
196
203
|
</UFormField>
|
|
197
204
|
<UFormField :label="selectedMeta.tokenLabel">
|
|
198
205
|
<UTextarea
|
|
@@ -203,21 +210,25 @@ async function disconnect(v: SubscriptionVendor) {
|
|
|
203
210
|
/>
|
|
204
211
|
</UFormField>
|
|
205
212
|
<div class="flex flex-wrap gap-3">
|
|
206
|
-
<UFormField label="
|
|
207
|
-
<UInput
|
|
213
|
+
<UFormField :label="t('personalSubscriptions.passwordField')" class="flex-1">
|
|
214
|
+
<UInput
|
|
215
|
+
v-model="password"
|
|
216
|
+
type="password"
|
|
217
|
+
:placeholder="t('personalSubscriptions.passwordPlaceholder')"
|
|
218
|
+
/>
|
|
208
219
|
</UFormField>
|
|
209
|
-
<UFormField label="
|
|
220
|
+
<UFormField :label="t('personalSubscriptions.renewsField')">
|
|
210
221
|
<UInput v-model="expiresOn" type="date" />
|
|
211
222
|
</UFormField>
|
|
212
223
|
</div>
|
|
213
224
|
<div class="flex justify-end">
|
|
214
225
|
<UButton
|
|
215
226
|
:loading="busy"
|
|
216
|
-
:disabled="!token.trim() || password.length <
|
|
227
|
+
:disabled="!token.trim() || password.length < 6"
|
|
217
228
|
icon="i-lucide-shield-check"
|
|
218
229
|
@click="connect()"
|
|
219
230
|
>
|
|
220
|
-
{{ existing ? '
|
|
231
|
+
{{ existing ? t('personalSubscriptions.replace') : t('personalSubscriptions.connect') }}
|
|
221
232
|
</UButton>
|
|
222
233
|
</div>
|
|
223
234
|
</div>
|
package/i18n/locales/en.json
CHANGED
|
@@ -88,5 +88,57 @@
|
|
|
88
88
|
"action": "Configure AI"
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
+
},
|
|
92
|
+
"personalSubscriptions": {
|
|
93
|
+
"heading": "Personal subscriptions (individual use only)",
|
|
94
|
+
"intro": "Claude (Pro/Max), GLM (Z.ai Coding Plan) and ChatGPT (Codex) are each licensed to you as an individual, so they are stored just for you and only your runs use them. Each token is encrypted under a personal password (never stored) that you enter when you start such a run; it is cached in this browser for a while so it stays out of your way. The password is a low-friction convenience and a transparency signal that the system will not silently share your credential, not a wall against a system-key holder. These models cannot be used on recurring schedules.",
|
|
95
|
+
"vendorField": "Subscription",
|
|
96
|
+
"labelField": "Label (optional)",
|
|
97
|
+
"labelPlaceholder": "e.g. my {vendor}",
|
|
98
|
+
"defaultLabel": "My {vendor} subscription",
|
|
99
|
+
"passwordField": "Personal password (min 6 chars)",
|
|
100
|
+
"passwordPlaceholder": "protects your token",
|
|
101
|
+
"renewsField": "Subscription renews on (optional)",
|
|
102
|
+
"connect": "Connect",
|
|
103
|
+
"replace": "Replace",
|
|
104
|
+
"expires": "Expires {date}",
|
|
105
|
+
"noExpiry": "No expiry set",
|
|
106
|
+
"renewal": {
|
|
107
|
+
"expired": "Your {vendor} subscription has expired. Renew it and reconnect to keep running its models.",
|
|
108
|
+
"soon": "Your {vendor} subscription renews in {count} day. Update it here once renewed. | Your {vendor} subscription renews in {count} days. Update it here once renewed.",
|
|
109
|
+
"@soon": {
|
|
110
|
+
"description": "Count-based renewal reminder; {count} is the number of days until renewal (always >= 1). Provide ALL plural forms your language needs (English has 2; Polish/Ukrainian need 3 - one/few/many - via the custom pluralRules in i18n.config.ts). {vendor} is the subscription's product name, kept verbatim."
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"toast": {
|
|
114
|
+
"connected": "{vendor} subscription connected",
|
|
115
|
+
"connectFailed": "Could not connect subscription",
|
|
116
|
+
"disconnected": "Disconnected",
|
|
117
|
+
"disconnectFailed": "Could not disconnect"
|
|
118
|
+
},
|
|
119
|
+
"vendors": {
|
|
120
|
+
"claude": {
|
|
121
|
+
"label": "Claude (Pro/Max)",
|
|
122
|
+
"tokenLabel": "Claude token",
|
|
123
|
+
"step1": "Install Claude Code and sign in with your Claude Pro/Max account: run `claude` once and complete the browser login.",
|
|
124
|
+
"step2": "Generate a long-lived token: run `claude setup-token` and copy it.",
|
|
125
|
+
"step3": "Paste it below and choose a personal password to protect it."
|
|
126
|
+
},
|
|
127
|
+
"glm": {
|
|
128
|
+
"label": "GLM (Z.ai Coding Plan)",
|
|
129
|
+
"tokenLabel": "Z.ai API key",
|
|
130
|
+
"tokenPlaceholder": "your GLM Coding Plan API key",
|
|
131
|
+
"step1": "Open your Z.ai GLM Coding Plan dashboard and create an API key for the Anthropic-compatible endpoint.",
|
|
132
|
+
"step2": "The GLM Coding Plan is licensed to you as an individual, so it is stored per-user here (not pooled).",
|
|
133
|
+
"step3": "Paste the key below and choose a personal password to protect it."
|
|
134
|
+
},
|
|
135
|
+
"codex": {
|
|
136
|
+
"label": "ChatGPT (Codex)",
|
|
137
|
+
"tokenLabel": "ChatGPT auth.json",
|
|
138
|
+
"step1": "Install the Codex CLI and sign in with your ChatGPT account: run `codex login` and complete the browser flow.",
|
|
139
|
+
"step2": "Open the credentials file Codex wrote at ~/.codex/auth.json (on Windows %USERPROFILE%\\.codex\\auth.json).",
|
|
140
|
+
"step3": "Copy the entire contents of auth.json, paste it below, and choose a personal password to protect it."
|
|
141
|
+
}
|
|
142
|
+
}
|
|
91
143
|
}
|
|
92
144
|
}
|
package/i18n/locales/es.json
CHANGED
|
@@ -67,5 +67,54 @@
|
|
|
67
67
|
"action": "Configurar IA"
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
+
},
|
|
71
|
+
"personalSubscriptions": {
|
|
72
|
+
"heading": "Suscripciones personales (solo para uso individual)",
|
|
73
|
+
"intro": "Claude (Pro/Max), GLM (Z.ai Coding Plan) y ChatGPT (Codex) tienen licencia para ti como individuo, así que se guardan solo para ti y únicamente tus ejecuciones las usan. Cada token se cifra con una contraseña personal (que nunca se almacena) que introduces al iniciar una de estas ejecuciones; se guarda en caché en este navegador durante un tiempo para que no te moleste. La contraseña es una comodidad de baja fricción y una señal de transparencia de que el sistema no compartirá tu credencial de forma silenciosa, no una barrera frente a quien posea la clave del sistema. Estos modelos no se pueden usar en programaciones recurrentes.",
|
|
74
|
+
"vendorField": "Suscripción",
|
|
75
|
+
"labelField": "Etiqueta (opcional)",
|
|
76
|
+
"labelPlaceholder": "p. ej. mi {vendor}",
|
|
77
|
+
"defaultLabel": "Mi suscripción de {vendor}",
|
|
78
|
+
"passwordField": "Contraseña personal (mín. 6 caracteres)",
|
|
79
|
+
"passwordPlaceholder": "protege tu token",
|
|
80
|
+
"renewsField": "La suscripción se renueva el (opcional)",
|
|
81
|
+
"connect": "Conectar",
|
|
82
|
+
"replace": "Reemplazar",
|
|
83
|
+
"expires": "Caduca el {date}",
|
|
84
|
+
"noExpiry": "Sin fecha de caducidad",
|
|
85
|
+
"renewal": {
|
|
86
|
+
"expired": "Tu suscripción de {vendor} ha caducado. Renuévala y vuelve a conectarla para seguir ejecutando sus modelos.",
|
|
87
|
+
"soon": "Tu suscripción de {vendor} se renueva en {count} día. Actualízala aquí cuando se renueve. | Tu suscripción de {vendor} se renueva en {count} días. Actualízala aquí cuando se renueve."
|
|
88
|
+
},
|
|
89
|
+
"toast": {
|
|
90
|
+
"connected": "Suscripción de {vendor} conectada",
|
|
91
|
+
"connectFailed": "No se pudo conectar la suscripción",
|
|
92
|
+
"disconnected": "Desconectada",
|
|
93
|
+
"disconnectFailed": "No se pudo desconectar"
|
|
94
|
+
},
|
|
95
|
+
"vendors": {
|
|
96
|
+
"claude": {
|
|
97
|
+
"label": "Claude (Pro/Max)",
|
|
98
|
+
"tokenLabel": "Token de Claude",
|
|
99
|
+
"step1": "Instala Claude Code e inicia sesión con tu cuenta de Claude Pro/Max: ejecuta `claude` una vez y completa el inicio de sesión en el navegador.",
|
|
100
|
+
"step2": "Genera un token de larga duración: ejecuta `claude setup-token` y cópialo.",
|
|
101
|
+
"step3": "Pégalo abajo y elige una contraseña personal para protegerlo."
|
|
102
|
+
},
|
|
103
|
+
"glm": {
|
|
104
|
+
"label": "GLM (Z.ai Coding Plan)",
|
|
105
|
+
"tokenLabel": "Clave de API de Z.ai",
|
|
106
|
+
"tokenPlaceholder": "tu clave de API del GLM Coding Plan",
|
|
107
|
+
"step1": "Abre tu panel del GLM Coding Plan de Z.ai y crea una clave de API para el endpoint compatible con Anthropic.",
|
|
108
|
+
"step2": "El GLM Coding Plan tiene licencia para ti como individuo, así que aquí se guarda por usuario (no se agrupa).",
|
|
109
|
+
"step3": "Pega la clave abajo y elige una contraseña personal para protegerla."
|
|
110
|
+
},
|
|
111
|
+
"codex": {
|
|
112
|
+
"label": "ChatGPT (Codex)",
|
|
113
|
+
"tokenLabel": "auth.json de ChatGPT",
|
|
114
|
+
"step1": "Instala la CLI de Codex e inicia sesión con tu cuenta de ChatGPT: ejecuta `codex login` y completa el flujo en el navegador.",
|
|
115
|
+
"step2": "Abre el archivo de credenciales que Codex escribió en ~/.codex/auth.json (en Windows %USERPROFILE%\\.codex\\auth.json).",
|
|
116
|
+
"step3": "Copia todo el contenido de auth.json, pégalo abajo y elige una contraseña personal para protegerlo."
|
|
117
|
+
}
|
|
118
|
+
}
|
|
70
119
|
}
|
|
71
120
|
}
|
package/i18n/locales/fr.json
CHANGED
|
@@ -67,5 +67,54 @@
|
|
|
67
67
|
"action": "Configurer l’IA"
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
+
},
|
|
71
|
+
"personalSubscriptions": {
|
|
72
|
+
"heading": "Abonnements personnels (usage individuel uniquement)",
|
|
73
|
+
"intro": "Claude (Pro/Max), GLM (Z.ai Coding Plan) et ChatGPT (Codex) vous sont concédés sous licence à titre individuel ; ils sont donc enregistrés rien que pour vous et seules vos exécutions les utilisent. Chaque jeton est chiffré avec un mot de passe personnel (jamais stocké) que vous saisissez au démarrage d'une telle exécution ; il est mis en cache dans ce navigateur pendant un certain temps pour ne pas vous gêner. Le mot de passe est une commodité à faible friction et un signal de transparence indiquant que le système ne partagera pas votre identifiant en silence, pas un rempart contre le détenteur de la clé système. Ces modèles ne peuvent pas être utilisés dans des planifications récurrentes.",
|
|
74
|
+
"vendorField": "Abonnement",
|
|
75
|
+
"labelField": "Libellé (facultatif)",
|
|
76
|
+
"labelPlaceholder": "p. ex. mon {vendor}",
|
|
77
|
+
"defaultLabel": "Mon abonnement {vendor}",
|
|
78
|
+
"passwordField": "Mot de passe personnel (6 caractères min.)",
|
|
79
|
+
"passwordPlaceholder": "protège votre jeton",
|
|
80
|
+
"renewsField": "L'abonnement se renouvelle le (facultatif)",
|
|
81
|
+
"connect": "Connecter",
|
|
82
|
+
"replace": "Remplacer",
|
|
83
|
+
"expires": "Expire le {date}",
|
|
84
|
+
"noExpiry": "Aucune date d'expiration",
|
|
85
|
+
"renewal": {
|
|
86
|
+
"expired": "Votre abonnement {vendor} a expiré. Renouvelez-le et reconnectez-le pour continuer à exécuter ses modèles.",
|
|
87
|
+
"soon": "Votre abonnement {vendor} se renouvelle dans {count} jour. Mettez-le à jour ici une fois renouvelé. | Votre abonnement {vendor} se renouvelle dans {count} jours. Mettez-le à jour ici une fois renouvelé."
|
|
88
|
+
},
|
|
89
|
+
"toast": {
|
|
90
|
+
"connected": "Abonnement {vendor} connecté",
|
|
91
|
+
"connectFailed": "Impossible de connecter l'abonnement",
|
|
92
|
+
"disconnected": "Déconnecté",
|
|
93
|
+
"disconnectFailed": "Impossible de déconnecter"
|
|
94
|
+
},
|
|
95
|
+
"vendors": {
|
|
96
|
+
"claude": {
|
|
97
|
+
"label": "Claude (Pro/Max)",
|
|
98
|
+
"tokenLabel": "Jeton Claude",
|
|
99
|
+
"step1": "Installez Claude Code et connectez-vous avec votre compte Claude Pro/Max : exécutez `claude` une fois et terminez la connexion dans le navigateur.",
|
|
100
|
+
"step2": "Générez un jeton de longue durée : exécutez `claude setup-token` et copiez-le.",
|
|
101
|
+
"step3": "Collez-le ci-dessous et choisissez un mot de passe personnel pour le protéger."
|
|
102
|
+
},
|
|
103
|
+
"glm": {
|
|
104
|
+
"label": "GLM (Z.ai Coding Plan)",
|
|
105
|
+
"tokenLabel": "Clé API Z.ai",
|
|
106
|
+
"tokenPlaceholder": "votre clé API du GLM Coding Plan",
|
|
107
|
+
"step1": "Ouvrez votre tableau de bord GLM Coding Plan de Z.ai et créez une clé API pour le point de terminaison compatible Anthropic.",
|
|
108
|
+
"step2": "Le GLM Coding Plan vous est concédé sous licence à titre individuel ; il est donc enregistré par utilisateur ici (non mutualisé).",
|
|
109
|
+
"step3": "Collez la clé ci-dessous et choisissez un mot de passe personnel pour la protéger."
|
|
110
|
+
},
|
|
111
|
+
"codex": {
|
|
112
|
+
"label": "ChatGPT (Codex)",
|
|
113
|
+
"tokenLabel": "auth.json de ChatGPT",
|
|
114
|
+
"step1": "Installez la CLI Codex et connectez-vous avec votre compte ChatGPT : exécutez `codex login` et terminez le flux dans le navigateur.",
|
|
115
|
+
"step2": "Ouvrez le fichier d'identifiants que Codex a écrit dans ~/.codex/auth.json (sous Windows %USERPROFILE%\\.codex\\auth.json).",
|
|
116
|
+
"step3": "Copiez tout le contenu de auth.json, collez-le ci-dessous et choisissez un mot de passe personnel pour le protéger."
|
|
117
|
+
}
|
|
118
|
+
}
|
|
70
119
|
}
|
|
71
120
|
}
|
package/i18n/locales/pl.json
CHANGED
|
@@ -67,5 +67,54 @@
|
|
|
67
67
|
"action": "Skonfiguruj AI"
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
+
},
|
|
71
|
+
"personalSubscriptions": {
|
|
72
|
+
"heading": "Subskrypcje osobiste (tylko do użytku indywidualnego)",
|
|
73
|
+
"intro": "Claude (Pro/Max), GLM (Z.ai Coding Plan) i ChatGPT (Codex) są licencjonowane dla Ciebie jako osoby prywatnej, więc są przechowywane wyłącznie dla Ciebie i korzystają z nich tylko Twoje uruchomienia. Każdy token jest szyfrowany osobistym hasłem (nigdy nieprzechowywanym), które podajesz przy uruchamianiu takiego zadania; jest ono buforowane w tej przeglądarce przez pewien czas, aby Ci nie przeszkadzać. Hasło to wygodne, mało uciążliwe rozwiązanie i sygnał przejrzystości, że system nie udostępni po cichu Twoich poświadczeń, a nie zabezpieczenie przed posiadaczem klucza systemowego. Tych modeli nie można używać w harmonogramach cyklicznych.",
|
|
74
|
+
"vendorField": "Subskrypcja",
|
|
75
|
+
"labelField": "Etykieta (opcjonalnie)",
|
|
76
|
+
"labelPlaceholder": "np. mój {vendor}",
|
|
77
|
+
"defaultLabel": "Moja subskrypcja {vendor}",
|
|
78
|
+
"passwordField": "Hasło osobiste (min. 6 znaków)",
|
|
79
|
+
"passwordPlaceholder": "chroni Twój token",
|
|
80
|
+
"renewsField": "Subskrypcja odnawia się (opcjonalnie)",
|
|
81
|
+
"connect": "Połącz",
|
|
82
|
+
"replace": "Zastąp",
|
|
83
|
+
"expires": "Wygasa {date}",
|
|
84
|
+
"noExpiry": "Brak daty wygaśnięcia",
|
|
85
|
+
"renewal": {
|
|
86
|
+
"expired": "Twoja subskrypcja {vendor} wygasła. Odnów ją i połącz ponownie, aby nadal uruchamiać jej modele.",
|
|
87
|
+
"soon": "Twoja subskrypcja {vendor} odnawia się za {count} dzień. Zaktualizuj ją tutaj po odnowieniu. | Twoja subskrypcja {vendor} odnawia się za {count} dni. Zaktualizuj ją tutaj po odnowieniu. | Twoja subskrypcja {vendor} odnawia się za {count} dni. Zaktualizuj ją tutaj po odnowieniu."
|
|
88
|
+
},
|
|
89
|
+
"toast": {
|
|
90
|
+
"connected": "Połączono subskrypcję {vendor}",
|
|
91
|
+
"connectFailed": "Nie udało się połączyć subskrypcji",
|
|
92
|
+
"disconnected": "Rozłączono",
|
|
93
|
+
"disconnectFailed": "Nie udało się rozłączyć"
|
|
94
|
+
},
|
|
95
|
+
"vendors": {
|
|
96
|
+
"claude": {
|
|
97
|
+
"label": "Claude (Pro/Max)",
|
|
98
|
+
"tokenLabel": "Token Claude",
|
|
99
|
+
"step1": "Zainstaluj Claude Code i zaloguj się na konto Claude Pro/Max: uruchom `claude` raz i dokończ logowanie w przeglądarce.",
|
|
100
|
+
"step2": "Wygeneruj długotrwały token: uruchom `claude setup-token` i skopiuj go.",
|
|
101
|
+
"step3": "Wklej go poniżej i wybierz osobiste hasło, aby go chronić."
|
|
102
|
+
},
|
|
103
|
+
"glm": {
|
|
104
|
+
"label": "GLM (Z.ai Coding Plan)",
|
|
105
|
+
"tokenLabel": "Klucz API Z.ai",
|
|
106
|
+
"tokenPlaceholder": "Twój klucz API GLM Coding Plan",
|
|
107
|
+
"step1": "Otwórz panel GLM Coding Plan w Z.ai i utwórz klucz API dla punktu końcowego zgodnego z Anthropic.",
|
|
108
|
+
"step2": "GLM Coding Plan jest licencjonowany dla Ciebie jako osoby prywatnej, więc tutaj jest przechowywany osobno dla każdego użytkownika (nie jest współdzielony).",
|
|
109
|
+
"step3": "Wklej klucz poniżej i wybierz osobiste hasło, aby go chronić."
|
|
110
|
+
},
|
|
111
|
+
"codex": {
|
|
112
|
+
"label": "ChatGPT (Codex)",
|
|
113
|
+
"tokenLabel": "auth.json ChatGPT",
|
|
114
|
+
"step1": "Zainstaluj Codex CLI i zaloguj się na konto ChatGPT: uruchom `codex login` i dokończ proces w przeglądarce.",
|
|
115
|
+
"step2": "Otwórz plik poświadczeń zapisany przez Codex w ~/.codex/auth.json (w systemie Windows %USERPROFILE%\\.codex\\auth.json).",
|
|
116
|
+
"step3": "Skopiuj całą zawartość auth.json, wklej ją poniżej i wybierz osobiste hasło, aby ją chronić."
|
|
117
|
+
}
|
|
118
|
+
}
|
|
70
119
|
}
|
|
71
120
|
}
|
package/i18n/locales/uk.json
CHANGED
|
@@ -67,5 +67,54 @@
|
|
|
67
67
|
"action": "Налаштувати ШІ"
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
+
},
|
|
71
|
+
"personalSubscriptions": {
|
|
72
|
+
"heading": "Особисті підписки (лише для індивідуального використання)",
|
|
73
|
+
"intro": "Claude (Pro/Max), GLM (Z.ai Coding Plan) і ChatGPT (Codex) ліцензовані для вас як для приватної особи, тож зберігаються лише для вас, і їх використовують тільки ваші запуски. Кожен токен шифрується особистим паролем (який ніколи не зберігається), який ви вводите під час запуску такого завдання; він кешується в цьому браузері на деякий час, щоб не заважати вам. Пароль забезпечує зручність із низьким тертям і слугує сигналом прозорості, що система не передасть ваші облікові дані потайки; це не бар'єр проти власника системного ключа. Ці моделі не можна використовувати в повторюваних розкладах.",
|
|
74
|
+
"vendorField": "Підписка",
|
|
75
|
+
"labelField": "Мітка (необов'язково)",
|
|
76
|
+
"labelPlaceholder": "напр., мій {vendor}",
|
|
77
|
+
"defaultLabel": "Моя підписка {vendor}",
|
|
78
|
+
"passwordField": "Особистий пароль (мін. 6 символів)",
|
|
79
|
+
"passwordPlaceholder": "захищає ваш токен",
|
|
80
|
+
"renewsField": "Підписка поновлюється (необов'язково)",
|
|
81
|
+
"connect": "Підключити",
|
|
82
|
+
"replace": "Замінити",
|
|
83
|
+
"expires": "Завершується {date}",
|
|
84
|
+
"noExpiry": "Дата завершення не вказана",
|
|
85
|
+
"renewal": {
|
|
86
|
+
"expired": "Термін дії вашої підписки {vendor} закінчився. Поновіть її та підключіть знову, щоб продовжити запускати її моделі.",
|
|
87
|
+
"soon": "Ваша підписка {vendor} поновлюється через {count} день. Оновіть її тут після поновлення. | Ваша підписка {vendor} поновлюється через {count} дні. Оновіть її тут після поновлення. | Ваша підписка {vendor} поновлюється через {count} днів. Оновіть її тут після поновлення."
|
|
88
|
+
},
|
|
89
|
+
"toast": {
|
|
90
|
+
"connected": "Підписку {vendor} підключено",
|
|
91
|
+
"connectFailed": "Не вдалося підключити підписку",
|
|
92
|
+
"disconnected": "Відключено",
|
|
93
|
+
"disconnectFailed": "Не вдалося відключити"
|
|
94
|
+
},
|
|
95
|
+
"vendors": {
|
|
96
|
+
"claude": {
|
|
97
|
+
"label": "Claude (Pro/Max)",
|
|
98
|
+
"tokenLabel": "Токен Claude",
|
|
99
|
+
"step1": "Встановіть Claude Code й увійдіть у свій обліковий запис Claude Pro/Max: запустіть `claude` один раз і завершіть вхід у браузері.",
|
|
100
|
+
"step2": "Згенеруйте довготривалий токен: запустіть `claude setup-token` і скопіюйте його.",
|
|
101
|
+
"step3": "Вставте його нижче та виберіть особистий пароль для його захисту."
|
|
102
|
+
},
|
|
103
|
+
"glm": {
|
|
104
|
+
"label": "GLM (Z.ai Coding Plan)",
|
|
105
|
+
"tokenLabel": "Ключ API Z.ai",
|
|
106
|
+
"tokenPlaceholder": "ваш ключ API GLM Coding Plan",
|
|
107
|
+
"step1": "Відкрийте панель GLM Coding Plan у Z.ai і створіть ключ API для сумісної з Anthropic кінцевої точки.",
|
|
108
|
+
"step2": "GLM Coding Plan ліцензований для вас як для приватної особи, тож тут він зберігається окремо для кожного користувача (не об'єднується в пул).",
|
|
109
|
+
"step3": "Вставте ключ нижче та виберіть особистий пароль для його захисту."
|
|
110
|
+
},
|
|
111
|
+
"codex": {
|
|
112
|
+
"label": "ChatGPT (Codex)",
|
|
113
|
+
"tokenLabel": "auth.json ChatGPT",
|
|
114
|
+
"step1": "Встановіть Codex CLI й увійдіть у свій обліковий запис ChatGPT: запустіть `codex login` і завершіть процес у браузері.",
|
|
115
|
+
"step2": "Відкрийте файл облікових даних, який Codex записав у ~/.codex/auth.json (у Windows %USERPROFILE%\\.codex\\auth.json).",
|
|
116
|
+
"step3": "Скопіюйте весь вміст auth.json, вставте його нижче та виберіть особистий пароль для його захисту."
|
|
117
|
+
}
|
|
118
|
+
}
|
|
70
119
|
}
|
|
71
120
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.46.
|
|
3
|
+
"version": "0.46.9",
|
|
4
4
|
"description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"@nuxt/ui": "^4.9.0",
|
|
22
22
|
"@nuxtjs/i18n": "^10.4.0",
|
|
23
23
|
"@pinia/nuxt": "^0.11.3",
|
|
24
|
-
"@toad-contracts/core": "0.
|
|
25
|
-
"@toad-contracts/frontend-http-client": "0.3.
|
|
26
|
-
"@toad-contracts/valibot": "0.
|
|
24
|
+
"@toad-contracts/core": "0.4.0",
|
|
25
|
+
"@toad-contracts/frontend-http-client": "0.3.2",
|
|
26
|
+
"@toad-contracts/valibot": "0.5.0",
|
|
27
27
|
"@vue-flow/background": "^1.3.2",
|
|
28
28
|
"@vue-flow/core": "^1.48.2",
|
|
29
29
|
"@vue-flow/node-resizer": "^1.5.1",
|
|
@@ -31,15 +31,15 @@
|
|
|
31
31
|
"markdown-it": "^14.2.0",
|
|
32
32
|
"pinia": "^3.0.4",
|
|
33
33
|
"pinia-plugin-persistedstate": "^4.7.1",
|
|
34
|
-
"vue": "^3.5.
|
|
34
|
+
"vue": "^3.5.39",
|
|
35
35
|
"wretch": "^3.0.9",
|
|
36
|
-
"@cat-factory/contracts": "0.43.
|
|
36
|
+
"@cat-factory/contracts": "0.43.3"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@toad-contracts/testing": "0.3.
|
|
39
|
+
"@toad-contracts/testing": "0.3.2",
|
|
40
40
|
"@types/markdown-it": "^14.1.2",
|
|
41
41
|
"happy-dom": "^20.10.6",
|
|
42
|
-
"msw": "^2.6
|
|
42
|
+
"msw": "^2.14.6",
|
|
43
43
|
"nuxt": "^4.4.8",
|
|
44
44
|
"typescript": "^6.0.3",
|
|
45
45
|
"vitest": "^4.1.9",
|