mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 09:01:17 +00:00
Merge remote-tracking branch 'origin/main' into foundry-terminal-pane
# Conflicts: # factory/packages/backend/src/driver.ts # factory/packages/backend/src/integrations/sandbox-agent/client.ts # factory/packages/backend/test/helpers/test-driver.ts # factory/packages/frontend/src/components/mock-layout.tsx # pnpm-lock.yaml # sdks/react/src/ProcessTerminal.tsx
This commit is contained in:
commit
b00c0109d0
288 changed files with 7048 additions and 9134 deletions
|
|
@ -33,10 +33,7 @@ const DEFAULT_CLASS_NAMES: AgentConversationClassNames = {
|
|||
|
||||
const cx = (...values: Array<string | false | null | undefined>) => values.filter(Boolean).join(" ");
|
||||
|
||||
const mergeClassNames = (
|
||||
defaults: AgentConversationClassNames,
|
||||
overrides?: Partial<AgentConversationClassNames>,
|
||||
): AgentConversationClassNames => ({
|
||||
const mergeClassNames = (defaults: AgentConversationClassNames, overrides?: Partial<AgentConversationClassNames>): AgentConversationClassNames => ({
|
||||
root: cx(defaults.root, overrides?.root),
|
||||
transcript: cx(defaults.transcript, overrides?.transcript),
|
||||
emptyState: cx(defaults.emptyState, overrides?.emptyState),
|
||||
|
|
@ -56,8 +53,7 @@ export const AgentConversation = ({
|
|||
composerProps,
|
||||
}: AgentConversationProps) => {
|
||||
const resolvedClassNames = mergeClassNames(DEFAULT_CLASS_NAMES, classNameOverrides);
|
||||
const hasTranscriptContent =
|
||||
entries.length > 0 || Boolean(transcriptProps?.sessionError) || Boolean(transcriptProps?.eventError);
|
||||
const hasTranscriptContent = entries.length > 0 || Boolean(transcriptProps?.sessionError) || Boolean(transcriptProps?.eventError);
|
||||
|
||||
return (
|
||||
<div className={cx(resolvedClassNames.root, className)} data-slot="root">
|
||||
|
|
@ -74,11 +70,7 @@ export const AgentConversation = ({
|
|||
</div>
|
||||
) : null}
|
||||
{composerProps ? (
|
||||
<ChatComposer
|
||||
className={cx(resolvedClassNames.composer, composerClassName)}
|
||||
classNames={composerClassNames}
|
||||
{...composerProps}
|
||||
/>
|
||||
<ChatComposer className={cx(resolvedClassNames.composer, composerClassName)} classNames={composerClassNames} {...composerProps} />
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -177,10 +177,7 @@ const DEFAULT_DIVIDER_TITLES = new Set(["Session Started", "Turn Started", "Turn
|
|||
|
||||
const cx = (...values: Array<string | false | null | undefined>) => values.filter(Boolean).join(" ");
|
||||
|
||||
const mergeClassNames = (
|
||||
defaults: AgentTranscriptClassNames,
|
||||
overrides?: Partial<AgentTranscriptClassNames>,
|
||||
): AgentTranscriptClassNames => ({
|
||||
const mergeClassNames = (defaults: AgentTranscriptClassNames, overrides?: Partial<AgentTranscriptClassNames>): AgentTranscriptClassNames => ({
|
||||
root: cx(defaults.root, overrides?.root),
|
||||
divider: cx(defaults.divider, overrides?.divider),
|
||||
dividerLine: cx(defaults.dividerLine, overrides?.dividerLine),
|
||||
|
|
@ -240,10 +237,7 @@ const getMessageVariant = (entry: TranscriptEntry) => {
|
|||
|
||||
const getToolItemLabel = (entry: TranscriptEntry) => {
|
||||
if (entry.kind === "tool") {
|
||||
const statusLabel =
|
||||
entry.toolStatus && entry.toolStatus !== "completed"
|
||||
? ` (${entry.toolStatus.replaceAll("_", " ")})`
|
||||
: "";
|
||||
const statusLabel = entry.toolStatus && entry.toolStatus !== "completed" ? ` (${entry.toolStatus.replaceAll("_", " ")})` : "";
|
||||
return `${entry.toolName ?? "tool"}${statusLabel}`;
|
||||
}
|
||||
|
||||
|
|
@ -287,18 +281,12 @@ const defaultRenderPendingIndicator = () => "...";
|
|||
const defaultRenderChevron = (expanded: boolean) => (expanded ? "▾" : "▸");
|
||||
const defaultRenderEventLinkContent = () => "Open";
|
||||
const defaultRenderPermissionIcon = () => "Permission";
|
||||
const defaultRenderPermissionOptionContent = ({
|
||||
label,
|
||||
}: PermissionOptionRenderContext) => label;
|
||||
const defaultIsDividerEntry = (entry: TranscriptEntry) =>
|
||||
entry.kind === "meta" && DEFAULT_DIVIDER_TITLES.has(entry.meta?.title ?? "");
|
||||
const defaultRenderPermissionOptionContent = ({ label }: PermissionOptionRenderContext) => label;
|
||||
const defaultIsDividerEntry = (entry: TranscriptEntry) => entry.kind === "meta" && DEFAULT_DIVIDER_TITLES.has(entry.meta?.title ?? "");
|
||||
|
||||
const defaultCanOpenEvent = (entry: TranscriptEntry) => Boolean(entry.eventId);
|
||||
|
||||
const buildGroupedEntries = (
|
||||
entries: TranscriptEntry[],
|
||||
isDividerEntry: (entry: TranscriptEntry) => boolean,
|
||||
): GroupedEntries[] => {
|
||||
const buildGroupedEntries = (entries: TranscriptEntry[], isDividerEntry: (entry: TranscriptEntry) => boolean): GroupedEntries[] => {
|
||||
const groupedEntries: GroupedEntries[] = [];
|
||||
let currentToolGroup: TranscriptEntry[] = [];
|
||||
|
||||
|
|
@ -524,11 +512,7 @@ const ToolGroup = ({
|
|||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cx(classNames.toolGroupContainer, hasFailed && "failed")}
|
||||
data-slot="tool-group"
|
||||
data-failed={hasFailed ? "true" : undefined}
|
||||
>
|
||||
<div className={cx(classNames.toolGroupContainer, hasFailed && "failed")} data-slot="tool-group" data-failed={hasFailed ? "true" : undefined}>
|
||||
<button
|
||||
type="button"
|
||||
className={cx(classNames.toolGroupHeader, expanded && "expanded")}
|
||||
|
|
@ -591,11 +575,7 @@ const PermissionPrompt = ({
|
|||
const canReply = Boolean(onPermissionReply) && !resolved;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cx(classNames.permissionPrompt, resolved && "resolved")}
|
||||
data-slot="permission-prompt"
|
||||
data-resolved={resolved ? "true" : undefined}
|
||||
>
|
||||
<div className={cx(classNames.permissionPrompt, resolved && "resolved")} data-slot="permission-prompt" data-resolved={resolved ? "true" : undefined}>
|
||||
<div className={classNames.permissionHeader} data-slot="permission-header">
|
||||
<span className={classNames.permissionIcon} data-slot="permission-icon">
|
||||
{renderPermissionIcon(entry)}
|
||||
|
|
@ -675,14 +655,8 @@ export const AgentTranscript = ({
|
|||
renderPermissionIcon = defaultRenderPermissionIcon,
|
||||
renderPermissionOptionContent = defaultRenderPermissionOptionContent,
|
||||
}: AgentTranscriptProps) => {
|
||||
const resolvedClassNames = useMemo(
|
||||
() => mergeClassNames(DEFAULT_CLASS_NAMES, classNameOverrides),
|
||||
[classNameOverrides],
|
||||
);
|
||||
const groupedEntries = useMemo(
|
||||
() => buildGroupedEntries(entries, isDividerEntry),
|
||||
[entries, isDividerEntry],
|
||||
);
|
||||
const resolvedClassNames = useMemo(() => mergeClassNames(DEFAULT_CLASS_NAMES, classNameOverrides), [classNameOverrides]);
|
||||
const groupedEntries = useMemo(() => buildGroupedEntries(entries, isDividerEntry), [entries, isDividerEntry]);
|
||||
|
||||
return (
|
||||
<div className={cx(resolvedClassNames.root, className)} data-slot="root">
|
||||
|
|
@ -771,13 +745,13 @@ export const AgentTranscript = ({
|
|||
</div>
|
||||
) : null}
|
||||
{isThinking
|
||||
? renderThinkingState?.({ agentId }) ?? (
|
||||
? (renderThinkingState?.({ agentId }) ?? (
|
||||
<div className={resolvedClassNames.thinkingRow} data-slot="thinking-row">
|
||||
<span className={resolvedClassNames.thinkingIndicator} data-slot="thinking-indicator">
|
||||
Thinking...
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
))
|
||||
: null}
|
||||
<div ref={endRef} className={resolvedClassNames.endAnchor} data-slot="end-anchor" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -24,11 +24,9 @@ export interface ChatComposerProps {
|
|||
classNames?: Partial<ChatComposerClassNames>;
|
||||
inputRef?: Ref<HTMLTextAreaElement>;
|
||||
rows?: number;
|
||||
textareaProps?: Omit<
|
||||
TextareaHTMLAttributes<HTMLTextAreaElement>,
|
||||
"className" | "disabled" | "onChange" | "onKeyDown" | "placeholder" | "rows" | "value"
|
||||
>;
|
||||
textareaProps?: Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, "className" | "disabled" | "onChange" | "onKeyDown" | "placeholder" | "rows" | "value">;
|
||||
renderSubmitContent?: () => ReactNode;
|
||||
renderFooter?: () => ReactNode;
|
||||
}
|
||||
|
||||
const DEFAULT_CLASS_NAMES: ChatComposerClassNames = {
|
||||
|
|
@ -41,10 +39,7 @@ const DEFAULT_CLASS_NAMES: ChatComposerClassNames = {
|
|||
|
||||
const cx = (...values: Array<string | false | null | undefined>) => values.filter(Boolean).join(" ");
|
||||
|
||||
const mergeClassNames = (
|
||||
defaults: ChatComposerClassNames,
|
||||
overrides?: Partial<ChatComposerClassNames>,
|
||||
): ChatComposerClassNames => ({
|
||||
const mergeClassNames = (defaults: ChatComposerClassNames, overrides?: Partial<ChatComposerClassNames>): ChatComposerClassNames => ({
|
||||
root: cx(defaults.root, overrides?.root),
|
||||
form: cx(defaults.form, overrides?.form),
|
||||
input: cx(defaults.input, overrides?.input),
|
||||
|
|
@ -68,6 +63,7 @@ export const ChatComposer = ({
|
|||
rows = 1,
|
||||
textareaProps,
|
||||
renderSubmitContent,
|
||||
renderFooter,
|
||||
}: ChatComposerProps) => {
|
||||
const resolvedClassNames = mergeClassNames(DEFAULT_CLASS_NAMES, classNameOverrides);
|
||||
const isSubmitDisabled = disabled || submitDisabled || (!allowEmptySubmit && message.trim().length === 0);
|
||||
|
|
@ -98,6 +94,7 @@ export const ChatComposer = ({
|
|||
rows={rows}
|
||||
disabled={disabled}
|
||||
/>
|
||||
{renderFooter?.()}
|
||||
<button
|
||||
type="submit"
|
||||
className={resolvedClassNames.submit}
|
||||
|
|
|
|||
|
|
@ -207,9 +207,7 @@ export const ProcessTerminal = ({
|
|||
|
||||
setConnectionState("closed");
|
||||
setExitCode(frame.exitCode ?? null);
|
||||
setStatusMessage(
|
||||
frame.exitCode == null ? "Process exited." : `Process exited with code ${frame.exitCode}.`
|
||||
);
|
||||
setStatusMessage(frame.exitCode == null ? "Process exited." : `Process exited with code ${frame.exitCode}.`);
|
||||
onExit?.(frame);
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue