- Ask's supplier loader didn't pass date_received, so supplier_balances
and the supplier_balance dataset crashed
- supplier_balances takes a period (thisMonth, thisWeek, month1-3) and
returns what was received from each supplier in it (payable)
- PocketBase's space-separated dates dropped deliveries on the 1st from
period filters, including the Suppliers page's Payable KPI
- The PDF route falls back to the answer text when a saved report has
no sections (older format), instead of a 500
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GET /api/ask/messages/[id]/pdf builds a PDF for one stored assistant
row: its structured make_pdf_report document when `parsed.pdf` is set,
otherwise its own markdown (headings/paragraphs/lists/GFM tables, with
[[chart:id]]/[[image:id]] tokens resolved against that message's own
stored charts and any referenced generated-image rows). 404s for a
missing message, a non-assistant row, or a thread owned by someone
else — same "not found, not forbidden" reasoning as the existing
thread routes, since there are no logins yet. Returns
application/pdf with Content-Disposition: attachment; filename="ask-<slug>-<date>.pdf".
The chat stream's "done" event now carries the persisted assistant
row's own id (messageId), which the browser needs to ask this route
for a PDF — see the next commit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
file_change_request (tools-actions.ts) logs an ask_log row
(type "request", status "open") for a change to the app itself — a new
page, column, button or report layout — distinct from propose_changes,
which changes data; the prompt now routes between the two.
list_change_requests (tools.ts, read-only) lists them, which the
existing MCP server picks up automatically since it iterates the whole
tools array. /dashboard/change-requests lists and re-statuses them
(open/planned/done/declined) via new GET/PATCH routes under
/api/ask/change-requests, linked from the sidebar under Ask.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds src/lib/agent/memory.ts (remember/forget/listMemories, dedupe by
normalised text, formatMemoriesForPrompt) and wires it in: a
"## What you remember" system-prompt section, the remember/forget/
list_memories tools (src/lib/agent/tools-actions.ts, a per-request
factory since these need the actor unlike the static read-only tool
set), a REST view for the UI (/api/ask/memories), and a Memory drawer
in chat-view.tsx (Mine / Shared with everyone, add, delete).
Adjusted src/lib/agent/read-only.test.ts: its blanket "no mutation
calls under src/lib/agent" contract now allowlists the specific write
seams the plan designates (memory.ts here; tools-actions.ts, gateway.ts
and images.ts to follow) instead of forbidding every file, since
memories/requests are specified to bypass the gateway and write
directly.
Live browser check skipped: ask_log doesn't exist yet in the target
PocketBase (pending the user's --apply of Task 1's schema). Covered by
mocked unit tests instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the "Who's using Ask?" picker (GET /api/ask/users), actor
resolution via x-ask-user (src/lib/agent/context.ts), and thread
persistence (src/lib/chat/threads.ts, /api/chat/threads routes).
/api/chat now accepts { threadId?, message, display?, images? } and
persists each turn as its own append-only ask_messages row; the old
{ history } body still works for one release. chat-view.tsx gained the
picker, a thread sidebar (new/select/rename/archive), and ?thread=<id>
in the URL.
Live browser check skipped: ask_threads/ask_messages/ask_log don't
exist yet in the target PocketBase (Task 1's schema is dry-run only,
pending the user's --apply). Covered by mocked unit tests instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>