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
This commit is contained in:
Mikkel Georgsen 2026-03-31 13:32:27 +02:00 committed by Nexus Dev
parent 4ab57d4145
commit d2d8217f02
20 changed files with 40 additions and 24 deletions

View file

@ -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`,
};
}

View file

@ -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}`,
};
}

View file

@ -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.`),
);
}

View file

@ -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<void> {
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<StartedServer> {
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)}`,
);
}

View file

@ -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 {
@ -188,7 +189,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: () => {
@ -199,7 +200,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);
},
});
@ -396,7 +397,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(),

View file

@ -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 <EmptyState icon={History} message="Select a company to view activity." />;
return <EmptyState icon={History} message={`Select a ${VOCAB.company.toLowerCase()} to view activity.`} />;
}
if (isLoading) {

View file

@ -1745,7 +1745,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);
},
});

View file

@ -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";
@ -123,7 +124,7 @@ export function Agents() {
}, [setBreadcrumbs]);
if (!selectedCompanyId) {
return <EmptyState icon={Bot} message="Select a company to view agents." />;
return <EmptyState icon={Bot} message={`Select a ${VOCAB.company.toLowerCase()} to view agents.`} />;
}
if (isLoading) {

View file

@ -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 <p className="text-sm text-muted-foreground">Select a company first.</p>;
return <p className="text-sm text-muted-foreground">{`Select a ${VOCAB.company.toLowerCase()} first.`}</p>;
}
if (isLoading) {

View file

@ -912,7 +912,7 @@ export function CompanyExport() {
}
if (!selectedCompanyId) {
return <EmptyState icon={Package} message="Select a company to export." />;
return <EmptyState icon={Package} message={`Select a ${VOCAB.company.toLowerCase()} to export.`} />;
}
if (exportPreviewMutation.isPending && !exportData) {

View file

@ -989,7 +989,7 @@ export function CompanySkills() {
});
if (!selectedCompanyId) {
return <EmptyState icon={Boxes} message="Select a company to manage skills." />;
return <EmptyState icon={Boxes} message={`Select a ${VOCAB.company.toLowerCase()} to manage skills.`} />;
}
function handleAddSkillSource() {

View file

@ -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 <EmptyState icon={Target} message="Select a company to view goals." />;
return <EmptyState icon={Target} message={`Select a ${VOCAB.company.toLowerCase()} to view goals.`} />;
}
if (isLoading) {

View file

@ -1,4 +1,5 @@
import { type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { VOCAB } from "@paperclipai/branding";
import { Link, useLocation, useNavigate } from "@/lib/router";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { INBOX_MINE_ISSUE_STATUS_FILTER } from "@paperclipai/shared";
@ -1523,7 +1524,7 @@ export function Inbox() {
}, [selectedIndex]);
if (!selectedCompanyId) {
return <EmptyState icon={InboxIcon} message="Select a company to view inbox." />;
return <EmptyState icon={InboxIcon} message={`Select a ${VOCAB.company.toLowerCase()} to view inbox.`} />;
}
const hasRunFailures = failedRuns.length > 0;

View file

@ -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";
@ -94,7 +95,7 @@ export function Issues() {
});
if (!selectedCompanyId) {
return <EmptyState icon={CircleDot} message="Select a company to view issues." />;
return <EmptyState icon={CircleDot} message={`Select a ${VOCAB.company.toLowerCase()} to view issues.`} />;
}
return (

View file

@ -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 <EmptyState icon={ListTodo} message="Select a company to view your issues." />;
return <EmptyState icon={ListTodo} message={`Select a ${VOCAB.company.toLowerCase()} to view your issues.`} />;
}
if (isLoading) {

View file

@ -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 <EmptyState icon={GitBranch} message="Select a company to view org chart." />;
return <EmptyState icon={GitBranch} message={`Select a ${VOCAB.company.toLowerCase()} to view org chart.`} />;
}
if (isLoading) {

View file

@ -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";
@ -257,7 +258,7 @@ export function OrgChart() {
}, [zoom, pan]);
if (!selectedCompanyId) {
return <EmptyState icon={Network} message="Select a company to view the org chart." />;
return <EmptyState icon={Network} message={`Select a ${VOCAB.company.toLowerCase()} to view the org chart.`} />;
}
if (isLoading) {

View file

@ -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 (
<div className="space-y-4">
<p className="text-sm text-muted-foreground">Select a company to view this page.</p>
<p className="text-sm text-muted-foreground">{`Select a ${VOCAB.company.toLowerCase()} to view this page.`}</p>
</div>
);
}

View file

@ -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 <EmptyState icon={Hexagon} message="Select a company to view projects." />;
return <EmptyState icon={Hexagon} message={`Select a ${VOCAB.company.toLowerCase()} to view projects.`} />;
}
if (isLoading) {

View file

@ -269,7 +269,7 @@ export function Routines() {
}
if (!selectedCompanyId) {
return <EmptyState icon={Repeat} message="Select a company to view routines." />;
return <EmptyState icon={Repeat} message={`Select a ${VOCAB.company.toLowerCase()} to view routines.`} />;
}
if (isLoading) {