{"version":3,"file":"index.cjs","names":["WORKFLOW_PI_TOOL_NAMES","toolResultText","resolveRootSessionId","LAUNCH_WORKFLOW_TOOL_NAME","resolveMaxConcurrent","withOptions","PI_SESSION_ENV","launchedRunSummary","launchHandoffSummary"],"sources":["../../../../src/services/workflowExecution/index.ts"],"sourcesContent":["import { resolveRootSessionId } from '@agimon-ai/doompi-core/child-process';\nimport type { DoomToolRestriction } from '@agimon-ai/doompi-core/tool-surface';\nimport { type EmbeddedWorkflowFeature, type WorkflowRunRecord } from '@agimon-ai/workflow-mcp';\nimport type { AgentToolResult, AgentToolUpdateCallback, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { z } from 'zod';\n\nimport { type WorkflowRunInput } from '../../schemas/workflowPi';\nimport {\n  launchedRunSummary,\n  launchHandoffSummary,\n  PI_SESSION_ENV,\n  resolveMaxConcurrent,\n  toolResultText,\n  withOptions,\n} from '../piToolBridge';\n\nconst AGIFLOW_JOB_ID_ENV = 'AGIFLOW_JOB_ID';\nconst AGIFLOW_JOB_KIND_ENV = 'AGIFLOW_JOB_KIND';\nconst AGIFLOW_PROJECT_ID_ENV = 'AGIFLOW_PROJECT_ID';\n\nimport { WORKFLOW_PI_TOOL_NAMES, LAUNCH_WORKFLOW_TOOL_NAME } from '../../constants/workflow';\n\n/**\n * What workflow mode does to the tool surface: nothing but hide its own tools.\n *\n * The tools are registered for the whole session because Pi has no other way to\n * add one later, so the mode is expressed as a restriction rather than as a\n * registration.\n */\nexport function workflowToolRestriction(enabled: boolean): DoomToolRestriction {\n  const hidden = new Set<string>(WORKFLOW_PI_TOOL_NAMES);\n  return (incoming) => (enabled ? incoming : incoming.filter((name) => !hidden.has(name)));\n}\n\nexport type WorkflowRunSelector = Pick<WorkflowRunInput, 'runKey' | 'workspace'>;\n\nexport type WorkflowLaunchInput = z.infer<ReturnType<EmbeddedWorkflowFeature['runTool']['getInputSchema']>>;\n\n/**\n * Where a launch was answered from, which decides what the caller is told.\n *\n * Tagged rather than inferred from an absent field: the failure carries an\n * `unknown`, and `unknown` includes `undefined`, so only a tag can tell a\n * rejection apart from a result.\n */\ntype LaunchOutcome = { kind: 'value'; result: CallToolResult } | { kind: 'error'; error: unknown };\ntype LaunchAck =\n  | { kind: 'settled'; outcome: LaunchOutcome }\n  | { kind: 'record'; record: WorkflowRunRecord }\n  | { kind: 'handoff' };\n\n/** How often the registry is asked whether the launch has produced a run. */\nconst LAUNCH_ACK_POLL_MS = 500;\n/**\n * How long to wait for that before answering without a run key.\n *\n * Long enough to cover a launcher that is merely slow, short enough that a\n * caller is never left holding a turn open for a launcher that will not answer.\n */\nconst LAUNCH_ACK_TIMEOUT_MS = 15_000;\n\nexport interface LaunchedRunQuery {\n  sessionId: string | undefined;\n  /** Epoch milliseconds the launch began, so an earlier run cannot match. */\n  since: number;\n  workflowPath: string;\n}\n\nexport interface WorkflowLaunchExecutorDependencies {\n  readonly environment: Readonly<Record<string, string | undefined>>;\n  activeRunCount?: () => Promise<number>;\n  onLaunch?: (ctx: ExtensionContext) => Promise<void> | void;\n  observeSession?: (sessionId: string | undefined) => void;\n  rejectRunner?: (workflowPath: string, runner: string) => string | undefined;\n  runTool: EmbeddedWorkflowFeature['runTool'];\n  trackPendingRun: <T>(run: Promise<T>) => Promise<T>;\n  /**\n   * The run this launch registered, or undefined while none has appeared.\n   *\n   * Its presence is what lets a launch answer on the registry instead of on the\n   * launcher process exiting. Left out, the launch waits for the process, which\n   * is the behaviour every caller had before.\n   */\n  findLaunchedRun?: (query: LaunchedRunQuery) => Promise<WorkflowRunRecord | undefined>;\n  /** Report a launch that fails after this call already answered \"started\". */\n  onLateFailure?: (error: unknown, ctx: ExtensionContext) => void;\n  launchAckPollMs?: number;\n  launchAckTimeoutMs?: number;\n}\n\nexport interface WorkflowLaunchExecutor {\n  execute(\n    input: WorkflowLaunchInput,\n    ctx: ExtensionContext,\n    onUpdate?: AgentToolUpdateCallback<{ tool: string }>,\n  ): Promise<CallToolResult>;\n}\n\nexport interface WorkflowPiToolDependencies {\n  readonly environment: Readonly<Record<string, string | undefined>>;\n  launchExecutor?: WorkflowLaunchExecutor;\n  onLaunch?: (ctx: ExtensionContext) => Promise<void> | void;\n  activeRunCount?: () => Promise<number>;\n  followRun?: (input: WorkflowRunSelector, ctx: ExtensionContext) => Promise<string>;\n  tailRun?: (input: WorkflowRunSelector, ctx: ExtensionContext) => Promise<string>;\n  openRun?: (input: WorkflowRunSelector, ctx: ExtensionContext) => Promise<string>;\n  rejectRunner?: (workflowPath: string, runner: string) => string | undefined;\n  requireSessionRun?: (input: WorkflowRunSelector, sessionId: string | undefined) => Promise<WorkflowRunRecord>;\n  /**\n   * Resolve a failed recovery target globally.\n   *\n   * Recovery is the one ownership-transferring action: a replacement Pi\n   * session must be able to adopt a terminal run whose launching session is\n   * gone. Every non-recovery action remains session-scoped.\n   */\n  requireRecoverableRun?: (input: WorkflowRunSelector) => Promise<WorkflowRunRecord>;\n  readRecoveryEvidence?: (input: WorkflowRunSelector, ctx: ExtensionContext) => Promise<string>;\n  /**\n   * Hand a recovery to a terminal launcher, returning what to tell the caller.\n   *\n   * Undefined means this recovery cannot be delegated, and the in-process\n   * replay below is used instead.\n   */\n  delegateRecovery?: (\n    input: { runKey: string; workspace?: string; runner?: string },\n    ctx: ExtensionContext,\n  ) => Promise<string | undefined>;\n  observeSession?: (sessionId: string | undefined) => void;\n  trackPendingRun?: <T>(run: Promise<T>) => Promise<T>;\n  feature?: EmbeddedWorkflowFeature;\n  recoverTool?: {\n    execute(input: {\n      dryRun?: boolean;\n      job?: string;\n      runKey: string;\n      runner?: string;\n      workspace?: string;\n    }): Promise<CallToolResult>;\n  };\n  controlTool?: ReturnType<EmbeddedWorkflowFeature['createControlTool']>;\n  runTool?: EmbeddedWorkflowFeature['runTool'];\n  listWorkflowsTool?: EmbeddedWorkflowFeature['listWorkflowsTool'];\n}\n\nexport function reportProgress(\n  onUpdate: AgentToolUpdateCallback<{ tool: string }> | undefined,\n  tool: string,\n  message: string,\n): void {\n  onUpdate?.({ content: [{ type: 'text', text: message }], details: { tool } });\n}\n\nexport function appendGuidance(\n  result: AgentToolResult<{ tool: string }>,\n  guidance: string,\n): AgentToolResult<{ tool: string }> {\n  return { ...result, content: [...result.content, { type: 'text', text: guidance }] };\n}\n\nfunction statusAction(runKey: string): string {\n  return `workflow_run {\"action\":\"status\",\"runKey\":${JSON.stringify(runKey)}}`;\n}\n\nexport function actionGuidance(action: WorkflowRunInput['action'], runKey: string): string[] {\n  const status = statusAction(runKey);\n  if (action === 'stop') return [`Next: call ${status} to confirm the run reached a terminal stage.`];\n  if (action === 'recover') {\n    return [\n      `Report the recovery failure and do not retry it blindly: call ${status} first.`,\n      'Ask the user before launching fresh work when the recorded recovery is no longer valid.',\n    ];\n  }\n  return [`Next: call ${status} to verify the recorded execution state.`];\n}\n\nexport const launchFailureOptions = [\n  'Report the failure to the user with the error above. A launch failure is usually a bad workflow path, a missing launcher, or a workflow whose own pre-conditions refused.',\n  'list_workflows: confirm the workflow path exists and its description matches the work, if the path may be wrong.',\n  'workflow_run with action status: check whether an earlier attempt is already running before launching again.',\n];\n\n/**\n * An Error, whatever the launch rejected with.\n *\n * A rejection reaches here as `unknown` because it crossed a promise boundary,\n * and rethrowing that as-is hands Pi's tool layer something it cannot read a\n * message or a stack off. The original is kept as the cause rather than\n * flattened into a string.\n */\nfunction asError(value: unknown): Error {\n  return value instanceof Error ? value : new Error(String(value), { cause: value });\n}\n\n/** Resolves to undefined, so a race against it reads as \"nothing settled yet\". */\nfunction sleep(ms: number): Promise<undefined> {\n  return new Promise((settle) => {\n    const timer = setTimeout(() => settle(undefined), ms);\n    timer.unref?.();\n  });\n}\n\n/**\n * Wait for whichever answer arrives first: the launch settling, the run\n * appearing in the registry, or the budget running out.\n *\n * A launch that delegates to a terminal launcher settles when that launcher's\n * whole process chain closes, which on a loaded machine has been measured\n * minutes after the run itself was registered and working. The registry is the\n * earlier and more truthful signal: a run recorded there is a run that started.\n */\nasync function awaitLaunchAck(\n  settled: Promise<LaunchOutcome>,\n  dependencies: WorkflowLaunchExecutorDependencies,\n  query: LaunchedRunQuery,\n): Promise<LaunchAck> {\n  const findLaunchedRun = dependencies.findLaunchedRun;\n  if (!findLaunchedRun) return { kind: 'settled', outcome: await settled };\n\n  const pollMs = dependencies.launchAckPollMs ?? LAUNCH_ACK_POLL_MS;\n  const deadline = Date.now() + (dependencies.launchAckTimeoutMs ?? LAUNCH_ACK_TIMEOUT_MS);\n  for (;;) {\n    const outcome = await Promise.race([settled, sleep(pollMs)]);\n    if (outcome) return { kind: 'settled', outcome };\n    // A registry read that throws must not fail the launch: the run may be\n    // perfectly healthy, and the settled promise is still the fallback.\n    const record = await findLaunchedRun(query).catch(() => undefined);\n    if (record) return { kind: 'record', record };\n    if (Date.now() >= deadline) return { kind: 'handoff' };\n  }\n}\n\n/**\n * Carry a failure that lands after the caller was told the run started.\n *\n * Answering early trades the launcher's exit code for timeliness. Dropping that\n * code entirely is not part of the trade: a launch that fails a minute later\n * would otherwise leave a user waiting on a run that never existed.\n */\nfunction reportLateFailure(\n  settled: Promise<LaunchOutcome>,\n  dependencies: WorkflowLaunchExecutorDependencies,\n  ctx: ExtensionContext,\n): void {\n  void settled.then((outcome) => {\n    if (outcome.kind === 'error') {\n      dependencies.onLateFailure?.(asError(outcome.error), ctx);\n      return;\n    }\n    if (outcome.result.isError) {\n      dependencies.onLateFailure?.(new Error(toolResultText(outcome.result) || 'Workflow launch failed.'), ctx);\n    }\n  });\n}\n\nexport function createWorkflowLaunchExecutor(dependencies: WorkflowLaunchExecutorDependencies): WorkflowLaunchExecutor {\n  return {\n    async execute(input, ctx, onUpdate) {\n      const sessionId = resolveRootSessionId(ctx.sessionManager.getSessionId(), dependencies.environment);\n      dependencies.observeSession?.(sessionId);\n      const agiflowJobKind = input.env?.[AGIFLOW_JOB_KIND_ENV]?.trim();\n      const agiflowJobId = input.env?.[AGIFLOW_JOB_ID_ENV]?.trim();\n      const explicitProjectId = input.env?.[AGIFLOW_PROJECT_ID_ENV]?.trim();\n      if (Boolean(agiflowJobKind) !== Boolean(agiflowJobId)) {\n        throw new Error('Agiflow workflow launches require AGIFLOW_JOB_KIND and AGIFLOW_JOB_ID together.');\n      }\n      if (agiflowJobKind && agiflowJobKind !== 'task' && agiflowJobKind !== 'work-unit') {\n        throw new Error('Agiflow workflow launches require AGIFLOW_JOB_KIND to be task or work-unit.');\n      }\n      if (agiflowJobKind && !explicitProjectId) {\n        throw new Error('Agiflow workflow launches require AGIFLOW_PROJECT_ID with the job identity.');\n      }\n      if (agiflowJobKind && !input.prompt?.trim()) {\n        throw new Error(\n          'Agiflow workflow launches require a non-empty prompt so user_prompt runs do not wait for terminal input.',\n        );\n      }\n      reportProgress(onUpdate, LAUNCH_WORKFLOW_TOOL_NAME, 'Checking workflow capacity...');\n      const maxConcurrent = resolveMaxConcurrent(dependencies.environment);\n      const active = (await dependencies.activeRunCount?.()) ?? 0;\n      if (active >= maxConcurrent) {\n        throw new Error(\n          withOptions(`This session is at capacity: ${active}/${maxConcurrent} workflows running.`, [\n            'Wait for a running workflow to finish, then launch again. The extension reports each one as it ends.',\n            'workflow_run with action status: show what is running, so the user can judge whether something is stuck.',\n            'workflow_run with action stop: free a slot by stopping a run the user no longer wants.',\n          ]),\n        );\n      }\n\n      if (input.runner) {\n        const rejection = dependencies.rejectRunner?.(input.workflowPath, input.runner);\n        if (rejection) throw new Error(rejection);\n      }\n      reportProgress(onUpdate, LAUNCH_WORKFLOW_TOOL_NAME, `Launching workflow ${input.workflowPath}...`);\n      const workflowEnv = { ...input.env };\n      const dispatcherContextFile = dependencies.environment.AGIFLOW_DISPATCH_CONTEXT_FILE;\n      const dispatcherProjectId = dependencies.environment[AGIFLOW_PROJECT_ID_ENV]?.trim();\n      if (\n        dispatcherContextFile &&\n        agiflowJobKind &&\n        dispatcherProjectId &&\n        explicitProjectId &&\n        dispatcherProjectId !== explicitProjectId\n      ) {\n        throw new Error(\n          `Agiflow workflow project identity conflicts with the dispatcher context (${explicitProjectId} versus ${dispatcherProjectId}).`,\n        );\n      }\n      if (dispatcherContextFile) {\n        for (const key of [\n          'AGIFLOW_ORGANIZATION_ID',\n          'AGIFLOW_PROJECT_ID',\n          'AGIFLOW_DEVICE_ID',\n          'BACKEND_AGIFLOW_API_ENDPOINT',\n          'AGIFLOW_DISPATCH_SECRET_FILE',\n        ] as const) {\n          const hostValue = dependencies.environment[key];\n          if (hostValue) workflowEnv[key] = hostValue;\n        }\n      }\n      const since = Date.now();\n      const launch = dependencies.trackPendingRun(\n        dependencies.runTool.execute({\n          ...input,\n          env: { ...workflowEnv, [PI_SESSION_ENV]: sessionId },\n        }),\n      );\n      // Folded into a value before anything races it. A promise this function\n      // may stop awaiting must never be able to reject unobserved, which in\n      // Node ends the whole process, Pi's TUI included.\n      const settled: Promise<LaunchOutcome> = launch.then(\n        (value): LaunchOutcome => ({ kind: 'value', result: value }),\n        (error: unknown): LaunchOutcome => ({ kind: 'error', error }),\n      );\n\n      const ack = await awaitLaunchAck(settled, dependencies, {\n        sessionId,\n        since,\n        workflowPath: input.workflowPath,\n      });\n\n      if (ack.kind === 'settled') {\n        const outcome = ack.outcome;\n        if (outcome.kind === 'error') throw asError(outcome.error);\n        const result = outcome.result;\n        if (result.isError)\n          throw new Error(withOptions(toolResultText(result) || 'Workflow launch failed.', launchFailureOptions));\n        await dependencies.onLaunch?.(ctx);\n        return result;\n      }\n\n      reportLateFailure(settled, dependencies, ctx);\n      await dependencies.onLaunch?.(ctx);\n      return {\n        content: [\n          {\n            type: 'text',\n            text: ack.kind === 'record' ? launchedRunSummary(ack.record) : launchHandoffSummary(input.workflowPath),\n          },\n        ],\n      };\n    },\n  };\n}\n"],"mappings":"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"}