Adjust skills
All checks were successful
Build and Push / build (push) Successful in 1m31s

This commit is contained in:
2026-05-11 21:25:09 +02:00
parent b58bdadad4
commit a13af83655
9 changed files with 507 additions and 118 deletions

View File

@@ -1,9 +1,32 @@
/**
* Portal-side package catalog. Hardcoded mirror of the operator-side
* catalog ConfigMap (deploy/helm/pieced-operator/templates/catalog-cm.yaml).
*
* The two have to stay in sync:
* - `id` here must match the catalog key in the ConfigMap.
* - `secrets[].key` here must match the catalog's env_vars[].secret_key
* so that POST /api/tenants/:name/secrets writes to the same OpenBao
* path the operator's ExternalSecret reads from.
* - `requiresSecrets` is true when the catalog declares any env_var
* that is a secret (vault_path_suffix set, no default value).
*
* Category model (Phase A rework):
* - core — platform-behaviour toggles (heartbeat, cron,
* active-memory, voice). Mostly no secrets. core-voice is
* a catalog stub in Phase A — toggling stores customer
* intent only; the OCI config_patch lands in Phase B.
* - channel — messaging integration.
* - skill — ClawHub skill install.
*/
export interface PackageSecretField {
key: string;
labelKey: string;
placeholderKey: string;
}
export type PackageCategory = "core" | "channel" | "skill";
export interface PackageDef {
id: string;
name: string;
@@ -12,10 +35,45 @@ export interface PackageDef {
secrets?: PackageSecretField[];
instructionsKey?: string;
disclaimerKey?: string;
category: "channel" | "skill";
category: PackageCategory;
}
export const PACKAGE_CATALOG: PackageDef[] = [
// -------------------------------------------------------------------------
// CORE
// -------------------------------------------------------------------------
{
id: "core-heartbeat",
name: "Heartbeat (Proactive Checks)",
descriptionKey: "packages.coreHeartbeat.description",
requiresSecrets: false,
category: "core",
},
{
id: "core-cron",
name: "Scheduled Tasks (Cron)",
descriptionKey: "packages.coreCron.description",
requiresSecrets: false,
category: "core",
},
{
id: "core-active-memory",
name: "Active Memory",
descriptionKey: "packages.coreActiveMemory.description",
requiresSecrets: false,
category: "core",
},
{
id: "core-voice",
name: "Voice Interaction",
descriptionKey: "packages.coreVoice.description",
requiresSecrets: false,
category: "core",
},
// -------------------------------------------------------------------------
// CHANNELS
// -------------------------------------------------------------------------
{
id: "telegram",
name: "Telegram",
@@ -43,42 +101,181 @@ export const PACKAGE_CATALOG: PackageDef[] = [
labelKey: "packages.discord.botTokenLabel",
placeholderKey: "packages.discord.botTokenPlaceholder",
},
// app-id was missing from the portal catalog historically while the
// operator catalog declared DISCORD_APP_ID as a required env var.
// Tenants who enabled Discord ended up with the env var blank
// because the secrets POST never wrote an `app-id` key to OpenBao
// and the operator's ExternalSecret couldn't populate it. Added
// here as part of the Phase A rework to close the alignment gap;
// not strictly secret (the application ID is visible in the bot's
// profile URL) but stored alongside the bot token for convenience.
{
key: "app-id",
labelKey: "packages.discord.appIdLabel",
placeholderKey: "packages.discord.appIdPlaceholder",
},
],
instructionsKey: "packages.discord.instructions",
disclaimerKey: "packages.discord.disclaimer",
category: "channel",
},
// -------------------------------------------------------------------------
// SKILLS
// -------------------------------------------------------------------------
{
id: "email",
name: "Email",
descriptionKey: "packages.email.description",
requiresSecrets: true,
secrets: [
{ key: "smtp-host", labelKey: "packages.email.smtpHostLabel", placeholderKey: "packages.email.smtpHostPlaceholder" },
{ key: "smtp-user", labelKey: "packages.email.smtpUserLabel", placeholderKey: "packages.email.smtpUserPlaceholder" },
{ key: "smtp-password", labelKey: "packages.email.smtpPasswordLabel", placeholderKey: "packages.email.smtpPasswordPlaceholder" },
{ key: "imap-host", labelKey: "packages.email.imapHostLabel", placeholderKey: "packages.email.imapHostPlaceholder" },
],
instructionsKey: "packages.email.instructions",
disclaimerKey: "packages.email.disclaimer",
category: "channel",
},
{
id: "web-search",
name: "Web Search",
descriptionKey: "packages.webSearch.description",
id: "git-cli",
name: "Git CLI",
descriptionKey: "packages.gitCli.description",
requiresSecrets: false,
category: "skill",
},
{
id: "document-processing",
name: "Document Processing",
descriptionKey: "packages.documentProcessing.description",
id: "github",
name: "GitHub (gh CLI)",
descriptionKey: "packages.github.description",
requiresSecrets: true,
secrets: [
{
key: "token",
labelKey: "packages.github.tokenLabel",
placeholderKey: "packages.github.tokenPlaceholder",
},
],
instructionsKey: "packages.github.instructions",
category: "skill",
},
{
id: "gitea",
name: "Gitea",
descriptionKey: "packages.gitea.description",
requiresSecrets: true,
secrets: [
{
key: "token",
labelKey: "packages.gitea.tokenLabel",
placeholderKey: "packages.gitea.tokenPlaceholder",
},
],
instructionsKey: "packages.gitea.instructions",
category: "skill",
},
{
id: "whisper-self-hosted",
name: "Whisper (Self-Hosted Transcription)",
descriptionKey: "packages.whisperSelfHosted.description",
requiresSecrets: false,
category: "skill",
},
{
id: "searxng-local-search",
name: "Web Search (SearXNG)",
descriptionKey: "packages.searxngLocalSearch.description",
requiresSecrets: false,
category: "skill",
},
{
id: "gog",
name: "Google Workspace (Gog)",
descriptionKey: "packages.gog.description",
requiresSecrets: true,
secrets: [
{
key: "client-id",
labelKey: "packages.gog.clientIdLabel",
placeholderKey: "packages.gog.clientIdPlaceholder",
},
{
key: "client-secret",
labelKey: "packages.gog.clientSecretLabel",
placeholderKey: "packages.gog.clientSecretPlaceholder",
},
{
key: "refresh-token",
labelKey: "packages.gog.refreshTokenLabel",
placeholderKey: "packages.gog.refreshTokenPlaceholder",
},
],
instructionsKey: "packages.gog.instructions",
disclaimerKey: "packages.gog.disclaimer",
category: "skill",
},
{
id: "mail",
name: "Email (IMAP / SMTP)",
descriptionKey: "packages.mail.description",
requiresSecrets: true,
secrets: [
{
key: "imap-host",
labelKey: "packages.mail.imapHostLabel",
placeholderKey: "packages.mail.imapHostPlaceholder",
},
{
key: "imap-user",
labelKey: "packages.mail.imapUserLabel",
placeholderKey: "packages.mail.imapUserPlaceholder",
},
{
key: "imap-pass",
labelKey: "packages.mail.imapPassLabel",
placeholderKey: "packages.mail.imapPassPlaceholder",
},
{
key: "smtp-host",
labelKey: "packages.mail.smtpHostLabel",
placeholderKey: "packages.mail.smtpHostPlaceholder",
},
{
key: "smtp-user",
labelKey: "packages.mail.smtpUserLabel",
placeholderKey: "packages.mail.smtpUserPlaceholder",
},
{
key: "smtp-pass",
labelKey: "packages.mail.smtpPassLabel",
placeholderKey: "packages.mail.smtpPassPlaceholder",
},
],
instructionsKey: "packages.mail.instructions",
disclaimerKey: "packages.mail.disclaimer",
category: "skill",
},
];
export function getPackageDef(id: string): PackageDef | undefined {
return PACKAGE_CATALOG.find((p) => p.id === id);
}
/**
* IDs of channel-category packages. Derived from the catalog so it
* cannot drift from the source of truth (previously hardcoded as
* `["telegram", "discord", "email"]` in tenants/[name]/page.tsx —
* removed as part of the Phase A package-model rework).
*
* Consumers: tenant detail page (filter spec.packages to channel set
* before rendering the channel-users panel).
*/
export const CHANNEL_PACKAGE_IDS: string[] = PACKAGE_CATALOG
.filter((p) => p.category === "channel")
.map((p) => p.id);
/**
* Default packages selected when the wizard opens a fresh onboarding
* request. The three CORE behaviours that make the assistant feel
* "smart out of the box":
* - heartbeat: proactive checks (otherwise the assistant is purely
* reactive).
* - cron: scheduled tasks (daily briefings, reminders).
* - active-memory: long-term recall of stable preferences and habits.
*
* Each adds some token cost — active-memory the most (one extra
* sub-agent turn per inbound message) — so customers can untoggle any
* of them before submitting. core-voice is deliberately excluded from
* defaults until its config_patch lands in Phase B.
*/
export const DEFAULT_PACKAGE_IDS: string[] = [
"core-heartbeat",
"core-cron",
"core-active-memory",
];