feat(dev): OTLP trace storage for local dev - #2039
Closed
tejaskash wants to merge 174 commits into
Closed
Conversation
fix(style): add .tsx to precommit hook + align on testing standard.
feat: add config command with positional argument support
Add Router.default(fn) to register a handler that runs when a group is selected without a subcommand (e.g. `agentcore` or `agentcore harness`). The leaf action-building logic is extracted into a shared attachAction helper so leaves and default handlers execute uniformly: same middleware wrapping, global-flag injection into context, and flag/arg parsing. A group's default handler runs with the group's own middleware and can read both inherited and its own group-level flags from the context. It has no own flags/arguments (globals-only).
Three group-level flag tests passed flags as a third constructor argument
(`new Router("app", "", [RegionKey])`), a form the constructor does not
accept, so the globals were never registered. Commander then rejected the
flags as unknown options and called process.exit, aborting the suite.
Switch to the chainable .groupFlags(...) API so the flags register.
Add a React + Ink TUI, mounted through the router's default-handler support: - renderTui(core) returns a DefaultHandle that reads the command path from the context and renders the Root component with the path and injected core clients. Wired onto the `agentcore` root and the `harness` group so bare invocations (`agentcore`, `agentcore harness`) open the TUI. - withTuiOnEmptyFlagsAndArgs(core) is a middleware that opens the TUI when a leaf command is invoked with no flags or arguments (and not --json), otherwise delegates to the real handler. - Hoist the Core type into handlers/types.tsx and thread it (rather than the bare CoreHarnessClient) through the harness handlers. Add react, ink, and @types/react as dependencies.
Relocate renderTui from components/index.tsx to a new src/tui/ directory to keep the TUI entry points organized, and update its three importers (middleware, root handler, harness handler). This is where the upcoming renderJson() will also live. Root stays in components/ and is imported by tui/ from ../components/Root.
useEffect(exit) with no dependency array ran on every render, so exit() fired repeatedly. Add an empty deps array so the effect runs a single time when HelpScreen mounts.
Add renderJson(data) alongside renderTui in src/tui/, which prints an indented JSON representation of a value to stdout. Use it in the harness get/list handlers in place of raw console.log so their output is consistently pretty-printed.
* feat(project): implement project build
`agentcore project build` compiles the project's CDK app and synthesizes its
CloudFormation templates, so the deployable artifacts exist before deploy.
Synthesis runs offline: each stack's environment comes from aws-targets.json,
so no credentials are needed. An empty targets file makes the CDK app fail with
its own actionable message rather than the CLI guessing an account.
The generated package.json defines `cdk` as "npm run build && cdk", so one
`npm run cdk -- synth --quiet` covers both compile and synthesis.
Also puts withProject to work for the first time: it resolves the enclosing
project and hands it to the handler through ProjectKey, and it wraps only build
so that `create` (which refuses to nest inside a project) stays unaffected. Its
cwd is now resolved per invocation instead of at wiring time, so the directory
the user actually ran in is the one searched.
* fix(project): set runtimeVersion on the CodeZip template
The CDK construct library rejects a CodeZip runtime that declares no
runtimeVersion ("runtimeVersion is required for CodeZip builds"), and it is the
field that selects the packager. Without it, synthesizing a freshly created
python project fails on its own scaffolded config.
Container builds take their version from the image, so the container template
is unaffected.
* feat(project): dispatch build on the project's managedBy backend
agentcore.json already records `managedBy` (CDK is the only value today), but
nothing read it: build() hardcoded the CDK path, so adding a terraform or
no-IaC backend later would have meant editing that path instead of adding
alongside it.
Carry managedBy on Project and switch on it in build(), delegating the CDK
work to a private buildWithCdk(). The default arm assigns to `never`, so a new
ManagedBySchema member fails to compile until it has an arm here.
* feat(gateway): add delete commands * feat(gateway): complete delete command surface * test(gateway): record delete fixtures with e2e profile * test(gateway): clean up partial delete fixtures * test(gateway): inject logs client in delete fixtures
* feat: add JSONL draft diff logic and update command support * fix: precompute all batches and add incremental ID persistence * fix: model MalformedResponseError * chore: add onProgress pattern to dataset update batches * chore: add fixture test for dataset update flow * fix: remove first-response behavior, sanitize URLs, and verify draft state when writing * fix: add missing logs stub in update test
* feat(dev): add container dev runner * fix(dev): address container runner review * fix(dev): address container runtime feedback
* feat(gateway): add headless invoke command * fix(gateway): preserve responses and redact paths * fix(gateway): sign authenticate-only invocations * test(gateway): update client construction after rebase * fix(gateway): allow empty no-content responses on TTY * test(gateway): update mutation helper dependencies * fix(gateway): preserve raw query values for SigV4 * fix(gateway): remove rebase conflict markers
* feat: add read-only datasets TUI * chore: replace OMIT parameter with supportedTUICommands handler
* feat(runtime): add contextual TUI actions * fix(runtime): show endpoint failure reason
Co-authored-by: jariy17 <tjariy+jariy17@users.noreply.github.com>
* feat(project): implement add harness scaffolding * refactor(test): clean up tests * refactor(project): rename add to addResource
* feat(tel): implement otel sink * docs(tel): add docstring comments to otel sink * test(tel): add a test of a local server for the collector sink * chore: remove extra space from telemetry test file * docs: add note in comment about default value * fix(tel): avoid letting flush failures stop shutdown * feat(tel): swap to cli from error method * fix(tel): remove duplicate resource attributes * feat(tel): add installationId header and temporarily preference * test(tel): adjust test to use passed down resource attributes
* feat(gateway): add interactive invoke console * fix(tui): keep long multiline input within its rows * fix(gateway): refine path editor and session labels * style(gateway): use neutral path dialog border * fix(gateway): make idle escape navigate back * fix(gateway): allow no-content responses in TUI * refactor(invoke): simplify TUI launch errors * test(gateway): allow TUI startup on slow runners * test(gateway): inject invoke TUI renderer
* feat(project): implement add harness scaffolding * refactor(test): clean up tests * refactor(project): rename add to addResource * feat(project): implement full add functionality for harness * feat(project): finish add implementation * refactor(proj): config --> spec * fix(proj): fail runtime early * fix(proj): swap to relative path for harness.json path reference * feat(proj): wire up dockerfile support * fix(proj): wire in gateway outbound auth * feat(schemas): add credentialArn for harness skills for non-project credentials * fix(harness): add flag for explicit vpc id to support vpc + dockerfile edgecase * feat(proj): handle partial failures of harnesss scaffolding * fix(harness): strip system prompt from config to ensure file is source of truth * fix(test): use path module to build path for windows support * test(harness): add case for unrecognized add flags * fix(add): reject vpc id if networkConfig is not present * test(harness): verify duplicate names are rejected * fix(add): log failed rollback cleanup errors * fix(add): add scaffolded paths before scaffolding * docs: add comments above long paramtrized tests
* feat(project): wire dev handler * fix(dev): read runtimes from Project.spec after #2004 * fix(dev): address project dev review feedback
`project create` scaffolds `agentcore/aws-targets.json` as an empty list, but
the generated CDK app threw on an empty list and synthesized one stack per
target, so a freshly created project had nothing to synthesize and
`project build` failed:
AgentCore CDK synthesis failed: No deployment targets configured.
Please define targets in agentcore/aws-targets.json
Build does not need to know where a project deploys. An empty target list now
synthesizes a single environment-agnostic stack, which resolves its account and
region from CloudFormation pseudo-parameters instead of pinning them at synth
time. That is enough to compile the app and produce a template, which is what
build is for.
The fallback stack is named `AgentCore-<project>` and carries no
`agentcore:target-name` tag, so it is not a deploy candidate: only a stack
synthesized for a real target is tagged, and selecting on that tag is how a
stack is chosen to ship.
A project that does configure targets is unaffected, still synthesizing one
environment-pinned, target-tagged stack per entry.
* refactor(eval): address on-demand review feedback * test(eval): consolidate on-demand regression coverage * fix(eval): restore semicolon and document runWithRealCore rationale - Restore dropped semicolon in src/core/types.tsx that failed format:check - Explain why runWithRealCore stubs the SDK .send() seam inline instead of using the golden fixture harness (failure conditions the recorder can't provoke against a live account) --------- Co-authored-by: jariy17 <tjariy+jariy17@users.noreply.github.com>
* fix(harness): avoid writing a corrupted spec to disk * fix(error): make deserialization error a user error * fix(test): update failing tests --------- Co-authored-by: Hweinstock <hkobew@amazom.com>
Pure OTLP wire handling (per-trace batch partitioning, id normalization, frontend shaping) and append-only per-trace JSONL storage. A batch routinely carries spans from several traces, so persistence partitions by trace id — writing whole batches under the first id corrupts trace identity. Consumed by the OTLP collector in #1980, which stacks on this.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## refactor #2039 +/- ##
============================================
+ Coverage 97.13% 97.14% +0.01%
============================================
Files 381 383 +2
Lines 22782 23076 +294
============================================
+ Hits 22130 22418 +288
- Misses 652 658 +6 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
First slice of the
project devtracing work (#1980 restacks onto this; see #2013's closing comment for the full split plan).What this does
The storage half of local trace collection, with no I/O beyond the filesystem:
otel/transforms.ts— pure OTLP wire handling: split one export batch into per-trace payloads (SDKs batch by time, not trace — attributing a whole batch to its first trace id corrupts trace identity), normalize protobuf/JSON ids to hex, and shape spans/logs for display (attribute flattening, transport-noise filtering).otel/store.ts— append-only storage: one JSON Lines file per trace under a directory, raw reads back. Malformed lines are skipped, never fatal (a half-written line must not break reads).Ported from the current CLI's
operations/dev/otel/transforms.tswith one correctness fix over the original: the per-trace batch partitioning described above.What consumes it
#1980 (the OTLP/HTTP collector +
project devwiring) stacks directly on this branch — the consumer is one PR up, visible now.Verification
23 tests (happy + unhappy paths per layer, audited for redundancy), tsc/lint/format clean. End-to-end proof of the full pipeline lives in #1980's stack (real project, real Bedrock invocation, traces on disk).