diff --git a/mateclaw-ui/package.json b/mateclaw-ui/package.json index 82fb5fff..d594fae9 100644 --- a/mateclaw-ui/package.json +++ b/mateclaw-ui/package.json @@ -6,9 +6,10 @@ "description": "MateClaw - Personal AI Assistant Web Console", "scripts": { "dev": "vite", - "build": "node --max-old-space-size=6144 ./node_modules/vue-tsc/bin/vue-tsc.js --noEmit && node --max-old-space-size=6144 ./node_modules/vite/bin/vite.js build", + "build": "bash ../scripts/check-snowflake-precision.sh && node --max-old-space-size=6144 ./node_modules/vue-tsc/bin/vue-tsc.js --noEmit && node --max-old-space-size=6144 ./node_modules/vite/bin/vite.js build", "preview": "vite preview", - "lint": "eslint src --ext .ts,.vue --fix" + "lint": "eslint src --ext .ts,.vue --fix && bash ../scripts/check-snowflake-precision.sh", + "lint:precision": "bash ../scripts/check-snowflake-precision.sh" }, "dependencies": { "@element-plus/icons-vue": "^2.3.1", diff --git a/mateclaw-ui/src/api/index.ts b/mateclaw-ui/src/api/index.ts index 22c098a3..1348575a 100644 --- a/mateclaw-ui/src/api/index.ts +++ b/mateclaw-ui/src/api/index.ts @@ -559,7 +559,10 @@ export const settingsApi = { // unrelated settings pages can't clobber them via partial payloads. This // endpoint is the only path that writes those fields unconditionally — // pass {defaultVisionModelId: null} here to explicitly clear a sidecar. - updateSidecar: (data: { defaultVisionModelId: number | null; defaultVideoModelId: number | null }) => + // Model IDs are accepted as either JSON numbers or strings — Jackson + // coerces both into Long. The string form is preferred from the UI to + // sidestep JS Number precision loss on 19-digit Snowflake IDs. + updateSidecar: (data: { defaultVisionModelId: number | string | null; defaultVideoModelId: number | string | null }) => http.put('/settings/sidecar', data), } @@ -1042,7 +1045,10 @@ export interface TriggerSummary { patternType: string patternJson: string targetType: string - targetId: number + // Snowflake ID — backend serializes Long as string (ToStringSerializer). + // Keep the union so v-model can hold the string form without TS errors + // and JS Number() coercion stays out of the round-trip. + targetId: number | string payloadTemplate?: string rateLimitPerMin: number dedupWindowSecs: number diff --git a/mateclaw-ui/src/components/workflow/StepPropertyPanel.vue b/mateclaw-ui/src/components/workflow/StepPropertyPanel.vue index 73e58964..b7ea7b97 100644 --- a/mateclaw-ui/src/components/workflow/StepPropertyPanel.vue +++ b/mateclaw-ui/src/components/workflow/StepPropertyPanel.vue @@ -406,10 +406,11 @@ function onAgentSelect(e: Event) { patch({ agentId: undefined, agentName: undefined }) return } - const id = Number(v) + // Keep the id as the raw string from the option value — Snowflake IDs + // exceed Number.MAX_SAFE_INTEGER, so Number(v) would silently truncate. const selected = props.availableAgents.find((a) => String(a.id) === v) patch({ - agentId: Number.isFinite(id) ? id : undefined, + agentId: v, // Kept as a denormalized label for the canvas node; runtime resolves by agentId. agentName: selected?.name, }) diff --git a/mateclaw-ui/src/components/workflow/TriggerPatternForm.vue b/mateclaw-ui/src/components/workflow/TriggerPatternForm.vue index d360f3f7..3d4164e8 100644 --- a/mateclaw-ui/src/components/workflow/TriggerPatternForm.vue +++ b/mateclaw-ui/src/components/workflow/TriggerPatternForm.vue @@ -86,10 +86,14 @@