feat(n8n-webhook): add compact approval history views

This commit is contained in:
zap
2026-03-12 21:24:32 +00:00
parent 060da7ea1d
commit 249e671971
5 changed files with 91 additions and 1 deletions

File diff suppressed because one or more lines are too long

View File

@@ -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."
}
}

View File

@@ -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."
}
}

View File

@@ -338,6 +338,63 @@ def parse_json(output: str):
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():
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')
@@ -459,6 +516,7 @@ def main():
pass
if code != 0:
refs = {}
execution = {
'driver': 'gog',
'op': op,
@@ -467,18 +525,23 @@ def main():
'dry_run': args.dry_run,
'stderr': stderr.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)
print(json.dumps({'resolved': resolved, 'execution': execution, 'attach': attach}, indent=2))
raise SystemExit(code)
parsed = parse_json(stdout) if stdout.strip() else None
refs = execution_result_refs(op, parsed)
execution = {
'driver': 'gog',
'op': op,
'status': success_status,
'account': account,
'dry_run': args.dry_run,
'result_refs': refs,
'summary': execution_summary(op, success_status, refs, args.dry_run),
'result': parsed,
}
attach = attach_execution(item['id'], execution, base_url=args.base_url, path=args.path, secret_header=args.secret_header, secret=secret)

View File

@@ -34,6 +34,8 @@ SAMPLE_FILES = [
'test-list-upcoming-events.json',
'test-update-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-approval-queue-list.json',
'test-inbound-event-filter.json',
@@ -71,6 +73,11 @@ ROUTER_SNIPPETS = [
'calendar_event_update',
'calendar_event_delete',
'makeApprovalPolicy',
'pending_compact',
'history_compact',
'summary_line',
'result_refs',
'default_mode',
'inboundEvents',
'eventDedup',
'notify_text',