Command: powershell -NoProfile -Command "Get-Content -LiteralPath '..\apps-script\Code.gs' | Select-Object -First 190"
Directory: projects
Status: SUCCESS
Exit code: 0
Cancel Job Rerun Command Refresh
const SPREADSHEET_ID = '1HkbrZ7Phos3GVMBhi-1xPDr3wIBxRcBF6mNzabYqhmE';
const COMMANDS_SHEET = 'commands';
const RESULTS_SHEET = 'results';
const STATE_SHEET = 'state';
const ARTIFACTS_SHEET = 'artifacts';
const MAX_CELL_CHARS = 45000;
function doGet(e) {
return handleRequest_(e, null);
}
function doPost(e) {
let body = {};
if (e && e.postData && e.postData.contents) {
try {
body = JSON.parse(e.postData.contents);
} catch (err) {
return json_({ ok: false, error: 'invalid_json' }, 400);
}
}
return handleRequest_(e, body);
}
function handleRequest_(e, body) {
const params = (e && e.parameter) || {};
const action = (body && body.action) || params.action || 'status';
const key = (body && (body.relay_key || body.key)) || params.relay_key || params.key || '';
if (!validKey_(key)) {
return json_({ ok: false, error: 'not_found' }, 404);
}
const lock = LockService.getScriptLock();
lock.waitLock(10000);
try {
ensureSheets_();
if (action === 'status') return status_();
if (action === 'poll') return poll_();
if (action === 'result') return result_(body || {});
if (action === 'heartbeat') return heartbeat_(body || {});
return json_({ ok: false, error: 'unknown_action' }, 400);
} catch (err) {
return json_({ ok: false, error: String(err && err.message ? err.message : err) }, 500);
} finally {
lock.releaseLock();
}
}
function validKey_(key) {
const expected = getStateValue_('relay_key') || PropertiesService.getScriptProperties().getProperty('BRIDGE_RELAY_KEY');
return Boolean(expected && key && key === expected);
}
function poll_() {
const sheet = sheet_(COMMANDS_SHEET);
const values = sheet.getDataRange().getValues();
const headers = values[0] || [];
const col = headerMap_(headers);
for (let r = 1; r < values.length; r++) {
const row = values[r];
const status = String(row[col.status] || '').toLowerCase();
const confirm = String(row[col.confirm] || '').toLowerCase();
if (status === 'pending' && confirm === 'yes') {
const attempts = Number(row[col.attempts] || 0) + 1;
sheet.getRange(r + 1, col.status + 1).setValue('running');
sheet.getRange(r + 1, col.claimed_at + 1).setValue(nowIso_());
sheet.getRange(r + 1, col.attempts + 1).setValue(attempts);
return json_({
ok: true,
command: {
row: r + 1,
id: String(row[col.id] || ''),
action: String(row[col.action] || ''),
payload_json: String(row[col.payload_json] || '{}'),
attempts: attempts
}
});
}
}
return json_({ ok: true, command: null });
}
function result_(body) {
const commandId = String(body.command_id || '');
if (!commandId) return json_({ ok: false, error: 'command_id_required' }, 400);
const status = String(body.status || 'done');
const completedAt = nowIso_();
const resultText = truncate_(String(body.result_text || ''));
const errorText = truncate_(String(body.error || ''));
const httpStatus = body.http_status === undefined ? '' : String(body.http_status);
const durationMs = body.duration_ms === undefined ? '' : String(body.duration_ms);
const sha = String(body.result_sha256 || '');
const truncated = body.truncated ? 'yes' : 'no';
const resultSheet = sheet_(RESULTS_SHEET);
const resultId = Utilities.getUuid();
resultSheet.appendRow([resultId, commandId, completedAt, status, httpStatus, resultText, errorText, durationMs, sha, truncated]);
const commandSheet = sheet_(COMMANDS_SHEET);
const rows = commandSheet.getDataRange().getValues();
const col = headerMap_(rows[0] || []);
for (let r = 1; r < rows.length; r++) {
if (String(rows[r][col.id] || '') === commandId) {
commandSheet.getRange(r + 1, col.status + 1).setValue(status);
commandSheet.getRange(r + 1, col.completed_at + 1).setValue(completedAt);
commandSheet.getRange(r + 1, col.result_ref + 1).setValue(resultId);
commandSheet.getRange(r + 1, col.error + 1).setValue(errorText);
break;
}
}
setStateValue_('last_command_id', commandId, 'Updated by relay result');
return json_({ ok: true, result_id: resultId });
}
function heartbeat_(body) {
setStateValue_('relay_status', String(body.relay_status || 'ONLINE'), 'Updated by laptop relay');
setStateValue_('bridge_local', String(body.bridge_local || 'UNKNOWN'), '127.0.0.1 bridge health from relay');
setStateValue_('relay_version', String(body.relay_version || ''), 'Sheet relay package revision');
return json_({ ok: true, updated_at: nowIso_() });
}
function status_() {
return json_({
ok: true,
status: getStateValue_('relay_status') || 'UNKNOWN',
bridge_local: getStateValue_('bridge_local') || 'UNKNOWN',
updated_at: nowIso_()
});
}
function ensureSheets_() {
const ss = SpreadsheetApp.openById(SPREADSHEET_ID);
ensureSheet_(ss, COMMANDS_SHEET, ['id', 'created_at', 'action', 'payload_json', 'status', 'confirm', 'claimed_at', 'completed_at', 'result_ref', 'error', 'attempts', 'notes']);
ensureSheet_(ss, RESULTS_SHEET, ['id', 'command_id', 'completed_at', 'status', 'http_status', 'result_text', 'error', 'duration_ms', 'result_sha256', 'truncated']);
ensureSheet_(ss, STATE_SHEET, ['key', 'value', 'updated_at', 'notes']);
ensureSheet_(ss, ARTIFACTS_SHEET, ['id', 'command_id', 'name', 'mime_type', 'size', 'sha256', 'drive_url_or_ref', 'created_at']);
}
function ensureSheet_(ss, name, headers) {
let sh = ss.getSheetByName(name);
if (!sh) sh = ss.insertSheet(name);
const current = sh.getRange(1, 1, 1, headers.length).getValues()[0];
let needsHeader = false;
for (let i = 0; i < headers.length; i++) {
if (String(current[i] || '') !== headers[i]) needsHeader = true;
}
if (needsHeader) {
sh.getRange(1, 1, 1, headers.length).setValues([headers]);
sh.getRange(1, 1, 1, headers.length).setFontWeight('bold');
sh.setFrozenRows(1);
}
}
function sheet_(name) {
const sh = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(name);
if (!sh) throw new Error('missing sheet: ' + name);
return sh;
}
function headerMap_(headers) {
const out = {};
headers.forEach(function (h, i) { out[String(h)] = i; });
return out;
}
function getStateValue_(key) {
const sh = sheet_(STATE_SHEET);
const rows = sh.getDataRange().getValues();
for (let i = 1; i < rows.length; i++) {
if (String(rows[i][0]) === key) return String(rows[i][1] || '');
}
return '';
}
function setStateValue_(key, value, notes) {
const sh = sheet_(STATE_SHEET);
const rows = sh.getDataRange().getValues();
for (let i = 1; i < rows.length; i++) {
if (String(rows[i][0]) === key) {
sh.getRange(i + 1, 2, 1, 3).setValues([[value, nowIso_(), notes || '']]);
return;
}
}
sh.appendRow([key, value, nowIso_(), notes || '']);
}
function json_(obj, statusCode) {
return ContentService
.createTextOutput(JSON.stringify(obj))
.setMimeType(ContentService.MimeType.JSON);