opencode-supertask 0.1.35 → 0.1.36

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.
@@ -20269,7 +20269,27 @@ function scopesMatch(left, right) {
20269
20269
  function currentScope() {
20270
20270
  return runtimeScope({ cwd: process.cwd(), env: process.env });
20271
20271
  }
20272
- function getGatewayDiagnostic() {
20272
+ function diagnoseOpenCodeRuntime(runtime = {
20273
+ cwd: process.cwd(),
20274
+ env: process.env
20275
+ }) {
20276
+ const executable = runtimeScope(runtime).opencodePath;
20277
+ const result = spawnSync2(executable, ["--version"], {
20278
+ cwd: runtime.cwd,
20279
+ env: runtime.env,
20280
+ encoding: "utf8",
20281
+ timeout: 1e4,
20282
+ killSignal: "SIGKILL"
20283
+ });
20284
+ const ok = result.status === 0 && result.error === void 0;
20285
+ return {
20286
+ ok,
20287
+ executable,
20288
+ version: ok ? result.stdout.trim() || result.stderr.trim() || null : null,
20289
+ error: ok ? null : result.error?.message || result.stderr.trim() || result.stdout.trim() || `exit code ${result.status}`
20290
+ };
20291
+ }
20292
+ function getGatewayDiagnostic(options = {}) {
20273
20293
  const producerScope = currentScope();
20274
20294
  if (!isPm2Installed()) {
20275
20295
  return {
@@ -20285,7 +20305,8 @@ function getGatewayDiagnostic() {
20285
20305
  startupConfigured: process.platform === "darwin" || process.platform === "linux" ? false : null,
20286
20306
  currentScope: producerScope,
20287
20307
  gatewayScope: null,
20288
- scopeMatches: false
20308
+ scopeMatches: false,
20309
+ gatewayOpenCode: null
20289
20310
  };
20290
20311
  }
20291
20312
  const processes = pm2JsonList();
@@ -20313,7 +20334,8 @@ function getGatewayDiagnostic() {
20313
20334
  ) : process.platform === "linux" ? isLinuxStartupConfigured(gatewayEnv, runtime?.cwd, runtime ?? void 0) : null,
20314
20335
  currentScope: producerScope,
20315
20336
  gatewayScope: managedScope,
20316
- scopeMatches: managedScope != null && scopesMatch(producerScope, managedScope)
20337
+ scopeMatches: managedScope != null && scopesMatch(producerScope, managedScope),
20338
+ gatewayOpenCode: runtime === null || !options.probeOpenCode ? null : diagnoseOpenCodeRuntime(runtime)
20317
20339
  };
20318
20340
  }
20319
20341
  function pm2Bin(env = process.env) {
@@ -20690,7 +20712,70 @@ function clientMessages(locale) {
20690
20712
  "action.refresh",
20691
20713
  "action.logs",
20692
20714
  "action.hideLogs",
20715
+ "details.title",
20716
+ "details.subtitle",
20717
+ "details.taskTitle",
20718
+ "details.runTitle",
20719
+ "details.templateTitle",
20720
+ "details.raw",
20693
20721
  "details.copySuccess",
20722
+ "details.id",
20723
+ "details.project",
20724
+ "details.prompt",
20725
+ "details.result",
20726
+ "details.category",
20727
+ "details.batch",
20728
+ "details.dependency",
20729
+ "details.importance",
20730
+ "details.urgency",
20731
+ "details.retryCount",
20732
+ "details.retryBackoff",
20733
+ "details.timeout",
20734
+ "details.createdAt",
20735
+ "details.updatedAt",
20736
+ "details.startedAt",
20737
+ "details.finishedAt",
20738
+ "details.scheduledAt",
20739
+ "details.enabled",
20740
+ "details.scheduleRule",
20741
+ "details.maxInstances",
20742
+ "details.maxRetries",
20743
+ "details.lastRun",
20744
+ "details.nextRun",
20745
+ "details.taskId",
20746
+ "details.session",
20747
+ "details.heartbeat",
20748
+ "details.process",
20749
+ "details.history",
20750
+ "details.noHistory",
20751
+ "details.none",
20752
+ "details.default",
20753
+ "details.enabledYes",
20754
+ "details.enabledNo",
20755
+ "table.name",
20756
+ "table.agent",
20757
+ "table.model",
20758
+ "table.status",
20759
+ "table.duration",
20760
+ "template.scheduleType",
20761
+ "status.pending",
20762
+ "status.running",
20763
+ "status.done",
20764
+ "status.failed",
20765
+ "status.dead_letter",
20766
+ "status.cancelled",
20767
+ "status.unknown",
20768
+ "runStatus.running",
20769
+ "runStatus.done",
20770
+ "runStatus.failed",
20771
+ "schedule.cron",
20772
+ "schedule.recurring",
20773
+ "schedule.delayed",
20774
+ "schedule.unknown",
20775
+ "duration.seconds",
20776
+ "duration.minutes",
20777
+ "duration.hours",
20778
+ "duration.days",
20694
20779
  "feedback.copyFailed",
20695
20780
  "dialog.cancelTask",
20696
20781
  "dialog.cancelTaskBody",
@@ -20819,8 +20904,8 @@ function renderLayout(options) {
20819
20904
  <div class="dialog-actions"><button type="button" class="btn" onclick="document.getElementById('directory-dialog').close()">${t(locale, "action.cancel")}</button><button id="directory-choose" type="button" class="btn btn-primary">${icon("folder")}${t(locale, "action.chooseThisFolder")}</button></div>
20820
20905
  </dialog>
20821
20906
  <dialog id="detail-dialog">
20822
- <div class="dialog-head"><div><h2>${t(locale, "details.title")}</h2><p>${t(locale, "details.subtitle")}</p></div><button class="icon-button" onclick="document.getElementById('detail-dialog').close()" aria-label="${t(locale, "action.close")}">${icon("close")}</button></div>
20823
- <div class="dialog-body"><pre id="detail-content" class="json-view"></pre></div>
20907
+ <div class="dialog-head"><div><h2 id="detail-title">${t(locale, "details.title")}</h2><p>${t(locale, "details.subtitle")}</p></div><button class="icon-button" onclick="document.getElementById('detail-dialog').close()" aria-label="${t(locale, "action.close")}">${icon("close")}</button></div>
20908
+ <div class="dialog-body"><div id="detail-content" class="detail-view"></div><details class="detail-raw"><summary>${t(locale, "details.raw")}</summary><pre id="detail-raw" class="json-view"></pre></details></div>
20824
20909
  <div class="dialog-actions"><button class="btn" onclick="copyDetails()">${icon("copy")}${t(locale, "action.copy")}</button><button class="btn btn-primary" onclick="document.getElementById('detail-dialog').close()">${t(locale, "action.close")}</button></div>
20825
20910
  </dialog>
20826
20911
  <dialog id="confirm-dialog">
@@ -20852,9 +20937,39 @@ function renderLayout(options) {
20852
20937
  async function retryTask(id){if(!await ask(text('dialog.retryTask',{id}),text('dialog.retryTaskBody')))return;try{await readJson(await fetch('/api/tasks/'+id+'/retry',{method:'POST'}));location.reload()}catch(error){showToast(text('feedback.retryFailed')+': '+error.message,'error')}}
20853
20938
  async function cancelTask(id){if(!await ask(text('dialog.cancelTask',{id}),text('dialog.cancelTaskBody'),true))return;try{await readJson(await fetch('/api/tasks/'+id+'/cancel',{method:'POST'}));location.reload()}catch(error){showToast(text('feedback.cancelFailed')+': '+error.message,'error')}}
20854
20939
  async function deleteTask(id){if(!await ask(text('dialog.deleteTask',{id}),text('dialog.deleteTaskBody'),true))return;try{await readJson(await fetch('/api/tasks/'+id,{method:'DELETE'}));location.reload()}catch(error){showToast(text('feedback.deleteFailed')+': '+error.message,'error')}}
20855
- async function showRecord(url){try{const data=await readJson(await fetch(url));document.getElementById('detail-content').textContent=JSON.stringify(data,null,2);document.getElementById('detail-dialog').showModal()}catch(error){showToast(error.message,'error')}}
20856
- const showDetail=id=>showRecord('/api/tasks/'+id);const showRunDetail=id=>showRecord('/api/runs/'+id);const showTemplateDetail=id=>showRecord('/api/templates/'+id);
20857
- async function copyDetails(){try{await navigator.clipboard.writeText(document.getElementById('detail-content').textContent);showToast(text('details.copySuccess'))}catch{showToast(text('feedback.copyFailed'),'error')}}
20940
+ function detailDate(value){if(value===null||value===undefined||value==='')return text('details.none');const epoch=typeof value==='number'&&value<100000000000?value*1000:value;const date=new Date(epoch);return Number.isNaN(date.getTime())?String(value):date.toLocaleString(document.documentElement.lang)}
20941
+ function detailDuration(value){if(value===null||value===undefined)return text('details.default');const milliseconds=Number(value);if(!Number.isFinite(milliseconds))return String(value);if(milliseconds===0)return '0 ms';const units=[[86400000,text('duration.days')],[3600000,text('duration.hours')],[60000,text('duration.minutes')],[1000,text('duration.seconds')]];for(const [size,label] of units){if(milliseconds>=size&&milliseconds%size===0)return String(milliseconds/size)+' '+label}return String(milliseconds)+' ms'}
20942
+ function detailStatus(type,value){const prefix=type==='run'?'runStatus.':'status.';const key=prefix+String(value||'unknown');return Object.prototype.hasOwnProperty.call(UI,key)?text(key):text('status.unknown')}
20943
+ function detailScheduleType(value){const key='schedule.'+String(value||'unknown');return Object.prototype.hasOwnProperty.call(UI,key)?text(key):text('schedule.unknown')}
20944
+ function detailModel(value){return !value||value==='default'?text('details.default'):String(value)}
20945
+ function detailSession(value){if(!value)return text('details.none');const session=String(value);return session.length<=10?session:session.slice(0,6)+'***'+session.slice(-4)}
20946
+ function detailTaskResult(data){const presentation=data._resultPresentation;if(!presentation)return text('details.none');const parts=[];if(Array.isArray(presentation.errors)&&presentation.errors.length)parts.push(presentation.errors.join('\\n'));if(presentation.text)parts.push(presentation.text);return parts.join('\\n\\n')||text('details.none')}
20947
+ function detailField(label,value,options={}){const item=document.createElement('div');item.className='detail-item'+(options.wide?' wide':'');const name=document.createElement('div');name.className='detail-label';name.textContent=label;const content=options.long?document.createElement('pre'):document.createElement('div');content.className='detail-value'+(options.mono?' mono':'')+(options.long?' long':'');content.textContent=value===null||value===undefined||value===''?text('details.none'):String(value);item.append(name,content);return item}
20948
+ function renderDetailHistory(runs){const section=document.createElement('section');section.className='detail-history';const title=document.createElement('h3');title.textContent=text('details.history');section.appendChild(title);if(!Array.isArray(runs)||runs.length===0){const empty=document.createElement('div');empty.className='muted small';empty.textContent=text('details.noHistory');section.appendChild(empty);return section}const list=document.createElement('div');list.className='detail-history-list';for(const run of runs){const item=document.createElement('div');item.className='detail-history-item';const primary=document.createElement('strong');primary.textContent='Run #'+run.id+' \xB7 '+detailStatus('run',run.status);const secondary=document.createElement('span');secondary.className='muted';secondary.textContent=detailDate(run.startedAt)+(run.model?' \xB7 '+detailModel(run.model):'');item.append(primary,secondary);list.appendChild(item)}section.appendChild(list);return section}
20949
+ function detailFields(type,data){if(type==='task')return [
20950
+ [text('details.id'),'#'+data.id],[text('table.name'),data.name],[text('table.status'),detailStatus('task',data.status)],[text('details.project'),data.cwd,{wide:true,mono:true}],
20951
+ [text('table.agent'),data.agent],[text('table.model'),detailModel(data.model)],[text('details.prompt'),data.prompt,{wide:true,long:true}],
20952
+ [text('details.category'),data.category],[text('details.batch'),data.batchId],[text('details.dependency'),data.dependsOn?'#'+data.dependsOn:text('details.none')],
20953
+ [text('details.importance'),data.importance],[text('details.urgency'),data.urgency],[text('details.retryCount'),String(data.retryCount??0)+' / '+String(data.maxRetries??0)],
20954
+ [text('details.retryBackoff'),detailDuration(data.retryBackoffMs)],[text('details.timeout'),detailDuration(data.timeoutMs)],[text('details.scheduledAt'),detailDate(data.scheduledAt)],
20955
+ [text('details.createdAt'),detailDate(data.createdAt)],[text('details.startedAt'),detailDate(data.startedAt)],[text('details.finishedAt'),detailDate(data.finishedAt)],
20956
+ [text('details.result'),detailTaskResult(data),{wide:true,long:true}]
20957
+ ];if(type==='run'){const started=data.startedAt?new Date(data.startedAt).getTime():null;const finished=data.finishedAt?new Date(data.finishedAt).getTime():null;return [
20958
+ [text('details.id'),'Run #'+data.id],[text('details.taskId'),'#'+data.taskId],[text('table.status'),detailStatus('run',data.status)],[text('table.model'),detailModel(data.model)],
20959
+ [text('details.session'),detailSession(data.sessionId)],[text('details.startedAt'),detailDate(data.startedAt)],[text('details.finishedAt'),detailDate(data.finishedAt)],
20960
+ [text('table.duration'),started!==null?detailDuration((finished??Date.now())-started):text('details.none')],[text('details.heartbeat'),detailDate(data.heartbeatAt)],
20961
+ [text('details.process'),'Worker PID '+String(data.workerPid??'\u2014')+' \xB7 OpenCode PID '+String(data.childPid??'\u2014'),{wide:true,mono:true}]
20962
+ ];}const scheduleRule=data.scheduleType==='cron'?data.cronExpr:data.scheduleType==='recurring'?detailDuration(data.intervalMs):detailDate(data.runAt);return [
20963
+ [text('details.id'),'#'+data.id],[text('table.name'),data.name],[text('details.enabled'),data.enabled?text('details.enabledYes'):text('details.enabledNo')],[text('details.project'),data.cwd,{wide:true,mono:true}],
20964
+ [text('table.agent'),data.agent],[text('table.model'),detailModel(data.model)],[text('details.prompt'),data.prompt,{wide:true,long:true}],
20965
+ [text('template.scheduleType'),detailScheduleType(data.scheduleType)],[text('details.scheduleRule'),scheduleRule],[text('details.category'),data.category],[text('details.batch'),data.batchId],
20966
+ [text('details.importance'),data.importance],[text('details.urgency'),data.urgency],[text('details.maxInstances'),data.maxInstances],[text('details.maxRetries'),data.maxRetries??0],
20967
+ [text('details.retryBackoff'),detailDuration(data.retryBackoffMs)],[text('details.timeout'),detailDuration(data.timeoutMs)],[text('details.lastRun'),detailDate(data.lastRunAt)],[text('details.nextRun'),detailDate(data.nextRunAt)],
20968
+ [text('details.createdAt'),detailDate(data.createdAt)],[text('details.updatedAt'),detailDate(data.updatedAt)]
20969
+ ]}
20970
+ async function showRecord(url,type){try{const data=await readJson(await fetch(url));const content=document.getElementById('detail-content');content.replaceChildren();const grid=document.createElement('div');grid.className='detail-grid';for(const [label,value,options] of detailFields(type,data))grid.appendChild(detailField(label,value,options));content.appendChild(grid);if(type==='task')content.appendChild(renderDetailHistory(data._runs));document.getElementById('detail-title').textContent=text(type==='task'?'details.taskTitle':type==='run'?'details.runTitle':'details.templateTitle');document.getElementById('detail-raw').textContent=JSON.stringify(data,null,2);document.querySelector('#detail-dialog .detail-raw').open=false;document.getElementById('detail-dialog').showModal()}catch(error){showToast(error.message,'error')}}
20971
+ const showDetail=id=>showRecord('/api/tasks/'+id,'task');const showRunDetail=id=>showRecord('/api/runs/'+id,'run');const showTemplateDetail=id=>showRecord('/api/templates/'+id,'template');
20972
+ async function copyDetails(){try{await navigator.clipboard.writeText(document.getElementById('detail-raw').textContent);showToast(text('details.copySuccess'))}catch{showToast(text('feedback.copyFailed'),'error')}}
20858
20973
  async function copySessionCommand(id){try{const data=await readJson(await fetch('/api/runs/'+id+'/session-command'));await navigator.clipboard.writeText(data.command);showToast(text('feedback.sessionCommandCopied'))}catch(error){showToast(error.message||text('feedback.copyFailed'),'error')}}
20859
20974
  async function copyRunCommand(id){try{await navigator.clipboard.writeText(document.getElementById('command-'+id).textContent);showToast(text('feedback.commandCopied'))}catch{showToast(text('feedback.copyFailed'),'error')}}
20860
20975
  function taskField(name){return document.getElementById('task-'+name)}
@@ -20892,7 +21007,7 @@ function renderLayout(options) {
20892
21007
  async function disableTmpl(id){if(!await ask(text('dialog.disableTemplate'),text('dialog.disableTemplateBody')))return;try{await readJson(await fetch('/api/templates/'+id+'/disable',{method:'POST'}));location.reload()}catch(error){showToast(error.message,'error')}}
20893
21008
  async function deleteTmpl(id){if(!await ask(text('dialog.deleteTemplate'),text('dialog.deleteTemplateBody'),true))return;try{await readJson(await fetch('/api/templates/'+id,{method:'DELETE'}));location.reload()}catch(error){showToast(error.message,'error')}}
20894
21009
  async function triggerTmpl(id){if(!await ask(text('dialog.triggerTemplate'),text('dialog.triggerTemplateBody')))return;try{const data=await readJson(await fetch('/api/templates/'+id+'/trigger',{method:'POST'}));showToast(text('feedback.triggered',{id:data.taskId}));setTimeout(()=>location.reload(),550)}catch(error){showToast(error.message,'error')}}
20895
- function toggleLog(id,button){const panel=document.getElementById('log-'+id);const hidden=!panel.hidden;panel.hidden=hidden;button.setAttribute('aria-expanded',String(!hidden));button.textContent=text(hidden?'action.logs':'action.hideLogs');}
21010
+ function toggleLog(id,button){const panel=document.getElementById('log-'+id);const hidden=!panel.hidden;panel.hidden=hidden;button.setAttribute('aria-expanded',String(!hidden));button.textContent=text(hidden?'action.logs':'action.hideLogs');if(!hidden)requestAnimationFrame(()=>panel.scrollIntoView({block:'nearest',behavior:'smooth'}));}
20896
21011
  function filterTasks(value){const query=value.trim().toLocaleLowerCase();let visible=0;document.querySelectorAll('[data-task-row]').forEach(row=>{const match=!query||row.dataset.search.toLocaleLowerCase().includes(query);row.hidden=!match;if(match)visible++});const empty=document.getElementById('search-empty');if(empty)empty.hidden=visible!==0;}
20897
21012
  async function clearDatabase(){if(!await askDanger())return;try{const data=await readJson(await fetch('/api/database/clear',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({confirmation:'CLEAR'})}));showToast(text('feedback.databaseCleared',{path:data.backupPath}));setTimeout(()=>location.reload(),1000)}catch(error){showToast(error.message,'error')}}
20898
21013
  async function confirmGatewayRestart(runningCount=0){const body=runningCount>0?text('dialog.restartGatewayRunningBody',{count:runningCount}):text('dialog.restartGatewayBody');return await ask(text('dialog.restartGateway'),body)}
@@ -20938,7 +21053,7 @@ var init_ui = __esm({
20938
21053
  "action.hideLogs": "\u6536\u8D77\u65E5\u5FD7",
20939
21054
  "action.save": "\u4FDD\u5B58\u8BBE\u7F6E",
20940
21055
  "action.saveAndRestart": "\u4FDD\u5B58\u5E76\u91CD\u542F",
20941
- "action.copy": "\u590D\u5236 JSON",
21056
+ "action.copy": "\u590D\u5236\u539F\u59CB\u6570\u636E",
20942
21057
  "action.close": "\u5173\u95ED",
20943
21058
  "action.confirm": "\u786E\u8BA4",
20944
21059
  "action.clearDatabase": "\u6E05\u7A7A\u6570\u636E\u5E93",
@@ -21130,9 +21245,46 @@ var init_ui = __esm({
21130
21245
  "theme.light": "\u6D45\u8272",
21131
21246
  "theme.dark": "\u6DF1\u8272",
21132
21247
  "language.label": "\u8BED\u8A00",
21133
- "details.title": "\u6570\u636E\u8BE6\u60C5",
21134
- "details.subtitle": "\u539F\u59CB\u8BB0\u5F55\uFF08JSON\uFF09",
21135
- "details.copySuccess": "JSON \u5DF2\u590D\u5236",
21248
+ "details.title": "\u8BE6\u60C5",
21249
+ "details.subtitle": "\u91CD\u70B9\u4FE1\u606F\u5DF2\u6574\u7406\uFF1B\u539F\u59CB\u6570\u636E\u4EC5\u7528\u4E8E\u6392\u969C\u3002",
21250
+ "details.taskTitle": "\u4EFB\u52A1\u8BE6\u60C5",
21251
+ "details.runTitle": "\u6267\u884C\u8BE6\u60C5",
21252
+ "details.templateTitle": "\u5B9A\u65F6\u4EFB\u52A1\u8BE6\u60C5",
21253
+ "details.raw": "\u67E5\u770B\u539F\u59CB\u6570\u636E\uFF08JSON\uFF09",
21254
+ "details.copySuccess": "\u539F\u59CB\u6570\u636E\u5DF2\u590D\u5236",
21255
+ "details.id": "\u7F16\u53F7",
21256
+ "details.project": "\u9879\u76EE\u76EE\u5F55",
21257
+ "details.prompt": "\u63D0\u793A\u8BCD",
21258
+ "details.result": "\u6267\u884C\u7ED3\u679C / \u5931\u8D25\u539F\u56E0",
21259
+ "details.category": "\u5206\u7C7B",
21260
+ "details.batch": "\u6279\u6B21",
21261
+ "details.dependency": "\u4F9D\u8D56\u4EFB\u52A1",
21262
+ "details.importance": "\u91CD\u8981\u7A0B\u5EA6",
21263
+ "details.urgency": "\u7D27\u6025\u7A0B\u5EA6",
21264
+ "details.retryCount": "\u5DF2\u91CD\u8BD5 / \u6700\u591A\u91CD\u8BD5",
21265
+ "details.retryBackoff": "\u91CD\u8BD5\u7B49\u5F85",
21266
+ "details.timeout": "\u6267\u884C\u8D85\u65F6",
21267
+ "details.createdAt": "\u521B\u5EFA\u65F6\u95F4",
21268
+ "details.updatedAt": "\u66F4\u65B0\u65F6\u95F4",
21269
+ "details.startedAt": "\u5F00\u59CB\u65F6\u95F4",
21270
+ "details.finishedAt": "\u7ED3\u675F\u65F6\u95F4",
21271
+ "details.scheduledAt": "\u8BA1\u5212\u65F6\u95F4",
21272
+ "details.enabled": "\u81EA\u52A8\u8FD0\u884C",
21273
+ "details.scheduleRule": "\u8FD0\u884C\u89C4\u5219",
21274
+ "details.maxInstances": "\u81EA\u52A8\u8C03\u5EA6\u4E0A\u9650",
21275
+ "details.maxRetries": "\u5931\u8D25\u91CD\u8BD5\u6B21\u6570",
21276
+ "details.lastRun": "\u4E0A\u6B21\u8FD0\u884C",
21277
+ "details.nextRun": "\u4E0B\u6B21\u8FD0\u884C",
21278
+ "details.taskId": "\u6240\u5C5E\u4EFB\u52A1",
21279
+ "details.session": "OpenCode \u4F1A\u8BDD",
21280
+ "details.heartbeat": "\u6700\u8FD1\u5FC3\u8DF3",
21281
+ "details.process": "\u8FDB\u7A0B",
21282
+ "details.history": "\u6267\u884C\u5386\u53F2",
21283
+ "details.noHistory": "\u8FD8\u6CA1\u6709\u6267\u884C\u8BB0\u5F55",
21284
+ "details.none": "\u65E0",
21285
+ "details.default": "\u8DDF\u968F\u7CFB\u7EDF\u9ED8\u8BA4",
21286
+ "details.enabledYes": "\u5DF2\u542F\u7528",
21287
+ "details.enabledNo": "\u5DF2\u505C\u7528",
21136
21288
  "dialog.cancelTask": "\u53D6\u6D88\u4EFB\u52A1 #{id}\uFF1F",
21137
21289
  "dialog.cancelTaskBody": "\u8FD0\u884C\u4E2D\u7684\u4EFB\u52A1\u4F1A\u5728\u4E0B\u4E00\u4E2A\u8F6E\u8BE2\u5468\u671F\u7EC8\u6B62\u5BF9\u5E94\u8FDB\u7A0B\u6811\u3002",
21138
21290
  "dialog.retryTask": "\u91CD\u8BD5\u4EFB\u52A1 #{id}\uFF1F",
@@ -21202,7 +21354,7 @@ var init_ui = __esm({
21202
21354
  "action.hideLogs": "Hide log",
21203
21355
  "action.save": "Save settings",
21204
21356
  "action.saveAndRestart": "Save and restart",
21205
- "action.copy": "Copy JSON",
21357
+ "action.copy": "Copy raw data",
21206
21358
  "action.close": "Close",
21207
21359
  "action.confirm": "Confirm",
21208
21360
  "action.clearDatabase": "Clear database",
@@ -21394,9 +21546,46 @@ var init_ui = __esm({
21394
21546
  "theme.light": "Light",
21395
21547
  "theme.dark": "Dark",
21396
21548
  "language.label": "Language",
21397
- "details.title": "Data details",
21398
- "details.subtitle": "Raw record (JSON)",
21399
- "details.copySuccess": "JSON copied",
21549
+ "details.title": "Details",
21550
+ "details.subtitle": "Key information is organized below; raw data is only for troubleshooting.",
21551
+ "details.taskTitle": "Task details",
21552
+ "details.runTitle": "Run details",
21553
+ "details.templateTitle": "Scheduled task details",
21554
+ "details.raw": "View raw data (JSON)",
21555
+ "details.copySuccess": "Raw data copied",
21556
+ "details.id": "ID",
21557
+ "details.project": "Project directory",
21558
+ "details.prompt": "Prompt",
21559
+ "details.result": "Result / failure reason",
21560
+ "details.category": "Category",
21561
+ "details.batch": "Batch",
21562
+ "details.dependency": "Dependency",
21563
+ "details.importance": "Importance",
21564
+ "details.urgency": "Urgency",
21565
+ "details.retryCount": "Retries used / allowed",
21566
+ "details.retryBackoff": "Retry delay",
21567
+ "details.timeout": "Run timeout",
21568
+ "details.createdAt": "Created",
21569
+ "details.updatedAt": "Updated",
21570
+ "details.startedAt": "Started",
21571
+ "details.finishedAt": "Finished",
21572
+ "details.scheduledAt": "Scheduled for",
21573
+ "details.enabled": "Automatic runs",
21574
+ "details.scheduleRule": "Schedule rule",
21575
+ "details.maxInstances": "Automatic scheduling limit",
21576
+ "details.maxRetries": "Failure retries",
21577
+ "details.lastRun": "Last run",
21578
+ "details.nextRun": "Next run",
21579
+ "details.taskId": "Task",
21580
+ "details.session": "OpenCode session",
21581
+ "details.heartbeat": "Latest heartbeat",
21582
+ "details.process": "Processes",
21583
+ "details.history": "Run history",
21584
+ "details.noHistory": "No runs yet",
21585
+ "details.none": "None",
21586
+ "details.default": "Use system default",
21587
+ "details.enabledYes": "Enabled",
21588
+ "details.enabledNo": "Disabled",
21400
21589
  "dialog.cancelTask": "Cancel task #{id}?",
21401
21590
  "dialog.cancelTaskBody": "A running task will terminate its process tree on the next worker poll.",
21402
21591
  "dialog.retryTask": "Retry task #{id}?",
@@ -21637,6 +21826,8 @@ var init_ui = __esm({
21637
21826
  .danger-card h2 .icon { width:17px; height:17px; }
21638
21827
  .danger-card p { max-width:800px; margin:0 0 14px; color:var(--text-2); font-size:12px; }
21639
21828
  .log-panel { margin:12px 0; animation:reveal .18s ease both; }
21829
+ .run-log-row td { padding:0 16px 16px; background:color-mix(in srgb,var(--surface-2) 64%,var(--surface)); }
21830
+ .run-log-row .log-panel { margin:0; box-shadow:none; }
21640
21831
  .log-content { display:grid; gap:14px; padding:16px; }
21641
21832
  .log-section-head { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:7px; }
21642
21833
  .run-command,.run-output,.run-error,.run-tools { min-width:0; }
@@ -21694,8 +21885,21 @@ var init_ui = __esm({
21694
21885
  .directory-item:active { transform:scale(.99); }
21695
21886
  .directory-item .icon { width:17px; height:17px; color:var(--primary); flex:0 0 auto; }
21696
21887
  .directory-empty { min-height:220px; display:grid; place-items:center; color:var(--text-3); }
21697
- .json-view { min-height:160px; margin:0; padding:15px; overflow:auto; border:1px solid var(--border); border-radius:10px; color:var(--text-2);
21698
- background:var(--surface-2); font-size:12px; white-space:pre-wrap; overflow-wrap:anywhere; }
21888
+ .detail-view { display:grid; gap:16px; }
21889
+ .detail-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px; }
21890
+ .detail-item { min-width:0; padding:12px 13px; border:1px solid var(--border); border-radius:10px; background:var(--surface-2); }
21891
+ .detail-item.wide { grid-column:1 / -1; }
21892
+ .detail-label { margin-bottom:5px; color:var(--text-3); font-size:10px; font-weight:750; letter-spacing:.045em; text-transform:uppercase; }
21893
+ .detail-value { color:var(--text); font-size:13px; line-height:1.55; overflow-wrap:anywhere; }
21894
+ .detail-value.mono { font-family:"SFMono-Regular",Consolas,monospace; font-size:11px; }
21895
+ .detail-value.long { max-height:240px; margin:0; overflow:auto; white-space:pre-wrap; }
21896
+ .detail-history h3 { margin:0 0 8px; font-size:13px; }
21897
+ .detail-history-list { display:grid; gap:7px; }
21898
+ .detail-history-item { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:9px 11px; border:1px solid var(--border); border-radius:9px; background:var(--surface-2); font-size:11px; }
21899
+ .detail-raw { padding-top:12px; border-top:1px solid var(--border); }
21900
+ .detail-raw summary { color:var(--text-2); cursor:pointer; font-size:12px; font-weight:650; }
21901
+ .json-view { max-height:320px; margin:10px 0 0; padding:15px; overflow:auto; border:1px solid var(--border); border-radius:10px; color:var(--text-2);
21902
+ background:var(--surface-2); font-family:"SFMono-Regular",Consolas,monospace; font-size:11px; white-space:pre-wrap; overflow-wrap:anywhere; }
21699
21903
  .confirm-copy { color:var(--text-2); margin:0; }
21700
21904
  .confirm-copy strong { display:block; margin-bottom:5px; color:var(--text); font-size:15px; }
21701
21905
  .danger-input { width:100%; height:40px; margin-top:14px; padding:0 12px; border:1px solid var(--border); border-radius:9px; outline:none;
@@ -21759,8 +21963,13 @@ var init_ui = __esm({
21759
21963
  .responsive-table td[data-primary]::before { display:none; }
21760
21964
  .responsive-table .task-prompt { max-width:100%; }
21761
21965
  .responsive-table .actions { justify-content:flex-start; }
21966
+ .responsive-table .run-log-row { padding:0; overflow:hidden; }
21967
+ .responsive-table .run-log-cell { display:block; padding:0; }
21968
+ .responsive-table .run-log-cell::before { display:none; }
21762
21969
  .project-grid { grid-template-columns:1fr; }
21763
21970
  .template-form-grid { grid-template-columns:1fr; }
21971
+ .detail-grid { grid-template-columns:1fr; }
21972
+ .detail-item.wide { grid-column:auto; }
21764
21973
  .form-field-wide { grid-column:auto; }
21765
21974
  .field-action { align-items:stretch; flex-direction:column; }
21766
21975
  .field-action .btn { width:100%; }
@@ -22080,7 +22289,7 @@ function renderRunLog(runId, taskName, log, locale) {
22080
22289
  const errors = presentation.errors.length > 0 ? `<div class="run-error"><strong>${t(locale, "logs.error")}</strong><pre>${esc(presentation.errors.join("\n"))}</pre></div>` : "";
22081
22290
  const tools = presentation.tools.length > 0 ? `<div class="run-tools"><strong>${t(locale, "logs.tools")}</strong><div class="actions">${presentation.tools.map((tool) => `<span class="tag">${esc(tool)}</span>`).join("")}</div></div>` : "";
22082
22291
  const output = `<div class="run-output"><strong>${t(locale, "logs.output")}</strong><pre>${esc(presentation.text || t(locale, "logs.noText"))}</pre></div>`;
22083
- return `<section id="log-${runId}" class="panel log-panel" hidden><div class="panel-head"><h3>Run #${runId} \xB7 ${esc(taskName)}</h3></div><div class="log-content">${command}${errors}${output}${tools}<details class="raw-log"><summary>${t(locale, "logs.raw")}</summary><div class="log-box">${esc(log)}</div></details></div></section>`;
22292
+ return `<section class="panel log-panel"><div class="panel-head"><h3>Run #${runId} \xB7 ${esc(taskName)}</h3></div><div class="log-content">${command}${errors}${output}${tools}<details class="raw-log"><summary>${t(locale, "logs.raw")}</summary><div class="log-box">${esc(log)}</div></details></div></section>`;
22084
22293
  }
22085
22294
  function esc(value) {
22086
22295
  if (!value) return "";
@@ -22520,14 +22729,11 @@ var init_web = __esm({
22520
22729
  const total = Number(totalResult[0]?.count ?? 0);
22521
22730
  const totalPages = Math.max(1, Math.ceil(total / limit));
22522
22731
  if (page > totalPages) return c.redirect(`/runs?page=${totalPages}`);
22523
- const logs = [];
22524
22732
  const rows = runs.map((run) => {
22525
22733
  const status = safeStatus(run.status);
22526
22734
  const resumable = isValidSessionId(run.sessionId);
22527
- if (run.log) {
22528
- logs.push(renderRunLog(run.id, run.taskName, run.log, locale));
22529
- }
22530
- return `<tr>
22735
+ const log = run.log ? renderRunLog(run.id, run.taskName, run.log, locale) : "";
22736
+ return `<tr class="run-summary-row">
22531
22737
  <td class="faint" data-label="${t(locale, "table.run")}">#${run.id}</td>
22532
22738
  <td data-primary data-label="${t(locale, "table.task")}"><div class="task-name">${esc(run.taskName)} <span class="faint">#${run.taskId}</span></div>${run.model ? `<div style="margin-top:4px"><span class="tag">${esc(run.model)}</span></div>` : ""}</td>
22533
22739
  <td data-label="${t(locale, "table.agent")}"><span class="tag">${esc(run.taskAgent)}</span></td>
@@ -22538,7 +22744,7 @@ var init_web = __esm({
22538
22744
  <td data-label="${t(locale, "table.actions")}"><div class="actions"><button type="button" class="btn" onclick="showRunDetail(${run.id})">${t(locale, "action.details")}</button>
22539
22745
  ${resumable ? `<button type="button" class="btn" onclick="copySessionCommand(${run.id})">${icon("copy")}${t(locale, "action.continueSession")}</button>` : ""}
22540
22746
  ${run.log ? `<button type="button" class="btn" aria-expanded="false" onclick="toggleLog(${run.id},this)">${t(locale, "action.logs")}</button>` : ""}</div></td>
22541
- </tr>`;
22747
+ </tr>${log ? `<tr id="log-${run.id}" class="run-log-row" hidden><td class="run-log-cell" colspan="8">${log}</td></tr>` : ""}`;
22542
22748
  }).join("");
22543
22749
  const body = `
22544
22750
  <div class="stats-grid">
@@ -22548,7 +22754,7 @@ var init_web = __esm({
22548
22754
  ${statCard(runs.filter((run) => run.status === "running").length, t(locale, "stats.pageRunning"), "tone-blue", icon("activity"), "reveal-delay-2")}
22549
22755
  </div>
22550
22756
  <section class="panel reveal reveal-delay-2">${runs.length === 0 ? emptyState(t(locale, "empty.runs"), "") : `<div class="table-wrap"><table class="responsive-table"><thead><tr><th>${t(locale, "table.run")}</th><th>${t(locale, "table.task")}</th><th>${t(locale, "table.agent")}</th><th>${t(locale, "table.session")}</th><th>${t(locale, "table.status")}</th><th>${t(locale, "table.duration")}</th><th>${t(locale, "table.heartbeat")}</th><th>${t(locale, "table.actions")}</th></tr></thead><tbody>${rows}</tbody></table></div>`}</section>
22551
- ${logs.join("")}${pagination(locale, "/runs", page, totalPages, total)}`;
22757
+ ${pagination(locale, "/runs", page, totalPages, total)}`;
22552
22758
  return c.html(renderLayout({ locale, activeTab: "runs", body }));
22553
22759
  });
22554
22760
  app.get("/system", async (c) => {
@@ -22655,7 +22861,11 @@ var init_web = __esm({
22655
22861
  const task = await TaskService.getById(id);
22656
22862
  if (!task) return c.json({ error: "not found" }, 404);
22657
22863
  const runs = await TaskRunService.listByTaskId(id);
22658
- return c.json({ ...task, _runs: runs });
22864
+ return c.json({
22865
+ ...task,
22866
+ _resultPresentation: task.resultLog ? presentRunLog(task.resultLog) : null,
22867
+ _runs: runs
22868
+ });
22659
22869
  });
22660
22870
  app.get("/api/runs/:id", async (c) => {
22661
22871
  const id = parsePositiveInteger(c.req.param("id"));