mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-25 00:36:31 +02:00
refactor: unify interrupt handling in Linear and Notion tools
Refactored the create, update, and delete functionalities in Linear and Notion tools to utilize a consistent InterruptResult interface with specific context types. This change enhances code clarity and maintains uniformity in handling user approvals by integrating the useHitlDecision hook for decision dispatching.
This commit is contained in:
parent
e6065b6793
commit
5169d3d56c
6 changed files with 129 additions and 301 deletions
|
|
@ -18,6 +18,8 @@ import {
|
|||
} from "@/components/ui/select";
|
||||
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
||||
import { useHitlPhase } from "@/hooks/use-hitl-phase";
|
||||
import { isInterruptResult, useHitlDecision } from "@/lib/hitl";
|
||||
import type { InterruptResult, HitlDecision } from "@/lib/hitl";
|
||||
|
||||
interface LinearLabel {
|
||||
id: string;
|
||||
|
|
@ -64,23 +66,9 @@ interface LinearWorkspace {
|
|||
auth_expired?: boolean;
|
||||
}
|
||||
|
||||
interface InterruptResult {
|
||||
__interrupt__: true;
|
||||
__decided__?: "approve" | "reject" | "edit";
|
||||
__completed__?: boolean;
|
||||
action_requests: Array<{
|
||||
name: string;
|
||||
args: Record<string, unknown>;
|
||||
}>;
|
||||
review_configs: Array<{
|
||||
action_name: string;
|
||||
allowed_decisions: Array<"approve" | "edit" | "reject">;
|
||||
}>;
|
||||
interrupt_type?: string;
|
||||
context?: {
|
||||
workspaces?: LinearWorkspace[];
|
||||
error?: string;
|
||||
};
|
||||
interface LinearCreateIssueContext {
|
||||
workspaces?: LinearWorkspace[];
|
||||
error?: string;
|
||||
}
|
||||
|
||||
interface SuccessResult {
|
||||
|
|
@ -103,16 +91,7 @@ interface AuthErrorResult {
|
|||
connector_type: string;
|
||||
}
|
||||
|
||||
type CreateLinearIssueResult = InterruptResult | SuccessResult | ErrorResult | AuthErrorResult;
|
||||
|
||||
function isInterruptResult(result: unknown): result is InterruptResult {
|
||||
return (
|
||||
typeof result === "object" &&
|
||||
result !== null &&
|
||||
"__interrupt__" in result &&
|
||||
(result as InterruptResult).__interrupt__ === true
|
||||
);
|
||||
}
|
||||
type CreateLinearIssueResult = InterruptResult<LinearCreateIssueContext> | SuccessResult | ErrorResult | AuthErrorResult;
|
||||
|
||||
function isErrorResult(result: unknown): result is ErrorResult {
|
||||
return (
|
||||
|
|
@ -138,12 +117,8 @@ function ApprovalCard({
|
|||
onDecision,
|
||||
}: {
|
||||
args: { title: string; description?: string };
|
||||
interruptData: InterruptResult;
|
||||
onDecision: (decision: {
|
||||
type: "approve" | "reject" | "edit";
|
||||
message?: string;
|
||||
edited_action?: { name: string; args: Record<string, unknown> };
|
||||
}) => void;
|
||||
interruptData: InterruptResult<LinearCreateIssueContext>;
|
||||
onDecision: (decision: HitlDecision) => void;
|
||||
}) {
|
||||
const { phase, setProcessing, setRejected } = useHitlPhase(interruptData);
|
||||
const [isPanelOpen, setIsPanelOpen] = useState(false);
|
||||
|
|
@ -609,18 +584,16 @@ export const CreateLinearIssueToolUI = ({
|
|||
args,
|
||||
result,
|
||||
}: ToolCallMessagePartProps<{ title: string; description?: string }, CreateLinearIssueResult>) => {
|
||||
const { dispatch } = useHitlDecision();
|
||||
|
||||
if (!result) return null;
|
||||
|
||||
if (isInterruptResult(result)) {
|
||||
return (
|
||||
<ApprovalCard
|
||||
args={args}
|
||||
interruptData={result}
|
||||
onDecision={(decision) => {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("hitl-decision", { detail: { decisions: [decision] } })
|
||||
);
|
||||
}}
|
||||
interruptData={result as InterruptResult<LinearCreateIssueContext>}
|
||||
onDecision={(decision) => dispatch([decision])}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,32 +7,20 @@ import { TextShimmerLoader } from "@/components/prompt-kit/loader";
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { useHitlPhase } from "@/hooks/use-hitl-phase";
|
||||
import { isInterruptResult, useHitlDecision } from "@/lib/hitl";
|
||||
import type { InterruptResult, HitlDecision } from "@/lib/hitl";
|
||||
|
||||
interface InterruptResult {
|
||||
__interrupt__: true;
|
||||
__decided__?: "approve" | "reject";
|
||||
__completed__?: boolean;
|
||||
action_requests: Array<{
|
||||
name: string;
|
||||
args: Record<string, unknown>;
|
||||
}>;
|
||||
review_configs: Array<{
|
||||
action_name: string;
|
||||
allowed_decisions: Array<"approve" | "reject">;
|
||||
}>;
|
||||
interrupt_type?: string;
|
||||
context?: {
|
||||
workspace?: { id: number; organization_name: string };
|
||||
issue?: {
|
||||
id: string;
|
||||
identifier: string;
|
||||
title: string;
|
||||
state?: string;
|
||||
document_id?: number;
|
||||
indexed_at?: string;
|
||||
};
|
||||
error?: string;
|
||||
interface LinearDeleteIssueContext {
|
||||
workspace?: { id: number; organization_name: string };
|
||||
issue?: {
|
||||
id: string;
|
||||
identifier: string;
|
||||
title: string;
|
||||
state?: string;
|
||||
document_id?: number;
|
||||
indexed_at?: string;
|
||||
};
|
||||
error?: string;
|
||||
}
|
||||
|
||||
interface SuccessResult {
|
||||
|
|
@ -65,22 +53,13 @@ interface AuthErrorResult {
|
|||
}
|
||||
|
||||
type DeleteLinearIssueResult =
|
||||
| InterruptResult
|
||||
| InterruptResult<LinearDeleteIssueContext>
|
||||
| SuccessResult
|
||||
| ErrorResult
|
||||
| NotFoundResult
|
||||
| WarningResult
|
||||
| AuthErrorResult;
|
||||
|
||||
function isInterruptResult(result: unknown): result is InterruptResult {
|
||||
return (
|
||||
typeof result === "object" &&
|
||||
result !== null &&
|
||||
"__interrupt__" in result &&
|
||||
(result as InterruptResult).__interrupt__ === true
|
||||
);
|
||||
}
|
||||
|
||||
function isErrorResult(result: unknown): result is ErrorResult {
|
||||
return (
|
||||
typeof result === "object" &&
|
||||
|
|
@ -123,12 +102,8 @@ function ApprovalCard({
|
|||
interruptData,
|
||||
onDecision,
|
||||
}: {
|
||||
interruptData: InterruptResult;
|
||||
onDecision: (decision: {
|
||||
type: "approve" | "reject";
|
||||
message?: string;
|
||||
edited_action?: { name: string; args: Record<string, unknown> };
|
||||
}) => void;
|
||||
interruptData: InterruptResult<LinearDeleteIssueContext>;
|
||||
onDecision: (decision: HitlDecision) => void;
|
||||
}) {
|
||||
const { phase, setProcessing, setRejected } = useHitlPhase(interruptData);
|
||||
const [deleteFromKb, setDeleteFromKb] = useState(false);
|
||||
|
|
@ -366,18 +341,15 @@ export const DeleteLinearIssueToolUI = ({
|
|||
{ issue_ref: string; delete_from_kb?: boolean },
|
||||
DeleteLinearIssueResult
|
||||
>) => {
|
||||
const { dispatch } = useHitlDecision();
|
||||
|
||||
if (!result) return null;
|
||||
|
||||
if (isInterruptResult(result)) {
|
||||
return (
|
||||
<ApprovalCard
|
||||
interruptData={result}
|
||||
onDecision={(decision) => {
|
||||
const event = new CustomEvent("hitl-decision", {
|
||||
detail: { decisions: [decision] },
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
}}
|
||||
interruptData={result as InterruptResult<LinearDeleteIssueContext>}
|
||||
onDecision={(decision) => dispatch([decision])}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ import {
|
|||
} from "@/components/ui/select";
|
||||
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
||||
import { useHitlPhase } from "@/hooks/use-hitl-phase";
|
||||
import { isInterruptResult, useHitlDecision } from "@/lib/hitl";
|
||||
import type { InterruptResult, HitlDecision } from "@/lib/hitl";
|
||||
|
||||
interface LinearLabel {
|
||||
id: string;
|
||||
|
|
@ -45,45 +47,31 @@ interface LinearPriority {
|
|||
label: string;
|
||||
}
|
||||
|
||||
interface InterruptResult {
|
||||
__interrupt__: true;
|
||||
__decided__?: "approve" | "reject" | "edit";
|
||||
__completed__?: boolean;
|
||||
action_requests: Array<{
|
||||
name: string;
|
||||
args: Record<string, unknown>;
|
||||
}>;
|
||||
review_configs: Array<{
|
||||
action_name: string;
|
||||
allowed_decisions: Array<"approve" | "edit" | "reject">;
|
||||
}>;
|
||||
interrupt_type?: string;
|
||||
context?: {
|
||||
workspace?: { id: number; organization_name: string };
|
||||
priorities?: LinearPriority[];
|
||||
issue?: {
|
||||
id: string;
|
||||
identifier: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
priority: number;
|
||||
url: string;
|
||||
current_state?: LinearState;
|
||||
current_assignee?: { id: string; name: string; email: string } | null;
|
||||
current_labels?: LinearLabel[];
|
||||
team_id: string;
|
||||
document_id: number;
|
||||
};
|
||||
team?: {
|
||||
id: string;
|
||||
name: string;
|
||||
key: string;
|
||||
states: LinearState[];
|
||||
members: LinearMember[];
|
||||
labels: LinearLabel[];
|
||||
};
|
||||
error?: string;
|
||||
interface LinearUpdateIssueContext {
|
||||
workspace?: { id: number; organization_name: string };
|
||||
priorities?: LinearPriority[];
|
||||
issue?: {
|
||||
id: string;
|
||||
identifier: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
priority: number;
|
||||
url: string;
|
||||
current_state?: LinearState;
|
||||
current_assignee?: { id: string; name: string; email: string } | null;
|
||||
current_labels?: LinearLabel[];
|
||||
team_id: string;
|
||||
document_id: number;
|
||||
};
|
||||
team?: {
|
||||
id: string;
|
||||
name: string;
|
||||
key: string;
|
||||
states: LinearState[];
|
||||
members: LinearMember[];
|
||||
labels: LinearLabel[];
|
||||
};
|
||||
error?: string;
|
||||
}
|
||||
|
||||
interface SuccessResult {
|
||||
|
|
@ -111,21 +99,12 @@ interface AuthErrorResult {
|
|||
}
|
||||
|
||||
type UpdateLinearIssueResult =
|
||||
| InterruptResult
|
||||
| InterruptResult<LinearUpdateIssueContext>
|
||||
| SuccessResult
|
||||
| ErrorResult
|
||||
| NotFoundResult
|
||||
| AuthErrorResult;
|
||||
|
||||
function isInterruptResult(result: unknown): result is InterruptResult {
|
||||
return (
|
||||
typeof result === "object" &&
|
||||
result !== null &&
|
||||
"__interrupt__" in result &&
|
||||
(result as InterruptResult).__interrupt__ === true
|
||||
);
|
||||
}
|
||||
|
||||
function isErrorResult(result: unknown): result is ErrorResult {
|
||||
return (
|
||||
typeof result === "object" &&
|
||||
|
|
@ -167,12 +146,8 @@ function ApprovalCard({
|
|||
new_priority?: number;
|
||||
new_label_names?: string[];
|
||||
};
|
||||
interruptData: InterruptResult;
|
||||
onDecision: (decision: {
|
||||
type: "approve" | "reject" | "edit";
|
||||
message?: string;
|
||||
edited_action?: { name: string; args: Record<string, unknown> };
|
||||
}) => void;
|
||||
interruptData: InterruptResult<LinearUpdateIssueContext>;
|
||||
onDecision: (decision: HitlDecision) => void;
|
||||
}) {
|
||||
const { phase, setProcessing, setRejected } = useHitlPhase(interruptData);
|
||||
|
||||
|
|
@ -752,18 +727,16 @@ export const UpdateLinearIssueToolUI = ({
|
|||
},
|
||||
UpdateLinearIssueResult
|
||||
>) => {
|
||||
const { dispatch } = useHitlDecision();
|
||||
|
||||
if (!result) return null;
|
||||
|
||||
if (isInterruptResult(result)) {
|
||||
return (
|
||||
<ApprovalCard
|
||||
args={args}
|
||||
interruptData={result}
|
||||
onDecision={(decision) => {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("hitl-decision", { detail: { decisions: [decision] } })
|
||||
);
|
||||
}}
|
||||
interruptData={result as InterruptResult<LinearUpdateIssueContext>}
|
||||
onDecision={(decision) => dispatch([decision])}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,41 +16,27 @@ import {
|
|||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { useHitlPhase } from "@/hooks/use-hitl-phase";
|
||||
import { isInterruptResult, useHitlDecision } from "@/lib/hitl";
|
||||
import type { InterruptResult, HitlDecision } from "@/lib/hitl";
|
||||
|
||||
interface InterruptResult {
|
||||
__interrupt__: true;
|
||||
__decided__?: "approve" | "reject" | "edit";
|
||||
__completed__?: boolean;
|
||||
action_requests: Array<{
|
||||
interface NotionCreatePageContext {
|
||||
accounts?: Array<{
|
||||
id: number;
|
||||
name: string;
|
||||
args: Record<string, unknown>;
|
||||
description?: string;
|
||||
workspace_id: string | null;
|
||||
workspace_name: string;
|
||||
workspace_icon: string;
|
||||
auth_expired?: boolean;
|
||||
}>;
|
||||
review_configs: Array<{
|
||||
action_name: string;
|
||||
allowed_decisions: Array<"approve" | "edit" | "reject">;
|
||||
}>;
|
||||
interrupt_type?: string;
|
||||
message?: string;
|
||||
context?: {
|
||||
accounts?: Array<{
|
||||
id: number;
|
||||
name: string;
|
||||
workspace_id: string | null;
|
||||
workspace_name: string;
|
||||
workspace_icon: string;
|
||||
auth_expired?: boolean;
|
||||
}>;
|
||||
parent_pages?: Record<
|
||||
number,
|
||||
Array<{
|
||||
page_id: string;
|
||||
title: string;
|
||||
document_id: number;
|
||||
}>
|
||||
>;
|
||||
error?: string;
|
||||
};
|
||||
parent_pages?: Record<
|
||||
number,
|
||||
Array<{
|
||||
page_id: string;
|
||||
title: string;
|
||||
document_id: number;
|
||||
}>
|
||||
>;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
interface SuccessResult {
|
||||
|
|
@ -75,16 +61,7 @@ interface AuthErrorResult {
|
|||
connector_type: string;
|
||||
}
|
||||
|
||||
type CreateNotionPageResult = InterruptResult | SuccessResult | ErrorResult | AuthErrorResult;
|
||||
|
||||
function isInterruptResult(result: unknown): result is InterruptResult {
|
||||
return (
|
||||
typeof result === "object" &&
|
||||
result !== null &&
|
||||
"__interrupt__" in result &&
|
||||
(result as InterruptResult).__interrupt__ === true
|
||||
);
|
||||
}
|
||||
type CreateNotionPageResult = InterruptResult<NotionCreatePageContext> | SuccessResult | ErrorResult | AuthErrorResult;
|
||||
|
||||
function isAuthErrorResult(result: unknown): result is AuthErrorResult {
|
||||
return (
|
||||
|
|
@ -110,12 +87,8 @@ function ApprovalCard({
|
|||
onDecision,
|
||||
}: {
|
||||
args: Record<string, unknown>;
|
||||
interruptData: InterruptResult;
|
||||
onDecision: (decision: {
|
||||
type: "approve" | "reject" | "edit";
|
||||
message?: string;
|
||||
edited_action?: { name: string; args: Record<string, unknown> };
|
||||
}) => void;
|
||||
interruptData: InterruptResult<NotionCreatePageContext>;
|
||||
onDecision: (decision: HitlDecision) => void;
|
||||
}) {
|
||||
const { phase, setProcessing, setRejected } = useHitlPhase(interruptData);
|
||||
const [isPanelOpen, setIsPanelOpen] = useState(false);
|
||||
|
|
@ -449,19 +422,16 @@ export const CreateNotionPageToolUI = ({
|
|||
args,
|
||||
result,
|
||||
}: ToolCallMessagePartProps<{ title: string; content: string }, CreateNotionPageResult>) => {
|
||||
const { dispatch } = useHitlDecision();
|
||||
|
||||
if (!result) return null;
|
||||
|
||||
if (isInterruptResult(result)) {
|
||||
return (
|
||||
<ApprovalCard
|
||||
args={args}
|
||||
interruptData={result}
|
||||
onDecision={(decision) => {
|
||||
const event = new CustomEvent("hitl-decision", {
|
||||
detail: { decisions: [decision] },
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
}}
|
||||
interruptData={result as InterruptResult<NotionCreatePageContext>}
|
||||
onDecision={(decision) => dispatch([decision])}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,36 +7,22 @@ import { TextShimmerLoader } from "@/components/prompt-kit/loader";
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { useHitlPhase } from "@/hooks/use-hitl-phase";
|
||||
import { isInterruptResult, useHitlDecision } from "@/lib/hitl";
|
||||
import type { InterruptResult, HitlDecision } from "@/lib/hitl";
|
||||
|
||||
interface InterruptResult {
|
||||
__interrupt__: true;
|
||||
__decided__?: "approve" | "reject";
|
||||
__completed__?: boolean;
|
||||
action_requests: Array<{
|
||||
interface NotionDeletePageContext {
|
||||
account?: {
|
||||
id: number;
|
||||
name: string;
|
||||
args: Record<string, unknown>;
|
||||
description?: string;
|
||||
}>;
|
||||
review_configs: Array<{
|
||||
action_name: string;
|
||||
allowed_decisions: Array<"approve" | "reject">;
|
||||
}>;
|
||||
interrupt_type?: string;
|
||||
message?: string;
|
||||
context?: {
|
||||
account?: {
|
||||
id: number;
|
||||
name: string;
|
||||
workspace_id: string | null;
|
||||
workspace_name: string;
|
||||
workspace_icon: string;
|
||||
};
|
||||
page_id?: string;
|
||||
current_title?: string;
|
||||
document_id?: number;
|
||||
indexed_at?: string;
|
||||
error?: string;
|
||||
workspace_id: string | null;
|
||||
workspace_name: string;
|
||||
workspace_icon: string;
|
||||
};
|
||||
page_id?: string;
|
||||
current_title?: string;
|
||||
document_id?: number;
|
||||
indexed_at?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
interface SuccessResult {
|
||||
|
|
@ -73,22 +59,13 @@ interface AuthErrorResult {
|
|||
}
|
||||
|
||||
type DeleteNotionPageResult =
|
||||
| InterruptResult
|
||||
| InterruptResult<NotionDeletePageContext>
|
||||
| SuccessResult
|
||||
| ErrorResult
|
||||
| InfoResult
|
||||
| WarningResult
|
||||
| AuthErrorResult;
|
||||
|
||||
function isInterruptResult(result: unknown): result is InterruptResult {
|
||||
return (
|
||||
typeof result === "object" &&
|
||||
result !== null &&
|
||||
"__interrupt__" in result &&
|
||||
(result as InterruptResult).__interrupt__ === true
|
||||
);
|
||||
}
|
||||
|
||||
function isErrorResult(result: unknown): result is ErrorResult {
|
||||
return (
|
||||
typeof result === "object" &&
|
||||
|
|
@ -131,12 +108,8 @@ function ApprovalCard({
|
|||
interruptData,
|
||||
onDecision,
|
||||
}: {
|
||||
interruptData: InterruptResult;
|
||||
onDecision: (decision: {
|
||||
type: "approve" | "reject";
|
||||
message?: string;
|
||||
edited_action?: { name: string; args: Record<string, unknown> };
|
||||
}) => void;
|
||||
interruptData: InterruptResult<NotionDeletePageContext>;
|
||||
onDecision: (decision: HitlDecision) => void;
|
||||
}) {
|
||||
const { phase, setProcessing, setRejected } = useHitlPhase(interruptData);
|
||||
const [deleteFromKb, setDeleteFromKb] = useState(false);
|
||||
|
|
@ -378,18 +351,15 @@ export const DeleteNotionPageToolUI = ({
|
|||
{ page_title: string; delete_from_kb?: boolean },
|
||||
DeleteNotionPageResult
|
||||
>) => {
|
||||
const { dispatch } = useHitlDecision();
|
||||
|
||||
if (!result) return null;
|
||||
|
||||
if (isInterruptResult(result)) {
|
||||
return (
|
||||
<ApprovalCard
|
||||
interruptData={result}
|
||||
onDecision={(decision) => {
|
||||
const event = new CustomEvent("hitl-decision", {
|
||||
detail: { decisions: [decision] },
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
}}
|
||||
interruptData={result as InterruptResult<NotionDeletePageContext>}
|
||||
onDecision={(decision) => dispatch([decision])}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,36 +9,22 @@ import { PlateEditor } from "@/components/editor/plate-editor";
|
|||
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useHitlPhase } from "@/hooks/use-hitl-phase";
|
||||
import { isInterruptResult, useHitlDecision } from "@/lib/hitl";
|
||||
import type { InterruptResult, HitlDecision } from "@/lib/hitl";
|
||||
|
||||
interface InterruptResult {
|
||||
__interrupt__: true;
|
||||
__decided__?: "approve" | "reject" | "edit";
|
||||
__completed__?: boolean;
|
||||
action_requests: Array<{
|
||||
interface NotionUpdatePageContext {
|
||||
account?: {
|
||||
id: number;
|
||||
name: string;
|
||||
args: Record<string, unknown>;
|
||||
description?: string;
|
||||
}>;
|
||||
review_configs: Array<{
|
||||
action_name: string;
|
||||
allowed_decisions: Array<"approve" | "edit" | "reject">;
|
||||
}>;
|
||||
interrupt_type?: string;
|
||||
message?: string;
|
||||
context?: {
|
||||
account?: {
|
||||
id: number;
|
||||
name: string;
|
||||
workspace_id: string | null;
|
||||
workspace_name: string;
|
||||
workspace_icon: string;
|
||||
};
|
||||
page_id?: string;
|
||||
current_title?: string;
|
||||
document_id?: number;
|
||||
indexed_at?: string;
|
||||
error?: string;
|
||||
workspace_id: string | null;
|
||||
workspace_name: string;
|
||||
workspace_icon: string;
|
||||
};
|
||||
page_id?: string;
|
||||
current_title?: string;
|
||||
document_id?: number;
|
||||
indexed_at?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
interface SuccessResult {
|
||||
|
|
@ -69,21 +55,12 @@ interface AuthErrorResult {
|
|||
}
|
||||
|
||||
type UpdateNotionPageResult =
|
||||
| InterruptResult
|
||||
| InterruptResult<NotionUpdatePageContext>
|
||||
| SuccessResult
|
||||
| ErrorResult
|
||||
| InfoResult
|
||||
| AuthErrorResult;
|
||||
|
||||
function isInterruptResult(result: unknown): result is InterruptResult {
|
||||
return (
|
||||
typeof result === "object" &&
|
||||
result !== null &&
|
||||
"__interrupt__" in result &&
|
||||
(result as InterruptResult).__interrupt__ === true
|
||||
);
|
||||
}
|
||||
|
||||
function isErrorResult(result: unknown): result is ErrorResult {
|
||||
return (
|
||||
typeof result === "object" &&
|
||||
|
|
@ -117,12 +94,8 @@ function ApprovalCard({
|
|||
onDecision,
|
||||
}: {
|
||||
args: Record<string, unknown>;
|
||||
interruptData: InterruptResult;
|
||||
onDecision: (decision: {
|
||||
type: "approve" | "reject" | "edit";
|
||||
message?: string;
|
||||
edited_action?: { name: string; args: Record<string, unknown> };
|
||||
}) => void;
|
||||
interruptData: InterruptResult<NotionUpdatePageContext>;
|
||||
onDecision: (decision: HitlDecision) => void;
|
||||
}) {
|
||||
const { phase, setProcessing, setRejected } = useHitlPhase(interruptData);
|
||||
const [isPanelOpen, setIsPanelOpen] = useState(false);
|
||||
|
|
@ -399,19 +372,16 @@ export const UpdateNotionPageToolUI = ({
|
|||
args,
|
||||
result,
|
||||
}: ToolCallMessagePartProps<{ page_title: string; content: string }, UpdateNotionPageResult>) => {
|
||||
const { dispatch } = useHitlDecision();
|
||||
|
||||
if (!result) return null;
|
||||
|
||||
if (isInterruptResult(result)) {
|
||||
return (
|
||||
<ApprovalCard
|
||||
args={args}
|
||||
interruptData={result}
|
||||
onDecision={(decision) => {
|
||||
const event = new CustomEvent("hitl-decision", {
|
||||
detail: { decisions: [decision] },
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
}}
|
||||
interruptData={result as InterruptResult<NotionUpdatePageContext>}
|
||||
onDecision={(decision) => dispatch([decision])}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue