Skip to content

Commit 649c68a

Browse files
committed
WIP tool approval flow frontend
1 parent e95a172 commit 649c68a

File tree

3 files changed

+38
-7
lines changed

3 files changed

+38
-7
lines changed

src/components/ToolCall.vue

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts">
2-
import { ArrowDown, ArrowUp, RefreshRight, Check, DocumentCopy } from '@element-plus/icons-vue'
2+
import { ArrowDown, ArrowUp, RefreshRight, Check, DocumentCopy, User } from '@element-plus/icons-vue'
33
import VueJsonPretty from 'vue-json-pretty';
44
import { ElMessage } from 'element-plus';
55
import 'vue-json-pretty/lib/styles.css';
@@ -32,6 +32,11 @@ export default {
3232
expanded: false,
3333
}
3434
},
35+
mounted() {
36+
if (this.status === 'awaiting_approval') {
37+
this.expanded = true;
38+
}
39+
},
3540
methods: {
3641
toggleExpanded() {
3742
this.expanded = !this.expanded;
@@ -64,15 +69,21 @@ export default {
6469

6570

6671
<template>
67-
<div class="tool-message-container" v-bind:class="expanded? 'expanded':''">
72+
<div class="tool-message-container" v-bind:class="(expanded || status === 'awaiting_approval' )? 'expanded':''">
6873

6974
<div class="tool-message-header">
7075
<div class="tool-name">Tool Call: {{ name }}</div>
7176
<div class="right-aligned">
77+
<div v-if="status === 'awaiting_approval'" style="margin-right: 10px;">
78+
<p style="color: #ffb400; font-size: small;">Awaiting Approval</p>
79+
</div>
7280
<div class="status" v-bind:class="status">
7381
<div v-if="status === 'pending'">
7482
<el-icon class="is-loading" color="#20cbeb"><RefreshRight /></el-icon>
7583
</div>
84+
<div v-else-if="status === 'awaiting_approval'">
85+
<el-icon color="#ffb400"><User /></el-icon>
86+
</div>
7687
<div v-else-if="status === 'success'">
7788
<el-icon color="#00ff18"><Check /></el-icon>
7889
</div>
@@ -96,7 +107,14 @@ export default {
96107
<vue-json-pretty :data="args" :expand-depth="2" />
97108
</el-scrollbar>
98109
</div>
99-
<h4>Result:</h4>
110+
<div v-if="status === 'awaiting_approval'" class="tool-approval-container">
111+
<h4>Approve this tool call?</h4>
112+
<el-button type="primary">Approve</el-button>
113+
<el-button type="danger">Deny</el-button>
114+
</div>
115+
<div v-else>
116+
<h4>Result:</h4>
117+
</div>
100118
<div v-if="result" class="tool-result-container">
101119
<div class="copy-to-clipboard">
102120
<el-button size="small" circle @click="copyToClipboard(JSON.stringify(result, null, 2))" :dark="true"><el-icon><DocumentCopy /></el-icon></el-button>

src/models/MessageModel.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ export interface RawOpeyMessage {
4343
* Original LangChain message in serialized form.
4444
*/
4545
original?: Record<string, any>;
46+
47+
/**
48+
* Whether the tool call was successful.
49+
*/
50+
tool_status?: "success" | "error"
4651
}
4752

4853
export interface OpeyMessage {

src/stores/chat.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export const useChat = defineStore('chat', {
9797
},
9898

9999
getToolCallById: (store) => {
100-
return (toolCallId: string): OpeyToolCall | undefined => {
100+
return (toolCallId: string): OpeyToolCall | undefined=> {
101101
const allMessages = store.messages.concat(store.currentAssistantMessage) // Include the current assistant message in the search
102102
for (const message of allMessages) {
103103
if (message.role === 'assistant') {
@@ -266,8 +266,16 @@ export const useChat = defineStore('chat', {
266266
// Process pending tool calls
267267
if (data.type === 'message') {
268268

269-
// 'message' type contains the tool calls from the assistant
270-
if (content.tool_calls && content.tool_calls.length > 0) {
269+
if (content.tool_approval_request) {
270+
if (!content.tool_call_id) {
271+
throw new Error('Tool call ID not found for approval request');
272+
}
273+
const awaitingApproval = this.getToolCallById(content.tool_call_id)
274+
awaitingApproval.status = "awaiting_approval"
275+
276+
277+
278+
} else if (content.tool_calls && content.tool_calls.length > 0) {
271279
console.log("Tool Calls: ", content)
272280
for (const toolCall of content.tool_calls) {
273281

@@ -297,7 +305,7 @@ export const useChat = defineStore('chat', {
297305
}
298306

299307
// Update the tool message with the content
300-
if (content.original?.data && content.original.data.status === 'error') {
308+
if (content.tool_status && content.tool_status === 'error') {
301309
toolMessage.status = "error";
302310
toolMessage.output = content.content;
303311
} else {

0 commit comments

Comments
 (0)