{ "kind": "open-flow-workflow", "version": 1, "name": "Hacker News Hiring to Airtable", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_57bfc98a208803af": { "name": "Find recent hiring posts", "kind": "start", "inputDefs": [] }, "n_b3e867634a884f92": { "inputs": { "endpoint": { "kind": "value", "value": "/search_by_date" }, "query.query": { "kind": "value", "value": "\"Ask HN: Who is hiring\"" }, "query.tags": { "kind": "value", "value": "story" }, "query.hitsPerPage": { "kind": "value", "value": 30 }, "query.page": { "kind": "value", "value": 0 }, "query.advancedSyntax": { "kind": "value", "value": true }, "query.restrictSearchableAttributes": { "kind": "value", "value": "title,comment_text,url,story_text,author" } }, "name": "Search hiring threads", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "endpoint" }, { "jsonSchema": { "type": [ "string", "number", "boolean", "null" ] }, "nullable": true, "handle": "query.query" }, { "jsonSchema": { "type": [ "string", "number", "boolean", "null" ] }, "nullable": true, "handle": "query.tags" }, { "jsonSchema": { "type": [ "string", "number", "boolean", "null" ] }, "nullable": true, "handle": "query.hitsPerPage" }, { "jsonSchema": { "type": [ "string", "number", "boolean", "null" ] }, "nullable": true, "handle": "query.page" }, { "jsonSchema": { "type": [ "string", "number", "boolean", "null" ] }, "nullable": true, "handle": "query.advancedSyntax" }, { "jsonSchema": { "type": [ "string", "number", "boolean", "null" ] }, "nullable": true, "handle": "query.restrictSearchableAttributes" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" }, { "jsonSchema": { "const": "base64" }, "nullable": true, "handle": "bodyEncoding" } ], "name": "Search hiring threads", "executor": { "providerId": "hackernews", "method": "GET", "query": { "mode": "fields", "names": [ "query", "tags", "hitsPerPage", "page", "advancedSyntax", "restrictSearchableAttributes" ] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "none", "kind": "connector-proxy" } } }, "n_f94851172a9a1a3c": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b3e867634a884f92", "output": "body" } ] }, "statusCode": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b3e867634a884f92", "output": "statusCode" } ] }, "bodyEncoding": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b3e867634a884f92", "output": "bodyEncoding" } ] }, "previousState": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_f94851172a9a1a3c", "output": "state" } ] }, "story": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_208245aecc0a799b", "output": "output" } ] } }, "name": "Collect thread comment IDs", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "const": "base64" }, "nullable": true, "handle": "bodyEncoding" }, { "jsonSchema": { "type": "object" }, "nullable": true, "handle": "previousState" }, { "jsonSchema": { "type": [ "object", "null" ], "properties": { "by": { "type": "string", "description": "The username of the item author." }, "id": { "type": "integer", "description": "The unique identifier of the item." }, "url": { "type": "string", "description": "The URL of the item." }, "dead": { "type": "boolean", "description": "Whether the item is dead." }, "kids": { "type": "array", "items": { "type": "integer", "description": "A child item ID." }, "description": "The list of child item IDs." }, "poll": { "type": "integer", "description": "The associated poll ID." }, "text": { "type": "string", "description": "The text content of the item." }, "time": { "type": "integer", "description": "The creation time as a Unix timestamp." }, "type": { "type": "string", "enum": [ "job", "story", "comment", "poll", "pollopt" ], "description": "The type of a Hacker News item." }, "parts": { "type": "array", "items": { "type": "integer", "description": "A poll option ID." }, "description": "The list of poll option IDs." }, "score": { "type": "integer", "description": "The score of the item." }, "title": { "type": "string", "description": "The title of the item." }, "parent": { "type": "integer", "description": "The parent item ID." }, "deleted": { "type": "boolean", "description": "Whether the item has been deleted." }, "descendants": { "type": "integer", "description": "The total number of descendants." } }, "required": [ "id", "type" ], "additionalProperties": true, "description": "The item or null if not found." }, "nullable": true, "handle": "story" } ], "outputs": [ { "jsonSchema": { "type": "object", "properties": { "commentIds": { "type": "array", "items": { "type": "integer", "minimum": 1 } } }, "required": [ "commentIds" ] }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "integer", "minimum": 1 }, "nullable": false, "handle": "itemId" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "more" } ], "name": "Collect thread comment IDs", "moduleId": "n_496f1cac5da8034f", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_c7a11e9a30b84278": { "inputs": {}, "name": "More hiring threads to read", "kind": "condition", "matchMode": "first", "cases": [ { "output": "more", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_f94851172a9a1a3c", "output": "more" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_208245aecc0a799b": { "inputs": { "id": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_f94851172a9a1a3c", "output": "itemId" } ] } }, "name": "Read hiring thread", "kind": "task", "task": { "inputs": [ { "description": "The item ID to fetch.", "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "The item ID to fetch." }, "nullable": false, "handle": "id" }, { "description": "The pretty-print flag for Firebase responses.", "jsonSchema": { "const": "pretty", "description": "The pretty-print flag for Firebase responses." }, "nullable": true, "handle": "print", "value": null } ], "outputs": [ { "description": "The item or null if not found.", "jsonSchema": { "type": [ "object", "null" ], "properties": { "by": { "type": "string", "description": "The username of the item author." }, "id": { "type": "integer", "description": "The unique identifier of the item." }, "url": { "type": "string", "description": "The URL of the item." }, "dead": { "type": "boolean", "description": "Whether the item is dead." }, "kids": { "type": "array", "items": { "type": "integer", "description": "A child item ID." }, "description": "The list of child item IDs." }, "poll": { "type": "integer", "description": "The associated poll ID." }, "text": { "type": "string", "description": "The text content of the item." }, "time": { "type": "integer", "description": "The creation time as a Unix timestamp." }, "type": { "type": "string", "enum": [ "job", "story", "comment", "poll", "pollopt" ], "description": "The type of a Hacker News item." }, "parts": { "type": "array", "items": { "type": "integer", "description": "A poll option ID." }, "description": "The list of poll option IDs." }, "score": { "type": "integer", "description": "The score of the item." }, "title": { "type": "string", "description": "The title of the item." }, "parent": { "type": "integer", "description": "The parent item ID." }, "deleted": { "type": "boolean", "description": "Whether the item has been deleted." }, "descendants": { "type": "integer", "description": "The total number of descendants." } }, "required": [ "id", "type" ], "additionalProperties": true, "description": "The item or null if not found." }, "nullable": true, "handle": "output" } ], "name": "Read hiring thread", "executor": { "kind": "connector", "action": "hackernews.get_item", "outputMode": "value" } } }, "n_6a6b56e4d23b86fd": { "inputs": { "commentIds": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_f94851172a9a1a3c", "output": "state", "field": "commentIds" } ] }, "previousState": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_6a6b56e4d23b86fd", "output": "state" } ] }, "comment": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ee00885f0daa2f67", "output": "output" } ] } }, "name": "Collect first five job comments", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "array", "items": { "type": "integer", "minimum": 1 } }, "nullable": false, "handle": "commentIds" }, { "jsonSchema": { "type": "object" }, "nullable": true, "handle": "previousState" }, { "jsonSchema": { "type": [ "object", "null" ], "properties": { "by": { "type": "string", "description": "The username of the item author." }, "id": { "type": "integer", "description": "The unique identifier of the item." }, "url": { "type": "string", "description": "The URL of the item." }, "dead": { "type": "boolean", "description": "Whether the item is dead." }, "kids": { "type": "array", "items": { "type": "integer", "description": "A child item ID." }, "description": "The list of child item IDs." }, "poll": { "type": "integer", "description": "The associated poll ID." }, "text": { "type": "string", "description": "The text content of the item." }, "time": { "type": "integer", "description": "The creation time as a Unix timestamp." }, "type": { "type": "string", "enum": [ "job", "story", "comment", "poll", "pollopt" ], "description": "The type of a Hacker News item." }, "parts": { "type": "array", "items": { "type": "integer", "description": "A poll option ID." }, "description": "The list of poll option IDs." }, "score": { "type": "integer", "description": "The score of the item." }, "title": { "type": "string", "description": "The title of the item." }, "parent": { "type": "integer", "description": "The parent item ID." }, "deleted": { "type": "boolean", "description": "Whether the item has been deleted." }, "descendants": { "type": "integer", "description": "The total number of descendants." } }, "required": [ "id", "type" ], "additionalProperties": true, "description": "The item or null if not found." }, "nullable": true, "handle": "comment" } ], "outputs": [ { "jsonSchema": { "type": "object", "properties": { "selected": { "type": "array", "items": { "type": "object" } } }, "required": [ "selected" ] }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "integer", "minimum": 1 }, "nullable": false, "handle": "itemId" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "more" } ], "name": "Collect first five job comments", "moduleId": "n_0fe3028c08c55a2f", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_6ec060bd16059899": { "inputs": {}, "name": "More job comments to read", "kind": "condition", "matchMode": "first", "cases": [ { "output": "more", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_6a6b56e4d23b86fd", "output": "more" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_ee00885f0daa2f67": { "inputs": { "id": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_6a6b56e4d23b86fd", "output": "itemId" } ] } }, "name": "Read hiring comment", "kind": "task", "task": { "inputs": [ { "description": "The item ID to fetch.", "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "The item ID to fetch." }, "nullable": false, "handle": "id" }, { "description": "The pretty-print flag for Firebase responses.", "jsonSchema": { "const": "pretty", "description": "The pretty-print flag for Firebase responses." }, "nullable": true, "handle": "print", "value": null } ], "outputs": [ { "description": "The item or null if not found.", "jsonSchema": { "type": [ "object", "null" ], "properties": { "by": { "type": "string", "description": "The username of the item author." }, "id": { "type": "integer", "description": "The unique identifier of the item." }, "url": { "type": "string", "description": "The URL of the item." }, "dead": { "type": "boolean", "description": "Whether the item is dead." }, "kids": { "type": "array", "items": { "type": "integer", "description": "A child item ID." }, "description": "The list of child item IDs." }, "poll": { "type": "integer", "description": "The associated poll ID." }, "text": { "type": "string", "description": "The text content of the item." }, "time": { "type": "integer", "description": "The creation time as a Unix timestamp." }, "type": { "type": "string", "enum": [ "job", "story", "comment", "poll", "pollopt" ], "description": "The type of a Hacker News item." }, "parts": { "type": "array", "items": { "type": "integer", "description": "A poll option ID." }, "description": "The list of poll option IDs." }, "score": { "type": "integer", "description": "The score of the item." }, "title": { "type": "string", "description": "The title of the item." }, "parent": { "type": "integer", "description": "The parent item ID." }, "deleted": { "type": "boolean", "description": "Whether the item has been deleted." }, "descendants": { "type": "integer", "description": "The total number of descendants." } }, "required": [ "id", "type" ], "additionalProperties": true, "description": "The item or null if not found." }, "nullable": true, "handle": "output" } ], "name": "Read hiring comment", "executor": { "kind": "connector", "action": "hackernews.get_item", "outputMode": "value" } } }, "n_c09dd196183b0bd3": { "inputs": { "selected": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_6a6b56e4d23b86fd", "output": "state", "field": "selected" } ] }, "previousState": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_c09dd196183b0bd3", "output": "state" } ] }, "completion": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_e48352a21e44b691", "output": "output" } ] } }, "name": "Collect extracted jobs", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "array", "items": { "type": "object" } }, "nullable": false, "handle": "selected" }, { "jsonSchema": { "type": "object" }, "nullable": true, "handle": "previousState" }, { "jsonSchema": { "type": "object", "properties": { "company": { "type": [ "string", "null" ], "description": "Name of the hiring company" }, "title": { "type": [ "string", "null" ], "description": "Job title/role being advertised" }, "location": { "type": [ "string", "null" ], "description": "Work location including remote/hybrid status" }, "type": { "type": [ "string", "null" ], "description": "Employment type (Full-time, Contract, etc)", "enum": [ "FULL_TIME", "PART_TIME", "CONTRACT", "INTERNSHIP", "FREELANCE", null ] }, "work_location": { "type": [ "string", "null" ], "description": "Work arrangement type", "enum": [ "REMOTE", "HYBRID", "ON_SITE", null ] }, "salary": { "type": [ "string", "null" ], "description": "Compensation details if provided" }, "description": { "type": [ "string", "null" ], "description": "Main job description text including requirements and team info" }, "apply_url": { "type": [ "string", "null" ], "description": "Direct application/job posting URL" }, "company_url": { "type": [ "string", "null" ], "description": "Company website or careers page" } }, "additionalProperties": false }, "nullable": true, "handle": "completion" } ], "outputs": [ { "jsonSchema": { "type": "object", "properties": { "plans": { "type": "array", "items": { "type": "object" } } }, "required": [ "plans" ] }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "text" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "more" } ], "name": "Collect extracted jobs", "moduleId": "n_15704b5157850aea", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_0462a41b24db0e0b": { "inputs": {}, "name": "More selected jobs to extract", "kind": "condition", "matchMode": "first", "cases": [ { "output": "more", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_c09dd196183b0bd3", "output": "more" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_e48352a21e44b691": { "inputs": { "text": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_c09dd196183b0bd3", "output": "text" } ] } }, "name": "Extract hiring details", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "text" } ], "outputs": [ { "description": "The final result produced by the Agent.", "jsonSchema": { "type": "object", "properties": { "company": { "type": [ "string", "null" ], "description": "Name of the hiring company" }, "title": { "type": [ "string", "null" ], "description": "Job title/role being advertised" }, "location": { "type": [ "string", "null" ], "description": "Work location including remote/hybrid status" }, "type": { "type": [ "string", "null" ], "description": "Employment type (Full-time, Contract, etc)", "enum": [ "FULL_TIME", "PART_TIME", "CONTRACT", "INTERNSHIP", "FREELANCE", null ] }, "work_location": { "type": [ "string", "null" ], "description": "Work arrangement type", "enum": [ "REMOTE", "HYBRID", "ON_SITE", null ] }, "salary": { "type": [ "string", "null" ], "description": "Compensation details if provided" }, "description": { "type": [ "string", "null" ], "description": "Main job description text including requirements and team info" }, "apply_url": { "type": [ "string", "null" ], "description": "Direct application/job posting URL" }, "company_url": { "type": [ "string", "null" ], "description": "Company website or careers page" } }, "additionalProperties": false }, "nullable": false, "handle": "output" } ], "name": "Extract hiring details", "executor": { "kind": "agent", "code": false, "model": "YOUR_HIRING_EXTRACTION_MODEL_ID", "prompt": "Extract the JSON data\n\n{{text}}", "maxRounds": 1, "tools": [] } } }, "n_546c5edfbdab5910": { "inputs": { "plans": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_c09dd196183b0bd3", "output": "state", "field": "plans" } ] }, "previousState": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_546c5edfbdab5910", "output": "state" } ] }, "records": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_63e22831ea8b7f03", "output": "records" } ] } }, "name": "Collect saved Airtable rows", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "array", "items": { "type": "object" } }, "nullable": false, "handle": "plans" }, { "jsonSchema": { "type": "object" }, "nullable": true, "handle": "previousState" }, { "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Record ID." }, "createdTime": { "type": "string", "description": "Record creation timestamp returned by Airtable." }, "fields": { "type": "object", "additionalProperties": { "description": "A record value." }, "description": "Record fields keyed by field name or field ID." }, "commentCount": { "type": "integer", "description": "Comment count returned by Airtable when enabled on the endpoint." } }, "required": [ "id", "fields" ], "additionalProperties": true, "description": "Airtable record." }, "description": "Records created by Airtable." }, "nullable": true, "handle": "records" } ], "outputs": [ { "jsonSchema": { "type": "object", "properties": { "receipts": { "type": "array", "items": { "type": "object" } } }, "required": [ "receipts" ] }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "fields": { "type": "object", "additionalProperties": { "description": "A record value." }, "description": "Field values for the new Airtable record." } }, "required": [ "fields" ], "additionalProperties": false, "description": "Record payload used when creating Airtable records." }, "minItems": 1, "maxItems": 10, "description": "Records to create in the Airtable table." }, "nullable": false, "handle": "records" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "more" }, { "jsonSchema": { "type": "integer", "minimum": 0 }, "nullable": false, "handle": "count" } ], "name": "Collect saved Airtable rows", "moduleId": "n_7131f59b7d2ba0c8", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_4f5187e98be33925": { "inputs": {}, "name": "More recruiting rows to save", "kind": "condition", "matchMode": "first", "cases": [ { "output": "more", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_546c5edfbdab5910", "output": "more" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_63e22831ea8b7f03": { "inputs": { "baseId": { "kind": "value", "value": "YOUR_AIRTABLE_BASE_ID" }, "tableIdOrName": { "kind": "value", "value": "YOUR_AIRTABLE_TABLE_ID" }, "records": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_546c5edfbdab5910", "output": "records" } ] } }, "name": "Create Airtable job", "kind": "task", "task": { "inputs": [ { "description": "Base ID in the format appXXXXXXXXXXXXXX.", "jsonSchema": { "type": "string", "minLength": 1, "description": "Base ID in the format appXXXXXXXXXXXXXX." }, "nullable": false, "handle": "baseId" }, { "description": "Table ID or table name accepted by the Airtable path parameter.", "jsonSchema": { "type": "string", "minLength": 1, "description": "Table ID or table name accepted by the Airtable path parameter." }, "nullable": false, "handle": "tableIdOrName" }, { "description": "Records to create in the Airtable table.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "fields": { "type": "object", "additionalProperties": { "description": "A record value." }, "description": "Field values for the new Airtable record." } }, "required": [ "fields" ], "additionalProperties": false, "description": "Record payload used when creating Airtable records." }, "minItems": 1, "maxItems": 10, "description": "Records to create in the Airtable table." }, "nullable": false, "handle": "records" }, { "description": "Whether Airtable should coerce incoming values to compatible field types.", "jsonSchema": { "type": "boolean", "description": "Whether Airtable should coerce incoming values to compatible field types." }, "nullable": true, "handle": "typecast", "value": null }, { "description": "Whether Airtable should return field IDs instead of field names in record objects.", "jsonSchema": { "type": "boolean", "description": "Whether Airtable should return field IDs instead of field names in record objects." }, "nullable": true, "handle": "returnFieldsByFieldId", "value": null } ], "outputs": [ { "description": "Records created by Airtable.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Record ID." }, "createdTime": { "type": "string", "description": "Record creation timestamp returned by Airtable." }, "fields": { "type": "object", "additionalProperties": { "description": "A record value." }, "description": "Record fields keyed by field name or field ID." }, "commentCount": { "type": "integer", "description": "Comment count returned by Airtable when enabled on the endpoint." } }, "required": [ "id", "fields" ], "additionalProperties": true, "description": "Airtable record." }, "description": "Records created by Airtable." }, "nullable": false, "handle": "records" } ], "name": "Create Airtable job", "executor": { "kind": "connector", "action": "airtable.create_records" } } }, "n_ec022f4efb60e50b": { "name": "Created recruiting records", "kind": "outputs", "outputDefs": [ { "jsonSchema": { "type": "array", "items": { "type": "object" } }, "nullable": false, "handle": "receipts" }, { "jsonSchema": { "type": "integer", "minimum": 0 }, "nullable": false, "handle": "count" } ], "outputMappings": { "receipts": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_546c5edfbdab5910", "output": "state", "field": "receipts" } ] }, "count": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_546c5edfbdab5910", "output": "count" } ] } } } }, "edges": [ { "source": "n_57bfc98a208803af", "target": "n_b3e867634a884f92" }, { "source": "n_b3e867634a884f92", "target": "n_f94851172a9a1a3c" }, { "source": "n_f94851172a9a1a3c", "target": "n_c7a11e9a30b84278" }, { "source": "n_c7a11e9a30b84278", "target": "n_208245aecc0a799b", "sourceHandle": "more" }, { "source": "n_208245aecc0a799b", "target": "n_f94851172a9a1a3c" }, { "source": "n_c7a11e9a30b84278", "target": "n_6a6b56e4d23b86fd", "sourceHandle": "otherwise" }, { "source": "n_6a6b56e4d23b86fd", "target": "n_6ec060bd16059899" }, { "source": "n_6ec060bd16059899", "target": "n_ee00885f0daa2f67", "sourceHandle": "more" }, { "source": "n_ee00885f0daa2f67", "target": "n_6a6b56e4d23b86fd" }, { "source": "n_6ec060bd16059899", "target": "n_c09dd196183b0bd3", "sourceHandle": "otherwise" }, { "source": "n_c09dd196183b0bd3", "target": "n_0462a41b24db0e0b" }, { "source": "n_0462a41b24db0e0b", "target": "n_e48352a21e44b691", "sourceHandle": "more" }, { "source": "n_e48352a21e44b691", "target": "n_c09dd196183b0bd3" }, { "source": "n_0462a41b24db0e0b", "target": "n_546c5edfbdab5910", "sourceHandle": "otherwise" }, { "source": "n_546c5edfbdab5910", "target": "n_4f5187e98be33925" }, { "source": "n_4f5187e98be33925", "target": "n_63e22831ea8b7f03", "sourceHandle": "more" }, { "source": "n_63e22831ea8b7f03", "target": "n_546c5edfbdab5910" }, { "source": "n_4f5187e98be33925", "target": "n_ec022f4efb60e50b", "sourceHandle": "otherwise" } ] } }, "modules": { "n_496f1cac5da8034f": { "name": "Collect thread comment IDs", "imports": [], "source": "export default function collectHiringStories({ body, statusCode, bodyEncoding, previousState, story }) {\n let state;\n if (previousState === null) {\n if (statusCode < 200 || statusCode >= 300 || bodyEncoding !== null || !body || typeof body !== 'object' || !Array.isArray(body.hits)) throw new Error('Hacker News search did not return a successful JSON hit list.');\n const cutoff=Date.now()-30*24*60*60*1000;\n for(const hit of body.hits)if(!hit||typeof hit.created_at!=='string'||!Number.isFinite(Date.parse(hit.created_at)))throw new Error('Search story has an invalid creation timestamp.');\n const ids=body.hits.filter(hit=>Date.parse(hit.created_at)>cutoff).map(hit=>{const id=Number(hit.objectID);if(!Number.isSafeInteger(id)||id<=0)throw new Error('Search story has an invalid objectID.');return id;});\n state={index:0,ids,commentIds:[]};\n } else {\n const {index,ids,commentIds}=previousState;\n if(!Number.isSafeInteger(index)||index<0||index>=ids.length||story?.id!==ids[index]||story.type!=='story'||(story.kids!==undefined&&!Array.isArray(story.kids)))throw new Error('Hiring story does not match this read frame.');\n const kids=story.kids??[];if(kids.some(id=>!Number.isSafeInteger(id)||id<=0))throw new Error('Invalid hiring comment ID.');\n state={index:index+1,ids,commentIds:[...commentIds,...kids]};\n }\n return {state,itemId:state.ids[state.index]??1,more:state.index]*>/g,'').replace(/\\|\\s*/g,'| ').replace(/\\s+/g,' ').replace(/\\s*(https?:\\/\\/[^\\s]+)\\s*/g,'\\n$1\\n').replace(/\\n{3,}/g,'\\n\\n').trim();\n}\nexport default function collectHiringComments({commentIds,previousState,comment}){\n let state;\n if(previousState===null)state={index:0,selected:[]};\n else{\n const {index,selected}=previousState;\n if(!Number.isSafeInteger(index)||index<0||index>=commentIds.length||comment?.id!==commentIds[index]||comment.type!=='comment'||comment.deleted||comment.dead)throw new Error('Hiring comment is missing, deleted or does not match this read frame.');\n const text=cleanHiringText(comment.text);\n state={index:index+1,selected:selected.length<5?[...selected,{id:comment.id,text}]:selected};\n }\n return {state,itemId:commentIds[state.index]??1,more:state.indexObject.hasOwn(result,key)).map(key=>[key,result[key]]));\n}\nexport default function collectHiringResults({selected,previousState,completion}){\n let state;\n if(previousState===null)state={index:0,plans:[]};\n else{\n const {index,plans}=previousState;if(!Number.isSafeInteger(index)||index<0||index>=selected.length||plans.length!==index)throw new Error('Invalid hiring model frame.');\n state={index:index+1,plans:[...plans,{commentId:selected[index].id,result:validateHiringResult(completion)}]};\n }\n return {state,text:selected[state.index]?.text??'unused-completed-frame',more:state.index=plans.length||receipts.length!==index||!Array.isArray(records)||records.length!==1||typeof records[0]?.id!=='string'||!records[0].id)throw new Error('Airtable did not confirm exactly one hiring record.');\n state={index:index+1,receipts:[...receipts,{commentId:plans[index].commentId,recordId:records[0].id}]};\n }\n const result=plans[state.index]?.result??{};\n const fields=Object.fromEntries(Object.entries(result).filter(([key])=>key!=='work_location'));\n return {state,records:[{fields}],more:state.index