enhancements/consumer #4

Merged
mohiit1502 merged 13 commits from enhancements/consumer into main 2026-04-21 01:11:05 +05:30
Owner
No description provided.
mohiit1502 added 13 commits 2026-04-21 01:10:15 +05:30
Backend (chat.py):
- Add bridge_mode field to ChatRequest
- Add bridge_required + bridge_messages fields to ChatResponse
- When bridge_mode=true (or model set + no backend provider):
  skip LLM call, return assembled RAG+system_prompt messages
- Backend never calls localhost — LLM call happens in browser

Frontend (ChatWorkspace.tsx):
- isBridgeActive = bridge.status === 'connected' (not model-gated)
- effectiveModel chain: chatModel ?? bridge.selectedModel ?? bridgeModels[0]
- Send bridge_mode:true when bridge connected
- On bridge_required response: call localBridgeFetch with bridge_messages

Resolution order (user-facing chat):
  1. Browser bridge (extension installed + local model) — zero backend config
  2. Offered AI / free tier (NEBULA_LLM_API_KEY in prod env) — TODO: set in prod
  3. BYOAI (user key in Settings)
  4. 503

client.ts:
- ApiChatRequest.bridge_mode?: boolean
- ApiChatResponse.bridge_required?: boolean
- ApiChatResponse.bridge_messages?: [{role,content}[]]
- nebula-local-bridge/content.js: forward requestId in models message relay (root cause of models=0)
- webapp/src/lib/localBridge.ts: deduplicate models by id in _listModelsRaw (fixes duplicate key console errors)
- webapp/src/components/layout/ChatWorkspace.tsx: add retry + 30s polling for bridge model fetch
- webapp/src/components/Toast.tsx: overhaul shared toast — dark panel, type-accent, slide-in, useToast hook
- webapp/src/pages/agents/AgentExtractMenu.tsx: replace inline toast with useToast
- webapp/src/pages/agents/AgentDetail.tsx: replace inline toast state with useToast
- webapp/src/api/client.ts: type Window.__NEBULA_TOAST__ via global interface augmentation
- webapp/src/components/layout/Layout.tsx: remove any cast for global toast
- webapp/src/components/layout/Navbar.tsx: remove floating help handle + dead imports
- webapp/src/components/help/HelpPanel.tsx: decouple useHelpAvailability from admin displayPanel config
- webapp/src/components/BridgeStatusBadge.tsx: Puzzle icon, retry+polling for model count
- scripts/seed_model_resolution_blog.py: upsert logic, remove platform key exposure, rich content
- .flake8: add per-file E501 ignore for scripts/
Backend (chat.py):
- _get_system_state: add recent tasks query (enables 'my tasks' queries)
- _build_system_prompt: inject recent tasks into SYSTEM STATE context
- _build_system_prompt: add anti-hallucination rule blocking web_scraper/doc_parser/email claims
- Built-in tools list: corrected to only list implemented tools (read_file, write_file, http_request)
- Add list_tasks tool to NEBULA_CHAT_TOOLS with status_filter + agent_id params
- Add list_tasks dispatch handler with parameterized DB query

Frontend (ChatWorkspace.tsx):
- Add ChatActionStrip component: renders quick-action nav buttons when AI replies
  with a capability overview (keyword heuristic on reply content)
- Buttons: Agents, Tasks, Plugins, Integrations, Models, Policies, Logs, Settings
- Hover accent per section for visual identity
- Import Settings + Shield icons from lucide-react

Docs:
- Add docs/All/architecture/CHAT_WORKSPACE_SPEC.md covering:
  - Differentiators vs ChatGPT/Claude
  - Full capability table with status (implemented/partial/not-started)
  - Message streaming ASCII diagram
  - System prompt spec (what to claim / not claim)
  - Implementation priority order
feat: mobile shell layout + chat workspace spec mobile section
All checks were successful
Stuffle/nebula-os/pipeline/head This commit looks good
738c2c5ff0
ShellLayout.tsx:
- Add useIsMobile() hook — MediaQueryList-based, no polling
- Mobile (≤640px): single-pane view with bottom tab bar (Global/Chat/Inspector)
- Tablet (641–768px): left panel hidden, center 60% + right 40%, no resizer
- Desktop (>768px): full 3-pane unchanged
- Bottom tab bar: nebula accent underline on active tab, dot badge on Chat when not active
- Pane switching: GlobalContextPanel / ChatWorkspace / RightPanel swap in-place

index.css:
- .ne-Shell__bottom-tabs — flex row, 3rem height, safe-area padding for notched phones
- .ne-Shell__tab — column flex, accent top-border on active, ripple on :active
- .ne-Shell__tab-dot — notification dot indicator
- Mobile chat: ne-ChatBubble max-width 96%, tighter padding, 100dvh for keyboard-aware layout
- Tablet chat: ne-ChatBubble max-width 92%

docs/All/architecture/CHAT_WORKSPACE_SPEC.md:
- Add section 8: Mobile Layout Spec
  - 8.1 Desktop reference ASCII diagram (from screenshot)
  - 8.2 Breakpoint table (desktop/tablet/mobile)
  - 8.3 Mobile layout ASCII diagrams (chat/global/inspector panes)
  - 8.4 Mobile interaction rules (9 rules)
  - 8.5 CSS additions reference
- _get_system_state now accepts user_email; all entity queries (agents, tasks,
  plugins) filter to the requesting user. Published plugins remain globally
  visible. integration_instances TODO'd for migration 044 (no owner column yet).

- Provider registry: Nebula always first (live registry); external providers
  only when status='active' AND is_implemented=true.

- Tool inline format changed to compact set notation {slug:{t1,t2,...}}.
  Threshold raised to 80 — compact format is ~3x more token-efficient.
  Over-limit falls back to count-only {slug:N} with list_provider_tools() hint.

- New tool: list_provider_tools(slug) — returns tool list for any provider
  on demand; used when compact/count-only mode is active.

- DATA REGISTRY also uses compact notation {agents:{name(id:state),...}}.
  Hardcoded route table replaced with a terse pattern rule.

- Bug fix: ii.is_active (non-existent) → ii.status='active' in both
  _fetch_ext_providers (chat.py) and list_integrations tool.

- Migration 043: is_implemented BOOLEAN NOT NULL DEFAULT FALSE on
  integration_providers. Applied.

- Test fix: test_create_plugin_tool.py updated to import from
  chat_tools/plugin_tools (refactored location) and use tool classes
  directly instead of removed _handle_* functions.
fix: launch-readiness P0/P1 gaps from launch report
All checks were successful
Stuffle/nebula-os/pipeline/head This commit was not built
2171100e79
BUG-01 (P0): Add stop/cancel button during streaming
- AbortController stored in abortRef; created fresh per nebulaMut call
- chatApi.send() and request() accept optional AbortSignal, passed to fetch()
- When isPending: send button replaced by red square stop button
- handleStop: aborts controller + resets mutation + adds 'Response stopped.' bubble
- AbortError suppressed — no error bubble shown when user intentionally stops
- localBridgeFetch has no signal support (postMessage bridge); abort only
  cancels the backend HTTP leg

BUG-02 (P0): Memory save error is now guided
- System prompt rule added: when memory operations fail because no agent
  exists, LLM must reply with explanation + [button:Create Memory Agent:...]
  pointing to /agents?spawn=1&skill=memory+agent

CSS: .ne-ChatWorkspace__stop-btn — red background, hover state
feat: inline typing bubble in chat thread
All checks were successful
Stuffle/nebula-os/pipeline/head This commit looks good
47dd3d4ffa
Replace floating 'Thinking...' footer with a proper Nebula message bubble
that appears inside the message list, directly below the user's message.

- TypingBubble renders with the Nebula sender label + sparkle icon (matching
  real response bubbles), animated three-dot bounce animation (ne-TypingDots),
  and a status label that cycles based on elapsed time.

- inferStatusLabel(): heuristic that reads the last user message and
  predicts the likely operation:
    plugin/build   → Writing plugin code… → Validating code…
    run/execute    → Dispatching task… → Agent is running…
    agent/create   → Checking agents…
    remember/save  → Checking memory…
    search/find    → Searching knowledge base…
    integrations   → Checking integrations…
    status/health  → Querying system state…
    default        → Calling tools… → Preparing response…

- Removed the detached Loader2 + 'Thinking…' div from below the list.
- CSS: ne-TypingDots with @keyframes ne-typing-dot bounce animation.
feat: live workflow trace + completed execution diagram in chat
All checks were successful
Stuffle/nebula-os/pipeline/head This commit looks good
75457e3f33
During pending:
- TypingBubble simplified to plain subtitle text (no bubble box):
  Sparkles icon + animated dots + status label (context-aware)
- LiveWorkflowTrace below the text: nodes appear one by one with
  timing (Input→Context→LLM→Tools→Response), each node glows purple
  while active, turns green when complete, current node spins Loader2

After response (on each Nebula message):
- WorkflowTrace renders below the message with a collapsible one-line
  summary: ' 285ms · 4o-mini · 2 tools · 3 chunks ▶'
- Expanded view: icon nodes in a horizontal scrollable flow with
  coloured circles, tool names, and detail labels per node
  (e.g. 'List Agents · 3 agents', 'Create Agent · ...abc123')
- Nodes built from real response data: toolActions, chunksUsed,
  latencyMs, modelUsed (now stored on ChatMessage)
- Shows RAG node only when chunks_used > 0
- Shows Synthesis node only when tools were called
- Model prefix stripped (gpt-, openai/, anthropic/) for compact display

Types:
- Added modelUsed?: string to ChatMessage
- aiMsg now stores resp.model_used
fix: retain workflow trace on response — linger + default open
All checks were successful
Stuffle/nebula-os/pipeline/head This commit was not built
d872254106
- showTyping state lingers 400ms after isPending drops so TypingBubble
  stays visible during the handoff to the completed message
- WorkflowTrace defaults to open=true so the execution diagram is
  immediately visible below the response (no need to click to expand)
fix(OBS-02): task badge immediately reflects final status from WS event
All checks were successful
Stuffle/nebula-os/pipeline/head This commit was not built
f47989c776
Root cause: taskStatus was only updated after tasksApi.get() resolved
(100-300ms after WS fires), so badge stayed 'running' during that gap.
Secondary bug: used task.status from the refetch which can be stale.

Fix:
- setPendingTaskIds and taskStatus flip happen synchronously on WS event
  receipt, before the API enrichment call — badge changes instantly
- tasksApi.get() still called to get content + tokenCost, but now
  uses finalStatus from WS type (not potentially-stale task.status)
- .catch() path removed redundant status override (already set above)
fix: try_it_out tool not invoked — anti-hallucination rule blocking demo
All checks were successful
Stuffle/nebula-os/pipeline/head This commit was not built
5f33371122
Root cause: refactor to provider/data registry removed the try_it_out
rule from the system prompt. LLM received 'Run the try-it-out demo:
Runtime Health Audit', treated 'Runtime Health Audit' as an agent name
lookup, found nothing in DATA REGISTRY, and applied anti-hallucination
rule → refused instead of calling the tool.

Fixes:
1. chat.py system prompt: add explicit try_it_out rule — triggers on
   'template_id=', 'tryit', 'run demo' etc. Note that it creates its
   own demo agent, no pre-existing agent required.
2. chat.py anti-hallucination: add EXCEPTION for try_it_out, create_agent,
   create_plugin — these CREATE entities, DATA REGISTRY is irrelevant.
3. ChatWorkspace.tsx: /tryit slash command now sends
   'Run try-it-out demo template_id=runtime_audit' (slug, not human label)
   so the LLM cannot confuse the template name with an agent name.
fix: remove redundant try_it_out tool rule from system prompt
All checks were successful
Stuffle/nebula-os/pipeline/head This commit was not built
689776fed8
Explicit 'Use try_it_out when...' instruction duplicates what the tool
description already declares. Tool descriptions are the right place
for capability/trigger declarations; the system prompt is for:
- multi-step confirm flows (create_plugin/publish_plugin gates)
- post-call state transitions
- fallback behaviors on tool failure
- cross-cutting policy exceptions (anti-hallucination EXCEPTION clause)

The real fixes (anti-hallucination exception + unambiguous template_id
message format) remain in place.
fix: agent visibility — user sees own + published agents (is_template=true)
Some checks failed
Stuffle/nebula-os/pipeline/head There was a failure building this commit
Stuffle/nebula-os/pipeline/pr-main Build started...
2227d566b5
Root causes:
1. _fetch_agents queried WHERE user_email=$1 but agents table has owner_id
   (no user_email column) → silent SQL error → empty DATA REGISTRY → LLM
   reports 'no agents exist'
2. tasks._fetch_tasks used user_email which is always NULL → empty tasks list
3. Silent except blocks swallowed all DB errors invisibly

Fixes:
- _get_system_state: add user_id param; pass identity.user_id at call site
- _fetch_agents: query owner_id=user_id OR is_template=true; dev fallback
  shows is_template=true only
- _fetch_tasks: query created_by=user_id; dev fallback shows all tasks
- list_agents tool: same visibility rule as _fetch_agents
- All except blocks now log errors (observability rule)

Data:
- Published 24 seeded agents (is_template=true) so all users see them
- User-created agents only visible to their owner (owner_id match)
mohiit1502 merged commit 4748e74311 into main 2026-04-21 01:11:05 +05:30
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Restruct-Corporate-Advantage/nebula-os#4