Skip to content

chore(shared-model): bring stranded node-UI demo into the feature branch (merge-order fix)#1162

Merged
branarakic merged 2 commits into
feat/llm-sharing-modulefrom
feat/shared-model-m1-fixes
Jun 14, 2026
Merged

chore(shared-model): bring stranded node-UI demo into the feature branch (merge-order fix)#1162
branarakic merged 2 commits into
feat/llm-sharing-modulefrom
feat/shared-model-m1-fixes

Conversation

@branarakic

Copy link
Copy Markdown
Contributor

Why

The stacked PRs were merged in the wrong order:

Net effect: the node-UI demo is stranded in feat/shared-model-m1-fixes and never reached the feature branch (feat/llm-sharing-module, the base of #1157).

What this does

Merges feat/shared-model-m1-fixesfeat/llm-sharing-module. The M1 fixes are already present in the base (via #1158), so the only delta is the UI demo:

  • packages/node-ui/src/ui/components/Modals/CuratorModelChatModal.tsx (new)
  • packages/node-ui/src/ui/components/Shell/Header.tsx (launch button)
  • packages/node-ui/src/ui/api.ts (invokeSharedModelChat)
  • packages/node-ui/test/invoke-shared-model-chat.test.ts (new)

Verified locally: clean merge, no conflicts, node-ui-only diff. Does not touch #1157→main.

🤖 Generated with Claude Code

Branimir Rakic and others added 2 commits June 14, 2026 14:10
…'s shared AI model (demo MVP)

Adds a self-contained, self-discovering chat modal that lets a context-graph
MEMBER chat with a curator's shared AI model. The completion runs ON THE
CURATOR'S node; the member node only proxies via its existing OpenAI-compatible
route POST /api/context-graph/:id/model/v1/chat/completions.

- api.ts: new invokeSharedModelChat(cg, messages, { model? }) helper. Uses the
  existing authHeaders() machinery (same-origin Bearer NODE token). Returns
  choices[0].message.content; on a non-2xx it unwraps the OpenAI-shaped error
  body { error: { message } } (an object — the generic post() helper would
  stringify it to [object Object]) and throws Error(error.message) so denials
  (403 "requester is not a member…", quota) surface as readable text.
- CuratorModelChatModal.tsx: new modal mirroring ShareProjectModal's chrome
  (v10-* classes, useModalDismiss). Cross-CG + self-discovering: lists the
  member's CGs via useMyContextGraphs, reads each grant via getModelGrant, keeps
  the enabled ones in a "<CG name> · <modelId>" dropdown (friendly empty state
  when none). In-memory chat (list + textarea + Send), a "thinking…" state while
  awaiting the single buffered reply, an inline error bubble for denials, and a
  header banner indicating the chat runs on the curator's shared model. No
  streaming, no tool-calls, no persistence.
- Header.tsx: single global launch point — a chat-bubble icon button in the
  header actions opens the modal (cross-CG, so global rather than per-project).
  The modal is mounted only while open so its discovery hook doesn't poll on
  every Header mount.
- Tests: invoke-shared-model-chat.test.ts pins the 200→content and
  403→error.message contract against a mocked fetch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
setInput('');
setSending(true);
try {
const reply = await invokeSharedModelChat(selectedCg, outbound, {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Bug: This request is not scoped to the currently selected context graph. If the user switches the dropdown while invokeSharedModelChat() is in flight, the selectedCg effect clears the session, but the old response/error still appends into the newly selected graph's conversation. Capture the graph/request id before awaiting and ignore late completions when selection changes, or disable graph switching until the send settles.

* persistence.
*/
export function CuratorModelChatModal({ open, onClose }: CuratorModelChatModalProps) {
const { myCgs, cgsLoading } = useMyContextGraphs();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Issue: useMyContextGraphs() applies the local "hidden from sidebar" filter. Using it here means hiding a context graph in the sidebar also makes its shared model undiscoverable, even though the user is still a member and this modal is meant to be a cross-context-graph surface. Consider sourcing membership without the hidden-ids filter (or add an opt-out for this hook) for the model picker.

@branarakic branarakic merged commit bf31847 into feat/llm-sharing-module Jun 14, 2026
3 checks passed
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