UN-2946 [FEAT] Prompt Studio lookups bridge, executor hook, and IDE wiring (OSS side)#1929
Conversation
…prompt list endpoint
- Add CustomToolListSerializer for the list action to avoid N+1 queries
(profile lookups, prompt fetching, coverage calculation per tool)
- Add ToolStudioPromptListSerializer with only prompt_id, prompt_key,
enforce_type, sequence_number
- Add GET /prompt-studio/prompt/?tool_id={uuid} list endpoint
- List action uses select_related and Subquery annotation for prompt_count
- Detail endpoint unchanged (still uses full CustomToolSerializer)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add lookup-studio plugin detection with dynamic import - Add PromptStudioPopoverContent for hover submenu (Projects / Look-Ups) following the same Popover pattern as HITL and Platform Settings - Register lookups/* route in useMainAppRoutes.js Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ofile_manager Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…on enrichment - Add lookup_config export in prompt_studio_helper and registry_helper via cloud plugin guard (try/except ImportError) - Store raw output in PromptStudioOutputManager, enriched in cloud LookupOutputResult — preserving both for UI tab display - Add LookupEnrichmentProtocol and plugin call in post-extraction pipeline using ExecutorPluginLoader (no-op in OSS) - Track lookup LLM usage via standard metrics pipeline (usage_kwargs with run_id/execution_id, capture_metrics) - Move webhook postprocessing from answer_prompt to pipeline - Frontend: dynamic plugin imports for LookupMenuItem, LookupIndicator, LookupOutputTabs in prompt cards; fetch lookup outputs on page load - Add scroll-to-prompt support via query param in DocumentParser Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…age reason - Extract get_lookup_config() to prompt_studio/lookup_utils.py, replacing 4 identical try/except ImportError blocks across prompt_studio_helper and prompt_studio_registry_helper - Add LOOKUP to LLMUsageReason choices (was missing, causing invalid choice on usage records from lookup enrichment LLM calls) - Migration: usage_v2/0004_add_lookup_usage_reason Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Store prompt/completion/total token counts from the most recent complete() call on the LLM object itself, making usage data queryable without relying on the Audit pipeline roundtrip. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…hook methods Move lookup result-application logic to the cloud plugin, matching the challenge plugin pattern where the plugin owns metadata mutation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…port fallback Add reusable extraction_complete/extraction_error callback tasks to the ide_callback worker, replacing the need for Django-based celery workers for text extraction. Add ExtractionAPIClient for internal API calls. Add polling fallback to WebSocket transport for local dev reliability. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ntrusive UX" This reverts commit d6e136d.
Replace inline DRAFT lookup check with pluggable cloud-only hook. Uses try/except ImportError pattern — zero lookup code in OSS. Collects all DRAFT lookups in one pass with markdown-linked error messages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Consolidate cloud imports into lookup_utils.py with persist_lookup_output() and validate_lookups_for_export() wrappers - Fix LookupEnrichmentProtocol.run() return type to None matching challenge/evaluation pattern - Revert logger.info to logger.debug in websocket_views.py - Eliminate duplicated LookupOutputTabs ternary with renderWithLookupWrapper helper - Move lookups menu constants from SideNavBar.jsx to cloud plugin - Harden DocumentParser.jsx scrollTo with UUID validation and fix useEffect dependency - Revert SocketContext transport to ["websocket"] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move Prompt Studio / Look-Ups navigation from a hover popover on the sidebar into a Segmented control within the ToolNavBar. CustomTools dynamically imports LookupList from the plugin and renders tabs when available, falling back to projects-only view in OSS mode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch from eager per-call Audit HTTP push to a deferred batch write pattern for adapter usage. LLM/embedding calls stash records in-memory; the executor flushes them into ExecutionResult metadata; the Celery task batch-writes via a new internal endpoint. Adds 5 nullable columns to Usage (reference_id, reference_type, execution_time_ms, status, error_message) and a composite index for lookup dashboard queries. Extensible choice lists allow cloud plugins to register additional usage reasons and reference types. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…izer Bridge function in lookup_utils.py lets cloud plugins enrich PromptStudioOutputSerializer with lookup data (enriched output, lookup name). Enables real-time lookup results via WebSocket without page refresh. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… metadata passthrough - Wire usage_kwargs_extra from lookup config into LLM usage_kwargs for execution observability - Add error handling around enricher.run() with explicit ERROR usage records - Generic passthrough of _usage_kwargs into usage records for arbitrary metadata (e.g. reference_id) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…hooks Add dynamic import of getEnrichedCopyText so the copy button copies enriched lookup output when the Enriched tab is active. Applied to both single-pass and multi-profile output paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…modified_at fix - Add /prompt-studio/<pk>/lookup-validation/ endpoint backing the FE Export/Deploy gate; multi-var block check accepts prompt_ids so a single prompt run isn't blocked by an unrelated multi-var lookup. - Add /prompt-output/latest-by-keys/ endpoint that returns the most recent raw output per prompt_key for the test panel's "Use Latest Outputs" helper. - Fix prompt output modified_at not refreshing on re-runs (QuerySet.update bypasses auto_now); set timezone.now() explicitly in the update args. - lookup_utils: bridge get_lookup_validation_for_tool and get_multi_var_lookups_for_tool with prompt_ids scoping. - Header wires useLookupExportGate via try-import (no-op stub in OSS). - TokenUsage treats all-null Usage rows as empty. - CombinedOutput / JsonView build enriched dict from metadata.lookup_outputs to back the Raw|Enriched output toggle. - .gitignore: widen docker/compose.*.yaml. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ab on back - ProfileInfoBar: swap Row/Col for plain flex-wrap div — kills Ant Row negative-margin quirk that overlapped wrapped pills in combined output. - CustomTools: honor location.state.activeTab so back navigation from lookup detail lands on the Look-Ups tab instead of defaulting to Projects. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduces nullable last_exported_at on CustomTool (populated on first successful export) so staleness checks can compare against downstream mutations without a data backfill. NULL is treated as "unknown" and suppresses the lookup-dirty flag to avoid false alarms on pre-feature projects. Adds the get_latest_lookup_mutation_for_tool bridge in lookup_utils so OSS stays decoupled from the cloud plugin. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When enricher.run() raises, surface a user-visible ERROR log line in the workflow execution log alongside the existing usage record. Keeps lookup failures observable next to the other pre/post lookup lines we already emit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Loads useLookupDirtySeed (server-side is_lookup_dirty) and useLookupExportGate from the cloud plugin via dynamic imports so the reminder banner reflects lookup changes across page reloads and the banner's Export flow goes through the same validation modal as the main buttons. Also adds a titleAdornment slot on ToolNavBar for rendering the onboarding tooltip and relaxes EmptyState.text to accept nodes for the tagline + link composition. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… state - Delegate production lookup enrichment to LookupEnrichment.run_with_metrics so the executor and the IDE test path share LLM construction, error handling, and usage-record emission. - Let ExecutionLogs callers pass an arbitrary backRouteState via location state so nested UI restore (e.g. a sub-tab) no longer needs special casing in this component. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bucket of hardening fixes driven by a staff-level PR re-review: - Org-scope latest_outputs_by_keys (was cross-tenant readable via raw .objects.filter() that bypassed OrganizationFilterBackend). - Hide lookup payload shape from OSS: three new opaque bridge helpers (get_original_value_if_enriched, attach_combined_output_enrichment, extract_prompt_output_enrichment) replace direct reads of metadata["lookup_outputs"] / _lookup_outputs / lookup_outputs in output_manager_helper, CombinedOutput.jsx, and usePromptOutput.js. - Split usage_v2 index into a new 0005 migration that uses AddIndexConcurrently + atomic=False so prod doesn't lock the billing table during build. - Delete stale workers/tests/test_usage.py that imported the removed UsageHelper module. - SDK1 LLM gains public get_last_usage_record() so downstream code stops reaching into _pending_usage across plugin boundaries. - legacy_executor stamps metadata["lookup_errors"][prompt] on a failed lookup outcome for dashboards that surface partial-failure runs. - extraction_client docstring notes the cloud-only endpoint contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Module-level probe in prompt_studio/lookup_utils.py — swap per-function try/except ImportError for a single LOOKUPS_AVAILABLE flag. Add attach_lookup_config / attach_lookup_configs_to_tool_settings helpers so the direct metadata["lookup_errors"] write and the lookup_config key stamping both route through the bridge. - Reject org=None in UsageBatchCreateView (usage_v2/internal_views.py). - Lift useLookupExportGate to a single mount in ToolIde.jsx; thread checkLookups down into custom-tools/header/Header.jsx (eliminates the double modal-portal risk). - Delete the direct metadata["lookup_errors"] write from workers/executor/executors/legacy_executor.py — flat summary is now stamped by LookupEnrichment.write_lookup_error in the cloud plugin. Replace hardcoded "lookup_llm" metrics key with lookup_cls.METRICS_KEY. - Trim boilerplate comments across CombinedOutput, PromptCardItems, PromptOutput, usePromptOutput, prompt-card/Header, CustomToolsHelper, SideNavBar — keep the why-comments, drop the what-comments.
OSS counterpart to the cloud-side data-model change. Wires the prompt studio runtime to the new wire shape, surfaces lookup runnability state in the prompt card, and adds the usage_v2 enum entries the cloud side records against (lookup as an LLM usage reason, lookup_version as a reference type). Partially working — known follow-up: TODO: rework lookup input UX. The current variable-mapping flow is awkward (separate rows, manual prompt selection per variable); needs a redesign that mirrors how users actually compose a lookup template. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bring in: - modified_at auto-bump fix (BaseModelQuerySet/BaseModelManager + save() override) - legacy_executor: tool-context warning, backtick log formatting, organization IDs threaded into ExecutorToolShim - prompt-service log streaming + markdown rendering - minio bucket-listing scope fix and CustomMarkdown URL-safety helper Conflict resolutions: - workers/executor/executors/legacy_executor.py: combine HEAD's _usage_records field and typed annotations with main's _execution_id/_organization_id context fields and tool-context warning. Keep both the usage flush after challenge and main's backticked stream_log message. Drop redundant explicit modified_at workarounds now that BaseModelQuerySet auto-bumps modified_at on QuerySet.update(): - prompt_studio_output_manager_v2/output_manager_helper.py: remove the "modified_at": timezone.now() entry passed to PromptStudioOutputManager .objects.filter(...).update(**args), and the now-unused timezone import.
When a configured lookup runs but extraction returned None for the source prompt, _run_lookup_enrichment used to fall through silently — leaving users wondering why enrichment didn't appear. Stream a one-line workflow log via shim.stream_log so the skip is visible alongside other tool-run events.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds lookup/enrichment plumbing with OSS-safe fallbacks, lookup validation and export staleness tracking, buffered/batched usage reporting with schema migrations and internal bulk API, extraction completion/error callbacks and client, worker-side usage buffering/flush, and multiple frontend integrations for lookup UI and enriched output. Changes
Sequence Diagram(s)sequenceDiagram
participant Executor as Worker Executor
participant Orchestrator as Orchestrator/Task
participant WorkerTask as Celery Task
participant UsageClient as UsageAPIClient
participant Backend as Backend API
participant DB as Database
Executor->>Orchestrator: run execution, collect _usage_records
Orchestrator->>WorkerTask: return ExecutionResult (metadata includes usage_records)
WorkerTask->>UsageClient: bulk_create_usage(usage_records, organization_id)
UsageClient->>Backend: POST /v1/usage/batch/ (records)
Backend->>DB: INSERT usage rows
DB-->>Backend: OK
Backend-->>UsageClient: 200 { created: N } / success
UsageClient-->>WorkerTask: success/failure
WorkerTask-->>Orchestrator: log result / continue
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
nit (couldn't anchor inline — line is unchanged context): the docstring at |
athul-rs
left a comment
There was a problem hiding this comment.
@chandrasekharan-zipstack please chekc the NIt comments added
Drop archaeology / "previously / before-X-now-Y" framing; collapse multi-line WHAT walkthroughs to single-line WHY. No logic changes.
…ient Pairs with the cloud-side removal of the lookup token_count / estimated_tokens fields — the worker no longer computes a value to send.
…ration - UsageBatchCreateView raises DRF exceptions (drf-standardized-errors envelope) instead of hand-rolled JsonResponse — serializer validation via raise_exception=True, dedicated UsagePersistError(APIException) for the bulk_create failure path. - Records validated through UsageBatchCreateSerializer / nested UsageRecordCreateSerializer so adapter_instance_id, model_name, usage_type are required and the rest get explicit defaults. - Fold 0006_alter_usage_status_and_more (UsageStatus choices + reference_pair CheckConstraint) into 0004 — branch hasn't merged to main, so squashing avoids an extra ALTER on deploy.
…helpers
- llm.py: token_counter fallback when prompt_tokens=0; rsplit('/',1) for
multi-segment provider IDs; spread _usage_kwargs first so explicit
billing fields win.
- utils/common.py: stamp every record appended during the call window
(was clobbering only the last entry).
- legacy_executor.py: extract run_lookup_enrichment / run_webhook_postprocessing
/ is_blank into workers/executor/executors/lookup_enrichment.py — caller
passes shim/state in, plugin returns usage_records for the caller to
extend its billing batch. Orchestrator stays pure dispatch.
- ide_callback/tasks.py: drop the char-÷4 token estimate heuristic;
context-manage the API clients so HTTP sessions don't leak.
- prompt_studio/views.py: _multi_var_lookup_block_response uses
``detail`` instead of ``error`` to match drf-standardized-errors.
- CombinedOutput.jsx: hoist build helpers to module scope (selectedProfile
passed as arg) — no per-render allocation, fewer useEffect closures.
- DocumentParser.jsx: hoist UUID_RE to module scope (no per-render compile).
- PromptOutput.jsx: silent ``catch {}`` on plugin dynamic-import failures
so OSS doesn't surface noisy warnings for cloud-only modules.
- SideNavBar.jsx: hide the lookups submenu item when the lookup-studio
plugin isn't loaded (keeps OSS nav clean).
…izer Both columns are UUIDField on the Usage model — leaving them as CharField in the serializer let invalid UUIDs slip through to bulk_create and surface as a 500. UUIDField catches them at validation with a standard DRF 400.
Drops the stale "Computes token count" line — the callback no longer derives a token count. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
If _validate_file_execution_id raised, the except handler hit UnboundLocalError and masked the original ValueError. Pre-bind a str(file_execution_id) fallback so the error response carries the real cause. Also gitignore Codex's AGENTS.md scratchpad. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jaseemjaskp
left a comment
There was a problem hiding this comment.
Re-reviewed with the multi-agent toolkit (Code Reviewer, Silent Failure Hunter, Type Design Analyzer, Comment Analyzer, PR Test Analyzer) against the latest HEAD. All previously-raised concerns from my prior pass have been addressed in subsequent commits — the salvage block, billing-flush ERROR promotion, JSON-parse webhook gate, broad-except narrowing, run_id/UUID coercion, and lookup helper extraction all look good. New agent findings either duplicate already-posted reviewer threads or fall below the bar I'm holding for this round (test coverage gaps and stricter serializer choice validation are worth follow-ups but don't block the merge). Approving.
…olumns + post-write hooks Drop reference_id / reference_type from Usage in favour of typed project_id / prompt_id columns indexed CONCURRENTLY for dashboard rollups. Cloud-only attribution (e.g. lookup_version_id) now flows through an opaque cloud_extras carrier on the batch endpoint, which forwards it verbatim to plugin-registered post-write hooks invoked inside the same atomic transaction as bulk_create — a hook failure rolls back the Usage rows so attribution stays consistent or nothing is written. Removes the need for cloud to subclass UsageBatchCreateView or prepend a URL override; the hook seam is generic for any future cloud feature.
…index - register_post_write_hook now dedupes by identity so AppConfig.ready() re-firing under test reloads or dev autoreload can't queue a second LookupUsage write that would IntegrityError and roll back the batch. - usage_objects builder collapsed to a comprehension (review polish). - New 0005 migration step adds a partial index idx_usage_lookup_recent on (organization_id, created_at DESC) WHERE llm_usage_reason='lookup', so the per-(run x prompt) dashboard aggregation stops heap-scanning all Usage rows when filtering by organisation + reason.
The SP cloud plugin returns its usage_records via ExecutionResult.metadata; the non-SP path recovers them via self._usage_records in LegacyExecutor.execute(). _handle_structure_pipeline only honoured the second carrier — every SP-mode API deployment lost its extraction + lookup billing rows silently because tasks.py guards the flush behind ``if usage_records:`` and the empty list short-circuits the post. Forwarding answer_result.metadata closes the gap. Surface drift here deserves a follow-up to consolidate to a single carrier; tracked separately.
…n_id Collapses the dual-carrier pattern in the executor worker so every handler returns its rows via ExecutionResult.metadata["usage_records"]. LegacyExecutor's instance attribute and recovery hook are removed; each helper returns its records, orchestrators absorb child metadata into a single list, and partial rows survive a mid-pipeline failure via LegacyExecutorError.partial_usage_records. tasks.py now logs an INFO line when an LLM-bearing op succeeds with zero rows so future drift surfaces immediately. Also fixes the long-standing dispatcher gap where structure_tool_task omitted execution_id and file_execution_id when constructing ExecutionContext for structure_pipeline / table_extract. The fields were only stuffed inside executor_params, so context.execution_id was None for every downstream handler. The legacy answer-prompt handler dug into executor_params and worked, but SP plugin and summarize handlers fell back to "" — and the dashboard's classifier mapped empty execution_id to the IDE bucket. Setting the dataclass field at dispatch plus reading context.execution_id in _handle_summarize lets workflow rows classify as WF/API. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop WHAT-comments, references to PR/conversation context, and multi-line explanations that didn't add WHY. Comments now describe behavior generically so they make sense without prior context. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Frontend Lint Report (Biome)✅ All checks passed! No linting or formatting issues found. |
Test ResultsSummary
Runner Tests - Full Report
SDK1 Tests - Full Report
|
|



What
OSS-side glue for Lookups V2 — a cloud-only Prompt Studio feature that runs an LLM-powered post-extraction enrichment over a prompt's structured output. This PR is the OSS half: a try-import bridge module, executor hook for non-SP runs, IDE wiring for the Raw/Enriched tabs and gating modals, and a few small schema extensions.
The cloud-side PR (where the feature actually lives) is on the
unstract-cloudrepo, same branch name, same ticket: https://github.com/Zipstack/unstract-cloud/pull/1463.Why
The cloud plugin needs to integrate with extraction (executor), with the per-prompt output flow (
prompt_studio_helper,prompt_studio_output_manager_v2), with export (prompt_studio_registry_helper), and with the IDE UI (Raw/Enriched tabs, gate modal, dirty-seed banner). All of that has to live in OSS — but OSS must never import cloud schema directly. This PR is that boundary.How
backend/prompt_studio/lookup_utils.pytry-imports the cloud plugin and exposes ~10 stable, opaque functions. Every function is a no-op in OSS. Callers don't know cloud key names or model shapes.legacy_executor._run_lookup_enrichmentresolves the worker plugin viaExecutorPluginLoader.get("lookup-enrichment")and runs after each prompt's extraction. Skips with a workflow-log entry when the source prompt extracted nothing.fetch_response/bulk_fetch_response, scoped to the prompt set being run.lookup-validationaction onCustomToolViewreturns the validation buckets that the FE modal renders.CustomTool.last_exported_at(new field) plusis_lookup_dirtyincheck_deployment_usagepowers the "needs re-export" banner.Usagemodel adds a few cloud-extensible enum choices (reference_type,llm_usage_reason="lookup",status,error_message,execution_time_ms).Reviewer aid
A condensed one-page primer for human reviewers — system shape, data model, execution diagrams, gates, smoke checklist — is at
lookups-v2-reviewer-refresher.html(attached, same file on both PRs). Read it before opening the diff.The full KB lives in the reviewer's vault at
~/Documents/Obsidian Vault/zipstuff/lookups/.Main files to review (sorted by significance)
The bridge — central to the OSS↔cloud contract
backend/prompt_studio/lookup_utils.py— every cloud call funnels through here. Tiny, opaque, no-op in OSS.Executor — non-SP entry
2.
workers/executor/executors/legacy_executor.py—_run_lookup_enrichmentdispatches the worker plugin; new "skip-with-log" branch when extraction yieldsNone.3.
workers/executor/executor_tool_shim.py—stream_logrouting (confirms the user-facing path for the new skip log).Prompt Studio integration
4.
backend/prompt_studio/prompt_studio_core_v2/views.py— multi-var pre-flight,lookup-validationaction,is_lookup_dirtyincheck_deployment_usage.5.
backend/prompt_studio/prompt_studio_core_v2/prompt_studio_helper.py— three call sites that attachlookup_configto per-prompt output / tool settings.6.
backend/prompt_studio/prompt_studio_registry_v2/prompt_studio_registry_helper.py— export-time validation + per-prompt config attach.7.
backend/prompt_studio/prompt_studio_output_manager_v2/output_manager_helper.py— persists lookup output via the bridge after enrichment.8.
backend/prompt_studio/prompt_studio_core_v2/models.py— addsCustomTool.last_exported_at.Usage / observability
9.
backend/usage_v2/models.py— extensibleLLM_USAGE_REASON_CHOICES/REFERENCE_TYPE_CHOICESvia try-import; new fields for lookup attribution.Frontend wiring
10.
frontend/src/components/custom-tools/prompt-card/PromptOutput.jsx— Raw vs Enriched tabs.11.
frontend/src/components/custom-tools/header/Header.jsx— wiresuseLookupExportGate(try-imported, no-op in OSS).12.
frontend/src/components/custom-tools/tool-ide/ToolIde.jsx— wiresuseLookupDirtySeed.13.
frontend/src/components/custom-tools/combined-output/{CombinedOutput,JsonView}.jsx— combined-output enrichment passthrough.Can this PR break any existing features?
No production breakage expected. All cloud calls flow through
lookup_utilsand degrade toNone/[]/{ok: True}in OSS, so existing flows behave identically when no lookup is assigned or when the cloud plugin isn't installed.Watch areas:
_run_lookup_enrichmentruns after every prompt in the non-SP path. Whenlookup_configisNone(no assignment) it returns immediately — should be invisible to non-lookup users.metadata["lookup_outputs"]is a new key on prompt output. FE consumers reflecting the fullmetadatashape need to ignore unknown keys.Usagetable now sees rows withreference_type="lookup_version"; dashboards should treat these as additional rows.legacy_executor.pyskip log usesshim.stream_logwhich routes throughLogPublisherto the workflow log UI — verified path inexecutor_tool_shim.py.Database Migrations
usage_v2/0005_usage_reason_ref_created_idxusage_v2/0006_alter_usage_llm_usage_reason_and_moreprompt_studio_core_v2/0007_customtool_last_exported_atEnv Config
None new.
Relevant Docs
~/Documents/Obsidian Vault/zipstuff/lookups/.lookups-v2-reviewer-refresher.html.Related Issues or PRs
Dependencies Versions
No new dependencies.
Notes on Testing
Smoke checklist in the reviewer refresher. The OSS-side hooks and bridge can be exercised against a cloud build; in pure OSS, every lookup-related code path is exercised but no-ops out via
LOOKUPS_AVAILABLE = False.Screenshots
UI screenshots live on the cloud PR (the OSS-side FE changes are wiring only).
Checklist
I have read and understood the Contribution Guidelines.