mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-15 02:20:38 +09:00
Merge public-gh/master into pap-1239-ui-ux
This commit is contained in:
commit
b578bf1f51
56 changed files with 16126 additions and 397 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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" />}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue