Merge public-gh/master into pap-1239-ui-ux

This commit is contained in:
dotta 2026-04-09 09:04:22 -05:00
commit b578bf1f51
56 changed files with 16126 additions and 397 deletions

View file

@ -2,72 +2,9 @@ import { Link } from "@/lib/router";
import { Identity } from "./Identity";
import { timeAgo } from "../lib/timeAgo";
import { cn } from "../lib/utils";
import { formatActivityVerb } from "../lib/activity-format";
import { deriveProjectUrlKey, type ActivityEvent, type Agent } from "@paperclipai/shared";
const ACTION_VERBS: Record<string, string> = {
"issue.created": "created",
"issue.updated": "updated",
"issue.checked_out": "checked out",
"issue.released": "released",
"issue.comment_added": "commented on",
"issue.attachment_added": "attached file to",
"issue.attachment_removed": "removed attachment from",
"issue.document_created": "created document for",
"issue.document_updated": "updated document on",
"issue.document_deleted": "deleted document from",
"issue.commented": "commented on",
"issue.deleted": "deleted",
"agent.created": "created",
"agent.updated": "updated",
"agent.paused": "paused",
"agent.resumed": "resumed",
"agent.terminated": "terminated",
"agent.key_created": "created API key for",
"agent.budget_updated": "updated budget for",
"agent.runtime_session_reset": "reset session for",
"heartbeat.invoked": "invoked heartbeat for",
"heartbeat.cancelled": "cancelled heartbeat for",
"approval.created": "requested approval",
"approval.approved": "approved",
"approval.rejected": "rejected",
"project.created": "created",
"project.updated": "updated",
"project.deleted": "deleted",
"goal.created": "created",
"goal.updated": "updated",
"goal.deleted": "deleted",
"cost.reported": "reported cost for",
"cost.recorded": "recorded cost for",
"company.created": "created company",
"company.updated": "updated company",
"company.archived": "archived",
"company.budget_updated": "updated budget for",
};
function humanizeValue(value: unknown): string {
if (typeof value !== "string") return String(value ?? "none");
return value.replace(/_/g, " ");
}
function formatVerb(action: string, details?: Record<string, unknown> | null): string {
if (action === "issue.updated" && details) {
const previous = (details._previous ?? {}) as Record<string, unknown>;
if (details.status !== undefined) {
const from = previous.status;
return from
? `changed status from ${humanizeValue(from)} to ${humanizeValue(details.status)} on`
: `changed status to ${humanizeValue(details.status)} on`;
}
if (details.priority !== undefined) {
const from = previous.priority;
return from
? `changed priority from ${humanizeValue(from)} to ${humanizeValue(details.priority)} on`
: `changed priority to ${humanizeValue(details.priority)} on`;
}
}
return ACTION_VERBS[action] ?? action.replace(/[._]/g, " ");
}
function entityLink(entityType: string, entityId: string, name?: string | null): string | null {
switch (entityType) {
case "issue": return `/issues/${name ?? entityId}`;
@ -88,7 +25,7 @@ interface ActivityRowProps {
}
export function ActivityRow({ event, agentMap, entityNameMap, entityTitleMap, className }: ActivityRowProps) {
const verb = formatVerb(event.action, event.details);
const verb = formatActivityVerb(event.action, event.details, { agentMap });
const isHeartbeatEvent = event.entityType === "heartbeat_run";
const heartbeatAgentId = isHeartbeatEvent

View file

@ -923,14 +923,14 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
<ToggleWithNumber
label="Heartbeat on interval"
hint={help.heartbeatInterval}
checked={eff("heartbeat", "enabled", heartbeat.enabled !== false)}
checked={eff("heartbeat", "enabled", heartbeat.enabled === true)}
onCheckedChange={(v) => mark("heartbeat", "enabled", v)}
number={eff("heartbeat", "intervalSec", Number(heartbeat.intervalSec ?? 300))}
onNumberChange={(v) => mark("heartbeat", "intervalSec", v)}
numberLabel="sec"
numberPrefix="Run heartbeat every"
numberHint={help.intervalSec}
showNumber={eff("heartbeat", "enabled", heartbeat.enabled !== false)}
showNumber={eff("heartbeat", "enabled", heartbeat.enabled === true)}
/>
</div>
<CollapsibleSection

View file

@ -33,6 +33,7 @@ import {
buildOnboardingProjectPayload,
selectDefaultCompanyGoalId
} from "../lib/onboarding-launch";
import { buildNewAgentRuntimeConfig } from "../lib/new-agent-runtime-config";
import {
DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX,
DEFAULT_CODEX_LOCAL_MODEL
@ -460,15 +461,7 @@ export function OnboardingWizard() {
role: "ceo",
adapterType,
adapterConfig: buildAdapterConfig(),
runtimeConfig: {
heartbeat: {
enabled: true,
intervalSec: 3600,
wakeOnDemand: true,
cooldownSec: 10,
maxConcurrentRuns: 1
}
}
runtimeConfig: buildNewAgentRuntimeConfig()
});
setCreatedAgentId(agent.id);
queryClient.invalidateQueries({

View file

@ -36,18 +36,20 @@ function updateVariableList(
}
export function RoutineVariablesEditor({
title,
description,
value,
onChange,
}: {
title: string;
description: string;
value: RoutineVariable[];
onChange: (value: RoutineVariable[]) => void;
}) {
const [open, setOpen] = useState(true);
const syncedVariables = useMemo(
() => syncRoutineVariablesWithTemplate(description, value),
[description, value],
() => syncRoutineVariablesWithTemplate([title, description], value),
[description, title, value],
);
const syncedSignature = serializeVariables(syncedVariables);
const currentSignature = serializeVariables(value);
@ -68,7 +70,7 @@ export function RoutineVariablesEditor({
<div>
<p className="text-sm font-medium">Variables</p>
<p className="text-xs text-muted-foreground">
Detected from `{"{{name}}"}` placeholders in the routine instructions.
Detected from `{"{{name}}"}` placeholders in the routine title and instructions.
</p>
</div>
{open ? <ChevronDown className="h-4 w-4 text-muted-foreground" /> : <ChevronRight className="h-4 w-4 text-muted-foreground" />}