这是indexloc提供的服务,不要输入任何密码
Skip to content
Closed
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
1 change: 0 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/kubechain/cmd/main.go",
"args": [],
"env": {
"KUBECONFIG": "${env:HOME}/.kube/config"
}
Expand Down
15 changes: 14 additions & 1 deletion kubechain/api/v1alpha1/taskruntoolcall_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// ToolType defines the type of a tool in the system
// +kubebuilder:validation:Enum=MCP;HumanContact
type ToolType string

const (
// ToolTypeMCP indicates a tool provided by an MCP server
ToolTypeMCP ToolType = "MCP"
// ToolTypeHumanContact indicates a tool for human interaction
ToolTypeHumanContact ToolType = "HumanContact"
)

type TaskRunToolCallStatusType string

const (
Expand Down Expand Up @@ -78,7 +89,7 @@ type TaskRunToolCallStatus struct {
}

// TaskRunToolCallPhase represents the phase of a TaskRunToolCall
// +kubebuilder:validation:Enum=Pending;Running;Succeeded;Failed;AwaitingHumanInput;AwaitingSubAgent;AwaitingHumanApproval;ReadyToExecuteApprovedTool;ErrorRequestingHumanApproval;ToolCallRejected
// +kubebuilder:validation:Enum=Pending;Running;Succeeded;Failed;AwaitingHumanInput;AwaitingSubAgent;AwaitingHumanApproval;ReadyToExecuteApprovedTool;ErrorRequestingHumanApproval;ToolCallRejected;ErrorRequestingHumanInput
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for myself, think we should just consolidate ErrorRequestingHuman* into ErrorExternalCallRequest or the like

type TaskRunToolCallPhase string

const (
Expand All @@ -102,6 +113,8 @@ const (
TaskRunToolCallPhaseErrorRequestingHumanApproval TaskRunToolCallPhase = "ErrorRequestingHumanApproval"
// TaskRunToolCallPhaseToolCallRejected indicates the tool call was rejected by human approval
TaskRunToolCallPhaseToolCallRejected TaskRunToolCallPhase = "ToolCallRejected"
// TaskRunToolCallPhaseErrorRequestingHumanInput indicates there was an error requesting human input
TaskRunToolCallPhaseErrorRequestingHumanInput TaskRunToolCallPhase = "ErrorRequestingHumanInput"
)

// +kubebuilder:object:root=true
Expand Down
11 changes: 0 additions & 11 deletions kubechain/api/v1alpha1/tool_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,6 @@ import (
"k8s.io/apimachinery/pkg/runtime"
)

// ToolType defines the type of a tool in the system
// +kubebuilder:validation:Enum=MCP;HumanContact
type ToolType string

const (
// ToolTypeMCP indicates a tool provided by an MCP server
ToolTypeMCP ToolType = "MCP"
// ToolTypeHumanContact indicates a tool for human interaction
ToolTypeHumanContact ToolType = "HumanContact"
)

// ToolSpec defines the desired state of Tool
type ToolSpec struct {
// Name is used for inline/function tools (optional if the object name is used).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ spec:
- ReadyToExecuteApprovedTool
- ErrorRequestingHumanApproval
- ToolCallRejected
- ErrorRequestingHumanInput
type: string
ready:
description: Ready indicates if the tool call is ready to be executed
Expand Down
78 changes: 64 additions & 14 deletions kubechain/hack/playground/humanlayer_client_play.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,37 @@ func requestApproval(
return functionCall
}

func requestHumanContact(
client humanlayer.HumanLayerClientWrapper,
channelType kubechainv1alpha1.ContactChannelType,
) *humanlayerapi.HumanContactOutput {
switch channelType {
case kubechainv1alpha1.ContactChannelTypeSlack:
client.SetSlackConfig(&kubechainv1alpha1.SlackChannelConfig{
ChannelOrUserID: "C07HR5JL15F",
ContextAboutChannelOrUser: "Channel for human contact",
})
case kubechainv1alpha1.ContactChannelTypeEmail:
client.SetEmailConfig(&kubechainv1alpha1.EmailChannelConfig{
Address: os.Getenv("HL_EXAMPLE_CONTACT_EMAIL"),
ContextAboutUser: "Contact for human interaction",
})
default:
panic("Unsupported channel type: " + channelType)
}

client.SetCallID("call-" + uuid.New().String())
client.SetRunID("sundeep-is-testing")

humanContact, statusCode, err := client.RequestHumanContact(context.Background())

fmt.Println(humanContact.GetCallId())
fmt.Println(statusCode)
fmt.Println(err)

return humanContact
}

func getFunctionCallStatus(client humanlayer.HumanLayerClientWrapper) *humanlayerapi.FunctionCallOutput {
functionCall, statusCode, err := client.GetFunctionCallStatus(context.Background())

Expand All @@ -63,6 +94,7 @@ func main() {
// Define command line flags
callIDFlag := flag.String("call-id", "", "Existing call ID to check status for")
typeFlag := flag.String("channel", "slack", "Channel type (slack or email)")
humanContactFlag := flag.Bool("human-contact", false, "Use human contact instead of approval")
flag.Parse()

factory, _ := humanlayer.NewHumanLayerClientFactory("")
Expand All @@ -73,29 +105,47 @@ func main() {
var callID string

if *callIDFlag != "" {
fmt.Println("Call ID provided as argument - skipping approval request")
fmt.Println("Call ID provided as argument - skipping request")
callID = *callIDFlag
} else if *humanContactFlag {
hc := requestHumanContact(client, kubechainv1alpha1.ContactChannelType(*typeFlag))
callID = hc.GetCallId()
} else {
fc := requestApproval(client, kubechainv1alpha1.ContactChannelType(*typeFlag))
callID = fc.GetCallId()
}

client.SetCallID(callID)

fcStatus := getFunctionCallStatus(client)
status := fcStatus.GetStatus()
if *humanContactFlag {
hc, _, _ := client.GetHumanContactStatus(context.Background())
status := hc.GetStatus()

approved, ok := status.GetApprovedOk()
response, ok := status.GetResponseOk()

if !ok {
fmt.Println("Not responded yet")
} else {
fmt.Println(*response)
}
} else {

fcStatus := getFunctionCallStatus(client)
status := fcStatus.GetStatus()

approved, ok := status.GetApprovedOk()

// Check if the value was set
switch {
case !ok:
fmt.Println("Not responded yet")
case approved == nil:
fmt.Println("Approval status is nil (Not responded yet)")
case *approved:
fmt.Println("Approved")
default:
fmt.Println("Rejected")
}

// Check if the value was set
switch {
case !ok:
fmt.Println("Not responded yet")
case approved == nil:
fmt.Println("Approval status is nil (Not responded yet)")
case *approved:
fmt.Println("Approved")
default:
fmt.Println("Rejected")
}
}
5 changes: 4 additions & 1 deletion kubechain/internal/controller/task/task_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,10 @@ func (r *TaskReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.
defer childSpan.End()
}

logger.V(3).Info("Sending LLM request")
logger.V(1).Info("Sending LLM request",
"phase", task.Status.Phase,
"status", task.Status.Status)

// Step 8: Send the prompt to the LLM
output, err := llmClient.SendRequest(childCtx, task.Status.ContextWindow, tools)
if err != nil {
Expand Down
Loading
Loading