Skip to content

feat: add @cacheplane/render and @cacheplane/chat libraries#15

Merged
blove merged 35 commits into
mainfrom
claude/angry-solomon
Apr 5, 2026
Merged

feat: add @cacheplane/render and @cacheplane/chat libraries#15
blove merged 35 commits into
mainfrom
claude/angry-solomon

Conversation

@blove
Copy link
Copy Markdown
Contributor

@blove blove commented Apr 5, 2026

Summary

  • @cacheplane/render (libs/render) — Angular rendering layer for @json-render/core specs. Recursive renderer using ngTemplateOutlet + NgComponentOutlet, Signal-backed StateStore, component registry, and DI provider. 37 tests.
  • @cacheplane/chat (libs/chat) — Chat UI component library with 10 headless primitives and 7 prebuilt Tailwind compositions (shadcn model). Includes <chat-debug> with checkpoint timeline, state inspector, state diff, and navigation controls. 112 tests.
  • Cockpit integration — 14 standalone Angular apps (8 LangGraph + 6 Deep Agents) demonstrating chat library usage for each capability.

Key design decisions

  • Layered stack: @json-render/core@cacheplane/render@cacheplane/chat@cacheplane/stream-resource
  • Consumer owns StreamResourceRef, chat components render from its signals
  • Headless primitives (unstyled, ng-template customizable) + prebuilt compositions (Tailwind)
  • <chat-generative-ui> bridges render and chat for inline AI-generated UI

Test plan

  • nx test render — 37 tests passing
  • nx test chat — 112 tests passing
  • nx build render — builds successfully
  • nx build chat — builds successfully
  • nx lint render — clean
  • nx lint chat — clean

blove and others added 30 commits April 4, 2026 20:31
Spec for three deliverables: @cacheplane/render (Angular renderer
for @json-render/core), @cacheplane/chat (headless primitives +
Tailwind compositions for LangGraph/Deep Agent UIs), and cockpit
integration. Covers rendering pipeline, debug tool architecture,
testing strategy, and dependency chain.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three plans covering the full chat component library:
1. @cacheplane/render — 11 tasks, Angular renderer for @json-render/core
2. @cacheplane/chat — 14 tasks, headless primitives + Tailwind compositions
3. Cockpit integration — 9 tasks, capability examples consuming chat lib

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Generates the publishable Angular library libs/render with Vitest test
executor, ng-packagr build, flat ESLint config, and SPDX license headers
matching the stream-resource reference patterns. Installs @json-render/core
as a devDependency and registers the @cacheplane/render path alias.
Implements the core rendering pipeline component that looks up elements
from the spec, resolves component classes from the registry, evaluates
visibility conditions, resolves dynamic prop expressions and bindings,
and renders via NgComponentOutlet. Includes repeat element support with
child Injector-scoped RepeatScope.
Entry point component that accepts spec, registry, store, functions,
handlers, and loading as inputs. Provides RENDER_CONTEXT to child
RenderElementComponents via viewProviders. Falls back to RENDER_CONFIG
from provideRender() for registry/store defaults, and creates an
internal signalStateStore from spec.state when no store is provided.
Adds tests verifying the recursive rendering pattern: parent components
receive childKeys and spec as inputs, each child element resolves
independently from the same spec, and deeply nested trees are traversable.
Adds RenderElementComponent, RenderSpecComponent, RENDER_CONTEXT,
RenderContext, REPEAT_SCOPE, and RepeatScope to the public API.
- Fix @json-render/core peer dep version to ^0.16.0
- Fix componentClass() to return null (not undefined) for ngComponentOutlet compatibility
- Fix test component selectors to use render- prefix per eslint config
- Remove unused imports from spec files
- Suppress no-empty-function lint errors in test helpers
- Add ChatConfig and MessageTemplateType to chat.types.ts
- Add createMockStreamResourceRef() with writable signals, matching
  the full StreamResourceRef<T, ResolvedBag> interface including all
  signals and action methods
- MessageTemplateDirective: ng-template[messageTemplate] with input.required<MessageTemplateType>()
- ChatMessagesComponent: collects templates via contentChildren, computes
  messages from ref.messages(), renders via ngTemplateOutlet with findTemplate()
- Extract getMessageType() as standalone function (human/ai/tool/system/function,
  fallback 'ai') to enable logic-level unit tests without DOM rendering
- 15 tests across 2 spec files; all passing
Adds ChatInputComponent with submitMessage() pure function, isDisabled computed from ref.isLoading, and onSubmit/onKeydown methods. Exports submitMessage for logic-level testing. 7 new tests passing (22 total).
Adds ChatTypingIndicatorComponent (visible computed from ref.isLoading) and ChatErrorComponent (errorMessage computed with Error/string/unknown handling). Exports isTyping() and extractErrorMessage() pure functions for logic-level testing. 14 new tests passing (36 total).
Adds ChatInterruptComponent with interrupt computed from ref.interrupt(), contentChild(TemplateRef) for consumer-provided templates, and ngTemplateOutlet rendering with interrupt as implicit context. Exports getInterrupt() pure function for logic-level testing. 5 new tests passing (41 total).
- Fix provide-chat test failures (tests were already passing, addressed
  pre-existing lint and build errors instead)
- Add missing peerDependencies: @angular/forms, @json-render/core,
  @langchain/langgraph-sdk
- Rename debug-* component selectors to chat-debug-* prefix to satisfy
  @angular-eslint/component-selector rule; update all template usages
- Rename messageTemplate directive attribute to chatMessageTemplate to
  satisfy @angular-eslint/directive-selector rule
- Fix tsconfig.json: remove baseUrl override so inherited paths from
  tsconfig.base.json resolve correctly in ng-packagr builds
- Fix TS2307: move ToolCallWithResult and ToolProgress imports from
  @cacheplane/stream-resource to @langchain/langgraph-sdk (not exported)
- Fix TS2551: update checkpoint_id access to state.checkpoint.checkpoint_id
  to match actual ThreadState type shape; update spec accordingly
- Fix TS6133: remove unused 'computed' and 'ThreadState' imports
- Fix TS2345: cast keydown event with $any() in chat-input template
- Add eslint-disable comments for intentionally empty mock no-op methods
blove and others added 5 commits April 5, 2026 09:05
…ling, type accuracy)

- I-1: Replace internalStore computed with lazy _internalStore field to prevent store recreation on every spec change
- I-2: Update AngularComponentInputs to reflect spread props pattern with index signature instead of props bag
- I-3: Fix setByPath to preserve array type when setting by numeric index; add test
- I-4: Extract repeatScopes computed to eliminate duplicate RepeatScope construction in repeatInjectors/repeatInputs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…correctness)

- C1: Remove ng-content from ChatTypingIndicator and ChatError; both are now
  self-contained status components with default markup (no content projection)
- I1+I2: Extract messageContent() to libs/chat/src/lib/compositions/shared/message-utils.ts;
  both Chat and ChatDebug expose it as a class property with co-location comment
- I3: Export MockStreamResourceRef interface with writable signals so tests avoid
  unsafe casts; createMockStreamResourceRef() now returns MockStreamResourceRef
- I4: ChatToolCalls uses AIMessage instanceof check + ref().getToolCalls() instead
  of (msg as any).tool_calls
- I5: ChatTimelineSlider emits replayRequested/forkRequested outputs instead of
  calling setBranch() with a checkpoint ID (setBranch takes a branch name)
- I6: ChatComponent accepts optional threads/activeThreadId inputs and renders a
  ChatThreadList sidebar when threads are provided

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…chat

Creates 14 Angular CockpitCapabilityModule descriptors (8 LangGraph + 6
deep-agents), each with package.json, project.json, tsconfig.json,
src/index.ts, src/app.component.ts, and prompts/{topic}.md.

LangGraph topics: streaming, persistence, interrupts, memory, time-travel,
subgraphs, durable-execution, deployment-runtime.

Deep-agents topics: planning, filesystem, subagents, memory, skills, sandboxes.

Each Angular component demonstrates the relevant @cacheplane/chat primitives:
<chat>, <chat-messages>, <chat-input>, <chat-typing-indicator>,
<chat-interrupt-panel>, <chat-timeline-slider>, <chat-subagent-card>,
<chat-error>, and <chat-debug>.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add main.ts, app.config.ts, and index.html to all 14 cockpit Angular
examples (8 LangGraph + 6 Deep Agents) so each can be independently
bootstrapped. Deep Agents examples include provideRender({}) from
@cacheplane/render to support generative UI via <chat-debug>.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@blove blove merged commit 480d6aa into main Apr 5, 2026
@blove blove deleted the claude/angry-solomon branch May 7, 2026 16:30
blove added a commit that referenced this pull request May 19, 2026
* docs: spec for aimock scaffold generator + helper consolidation

Task #15 in the pre-batching cleanup arc. Single-cap throwaway
generator (scripts/generate-aimock-scaffold.ts) reads the registry
and emits e2e/ files + project.json edit + ci.yml matrix entry. Also
consolidates the duplicate submit-and-wait helpers in libs/e2e-harness/
— migrate 3 cockpit cap specs to submitAndWaitForResponse and remove
sendPromptAndWait. After this PR, Task #4 batching becomes mechanical.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: plan for aimock scaffold generator + helper consolidation

7-task plan: migrate 3 specs, delete sendPromptAndWait from harness +
barrel, create generator script, verify via c-messages generation +
revert, commit/push/PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: aimock scaffold generator + helper consolidation

Ships scripts/generate-aimock-scaffold.ts — a single-cap throwaway
generator that reads apps/cockpit/scripts/capability-registry.ts and
emits a cap's e2e/ directory (5 files) plus the project.json e2e
target plus a ci.yml matrix entry. Validates all preconditions before
writing; refuses on any pre-existing target. Unblocks Task #4 batch.

Consolidates the duplicate submit-and-wait helpers:
- Migrate streaming.spec.ts, c-tool-calls.spec.ts, c-subagents.spec.ts
  from sendPromptAndWait → submitAndWaitForResponse (mechanical swap;
  semantically equivalent for composed-<chat> caps).
- Remove sendPromptAndWait + SendPromptAndWaitOptions from
  libs/e2e-harness/src/{test-helpers,index}.ts.
- Keep sendPromptAndWaitForInterrupt + clickInterruptActionAndWaitFinal
  (interrupt-flow specific; c-interrupts depends on them).
- Update libs/e2e-harness/README.md to drop stale references.

After this PR, batching the 7 chat caps in Task #4 is mechanical:
run the generator per cap → hand-author fixture + spec assertions.

Note: examples/chat/angular/e2e/test-helpers.ts has its own local
sendPromptAndWait — left untouched (separate ownership boundary;
follow-up task if consolidation desired).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant