From 93a155245b6bf748fa25036cd86b951fa441996a Mon Sep 17 00:00:00 2001 From: aiyakitori <16633065+chiang-daniel@users.noreply.github.com> Date: Tue, 21 Apr 2026 15:15:19 -0700 Subject: [PATCH 1/3] force reload on deeplink --- .../run_config/[run_config_id]/+page.svelte | 7 +++- .../[task_id]/clone/[prompt_id]/+page.svelte | 4 +- .../[task_id]/saved/[prompt_id]/+page.svelte | 39 ++++++++++++++++--- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/app/web_ui/src/routes/(app)/optimize/[project_id]/[task_id]/run_config/[run_config_id]/+page.svelte b/app/web_ui/src/routes/(app)/optimize/[project_id]/[task_id]/run_config/[run_config_id]/+page.svelte index 4eb70c452..819f6a11e 100644 --- a/app/web_ui/src/routes/(app)/optimize/[project_id]/[task_id]/run_config/[run_config_id]/+page.svelte +++ b/app/web_ui/src/routes/(app)/optimize/[project_id]/[task_id]/run_config/[run_config_id]/+page.svelte @@ -49,8 +49,13 @@ load_available_tools(project_id) await Promise.all([load_model_info(), load_available_models()]) await Promise.all([ + // Prompts are only used for display-name lookups in + // getRunConfigUiProperties; the normal cache is fine. load_task_prompts(project_id, task_id), - load_task_run_configs(project_id, task_id), + // Force-refresh so deeplinks to run configs created mid-chat + // (which bypass the store's save helpers) are picked up on + // direct load. + load_task_run_configs(project_id, task_id, true), ]) task = await load_task(project_id, task_id) } catch (e) { diff --git a/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/clone/[prompt_id]/+page.svelte b/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/clone/[prompt_id]/+page.svelte index 720506843..16756fba9 100644 --- a/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/clone/[prompt_id]/+page.svelte +++ b/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/clone/[prompt_id]/+page.svelte @@ -27,7 +27,9 @@ onMount(async () => { try { - await load_task_prompts(project_id, task_id) + // Force-refresh so deeplinks to prompts created mid-chat (which + // bypass the store's save helpers) are picked up on direct load. + await load_task_prompts(project_id, task_id, true) const task_prompts = $prompts_by_task_composite_id[ get_task_composite_id(project_id, task_id) diff --git a/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/saved/[prompt_id]/+page.svelte b/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/saved/[prompt_id]/+page.svelte index 7bb6fb7e4..cf6ea7d9e 100644 --- a/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/saved/[prompt_id]/+page.svelte +++ b/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/saved/[prompt_id]/+page.svelte @@ -1,10 +1,17 @@
@@ -78,6 +69,8 @@
{loading_error.getMessage() || "An unknown error occurred"}
+ {:else if !source_prompt} +
Source prompt not found.
{:else} import { page } from "$app/stores" - import { current_task, get_task_composite_id } from "$lib/stores" + import { get_task_composite_id } from "$lib/stores" import { load_task_prompts, prompts_by_task_composite_id, @@ -22,7 +22,6 @@ description: `Saved prompt detail for prompt ID ${prompt_id} in project ID ${project_id}, task ID ${task_id}. Prompt name: ${prompt_model?.name ?? "[loading]"}. Shows prompt content, version history, and options to clone or edit.`, }) - let prompt_model: ApiPrompt | null = null let loading = true let loading_error: KilnError | null = null @@ -31,12 +30,6 @@ // Force-refresh so deeplinks to prompts created mid-chat (which // bypass the store's save helpers) are picked up on direct load. await load_task_prompts(project_id, task_id, true) - const task_prompts = - $prompts_by_task_composite_id[ - get_task_composite_id(project_id, task_id) - ] - prompt_model = - task_prompts?.prompts.find((p) => p.id === prompt_id) ?? null } catch (e) { loading_error = createKilnError(e) } finally { @@ -44,6 +37,11 @@ } }) + $: prompt_model = + ($prompts_by_task_composite_id[ + get_task_composite_id(project_id, task_id) + ]?.prompts.find((p) => p.id === prompt_id) as ApiPrompt | undefined) ?? null + let prompt_props: Record = {} $: { prompt_props = Object.fromEntries( @@ -105,12 +103,6 @@
{loading_error.getMessage() || "Failed to load prompt."}
- {:else if $current_task?.id != task_id} -
- This link is to another task's prompt. Either select that task in the - sidebar, or click 'Prompts' in the sidebar to load the current task's - prompts. -
{:else if prompt_model}
From e041b19981626a6dc93308752c28109abcee8fda Mon Sep 17 00:00:00 2001 From: aiyakitori <16633065+chiang-daniel@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:00:12 -0700 Subject: [PATCH 3/3] use .ts file with load --- .../run_config/[run_config_id]/+page.svelte | 7 +--- .../run_config/[run_config_id]/+page.ts | 17 +++++++++ .../[task_id]/clone/[prompt_id]/+page.svelte | 35 ++++++++++-------- .../[task_id]/clone/[prompt_id]/+page.ts | 13 +++++++ .../[task_id]/saved/[prompt_id]/+page.svelte | 37 ++----------------- .../[task_id]/saved/[prompt_id]/+page.ts | 13 +++++++ 6 files changed, 68 insertions(+), 54 deletions(-) diff --git a/app/web_ui/src/routes/(app)/optimize/[project_id]/[task_id]/run_config/[run_config_id]/+page.svelte b/app/web_ui/src/routes/(app)/optimize/[project_id]/[task_id]/run_config/[run_config_id]/+page.svelte index 819f6a11e..4eb70c452 100644 --- a/app/web_ui/src/routes/(app)/optimize/[project_id]/[task_id]/run_config/[run_config_id]/+page.svelte +++ b/app/web_ui/src/routes/(app)/optimize/[project_id]/[task_id]/run_config/[run_config_id]/+page.svelte @@ -49,13 +49,8 @@ load_available_tools(project_id) await Promise.all([load_model_info(), load_available_models()]) await Promise.all([ - // Prompts are only used for display-name lookups in - // getRunConfigUiProperties; the normal cache is fine. load_task_prompts(project_id, task_id), - // Force-refresh so deeplinks to run configs created mid-chat - // (which bypass the store's save helpers) are picked up on - // direct load. - load_task_run_configs(project_id, task_id, true), + load_task_run_configs(project_id, task_id), ]) task = await load_task(project_id, task_id) } catch (e) { diff --git a/app/web_ui/src/routes/(app)/optimize/[project_id]/[task_id]/run_config/[run_config_id]/+page.ts b/app/web_ui/src/routes/(app)/optimize/[project_id]/[task_id]/run_config/[run_config_id]/+page.ts index 9786e09d9..9b99ed8ea 100644 --- a/app/web_ui/src/routes/(app)/optimize/[project_id]/[task_id]/run_config/[run_config_id]/+page.ts +++ b/app/web_ui/src/routes/(app)/optimize/[project_id]/[task_id]/run_config/[run_config_id]/+page.ts @@ -1 +1,18 @@ +import { load_task_prompts } from "$lib/stores/prompts_store" +import { load_task_run_configs } from "$lib/stores/run_configs_store" + export const prerender = false + +// Runs on every navigation (including same-route param changes), so the stores +// are always fresh when the component reads them — fixes stale-data bug when +// navigating between detail pages for entities created mid-session. +export async function load({ + params, +}: { + params: { project_id: string; task_id: string } +}) { + await Promise.all([ + load_task_run_configs(params.project_id, params.task_id, true), + load_task_prompts(params.project_id, params.task_id, true), + ]) +} diff --git a/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/clone/[prompt_id]/+page.svelte b/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/clone/[prompt_id]/+page.svelte index e46db7a5d..720506843 100644 --- a/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/clone/[prompt_id]/+page.svelte +++ b/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/clone/[prompt_id]/+page.svelte @@ -19,30 +19,37 @@ description: `Clone prompt ID ${prompt_id} for project ID ${project_id}, task ID ${task_id}.`, }) + let initial_prompt_name = "" + let initial_prompt = "" + let initial_chain_of_thought_instructions: string | null = null let loading = true let loading_error: KilnError | null = null onMount(async () => { try { - // Force-refresh so deeplinks to prompts created mid-chat (which - // bypass the store's save helpers) are picked up on direct load. - await load_task_prompts(project_id, task_id, true) + await load_task_prompts(project_id, task_id) + const task_prompts = + $prompts_by_task_composite_id[ + get_task_composite_id(project_id, task_id) + ] + const source_prompt = task_prompts?.prompts.find( + (p) => p.id === prompt_id, + ) + + if (!source_prompt) { + throw new KilnError("Source prompt not found.") + } + + initial_prompt_name = `Copy of ${source_prompt.name}` + initial_prompt = source_prompt.prompt + initial_chain_of_thought_instructions = + source_prompt.chain_of_thought_instructions || null } catch (e) { loading_error = createKilnError(e) } finally { loading = false } }) - - $: source_prompt = - $prompts_by_task_composite_id[ - get_task_composite_id(project_id, task_id) - ]?.prompts.find((p) => p.id === prompt_id) ?? null - - $: initial_prompt_name = source_prompt ? `Copy of ${source_prompt.name}` : "" - $: initial_prompt = source_prompt?.prompt ?? "" - $: initial_chain_of_thought_instructions = - source_prompt?.chain_of_thought_instructions ?? null
@@ -69,8 +76,6 @@
{loading_error.getMessage() || "An unknown error occurred"}
- {:else if !source_prompt} -
Source prompt not found.
{:else} import { page } from "$app/stores" import { get_task_composite_id } from "$lib/stores" - import { - load_task_prompts, - prompts_by_task_composite_id, - } from "$lib/stores/prompts_store" + import { prompts_by_task_composite_id } from "$lib/stores/prompts_store" import AppPage from "../../../../../app_page.svelte" import Output from "$lib/ui/output.svelte" import { formatDate } from "$lib/utils/formatters" import EditDialog from "$lib/ui/edit_dialog.svelte" - import { onMount } from "svelte" - import { KilnError, createKilnError } from "$lib/utils/error_handlers" - import type { ApiPrompt } from "$lib/types" import { agentInfo } from "$lib/agent" $: project_id = $page.params.project_id! @@ -22,25 +16,10 @@ description: `Saved prompt detail for prompt ID ${prompt_id} in project ID ${project_id}, task ID ${task_id}. Prompt name: ${prompt_model?.name ?? "[loading]"}. Shows prompt content, version history, and options to clone or edit.`, }) - let loading = true - let loading_error: KilnError | null = null - - onMount(async () => { - try { - // Force-refresh so deeplinks to prompts created mid-chat (which - // bypass the store's save helpers) are picked up on direct load. - await load_task_prompts(project_id, task_id, true) - } catch (e) { - loading_error = createKilnError(e) - } finally { - loading = false - } - }) - $: prompt_model = - ($prompts_by_task_composite_id[ + $prompts_by_task_composite_id[ get_task_composite_id(project_id, task_id) - ]?.prompts.find((p) => p.id === prompt_id) as ApiPrompt | undefined) ?? null + ]?.prompts.find((p) => p.id === prompt_id) ?? null let prompt_props: Record = {} $: { @@ -95,15 +74,7 @@ : []), ]} > - {#if loading} -
-
-
- {:else if loading_error} -
- {loading_error.getMessage() || "Failed to load prompt."} -
- {:else if prompt_model} + {#if prompt_model}
Prompt
diff --git a/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/saved/[prompt_id]/+page.ts b/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/saved/[prompt_id]/+page.ts index 9786e09d9..80eb9ae40 100644 --- a/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/saved/[prompt_id]/+page.ts +++ b/app/web_ui/src/routes/(app)/prompts/[project_id]/[task_id]/saved/[prompt_id]/+page.ts @@ -1 +1,14 @@ +import { load_task_prompts } from "$lib/stores/prompts_store" + export const prerender = false + +// Runs on every navigation (including same-route param changes), so the store +// is always fresh when the component reads it — fixes stale-data bug when +// navigating between detail pages for entities created mid-session. +export async function load({ + params, +}: { + params: { project_id: string; task_id: string } +}) { + await load_task_prompts(params.project_id, params.task_id, true) +}