Documentation
¶
Index ¶
- Variables
- func GetHTTPClientFunctions(config *cfg.Config) map[string]function.Function
- func GetHTTPResponseFunctions() map[string]function.Function
- func GetLogFunctions(logger *zap.Logger) map[string]function.Function
- func GetMcpFunctions() map[string]function.Function
- func GetStandardLibraryFunctions() map[string]function.Function
- func MakeFileAppendFunc(baseDir string) function.Function
- func MakeFileBytesFunc(baseDir string) function.Function
- func MakeFileWriteFunc(baseDir string) function.Function
- func MakeGoTemplateFileFunc(baseDir string, constants map[string]cty.Value) function.Function
- func MakeTemplateFileFunc(baseDir string, constants map[string]cty.Value, ...) function.Function
- func NewMCPResultCapsule(r MCPResult) cty.Value
- type MCPResult
Constants ¶
This section is empty.
Variables ¶
var AddHeaderFunc = function.New(&function.Spec{ Description: "Returns a new response with the given header value appended", Params: []function.Parameter{ {Name: "response", Type: cty.DynamicPseudoType}, {Name: "name", Type: cty.String}, {Name: "value", Type: cty.String}, }, Type: function.StaticReturnType(types.HTTPResponseObjectType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { orig, ok := types.GetHTTPResponseFromValue(args[0]) if !ok { return cty.NilVal, fmt.Errorf("addheader: first argument must be an httpresponse value") } r := cloneResponse(orig) r.Headers.Add(textproto.CanonicalMIMEHeaderKey(args[1].AsString()), args[2].AsString()) return types.BuildHTTPResponseObject(r), nil }, })
AddHeaderFunc implements addheader(response, name, value). Returns a new httpresponse with the given header appended (multi-value safe).
var BasicAuthFunc = function.New(&function.Spec{ Description: "Returns the value for an HTTP Basic Authorization header for the given username and password", Params: []function.Parameter{ {Name: "user", Type: cty.String, Description: "Username"}, {Name: "password", Type: cty.String, Description: "Password"}, }, Type: function.StaticReturnType(cty.String), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { user := args[0].AsString() password := args[1].AsString() encoded := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", user, password))) return cty.StringVal("Basic " + encoded), nil }, })
BasicAuthFunc returns the value for an HTTP Authorization header using Basic auth
var CondFunc = function.New(&function.Spec{ Description: "Lazy conditional: cond(c1, r1, c2, r2, ..., else). Evaluates conditions in order; only the selected result expression is evaluated.", VarParam: &function.Parameter{ Name: "exprs", Type: customdecode.ExpressionClosureType, }, Type: func(args []cty.Value) (cty.Type, error) { if len(args) < 3 || len(args)%2 == 0 { return cty.NilType, fmt.Errorf("cond requires an odd number of arguments >= 3 (got %d)", len(args)) } return cty.DynamicPseudoType, nil }, Impl: func(args []cty.Value, _ cty.Type) (cty.Value, error) { for i := 0; i+1 < len(args); i += 2 { cv, diags := customdecode.ExpressionClosureFromVal(args[i]).Value() if diags.HasErrors() { return cty.NilVal, diagsToError(fmt.Sprintf("cond: condition #%d", i/2+1), diags) } bv, err := convert.Convert(cv, cty.Bool) if err != nil { return cty.NilVal, fmt.Errorf("cond: condition #%d: %w", i/2+1, err) } if bv.IsNull() { return cty.NilVal, fmt.Errorf("cond: condition #%d is null", i/2+1) } if bv.True() { return evalClosure(args[i+1], fmt.Sprintf("cond: result #%d", i/2+1)) } } return evalClosure(args[len(args)-1], "cond: else") }, })
CondFunc is a lazy, multi-branch conditional.
Usage: cond(c1, r1, c2, r2, ..., else). Conditions are evaluated in order; only the result expression paired with the first truthy condition is evaluated. If no condition is truthy, the trailing "else" expression is evaluated. Unevaluated expressions produce no side effects.
var DiffFunc = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "a", Type: cty.DynamicPseudoType}, {Name: "b", Type: cty.DynamicPseudoType}, }, Type: function.StaticReturnType(cty.DynamicPseudoType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { a, err := go2cty2go.CtyToAny(args[0]) if err != nil { return cty.UnknownVal(cty.NilType), fmt.Errorf("unable to convert first argument: %s", err) } b, err := go2cty2go.CtyToAny(args[1]) if err != nil { return cty.UnknownVal(cty.NilType), fmt.Errorf("unable to convert second argument: %s", err) } diff, err := structdiff.Diff(a, b) if err != nil { return cty.UnknownVal(cty.NilType), fmt.Errorf("unable to diff values: %s", err) } return go2cty2go.AnyToCty(diff) }, })
var ErrorFunc = function.New(&function.Spec{ Description: "Returns an error with the given message", Params: []function.Parameter{ {Name: "message", Type: cty.String}, }, Type: function.StaticReturnType(cty.String), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { return args[0], errors.New(args[0].AsString()) }, })
var HTTPErrorFunc = function.New(&function.Spec{ Description: "Builds an HTTP error response with the given status code and message body", Params: []function.Parameter{ {Name: "status", Type: cty.Number}, {Name: "message", Type: cty.String}, }, Type: function.StaticReturnType(types.HTTPResponseObjectType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { status, _ := args[0].AsBigFloat().Int64() r := &types.HTTPResponseWrapper{ Status: int(status), Headers: make(http.Header), Body: []byte(args[1].AsString()), ContentType: "text/plain; charset=utf-8", IsError: true, } return types.BuildHTTPResponseObject(r), nil }, })
HTTPErrorFunc implements http_error(status, message). Returns an httpresponse value marked as an error with the given status and plain-text body.
var HTTPMustFunc = function.New(&function.Spec{ Description: "Returns response unchanged if its status matches expected (default any 2xx); otherwise raises an HCL error", Params: []function.Parameter{ {Name: "response", Type: cty.DynamicPseudoType, AllowDynamicType: true}, }, VarParam: &function.Parameter{Name: "expected", Type: cty.DynamicPseudoType, AllowNull: true, AllowDynamicType: true}, Type: function.StaticReturnType(types.HTTPClientResponseObjectType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { respVal := args[0] wrapper, ok := types.GetHTTPClientResponseFromValue(respVal) if !ok { return cty.NilVal, fmt.Errorf("http_must: first argument must be an httpclientresponse value") } check := func(status int) bool { return status >= 200 && status < 300 } var expectedDesc string if len(args) > 1 && !args[1].IsNull() { c, desc, err := parseHTTPMustExpected(args[1]) if err != nil { return cty.NilVal, fmt.Errorf("http_must: %w", err) } check = c expectedDesc = desc } else { expectedDesc = "any 2xx" } if check(wrapper.R.StatusCode) { return respVal, nil } method := "<unknown>" urlStr := "<unknown>" if wrapper.R.Request != nil { if wrapper.R.Request.Method != "" { method = wrapper.R.Request.Method } if wrapper.R.Request.URL != nil { urlStr = wrapper.R.Request.URL.String() } } bodyExcerpt := buildHTTPMustBodyExcerpt(wrapper) return cty.NilVal, fmt.Errorf( "http_must: %s %s returned %d %s\n expected: %s\n body: %s", method, urlStr, wrapper.R.StatusCode, nethttp.StatusText(wrapper.R.StatusCode), expectedDesc, bodyExcerpt, ) }, })
HTTPMustFunc implements http_must(response[, expected]) → response.
Returns the response unchanged when its status is acceptable; otherwise raises an HCL error containing the method, final URL, actual status, expected set, and a body excerpt.
expected may be:
- omitted (or null) — any 2xx is acceptable
- a single number — exact match
- a list of numbers — any one matches
- a list of [lo, hi] tuples — inclusive ranges
- a mix of numbers and [lo, hi] tuples in the same list
var HTTPRedirectFunc = function.New(&function.Spec{ Description: "Builds an HTTP redirect response; http_redirect(url) defaults to 302, http_redirect(status, url) uses the given status", Params: []function.Parameter{ {Name: "first", Type: cty.DynamicPseudoType}, }, VarParam: &function.Parameter{Name: "rest", Type: cty.DynamicPseudoType}, Type: function.StaticReturnType(types.HTTPResponseObjectType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { var status int var url string switch { case args[0].Type() == cty.String: if len(args) != 1 { return cty.NilVal, fmt.Errorf("http_redirect: url-only form takes exactly 1 argument") } status = http.StatusFound url = args[0].AsString() case args[0].Type() == cty.Number: if len(args) != 2 { return cty.NilVal, fmt.Errorf("http_redirect: status+url form takes exactly 2 arguments") } if args[1].Type() != cty.String { return cty.NilVal, fmt.Errorf("http_redirect: second argument must be a string URL, got %s", args[1].Type().FriendlyName()) } s, _ := args[0].AsBigFloat().Int64() status = int(s) url = args[1].AsString() default: return cty.NilVal, fmt.Errorf("http_redirect: first argument must be a URL string or status number, got %s", args[0].Type().FriendlyName()) } r := &types.HTTPResponseWrapper{ Status: status, Headers: http.Header{"Location": {url}}, } return types.BuildHTTPResponseObject(r), nil }, })
HTTPRedirectFunc implements http_redirect(url) and http_redirect(status, url). When the first argument is a string it is treated as the URL with a default 302 status. When the first argument is a number it is treated as the status code and the second argument must be the URL string.
var HTTPResponseFunc = function.New(&function.Spec{ Description: "Builds an HTTP response value with the given status code, optional body, and optional headers", Params: []function.Parameter{ {Name: "status", Type: cty.Number}, }, VarParam: &function.Parameter{Name: "args", Type: cty.DynamicPseudoType}, Type: function.StaticReturnType(types.HTTPResponseObjectType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { status, _ := args[0].AsBigFloat().Int64() r := &types.HTTPResponseWrapper{ Status: int(status), Headers: make(http.Header), } if len(args) > 1 { body, ct, err := types.CoerceBodyToBytes(args[1]) if err != nil { return cty.NilVal, fmt.Errorf("http_response: invalid body: %w", err) } r.Body = body r.ContentType = ct } if len(args) > 2 { if err := applyHeadersArg(r.Headers, args[2]); err != nil { return cty.NilVal, fmt.Errorf("http_response: invalid headers: %w", err) } } return types.BuildHTTPResponseObject(r), nil }, })
HTTPResponseFunc implements http_response(status[, body[, headers]]).
var KillFunc = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "pid", Type: cty.Number}, {Name: "signal", Type: cty.Number}, }, Type: function.StaticReturnType(cty.Bool), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { pid, accuracy := args[0].AsBigFloat().Int64() if accuracy != 0 { return cty.False, fmt.Errorf("pid must be an integer") } sig, accuracy := args[1].AsBigFloat().Int64() if accuracy != 0 { return cty.False, fmt.Errorf("signal must be an integer") } if err := syscall.Kill(int(pid), syscall.Signal(sig)); err != nil { return cty.False, fmt.Errorf("kill(%d, %d): %w", pid, sig, err) } return cty.True, nil }, })
KillFunc sends a signal to a process. Both pid and signal are integers. Returns true on success, or an error if the syscall fails.
var LLMWrapFunc = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "content", Type: cty.String}, }, Type: function.StaticReturnType(cty.String), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { content := args[0].AsString() return cty.StringVal("<user_input>\n" + content + "\n</user_input>"), nil }, })
LLMWrapFunc wraps user-controlled content in <user_input> XML-like delimiters as a prompt injection mitigation. The system prompt should reference these tags to tell the model where untrusted input begins and ends.
Input: "hello" Output: "<user_input>\nhello\n</user_input>"
var MCPAssistantMessageFunc = function.New(&function.Spec{ Description: "Returns an assistant-role message for an MCP prompt result (few-shot example)", Params: []function.Parameter{ {Name: "content", Type: cty.String, Description: "Message content"}, }, Type: function.StaticReturnType(MCPResultCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { return NewMCPResultCapsule(MCPResult{ Kind: "assistant_message", Text: args[0].AsString(), }), nil }, })
MCPAssistantMessageFunc returns an mcp_assistantmessage function for prompt results.
var MCPErrorFunc = function.New(&function.Spec{ Description: "Returns an error result for an MCP tool call", Params: []function.Parameter{ {Name: "message", Type: cty.String, Description: "Error message"}, }, Type: function.StaticReturnType(MCPResultCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { return NewMCPResultCapsule(MCPResult{ Kind: "error", Text: args[0].AsString(), }), nil }, })
MCPErrorFunc returns an mcp_error function that signals a tool error result.
var MCPImageFunc = function.New(&function.Spec{ Description: "Returns image content for an MCP resource or tool result", Params: []function.Parameter{ {Name: "data", Type: cty.DynamicPseudoType, Description: "Base64-encoded image string or bytes capsule"}, }, VarParam: &function.Parameter{ Name: "mime_type", Type: cty.String, Description: "MIME type of the image (required when data is a base64 string; optional when data is a bytes capsule)", }, Type: function.StaticReturnType(MCPResultCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { var imageData []byte var mimeType string switch { case args[0].Type() == cty.String: var err error imageData, err = base64.StdEncoding.DecodeString(args[0].AsString()) if err != nil { return cty.NilVal, fmt.Errorf("mcp_image: invalid base64 data: %w", err) } if len(args) < 2 { return cty.NilVal, fmt.Errorf("mcp_image: mime_type is required when data is a base64 string") } mimeType = args[1].AsString() default: b, err := bytescty.GetBytesFromValue(args[0]) if err != nil { return cty.NilVal, fmt.Errorf("mcp_image: data must be a base64 string or bytes value, got %s", args[0].Type().FriendlyName()) } imageData = b.Data mimeType = b.ContentType if len(args) > 1 { mimeType = args[1].AsString() } } return NewMCPResultCapsule(MCPResult{ Kind: "image", Data: imageData, MIMEType: mimeType, }), nil }, })
MCPImageFunc returns an mcp_image function that produces image content.
Accepted call forms:
mcp_image(base64_string, mime_type) - original form, both args required mcp_image(bytes_capsule) - mime_type taken from bytes content type mcp_image(bytes_capsule, mime_type) - mime_type overrides bytes content type
var MCPResultCapsuleType = cty.CapsuleWithOps("mcp_result", reflect.TypeOf(MCPResult{}), &cty.CapsuleOps{ GoString: func(val interface{}) string { r := val.(*MCPResult) return fmt.Sprintf("mcp_result(%s)", r.Kind) }, TypeGoString: func(_ reflect.Type) string { return "mcp_result" }, })
MCPResultCapsuleType is the cty capsule type for MCPResult values.
var MCPUserMessageFunc = function.New(&function.Spec{ Description: "Returns a user-role message for an MCP prompt result", Params: []function.Parameter{ {Name: "content", Type: cty.String, Description: "Message content"}, }, Type: function.StaticReturnType(MCPResultCapsuleType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { return NewMCPResultCapsule(MCPResult{ Kind: "user_message", Text: args[0].AsString(), }), nil }, })
MCPUserMessageFunc returns an mcp_usermessage function for prompt results.
var PatchFunc = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "target", Type: cty.DynamicPseudoType}, {Name: "patch", Type: cty.DynamicPseudoType}, }, Type: function.StaticReturnType(cty.DynamicPseudoType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { target, err := go2cty2go.CtyToAny(args[0]) if err != nil { return cty.UnknownVal(cty.NilType), fmt.Errorf("unable to convert target argument: %s", err) } patch, err := go2cty2go.CtyToAny(args[1]) if err != nil { return cty.UnknownVal(cty.NilType), fmt.Errorf("unable to convert patch argument: %s", err) } patchMap, ok := patch.(map[string]any) if !ok { return cty.UnknownVal(cty.NilType), fmt.Errorf("patch must be a map") } targetMap, ok := target.(map[string]any) if !ok { return cty.UnknownVal(cty.NilType), fmt.Errorf("target must be a map") } err = structdiff.Apply(&targetMap, patchMap) if err != nil { return cty.UnknownVal(cty.NilType), fmt.Errorf("unable to apply patch: %s", err) } return go2cty2go.AnyToCty(targetMap) }, })
var RemoveHeaderFunc = function.New(&function.Spec{ Description: "Returns a new response with all values for the given header removed", Params: []function.Parameter{ {Name: "response", Type: cty.DynamicPseudoType}, {Name: "name", Type: cty.String}, }, Type: function.StaticReturnType(types.HTTPResponseObjectType), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { orig, ok := types.GetHTTPResponseFromValue(args[0]) if !ok { return cty.NilVal, fmt.Errorf("removeheader: first argument must be an httpresponse value") } r := cloneResponse(orig) r.Headers.Del(args[1].AsString()) return types.BuildHTTPResponseObject(r), nil }, })
RemoveHeaderFunc implements removeheader(response, name). Returns a new httpresponse with all values for the given header removed.
var SQLMustFunc = function.New(&function.Spec{ Params: []function.Parameter{ { Name: "result", Type: cty.DynamicPseudoType, AllowNull: true, AllowDynamicType: true, }, }, Type: func(args []cty.Value) (cty.Type, error) { return args[0].Type(), nil }, Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { result := args[0] if !result.IsKnown() { return cty.UnknownVal(retType), nil } if result.IsNull() || !result.Type().IsObjectType() || !result.Type().HasAttribute("error") { return cty.NilVal, fmt.Errorf("sql_must: argument is not a result object (no \"error\" field)") } errVal := result.GetAttr("error") if errVal.IsNull() { return result, nil } return cty.NilVal, fmt.Errorf("sql_must: %s", formatSQLError(errVal)) }, })
SQLMustFunc turns the "error rides in the result object" convention used by SQL `call()` into a fail-fast: given a result object, if its `error` field is non-null it raises an evaluation error built from the error fields; otherwise it returns the result unchanged.
# branch on the error... r = call(ctx, client.db, "INSERT ...") # ...or just fail the action if it errored: r = sql_must(call(ctx, client.db, "INSERT ..."))
var SetCookieFunc = function.New(&function.Spec{ Description: "Formats a Set-Cookie header value from a cookie definition object", Params: []function.Parameter{ {Name: "cookie", Type: cty.DynamicPseudoType}, }, Type: function.StaticReturnType(cty.String), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { val := args[0] if !val.Type().IsObjectType() { return cty.NilVal, fmt.Errorf("setcookie: argument must be an object, got %s", val.Type().FriendlyName()) } if !val.Type().HasAttribute("name") || !val.Type().HasAttribute("value") { return cty.NilVal, fmt.Errorf("setcookie: object must have 'name' and 'value' attributes") } c := &http.Cookie{ Name: val.GetAttr("name").AsString(), Value: val.GetAttr("value").AsString(), } if val.Type().HasAttribute("path") { c.Path = val.GetAttr("path").AsString() } if val.Type().HasAttribute("domain") { c.Domain = val.GetAttr("domain").AsString() } if val.Type().HasAttribute("expires") { exp := val.GetAttr("expires") switch { case exp.Type() == timecty.TimeCapsuleType: t, _ := timecty.GetTime(exp) c.Expires = t case exp.Type() == timecty.DurationCapsuleType: d, _ := timecty.GetDuration(exp) c.Expires = time.Now().Add(d) case exp.Type() == cty.String: s := exp.AsString() if s != "" { t, err := time.Parse(time.RFC3339, s) if err != nil { return cty.NilVal, fmt.Errorf("setcookie: invalid expires value %q: %w", s, err) } c.Expires = t } default: return cty.NilVal, fmt.Errorf("setcookie: expires must be a time, duration, or RFC3339 string, got %s", exp.Type().FriendlyName()) } } if val.Type().HasAttribute("max_age") { f, _ := val.GetAttr("max_age").AsBigFloat().Int64() c.MaxAge = int(f) } if val.Type().HasAttribute("secure") { c.Secure = val.GetAttr("secure").True() } if val.Type().HasAttribute("http_only") { c.HttpOnly = val.GetAttr("http_only").True() } if val.Type().HasAttribute("same_site") { switch strings.ToLower(val.GetAttr("same_site").AsString()) { case "strict": c.SameSite = http.SameSiteStrictMode case "lax": c.SameSite = http.SameSiteLaxMode case "none": c.SameSite = http.SameSiteNoneMode default: c.SameSite = http.SameSiteDefaultMode } } if val.Type().HasAttribute("partitioned") { c.Partitioned = val.GetAttr("partitioned").True() } return cty.StringVal(c.String()), nil }, })
SetCookieFunc implements setcookie(cookieObj). Formats a Set-Cookie header value from an object with cookie fields. The name and value fields are required; all others are optional.
var SwitchFunc = function.New(&function.Spec{ Description: "Switch dispatch: switch(on, v1, r1, v2, r2, ..., default?). Evaluates `on` once, then each vN until a match; returns the matching rN, or the optional default. Errors if nothing matches and no default was given. Each branch is evaluated at most once.", VarParam: &function.Parameter{ Name: "exprs", Type: customdecode.ExpressionClosureType, }, Type: func(args []cty.Value) (cty.Type, error) { if len(args) < 3 { return cty.NilType, fmt.Errorf("switch requires at least 3 arguments (got %d)", len(args)) } return cty.DynamicPseudoType, nil }, Impl: func(args []cty.Value, _ cty.Type) (cty.Value, error) { hasDefault := len(args)%2 == 0 caseEnd := len(args) if hasDefault { caseEnd = len(args) - 1 } on, err := evalClosure(args[0], "switch: on") if err != nil { return cty.NilVal, err } for i := 1; i+1 < caseEnd; i += 2 { caseNum := (i + 1) / 2 v, err := evalClosure(args[i], fmt.Sprintf("switch: case #%d value", caseNum)) if err != nil { return cty.NilVal, err } if on.RawEquals(v) { return evalClosure(args[i+1], fmt.Sprintf("switch: case #%d result", caseNum)) } } if hasDefault { return evalClosure(args[len(args)-1], "switch: default") } return cty.NilVal, errors.New("switch: no case matched and no default was given") }, })
SwitchFunc dispatches on a single value against a series of (match, result) pairs, with an optional trailing default.
Usage: switch(on, v1, r1, v2, r2, ..., default?). The trailing default is optional; with it the total argument count is even, without it odd.
`on` is evaluated exactly once. Then for each (vN, rN) pair, vN is evaluated and compared to `on` for equality; on the first match, rN is evaluated and returned. If no vN matches, the default (when present) is evaluated and returned; if no default was given, switch() errors. Case values past the matching arm are not evaluated, nor are unselected results or the default.
Equality uses cty.Value.RawEquals — exact structural equality. Type mismatches (e.g. number 200 vs string "200") count as no match rather than erroring.
var TryFunc = function.New(&function.Spec{ Description: "Try each expression in order; return the first that evaluates without error. Evaluates each expression at most once (unlike stock HCL try()).", VarParam: &function.Parameter{ Name: "exprs", Type: customdecode.ExpressionClosureType, }, Type: func(args []cty.Value) (cty.Type, error) { if len(args) == 0 { return cty.NilType, errors.New("try requires at least one argument") } return cty.DynamicPseudoType, nil }, Impl: func(args []cty.Value, _ cty.Type) (cty.Value, error) { var accum hcl.Diagnostics for _, a := range args { v, diags := customdecode.ExpressionClosureFromVal(a).Value() if diags.HasErrors() { accum = append(accum, diags...) continue } if !v.IsWhollyKnown() { return cty.DynamicVal, nil } return v, nil } return cty.NilVal, diagsToError("no try expression succeeded", accum) }, })
TryFunc evaluates each argument in order and returns the first whose evaluation produces no diagnostics. Unlike upstream tryfunc.TryFunc, this returns cty.DynamicPseudoType from the Type callback so each selected expression is evaluated exactly once (upstream's concrete-type inference evaluates the successful branch twice, which is unsafe for side-effectful expressions).
var TypeOfFunc = function.New(&function.Spec{ Params: []function.Parameter{ {Name: "value", Type: cty.DynamicPseudoType}, }, Type: function.StaticReturnType(cty.String), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { return cty.StringVal(args[0].Type().FriendlyName()), nil }, })
TypeOfFunc returns the friendly name of the type of a given value
Functions ¶
func GetHTTPClientFunctions ¶ added in v0.26.0
GetHTTPClientFunctions returns the eight http_* verb functions, capturing the supplied config so verb functions can evaluate lazy expressions like retry.on_response against the same eval context the rest of vinculum uses. config may be nil in tests that do not exercise hooks.
func GetHTTPResponseFunctions ¶ added in v0.20.0
GetHTTPResponseFunctions returns all HTTP response functions for global registration.
func GetLogFunctions ¶
GetLogFunctions returns HCL functions for logging with zap logger
func GetMcpFunctions ¶ added in v0.10.0
GetMcpFunctions returns all MCP-specific cty functions. These are included in the global function set so they are available in any action expression, including bus subscriptions that construct MCP values for async handlers.
func GetStandardLibraryFunctions ¶
GetStandardLibraryFunctions returns a map of all cty standard library functions suitable for providing to an HCL evaluation context.
func MakeFileAppendFunc ¶ added in v0.15.0
MakeFileAppendFunc constructs a function that appends a string to a file, creating the file if it does not exist. The path must be within baseDir.
func MakeFileBytesFunc ¶ added in v0.19.0
MakeFileBytesFunc returns a filebytes function restricted to baseDir. filebytes(path) or filebytes(path, content_type)
func MakeFileWriteFunc ¶ added in v0.15.0
MakeFileWriteFunc constructs a function that writes a string to a file, creating or overwriting it. The path must be within baseDir.
func MakeGoTemplateFileFunc ¶ added in v0.15.0
MakeGoTemplateFileFunc constructs a gotemplatefile(path, vars) function. It reads a Go text/template file, evaluates it with the given vars merged on top of the standard VCL constants (env, sys, var, metric, etc.), and returns the rendered string. The path is resolved relative to baseDir.
constants is the live Config.Constants map. Unlike templatefile(), no funcsGetter is needed because Go templates use their own FuncMap.
func MakeTemplateFileFunc ¶ added in v0.15.0
func MakeTemplateFileFunc( baseDir string, constants map[string]cty.Value, funcsGetter func() map[string]function.Function, ) function.Function
MakeTemplateFileFunc constructs a templatefile(path, vars) function. It reads an HCL template file, evaluates it with the given vars merged into the standard VCL variable scope (env, sys, var, metric, etc.), and returns the result. The path is resolved relative to baseDir.
constants is the live Config.Constants map (captured by reference so that var/metric/bus/server/client entries added during block processing are visible at evaluation time). funcsGetter returns all available functions excluding templatefile itself, preventing recursion.
func NewMCPResultCapsule ¶ added in v0.10.0
NewMCPResultCapsule wraps an MCPResult in a cty capsule value.
Types ¶
type MCPResult ¶ added in v0.10.0
type MCPResult struct {
// Kind is one of: "image", "error", "user_message", "assistant_message"
Kind string
Text string
Data []byte // decoded bytes for images
MIMEType string
}
MCPResult holds typed return values from MCP action expressions. It is wrapped in a cty capsule so it can pass through HCL evaluation.
func GetMCPResult ¶ added in v0.10.0
GetMCPResult extracts an MCPResult from a cty capsule value. Returns nil if the value is not an MCPResult capsule.