LCOV - code coverage report
Current view: top level - dashql-app/src/agent - use_composer_agent.ts Coverage Total Hit
Test: DashQL 6e74948 Lines: 100.0 % 37 37
Test Date: 2026-11-06 17:46:50

            Line data    Source code
       1              : import * as React from 'react';
       2              : 
       3              : import type { AgentBridge } from './agent_bridge.js';
       4              : import { AgentConnectionStatus } from './agent_client.js';
       5              : import type { ScriptData, SessionScripts } from '../session/scripts/session_scripts.js';
       6              : import { scriptDisplayName } from '../session/scripts/script_types.js';
       7              : import { isAgentAnswering, useAgentQuestions, type AgentFollowTarget } from './use_agent_questions.js';
       8              : import { useAgentSessionContext, type ComposerAgent, type ComposerAgentScript, type ComposerAgentTurn } from './agent_prompt_panel.js';
       9              : 
      10              : /// The session of the composer and what the feed does for the agent
      11              : export interface ComposerAgentArgs {
      12              :     /// The agent bridge, null outside of the provider
      13              :     agent: AgentBridge | null;
      14              :     /// The scripts of the session
      15              :     sessionScripts: SessionScripts;
      16              :     /// Runs a script that the agent wrote
      17              :     runScript: (next: SessionScripts, scriptData: ScriptData) => void;
      18              :     /// Follows the agent to a script, every time the agent edits or runs it
      19              :     followScript: (scriptKey: number, target: AgentFollowTarget) => void;
      20              :     /// Shows a script that the user picked in a question
      21              :     showScript: (scriptKey: number) => void;
      22              : }
      23              : 
      24              : /// The agent of the composer
      25              : export interface ComposerAgentState {
      26              :     /// The agent on top of the composer, null without agent access
      27              :     agent: ComposerAgent | null;
      28              :     /// Can the composer ask the agent?
      29              :     available: boolean;
      30              :     /// Ask the agent a question
      31              :     ask: (question: string) => Promise<void>;
      32              : }
      33              : 
      34              : /// The agent of a session in the composer: its harness, its status lines and its answers.
      35              : /// The scripts of the feed only show the edits of the agent.
      36            1 : export function useComposerAgent(args: ComposerAgentArgs): ComposerAgentState {
      37            1 :     const { agent, sessionScripts, showScript } = args;
      38            1 :     const sessionId = sessionScripts.sessionId;
      39            1 :     const questions = useAgentQuestions({
      40            1 :         agent,
      41            1 :         sessionScripts,
      42            1 :         runScript: args.runScript,
      43            1 :         followScript: args.followScript,
      44            1 :     });
      45              : 
      46              :     // The harness context changes with every finished question
      47            1 :     let workingCount = 0;
      48            1 :     for (const question of questions.questions.values()) {
      49            1 :         if (isAgentAnswering(question)) ++workingCount;
      50              :     }
      51            1 :     const context = useAgentSessionContext(agent, sessionId, workingCount);
      52              : 
      53            1 :     const access = agent != null && agent.supported && agent.hasAccess(sessionId);
      54            1 :     const composerAgent = React.useMemo<ComposerAgent | null>(() => {
      55            1 :         if (agent == null || !access) return null;
      56            1 :         const turns: ComposerAgentTurn[] = [];
      57            1 :         for (const [questionId, question] of questions.questions) {
      58              :             // Deleted scripts drop out
      59            1 :             const scripts: ComposerAgentScript[] = [];
      60            1 :             for (const scriptKey of question.scripts) {
      61            1 :                 const scriptData = sessionScripts.scripts[scriptKey];
      62            1 :                 if (scriptData != null) scripts.push({ scriptKey, scriptName: scriptDisplayName(scriptData.fileName) });
      63            1 :             }
      64            1 :             turns.push({ questionId, question, scripts });
      65            1 :         }
      66            1 :         return {
      67            1 :             connected: agent.status === AgentConnectionStatus.Connected,
      68            1 :             port: agent.port,
      69            1 :             context,
      70            1 :             turns,
      71            1 :             onStop: questions.stop,
      72            1 :             onDismiss: questions.dismiss,
      73            1 :             onShowScript: showScript,
      74            1 :         };
      75            1 :     }, [agent, access, context, questions.questions, questions.stop, questions.dismiss, sessionScripts.scripts, showScript]);
      76            1 :     return { agent: composerAgent, available: questions.available, ask: questions.ask };
      77            1 : }
        

Generated by: LCOV version 2.0-1