mirror of
https://github.com/dataelement/bisheng.git
synced 2026-09-21 12:43:36 +08:00
fix(linsight): thread task-mode skill selection to the submit
Follow-up to the None≡[] skill gate: with skills now strictly opt-in, the
daily task-mode path (ChatView → useAiChat → unified /chat/completions →
_to_linsight_submit) exposed a latent gap — it never carried the picked
skills, so the stored SV had skills=None and NOTHING was materialized. The
picker looked broken ("workspace has no such skill file"). Previously this
was masked because None loaded every enabled skill.
Thread the selection end-to-end:
- APIChatCompletion gains `skills` (Track H); _to_linsight_submit maps it
onto the linsight submit schema (None/[] = no skills, opt-in list = those).
- useAiChat sends the picked skill names (taskModeSkillsState('new')) on
task-mode turns only; the daily chain ignores the field.
- tests: _to_linsight_submit forwards a selection / stays None when absent.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
58325411d1
commit
97d43716a2
@@ -100,6 +100,13 @@ class APIChatCompletion(BaseModel):
|
||||
# daily chain; the turn still lives in the same conversation (chat_id).
|
||||
task_mode: bool | None = False
|
||||
|
||||
# --- F035 Track H: per-turn selected skill names (task mode only) ---
|
||||
# The skills the user picked in the daily task-mode input. Threaded onto the
|
||||
# linsight submit schema by ``_to_linsight_submit``; ``None``/``[]`` both mean
|
||||
# "no skills this turn" (skills are opt-in, see materialize_session_skills).
|
||||
# Ignored on the plain daily chain.
|
||||
skills: list[str] | None = None
|
||||
|
||||
# --- Preserved (new code-path also honours use_knowledge_base / files) ---
|
||||
use_knowledge_base: UseKnowledgeBaseParam | None = None
|
||||
files: list[dict] | None = None
|
||||
|
||||
@@ -2031,4 +2031,7 @@ def _to_linsight_submit(data: APIChatCompletion):
|
||||
model=data.model or None,
|
||||
files=submit_files,
|
||||
tools=submit_tools,
|
||||
# F035 Track H: thread the daily task-mode skill picker onto the submit so
|
||||
# only the user's explicit selection is materialized (None/[] = no skills).
|
||||
skills=data.skills,
|
||||
)
|
||||
|
||||
@@ -106,3 +106,28 @@ def test_to_linsight_submit_no_knowledge_defaults_false():
|
||||
|
||||
assert submit.org_knowledge_enabled is False
|
||||
assert submit.personal_knowledge_enabled is False
|
||||
|
||||
|
||||
def test_to_linsight_submit_forwards_selected_skills():
|
||||
"""The daily task-mode skill picker must reach the submit schema.
|
||||
|
||||
Regression: _to_linsight_submit dropped skills entirely, so the stored SV had
|
||||
skills=None. That was masked while None meant "load all enabled skills"; once
|
||||
None means "no skills", an explicit pick that never arrived silently loaded
|
||||
nothing — the picker looked broken.
|
||||
"""
|
||||
data = APIChatCompletion(
|
||||
clientTimestamp="t", conversationId="c", model="m", text="hi", task_mode=True, skills=["morning-report"]
|
||||
)
|
||||
|
||||
submit = chat_service._to_linsight_submit(data)
|
||||
|
||||
assert submit.skills == ["morning-report"]
|
||||
|
||||
|
||||
def test_to_linsight_submit_no_skills_stays_none():
|
||||
data = APIChatCompletion(clientTimestamp="t", conversationId="c", model="m", text="hi", task_mode=True)
|
||||
|
||||
submit = chat_service._to_linsight_submit(data)
|
||||
|
||||
assert submit.skills is None
|
||||
|
||||
@@ -17,7 +17,7 @@ import useAiChatSSE, { type SSESubmission } from "~/hooks/useAiChatSSE";
|
||||
import { useGetBsConfig } from "~/hooks/queries/data-provider";
|
||||
import { useLinsightManager } from "~/hooks/useLinsightManager";
|
||||
import { startLinsight, getLinsightSessionVersionList } from "~/api/linsight";
|
||||
import { SopStatus } from "~/store/linsight";
|
||||
import { SopStatus, taskModeSkillsState } from "~/store/linsight";
|
||||
|
||||
const NO_PARENT = "00000000-0000-0000-0000-000000000000";
|
||||
|
||||
@@ -46,6 +46,10 @@ export default function useAiChat(initialConversationId: string = "new", isLings
|
||||
// emits the new ChatResponse SSE format). Empty array keeps us on the
|
||||
// legacy flow so existing tests / old clients aren't disrupted.
|
||||
const [selectedAgentTools] = useRecoilState(store.selectedAgentTools);
|
||||
// F035 Track H: skills picked in the daily task-mode input live in the shared
|
||||
// 'new' atom (AiChatInput keys the picker there). Threaded onto the task-mode
|
||||
// turn's submit payload so the user's explicit selection is what gets loaded.
|
||||
const [dailyTaskSkills] = useRecoilState(taskModeSkillsState('new'));
|
||||
// Admin-level org-KB toggle. Knowledge spaces remain available even when
|
||||
// the org knowledge base feature is disabled, so we only strip org ids.
|
||||
const { data: bsConfig } = useGetBsConfig();
|
||||
@@ -244,6 +248,10 @@ export default function useAiChat(initialConversationId: string = "new", isLings
|
||||
// F035 Track J (TJ-6): route this turn to the linsight task kernel
|
||||
// via the SAME unified entry. Backend replies with a handoff event.
|
||||
task_mode: taskMode,
|
||||
// F035 Track H: send the picked skill names on task-mode turns so
|
||||
// the backend materializes exactly those (empty = none). Omitted
|
||||
// outside task mode (the daily chain ignores it).
|
||||
skills: taskMode ? dailyTaskSkills.map((s) => s.name) : [],
|
||||
};
|
||||
|
||||
// Correlation key for the user (question) message. Starts as the
|
||||
@@ -609,7 +617,7 @@ export default function useAiChat(initialConversationId: string = "new", isLings
|
||||
setIsStreaming(true);
|
||||
setSseSubmission(submission);
|
||||
},
|
||||
[conversationId, isStreaming, chatModel, selectedOrgKbs, searchType, selectedAgentTools, isLingsi, createLinsight, updateLinsight, localize, queryClient]
|
||||
[conversationId, isStreaming, chatModel, selectedOrgKbs, searchType, selectedAgentTools, dailyTaskSkills, isLingsi, createLinsight, updateLinsight, localize, queryClient]
|
||||
);
|
||||
|
||||
// --- Stop generating ---
|
||||
|
||||
Reference in New Issue
Block a user