agents-relay 2.0.118 → 2.0.119

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -352,7 +352,7 @@ function parseAgentGraphSource(source){if(typeof source!=='string'||!source.trim
352
352
  function agentGraphField(task){if(typeof task.agentGraph!=='string'||!task.agentGraph.trim())return null;const box=element('div','detail-group');box.style.gridColumn='1 / -1';box.append(element('p','detail-label',text('Task agent graph')));const graph=element('div','agent-graph');const parsed=parseAgentGraphSource(task.agentGraph);if(parsed&&parsed.waves.length){parsed.waves.forEach((wave,index)=>{const row=element('div','agent-wave');if(index>0)row.append(element('span','agent-arrow',text('↓')));for(const id of wave)row.append(element('span','agent-node',text(id+' · '+(parsed.agents.get(id)||id))));graph.append(row);});}const source=document.createElement('pre');source.className='agent-graph-source';source.textContent=task.agentGraph;graph.append(source);box.append(graph);return box;}
353
353
  function clearEvents(){displayedEventIds.clear();eventFeed.replaceChildren(element('li','empty',text('Waiting for events.')));}
354
354
  async function loadEventHistory(){const job=selected();if(!job){clearEvents();return;}const params=new URLSearchParams({job:job.id,limit:String(MAX_EVENTS)});if(eventTaskId)params.set('task',eventTaskId);try{const history=await loadJSON('/api/events?'+params.toString());clearEvents();for(const event of Array.isArray(history)?history.slice().reverse():[])addEvent(event);}catch{clearEvents();}}
355
- function copySelectedJobIdentity(job){if(!job||!navigator.clipboard?.writeText)return;void navigator.clipboard.writeText(jobChatRef(job)).catch(()=>{});}
355
+ function copySelectedJobIdentity(job){if(!job||!navigator.clipboard?.writeText)return;void navigator.clipboard.writeText(repoName(job.repository)+'/'+value(job.id)).catch(()=>{});}
356
356
  function selectJob(job){selectedJob=jobSelectionKey(job);selectedTaskId=null;eventTaskId=null;rememberSelection();clearEvents();location.hash=selectedJob?'#/jobs/'+encodeURIComponent(selectedJob):'#/jobs';copySelectedJobIdentity(job);renderAll();void loadEventHistory();}
357
357
  function matchesQuickFilter(job){if(quickMode==='autonomous')return job.executionMode==='autonomous';if(quickMode==='draft')return job.draft||job.state==='DRAFT';if(quickMode==='status')return !!selectedRuntimeStatus&&(job.runtimeStatus||'IDLE')===selectedRuntimeStatus;return true;}
358
358
  function matchesSearch(job){const query=searchQuery.trim().toLowerCase();if(!query)return true;const pr=String(job.prNumber||'');const normalized=query.replace(/^pr\s*#?/,'').replace(/^#/,'');return String(job.title||job.id||'').toLowerCase().includes(query)||String(job.id||'').toLowerCase().includes(query)||shortManagedId(job.id,job.repository,'j').toLowerCase().includes(query)||pr.includes(normalized);}
@@ -388,7 +388,7 @@ function jobChatRef(job){const pr=Number(job?.prNumber||0);return repoName(job?.
388
388
  function chatShortcutUrl(prompt){return 'https://chatgpt.com/?prompt='+encodeURIComponent(prompt);}
389
389
  const CHAT_SHORTCUT_TARGET='agents-relay-shortcut';
390
390
  function chatShortcutField(job){const box=element('div','detail-group');box.append(element('p','detail-label',text('ChatGPT shortcut')));const select=document.createElement('select');select.className='job-filter job-chat-shortcut-select';select.setAttribute('aria-label','ChatGPT shortcut');select.append(new Option('',''));for(const item of parseChatShortcuts(chatShortcutText()))select.append(new Option(item.name,item.prompt));select.value='';select.addEventListener('change',()=>{if(!select.value)return;const prompt=select.value.replaceAll('%1',jobChatRef(job));window.open(chatShortcutUrl(prompt),CHAT_SHORTCUT_TARGET,'noopener');select.value='';});box.append(select);return box;}
391
- function renderJobList(){jobList.replaceChildren();const visible=filteredJobs();if(!jobs.length){jobList.append(element('li','empty',text('No durable jobs discovered.')));return;}if(!visible.length){jobList.append(element('li','empty',text('No jobs match the selected repo.')));return;}for(const job of visible){const row=element('div','job-row'+(isCompleteUnmerged(job)?' complete-unmerged':''));row.setAttribute('aria-current',String(jobSelectionKey(job)===selectedJob));row.addEventListener('click',()=>selectJob(job));const content=element('div','job-content');const select=document.createElement('button');select.type='button';select.className='job-button';select.setAttribute('aria-current',String(jobSelectionKey(job)===selectedJob));select.title=job.title||job.id;select.addEventListener('click',event=>{event.stopPropagation();selectJob(job);});select.append(element('span','job-title',text(repoName(job.repository)+'/'+value(job.id)+(Number(job.prNumber||0)>0?'/PR#'+value(job.prNumber):''))));const states=element('span','job-status-line');states.append(element('span','badge '+value(job.state),text(value(job.state))),element('span','badge '+value(job.runtimeStatus||'IDLE'),text(value(job.runtimeStatus||'IDLE'))));if(job.publicationFailure)states.append(element('span','badge FAILED',text('PUBLISH FAILED: '+value(job.publicationFailure.stage))));else if(job.publication?.version)states.append(element('span','badge SUCCEEDED',text('v'+job.publication.version)));else if(Number(job.prNumber||0)>0&&job.githubState==='MERGED')states.append(element('span','badge MERGED',text('PR Merged')));else if(job.state==='COMPLETED'&&job.githubState==='CLOSED')states.append(element('span','badge SUCCEEDED',text('PR Archived')));if(job.executionMode==='autonomous')states.append(element('span','badge flag-autonomous',text('AUTONOMOUS')));if(job.state==='ACTIVE'&&job.reviewEnabled!==false)states.append(element('span','badge flag-review',text('REVIEW REQUIRED')));if(job.localMerge?.status==='failed')states.append(element('span','badge FAILED',text('MERGE FAILED: '+value(job.localMerge.error||'Unknown error'))));else if(isCompleteUnmerged(job))states.append(element('span','badge MERGE_PENDING',text('MERGE PENDING')));const primary=element('div','job-primary');primary.append(states);const lastLine=element('div','job-last-line');lastLine.append(element('span','subtle',text(compactCounts(counts(job.tasks)))),element('span','subtle',text(relativeTime(job.updatedAt))));content.append(select,primary,lastLine);row.append(content);jobList.append(element('li','',row));}}
391
+ function renderJobList(){jobList.replaceChildren();const visible=filteredJobs();if(!jobs.length){jobList.append(element('li','empty',text('No durable jobs discovered.')));return;}if(!visible.length){jobList.append(element('li','empty',text('No jobs match the selected repo.')));return;}for(const job of visible){const row=element('div','job-row'+(isCompleteUnmerged(job)?' complete-unmerged':''));row.setAttribute('aria-current',String(jobSelectionKey(job)===selectedJob));row.addEventListener('click',()=>selectJob(job));const content=element('div','job-content');const select=document.createElement('button');select.type='button';select.className='job-button';select.setAttribute('aria-current',String(jobSelectionKey(job)===selectedJob));select.title=job.title||job.id;select.addEventListener('click',event=>{event.stopPropagation();selectJob(job);});select.append(element('span','job-title',text(repoName(job.repository)+'/'+value(job.id)+(Number(job.prNumber||0)>0?'/PR#'+value(job.prNumber):'')+': '+value(job.title||job.id))));const states=element('span','job-status-line');states.append(element('span','badge '+value(job.state),text(value(job.state))),element('span','badge '+value(job.runtimeStatus||'IDLE'),text(value(job.runtimeStatus||'IDLE'))));if(job.publicationFailure)states.append(element('span','badge FAILED',text('PUBLISH FAILED: '+value(job.publicationFailure.stage))));else if(job.publication?.version)states.append(element('span','badge SUCCEEDED',text('v'+job.publication.version)));else if(Number(job.prNumber||0)>0&&job.githubState==='MERGED')states.append(element('span','badge MERGED',text('PR Merged')));else if(job.state==='COMPLETED'&&job.githubState==='CLOSED')states.append(element('span','badge SUCCEEDED',text('PR Archived')));if(job.executionMode==='autonomous')states.append(element('span','badge flag-autonomous',text('AUTONOMOUS')));if(job.state==='ACTIVE'&&job.reviewEnabled!==false)states.append(element('span','badge flag-review',text('REVIEW REQUIRED')));if(job.localMerge?.status==='failed')states.append(element('span','badge FAILED',text('MERGE FAILED: '+value(job.localMerge.error||'Unknown error'))));else if(isCompleteUnmerged(job))states.append(element('span','badge MERGE_PENDING',text('MERGE PENDING')));const primary=element('div','job-primary');primary.append(states);const lastLine=element('div','job-last-line');lastLine.append(element('span','subtle',text(compactCounts(counts(job.tasks)))),element('span','subtle',text(relativeTime(job.updatedAt))));content.append(select,primary,lastLine);row.append(content);jobList.append(element('li','',row));}}
392
392
  function taskTagDisplay(job,task){const display=task.tag&&job?.tag?.values?.[task.tag];return typeof display==='string'&&display?display:null;}
393
393
  function taskSubtreeComplete(task,children){return ['SUCCEEDED','CANCELLED'].includes(task.state)&&(children.get(task.id)||[]).every(child=>taskSubtreeComplete(child,children));}
394
394
  function taskNode(task,children,depth){const li=element('li');const nested=children.get(task.id)||[];const line=element('div','task-line');if(nested.length){const key=(selectedJob||'')+':'+task.id;const collapsed=collapsedTasks.has(key)||(!expandedTasks.has(key)&&taskSubtreeComplete(task,children));const fold=document.createElement('button');fold.type='button';fold.className='task-fold';fold.setAttribute('aria-expanded',String(!collapsed));fold.setAttribute('aria-label',(collapsed?'Expand ':'Collapse ')+task.id);fold.textContent=collapsed?'▸':'▾';line.append(fold);const ul=element('ul','tree');ul.hidden=collapsed;for(const child of nested)ul.append(taskNode(child,children,depth+1));fold.addEventListener('click',()=>{const next=!ul.hidden;ul.hidden=next;fold.setAttribute('aria-expanded',String(!next));fold.setAttribute('aria-label',(next?'Expand ':'Collapse ')+task.id);fold.textContent=next?'▸':'▾';if(next){collapsedTasks.add(key);expandedTasks.delete(key);}else{collapsedTasks.delete(key);expandedTasks.add(key);}});li.append(line,ul);}else li.append(line);const row=document.createElement('button');row.type='button';row.className='task-row';row.setAttribute('aria-current',String(task.id===selectedTaskId));row.title=task.id;row.addEventListener('click',()=>{const deselect=selectedTaskId===task.id;selectedTaskId=deselect?null:task.id;eventTaskId=deselect?null:task.id;rememberSelection();clearEvents();renderAll();void loadEventHistory();});const label=element('span','task-id',text(value(task.id)+': '+value(task.title||task.input?.split(/\\r?\\n/).find(line=>line.trim())?.trim()||shortManagedId(task.id,selected()?.repository,'t'))));label.style.paddingLeft=Math.min(depth,4)*6+'px';row.append(label,element('span','badge '+value(task.state),text(task.state)));const tag=taskTagDisplay(selected(),task);if(tag){const badge=element('span','task-tag',text(tag));badge.title=(selected()?.tag?.description||'Task tag')+': '+task.tag;row.append(badge);}line.append(row);return li;}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-relay",
3
- "version": "2.0.118",
3
+ "version": "2.0.119",
4
4
  "description": "Durable async agent jobs coordinated through GitHub pull requests",
5
5
  "repository": {
6
6
  "type": "git",