| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- #!/usr/bin/env node
- /**
- * init-tables.mjs — 初始化 FmodeAgent / AgentTaskStatus / AgentDeliverable 三表
- *
- * 真连 Parse REST /schemas 建(或校验)表结构,幂等可重跑:
- * - 表不存在 → 创建
- * - 字段已存在 → 忽略(Parse schema API 幂等)
- * 建完逐表回读 schema 校验关键列,输出索引提示。
- *
- * 用法: node init-tables.mjs [--server <url>]
- * 凭据: 四级解析(见 parse-client.mjs 头注释)
- */
- import {
- resolveCredentials, failNoCredentials, getSchema, createSchema,
- } from './parse-client.mjs';
- const argServer = process.argv.includes('--server')
- ? process.argv[process.argv.indexOf('--server') + 1] : null;
- const cred = resolveCredentials();
- if (!cred) failNoCredentials();
- if (argServer) cred.serverURL = argServer;
- // 三表 schema(与 agent-status-reporter 平台侧既有结构对齐)
- const TABLES = {
- FmodeAgent: {
- agentId: { type: 'String' },
- soulSummary: { type: 'String' },
- containerRef: { type: 'String' },
- lastHeartbeat: { type: 'Date' },
- status: { type: 'String' },
- scope: { type: 'String' },
- },
- AgentTaskStatus: {
- agentId: { type: 'String' },
- taskId: { type: 'String' },
- taskName: { type: 'String' },
- status: { type: 'String' }, // ack | running | done | failed
- startedAt: { type: 'Date' },
- endedAt: { type: 'Date' },
- heartbeatAt: { type: 'Date' },
- resultNote: { type: 'String' },
- },
- AgentDeliverable: {
- agentId: { type: 'String' },
- taskId: { type: 'String' },
- title: { type: 'String' },
- project: { type: 'String' },
- deliverableType: { type: 'String' }, // report | code | courseware | data
- url: { type: 'String' },
- summary: { type: 'String' },
- deliveredAt: { type: 'Date' },
- },
- };
- // 查询索引提示(Parse REST 不直接建索引,平台侧 mongo 手工建;此处只提示)
- const INDEX_HINTS = {
- FmodeAgent: 'agentId',
- AgentTaskStatus: 'agentId + taskId 复合查询(status.mjs / progress.mjs 幂等键)',
- AgentDeliverable: 'agentId + taskId + deliverableType(deliver.mjs 幂等覆盖键)',
- };
- const results = [];
- for (const [table, fields] of Object.entries(TABLES)) {
- const before = await getSchema(table, cred); // eslint-disable-line no-await-in-loop
- if (!before) {
- await createSchema(table, cred, fields); // eslint-disable-line no-await-in-loop
- } else {
- await createSchema(table, cred, fields); // 幂等补列(已存在列忽略)// eslint-disable-line no-await-in-loop
- }
- // 回读校验关键列
- const after = await getSchema(table, cred); // eslint-disable-line no-await-in-loop
- const missing = Object.entries(fields)
- .filter(([name, spec]) => !after || !after.fields[name] || after.fields[name].type !== spec.type)
- .map(([name]) => name);
- results.push({
- table, created: !before, columns: Object.keys(fields).length,
- verified: missing.length === 0, missing,
- indexHint: INDEX_HINTS[table],
- });
- }
- console.log(JSON.stringify({
- ok: true,
- server: cred.serverURL,
- credentialSource: cred.source,
- tables: results,
- }, null, 2));
- const failed = results.filter((r) => !r.verified);
- if (failed.length > 0) {
- console.error(`[task-progress] ${failed.length} 表字段校验未通过: ${failed.map((f) => f.table).join(', ')}`);
- process.exit(1);
- }
|