Files

92 lines
4.4 KiB
JavaScript
Raw Permalink Normal View History

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
})