// @bun
import {
  DEV_SERVER_DOWN_ERROR,
  getDevServerConfig,
  getDevServerWorkflow,
  listDevServerWorkflows
} from "./chunk-91ams3v9.js";
import {
  JSON_ONLY_FORMAT_ERROR,
  ensureJsonOnlyFormat
} from "./chunk-5zqmmchg.js";
import {
  createCliLogger
} from "./chunk-t993tmz7.js";
import"./chunk-px7fts59.js";
import {
  getProjectClient
} from "./chunk-7krp2mgz.js";
import"./chunk-np5wcwfv.js";
import"./chunk-je8v6rhj.js";
import"./chunk-6w0knnta.js";
import"./chunk-w15xmtkn.js";
import"./chunk-3sd5p4qp.js";
import"./chunk-nh2akp42.js";
import"./chunk-kat1bv74.js";
import"./chunk-2a5b6azq.js";
import"./chunk-s8cp3qe6.js";
import"./chunk-fv5teh9w.js";
import"./chunk-8ab2w9a1.js";
import"./chunk-3xrpxgq4.js";
import"./chunk-w346ejn9.js";
import"./chunk-n8gath4k.js";
import"./chunk-v3ens42y.js";
import"./chunk-8839jtgk.js";
import"./chunk-s2akeqpw.js";
import"./chunk-6771vrjp.js";
import"./chunk-g8mm42v1.js";
import"./chunk-0q5d80bn.js";
import"./chunk-300xaact.js";
import"./chunk-b8c41yvb.js";
import"./chunk-jsqe5am4.js";
import"./chunk-m4c14gcg.js";
import"./chunk-gspjbr79.js";
import"./chunk-wesykvkp.js";
import"./chunk-gzj56z73.js";
import"./chunk-dhs2bg35.js";

// src/commands/adk-workflows.ts
import { fstatSync } from "fs";
var DEFAULT_WAIT_TIMEOUT = "60s";
var DEFAULT_POLL_INTERVAL_MS = 1000;
var PAYLOAD_NOT_OBJECT_ERROR = `Payload must be a JSON object (e.g. '{"key":"value"}').`;
class WorkflowCommandError extends Error {
  exitCode;
  json;
  constructor(message, options = {}) {
    super(message);
    this.name = "WorkflowCommandError";
    this.exitCode = options.exitCode ?? 1;
    this.json = options.json;
  }
}
function ensureWorkflowJsonOnlyFormat(format) {
  try {
    ensureJsonOnlyFormat(format);
  } catch {
    throw new WorkflowCommandError(JSON_ONLY_FORMAT_ERROR);
  }
}
function formatScalar(value) {
  if (value === null) {
    return "null";
  }
  switch (typeof value) {
    case "string":
      return value;
    case "number":
      return String(value);
    case "boolean":
      return value ? "true" : "false";
    default:
      return String(value);
  }
}
function appendYamlLikeValue(lines, key, value, indent) {
  const prefix = " ".repeat(indent);
  const keyLabel = `${key}:`;
  if (Array.isArray(value)) {
    if (value.length === 0) {
      lines.push(`${prefix}${keyLabel} []`);
      return;
    }
    lines.push(`${prefix}${keyLabel}`);
    for (const item of value) {
      appendYamlLikeListItem(lines, item, indent + 2);
    }
    return;
  }
  if (value && typeof value === "object") {
    const entries = Object.entries(value);
    if (entries.length === 0) {
      lines.push(`${prefix}${keyLabel} {}`);
      return;
    }
    lines.push(`${prefix}${keyLabel}`);
    for (const [childKey, childValue] of entries) {
      appendYamlLikeValue(lines, childKey, childValue, indent + 2);
    }
    return;
  }
  lines.push(`${prefix}${keyLabel} ${formatScalar(value)}`);
}
function appendYamlLikeListItem(lines, value, indent) {
  const prefix = " ".repeat(indent);
  if (Array.isArray(value)) {
    if (value.length === 0) {
      lines.push(`${prefix}- []`);
      return;
    }
    lines.push(`${prefix}-`);
    for (const item of value) {
      appendYamlLikeListItem(lines, item, indent + 2);
    }
    return;
  }
  if (value && typeof value === "object") {
    const entries = Object.entries(value);
    if (entries.length === 0) {
      lines.push(`${prefix}- {}`);
      return;
    }
    const [firstKey, firstValue] = entries[0];
    if (Array.isArray(firstValue) || firstValue && typeof firstValue === "object") {
      lines.push(`${prefix}- ${firstKey}:`);
      if (Array.isArray(firstValue)) {
        for (const item of firstValue) {
          appendYamlLikeListItem(lines, item, indent + 4);
        }
      } else {
        for (const [childKey, childValue] of Object.entries(firstValue)) {
          appendYamlLikeValue(lines, childKey, childValue, indent + 4);
        }
      }
    } else {
      lines.push(`${prefix}- ${firstKey}: ${formatScalar(firstValue)}`);
    }
    for (const [childKey, childValue] of entries.slice(1)) {
      appendYamlLikeValue(lines, childKey, childValue, indent + 2);
    }
    return;
  }
  lines.push(`${prefix}- ${formatScalar(value)}`);
}
function formatWorkflowForText(workflow, options = {}) {
  const lines = [];
  appendYamlLikeValue(lines, "name", workflow.name, 0);
  appendYamlLikeValue(lines, "description", workflow.description ?? "\u2014", 0);
  appendYamlLikeValue(lines, "schedule", workflow.schedule ?? "manual", 0);
  appendYamlLikeValue(lines, "timeout", workflow.timeout ?? "\u2014", 0);
  if (options.includeInputSchema) {
    lines.push("inputSchema:");
    for (const line of JSON.stringify(workflow.inputSchema, null, 2).split(`
`)) {
      lines.push(`  ${line}`);
    }
  }
  return lines.join(`
`);
}
async function readPipedStdin(stdin) {
  if (!stdinHasPipedData(stdin)) {
    return;
  }
  let raw = "";
  for await (const chunk of stdin) {
    raw += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
  }
  return raw.trim() === "" ? undefined : raw;
}
function stdinHasPipedData(stdin) {
  if (stdin.isTTY) {
    return false;
  }
  const fd = "fd" in stdin && typeof stdin.fd === "number" ? stdin.fd : undefined;
  if (fd !== undefined) {
    try {
      const stat = fstatSync(fd);
      if (stat.isFIFO() || stat.isFile() || stat.isSocket()) {
        return true;
      }
      if (stat.isCharacterDevice()) {
        return false;
      }
    } catch {}
  }
  return true;
}
function isPlainObject(value) {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}
async function resolvePayload(payloadArg, stdin) {
  const rawPayload = payloadArg ?? await readPipedStdin(stdin);
  if (rawPayload === undefined) {
    return;
  }
  let parsed;
  try {
    parsed = JSON.parse(rawPayload);
  } catch (error) {
    throw new WorkflowCommandError(`Invalid JSON payload: ${error instanceof Error ? error.message : String(error)}`);
  }
  if (!isPlainObject(parsed)) {
    throw new WorkflowCommandError(PAYLOAD_NOT_OBJECT_ERROR);
  }
  return parsed;
}
function getRequiredInputShape(inputSchema) {
  const required = Array.isArray(inputSchema.required) ? inputSchema.required.filter((field) => typeof field === "string") : [];
  return required.length > 0 ? { required } : null;
}
function parseDuration(duration) {
  const label = duration ?? DEFAULT_WAIT_TIMEOUT;
  const match = label.match(/^(\d+)(ms|s|m|h)$/);
  if (!match) {
    throw new WorkflowCommandError("Invalid timeout. Use a duration like 500ms, 30s, 1m, or 5m.");
  }
  const value = Number(match[1]);
  const unit = match[2];
  const multiplier = unit === "ms" ? 1 : unit === "s" ? 1000 : unit === "m" ? 60000 : 3600000;
  return {
    ms: value * multiplier,
    label
  };
}
function isTerminalStatus(status) {
  return status === "completed" || status === "failed" || status === "cancelled" || status === "timedout";
}
function resolveDuration(workflow, startedAt, endedAt) {
  if (typeof workflow.duration === "number") {
    return workflow.duration;
  }
  const finishedAt = workflow.endedAt ?? workflow.updatedAt;
  if (workflow.createdAt && finishedAt) {
    const started = Date.parse(workflow.createdAt);
    const ended = Date.parse(finishedAt);
    if (Number.isFinite(started) && Number.isFinite(ended)) {
      return Math.max(0, ended - started);
    }
  }
  return Math.max(0, endedAt - startedAt);
}
function buildWorkflowWaitOutput(workflowId, name, workflow, startedAt, endedAt) {
  const output = {
    workflowId,
    workflow: name,
    status: workflow.status,
    duration: resolveDuration(workflow, startedAt, endedAt)
  };
  if (workflow.output !== undefined) {
    output.output = workflow.output;
  }
  return output;
}
async function getClientFromDevServer() {
  const config = await getDevServerConfig();
  const credentials = config.credentials ?? {};
  const token = typeof credentials.token === "string" ? credentials.token : undefined;
  const botId = typeof credentials.devBotId === "string" ? credentials.devBotId : undefined;
  const apiUrl = typeof credentials.apiUrl === "string" ? credentials.apiUrl : undefined;
  const workspaceId = typeof credentials.workspaceId === "string" ? credentials.workspaceId : undefined;
  if (!token || !botId) {
    throw new WorkflowCommandError("Could not get credentials from dev server. Ensure the bot is properly linked.");
  }
  return getProjectClient({
    credentials: {
      token,
      apiUrl: apiUrl || "https://api.botpress.cloud",
      ...workspaceId ? { workspaceId } : {}
    },
    botId
  });
}
async function resolveStatePayload(client, payload) {
  if (!payload || typeof payload !== "object")
    return payload;
  const p = payload;
  if (p.location?.type === "state" && "value" in p)
    return p.value;
  if (p.location?.type !== "file" || !p.location.key)
    return payload;
  try {
    const { file } = await client.getFile({ id: p.location.key });
    const res = await fetch(file.url);
    if (!res.ok) {
      throw new Error(`HTTP ${res.status}${res.statusText ? ` ${res.statusText}` : ""}`);
    }
    return await res.json();
  } catch (error) {
    throw new WorkflowCommandError(`Failed to resolve file-swapped state payload (key=${p.location.key}): ${error instanceof Error ? error.message : String(error)}`);
  }
}
async function fetchWorkflowStateDoc(client, workflowId, name) {
  const response = await client.getState({ type: "workflow", id: workflowId, name });
  const resolved = await resolveStatePayload(client, response.state.payload);
  return { updatedAt: response.state.updatedAt, payload: resolved };
}
function isRecord(value) {
  return typeof value === "object" && value !== null;
}
function isMissingStateDocError(error) {
  if (!isRecord(error))
    return false;
  const response = isRecord(error.response) ? error.response : undefined;
  const code = error.code ?? error.status ?? error.statusCode ?? response?.status;
  const type = typeof error.type === "string" ? error.type : undefined;
  const name = typeof error.name === "string" ? error.name : undefined;
  return code === 404 || code === "404" || type === "ResourceNotFound" || name === "ResourceNotFoundError";
}
function formatErrorMessage(error) {
  return error instanceof Error ? error.message : String(error);
}
async function fetchWorkflowStateDocForRuns(client, workflowId, name) {
  try {
    return { doc: await fetchWorkflowStateDoc(client, workflowId, name) };
  } catch (error) {
    if (isMissingStateDocError(error)) {
      return { doc: null };
    }
    return { doc: null, error: formatErrorMessage(error) };
  }
}
async function adkWorkflowsList(options = {}) {
  ensureWorkflowJsonOnlyFormat(options.format);
  const logger = createCliLogger({ format: options.format });
  const workflows = await listDevServerWorkflows();
  if (workflows.length === 0) {
    logger.info("No workflows found.").result({ workflows: [], count: 0 });
    return;
  }
  logger.info(workflows.map((workflow) => formatWorkflowForText(workflow)).join(`

`)).result({
    workflows: workflows.map((workflow) => ({
      name: workflow.name,
      description: workflow.description,
      hasSchedule: workflow.hasSchedule,
      hasInput: workflow.hasInput,
      schedule: workflow.schedule,
      timeout: workflow.timeout
    })),
    count: workflows.length
  });
}
async function adkWorkflowsInspect(name, options = {}) {
  ensureWorkflowJsonOnlyFormat(options.format);
  const logger = createCliLogger({ format: options.format });
  const workflow = await getDevServerWorkflow(name);
  if (!workflow) {
    throw new WorkflowCommandError(`Workflow '${name}' not found.`);
  }
  logger.info(formatWorkflowForText(workflow, { includeInputSchema: true })).result({
    name: workflow.name,
    description: workflow.description,
    hasSchedule: workflow.hasSchedule,
    hasInput: workflow.hasInput,
    schedule: workflow.schedule,
    timeout: workflow.timeout,
    inputSchema: workflow.inputSchema
  });
}
async function adkWorkflowsRun(name, payloadArg, options = {}) {
  ensureWorkflowJsonOnlyFormat(options.format);
  const logger = createCliLogger({ format: "json" });
  const timeout = options.timeout === undefined ? undefined : parseDuration(options.timeout);
  const workflow = await getDevServerWorkflow(name);
  if (!workflow) {
    throw new WorkflowCommandError(`Workflow '${name}' not found.`);
  }
  const requiredInputShape = getRequiredInputShape(workflow.inputSchema);
  const stdin = options.stdin ?? process.stdin;
  if (payloadArg === undefined && requiredInputShape && !stdinHasPipedData(stdin)) {
    throw new WorkflowCommandError(`Workflow '${name}' requires input. Run \`adk workflows inspect ${name}\` to see the schema.`, {
      json: {
        error: `Workflow '${name}' requires input. Run \`adk workflows inspect ${name}\` to see the schema.`,
        inputSchema: requiredInputShape
      }
    });
  }
  const payload = await resolvePayload(payloadArg, stdin);
  if (payload === undefined && requiredInputShape) {
    throw new WorkflowCommandError(`Workflow '${name}' requires input. Run \`adk workflows inspect ${name}\` to see the schema.`, {
      json: {
        error: `Workflow '${name}' requires input. Run \`adk workflows inspect ${name}\` to see the schema.`,
        inputSchema: requiredInputShape
      }
    });
  }
  const client = await getClientFromDevServer();
  const now = options.now ?? (() => Date.now());
  const startedAt = now();
  const createWorkflowPayload = {
    name,
    status: "pending",
    input: payload ?? {}
  };
  if (typeof workflow.timeout === "number") {
    createWorkflowPayload.timeoutAt = new Date(startedAt + workflow.timeout).toISOString();
  }
  const shouldWait = options.wait || options.timeout !== undefined;
  if (!shouldWait) {
    const created2 = await client.createWorkflow(createWorkflowPayload);
    const workflowId2 = created2.workflow.id;
    logger.info(`Workflow '${name}' started (${workflowId2})`).result({
      workflowId: workflowId2,
      workflow: name,
      status: "started"
    });
    return;
  }
  const waitTimeout = timeout ?? parseDuration(undefined);
  const created = await client.createWorkflow(createWorkflowPayload);
  const workflowId = created.workflow.id;
  const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
  const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
  const deadline = startedAt + waitTimeout.ms;
  let consecutivePollErrors = 0;
  while (now() < deadline) {
    let current;
    try {
      const response = await client.getWorkflow({ id: workflowId });
      current = response.workflow;
      consecutivePollErrors = 0;
    } catch (error) {
      consecutivePollErrors += 1;
      if (consecutivePollErrors >= 3) {
        throw new WorkflowCommandError(`Failed to poll workflow status: ${error instanceof Error ? error.message : String(error)}`);
      }
      current = undefined;
    }
    if (current && isTerminalStatus(current.status)) {
      const output = buildWorkflowWaitOutput(workflowId, name, current, startedAt, now());
      if (current.status !== "completed") {
        throw new WorkflowCommandError(`Workflow ended with status '${current.status}'.`, { json: output });
      }
      logger.info(`Workflow '${name}' ${current.status} (${workflowId})`).result(output);
      return;
    }
    await sleep(pollIntervalMs);
  }
  throw new WorkflowCommandError(`Workflow did not complete within ${waitTimeout.label}.`, {
    json: {
      workflowId,
      workflow: name,
      status: "timeout",
      message: `Workflow did not complete within ${waitTimeout.label}. Check adk traces workflow=${name} for details.`
    }
  });
}
var VALID_STATUSES = [
  "pending",
  "in_progress",
  "failed",
  "completed",
  "listening",
  "paused",
  "timedout",
  "cancelled"
];
function parseRunsTokens(tokens) {
  const filters = {};
  for (const token of tokens) {
    const eq = token.indexOf("=");
    const key = eq === -1 ? token : token.slice(0, eq);
    const value = eq === -1 ? undefined : token.slice(eq + 1);
    if (!key || value === undefined) {
      throw new WorkflowCommandError(`Invalid filter '${token}'. Expected key=value (e.g. name=onboarding, status=failed, limit=20).`);
    }
    if (key === "name") {
      filters.name = value;
    } else if (key === "status") {
      const statuses = value.split(",").map((s) => s.trim());
      for (const s of statuses) {
        if (!VALID_STATUSES.includes(s)) {
          throw new WorkflowCommandError(`Invalid status '${s}'. Valid: ${VALID_STATUSES.join(", ")}.`);
        }
      }
      filters.statuses = statuses;
    } else if (key === "limit") {
      const n = Number(value);
      if (!Number.isFinite(n) || n <= 0) {
        throw new WorkflowCommandError(`Invalid limit '${value}'. Must be a positive integer.`);
      }
      filters.limit = Math.floor(n);
    } else if (key === "nextToken") {
      filters.nextToken = value;
    } else {
      throw new WorkflowCommandError(`Unknown filter '${key}'. Supported: name, status, limit, nextToken.`);
    }
  }
  return filters;
}
function isWorkflowInstanceId(value) {
  return /^wrkflow_/i.test(value);
}
async function listWorkflowRuns(client, filters) {
  const workflows = [];
  let nextToken = filters.nextToken;
  let locallyTruncated = false;
  do {
    const remaining = filters.limit === undefined ? undefined : filters.limit - workflows.length;
    if (remaining !== undefined && remaining <= 0)
      break;
    const response = await client.listWorkflows({
      ...filters.name ? { name: filters.name } : {},
      ...filters.statuses ? { statuses: filters.statuses } : {},
      ...nextToken ? { nextToken } : {}
    });
    const pageItems = remaining === undefined ? response.workflows : response.workflows.slice(0, remaining);
    locallyTruncated = remaining !== undefined && response.workflows.length > remaining;
    workflows.push(...pageItems);
    nextToken = response.meta?.nextToken;
    if (filters.limit === undefined || locallyTruncated) {
      break;
    }
  } while (nextToken);
  return {
    workflows,
    ...nextToken && !locallyTruncated ? { nextToken } : {}
  };
}
async function adkWorkflowsRuns(workflowIdOrTokens, options = {}) {
  ensureWorkflowJsonOnlyFormat(options.format);
  const logger = createCliLogger({ format: options.format });
  const isShowMode = typeof workflowIdOrTokens === "string" && isWorkflowInstanceId(workflowIdOrTokens);
  const client = await getClientFromDevServer();
  if (isShowMode) {
    const workflowId = workflowIdOrTokens;
    const [wfResponse, stateResult, stepsResult] = await Promise.all([
      client.getWorkflow({ id: workflowId }),
      fetchWorkflowStateDocForRuns(client, workflowId, "workflowState"),
      fetchWorkflowStateDocForRuns(client, workflowId, "workflowSteps")
    ]);
    const wf = wfResponse.workflow;
    const stateDoc = stateResult.doc;
    const stepsDoc = stepsResult.doc;
    const lines = [];
    appendYamlLikeValue(lines, "workflowId", wf.id, 0);
    appendYamlLikeValue(lines, "name", wf.name, 0);
    appendYamlLikeValue(lines, "status", wf.status, 0);
    appendYamlLikeValue(lines, "createdAt", wf.createdAt, 0);
    appendYamlLikeValue(lines, "updatedAt", wf.updatedAt, 0);
    if (wf.input !== undefined)
      appendYamlLikeValue(lines, "input", wf.input, 0);
    if (wf.output !== undefined)
      appendYamlLikeValue(lines, "output", wf.output, 0);
    if (stateDoc) {
      appendYamlLikeValue(lines, "workflowState.updatedAt", stateDoc.updatedAt, 0);
      appendYamlLikeValue(lines, "workflowState.payload", stateDoc.payload, 0);
    }
    if (stepsDoc) {
      appendYamlLikeValue(lines, "workflowSteps.updatedAt", stepsDoc.updatedAt, 0);
      appendYamlLikeValue(lines, "workflowSteps.payload", stepsDoc.payload, 0);
    }
    if (stateResult.error)
      appendYamlLikeValue(lines, "workflowState.error", stateResult.error, 0);
    if (stepsResult.error)
      appendYamlLikeValue(lines, "workflowSteps.error", stepsResult.error, 0);
    logger.info(lines.join(`
`)).result({
      workflowId: wf.id,
      workflow: wf,
      workflowState: stateDoc,
      workflowSteps: stepsDoc,
      ...stateResult.error ? { workflowStateError: stateResult.error } : {},
      ...stepsResult.error ? { workflowStepsError: stepsResult.error } : {}
    });
    return;
  }
  const tokens = Array.isArray(workflowIdOrTokens) ? workflowIdOrTokens : workflowIdOrTokens ? [workflowIdOrTokens] : [];
  const filters = parseRunsTokens(tokens);
  const response = await listWorkflowRuns(client, filters);
  const items = response.workflows;
  if (items.length === 0) {
    logger.info("No workflow runs found.").result({ workflows: [], count: 0 });
    return;
  }
  const textLines = items.map((wf) => `${wf.id}  ${wf.name.padEnd(24)}  ${wf.status.padEnd(12)}  ${wf.createdAt}`);
  logger.info(textLines.join(`
`)).result({
    workflows: items.map((wf) => ({
      id: wf.id,
      name: wf.name,
      status: wf.status,
      createdAt: wf.createdAt,
      updatedAt: wf.updatedAt
    })),
    count: items.length,
    ...response.nextToken ? { nextToken: response.nextToken } : {}
  });
}
export {
  isWorkflowInstanceId,
  adkWorkflowsRuns,
  adkWorkflowsRun,
  adkWorkflowsList,
  adkWorkflowsInspect,
  WorkflowCommandError,
  PAYLOAD_NOT_OBJECT_ERROR,
  JSON_ONLY_FORMAT_ERROR,
  DEV_SERVER_DOWN_ERROR
};
