const assert = require('node:assert/strict') const fs = require('node:fs') const path = require('node:path') const { execFileSync } = require('node:child_process') const { idle } = require('./publish_public_runtime.cjs') const root = path.resolve(__dirname, '../..') const modelID = '404e005b-83ae-5e2e-a3b3-999f9d5cd47e' const tenantID = 10059 const report = { checked_at: new Date().toISOString(), model_id: modelID, tenant_id: tenantID, model_calls: 0, changed: false } let token, stage = 'snapshot' function snapshot() { const sql = `BEGIN READ ONLY; SELECT json_build_object('model_id',id,'provider',parameters->>'provider', 'thinking_control',parameters->'extra_config'->>'thinking_control', 'unchanged_fields_sha256',encode(sha256(convert_to((to_jsonb(models) - 'updated_at' - 'parameters' || jsonb_build_object('parameters',parameters #- '{extra_config,thinking_control}'))::text,'UTF8')),'hex')) FROM models WHERE id='${modelID}' AND tenant_id=${tenantID} AND deleted_at IS NULL; COMMIT;` const result = execFileSync('docker', ['--context', 'colima-yawan', 'exec', '-i', 'WeKnora-postgres', 'psql', '-X', '-qAt', '-v', 'ON_ERROR_STOP=1', '-U', 'postgres', '-d', 'yawan_native_acceptance_20260915'], { input: sql, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 15000 }) return JSON.parse(result) } async function api(route, method = 'GET', body) { const response = await fetch(`http://127.0.0.1:18080/api/v1${route}`, { method, headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}`, 'X-Tenant-ID': String(tenantID) } : {}) }, body: body === undefined ? undefined : JSON.stringify(body), signal: AbortSignal.timeout(30000), }) assert.equal(response.status, 200) const result = await response.json() assert.notEqual(result.success, false) return result.data || result } async function main() { const before = snapshot() report.before = before assert.equal(before.provider, 'deepseek') assert.equal(before.thinking_control, 'none') if (!process.argv.includes('--apply')) { console.log(JSON.stringify({ ...report, proposed: 'thinking_type', dry_run: true })) return } stage = 'idle_check' idle() stage = 'login' const credentials = JSON.parse(fs.readFileSync(path.join(root, 'acceptance/super-admin-login.json'), 'utf8')) token = (await api('/auth/login', 'POST', credentials)).token assert.ok(token) stage = 'model_read' const model = await api(`/models/${modelID}`) assert.equal(model.tenant_id, tenantID) assert.equal(model.name, 'deepseek-flash') assert.equal(model.type, 'KnowledgeQA') assert.equal(model.source, 'remote') assert.equal(model.parameters.provider, 'deepseek') assert.equal(new URL(model.parameters.base_url).hostname, 'api.deepseek.com') assert.equal(model.parameters.extra_config?.thinking_control, 'none') const receiptPath = path.join(root, 'acceptance', `graph-model-thinking-fix-${Date.now()}.json`) fs.writeFileSync(receiptPath, JSON.stringify(report, null, 2) + '\n', { flag: 'wx', mode: 0o600 }) stage = 'compare_before_update' assert.deepEqual(snapshot(), before) stage = 'model_update' await api(`/models/${modelID}`, 'PUT', { name: model.name, display_name: model.display_name, description: model.description, type: model.type, source: model.source, parameters: { ...model.parameters, extra_config: { ...model.parameters.extra_config, thinking_control: 'thinking_type' } }, }) report.changed = true stage = 'verify' report.after = snapshot() fs.writeFileSync(receiptPath, JSON.stringify(report, null, 2) + '\n', { mode: 0o600 }) assert.equal(report.after.thinking_control, 'thinking_type') assert.equal(report.after.unchanged_fields_sha256, before.unchanged_fields_sha256) const after = await api(`/models/${modelID}`) assert.equal(after.parameters.extra_config.thinking_control, 'thinking_type') report.passed = true report.verified_at = new Date().toISOString() fs.writeFileSync(receiptPath, JSON.stringify(report, null, 2) + '\n', { mode: 0o600 }) console.log(JSON.stringify({ passed: true, changed: true, before: 'none', after: 'thinking_type', unrelated_fields_and_credentials_preserved: true, model_calls: 0, receipt_path: receiptPath })) } main().catch(() => { console.error(JSON.stringify({ passed: false, stage, changed: report.changed, model_calls: 0, error: 'Guarded model configuration update stopped; inspect the private receipt without printing credentials.' })) process.exitCode = 1 })