From bf3215cc871bb953e0a80b49869ad2bebc0ef7d6 Mon Sep 17 00:00:00 2001 From: Mikkel Georgsen Date: Tue, 31 Mar 2026 13:32:27 +0200 Subject: [PATCH] feat(06-02): replace Select a company empty states + CLI Paperclip strings - 14 UI pages: all Select a company empty states use VOCAB.company.toLowerCase() - AgentConfigForm: 3 error throws use VOCAB.company - AgentDetail: additional Select a company upload error replaced - CLI run.ts: Starting/Could not locate/failed to start messages use VOCAB.appName - CLI deployment-auth-check: repairHint uses VOCAB.appName - CLI agent-jwt-secret-check: repairHint uses VOCAB.appName - CLI allowed-hostname: restart message uses VOCAB.appName - Added VOCAB import to all files missing it --- cli/src/checks/agent-jwt-secret-check.ts | 3 ++- cli/src/checks/deployment-auth-check.ts | 3 ++- cli/src/commands/allowed-hostname.ts | 3 ++- cli/src/commands/run.ts | 7 ++++--- ui/src/components/AgentConfigForm.tsx | 7 ++++--- ui/src/pages/Activity.tsx | 3 ++- ui/src/pages/AgentDetail.tsx | 2 +- ui/src/pages/Agents.tsx | 3 ++- ui/src/pages/Approvals.tsx | 3 ++- ui/src/pages/CompanyExport.tsx | 2 +- ui/src/pages/CompanySkills.tsx | 2 +- ui/src/pages/Goals.tsx | 3 ++- ui/src/pages/Inbox.tsx | 3 ++- ui/src/pages/Issues.tsx | 3 ++- ui/src/pages/MyIssues.tsx | 3 ++- ui/src/pages/Org.tsx | 3 ++- ui/src/pages/OrgChart.tsx | 3 ++- ui/src/pages/PluginPage.tsx | 3 ++- ui/src/pages/Projects.tsx | 3 ++- ui/src/pages/Routines.tsx | 2 +- 20 files changed, 40 insertions(+), 24 deletions(-) diff --git a/cli/src/checks/agent-jwt-secret-check.ts b/cli/src/checks/agent-jwt-secret-check.ts index 65a75cf5..9f222c1d 100644 --- a/cli/src/checks/agent-jwt-secret-check.ts +++ b/cli/src/checks/agent-jwt-secret-check.ts @@ -4,6 +4,7 @@ import { readAgentJwtSecretFromEnvFile, resolveAgentJwtEnvFile, } from "../config/env.js"; +import { VOCAB } from "@paperclipai/branding"; import type { CheckResult } from "./index.js"; export function agentJwtSecretCheck(configPath?: string): CheckResult { @@ -23,7 +24,7 @@ export function agentJwtSecretCheck(configPath?: string): CheckResult { name: "Agent JWT secret", status: "warn", message: `PAPERCLIP_AGENT_JWT_SECRET is present in ${envPath} but not loaded into environment`, - repairHint: `Set the value from ${envPath} in your shell before starting the Paperclip server`, + repairHint: `Set the value from ${envPath} in your shell before starting the ${VOCAB.appName} server`, }; } diff --git a/cli/src/checks/deployment-auth-check.ts b/cli/src/checks/deployment-auth-check.ts index 580e7e08..6a318136 100644 --- a/cli/src/checks/deployment-auth-check.ts +++ b/cli/src/checks/deployment-auth-check.ts @@ -1,4 +1,5 @@ import type { PaperclipConfig } from "../config/schema.js"; +import { VOCAB } from "@paperclipai/branding"; import type { CheckResult } from "./index.js"; function isLoopbackHost(host: string) { @@ -37,7 +38,7 @@ export function deploymentAuthCheck(config: PaperclipConfig): CheckResult { status: "fail", message: "authenticated mode requires BETTER_AUTH_SECRET (or PAPERCLIP_AGENT_JWT_SECRET)", canRepair: false, - repairHint: "Set BETTER_AUTH_SECRET before starting Paperclip", + repairHint: `Set BETTER_AUTH_SECRET before starting ${VOCAB.appName}`, }; } diff --git a/cli/src/commands/allowed-hostname.ts b/cli/src/commands/allowed-hostname.ts index d47a3bba..14154dee 100644 --- a/cli/src/commands/allowed-hostname.ts +++ b/cli/src/commands/allowed-hostname.ts @@ -1,4 +1,5 @@ import * as p from "@clack/prompts"; +import { VOCAB } from "@paperclipai/branding"; import pc from "picocolors"; import { normalizeHostnameInput } from "../config/hostnames.js"; import { readConfig, resolveConfigPath, writeConfig } from "../config/store.js"; @@ -27,7 +28,7 @@ export async function addAllowedHostname(host: string, opts: { config?: string } } else { p.log.success(`Added allowed hostname: ${pc.cyan(normalized)}`); p.log.message( - pc.dim("Restart the Paperclip server for this change to take effect."), + pc.dim(`Restart the ${VOCAB.appName} server for this change to take effect.`), ); } diff --git a/cli/src/commands/run.ts b/cli/src/commands/run.ts index 04743b48..87df6a4e 100644 --- a/cli/src/commands/run.ts +++ b/cli/src/commands/run.ts @@ -1,4 +1,5 @@ import fs from "node:fs"; +import { VOCAB } from "@paperclipai/branding"; import path from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; import * as p from "@clack/prompts"; @@ -78,7 +79,7 @@ export async function runCommand(opts: RunOptions): Promise { process.exit(1); } - p.log.step("Starting Paperclip server..."); + p.log.step(`Starting ${VOCAB.appName} server...`); const startedServer = await importServerEntry(); if (shouldGenerateBootstrapInviteAfterStart(config)) { @@ -165,13 +166,13 @@ async function importServerEntry(): Promise { const missingServerEntrypoint = !missingSpecifier || missingSpecifier === "@paperclipai/server"; if (isModuleNotFoundError(err) && missingServerEntrypoint) { throw new Error( - `Could not locate a Paperclip server entrypoint.\n` + + `Could not locate a ${VOCAB.appName} server entrypoint.\n` + `Tried: ${devEntry}, @paperclipai/server\n` + `${formatError(err)}`, ); } throw new Error( - `Paperclip server failed to start.\n` + + `${VOCAB.appName} server failed to start.\n` + `${formatError(err)}`, ); } diff --git a/ui/src/components/AgentConfigForm.tsx b/ui/src/components/AgentConfigForm.tsx index 1810e9a8..8ab994ec 100644 --- a/ui/src/components/AgentConfigForm.tsx +++ b/ui/src/components/AgentConfigForm.tsx @@ -1,4 +1,5 @@ import { useState, useEffect, useRef, useMemo, useCallback } from "react"; +import { VOCAB } from "@paperclipai/branding"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { AGENT_ADAPTER_TYPES } from "@paperclipai/shared"; import type { @@ -186,7 +187,7 @@ export function AgentConfigForm(props: AgentConfigFormProps) { const createSecret = useMutation({ mutationFn: (input: { name: string; value: string }) => { - if (!selectedCompanyId) throw new Error("Select a company to create secrets"); + if (!selectedCompanyId) throw new Error(`Select a ${VOCAB.company.toLowerCase()} to create secrets`); return secretsApi.create(selectedCompanyId, input); }, onSuccess: () => { @@ -197,7 +198,7 @@ export function AgentConfigForm(props: AgentConfigFormProps) { const uploadMarkdownImage = useMutation({ mutationFn: async ({ file, namespace }: { file: File; namespace: string }) => { - if (!selectedCompanyId) throw new Error("Select a company to upload images"); + if (!selectedCompanyId) throw new Error(`Select a ${VOCAB.company.toLowerCase()} to upload images`); return assetsApi.uploadImage(selectedCompanyId, file, namespace); }, }); @@ -359,7 +360,7 @@ export function AgentConfigForm(props: AgentConfigFormProps) { const testEnvironment = useMutation({ mutationFn: async () => { if (!selectedCompanyId) { - throw new Error("Select a company to test adapter environment"); + throw new Error(`Select a ${VOCAB.company.toLowerCase()} to test adapter environment`); } return agentsApi.testEnvironment(selectedCompanyId, adapterType, { adapterConfig: buildAdapterConfigForTest(), diff --git a/ui/src/pages/Activity.tsx b/ui/src/pages/Activity.tsx index cfb347bb..c575a930 100644 --- a/ui/src/pages/Activity.tsx +++ b/ui/src/pages/Activity.tsx @@ -1,4 +1,5 @@ import { useEffect, useMemo, useState } from "react"; +import { VOCAB } from "@paperclipai/branding"; import { useQuery } from "@tanstack/react-query"; import { activityApi } from "../api/activity"; import { agentsApi } from "../api/agents"; @@ -82,7 +83,7 @@ export function Activity() { }, [issues]); if (!selectedCompanyId) { - return ; + return ; } if (isLoading) { diff --git a/ui/src/pages/AgentDetail.tsx b/ui/src/pages/AgentDetail.tsx index 415afa21..12f5233f 100644 --- a/ui/src/pages/AgentDetail.tsx +++ b/ui/src/pages/AgentDetail.tsx @@ -1727,7 +1727,7 @@ function PromptsTab({ const uploadMarkdownImage = useMutation({ mutationFn: async ({ file, namespace }: { file: File; namespace: string }) => { - if (!selectedCompanyId) throw new Error("Select a company to upload images"); + if (!selectedCompanyId) throw new Error(`Select a ${VOCAB.company.toLowerCase()} to upload images`); return assetsApi.uploadImage(selectedCompanyId, file, namespace); }, }); diff --git a/ui/src/pages/Agents.tsx b/ui/src/pages/Agents.tsx index b14112c4..972a9b8d 100644 --- a/ui/src/pages/Agents.tsx +++ b/ui/src/pages/Agents.tsx @@ -1,4 +1,5 @@ import { useState, useEffect, useMemo } from "react"; +import { VOCAB } from "@paperclipai/branding"; import { Link, useNavigate, useLocation } from "@/lib/router"; import { useQuery } from "@tanstack/react-query"; import { agentsApi, type OrgNode } from "../api/agents"; @@ -122,7 +123,7 @@ export function Agents() { }, [setBreadcrumbs]); if (!selectedCompanyId) { - return ; + return ; } if (isLoading) { diff --git a/ui/src/pages/Approvals.tsx b/ui/src/pages/Approvals.tsx index 24c8da0a..1989b1eb 100644 --- a/ui/src/pages/Approvals.tsx +++ b/ui/src/pages/Approvals.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; +import { VOCAB } from "@paperclipai/branding"; import { useNavigate, useLocation } from "@/lib/router"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { approvalsApi } from "../api/approvals"; @@ -75,7 +76,7 @@ export function Approvals() { ).length; if (!selectedCompanyId) { - return

Select a company first.

; + return

{`Select a ${VOCAB.company.toLowerCase()} first.`}

; } if (isLoading) { diff --git a/ui/src/pages/CompanyExport.tsx b/ui/src/pages/CompanyExport.tsx index 7760067a..7314818f 100644 --- a/ui/src/pages/CompanyExport.tsx +++ b/ui/src/pages/CompanyExport.tsx @@ -912,7 +912,7 @@ export function CompanyExport() { } if (!selectedCompanyId) { - return ; + return ; } if (exportPreviewMutation.isPending && !exportData) { diff --git a/ui/src/pages/CompanySkills.tsx b/ui/src/pages/CompanySkills.tsx index afcf7a1d..0516011e 100644 --- a/ui/src/pages/CompanySkills.tsx +++ b/ui/src/pages/CompanySkills.tsx @@ -989,7 +989,7 @@ export function CompanySkills() { }); if (!selectedCompanyId) { - return ; + return ; } function handleAddSkillSource() { diff --git a/ui/src/pages/Goals.tsx b/ui/src/pages/Goals.tsx index 490bb048..04975e99 100644 --- a/ui/src/pages/Goals.tsx +++ b/ui/src/pages/Goals.tsx @@ -1,4 +1,5 @@ import { useEffect } from "react"; +import { VOCAB } from "@paperclipai/branding"; import { useQuery } from "@tanstack/react-query"; import { goalsApi } from "../api/goals"; import { useCompany } from "../context/CompanyContext"; @@ -27,7 +28,7 @@ export function Goals() { }); if (!selectedCompanyId) { - return ; + return ; } if (isLoading) { diff --git a/ui/src/pages/Inbox.tsx b/ui/src/pages/Inbox.tsx index 149bd292..763fe94c 100644 --- a/ui/src/pages/Inbox.tsx +++ b/ui/src/pages/Inbox.tsx @@ -1,4 +1,5 @@ import { useEffect, useMemo, useState } from "react"; +import { VOCAB } from "@paperclipai/branding"; import { Link, useLocation, useNavigate } from "@/lib/router"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { approvalsApi } from "../api/approvals"; @@ -909,7 +910,7 @@ export function Inbox() { }; if (!selectedCompanyId) { - return ; + return ; } const hasRunFailures = failedRuns.length > 0; diff --git a/ui/src/pages/Issues.tsx b/ui/src/pages/Issues.tsx index 2b6e48b0..1cc33c55 100644 --- a/ui/src/pages/Issues.tsx +++ b/ui/src/pages/Issues.tsx @@ -1,4 +1,5 @@ import { useEffect, useMemo, useCallback } from "react"; +import { VOCAB } from "@paperclipai/branding"; import { useLocation, useSearchParams } from "@/lib/router"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { issuesApi } from "../api/issues"; @@ -93,7 +94,7 @@ export function Issues() { }); if (!selectedCompanyId) { - return ; + return ; } return ( diff --git a/ui/src/pages/MyIssues.tsx b/ui/src/pages/MyIssues.tsx index 301c526f..a2f7d55f 100644 --- a/ui/src/pages/MyIssues.tsx +++ b/ui/src/pages/MyIssues.tsx @@ -1,4 +1,5 @@ import { useEffect } from "react"; +import { VOCAB } from "@paperclipai/branding"; import { useQuery } from "@tanstack/react-query"; import { issuesApi } from "../api/issues"; import { useCompany } from "../context/CompanyContext"; @@ -27,7 +28,7 @@ export function MyIssues() { }); if (!selectedCompanyId) { - return ; + return ; } if (isLoading) { diff --git a/ui/src/pages/Org.tsx b/ui/src/pages/Org.tsx index 2cbc1816..7d77262a 100644 --- a/ui/src/pages/Org.tsx +++ b/ui/src/pages/Org.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; +import { VOCAB } from "@paperclipai/branding"; import { Link } from "@/lib/router"; import { useQuery } from "@tanstack/react-query"; import { agentsApi, type OrgNode } from "../api/agents"; @@ -104,7 +105,7 @@ export function Org() { }); if (!selectedCompanyId) { - return ; + return ; } if (isLoading) { diff --git a/ui/src/pages/OrgChart.tsx b/ui/src/pages/OrgChart.tsx index 45993717..91651854 100644 --- a/ui/src/pages/OrgChart.tsx +++ b/ui/src/pages/OrgChart.tsx @@ -1,4 +1,5 @@ import { useEffect, useRef, useState, useMemo, useCallback } from "react"; +import { VOCAB } from "@paperclipai/branding"; import { Link, useNavigate } from "@/lib/router"; import { useQuery } from "@tanstack/react-query"; import { agentsApi, type OrgNode } from "../api/agents"; @@ -256,7 +257,7 @@ export function OrgChart() { }, [zoom, pan]); if (!selectedCompanyId) { - return ; + return ; } if (isLoading) { diff --git a/ui/src/pages/PluginPage.tsx b/ui/src/pages/PluginPage.tsx index 687e0814..f8ea8b35 100644 --- a/ui/src/pages/PluginPage.tsx +++ b/ui/src/pages/PluginPage.tsx @@ -1,4 +1,5 @@ import { useEffect, useMemo } from "react"; +import { VOCAB } from "@paperclipai/branding"; import { Link, Navigate, useParams } from "@/lib/router"; import { useQuery } from "@tanstack/react-query"; import { useCompany } from "@/context/CompanyContext"; @@ -104,7 +105,7 @@ export function PluginPage() { } return (
-

Select a company to view this page.

+

{`Select a ${VOCAB.company.toLowerCase()} to view this page.`}

); } diff --git a/ui/src/pages/Projects.tsx b/ui/src/pages/Projects.tsx index 886a2b60..8a705867 100644 --- a/ui/src/pages/Projects.tsx +++ b/ui/src/pages/Projects.tsx @@ -1,4 +1,5 @@ import { useEffect, useMemo } from "react"; +import { VOCAB } from "@paperclipai/branding"; import { useQuery } from "@tanstack/react-query"; import { projectsApi } from "../api/projects"; import { useCompany } from "../context/CompanyContext"; @@ -33,7 +34,7 @@ export function Projects() { ); if (!selectedCompanyId) { - return ; + return ; } if (isLoading) { diff --git a/ui/src/pages/Routines.tsx b/ui/src/pages/Routines.tsx index 8fc6b91f..70cce082 100644 --- a/ui/src/pages/Routines.tsx +++ b/ui/src/pages/Routines.tsx @@ -219,7 +219,7 @@ export function Routines() { const currentProject = draft.projectId ? projectById.get(draft.projectId) ?? null : null; if (!selectedCompanyId) { - return ; + return ; } if (isLoading) {