feat(n8n-webhook): add compact approval history views
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"action": "create_calendar_event",
|
||||||
|
"request_id": "verify-calendar-event-cycle-001",
|
||||||
|
"args": {
|
||||||
|
"calendar": "primary",
|
||||||
|
"title": "[zap verify] Calendar event cycle smoke",
|
||||||
|
"start": "2030-01-15T18:00:00Z",
|
||||||
|
"end": "2030-01-15T18:30:00Z",
|
||||||
|
"description": "Recurring verification payload for the n8n Google Workspace action bus. Queue this event, approve it through the gog bridge, verify the created calendar event, then delete the event as cleanup."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"action": "send_email_draft",
|
||||||
|
"request_id": "verify-email-draft-cycle-001",
|
||||||
|
"args": {
|
||||||
|
"to": ["will@example.com"],
|
||||||
|
"subject": "[zap verify] Gmail draft cycle smoke",
|
||||||
|
"body_text": "Recurring verification payload for the n8n Google Workspace action bus. Queue this draft, approve it through the gog bridge, verify the created Gmail draft, then delete the draft as cleanup."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -338,6 +338,63 @@ def parse_json(output: str):
|
|||||||
return json.loads(text)
|
return json.loads(text)
|
||||||
|
|
||||||
|
|
||||||
|
def first_string(*values):
|
||||||
|
for value in values:
|
||||||
|
if isinstance(value, str) and value.strip():
|
||||||
|
return value.strip()
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
def execution_result_refs(op: str, parsed):
|
||||||
|
refs = {}
|
||||||
|
if not isinstance(parsed, dict):
|
||||||
|
return refs
|
||||||
|
|
||||||
|
draft = parsed.get('draft') if isinstance(parsed.get('draft'), dict) else {}
|
||||||
|
message = parsed.get('message') if isinstance(parsed.get('message'), dict) else {}
|
||||||
|
event = parsed.get('event') if isinstance(parsed.get('event'), dict) else {}
|
||||||
|
|
||||||
|
draft_id = first_string(
|
||||||
|
parsed.get('draft_id'),
|
||||||
|
draft.get('id'),
|
||||||
|
parsed.get('id') if op.startswith('gmail.drafts.') else '',
|
||||||
|
)
|
||||||
|
if draft_id:
|
||||||
|
refs['draft_id'] = draft_id
|
||||||
|
|
||||||
|
message_id = first_string(parsed.get('message_id'), message.get('id'))
|
||||||
|
if message_id:
|
||||||
|
refs['message_id'] = message_id
|
||||||
|
|
||||||
|
event_id = first_string(
|
||||||
|
parsed.get('event_id'),
|
||||||
|
event.get('id'),
|
||||||
|
parsed.get('id') if op.startswith('calendar.') else '',
|
||||||
|
)
|
||||||
|
if event_id:
|
||||||
|
refs['event_id'] = event_id
|
||||||
|
|
||||||
|
calendar = first_string(parsed.get('calendar'), parsed.get('calendar_id'), event.get('calendar'))
|
||||||
|
if calendar:
|
||||||
|
refs['calendar'] = calendar
|
||||||
|
|
||||||
|
return refs
|
||||||
|
|
||||||
|
|
||||||
|
def execution_summary(op: str, status: str, refs: dict, dry_run: bool):
|
||||||
|
if status == 'failed':
|
||||||
|
return f'{op} failed'
|
||||||
|
suffix = 'dry run' if dry_run else status.replace('_', ' ')
|
||||||
|
ref_parts = []
|
||||||
|
for key in ('draft_id', 'message_id', 'event_id', 'calendar'):
|
||||||
|
value = refs.get(key, '')
|
||||||
|
if value:
|
||||||
|
ref_parts.append(f'{key}={value}')
|
||||||
|
if ref_parts:
|
||||||
|
return f'{op} {suffix} ({", ".join(ref_parts)})'
|
||||||
|
return f'{op} {suffix}'
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
ap = argparse.ArgumentParser(description='Resolve an n8n approval item and execute email/calendar actions via gog.')
|
ap = argparse.ArgumentParser(description='Resolve an n8n approval item and execute email/calendar actions via gog.')
|
||||||
ap.add_argument('--id', required=True, help='Approval queue item id')
|
ap.add_argument('--id', required=True, help='Approval queue item id')
|
||||||
@@ -459,6 +516,7 @@ def main():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
if code != 0:
|
if code != 0:
|
||||||
|
refs = {}
|
||||||
execution = {
|
execution = {
|
||||||
'driver': 'gog',
|
'driver': 'gog',
|
||||||
'op': op,
|
'op': op,
|
||||||
@@ -467,18 +525,23 @@ def main():
|
|||||||
'dry_run': args.dry_run,
|
'dry_run': args.dry_run,
|
||||||
'stderr': stderr.strip(),
|
'stderr': stderr.strip(),
|
||||||
'stdout': stdout.strip(),
|
'stdout': stdout.strip(),
|
||||||
|
'result_refs': refs,
|
||||||
|
'summary': execution_summary(op, 'failed', refs, args.dry_run),
|
||||||
}
|
}
|
||||||
attach = attach_execution(item['id'], execution, base_url=args.base_url, path=args.path, secret_header=args.secret_header, secret=secret)
|
attach = attach_execution(item['id'], execution, base_url=args.base_url, path=args.path, secret_header=args.secret_header, secret=secret)
|
||||||
print(json.dumps({'resolved': resolved, 'execution': execution, 'attach': attach}, indent=2))
|
print(json.dumps({'resolved': resolved, 'execution': execution, 'attach': attach}, indent=2))
|
||||||
raise SystemExit(code)
|
raise SystemExit(code)
|
||||||
|
|
||||||
parsed = parse_json(stdout) if stdout.strip() else None
|
parsed = parse_json(stdout) if stdout.strip() else None
|
||||||
|
refs = execution_result_refs(op, parsed)
|
||||||
execution = {
|
execution = {
|
||||||
'driver': 'gog',
|
'driver': 'gog',
|
||||||
'op': op,
|
'op': op,
|
||||||
'status': success_status,
|
'status': success_status,
|
||||||
'account': account,
|
'account': account,
|
||||||
'dry_run': args.dry_run,
|
'dry_run': args.dry_run,
|
||||||
|
'result_refs': refs,
|
||||||
|
'summary': execution_summary(op, success_status, refs, args.dry_run),
|
||||||
'result': parsed,
|
'result': parsed,
|
||||||
}
|
}
|
||||||
attach = attach_execution(item['id'], execution, base_url=args.base_url, path=args.path, secret_header=args.secret_header, secret=secret)
|
attach = attach_execution(item['id'], execution, base_url=args.base_url, path=args.path, secret_header=args.secret_header, secret=secret)
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ SAMPLE_FILES = [
|
|||||||
'test-list-upcoming-events.json',
|
'test-list-upcoming-events.json',
|
||||||
'test-update-calendar-event.json',
|
'test-update-calendar-event.json',
|
||||||
'test-delete-calendar-event.json',
|
'test-delete-calendar-event.json',
|
||||||
|
'test-verify-email-draft-cycle.json',
|
||||||
|
'test-verify-calendar-event-cycle.json',
|
||||||
'test-fetch-and-normalize-url.json',
|
'test-fetch-and-normalize-url.json',
|
||||||
'test-approval-queue-list.json',
|
'test-approval-queue-list.json',
|
||||||
'test-inbound-event-filter.json',
|
'test-inbound-event-filter.json',
|
||||||
@@ -71,6 +73,11 @@ ROUTER_SNIPPETS = [
|
|||||||
'calendar_event_update',
|
'calendar_event_update',
|
||||||
'calendar_event_delete',
|
'calendar_event_delete',
|
||||||
'makeApprovalPolicy',
|
'makeApprovalPolicy',
|
||||||
|
'pending_compact',
|
||||||
|
'history_compact',
|
||||||
|
'summary_line',
|
||||||
|
'result_refs',
|
||||||
|
'default_mode',
|
||||||
'inboundEvents',
|
'inboundEvents',
|
||||||
'eventDedup',
|
'eventDedup',
|
||||||
'notify_text',
|
'notify_text',
|
||||||
|
|||||||
Reference in New Issue
Block a user