Sunday, 30 August 2026

junior devops engnr

 Position Overview:

We are a growing start up seeking a Junior Azure DevOps Engineer with 2 to 3 years of experience to support our Azure cloud environment. The role involves managing Azure App Services, maintaining Azure DevOps Pipelines and Git repositories and assisting with Microsoft 365 administration. The successful candidate will also support Azure PostgreSQL databases, networking configurations, domain management, and cloud cost monitoring using Azure Cost Management tools.


Position Title: Junior Azure DevOps Engineer


Job Classification: Full-time, Monday to Saturday, excluding 2nd and 4th Saturdays of each month


Hours: 48 hours per week (40 hours on the 2nd and 4th Saturdays of each month)


Reports To: Team Manager and Senior Backend Developer


Location: Fully Remote (Bring your own device)


link


Thursday, 20 August 2026

Friday, 14 August 2026

AI webnar

 

bout the Webinar

Most people are still using a single AI assistant to handle everything. That model is already breaking.

The shift is toward multi-agent systems, where specialized agents handle distinct tasks and pass work between each other, just like a real team. This Build-a-thon makes that shift tangible.

In 3 hours, instead of building a single-purpose bot or application, you’ll build a coordinated “super agent” system where:

  • One agent researches
  • One drafts
  • One reviews
  • One executes

And they work together without you managing every step manually. By the end, you won’t just understand the concept. You’ll have a working system.

📅 Aug 22, 2026 | ⏰ 10 AM to 1 PM IST

What This Build-a-thon Will Show You

You’ll build a multi-agent system from scratch in two phases:

Part 1: Agent Design + Setup

You’ll start by defining how real systems are structured:

  • Break down work into distinct agent roles
  • Build individual agents for research, drafting, review, and execution
  • Test each agent independently
  • Understand what happens when roles are too broad (and how to fix it)

Part 2: Orchestration + Handoffs

Then you’ll connect everything into a working system:

  • Build the orchestration layer that connects agents
  • Create structured handoffs between agents
  • Pass outputs between agents automatically
  • Add human checkpoints where they actually matter

By the end, your system runs end-to-end.

No Advanced Coding Required

This Build-a-thon is for people who are ready to move beyond basic AI usage. Join if you are:

  • A product, ops, or business professional handling repetitive workflows
  • An AI user who wants to build systems, not just write prompts
  • A founder or builder exploring agent-based automation
  • Anyone curious how enterprise AI systems are actually structured

If you can break down a workflow, you can build this.

Meet the Builder Behind the Build

Shubham Lal is an AI entrepreneur, technology leader, and former Microsoft engineer with over a decade of experience building across AI, software engineering, cloud, data science, and developer technologies. At Microsoft, he worked across enterprise cloud, AI, productivity, and developer-tooling teams, building technology at scale.

Today, he is the Founder and CEO of AI Linc, an AI-native education company focused on helping people learn and apply technology through hands-on building. Having worked across the engineering and AI ecosystem, Shubham brings a practical perspective on how AI systems are designed, built, and put to work.

Skills You’ll Build

  • Multi-agent system design
  • Task decomposition and role structuring
  • Agent orchestration and workflow design
  • Designing handoffs between AI systems
  • Human-in-the-loop system thinking
  • Practical automation architecture

Attendee-Only: Walk Away With More Than the Build

Attend the Build-a-thon live and unlock exclusive resources:

🎥 Full Session Recording + Participation Certificate: Revisit anytime and get certified for completing the session.

🧩 Multi-Agent System Blueprint: A practical guide to designing and building a multi-agent system for any workflow or use case.

🎁 Exclusive, Never-Seen-Before Offers: Unlock special discounts available only to Build-a-thon attendees.

Friday, 31 July 2026

ADE JOB

 Data Engineer (Night Shift - Remote)

Job ID: 378310
 Remote 

India

 

2 - 5 years




Remote Job Link

Positions: Data Engineer I & II
Timings: 5:30 PM IST to 3:30 AM IST (Remote India)


Job Description :
As a Data Engineer , you will be responsible for designing, developing, and maintaining the data infrastructure that powers our advertising technology platform. You will work closely with cross-functional teams to build scalable data pipelines, optimize data workflows, and ensure the reliability and performance of our data systems.


Responsibilities:
● Design, develop, and maintain ETL pipelines to collect, process, and store data from various sources.
● Work with APIs, databases, and other data sources to integrate data into the data warehouse.
● Implement and maintain data validation and monitoring processes to ensure data accuracy and reliability.
● Collaborate with data scientists, analysts, and other stakeholders to understand data needs and deliver solutions.
● Transform raw data into a form that is easily usable for analysis and business intelligence.
● Maintain comprehensive documentation of data pipelines, processes, and systems.
● Optimize data systems and pipelines for performance and scalability.


Requirements:
● Bachelor’s degree in Computer Science, Information Systems, or a related field.
● Minimum of 3 years of experience in data engineering or a related role.
● Proficiency in SQL and experience with at least one programming language such as Python.
● Experience with cloud-based data platforms (AWS, Azure, GCP) and services such as AWS Redshift or Google BigQuery.
● Knowledge of big data technologies like Hadoop, Spark, or Kafka is a plus.
● Experience with ETL tools such as Apache Airflow.
● Familiarity with data warehousing concepts and relational databases.
● Monitor and troubleshoot data pipeline issues, performance bottlenecks, and data quality issues in production environments.
● Implement data governance policies and procedures to ensure data integrity, security, and compliance with regulatory requirements.
● Understanding of data modeling and database design principles.
● Strong problem-solving and analytical skills.
● Excellent communication and collaboration skills.
● Ability to work independently and manage multiple tasks and projects simultaneously.
● Detail-oriented and committed to data quality.

Sunday, 26 July 2026

Job AI Remote

 https://adit.keka.com/careers/jobdetails/133505


Job Title: AI Engineer

Location: 100% Remote
Department: Product Team
Employment Type: Full-time

About the Role:

We are looking to hire enthusiastic and driven Software Engineers to join our AI Team. The ideal candidates should have foundational experience in AI/LLM development and Python, along with a strong interest in building and enhancing AI-driven solutions. This role offers an excellent opportunity to work on cutting-edge AI and LLM projects while collaborating with cross-functional teams.


Key Responsibilities:

  • Assist in the deployment of AI/LLM-based applications and tools.
  • Work with senior team members to implement and fine-tune machine learning and large language model (LLM) solutions.
  • Analyze, interpret, and validate outputs generated by AI tools such as ChatGPT.
  • Support research activities related to AI, LLMs, and emerging technologies.
  • Collaborate with the team to troubleshoot issues and optimize existing models and scripts.
  • Prepare clear documentation for code, experiments, and project workflows.


Required Qualifications:

  • 3+ years of experience in AI/LLM development and Python programming.
  • Candidates with relevant AI internships or hands-on academic projects will also be considered.
  • Strong understanding of Python fundamentals and basic machine learning concepts.
  • Familiarity with AI frameworks or tools (e.g., TensorFlow, PyTorch, Hugging Face) is a plus.
  • Ability to comprehend, interpret, and reason with outputs generated by LLM tools such as ChatGPT.
  • Strong communication skills and the ability to work in a collaborative, research-driven environment.


Desired Skills:

  • Knowledge of prompt engineering or experience experimenting with LLM APIs.
  • Understanding of data processing workflows and NLP concepts.
  • Problem-solving skills with a willingness to learn and explore new technologies.

Why Adit?

► We trust our people and offer completely remote opportunities.
► Flexible work schedules for better work-life balance.
► Group of 550+ Agile, Smart, and Dynamic IT Professionals.
► Supportive and collaborative work environment.
► 5-day working company (Monday - Friday). All weekends are off!
► Great working and learning environment
► Company-sponsored insurance

Saturday, 18 July 2026

sql jd harsco

 

SOL-7Senior BI Developer

Solution
Topic :  General

Job Description:

  • Experience working closely with business users/leaders.
  • Well-versed in requirement gathering and can lead business users in requirement gathering sessions.
  • Engage with stakeholders to define KPIs and reporting needs
  • Should have the ability to transform the requirements into a BI visualization.
  • Develop BI solutions with enterprise architecture
  • Drive innovation and adoption of best practices
  • Work closely with BI developers, Data Engineers, and Analysts in developing interactive and decision-making Power BI visualizations.

Key Responsibilities:

Client Engagement & Requirement Gathering:

  • Collaborate directly with clients and business stakeholders to understand and document BI requirements.
  • Conduct workshops and discovery sessions to define KPIs, reporting needs, and success criteria.

Solution Design & Proof of Concept Development:

  • Translate business requirements into intuitive and impactful BI visualizations.
  • Develop the proof of concepts (PoCs) to validate solution approaches and demonstrate value to stakeholders.
  • Present PoCs and prototypes to clients for feedback and refinement.

Technical Strategy & Governance:

  • Develop BI solutions with enterprise architecture and data governance standards.
  • Drive adoption of best practices in data modeling, visualization, and performance optimization.

Team Player:

  • Foster a culture of innovation, collaboration, and continuous improvement.

Technical Skills:

  • Advanced Power BI Development: - Expertise in building interactive dashboards and reports. Strong command of Power Query and DAX (including advanced functions).
  • Data Modeling & ETL: - Ability to design and optimize complex data models. Experience with data transformation pipelines.
  • SQL Proficiency: - Writing and debugging complex SQL queries. Performance tuning using SQL Server/Oracle.
  • Performance Optimization: - Use of tools like DAX Studio and SQL Profiler for report tuning.
  • Version Control & Deployment: - Git/Azure DevOps for version control for managing BI assets.
  • Agile/Scrum Practices: - Experience working in Agile environments


Education:

  • Bachelor's in Engineering (or) Technology /Master's in Computer Science Applications/Information Systems from a recognized College/University.
  • Experience
  • 6 To 10 years of experience in a BI reporting environment. 2 years in a lead role working closely with Business stakeholders and leading requirement gathering sessions.

Knowledge and Skills:

  • Hands-on experience in SQL, PL/SQL, Packages/Procedures.
  • Strong knowledge of DAX Studio, Tabular Editor, Power BI Report Builder, and ALM Tool Kit.
  • Good knowledge of Azure Cloud Computing

Preferred:

  • Certification in Microsoft PL-300, Microsoft AZ-900 and Microsoft DP-900.
  • Should have knowledge Software development life cycle.

Monday, 13 July 2026

non cluster index

 CREATE TABLE [HangFire].[Set] (

    [Key]      NVARCHAR (100) NOT NULL,

    [Score]    FLOAT (53)     NOT NULL,

    [Value]    NVARCHAR (256) NOT NULL,

    [ExpireAt] DATETIME       NULL,

    CONSTRAINT [PK_HangFire_Set] PRIMARY KEY CLUSTERED ([Key] ASC, [Value] ASC) WITH (IGNORE_DUP_KEY = ON)

);

GO


CREATE NONCLUSTERED INDEX [IX_HangFire_Set_ExpireAt]

    ON [HangFire].[Set]([ExpireAt] ASC) WHERE ([ExpireAt] IS NOT NULL);

GO


CREATE NONCLUSTERED INDEX [IX_HangFire_Set_Score]

    ON [HangFire].[Set]([Key] ASC, [Score] ASC);

GO


Friday, 10 July 2026

Enviri JD for BI

 Job Description:

  • Experience working closely with business users/leaders.
  • Well-versed in requirement gathering and can lead business users in requirement gathering sessions.
  • Engage with stakeholders to define KPIs and reporting needs
  • Should have the ability to transform the requirements into a BI visualization.
  • Develop BI solutions with enterprise architecture
  • Drive innovation and adoption of best practices
  • Work closely with BI developers, Data Engineers, and Analysts in developing interactive and decision-making Power BI visualizations.

Key Responsibilities:

Client Engagement & Requirement Gathering:

  • Collaborate directly with clients and business stakeholders to understand and document BI requirements.
  • Conduct workshops and discovery sessions to define KPIs, reporting needs, and success criteria.

Solution Design & Proof of Concept Development:

  • Translate business requirements into intuitive and impactful BI visualizations.
  • Develop the proof of concepts (PoCs) to validate solution approaches and demonstrate value to stakeholders.
  • Present PoCs and prototypes to clients for feedback and refinement.

Technical Strategy & Governance:

  • Develop BI solutions with enterprise architecture and data governance standards.
  • Drive adoption of best practices in data modeling, visualization, and performance optimization.

Team Player:

  • Foster a culture of innovation, collaboration, and continuous improvement.

Technical Skills:

  • Advanced Power BI Development: - Expertise in building interactive dashboards and reports. Strong command of Power Query and DAX (including advanced functions).
  • Data Modeling & ETL: - Ability to design and optimize complex data models. Experience with data transformation pipelines.
  • SQL Proficiency: - Writing and debugging complex SQL queries. Performance tuning using SQL Server/Oracle.
  • Performance Optimization: - Use of tools like DAX Studio and SQL Profiler for report tuning.
  • Version Control & Deployment: - Git/Azure DevOps for version control for managing BI assets.
  • Agile/Scrum Practices: - Experience working in Agile environments


Education:

  • Bachelor's in Engineering (or) Technology /Master's in Computer Science Applications/Information Systems from a recognized College/University.
  • Experience
  • 6 To 10 years of experience in a BI reporting environment. 2 years in a lead role working closely with Business stakeholders and leading requirement gathering sessions.

Knowledge and Skills:

  • Hands-on experience in SQL, PL/SQL, Packages/Procedures.
  • Strong knowledge of DAX Studio, Tabular Editor, Power BI Report Builder, and ALM Tool Kit.
  • Good knowledge of Azure Cloud Computing

Preferred:

  • Certification in Microsoft PL-300, Microsoft AZ-900 and Microsoft DP-900.
  • Should have knowledge Software development life cycle.

Script download chat Gpt chat converstaion

 Note:copy below script code and paste in console window for which chat gpt chat history you want.then enter.


 (async () => {
  "use strict";

  const SCROLL_STEP_RATIO = 1.8;
  const MAX_SCROLL_PASSES = 220;
  const IDLE_PASSES_TO_STOP = 4;
  const PDF_LIB_URL = "https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js";

  function sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
  }

  function createProgressPanel() {
    const panel = document.createElement("div");
    panel.style.position = "fixed";
    panel.style.top = "18px";
    panel.style.right = "18px";
    panel.style.zIndex = "2147483647";
    panel.style.width = "320px";
    panel.style.background = "#ffffff";
    panel.style.border = "1px solid #d8dee8";
    panel.style.borderRadius = "14px";
    panel.style.boxShadow = "0 12px 30px rgba(15, 23, 42, 0.18)";
    panel.style.padding = "14px";
    panel.style.font = '13px/1.4 "Segoe UI", Arial, sans-serif';
    panel.style.color = "#111827";

    const title = document.createElement("div");
    title.textContent = "Loading conversation...";
    title.style.fontWeight = "700";

    const status = document.createElement("div");
    status.textContent = "Preparing fast auto-scroll";
    status.style.marginTop = "6px";
    status.style.color = "#4b5563";

    const cancel = document.createElement("button");
    cancel.type = "button";
    cancel.textContent = "Cancel";
    cancel.style.marginTop = "12px";
    cancel.style.border = "1px solid #cbd5e1";
    cancel.style.background = "#f8fafc";
    cancel.style.borderRadius = "8px";
    cancel.style.padding = "6px 12px";
    cancel.style.cursor = "pointer";

    panel.appendChild(title);
    panel.appendChild(status);
    panel.appendChild(cancel);
    document.body.appendChild(panel);

    const state = { cancelled: false };
    cancel.addEventListener("click", () => {
      state.cancelled = true;
      status.textContent = "Cancelling...";
      cancel.disabled = true;
    });

    return {
      isCancelled: () => state.cancelled,
      update: (text) => {
        status.textContent = text;
      },
      done: () => {
        panel.remove();
      }
    };
  }

  function loadScript(url) {
    return new Promise((resolve, reject) => {
      const existing = Array.from(document.querySelectorAll("script")).find((s) => s.src === url);
      if (existing && window.html2pdf) {
        resolve();
        return;
      }

      const script = document.createElement("script");
      script.src = url;
      script.async = true;
      script.onload = () => resolve();
      script.onerror = () => reject(new Error(`Failed to load script: ${url}`));
      document.head.appendChild(script);
    });
  }

  function chooseExportFormat() {
    const raw = (prompt("Export format? Type WORD or PDF", "WORD") || "WORD").trim().toLowerCase();
    return raw === "pdf" ? "pdf" : "word";
  }

  function chooseExportScope() {
    const help = [
      "Export scope?",
      "1 = Complete conversation",
      "2 = Single ChatGPT response (latest)",
      "3 = Selected messages (highlight text first)",
      "4 = ChatGPT responses only"
    ].join("\n");
    const raw = (prompt(help, "1") || "1").trim().toLowerCase();

    if (raw === "2" || raw === "single") {
      return "single";
    }
    if (raw === "3" || raw === "selected") {
      return "selected";
    }
    if (raw === "4" || raw === "assistant" || raw === "chatgpt") {
      return "assistant";
    }
    return "all";
  }

  function getSelectionMessageNodes() {
    const selection = window.getSelection();
    if (!selection || !selection.rangeCount || selection.isCollapsed) {
      return [];
    }

    const range = selection.getRangeAt(0);
    const all = Array.from(document.querySelectorAll("[data-message-author-role]"));
    return all.filter((node) => {
      try {
        return range.intersectsNode(node);
      } catch (_error) {
        return false;
      }
    });
  }

  function normalizeText(text) {
    return (text || "").replace(/\r\n/g, "\n").trim();
  }

  function cleanFileName(name) {
    return (name || "chatgpt-chat")
      .replace(/[\\/:*?"<>|]/g, "-")
      .replace(/\s+/g, " ")
      .trim()
      .slice(0, 80);
  }

  function normalizePossibleTitle(value) {
    return (value || "")
      .replace(/\s+/g, " ")
      .replace(/\s*-\s*ChatGPT\s*$/i, "")
      .trim();
  }

  function pickBestTitle(candidates) {
    const cleaned = candidates
      .map((x) => normalizePossibleTitle(x))
      .filter((x) => x && x.length > 1 && !/^chatgpt$/i.test(x));

    if (!cleaned.length) {
      return "chatgpt-chat";
    }

    // Prefer longer descriptive titles over short/generic labels.
    cleaned.sort((a, b) => b.length - a.length);
    return cleaned[0];
  }

  function resolveConversationTitle() {
    const titleCandidates = [];

    // Browser title is usually the most reliable conversation title.
    titleCandidates.push(document.title || "");

    const metaOg = document.querySelector('meta[property="og:title"]')?.getAttribute("content") || "";
    const metaTwitter = document.querySelector('meta[name="twitter:title"]')?.getAttribute("content") || "";
    titleCandidates.push(metaOg, metaTwitter);

    const selectorCandidates = [
      '[data-testid="conversation-title"]',
      'a[aria-current="page"]',
      'nav [aria-current="page"]',
      'main header h1',
      'header h1'
    ];

    selectorCandidates.forEach((selector) => {
      const el = document.querySelector(selector);
      if (el) {
        titleCandidates.push(el.textContent || "", el.getAttribute("title") || "");
      }
    });

    return pickBestTitle(titleCandidates);
  }

  function escapeHtml(input) {
    return (input || "")
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/\"/g, "&quot;")
      .replace(/'/g, "&#39;");
  }

  function blobToDataUrl(blob) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => resolve(reader.result);
      reader.onerror = () => reject(new Error("Failed to read image blob."));
      reader.readAsDataURL(blob);
    });
  }

  async function imageUrlToDataUrl(url) {
    if (!url) {
      throw new Error("Image URL is empty.");
    }

    if (url.startsWith("data:")) {
      return url;
    }

    const response = await fetch(url, { credentials: "include" });
    if (!response.ok) {
      throw new Error(`Image fetch failed with ${response.status}`);
    }

    const blob = await response.blob();
    return blobToDataUrl(blob);
  }

  function imageElementToDataUrl(imgEl) {
    try {
      if (!imgEl || !imgEl.naturalWidth || !imgEl.naturalHeight) {
        return null;
      }
      const canvas = document.createElement("canvas");
      canvas.width = imgEl.naturalWidth;
      canvas.height = imgEl.naturalHeight;
      const ctx = canvas.getContext("2d");
      if (!ctx) {
        return null;
      }
      ctx.drawImage(imgEl, 0, 0);
      return canvas.toDataURL("image/png");
    } catch (_error) {
      return null;
    }
  }

  function getImageSource(imgEl) {
    if (!imgEl) {
      return "";
    }
    return (
      imgEl.currentSrc ||
      imgEl.getAttribute("src") ||
      imgEl.getAttribute("data-src") ||
      imgEl.getAttribute("data-original") ||
      ""
    );
  }

  function getScrollableContainer() {
    const all = Array.from(document.querySelectorAll("div, main, section"));
    const candidates = all.filter((el) => {
      const style = window.getComputedStyle(el);
      const canScroll = /(auto|scroll)/.test(style.overflowY);
      return canScroll && el.scrollHeight > el.clientHeight + 120;
    });

    candidates.sort((a, b) => b.scrollHeight - a.scrollHeight);
    return candidates[0] || document.scrollingElement || document.documentElement;
  }

  function textHash(input) {
    const str = input || "";
    let hash = 0;
    for (let i = 0; i < str.length; i += 1) {
      hash = (hash << 5) - hash + str.charCodeAt(i);
      hash |= 0;
    }
    return String(hash);
  }

  function getStableMessageId(node) {
    return (
      node.getAttribute("data-message-id") ||
      node.getAttribute("data-testid") ||
      node.getAttribute("id") ||
      ""
    );
  }

  function getNodeFingerprint(node) {
    const role = (node.getAttribute("data-message-author-role") || "").toLowerCase();
    const stableId = getStableMessageId(node);
    const text = normalizeText(node.innerText).replace(/\s+/g, " ");
    const shortText = text.slice(0, 1000);
    const imageCount = node.querySelectorAll("img").length;
    return `${role}|id:${stableId}|txt:${textHash(shortText)}|img:${imageCount}`;
  }

  function collectVisibleMessages(store, sequenceState) {
    const visibleNodes = Array.from(document.querySelectorAll("[data-message-author-role]"));
    visibleNodes.forEach((node) => {
      const key = getNodeFingerprint(node);
      const existing = store.get(key);
      if (!existing) {
        store.set(key, {
          key,
          node,
          firstSeen: sequenceState.value
        });
        sequenceState.value += 1;
      } else {
        existing.node = node;
      }
    });
  }

  async function collectEntireConversation(progress) {
    const container = getScrollableContainer();
    const messagesMap = new Map();

    if (!container) {
      return [];
    }

    // Start at top and collect strictly while moving top -> bottom.
    progress.update("Phase 1/1: Jumping to top...");
    container.scrollTop = 0;
    await sleep(140);

    const step = Math.max(200, Math.floor(container.clientHeight * SCROLL_STEP_RATIO));

    // Collect while sweeping top -> bottom so ordering remains stable.
    progress.update("Phase 1/1: Sweeping top to bottom...");
    const sequenceState = { value: 0 };
    let idlePasses = 0;
    let previousCount = -1;
    let previousScroll = -1;

    for (let pass = 0; pass < MAX_SCROLL_PASSES; pass += 1) {
      if (progress.isCancelled()) {
        return [];
      }

      collectVisibleMessages(messagesMap, sequenceState);

      if (pass % 8 === 0) {
        progress.update(`Phase 1/1: Sweeping... ${messagesMap.size} messages captured`);
      }

      const currentCount = messagesMap.size;
      if (currentCount === previousCount) {
        idlePasses += 1;
      } else {
        idlePasses = 0;
      }
      previousCount = currentCount;

      const beforeTop = container.scrollTop;
      container.scrollTop = Math.min(container.scrollHeight, beforeTop + step);
      await sleep(40);

      const atBottom = container.scrollTop + container.clientHeight >= container.scrollHeight - 4;
      const stuck = container.scrollTop === previousScroll;
      previousScroll = container.scrollTop;

      if (atBottom) {
        collectVisibleMessages(messagesMap, sequenceState);
        await sleep(100);
        collectVisibleMessages(messagesMap, sequenceState);
        if (idlePasses >= IDLE_PASSES_TO_STOP || stuck) {
          break;
        }
      }
    }

    const collected = Array.from(messagesMap.values());
    collected.sort((a, b) => a.firstSeen - b.firstSeen);

    return collected.map((x) => x.node);
  }

  function getMessageContentNode(messageNode) {
    const candidates = [
      ".markdown",
      ".prose",
      ".whitespace-pre-wrap",
      "[data-testid='conversation-turn-content']"
    ];

    for (const selector of candidates) {
      const el = messageNode.querySelector(selector);
      if (el && normalizeText(el.innerText)) {
        return el;
      }
    }

    return messageNode;
  }

  async function buildMessagePayload(messageNode) {
    const contentNode = getMessageContentNode(messageNode);
    const text = normalizeText(contentNode.innerText);

    const clonedContent = contentNode.cloneNode(true);
    const clonedImages = Array.from(clonedContent.querySelectorAll("img"));
    const sourceImages = Array.from(contentNode.querySelectorAll("img"));

    await Promise.all(
      clonedImages.map(async (img, index) => {
        const srcImg = sourceImages[index];
        const src = getImageSource(srcImg) || getImageSource(img);

        if (!src) {
          img.remove();
          return;
        }

        try {
          const dataUrl = await imageUrlToDataUrl(src);
          img.setAttribute("src", dataUrl);
        } catch (_error) {
          const drawnData = imageElementToDataUrl(srcImg || img);
          if (drawnData) {
            img.setAttribute("src", drawnData);
          } else {
            // Keep original source as fallback if inlining fails.
            img.setAttribute("src", src);
          }
        }

        img.removeAttribute("srcset");
        img.removeAttribute("sizes");
        img.setAttribute("loading", "eager");
      })
    );

    const html = clonedContent.innerHTML && clonedContent.innerHTML.trim().length
      ? clonedContent.innerHTML
      : escapeHtml(contentNode.innerText).replace(/\n/g, "<br>");

    return { text, html };
  }

  function filterMessagesByScope(messageNodes, scope) {
    if (scope === "assistant") {
      return messageNodes.filter(
        (node) => (node.getAttribute("data-message-author-role") || "").toLowerCase() === "assistant"
      );
    }

    if (scope === "single") {
      const latestAssistant = [...messageNodes]
        .reverse()
        .find((node) => (node.getAttribute("data-message-author-role") || "").toLowerCase() === "assistant");
      return latestAssistant ? [latestAssistant] : [];
    }

    if (scope === "selected") {
      const selectedNodes = getSelectionMessageNodes();
      if (selectedNodes.length) {
        return selectedNodes;
      }
      alert("No selected messages found. Please highlight message text first. Exporting complete conversation instead.");
      return messageNodes;
    }

    return messageNodes;
  }

  function buildMetaLabel(scope) {
    if (scope === "assistant") {
      return "ChatGPT responses only";
    }
    if (scope === "single") {
      return "Single ChatGPT response";
    }
    if (scope === "selected") {
      return "Selected messages";
    }
    return "Complete conversation";
  }

  function scopeSuffix(scope) {
    if (scope === "assistant") {
      return "assistant-only";
    }
    if (scope === "single") {
      return "single-response";
    }
    if (scope === "selected") {
      return "selected";
    }
    return "full-chat";
  }

  async function exportAsPdf(htmlDoc, fileNameBase) {
    await loadScript(PDF_LIB_URL);
    if (!window.html2pdf) {
      throw new Error("PDF engine did not load.");
    }

    const holder = document.createElement("div");
    holder.style.position = "fixed";
    holder.style.left = "-100000px";
    holder.style.top = "0";
    holder.style.width = "1280px";
    holder.style.background = "#ffffff";
    holder.innerHTML = htmlDoc;
    document.body.appendChild(holder);

    const target = holder.querySelector("body") || holder;
    const opt = {
      margin: [8, 8, 8, 8],
      filename: `${fileNameBase}.pdf`,
      image: { type: "jpeg", quality: 0.98 },
      html2canvas: { scale: 2, useCORS: true, allowTaint: true },
      jsPDF: { unit: "mm", format: "a4", orientation: "portrait" },
      pagebreak: { mode: ["css", "legacy"] }
    };

    await window.html2pdf().set(opt).from(target).save();
    holder.remove();
  }

  function exportAsWord(htmlDoc, fileNameBase) {
    const blob = new Blob([htmlDoc], { type: "application/msword;charset=utf-8" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `${fileNameBase}.doc`;
    document.body.appendChild(a);
    a.click();
    a.remove();
    URL.revokeObjectURL(url);
    return a.download;
  }

  const exportFormat = chooseExportFormat();
  const exportScope = chooseExportScope();

  const progress = createProgressPanel();
  const collectedNodes = await collectEntireConversation(progress);
  progress.done();

  if (!collectedNodes.length) {
    alert("Export cancelled or no messages collected.");
    return;
  }

  const messageNodes = filterMessagesByScope(collectedNodes, exportScope);

  if (!messageNodes.length) {
    alert("No messages matched your export scope.");
    return;
  }

  const entriesRaw = await Promise.all(
    messageNodes.map(async (node) => {
      const roleRaw = (node.getAttribute("data-message-author-role") || "").toLowerCase();
      const role = roleRaw === "assistant" ? "ChatGPT" : roleRaw === "user" ? "You" : "System";
      const payload = await buildMessagePayload(node);
      return { role, text: payload.text, html: payload.html, roleRaw };
    })
  );

  const entries = entriesRaw.filter((x) => x.text.length > 0);

  if (!entries.length) {
    alert("Messages were found, but text content could not be extracted.");
    return;
  }

  const title = cleanFileName(resolveConversationTitle());

  const now = new Date();
  const stamp = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(
    now.getDate()
  ).padStart(2, "0")}`;
  const scopeName = buildMetaLabel(exportScope);
  const fileNameBase = `${title}_${scopeSuffix(exportScope)}_${stamp}`;

  const messagesHtml = entries
    .map((e) => {
      const roleClass = e.roleRaw === "user" ? "user" : e.roleRaw === "assistant" ? "assistant" : "system";
      return `
        <article class="msg ${roleClass}">
          <div class="role">${escapeHtml(e.role)}</div>
          <div class="content">${e.html}</div>
        </article>
      `;
    })
    .join("\n");

  const htmlDoc = `<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>${escapeHtml(title)}</title>
  <style>
    :root {
      --page-bg: #f3f6fb;
      --ink: #1f2937;
      --muted: #5b6470;
      --card: #ffffff;
      --user-accent: #2864dc;
      --assistant-accent: #16a085;
      --system-accent: #7a5ccf;
      --code-bg: #f1f3f6;
      --code-ink: #1a1f2a;
      --line: #dde2ea;
    }

    * { box-sizing: border-box; }

    body {
      margin: 0;
      color: var(--ink);
      font: 15px/1.6 "Segoe UI", Tahoma, Arial, sans-serif;
      background:
        radial-gradient(circle at 10% 0%, #ffffff 0%, #eaf0ff 35%, transparent 60%),
        radial-gradient(circle at 100% 10%, #e8fff8 0%, transparent 35%),
        var(--page-bg);
      padding: 28px;
    }

    .sheet {
      max-width: 900px;
      margin: 0 auto;
      background: var(--card);
      border: 1px solid var(--line);
      border-radius: 18px;
      box-shadow: 0 12px 35px rgba(12, 22, 44, 0.08);
      padding: 28px;
    }

    .head h1 {
      margin: 0;
      font-size: 26px;
      line-height: 1.25;
    }

    .meta {
      margin-top: 6px;
      color: var(--muted);
      font-size: 13px;
    }

    .meta + .meta {
      margin-top: 2px;
    }

    .timeline {
      margin-top: 22px;
      display: grid;
      gap: 14px;
    }

    .msg {
      border: 1px solid var(--line);
      border-left-width: 6px;
      border-radius: 14px;
      padding: 14px 16px;
      background: #fff;
    }

    .msg.user { border-left-color: var(--user-accent); background: #f8fbff; }
    .msg.assistant { border-left-color: var(--assistant-accent); }
    .msg.system { border-left-color: var(--system-accent); background: #fbfaff; }

    .role {
      font-size: 12px;
      letter-spacing: 0.05em;
      text-transform: uppercase;
      font-weight: 700;
      color: var(--muted);
      margin-bottom: 8px;
    }

    .content h1, .content h2, .content h3, .content h4 {
      margin: 0.8em 0 0.35em;
      line-height: 1.3;
    }

    .content h1 { font-size: 24px; }
    .content h2 { font-size: 21px; }
    .content h3 { font-size: 18px; }
    .content h4 { font-size: 16px; }

    .content p { margin: 0.4em 0 0.75em; }
    .content ul, .content ol { margin: 0.4em 0 0.9em 1.4em; }
    .content li { margin: 0.22em 0; }
    .content blockquote {
      margin: 0.8em 0;
      border-left: 4px solid #c5d4f2;
      padding: 0.3em 0.8em;
      color: #3e4b63;
      background: #f8fbff;
    }

    .content pre {
      margin: 0.8em 0;
      background: var(--code-bg);
      color: var(--code-ink);
      border: 1px solid #d7dde7;
      border-radius: 12px;
      padding: 12px 14px;
      overflow: auto;
      white-space: pre-wrap;
      word-break: break-word;
      font: 13px/1.5 Consolas, "Courier New", monospace;
    }

    .content code {
      background: #eef2f8;
      border: 1px solid #d8dfe9;
      border-radius: 6px;
      padding: 1px 5px;
      font: 12px Consolas, "Courier New", monospace;
    }

    .content pre code {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 0;
      font: inherit;
    }

    .content table {
      border-collapse: collapse;
      margin: 0.8em 0;
      width: 100%;
    }

    .content img {
      display: block;
      max-width: 100%;
      height: auto;
      margin: 0.7em 0;
      border: 1px solid #d7dde7;
      border-radius: 10px;
    }

    .content th,
    .content td {
      border: 1px solid var(--line);
      padding: 6px 8px;
      text-align: left;
      vertical-align: top;
    }
  </style>
</head>
<body>
  <main class="sheet">
    <header class="head">
      <h1>${escapeHtml(title)}</h1>
      <div class="meta">Exported on ${escapeHtml(now.toLocaleString())}</div>
      <div class="meta">Scope: ${escapeHtml(scopeName)} | Format: ${escapeHtml(exportFormat.toUpperCase())}</div>
    </header>
    <section class="timeline">
      ${messagesHtml}
    </section>
  </main>
</body>
</html>`;

  let downloadName = "";
  if (exportFormat === "pdf") {
    await exportAsPdf(htmlDoc, fileNameBase);
    downloadName = `${fileNameBase}.pdf`;
  } else {
    downloadName = exportAsWord(htmlDoc, fileNameBase);
  }

  const container = getScrollableContainer();
  if (container) {
    container.scrollTop = container.scrollHeight;
  }

  console.log(`Export complete: ${downloadName}`);
  alert(`Exported ${entries.length} messages to ${downloadName}`);
})();

junior devops engnr

  Position Overview: We are a growing start up seeking a Junior Azure DevOps Engineer with 2 to 3 years of experience to support our Azure...