PluginProbe
ZIP AI – AI Website Builder & AI Agent (Beta) / 0.0.4
ZIP AI – AI Website Builder & AI Agent (Beta) v0.0.4
0.0.10 0.0.9 trunk 0.0.4 0.0.5 0.0.6 0.0.7 0.0.8
zip-ai / src / utils / componentInstanceId.js

componentInstanceId.js in ZIP AI – AI Website Builder & AI Agent (Beta) 0.0.4, at src/utils/componentInstanceId.js

37 lines 1.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Deterministic instance ID resolver for inline components.
3 *
4 * The same componentType + props must produce the same instanceId in three
5 * render paths (live SSE, persisted history, pending_component re-injection)
6 * so the per-instance state in `useComponentStateStore` (resolved /
7 * superseded / submitted values) survives reload.
8 *
9 * Priority: explicit `instance_id` > `call_id` (per-tool-call unique) >
10 * `form_id` > derived key + props hash. call_id beats form_id because the
11 * brain reuses form_id values across distinct tool calls (e.g. two smart-
12 * forms with form_id "website-batch-1" in different turns), which would
13 * otherwise collide on submitted state.
14 */
15
16 function stablePropsHash(props) {
17 try {
18 const str = JSON.stringify(props);
19 let hash = 5381;
20 for (let i = 0; i < str.length; i += 1) {
21 hash = ((hash << 5) + hash) + str.charCodeAt(i);
22 hash |= 0; // keep 32-bit
23 }
24 return Math.abs(hash).toString(36);
25 } catch {
26 return '0';
27 }
28 }
29
30 export function resolveComponentInstanceId(componentType, props = {}) {
31 if (props.instance_id) return props.instance_id;
32 if (props.call_id) return props.call_id;
33 if (props.form_id) return `${props.form_id}-${stablePropsHash(props)}`;
34 const derivedKey = props.brief?.business_name || props.title || props.action || 'default';
35 return `${componentType}-${derivedKey}-${stablePropsHash(props)}`;
36 }
37