Repository navigation
S20a: lousho.node.id on agent, chat, tool, subagent and flow spans - #862
Open
LinuxDevil wants to merge 1 commit into
Open
LinuxDevil wants to merge 1 commit into
LinuxDevil wants to merge 1 commit into
Conversation
…ow spans Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
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.
What changed
Every span an agent compiled from a v2 spec emits now carries
lousho.node.id(SdkAttr.NODE_ID) — the canvas node id of the thing that produced it — so Studio can light up the right node without guessing from names. No executor change:specV2ToAgentwrapshost.exporterin a new exporter that stamps the attribute inonSpanStartfrom an index built from the spec and the compiled tool names, then forwards the same span objects in the same order. Only node ids land on spans — never spec values or secrets.src/execution/semconv.ts:SdkAttr.NODE_ID = 'lousho.node.id'(re-exported from the root;api/index.api.mdregenerated).src/spec/v2/nodeIds.ts(browser-safe, pure):specNodeIds(spec)returns the spec's node ids by section — tools (tool:<id ?? builtin ?? registry ?? hosted ?? integration ?? file basename w/o ext ?? "openapi" ?? "hub">, deduped#2,#3),mcp:<key>,skill:<…>,memory:<name>,sub:<name>,handoff:<agent>,guard/perm/hook/trigger/abort:<id>, andflow:<step id>for every step ofspec.flow.flow(depth-first throughsteps,options[].step,step).src/spec/v2/nodeIdExporter.ts:nodeIdIndexOf(spec, toolNamesByRef, subIndexes)builds the span→node index;nodeIdExporter(inner, index)stampslousho.node.idat start via a rule table (invoke_agent→ enclosing agent or<scope>sub:<n>with a new child scope,chat→ enclosing agent,execute_tool→ tool/MCP/handoff/memory lookup,flow.node …→flow:<id>) and deletes scope entries on end;isNodeIdExporterbrands wrapped exporters with a WeakSet so nested compiles never wrap twice.src/spec/v2/specToAgent.ts: whenhost.exporteris set and not already wrapped, an empty mutable index + wrapper are created, the spec compiles against the wrapped exporter (inline sub-agents share the one scope map), and the index is filled — including each spec-built sub-agent's own index — beforecreateAgent()returns, i.e. before any span can start.How tested
npx tsc --noEmit— clean.npm run typecheck:tests— clean.npm run lint— clean.npx vitest run src/spec/v2— 424/430 pass; the only 6 failures aretemplates.test.tsREADME assertions that fail identically on the base commit (verified viagit stash); unrelated to this change.npm run test:coverage -- --minWorkers=1 --maxWorkers=4— same 6 pre-existing failures, everything else green (7210 pass).npm run fallow— ✓ 0 above threshold, maintainability 89.2.npm run api:check,npm run docs:ratchet(at baseline),npm run docs:llms:check,npm run size-check— all pass.nodeIds.test.ts(12: one per section + dedupe + flow walk + empty spec) andnodeIdExporter.test.ts(8: unit stamping of hand-built spans incl. sub-agent scoping, unknown-parent root scope, scope cleanup,isNodeIdExporter; integration: realspecV2ToAgentruns with a scripted mock model assertingagent,tool:current_date,tool:fetch,sub:research,sub:research/tool:web_fetch).Acceptance criteria
[{ builtin: 'current_date' }, { builtin: 'web_fetch', id: 'fetch' }], traced into an in-memory exporter, has:invoke_agent→agent; everychat→agent;execute_tool current_date→tool:current_date;execute_tool web_fetch→tool:fetch.docs__searchgetsmcp:docs(fed directly to the exporter; no MCP server needed).remember_notesgetsmemory:notes;transfer_to_billinggetshandoff:billing.tasktool → sub'sinvoke_agentwithlousho.subagent.name = research) getssub:research, itschatspanssub:research, and its own toolweb_fetch→sub:research/tool:web_fetch.flow.nodespan withlousho.flow.node.id = s1getsflow:s1.specNodeIdsdedupes two{ builtin: 'http_request' }refs totool:http_requestandtool:http_request#2.lousho.node.id; the inner exporter receives the same span objects.Guardrail check spans (S20b), handoff/approval-wait spans (S20c) and Studio's WS
nodemapping (D14) are out of scope.Generated with Devin