Claude/chat stream mechanics pq hs8#166
Open
mwcyu wants to merge 12 commits into
Open
Conversation
Replace the hand-rolled fetch + SSE parsing in the OpenAI adapter with the
official openai package. client.responses.create({ stream: true }) returns a
typed async-iterable of events, eliminating the manual TextDecoder/buffer and
extractSseJson machinery. Behavior, exports, and the tool-call loop are
unchanged.
The Claude, OpenAI, and Gemini adapters each re-implemented the same
agentic streaming loop (iterate to maxIterations, stream a turn,
accumulate fullText, run tools, feed results back). That triplication
let the loop logic drift between providers.
Introduce backend/src/lib/llm/driver.ts owning the loop, break
conditions, the runTools call, and the single fullText accumulation.
Each provider becomes a thin session factory (create{Claude,OpenAI,
Gemini}Session) that owns its SDK call, event parsing, follow-up
message state, and all callback firing. Public stream* signatures are
unchanged, so callers stay untouched.
Behavior is preserved: per-provider callback ordering, the OpenAI
pre-tool preamble drop, Claude's stop_reason hard-stop, Gemini's
verbatim thoughtSignature replay, and OpenAI instructions-on-iter-0.
Chat history persistence (route-level, fed by callbacks + fullText) is
unaffected. Typecheck passes.
Enable each provider's built-in, server-executed web search so the main chat can browse the internet: - Claude: native web_search_20250305 server tool - OpenAI Responses: web_search built-in tool - Gemini: googleSearch grounding tool These run server-side (the provider performs the search and folds results into its answer), so they bypass the runTools function-call loop. A new enableWebSearch flag on StreamChatParams gates them; only the interactive main chat (runLLMStream) opts in, leaving tabular review and bulk extraction untouched. Surface searches to the UI via a new onWebSearch callback that each adapter fires when a search starts — Claude on the server_tool_use contentBlock, OpenAI on the web_search_call output item, Gemini on groundingMetadata.webSearchQueries. runLLMStream streams a web_search event and persists it to the assistant message (unlike the transient tool_call_start), so reloaded chats still show "Searched the web for …". Added the web_search variant to the backend and frontend AssistantEvent unions, a stream handler, and a WebSearchBlock renderer. Backend and frontend typecheck clean.
Introduce a supertest-based integration suite covering user, chat, projectChat, projects, documents, tabular, workflows and downloads routes (77 tests). Supabase, auth, storage and the LLM/chat tooling are mocked; streaming SSE endpoints and the signed-download token round-trip are exercised end to end. Refactor src/index.ts to export createApp() and only bind a port when run directly, and skip rate limiters under NODE_ENV=test so the suite is deterministic. Add vitest + supertest dev deps and test scripts.
…prompt Add a free-text practice profile to user_profiles (firm positions, house style, escalation rules) that is injected into the assistant system prompt for the chat and project-chat routes, so ported legal workflows can rely on the user's configured playbook instead of assuming defaults. Mirrors the per-team CLAUDE.md profiles used by the claude-for-legal skill set. - schema.sql + migrations/001_practice_profile.sql add user_profiles.practice_profile - getUserPracticeProfile loader and formatPracticeProfile prompt-block helper - GET/PATCH /user/profile expose and validate the field (20k char cap) - tests for serialization, validation, the formatter, and the loader
Add a Practice Profile textarea to the account page (with a 20k char counter and save state) wired through UserProfileContext.updatePracticeProfile to PATCH /user/profile. Extend the UserProfile API/context types with the practiceProfile field.
…flows Add an importer (backend/scripts/import-skills.ts) that adapts Anthropic's claude-for-legal skills (Apache-2.0) into Mike "assistant" workflows, and run it for the commercial-legal area. It selects the user-invocable document tasks (promoting the vendor/NDA/SaaS review playbooks that are sub-skills upstream), drops plugin-runtime/config skills, and rewrites upstream references — the per-team CLAUDE.md profile becomes Mike's per-user Practice Profile, external CLM/e-sign connectors become Mike's document tools, and slash-commands point at the corresponding workflows. Generated catalogues (portedLegalWorkflows.ts) are merged into the backend BUILTIN_WORKFLOWS (so read_workflow can inject them) and the frontend BUILT_IN_WORKFLOWS (so they appear in the picker). Adds attribution in THIRD_PARTY_NOTICES.md and tests for selection and body adaptation.
Port all nine professional practice areas from claude-for-legal (90 built-in workflows across AI Governance, Commercial, Corporate/M&A, Employment, IP, Litigation, Privacy, Product, Regulatory). The importer now hardens the denylist (onboarding/customize/workspace + scheduled watchers/trackers) and rewrites every ~/.claude working-file path — not just CLAUDE.md — to Mike's project documents / Practice Profile. Educational/meta plugins (law-student, legal-clinic, legal-builder-hub) are intentionally excluded. Make the practice profile per-area: alongside the always-injected general profile, user_profiles.practice_profiles holds an area-keyed map, and the profile for the *active workflow's* practice area is injected with it. Adds a canonical PRACTICE_AREAS list, resolveWorkflowPractice (built-in map + workflows-table fallback), buildPracticeProfileBlock, GET/PATCH validation, and a per-area editor in Account settings. migrations/002 adds practice_profiles jsonb. Tests cover area selection, injection, validation, and the expanded catalogue (94 passing).
Add the two educational claude-for-legal plugins as practice areas — 15 more built-in workflows (case briefing, IRAC/Socratic drilling, flashcards, outline building, bar prep; clinic intake, client letters, drafts, memos, research). Bringing the catalogue to 105. Extend the importer's denylist to drop their session/workspace-state skills (study sessions, deadline trackers, semester handoff, supervisor queue, comms log, guide builder) and skip skills the upstream marks DEPRECATED. Add the two areas to the canonical PRACTICE_AREAS list (backend + frontend) and expand the acronym map (IRAC, DPA, DSAR, PIA, FTO, OSS, AIA, Q&A). legal-builder-hub stays excluded — it's skill-marketplace meta-tooling.
Wire the practice profile into both tabular endpoints, completing coverage across all assistant-facing routes: - /tabular-review/:reviewId/chat — append the profile block to the tabular chat system prompt. - /tabular-review/:reviewId/generate — pass the profile into queryTabularAllColumns so the firm's positions inform cell flags (green/yellow/red) and house style during extraction. A review's practice area is resolved from its workflow_id, so the general profile plus the matching area profile are injected (reviewPracticeProfileBlock helper). Adds a test asserting the profile reaches the tabular LLM call.
The assistant workflow picker now renders workflows under sticky practice-area headers (ordered by the canonical PRACTICE_AREAS list, then any other areas alphabetically, with untagged workflows under "Other"), with titles sorted within each group. Makes the 100+ built-in legal workflows navigable. Search filters within the grouping.
- Extract the duplicated load-profiles + resolve-area + build-block logic from the chat, project-chat, and tabular routes into one buildWorkflowPracticeBlock helper in userSettings; parallelize its two reads. - Static-import builtinWorkflows in resolveWorkflowPractice instead of a per-call dynamic import. - Collapse the per-field profile type/length checks in user.ts into a shared validateProfileText helper. - Factor the four near-identical account save handlers into one runSave flow; memoize areasDirty. - Memoize + single-pass the workflow-picker grouping (drops repeated Map.get). - Drift-guard the importer's area labels against the canonical PRACTICE_AREAS.
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.
adding funcitonality