Changelog
June 2026
Language — ImportError handling:
- Failed
importandfrom ... import ...statements now raise catchableImportErrorexceptions insidetry/except, while uncaught import failures still terminate evaluation as before ImportError(...)is available as a built-in exception constructor and can be used in typedexcept ImportErrorand tupleexcept (..., ImportError)clauses
Plugin System:
- Plugin class properties are exposed through generated and native proxies, including read-only getters and getter/setter pairs
- Go plugins can emit records to the host logger with
plugin.Logger(ctx); host applications pass the manager-lifetime logger toplugin.NewManager(appLogger, crashHandler) - Plugin manager crash handling can be supplied during construction, with
SetCrashHandler()still available for late wiring - New runnable plugin examples for properties and host logging
Version:
- Scriptling version bumped to
v0.11.0
Plugin System:
- Go plugin system for extending Scriptling with out-of-process plugins written in Go
plugin.NewServerfor building plugin executables that register functions, classes, and constants via RPCplugin.Managerfor loading and managing plugin binaries from directories--plugin-dirCLI flag andSCRIPTLING_PLUGIN_DIRenv var for loading plugins in both CLI and server modes- Auto-generated proxy classes with
__del__that releases plugin-side objects on garbage collection - GC finalizers installed automatically on all class instances with
__del__— both in-process and plugin objects are cleaned up when unreachable - Custom wrapper class source for full control over the host-side proxy
scriptling.plugincontrol library:list(),describe(),call_function(),call_method(),release()- Concurrent plugin server — multiple requests are dispatched in parallel so slow calls from one environment don’t block another
plugin.RegisterScriptFunc/plugin.RegisterScriptClassfor host-side Scriptling code within plugin libraries- Plugin callbacks — plugins can call host-provided functions via
plugin.Callbackinterface during RPC calls, enabling streaming, event handlers, and other bidirectional patterns object.GCReleaseHookfor best-effort cleanup when GC collects plugin-owned objects- Evaluator installs
runtime.SetFinalizeron instances of classes that define__del__, calling the destructor automatically on garbage collection
Class Builder:
object.ClassBuilder.Constructor(fn)for typed receiver classes — constructor returns a Go struct, methods receive it directlyobject.ClassBuilder.Property(name, getter)andPropertyWithSetter(name, getter, setter)for exposing private Go struct fields as readable/writable Scriptling properties
AI Library — Vector Similarity:
- New
ai.cosine_similarity(a, b)for comparing two embedding vectors; returns a score from -1.0 to 1.0
Networking Library — DNS Resolve:
- New
scriptling.net.resolvelibrary withlookup_ip,lookup_srv, andresolve_srv_httpfor DNS resolution
Provisioning Library — File:
- New
scriptling.provision.filelibrary withensure(path, content, mode=0o644)for idempotent file provisioning
MCP Server — tool.return_error() messages lost:
- When a tool called
return_error(), the error message was discarded and replaced with a genericTool execution failed: script execution failed: SystemExit: 1; the actual error message from the script is now correctly returned to the MCP client
MCP Server — Tool script changes not auto-reloading:
- The file watcher only triggered a reload on
.tomlchanges; editing a tool’s.pyscript now also triggers an automatic reload
CLI — Server Logging:
- The HTTP and MCP servers now emit
trace/debug-level diagnostics for incoming requests, dispatched handlers, middleware execution, MCP tool invocations, and WebSocket lifecycle events, controlled by--log-level/SCRIPTLING_LOG_LEVELand--log-format/SCRIPTLING_LOG_FORMAT
Docs — AI Client reference split:
- The AI Client method reference (completion, streaming, embeddings, Responses API, Pipeline, etc.) has been split into its own Client page for easier navigation
Filesystem Libraries — Pathlib copy, rename, iterdir, glob:
- New
pathlib.Path.copy(target)to copy a file or directory tree to a target path, returning a newPathpointing to the target - New
pathlib.Path.rename(target)to rename or move a file or directory, returning a newPathpointing to the target - New
pathlib.Path.iterdir()to list directory contents asPathobjects - New
pathlib.Path.glob(pattern)to match a shell-style wildcard pattern (*,?,**) within a directory and return matchingPathobjects
Language — Constant Folding:
- Constant expressions (arithmetic, string concatenation, comparisons on literals) are now evaluated at compile time, reducing runtime overhead
Language — Keyword-only Parameters:
- Function and lambda signatures now support Python-style keyword-only parameters using a bare
*, such asdef resize(image, *, width, height=100): - Keyword-only parameters are enforced at call time, so values after bare
*must be supplied by name - Keyword-only parameters can also follow
*args, such asdef collect(prefix, *items, sep):
Language — Shorthand operators:
- Shorthand assignment operators (
+=,-=,*=,/=,//=,%=,**=,&=,|=,^=,>>=,<<=) now correctly evaluate the left-hand side expression against objects.
AI Library — Parallel Completions:
- New
client.completion_parallel(model, messages_list, max_parallel=1, **kwargs)— run multiple chat completions concurrently - New
client.ask_parallel(model, messages_list, max_parallel=1, **kwargs)— run multiple ask completions concurrently - The
max_parallelparameter controls the number of concurrent API requests (default: 1, sequential)
AI Library — Automatic Retry & Adaptive Parallel Concurrency:
ai.Client()now acceptsmax_retries(default 3),retry_backoff(default 1.0s),retry_on_rate_limit(default True), andretry_on_server_error(default True) kwargs- 429 (rate limit) and 5xx (server error) responses are automatically retried with exponential backoff
- Completion responses now include a
retrydict when retries occurred:{"attempts": 2, "rate_limit_hit": true, "total_backoff": 1.0} completion_parallel()andask_parallel()now use adaptive concurrency — parallelism is automatically halved when rate limits are detected, reducing API pressure without manual tuning; workers wake immediately when backoff expires
AI Library — Pipeline:
- New
client.Pipeline(model, max_parallel=1, ask=False, **kwargs)— creates a streaming completion pipeline that starts processing requests immediately as they are added, overlapping prompt generation with inference pipe.add(message)— queues a message; inference begins immediately as concurrency slots are availablepipe.complete()— waits for all in-flight requests and returns results ordered by submissionask=Truemode returns plain text strings;ask=False(default) returns full response dictscompletion_parallel()andask_parallel()are now implemented on top of Pipeline internally, giving them the same overlap benefit when items are added faster than they complete
Requests Library — Parallel HTTP Requests:
- New
requests.parallel(requests, max_parallel=4)— execute multiple HTTP requests concurrently and return responses in submission order - Each request is a dict with
method,url, and optionaldata,json,headers,params,auth,timeout - Returns a list of
Responseobjects (or objects with anerrorattribute on failure) - The
max_parallelparameter controls the concurrency limit (default: 4)
Filesystem Libraries — Permission Modes:
- New
os.chmod(path, mode)andpathlib.Path.chmod(mode)for changing file or directory permissions os.mkdir(path, mode=0o777),os.makedirs(path, mode=0o777, exist_ok=False), andpathlib.Path.mkdir(mode=0o777, parents=False, exist_ok=False)now accept Python-style mode arguments for directory creation- New
os.removedirs(name)for pruning empty directory trees - New
pathlib.Path.read_bytes()andpathlib.Path.write_bytes(data)for byte-oriented file helpers os.write_file(path, content, mode=0o644)now accepts an optional mode for newly-created filesfs.write_bytes(path, offset, data, mode=0o644)now accepts an optional mode for newly-created files
AI Library — Removed tool_round and tool_round_parallel:
- Removed
ai.tool_round()— useclient.completion()withai.tool_calls()andai.execute_tool_calls()directly, or use theAgentclass for full tool loops - Removed
ai.tool_round_parallel()— useclient.completion_parallel()withai.execute_tool_calls()directly
May 2026
Go API — Private Value fields:
Integer.Value,Float.Value,Boolean.Value, andString.Valueare now private- Use
object.NewInteger(),object.NewFloat(),object.NewBoolean(),object.NewString()constructors instead of struct literals - Use
.IntValue(),.FloatValue(),.BoolValue(),.StringValue()getters instead of.Value - Small integer caching now prevents accidental mutation of shared singletons
AI Tool Registry - type aliases:
registry.add()now accepts Python-style type aliases:int→integer,float→number,str→string,bool→boolean,dict→object,list→array
MCP Go library:
- New
mcp.Integer()andmcp.IntegerArray()parameter constructors for tools that require whole numbers
str.upper()andstr.lower()now correctly handle strings that mix ASCII letters with non-ASCII Unicode characters (e.g."naïve résumé".upper()now returns"NAÏVE RÉSUMÉ")- AI Tool Registry:
"number"is now emitted as JSON Schemanumber(was silently downgraded tointeger) - AI Tool Registry: unknown type strings now raise an error at
registry.add()time instead of producing invalid schemas silently - MCP tool metadata:
int/integernow emit JSON Schemainteger;float/numberemitnumber(previously both mapped tonumber) - MCP tool metadata:
array:int/array:integernow emit array items of typeinteger;array:float/array:numberemit items of typenumber - MCP tool metadata: unknown type strings in
.tomltool definitions now produce a registration error instead of silently defaulting tostring
AI library:
scriptling.ai.Client(..., headers={...})— Add custom HTTP headers to every AI API request made by that clientclient.completion(..., extra_body={...})andclient.completion_stream(..., extra_body={...})— Merge provider-specific fields into chat completion request bodies, such as Z.ai thinking-mode optionsscriptling.ai.estimate_tokens(request, response=None)— Allow request-only and response-only token estimates by omittingresponseor passingNonefor either side
FloatArray enhancements:
.tolist()method - Convert FloatArray to a plain list (1D returns list of floats, 2D returns list of lists).shape()method - Return shape as a list of integers (method equivalent ofmath.shape())+operator - Concatenate FloatArrays (1D joins elements, 2D stacks rows with matching columns)- List comprehension support - Iterate FloatArray in comprehensions with optional filtering (
[v * 2 for v in a],[row[0] for row in m])
Go API:
GetFloatMatrix(obj)- Typed getter that extracts data, rows, and cols from a 2D FloatArray
Performance improvements
Language:
rf"..."andfr"..."raw f-string prefixes now supported (previously onlyrandfseparately)- Triple-quoted f-strings:
f"""..."""andf'''...'''
FloatArray type:
- New
FloatArraytype for efficient numerical operations, avoiding per-element boxing overhead - 1D and 2D arrays with row-major storage
- Supports indexing, slicing, assignment, iteration, equality,
inoperator,forloops,len(),list()conversion math.array(data)- Create a FloatArray from a list of numbers or list of listsmath.shape(a)- Return the shape of a FloatArray as a list of ints
Math library:
softmax,dot,matmul,transpose,mat_addnow acceptFloatArrayinputs- Functions return
FloatArraywhen givenFloatArrayinput, preserving type
Built-in functions:
sum(),min(),max()acceptFloatArrayenumerate(),zip(),reversed()acceptFloatArraylist()convertsFloatArrayto a list of floatsforloop iterates overFloatArrayelements (1D) or rows (2D)
April 2026
Math library:
tanh(x)- Hyperbolic tangenterf(x)/erfc(x)- Error function and complementary error functiongamma(x)/lgamma(x)- Gamma function and log-gammacbrt(x)- Cube rootnextafter(x, y)- Next floating-point valueremainder(x, y)- IEEE 754-style remainderlog1p(x)/expm1(x)- Accurate log(1+x) and exp(x)-1 for small xcomb(n, k)- Binomial coefficientperm(n[, k])- Permutationsprod(iterable, start=1)- Product of all elementsdist(p, q)- Euclidean distance between two pointssoftmax(x)- Numerically stable softmaxdot(a, b)- Dot product of two vectorsmatmul(a, b)- Matrix multiplicationtranspose(m)- Matrix transposemat_add(a, b)- Element-wise matrix additiontauconstant - 2π (6.283185…)
Random library:
choices(population, weights, k)- Weighted random sampling with replacementbetavariate(alpha, beta)- Beta distributiongammavariate(alpha, beta)- Gamma distributiontriangular(low, high[, mode])- Triangular distributionparetovariate(alpha)- Pareto distributionweibullvariate(alpha, beta)- Weibull distribution
fs extension library:
read_bytes(path, offset, length)- Read bytes from a filewrite_bytes(path, offset, data)- Write bytes to a fileunpack(format, data)/pack(format, values)- Binary struct packing/unpackingbyte_at(data, index)- Get unsigned byte valuelen(data)- Byte length (not Unicode code points)slice(data, start[, end])- Byte-safe slicing
Container library:
volume_create(name, size=...)- optionalsizekwarg (e.g."20G","512M") sets the volume size on Apple Containers; silently ignored for Docker and Podman
HTTP server:
runtime.http.not_found(handler)- Register a custom 404 handler, called when no route matches or a web root file is not found--web-root <dir|zip>CLI flag (SCRIPTLING_WEB_ROOT/server.web_root) - Serve static files from a directory or zip archive; requests fall through to thenot_foundhandler if no file is found
Template library:
scriptling.template.html-html/templaterendering with automatic HTML escapingscriptling.template.text-text/templaterendering with no escaping
Gossip library updates:
scriptling.textrenamed toscriptling.sedto better reflect its in-place editing capabilities
Configuration file:
- Optional
scriptling.tomlconfiguration file with search paths (.,$HOME/,$HOME/.config/scriptling/) -C/--configflag to specify a custom config file path- All flags with a config path column can be set in the file
- Priority order: command-line flag > environment variable > config file > default
Container management:
scriptling.container- Container lifecycle management for Docker, Podman, and Apple Containers
Search:
scriptling.grep- Fast file content search with concurrent worker pool, glob filtering, binary file detection, and path restriction supportscriptling.text- In-place file content replacement with atomic temp-file rename, concurrent worker pool, and path restriction support
Gossip library updates:
- Request/reply messaging, node groups, and leader election
Networking libraries:
scriptling.net.gossip- Gossip protocol cluster membership and messaging with failure detection, metadata propagation, tag-based routing, encryption, and compressionscriptling.net.multicast- UDP multicast group messaging for one-to-many communicationscriptling.net.unicast- UDP and TCP point-to-point messaging with client and server support
Secrets:
scriptling.secret- Provider-agnostic secret access through host-configured aliases--secret-config- CLI support for loading Vault and 1Password provider aliases from TOML
Runtime and tooling:
scriptling.websocketmoved toscriptling.net.websocketto consolidate all networking libraries under thescriptling.netnamespace
Language:
delstatement for removing list indices, slices, dict keys, and object attributes (del items[0],del cache["key"],del obj.attr)
AI library:
ai.tool_calls(response)- Extract and normalize tool calls from a completion response, message dict, or raw listai.execute_tool_calls(registry, tool_calls)- Execute tool calls using aToolRegistryand return result messagesai.collect_stream(stream, **kwargs)- Collect a chat stream into a single aggregated result with optional per-chunk callbacksai.tool_round(client, model, messages, registry)- Perform a single tool-use round: complete, execute tool calls, return resultsai.estimate_tokens(messages, model)- Estimate token count for a message list
Agent framework:
- Agent constructor gains
max_tokensandcompaction_thresholdparameters - Automatic message compaction for long conversations, with configurable threshold
- Improved streaming support with reasoning and content chunk helpers
Console:
- Panel
add_message()now accepts aroleparameter (user,system,thinking,tool,assistant) for richer TUI output
Runtime and tooling:
isinstance()now accepts a tuple or list of types, matching Python semantics (isinstance(x, (int, float)))- Lexer keyword lookup refactored from map-based to switch-based dispatch for improved performance
- Better concurrency handling in
ChatStreamInstancewith caller cancellation support - Improved error handling in variadic function calls
- Parser refactored with cleaner initialization and improved regex handling