Repository navigation
feat!: SharedOS sets no limits of its own - #118
Merged
Merged
Conversation
Every turn and harness limit SharedOS chose on a host's behalf is now unset unless the host sets it, and an unset limit is no limit. SharedOS decides whether each action is allowed, denied or escalated; how long a turn runs and how much it does is the host's call. Unset by default, and still settable by a host: the executor's step, tool-call and time limits (the tool-call limit no longer falls back to the step limit); the standard loop's session close timeout; the model client's output ceiling and request timeout; the malformed-call and ignored-frame guards; an MCP harness's idle timeout and per-call tool timeout; the delegation chain length. Removed outright: the ceilings on a request's limits (1,000 steps, 10,000 tool calls, two hours), the 256-grant cap, the 512-tool cap, the 512-character escalation reason cap and its truncation, the image count and size caps on MCP results, the file tools' caps on results, grep context, path segments and commit messages, and the 10 s timeout on a harness version probe. A turn deadline longer than one timer can hold is waited out rather than firing early.
Every string length, list length and count in the contracts is gone: identifiers and path segments, resource paths, capabilities, actions and purposes per grant, tool names and descriptions, error messages, reach lists, namespace catalogues, tool policy lists, message parent ids, the MCP execution token's claims and the file tools' remaining fields. The JSON schemas published for the message and file tools drop their matching maxLength. Shape checks are unchanged. Whatever carries a value (a filesystem, a vendor's tool name rules, an HTTP server) still applies its own limit, and SharedOS no longer adds a stricter one. The OpenAI-compatible client now retries a failed call that is worth retrying ten times, 1.5 s apart, where it retried once.
The record schema still carried the old contract caps: purpose 512, grant ids and snapshots 256, exposed and requested tools 512, decisions and operations 4,096, events 8,192, and an escalation reason of 512. Since the runtime stopped cutting reasons at 512, a longer ask failed EscalationAskedSchema, which assemble reads with safeParse, so the ask vanished from the record and the judge graded the turn as never having asked. The other caps made assembleExecutionRecord throw on turns the kernel now accepts. All are dropped. A test lifts a 100,000-character reason whole; it fails on the old schema.
The threat model, architecture, release readiness, host integration, MCP toolshare, docs README, errors table and the adapters and mcp READMEs still described step, tool-call, time, size and cleanup limits as always present. They now say each applies only when the host sets it.
Node's built-in fetch gives up after 300 s without response headers and after 300 s without body data. A model that thought longer than that failed the call, and every retry failed the same way. With no fetch passed, the model client now calls through undici's own fetch with an agent whose headers and body waits are switched off, so only the host's request timeout or the turn's deadline ends a call. undici is imported on first use and only on Node, so the package's main entry still loads elsewhere. A fetch the host passes is used as given. undici 8, on the Node 22.19 floor. It uses HTTP/2 where the provider offers it, and the same options switch the waits off there.
One timer holds at most 2^31 - 1 ms (about 24.8 days). Asked for more, the platform fires it almost at once, or refuses it. A turn's deadline already waited out a longer delay in steps; three host-set timeouts did not: - the model client's requestTimeoutMs failed every model call, retries included; - an MCP harness launch's idleTimeoutMs closed a session harness's input almost as soon as it opened; - the kernel's auditWriteTimeoutMs treated any audit write after an effect that took more than a millisecond as timed out. The step-wise wait moves from the runtime into core's internal helpers, with an option to leave its timers unreferenced, and all three use it. The model client's timeout still aborts with a TimeoutError and still does not keep the process running on its own; it is now also cleared once the request ends.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
SharedOS decides whether an action from an external harness is allowed, denied or escalated. How long a turn runs and how much it does is the host's call. SharedOS still chose many limits on the host's behalf: step, tool-call and time defaults, ceilings on what a host could set, size caps in the contracts, and harness timeouts. One was invisible until it bit: Node's built-in fetch gives up after 300 s of silence, so a model that thought longer failed every attempt.
What
maxLengthin the published tool schemas. Shape checks are unchanged. The conformance execution record drops the same caps, so a long escalation reason, no longer cut at 512, stays in the record.fetchpassed, calls on Node go through undici 8's own fetch with its header and body waits off, so a model that thinks past 300 s is no longer cut off. undici is imported on first use and only on Node, and uses HTTP/2 where the provider offers it. Afetchthe host passes is used as given.docs/apiis regenerated.78 files: 1,547 lines added, 1,117 removed. Of those, regenerated
docs/apiis 539 added and 579 removed, and tests are 406 added and 90 removed.What a host has to update
The full list is in the CHANGELOG under Unreleased, Changed. The ones most likely to matter:
SharedOSExecutorhas no defaultdefaultMaxSteps(was 16),defaultTimeoutMs(was 120 000) ordefaultMaxToolCalls, and the tool-call limit no longer falls back to the step limit. A host that relied on the defaults sets them.MAX_EXECUTION_TIMEOUT_MS,MAX_EXECUTION_TOOL_CALLS,MAX_RESOLVED_GRANTS,ESCALATION_REASON_MAX_LENGTHandDEFAULT_MAX_DELEGATION_CHAIN_LENGTHare removed, and thegrant_limit_exceededcode with them.OpenAiCompatibleModelClientsends nomax_completion_tokensunlessmaxOutputTokensis set, and has no request timeout unlessrequestTimeoutMsis set.@aicoo/sharedos-adaptersdepends onundici8.Related
Builds on #116 (Node 22.19, which undici 8 needs) and #117, both merged. Follow-ups, not in this PR:
--disallowedTools,--no-builtin-tools).Checks
pnpm checkis green in a plain clone on Node 22.19 and on Node 24: format, typecheck, vitest 1170/1170, test:release 7/7,docs:api:checkandconformance:check.pnpm pack:checkandpnpm pack:lintpass.