Repository navigation
[release] v0.128.2 - #7976
Merged
Merged
[release] v0.128.2#7976
Conversation
AuthService is imported locally inside create_accounts(), so it is not an attribute of oss.src.services.commoners. Patch the defining module instead: oss.src.core.auth.service.AuthService.
LoopsConfig.enabled is a read-only property with no setter. Instantiating a real LoopsConfig() and setting .enabled crashed with: AttributeError: property 'enabled' of 'LoopsConfig' object has no setter Replaced real instantiation with MagicMock() in all 3 tests: - test_add_contact_success - test_add_contact_retries_on_429_then_succeeds - test_add_contact_exhausts_retries
…reams client The Redis client used for the durable streams had no socket timeout and no health check. The streams worker (entrypoints/worker_streams.py) passed socket_timeout=None explicitly, which means "wait forever". After a managed Redis failover, an open connection can stop answering without ever closing, and any call on it (XREADGROUP, XACK, heartbeat) then waits indefinitely, so the worker stalls with no error and never reaches its retry path. Add streams_client_options() in oss/src/dbs/redis/shared/engine.py: socket_timeout=15s, health_check_interval=30s, socket_keepalive=True. The read timeout is longer than the XREADGROUP block (max_block_ms=5000 in StreamConsumer), so a normal idle blocking read does not time out. Use it for both StreamsEngine.get_redis() and the worker's own client. A timed-out call now raises redis.exceptions.TimeoutError. StreamConsumer already catches Exception in read_batch() and run() and retries after a 1s sleep, so the consumer reconnects and continues without further changes. Tests (api/oss/tests/pytest/unit/test_redis_streams_client_options.py): - the option values, and that both clients are built from them - a client against a server that accepts and never answers raises RedisTimeoutError within 2s. With the options removed this test and two others fail. redis-py 8.0.1 (pinned in uv.lock) falls back to a 5s default when socket_timeout is omitted, and hangs forever with socket_timeout=None, which is what the worker was passing. Not covered: no test against a real Redis failover, and none that drives StreamConsumer through a timeout end to end; the retry behaviour is from reading read_batch()/run(), not from a new test. Fixes #7535
…annel limits M7: person or project accounts (caller_account, project_default), personal MCP servers, custom secrets wait for hidden secrets, durable-work edit rule. M6a: installation turns keep today's role. M6 and M9 prerequisites match CONTRACT section 14. CONTRACT: channel rules, gateway always on, no save-time checks. New changes agent-needs-setup and channel-limits (M10).
…pace_id and meters.workspace_id (M4b step 2b) No deployed code reads or writes the workspace storage any more, so step 3 can drop it while these pods serve. A legacy workspace id is now an unknown id: the Bearer workspace parameter, accept links and the admin graph take the organization id only. The runtime ORM no longer maps the dropped objects; the legacy core-chain data migrations use their frozen models instead. oss000000055 and ee0000000008 rerun the step-2 repair, one-default consolidation and meter fold for rows that step-1 pods wrote during the step-2 rollout.
…ls test (Codex r1)
…no longer maps workspaces)
…s 404, not 500 (live QA)
…ks with an old id still open
A channel turn uses the linked user's own account and refuses an unlinked user at run time, with no check when a channel binding is saved. Personal MCP servers use the reference scope user. The durable-work edit rule covers API-key work. M7 no longer waits for M6: until M6a, an API-key run has no person.
The owner rule is no checks at save time. A revision with the specific binding or an unsupported binding saves, and its run is refused at run start.
…s (M7) A schedule, a trigger subscription or an evaluation run executes as its stored principal. Edits that change what it executes (target, inputs, event, connection, evaluation configuration) are now refused unless the request comes from that principal. Others with the edit capability can still rename, pause, stop or delete the work. The refusal (403 owner_only) names the person the work runs as, and /m shows that sentence when an automation save is refused.
Codex review: dropping nulls and comparing with Python equality let a null input or a true-to-1 change pass as no change, and the check ran before the DAO locked the row. The comparison now uses canonical JSON, and the trigger DAOs run the check on the row they lock for the write.
Codex round 2: the evaluation edit compared against an unlocked read. The DAO now locks the run for a user edit and runs the check on that row.
Review loop round 1: the simple evaluation edit rebuilt the run configuration from targets read before a stop and a wait, then wrote it without a locked check, so a rename could undo a concurrent change by the executing principal. The final write now refuses when the locked run changed since the read, unless the editor is the executing principal. The early duplicate checks before the locked ones are removed for schedules and evaluation runs.
Review loop round 2: the rename rebuilt the configuration from targets read before a second read, so a change between the two reads could still be undone, and the rebuild dropped concurrency and inferred schemas. An edit that does not change the targets now writes the configuration as stored, and edit_run checks it against the locked row with the editor, which refuses it when the executing principal changed the run in between.
…ser batches - An edit that sends no configuration leaves it as it is, so it is a lifecycle edit. - Simple evaluation targets compare by their ids, so a list and the stored map of the same ids are equal. - A user's batch edit writes run by run, each checked on its locked row.
Every agent connection reference can name its binding: caller_account (each person's own account) or project_default (the project's shared account, the default). The server derives the caller_account bindings from the resolved revision in _prepare_invoke, signs them into the run credential as gateway_bindings, and copies them at every re-mint. A lookup without a signed binding stays the project's shared account; a caller_account connection whose run carries none is refused, never answered with the shared account. People can store their own provider key per organization (secrets.user_id, scope=user on the vault create, list and delete routes). The LLM gateway gets a user namespace that answers the run's person's own key only for a bound model connection. A human run uses that human; a channel turn uses the linked person; an API key run and an unlinked channel user are refused. Gated by AGENTA_ACCESS_PERSONAL_CREDENTIALS_ENABLED (default off) and, in EE, the organization flag allow_personal_credentials (default on). Unsupported bindings (specific, a personal account on an organization connection, a personal subscription login for now) are refused as a format error at commit and again at run start.
… yet Codex review: Composio and MCP caller_account bindings were signed but the run path still resolved the project's connection, and the SDK's vault fallback could answer the project's key for a personal model connection. Both now refuse. The organization slug index is rebuilt under a temporary name so organization slugs stay unique during the migration.
…e binding parse Review loop round 1 (simplify and slop): - Personal MCP is deferred, so the SDK keeps MCPGatewayConnection as before and the server refuses any personal MCP reference without building a claim for it. - No module flags: a personal Composio binding is refused here and served in the personal connections change. - PersonalCredentialRefused is the one refusal type on the LLM plane too. - _prepare_invoke parses the bindings once. - Comment and route placement fixes.
…gned-binding refusal Review loop round 2: a directly invoked SDK agent could name a project subscription slug with caller_account and get the shared login. The Connection model now refuses caller_account with mode self_managed. The unsigned-binding refusal is built in one place, and the binding parser is named for what it returns.
- The personal-credentials policy stops new personal keys, not a person listing or removing the ones they stored. - A person's own key is always write-only. - A workflow-tool child whose binding is refused answers that refusal, not a generic failure. - The SDK refuses a personal model connection that the gateway answered outside the user namespace (an API that predates bindings).
The owner rule is no checks at save time. A revision with an unsupported binding now saves; the run that uses it is refused with binding_not_supported.
[fix] Show a file card for zips and other files the answer links to
[fix] Steer a message sent over any parked dock
The new test renders the question with a saved Other answer, clears the text box, and checks that the box stays open and a letter key does not pick another choice. Both checks fail on the code before the fix.
…ns too Move the activity heartbeat into withDaytonaActivityHeartbeat and wrap every runTurn entry point with it: the keep-alive dispatch, its runCold path, and runSandboxAgent. Before, only the keep-alive dispatch had it.
fix: make Loops contact creation non-blocking
[fix] Drain queued messages after a turn the watchdog closes
…t_keepalive A unix:// Redis URL rejects socket_keepalive, and redis-py already enables keepalive for TCP. A failed accumulation read in read_batch dropped the entries the first read had returned, and they stayed pending.
fix: map EmbedError subclasses to 400 instead of 500
…t-gate [fix] Create template agents without asking to connect apps first
[fix] Refuse skill embeds whose slug and id name different workflows
…stop fix(runner): keep Daytona sandboxes active during turns
…piry fix(runner): disable GeeseFS multipart expiry for agent drive mounts
fix(frontend): keep Other write-in box visible after clearing text on reload
…timeout fix(api): add socket timeout and health check to the durable Redis streams client
fix(runner): bump zod to 4.6.6 (Dependabot alert #1866)
Contributor
Author
Railway Preview Environment
PR closed or converted to draft. Environment absence verified; retained storage requires separate provider accounting. Post |
feat(api): stop reading workspaces (M4b step 2b)
docs(sharing): specs for the 2026-10-26 decisions, needs setup and channel limits
Keeps the release branch's tasks.md: task 2.1 now covers more than the SecretMode removal, so this PR no longer ticks it.
…tellm-otel fix(api): bump certifi and litellm in api/uv.lock (Dependabot alerts)
refactor(api): remove SecretMode from the secrets resolver
origin is the public repository. With the shared config from #7873, every git push from a checkout also pushed refs/entire/checkpoints/* with the full agent transcript, which carries internal details. Keep checkpoints local until they have a private remote. Entire-Checkpoint: 01M6EKKZJJY7E7D5VT3PAF3HW6
…n-push chore: stop Entire from pushing session transcripts to origin
mmabrouk
approved these changes
Nov 2, 2026
mmabrouk
left a comment
Member
There was a problem hiding this comment.
🤖 The AI agent says: Approved on Mahmoud's instruction after the v0.128.2 production deploy went green in US (run 41500497682) and EU (run 41502633804), with the live check passing every turn in both regions.
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.
New version v0.128.2 in
Final QA
SANDBOX_AGENT_ACP_HEADERS_TIMEOUT_MS=60000on a runner and start a Claude turn that runs longer than one minute. Pass: the turn fails with an error, the transcript has one copy of the prompt, and the runner log has noACP write retryline for it. Also confirm a normal long turn (over 60 minutes) keeps its final message.?view=mobilestays on /m and drops the param. Also click between session tabs. Pass: the tab and URL change at once.SKILL.mdwith name and description. On a multi-file skill (for exampleslack-gif-creator) you get<name>.zipwith one folder holdingSKILL.mdand every file. In a skill drawer and in the playground, the download icon next to+in the Files header gives the same file. Upload the zip in the New skill flow: it parses back into the same skill. The New skill drawer shows no download icon.api/oss/tests/pytest/acceptance/workflows/test_workflow_embeds_errors.pyon the release preview or staging. They did not run on the fork PR. A pass means the circular, max depth and max embeds tests get 400, and the circular tests see "Circular embed detected" in the detail.inconsistent_embed_referenceand nothing is saved; a normal skill embed still commits and runs.AGENTA_RUNNER_DAYTONA_AUTOSTOP_MINUTESlow (for example 2) on the runner, then run one agent turn that works for longer than that, for example a shellsleep 300step. Pass: the turn finishes, the sandbox is still running when it ends, and the runner log has no[daytona] heartbeat failedline. Do it once in a session chat and once as a sessionless run (the cold path). The fix was tested only with mocks.alembic_versionshowsoss000000062andee0000000009; every organization has at most oneis_defaultproject; no project points at a workspace of another organization; nometersrow has aworkspace_id; meter sums equal the pre-deploy dump./m/w/<old workspace id>/p/<project>/agents(pass: the app rewrites it to the organization id) and call the API with?workspace_id=<old workspace id>(pass: 401; with the organization id: 200).mounts/test_attachments_mount_hidden.py,mounts/test_mount_storage_prefix_hidden.py,loadables/test_loadable_strategies.py(edge b2 windowing),sharing/test_private_session_probe.py(rbac-secret).api/uv.lockclose.Deploy steps
projectsandmeters. The owner adds themigration:destructive-approvedlabel to feat(api): stop reading workspaces (M4b step 2b) #7882 (design.md asks for it; the migrations rewrite data and are one-way). Deploy production on or after 2026-11-05, one week after 0.127.0 reached every region, because invitation links sent before 0.127.0 carry an old workspace id and are refused from this release on; check when 0.127.0 reached EU and US. See the PR for details.ee0000000009is interrupted (pod killed): check that no usage report runs, delete the stalemeters:reportlock key in Redis, and rerun. See the PR for details.ALEMBIC_AUTO_MIGRATIONS=false, and before the old version serves traffic run theworkspace_memberscleanup statement from the PR description once. See the PR for details.