@cat-factory/app 0.127.0 → 0.129.0
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/layout/NotificationsInbox.vue +7 -0
- package/app/components/settings/ApiTokensPanel.vue +18 -0
- package/app/components/slack/SlackPanel.vue +2 -0
- package/app/stores/publicApiKeys.spec.ts +1 -0
- package/i18n/locales/de.json +4 -0
- package/i18n/locales/en.json +4 -0
- package/i18n/locales/es.json +4 -0
- package/i18n/locales/fr.json +4 -0
- package/i18n/locales/he.json +4 -0
- package/i18n/locales/it.json +4 -0
- package/i18n/locales/ja.json +4 -0
- package/i18n/locales/pl.json +4 -0
- package/i18n/locales/tr.json +4 -0
- package/i18n/locales/uk.json +4 -0
- package/package.json +2 -2
|
@@ -70,6 +70,9 @@ const META: Record<Notification['type'], { icon: string; color: Accent }> = {
|
|
|
70
70
|
// The initiative loop needs attention (a blocked task, or completion). Clicking the title
|
|
71
71
|
// opens the initiative tracker window; "act" just marks it read.
|
|
72
72
|
initiative: { icon: 'i-lucide-milestone', color: 'primary' },
|
|
73
|
+
// The deployment's OWN run health crossed an operator threshold. Not block-scoped: clicking
|
|
74
|
+
// the title opens the operator dashboard (where the live numbers are); "act" marks it read.
|
|
75
|
+
platform_health: { icon: 'i-lucide-server-cog', color: 'warning' },
|
|
73
76
|
// Runs were paused by the spend safeguard. Workspace-scoped (no block to reveal); "act" just
|
|
74
77
|
// marks it read (the human raises the budget then resumes from the spend panel).
|
|
75
78
|
budget_paused: { icon: 'i-lucide-wallet', color: 'warning' },
|
|
@@ -94,6 +97,7 @@ const ACTION_KEYS: Record<Notification['type'], string> = {
|
|
|
94
97
|
fork_decision_pending: 'layout.notifications.action.fork_decision_pending',
|
|
95
98
|
pr_review_ready: 'layout.notifications.action.pr_review_ready',
|
|
96
99
|
initiative: 'layout.notifications.action.initiative',
|
|
100
|
+
platform_health: 'layout.notifications.action.platform_health',
|
|
97
101
|
budget_paused: 'layout.notifications.action.budget_paused',
|
|
98
102
|
}
|
|
99
103
|
|
|
@@ -156,6 +160,9 @@ async function dismiss(n: Notification) {
|
|
|
156
160
|
* type just focuses the related block on the board.
|
|
157
161
|
*/
|
|
158
162
|
function reveal(n: Notification) {
|
|
163
|
+
// A `platform_health` card is deployment-scoped (no block) — send the operator to the
|
|
164
|
+
// dashboard where the live aggregate numbers behind the alert live.
|
|
165
|
+
if (n.type === 'platform_health') return ui.openOperatorDashboard()
|
|
159
166
|
if (!n.blockId) return
|
|
160
167
|
if (n.type === 'requirement_review') ui.openRequirementReview(n.blockId)
|
|
161
168
|
else if (n.type === 'clarity_review') ui.openClarityReview(n.blockId)
|
|
@@ -30,7 +30,21 @@ function scopeLabel(scope: PublicApiScope): string {
|
|
|
30
30
|
|
|
31
31
|
const scopeItems = computed(() => SCOPES.map((value) => ({ value, label: scopeLabel(value) })))
|
|
32
32
|
const ui = useUiStore()
|
|
33
|
+
const auth = useAuthStore()
|
|
33
34
|
const store = usePublicApiKeysStore()
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The minter to attribute a key to. `null` when the key predates the audit column (or was
|
|
38
|
+
* minted with no session), so the row simply omits the segment. When the minter is the
|
|
39
|
+
* signed-in user we show a localized "you"; otherwise the raw `usr_*` id (the list has no
|
|
40
|
+
* user-name lookup — the audit id is the honest, non-misleading thing to show).
|
|
41
|
+
*/
|
|
42
|
+
function minterLabel(key: PublicApiKey): string | null {
|
|
43
|
+
if (!key.createdByUserId) return null
|
|
44
|
+
return key.createdByUserId === auth.user?.id
|
|
45
|
+
? t('settings.apiTokens.list.createdByYou')
|
|
46
|
+
: key.createdByUserId
|
|
47
|
+
}
|
|
34
48
|
const toast = useToast()
|
|
35
49
|
const { confirmAction, toastDone } = useConfirmAction()
|
|
36
50
|
|
|
@@ -191,6 +205,10 @@ async function revokeToken(key: PublicApiKey) {
|
|
|
191
205
|
})
|
|
192
206
|
}}</template>
|
|
193
207
|
<template v-else>{{ t('settings.apiTokens.list.neverUsed') }}</template>
|
|
208
|
+
<template v-if="minterLabel(key)">
|
|
209
|
+
<span aria-hidden="true"> · </span>
|
|
210
|
+
{{ t('settings.apiTokens.list.createdBy', { user: minterLabel(key) }) }}
|
|
211
|
+
</template>
|
|
194
212
|
</div>
|
|
195
213
|
</div>
|
|
196
214
|
<UButton
|
|
@@ -41,6 +41,7 @@ const ROUTABLE = computed<{ type: NotificationType; label: string }[]>(() => [
|
|
|
41
41
|
{ type: 'visual_confirmation_ready', label: t('slack.routable.visual_confirmation_ready') },
|
|
42
42
|
{ type: 'pr_review_ready', label: t('slack.routable.pr_review_ready') },
|
|
43
43
|
{ type: 'initiative', label: t('slack.routable.initiative') },
|
|
44
|
+
{ type: 'platform_health', label: t('slack.routable.platform_health') },
|
|
44
45
|
])
|
|
45
46
|
|
|
46
47
|
/** Notification-role options for a mapped member (drives who gets @-mentioned). */
|
|
@@ -67,6 +68,7 @@ const routes = reactive<Record<NotificationType, SlackRoute>>({
|
|
|
67
68
|
fork_decision_pending: { enabled: false, channel: '' },
|
|
68
69
|
pr_review_ready: { enabled: false, channel: '' },
|
|
69
70
|
initiative: { enabled: false, channel: '' },
|
|
71
|
+
platform_health: { enabled: false, channel: '' },
|
|
70
72
|
budget_paused: { enabled: false, channel: '' },
|
|
71
73
|
})
|
|
72
74
|
const mentionsEnabled = ref(false)
|
package/i18n/locales/de.json
CHANGED
|
@@ -534,6 +534,8 @@
|
|
|
534
534
|
"created": "Erstellt am {date}",
|
|
535
535
|
"lastUsed": "zuletzt verwendet am {date}",
|
|
536
536
|
"neverUsed": "nie verwendet",
|
|
537
|
+
"createdBy": "erstellt von {user}",
|
|
538
|
+
"createdByYou": "Ihnen",
|
|
537
539
|
"revoke": "Token widerrufen"
|
|
538
540
|
},
|
|
539
541
|
"add": {
|
|
@@ -1729,6 +1731,7 @@
|
|
|
1729
1731
|
"requirement_review": "Als gelesen markieren",
|
|
1730
1732
|
"clarity_review": "Als gelesen markieren",
|
|
1731
1733
|
"release_regression": "Bestätigen",
|
|
1734
|
+
"platform_health": "Bestätigen",
|
|
1732
1735
|
"decision_required": "Als gelesen markieren",
|
|
1733
1736
|
"human_test_ready": "Als gelesen markieren",
|
|
1734
1737
|
"visual_confirmation_ready": "Als gelesen markieren",
|
|
@@ -4043,6 +4046,7 @@
|
|
|
4043
4046
|
"incompleteBody": "Gib vor dem Speichern sowohl die Benutzer-ID als auch die Slack-Mitglieds-ID ein oder entferne die Zeile."
|
|
4044
4047
|
},
|
|
4045
4048
|
"routable": {
|
|
4049
|
+
"platform_health": "Plattformzustand",
|
|
4046
4050
|
"merge_review": "Merge-Review",
|
|
4047
4051
|
"pipeline_complete": "Pipeline abgeschlossen",
|
|
4048
4052
|
"ci_failed": "CI fehlgeschlagen",
|
package/i18n/locales/en.json
CHANGED
|
@@ -1696,6 +1696,7 @@
|
|
|
1696
1696
|
"requirement_review": "Mark read",
|
|
1697
1697
|
"clarity_review": "Mark read",
|
|
1698
1698
|
"release_regression": "Acknowledge",
|
|
1699
|
+
"platform_health": "Acknowledge",
|
|
1699
1700
|
"decision_required": "Mark read",
|
|
1700
1701
|
"human_test_ready": "Mark read",
|
|
1701
1702
|
"visual_confirmation_ready": "Mark read",
|
|
@@ -2482,6 +2483,8 @@
|
|
|
2482
2483
|
"created": "Created {date}",
|
|
2483
2484
|
"lastUsed": "last used {date}",
|
|
2484
2485
|
"neverUsed": "never used",
|
|
2486
|
+
"createdBy": "created by {user}",
|
|
2487
|
+
"createdByYou": "you",
|
|
2485
2488
|
"revoke": "Revoke token"
|
|
2486
2489
|
},
|
|
2487
2490
|
"add": {
|
|
@@ -3188,6 +3191,7 @@
|
|
|
3188
3191
|
"incompleteBody": "Fill in both the user id and the Slack member id, or remove the row, before saving."
|
|
3189
3192
|
},
|
|
3190
3193
|
"routable": {
|
|
3194
|
+
"platform_health": "Platform health",
|
|
3191
3195
|
"merge_review": "Merge review",
|
|
3192
3196
|
"pipeline_complete": "Pipeline complete",
|
|
3193
3197
|
"ci_failed": "CI failed",
|
package/i18n/locales/es.json
CHANGED
|
@@ -1630,6 +1630,7 @@
|
|
|
1630
1630
|
"requirement_review": "Marcar como leída",
|
|
1631
1631
|
"clarity_review": "Marcar como leída",
|
|
1632
1632
|
"release_regression": "Confirmar recepción",
|
|
1633
|
+
"platform_health": "Confirmar recepción",
|
|
1633
1634
|
"decision_required": "Marcar como leída",
|
|
1634
1635
|
"human_test_ready": "Marcar como leída",
|
|
1635
1636
|
"visual_confirmation_ready": "Marcar como leída",
|
|
@@ -2297,6 +2298,8 @@
|
|
|
2297
2298
|
"created": "Creado el {date}",
|
|
2298
2299
|
"lastUsed": "usado por última vez el {date}",
|
|
2299
2300
|
"neverUsed": "nunca usado",
|
|
2301
|
+
"createdBy": "creado por {user}",
|
|
2302
|
+
"createdByYou": "ti",
|
|
2300
2303
|
"revoke": "Revocar token"
|
|
2301
2304
|
},
|
|
2302
2305
|
"add": {
|
|
@@ -3095,6 +3098,7 @@
|
|
|
3095
3098
|
"incompleteBody": "Antes de guardar, completa tanto el id de usuario como el id de miembro de Slack, o elimina la fila."
|
|
3096
3099
|
},
|
|
3097
3100
|
"routable": {
|
|
3101
|
+
"platform_health": "Estado de la plataforma",
|
|
3098
3102
|
"merge_review": "Revision de fusion",
|
|
3099
3103
|
"pipeline_complete": "Pipeline completado",
|
|
3100
3104
|
"ci_failed": "CI fallido",
|
package/i18n/locales/fr.json
CHANGED
|
@@ -1630,6 +1630,7 @@
|
|
|
1630
1630
|
"requirement_review": "Marquer comme lu",
|
|
1631
1631
|
"clarity_review": "Marquer comme lu",
|
|
1632
1632
|
"release_regression": "Accuser réception",
|
|
1633
|
+
"platform_health": "Accuser réception",
|
|
1633
1634
|
"decision_required": "Marquer comme lu",
|
|
1634
1635
|
"human_test_ready": "Marquer comme lu",
|
|
1635
1636
|
"visual_confirmation_ready": "Marquer comme lu",
|
|
@@ -2297,6 +2298,8 @@
|
|
|
2297
2298
|
"created": "Créé le {date}",
|
|
2298
2299
|
"lastUsed": "dernière utilisation le {date}",
|
|
2299
2300
|
"neverUsed": "jamais utilisé",
|
|
2301
|
+
"createdBy": "créé par {user}",
|
|
2302
|
+
"createdByYou": "vous",
|
|
2300
2303
|
"revoke": "Révoquer le jeton"
|
|
2301
2304
|
},
|
|
2302
2305
|
"add": {
|
|
@@ -3095,6 +3098,7 @@
|
|
|
3095
3098
|
"incompleteBody": "Avant d’enregistrer, renseignez l’id utilisateur et l’id de membre Slack, ou supprimez la ligne."
|
|
3096
3099
|
},
|
|
3097
3100
|
"routable": {
|
|
3101
|
+
"platform_health": "Santé de la plateforme",
|
|
3098
3102
|
"merge_review": "Revue de fusion",
|
|
3099
3103
|
"pipeline_complete": "Pipeline termine",
|
|
3100
3104
|
"ci_failed": "Echec de CI",
|
package/i18n/locales/he.json
CHANGED
|
@@ -1630,6 +1630,7 @@
|
|
|
1630
1630
|
"requirement_review": "סמן כנקרא",
|
|
1631
1631
|
"clarity_review": "סמן כנקרא",
|
|
1632
1632
|
"release_regression": "אשר",
|
|
1633
|
+
"platform_health": "אשר",
|
|
1633
1634
|
"decision_required": "סמן כנקרא",
|
|
1634
1635
|
"human_test_ready": "סמן כנקרא",
|
|
1635
1636
|
"visual_confirmation_ready": "סמן כנקרא",
|
|
@@ -2418,6 +2419,8 @@
|
|
|
2418
2419
|
"created": "נוצר בתאריך {date}",
|
|
2419
2420
|
"lastUsed": "שימוש אחרון בתאריך {date}",
|
|
2420
2421
|
"neverUsed": "מעולם לא היה בשימוש",
|
|
2422
|
+
"createdBy": "נוצר על ידי {user}",
|
|
2423
|
+
"createdByYou": "אתה",
|
|
2421
2424
|
"revoke": "בטל אסימון"
|
|
2422
2425
|
},
|
|
2423
2426
|
"add": {
|
|
@@ -3106,6 +3109,7 @@
|
|
|
3106
3109
|
"incompleteBody": "לפני השמירה מלא גם את מזהה המשתמש וגם את מזהה החבר ב-Slack, או הסר את השורה."
|
|
3107
3110
|
},
|
|
3108
3111
|
"routable": {
|
|
3112
|
+
"platform_health": "תקינות הפלטפורמה",
|
|
3109
3113
|
"merge_review": "סקירת מיזוג",
|
|
3110
3114
|
"pipeline_complete": "הצינור הושלם",
|
|
3111
3115
|
"ci_failed": "CI נכשל",
|
package/i18n/locales/it.json
CHANGED
|
@@ -534,6 +534,8 @@
|
|
|
534
534
|
"created": "Creato il {date}",
|
|
535
535
|
"lastUsed": "ultimo utilizzo il {date}",
|
|
536
536
|
"neverUsed": "mai utilizzato",
|
|
537
|
+
"createdBy": "creato da {user}",
|
|
538
|
+
"createdByYou": "te",
|
|
537
539
|
"revoke": "Revoca token"
|
|
538
540
|
},
|
|
539
541
|
"add": {
|
|
@@ -1729,6 +1731,7 @@
|
|
|
1729
1731
|
"requirement_review": "Segna come letto",
|
|
1730
1732
|
"clarity_review": "Segna come letto",
|
|
1731
1733
|
"release_regression": "Conferma presa visione",
|
|
1734
|
+
"platform_health": "Conferma presa visione",
|
|
1732
1735
|
"decision_required": "Segna come letto",
|
|
1733
1736
|
"human_test_ready": "Segna come letto",
|
|
1734
1737
|
"visual_confirmation_ready": "Segna come letto",
|
|
@@ -4043,6 +4046,7 @@
|
|
|
4043
4046
|
"incompleteBody": "Prima di salvare, compila sia l’id utente sia l’id membro Slack, oppure rimuovi la riga."
|
|
4044
4047
|
},
|
|
4045
4048
|
"routable": {
|
|
4049
|
+
"platform_health": "Salute della piattaforma",
|
|
4046
4050
|
"merge_review": "Revisione del merge",
|
|
4047
4051
|
"pipeline_complete": "Pipeline completata",
|
|
4048
4052
|
"ci_failed": "CI non riuscita",
|
package/i18n/locales/ja.json
CHANGED
|
@@ -1630,6 +1630,7 @@
|
|
|
1630
1630
|
"requirement_review": "既読にする",
|
|
1631
1631
|
"clarity_review": "既読にする",
|
|
1632
1632
|
"release_regression": "確認",
|
|
1633
|
+
"platform_health": "確認",
|
|
1633
1634
|
"decision_required": "既読にする",
|
|
1634
1635
|
"human_test_ready": "既読にする",
|
|
1635
1636
|
"visual_confirmation_ready": "既読にする",
|
|
@@ -2419,6 +2420,8 @@
|
|
|
2419
2420
|
"created": "{date} に作成",
|
|
2420
2421
|
"lastUsed": "最終使用 {date}",
|
|
2421
2422
|
"neverUsed": "未使用",
|
|
2423
|
+
"createdBy": "作成者: {user}",
|
|
2424
|
+
"createdByYou": "あなた",
|
|
2422
2425
|
"revoke": "トークンを取り消す"
|
|
2423
2426
|
},
|
|
2424
2427
|
"add": {
|
|
@@ -3107,6 +3110,7 @@
|
|
|
3107
3110
|
"incompleteBody": "保存する前に、ユーザー ID と Slack メンバー ID の両方を入力するか、行を削除してください。"
|
|
3108
3111
|
},
|
|
3109
3112
|
"routable": {
|
|
3113
|
+
"platform_health": "プラットフォームの健全性",
|
|
3110
3114
|
"merge_review": "マージレビュー",
|
|
3111
3115
|
"pipeline_complete": "パイプライン完了",
|
|
3112
3116
|
"ci_failed": "CI失敗",
|
package/i18n/locales/pl.json
CHANGED
|
@@ -1630,6 +1630,7 @@
|
|
|
1630
1630
|
"requirement_review": "Oznacz jako przeczytane",
|
|
1631
1631
|
"clarity_review": "Oznacz jako przeczytane",
|
|
1632
1632
|
"release_regression": "Potwierdź",
|
|
1633
|
+
"platform_health": "Potwierdź",
|
|
1633
1634
|
"decision_required": "Oznacz jako przeczytane",
|
|
1634
1635
|
"human_test_ready": "Oznacz jako przeczytane",
|
|
1635
1636
|
"visual_confirmation_ready": "Oznacz jako przeczytane",
|
|
@@ -2297,6 +2298,8 @@
|
|
|
2297
2298
|
"created": "Utworzono {date}",
|
|
2298
2299
|
"lastUsed": "ostatnio użyto {date}",
|
|
2299
2300
|
"neverUsed": "nigdy nie użyto",
|
|
2301
|
+
"createdBy": "utworzone przez {user}",
|
|
2302
|
+
"createdByYou": "Ciebie",
|
|
2300
2303
|
"revoke": "Unieważnij token"
|
|
2301
2304
|
},
|
|
2302
2305
|
"add": {
|
|
@@ -3095,6 +3098,7 @@
|
|
|
3095
3098
|
"incompleteBody": "Przed zapisaniem uzupełnij zarówno identyfikator użytkownika, jak i identyfikator członka Slack, albo usuń wiersz."
|
|
3096
3099
|
},
|
|
3097
3100
|
"routable": {
|
|
3101
|
+
"platform_health": "Kondycja platformy",
|
|
3098
3102
|
"merge_review": "Przeglad scalenia",
|
|
3099
3103
|
"pipeline_complete": "Pipeline ukonczony",
|
|
3100
3104
|
"ci_failed": "Niepowodzenie CI",
|
package/i18n/locales/tr.json
CHANGED
|
@@ -1630,6 +1630,7 @@
|
|
|
1630
1630
|
"requirement_review": "Okundu olarak işaretle",
|
|
1631
1631
|
"clarity_review": "Okundu olarak işaretle",
|
|
1632
1632
|
"release_regression": "Onayla",
|
|
1633
|
+
"platform_health": "Onayla",
|
|
1633
1634
|
"decision_required": "Okundu işaretle",
|
|
1634
1635
|
"human_test_ready": "Okundu işaretle",
|
|
1635
1636
|
"visual_confirmation_ready": "Okundu işaretle",
|
|
@@ -2419,6 +2420,8 @@
|
|
|
2419
2420
|
"created": "{date} tarihinde oluşturuldu",
|
|
2420
2421
|
"lastUsed": "son kullanım {date}",
|
|
2421
2422
|
"neverUsed": "hiç kullanılmadı",
|
|
2423
|
+
"createdBy": "oluşturan: {user}",
|
|
2424
|
+
"createdByYou": "siz",
|
|
2422
2425
|
"revoke": "Belirteci iptal et"
|
|
2423
2426
|
},
|
|
2424
2427
|
"add": {
|
|
@@ -3107,6 +3110,7 @@
|
|
|
3107
3110
|
"incompleteBody": "Kaydetmeden önce hem kullanıcı kimliğini hem de Slack üye kimliğini girin ya da satırı kaldırın."
|
|
3108
3111
|
},
|
|
3109
3112
|
"routable": {
|
|
3113
|
+
"platform_health": "Platform sağlığı",
|
|
3110
3114
|
"merge_review": "Birleştirme incelemesi",
|
|
3111
3115
|
"pipeline_complete": "Pipeline tamamlandı",
|
|
3112
3116
|
"ci_failed": "CI başarısız",
|
package/i18n/locales/uk.json
CHANGED
|
@@ -1630,6 +1630,7 @@
|
|
|
1630
1630
|
"requirement_review": "Позначити прочитаним",
|
|
1631
1631
|
"clarity_review": "Позначити прочитаним",
|
|
1632
1632
|
"release_regression": "Підтвердити отримання",
|
|
1633
|
+
"platform_health": "Підтвердити отримання",
|
|
1633
1634
|
"decision_required": "Позначити прочитаним",
|
|
1634
1635
|
"human_test_ready": "Позначити прочитаним",
|
|
1635
1636
|
"visual_confirmation_ready": "Позначити прочитаним",
|
|
@@ -2297,6 +2298,8 @@
|
|
|
2297
2298
|
"created": "Створено {date}",
|
|
2298
2299
|
"lastUsed": "востаннє використано {date}",
|
|
2299
2300
|
"neverUsed": "ніколи не використовувався",
|
|
2301
|
+
"createdBy": "створено {user}",
|
|
2302
|
+
"createdByYou": "вами",
|
|
2300
2303
|
"revoke": "Відкликати токен"
|
|
2301
2304
|
},
|
|
2302
2305
|
"add": {
|
|
@@ -3095,6 +3098,7 @@
|
|
|
3095
3098
|
"incompleteBody": "Перед збереженням заповніть і ідентифікатор користувача, і ідентифікатор учасника Slack, або видаліть рядок."
|
|
3096
3099
|
},
|
|
3097
3100
|
"routable": {
|
|
3101
|
+
"platform_health": "Стан платформи",
|
|
3098
3102
|
"merge_review": "Перевірка злиття",
|
|
3099
3103
|
"pipeline_complete": "Конвеєр завершено",
|
|
3100
3104
|
"ci_failed": "Збій CI",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.129.0",
|
|
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",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"valibot": "^1.4.2",
|
|
35
35
|
"vue": "3.5.39",
|
|
36
36
|
"wretch": "^3.0.9",
|
|
37
|
-
"@cat-factory/contracts": "0.
|
|
37
|
+
"@cat-factory/contracts": "0.147.1"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@toad-contracts/testing": "0.3.2",
|