mateclaw/mateclaw-ui/src/views
matevip b4697f2806 fix(cron): post-deploy bug bundle — flakiness, scheduler, channel UI
User-reported field issues + a deeper code audit revealed multiple
overlapping bugs in the prior cron-channel delivery change. This fixes
all six.

#1 — Concurrency race on ToolExecutionExecutor (root cause of 'sometimes
   succeeds, sometimes fails' tool calls). The volatile instance fields
   currentRequesterId / currentWorkspaceBasePath / currentChatOrigin
   were shared by every conversation routed through the same per-agent
   executor; one user mid-build-loop while another's execute()
   overwrote the field would cross-contaminate the captured values into
   PreparedToolCall. Fix: kill the instance fields, thread
   origin/requester/workspace as method params straight into
   PreparedToolCall snapshot. Comment pins the rule so it cannot regress.

#2 — CHAT_ORIGIN missing from KeyStrategyFactory (latent timebomb,
   masked by spring-ai-alibaba-graph-core's non-filtering builder path).
   Without an addStrategy registration, multi-node state merges in long
   ReAct / Plan-Execute loops drop the key, ActionNode reads
   ChatOrigin.EMPTY, and the cron persists with channel_id=NULL. Also
   caught 4 more keys that were latently unregistered:
   WORKSPACE_BASE_PATH, STOP_REQUESTED, RETURN_DIRECT_TRIGGERED,
   DIRECT_TOOL_OUTPUTS. All five now registered in both ReAct and
   Plan-Execute factories.

#3 — CronJobs UI didn't surface channel binding. CronJobDTO carried
   channelId / deliveryConfig but the list page never rendered them.
   Added: (a) 'channel' column on list page, (b) channel + targetId
   rows in the detail modal, (c) backend batch-loads channel names via
   ChannelMapper.selectBatchIds so the column shows the human-readable
   name, (d) i18n keys (zh + en), (e) channelName field on TS CronJob
   type.

#4a — DingTalk targetId expiry. ChannelChatOriginFactory.resolveTargetId
   used to prefer ChannelMessage.replyToken which for DingTalk encodes
   a sessionWebhook URL that expires ~90 minutes after the inbound
   message. Cron persisted with that webhook then dies with 401/403 and
   marks NOT_DELIVERED forever. Fix: prefer the stable chatId, fall
   back to senderId — both work indefinitely via DingTalk's Robot API.

#4b — Scheduler pool exhaustion under long LLM. CronJobService's
   ThreadPoolTaskScheduler ran with poolSize=4 AND the LLM call lived
   on the scheduler thread. Four concurrent crons saturated the pool
   and the 5th silently missed its tick. Fix: keep scheduler tiny (it
   just fires triggers) and offload runAgent to a dedicated
   virtual-thread executor (cron-execute-* threads). LLM workload is
   I/O-bound — virtual threads scale to thousands at trivial cost.

#5 — Minor latent bugs:
   - AbstractCronResultDelivery.claimRun used .in(... 'NONE','PENDING',null),
     but SQL IN never matches NULL. Rewrote as IS NULL OR IN
     (NONE,PENDING) so legacy pre-V57 rows can still claim.
   - CronDeliveryListener.onCompletedRaw was an empty @EventListener
     with a wrong-headed comment about test fallbackExecution. Removed.
   - CronJobTool.resolveAgentId silently returned 1L when origin
     lacked an agentId — would silently bind to whatever agent #1
     happens to be. Replaced with explicit error so wiring bugs surface
     immediately instead of producing scheduled-but-never-runs crons.

State-key registration guard. New StateKeyRegistrationCoverageTest
scans MateClawStateKeys via reflection and parses
AgentGraphBuilder.java to extract every
.addStrategy(MateClawStateKeys.X, ...). Asserts every non-_NODE
constant appears in at least one factory. Caught the 4 unregistered
keys above on first run; will catch any future 'forgot to register'
regression.

Tests: 33 unit/arch tests + 27 regression in touched areas — all green.
Vue typecheck clean.

Refs: #25, #16
2026-04-28 21:45:07 +08:00
..
Doctor fix(ui): prevent modals from closing on backdrop click 2026-04-11 18:06:48 +08:00
layout refactor(ui): split useProviders into 5 single-responsibility composables 2026-04-28 15:01:14 +08:00
Memory feat(memory): enable Memory Browser tab + audit fixes 2026-04-21 15:28:31 +08:00
Onboarding feat(ux): Phase 1 — onboarding, doctor, templates, navigation convergence 2026-04-09 00:32:35 +08:00
Security feat(auth): password change dialog + workspace member provisioning improvements 2026-04-17 00:11:10 +08:00
Settings feat(llm): enabled column for providers + Add Provider drawer 2026-04-28 15:03:40 +08:00
Wiki feat(wiki): download original raw material file 2026-04-26 20:46:52 +08:00
AgentContext.vue fix(wiki): smaller batch-create + resume button for partial generation 2026-04-26 18:42:27 +08:00
Agents.vue feat(skill-market): paginated skill list with search and frosted-glass UI 2026-04-24 06:55:19 +08:00
Channels.vue perf(channels): split Channels.vue, lazy-load modal, async locales, keep-alive route 2026-04-28 11:08:36 +08:00
ChatConsole.vue fix(chat): surface SSE error in retry card and stop poll from wiping local-only failed turn 2026-04-28 00:16:14 +08:00
CronJobs.vue fix(cron): post-deploy bug bundle — flakiness, scheduler, channel UI 2026-04-28 21:45:07 +08:00
Dashboard.vue refactor(ux): simplify interactions and humanize UI with Jobs-inspired review 2026-04-09 20:56:50 +08:00
Datasources.vue refactor(ui): minimalist login redesign, MCP fixes, Flyway upgrade compatibility 2026-04-11 23:01:08 +08:00
Login.vue feat(auth): password change dialog + workspace member provisioning improvements 2026-04-17 00:11:10 +08:00
McpServers.vue refactor(ui): minimalist login redesign, MCP fixes, Flyway upgrade compatibility 2026-04-11 23:01:08 +08:00
Plugins.vue feat(plugin): Plugin SDK + UI layout improvements 2026-04-13 18:38:03 +08:00
Sessions.vue feat(ui): add mobile responsive layout and fix hardcoded i18n strings 2026-04-05 18:56:41 +08:00
SkillMarket.vue feat(skill-market): bilingual skill display names (nameZh / nameEn) 2026-04-24 06:55:20 +08:00
TokenUsage.vue feat(ui): unify workspace and platform console surfaces 2026-04-09 19:48:17 +08:00
Tools.vue fix(ui): prevent modals from closing on backdrop click 2026-04-11 18:06:48 +08:00