Merge remote-tracking branch 'public-gh/master'

* public-gh/master:
  fix: disable secure cookies for HTTP deployments
  feat(adapters): add claude-sonnet-4-6 and claude-haiku-4-6 models
  Add opencode-ai to global npm install in Dockerfile
  fix: correct env var priority for authDisableSignUp
  Add pi-local package.json to Dockerfile
  feat: add auth.disableSignUp config option
  refactor: extract roleLabels to shared constants
  fix(secrets): add secretKeys tracking to resolveEnvBindings for consistent redaction
  fix(db): reuse MIGRATIONS_FOLDER constant instead of recomputing
  fix(server): wake agent when issue status changes from backlog
  fix(server): use home-based path for run logs instead of cwd
  fix(db): use fileURLToPath for Windows-safe migration paths
  fix(server): auto-deduplicate agent names on creation instead of rejecting
  feat(ui): show human-readable role labels in agent list and properties
  fix(ui): prevent blank screen when prompt template is emptied
  fix(server): redact secret-sourced env vars in run logs by provenance
  fix(cli): split path and query in buildUrl to prevent %3F encoding
  fix(scripts): use shell on Windows to fix spawn EINVAL in dev-runner
This commit is contained in:
Dotta
2026-03-09 07:29:34 -05:00
21 changed files with 98 additions and 42 deletions

View File

@@ -441,7 +441,7 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
"promptTemplate",
String(config.promptTemplate ?? ""),
)}
onChange={(v) => mark("adapterConfig", "promptTemplate", v || undefined)}
onChange={(v) => mark("adapterConfig", "promptTemplate", v ?? "")}
placeholder="You are agent {{ agent.name }}. Your role is {{ agent.role }}..."
contentClassName="min-h-[88px] text-sm font-mono"
imageUploadHandler={async (file) => {

View File

@@ -1,6 +1,6 @@
import { useQuery } from "@tanstack/react-query";
import { Link } from "@/lib/router";
import type { Agent, AgentRuntimeState } from "@paperclipai/shared";
import { AGENT_ROLE_LABELS, type Agent, type AgentRuntimeState } from "@paperclipai/shared";
import { agentsApi } from "../api/agents";
import { useCompany } from "../context/CompanyContext";
import { queryKeys } from "../lib/queryKeys";
@@ -24,6 +24,8 @@ const adapterLabels: Record<string, string> = {
http: "HTTP",
};
const roleLabels = AGENT_ROLE_LABELS as Record<string, string>;
function PropertyRow({ label, children }: { label: string; children: React.ReactNode }) {
return (
<div className="flex items-center gap-3 py-1.5">
@@ -51,7 +53,7 @@ export function AgentProperties({ agent, runtimeState }: AgentPropertiesProps) {
<StatusBadge status={agent.status} />
</PropertyRow>
<PropertyRow label="Role">
<span className="text-sm">{agent.role}</span>
<span className="text-sm">{roleLabels[agent.role] ?? agent.role}</span>
</PropertyRow>
{agent.title && (
<PropertyRow label="Title">

View File

@@ -15,6 +15,7 @@ import {
import { Button } from "@/components/ui/button";
import { HelpCircle, ChevronDown, ChevronRight } from "lucide-react";
import { cn } from "../lib/utils";
import { AGENT_ROLE_LABELS } from "@paperclipai/shared";
/* ---- Help text for (?) tooltips ---- */
export const help: Record<string, string> = {
@@ -59,11 +60,7 @@ export const adapterLabels: Record<string, string> = {
http: "HTTP",
};
export const roleLabels: Record<string, string> = {
ceo: "CEO", cto: "CTO", cmo: "CMO", cfo: "CFO",
engineer: "Engineer", designer: "Designer", pm: "PM",
qa: "QA", devops: "DevOps", researcher: "Researcher", general: "General",
};
export const roleLabels = AGENT_ROLE_LABELS as Record<string, string>;
/* ---- Primitive components ---- */

View File

@@ -18,7 +18,7 @@ import { PageTabBar } from "../components/PageTabBar";
import { Tabs } from "@/components/ui/tabs";
import { Button } from "@/components/ui/button";
import { Bot, Plus, List, GitBranch, SlidersHorizontal } from "lucide-react";
import type { Agent } from "@paperclipai/shared";
import { AGENT_ROLE_LABELS, type Agent } from "@paperclipai/shared";
const adapterLabels: Record<string, string> = {
claude_local: "Claude",
@@ -30,11 +30,7 @@ const adapterLabels: Record<string, string> = {
http: "HTTP",
};
const roleLabels: Record<string, string> = {
ceo: "CEO", cto: "CTO", cmo: "CMO", cfo: "CFO",
engineer: "Engineer", designer: "Designer", pm: "PM",
qa: "QA", devops: "DevOps", researcher: "Researcher", general: "General",
};
const roleLabels = AGENT_ROLE_LABELS as Record<string, string>;
type FilterTab = "all" | "active" | "paused" | "error";
@@ -230,7 +226,7 @@ export function Agents() {
<EntityRow
key={agent.id}
title={agent.name}
subtitle={`${agent.role}${agent.title ? ` - ${agent.title}` : ""}`}
subtitle={`${roleLabels[agent.role] ?? agent.role}${agent.title ? ` - ${agent.title}` : ""}`}
to={agentUrl(agent)}
leading={
<span className="relative flex h-2.5 w-2.5">

View File

@@ -10,7 +10,7 @@ import { EmptyState } from "../components/EmptyState";
import { PageSkeleton } from "../components/PageSkeleton";
import { AgentIcon } from "../components/AgentIconPicker";
import { Network } from "lucide-react";
import type { Agent } from "@paperclipai/shared";
import { AGENT_ROLE_LABELS, type Agent } from "@paperclipai/shared";
// Layout constants
const CARD_W = 200;
@@ -421,11 +421,7 @@ export function OrgChart() {
);
}
const roleLabels: Record<string, string> = {
ceo: "CEO", cto: "CTO", cmo: "CMO", cfo: "CFO",
engineer: "Engineer", designer: "Designer", pm: "PM",
qa: "QA", devops: "DevOps", researcher: "Researcher", general: "General",
};
const roleLabels = AGENT_ROLE_LABELS as Record<string, string>;
function roleLabel(role: string): string {
return roleLabels[role] ?? role;