Team Ai
Apppublic

augment17/claude-code-backend

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
backend.cpython-310.pyc893 linesDownload Raw Back to __pycache__
1o

2�'Fj���@s�UdZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl3Z4ddlmZddl
mZmZmZmZmZddlmZddlmZmZmZmZddlmZmZmZddlmZdd	l m!Z!ddl"Z"ddl#Z#e5j$d6d�Z%iZ&e'�Z(de)fd
d�Z*ej+�,dd�Z-ej+�,dd�Z.ej+�,dd�Z/ej+�,dd�Z0ej+�,dd�Z1e2ej+�,dd��Z3ddddddddd d!d"d#�Z4ie4�d$d%d&��Z5d'a6ee0�j7d(d(d)�e!d*e-d+�Z8ej+�,d,d�Z9e9r�e!d-e9r�e9nd.d+�ndZ:Gd/d0�d0�Z;e;�Z<d1d2d3d4d5d6d7d8�id5gd9�d:�d;�d1d<d=d4d6d7d8�d6d>d8�d?�d5d@gd9�d:�d;�d1dAdBd4dCd6dDd8�idCgd9�d:�d;�d1dEdFd4d5d6dGd8�id5gd9�d:�d;�d1dHdId4d6dJd8�d6dKd8�dL�dMgd9�d:�d;�gZ=dNe)dOefdPdQ�Z>dRe)dSe?dOe@e?eAe)ffdTdU�ZBdVe)dWe?dOe)fdXdY�ZCdaDee#jEeFdZ<d[d\�ZG		d�d]e)d^e)d@e)d_eAd`e)f7dadb�ZHd]e)dOeAfdcdd�ZId�dee)dfe)d@e)dge)dOe)f8dhdi�ZJedjdkdl�ZKeKjLedmgdmgdmgdn�d�doe)fdpdq�ZMdrds�ZNdtdu�ZOeK�Pdv�dwdv��ZQdxZRdyeAdOeAfdzd{�ZSeK�Td|�ed�fd}edoe)fd~d��ZUeK�,d��ed�fdoe)fd�d���ZVeK�,d��d�d���ZWeK�,d��d5e)fd�d���ZXd�ZYe�Zd��Z[Gd�d��d�e�Z\eK�Td��ed�fd�e\doe)fd�d���Z]Gd�d��d�e�Z^eK�Td��ed�fd�e^doe)fd�d���Z_Gd�d��d�e�Z`eK�Td��ed�fd�e`doe)fd�d���ZaGd�d��d�e�ZbeK�Td��ed�fd�ebdoe)fd�d���Zcdd�ldmdZdmeZemfZfGd�d��d�e�ZgeK�Td��d�egfd�d���ZhGd�d��d�e�ZieK�Td��d�eifd�d���ZjGd�d��d�e�ZkeK�Td��d�ekfd�d���ZleK�,d��d�d���ZmeK�,d��d�d���ZnGd�d��d�e�ZoeK�Td��ed�fd�eodoe)fd�d���Zpd�d��Zqej+�,d�d��Zrej+�,d�d��Zsej+�,d�d¡Ztej+�,d�dġZud�dƄZvd�e)d�e)fd�dʄZwd�e)d�e)fd�d̈́Zxd�e)d�eAfd�dЄZyd�e)d�e?dOe?fd�dԄZzd�e)d�e)fd�dׄZ{d�e)d�e)fd�dلZ|iZ}d�dۄZ~eKj,d�edݍd�d߄�ZeK�,d�d�d��Z�eK�,d�d�d��Z�ddlZddlZddl�Z�dd�lm�Z�eK�,d�ed�fdoe)fd�d��Z�eK�,d�d�d��Z�d�d�Z�d�d��Zqd�d�Z�d�d�Z�eK�Pdv�d�d���Z�e�d�k�r�ddl�Z�e�j�eKd�d�d��dSdS)�u9Claude Code Backend — Agentic coding backend powered by NVIDIA NIM models.10Exposes an OpenAI-compatible /v1/chat/completions endpoint with built-in11tools for file operations and bash execution.12 13Architecture:14  Space 1 (better-chatbot) --> this backend --> NVIDIA NIM API15  16The agentic loop:17  1. Receive user message from Space 118  2. Send to NIM model with tool definitions19  3. If model returns tool_calls, execute them and loop20  4. If model returns text, stream it back to Space 121  5. Persist conversation in Postgres22�N)�Path)�
AsyncIterator�Optional�List�Dict�Any)�	BaseModel)�FastAPI�Request�Header�
HTTPException)�StreamingResponse�JSONResponse�HTMLResponse)�CORSMiddleware)�AsyncOpenAI�d)�maxlen�msgcCs0t�d�}d|�d|��}t�|�t|�dS)Nz%H:%M:%S�[z] )�time�strftime�
activity_logs�append�print)rZ	timestampZlog_line�r�23backend.py�log_activity-s2425rZNVIDIA_NIM_API_KEY��BACKEND_API_KEY�DATABASE_URL�
WORKSPACE_DIRz/tmp/workspace�BACKUP_GIT_REPO�MAX_TOOL_ROUNDSZ10zNemotron 3 Ultra 550B (Agentic)zGLM 5.1 (Agentic)zKimi K2.6 (Agentic)zMiniMax M3 (Agentic)zStep 3.7 Flash (Agentic)zMiniMax M2.7 (Agentic)zLlama 3.1 70B (Agentic)zLlama 3.1 405B (Agentic)zQwen 2.5 Coder 32B (Agentic)zNemotron 70B (Agentic)zLlama 3.3 70B (Agentic))�!nvidia/nemotron-3-ultra-550b-a55b�z-ai/glm-5.1�moonshotai/kimi-k2.6�minimaxai/minimax-m3�stepfun-ai/step-3.7-flash�minimaxai/minimax-m2.7�meta/llama-3.1-70b-instruct�meta/llama-3.1-405b-instruct�qwen/qwen2.5-coder-32b-instruct�&nvidia/llama-3.1-nemotron-70b-instructzmeta/llama-3.3-70b-instructzDeepSeek R1 (Chat only)zMistral Large 2 (Chat only))zdeepseek-ai/deepseek-r1z"mistralai/mistral-large-2-instructr-T��parents�exist_okz#https://integrate.api.nvidia.com/v1)Zbase_urlZapi_key�MISTRAL_API_KEYzhttps://api.mistral.ai/v1Z	dummy_keyc@s$eZdZdd�Zdd�Zdd�ZdS)�MultiProviderRateLimitercCs&d|_d|_g|_d|_t��|_dS)N�(�<�)�	nim_limit�26nim_window�	nim_calls�mistral_last_call�asyncioZLock�lock)�selfrrr�__init__ms27z!MultiProviderRateLimiter.__init__c	�sz�|j4IdH�(t��}||j}|dkr t�d|�IdHt��|_Wd�IdHdS1IdHs6wYdS)Ng�?)r;rr9r:�sleep)r<�now�elapsedrrr�wait_for_mistralts�28.�z)MultiProviderRateLimiter.wait_for_mistralc	�s���j4IdH�It�����fdd��jD��_t�j��jdkr>�j��jd}td|d�d��t�|�IdH�j�	t���Wd�IdHdS1IdHsWwYdS)Ncsg|]}�|�jkr|�qSr)r7)�.0�t�r?r<rr�29<listcomp>sz9MultiProviderRateLimiter.wait_for_nim.<locals>.<listcomp>�rz<[RateLimiter] Approaching NIM rate limit (40 RPM). Sleeping �.2fzs...)30r;rr8�lenr6r7rr:r>r)r<Z31sleep_timerrDr�wait_for_nim|s�.�z%MultiProviderRateLimiter.wait_for_nimN)�__name__�32__module__�__qualname__r=rArIrrrrr2lsr2�function�	read_filezZRead the contents of a file. Use this to inspect existing code, configs, or any text file.�object�path�stringz1Relative path to the file from the workspace root)�type�description)rRZ33properties�required)�namerSZ34parameters)rRrM�35write_filezWrite content to a file. Creates the file if it doesn't exist, overwrites if it does. Creates parent directories automatically.z%The full content to write to the file�rP�contentrX�run_bashz�Execute a bash command in the workspace directory. Use for installing packages, running scripts, git operations, etc. Commands run with a 30 second timeout.�commandzThe bash command to execute�list_directoryzSList files and directories in a given path. Shows file sizes and directory markers.zSRelative path to the directory from workspace root. Use '.' for the workspace root.�grep_searchzlSearch for a pattern in files within the workspace. Returns matching lines with file paths and line numbers.z)The search pattern (supports basic regex)zKDirectory or file to search in, relative to workspace root. Defaults to '.')�patternrPr]�rel_path�returncCs<tt���}||��}t|��t|��std|����|S)z4Resolve a relative path safely within the workspace.zPath traversal detected: )rr!�resolve�str�36startswith�37ValueError)r^�	workspace�targetrrr�38_safe_path�s39rf�	func_name�argsc40Csbg}t|�}t|���D]}||}t|t�r*||vr*||||<|�d|�d��q|dkrVd|vrV|d}t|t�rVd}t�||tj�}|rV|�	d��41�|d<|�d�|��D]6\}}t|t�r�|�42��d�r�|�43��
d	�r�zt�|�}	t|	t�r�|	||<|�d44|�d��WqZYqZqZt|���D]}||ikr�d||<|�d|�d
��q�||fS)NzFlattened nested parameter '�'rYrZz```(?:bash)?\s*(.*?)\s*```�z/Stripped markdown code blocks from bash commandr�]z+Converted stringified array for parameter 'z' to native arrayz%Replaced empty object for parameter 'z' with null)�dict�list�keys�45isinstancerra�re�search�DOTALL�group�strip�itemsrb�endswith�json�loads)46rgrhZnotes�
repaired_args�key�val�cmdr]�matchZ47parsed_arrrrr�repair_arguments�sB�4849&5051���r~rU�	argumentsc�s���z9|dkrDt|d�}|��sd|d��WS|��s%d|d��WS|jddd�}t|�dkrA|d	d�d52t|��d�WS|WS|dkrnt|d�}|jjd
d
d�|j|ddd�dt|d��d|d��WS|dk�r(|d�gd�}t�fdd�|D��r�WdSt	j53�t	jjt	jjt
itj�dtj�dd�d��d�Id	H}zCt	j|��dd�Id	H\}}d }|r�||jddd!�7}|r�||r�d"nd d#|jddd!���7}|jd$kr�|d%|j�d&�7}|s�d'}Wn%t	j�yz|��Wn54t�yYnw|��Id	HYWd(Swt|�d)k�r%|d	d)�d*t|��d�}|WS|d+k�r�t|�dd,��}|���sDd-|�dd,���WS|���sSd.|�dd,���WSg}	t|���D]G}55|56���rn|	�d/|57j�d0���q[|58��j}|d1k�r~|�d2�}n|d3k�r�|d1d4�d5�}n|d3d4�d6�}|	�d7|59j�d8|�d9���q[|	�r�d:|�dd,��d;�d"�|	�WSd<WS|d=k�r6|d>}
|�dd,�}t|�}t	j d?d@dA|
t!|�t	jjt	jjt
dB�Id	H}zt	j|��dCd�Id	H\}}|�r�|jddd!�ndD}Wn%t	j�y#z|��Wn60t�yYnw|��Id	HYWdESwt|�dFk�r3|d	dF�dG}|WSdH|��WSt�yX}zdI|�dJt!|���WYd	}~Sd	}~ww)Kz@Execute a tool and return its output as a string asynchronously.rNrPzError: File not found: zError: Not a file: �utf-8�replace��encoding�errorsiP�Nu61 62[Truncated — file is z chars]rVTr.rX)r�zSuccessfully wrote z63 chars to rYrZ)zrm -rf /Zmkfszdd if=z:(){z	fork bombc3s�|]	}|���vVqdS�N)�lower)rB�b�rZrr�	<genexpr>;s�zexecute_tool.<locals>.<genexpr>z)Error: Command blocked for safety reasonsz/tmp�PATHz/usr/local/bin:/usr/bin:/bin)�HOMEr�)�stdout�stderr�cwd�env��Ztimeoutr)r��64z	[stderr] rz
65[exit code: rkz"[command completed with no output]z)Error: Command timed out after 30 secondsi Nu66 67[Truncated — output is r[�.zError: Directory not found: zError: Not a directory: u  📁 �/i�Biz.1fZKBZMBu  📄 � (�)zContents of z:68zEmpty directoryr\r]Zgrepz-rnz--include=*)r�r�r��69zNo matches foundzError: Grep search timed outi'z
70 71[Truncated]zError: Unknown tool: zError executing z: )"rf�exists�is_file�	read_textrH�parent�mkdirZ72write_text�anyr:Zcreate_subprocess_shell�73subprocess�PIPEr!�os�environ�getZwait_forZcommunicate�decode�74returncode�TimeoutError�kill�	Exception�is_dir�sorted�iterdirrrU�stat�st_size�joinZcreate_subprocess_execra)rUrrPrXZblockedZprocessr�r��output�entries�item�sizeZsize_strr]Zsearch_path�err�r�execute_tool#s��75�$76���77787980818283,84��� ��r��db_poolc85�s��tsdSz8tjtddddd�IdHat��4IdH�}|�d�IdHWd�IdHWdS1IdHs6wYWdStyY}ztd|���daWYd}~dSd}~ww)	z6Initialize database connection pool and create tables.NZrequirerj��,)ZsslZmin_sizeZmax_sizeZ max_inactive_connection_lifetimea>86                CREATE TABLE IF NOT EXISTS agent_session_entries (87                    id          BIGSERIAL PRIMARY KEY,88                    project_key TEXT        NOT NULL,89                    session_id  TEXT        NOT NULL,90                    subpath     TEXT,91                    entry       JSONB       NOT NULL,92                    created_at  TIMESTAMPTZ NOT NULL DEFAULT now()93                );94                CREATE INDEX IF NOT EXISTS idx_session_key ON agent_session_entries (project_key, session_id, subpath, id);95                CREATE INDEX IF NOT EXISTS idx_project_session ON agent_session_entries (project_key, session_id);96                97                CREATE TABLE IF NOT EXISTS eternity_projects (98                    id           SERIAL PRIMARY KEY,99                    project_name VARCHAR(100) UNIQUE NOT NULL,100                    goal         TEXT NOT NULL,101                    deadline     TIMESTAMPTZ NOT NULL,102                    current_mode VARCHAR(20) NOT NULL DEFAULT 'build',103                    is_active    BOOLEAN NOT NULL DEFAULT true,104                    priority     VARCHAR(20) NOT NULL DEFAULT 'low',105                    roadmap      JSONB DEFAULT '[]',106                    latest_brief TEXT,107                    created_at   TIMESTAMPTZ NOT NULL DEFAULT now()108                );109            z-[DB] Warning: Could not initialize database: )r �asyncpgZcreate_poolr��acquire�executer�r��connr�rrr�init_db�s&��2���r��110session_id�role�111tool_calls�tool_call_idc112�s��tsdSd|i}|dur||d<|r||d<|r||d<z2t��4IdH�}|�dd|dt�|��IdHWd�IdHWdS1IdHsHwYWdStyi}ztd|���WYd}~dSd}~ww)	z=Save a message to the session store using the unified schema.Nr�rXr�r��cINSERT INTO agent_session_entries (project_key, session_id, subpath, entry) VALUES ($1, $2, $3, $4)�fastapi-completionsz&[DB] Warning: Could not save message: )r�r�r�rw�dumpsr�r)r�r�rXr�r�rr�r�rrr�save_message�s0��2���r�c113�s��tsgSz4t��4IdH�}|�dd|d�IdH}dd�|D�Wd�IdHWS1IdHs2wYWdStyT}ztd|���gWYd}~Sd}~ww)zJLoad conversation history from the session store using the unified schema.Nz�SELECT entry FROM agent_session_entries WHERE project_key = $1 AND session_id = $2 AND subpath IS NOT DISTINCT FROM $3 ORDER BY idr�cS�g|]	}t�|d��qS��entry�rwrx)rB�rowrrrrE��z load_session.<locals>.<listcomp>z&[DB] Warning: Could not load session: )r�r��fetchr�r)r�r��rowsr�rrr�load_session�s$�114�4���r��115request_id�model�
finish_reasoncCsVi}|r||d<|r|si}d|��dtt���|d||d�gd�}dt�|��d�S)	z&Create an OpenAI-compatible SSE chunk.rX�	chatcmpl-zchat.completion.chunkr)�index�deltar���idrO�createdr��choiceszdata: z116 117)�intrrwr�)r�r�rXr�r��chunkrrr�118make_chunk�s119��r�zClaude Code Backendz1.0.0)�title�version�*)Z
allow_originsZ
allow_methodsZ
allow_headers�
authorizationcCs*tsdSdt��}||krtddd��dS)zVerify bearer token.N�Bearer i�ZUnauthorized��status_codeZdetail)rr)r�Zexpectedrrr�auths120�r�c�s��gd�}d}d}gd�}|D]121}dddd�t|<qtd�|D]�}t��}zXt�d	�4IdH�tjjj|d122dd�gd
d�IdHWd�IdHn1IdHsRwYt��|}d|d�d�|d�t|<td|�d|d�d��||kr}|}|}Wq t	y�}zdddd�t|<td|�d|���WYd}~q d}~ww|r�|a123tdt124�d|d�d��dSda125tdt126���dS)N)r&r%r'r)r+g8�@)r(r$r,zONLINE (Stable)ZFast皙�����?��status�latencyZraw_latencyzHPeriodic health check started: verifying unstable frontier NIM models...g.@�userz1+1=�r�rXr��r��messagesZ127max_tokens�ONLINErG�szModel checked: z is ONLINE (zs)ZOFFLINE�N/Az is OFFLINE / TIMEOUT: zBest frontier model selected: r�r(zGAll frontier models offline. Falling back to stable recommended model: )�MODEL_STATUSESrr�anyioZ128fail_after�129nim_client�chat�completions�creater��RECOMMENDED_MODEL)Zmodels_to_testZ130best_modelZbest_latencyZ
stable_modelsr�Z131start_timer�r�rrr�check_models_health#sF�132�(�� ��r�c133�sj�t�d�IdH	zt�IdHWnty+}z
td|���WYd}~nd}~wwt�d�IdHq134)Nr�TzHealth check loop error: i�)r:r>r�r�r)r�rrr�periodic_health_check_loop[s����r��startupc�sT�t�IdHtt�jddd�t��D]\}}dddd�t|<qtdt���dS)NTr.r�z0.10sr�r�z$FastAPI backend started. Workspace: )r�rr!r��135ALL_MODELSrur�r)�model_id�display_namerrrr�es�u�You are an expert coding assistant with access to tools for file operations and command execution. 136 137When the user asks you to create, edit, or debug code:1381. Use `list_directory` and `read_file` to understand the current state1392. Use `write_file` to create or modify files1403. Use `run_bash` to execute commands (install packages, run scripts, test code)1414. Use `grep_search` to find patterns in code142 143IMPORTANT RULES:144- Always use tools to take action. Do NOT just describe what to do — actually DO it.145- After writing code, run it to verify it works.146- If a command fails, read the error and fix it.147- Work in the /tmp/workspace directory.148- Be concise in your explanations, but thorough in your tool usage.149r�c150CsBt|�dkr|Sg}|r|d�d�dkr|�|d�d}nd}d}|||�}||d�}|D]X}|�d�}|�d�p@d	}|d151krht|�dkrgd|dd
��dt|��d�}	|�d152|�d�|	d��q3n153|dkrr|�d�rr	t|�dkr�t|�}|dd�d|d<|�|�q3|�|�tdt|��dt|����|S)z�154    Compact conversation history to prevent context window overflow.155    Replaces massive tool call outputs with concise summaries if history is long.156    �rr��systemrj�NrXr�tooli�z[Tool output compacted: ��z... (Total z+ chars truncated for context preservation)]r��r�r�rX�	assistantr�i�z#157[Content truncated for compaction]z2[Auto-Compaction] Compressed message history from z	 down to )rHr�rrl�extendr)158r�Z	compactedZ	start_idxZrecent_countZmid_messagesZrecent_messagesrr�rX�summaryrrr�compact_history�s@159��160rz/v1/chat/completions�requestc
161�s��t|�|��IdH}|�dd��|�dg�}|�dd�}|�d�p(tt�����tv�tt���dd��t���t	d�dd	��d162����g��r�t163dd�|D��}|ry|D]}|d
dkrr��dtd|dd��q[��|�q[n��dtd����
|�nt|��t���tdd�t|�D�d�}|r�t�d|�dd��IdH|�sHzu��d�}�r�t|d<d|d<t4IdH�tjjjd/i|��IdH}	Wd�IdHn1IdHs�wY|	jdjjp�d}164t�d|165�IdHt���t	d�dd	��d��td���dtt����dd|166d�dd�gd ��WSt �yG}zt���td!t|�d"d#�id$d%�WYd}~Sd}~wwd&t!tf�����fd'd(�}t"|�d)d*d+d,d-�d.�S)0Nr�r*r��streamFr��z	Session [�z] connected. Model: css�|]167}|�d�dkVqdS)r�r�N�r��rB�mrrrr��s�z#chat_completions.<locals>.<genexpr>r�r�z168 169Additional instructions:170rXr�css"�|]}|�d�dkr|VqdS)r�r�Nr171rrrrr��s� r�r)r�r��tools�auto�tool_choicerrz] finished (non-streaming)r�zchat.completion�stop)r��messager�r��errorZinternal_error)rrR��)r�r_cs��t4IdH����zuttd�D]�}t�����dd�}�r't|d<d|d<d}i}tjjjd9i|��IdH2z�3dHW}|j	rF|j	dnd}|sKq8|j172}|r`|jr`||j7}t��|j�V|r�|j
r�|j
D]U}|j}||vr�|jpd	t��jdd173���|jr�|jjr�|jjnddd�||<|jr�|jjr�|jj||d<|jr�|j||d
<|jr�|jjr�||d|jj7<qh|jdkr�n	|jdkr�nq86q|s�t�d|�IdHt��dd�VdVWWd�IdHdSg}	t|���D]}||}|	�|d
d|d|dd�d��q�d|�pd|	d�}174��|175�|	D�]H}|dd}|dd}zt�|�}
Wn8tj�yp|��}|�d��sOd|}|� d��sY|d}zt�|�}
t!d|���Wni}
YYnwt"||
�\}}t!d|�d|���|�r�|D]176}t!d|����q�t��d|�d��V|�r�t��d �V|d!k�r�d"|v�r�t��d#|d"�d$��Vna|d%k�r�d&|v�r�t��d#|d&�d$��VnI|d'k�r�d&|v�r�t��d#|d&�d$��Vn1|d(k�rt��d#|�#d&d)��d$��Vn|d*k�rt��d#|�#d+d��d$��Vnt��d,�Vt$||�IdH}|�r6|d-d.�%|��d/�7}|dd0�t&|�d0k�rDd1nd}t��d2|�d3��V��d4|d
|d5��t�d4||d
d6�IdH�q"t��d7�Vt��dd�VdVWn,t'�y�}zd8t(|���}t��|�Vt��dd�VdVWYd}~nd}~wwWd�IdHdSWd�IdHdS1IdH�s�wYdS):NrjT)r�r�rr
rrrrZcall_r)r�rUrrUr�rrr�r)r�zdata: [DONE]177 178rM�rUr�r�rRrM�r�rXr��{�}z)Auto-fixed invalid JSON string for tool: zTool execution: z args=z[Tool Repair] u	179 180🔧 **z**z *(Auto-Repaired)*rYrZz: `z`181rNrPrVr[r�r\r]r�zJ182 183[SYSTEM REPAIR NOTE: The harness automatically fixed formatting issues: z, zn. Please strictly follow the tool's JSON schema in subsequent calls without these wrapping/formatting errors.]r�...z```184z185```186r�r)r�u*187 188⚠️ Reached maximum tool call rounds.u
189 190❌ Error: r))�completions_semaphore�ranger#r�TOOLSr�r�r�r�r�r�rXr�r�r�r��uuid�uuid4�hexrMrUrr�r�r�rnrrwrxZJSONDecodeErrorrtrbrvrr~r�r�r�rHr�ra)�	round_num�kwargsZfull_contentZtool_calls_rawr��choicer��tc�idxZtool_calls_listZ
assistant_msgrg�raw_args_str�	func_args�repaired_strryZrepair_notesZnote�resultZpreviewr�Z	error_msg��final_messages�191is_agenticr�Zrequested_modelr�rr�generate�s��&192193194195196��197198���#�8199�200201202��203 204 "�205������0�z"chat_completions.<locals>.generateztext/event-streamzno-cache�noz206keep-alive)z
Cache-ControlzX-Accel-BufferingZ207Connection)�208media_type�headersr)#r�rwr�rarr�TOOL_CAPABLE_MODELS�ACTIVE_SESSIONS�addrr�r�AGENTIC_SYSTEM_PROMPTrrmr�next�reversedr�rrr�r�r�r�r�rrX�discardrr�rr�rr
)
rr��bodyr�rZ209has_systemrZuser_msgr!�responserXr�r,rr)r�chat_completions�s��210211��	212(�213214215�216&����r9z217/v1/modelsc�sD�t|�g}t��D]\}}|�|dddg|dd��qd|d�S)Nr�i�Sez218nvidia-nim)r�rOr�Zowned_byZ219permission�rootr�rm)rO�data)r�r�rur)r�Zmodelsr�r�rrr�list_models�s�220�221	r<z/api/workspace/treec222�s|�dtdtdtf�fdd��ztt���}|��s |jddd��||�WSty=}zdt|�iWYd}~Sd}~ww)	N�current_path�relative_tor_cs�|j}z
t|�|���dd�}Wntyd}Ynw|dkr"d}|��rXg}zt|��dd�d�D]}|jdvr;q3|��||��q3Wn	t	yNYnw|pRd	|d223|d�S||d|�224�rf|��jd�Sd
d�S)N�\r�rr�cSs|��|jfSr�)r�rU)�xrrr�<lambda>�sz8get_workspace_tree.<locals>.build_tree.<locals>.<lambda>�rz)�.git�node_modules�.next�__pycache__z.agentsz.geminirdZ	directory)rUrPrR�children�filer)rUrPrRr�)
rUrar>r�rcr�r�r�rr�r�r�r�)r=r>rUr^rG�child��225build_treerrrK�s>�226�����z&get_workspace_tree.<locals>.build_treeTr.r)rrlr!r`r�r�r�ra)Zw_pathr�rrJr�get_workspace_tree�s� ��rLz/api/workspace/filec227�sj�zt|�}|��r|��stddd��|jddd�}||d�WSty4}ztdt|�d��d}~ww)	Ni�zFile not foundr�r�r�r�rWr)rfr�r�rr�r�ra)rPZsafe_prXr�rrr�get_workspace_file�s���rMu_l228<!DOCTYPE html>229<html lang="en">230<head>231    <meta charset="UTF-8">232    <meta name="viewport" content="width=device-width, initial-scale=1.0">233    <title>Claude Code Agent Console</title>234    <script src="https://cdn.tailwindcss.com"></script>235    <style>236        @import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;700&family=Outfit:wght@400;600;800&display=swap');237        body {238            font-family: 'Outfit', sans-serif;239            background-color: #0b0c10;240        }241        .code-font {242            font-family: 'Fira Code', monospace;243        }244        .glow-amber {245            box-shadow: 0 0 15px rgba(245, 158, 11, 0.2);246        }247    </style>248</head>249<body class="text-gray-100 min-h-screen flex flex-col pb-10">250    <header class="border-b border-gray-800 bg-gray-950/80 backdrop-blur px-6 py-4 flex items-center justify-between sticky top-0 z-50">251        <div class="flex items-center space-x-3">252            <span class="text-2xl font-extrabold tracking-tight bg-gradient-to-r from-blue-400 via-indigo-400 to-purple-400 bg-clip-text text-transparent">253                Claude Code Agent Console254            </span>255            <span class="px-2 py-0.5 text-xs rounded bg-blue-500/10 text-blue-400 border border-blue-500/20 font-semibold animate-pulse">256                LIVE257            </span>258        </div>259        <div class="flex items-center space-x-4 text-sm text-gray-400">260            <div>Workspace: <span class="text-gray-200 code-font">/tmp/workspace</span></div>261            <div class="h-4 w-px bg-gray-800"></div>262            <div>Active Sessions: <span id="active-sessions-count" class="text-blue-400 font-bold code-font">0</span></div>263        </div>264    </header>265 266    <!-- Navigation Tabs -->267    <div class="border-b border-gray-800 max-w-7xl w-full mx-auto px-6 mt-6 flex space-x-6 text-sm">268        <button onclick="switchTab('models')" id="tab-btn-models" class="pb-3 border-b-2 border-blue-500 font-semibold text-blue-400 transition-all">NIM Models</button>269        <button onclick="switchTab('logs')" id="tab-btn-logs" class="pb-3 border-b-2 border-transparent text-gray-400 hover:text-gray-200 font-semibold transition-all">Live Logs</button>270        <button onclick="switchTab('eternity')" id="tab-btn-eternity" class="pb-3 border-b-2 border-transparent text-gray-400 hover:text-gray-200 font-semibold transition-all">Eternity R&D Lab</button>271        <button onclick="switchTab('explorer')" id="tab-btn-explorer" class="pb-3 border-b-2 border-transparent text-gray-400 hover:text-gray-200 font-semibold flex items-center space-x-1 transition-all">272            <span>Workspace Explorer (IDE)</span>273            <span class="px-1.5 py-0.5 rounded bg-blue-500/10 text-blue-400 border border-blue-500/20 text-[10px] font-bold">VS Code View</span>274        </button>275    </div>276 277    <!-- MAIN SECTIONS -->278    <main class="max-w-7xl w-full mx-auto px-6 mt-8 flex-1">279        280        <!-- SECTION: Models -->281        <div id="section-models" class="space-y-6">282            <div class="flex items-center justify-between">283                <h2 class="text-lg font-bold tracking-tight text-gray-300">Nvidia NIM Models & Health Status</h2>284                <span class="text-xs text-gray-500">Checked every 15 mins</span>285            </div>286            <div id="models-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">287                <!-- Dynamically loaded models go here -->288            </div>289        </div>290 291        <!-- SECTION: Logs -->292        <div id="section-logs" class="hidden space-y-6">293            <h2 class="text-lg font-bold tracking-tight text-gray-300">System Activity Logs</h2>294            <div class="border border-gray-800 rounded-lg overflow-hidden bg-gray-950 flex flex-col min-h-[500px]">295                <div class="bg-gray-900 px-4 py-2 border-b border-gray-800 flex items-center justify-between">296                    <span class="text-xs text-gray-400 font-semibold code-font">agent-stdout.log</span>297                    <div class="flex space-x-1.5">298                        <span class="w-2.5 h-2.5 rounded-full bg-red-500/30"></span>299                        <span class="w-2.5 h-2.5 rounded-full bg-yellow-500/30"></span>300                        <span class="w-2.5 h-2.5 rounded-full bg-green-500/30"></span>301                    </div>302                </div>303                <div id="terminal-content" class="p-4 flex-1 overflow-y-auto code-font text-xs text-green-400 bg-black/90 space-y-1 select-all h-[450px]">304                    <!-- Logs go here -->305                </div>306            </div>307        </div>308 309        <!-- SECTION: Workspace Explorer -->310        <div id="section-explorer" class="hidden space-y-6">311            <div class="flex items-center justify-between">312                <h2 class="text-lg font-bold tracking-tight text-gray-300">Visual Workspace IDE</h2>313                <button onclick="refreshFileTree()" class="text-xs px-2.5 py-1 rounded bg-blue-500/10 text-blue-400 border border-blue-500/20 hover:bg-blue-500/20 transition-all font-semibold">314                    🔄 Refresh Tree315                </button>316            </div>317            318            <div class="grid grid-cols-1 md:grid-cols-3 gap-6 border border-gray-800 rounded-xl bg-gray-950 overflow-hidden h-[600px]">319                <!-- File Tree Sidebar -->320                <div class="border-r border-gray-800 flex flex-col bg-gray-950 h-full">321                    <div class="px-4 py-2 border-b border-gray-800 bg-gray-900 text-xs font-semibold tracking-wider text-gray-400 code-font">322                        📁 EXPLORER: WORKSPACE323                    </div>324                    <div id="file-tree" class="p-3 flex-1 overflow-y-auto space-y-0.5 select-none">325                        <!-- Tree will be loaded here -->326                        <span class="text-xs text-gray-500 italic px-2">Loading directory tree...</span>327                    </div>328                </div>329 330                <!-- Editor panel -->331                <div class="md:col-span-2 flex flex-col bg-black/40 h-full">332                    <div class="px-4 py-2 border-b border-gray-800 bg-gray-900 flex items-center justify-between">333                        <span id="editor-title" class="text-xs font-semibold text-gray-400 code-font">📄 Welcome screen</span>334                        <div class="flex space-x-1.5">335                            <span class="w-2 h-2 rounded-full bg-gray-700"></span>336                            <span class="w-2 h-2 rounded-full bg-gray-700"></span>337                        </div>338                    </div>339                    <div class="flex-1 p-4 overflow-auto code-font text-xs text-gray-200">340                        <pre id="editor-content" class="whitespace-pre overflow-x-auto select-text h-[500px]">341Welcome to Claude Code Workspace Explorer.342Select a file from the sidebar explorer on the left to read its code contents in real-time.343                        </pre>344                    </div>345                </div>346            </div>347        </div>348 349        <!-- SECTION: Eternity Lab -->350        <div id="section-eternity" class="hidden space-y-6">351            <div class="flex items-center justify-between border-b border-gray-800 pb-4">352                <div>353                    <h2 class="text-xl font-bold tracking-tight text-gray-200">Eternity R&D Projects</h2>354                    <p class="text-xs text-gray-500 mt-1">Autonomous multi-agent loop orchestrator panel</p>355                </div>356                <button onclick="openNewProjectModal()" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded text-sm font-semibold transition-all shadow-lg glow-amber">357                    ➕ New R&D Goal358                </button>359            </div>360            361            <div id="eternity-projects-list" class="grid grid-cols-1 gap-6">362                <!-- Dynamically populated project cards -->363            </div>364        </div>365 366    </main>367 368    <!-- MODAL: New Project -->369    <div id="new-project-modal" class="fixed inset-0 bg-black/80 backdrop-blur-sm flex items-center justify-center hidden z-50">370        <div class="bg-gray-900 border border-gray-800 p-6 rounded-xl max-w-md w-full space-y-4">371            <h3 class="text-lg font-bold text-gray-100">Initialize R&D Goal</h3>372            <div class="space-y-3 text-sm">373                <div>374                    <label class="block text-gray-400 mb-1">Project Name (Letters/Numbers/Dashes only)</label>375                    <input id="proj-name" type="text" class="w-full bg-black border border-gray-800 rounded p-2 text-gray-200" placeholder="e.g. stoichiometry-solver">376                </div>377                <div>378                    <label class="block text-gray-400 mb-1">Problem Statement / Goal</label>379                    <textarea id="proj-goal" rows="4" class="w-full bg-black border border-gray-800 rounded p-2 text-gray-200" placeholder="Describe the goal in detail..."></textarea>380                </div>381                <div class="grid grid-cols-2 gap-4">382                    <div>383                        <label class="block text-gray-400 mb-1">Deadline (Hours)</label>384                        <input id="proj-deadline" type="number" step="0.01" value="1.0" class="w-full bg-black border border-gray-800 rounded p-2 text-gray-200">385                    </div>386                    <div>387                        <label class="block text-gray-400 mb-1">Priority</label>388                        <select id="proj-priority" class="w-full bg-black border border-gray-800 rounded p-2 text-gray-200">389                            <option value="supreme">Supreme Priority</option>390                            <option value="low" selected>Low Priority</option>391                        </select>392                    </div>393                </div>394            </div>395            <div class="flex justify-end space-x-3 text-sm pt-2">396                <button onclick="closeNewProjectModal()" class="px-4 py-2 border border-gray-800 text-gray-400 rounded hover:bg-gray-800">Cancel</button>397                <button onclick="submitNewProject()" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded font-semibold">Start R&D</button>398            </div>399        </div>400    </div>401 402    <script>403        let currentTab = 'models';404 405        function switchTab(tabId) {406            currentTab = tabId;407            // Toggle sections408            document.getElementById('section-models').classList.add('hidden');409            document.getElementById('section-logs').classList.add('hidden');410            document.getElementById('section-explorer').classList.add('hidden');411            document.getElementById('section-eternity').classList.add('hidden');412            413            document.getElementById('tab-btn-models').className = 'pb-3 border-b-2 border-transparent text-gray-400 hover:text-gray-200 font-semibold transition-all';414            document.getElementById('tab-btn-logs').className = 'pb-3 border-b-2 border-transparent text-gray-400 hover:text-gray-200 font-semibold transition-all';415            document.getElementById('tab-btn-eternity').className = 'pb-3 border-b-2 border-transparent text-gray-400 hover:text-gray-200 font-semibold transition-all';416            document.getElementById('tab-btn-explorer').className = 'pb-3 border-b-2 border-transparent text-gray-400 hover:text-gray-200 font-semibold flex items-center space-x-1 transition-all';417 418            if (tabId === 'models') {419                document.getElementById('section-models').classList.remove('hidden');420                document.getElementById('tab-btn-models').className = 'pb-3 border-b-2 border-blue-500 font-semibold text-blue-400 transition-all';421            } else if (tabId === 'logs') {422                document.getElementById('section-logs').classList.remove('hidden');423                document.getElementById('tab-btn-logs').className = 'pb-3 border-b-2 border-blue-500 font-semibold text-blue-400 transition-all';424            } else if (tabId === 'explorer') {425                document.getElementById('section-explorer').classList.remove('hidden');426                document.getElementById('tab-btn-explorer').className = 'pb-3 border-b-2 border-blue-500 font-semibold text-blue-400 flex items-center space-x-1 transition-all';427                refreshFileTree();428            } else if (tabId === 'eternity') {429                document.getElementById('section-eternity').classList.remove('hidden');430                document.getElementById('tab-btn-eternity').className = 'pb-3 border-b-2 border-blue-500 font-semibold text-blue-400 transition-all';431                fetchEternityProjects();432            }433        }434 435        async function fetchSystemData() {436            try {437                const res = await fetch('/health');438                if (!res.ok) return;439                const data = await res.json();440                document.getElementById('active-sessions-count').innerText = data.active_sessions || 0;441            } catch (e) {442                console.error(e);443            }444        }445 446        async function fetchModels() {447            try {448                const res = await fetch('/api/models-status');449                if (!res.ok) return;450                const models = await res.json();451                452                const container = document.getElementById('models-container');453                container.innerHTML = '';454                455                models.forEach(model => {456                    const isRec = model.is_recommended;457                    const isOnline = model.status.includes('ONLINE');458                    459                    const card = document.createElement('div');460                    card.className = `p-4 border rounded-xl bg-gray-950 transition-all ${461                        isRec ? 'border-amber-500/50 glow-amber bg-amber-500/5' : 'border-gray-800 bg-gray-950'462                    }`;463                    464                    card.innerHTML = `465                        <div class="flex items-center justify-between mb-3">466                            <span class="text-xs text-gray-500 code-font truncate max-w-[200px]" title="${model.id}">${model.id}</span>467                            <div class="flex items-center space-x-2">468                                ${isRec ? '<span class="text-[10px] px-1.5 py-0.5 rounded bg-amber-500/10 text-amber-400 border border-amber-500/20 font-bold">★ Recommended</span>' : ''}469                                <span class="h-2 w-2 rounded-full ${isOnline ? 'bg-green-500 animate-pulse' : 'bg-red-500'}"></span>470                                <span class="text-[10px] font-bold ${isOnline ? 'text-green-400' : 'text-red-400'}">${model.status}</span>471                            </div>472                        </div>473                        <h3 class="text-sm font-bold text-gray-200 mb-2 truncate">${model.name}</h3>474                        <div class="flex items-center justify-between text-xs text-gray-400 border-t border-gray-900 pt-2">475                            <span>Type: <strong class="text-gray-300 font-medium">${model.type}</strong></span>476                            <span>Latency: <strong class="text-blue-400 code-font">${model.latency}</strong></span>477                        </div>478                    `;479                    container.appendChild(card);480                });481            } catch (e) {482                console.error(e);483            }484        }485 486        async function fetchLogs() {487            if (currentTab !== 'logs') return;488            try {489                const res = await fetch('/api/logs');490                if (!res.ok) return;491                const logs = await res.json();492                493                const term = document.getElementById('terminal-content');494                const shouldScroll = term.scrollHeight - term.clientHeight <= term.scrollTop + 50;495                term.innerHTML = logs.map(line => `<div>${line}</div>`).join('');496                if (shouldScroll) {497                    term.scrollTop = term.scrollHeight;498                }499            } catch (e) {500                console.error(e);501            }502        }503 504        // File Explorer Logic505        async function refreshFileTree() {506            try {507                const res = await fetch('/api/workspace/tree');508                if (!res.ok) return;509                const root = await res.json();510                511                const container = document.getElementById('file-tree');512                container.innerHTML = renderNode(root);513            } catch (e) {514                console.error(e);515            }516        }517 518        function renderNode(node, depth = 0) {519            const isDir = node.type === 'directory';520            const icon = isDir ? '📁' : '📄';521            const indent = depth * 12;522            523            let html = `524                <div class="flex items-center py-1 px-2 hover:bg-gray-800 rounded cursor-pointer transition-all text-xs" 525                     style="padding-left: ${indent}px"526                     onclick="${isDir ? `toggleDir('${node.path}')` : `openFile('${node.path}')`}">527                    <span class="mr-2">${icon}</span>528                    <span class="truncate ${isDir ? 'text-gray-300 font-medium' : 'text-gray-400'}">${node.name}</span>529                </div>530            `;531            532            if (isDir && node.children && node.children.length > 0) {533                html += `<div id="dir-${node.path.replace(/\/g, '-').replace(/\//g, '-')}" class="space-y-0.5">`;534                node.children.forEach(child => {535                    html += renderNode(child, depth + 1);536                });537                html += `</div>`;538            } else if (isDir && (!node.children || node.children.length === 0)) {539                html += `<div class="text-[10px] text-gray-600 italic" style="padding-left: ${indent + 16}px">(empty)</div>`;540            }541            542            return html;543        }544 545        async function openFile(path) {546            document.getElementById('editor-title').innerText = `📄 ${path}`;547            document.getElementById('editor-content').innerText = "Loading file content...";548            try {549                const res = await fetch(`/api/workspace/file?path=${encodeURIComponent(path)}`);550                if (!res.ok) {551                    document.getElementById('editor-content').innerText = "Error: Failed to fetch file content.";552                    return;553                }554                const data = await res.json();555                document.getElementById('editor-content').innerText = data.content;556            } catch (e) {557                document.getElementById('editor-content').innerText = `Error: ${e.message}`;558            }559        }560 561        function toggleDir(path) {562            const safeId = `dir-${path.replace(/\/g, '-').replace(/\//g, '-')}`;563            const elem = document.getElementById(safeId);564            if (elem) {565                elem.classList.toggle('hidden');566            }567        }568 569        // Eternity R&D UI Logic570        function openNewProjectModal() {571            document.getElementById('new-project-modal').classList.remove('hidden');572        }573 574        function closeNewProjectModal() {575            document.getElementById('new-project-modal').classList.add('hidden');576        }577 578        async function submitNewProject() {579            const name = document.getElementById('proj-name').value.trim();580            const goal = document.getElementById('proj-goal').value.trim();581            const deadline = parseFloat(document.getElementById('proj-deadline').value) || 1.0;582            const priority = document.getElementById('proj-priority').value;583 584            if (!goal) {585                alert('Please enter a goal statement.');586                return;587            }588 589            try {590                const res = await fetch('/api/eternity/init', {591                    method: 'POST',592                    headers: { 'Content-Type': 'application/json' },593                    body: JSON.stringify({594                        project_name: name,595                        goal: goal,596                        deadline_hours: deadline,597                        priority: priority598                    })599                });600                if (res.ok) {601                    closeNewProjectModal();602                    // Clear fields603                    document.getElementById('proj-name').value = '';604                    document.getElementById('proj-goal').value = '';605                    fetchEternityProjects();606                } else {607                    const data = await res.json();608                    alert(`Failed: ${data.detail || 'Unknown error'}`);609                }610            } catch (e) {611                alert(`Error: ${e.message}`);612            }613        }614 615        async function toggleActive(projName, isActive) {616            try {617                await fetch('/api/eternity/toggle', {618                    method: 'POST',619                    headers: { 'Content-Type': 'application/json' },620                    body: JSON.stringify({ project_name: projName, is_active: isActive })621                });622                fetchEternityProjects();623            } catch (e) {624                console.error(e);625            }626        }627 628        async function setPriority(projName, priorityVal) {629            try {630                await fetch('/api/eternity/set-priority', {631                    method: 'POST',632                    headers: { 'Content-Type': 'application/json' },633                    body: JSON.stringify({ project_name: projName, priority: priorityVal })634                });635                fetchEternityProjects();636            } catch (e) {637                console.error(e);638            }639        }640 641        async function fetchEternityProjects() {642            if (currentTab !== 'eternity') return;643            try {644                const res = await fetch('/api/eternity/list');645                if (!res.ok) return;646                const data = await res.json();647                648                const container = document.getElementById('eternity-projects-list');649                if (data.projects.length === 0) {650                    container.innerHTML = `651                        <div class="text-center py-12 border border-dashed border-gray-800 rounded-lg text-gray-500">652                            No active R&D goals configured. Click "New R&D Goal" to launch one!653                        </div>654                    `;655                    return;656                }657                658                container.innerHTML = data.projects.map(p => {659                    const modeColor = p.current_mode === 'build' ? 'from-amber-500/20 to-orange-500/20 text-orange-400 border-orange-500/30' : 'from-green-500/20 to-emerald-500/20 text-green-400 border-green-500/30';660                    const activeBadge = p.is_active ? '<span class="bg-green-500/10 text-green-400 border border-green-500/20 px-2 py-0.5 rounded text-[10px] font-bold">ACTIVE</span>' : '<span class="bg-gray-800 text-gray-500 border border-gray-700 px-2 py-0.5 rounded text-[10px] font-bold">PAUSED</span>';661                    const priorityColor = p.priority === 'supreme' ? 'bg-red-500/10 text-red-400 border-red-500/20' : 'bg-blue-500/10 text-blue-400 border-blue-500/20';662                    663                    return `664                        <div class="bg-gray-950 border border-gray-800 rounded-xl p-6 space-y-4 hover:border-gray-700 transition-all">665                            <div class="flex items-start justify-between">666                                <div class="space-y-1">667                                    <div class="flex items-center space-x-2">668                                        <h3 class="text-lg font-bold text-gray-200 code-font">${p.project_name}</h3>669                                        ${activeBadge}670                                        <span class="px-2 py-0.5 rounded text-[10px] font-bold border ${priorityColor}">${p.priority.toUpperCase()}</span>671                                    </div>672                                    <p class="text-xs text-gray-500">Started on ${new Date(p.created_at).toLocaleString()}</p>673                                </div>674                                <div class="flex items-center space-x-3">675                                    <select onchange="setPriority('${p.project_name}', this.value)" class="bg-black border border-gray-850 rounded px-2.5 py-1 text-xs text-gray-300 focus:outline-none">676                                        <option value="supreme" ${p.priority === 'supreme' ? 'selected' : ''}>Supreme</option>677                                        <option value="low" ${p.priority === 'low' ? 'selected' : ''}>Low</option>678                                    </select>679                                    680                                    <button onclick="toggleActive('${p.project_name}', ${!p.is_active})" class="text-xs px-3.5 py-1 rounded border ${p.is_active ? 'border-red-500/30 text-red-400 bg-red-500/5 hover:bg-red-500/10' : 'border-green-500/30 text-green-400 bg-green-500/5 hover:bg-green-500/10'} font-semibold transition-all">681                                        ${p.is_active ? 'Pause' : 'Resume'}682                                    </button>683                                </div>684                            </div>685                            686                            <div class="space-y-2">687                                <div class="text-sm text-gray-300 font-semibold">Goal Description:</div>688                                <div class="text-sm text-gray-400 bg-black/40 p-3 rounded border border-gray-900 leading-relaxed">${p.goal}</div>689                            </div>690                            691                            <div class="grid grid-cols-2 gap-4 text-xs">692                                <div class="bg-gray-900/50 p-3 rounded border border-gray-850 space-y-1">693                                    <div class="text-gray-500">Mode Status</div>694                                    <div class="font-bold bg-gradient-to-r ${modeColor} bg-clip-text text-transparent">${p.current_mode.toUpperCase()} MODE</div>695                                </div>696                                <div class="bg-gray-900/50 p-3 rounded border border-gray-850 space-y-1">697                                    <div class="text-gray-500">Deadline Countdown</div>698                                    <div class="font-bold text-gray-200 code-font">${p.time_remaining_str || 'Expired'}</div>699                                </div>700                            </div>701                            702                            ${p.latest_brief ? `703                                <div class="bg-blue-950/20 border border-blue-900/30 rounded p-4 text-xs text-blue-300 leading-relaxed space-y-1">704                                    <div class="font-bold text-blue-400 flex items-center space-x-1">705                                        <span>📘 Latest Research Brief Summary</span>706                                    </div>707                                    <div class="text-blue-300 mt-1">${p.latest_brief}</div>708                                </div>709                            ` : ''}710                        </div>711                    `;712                }).join('');713            } catch (e) {714                console.error(e);715            }716        }717 718        setInterval(fetchSystemData, 3000);719        setInterval(fetchModels, 3000);720        setInterval(fetchLogs, 2000);721        setInterval(fetchEternityProjects, 5000);722        723        fetchSystemData();724        fetchModels();725        fetchLogs();726    </script>727</body>728</html>729rFc@sBeZdZUeed<eed<dZeeed<eeee	fed<dS)�SessionAppendRequest�project_keyr�N�subpathr�)730rJrKrLra�__annotations__rPrrrrrrrrrN�s731732rNz/api/sessions/append�reqc733�s��t|�ts
tddd��zT�jD]}|�d�dkr+|�d�dkr+td|�d	����q�fd734d��jD�}t��4IdH�}|�d|�IdHWd�IdHn1IdHsXwYd
diWSty|}ztd|���tdt	|�d��d}~ww)Nr�Database not connectedr�rRr�ZsubtypeZmirror_errorz0[ALERT] Claude Agent SDK reported mirror_error: rcs$g|]}�j�j�jt�|�f�qSr)rOr�rPrwr�)rBr��rRrrrEs$z*append_session_entries.<locals>.<listcomp>r�r��successz$[SessionStore Error] Failed append: )735r�r�rr�r�rr�Zexecutemanyr�ra)rRr�r�r�r�rrTr�append_session_entries�s,�736��(�737��rVc@s.eZdZUeed<eed<dZeeed<dS)�SessionLoadRequestrOr�NrP)rJrKrLrarQrPrrrrrrWs738rWz/api/sessions/loadc739�s��t|�ts
tddd��z6t��4IdH�}|�d|j|j|j�IdH}Wd�IdHn1IdHs5wYddd�|D�iWSty^}zt	d|���tdt740|�d��d}~ww)	NrrSr�z~SELECT entry FROM agent_session_entries WHERE project_key=$1 AND session_id=$2 AND subpath IS NOT DISTINCT FROM $3 ORDER BY idr�cSr�r�r��rB�rrrrrE"r�z(load_session_entries.<locals>.<listcomp>z"[SessionStore Error] Failed load: )r�r�rr�r�rOr�rPr�rra�rRr�r�r�r�rrr�load_session_entriess"��(���r[c@seZdZUeed<dS)�SessionListRequestrON�rJrKrLrarQrrrrr\'s741r\z/api/sessions/listc742�s��t|�ts
tddd��z2t��4IdH�}|�d|j�IdH}Wd�IdHn1IdHs1wYddd�|D�iWStyS}ztdt|�d��d}~ww)NrrSr�zJSELECT DISTINCT session_id FROM agent_session_entries WHERE project_key=$1ZsessionscSsg|]}|d�qS)r�rrXrrrrE5sz!list_sessions.<locals>.<listcomp>)r�r�rr�r�rOr�rarZrrr�
list_sessions*s ��(���r^c@�eZdZUeed<eed<dS)�SessionDeleteRequestrOr�Nr]rrrrr`9�743r`z/api/sessions/deletec744�s��t|�ts
tddd��z/t��4IdH�}|�d|j|j�IdHWd�IdHn1IdHs3wYddiWStyP}ztdt|�d��d}~ww)NrrSr�zHDELETE FROM agent_session_entries WHERE project_key=$1 AND session_id=$2r�rU)	r�r�rr�r�rOr�r�ra)rRr�r�r�rrr�delete_session=s ��(�745��rb)�datetime�	timedelta�timezonec@sVeZdZUdZeeed<dZeeed<dZeeed<e	ed<dZ746eeed<dS)�EternityInitRequestN�project_name�goal�problem_statement�deadline_hours�low�priority)rJrKrLrgrrarQrhri�floatrlrrrrrfOs747rfz/api/eternity/initc748�s0�ts	tddd��zs|jp|jpd}ddl}|j}|s-|�dd|����d�dd�p,d	}t	�749tj�t
|jd750�}t��4IdH�}|�d||||jpLd�IdHWd�IdHn1IdHsawYtd
|�d|�d|j���d||��d�WSty�}ztd|���tdt|�d��d}~ww)NrrSr�zBuild a calculatorrz751[^a-z0-9]+�-r�Zproject)Zhoursay752                INSERT INTO eternity_projects (project_name, goal, deadline, current_mode, priority, is_active)753                VALUES ($1, $2, $3, 'build', $4, true)754                ON CONFLICT (project_name) DO UPDATE 755                SET goal = EXCLUDED.goal, deadline = EXCLUDED.deadline, current_mode = 'build', priority = EXCLUDED.priority, is_active = true756            rk�[Eternity Loop] Project 'z' initialized | Goal: 'z' | Priority: rU)r�rg�deadlinez#[Eternity Loop Error] Init failed: )r�rrhrirprg�subr�rtrcr?re�utcrdrjr�r�rlr�	isoformatr�ra)rRZ	goal_textrpZslugrpr�r�rrr�init_eternity_systemVs,�$�(���rtc@seZdZUeed<eed<dS)�EternityToggleRequestrg�	is_activeN)rJrKrLrarQ�boolrrrrrupraruz/api/eternity/togglec757�s��ts	tddd��z;t��4IdH�}|�d|j|j�IdHWd�IdHn1IdHs/wYtd|j�d|j���ddiWStyX}ztdt|�d��d}~ww)	NrrSr�zCUPDATE eternity_projects SET is_active = $1 WHERE project_name = $2roz' is_active set to r�rU)	r�rr�r�rvrgrr�ra�rRr�r�rrr�toggle_projectts�(�758��ryc@r_)�EternityPriorityRequestrgrlNr]rrrrrz�rarzz/api/eternity/set-priorityc759�s��ts	tddd��zF|jdvrtddd��t��4IdH�}|�d|j|j�IdHWd�IdHn1IdHs:wYtd|j�d	|j���d760diWStyc}ztdt|�d��d}~ww)NrrSr�)Zsupremerki�zInvalid priorityzBUPDATE eternity_projects SET priority = $1 WHERE project_name = $2roz' priority set to r�rU)	r�rrlr�r�rgrr�rarxrrr�set_project_priority�s�761(�762��r{z/api/eternity/listc�sH�ts	tddd��z�t��4IdH�p}|�d�IdH}g}t�tj�}|D]M}|d}td||�	��}|dkrOt763|d�}t764|dd	�}|�d765|�d�}	nd}	|�|d
|d|��|d|d|d|d|d��|	d�	�q%d|iWd�IdHWS1IdHs�wYWdSt
y�}766ztdt|767�d��d}768~769ww)NrrSr�z�SELECT project_name, goal, deadline, current_mode, is_active, priority, latest_brief, created_at FROM eternity_projects ORDER BY created_at DESCrpr5rir4zh rZExpiredrgrh�current_modervrl�latest_brief�770created_at)	rgrhrpr|rvrlr}r~Ztime_remaining_str�projects)r�rr�r�rcr?rerr�max�
total_secondsr�rrsr�ra)r�r�rr?rYrp�	remaining�hrZrem_strr�rrr�list_eternity_projects�sB�771772�4���r�z/api/eternity/statusc773�s"�ts	tddd��zst��4IdH�]}|�d�IdH}|s,ddiWd�IdHWS|d}t�tj�}td||�	��}d	|d774|d|�775�|dt|d
t�rZt
�|d
�n|d
|d|d�Wd�IdHWS1IdHsuwYWdSty�}ztdt|�d��d}~ww)NrrSr�z�SELECT project_name, goal, deadline, current_mode, roadmap, latest_brief FROM eternity_projects WHERE is_active = true ORDER BY id DESC LIMIT 1�activeFrpr5Trgrhr|�roadmapr})r�rgrhrpr|r�r}Ztime_remaining_seconds)r�rr�Zfetchrowrcr?rerrr�r�rsrorarwrxr�)r�r�rpr?r�r�rrr�get_eternity_status�s4��"�4���r�c@s6eZdZUeed<eed<eed<dZeeed<dS)�ForgeExecuteRequest�task_id�action�promptr�
context_rulesN)rJrKrLrarQr�rrrrrr��s776777r��/api/forge/executec
�s.�t|�td|j�d|j�d��z�dtd|j��d�d|jd�g}t|�}d}d	}d}ttd778�D]�}t	�779�IdHtjj
jt|tdd�IdH}|jd
j}	d}780|	jrrg}781|	jD]}|j|j|jj|jjd�d�}|782�|�q[|�d|	j|783d��|	js�d}|	jp�d}n]|	jD]V}|jj}
|jj}zt�|�}Wn2ty�|��}|�d�s�d|}|� d�s�|d}zt�|�}Wnty�i}YnwYnwt!|
|�IdH}|�d|j|d��q�q4d}|r�d|dd�WSd|p�dd�WSt�y}ztd|���dt"|�d�WYd}~Sd}~ww)Nz,[Forge] Received execution request for task z: 'rir�z784Context rules: r�r�Frrjr)r�r�r
rrrrrrTzTask completed.rrr�rzMax tool call rounds exceeded.rU)r�rrrzTask execution failed.�r�rz%[Forge Error] Task execution failed: )#r�rr�r�r3r�rmrr#�rate_limiterrIr�r�r�r�r�rr�rr�r�rRrMrUrrrXrwrxr�rtrbrvr�ra)rRr�r�r*rUrrr r8rZtool_calls_payloadr#Ztc_dictrgr%r&r'r(r�rrr�
forge_execute�s��785��786���787788789790���791792�������r�c793���td�	z.tr3t��4IdH�}|�d�IdHtd�Wd�IdHn1IdHs.wYWntyM}z
td|���WYd}~nd}~wwt�d�IdHq�NzDatabase Heartbeat task startedTzSELECT 1z0[Heartbeat] Pinged Aiven PostgreSQL successfullyz-[Heartbeat Warning] Failed to ping database: ���rr�r�r�r�r:r>r�rrr�db_heartbeat_loop;� �794(�����r��795SPACE3_URLz.https://augment17-claude-code-backend.hf.space�796SPACE4_URLz&https://shyota-mcp-cloud-host.hf.space�797SPACE5_URLz)https://augment17-better-chatbot.hf.space�798SPACE6_URLz)https://augment17-mcp-cloud-host.hf.spacec	�sR�t��4IdH�}|�d�IdHWd�IdHS1IdHs"wYdS)NzzSELECT project_name, goal, deadline, current_mode, priority FROM eternity_projects WHERE is_active = true ORDER BY id DESC)r�r�r�)r�rrr�get_active_projectsMs�0�r�rg�modec	��X�t��4IdH�}|�d||�IdHWd�IdHdS1IdHs%wYdS)NzFUPDATE eternity_projects SET current_mode = $1 WHERE project_name = $2�r�r�r�)rgr�r�rrr�update_db_modeQ��.�r��briefc	�r�)NzFUPDATE eternity_projects SET latest_brief = $1 WHERE project_name = $2r�)rgr�r�rrr�update_db_briefUr�r�r�c	�s^�t��4IdH�}|�dt�|�|�IdHWd�IdHdS1IdHs(wYdS)NzAUPDATE eternity_projects SET roadmap = $1 WHERE project_name = $2)r�r�r�rwr�)rgr�r�rrr�update_db_roadmapYs�.�r��url�payloadc799Cs�dt��dd�}tjj|t�|��d�|dd�}z&tjj|dd��}t�|�	��800d��Wd�WS1s7wYWdStya}ztd	|�d801|���dt
|�d�WYd}~Sd}~ww)
Nr�zapplication/json)Z
AuthorizationzContent-Typer�ZPOST)r;r/�method�xr�z[HTTP Error] POST to z	 failed: rr�)rZurllibrr802rwr��encodeZurlopenrx�readr�r�rra)r�r�r/rRrYr�rrr�	post_json]s$��(���r�rhc803804�s��td|�d|�d��t��IdHd|�d�d}z*tjjjdd|d	�gd805d�IdH}t�|j	dj806j���}|�
d
�}|�
dd�}Wntyb}ztd|�d|���WYd}~dSd}~wwtd|�d|�d��tt�d�d|�dtt�����d||d��}|�
d�dkr�td|�d|�
d����td|�d��tt�d �d!t�d"��}	td#|	�
d$��d%|	�
d&����td'�tt�d(�i�dStd)|�
d*����dS)+Nz1[Build Mode] Initiating build cycle for project '�807' (goal: '�')zWe are building: 'z~'. Write a JSON instruction for Space 3 (The Forge) to code the next milestone. Respond ONLY with JSON matching the contract: �8{"prompt": "task description", "context_rules": "rules"}r-r�r�r�r�rr�r�rz4[Build Mode Error] NIM planning failed for project '�': z"[Build Mode] Dispatching project 'z' task to Space 3: 'rir�Zbuild_�_�execute_code�r�r�r�r�r�rUz*[Build Mode] Space 3 success for project 'rzK[Build Mode] Triggering Space 6 (The Sandbox) UI verification for project '�'...z/api/sandbox/testZ	verify_ui)Ztest_cmdr�z#[Build Mode] Space 6 Test Verdict: Zverdictz | Reason: �reasonz<[Build Mode] Triggering Space 5 (The Vault) backup commit...�/api/vault/pushz/[Build Mode Warning] Space 3 reported failure: r)rr�rIr�r�r�r�rwrxr�rrXrtr�r�r�r�r�rr�r�)808rgrhr��res�task�task_promptr�r��	forge_resZtest_resrrr�execute_build_cycleosH�809�810��811�812� r�c813�s��td|�d|�d��td|�d��tt�d�dd|��i�}|�d	d814�}t||�IdHtd|�d|dd
��d��t��IdHd|�d|�d�d}z*tjj	j815dd|d�gdd�IdH}t�|j
djj���}|�d�}|�dd�}Wnty�}	ztd|�d|	���WYd}	~	dSd}	~	wwtd|�d��tt�d�d |�d!tt�����d"||d#��}816|817�d$�d%kr�td&|818�d'����td(�tt�d)�i�dSdS)*Nz=[Eternity Mode] Initiating autonomous R&D cycle for project 'r�r�zH[Eternity Mode] Querying Space 4 (The Library) for research on project 'r�z
/api/researchZqueryz$novel algorithms and components for r�zNo new features found.z-[Eternity Mode] Received research brief for 'r�rrzGoal: 'z'. Research Brief: 'zD'. Plan the next feature/optimization code. Respond ONLY with JSON: r�r-r�r�r�r�rr�r�rz7[Eternity Mode Error] NIM planning failed for project 'z.[Eternity Mode] Dispatching task to Space 3: 'rir�Z	eternity_r�r�r�r�rUz![Eternity Mode] Space 3 success: rz?[Eternity Mode] Triggering Space 5 (The Vault) backup commit...r�)rr�r�r�r�r�rIr�r�r�r�rwrxr�rrXrtr�r�r�rr�)rgrhZresearch_resr�r�r�r�r�r�r�r�rrr�execute_eternity_cycle�sF�819�820��821��r�c
822�s��td�d}	z�tst�d�IdHWqt�IdH}|s't�d�IdHWq|d7}|D]t}|d}|d}|d	}|d823}|d}|dkrN|d
dkrNq-t�tj�}|dkrn||krnt	|d�IdHd}td|�d��|dkr{t824||�IdHq-t�|d�}	t
�
�}825ttj�dd��}|826|	|kr�q-|827t|<t||�IdHq-t�d�IdHWn!ty�}ztd|���t�d�IdHWYd}~nd}~wwq)Nz0[Eternity Loop] Async task started on main loop.rTr�r�rjrgrhrpr|rlrkr��buildZeternityroz6' deadline reached. Transitioned to Eternity R&D Mode.r5ZETERNITY_LOOP_INTERVALZ3600r�z"[Eternity Loop Error] Loop crash: r4)rr�r:r>r�rcr?rerrr�r��last_run_timesr�rr�r�r�r�r�)
Zloop_counterr�prUrhrpr|rlr?Zlast_runZnow_ts�intervalr�rrr�run_eternity_loop�sT����r�r�)Zresponse_classc�s�ttd�S)N)rX)r�DASHBOARD_HTMLrrrr�	dashboard�s�828r�z	/api/logsc�s829�tt�Sr�)rmrrrrr�get_logs�s�r�z/api/models-statusc830�sv�g}t��D])\}}t�|ddd��}|tk}|tv}|�|||d|d||r+dndd��q|jd	d831�d�|S)NzONLINE (Unchecked)r�)r�r�r�r��Agentic (Tools)z	Chat Only)r�rUr�r��is_recommendedrRcSs|d|ddk|dfS)Nr�rRr�rUr)rrrrrA
sz#get_models_status.<locals>.<lambda>rB)r�rur�r�r�r0r�sort)Zstatus_listr�r�Zstatus_infoZis_recr+rrr�get_models_status�s �832833�	r�)�FileResponsez/api/backup/downloadc834�s835�t|�d}d}|d}||fD]%}tj�|�r6ztj�|�r&t�|�nt�|�Wqty5Yqwqz.tj	t836|dt�ddd�d�t�|d	|�t�|�tj�|�s^t
d837dd��t|d
dd�WSty�}ztj�|�rxt�|�t
d838t|�d��d}~ww)N�/tmp/workspace_snapshot�/tmp/workspace_backup_download�.zipTrCrDrE��symlinks�ignore�ziprzFailed to create zip archiver�zapplication/zip�workspace_backup.zip)r.�filename)r�r�rPr��isdir�shutil�rmtree�unlinkr��copytreer!�ignore_patterns�make_archiverr�ra)r��snapshot_dir�archive_base�archive_ziprPr�rrr�download_backups:�839���	840841��r�z/healthc�s*�dttt���tdutt�ttt�d�S)N�ok)r�rdZworkspace_existsZdb_connectedZmodels_countZrecommended_modelZactive_sessions)r!rr�r�rHr�r�r1rrrr�health9s�842�r�cCsDtd�	z~ddl}|�gd��D]p}zed�|jdpg�}d|��vs*d|��vrw|jd	}|jd843}d}|dkrYz|�|�}|��rM|��|j	krMd}Wn844|j845yXYnw|swtd
|�d|�d��|��t�
d�|��rw|��Wqty�YqwWn�t�yzktjdddd�}|���d�D]Y}|���dd�}	t|	�dkr�t|	d�}t|	d�}d}|dkr�tj�d|���r�d}|s�td|�d|�d��zt�|tj�t�
d�t�|tj�Wq�ty�Yq�wq�Wn	ty�YnwYnt�y}846z
td|847���WYd}848~849nd}850~851wwt�
d�q)Nz<System Watchdog Daemon started (PPID-based Orphan detection)Tr)�pid�ppidrU�cmdliner�� r�ZclaudeZ	anthropicr�r�Frjz<[Watchdog SIGKILL] Reaping orphaned Claude Code process PID z (PPID r�rFz?ps -o pid,ppid,args | grep -E 'claude|anthropic' | grep -v grep)�shell�textr�z/proc/z9[Watchdog SIGKILL Fallback] Reaping orphaned process PID z[Watchdog Error] r4)r�psutilZprocess_iterr��infor�ZProcessZ852is_runningr�Z
STATUS_ZOMBIEZ
NoSuchProcessZ	terminaterr>r�r��ImportErrorr�Zcheck_outputrt�splitrHr�r�rPr��signal�SIGTERMZSIGKILL)r��procr|r�r�Z
parent_existsZparent_proc�out�line�partsr�rrr�run_watchdogJs�853854855��856���857�������858�r�c859�r�r�r�r�rrrr��r�c	860Cs td�	t�d�ts
qz�td�d}tj�|�rt�|�tj	|dd�d}tj�|�r3t�|�tj861t|dt�dd	d862�d�d}|d
}tj�|�rRt�
|�t�|d|�t�|�tj�|d�}tj�|�}d}||kr�tjd|�d|�d�dd�nt�||�t�
|�tjdd|tjd�tjdd|tjd�tjdd|tjd�tjdt��d|tjd�tjdd|tjd�tjdd|tjd�tjdt�d�dd|tjd�tjdd|tjd�}|jd kr�td!�ntd"�Wnt�y}z
td#|���WYd}~nd}~wwq)$NzLocal Git Backup Loop startedTr�z+[Backup] Starting local workspace backup...z/tmp/git_backup_repo)r0r�rCrDrEr�r�r�r�r�i z
split -b 50M r�z.part)r�zgit init)r�r�r�z#git config user.name 'Backup Agent'z-git config user.email 'backup@agent.internal'zgit remote add origin zgit checkout -b mainz863git add -Azgit commit -m "Auto-backup: z%Y-%m-%d %H:%M:%S�"zgit push origin main --forcerz9[Backup] Sync completed successfully (git history purged)z[Backup Error] Git push failedz[Backup Error] )rrr>r"r�rPr�r�r��makedirsr�r!r�r�r�r��getsizer��run�copyZDEVNULLrr�r�)	Zbackup_local_dirr�r�r�Ztarget_destZzip_sizeZ
max_part_sizer(r�rrr�run_backup_loop�sZ864865866867868869"870871����r�c872�s��td�	z1tr6t��4IdH�}|�d�IdH}td|���Wd�IdHn1IdHs1wYWntyP}z
td|���WYd}~nd}~wwt�d�IdHq)Nz'Database Retention Cleanup task startedTzODELETE FROM agent_session_entries WHERE created_at < NOW() - INTERVAL '30 days'z4[Cleanup] Nightly retention sweep complete. Status: z3[Cleanup Warning] Failed to run retention cleanup: i�Qr�)r�r(r�rrr�db_cleanup_loop�s$�873�(�����r�c�sN�tjtdd���tjtdd���t�t��t�t��t�t	��dS)NT)reZdaemon)874�	threadingZThreadr��startr�r:Zcreate_taskr�r�r�rrrr�
startup_event�s�r��__main__z0.0.0.0i�)ZhostZport)NNN)rNr�)��__doc__r�r�r�rwrr�r:rrp�collectionsZpathlibr�typingrrrrrZpydanticrZfastapir	r875rrZfastapi.responsesr
rrZfastapi.middleware.corsrZopenairr�r��dequerr��setr1rarr�r�ZNIM_API_KEYrr r!r"r�r#r0r�r�r�r�r1Zmistral_clientr2r�rrfrl�tuplermr~r�r�ZPoolrQr�r�r�r�ZappZadd_middlewarer�r�r�Zon_eventr�r3rZpostr9r<rLrMr�Z	SemaphorerrNrVrWr[r\r^r`rbrcrdrerfrtruryrzr{r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rJZuvicornr�rrrr�<module>s�876����	�877����������878����������������879����d"880)u,��881� �	8882 883
3m884*885~
886#887b
'%6888889890"891@
9892893�