Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions dato-agent/src/components/AgentIcons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,16 @@ export function CopyIcon({ className }: IconProps) {
);
}

export function ExternalLinkIcon({ className }: IconProps) {
return (
<Icon className={className}>
<path d="M14 5h5v5" />
<path d="M19 5 10 14" />
<path d="M17 13.5V18a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1h4.5" />
</Icon>
);
}

export function EditIcon({ className }: IconProps) {
return (
<Icon className={className}>
Expand Down
37 changes: 37 additions & 0 deletions dato-agent/src/components/AgentSurface.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -1184,6 +1184,43 @@
flex: 1 1 auto;
}

.mentionReceiptItems .recordExternalLink {
display: inline-grid;
width: 22px;
height: 22px;
flex: none;
place-items: center;
padding: 0;
overflow: visible;
border: 0;
border-radius: 4px;
color: var(--color--ink-subtle);
background: transparent;
cursor: pointer;
}

.mentionReceiptItems .recordExternalLink svg {
width: 12px;
height: 12px;
}

.mentionReceiptItems .recordExternalLink:hover,
.mentionReceiptItems .recordExternalLink:focus-visible {
color: var(--color--ink);
background: var(--color--surface-hover);
}

.mentionReceiptItems .recordExternalLink:focus-visible {
outline: 2px solid var(--color--focus--outline);
outline-offset: 1px;
}

.mentionReceiptItems .recordExternalLink:disabled {
color: var(--color--disabled--ink);
cursor: default;
background: transparent;
}

.mentionReceiptState {
flex: none;
color: var(--color--ink-subtle);
Expand Down
32 changes: 32 additions & 0 deletions dato-agent/src/components/AgentSurface.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,38 @@ describe('AgentSurface', () => {
);
});

it('opens a record result in the full editor without opening it in the pane', async () => {
const user = userEvent.setup();
const onOpenRecord = vi.fn();
const onOpenRecordInFullEditor = vi.fn();

render(
<AgentSurface
connection={connected}
entries={[
{
id: 'records',
kind: 'records',
title: 'Matching articles',
records: [{ itemId: 'two', itemTypeId: 'post', title: 'Two' }],
},
]}
onOpenRecord={onOpenRecord}
onOpenRecordInFullEditor={onOpenRecordInFullEditor}
onSubmit={vi.fn()}
/>,
);

await user.click(
screen.getByRole('button', { name: 'Open Two in the full editor' }),
);
expect(onOpenRecordInFullEditor).toHaveBeenCalledWith(
{ itemId: 'two', itemTypeId: 'post', title: 'Two' },
'records',
);
expect(onOpenRecord).not.toHaveBeenCalled();
});

it('opens record, field, asset, model, and user mentions directly from user messages', async () => {
const user = userEvent.setup();
const onOpenRecord = vi.fn();
Expand Down
62 changes: 49 additions & 13 deletions dato-agent/src/components/AgentSurface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
CopyIcon,
DisconnectIcon,
EditIcon,
ExternalLinkIcon,
HistoryIcon,
PlusIcon,
RetryIcon,
Expand Down Expand Up @@ -299,6 +300,10 @@ export type AgentSurfaceProps = {
record: AgentRecordResultViewModel,
entryId?: string,
) => void | Promise<void>;
onOpenRecordInFullEditor?: (
record: AgentRecordResultViewModel,
entryId?: string,
) => void | Promise<void>;
onOpenField?: (
field: AgentFieldResultViewModel,
entryId?: string,
Expand Down Expand Up @@ -1144,12 +1149,14 @@ function RecordsEntry({
entry,
mentionHost,
onOpenRecord,
onOpenRecordInFullEditor,
}: {
disabled?: boolean;
currentRecordId?: string;
entry: AgentRecordsEntry;
mentionHost: AgentMentionHost;
onOpenRecord?: AgentSurfaceProps['onOpenRecord'];
onOpenRecordInFullEditor?: AgentSurfaceProps['onOpenRecordInFullEditor'];
}) {
const modelsById = new Map(
mentionHost.projectModels.map((model) => [model.id, model]),
Expand Down Expand Up @@ -1187,20 +1194,41 @@ function RecordsEntry({
: {}),
});
return (
<MentionDisplay
accessibleLabel={`Open ${mention.title}`}
currentRecordId={currentRecordId}
isClickable={!disabled && Boolean(onOpenRecord)}
<span
className={styles.mentionReceiptItem}
key={`${record.itemTypeId ?? 'record'}:${record.itemId}`}
mention={mention}
onClick={() => {
if (!disabled && onOpenRecord) {
void Promise.resolve(onOpenRecord(record, entry.id)).catch(
() => undefined,
);
}
}}
/>
>
<MentionDisplay
accessibleLabel={`Open ${mention.title}`}
currentRecordId={currentRecordId}
isClickable={!disabled && Boolean(onOpenRecord)}
mention={mention}
onClick={() => {
if (!disabled && onOpenRecord) {
void Promise.resolve(onOpenRecord(record, entry.id)).catch(
() => undefined,
);
}
}}
/>
{onOpenRecordInFullEditor && (
<button
aria-label={`Open ${mention.title} in the full editor`}
className={styles.recordExternalLink}
disabled={disabled}
onClick={() => {
if (!disabled) {
void Promise.resolve(
onOpenRecordInFullEditor(record, entry.id),
).catch(() => undefined);
}
}}
type="button"
>
<ExternalLinkIcon />
</button>
)}
</span>
);
})}
</div>
Expand Down Expand Up @@ -1799,6 +1827,7 @@ function AgentTurnEntry({
onOpenAsset,
onOpenField,
onOpenRecord,
onOpenRecordInFullEditor,
onRejectUnsafeAction,
onRepairUnsafeAction,
onRetryFailedTurn,
Expand All @@ -1814,6 +1843,7 @@ function AgentTurnEntry({
onOpenAsset?: AgentSurfaceProps['onOpenAsset'];
onOpenField?: AgentSurfaceProps['onOpenField'];
onOpenRecord?: AgentSurfaceProps['onOpenRecord'];
onOpenRecordInFullEditor?: AgentSurfaceProps['onOpenRecordInFullEditor'];
onRejectUnsafeAction?: AgentSurfaceProps['onRejectUnsafeAction'];
onRepairUnsafeAction?: AgentSurfaceProps['onRepairUnsafeAction'];
onRetryFailedTurn?: AgentSurfaceProps['onRetryFailedTurn'];
Expand Down Expand Up @@ -1859,6 +1889,7 @@ function AgentTurnEntry({
key={entry.id}
mentionHost={mentionHost}
onOpenRecord={onOpenRecord}
onOpenRecordInFullEditor={onOpenRecordInFullEditor}
/>
);
case 'fields':
Expand Down Expand Up @@ -1917,6 +1948,7 @@ function Transcript({
entries,
mentionHost,
onOpenRecord,
onOpenRecordInFullEditor,
onOpenField,
onOpenAsset,
onReviewUnsafeAction,
Expand All @@ -1933,6 +1965,7 @@ function Transcript({
| 'autoApproveEnabled'
| 'currentRecordId'
| 'onOpenRecord'
| 'onOpenRecordInFullEditor'
| 'onOpenField'
| 'onOpenAsset'
| 'onReviewUnsafeAction'
Expand Down Expand Up @@ -2026,6 +2059,7 @@ function Transcript({
onOpenAsset={onOpenAsset}
onOpenField={onOpenField}
onOpenRecord={onOpenRecord}
onOpenRecordInFullEditor={onOpenRecordInFullEditor}
onRejectUnsafeAction={onRejectUnsafeAction}
onRepairUnsafeAction={onRepairUnsafeAction}
onRetryFailedTurn={onRetryFailedTurn}
Expand Down Expand Up @@ -2151,6 +2185,7 @@ export function AgentSurface({
onStartNewChat,
onStop,
onOpenRecord,
onOpenRecordInFullEditor,
onOpenField,
onOpenAsset,
hostActionPending = false,
Expand Down Expand Up @@ -2372,6 +2407,7 @@ export function AgentSurface({
onOpenAsset={onOpenAsset}
onOpenField={onOpenField}
onOpenRecord={onOpenRecord}
onOpenRecordInFullEditor={onOpenRecordInFullEditor}
hostActionPending={hostActionPending}
onRejectUnsafeAction={onRejectUnsafeAction}
onRepairUnsafeAction={onRepairUnsafeAction}
Expand Down
Loading