[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
211
components/ai/toolArtifacts/VaultArtifactCard.tsx
Normal file
211
components/ai/toolArtifacts/VaultArtifactCard.tsx
Normal file
@@ -0,0 +1,211 @@
|
||||
import { ChevronRight } from 'lucide-react';
|
||||
import React from 'react';
|
||||
import { useI18n } from '../../../application/i18n/I18nProvider';
|
||||
import { cn } from '../../../lib/utils';
|
||||
import type { VaultToolArtifact } from './vaultToolArtifact';
|
||||
import {
|
||||
canNavigateVaultArtifact,
|
||||
navigateVaultArtifact,
|
||||
useVaultArtifactNavigation,
|
||||
} from './VaultArtifactNavigationContext';
|
||||
import { VaultArtifactIcon } from './vaultArtifactPresentation';
|
||||
|
||||
interface VaultArtifactCardProps {
|
||||
artifact: VaultToolArtifact;
|
||||
toolName?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function getArtifactPresentation(
|
||||
artifact: VaultToolArtifact,
|
||||
t: (key: string, values?: Record<string, unknown>) => string,
|
||||
): {
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
clickable: boolean;
|
||||
} {
|
||||
switch (artifact.kind) {
|
||||
case 'vault.note':
|
||||
return {
|
||||
title: artifact.title,
|
||||
subtitle: artifact.group ?? t('ai.chat.artifact.noteFallback'),
|
||||
clickable: true,
|
||||
};
|
||||
case 'vault.host':
|
||||
return {
|
||||
title: artifact.label,
|
||||
subtitle: artifact.port
|
||||
? `${artifact.hostname}:${artifact.port}`
|
||||
: artifact.hostname,
|
||||
clickable: true,
|
||||
};
|
||||
case 'vault.hosts.batch': {
|
||||
const preview = artifact.preview
|
||||
.slice(0, 2)
|
||||
.map((host) => host.label || host.hostname)
|
||||
.filter(Boolean)
|
||||
.join(', ');
|
||||
return {
|
||||
title: artifact.dryRun
|
||||
? t('ai.chat.artifact.hostsPreview', { count: artifact.addedCount })
|
||||
: t('ai.chat.artifact.hostsAdded', { count: artifact.addedCount }),
|
||||
subtitle: preview || t('ai.chat.artifact.openHosts'),
|
||||
clickable: true,
|
||||
};
|
||||
}
|
||||
case 'vault.summary':
|
||||
return {
|
||||
title: artifact.section === 'notes'
|
||||
? t('ai.chat.artifact.notesSummary', { count: artifact.count })
|
||||
: artifact.section === 'hosts'
|
||||
? t('ai.chat.artifact.hostsSummary', { count: artifact.count })
|
||||
: artifact.section === 'snippets'
|
||||
? t('ai.chat.artifact.snippetsSummary', { count: artifact.count })
|
||||
: t('ai.chat.artifact.scriptsSummary', { count: artifact.count }),
|
||||
subtitle: artifact.section === 'notes'
|
||||
? t('ai.chat.artifact.openNotes')
|
||||
: artifact.section === 'hosts'
|
||||
? t('ai.chat.artifact.openHosts')
|
||||
: t('ai.chat.artifact.openSnippets'),
|
||||
clickable: true,
|
||||
};
|
||||
case 'vault.snippet':
|
||||
return {
|
||||
title: artifact.label,
|
||||
subtitle: artifact.package || t('ai.chat.artifact.snippetFallback'),
|
||||
clickable: true,
|
||||
};
|
||||
case 'vault.script':
|
||||
return {
|
||||
title: artifact.label,
|
||||
subtitle: artifact.language
|
||||
? t('ai.chat.artifact.scriptLanguage', { language: artifact.language })
|
||||
: artifact.package || t('ai.chat.artifact.scriptFallback'),
|
||||
clickable: true,
|
||||
};
|
||||
case 'vault.snippet.deleted':
|
||||
return {
|
||||
title: t('ai.chat.artifact.snippetDeleted'),
|
||||
subtitle: artifact.snippetId,
|
||||
clickable: false,
|
||||
};
|
||||
case 'vault.script.deleted':
|
||||
return {
|
||||
title: t('ai.chat.artifact.scriptDeleted'),
|
||||
subtitle: artifact.scriptId,
|
||||
clickable: false,
|
||||
};
|
||||
case 'vault.snippet.run':
|
||||
return {
|
||||
title: t('ai.chat.artifact.snippetRan'),
|
||||
subtitle: artifact.command || artifact.snippetId,
|
||||
clickable: true,
|
||||
};
|
||||
case 'vault.script.run':
|
||||
return {
|
||||
title: artifact.status
|
||||
? t('ai.chat.artifact.scriptRunStatus', { status: artifact.status })
|
||||
: t('ai.chat.artifact.scriptStarted'),
|
||||
subtitle: artifact.runId,
|
||||
clickable: true,
|
||||
};
|
||||
case 'vault.script.runs':
|
||||
return {
|
||||
title: t('ai.chat.artifact.scriptRunsSummary', { count: artifact.count }),
|
||||
subtitle: t('ai.chat.artifact.openSnippets'),
|
||||
clickable: true,
|
||||
};
|
||||
case 'vault.script.action':
|
||||
return {
|
||||
title: artifact.action === 'stop'
|
||||
? t('ai.chat.artifact.scriptRunStopped')
|
||||
: artifact.action === 'pause'
|
||||
? t('ai.chat.artifact.scriptRunPaused')
|
||||
: t('ai.chat.artifact.scriptRunResumed'),
|
||||
subtitle: artifact.runId,
|
||||
clickable: false,
|
||||
};
|
||||
case 'vault.script.reference':
|
||||
return {
|
||||
title: t('ai.chat.artifact.scriptReference'),
|
||||
subtitle: t('ai.chat.artifact.openSnippets'),
|
||||
clickable: true,
|
||||
};
|
||||
case 'error':
|
||||
return {
|
||||
title: t('ai.chat.artifact.failed'),
|
||||
subtitle: artifact.message,
|
||||
clickable: false,
|
||||
};
|
||||
default:
|
||||
return {
|
||||
title: '',
|
||||
clickable: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const VaultArtifactCard: React.FC<VaultArtifactCardProps> = ({
|
||||
artifact,
|
||||
toolName,
|
||||
className,
|
||||
}) => {
|
||||
const { t } = useI18n();
|
||||
const navigation = useVaultArtifactNavigation();
|
||||
const presentation = getArtifactPresentation(artifact, t);
|
||||
const canNavigate = presentation.clickable && canNavigateVaultArtifact(artifact, navigation);
|
||||
|
||||
const handleClick = () => {
|
||||
if (!canNavigate || !navigation) return;
|
||||
navigateVaultArtifact(artifact, navigation);
|
||||
};
|
||||
|
||||
const content = (
|
||||
<>
|
||||
<VaultArtifactIcon artifact={artifact} toolName={toolName} />
|
||||
<div className="min-w-0 flex-1 text-left">
|
||||
<div className="truncate text-[12px] font-medium text-foreground/85">
|
||||
{presentation.title}
|
||||
</div>
|
||||
{presentation.subtitle && (
|
||||
<div className="truncate text-[11px] text-muted-foreground/60">
|
||||
{presentation.subtitle}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{canNavigate && (
|
||||
<ChevronRight size={12} className="shrink-0 text-muted-foreground/40" />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
if (!canNavigate) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
presentation.clickable
|
||||
? 'flex w-full items-center gap-2.5 rounded-md border border-border/25 bg-muted/10 px-2.5 py-2 text-left'
|
||||
: 'flex items-center gap-2 px-1 py-0.5',
|
||||
className,
|
||||
'cursor-default',
|
||||
)}
|
||||
>
|
||||
{content}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleClick}
|
||||
className={cn(
|
||||
'flex w-full items-center gap-2.5 rounded-md border border-border/25 bg-muted/10 px-2.5 py-2',
|
||||
'text-left transition-colors hover:bg-muted/20',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{content}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user