fix(frontend): initializeStores dedup + retryAllMessages guard + as any cleanup
- index.ts: add _storesInitialized guard to prevent triple initialization - offlineStore.ts: add isRetrying mutex for retryAllMessages concurrency - PropertyPanel.tsx: replace 13x (data as any) with typed d accessor - chatStore.ts: replace window as any with Record<string, unknown> - kernel-*.ts: replace prototype as any with Record<string, unknown> - gateway-heartbeat.ts: delete dead code (9 as any, zero imports)
This commit is contained in:
@@ -87,6 +87,8 @@ function renderTypeSpecificFields(
|
||||
data: Partial<WorkflowNodeData>,
|
||||
onChange: (field: string, value: unknown) => void
|
||||
) {
|
||||
// Type-safe property accessor for union-typed node data
|
||||
const d = data as Record<string, unknown>;
|
||||
switch (type) {
|
||||
case 'input':
|
||||
return (
|
||||
@@ -97,7 +99,7 @@ function renderTypeSpecificFields(
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={(data as any).variableName || ''}
|
||||
value={d.variableName || ''}
|
||||
onChange={(e) => onChange('variableName', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono"
|
||||
/>
|
||||
@@ -107,7 +109,7 @@ function renderTypeSpecificFields(
|
||||
Default Value
|
||||
</label>
|
||||
<textarea
|
||||
value={(data as any).defaultValue || ''}
|
||||
value={d.defaultValue || ''}
|
||||
onChange={(e) => {
|
||||
try {
|
||||
const parsed = JSON.parse(e.target.value);
|
||||
@@ -132,7 +134,7 @@ function renderTypeSpecificFields(
|
||||
Template
|
||||
</label>
|
||||
<textarea
|
||||
value={(data as any).template || ''}
|
||||
value={d.template || ''}
|
||||
onChange={(e) => onChange('template', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono text-sm"
|
||||
rows={6}
|
||||
@@ -144,7 +146,7 @@ function renderTypeSpecificFields(
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={(data as any).model || ''}
|
||||
value={d.model || ''}
|
||||
onChange={(e) => onChange('model', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
|
||||
placeholder="e.g., gpt-4"
|
||||
@@ -159,7 +161,7 @@ function renderTypeSpecificFields(
|
||||
min="0"
|
||||
max="2"
|
||||
step="0.1"
|
||||
value={(data as any).temperature ?? ''}
|
||||
value={d.temperature ?? ''}
|
||||
onChange={(e) => onChange('temperature', parseFloat(e.target.value))}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
|
||||
/>
|
||||
@@ -167,7 +169,7 @@ function renderTypeSpecificFields(
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={(data as any).jsonMode || false}
|
||||
checked={d.jsonMode || false}
|
||||
onChange={(e) => onChange('jsonMode', e.target.checked)}
|
||||
className="w-4 h-4 text-blue-600 rounded"
|
||||
/>
|
||||
@@ -185,7 +187,7 @@ function renderTypeSpecificFields(
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={(data as any).skillId || ''}
|
||||
value={d.skillId || ''}
|
||||
onChange={(e) => onChange('skillId', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono"
|
||||
/>
|
||||
@@ -195,7 +197,7 @@ function renderTypeSpecificFields(
|
||||
Input Mappings (JSON)
|
||||
</label>
|
||||
<textarea
|
||||
value={JSON.stringify((data as any).inputMappings || {}, null, 2)}
|
||||
value={JSON.stringify(d.inputMappings || {}, null, 2)}
|
||||
onChange={(e) => {
|
||||
try {
|
||||
const parsed = JSON.parse(e.target.value);
|
||||
@@ -220,7 +222,7 @@ function renderTypeSpecificFields(
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={(data as any).handId || ''}
|
||||
value={d.handId || ''}
|
||||
onChange={(e) => onChange('handId', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono"
|
||||
/>
|
||||
@@ -231,7 +233,7 @@ function renderTypeSpecificFields(
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={(data as any).action || ''}
|
||||
value={d.action || ''}
|
||||
onChange={(e) => onChange('action', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
|
||||
/>
|
||||
@@ -251,9 +253,9 @@ function renderTypeSpecificFields(
|
||||
<label key={format} className="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={((data as any).formats || []).includes(format)}
|
||||
checked={(d.formats || []).includes(format)}
|
||||
onChange={(e) => {
|
||||
const formats = (data as any).formats || [];
|
||||
const formats = d.formats || [];
|
||||
if (e.target.checked) {
|
||||
onChange('formats', [...formats, format]);
|
||||
} else {
|
||||
@@ -273,7 +275,7 @@ function renderTypeSpecificFields(
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={(data as any).outputDir || ''}
|
||||
value={d.outputDir || ''}
|
||||
onChange={(e) => onChange('outputDir', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
|
||||
placeholder="./output"
|
||||
|
||||
Reference in New Issue
Block a user