feat(timeline): add live filter, actor chips, group headers, copy button, source toggle, count badge
- Live search/filter bar: filters events by keyword across event, actor, source_excerpt, date - Actor filter chips: click to filter by actor, multi-select, teal active state - Year/month group headers when sorted chronologically (── 2023 ──, Mar 2024 ──) - Per-event copy button (hover-revealed 📋): copies "date · actor · event" to clipboard - "Hide/show sources" toggle: collapses all source excerpts without re-rendering - Count badge: "23 events · 3 actors · 2022–2025" above the list - applyTimelineFilters() unifies sort + actor + text filters in one re-render pass - CSV export now includes end_date column - Reset all filter state on each new run Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -65,8 +65,9 @@ try {
|
||||
if (mb_strlen($advocateRole, 'UTF-8') > 200) {
|
||||
throw new DbnToolsHttpException('advocate_role is too long.', 422, 'advocate_role_too_long');
|
||||
}
|
||||
$priorContext = is_array($input['prior_context'] ?? null) ? $input['prior_context'] : null;
|
||||
$branchNotes = mb_substr(trim((string)($input['branch_notes'] ?? '')), 0, 1000, 'UTF-8');
|
||||
$priorContext = is_array($input['prior_context'] ?? null) ? $input['prior_context'] : null;
|
||||
$branchNotes = mb_substr(trim((string)($input['branch_notes'] ?? '')), 0, 1000, 'UTF-8');
|
||||
$subQsOverride = is_array($input['sub_questions_override'] ?? null) ? $input['sub_questions_override'] : [];
|
||||
|
||||
if (mb_strlen($seedQuery, 'UTF-8') > 4000) {
|
||||
throw new DbnToolsHttpException('Query is too long.', 422, 'query_too_long');
|
||||
@@ -125,7 +126,8 @@ try {
|
||||
$emit,
|
||||
$advocateRole,
|
||||
$priorContext,
|
||||
$branchNotes
|
||||
$branchNotes,
|
||||
$subQsOverride
|
||||
);
|
||||
|
||||
$result['ok'] = true;
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../includes/bootstrap.php';
|
||||
require_once __DIR__ . '/../includes/DeepResearchAgent.php';
|
||||
|
||||
dbnToolsRequireMethod('POST');
|
||||
dbnToolsRequireAuth();
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('Cache-Control: no-store');
|
||||
|
||||
try {
|
||||
$raw = file_get_contents('php://input');
|
||||
if ($raw === false || strlen($raw) > 20000) {
|
||||
throw new DbnToolsHttpException('Request body unreadable or too large.', 413, 'body_too_large');
|
||||
}
|
||||
$input = json_decode((string)$raw, true);
|
||||
if (!is_array($input)) {
|
||||
throw new DbnToolsHttpException('Request body must be valid JSON.', 400, 'invalid_json');
|
||||
}
|
||||
|
||||
$seedQuery = mb_substr(trim((string)($input['query'] ?? '')), 0, 4000, 'UTF-8');
|
||||
$pastedText = mb_substr(trim((string)($input['paste_text'] ?? '')), 0, 64000, 'UTF-8');
|
||||
$engine = (string)($input['engine'] ?? 'azure_mini');
|
||||
$language = dbnToolsNormalizeLanguage($input['language'] ?? 'en');
|
||||
$controls = is_array($input['controls'] ?? null) ? $input['controls'] : [];
|
||||
$advocateRole = mb_substr(trim((string)($input['advocate_role'] ?? '')), 0, 200, 'UTF-8');
|
||||
$priorContext = is_array($input['prior_context'] ?? null) ? $input['prior_context'] : null;
|
||||
$branchNotes = mb_substr(trim((string)($input['branch_notes'] ?? '')), 0, 1000, 'UTF-8');
|
||||
|
||||
if ($seedQuery === '' && $pastedText === '') {
|
||||
throw new DbnToolsHttpException('Provide a query or pasted text.', 422, 'missing_seed');
|
||||
}
|
||||
|
||||
$result = (new DbnDeepResearchAgent())->generateSubQPreview(
|
||||
$seedQuery,
|
||||
$pastedText,
|
||||
$engine,
|
||||
$language,
|
||||
$controls,
|
||||
$advocateRole,
|
||||
$priorContext,
|
||||
$branchNotes
|
||||
);
|
||||
|
||||
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
} catch (DbnToolsHttpException $e) {
|
||||
http_response_code($e->getCode() ?: 500);
|
||||
echo json_encode(['ok' => false, 'code' => $e->getSlug(), 'message' => $e->getMessage()]);
|
||||
} catch (Throwable $e) {
|
||||
error_log('DBN generate-subq error: ' . $e->getMessage());
|
||||
http_response_code(500);
|
||||
echo json_encode(['ok' => false, 'code' => 'internal_error', 'message' => 'Could not generate sub-questions.']);
|
||||
}
|
||||
Reference in New Issue
Block a user