1package tools
2
3import (
4 "context"
5
6 "charm.land/fantasy"
7)
8
9type (
10 sessionIDContextKey string
11 messageIDContextKey string
12 supportsImagesKey string
13 modelNameKey string
14)
15
16const (
17 // SessionIDContextKey is the key for the session ID in the context.
18 SessionIDContextKey sessionIDContextKey = "session_id"
19 // MessageIDContextKey is the key for the message ID in the context.
20 MessageIDContextKey messageIDContextKey = "message_id"
21 // SupportsImagesContextKey is the key for the model's image support capability.
22 SupportsImagesContextKey supportsImagesKey = "supports_images"
23 // ModelNameContextKey is the key for the model name in the context.
24 ModelNameContextKey modelNameKey = "model_name"
25)
26
27// getContextValue is a generic helper that retrieves a typed value from context.
28// If the value is not found or has the wrong type, it returns the default value.
29func getContextValue[T any](ctx context.Context, key any, defaultValue T) T {
30 value := ctx.Value(key)
31 if value == nil {
32 return defaultValue
33 }
34 if typedValue, ok := value.(T); ok {
35 return typedValue
36 }
37 return defaultValue
38}
39
40// GetSessionFromContext retrieves the session ID from the context.
41func GetSessionFromContext(ctx context.Context) string {
42 return getContextValue(ctx, SessionIDContextKey, "")
43}
44
45// GetMessageFromContext retrieves the message ID from the context.
46func GetMessageFromContext(ctx context.Context) string {
47 return getContextValue(ctx, MessageIDContextKey, "")
48}
49
50// GetSupportsImagesFromContext retrieves whether the model supports images from the context.
51func GetSupportsImagesFromContext(ctx context.Context) bool {
52 return getContextValue(ctx, SupportsImagesContextKey, false)
53}
54
55// GetModelNameFromContext retrieves the model name from the context.
56func GetModelNameFromContext(ctx context.Context) string {
57 return getContextValue(ctx, ModelNameContextKey, "")
58}
59
60// NewPermissionDeniedResponse returns a tool response indicating the user
61// denied permission, with StopTurn set so the agent loop does not retry.
62func NewPermissionDeniedResponse() fantasy.ToolResponse {
63 resp := fantasy.NewTextErrorResponse("User denied permission")
64 resp.StopTurn = true
65 return resp
66}