mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-29 06:28:23 +02:00
Splits the conflated 5-state agent presence into two independent axes:
- AgentAvailability (3-state): online / unstable / offline — drives the
dot indicator everywhere a dot appears. Pure runtime reachability;
never sticky-red because of a past task outcome.
- LastTaskState (5-state): running / completed / failed / cancelled /
idle — surfaced as text + icon on focused surfaces (hover card,
agent detail page, agents list, runtime detail). Never colours the dot.
Major changes:
* Domain layer: AgentPresence union → AgentAvailability + LastTaskState.
derive-presence split into deriveAgentAvailability + deriveLastTaskState
+ deriveAgentPresenceDetail orchestrator. Tests reorganised into three
groups (availability invariants, last-task invariants, composition).
* Visual config: presenceConfig (5 entries) → availabilityConfig (3) +
taskStateConfig (5). availabilityOrder + lastTaskOrder for filter chips.
* Workspace-level presence prefetch: new useWorkspacePresencePrefetch
hook + WorkspacePresencePrefetch mount component, wired into
DashboardLayout (web) and WorkspaceRouteLayout (desktop). Hover cards
render synchronously with no skeleton flash on first hover.
* ActorAvatar hover: flipped default — disableHoverCard removed,
enableHoverCard added (default false). Opt-in at ~14 decision-moment
surfaces; pickers / decoration sub-chips stay plain. Status dot
decoupled (showStatusDot prop) so picker rows can show presence
without nesting popovers.
* Hover cards: AgentProfileCard simplified — availability dot only,
Detail link top-right (logs live on the detail page). New
MemberProfileCard mirrors the structure: name + role + email +
top-2 owned agents (sorted by 30d run count) with click-through to
agent detail.
* Agents list: split Status into two columns — availability (3-color
dot + label) and Last run (task icon + label, optional running
counts). Two independent filter chip groups (Status + Last run);
combination acts as intersection ("online + failed" finds broken-
but-alive agents).
* Other UI surfaces (issue list/board/detail, comments, autopilots,
projects, runtimes, mention autocomplete, subscribers picker)
updated to the new dot semantics; status dot now strictly 3-color.
Server changes accompany the client redesign — workspace-wide
agent-task-snapshot endpoint, runtime usage queries, etc. — to feed
the derive layer with the data it needs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
38 lines
1.9 KiB
TypeScript
38 lines
1.9 KiB
TypeScript
/**
|
|
* Client-side fallback for redacting sensitive information in agent output.
|
|
* The server performs primary redaction; this is a safety net for display.
|
|
*/
|
|
|
|
const patterns: { re: RegExp; replacement: string }[] = [
|
|
// AWS access key IDs
|
|
{ re: /\bAKIA[0-9A-Z]{16}\b/g, replacement: "[REDACTED AWS KEY]" },
|
|
// AWS secret access keys
|
|
{ re: /(?:aws_secret_access_key|secret_?access_?key)\s*[=:]\s*[A-Za-z0-9/+=]{40}/gi, replacement: "[REDACTED AWS SECRET]" },
|
|
// PEM private keys
|
|
{ re: /-----BEGIN[A-Z\s]*PRIVATE KEY-----[\s\S]*?-----END[A-Z\s]*PRIVATE KEY-----/g, replacement: "[REDACTED PRIVATE KEY]" },
|
|
// GitHub tokens
|
|
{ re: /\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36,255}\b/g, replacement: "[REDACTED GITHUB TOKEN]" },
|
|
// GitLab personal access tokens
|
|
{ re: /\bglpat-[A-Za-z0-9_-]{20,}\b/g, replacement: "[REDACTED GITLAB TOKEN]" },
|
|
// OpenAI / Anthropic API keys
|
|
{ re: /\bsk-[A-Za-z0-9_-]{20,}\b/g, replacement: "[REDACTED API KEY]" },
|
|
// Slack tokens
|
|
{ re: /\bxox[bporas]-[A-Za-z0-9-]{10,}\b/g, replacement: "[REDACTED SLACK TOKEN]" },
|
|
// JWT tokens
|
|
{ re: /\bey[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g, replacement: "[REDACTED JWT]" },
|
|
// Bearer tokens
|
|
{ re: /\bBearer\s+[A-Za-z0-9\-._~+/]+=*/gi, replacement: "Bearer [REDACTED]" },
|
|
// Connection strings with embedded passwords
|
|
{ re: /(?:postgres|mysql|mongodb|redis|amqp)(?:ql)?:\/\/[^:\s]+:[^@\s]+@/gi, replacement: "[REDACTED CONNECTION STRING]@" },
|
|
// Generic key=value secret env vars
|
|
{ re: /(?:API_KEY|API_SECRET|SECRET_KEY|SECRET|ACCESS_TOKEN|AUTH_TOKEN|PRIVATE_KEY|DATABASE_URL|DB_PASSWORD|DB_URL|REDIS_URL|PASSWORD|TOKEN)\s*[=:]\s*\S+/gi, replacement: "[REDACTED CREDENTIAL]" },
|
|
];
|
|
|
|
export function redactSecrets(text: string): string {
|
|
let result = text;
|
|
for (const { re, replacement } of patterns) {
|
|
result = result.replace(re, replacement);
|
|
}
|
|
return result;
|
|
}
|