Governed substrate for autonomous agents: scoped identity (passports), audited actions, MCP workspace. Infra IPs and secrets redacted for public release.
181 lines
8.5 KiB
JavaScript
181 lines
8.5 KiB
JavaScript
// Script to create CRM automations for Calendar → Tickets in GERAVIKA space
|
|
// Run once, then delete. After this, rules are managed via CRM UI.
|
|
|
|
import { dbAll, dbRun, dbGet, sqlNow } from '../backend/database/connection.js';
|
|
import crypto from 'crypto';
|
|
|
|
async function main() {
|
|
// Find or create automations_list table in System Data (project 101, space 37)
|
|
let automationsTable = await dbGet(
|
|
"SELECT id FROM universal_tables WHERE project_id = 101 AND name = 'automations_list'"
|
|
);
|
|
|
|
if (!automationsTable) {
|
|
const now = new Date().toISOString();
|
|
const result = await dbRun(
|
|
"INSERT INTO universal_tables (name, display_name, project_id, created_at, updated_at) VALUES ($1, $2, $3, $4, $5)",
|
|
['automations_list', 'Automations', 101, now, now]
|
|
);
|
|
automationsTable = { id: result.lastID || result.lastInsertRowid };
|
|
console.log('Created automations_list table:', automationsTable.id);
|
|
|
|
const columns = [
|
|
{ column_name: 'name', display_name: 'Name', type: 'text', order_index: 0 },
|
|
{ column_name: 'description', display_name: 'Description', type: 'text', order_index: 1 },
|
|
{ column_name: 'table_id', display_name: 'Table ID', type: 'number', order_index: 2 },
|
|
{ column_name: 'table_name', display_name: 'Table', type: 'text', order_index: 3 },
|
|
{ column_name: 'trigger_type', display_name: 'Trigger', type: 'select', order_index: 4 },
|
|
{ column_name: 'action_type', display_name: 'Action', type: 'select', order_index: 5 },
|
|
{ column_name: 'is_active', display_name: 'Active', type: 'checkbox', order_index: 6 },
|
|
{ column_name: 'trigger_config', display_name: 'Trigger Config', type: 'text', order_index: 7 },
|
|
{ column_name: 'action_config', display_name: 'Action Config', type: 'text', order_index: 8 },
|
|
{ column_name: 'last_run', display_name: 'Last Run', type: 'date', order_index: 9 },
|
|
{ column_name: 'run_count', display_name: 'Run Count', type: 'number', order_index: 10 },
|
|
{ column_name: 'created_at', display_name: 'Created At', type: 'date', order_index: 11 }
|
|
];
|
|
for (const col of columns) {
|
|
await dbRun(
|
|
'INSERT INTO table_columns (table_id, column_name, display_name, type, order_index, is_visible) VALUES ($1, $2, $3, $4, $5, true)',
|
|
[automationsTable.id, col.column_name, col.display_name, col.type, col.order_index]
|
|
);
|
|
}
|
|
console.log('Created automation columns');
|
|
} else {
|
|
console.log('automations_list table exists:', automationsTable.id);
|
|
}
|
|
|
|
// Find or create logs table
|
|
let logsTable = await dbGet(
|
|
"SELECT id FROM universal_tables WHERE project_id = 101 AND name = 'automation_logs_list'"
|
|
);
|
|
if (!logsTable) {
|
|
const now = new Date().toISOString();
|
|
const result = await dbRun(
|
|
"INSERT INTO universal_tables (name, display_name, project_id, created_at, updated_at) VALUES ($1, $2, $3, $4, $5)",
|
|
['automation_logs_list', 'Automation Logs', 101, now, now]
|
|
);
|
|
logsTable = { id: result.lastID || result.lastInsertRowid };
|
|
console.log('Created logs table:', logsTable.id);
|
|
const logCols = [
|
|
{ column_name: 'automation_id', display_name: 'Automation ID', type: 'number', order_index: 0 },
|
|
{ column_name: 'automation_name', display_name: 'Automation', type: 'text', order_index: 1 },
|
|
{ column_name: 'status', display_name: 'Status', type: 'select', order_index: 2 },
|
|
{ column_name: 'trigger_data', display_name: 'Trigger Data', type: 'text', order_index: 3 },
|
|
{ column_name: 'result_data', display_name: 'Result', type: 'text', order_index: 4 },
|
|
{ column_name: 'error_message', display_name: 'Error', type: 'text', order_index: 5 },
|
|
{ column_name: 'duration_ms', display_name: 'Duration (ms)', type: 'number', order_index: 6 },
|
|
{ column_name: 'executed_at', display_name: 'Executed At', type: 'date', order_index: 7 }
|
|
];
|
|
for (const col of logCols) {
|
|
await dbRun(
|
|
'INSERT INTO table_columns (table_id, column_name, display_name, type, order_index, is_visible) VALUES ($1, $2, $3, $4, $5, true)',
|
|
[logsTable.id, col.column_name, col.display_name, col.type, col.order_index]
|
|
);
|
|
}
|
|
console.log('Created log columns');
|
|
} else {
|
|
console.log('automation_logs_list exists:', logsTable.id);
|
|
}
|
|
|
|
console.log('Tables ready:', { automationsTableId: automationsTable.id, logsTableId: logsTable.id });
|
|
|
|
// Create automations
|
|
const now = new Date().toISOString();
|
|
const automations = [
|
|
{
|
|
name: 'Personal Calendar → Task',
|
|
description: 'When a new event syncs from geramonnn@gmail.com, auto-create a Task in Family Task Board. Excludes holidays/birthdays.',
|
|
table_id: 2671,
|
|
table_name: 'google_calendar_events',
|
|
trigger_type: 'row_create',
|
|
trigger_config: JSON.stringify({}),
|
|
action_type: 'create_row',
|
|
action_config: JSON.stringify({
|
|
targetTableId: 2649,
|
|
conditions: [
|
|
{ field: 'calendar_name', operator: 'equals', value: 'geramonnn@gmail.com' },
|
|
{ field: 'status', operator: 'not_equals', value: 'cancelled' },
|
|
{ field: 'title', operator: 'not_contains', value: 'праздник' },
|
|
{ field: 'title', operator: 'not_contains', value: 'holiday' }
|
|
],
|
|
fieldMappings: [
|
|
{ sourceColumnId: 'title', targetColumnId: 'what' },
|
|
{ sourceColumnId: 'description', targetColumnId: 'why' },
|
|
{ sourceColumnId: 'start_datetime', targetColumnId: 'scheduled_date' },
|
|
{ sourceColumnId: 'end_datetime', targetColumnId: 'due_date' },
|
|
{ targetColumnId: 'state', staticValue: 24275 },
|
|
{ targetColumnId: 'type', staticValue: 24269 },
|
|
{ targetColumnId: 'priority', staticValue: 24272 }
|
|
]
|
|
}),
|
|
is_active: true, run_count: 0, last_run: null, created_at: now
|
|
},
|
|
{
|
|
name: 'Family Calendar → Task',
|
|
description: 'Auto-create Task from Family Group calendar events.',
|
|
table_id: 2671,
|
|
table_name: 'google_calendar_events',
|
|
trigger_type: 'row_create',
|
|
trigger_config: JSON.stringify({}),
|
|
action_type: 'create_row',
|
|
action_config: JSON.stringify({
|
|
targetTableId: 2649,
|
|
conditions: [
|
|
{ field: 'calendar_name', operator: 'contains', value: 'Семейная' },
|
|
{ field: 'status', operator: 'not_equals', value: 'cancelled' }
|
|
],
|
|
fieldMappings: [
|
|
{ sourceColumnId: 'title', targetColumnId: 'what' },
|
|
{ sourceColumnId: 'description', targetColumnId: 'why' },
|
|
{ sourceColumnId: 'start_datetime', targetColumnId: 'scheduled_date' },
|
|
{ sourceColumnId: 'end_datetime', targetColumnId: 'due_date' },
|
|
{ targetColumnId: 'state', staticValue: 24275 },
|
|
{ targetColumnId: 'type', staticValue: 24269 },
|
|
{ targetColumnId: 'priority', staticValue: 24272 }
|
|
]
|
|
}),
|
|
is_active: true, run_count: 0, last_run: null, created_at: now
|
|
},
|
|
{
|
|
name: 'New Event → Notification',
|
|
description: 'Notify on new calendar events (exclude Thai holidays).',
|
|
table_id: 2671,
|
|
table_name: 'google_calendar_events',
|
|
trigger_type: 'row_create',
|
|
trigger_config: JSON.stringify({}),
|
|
action_type: 'notification',
|
|
action_config: JSON.stringify({
|
|
notificationType: 'in_app',
|
|
conditions: [
|
|
{ field: 'calendar_name', operator: 'not_contains', value: 'Праздники' },
|
|
{ field: 'status', operator: 'not_equals', value: 'cancelled' }
|
|
],
|
|
recipients: ['1'],
|
|
messageTemplate: '📅 New event: {{title}} ({{start_datetime}})'
|
|
}),
|
|
is_active: false, run_count: 0, last_run: null, created_at: now
|
|
}
|
|
];
|
|
|
|
for (const auto of automations) {
|
|
const baseId = 'auto_' + Date.now() + '_' + crypto.randomBytes(4).toString('hex');
|
|
const result = await dbRun(
|
|
'INSERT INTO table_rows (table_id, base_id, data, created_at, updated_at) VALUES ($1, $2, $3, $4, $5)',
|
|
[automationsTable.id, baseId, JSON.stringify(auto), now, now]
|
|
);
|
|
const id = result.lastID || result.lastInsertRowid;
|
|
console.log(`Created: #${id} - ${auto.name} [${auto.trigger_type} → ${auto.action_type}] active=${auto.is_active}`);
|
|
}
|
|
|
|
// Verify
|
|
const all = await dbAll('SELECT id, data FROM table_rows WHERE table_id = $1', [automationsTable.id]);
|
|
console.log(`\nTotal automations in GERAVIKA space: ${all.length}`);
|
|
for (const a of all) {
|
|
const d = JSON.parse(a.data);
|
|
console.log(` #${a.id}: ${d.name} [${d.trigger_type} → ${d.action_type}] active=${d.is_active}`);
|
|
}
|
|
|
|
process.exit(0);
|
|
}
|
|
|
|
main().catch(err => { console.error(err); process.exit(1); });
|