@nextclaw/ui 0.11.13 → 0.11.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/assets/{ChannelsList-BlQD1VuM.js → ChannelsList-WmCqjuMG.js} +1 -1
- package/dist/assets/ChatPage-vfnUvEdN.js +37 -0
- package/dist/assets/{DocBrowser-DTww3NZc.js → DocBrowser-Cuds8S4N.js} +1 -1
- package/dist/assets/{LogoBadge-D0ogG1ut.js → LogoBadge-CiukNh5R.js} +1 -1
- package/dist/assets/{MarketplacePage-DTHw6n0X.js → MarketplacePage--cCya2vU.js} +1 -1
- package/dist/assets/{McpMarketplacePage-BikE0mBl.js → McpMarketplacePage-SYy23E4x.js} +1 -1
- package/dist/assets/{ModelConfig-CvM__Pz1.js → ModelConfig-D4Nd4HWX.js} +1 -1
- package/dist/assets/{ProvidersList-DtZWZlL0.js → ProvidersList-k95kUPqD.js} +1 -1
- package/dist/assets/{RemoteAccessPage-E5fT1pem.js → RemoteAccessPage-XjDtIQV4.js} +1 -1
- package/dist/assets/{RuntimeConfig-DyZNiqYT.js → RuntimeConfig-BR4oBxQ-.js} +1 -1
- package/dist/assets/{SearchConfig-C1bhOCNX.js → SearchConfig-fJjFykmH.js} +1 -1
- package/dist/assets/{SecretsConfig-CYmy1Sqy.js → SecretsConfig-D7CxxH1q.js} +1 -1
- package/dist/assets/{SessionsConfig-DSlhPpIE.js → SessionsConfig-2hYobMkj.js} +1 -1
- package/dist/assets/{chat-session-display-D9YuDGe3.js → chat-session-display-BeoRHq9x.js} +1 -1
- package/dist/assets/index-DWrpxFk0.js +8 -0
- package/dist/assets/{label-C7Xd_hqz.js → label-C2uGecRa.js} +1 -1
- package/dist/assets/{page-layout-VxCaUcrD.js → page-layout-DICppNFk.js} +1 -1
- package/dist/assets/{popover-CC4znqAM.js → popover-DoacXI3f.js} +1 -1
- package/dist/assets/{security-config-7eVxJq8b.js → security-config-54LcQtst.js} +1 -1
- package/dist/assets/{skeleton-DhZRDdHm.js → skeleton-DjjQR4NY.js} +1 -1
- package/dist/assets/{status-dot-Bi7Ze-LS.js → status-dot-OjV8JCSV.js} +1 -1
- package/dist/assets/{switch-COBEivEX.js → switch-Dvd2FqUB.js} +1 -1
- package/dist/assets/{tabs-custom-B9j40wuu.js → tabs-custom-DlwuO0Gw.js} +1 -1
- package/dist/assets/{useConfirmDialog-N8nuxOq-.js → useConfirmDialog-BuB9l_2r.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +5 -5
- package/src/components/chat/adapters/chat-input-bar.adapter.test.ts +39 -0
- package/src/components/chat/adapters/chat-input-bar.adapter.ts +4 -1
- package/src/components/chat/adapters/chat-message.adapter.test.ts +40 -0
- package/src/components/chat/adapters/chat-message.adapter.ts +11 -0
- package/src/components/chat/adapters/chat-message.subagent-tool-card.ts +125 -0
- package/src/components/chat/containers/chat-input-bar.container.tsx +8 -10
- package/src/components/chat/ncp/NcpChatPage.tsx +18 -24
- package/src/components/config/README.md +1 -1
- package/src/lib/i18n.ts +0 -2
- package/dist/assets/ChatPage-DBvm558n.js +0 -37
- package/dist/assets/index-BBz4mi7g.js +0 -8
package/dist/index.html
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
8
|
<title>NextClaw</title>
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-DWrpxFk0.js"></script>
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/vendor-MCpnpiKt.js">
|
|
11
11
|
<link rel="stylesheet" crossorigin href="/assets/index-CfVmBgkf.css">
|
|
12
12
|
</head>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/ui",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.15",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"tailwind-merge": "^2.5.4",
|
|
29
29
|
"zod": "^3.23.8",
|
|
30
30
|
"zustand": "^5.0.2",
|
|
31
|
-
"@nextclaw/ncp": "0.4.1",
|
|
32
|
-
"@nextclaw/agent-chat-ui": "0.2.14",
|
|
33
|
-
"@nextclaw/ncp-react": "0.4.5",
|
|
34
31
|
"@nextclaw/agent-chat": "0.1.4",
|
|
35
|
-
"@nextclaw/ncp-http-agent-client": "0.3.
|
|
32
|
+
"@nextclaw/ncp-http-agent-client": "0.3.6",
|
|
33
|
+
"@nextclaw/ncp": "0.4.2",
|
|
34
|
+
"@nextclaw/agent-chat-ui": "0.2.14",
|
|
35
|
+
"@nextclaw/ncp-react": "0.4.6"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@testing-library/react": "^16.3.0",
|
|
@@ -175,4 +175,43 @@ describe('buildModelToolbarSelect', () => {
|
|
|
175
175
|
}
|
|
176
176
|
]);
|
|
177
177
|
});
|
|
178
|
+
|
|
179
|
+
it('preserves recent model order from newest to oldest', () => {
|
|
180
|
+
const select = buildModelToolbarSelect({
|
|
181
|
+
modelOptions: [
|
|
182
|
+
{
|
|
183
|
+
value: 'openai/gpt-5',
|
|
184
|
+
modelLabel: 'gpt-5',
|
|
185
|
+
providerLabel: 'OpenAI'
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
value: 'anthropic/claude-sonnet-4',
|
|
189
|
+
modelLabel: 'claude-sonnet-4',
|
|
190
|
+
providerLabel: 'Anthropic'
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
value: 'deepseek/deepseek-chat',
|
|
194
|
+
modelLabel: 'deepseek-chat',
|
|
195
|
+
providerLabel: 'DeepSeek'
|
|
196
|
+
}
|
|
197
|
+
],
|
|
198
|
+
recentModelValues: ['deepseek/deepseek-chat', 'openai/gpt-5', 'anthropic/claude-sonnet-4'],
|
|
199
|
+
selectedModel: 'openai/gpt-5',
|
|
200
|
+
isModelOptionsLoading: false,
|
|
201
|
+
hasModelOptions: true,
|
|
202
|
+
onValueChange: vi.fn(),
|
|
203
|
+
texts: {
|
|
204
|
+
modelSelectPlaceholder: 'Select model',
|
|
205
|
+
modelNoOptionsLabel: 'No models',
|
|
206
|
+
recentModelsLabel: 'Recent',
|
|
207
|
+
allModelsLabel: 'All models'
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
expect(select.groups?.[0]?.options.map((option) => option.value)).toEqual([
|
|
212
|
+
'deepseek/deepseek-chat',
|
|
213
|
+
'openai/gpt-5',
|
|
214
|
+
'anthropic/claude-sonnet-4'
|
|
215
|
+
]);
|
|
216
|
+
});
|
|
178
217
|
});
|
|
@@ -251,7 +251,10 @@ export function buildModelToolbarSelect(params: {
|
|
|
251
251
|
const resolvedModelOption = selectedModelOption ?? fallbackModelOption;
|
|
252
252
|
const resolvedValue = params.hasModelOptions ? resolvedModelOption?.value : undefined;
|
|
253
253
|
const recentValueSet = new Set(params.recentModelValues ?? []);
|
|
254
|
-
const
|
|
254
|
+
const modelOptionMap = new Map(params.modelOptions.map((option) => [option.value, option] as const));
|
|
255
|
+
const recentOptions = (params.recentModelValues ?? [])
|
|
256
|
+
.map((value) => modelOptionMap.get(value))
|
|
257
|
+
.filter((option): option is ChatModelRecord => Boolean(option));
|
|
255
258
|
const remainingOptions = params.modelOptions.filter((option) => !recentValueSet.has(option.value));
|
|
256
259
|
const optionGroups =
|
|
257
260
|
recentOptions.length > 0
|
|
@@ -141,6 +141,46 @@ it("maps tool lifecycle statuses into visible card state feedback", () => {
|
|
|
141
141
|
});
|
|
142
142
|
});
|
|
143
143
|
|
|
144
|
+
it("renders spawn tool cards from structured subagent status updates", () => {
|
|
145
|
+
const adapted = adapt([
|
|
146
|
+
{
|
|
147
|
+
id: "assistant-subagent",
|
|
148
|
+
role: "assistant",
|
|
149
|
+
parts: [
|
|
150
|
+
{
|
|
151
|
+
type: "tool-invocation",
|
|
152
|
+
toolInvocation: {
|
|
153
|
+
status: ToolInvocationStatus.RESULT,
|
|
154
|
+
toolCallId: "spawn-call-1",
|
|
155
|
+
toolName: "spawn",
|
|
156
|
+
args: '{"label":"Verifier","task":"Verify 1+1=2"}',
|
|
157
|
+
result: {
|
|
158
|
+
kind: "nextclaw.subagent_run",
|
|
159
|
+
runId: "subagent-1",
|
|
160
|
+
label: "Verifier",
|
|
161
|
+
task: "Verify 1+1=2",
|
|
162
|
+
status: "completed",
|
|
163
|
+
result: "Verified 1+1=2.",
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
] as unknown as ChatMessageSource[]);
|
|
170
|
+
|
|
171
|
+
expect(adapted[0]?.parts[0]).toMatchObject({
|
|
172
|
+
type: "tool-card",
|
|
173
|
+
card: {
|
|
174
|
+
toolName: "spawn",
|
|
175
|
+
summary: "label: Verifier · task: Verify 1+1=2",
|
|
176
|
+
output: "Verified 1+1=2.",
|
|
177
|
+
statusTone: "success",
|
|
178
|
+
statusLabel: "Completed",
|
|
179
|
+
titleLabel: "Tool Result",
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
144
184
|
it("maps non-standard roles back to the generic message role", () => {
|
|
145
185
|
const adapted = adapt([
|
|
146
186
|
{
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
summarizeToolArgs,
|
|
4
4
|
type ToolCard,
|
|
5
5
|
} from "@/lib/chat-message";
|
|
6
|
+
import { buildSubagentToolCard } from "@/components/chat/adapters/chat-message.subagent-tool-card";
|
|
6
7
|
import type {
|
|
7
8
|
ChatMessageRole,
|
|
8
9
|
ChatMessageViewModel,
|
|
@@ -386,6 +387,16 @@ export function adaptChatMessage(
|
|
|
386
387
|
if (assetFileView) {
|
|
387
388
|
return assetFileView;
|
|
388
389
|
}
|
|
390
|
+
const subagentToolCard = buildSubagentToolCard({
|
|
391
|
+
invocation,
|
|
392
|
+
texts: params.texts,
|
|
393
|
+
});
|
|
394
|
+
if (subagentToolCard) {
|
|
395
|
+
return {
|
|
396
|
+
type: "tool-card" as const,
|
|
397
|
+
card: buildToolCard(subagentToolCard, params.texts),
|
|
398
|
+
};
|
|
399
|
+
}
|
|
389
400
|
const statusView = resolveToolCardStatus({
|
|
390
401
|
status: invocation.status,
|
|
391
402
|
error: invocation.error,
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import {
|
|
2
|
+
stringifyUnknown,
|
|
3
|
+
summarizeToolArgs,
|
|
4
|
+
type ToolCard,
|
|
5
|
+
} from "@/lib/chat-message";
|
|
6
|
+
import type { ChatToolPartViewModel } from "@nextclaw/agent-chat-ui";
|
|
7
|
+
|
|
8
|
+
type ToolCardViewSource = ToolCard & {
|
|
9
|
+
statusTone: ChatToolPartViewModel["statusTone"];
|
|
10
|
+
statusLabel: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type SpawnToolInvocation = {
|
|
14
|
+
toolName: string;
|
|
15
|
+
toolCallId?: string;
|
|
16
|
+
args?: unknown;
|
|
17
|
+
result?: unknown;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type SubagentToolCardTexts = {
|
|
21
|
+
toolStatusRunningLabel: string;
|
|
22
|
+
toolStatusCompletedLabel: string;
|
|
23
|
+
toolStatusFailedLabel: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type SubagentRunResult = {
|
|
27
|
+
runId?: string;
|
|
28
|
+
label?: string;
|
|
29
|
+
task?: string;
|
|
30
|
+
status?: string;
|
|
31
|
+
result?: unknown;
|
|
32
|
+
message?: string;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
36
|
+
return typeof value === "object" && value !== null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function readOptionalString(value: unknown): string | null {
|
|
40
|
+
if (typeof value !== "string") {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const trimmed = value.trim();
|
|
44
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function readSubagentRunResult(value: unknown): SubagentRunResult | null {
|
|
48
|
+
if (!isRecord(value)) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
if (value.kind === "nextclaw.subagent_run") {
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
if (typeof value.runId === "string" && typeof value.status === "string") {
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function buildSubagentToolCard(params: {
|
|
61
|
+
invocation: SpawnToolInvocation;
|
|
62
|
+
texts: SubagentToolCardTexts;
|
|
63
|
+
}): ToolCardViewSource | null {
|
|
64
|
+
if (params.invocation.toolName !== "spawn") {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const subagentRun = readSubagentRunResult(params.invocation.result);
|
|
69
|
+
if (!subagentRun) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const detailParts = [
|
|
74
|
+
readOptionalString(subagentRun.label)
|
|
75
|
+
? `label: ${subagentRun.label?.trim()}`
|
|
76
|
+
: null,
|
|
77
|
+
readOptionalString(subagentRun.task)
|
|
78
|
+
? `task: ${subagentRun.task?.trim()}`
|
|
79
|
+
: null,
|
|
80
|
+
].filter((value): value is string => Boolean(value));
|
|
81
|
+
const normalizedStatus = readOptionalString(subagentRun.status)?.toLowerCase();
|
|
82
|
+
const output =
|
|
83
|
+
(typeof subagentRun.result !== "undefined"
|
|
84
|
+
? stringifyUnknown(subagentRun.result).trim()
|
|
85
|
+
: "") ||
|
|
86
|
+
readOptionalString(subagentRun.message) ||
|
|
87
|
+
undefined;
|
|
88
|
+
|
|
89
|
+
if (normalizedStatus === "failed") {
|
|
90
|
+
return {
|
|
91
|
+
kind: "result",
|
|
92
|
+
name: params.invocation.toolName,
|
|
93
|
+
detail: detailParts.join(" · ") || summarizeToolArgs(params.invocation.args),
|
|
94
|
+
text: output,
|
|
95
|
+
callId: params.invocation.toolCallId || undefined,
|
|
96
|
+
hasResult: Boolean(output),
|
|
97
|
+
statusTone: "error",
|
|
98
|
+
statusLabel: params.texts.toolStatusFailedLabel,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (normalizedStatus === "completed") {
|
|
103
|
+
return {
|
|
104
|
+
kind: "result",
|
|
105
|
+
name: params.invocation.toolName,
|
|
106
|
+
detail: detailParts.join(" · ") || summarizeToolArgs(params.invocation.args),
|
|
107
|
+
text: output,
|
|
108
|
+
callId: params.invocation.toolCallId || undefined,
|
|
109
|
+
hasResult: Boolean(output),
|
|
110
|
+
statusTone: "success",
|
|
111
|
+
statusLabel: params.texts.toolStatusCompletedLabel,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
kind: "result",
|
|
117
|
+
name: params.invocation.toolName,
|
|
118
|
+
detail: detailParts.join(" · ") || summarizeToolArgs(params.invocation.args),
|
|
119
|
+
text: output,
|
|
120
|
+
callId: params.invocation.toolCallId || undefined,
|
|
121
|
+
hasResult: Boolean(output),
|
|
122
|
+
statusTone: "running",
|
|
123
|
+
statusLabel: params.texts.toolStatusRunningLabel,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
@@ -108,14 +108,10 @@ export function ChatInputBarContainer() {
|
|
|
108
108
|
[snapshot.skillRecords, officialSkillBadgeLabel]
|
|
109
109
|
);
|
|
110
110
|
const modelRecords = useMemo(() => toModelRecords(snapshot.modelOptions), [snapshot.modelOptions]);
|
|
111
|
-
const recentModelValues =
|
|
112
|
-
() =>
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
minAvailableCount: CHAT_RECENT_MODELS_MIN_OPTIONS
|
|
116
|
-
}),
|
|
117
|
-
[modelRecords, snapshot.selectedModel]
|
|
118
|
-
);
|
|
111
|
+
const recentModelValues = chatRecentModelsManager.resolveVisible({
|
|
112
|
+
availableValues: modelRecords.map((option) => option.value),
|
|
113
|
+
minAvailableCount: CHAT_RECENT_MODELS_MIN_OPTIONS
|
|
114
|
+
});
|
|
119
115
|
|
|
120
116
|
const hasModelOptions = modelRecords.length > 0;
|
|
121
117
|
const isModelOptionsLoading = !snapshot.isProviderStateResolved && !hasModelOptions;
|
|
@@ -128,6 +124,8 @@ export function ChatInputBarContainer() {
|
|
|
128
124
|
: hasModelOptions
|
|
129
125
|
? t('chatInputPlaceholder')
|
|
130
126
|
: t('chatModelNoOptions');
|
|
127
|
+
const recentModelsLabel = language === 'zh' ? '最近选择' : 'Recent';
|
|
128
|
+
const allModelsLabel = language === 'zh' ? '全部模型' : 'All models';
|
|
131
129
|
|
|
132
130
|
const slashItems = useMemo(
|
|
133
131
|
() => buildChatSlashItems(skillRecords, slashQuery ?? '', slashTexts),
|
|
@@ -191,8 +189,8 @@ export function ChatInputBarContainer() {
|
|
|
191
189
|
texts: {
|
|
192
190
|
modelSelectPlaceholder: t('chatSelectModel'),
|
|
193
191
|
modelNoOptionsLabel: t('chatModelNoOptions'),
|
|
194
|
-
recentModelsLabel
|
|
195
|
-
allModelsLabel
|
|
192
|
+
recentModelsLabel,
|
|
193
|
+
allModelsLabel
|
|
196
194
|
}
|
|
197
195
|
}),
|
|
198
196
|
buildThinkingToolbarSelect({
|
|
@@ -70,7 +70,7 @@ export function NcpChatPage({ view }: ChatPageProps) {
|
|
|
70
70
|
const { sessionId: routeSessionIdParam } = useParams<{ sessionId?: string }>();
|
|
71
71
|
const threadRef = useRef<HTMLDivElement | null>(null);
|
|
72
72
|
const selectedSessionKeyRef = useRef<string | null>(selectedSessionKey);
|
|
73
|
-
const
|
|
73
|
+
const sessionStreamAttachInFlightRef = useRef(false);
|
|
74
74
|
const routeSessionKey = useMemo(
|
|
75
75
|
() => parseSessionKeyFromRoute(routeSessionIdParam),
|
|
76
76
|
[routeSessionIdParam]
|
|
@@ -157,39 +157,33 @@ export function NcpChatPage({ view }: ChatPageProps) {
|
|
|
157
157
|
const lastSendError = agent.hydrateError?.message ?? agent.snapshot.error?.message ?? null;
|
|
158
158
|
|
|
159
159
|
useEffect(() => {
|
|
160
|
-
const
|
|
160
|
+
const attachRealtimeSessionStream = () => {
|
|
161
|
+
if (sessionStreamAttachInFlightRef.current) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
161
164
|
if (agent.isHydrating || agent.isRunning || agent.isSending) {
|
|
162
|
-
pendingRealtimeReloadRef.current = true;
|
|
163
165
|
return;
|
|
164
166
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
+
|
|
168
|
+
sessionStreamAttachInFlightRef.current = true;
|
|
169
|
+
void ncpClient
|
|
170
|
+
.stream({ sessionId: activeSessionId })
|
|
171
|
+
.catch(() => undefined)
|
|
172
|
+
.finally(() => {
|
|
173
|
+
sessionStreamAttachInFlightRef.current = false;
|
|
174
|
+
});
|
|
167
175
|
};
|
|
168
176
|
|
|
169
177
|
return appClient.subscribe((event) => {
|
|
170
|
-
if (event.type === 'session.
|
|
171
|
-
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
flushRealtimeReload();
|
|
178
|
+
if (event.type === 'session.updated' && event.payload.sessionKey === activeSessionId) {
|
|
179
|
+
attachRealtimeSessionStream();
|
|
175
180
|
return;
|
|
176
181
|
}
|
|
177
|
-
if (event.type === 'session.
|
|
178
|
-
|
|
182
|
+
if (event.type === 'session.summary.upsert' && event.payload.summary.sessionId === activeSessionId) {
|
|
183
|
+
attachRealtimeSessionStream();
|
|
179
184
|
}
|
|
180
185
|
});
|
|
181
|
-
}, [activeSessionId, agent.isHydrating, agent.isRunning, agent.isSending,
|
|
182
|
-
|
|
183
|
-
useEffect(() => {
|
|
184
|
-
if (!pendingRealtimeReloadRef.current) {
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
if (agent.isHydrating || agent.isRunning || agent.isSending) {
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
pendingRealtimeReloadRef.current = false;
|
|
191
|
-
void agent.reloadSeed();
|
|
192
|
-
}, [agent.isHydrating, agent.isRunning, agent.isSending, agent.reloadSeed]);
|
|
186
|
+
}, [activeSessionId, agent.isHydrating, agent.isRunning, agent.isSending, ncpClient]);
|
|
193
187
|
|
|
194
188
|
useEffect(() => {
|
|
195
189
|
presenter.chatStreamActionsManager.bind({
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
## 目录预算豁免
|
|
2
|
-
- 原因:配置中心目录按配置面板维度组织,每个面板都需要独立入口、局部测试与装配文件;当前结构受 UI
|
|
2
|
+
- 原因:配置中心目录按配置面板维度组织,每个面板都需要独立入口、局部测试与装配文件;当前结构受 UI 信息架构约束,需要保留达到或超过 `12` 个直接代码文件的扁平集合。
|
package/src/lib/i18n.ts
CHANGED
|
@@ -185,8 +185,6 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
185
185
|
zh: 'Agent 默认模型标识,使用带 provider 前缀的格式。例如:openai/gpt-5.1、anthropic/claude-opus-4-1、deepseek/deepseek-chat、minimax/MiniMax-M2.5、openrouter/openai/gpt-5.3-codex。',
|
|
186
186
|
en: 'Default model identifier used by the agent. Use provider-prefixed format. Examples: openai/gpt-5.1 · anthropic/claude-opus-4-1 · deepseek/deepseek-chat · minimax/MiniMax-M2.5 · openrouter/openai/gpt-5.3-codex.'
|
|
187
187
|
},
|
|
188
|
-
chatRecentModels: { zh: '最近选择', en: 'Recent' },
|
|
189
|
-
chatAllModels: { zh: '全部模型', en: 'All models' },
|
|
190
188
|
maxToolIterations: { zh: '最大工具迭代次数', en: 'Max Tool Iterations' },
|
|
191
189
|
saveChanges: { zh: '保存变更', en: 'Save Changes' },
|
|
192
190
|
|