Implement optional single-image intake, Signal ingestion, and multimodal vision analysis

- Add image intake service with format validation (JPEG, PNG, WebP) and EXIF/GPS stripping
- Enforce strict single-image rule across Web and Signal attachment channels
- Implement token-optimized vision downscaling and JPEG compression
- Add IMAGE_CONTEXT pipeline stage with OmniRoute vision routing and resilient failover
- Seed and manage versioned idea-image-interpreter prompt in catalog
- Update Web UI with responsive image picker, preview chip, and Visual Context tab
- Add comprehensive automated test suite in test_image_intake.py
- Update README and Labyricorn devlog
This commit is contained in:
2026-08-23 01:40:22 -07:00
parent 94ff1e4408
commit 41e08611c9
30 changed files with 3784 additions and 278 deletions
+48 -2
View File
@@ -204,7 +204,30 @@
</div>
</div>
<div style="background:rgba(0,0,0,0.3); padding:0.75rem; border-radius:var(--radius-sm); font-size:0.9rem; margin-bottom:0.75rem; white-space:pre-wrap;">{{ q.original_text }}</div>
<div class="markdown-view-container" data-markdown-view style="margin-bottom:0.75rem;">
<div class="markdown-view-header" style="margin-bottom:0.4rem;">
<div class="markdown-view-actions">
<div class="markdown-toggle-pill">
<button type="button" class="btn-toggle-view active" data-view="formatted" title="Formatted View">
<span>👁️ Formatted</span>
</button>
<button type="button" class="btn-toggle-view" data-view="code" title="Code / Raw View">
<span>💻 Code</span>
</button>
</div>
<button type="button" class="btn-copy-markdown" onclick="copyMarkdownFromContainer(this)" title="Copy text">
<span>📋 Copy</span>
</button>
</div>
</div>
<div class="markdown-view-body" style="background:rgba(0,0,0,0.3); padding:0.75rem; border-radius:var(--radius-sm); border:1px solid var(--border-glass); font-size:0.9rem;">
<div class="markdown-formatted markdown-body"></div>
<div class="markdown-code" style="display:none; background:transparent; border:none; padding:0; margin:0;">
<pre style="margin:0; background:transparent; border:none; padding:0; line-height:1.6;"><code>{{ q.original_text }}</code></pre>
</div>
<textarea class="raw-markdown-source" style="display:none;">{{ q.original_text }}</textarea>
</div>
</div>
<div>
<h5 style="font-size:0.85rem; color:var(--text-secondary); margin-bottom:0.4rem;">Flagged URLs:</h5>
@@ -262,7 +285,30 @@
</div>
</div>
<div style="background:rgba(0,0,0,0.3); padding:0.75rem; border-radius:var(--radius-sm); font-size:0.88rem; color:var(--text-secondary); white-space:pre-wrap;">{{ t.original_text }}</div>
<div class="markdown-view-container" data-markdown-view>
<div class="markdown-view-header" style="margin-bottom:0.4rem;">
<div class="markdown-view-actions">
<div class="markdown-toggle-pill">
<button type="button" class="btn-toggle-view active" data-view="formatted" title="Formatted View">
<span>👁️ Formatted</span>
</button>
<button type="button" class="btn-toggle-view" data-view="code" title="Code / Raw View">
<span>💻 Code</span>
</button>
</div>
<button type="button" class="btn-copy-markdown" onclick="copyMarkdownFromContainer(this)" title="Copy text">
<span>📋 Copy</span>
</button>
</div>
</div>
<div class="markdown-view-body" style="background:rgba(0,0,0,0.3); padding:0.75rem; border-radius:var(--radius-sm); border:1px solid var(--border-glass); font-size:0.88rem; color:var(--text-secondary);">
<div class="markdown-formatted markdown-body"></div>
<div class="markdown-code" style="display:none; background:transparent; border:none; padding:0; margin:0;">
<pre style="margin:0; background:transparent; border:none; padding:0; line-height:1.6;"><code>{{ t.original_text }}</code></pre>
</div>
<textarea class="raw-markdown-source" style="display:none;">{{ t.original_text }}</textarea>
</div>
</div>
</div>
{% endfor %}
</div>