Skip to content

feat: tangent - remote agent for runview and editor - #2728

Open
maxy-shpfy wants to merge 2 commits into
09-16-refactor_tangent_-_structured_workarea_targetfrom
09-16-feat_tangent_-_remote_agent_for_runview_and_editor
Open

maxy-shpfy wants to merge 2 commits into
09-16-refactor_tangent_-_structured_workarea_targetfrom
09-16-feat_tangent_-_remote_agent_for_runview_and_editor

Conversation

@maxy-shpfy

@maxy-shpfy maxy-shpfy commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

Description

Introduces the remote sub-agent runtime for Tangent, enabling Prime to spawn editor and run-inspector agents directly into embedded pipeline and run-view tabs. Each spawned agent runs in a dedicated Web Worker (remoteEnvWorker.ts) backed by createRemoteEnvWorkerApi, which hosts multiple isolated MemorySession instances and serializes turns per agent. The agent worker is wired to the tab's live ToolBridgeApi via Comlink, so CSOM mutations are undoable canvas edits visible in real time.

Key additions:

  • remoteEditorAgent — a flat (non-routing) agent that receives a resolved CSOM tool allowlist and system prompt from Prime, selects the permitted tools from a mode-aware registry (full mutating surface for editor, read-only inspect surface for runView), and appends a tool-availability section and optional task-specific instructions to its base prompt.
  • createRemoteEnvWorkerApi — the worker-side API: init, setAiConfig, setContext, spawnAgent, runTurn, abortAgent, killAgent. Turns are serialized per agent; overlapping turns for the same agent are rejected. Respawn correctly isolates old abort controllers from new ones.
  • remoteEnvHost — upgraded from a pure tool-catalog host to a full spawn/message/kill orchestrator. Turns are chained per agentId, kill/disconnect abort in-flight turns without surfacing them as errors, and lifecycle events (start, activity, end, error) are streamed back to Prime via agentEvent.
  • connectRemoteEnvWithRefresh — extracted token-refresh loop with exponential back-off on failure, onConnected callback fired only after the socket resolves, and a stop function for clean teardown.
  • TangentRemoteEnvProvider — shared transport component for any spawnable tab: boots the worker, connects with token refresh, pushes AI config and context changes into the worker without rebuilding the connection.
  • TangentEditorAgentProvider / TangentRunAgentProvider — thin wrappers that build the appropriate ToolBridgeApi (editor with live CSOM mutations, run view with read-only fetches) and hand it to TangentRemoteEnvProvider.
  • EmbeddedPipelineEditor and EmbeddedRunView — extended with sessionId, environmentId, and environment/bridge lifecycle callbacks so the workarea shell can wire each tab into the project-level environment registry.
  • TangentProjectContext — adds per-tab environment and bridge registries (registerTabEnvironment, waitForTabEnvironment, registerTabBridge, getActiveTabBridge) backed by refs so the routing bridge and workarea tools can read live state outside React's render cycle.
  • createActiveTabRoutingBridge — a ToolBridgeApi that forwards every call to whichever pipeline tab is currently active, giving the project-level editor agent a stable target as the user switches tabs.
  • createWorkareaRemoteTools — extended with run-inspect tools (get_run_status, debug_pipeline_run, get_execution_details, get_execution_state, get_container_state, get_container_log) backed by a project-level backend bridge, and open_workarea_target now waits for the tab's environment to connect before returning so Prime receives the environmentId it needs to spawn into that tab.
  • useLazyBridgeAuth — extracted hook providing stable lazy getters for backend URL and auth token, used by both the editor and run-view bridge builders.
  • System prompts for the remote editor (remoteEditor.md) and run inspector (remoteRun.md) agents.
  • The tangent-shell feature flag now also enables the AI settings sidebar item.
  • validatePipeline is now individually exported from createCsomTools alongside allTools.

Screenshots (if applicable)

Test Instructions

  1. Open a Tangent session with the tangent-shell flag enabled.
  2. Open a pipeline tab in the Dynamic Workarea and confirm the tab's environment id appears in list_workarea_tabs / open_workarea_target responses.
  3. Have Prime spawn an editor sub-agent into the pipeline tab's environment; verify CSOM mutations appear on the canvas and are undoable.
  4. Open a run tab and confirm Prime can spawn a run-inspector agent that can call debug_pipeline_run and the fine-grained execution tools without being able to mutate the spec.
  5. Switch active pipeline tabs and confirm the project-level routing bridge re-targets the newly active tab.
  6. Revoke and refresh the AI provider config mid-session and confirm the next turn uses the updated settings without reconnecting.
  7. Kill an in-flight agent turn and confirm no error toast is shown and the agent lifecycle is correctly cleaned up.

Additional Comments

@tangent/remote-subagent has been removed from the knip ignore list as it is now a direct runtime dependency of remoteEnvHost. The remoteEnvWorker.ts entry point has been added to knip so dead-code analysis covers the worker build.

@github-actions

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown

🎩 Preview

A preview build has been created at: 09-16-feat_tangent_-_remote_agent_for_runview_and_editor/ae3a256

maxy-shpfy commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

);
client = nextClient;

return new Promise<void>((resolve, reject) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 This is an AI-generated code review comment.

Medium — this promise can never settle.

If client !== nextClient (a newer connect() superseded this one), both the connect and connect_error handlers return early, so neither resolve nor reject ever runs. Any caller awaiting connect() hangs forever and its cleanup never fires. A socket that stalls without emitting connect_error has the same effect.

Two suggestions:

  • In the superseded branches, settle rather than return — either resolve() or reject(new Error("superseded by a newer connection")), whichever the callers should see.
  • Add a connection timeout that rejects, so a silently stalled socket surfaces instead of hanging.

maxy-shpfy and others added 2 commits September 23, 2026 16:12
The routing bridge resolved the active tab on every call, so a project-level
agent could read pipeline A, the person switches to B while it reasons, and
its next addInput or setPipelineName lands in B. submitPipelineRun routes the
same way.

Each agent now gets its own bridge, proxied in at spawn, whose target is
pinned at the start of every turn. Re-targeting between turns is kept — that
is what the router is for — but a turn stays on the tab it began against.

The pin is per agent rather than global because one worker hosts several and
turns are only serialized per agentId, so two can be in flight at once.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@camielvs
camielvs force-pushed the 09-16-feat_tangent_-_remote_agent_for_runview_and_editor branch from c8f0685 to ae3a256 Compare September 23, 2026 23:37

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants