fix(types): Desktop type safety hardening (TYPE-01)
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

- Unify ConnectionState: kernel-types.ts now canonical source
  with 'handshaking', gateway-types.ts re-exports
- PromptTemplateInfo source/status → union literals
- PromptVariable.type → union literal
- CreateRoleRequest id/permissions → optional
- PropertyPanel: replace 13 as any with typed accessor pattern
- chatStore: window cast via as unknown as Record
This commit is contained in:
iven
2026-04-05 01:30:29 +08:00
parent 36168d6978
commit 3b0ab1a7b7
6 changed files with 32 additions and 26 deletions

View File

@@ -87,8 +87,13 @@ function renderTypeSpecificFields(
data: Partial<WorkflowNodeData>,
onChange: (field: string, value: unknown) => void
) {
// Type-safe property accessor for union-typed node data
// Type-safe property accessors for union-typed node data
const d = data as Record<string, unknown>;
const str = (key: string): string => (d[key] as string) || '';
const num = (key: string): number | string => (d[key] as number) ?? '';
const bool = (key: string): boolean => (d[key] as boolean) || false;
const arr = (key: string): string[] => (d[key] as string[]) || [];
const obj = (key: string): Record<string, unknown> => (d[key] as Record<string, unknown>) || {};
switch (type) {
case 'input':
return (
@@ -99,7 +104,7 @@ function renderTypeSpecificFields(
</label>
<input
type="text"
value={d.variableName || ''}
value={str('variableName')}
onChange={(e) => onChange('variableName', e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono"
/>
@@ -109,7 +114,7 @@ function renderTypeSpecificFields(
Default Value
</label>
<textarea
value={d.defaultValue || ''}
value={str('defaultValue')}
onChange={(e) => {
try {
const parsed = JSON.parse(e.target.value);
@@ -134,7 +139,7 @@ function renderTypeSpecificFields(
Template
</label>
<textarea
value={d.template || ''}
value={str('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}
@@ -146,7 +151,7 @@ function renderTypeSpecificFields(
</label>
<input
type="text"
value={d.model || ''}
value={str('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"
@@ -161,7 +166,7 @@ function renderTypeSpecificFields(
min="0"
max="2"
step="0.1"
value={d.temperature ?? ''}
value={num('temperature')}
onChange={(e) => onChange('temperature', parseFloat(e.target.value))}
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
/>
@@ -169,7 +174,7 @@ function renderTypeSpecificFields(
<div className="flex items-center gap-2">
<input
type="checkbox"
checked={d.jsonMode || false}
checked={bool('jsonMode')}
onChange={(e) => onChange('jsonMode', e.target.checked)}
className="w-4 h-4 text-blue-600 rounded"
/>
@@ -187,7 +192,7 @@ function renderTypeSpecificFields(
</label>
<input
type="text"
value={d.skillId || ''}
value={str('skillId')}
onChange={(e) => onChange('skillId', e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono"
/>
@@ -197,7 +202,7 @@ function renderTypeSpecificFields(
Input Mappings (JSON)
</label>
<textarea
value={JSON.stringify(d.inputMappings || {}, null, 2)}
value={JSON.stringify(obj('inputMappings'), null, 2)}
onChange={(e) => {
try {
const parsed = JSON.parse(e.target.value);
@@ -222,7 +227,7 @@ function renderTypeSpecificFields(
</label>
<input
type="text"
value={d.handId || ''}
value={str('handId')}
onChange={(e) => onChange('handId', e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono"
/>
@@ -233,7 +238,7 @@ function renderTypeSpecificFields(
</label>
<input
type="text"
value={d.action || ''}
value={str('action')}
onChange={(e) => onChange('action', e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
/>
@@ -253,13 +258,13 @@ function renderTypeSpecificFields(
<label key={format} className="flex items-center gap-2">
<input
type="checkbox"
checked={(d.formats || []).includes(format)}
checked={arr('formats').includes(format)}
onChange={(e) => {
const formats = d.formats || [];
const formats = arr('formats');
if (e.target.checked) {
onChange('formats', [...formats, format]);
} else {
onChange('formats', formats.filter((f: string) => f !== format));
onChange('formats', formats.filter((f) => f !== format));
}
}}
className="w-4 h-4 text-blue-600 rounded"
@@ -275,7 +280,7 @@ function renderTypeSpecificFields(
</label>
<input
type="text"
value={d.outputDir || ''}
value={str('outputDir')}
onChange={(e) => onChange('outputDir', e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
placeholder="./output"