@jmanuelcorral/openteam 0.19.0 → 0.20.0
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.
- package/README.es.md +10 -2
- package/README.md +9 -2
- package/dist/certificates/graph-release-certificate.json +2 -2
- package/dist/certificates/graph-shadow-certificate.json +2 -2
- package/dist/cli/consoleServe.d.ts +16 -0
- package/dist/cli/consoleServe.d.ts.map +1 -1
- package/dist/cli/graphOperator.d.ts +10 -1
- package/dist/cli/graphOperator.d.ts.map +1 -1
- package/dist/cli/lifecycleHistoryProvider.d.ts +21 -0
- package/dist/cli/lifecycleHistoryProvider.d.ts.map +1 -0
- package/dist/cli.d.ts +3 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6163 -1632
- package/dist/config/errors.d.ts.map +1 -1
- package/dist/config/schema.d.ts +31 -1
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/console/assets.d.ts +22 -1
- package/dist/console/assets.d.ts.map +1 -1
- package/dist/console/render.d.ts +12 -0
- package/dist/console/render.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2849 -261
- package/dist/lifecycle/contracts.d.ts +618 -0
- package/dist/lifecycle/contracts.d.ts.map +1 -0
- package/dist/lifecycle/historyReader.d.ts +11 -0
- package/dist/lifecycle/historyReader.d.ts.map +1 -0
- package/dist/lifecycle/historySourceError.d.ts +7 -0
- package/dist/lifecycle/historySourceError.d.ts.map +1 -0
- package/dist/lifecycle/project.d.ts +3 -0
- package/dist/lifecycle/project.d.ts.map +1 -0
- package/dist/lifecycle/root.d.ts +3 -0
- package/dist/lifecycle/root.d.ts.map +1 -0
- package/dist/lifecycle/runtimeRecorder.d.ts +6 -0
- package/dist/lifecycle/runtimeRecorder.d.ts.map +1 -0
- package/dist/lifecycle/schema.d.ts +487 -0
- package/dist/lifecycle/schema.d.ts.map +1 -0
- package/dist/messages/index.d.ts +1 -0
- package/dist/messages/index.d.ts.map +1 -1
- package/dist/messages/lifecycle.d.ts +95 -0
- package/dist/messages/lifecycle.d.ts.map +1 -0
- package/dist/messages/lifecycleRuntime.d.ts +4 -0
- package/dist/messages/lifecycleRuntime.d.ts.map +1 -0
- package/dist/messages/lifecycleStorage.d.ts +4 -0
- package/dist/messages/lifecycleStorage.d.ts.map +1 -0
- package/dist/orchestrator/coordinator.d.ts +11 -1
- package/dist/orchestrator/coordinator.d.ts.map +1 -1
- package/dist/orchestrator/graphIngress.d.ts +5 -0
- package/dist/orchestrator/graphIngress.d.ts.map +1 -1
- package/dist/orchestrator/graphRuntime.d.ts +13 -1
- package/dist/orchestrator/graphRuntime.d.ts.map +1 -1
- package/dist/orchestrator/subsessions.d.ts +3 -0
- package/dist/orchestrator/subsessions.d.ts.map +1 -1
- package/dist/plugin/orchestrateTool.d.ts +3 -0
- package/dist/plugin/orchestrateTool.d.ts.map +1 -1
- package/dist/storage/lifecycle/codec.d.ts +19 -0
- package/dist/storage/lifecycle/codec.d.ts.map +1 -0
- package/dist/storage/lifecycle/fsLifecycleJournal.d.ts +3 -0
- package/dist/storage/lifecycle/fsLifecycleJournal.d.ts.map +1 -0
- package/dist/storage/lifecycle/fsLifecycleSupport.d.ts +17 -0
- package/dist/storage/lifecycle/fsLifecycleSupport.d.ts.map +1 -0
- package/dist/storage/lifecycle/fsLifecycleWriterLivenessProbe.d.ts +3 -0
- package/dist/storage/lifecycle/fsLifecycleWriterLivenessProbe.d.ts.map +1 -0
- package/dist/web/graphRoute.d.ts +39 -1
- package/dist/web/graphRoute.d.ts.map +1 -1
- package/dist/web/server.d.ts +19 -0
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/start.d.ts +11 -0
- package/dist/web/start.d.ts.map +1 -1
- package/dist/web/watch.d.ts +17 -2
- package/dist/web/watch.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/config/errors.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS,WAAW,CAAC;AAIlC,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/config/errors.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS,WAAW,CAAC;AAIlC,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAsHzE,CAAC;AAgIL,KAAK,6BAA6B,GAAG;IACnC,QAAQ,CAAC,eAAe,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;IAClE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACxC,CAAC;AAEF,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,6BAAkC,GAC1C,MAAM,CA0BR;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAKxD"}
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -57,6 +57,18 @@ export declare const GraphEngineSchema: z.ZodEnum<{
|
|
|
57
57
|
*/
|
|
58
58
|
export declare const DEFAULT_GRAPH_JOURNAL_ROOT = ".opencode/openteam-local/graph/runs";
|
|
59
59
|
export declare const DEFAULT_GRAPH_WORKTREES_DIR = ".opencode/openteam-local/graph/worktrees";
|
|
60
|
+
export declare const DEFAULT_LIFECYCLE_ROOT = ".opencode/openteam-local/lifecycle/runs";
|
|
61
|
+
export declare const DEFAULT_LIFECYCLE_MAX_TERMINAL_RUNS = 200;
|
|
62
|
+
export declare const DEFAULT_LIFECYCLE_MAX_AGE_DAYS = 30;
|
|
63
|
+
export declare const DEFAULT_LIFECYCLE_MAX_BYTES = 268435456;
|
|
64
|
+
export declare const LifecycleConfigSchema: z.ZodDefault<z.ZodObject<{
|
|
65
|
+
root: z.ZodDefault<z.ZodString>;
|
|
66
|
+
retention: z.ZodDefault<z.ZodObject<{
|
|
67
|
+
maxTerminalRuns: z.ZodDefault<z.ZodNumber>;
|
|
68
|
+
maxAgeDays: z.ZodDefault<z.ZodNumber>;
|
|
69
|
+
maxBytes: z.ZodDefault<z.ZodNumber>;
|
|
70
|
+
}, z.core.$strict>>;
|
|
71
|
+
}, z.core.$strict>>;
|
|
60
72
|
export declare const GraphConfigSchema: z.ZodObject<{
|
|
61
73
|
mode: z.ZodDefault<z.ZodEnum<{
|
|
62
74
|
active: "active";
|
|
@@ -469,6 +481,14 @@ export declare const OpenTeamConfigObjectSchema: z.ZodObject<{
|
|
|
469
481
|
}, z.core.$strict>>;
|
|
470
482
|
}, z.core.$strict>>;
|
|
471
483
|
}, z.core.$strict>>;
|
|
484
|
+
lifecycle: z.ZodDefault<z.ZodObject<{
|
|
485
|
+
root: z.ZodDefault<z.ZodString>;
|
|
486
|
+
retention: z.ZodDefault<z.ZodObject<{
|
|
487
|
+
maxTerminalRuns: z.ZodDefault<z.ZodNumber>;
|
|
488
|
+
maxAgeDays: z.ZodDefault<z.ZodNumber>;
|
|
489
|
+
maxBytes: z.ZodDefault<z.ZodNumber>;
|
|
490
|
+
}, z.core.$strict>>;
|
|
491
|
+
}, z.core.$strict>>;
|
|
472
492
|
graph: z.ZodDefault<z.ZodObject<{
|
|
473
493
|
mode: z.ZodDefault<z.ZodEnum<{
|
|
474
494
|
active: "active";
|
|
@@ -649,6 +669,14 @@ export declare const OpenTeamConfigSchema: z.ZodObject<{
|
|
|
649
669
|
}, z.core.$strict>>;
|
|
650
670
|
}, z.core.$strict>>;
|
|
651
671
|
}, z.core.$strict>>;
|
|
672
|
+
lifecycle: z.ZodDefault<z.ZodObject<{
|
|
673
|
+
root: z.ZodDefault<z.ZodString>;
|
|
674
|
+
retention: z.ZodDefault<z.ZodObject<{
|
|
675
|
+
maxTerminalRuns: z.ZodDefault<z.ZodNumber>;
|
|
676
|
+
maxAgeDays: z.ZodDefault<z.ZodNumber>;
|
|
677
|
+
maxBytes: z.ZodDefault<z.ZodNumber>;
|
|
678
|
+
}, z.core.$strict>>;
|
|
679
|
+
}, z.core.$strict>>;
|
|
652
680
|
graph: z.ZodDefault<z.ZodObject<{
|
|
653
681
|
mode: z.ZodDefault<z.ZodEnum<{
|
|
654
682
|
active: "active";
|
|
@@ -693,15 +721,17 @@ export type ExecutionMode = z.infer<typeof ExecutionModeSchema>;
|
|
|
693
721
|
export type PrivacyMode = z.infer<typeof PrivacyModeSchema>;
|
|
694
722
|
export type GraphMode = z.infer<typeof GraphModeSchema>;
|
|
695
723
|
export type GraphConfig = z.infer<typeof GraphConfigSchema>;
|
|
724
|
+
export type LifecycleConfig = z.infer<typeof LifecycleConfigSchema>;
|
|
696
725
|
export type LocalRuntime = z.infer<typeof LocalRuntimeSchema>;
|
|
697
726
|
type ParsedConsoleConfig = z.infer<typeof ConsoleConfigSchema>;
|
|
698
727
|
export type ConsoleConfig = Omit<ParsedConsoleConfig, "graphView"> & {
|
|
699
728
|
readonly graphView?: ParsedConsoleConfig["graphView"];
|
|
700
729
|
};
|
|
701
730
|
type ParsedOpenTeamConfig = z.infer<typeof OpenTeamConfigSchema>;
|
|
702
|
-
export type OpenTeamConfig = Omit<ParsedOpenTeamConfig, "console" | "graph"> & {
|
|
731
|
+
export type OpenTeamConfig = Omit<ParsedOpenTeamConfig, "console" | "graph" | "lifecycle"> & {
|
|
703
732
|
readonly console: ConsoleConfig;
|
|
704
733
|
readonly graph?: ParsedOpenTeamConfig["graph"];
|
|
734
|
+
readonly lifecycle?: ParsedOpenTeamConfig["lifecycle"];
|
|
705
735
|
};
|
|
706
736
|
export type StorageConfig = z.infer<typeof StorageConfigSchema>;
|
|
707
737
|
export type MemoryConfig = z.infer<typeof MemoryConfigSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EACL,KAAK,gBAAgB,EAKtB,MAAM,uBAAuB,CAAC;AAS/B,eAAO,MAAM,cAAc;;;kBAKhB,CAAC;AAEZ,eAAO,MAAM,gBAAgB;;;;EAA6C,CAAC;AAC3E,eAAO,MAAM,mBAAmB;;;;EAAyC,CAAC;AAC1E,eAAO,MAAM,iBAAiB;;;;EAI5B,CAAC;AACH,eAAO,MAAM,kBAAkB;;;EAA6B,CAAC;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,eAAe;;;;EAAsC,CAAC;AAEnE;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB;;;EAAmC,CAAC;AAElE;;;GAGG;AAEH;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,wCAAwC,CAAC;AAChF,eAAO,MAAM,2BAA2B,6CACI,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/console/assets.d.ts
CHANGED
|
@@ -13,5 +13,26 @@ export declare const CONSOLE_STYLE = "\n:root{color-scheme:dark;--bg:#0f0f0f;--s
|
|
|
13
13
|
* cancelación/veredicto/linaje/artefacto).
|
|
14
14
|
*/
|
|
15
15
|
export declare const GRAPH_STYLE = "\n.graph-wrap{overflow:auto;background:#0b0d11;border:1px solid var(--line);border-radius:8px;padding:8px}\nsvg.graph{display:block}\n.gedge{stroke:#3a4250;stroke-width:1.5;marker-end:url(#garrow)}\n.gnode rect{fill:var(--panel);stroke:var(--line);stroke-width:1.5;rx:8}\n.gnode .gname{fill:var(--fg);font:600 12px ui-monospace,Consolas,monospace}\n.gnode .grole{fill:var(--muted);font-size:11px}\n.gnode .gstate{font-size:10px;text-transform:uppercase;letter-spacing:.05em}\n.gnode.state-pending rect{stroke:#6e7681}\n.gnode.state-pending .gstate{fill:#6e7681}\n.gnode.state-ready rect{stroke:var(--local)}\n.gnode.state-ready .gstate{fill:var(--local)}\n.gnode.state-active rect{stroke:var(--frontier)}\n.gnode.state-active .gstate{fill:var(--frontier)}\n.gnode.state-succeeded rect{stroke:var(--good)}\n.gnode.state-succeeded .gstate{fill:var(--good)}\n.gnode.state-failed rect{stroke:#f85149}\n.gnode.state-failed .gstate{fill:#f85149}\n.gnode.state-cancelled rect{stroke:#484f58}\n.gnode.state-cancelled .gstate{fill:#484f58}\n.gbadge{font-size:10px;font-family:ui-monospace,Consolas,monospace}\n.gbadge.badge-retry{fill:var(--frontier)}\n.gbadge.badge-error{fill:#f85149}\n.gbadge.badge-cancelled{fill:#484f58}\n.gbadge.badge-verdict.verdict-approved{fill:var(--good)}\n.gbadge.badge-verdict.verdict-rejected{fill:#f85149}\n.gbadge.badge-verdict.verdict-inconclusive{fill:var(--frontier)}\n.gbadge.badge-lineage{fill:var(--local)}\n.gbadge.badge-artifact{fill:var(--muted)}\n.gnode[data-session]{cursor:pointer}\n.gnode[data-session]:hover rect{stroke-width:2.5}\n.graph-health{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 12px}\n.gchip{font-size:11px;padding:2px 10px;border-radius:10px;border:1px solid var(--line);color:var(--muted)}\n.gchip.on{font-weight:600}\n.gchip.gh-recovery.on,.gchip.gh-unknown.on{color:var(--frontier);border-color:var(--frontier)}\n.gchip.gh-conflict.on,.gchip.gh-kill.on{color:#f85149;border-color:#f85149}\n.graph-drill{margin-top:14px;border-top:1px solid var(--line);padding-top:12px}\n.graph-drill h3{font-size:13px;margin:0 0 8px;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}\n.graph-drill .drilllog{background:#0b0d11;border:1px solid var(--line);border-radius:8px;padding:10px;max-height:280px;overflow:auto;font-family:ui-monospace,Consolas,monospace;font-size:12px;white-space:pre-wrap}\n.graph-drill .drilllog .tl{padding:1px 0}\n.graph-drill .drilllog .tl.tool{color:var(--frontier)}\n.graph-drill .drilllog .tl.status{color:var(--muted)}\n.graph-drill .drilllog .tl.permission{color:var(--frontier);font-weight:600}\n.graph-drill .drilllog .tl.error{color:#f85149}\n";
|
|
16
|
-
export declare const CONSOLE_CLIENT_JS = "\n(function(){\n var authTok='';\n try{\n var qp=new URLSearchParams(window.location.search).get('token');\n if(qp){authTok='?token='+encodeURIComponent(qp)}\n }catch(e){/* ignore */}\n function reloadIfChanged(prev){\n fetch('/api/state'+authTok).then(function(r){return r.json()}).then(function(s){\n if(s.generatedAt!==prev&&!configActive()){location.reload()}\n }).catch(function(){});\n }\n var current=document.documentElement.getAttribute('data-generated')||'';\n if('EventSource' in window){\n try{\n var es=new EventSource('/events'+authTok);\n es.addEventListener('state',function(){if(!configActive()){location.reload()}});\n es.onerror=function(){/* fallback below */};\n }catch(e){/* ignore */}\n }\n var ms=parseInt(document.documentElement.getAttribute('data-refresh')||'2000',10);\n setInterval(function(){reloadIfChanged(current)},isNaN(ms)?2000:Math.max(250,ms));\n\n function configActive(){\n var s=document.getElementById('screen-config');\n return !!(s&&!s.hidden);\n }\n function wireLogsScreen(screen){\n if(screen.__logsWired){return}\n screen.__logsWired=true;\n var buttons=screen.querySelectorAll('[data-session-target]');\n var cards=screen.querySelectorAll('[data-session-view]');\n function showSession(id){\n var matched=false;\n for(var i=0;i<buttons.length;i++){\n var on=buttons[i].getAttribute('data-session-target')===id;\n buttons[i].classList.toggle('sel',on);\n buttons[i].setAttribute('aria-selected',on?'true':'false');\n }\n for(var j=0;j<cards.length;j++){\n var show=cards[j].getAttribute('data-session-view')===id;\n cards[j].hidden=!show;\n if(show){matched=true;connectTerminal(cards[j],id)}\n }\n return matched;\n }\n for(var k=0;k<buttons.length;k++){\n buttons[k].addEventListener('click',function(e){\n var id=e.currentTarget.getAttribute('data-session-target');\n if(id){showSession(id)}\n });\n }\n if(buttons.length>0){\n showSession(buttons[0].getAttribute('data-session-target'));\n }\n }\n function selectScreen(name){\n var screens=document.querySelectorAll('.screen');\n var items=document.querySelectorAll('[data-screen]');\n var matched=false;\n var titleText='';\n var activeScreen=null;\n for(var i=0;i<screens.length;i++){\n var show=screens[i].id==='screen-'+name;\n screens[i].classList.toggle('active',show);\n screens[i].hidden=!show;\n if(show){matched=true;activeScreen=screens[i]}\n }\n if(!matched){return false}\n for(var j=0;j<items.length;j++){\n var on=items[j].getAttribute('data-screen')===name;\n if(on){\n items[j].setAttribute('aria-current','page');\n titleText=items[j].getAttribute('data-title')||'';\n }else{\n items[j].removeAttribute('aria-current');\n }\n }\n var title=document.getElementById('screen-title');\n if(title){title.textContent=titleText}\n if(name==='config'&&activeScreen){loadConfig(activeScreen)}\n if(name==='logs'&&activeScreen){wireLogsScreen(activeScreen)}\n try{localStorage.setItem('openteam.screen',name)}catch(e){}\n document.body.classList.remove('nav-open');\n return true;\n }\n function esc(s){return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')}\n // Config editor (W7-S09 / #193). The config values travel only over the\n // token-gated /api/config, never in this open page, so the browser fetches\n // the server-rendered form with the bearer token and injects it. The\n // applied/pending-restart summary is likewise server-rendered and injected\n // verbatim, so the P14 honesty is enforced server-side, not here.\n function loadConfig(view){\n var root=document.documentElement;\n if(root.getAttribute('data-config')!=='1'||view.__configWired){return}\n var mount=view.querySelector('[data-config-mount]');\n if(!mount){return}\n var token=root.getAttribute('data-token');\n if(!token){mount.innerHTML='<p class=\"muted\">Read-only: no console token present.</p>';return}\n view.__configWired=true;\n fetch('/api/config',{headers:{Authorization:'Bearer '+token}})\n .then(function(r){return r.json()})\n .then(function(d){\n mount.innerHTML=d.render||'<p class=\"config-err\">Could not load configuration.</p>';\n wireConfigForm(mount,token);\n })\n .catch(function(){view.__configWired=false;mount.innerHTML='<p class=\"config-err\">Could not load configuration.</p>'});\n }\n function wireConfigForm(mount,token){\n var form=mount.querySelector('[data-config-form]');\n if(!form){return}\n var out=form.querySelector('[data-config-result]');\n form.addEventListener('submit',function(e){\n e.preventDefault();\n var ta=form.querySelector('textarea[name=\"config\"]');\n var parsed;\n try{parsed=JSON.parse(ta.value)}catch(err){out.innerHTML='<div class=\"config-summary\"><p class=\"config-err\">Invalid JSON: '+esc(err.message||err)+'</p></div>';return}\n var btn=form.querySelector('.config-save');\n if(btn){btn.disabled=true}\n fetch('/api/config',{method:'POST',headers:{Authorization:'Bearer '+token,'content-type':'application/json'},body:JSON.stringify(parsed)})\n .then(function(r){return r.json().then(function(b){return{status:r.status,body:b}})})\n .then(function(res){\n if(btn){btn.disabled=false}\n if(res.status===200){out.innerHTML=res.body.render||''}\n else{out.innerHTML='<div class=\"config-summary\"><p class=\"config-err\">'+esc(res.body&&res.body.error?res.body.error:'Save failed.')+'</p></div>'}\n })\n .catch(function(){if(btn){btn.disabled=false}out.innerHTML='<div class=\"config-summary\"><p class=\"config-err\">Save failed.</p></div>'});\n });\n }\n function connectTerminal(view,id){\n if(view.__wired){return}\n var root=document.documentElement;\n var token=root.getAttribute('data-token');\n if(root.getAttribute('data-terminal')!=='1'||!token){return}\n var log=view.querySelector('.termlog');\n if(!log){return}\n view.__wired=true;\n function append(cls,text){\n var line=document.createElement('div');\n line.className='tl '+cls;line.textContent=text;\n log.appendChild(line);log.scrollTop=log.scrollHeight;\n }\n var q='/console/session/'+encodeURIComponent(id);\n var tk='token='+encodeURIComponent(token);\n if('EventSource' in window){\n try{\n var es=new EventSource(q+'/stream?'+tk);\n es.addEventListener('frame',function(e){try{var f=JSON.parse(e.data);append(f.kind,f.text)}catch(_){}}); \n es.onerror=function(){/* reconnects on its own */};\n }catch(_){/* ignore */}\n }\n var form=view.querySelector('form.terminput');\n if(form){\n form.addEventListener('submit',function(e){\n e.preventDefault();\n var inp=form.querySelector('input[name=text]');\n var text=inp.value;\n if(!text){return}\n inp.value='';append('input','\u203A '+text);\n fetch(q+'/input?'+tk,{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({text:text})})\n .then(function(r){if(!r.ok){append('error','\u2716 send rejected ('+r.status+')')}})\n .catch(function(){append('error','\u2716 could not send')});\n });\n }\n connectPty(view,id,q,tk);\n }\n function connectPty(view,id,q,tk){\n var root=document.documentElement;\n if(root.getAttribute('data-pty')!=='1'){return}\n var pane=view.querySelector('.pty');\n if(!pane){return}\n var log=pane.querySelector('.ptylog');\n var startBtn=pane.querySelector('.pty-start');\n var input=pane.querySelector('form.ptyinput');\n function plog(text){\n var d=document.createElement('span');d.textContent=text;\n log.appendChild(d);log.scrollTop=log.scrollHeight;\n }\n if(!startBtn){return}\n startBtn.addEventListener('click',function(){\n startBtn.disabled=true;plog('Opening shell\u2026\n');\n fetch(q+'/pty?'+tk,{method:'POST',headers:{'content-type':'application/json'},body:'{}'})\n .then(function(r){return r.ok?r.json():Promise.reject(r.status)})\n .then(function(info){openPtyWs(info.wsUrl)})\n .catch(function(s){plog('\u2716 could not open PTY ('+s+')\n');startBtn.disabled=false});\n });\n function openPtyWs(url){\n try{\n var ws=new WebSocket(url);\n ws.binaryType='arraybuffer';\n ws.onmessage=function(e){\n var data=e.data;\n if(data instanceof ArrayBuffer){data=new TextDecoder().decode(new Uint8Array(data))}\n plog(data);\n };\n ws.onclose=function(){plog('\n[shell closed]\n');startBtn.disabled=false};\n ws.onerror=function(){plog('\n\u2716 WebSocket error\n')};\n if(input){\n input.hidden=false;\n input.addEventListener('submit',function(e){\n e.preventDefault();\n var c=input.querySelector('input[name=cmd]');\n if(!c.value){return}\n ws.send(c.value+'\r');c.value='';\n });\n }\n }catch(_){plog('\n\u2716 WebSocket unavailable\n');startBtn.disabled=false}\n }\n }\n function wireGraphDrill(){\n var root=document.documentElement;\n if(root.getAttribute('data-drilldown')!=='1'){return}\n var token=root.getAttribute('data-token');\n if(!token){return}\n var drill=document.querySelector('.graph-drill');\n if(!drill){return}\n var gview=drill.closest('.screen');\n if(!gview){return}\n var log=drill.querySelector('.drilllog');\n var title=drill.querySelector('.drill-title');\n if(!log){return}\n var es=null;\n function append(cls,text){\n var line=document.createElement('div');\n line.className='tl '+cls;line.textContent=text;\n log.appendChild(line);log.scrollTop=log.scrollHeight;\n }\n function open(id){\n if(es){try{es.close()}catch(_){}}\n log.textContent='';drill.hidden=false;\n if(title){title.textContent='Conversation \u00B7 '+id}\n var tk='token='+encodeURIComponent(token);\n var base='/console/session/'+encodeURIComponent(id);\n fetch(base+'/messages?'+tk).then(function(r){return r.ok?r.json():Promise.reject(r.status)})\n .then(function(d){(d&&d.frames||[]).forEach(function(f){append(f.kind,f.text)})})\n .catch(function(s){append('error','\u2716 could not load conversation ('+s+')')});\n if('EventSource' in window){\n try{\n es=new EventSource(base+'/stream?'+tk);\n es.addEventListener('frame',function(e){try{var f=JSON.parse(e.data);append(f.kind,f.text)}catch(_){}}); \n es.onerror=function(){/* reconnects on its own */};\n }catch(_){/* ignore */}\n }\n }\n gview.addEventListener('click',function(e){\n var t=e.target;\n while(t&&t!==gview&&!(t.getAttribute&&t.getAttribute('data-session'))){t=t.parentNode}\n if(t&&t.getAttribute&&t.getAttribute('data-session')){open(t.getAttribute('data-session'))}\n });\n }\n var nav=document.querySelector('.nav');\n if(nav){\n nav.addEventListener('click',function(e){\n var t=e.target;\n while(t&&t!==nav&&!(t.getAttribute&&t.getAttribute('data-screen'))){t=t.parentNode}\n if(t&&t.getAttribute&&t.getAttribute('data-screen')){selectScreen(t.getAttribute('data-screen'))}\n });\n }\n var toggle=document.querySelector('[data-toggle-nav]');\n if(toggle){toggle.addEventListener('click',function(){document.body.classList.toggle('nav-open')})}\n var close=document.querySelector('[data-close-nav]');\n if(close){close.addEventListener('click',function(){document.body.classList.remove('nav-open')})}\n var saved='tree';\n try{saved=localStorage.getItem('openteam.screen')||'tree'}catch(e){}\n if(!selectScreen(saved)){selectScreen('tree')}\n wireGraphDrill();\n})();\n";
|
|
16
|
+
export declare const CONSOLE_CLIENT_JS = "\n(function(){\n var authTok='';\n try{\n var qp=new URLSearchParams(window.location.search).get('token');\n if(qp){authTok='?token='+encodeURIComponent(qp)}\n }catch(e){/* ignore */}\n function reloadIfChanged(prev){\n fetch('/api/state'+authTok).then(function(r){return r.json()}).then(function(s){\n if(s.generatedAt!==prev&&!configActive()&&!lifecycleActive()){location.reload()}\n }).catch(function(){});\n }\n var current=document.documentElement.getAttribute('data-generated')||'';\n if('EventSource' in window){\n try{\n var es=new EventSource('/events'+authTok);\n es.addEventListener('state',function(ev){\n try{\n var d=JSON.parse(ev.data||'{}');\n if(d.generatedAt&&d.generatedAt!==current&&!configActive()&&!lifecycleActive()){location.reload()}\n }catch(e){}\n });\n es.addEventListener('graph-append',function(ev){\n try{\n var d=JSON.parse(ev.data||'{}');\n document.dispatchEvent(new CustomEvent('lifecycle-append',{detail:{runID:d.runID,head:d.head}}));\n }catch(e){}\n });\n es.onerror=function(){/* fallback below */};\n }catch(e){/* ignore */}\n }\n var ms=parseInt(document.documentElement.getAttribute('data-refresh')||'2000',10);\n setInterval(function(){reloadIfChanged(current)},isNaN(ms)?2000:Math.max(250,ms));\n\n function configActive(){\n var s=document.getElementById('screen-config');\n return !!(s&&!s.hidden);\n }\n // Only the visible timeline owns incremental refresh. Other screens still\n // need state reloads; their navigation preserves the timeline URL selection.\n function lifecycleActive(){\n var mount=document.getElementById('lifecycle-timeline-mount');\n var screen=mount&&mount.closest('.screen');\n return !!(screen&&!screen.hidden);\n }\n function wireLogsScreen(screen){\n if(screen.__logsWired){return}\n screen.__logsWired=true;\n var buttons=screen.querySelectorAll('[data-session-target]');\n var cards=screen.querySelectorAll('[data-session-view]');\n function showSession(id){\n var matched=false;\n for(var i=0;i<buttons.length;i++){\n var on=buttons[i].getAttribute('data-session-target')===id;\n buttons[i].classList.toggle('sel',on);\n buttons[i].setAttribute('aria-selected',on?'true':'false');\n }\n for(var j=0;j<cards.length;j++){\n var show=cards[j].getAttribute('data-session-view')===id;\n cards[j].hidden=!show;\n if(show){matched=true;connectTerminal(cards[j],id)}\n }\n return matched;\n }\n for(var k=0;k<buttons.length;k++){\n buttons[k].addEventListener('click',function(e){\n var id=e.currentTarget.getAttribute('data-session-target');\n if(id){showSession(id)}\n });\n }\n if(buttons.length>0){\n showSession(buttons[0].getAttribute('data-session-target'));\n }\n }\n function selectScreen(name){\n var screens=document.querySelectorAll('.screen');\n var items=document.querySelectorAll('[data-screen]');\n var matched=false;\n var titleText='';\n var activeScreen=null;\n for(var i=0;i<screens.length;i++){\n var show=screens[i].id==='screen-'+name;\n screens[i].classList.toggle('active',show);\n screens[i].hidden=!show;\n if(show){matched=true;activeScreen=screens[i]}\n }\n if(!matched){return false}\n for(var j=0;j<items.length;j++){\n var on=items[j].getAttribute('data-screen')===name;\n if(on){\n items[j].setAttribute('aria-current','page');\n titleText=items[j].getAttribute('data-title')||'';\n }else{\n items[j].removeAttribute('aria-current');\n }\n }\n var title=document.getElementById('screen-title');\n if(title){title.textContent=titleText}\n if(name==='config'&&activeScreen){loadConfig(activeScreen)}\n if(name==='logs'&&activeScreen){wireLogsScreen(activeScreen)}\n try{localStorage.setItem('openteam.screen',name)}catch(e){}\n document.body.classList.remove('nav-open');\n return true;\n }\n function esc(s){return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')}\n // Config editor (W7-S09 / #193). The config values travel only over the\n // token-gated /api/config, never in this open page, so the browser fetches\n // the server-rendered form with the bearer token and injects it. The\n // applied/pending-restart summary is likewise server-rendered and injected\n // verbatim, so the P14 honesty is enforced server-side, not here.\n function loadConfig(view){\n var root=document.documentElement;\n if(root.getAttribute('data-config')!=='1'||view.__configWired){return}\n var mount=view.querySelector('[data-config-mount]');\n if(!mount){return}\n var token=root.getAttribute('data-token');\n if(!token){mount.innerHTML='<p class=\"muted\">Read-only: no console token present.</p>';return}\n view.__configWired=true;\n fetch('/api/config',{headers:{Authorization:'Bearer '+token}})\n .then(function(r){return r.json()})\n .then(function(d){\n mount.innerHTML=d.render||'<p class=\"config-err\">Could not load configuration.</p>';\n wireConfigForm(mount,token);\n })\n .catch(function(){view.__configWired=false;mount.innerHTML='<p class=\"config-err\">Could not load configuration.</p>'});\n }\n function wireConfigForm(mount,token){\n var form=mount.querySelector('[data-config-form]');\n if(!form){return}\n var out=form.querySelector('[data-config-result]');\n form.addEventListener('submit',function(e){\n e.preventDefault();\n var ta=form.querySelector('textarea[name=\"config\"]');\n var parsed;\n try{parsed=JSON.parse(ta.value)}catch(err){out.innerHTML='<div class=\"config-summary\"><p class=\"config-err\">Invalid JSON: '+esc(err.message||err)+'</p></div>';return}\n var btn=form.querySelector('.config-save');\n if(btn){btn.disabled=true}\n fetch('/api/config',{method:'POST',headers:{Authorization:'Bearer '+token,'content-type':'application/json'},body:JSON.stringify(parsed)})\n .then(function(r){return r.json().then(function(b){return{status:r.status,body:b}})})\n .then(function(res){\n if(btn){btn.disabled=false}\n if(res.status===200){out.innerHTML=res.body.render||''}\n else{out.innerHTML='<div class=\"config-summary\"><p class=\"config-err\">'+esc(res.body&&res.body.error?res.body.error:'Save failed.')+'</p></div>'}\n })\n .catch(function(){if(btn){btn.disabled=false}out.innerHTML='<div class=\"config-summary\"><p class=\"config-err\">Save failed.</p></div>'});\n });\n }\n function connectTerminal(view,id){\n if(view.__wired){return}\n var root=document.documentElement;\n var token=root.getAttribute('data-token');\n if(root.getAttribute('data-terminal')!=='1'||!token){return}\n var log=view.querySelector('.termlog');\n if(!log){return}\n view.__wired=true;\n function append(cls,text){\n var line=document.createElement('div');\n line.className='tl '+cls;line.textContent=text;\n log.appendChild(line);log.scrollTop=log.scrollHeight;\n }\n var q='/console/session/'+encodeURIComponent(id);\n var tk='token='+encodeURIComponent(token);\n if('EventSource' in window){\n try{\n var es=new EventSource(q+'/stream?'+tk);\n es.addEventListener('frame',function(e){try{var f=JSON.parse(e.data);append(f.kind,f.text)}catch(_){}}); \n es.onerror=function(){/* reconnects on its own */};\n }catch(_){/* ignore */}\n }\n var form=view.querySelector('form.terminput');\n if(form){\n form.addEventListener('submit',function(e){\n e.preventDefault();\n var inp=form.querySelector('input[name=text]');\n var text=inp.value;\n if(!text){return}\n inp.value='';append('input','\u203A '+text);\n fetch(q+'/input?'+tk,{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({text:text})})\n .then(function(r){if(!r.ok){append('error','\u2716 send rejected ('+r.status+')')}})\n .catch(function(){append('error','\u2716 could not send')});\n });\n }\n connectPty(view,id,q,tk);\n }\n function connectPty(view,id,q,tk){\n var root=document.documentElement;\n if(root.getAttribute('data-pty')!=='1'){return}\n var pane=view.querySelector('.pty');\n if(!pane){return}\n var log=pane.querySelector('.ptylog');\n var startBtn=pane.querySelector('.pty-start');\n var input=pane.querySelector('form.ptyinput');\n function plog(text){\n var d=document.createElement('span');d.textContent=text;\n log.appendChild(d);log.scrollTop=log.scrollHeight;\n }\n if(!startBtn){return}\n startBtn.addEventListener('click',function(){\n startBtn.disabled=true;plog('Opening shell\u2026\\n');\n fetch(q+'/pty?'+tk,{method:'POST',headers:{'content-type':'application/json'},body:'{}'})\n .then(function(r){return r.ok?r.json():Promise.reject(r.status)})\n .then(function(info){openPtyWs(info.wsUrl)})\n .catch(function(s){plog('\u2716 could not open PTY ('+s+')\\n');startBtn.disabled=false});\n });\n function openPtyWs(url){\n try{\n var ws=new WebSocket(url);\n ws.binaryType='arraybuffer';\n ws.onmessage=function(e){\n var data=e.data;\n if(data instanceof ArrayBuffer){data=new TextDecoder().decode(new Uint8Array(data))}\n plog(data);\n };\n ws.onclose=function(){plog('\\n[shell closed]\\n');startBtn.disabled=false};\n ws.onerror=function(){plog('\\n\u2716 WebSocket error\\n')};\n if(input){\n input.hidden=false;\n input.addEventListener('submit',function(e){\n e.preventDefault();\n var c=input.querySelector('input[name=cmd]');\n if(!c.value){return}\n ws.send(c.value+'\\r');c.value='';\n });\n }\n }catch(_){plog('\\n\u2716 WebSocket unavailable\\n');startBtn.disabled=false}\n }\n }\n function wireGraphDrill(){\n var root=document.documentElement;\n if(root.getAttribute('data-drilldown')!=='1'){return}\n var token=root.getAttribute('data-token');\n if(!token){return}\n var drill=document.querySelector('.graph-drill');\n if(!drill){return}\n var gview=drill.closest('.screen');\n if(!gview){return}\n var log=drill.querySelector('.drilllog');\n var title=drill.querySelector('.drill-title');\n if(!log){return}\n var es=null;\n function append(cls,text){\n var line=document.createElement('div');\n line.className='tl '+cls;line.textContent=text;\n log.appendChild(line);log.scrollTop=log.scrollHeight;\n }\n function open(id){\n if(es){try{es.close()}catch(_){}}\n log.textContent='';drill.hidden=false;\n if(title){title.textContent='Conversation \u00B7 '+id}\n var tk='token='+encodeURIComponent(token);\n var base='/console/session/'+encodeURIComponent(id);\n fetch(base+'/messages?'+tk).then(function(r){return r.ok?r.json():Promise.reject(r.status)})\n .then(function(d){(d&&d.frames||[]).forEach(function(f){append(f.kind,f.text)})})\n .catch(function(s){append('error','\u2716 could not load conversation ('+s+')')});\n if('EventSource' in window){\n try{\n es=new EventSource(base+'/stream?'+tk);\n es.addEventListener('frame',function(e){try{var f=JSON.parse(e.data);append(f.kind,f.text)}catch(_){}}); \n es.onerror=function(){/* reconnects on its own */};\n }catch(_){/* ignore */}\n }\n }\n gview.addEventListener('click',function(e){\n var t=e.target;\n while(t&&t!==gview&&!(t.getAttribute&&t.getAttribute('data-session'))){t=t.parentNode}\n if(t&&t.getAttribute&&t.getAttribute('data-session')){open(t.getAttribute('data-session'))}\n });\n }\n var nav=document.querySelector('.nav');\n if(nav){\n nav.addEventListener('click',function(e){\n var t=e.target;\n while(t&&t!==nav&&!(t.getAttribute&&t.getAttribute('data-screen'))){t=t.parentNode}\n if(t&&t.getAttribute&&t.getAttribute('data-screen')){selectScreen(t.getAttribute('data-screen'))}\n });\n }\n var toggle=document.querySelector('[data-toggle-nav]');\n if(toggle){toggle.addEventListener('click',function(){document.body.classList.toggle('nav-open')})}\n var close=document.querySelector('[data-close-nav]');\n if(close){close.addEventListener('click',function(){document.body.classList.remove('nav-open')})}\n var saved='tree';\n try{saved=localStorage.getItem('openteam.screen')||'tree'}catch(e){}\n if(!selectScreen(saved)){selectScreen('tree')}\n wireGraphDrill();\n wireLifecycleTimeline();\n})();\n";
|
|
17
|
+
/**
|
|
18
|
+
* Styles for the lifecycle history timeline surface. Uses `var(--cp-*)` from
|
|
19
|
+
* the Clawpilot theme — injected only when lifecycle history is enabled.
|
|
20
|
+
* Theme detection (prefers-color-scheme / ?scoutTheme) is bootstrapped by
|
|
21
|
+
* LIFECYCLE_THEME_BOOT inserted once into the HTML <head>.
|
|
22
|
+
*/
|
|
23
|
+
export declare const LIFECYCLE_STYLE = "\n:root {\n color-scheme: light;\n --cp-bg: #f7f4ef;\n --cp-bg-elevated: #fcfbf8;\n --cp-surface: #ffffff;\n --cp-surface-soft: #f5f5f5;\n --cp-border: #dedede;\n --cp-border-strong: #919191;\n --cp-text: #242424;\n --cp-text-muted: #5c5c5c;\n --cp-text-soft: #6f6f6f;\n --cp-accent: #b11f4b;\n --cp-accent-hover: #9a1a41;\n --cp-accent-soft: rgba(177, 31, 75, 0.08);\n --cp-accent-fg: #ffffff;\n --cp-success: #16a34a;\n --cp-danger: #dc2626;\n --cp-warning: #f59e0b;\n --cp-link: #0078d4;\n --cp-shadow: 0 18px 48px rgba(0, 0, 0, 0.12);\n --cp-overlay: rgba(255, 255, 255, 0.8);\n --cp-panel: rgba(255, 255, 255, 0.86);\n --cp-panel-strong: rgba(255, 255, 255, 0.96);\n --cp-sheen: rgba(255, 255, 255, 0.55);\n --cp-highlight: rgba(177, 31, 75, 0.12);\n --cp-card-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.14);\n}\nhtml[data-theme=\"dark\"] {\n color-scheme: dark;\n --cp-bg: #3d3b3a;\n --cp-bg-elevated: #343231;\n --cp-surface: #292929;\n --cp-surface-soft: #2e2e2e;\n --cp-border: #474747;\n --cp-border-strong: #5f5f5f;\n --cp-text: #dedede;\n --cp-text-muted: #919191;\n --cp-text-soft: #b0b0b0;\n --cp-accent: #fd8ea1;\n --cp-accent-hover: #fb7b91;\n --cp-accent-soft: rgba(253, 142, 161, 0.14);\n --cp-accent-fg: #1a1a1a;\n --cp-success: #4ade80;\n --cp-danger: #f87171;\n --cp-warning: #fbbf24;\n --cp-link: #4da6ff;\n --cp-shadow: 0 18px 48px rgba(0, 0, 0, 0.32);\n --cp-overlay: rgba(41, 41, 41, 0.88);\n --cp-panel: rgba(41, 41, 41, 0.72);\n --cp-panel-strong: rgba(41, 41, 41, 0.96);\n --cp-sheen: rgba(255, 255, 255, 0.04);\n --cp-highlight: rgba(253, 142, 161, 0.12);\n --cp-card-shadow: 0 0 2px rgba(0, 0, 0, 0.32), 0 1px 2px rgba(0, 0, 0, 0.36);\n}\n/* Clawpilot lifecycle hierarchy \u2014 scoped, no repaint of other Console screens. */\n.lifecycle-primary{background:var(--cp-bg-elevated);border-color:var(--cp-border)}\n.lc-host{box-sizing:border-box;color:var(--cp-text);font-family:\"Segoe UI\",Aptos,Calibri,-apple-system,BlinkMacSystemFont,sans-serif}\n.lc-host *{box-sizing:border-box}\n.lc-panel-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:16px}\n.lc-panel-head h3{margin:2px 0 0;color:var(--cp-text);font-size:18px}\n.lc-eyebrow{color:var(--cp-accent);font-size:10px;font-weight:700;letter-spacing:.09em;text-transform:uppercase}\n.lc-cursor-feedback{display:flex;flex-direction:column;align-items:flex-end;gap:3px;min-width:180px;color:var(--cp-text-muted)}\n.lc-cursor-count{font-family:Consolas,\"Courier New\",Courier,monospace;font-size:12px;font-weight:700;color:var(--cp-text)}\n.lc-cursor-time{font-family:Consolas,\"Courier New\",Courier,monospace;font-size:10px}\n.lc-controls{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:12px}\n.lc-run-select{min-width:180px;max-width:300px;padding:7px 28px 7px 10px;border:1px solid var(--cp-border);border-radius:.625rem;background:var(--cp-surface);color:var(--cp-text);font:inherit;font-size:12px}\n.lc-live-btn{display:inline-flex;align-items:center;gap:6px;padding:7px 12px;border:1px solid var(--cp-border-strong);border-radius:.625rem;background:var(--cp-surface);color:var(--cp-text);font:600 12px inherit;cursor:pointer}\n.lc-live-btn.active{border-color:var(--cp-accent);background:var(--cp-accent);color:var(--cp-accent-fg)}\n.lc-live-btn:hover:not(:disabled){border-color:var(--cp-accent);color:var(--cp-accent)}\n.lc-live-btn.active:hover:not(:disabled){background:var(--cp-accent-hover);color:var(--cp-accent-fg)}\n.lc-live-btn.paused{border-color:var(--cp-accent);color:var(--cp-accent)}\n.lc-live-btn:disabled{opacity:.45;cursor:not-allowed}\n.lc-live-dot{width:7px;height:7px;border-radius:50%;background:var(--cp-text-muted)}\n.lc-live-btn.active .lc-live-dot{background:var(--cp-accent-fg)}\n.lc-activity{display:inline-flex;align-items:center;gap:5px;padding:5px 9px;border:1px solid var(--cp-border);border-radius:999px;background:var(--cp-surface);color:var(--cp-text-muted);font-size:11px}\n.lc-activity-dot{width:6px;height:6px;border-radius:50%;background:var(--cp-text-muted)}\n.lc-activity.active{border-color:var(--cp-success);color:var(--cp-success)}\n.lc-activity.active .lc-activity-dot{background:var(--cp-success);animation:lc-pulse 1.8s infinite}\n.lc-activity.unknown{border-color:var(--cp-warning);color:var(--cp-warning)}\n.lc-activity.unknown .lc-activity-dot{background:var(--cp-warning)}\n.lc-activity.terminal{border-color:var(--cp-border-strong);color:var(--cp-text-muted)}\n@keyframes lc-pulse{0%,100%{opacity:1}50%{opacity:.35}}\n.lc-incoming-badge{padding:4px 8px;border-radius:999px;background:var(--cp-accent-soft);color:var(--cp-accent);font-size:11px;font-weight:600}\n.lc-slider-row{display:flex;align-items:center;gap:10px;margin:8px 0 14px}\n.lc-slider{flex:1;min-width:120px;accent-color:var(--cp-accent)}\n.lc-slider:disabled{opacity:.4}\n.lc-counts{font-family:Consolas,\"Courier New\",Courier,monospace;font-size:11px;color:var(--cp-text-muted);white-space:nowrap}\n.lc-tree-mount{min-height:80px;max-height:min(70vh,760px);padding:4px 4px 16px;overflow:auto}\n.lc-empty,.lc-error,.lc-legacy-note,.lc-partial-note{padding:12px 14px;border:1px solid var(--cp-border);border-radius:.625rem;background:var(--cp-surface-soft);color:var(--cp-text-muted);font-size:12px}\n.lc-error{border-color:var(--cp-danger);color:var(--cp-danger);background:var(--cp-surface)}\n.lc-legacy-note,.lc-partial-note{border-color:var(--cp-warning);color:var(--cp-text);margin-bottom:10px}\n.lct-tree{min-width:42rem;padding:4px}\n.lct-operation{position:relative;display:block;min-width:38rem;margin:0 0 14px}\n.lct-operation-card{position:relative;z-index:1;padding:14px;border:1px solid var(--cp-border);border-left:4px solid var(--cp-accent);border-radius:16px;background:var(--cp-surface);box-shadow:var(--cp-card-shadow)}\n.lct-operation[data-op-state=\"succeeded\"]>.lct-operation-card{border-left-color:var(--cp-success)}\n.lct-operation[data-op-state=\"failed\"]>.lct-operation-card,.lct-operation[data-op-state=\"cancelled\"]>.lct-operation-card{border-left-color:var(--cp-danger)}\n.lct-operation-head,.lct-attempt-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}\n.lct-operation-label{display:block;margin-bottom:3px;color:var(--cp-text-muted);font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase}\n.lct-operation-id{display:block;max-width:48rem;overflow:hidden;color:var(--cp-text);font-size:13px;text-overflow:ellipsis;white-space:nowrap}\n.lct-state{display:inline-flex;flex:none;padding:3px 8px;border:1px solid var(--cp-border-strong);border-radius:999px;background:var(--cp-surface-soft);color:var(--cp-text);font-size:10px;font-weight:700}\n.lct-state[data-state=\"succeeded\"]{border-color:var(--cp-success);color:var(--cp-success)}\n.lct-state[data-state=\"failed\"],.lct-state[data-state=\"cancelled\"]{border-color:var(--cp-danger);color:var(--cp-danger)}\n.lct-state[data-state=\"running\"],.lct-state[data-state=\"queued\"],.lct-state[data-state=\"selected\"]{border-color:var(--cp-accent);color:var(--cp-accent)}\n.lct-operation-meta,.lct-attempt-meta{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;margin:12px 0 0}\n.lct-meta-item{min-width:0}\n.lct-meta-item dt{margin:0 0 2px;color:var(--cp-text-muted);font-size:10px}\n.lct-meta-item dd{margin:0;overflow-wrap:anywhere;color:var(--cp-text);font-size:11px}\n.lct-dependencies,.lct-parent-reference{display:flex;align-items:flex-start;gap:8px;margin-top:12px;padding:9px 10px;border-left:3px solid var(--cp-warning);border-radius:.625rem;background:var(--cp-surface-soft);font-size:11px}\n.lct-relation-label,.lct-parent-reference>span:first-child{flex:none;color:var(--cp-text-muted);font-weight:700}\n.lct-dependencies ul{display:flex;flex-wrap:wrap;gap:6px;margin:0;padding:0;list-style:none}\n.lct-dependencies li{padding:2px 6px;border:1px dashed var(--cp-border-strong);border-radius:.625rem;background:var(--cp-surface)}\n.lct-missing-reference{color:var(--cp-danger);font-weight:700}\n.lct-attempts{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:10px;margin-top:14px}\n.lct-attempt{min-width:0;padding:11px;border:1px solid var(--cp-border);border-radius:.625rem;background:var(--cp-surface-soft)}\n.lct-attempt-head strong{font-size:12px}\n.lct-times{display:flex;flex-wrap:wrap;gap:6px 12px;margin-top:10px}\n.lct-time-item{display:flex;gap:5px;color:var(--cp-text-muted);font-size:10px}\n.lct-time-item time{font-family:Consolas,\"Courier New\",Courier,monospace;color:var(--cp-text-soft)}\n.lct-failure{display:flex;flex-wrap:wrap;gap:6px 10px;margin-top:10px;padding:8px;border:1px solid var(--cp-danger);border-radius:.625rem;background:var(--cp-surface);color:var(--cp-danger);font-size:10px}\n.lct-failure-label{font-weight:700}\n.lct-model,.lct-session,.lct-session-empty{margin-top:10px;padding:9px 10px;border-left:3px solid var(--cp-accent);border-radius:.625rem;background:var(--cp-surface);font-size:10px}\n.lct-model,.lct-session{display:flex;flex-wrap:wrap;gap:5px 8px;align-items:center}\n.lct-model>span:first-child,.lct-session>span:first-child{color:var(--cp-accent);font-weight:700}\n.lct-parent-session{color:var(--cp-text-muted)}\n.lct-session-empty,.lct-no-attempts{color:var(--cp-text-muted)}\n.lct-operation-children{position:relative;margin:14px 0 0 24px;padding-left:24px;border-left:2px solid var(--cp-border-strong)}\n.lct-operation-children>.lct-operation::before{position:absolute;top:30px;left:-24px;width:24px;border-top:2px solid var(--cp-border-strong);content:\"\"}\n.lct-operation-children>.lct-operation:last-child::after{position:absolute;top:32px;bottom:-15px;left:-26px;width:4px;background:var(--cp-bg-elevated);content:\"\"}\n.lct-unlinked{margin-top:18px;padding:12px;border:1px dashed var(--cp-warning);border-radius:16px;background:var(--cp-surface-soft)}\n.lct-unlinked h4{margin:0;color:var(--cp-warning)}\n.lct-unlinked p{margin:4px 0 12px;color:var(--cp-text-muted);font-size:11px}\n.lct-root-missing{margin-bottom:12px;color:var(--cp-danger);font-size:12px}\n.lct-route-local{color:var(--cp-link)}.lct-route-frontier{color:var(--cp-warning)}\n.lc-graph-supplement{margin-top:18px;border-top:1px solid var(--cp-border);padding-top:14px}\n.lc-graph-supplement summary{cursor:pointer;color:var(--cp-link);font-size:12px}\n.lc-graph-supplement-body{margin-top:12px}\n@media(max-width:700px){\n .lc-panel-head{flex-direction:column}\n .lc-cursor-feedback{align-items:flex-start;min-width:0}\n .lc-controls{align-items:stretch}\n .lc-run-select{max-width:none;flex:1}\n .lct-tree{min-width:34rem}\n .lct-operation{min-width:31rem}\n}\n";
|
|
24
|
+
/**
|
|
25
|
+
* Theme detection boot fragment — inserted once per page before lifecycle JS.
|
|
26
|
+
* Uses the Clawpilot `?scoutTheme` param + `prefers-color-scheme` fallback.
|
|
27
|
+
* Pure, side-effect-limited: only sets `data-theme` on the root element.
|
|
28
|
+
*/
|
|
29
|
+
export declare const LIFECYCLE_THEME_BOOT = "\n(() => {\n const param = new URLSearchParams(window.location.search).get(\"scoutTheme\");\n const theme =\n param || (window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\");\n document.documentElement.setAttribute(\"data-theme\", theme);\n})();\n";
|
|
30
|
+
/**
|
|
31
|
+
* Lifecycle timeline client JS. Wired by `wireLifecycleTimeline()` (called
|
|
32
|
+
* from CONSOLE_CLIENT_JS after the console initialisation). No inline
|
|
33
|
+
* user-facing message strings — labels come from `data-*` attributes set
|
|
34
|
+
* server-side. No dynamic `innerHTML` from user data; escaping is done on
|
|
35
|
+
* the server side.
|
|
36
|
+
*/
|
|
37
|
+
export declare const LIFECYCLE_CLIENT_JS = "\nfunction wireLifecycleTimeline(){\n var mount=document.getElementById('lifecycle-timeline-mount');\n if(!mount){return}\n var authTok='';\n try{var qp=new URLSearchParams(window.location.search).get('token');if(qp){authTok='?token='+encodeURIComponent(qp)}}catch(e){}\n\n var runSelect=mount.querySelector('[data-lifecycle-run-select]');\n var liveBtn=mount.querySelector('[data-lifecycle-live-btn]');\n var slider=mount.querySelector('[data-lifecycle-slider]');\n var treeMountEl=mount.querySelector('[data-lifecycle-tree-mount]');\n var countsEl=mount.querySelector('[data-lifecycle-counts]');\n var activityEl=mount.querySelector('[data-lifecycle-activity]');\n var incomingEl=mount.querySelector('[data-lifecycle-incoming]');\n var cursorCountEl=mount.querySelector('[data-lifecycle-cursor-count]');\n var cursorTimeEl=mount.querySelector('[data-lifecycle-cursor-time]');\n var screenEl=mount.closest('.screen');\n var screenHeadingEl=screenEl&&screenEl.querySelector('.screen-head h2');\n var screenDescriptionEl=screenEl&&screenEl.querySelector('.screen-head p');\n\n // scrubInProgress / sliderWired: gesture and wiring state shared by\n // wireSlider() \u2014 declared here so ensureViewControls() can call wireSlider()\n // after dynamically creating slider during an empty\u2192view promotion.\n var scrubInProgress=false;\n var sliderWired=false;\n\n var state={\n explicitRun:urlRun(),\n runID:mount.getAttribute('data-lifecycle-run')||null,\n cursor:urlCursor(),\n head:Number(mount.getAttribute('data-lifecycle-head'))||0,\n followLive:urlCursor()===null,\n generation:0,\n request:null,\n pending:false,\n stopped:false,\n lastSseHead:new Map()\n };\n var projectionKey='';\n\n function urlCursor(){\n try{\n var values=new URLSearchParams(window.location.search).getAll('cursor');\n if(values.length>1){return 'invalid'}\n return values.length?values[0]:null;\n }catch(e){return null}\n }\n function urlRun(){\n try{return new URLSearchParams(window.location.search).get('run')}catch(e){return null}\n }\n\n // buildUrl: compute the target URL string without touching history.\n function buildUrl(runID,cursor){\n try{\n var sp=new URLSearchParams(window.location.search);\n if(runID){sp.set('run',runID)}else{sp.delete('run')}\n if(cursor!==null&&cursor!==undefined){sp.set('cursor',String(cursor))}else{sp.delete('cursor')}\n var qs=sp.toString();\n return qs?('?'+qs):window.location.pathname;\n }catch(e){return window.location.href}\n }\n // replaceUrl: mid-drag / intermediate updates \u2014 no history entry.\n function replaceUrl(runID,cursor){\n try{history.replaceState(null,'',buildUrl(runID,cursor));}catch(e){}\n }\n // pushUrl: committed navigation \u2014 creates a traversable history entry.\n function pushUrl(runID,cursor){\n try{history.pushState(null,'',buildUrl(runID,cursor));}catch(e){}\n }\n\n function buildApiUrl(runID,cursor){\n var u='/api/graph'+authTok;\n var sep=authTok?'&':'?';\n if(runID!==null&&runID!==undefined){u+=sep+'run='+encodeURIComponent(runID);sep='&'}\n if(cursor!==null&&cursor!==undefined){u+=sep+'cursor='+encodeURIComponent(String(cursor))}\n return u;\n }\n\n function cancelRequest(){\n var request=state.request;\n state.request=null;\n if(request){clearTimeout(request.timeout);request.controller.abort()}\n }\n\n // Background invalidations share one flight and one pending bit. Only user\n // navigation advances the epoch; a busy stream cannot starve valid replies.\n function fetchHistory(){\n if(state.stopped){return}\n if(state.request){state.pending=true;return}\n state.pending=false;\n var cursor=state.followLive?null:state.cursor;\n var runID=state.explicitRun;\n if(runID===null&&!state.followLive){runID=state.runID}\n var request={generation:state.generation,controller:new AbortController(),timeout:null};\n state.request=request;\n function current(){return !state.stopped&&state.request===request&&request.generation===state.generation}\n function finish(){\n if(!current()){return}\n clearTimeout(request.timeout);\n state.request=null;\n if(state.pending){fetchHistory()}\n }\n request.timeout=setTimeout(function(){\n if(!current()){return}\n request.controller.abort();\n showError();\n finish();\n },15000);\n fetch(buildApiUrl(runID,cursor),{signal:request.controller.signal}).then(function(r){return r.json()}).then(function(d){\n if(!current()){return}\n handleResponse(d,cursor);\n finish();\n }).catch(function(){\n if(!current()){return}\n showError();\n finish();\n });\n }\n\n function navigateFromUrl(initial){\n state.generation++;\n cancelRequest();\n state.pending=false;\n scrubInProgress=false;\n state.explicitRun=urlRun();\n state.cursor=urlCursor();\n state.followLive=state.cursor===null;\n state.runID=state.explicitRun!==null?state.explicitRun:initial&&!state.followLive?mount.getAttribute('data-lifecycle-run'):null;\n state.head=0;\n fetchHistory();\n }\n\n function handleResponse(d,requestedCursor){\n if(!d||d.version!==1){showError();return}\n if(d.kind==='error'){showApiError(d.error);return}\n if(d.kind==='disabled'){showDisabled(d);return}\n if(d.kind==='empty'){showEmpty();return}\n if(d.kind==='legacy'){renderLegacy(d);return}\n if(d.kind==='view'){renderView(d,requestedCursor);return}\n showError();\n }\n\n // wireSlider: attach input/change listeners once (guarded by sliderWired).\n function wireSlider(){\n if(sliderWired||!slider){return}\n sliderWired=true;\n slider.addEventListener('input',function(){\n var c=parseInt(slider.value,10);\n if(!scrubInProgress){\n history.pushState(null,'',window.location.href);\n scrubInProgress=true;\n }\n replaceUrl(state.runID,c);\n navigateFromUrl(false);\n scrubInProgress=true;\n });\n slider.addEventListener('change',function(){\n var c=parseInt(slider.value,10);\n replaceUrl(state.runID,c);\n scrubInProgress=false;\n });\n }\n\n // ensureViewControls: promote the empty SSR shell to a full view shell when\n // the first run data arrives. SSR empty only renders runSelect+liveBtn; all\n // other controls (activity, incoming, slider, treeMount) are missing. Build\n // and append them so renderView/renderLegacy can update them normally.\n function ensureViewControls(){\n if(slider!==null){return} // already promoted or SSR was full view/legacy\n // Remove placeholder status element (lc-empty or lc-legacy-note).\n var placeholder=mount.querySelector('.lc-empty,.lc-legacy-note');\n if(placeholder){mount.removeChild(placeholder)}\n // Append activity badge + incoming badge to the controls div.\n var controlsDiv=mount.querySelector('.lc-controls');\n if(controlsDiv){\n var actSpan=document.createElement('span');\n actSpan.className='lc-activity unknown';\n actSpan.setAttribute('data-lifecycle-activity','writer-unknown');\n actSpan.setAttribute('aria-live','polite');\n var actDot=document.createElement('span');actDot.className='lc-activity-dot';actDot.setAttribute('aria-hidden','true');\n var actLbl=document.createElement('span');actLbl.setAttribute('data-lc-activity-label','');\n actSpan.appendChild(actDot);actSpan.appendChild(actLbl);\n controlsDiv.appendChild(actSpan);\n activityEl=actSpan;\n var incSpan=document.createElement('span');\n incSpan.className='lc-incoming-badge';\n incSpan.setAttribute('data-lifecycle-incoming','');\n incSpan.hidden=true;\n controlsDiv.appendChild(incSpan);\n incomingEl=incSpan;\n }\n // Build slider row: <div class=\"lc-slider-row\"><input ...><span data-lifecycle-counts>\n var sliderRow=document.createElement('div');sliderRow.className='lc-slider-row';\n var inp=document.createElement('input');\n inp.type='range';inp.className='lc-slider';\n inp.setAttribute('data-lifecycle-slider','');\n inp.min='0';inp.max='0';inp.value='0';\n inp.setAttribute('aria-label',mount.getAttribute('data-msg-slider-aria')||'Timeline cursor');\n inp.setAttribute('aria-valuenow','0');inp.setAttribute('aria-valuemax','0');\n inp.disabled=true;\n var cntSpan=document.createElement('span');\n cntSpan.className='lc-counts';\n cntSpan.setAttribute('data-lifecycle-counts','');\n var evtLabel=mount.getAttribute('data-msg-events')||'{n} events';\n cntSpan.textContent=evtLabel.replace('{n}','0');\n sliderRow.appendChild(inp);sliderRow.appendChild(cntSpan);\n mount.appendChild(sliderRow);\n slider=inp;countsEl=cntSpan;\n // Build tree mount.\n var tm=document.createElement('div');tm.className='lc-tree-mount';\n tm.setAttribute('data-lifecycle-tree-mount','');\n mount.appendChild(tm);\n treeMountEl=tm;\n // Wire slider now that the element exists.\n wireSlider();\n }\n\n function message(name){\n return mount.getAttribute('data-msg-'+name)||'';\n }\n\n function fillTemplate(template,values){\n var result=template;\n Object.keys(values).forEach(function(key){\n result=result.split('{'+key+'}').join(String(values[key]));\n });\n return result;\n }\n\n function updateCursorFeedback(proj){\n if(cursorCountEl){\n if(!proj){\n cursorCountEl.textContent='';\n }else{\n var countTemplate=message(proj.head===1?'cursor-count-one':'cursor-count');\n cursorCountEl.textContent=fillTemplate(countTemplate,{cursor:proj.cursor,head:proj.head});\n }\n }\n if(cursorTimeEl){\n if(!proj||proj.lastEventAt===null||proj.lastEventAt===undefined){\n cursorTimeEl.removeAttribute('datetime');\n cursorTimeEl.textContent=message('no-event-time');\n }else{\n var iso=new Date(proj.lastEventAt).toISOString();\n cursorTimeEl.setAttribute('datetime',iso);\n cursorTimeEl.textContent=message('latest-event')+': '+iso;\n }\n }\n }\n\n function updateScreenCopy(kind,followLive,activity){\n var headingKey='screen-heading';\n var descriptionKey='screen-description';\n if(kind==='legacy'){\n headingKey='activity-legacy';\n descriptionKey='legacy-note';\n }else if(kind==='unavailable'){\n descriptionKey='screen-description-unavailable';\n }else if(kind==='view'&&!followLive){\n headingKey='screen-heading-historical';\n descriptionKey='screen-description-historical';\n }else if(kind==='view'&&activity&&activity.kind==='terminal'){\n headingKey='screen-heading-completed';\n descriptionKey='screen-description-completed';\n }else if(kind==='view'&&activity&&activity.kind==='writer-active'){\n headingKey='screen-heading-live';\n descriptionKey='screen-description-live';\n }\n if(screenHeadingEl){screenHeadingEl.textContent=message(headingKey)}\n if(screenDescriptionEl){screenDescriptionEl.textContent=message(descriptionKey)}\n }\n\n function updateFollowControl(followLive,activity){\n if(!liveBtn){return}\n var writerActive=followLive&&activity&&activity.kind==='writer-active';\n var labelKey=!followLive?'return-live':activity&&activity.kind==='terminal'?'latest':writerActive?'live':'following-head';\n var label=message(labelKey);\n liveBtn.classList.toggle('paused',!followLive);\n liveBtn.classList.toggle('active',writerActive);\n liveBtn.setAttribute('aria-pressed',followLive?'true':'false');\n liveBtn.setAttribute('aria-label',!followLive?message('return-live-aria'):writerActive?message('live-aria'):label);\n var labelEl=liveBtn.querySelector('[data-lc-live-label]');\n if(labelEl){labelEl.textContent=label}\n liveBtn.disabled=false;\n }\n\n function renderView(d,requestedCursor){\n ensureViewControls();\n state.runID=d.selection.runID;\n state.head=d.selection.head;\n state.cursor=d.selection.cursor;\n state.followLive=requestedCursor===null;\n if(!state.followLive&&state.explicitRun===null){\n state.explicitRun=state.runID;\n replaceUrl(state.runID,state.cursor);\n }\n\n // Update run selector.\n if(runSelect&&d.runs){\n syncRunOptions(d.runs,d.selection.runID);\n }\n\n // Update slider.\n if(slider){\n slider.max=String(state.head);\n slider.value=String(state.cursor);\n slider.disabled=(state.head===0);\n slider.setAttribute('aria-valuenow',String(state.cursor));\n slider.setAttribute('aria-valuemax',String(state.head));\n }\n\n // Update counts.\n if(countsEl){\n var countLabel=mount.getAttribute('data-msg-events')||'{n} events';\n countsEl.textContent=countLabel.replace('{n}',String(state.head));\n countsEl.hidden=false;\n }\n if(incomingEl){\n var inc=d.selection.incomingEvents||0;\n var incomingLabel=mount.getAttribute('data-msg-incoming')||'';\n incomingEl.textContent=inc>0?incomingLabel.replace('{n}',String(inc)):'';\n incomingEl.hidden=(inc===0);\n }\n\n updateFollowControl(state.followLive,d.activity);\n updateActivity(d.activity);\n updateScreenCopy('view',state.followLive,d.activity);\n updateCursorFeedback(d.projection);\n\n // Render tree projection.\n renderProjection(d.projection,d.recording);\n\n // Sync mount data attributes so QA selectors and popstate reads reflect\n // current state. These were set by SSR but never updated by client JS.\n mount.setAttribute('data-lifecycle-state', state.followLive?'live':'paused');\n mount.setAttribute('data-lifecycle-run', d.selection.runID||'');\n mount.setAttribute('data-lifecycle-head', String(state.head));\n }\n\n function syncRunOptions(runs,selectedID){\n if(!runSelect){return}\n var current=runSelect.value;\n // Rebuild options only if the set changed.\n var existingIds=Array.prototype.map.call(runSelect.options,function(o){return o.value});\n var newIds=runs.map(function(r){return r.runID});\n var changed=JSON.stringify(existingIds)!==JSON.stringify(newIds);\n if(changed){\n runSelect.innerHTML='';\n for(var i=0;i<runs.length;i++){\n var opt=document.createElement('option');\n opt.value=runs[i].runID;\n var label=runs[i].runID.slice(0,16)+(runs[i].source==='legacy-graph'?' (legacy)':'');\n opt.textContent=label;\n runSelect.appendChild(opt);\n }\n }\n runSelect.value=selectedID;\n }\n\n function renderLegacy(d){\n ensureViewControls();\n state.runID=d.selection.runID;\n state.head=0;\n if(runSelect&&d.runs){syncRunOptions(d.runs,d.selection.runID)}\n if(slider){\n slider.disabled=true;slider.value='0';slider.max='0';\n slider.setAttribute('aria-valuenow','0');slider.setAttribute('aria-valuemax','0');\n }\n if(incomingEl){incomingEl.textContent='';incomingEl.hidden=true}\n if(countsEl){countsEl.textContent='';countsEl.hidden=true}\n updateFollowControl(false,{kind:'legacy'});\n if(liveBtn){liveBtn.disabled=true}\n updateActivity({kind:'legacy'});\n updateScreenCopy('legacy',false,{kind:'legacy'});\n updateCursorFeedback(null);\n // Show legacy graph using existing graph render (the projection is GraphViewProjectionV1).\n if(treeMountEl){\n projectionKey='';\n var legacyNote=document.createElement('div');\n legacyNote.className='lc-legacy-note';\n legacyNote.setAttribute('role','status');\n var noteMsg=mount.getAttribute('data-msg-legacy-note')||'';\n legacyNote.textContent=noteMsg;\n treeMountEl.innerHTML='';\n treeMountEl.appendChild(legacyNote);\n // Render the legacy graph SVG if the projection has nodes.\n if(d.projection&&d.projection.nodes){\n renderGraphViewInline(d.projection,treeMountEl);\n }\n }\n mount.setAttribute('data-lifecycle-state','legacy');\n mount.setAttribute('data-lifecycle-run',d.selection.runID||'');\n mount.setAttribute('data-lifecycle-head','0');\n }\n\n function renderProjection(proj,recording){\n if(!proj||!treeMountEl){return}\n var degraded=recording&&recording.state==='degraded';\n var key=JSON.stringify([proj.runID,proj.cursor,proj.rootOperationID,proj.operations,degraded]);\n if(key===projectionKey){return}\n projectionKey=key;\n treeMountEl.textContent='';\n if(degraded){\n var note=makeElement('div','lc-partial-note',message('partial-tail'));\n note.setAttribute('role','status');\n treeMountEl.appendChild(note);\n }\n treeMountEl.appendChild(buildOperationTree(proj));\n }\n\n function makeElement(tag,className,text){\n var element=document.createElement(tag);\n if(className){element.className=className}\n if(text!==undefined&&text!==null){element.textContent=String(text)}\n return element;\n }\n\n function appendMeta(parent,label,value,className){\n var item=makeElement('div','lct-meta-item');\n item.appendChild(makeElement('dt','',label));\n var detail=makeElement('dd',className||'',value);\n item.appendChild(detail);\n parent.appendChild(item);\n }\n\n function stateBadge(stateValue){\n var badge=makeElement('span','lct-state',stateValue);\n badge.setAttribute('data-state',stateValue);\n badge.setAttribute('aria-label',message('state')+': '+stateValue);\n return badge;\n }\n\n function appendTime(parent,label,value){\n if(value===undefined||value===null){return}\n var iso=new Date(value).toISOString();\n var item=makeElement('div','lct-time-item');\n item.appendChild(makeElement('span','',label));\n var time=makeElement('time','',iso);\n time.setAttribute('datetime',iso);\n item.appendChild(time);\n parent.appendChild(item);\n }\n\n function appendFailure(parent,failure){\n if(!failure){return}\n var box=makeElement('div','lct-failure');\n box.appendChild(makeElement('span','lct-failure-label',message('failure')));\n box.appendChild(makeElement('code','',failure.class));\n if(failure.statusCode!==undefined){\n var status=makeElement('span','',message('status-code')+' ');\n status.appendChild(makeElement('code','',failure.statusCode));\n box.appendChild(status);\n }\n if(failure.retryable!==undefined){\n box.appendChild(makeElement('span','',message('retryable')+' '+message(failure.retryable?'yes':'no')));\n }\n parent.appendChild(box);\n }\n\n function appendSession(parent,attempt){\n if(!attempt.sessionID){\n parent.appendChild(makeElement('div','lct-session-empty',message('no-session')));\n return;\n }\n var session=makeElement('div','lct-session');\n session.setAttribute('data-lifecycle-session-id',attempt.sessionID);\n session.appendChild(makeElement('span','',message('session')));\n session.appendChild(makeElement('code','',attempt.sessionID));\n if(attempt.parentSessionID){\n var parentSession=makeElement('span','lct-parent-session',message('parent-session')+' ');\n parentSession.appendChild(makeElement('code','',attempt.parentSessionID));\n session.appendChild(parentSession);\n }\n parent.appendChild(session);\n }\n\n function buildAttempt(attempt){\n var article=makeElement('article','lct-attempt');\n article.setAttribute('data-lifecycle-attempt-id',attempt.attemptID);\n article.setAttribute('data-lifecycle-attempt-state',attempt.state);\n article.setAttribute('data-lifecycle-retry-index',String(attempt.retryIndex));\n var header=makeElement('header','lct-attempt-head');\n header.appendChild(makeElement('strong','',fillTemplate(message('attempt'),{n:Number(attempt.attempt)+1})));\n header.appendChild(stateBadge(attempt.state));\n article.appendChild(header);\n\n var metadata=makeElement('dl','lct-attempt-meta');\n if(!attempt.model){appendMeta(metadata,message('model'),message('no-model'),'muted')}\n appendMeta(metadata,message('route'),attempt.routeKind||message('no-route'),attempt.routeKind?'lct-route-'+attempt.routeKind:'muted');\n appendMeta(metadata,message('retry-label'),attempt.retryIndex,'mono');\n if(attempt.selectionCause){appendMeta(metadata,message('selection'),attempt.selectionCause,'mono')}\n if(attempt.runtimeID){appendMeta(metadata,message('runtime'),attempt.runtimeID,'mono')}\n article.appendChild(metadata);\n\n var times=makeElement('div','lct-times');\n appendTime(times,message('selected-at'),attempt.selectedAt);\n appendTime(times,message('queued-at'),attempt.queuedAt);\n appendTime(times,message('started-at'),attempt.startedAt);\n appendTime(times,message('terminal-at'),attempt.terminalAt);\n article.appendChild(times);\n appendFailure(article,attempt.failure);\n if(attempt.model){\n var identity=attempt.model.providerID+'/'+attempt.model.modelID;\n var model=makeElement('div','lct-model');\n model.setAttribute('data-lifecycle-model-id',identity);\n model.appendChild(makeElement('span','',message('model')));\n model.appendChild(makeElement('code','',identity));\n article.appendChild(model);\n }\n appendSession(article,attempt);\n return article;\n }\n\n function appendParentReference(card,op,known){\n if(!op.parentOperationID||known.has(op.parentOperationID)){return}\n var reference=makeElement('div','lct-parent-reference');\n reference.appendChild(makeElement('span','',message('parent-reference')));\n reference.appendChild(makeElement('code','',op.parentOperationID));\n reference.appendChild(makeElement('span','lct-missing-reference',message('missing-operation')));\n card.appendChild(reference);\n }\n\n function appendDependencies(card,op,known){\n var dependencyIDs=op.dependsOnOperationIDs||[];\n if(dependencyIDs.length===0){return}\n var box=makeElement('div','lct-dependencies');\n box.appendChild(makeElement('span','lct-relation-label',message('depends-on')));\n var list=makeElement('ul','');\n dependencyIDs.forEach(function(dependencyID){\n var item=makeElement('li','');\n item.setAttribute('data-lifecycle-dependency-from',dependencyID);\n item.appendChild(makeElement('code','',dependencyID));\n if(!known.has(dependencyID)){\n item.appendChild(document.createTextNode(' '));\n item.appendChild(makeElement('span','lct-missing-reference',message('missing-operation')));\n }\n list.appendChild(item);\n });\n box.appendChild(list);\n card.appendChild(box);\n }\n\n function buildOperation(op,known,depth){\n var article=makeElement('article','lct-operation');\n article.setAttribute('role','treeitem');\n article.setAttribute('aria-level',String(depth));\n article.setAttribute('data-lifecycle-operation-id',op.operationID);\n if(op.parentOperationID){article.setAttribute('data-lifecycle-parent-operation-id',op.parentOperationID)}\n article.setAttribute('data-lifecycle-operation-state',op.state);\n article.setAttribute('data-op-id',op.operationID);\n article.setAttribute('data-op-state',op.state);\n\n var card=makeElement('div','lct-operation-card');\n var header=makeElement('header','lct-operation-head');\n var identity=makeElement('div','');\n identity.appendChild(makeElement('span','lct-operation-label',message('operation')));\n identity.appendChild(makeElement('code','lct-operation-id',op.operationID));\n header.appendChild(identity);\n header.appendChild(stateBadge(op.state));\n card.appendChild(header);\n\n var metadata=makeElement('dl','lct-operation-meta');\n appendMeta(metadata,message('role'),op.roleID,'mono');\n appendMeta(metadata,message('kind'),op.kind,'mono');\n appendMeta(metadata,message('task'),op.taskID,'mono');\n if(op.agentID){appendMeta(metadata,message('agent'),op.agentID,'mono')}\n card.appendChild(metadata);\n appendParentReference(card,op,known);\n appendDependencies(card,op,known);\n\n var attempts=makeElement('section','lct-attempts');\n attempts.setAttribute('aria-label',message('attempts'));\n var attemptList=op.attempts||[];\n if(attemptList.length===0){\n attempts.appendChild(makeElement('div','lct-no-attempts',message('no-attempts')));\n }else{\n attemptList.forEach(function(attempt){attempts.appendChild(buildAttempt(attempt))});\n }\n card.appendChild(attempts);\n article.appendChild(card);\n return article;\n }\n\n function buildOperationTree(proj){\n var operations=Array.isArray(proj.operations)?proj.operations:[];\n if(operations.length===0){\n return makeElement('div','lc-empty',message('no-operations'));\n }\n var byID=new Map();\n operations.forEach(function(op){if(!byID.has(op.operationID)){byID.set(op.operationID,op)}});\n var uniqueOperations=Array.from(byID.values());\n var known=new Set(byID.keys());\n var childrenByParent=new Map();\n uniqueOperations.forEach(function(op){\n if(!op.parentOperationID||!known.has(op.parentOperationID)){return}\n var children=childrenByParent.get(op.parentOperationID)||[];\n children.push(op);\n childrenByParent.set(op.parentOperationID,children);\n });\n var visited=new Set();\n function buildBranch(op,depth){\n if(visited.has(op.operationID)){return null}\n visited.add(op.operationID);\n var article=buildOperation(op,known,depth);\n var children=childrenByParent.get(op.operationID)||[];\n var childNodes=[];\n children.forEach(function(child){\n var node=buildBranch(child,depth+1);\n if(node){childNodes.push(node)}\n });\n if(childNodes.length>0){\n var group=makeElement('div','lct-operation-children');\n group.setAttribute('role','group');\n childNodes.forEach(function(node){group.appendChild(node)});\n article.appendChild(group);\n }\n return article;\n }\n\n var tree=makeElement('div','lct-tree');\n tree.setAttribute('role','tree');\n tree.setAttribute('aria-label',message('tree-aria'));\n var root=byID.get(proj.rootOperationID);\n if(root){\n var rootNode=buildBranch(root,1);\n if(rootNode){tree.appendChild(rootNode)}\n }else{\n tree.appendChild(makeElement('div','lct-root-missing',message('root-missing')));\n }\n\n var unlinked=null;\n var unlinkedGroup=null;\n while(visited.size<uniqueOperations.length){\n var next=uniqueOperations.find(function(op){\n return !visited.has(op.operationID)&&(!op.parentOperationID||!known.has(op.parentOperationID)||visited.has(op.parentOperationID));\n })||uniqueOperations.find(function(op){return !visited.has(op.operationID)});\n if(!next){break}\n if(!unlinked){\n unlinked=makeElement('section','lct-unlinked');\n unlinked.appendChild(makeElement('h4','',message('unlinked')));\n unlinked.appendChild(makeElement('p','',message('unlinked-note')));\n unlinkedGroup=makeElement('div','');\n unlinkedGroup.setAttribute('role','group');\n unlinked.appendChild(unlinkedGroup);\n tree.appendChild(unlinked);\n }\n var unlinkedNode=buildBranch(next,1);\n if(unlinkedNode){unlinkedGroup.appendChild(unlinkedNode)}\n }\n return tree;\n }\n\n function renderGraphViewInline(proj,container){\n // Minimal DAG SVG for legacy projections (GraphViewProjectionV1).\n // Uses existing .graph-wrap / .gnode styles from GRAPH_STYLE.\n if(!proj.nodes||proj.nodes.length===0){return}\n var COL_W=220,ROW_H=96,NODE_W=180,NODE_H=64,PAD=20;\n var layer={};\n proj.nodes.forEach(function(n){layer[n.nodeID]=0});\n for(var pass=0;pass<proj.nodes.length;pass++){\n var changed=false;\n for(var e=0;e<(proj.edges||[]).length;e++){\n var edge=proj.edges[e];\n var from=(layer[edge.from]||0),to=(layer[edge.to]||0);\n if(from+1>to){layer[edge.to]=from+1;changed=true}\n }\n if(!changed){break}\n }\n var byLayer=[];\n proj.nodes.forEach(function(n){\n var l=layer[n.nodeID]||0;\n if(!byLayer[l]){byLayer[l]=[]}\n byLayer[l].push(n.nodeID);\n });\n var pos={};var maxL=0,maxR=0;\n byLayer.forEach(function(ids,l){\n if(l>maxL){maxL=l}if(ids.length>maxR){maxR=ids.length}\n ids.forEach(function(id,r){pos[id]={x:PAD+l*COL_W,y:PAD+r*ROW_H}});\n });\n var W=PAD*2+maxL*COL_W+NODE_W,H=PAD*2+Math.max(0,maxR-1)*ROW_H+NODE_H;\n var svgParts=['<svg class=\"graph\" viewBox=\"0 0 '+W+' '+H+'\" width=\"'+W+'\" height=\"'+H+'\" role=\"img\"><defs><marker id=\"ga2\" viewBox=\"0 0 8 8\" refX=\"7\" refY=\"4\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L8 4 L0 8 z\" fill=\"var(--cp-border-strong)\"></path></marker></defs>'];\n (proj.edges||[]).forEach(function(e){\n var a=pos[e.from],b=pos[e.to];\n if(!a||!b){return}\n svgParts.push('<line class=\"gedge\" x1=\"'+(a.x+NODE_W)+'\" y1=\"'+(a.y+NODE_H/2)+'\" x2=\"'+b.x+'\" y2=\"'+(b.y+NODE_H/2)+'\" marker-end=\"url(#ga2)\"></line>');\n });\n proj.nodes.forEach(function(n){\n var p=pos[n.nodeID];if(!p){return}\n function escape(value){return String(value).replace(/[&<>\"']/g,function(c){return{'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]||c})}\n var safe=escape(n.nodeID);\n var session=typeof n.sessionRef==='string'&&n.sessionRef?' data-session=\"'+escape(n.sessionRef)+'\"':'';\n svgParts.push('<g class=\"gnode state-'+escape(n.state)+'\" data-node=\"'+safe+'\"'+session+' transform=\"translate('+p.x+','+p.y+')\"><rect width=\"'+NODE_W+'\" height=\"'+NODE_H+'\"></rect><text class=\"gname\" x=\"10\" y=\"20\">'+safe+'</text><text class=\"gstate\" x=\"10\" y=\"40\">'+escape(n.state)+'</text></g>');\n });\n svgParts.push('</svg>');\n var wrap=document.createElement('div');wrap.className='graph-wrap';\n wrap.innerHTML=svgParts.join('');\n container.appendChild(wrap);\n }\n\n function updateActivity(activity){\n if(!activityEl){return}\n var kind=activity&&activity.kind?activity.kind:'writer-unknown';\n var cssKind=kind==='writer-active'?'active':kind==='writer-unknown'?'unknown':kind;\n var dot=activityEl.querySelector('.lc-activity-dot');\n activityEl.className='lc-activity '+cssKind;\n activityEl.setAttribute('data-lifecycle-activity',kind);\n var label=mount.getAttribute('data-msg-activity-'+kind)||kind;\n var textNode=activityEl.querySelector('[data-lc-activity-label]');\n if(textNode){textNode.textContent=label}\n if(dot){dot.setAttribute('aria-hidden','true')}\n }\n\n function showError(){\n projectionKey='';\n mount.setAttribute('data-lifecycle-state','error');\n updateScreenCopy('unavailable',false,null);\n updateCursorFeedback(null);\n if(liveBtn){liveBtn.disabled=true}\n if(slider){slider.disabled=true}\n if(treeMountEl){\n treeMountEl.innerHTML='';\n var div=document.createElement('div');div.className='lc-error';div.setAttribute('role','alert');\n div.textContent=mount.getAttribute('data-msg-error-loading')||'';\n treeMountEl.appendChild(div);\n }\n }\n\n function showApiError(err){\n projectionKey='';\n mount.setAttribute('data-lifecycle-state','error');\n updateScreenCopy('unavailable',false,null);\n updateCursorFeedback(null);\n if(liveBtn){liveBtn.disabled=true}\n if(slider){slider.disabled=true}\n if(!treeMountEl||!err){showError();return}\n var code=err.code||'';\n var msg=mount.getAttribute('data-msg-error-'+code)||mount.getAttribute('data-msg-error-loading')||'';\n treeMountEl.innerHTML='';\n var div=document.createElement('div');div.className='lc-error';div.setAttribute('role','alert');\n div.textContent=msg;\n treeMountEl.appendChild(div);\n }\n\n function showDisabled(d){\n projectionKey='';\n mount.setAttribute('data-lifecycle-state','disabled');\n updateScreenCopy('unavailable',false,null);\n updateCursorFeedback(null);\n if(liveBtn){liveBtn.disabled=true}\n if(slider){slider.disabled=true}\n var reason=d&&d.reason?d.reason:'history-disabled';\n var msg=mount.getAttribute('data-msg-disabled-'+reason)||'';\n if(treeMountEl){\n treeMountEl.innerHTML='';\n var div=document.createElement('div');div.className='lc-empty';div.setAttribute('role','status');\n div.textContent=msg;\n treeMountEl.appendChild(div);\n }\n }\n\n function showEmpty(){\n projectionKey='';\n mount.setAttribute('data-lifecycle-state','empty');\n updateScreenCopy('empty',false,null);\n updateCursorFeedback(null);\n if(liveBtn){liveBtn.disabled=true}\n if(slider){slider.disabled=true}\n var msg=mount.getAttribute('data-msg-no-runs')||'';\n if(treeMountEl){\n treeMountEl.innerHTML='';\n var div=document.createElement('div');div.className='lc-empty';div.setAttribute('role','status');\n div.textContent=msg;\n treeMountEl.appendChild(div);\n }\n }\n\n // --- Run selector change ---\n if(runSelect){\n runSelect.addEventListener('change',function(){\n var newRun=runSelect.value;\n pushUrl(newRun,null); // committed selection \u2192 traversable entry\n navigateFromUrl(false);\n });\n }\n\n // --- Slider scrub ---\n // Wire slider event listeners if slider was present in SSR (view/legacy state).\n // When SSR is empty, wireSlider() is deferred to ensureViewControls().\n wireSlider();\n\n // --- Live / Return to live ---\n if(liveBtn){\n liveBtn.addEventListener('click',function(){\n pushUrl(state.explicitRun,null); // return-to-live preserves automatic run selection\n navigateFromUrl(false);\n });\n }\n\n // --- SSE graph-append handler ---\n function onAppend(e){\n if(state.stopped){return}\n var detail=e.detail||{};\n var runID=detail.runID;var head=detail.head;\n if(typeof runID!=='string'||!runID||!Number.isSafeInteger(head)||head<0){return}\n if((state.explicitRun!==null||!state.followLive)&&runID!==state.runID){return}\n var known=Math.max(state.lastSseHead.get(runID)||0,runID===state.runID?state.head:0);\n if(head<=known){return}\n state.lastSseHead.set(runID,head);\n if(state.lastSseHead.size>64){state.lastSseHead.delete(state.lastSseHead.keys().next().value)}\n // Hints never change displayed head/incoming; the confirmed API selection\n // is authoritative, including while paused at zero or exactly at head.\n fetchHistory();\n }\n document.addEventListener('lifecycle-append',onAppend);\n\n // --- Browser back/forward ---\n window.addEventListener('popstate',function(){\n navigateFromUrl(false);\n });\n\n // --- Catch-up polling (SSE-absent / coalesced-event recovery) ---\n // Paused requests retain their exact prefix while refreshing head metadata.\n var lcRefreshMs=parseInt(document.documentElement.getAttribute('data-refresh')||'2000',10);\n if(isNaN(lcRefreshMs)||lcRefreshMs<500){lcRefreshMs=2000;}\n var pollTimer=setInterval(fetchHistory,lcRefreshMs);\n window.addEventListener('pagehide',function(){\n state.stopped=true;\n state.generation++;\n state.pending=false;\n cancelRequest();\n clearInterval(pollTimer);\n document.removeEventListener('lifecycle-append',onAppend);\n });\n window.addEventListener('pageshow',function(e){\n if(!e.persisted||!state.stopped){return}\n state.stopped=false;\n document.addEventListener('lifecycle-append',onAppend);\n pollTimer=setInterval(fetchHistory,lcRefreshMs);\n navigateFromUrl(false);\n });\n\n navigateFromUrl(true);\n}\n";
|
|
17
38
|
//# sourceMappingURL=assets.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/console/assets.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,aAAa,upYA6BzB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,klFA4CvB,CAAC;AAEF,eAAO,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/console/assets.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,aAAa,upYA6BzB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,klFA4CvB,CAAC;AAEF,eAAO,MAAM,iBAAiB,qjZA8R7B,CAAC;AAMF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,w/UAiJ3B,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,gSAOhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,u6lCA20B/B,CAAC"}
|
package/dist/console/render.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { GraphMode } from "../config/schema";
|
|
2
|
+
import type { LifecycleHistoryResponseV1 } from "../lifecycle/contracts";
|
|
2
3
|
import type { GraphViewProjectionV1 } from "../telemetry/graphView";
|
|
3
4
|
import type { ConsoleState } from "./types";
|
|
4
5
|
export declare const GRAPH_EMPTY_REMEDIATION: "No graph run yet. The tree fills when openteam-orchestrate dispatches roles; ordinary chat does not create a graph run.";
|
|
@@ -58,6 +59,17 @@ export type RenderOptions = {
|
|
|
58
59
|
configEditor?: {
|
|
59
60
|
readonly hasToken: boolean;
|
|
60
61
|
};
|
|
62
|
+
/**
|
|
63
|
+
* Lifecycle history timeline surface (#222). When provided, renders the
|
|
64
|
+
* timeline panel in the tree screen and injects the lifecycle CSS/JS.
|
|
65
|
+
* `response` is the current history view (or disabled/empty/etc.); may be
|
|
66
|
+
* `null` when the provider is wired but has not yet responded.
|
|
67
|
+
*/
|
|
68
|
+
lifecycleView?: {
|
|
69
|
+
readonly response: LifecycleHistoryResponseV1 | null;
|
|
70
|
+
/** Run ID from the URL query (for initial state). */
|
|
71
|
+
readonly initialRunID?: string;
|
|
72
|
+
};
|
|
61
73
|
};
|
|
62
74
|
/**
|
|
63
75
|
* Renderiza el console como un único HTML autocontenido (CSS + JS inline, sin
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/console/render.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/console/render.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAEV,0BAA0B,EAK3B,MAAM,wBAAwB,CAAC;AAUhC,OAAO,KAAK,EAGV,qBAAqB,EACtB,MAAM,wBAAwB,CAAC;AAYhC,OAAO,KAAK,EAGV,YAAY,EAIb,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,uBAAuB,EAClC,yHAAkI,CAAC;AASrI,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOhD;AA4mBD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,qBAAqB,GAAG,IAAI,EACxC,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACnC,MAAM,CA2BR;AA67BD,MAAM,MAAM,aAAa,GAAG;IAC1B,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV,QAAQ,CAAC,UAAU,EAAE,qBAAqB,GAAG,IAAI,CAAC;QAClD,sEAAsE;QACtE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;QACzB;;;WAGG;QACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;KAC7B,CAAC;IACF;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9C;;;;;OAKG;IACH,aAAa,CAAC,EAAE;QACd,QAAQ,CAAC,QAAQ,EAAE,0BAA0B,GAAG,IAAI,CAAC;QACrD,qDAAqD;QACrD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;KAChC,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,aAAkB,GAC1B,MAAM,CA2GR"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAe,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAM7E,OAAO,KAAK,EACV,OAAO,EAEP,qBAAqB,EACtB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAGL,KAAK,cAAc,EAGpB,MAAM,2BAA2B,CAAC;AAOnC,OAAO,EAEL,KAAK,YAAY,EAElB,MAAM,kBAAkB,CAAC;AAQ1B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|