my-durable 0.0.29 → 0.0.31
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/apps/dpi-backend/src/faux.ts +6 -0
- package/apps/dpi-backend/src/git.ts +57 -2
- package/apps/dpi-backend/src/routes.ts +12 -0
- package/apps/dpi-backend/src/store.ts +91 -1
- package/apps/dpi-playground/apps/dpi-playground-fe/dist/assets/index-B2OcBmds.js +81 -0
- package/apps/dpi-playground/apps/dpi-playground-fe/dist/assets/index-CL5-3stf.css +1 -0
- package/apps/dpi-playground/apps/dpi-playground-fe/dist/index.html +2 -2
- package/apps/dpi-playground/apps/dpi-playground-fe/src/components/GitPanel.vue +287 -32
- package/apps/dpi-sdk/src/client.ts +18 -1
- package/apps/dpi-sdk/src/protocol/rest-routes.ts +1 -0
- package/package.json +1 -1
- package/apps/dpi-playground/apps/dpi-playground-fe/dist/assets/index-C325mnAU.css +0 -1
- package/apps/dpi-playground/apps/dpi-playground-fe/dist/assets/index-CWO1e3Gk.js +0 -79
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;450;500;550;600;650;700&family=Manrope:wght@400;500;600;650;700;750;800&family=IBM+Plex+Mono:wght@400;500&display=swap";.git-chip-wrap[data-v-c0fb9e98]{align-items:center;display:inline-flex;position:relative}.git-chip[data-v-c0fb9e98]{gap:4px}.git-chip .branch[data-v-c0fb9e98]{text-overflow:ellipsis;white-space:nowrap;max-width:14ch;overflow:hidden}.dirty[data-v-c0fb9e98]{color:var(--warn,#e5a50a)}.ahead[data-v-c0fb9e98]{color:var(--ok,#2ea043)}.behind[data-v-c0fb9e98]{color:var(--info,#58a6ff)}.tunnel-status{flex-wrap:wrap;align-items:center;gap:.5rem;font-size:.75rem;display:inline-flex}.tunnel-status .axis{border:1px solid var(--border,#333);border-radius:999px;align-items:center;gap:.25rem;padding:.1rem .5rem;display:inline-flex}.tunnel-status .axis.transport{color:var(--fg,#eee)}.tunnel-status .axis.monitor.offline{color:var(--muted,#888)}.tunnel-status .axis.monitor.unauthorized,.tunnel-status .axis.monitor.mismatch,.tunnel-status .axis.monitor.incompatible{color:var(--warn,#e0b040)}.tunnel-status .axis.monitor.online{color:var(--ok,#6cc070)}.tunnel-status .axis.muted{color:var(--muted,#888);border-style:dashed}.tunnel-status .axis.url{color:var(--accent,#7ab8ff);text-decoration:none}.tunnel-status .live{color:var(--ok,#6cc070)}.token-manager{border:1px solid var(--border,#333);border-radius:8px;flex-direction:column;gap:.5rem;padding:.6rem .8rem;font-size:.8rem;display:flex}.token-manager header{align-items:center;gap:.4rem;display:flex}.token-manager h3{text-transform:uppercase;letter-spacing:.08em;margin:0;font-size:.8rem}.token-manager .pairing-status{border:1px solid var(--border,#333);border-radius:999px;margin-left:auto;padding:.05rem .5rem;font-size:.7rem}.token-manager .pairing-status.paired{color:var(--ok,#6cc070)}.token-manager .pairing-status.revoked{color:var(--warn,#e0b040)}.token-manager dl{grid-template-columns:auto 1fr;gap:.15rem .8rem;margin:0;display:grid}.token-manager dt{color:var(--muted,#888)}.token-manager dd{text-overflow:ellipsis;min-width:0;margin:0;overflow:hidden}.token-manager .credential-fingerprint{white-space:normal;overflow-wrap:anywhere}.token-manager .rotation-badge{color:var(--warn,#e0b040);align-items:center;gap:.35rem;margin:0;font-size:.75rem;display:flex}.token-manager .token-actions{flex-wrap:wrap;gap:.5rem;display:flex}.token-manager .spin{animation:1.2s linear infinite tm-spin}@keyframes tm-spin{to{transform:rotate(360deg)}}.git-pane[data-v-31f66416]{gap:4px;display:grid}.git-top[data-v-31f66416]{flex-wrap:wrap;gap:8px}.branch-wrap[data-v-31f66416]{position:relative}.branch-btn[data-v-31f66416]{border:1px solid var(--line);border-radius:6px;align-items:center;gap:7px;padding:6px 12px;display:inline-flex}.branch-btn strong[data-v-31f66416]{font-size:16px}.menu[data-v-31f66416]{z-index:40;background:var(--bg-2,#221a1c);border:1px solid var(--line);border-radius:8px;min-width:300px;max-height:280px;padding:4px;position:absolute;top:calc(100% + 6px);left:0;overflow:auto;box-shadow:0 10px 30px #00000080}.menu button[data-v-31f66416]{text-align:left;border-radius:6px;align-items:center;gap:10px;width:100%;padding:7px 10px;font-size:15px;display:flex}.menu button[data-v-31f66416]:hover,.menu button.cur[data-v-31f66416]{background:#403536}.menu .new-branch[data-v-31f66416]{border-top:1px solid var(--line);gap:6px;padding:8px;display:flex}.menu .new-branch input[data-v-31f66416]{flex:1;min-width:0}.auto-stash[data-v-31f66416]{opacity:.85;align-items:center;gap:8px;padding:8px 10px;font-size:14px;display:flex}.muted-line[data-v-31f66416]{opacity:.65;font-size:13px}.cap[data-v-31f66416]{padding:4px 0}.row[data-v-31f66416]{flex-wrap:wrap;align-items:center;gap:6px;margin:8px 0;display:flex}.hintbox[data-v-31f66416]{border-radius:6px;flex-wrap:wrap;align-items:center;gap:10px;margin:4px 0;padding:6px 10px;display:flex}.hintbox.warn[data-v-31f66416]{border:1px solid var(--warn,#e5a50a);color:var(--warn,#e5a50a)}.merge-banner[data-v-31f66416]{border-radius:6px;padding:8px 10px}.files[data-v-31f66416]{border:1px solid var(--line);border-radius:8px;max-height:260px;padding:4px 10px;overflow:auto}.file[data-v-31f66416]{justify-content:space-between;align-items:center;gap:6px;padding:3px 0;display:flex}.file.all[data-v-31f66416]{border-bottom:1px solid var(--line)}.file-label[data-v-31f66416]{cursor:pointer;flex:1;align-items:center;gap:8px;min-width:0;display:flex}.file .path[data-v-31f66416]{text-overflow:ellipsis;white-space:nowrap;font-size:14px;overflow:hidden}.file .xy[data-v-31f66416]{opacity:.7;font-size:12px}.nums[data-v-31f66416]{opacity:.8;color:var(--ok,#2ea043);white-space:nowrap;font-size:11px}.nums.bin[data-v-31f66416]{color:var(--warn,#e5a50a)}.dir-row[data-v-31f66416]{opacity:.8;align-items:center;gap:6px;width:100%;padding:3px 0;font-size:13px;display:flex}.dir-row .open[data-v-31f66416]{transform:rotate(90deg)}.file-acts[data-v-31f66416]{gap:2px;display:flex}.file-diff[data-v-31f66416]{border:1px solid var(--line);border-radius:8px;flex-wrap:wrap;align-items:center;gap:8px;margin:8px 0;padding:8px 10px;display:flex}.file-diff pre[data-v-31f66416]{width:100%;max-height:260px;margin:6px 0 0;font-size:12px;overflow:auto}.mode-chips[data-v-31f66416]{gap:2px;display:inline-flex}.mode-chips button[data-v-31f66416]{border:1px solid var(--line);border-radius:10px;padding:2px 8px;font-size:12px}.mode-chips button.on[data-v-31f66416]{background:#403536}textarea[data-v-31f66416]{resize:vertical;width:100%;min-height:76px;font:inherit;margin-top:8px}.commits[data-v-31f66416]{gap:3px;max-height:340px;display:grid;overflow:auto}.commit-row[data-v-31f66416]{white-space:nowrap;align-items:center;gap:8px;display:flex}.commit-row .lane[data-v-31f66416]{flex-shrink:0}.commit-row .hash[data-v-31f66416]{color:var(--ok,#2ea043);font-size:13px}.hash-btn svg[data-v-31f66416]{transition:transform .1s}.hash-btn svg.open[data-v-31f66416]{transform:rotate(90deg)}.commit-row .refs[data-v-31f66416]{color:var(--warn,#e5a50a);text-overflow:ellipsis;max-width:18ch;font-size:12px;overflow:hidden}.commit-row .subject[data-v-31f66416]{text-overflow:ellipsis;max-width:40%;font-size:14px;overflow:hidden}.commit-row .who[data-v-31f66416]{font-size:12px}.commit-files[data-v-31f66416]{border-left:2px solid var(--line);margin-left:16px;padding:2px 0 6px 34px}.cf[data-v-31f66416]{gap:10px;padding:1px 0;font-size:13px;display:flex}.cf-status[data-v-31f66416]{opacity:.8;width:2ch;font-size:11px}.cps[data-v-31f66416]{border:1px solid var(--line);border-radius:8px;margin-bottom:6px;padding:4px 10px}.cp-row[data-v-31f66416]{align-items:center;gap:10px;padding:2px 0;font-size:14px;display:flex}.cp-row code[data-v-31f66416]{color:var(--warn,#e5a50a)}.cp-subj[data-v-31f66416]{text-overflow:ellipsis;white-space:nowrap;max-width:40%;overflow:hidden}.wt[data-v-31f66416]{align-items:center;gap:8px;padding:2px 0;display:flex}.wt code[data-v-31f66416]{text-overflow:ellipsis;white-space:nowrap;max-width:40%;font-size:13px;overflow:hidden}.wt.main code[data-v-31f66416]{font-weight:650}.grow[data-v-31f66416]{flex:1}.tag-x[data-v-31f66416]{opacity:.7;margin-left:4px;display:inline-flex}.pr-row[data-v-31f66416]{white-space:nowrap;align-items:center;gap:8px;padding:2px 0;display:flex}.pr-row .tag.open[data-v-31f66416]{color:var(--ok,#2ea043)}.pr-checks[data-v-31f66416]{white-space:pre-wrap;background:#00000040;border-radius:6px;margin:4px 0;padding:8px;font-size:12px}.turns[data-v-31f66416]{max-height:180px;overflow:auto}.modal-veil[data-v-31f66416]{z-index:90;background:#0000008c;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.modal[data-v-31f66416]{background:var(--bg-2,#221a1c);border:1px solid var(--line);border-radius:10px;min-width:340px;max-width:520px;padding:16px 18px}.modal.danger[data-v-31f66416]{border-color:var(--warn,#e5a50a)}.modal h5[data-v-31f66416]{margin:0 0 6px;font-size:17px}.modal p[data-v-31f66416]{margin:0 0 10px;font-size:15px}.modal textarea[data-v-31f66416]{min-height:56px}.modal .danger[data-v-31f66416]{border-color:var(--warn,#e5a50a)}.op-out[data-v-31f66416]{background:#00000040;border-radius:6px;max-height:300px;margin-top:8px;padding:10px;font-size:12px;overflow:auto}h4[data-v-31f66416]{align-items:center;gap:8px;margin:0;font-size:16px;display:flex}.device-handoff[data-v-01884b7b]{border:1px solid var(--border);background:var(--panel);border-radius:12px;margin-bottom:14px;padding:14px 16px}header[data-v-01884b7b]{align-items:center;gap:8px;margin-bottom:6px;font-weight:650;display:flex}h3[data-v-01884b7b]{margin:0;font-size:14.5px}.what[data-v-01884b7b]{color:var(--muted);margin:0 0 10px;font-size:13px}code[data-v-01884b7b]{font-family:ui-monospace,monospace;font-size:12px}.row[data-v-01884b7b]{flex-wrap:wrap;align-items:end;gap:8px;display:flex}label[data-v-01884b7b]{color:var(--muted);gap:4px;font-size:12px;display:grid}input[data-v-01884b7b]{border:1px solid var(--border);background:var(--panel);width:90px;color:inherit;font:inherit;border-radius:8px;padding:7px 9px}.err[data-v-01884b7b]{color:var(--danger,#f28b82);margin:8px 0 0;font-size:12.5px}.target[data-v-01884b7b]{color:var(--muted);word-break:break-all;margin:10px 0 0;font-family:ui-monospace,monospace;font-size:12px}.pair-wizard .pair-steps{color:var(--muted,#888);gap:.5rem;margin:.25rem 0 .75rem;padding:0;font-size:.78rem;list-style:none;display:flex}.pair-wizard .pair-steps li{border:1px solid #0000;border-radius:999px;padding:.15rem .6rem}.pair-wizard .pair-steps li.on{color:var(--fg,#eee);border-color:currentColor}.pair-wizard .pair-grid{grid-template-columns:auto 1fr;align-items:start;gap:1rem;display:grid}.pair-wizard .pair-code{letter-spacing:.18em;font-size:1.7rem;font-family:var(--mono,monospace);margin-bottom:.35rem}.pair-wizard .pair-copy-actions{flex-wrap:wrap;gap:.4rem;display:flex}.pair-wizard .pair-qr svg{border:1px solid var(--border,#333);border-radius:6px}.pair-wizard .pair-side{flex-direction:column;gap:.6rem;min-width:0;display:flex}.pair-wizard .fp{word-break:break-all;background:var(--bg2,#222);border-radius:6px;padding:.4rem;font-size:.78rem;display:block}.pair-wizard .pair-confirm{align-items:center;gap:.45rem;font-size:.85rem;display:flex}.pair-wizard .pair-confirm.warn{color:var(--warn,#e0b040)}.pair-wizard .spin{animation:1.2s linear infinite pair-spin}@keyframes pair-spin{to{transform:rotate(360deg)}}.pair-pending{border:1px solid #2a3442;border-radius:12px;margin:0 0 18px;padding:14px 16px}.pair-pending h3{margin:0 0 10px;font-size:14px}.pair-pending ul{gap:10px;margin:0;padding:0;list-style:none;display:grid}.pair-pending li{border-bottom:1px solid #222b36;gap:4px;padding-bottom:10px;display:grid}.pair-pending li:last-child{border-bottom:0;padding-bottom:0}.pair-pending .who{flex-wrap:wrap;align-items:baseline;gap:8px;display:flex}.pair-pending .fp{word-break:break-all;color:#7ee2a8;font-family:ui-monospace,monospace;font-size:12px}.pair-pending .row{justify-content:space-between;align-items:center;gap:10px;display:flex}.pair-pending .phase{color:#8fa0b5;font-size:12px}:root{font-family:var(--font-body);color:var(--fg);background:var(--bg);font-synthesis:none;--bg:#151010;--tree:#181213;--chat:#161011;--panel:#1c1516;--card:#251a1b;--line-soft:#2a2021;--fg:#f2eeee;--faint:#8d7778;--primary:#b9283c;--primary-line:#df5363;--primary-hover:#cf354a;--on-primary:#fff;--ok:#6fcf97;--warn:#f2c94c;--err:#ff6b6b;--offline:#5a4a4b;--font-body:"DM Sans", "Segoe UI", sans-serif;--font-display:"Manrope", "Segoe UI", sans-serif;--font-mono:"IBM Plex Mono", ui-monospace, Menlo, monospace;--topbar-h:65px;--tree-w:300px;--insp-w:450px;--radius:10px;--radius-sm:6px;--ease:cubic-bezier(.2, .7, .3, 1);--secondary:#c9a87c;--muted:var(--secondary);--line:#332829;--accent:#ff8997;--surface:#1e1718;--font-title:var(--font-display);font-size:16px}*{box-sizing:border-box}body{margin:0}button,input,textarea,select{font:inherit}button{cursor:pointer}button,a,input,textarea,select{-webkit-tap-highlight-color:transparent}button{color:inherit;background:0 0;border:0;justify-content:center;align-items:center;gap:7px;display:inline-flex}button:disabled{opacity:.8;cursor:not-allowed}button:not(:disabled):hover{filter:brightness(1.13)}button:focus-visible,summary:focus-visible{outline:2px solid var(--accent);outline-offset:3px}input,textarea,select{color:inherit;background:var(--chat);border:1px solid var(--line);border-radius:7px;outline:none;min-width:0;padding:10px 12px}input::placeholder,textarea::placeholder{color:var(--fg)}textarea{resize:vertical;line-height:1.6}select{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;cursor:pointer}h1,h2,h3,p{margin:0}h1,h2,h3{font-family:var(--font-title)}h2{font-size:16px;font-weight:650}pre,code{font-family:var(--font-mono)}pre{white-space:pre-wrap;overflow-wrap:anywhere;font-size:16px;line-height:1.7}small{font-size:16px}svg{flex-shrink:0}.shell{flex-direction:column;height:100dvh;display:flex;overflow:hidden}.topbar{height:var(--topbar-h);min-height:var(--topbar-h);border-bottom:1px solid var(--line);background:var(--panel);z-index:10;justify-content:space-between;align-items:center;padding:0 26px 0 17px;display:flex}.brand,.top-actions{align-items:center;gap:14px;display:flex}.brand strong{letter-spacing:-.5px;font-size:16px;font-family:var(--font-title);font-weight:750}.brandmark{flex-shrink:0;width:45px;height:25px;margin-left:3px;display:block}.brand-separator{color:var(--fg);margin:0 2px;font-weight:400}.muted{color:var(--muted)}.icon-button{width:29px;height:29px;color:var(--muted);border-radius:5px;padding:4px}.icon-button:hover{color:var(--fg);background:#ffffff08}.primary{background:var(--accent);color:var(--fg);border:1px solid var(--accent);white-space:nowrap;border-radius:7px;padding:12px 18px;font-weight:650;box-shadow:0 1px 2px #0002}.primary.small{padding:8px 12px;font-size:16px}.secondary{background:#2b2021;border:1px solid #443738;border-radius:6px;padding:8px 12px;font-size:16px;font-weight:500}.connection{color:var(--muted);align-items:center;gap:7px;font-size:16px;display:flex}.connection i,.live-dot{background:#756062;border-radius:100%;flex-shrink:0;width:5px;height:5px;display:inline-block}.connection .online,.live-dot{background:var(--accent);box-shadow:0 0 7px #cdadb018}.version{font-family:var(--font-mono);color:var(--fg);border:1px solid #3b3031;border-radius:4px;padding:4px 6px;font-size:16px}.workspace{flex:1;grid-template-columns:minmax(340px,34%) minmax(0,1fr);min-height:0;display:grid}.inspector{border-right:1px solid var(--line);background:var(--panel);flex-direction:column;min-height:0;display:flex}.session-heading{padding:25px 26px 21px}.eyebrow{letter-spacing:1.8px;color:var(--fg);font-size:16px;font-weight:600}.session-heading h1{color:var(--fg);letter-spacing:-.7px;overflow-wrap:anywhere;justify-content:space-between;align-items:center;gap:10px;margin:0 0 10px;font-size:16px;font-weight:650;display:flex}.path{font-family:var(--font-mono);color:var(--fg);overflow-wrap:anywhere;align-items:center;gap:7px;font-size:16px;display:flex}.session-status{align-items:center;gap:9px;margin-top:19px;display:flex}.status-pill{color:var(--fg);background:#352728;border-radius:4px;align-items:center;gap:6px;padding:4px 8px;font-size:16px;line-height:1.3;display:flex}.status-pill i{background:currentColor;border-radius:50%;width:4px;height:4px}.status-pill.working{color:var(--accent);background:#412b2d}.working i{animation:1.5s infinite pulse}.saved{color:var(--fg);align-items:center;gap:5px;margin-left:auto;font-size:16px;display:flex}.background-pill{color:var(--fg);font-size:16px}.model-section{border-top:1px solid var(--line);padding:18px 26px 22px}.section-label{letter-spacing:1.3px;color:var(--fg);justify-content:space-between;margin-bottom:13px;font-size:16px;display:flex}.section-label span+span{letter-spacing:0;color:var(--fg)}.model-button{text-align:left;background:#251c1d;border:1px solid #423435;border-radius:8px;width:100%;padding:11px 13px}.model-button img,.model-list img{object-fit:contain;background:#f0e8e9;border-radius:6px;width:29px;height:29px;padding:3px}.model-button>div{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}.model-button strong{text-overflow:ellipsis;white-space:nowrap;font-size:16px;overflow:hidden}.model-button small{color:var(--muted);font-size:16px}.thinking-row{color:var(--fg);justify-content:space-between;align-items:center;margin-top:10px;font-size:16px;display:flex}.thinking-row select{color:var(--fg);background:0 0;border:0;padding:4px 2px;font-size:16px}.metrics{grid-template-columns:1fr 1.3fr .5fr;margin-top:21px;display:grid}.metrics>div{flex-direction:column;gap:5px;display:flex}.metrics span{font-family:var(--font-title);letter-spacing:-.5px;font-size:19px;font-weight:500}.metrics small{color:var(--fg);font-size:16px}.stats-section{margin-top:24px}.stats-section .metrics{margin-top:14px}.usage-breakdown{border-collapse:collapse;font-variant-numeric:tabular-nums;width:100%;margin-top:22px;font-size:16px}.usage-breakdown th,.usage-breakdown td{text-align:right;border-bottom:1px solid var(--line);padding:10px 0;font-weight:400}.usage-breakdown th{color:var(--secondary)}.usage-breakdown th:first-child{text-align:left}.usage-breakdown td{color:var(--fg)}.inspector-tabs{border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:var(--tree);padding:0 16px;display:flex}.inspector-tabs button{color:var(--fg);border-bottom:2px solid #0000;flex:1;gap:6px;padding:15px 3px 13px;font-size:16px}.inspector-tabs button.active{color:var(--accent);border-bottom-color:var(--accent)}.count{background:#462f31;border-radius:4px;padding:1px 4px;font-size:16px}.inspector-body{scrollbar-width:thin;scrollbar-color:var(--line) transparent;flex:1;padding:23px 26px 32px;overflow:auto}.panel-heading{justify-content:space-between;align-items:center;gap:9px;display:flex}.panel-heading svg{color:var(--fg)}.tag{color:var(--fg);white-space:nowrap;background:#302526;border:1px solid #403536;border-radius:4px;padding:3px 5px;font-size:16px}.tag.completed{color:var(--accent)}.tag.waiting,.tag.aborted,.tag.rejected{color:var(--fg)}.hint{color:var(--fg);margin:8px 0 18px;font-size:16px;line-height:1.65}.field-label{letter-spacing:1px;color:var(--fg);margin-bottom:8px;font-size:16px;display:block}.inline-input{background:#181112;border:1px solid #3a2d2e;border-radius:7px;align-items:center;display:flex;overflow:hidden}.inline-input input{width:100%;box-shadow:none;background:0 0;border:0;padding:10px;font-size:16px}.inline-input .icon-button{margin-right:4px}.counter-card{background:#261b1c;border:1px solid #403031;border-radius:8px;justify-content:space-between;align-items:center;margin:16px 0;padding:17px 15px;display:flex}.app-state-json{white-space:pre-wrap;overflow-wrap:anywhere;border:1px solid var(--line);background:#140e10;border-radius:8px;max-height:300px;margin:16px 0 24px;padding:16px;font-size:16px;line-height:1.6;overflow:auto}.state-field{min-width:0}.state-field:not(.state-root){border:1px solid var(--line);border-radius:8px;margin:10px 0;padding:12px}.state-field .state-field{background:#25191c40}.state-field-heading{align-items:center;gap:8px;margin-bottom:12px;display:flex}.state-field-heading strong{overflow-wrap:anywhere;flex:1;min-width:0;font-size:16px}.state-field-heading select{width:auto;max-width:120px;color:var(--secondary);padding:5px}.state-field-heading .icon-button{flex-shrink:0}.state-field textarea,.state-field input{width:100%;min-width:0;font-size:16px}.state-number{align-items:center;gap:8px;display:flex}.state-number input{text-align:center;appearance:textfield}.state-number input::-webkit-inner-spin-button{appearance:none}.state-number input::-webkit-outer-spin-button{appearance:none}.state-number button{flex-shrink:0;padding:10px}.state-boolean{align-items:center;gap:12px;display:flex}.state-boolean>span{color:var(--secondary)}.state-add{flex-wrap:wrap;gap:8px;margin-top:12px;display:flex}.state-add input{flex-basis:100%}.state-add select{flex:1;width:auto}.state-add-button{margin-top:8px}.counter-card .field-label{margin:0;font-size:16px}.counter-card strong{font-family:var(--font-title);color:var(--accent);margin-top:4px;font-size:32px;font-weight:500;line-height:1.1;display:block}.counter-card .secondary{color:var(--fg);background:#392a2b;border-color:#5a3c3f;padding:7px 9px;font-size:16px}.note{color:var(--fg);overflow-wrap:anywhere;align-items:flex-start;gap:8px;margin:0 0 10px;font-size:16px;line-height:1.6;display:flex}.note>span{background:#836669;border-radius:50%;flex-shrink:0;width:4px;height:4px;margin-top:7px}.notes{margin-bottom:14px}.raw{border-top:1px solid var(--line);margin-top:16px;padding-top:12px}.raw summary{cursor:pointer;color:var(--fg);font-family:var(--font-mono);align-items:center;gap:7px;font-size:16px;list-style:none;display:flex}.raw summary:after{content:"+";color:var(--fg);margin-left:auto}.raw[open] summary:after{content:"−"}.raw summary span{color:var(--fg);margin-left:auto;font-size:16px}.raw pre{background:var(--chat);color:var(--fg);border:1px solid #35292a;border-radius:6px;max-height:340px;padding:11px;overflow:auto}.raw textarea{width:100%;font-size:16px}.raw button{margin-top:8px}.section-divider{border-top:1px solid var(--line);margin:25px 0 22px}.demo-action{text-align:left;border-bottom:1px solid #362829;align-items:center;gap:11px;width:100%;padding:12px 0;display:flex}.demo-action>span:nth-child(2){flex-direction:column;flex:1;gap:4px;display:flex}.demo-action strong{font-size:16px;font-weight:500}.demo-action small{color:var(--fg);font-size:16px}.demo-action>svg{color:var(--fg)}.demo-icon{width:32px;height:32px;color:var(--accent);background:#3b292b;border-radius:7px;justify-content:center;align-items:center;display:flex}.demo-icon.lavender{color:var(--fg);background:#3b292b}.job-card{background:#26191a;border:1px solid #453536;border-radius:7px;margin-top:16px;padding:13px}.job-title{justify-content:space-between;align-items:center;gap:5px;display:flex}.job-title strong{font-size:16px;font-weight:500}.progress{background:#403031;border-radius:4px;height:3px;margin:14px 0 8px;overflow:hidden}.progress>div{background:var(--accent);height:100%;transition:width .3s}.job-meta{font-family:var(--font-mono);color:var(--fg);justify-content:space-between;gap:6px;font-size:16px;display:flex}.approval{flex-wrap:wrap;gap:7px;margin-top:15px;display:flex}.approval>span{width:100%;color:var(--fg);margin-bottom:3px;font-size:16px}.approval button{padding:6px 10px;font-size:16px}.text-button{color:var(--accent);margin-top:12px;padding:0;font-size:16px}.danger{color:var(--fg)}.inspector-footer{height:39px;min-height:39px;color:var(--fg);border-top:1px solid #372728;align-items:center;gap:8px;padding:0 22px;font-size:16px;display:flex}.inspector-footer .icon-button{margin-left:auto}.chat-panel{background:var(--chat);flex-direction:column;min-height:0;display:flex;position:relative}.agent-stream-status{border-bottom:1px solid var(--warn);color:var(--warn);flex-wrap:wrap;align-items:center;gap:12px;padding:12px 24px;display:flex}.agent-stream-status>div{overflow-wrap:anywhere;flex:220px;min-width:0}.agent-stream-status p{margin:4px 0 0;font-size:13px}.chat-header{border-bottom:1px solid var(--line);background:#1c1415;justify-content:space-between;align-items:center;min-height:63px;padding:0 25px;display:flex}.conversation-select{color:var(--fg);align-items:center;gap:9px;min-width:0;display:flex}.conversation-select select{box-shadow:none;color:var(--fg);background:0 0;border:0;max-width:230px;padding:8px 3px;font-size:16px}.fork-label{white-space:nowrap;color:var(--fg);align-items:center;gap:3px;font-size:16px;display:flex}.chat-header-actions{align-items:center;gap:8px;display:flex}.relative{position:relative}.dropdown{z-index:20;background:var(--line-soft);border:1px solid #4b3b3c;border-radius:8px;min-width:205px;padding:6px;position:absolute;top:36px;right:0;box-shadow:0 10px 35px #0005}.dropdown button{width:100%;color:var(--fg);border-radius:5px;justify-content:flex-start;padding:10px 9px;font-size:16px;display:flex}.dropdown button:hover{background:#3c2d2e}.chat-scroll{scrollbar-width:thin;scrollbar-color:var(--line) transparent;scroll-behavior:smooth;flex:1;padding:32px clamp(24px,5vw,88px) 20px;overflow:auto}.chat-empty{text-align:center;flex-direction:column;justify-content:center;align-items:center;min-height:100%;padding:30px 0 48px;display:flex}.agent-orb{background:radial-gradient(at top,#492d2f,#281a1b);border:1px solid #503a3c;border-radius:17px;justify-content:center;align-items:center;width:58px;height:58px;margin-bottom:26px;display:flex;position:relative;box-shadow:0 10px 50px #b07d820c}.agent-orb>img{width:45px;height:25px}.agent-orb>i{border:3px solid var(--chat);background:var(--accent);border-radius:50%;width:11px;height:11px;position:absolute;bottom:-1px;right:-2px}.chat-empty .eyebrow{letter-spacing:2.1px;font-size:16px}.chat-empty h2{letter-spacing:-.8px;margin:11px 0;font-size:27px;font-weight:500}.chat-empty p{color:var(--fg);font-size:16px;line-height:1.7}.starter-grid{grid-template-columns:1fr 1fr;gap:13px;width:100%;max-width:470px;margin-top:34px;display:grid}.starter-grid button{text-align:left;background:var(--tree);border:1px solid #3c2c2d;border-radius:8px;flex-direction:column;align-items:flex-start;gap:6px;padding:18px;display:flex;position:relative}.starter-grid button>svg:first-child{color:var(--fg);margin-bottom:13px}.starter-grid strong{font-size:16px;font-weight:500}.starter-grid span{color:var(--fg);font-size:16px}.starter-grid button>svg:last-child{color:var(--fg);position:absolute;top:16px;right:13px}.composer-region{background:linear-gradient(transparent, var(--chat) 15%);padding:18px clamp(20px,3vw,46px) 16px}.composer{background:#281c1d;border:1px solid #513d3f;border-radius:11px;box-shadow:0 6px 30px #0002}.composer textarea{resize:none;width:100%;min-height:80px;max-height:220px;box-shadow:none;background:0 0;border:0;padding:18px 20px 9px;font-size:16px;display:block}.composer-toolbar{justify-content:space-between;align-items:center;gap:7px;padding:9px 11px 12px 17px;display:flex}.composer-left,.composer-right{align-items:center;gap:12px;display:flex}.context-indicator{color:var(--fg);align-items:center;gap:5px;font-size:16px;display:flex}.composer-left select{color:var(--fg);background:0 0;border:0;padding:4px;font-size:16px}.interrupt{color:var(--fg);background:#452b2d24;border:1px solid #66414460;border-radius:5px;padding:6px 8px;font-size:16px}.send{background:var(--accent);width:33px;height:33px;color:var(--fg);border-radius:7px}.composer-footnote{color:var(--fg);justify-content:space-between;align-items:center;gap:12px;margin-top:11px;font-size:16px;display:flex}.composer-footnote>span:first-child{align-items:center;gap:6px;display:flex}.composer-footnote .live-dot{width:4px;height:4px}.entry{margin-bottom:26px;position:relative}.message-label{color:var(--fg);letter-spacing:1.3px;align-items:center;gap:8px;margin-bottom:10px;font-size:16px;display:flex}.message-label>span:not(.mini-pi):not(.streaming){font-family:var(--font-mono);letter-spacing:0;color:var(--fg);font-size:16px}.user-message{white-space:pre-wrap;color:var(--fg);font-size:16px;line-height:1.8}.pi-user{border-bottom:1px solid #392628;padding-bottom:20px}.mini-pi{flex-shrink:0;width:36px;height:20px}.markdown{color:var(--fg);overflow-wrap:anywhere;font-size:16px;line-height:1.85}.markdown p{margin:0 0 14px}.markdown p:last-child{margin-bottom:0}.markdown h1,.markdown h2,.markdown h3{color:var(--fg);margin:22px 0 12px;font-size:16px}.markdown ul,.markdown ol{margin:12px 0;padding-left:23px}.markdown li{margin:6px 0}.markdown strong{color:var(--fg);font-weight:600}.markdown code{color:var(--fg);background:#3a2628;border-radius:4px;padding:2px 5px;font-size:16px}.markdown pre{white-space:pre;background:#251819;border:1px solid #3d2b2d;border-radius:7px;margin:14px 0;padding:16px;overflow:auto}.markdown pre code{background:0 0;padding:0}.markdown a{color:var(--accent)}.markdown table{border-collapse:collapse;width:100%}.markdown td,.markdown th{border:1px solid var(--line);text-align:left;padding:8px}.fork-button{color:var(--fg);letter-spacing:0;opacity:1;white-space:nowrap;margin-left:auto;padding:3px 5px;font-size:16px;display:inline-flex}.entry:hover .fork-button,.fork-button:focus-visible{opacity:1}.event-line{color:var(--fg);align-items:center;gap:7px;padding:8px 0;font-size:16px;display:flex}.event-line>span{flex:1}.pi-tool-result{margin-top:-17px;margin-bottom:20px}.tool-call,.tool-result{color:var(--fg);background:#251819;border:1px solid #453032;border-radius:6px;margin:10px 0;font-size:16px;overflow:hidden}.tool-call summary,.tool-result summary{cursor:pointer;align-items:center;gap:9px;padding:10px 12px;list-style:none;display:flex}.tool-call summary:after,.tool-result summary:after{content:"⌄";color:var(--fg);margin-left:auto}.tool-call summary code{white-space:nowrap;text-overflow:ellipsis;color:var(--fg);font-size:16px;overflow:hidden}.tool-call pre,.tool-result pre{color:var(--fg);border-top:1px solid #412b2d;max-height:340px;margin:0;padding:11px;overflow:auto}.tool-result{background:#201415;border-color:#3b2b2c}.tool-result summary>span{color:var(--fg);font-size:16px}.tool-result.failed{color:var(--fg);border-color:#673f43}.tool-call.failed{border-color:#a44c58}.tool-status{color:var(--secondary);margin-left:auto}.tool-section-label{color:var(--secondary);border-top:1px solid #412b2d;align-items:center;gap:12px;padding:10px 12px;display:flex}.tool-section-label .fork-button{margin-left:auto}.thinking{color:var(--fg);margin:8px 0 16px;font-size:16px}.thinking summary{cursor:pointer}.thinking div{white-space:pre-wrap;color:var(--fg);border-left:1px solid #5a3a3d;margin-top:12px;padding-left:12px;font-size:16px;line-height:1.8}.message-error{color:var(--fg);overflow-wrap:anywhere;background:#39232550;border:1px solid #6b4245;border-radius:6px;margin-top:10px;padding:10px;font-size:16px;line-height:1.7}.streaming{letter-spacing:0;color:var(--accent);margin-left:auto;font-size:16px}.typing{gap:5px;padding:12px 0;display:flex}.typing i{background:#af7c81;border-radius:50%;width:5px;height:5px;animation:1.2s infinite pulse}.typing i:nth-child(2){animation-delay:.2s}.typing i:nth-child(3){animation-delay:.4s}.live-tool{background:#2c1d1e;border:1px solid #624346;border-radius:6px;margin:10px 0;padding:11px}.live-tool>div{color:var(--fg);align-items:center;gap:8px;font-size:16px;display:flex}.live-tool>div>span{color:var(--fg);margin-left:auto;font-size:16px}.live-tool pre{max-height:150px;color:var(--fg);overflow:auto}.queue{background:#2e1f20;border:1px solid #4a3537;border-radius:7px;margin-bottom:10px;padding:5px 10px}.queue>div{color:var(--fg);align-items:center;gap:7px;font-size:16px;display:flex}.queue span{white-space:nowrap;text-overflow:ellipsis;flex:1;overflow:hidden}.history-banner{color:var(--fg);background:#33292a33;align-items:center;gap:7px;padding:8px 26px;font-size:16px;display:flex}.empty-panel{color:var(--fg);flex-direction:column;align-items:center;gap:12px;padding:30px 0;font-size:16px;display:flex}.empty-panel strong{color:var(--fg);font-weight:500}.task-card{background:#2a1b1c;border:1px solid #4d3537;border-radius:7px;margin:10px 0;padding:13px}.task-card.child{border-left:2px solid #84595d;margin-left:14px}.task-card>div:first-child{justify-content:space-between;align-items:center;gap:6px;display:flex}.task-card strong{font-family:var(--font-mono);overflow-wrap:anywhere;font-size:16px;font-weight:400}.task-card p{color:var(--fg);margin:8px 0 11px;font-size:16px}.hook-card{background:#2a2525;border:1px solid #483c3d;border-radius:7px;margin-bottom:20px;padding:14px}.hook-card>div{color:var(--fg);align-items:center;gap:8px;display:flex}.hook-card strong{font-size:16px;font-weight:500}.hook-card p{color:var(--fg);margin-top:10px;font-size:16px;line-height:1.6}.switch{background:#544b4c;border-radius:12px;justify-content:flex-start;width:29px;height:17px;margin-left:auto;padding:2px}.switch>span{background:#dbcccd;border-radius:50%;width:13px;height:13px}.switch.on{background:var(--primary);justify-content:flex-end}.tool-row{border-bottom:1px solid #3a2a2b;padding:12px 0}.tool-row summary{cursor:pointer;color:var(--fg);align-items:center;gap:7px;list-style:none;display:flex}.tool-row strong{font-family:var(--font-mono);font-size:16px;font-weight:500}.tool-row .tag{margin-left:auto;font-size:16px}.tool-row p{color:var(--fg);white-space:pre-wrap;margin:12px 0;font-size:16px;line-height:1.75}.tool-row small{color:var(--fg);line-height:1.6}.tool-signature{border:1px solid var(--line);font-family:var(--font-mono);white-space:pre-wrap;overflow-wrap:anywhere;color:var(--fg);background:#120d0e;border-radius:8px;margin:0 0 12px;padding:12px 14px;font-size:14px;line-height:1.6}.tk-keyword{color:var(--accent)}.tk-function{color:#ffd38a}.tk-property{color:#9ed8cf}.tk-type{color:#8fb6ff}.tk-string{color:#e6b98f}.tk-number{color:#d4a5ff}.tk-comment{color:var(--faint);font-style:italic}.tk-punct{color:#b8a6a7}.prompt-chip{width:100%;color:var(--fg);text-align:left;border-bottom:1px solid var(--line);justify-content:space-between;padding:14px 0;font-size:16px;display:flex}.drawer-backdrop{z-index:40;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);background:#0007;position:fixed;inset:65px 0 0}.sessions-drawer{background:var(--card);border-right:1px solid #513d3f;flex-direction:column;width:326px;max-width:90vw;height:100%;padding:24px 18px;display:flex;box-shadow:20px 0 70px #0004}.sessions-drawer header{justify-content:space-between;align-items:center;margin-bottom:22px;padding:0 7px;display:flex}.sessions-drawer h2{font-size:17px;font-weight:550}.sessions-drawer h2 span{color:var(--fg);margin-left:6px;font-size:16px}.sessions-drawer>.primary{margin:0 6px 22px}.session-list{flex:1;overflow:auto}.session-item{text-align:left;border:1px solid #0000;border-radius:7px;flex-direction:column;align-items:stretch;gap:10px;width:100%;margin-bottom:7px;padding:15px;display:flex}.session-item.active{background:#362527;border-color:#5e3e41}.session-item:hover{background:#312324}.session-item strong{justify-content:space-between;align-items:center;font-size:16px;font-weight:550;display:flex}.session-item .path{font-size:16px}.session-model{color:var(--fg);overflow-wrap:anywhere;align-items:center;gap:6px;font-size:16px;display:flex}.session-model img{background:#ecdfe0;border-radius:3px;width:15px;height:15px;padding:1px}.active-dot{background:var(--accent);border-radius:50%;width:5px;height:5px}.sessions-drawer footer{color:var(--fg);align-items:center;gap:8px;padding:18px 8px 0;font-size:16px;display:flex}.modal-backdrop{z-index:80;-webkit-backdrop-filter:blur(7px);backdrop-filter:blur(7px);background:#0d0808bd;justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;inset:0}.modal{background:var(--panel);border:1px solid var(--line);border-radius:12px;width:460px;max-width:100%;max-height:90dvh;padding:28px;overflow:auto;box-shadow:0 24px 70px #0000008c}.modal header{justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:27px;display:flex}.modal header h2{letter-spacing:-.5px;margin-top:7px;font-size:22px;font-weight:550}.modal label{color:var(--fg);flex-direction:column;gap:9px;margin-top:20px;font-size:16px;display:flex}.modal input,.modal select{width:100%;padding:12px;font-size:16px}.modal small.path{color:var(--fg);margin-top:-1px;font-size:16px;line-height:1.6}.modal footer{justify-content:flex-end;gap:10px;margin-top:26px;display:flex}.model-modal{flex-direction:column;width:500px;display:flex;overflow:hidden}.login-veil{z-index:100;-webkit-backdrop-filter:blur(7px);backdrop-filter:blur(7px);background:#0d0808e0;justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;inset:0}.login-card{width:400px}.login-card .hint{color:var(--fg);font-size:15px;line-height:1.55}.login-card footer{justify-content:flex-end}.model-list{max-height:50vh;margin-top:12px;overflow:auto}.model-list button{text-align:left;border-radius:6px;justify-content:flex-start;gap:12px;width:100%;padding:12px 10px;display:flex}.model-list button.selected,.model-list button:hover{background:#402b2d}.model-list button>div{flex-direction:column;flex:1;gap:5px;display:flex}.model-list strong{font-size:16px;font-weight:500}.model-list small{color:var(--fg);font-size:16px}.model-modal .hint{margin:14px 0 0}.learning-list{flex-direction:column;gap:23px;padding:0;list-style:none;display:flex}.learning-list li{gap:17px;display:flex}.learning-list li>span{font-family:var(--font-mono);color:var(--fg);border:1px solid #5a383b;border-radius:5px;flex-shrink:0;justify-content:center;align-items:center;width:28px;height:27px;font-size:16px;display:flex}.learning-list strong{color:var(--fg);font-size:16px;font-weight:500}.learning-list p{color:var(--fg);margin-top:5px;font-size:16px;line-height:1.8}.help-modal{width:530px}.toast{z-index:100;background:var(--card);color:var(--on-primary);border:1px solid var(--line);border-radius:999px;align-items:center;gap:10px;max-width:90%;padding:13px 19px;font-size:16px;font-weight:600;line-height:1.5;display:flex;position:fixed;bottom:28px;left:50%;transform:translate(-50%);box-shadow:0 10px 30px #00000073}.toast svg{color:var(--accent);flex-shrink:0}.pi-user .message-label{justify-content:flex-end}.pi-user .user-message{text-align:right}.state-json-actions{flex-wrap:wrap;justify-content:flex-end;gap:10px;margin-bottom:20px;display:flex}.state-json-actions .hint{flex-basis:100%;margin:0}textarea.app-state-json{resize:vertical;width:100%;min-height:280px;max-height:none;font-family:var(--font-mono);color:var(--fg);margin-bottom:10px}.toast-enter-active,.toast-leave-active{transition:opacity .2s}.toast-enter-from,.toast-leave-to{opacity:0}.error-banner{color:var(--fg);z-index:90;background:#462b2d;align-items:center;gap:10px;padding:10px 25px;font-size:16px;display:flex}.error-banner span{flex:1}.welcome{text-align:center;background:radial-gradient(#39232533,#0000 65%);flex-direction:column;flex:1;justify-content:center;align-items:center;padding:35px;display:flex}.welcome-symbol{width:126px;height:70px;margin-bottom:33px;position:relative}.welcome .eyebrow{color:var(--fg);letter-spacing:2.6px;font-size:16px}.welcome h1{letter-spacing:-2.5px;color:var(--fg);margin:20px 0;font-size:clamp(36px,4.6vw,64px);font-weight:500;line-height:1.15}.welcome p{color:var(--fg);margin:4px 0 30px;font-size:16px}.welcome-features{color:var(--fg);gap:33px;margin-top:70px;font-size:16px;display:flex}.welcome-features>span{align-items:center;gap:8px;display:flex}.selected{color:var(--accent)}@keyframes pulse{0%,to{opacity:.45}50%{opacity:1}}@media (width>=1600px){.workspace{grid-template-columns:440px minmax(0,1fr)}.chat-scroll{padding-left:max(70px,50% - 385px);padding-right:max(70px,50% - 385px)}.composer-region{padding-left:max(46px,50% - 415px);padding-right:max(46px,50% - 415px)}}@media (width<=1050px){.workspace{grid-template-columns:330px minmax(0,1fr)}.session-heading,.model-section,.inspector-body{padding-left:20px;padding-right:20px}.chat-empty h2{font-size:23px}.composer-footnote>span:last-child{display:none}.starter-grid{grid-template-columns:1fr;max-width:300px}.starter-grid button{padding:13px}.starter-grid button>svg:first-child{margin-bottom:3px}.topbar{padding-right:16px}}@media (width<=740px){.shell{height:auto;min-height:100dvh;overflow:visible}.topbar{height:58px;min-height:58px;padding:0 12px;position:sticky;top:0}.brand{gap:8px}.brand strong{font-size:16px}.brand-separator,.brand>.muted,.version,.connection{display:none}.top-actions{gap:5px}.workspace{flex-direction:column;display:flex}.inspector{border-right:0;border-bottom:1px solid var(--line);min-height:310px;max-height:55vh}.session-heading{padding:17px 20px 10px}.session-heading h1{margin:5px 0;font-size:19px}.session-heading>.eyebrow,.session-status,.model-section,.inspector-footer{display:none}.inspector-tabs{padding:0 13px}.inspector-tabs button{padding:11px 3px}.inspector-body{min-height:150px;padding:17px 20px}.chat-panel{height:85dvh;min-height:500px}.chat-header{min-height:55px;padding:0 13px}.chat-scroll{padding:24px 22px}.chat-empty h2{font-size:22px}.composer-region{padding:12px}.composer-left{gap:3px}.composer-left .context-indicator{display:none}.composer-right{gap:8px}.modal{padding:22px}.welcome{min-height:90dvh}.welcome-features{flex-direction:column;align-items:center;gap:20px;margin-top:40px}.drawer-backdrop{top:58px}.toast{width:max-content;max-width:90%;font-size:16px;bottom:15px}.fork-label{display:none}}@media (prefers-reduced-motion:reduce){*{scroll-behavior:auto!important;transition:none!important;animation:none!important}}@media (width<=740px){.model-section{padding:9px 20px;display:block}.model-section .section-label,.model-section .thinking-row,.model-section .metrics{display:none}.model-button{padding:7px 10px}.model-button img{width:24px;height:24px}.model-button small{display:none}}.primary,.send{background:var(--primary);border-color:var(--primary-line);color:#fff}.primary:hover,.send:hover{background:var(--primary-hover)}.model-button img,.model-list img{background:#fff;border:1px solid #67575c;flex-shrink:0;width:42px;height:42px;padding:5px}.session-model img{background:#fff;flex-shrink:0;width:32px;height:32px;padding:3px}img[src$=openai\.png]{background:#242024;border-color:#81747a;padding:3px}button:disabled{opacity:1;color:#d4c7ca;background-color:#33272b;border-color:#554249}.icon-button{width:36px;height:36px;color:var(--fg)}.inspector-tabs{padding:0 10px}.inspector-tabs button{min-width:0;padding:15px 7px 13px}.session-heading h1{line-height:1.4}.session-status,.section-label,.panel-heading,.job-title,.job-meta,.composer-footnote,.composer-toolbar{flex-wrap:wrap}.metrics{grid-template-columns:1fr 1.4fr .6fr;gap:12px}.metrics small{line-height:1.5}.model-button{min-height:70px}.model-button small{line-height:1.5}.model-button strong{white-space:normal}.inspector-footer{height:auto;min-height:52px;padding:8px 20px}.counter-card{flex-wrap:wrap;gap:12px}.counter-card .field-label{max-width:180px;line-height:1.5}.raw summary{flex-wrap:wrap;line-height:1.6}.raw summary span{color:var(--fg)}.tool-row summary{flex-wrap:wrap}.tool-row .tag{margin-left:auto}.tool-call summary{flex-wrap:wrap}.tool-call summary code{max-width:100%}.fork-button{opacity:1;color:#ffd3da}.session-item .path{line-height:1.6}.sessions-drawer{width:420px}.modal{width:560px}.model-modal{width:650px}.model-list button{min-height:78px}.model-list small{line-height:1.5}.task-card>div:first-child{flex-wrap:wrap}.composer-footnote{line-height:1.6}.composer-left,.composer-right{flex-wrap:wrap;gap:8px}.send{width:40px;height:40px}.interrupt{min-height:40px}.tag{line-height:1.4}.brand{gap:10px}.welcome-features{flex-wrap:wrap;justify-content:center}@media (width>=741px) and (width<=1599px){.workspace{grid-template-columns:minmax(410px,36%) minmax(0,1fr)}.chat-scroll{padding-left:30px;padding-right:30px}.composer-footnote>span:last-child{display:none}.chat-header{flex-wrap:wrap;gap:10px;padding:10px 18px}}@media (width<=1100px) and (width>=741px){.brand>.muted,.brand-separator,.version{display:none}.starter-grid{grid-template-columns:1fr}.composer-left .context-indicator{display:none}.conversation-select select{max-width:205px}}@media (width<=740px){.inspector{max-height:60vh}.topbar{height:68px;min-height:68px}.top-actions .icon-button{display:none}.brand strong{font-size:16px}.model-button img{width:40px;height:40px}.model-button small{display:block}.model-button{min-height:64px}.inspector-tabs{padding:0 4px}.inspector-tabs button{gap:4px;padding:12px 4px}.inspector-body{padding:18px 16px}.conversation-select{gap:6px;max-width:calc(100% - 94px)}.conversation-select select{width:100%;max-width:180px}.chat-header-actions{gap:0}.chat-header-actions .icon-button{width:30px}.chat-header{padding:0 10px}.drawer-backdrop{top:68px}.composer-toolbar{padding-left:9px}.composer-left select{max-width:120px;padding-left:0}.composer-footnote{align-items:flex-start}.composer-footnote>span:first-child{align-items:baseline}.starter-grid strong,.starter-grid span{line-height:1.5}.chat-empty{padding:24px 0}.chat-panel{min-height:760px}.modal{padding:20px}.top-actions .primary{padding:8px}}.session-heading .cwd-button{text-align:left;width:100%;min-width:0;display:flex}.cwd-button:hover{color:var(--fg)}.cwd-button svg{flex-shrink:0}.cwd-trail{white-space:nowrap;text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.full-directory{white-space:pre-wrap;overflow-wrap:anywhere;-webkit-user-select:text;user-select:text;font-size:16px;line-height:1.6;display:block}.modal.path-modal{width:max-content;min-width:min(960px,100%)}.markdown :is(h4,h5,h6,small,sub,sup){font-size:16px}.inspector>.inspector-tabs{border-top:0;flex-shrink:0;min-height:74px;padding:0 8px}.inspector>.inspector-tabs button{flex-direction:column;gap:5px;padding:10px 4px;line-height:1.4;position:relative}.inspector-tabs .count{position:absolute;top:4px;right:4px}.inspector-body.session-panel{padding:0 0 24px}.session-panel .session-heading{padding:24px 26px}.session-panel .model-section{padding:22px 26px}@media (width<=740px){.inspector>.inspector-tabs{padding:0 4px}.session-panel .session-heading,.session-panel .model-section{padding:20px 16px}.session-panel .session-heading>.eyebrow{display:block}.session-panel .session-status,.session-panel .section-label,.session-panel .thinking-row{display:flex}.session-panel .metrics{display:grid}}.hint,.path,.eyebrow,.section-label,.section-label span+span,.field-label,.counter-card .field-label,.model-button small,.model-list small,.metrics small,.thinking-row>span,.saved,.job-meta,.demo-action small,.task-card p,.tool-row p,.tool-row small,.tool-call summary code,.tool-result summary>span,.thinking,.thinking div,.raw summary,.raw summary span,.message-label>span:not(.mini-pi):not(.streaming),.composer-footnote,.context-indicator,.composer-left select,.version,.session-model,.sessions-drawer footer,.inspector-footer,.starter-grid span,.chat-empty p,.welcome p,.welcome-features,.learning-list p{color:var(--secondary)}input::placeholder,textarea::placeholder{color:var(--secondary);opacity:1}.chat-header{flex-wrap:nowrap;gap:14px}.chat-header-actions{flex-shrink:0}.lineage-picker{flex:1;min-width:0;padding:8px 0;position:relative}.lineage-toolbar{align-items:center;gap:4px;min-width:0;display:flex}.conversation-lineage{scrollbar-width:thin;scrollbar-color:var(--line) transparent;align-items:center;gap:4px;min-width:0;display:flex;overflow-x:auto}.lineage-crumb{color:var(--secondary);white-space:nowrap;border-radius:6px;flex-shrink:0;padding:7px 9px;font-size:16px}.lineage-crumb:hover{background:#342328}.lineage-crumb.current{color:var(--accent);background:#392328}.lineage-separator{color:var(--secondary)}.conversation-menu-toggle{flex-shrink:0}.lineage-source{color:var(--secondary);margin:4px 9px 0;font-size:16px;line-height:1.5}.conversation-menu-dismiss{z-index:25;cursor:default;position:fixed;inset:0}.conversation-picker{z-index:30;background:#251b1e;border:1px solid #68474e;border-radius:9px;width:min(540px,100vw - 48px);max-height:min(65vh,620px);padding:8px;position:absolute;top:100%;left:0;overflow-y:auto;box-shadow:0 16px 48px #0007}.conversation-picker-heading{color:var(--secondary);padding:10px 12px 14px;font-size:16px}.conversation-choice{text-align:left;border-radius:6px;justify-content:space-between;align-items:center;gap:14px;width:100%;padding:12px;display:flex}.conversation-choice:hover,.conversation-choice.selected{background:#3b272d}.conversation-choice-content{flex-direction:column;gap:6px;min-width:0;display:flex}.choice-lineage{color:var(--fg);flex-wrap:wrap;align-items:center;gap:5px;font-size:16px;line-height:1.5;display:flex}.choice-lineage>span{white-space:nowrap}.choice-lineage .choice-ancestor,.choice-lineage>svg,.choice-source{color:var(--secondary)}.choice-source{font-size:16px;line-height:1.5}.conversation-choice.selected .choice-lineage>span:last-child{color:var(--accent)}@media (width<=740px){.chat-header{flex-wrap:wrap;gap:4px;padding:8px 10px}.lineage-picker{flex-basis:100%;width:100%}.chat-header-actions{margin-left:auto}.conversation-picker{width:min(540px,100vw - 20px)}.lineage-crumb{padding:7px}}.queue-mode{min-width:150px;position:relative}.composer-left .queue-mode select{appearance:none;color:#f8eeee;cursor:pointer;background:#342329;border:1px solid #77515a;border-radius:8px;width:100%;max-width:none;min-height:40px;padding:7px 36px 7px 12px;font-size:16px;font-weight:600}.queue-mode>svg{pointer-events:none;color:var(--secondary);position:absolute;top:50%;right:10px;transform:translateY(-50%)}.interrupt .stop-sign{color:#ff647a;stroke:#ffb5c0;flex-shrink:0}.switch{border-radius:20px;flex-shrink:0;width:58px;height:34px;padding:4px}.switch>span{width:26px;height:26px}.state-boolean .switch{margin-left:0}.task-section{border-top:1px solid var(--line);margin-top:24px;padding-top:20px}.task-section h3,.task-example h4{align-items:center;gap:8px;margin:0 0 10px;font-size:16px;font-weight:650;display:flex}.task-example{border:1px solid var(--line);background:#25191c;border-radius:8px;margin-top:12px;padding:16px}.task-example p,.task-explanation p,.task-empty{color:var(--secondary);margin:8px 0 14px;font-size:16px;line-height:1.6}.task-decision-buttons{flex-wrap:wrap;gap:8px;margin:16px 0;display:flex}.approval-card{border-color:#c68957}.tasks-panel .task-note{margin-bottom:0}.tasks-panel .task-card .raw{margin-top:12px}.chat-header-actions{flex-wrap:wrap;justify-content:flex-end;gap:8px;display:flex}.chat-header{flex-wrap:wrap}.chat-header-actions .secondary{min-height:38px}@media (width<=740px){.topbar{flex-wrap:wrap;gap:12px;height:auto;padding:12px 16px}.top-actions{flex-wrap:wrap;gap:8px;margin-left:auto}.chat-header-actions{justify-content:flex-start;width:100%}}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--line);background-clip:padding-box;border:2px solid #0000;border-radius:10px}::-webkit-scrollbar-thumb:hover{background:var(--faint);background-clip:padding-box}.label{font-family:var(--font-display);letter-spacing:.14em;text-transform:uppercase;color:var(--faint);font-size:14px;font-weight:700}.topbar-sep{background:var(--line);flex-shrink:0;width:1px;height:22px}.daemon{color:var(--faint);flex-wrap:wrap;align-items:center;gap:8px;min-width:0;font-size:15px;display:flex}.daemon b{color:var(--fg);font-weight:500;font-family:var(--font-mono)}.daemon .sep{color:var(--offline);flex-shrink:0}.dot{background:var(--ok);width:8px;height:8px;box-shadow:0 0 0 3px color-mix(in oklab, var(--ok) 16%, transparent);border-radius:50%;flex:0 0 8px;display:inline-block}.dot.off{background:var(--offline);box-shadow:none}.chip{border:1px solid var(--line);height:28px;font-family:var(--font-mono);color:var(--faint);background:var(--bg);white-space:nowrap;border-radius:999px;align-items:center;gap:6px;padding:0 12px;font-size:13px;display:inline-flex}.chip b{color:var(--fg);font-weight:500}.chip.accent{border-color:color-mix(in oklab, var(--accent) 40%, var(--line));color:var(--accent)}.chip .dot{width:7px;height:7px;box-shadow:none;flex:0 0 7px}.secondary{border:1px solid var(--line);background:var(--card);transition:background .12s var(--ease), border-color .12s var(--ease)}.secondary:not(:disabled):hover{border-color:var(--faint)}.scrim{z-index:80;background:#0a0607ad;place-items:center;padding:20px;display:grid;position:fixed;inset:0}.dialog{border:1px solid var(--line);background:var(--panel);border-radius:12px;width:min(560px,100%);max-height:calc(100dvh - 40px);overflow-y:auto;box-shadow:0 24px 70px #0000008c}.dialog-head{justify-content:space-between;align-items:flex-start;gap:12px;padding:18px 20px 0;display:flex}.dialog-eyebrow{font-family:var(--font-display);letter-spacing:.14em;text-transform:uppercase;color:var(--accent);font-size:14px;font-weight:700}.dialog h3{font-family:var(--font-display);letter-spacing:-.01em;margin:5px 0 0;font-size:20px;font-weight:700}.dialog-body{flex-direction:column;gap:12px;padding:16px 20px;display:flex}.help-step{border-bottom:1px solid var(--line-soft);grid-template-columns:26px minmax(0,1fr);gap:10px;padding:7px 0;font-size:16px;display:grid}.help-step:last-of-type{border-bottom:0}.help-step .n{font-family:var(--font-mono);color:var(--accent)}.help-step b{font-weight:600}.help-step .body{color:var(--muted);margin-top:2px;line-height:1.6}.help-callout{border-radius:var(--radius-sm);border:1px solid var(--line);background:var(--chat);color:var(--muted);align-items:flex-start;gap:10px;margin-top:4px;padding:10px 12px;font-size:16px;display:flex}.help-callout svg{flex-shrink:0;margin-top:2px}.dialog-foot{align-items:center;gap:8px;padding:0 20px 18px;display:flex}.dialog-foot .right{gap:8px;margin-left:auto;display:flex}.mnav{display:none}@media (width<=760px){.daemon,.topbar-sep{display:none}.mnav{padding:4px 6px calc(4px + env(safe-area-inset-bottom));border-top:1px solid var(--line);background:var(--panel);grid-template-columns:repeat(3,1fr);gap:2px;display:grid}.mnav button{min-height:48px;color:var(--faint);background:0 0;border:0;border-radius:8px;flex-direction:column;justify-content:center;align-items:center;gap:2px;font-size:12px;display:flex;position:relative}.mnav button.is-on{color:var(--accent);background:color-mix(in oklab, var(--accent) 9%, transparent)}.mnav .badge{background:var(--primary);min-width:16px;height:16px;color:var(--on-primary);font-family:var(--font-mono);border-radius:999px;padding:0 4px;font-size:11px;line-height:16px;position:absolute;top:5px;right:calc(50% - 22px)}}.composer:focus-within{border-color:color-mix(in oklab, var(--accent) 55%, var(--line));box-shadow:0 0 0 3px color-mix(in oklab, var(--accent) 10%, transparent)}.send{border:1px solid var(--primary-line);transition:background .12s var(--ease);border-radius:8px}.pi-user{border-bottom:0;flex-direction:column;align-items:flex-end;gap:8px;padding-bottom:12px;display:flex}.pi-user .user-message{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);max-width:78%;padding:10px 14px}.inspector-tabs{background:var(--tree)}.inspector-tabs button{color:var(--muted)}.inspector-tabs button:hover{color:var(--fg)}.inspector-tabs button.active{color:var(--accent)}.insp-tab-active-line{border-bottom:2px solid var(--accent)}.switch{background:var(--offline)}.switch.on{background:var(--primary)}.switch.on>span{background:var(--on-primary)}.tool-call{background:var(--card);border-color:var(--line)}.tool-result{background:var(--chat)}.tool-result.failed,.tool-call.failed{border-color:color-mix(in oklab, var(--err) 45%, var(--line))}.metrics{border:1px solid var(--line);border-radius:var(--radius);background:var(--line);gap:1px;overflow:hidden}.metrics>div{background:var(--chat);padding:9px 12px}.metrics span{font-family:var(--font-mono);font-weight:500}.model-button{background:var(--chat);border:1px solid var(--line);border-radius:var(--radius)}.model-button:hover{border-color:var(--faint)}input,textarea,select{border-radius:var(--radius-sm)}input:focus,textarea:focus,select:focus{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in oklab, var(--accent) 10%, transparent)}.chat-panel{background:var(--chat)}.chat-header,.inspector{background:var(--panel)}.network-sidebar{background:var(--tree)}.net-workspace{--tree-w:300px;--inspector-w:450px;--rail-w:52px;flex:1;min-height:0;display:flex;position:relative}.net-workspace>.chat-panel,.net-workspace>.welcome,.net-workspace>.offline-panel{flex:auto;min-width:0}.net-workspace>.network-sidebar{width:var(--tree-w);flex:none}.net-workspace>.network-sidebar.collapsed{width:var(--rail-w)}.net-workspace>.inspector{width:var(--inspector-w);border-right:1px solid var(--line);border-left:0;flex:none;min-height:0;max-height:none}.net-workspace>.inspector.collapsed{width:var(--rail-w)}.network-summary{color:var(--muted);border:1px solid var(--line);white-space:nowrap;border-radius:999px;align-items:center;gap:6px;margin-left:6px;padding:3px 10px;font-size:15px;display:inline-flex}.tree-toggle,.inspector-toggle,.tree-backdrop,.inspector-backdrop{display:none}.panel-rail{scrollbar-width:none;flex-direction:column;align-items:center;gap:6px;height:100%;padding:10px 0;display:flex;overflow-y:auto}.panel-rail .panel-toggle{margin-bottom:6px}.rail-device,.rail-tab{width:38px;height:38px;color:var(--muted);border-radius:8px;position:relative}.rail-device:hover,.rail-tab:hover{color:var(--fg);background:#ffffff0a}.rail-tab.active{color:var(--accent);background:#ff899714}.rail-device .dot{width:8px;height:8px;box-shadow:0 0 0 2px var(--tree);flex-basis:8px;position:absolute;bottom:4px;right:4px}.rail-tab .count{background:var(--accent);color:#1a1012;border-radius:8px;min-width:16px;height:16px;padding:0 4px;font-size:11px;line-height:16px;position:absolute;top:2px;right:2px}.inspector .panel-rail{background:var(--panel)}.inspector-tabs .panel-toggle{align-self:center;margin-left:auto}.device-icon{flex:none;display:inline-block}.device-icon.exe,.device-icon.apple{color:#e9e2e2}.network-sidebar{background:var(--tree);border-right:1px solid var(--line);flex-direction:column;min-height:0;display:flex}.tree-head{color:var(--muted);letter-spacing:1.6px;justify-content:space-between;align-items:center;padding:10px 12px 10px 16px;font-size:14px;font-weight:650;display:flex}.tree-head span{align-items:center;gap:8px;display:inline-flex}.tree-list{scrollbar-width:thin;scrollbar-color:var(--line) transparent;outline:none;flex:1;padding:4px 6px 12px;overflow:auto}.tree-list:focus-visible{box-shadow:inset 0 0 0 1px #856669}.tree-empty{padding:12px 10px}.tree-row{--depth:0;min-height:34px;padding:3px 6px 3px calc(4px + var(--depth) * 16px);cursor:pointer;color:#e9e2e2;white-space:nowrap;border-radius:6px;align-items:center;gap:7px;font-size:15px;display:flex;position:relative}.tree-row:hover{background:#ffffff08}.tree-row.focus{box-shadow:inset 0 0 0 1px #6d5557}.tree-row.sel{background:#ff899714}.tree-row.sel:before{content:"";background:var(--accent);border-radius:2px;width:3px;position:absolute;top:5px;bottom:5px;left:0}.tree-row.stale{opacity:.55}.tree-row .chev{width:18px;height:18px;color:var(--muted);flex:0 0 18px;padding:0}.tree-row span.chev{display:inline-block}.tree-row .name{text-overflow:ellipsis;min-width:0;overflow:hidden}.tree-row.device .name{font-family:var(--font-mono);font-size:15px}.tree-row.session .name{font-weight:600}.tree-row .ico{color:var(--muted);flex:none}.tree-row .ico.root{color:var(--accent)}.tree-row .badge{color:var(--muted);font-size:12px;font-family:var(--font-mono);border:1px solid #443738;border-radius:4px;padding:1px 5px}.tree-row .meta,.tree-row .path{color:var(--muted);text-overflow:ellipsis;min-width:0;font-size:13px;overflow:hidden}.tree-row .path{font-family:var(--font-mono);flex:1}.tree-row .meta.err{color:#ff8a80}.tree-row .acts{background:var(--tree);border-radius:6px;gap:2px;margin-left:auto;display:none}.tree-row:hover .acts,.tree-row.focus .acts{display:inline-flex}.tree-row:hover .acts~*,.tree-row .acts .icon-button{width:26px;height:26px}.tree-row .acts .icon-button:disabled{opacity:.35;background:0 0}.tree-row .bg-count{color:var(--muted);align-items:center;gap:4px;font-size:13px;display:inline-flex}.tree-row>.dot.work,.tree-row>.bg-count{margin-left:auto}.tree-row>.dot.work+.bg-count{margin-left:6px}.tree-row:hover>.dot.work,.tree-row:hover>.bg-count,.tree-row.focus>.dot.work,.tree-row.focus>.bg-count{display:none}.dot{background:#756062;border-radius:50%;flex:0 0 9px;width:9px;height:9px;display:inline-block}.dot.on{background:var(--ok);box-shadow:0 0 6px #6fcf9766}.dot.chk{background:var(--secondary);animation:1.1s ease-in-out infinite dpi-pulse}.dot.err{background:var(--err)}.dot.off{background:var(--offline)}.dot.work{background:var(--accent);animation:1.1s ease-in-out infinite dpi-pulse}.dot.bg{border:2px solid var(--accent);background:0 0;width:9px;height:9px}@keyframes dpi-pulse{50%{opacity:.35}}.tree-resizer{cursor:col-resize;z-index:5;flex:0 0 6px;width:6px;margin:0 -3px;position:relative}.tree-resizer:hover{background:#ff899733}.crumbs{scrollbar-width:thin;scrollbar-color:var(--line) transparent;align-items:flex-end;gap:4px;min-width:0;padding:2px 0;display:flex;overflow-x:auto}.crumb{color:#e9e2e2;border-radius:8px;flex-direction:column;flex:none;align-items:flex-start;gap:2px;max-width:260px;padding:5px 10px 6px;display:inline-flex}.crumb:hover{background:#ffffff0a}.crumb.current{color:var(--accent);background:#ff899714}.crumb-kind{letter-spacing:1.2px;text-transform:uppercase;color:var(--muted);font-size:11px;line-height:1}.crumb-main{align-items:center;gap:7px;min-width:0;max-width:100%;font-size:17px;font-weight:600;line-height:1.2;display:inline-flex}.crumb-name,.crumb .device-chip{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.crumb .device-chip{font-family:var(--font-mono)}.crumb-sep{color:var(--muted);flex:none;margin-bottom:8px}.chat-header-actions .secondary.active{border-color:var(--accent)}.history-divider{color:var(--muted);letter-spacing:1px;text-transform:uppercase;align-items:center;gap:8px;margin:8px 0 18px;font-size:14px;display:flex}.history-divider:after{content:"";border-top:1px dashed #4a3b3c;flex:1}.entry.history{opacity:.6}.retry-note{margin-top:4px}.session-modal{width:1120px}.device-modal code,.session-modal code{overflow-wrap:anywhere}.modal .field{flex-direction:column;gap:9px;margin-top:20px;display:flex}.dir-browser{flex-direction:column;gap:8px;display:flex}.dir-path{gap:8px;display:flex}.dir-path input{font-family:var(--font-mono);flex:1;font-size:14px!important}.dir-list{border:1px solid var(--line);background:var(--chat);border-radius:7px;max-height:220px;padding:4px;overflow:auto}.dir-item{color:#e9e2e2;border-radius:5px;justify-content:flex-start;width:100%;padding:6px 8px;font-size:15px}.dir-item:hover{background:#ffffff0a}.dir-item[aria-selected=true]{color:#fff;background:#ff899714}.dir-item span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.device-result{overflow-wrap:anywhere;border:1px solid #544042;border-radius:8px;align-items:flex-start;gap:10px;margin-top:18px;padding:12px;display:flex}.device-result.online{border-color:#6fcf9777}.device-result:not(.online){border-color:#ff6b6b77}.primary.danger{background:#c94f5d;border-color:#c94f5d}.offline-panel .chat-empty{gap:6px;max-width:640px;margin:0 auto}.offline-panel .eyebrow{font-family:var(--font-mono);letter-spacing:.5px;color:var(--muted);overflow-wrap:anywhere}.offline-panel.unauthorized svg,.offline-panel.mismatch svg{color:var(--err)}.offline-error{font-family:var(--font-mono);overflow-wrap:anywhere;font-size:14px}.offline-command{border:1px solid var(--line);background:#0f0a0b;border-radius:8px;align-items:center;gap:8px;margin:10px 0 4px;padding:10px 14px;display:inline-flex}.offline-command code{color:#fff;font-size:17px}.offline-actions{gap:10px;margin-top:16px;display:flex}.spin{animation:1s linear infinite dpi-spin}@keyframes dpi-spin{to{transform:rotate(360deg)}}@media (width<=1100px){.inspector-toggle{display:inline-flex}.net-workspace>.inspector.overlay{z-index:30;width:min(420px,100%);position:absolute;top:0;bottom:0;left:0;box-shadow:20px 0 60px #0008}.inspector-backdrop{z-index:29;background:#0d080899;display:block;position:absolute;inset:0}}@media (width<=760px){.tree-resizer{display:none}.tree-toggle{display:inline-flex}.net-workspace>.network-sidebar{display:none}.net-workspace>.network-sidebar.open{z-index:40;width:min(340px,90vw);display:flex;position:absolute;top:0;bottom:0;left:0;box-shadow:20px 0 60px #0008}.tree-backdrop{z-index:39;background:#0d080899;display:block;position:absolute;inset:0}.network-summary,.new-agent-button{display:none!important}.shell{height:100dvh;overflow:hidden}.net-workspace .chat-panel{height:auto;min-height:0}.net-workspace>.inspector .session-status,.net-workspace>.inspector .model-section{display:block}.top-actions .inspector-toggle{display:inline-flex}.crumb-kind{display:none}}.net-workspace .lineage-picker{flex:240px}.net-workspace .conversation-lineage{flex:0 auto}.composer{position:relative}.slash-menu{background:var(--card);z-index:20;border:1px solid #544042;border-radius:10px;max-height:320px;margin:0;padding:6px;list-style:none;position:absolute;bottom:calc(100% + 8px);left:0;right:0;overflow-y:auto;box-shadow:0 20px 60px #0007}.slash-menu li{cursor:pointer;border-radius:6px;align-items:baseline;gap:10px;padding:7px 10px;display:flex}.slash-menu li.active{background:#ff899714}.slash-menu code{color:var(--accent);font-size:15px}.slash-args{color:var(--muted);font-family:var(--font-mono);font-size:14px}.slash-desc{color:var(--muted);text-align:right;margin-left:auto;font-size:14px}.job-run{border:1px solid #5a3a3e;border-left:4px solid var(--accent);min-width:0;color:var(--fg);background:linear-gradient(#2a1b1d,#221617);border-radius:9px;margin:14px 0 6px;padding:16px 18px 14px}.job-run.is-completed{border-left-color:var(--ok)}.job-run.is-waiting{border-left-color:var(--warn)}.job-run.is-failed,.job-run.is-declined,.job-run.is-aborted{border-left-color:#8d6a6d}.job-run-head{align-items:center;gap:12px;display:flex}.job-run-icon{width:40px;height:40px;color:var(--accent);background:#3d2629;border-radius:9px;flex:none;place-items:center;display:grid}.job-run-titles{flex:1;min-width:0}.job-run-titles h3{font-family:var(--font-title);margin:2px 0 0;font-size:19px;font-weight:750}.job-run-eyebrow{letter-spacing:1.2px;color:var(--secondary);flex-wrap:wrap;align-items:center;gap:4px 12px;font-size:16px;display:flex}.job-run-repeat{letter-spacing:0;color:var(--fg);align-items:center;gap:5px;display:inline-flex}.job-run-status{background:#352728;border-radius:5px;flex:none;align-items:center;gap:7px;padding:4px 9px;font-size:16px;display:inline-flex}.job-run-status i{background:currentColor;border-radius:50%;width:7px;height:7px}.job-run-status.running{color:var(--accent)}.job-run-status.running i{animation:1.5s infinite pulse}.job-run-status.waiting{color:var(--warn)}.job-run-status.completed{color:var(--ok)}.job-run-about{margin:12px 0 8px;font-size:16px;line-height:1.55}.job-run-meta{font-family:var(--font-mono);color:var(--secondary);flex-wrap:wrap;gap:6px 14px;font-size:16px;display:flex}.job-run-input,.job-run-resumed{color:var(--fg)}.job-run-resumed{color:var(--warn)}.job-stepper{flex-wrap:wrap;align-items:center;gap:8px 0;margin:16px 0 12px;padding:0;list-style:none;display:flex}.job-stepper li{align-items:center;display:inline-flex}.job-stepper li:not(:last-child):after{content:"→";color:#8d6a6d;margin:0 8px}.job-chip{background:#241819;border:1px solid #4a3638;border-radius:999px;align-items:center;gap:7px;padding:4px 11px 4px 4px;font-size:16px;display:inline-flex}.job-step-dot{width:24px;height:24px;font-family:var(--font-mono);background:#3a2a2c;border-radius:50%;place-items:center;font-size:15px;display:grid}.ph-done .job-chip{border-color:#3f6b52}.ph-done .job-step-dot{color:#b9f2cf;background:#24543a}.ph-running .job-chip{border-color:var(--accent);box-shadow:0 0 0 3px #ff899722}.ph-running .job-step-dot{color:var(--accent);background:#5a2a31}.ph-waiting .job-chip{border-color:var(--warn);box-shadow:0 0 0 3px #f2c94c22}.ph-waiting .job-step-dot{color:var(--warn);background:#574719}.ph-failed .job-chip,.ph-aborted .job-chip{border-color:#8d4a52}.job-stepper .ph-skipped{opacity:.55}.job-step-progress{font-family:var(--font-mono);color:var(--secondary)}.job-phases{grid-template-columns:minmax(0,1fr);gap:6px;display:grid}.job-phase{background:#1f1415;border:1px solid #3c2b2d;border-radius:7px}.job-phase.ph-running{border-color:#6a3a41}.job-phase.ph-waiting{border-color:#6b5a24}.job-phase.ph-skipped,.job-phase.ph-pending{opacity:.7}.job-phase>summary{cursor:pointer;flex-wrap:wrap;align-items:baseline;gap:4px 10px;padding:9px 12px;font-size:16px;list-style:none;display:flex}.job-phase summary::-webkit-details-marker{display:none}.job-phase-n{font-family:var(--font-mono);color:var(--secondary)}.job-phase-summary{color:#e6d7d8;flex:1;min-width:160px}.job-phase-time{font-family:var(--font-mono);color:var(--secondary);margin-left:auto}.job-phase-about,.job-phase-empty{color:var(--secondary);margin:0;padding:0 12px 8px 34px;font-size:16px}.job-steps{grid-template-columns:minmax(0,1fr);gap:5px;margin:0;padding:0 12px 10px 34px;list-style:none;display:grid}.job-steps>li{font-size:16px;display:block}.job-steps summary,.job-step-line{align-items:center;gap:9px;min-width:0;list-style:none;display:flex}.job-steps summary{cursor:pointer}.job-steps summary:after{content:"⌄";color:var(--secondary);margin-left:2px}.job-steps details[open] summary:after{content:"⌃"}.job-steps code{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:var(--font-mono);background:#2c1e20;border-radius:4px;padding:1px 6px;font-size:16px;overflow:hidden}.job-steps .k-tool code{border:1px solid #5a3a3e;flex:none}.job-step-kind{color:var(--secondary)}.job-steps .k-tool .job-step-kind,.job-steps .k-agent .job-step-kind{color:var(--accent)}.job-step-text{min-width:0;color:var(--fg)}.job-step-args{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:var(--font-mono);color:var(--secondary);overflow:hidden}.job-step-state{font-family:var(--font-mono);color:var(--secondary);flex:none;align-items:center;gap:5px;display:inline-flex}.job-steps .st-done .job-step-state svg{color:var(--ok)}.job-steps .st-error .job-step-state svg{color:#ff8997}.job-steps .st-waiting .job-step-state svg{color:var(--warn)}.job-steps pre{white-space:pre-wrap;color:#e6d7d8;background:#180f10;border-radius:5px;max-height:180px;margin:4px 0 2px 25px;padding:7px 9px;font-size:16px;overflow:auto}.job-step-link{margin:2px 0 0 25px}.job-approval{background:#2c2514;border:1px solid #8a7330;border-radius:8px;margin-top:12px;padding:12px 14px}.job-approval>div:first-child{color:var(--warn);align-items:center;gap:8px;display:flex}.job-approval p{margin:6px 0 10px;font-size:16px;line-height:1.5}.job-approval-buttons{flex-wrap:wrap;gap:8px;display:flex}.job-run-foot{color:var(--secondary);border-top:1px solid #3c2b2d;flex-wrap:wrap;align-items:center;gap:8px 14px;margin-top:12px;padding-top:10px;font-size:16px;display:flex}.job-run-foot span{flex:1;min-width:220px}.job-def{background:#241819;border:1px solid #453536;border-radius:8px;margin-top:12px;padding:13px}.job-def-head{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.job-def-head svg{color:var(--accent)}.job-def-head strong{margin-right:auto;font-size:16px}.job-def p{margin:8px 0;font-size:16px;line-height:1.5}.job-chain{flex-wrap:wrap;gap:6px 4px;margin:8px 0;padding:0;list-style:none;display:flex}.job-chain li{border:1px solid #4a3638;border-radius:999px;align-items:center;gap:5px;padding:3px 9px 3px 3px;font-size:16px;display:inline-flex}.job-chain li span{width:20px;height:20px;font-family:var(--font-mono);background:#3a2a2c;border-radius:50%;place-items:center;font-size:14px;display:grid}.job-chain li:not(:last-child):after{content:"→";color:#8d6a6d;margin-left:4px}.job-def-meta{flex-wrap:wrap;gap:6px;display:flex}.job-def-meta code{font-family:var(--font-mono);color:var(--secondary);overflow-wrap:anywhere;font-size:16px}.job-def-last{flex-wrap:wrap;align-items:center;gap:6px 10px;margin-top:10px;font-size:16px;display:flex}.job-def-last .text-button{margin-top:0}.job-def-run{margin-top:12px}.task-tree{gap:4px;margin:0 0 12px;padding:0;list-style:none;display:grid}.task-row{margin-left:calc(var(--depth) * 18px);background:#211617;border:1px solid #3c2b2d;border-left:3px solid #5a3a3e;border-radius:6px;flex-wrap:wrap;align-items:center;gap:4px 8px;padding:7px 10px;font-size:16px;display:flex}.task-row[data-task-kind=pi\.tool]{border-left-color:var(--accent)}.task-row[data-task-kind^="demo.job."]{border-left-color:var(--warn)}.task-row small{width:100%;font-family:var(--font-mono);color:var(--secondary);font-size:16px}.task-row .text-button{margin-top:0}.task-phase{font-family:var(--font-mono);color:var(--secondary)}.context-section{margin-top:18px}.context-numbers{flex-wrap:wrap;align-items:baseline;gap:6px 8px;font-size:16px;display:flex}.context-numbers strong{font-family:var(--font-title);font-size:22px}.context-pct{font-family:var(--font-mono);color:var(--secondary)}.context-compacting{color:var(--warn);align-items:center;gap:6px;margin-left:auto;display:inline-flex}.context-compacting i{background:currentColor;border-radius:50%;width:7px;height:7px;animation:1.2s infinite pulse}.context-bar{touch-action:none;background:#2d2122;border:1px solid #453536;border-radius:7px;height:14px;margin:40px 0 44px;position:relative}.context-bar.off .context-marker{opacity:.45}.context-fill{background:linear-gradient(90deg, #8a3a45, var(--accent));border-radius:7px 0 0 7px;transition:width .3s;position:absolute;inset:0 auto 0 0}.context-fill.hot{background:linear-gradient(90deg, #8a3a45, var(--warn))}.context-reserve{background:repeating-linear-gradient(135deg,#ffffff10 0 5px,#0000 5px 10px);border-left:1px solid #8d6a6d;border-radius:0 7px 7px 0;position:absolute;top:0;bottom:0;right:0}.context-marker{background:var(--warn);cursor:ew-resize;touch-action:none;border-radius:2px;width:4px;height:26px;margin-left:-2px;padding:0;position:absolute;top:-7px}.context-marker:before{content:"";position:absolute;inset:-4px -10px}.context-marker.wait{background:var(--fg)}.context-marker-label{white-space:nowrap;font-size:16px;font-family:var(--font-mono);color:var(--warn);pointer-events:none;position:absolute;left:50%;transform:translate(-50%)}.context-marker.auto .context-marker-label{bottom:calc(100% + 4px)}.context-marker.wait .context-marker-label{color:var(--fg);top:calc(100% + 4px)}.context-marker.label-start .context-marker-label{left:-2px;transform:none}.context-marker.label-end .context-marker-label{left:auto;right:-2px;transform:none}.context-hint{margin:0 0 10px}.context-details-toggle{color:var(--warn);letter-spacing:0;align-items:center;gap:4px;padding:0;font-size:16px;display:inline-flex}.compaction-modal p{margin:0 0 12px;font-size:16px;line-height:1.6}.modal .context-toggle{flex-direction:row;align-items:center;gap:8px;margin-top:6px}.modal .context-toggle input{width:auto;padding:0}.context-toggle{flex-wrap:wrap;align-items:center;gap:4px 8px;font-size:16px;display:flex}.context-toggle small{width:100%;color:var(--secondary);font-size:16px}.ext-card{background:#241819;border:1px solid #453536;border-left:3px solid #5a3a3e;border-radius:8px;margin-top:12px;padding:13px 14px}.ext-card.on{border-left-color:var(--ok)}.ext-head{align-items:center;gap:12px;display:flex}.ext-head>div{flex-wrap:wrap;align-items:baseline;gap:4px 10px;min-width:0;display:flex}.ext-head strong{font-size:16px}.ext-head code{font-family:var(--font-mono);color:var(--secondary);font-size:16px}.ext-card>p{margin:8px 0 0;font-size:16px;line-height:1.5}.ext-prompts{border-top:1px solid #3c2b2d;gap:10px;margin:12px 0 0;padding:10px 0 0;list-style:none;display:grid}.ext-prompts.off{opacity:.6}.ext-prompts li{gap:4px;font-size:16px;display:grid}.ext-prompts label{cursor:pointer;align-items:center;gap:8px;display:flex}.ext-prompts code{font-family:var(--font-mono);font-size:16px}.ext-prompts li>span{color:var(--secondary);padding-left:26px;line-height:1.45}.ext-prompts details{padding-left:26px}.ext-prompts summary{cursor:pointer;color:var(--accent)}.ext-prompts pre{white-space:pre-wrap;background:#180f10;border-radius:6px;max-height:260px;margin:6px 0 0;padding:9px;font-size:16px;overflow:auto}.tool-row.disabled summary>strong,.tool-row.disabled summary>svg,.tool-row.disabled>p,.tool-row.disabled>pre,.tool-row.disabled>small{opacity:.45}.tool-row summary .tag.tool-disabled{color:var(--warn);border-color:#6b5a24;margin-left:2px;margin-right:auto}.tool-row summary .tag.tool-disabled+.tag{margin-left:auto}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
<meta name="referrer" content="no-referrer" />
|
|
8
8
|
<link rel="icon" type="image/svg+xml" href="/icons/durable-pi.svg" />
|
|
9
9
|
<title>Durable Pi | Network</title>
|
|
10
|
-
<script type="module" crossorigin src="/assets/index-
|
|
11
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
10
|
+
<script type="module" crossorigin src="/assets/index-B2OcBmds.js"></script>
|
|
11
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CL5-3stf.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
14
|
<div id="app"></div>
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
Flag,
|
|
22
22
|
GitBranch,
|
|
23
23
|
GitCompare,
|
|
24
|
+
GitMerge,
|
|
24
25
|
History,
|
|
25
26
|
Minus,
|
|
26
27
|
PackageOpen,
|
|
@@ -79,11 +80,151 @@ const sessionCount = computed(() => {
|
|
|
79
80
|
const mine = (status.value?.files ?? []).filter((f) => touched.has(abs(f.path)));
|
|
80
81
|
return { changed: mine.length, total: sessionFiles.value.length };
|
|
81
82
|
});
|
|
83
|
+
/** App-styled confirm modal — native confirm() cannot be driven headless
|
|
84
|
+
* (checklist Q4) and looks foreign. One slot, Escape backs out. */
|
|
85
|
+
const ask = ref<{ title: string; body: string; confirmLabel?: string; danger?: boolean; input?: { placeholder: string; value: string }; action: (input: string) => void } | null>(null);
|
|
86
|
+
const askInput = ref("");
|
|
87
|
+
const openAsk = (m: NonNullable<typeof ask.value>) => {
|
|
88
|
+
askInput.value = m.input?.value ?? "";
|
|
89
|
+
ask.value = m;
|
|
90
|
+
};
|
|
91
|
+
const runAsk = () => {
|
|
92
|
+
const m = ask.value;
|
|
93
|
+
ask.value = null;
|
|
94
|
+
if (m) m.action(askInput.value);
|
|
95
|
+
};
|
|
96
|
+
const onKeyEsc = (e: KeyboardEvent) => {
|
|
97
|
+
if (e.key === "Escape" && ask.value) ask.value = null;
|
|
98
|
+
};
|
|
99
|
+
if (!import.meta.env.SSR) window.addEventListener("keydown", onKeyEsc);
|
|
100
|
+
|
|
82
101
|
/** Checkpoints (zcode): named refs of HEAD you can rewind to. */
|
|
83
102
|
const checkpoints = ref<{ name: string; hash: string; date: string; subject: string }[]>([]);
|
|
84
103
|
const cpsOpen = ref(false);
|
|
85
104
|
/** Log row expander: files of one commit. */
|
|
86
105
|
const expanded = ref<Map<string, { status: string; path: string }[]>>(new Map());
|
|
106
|
+
/** PRs via the device's gh CLI (forge territory, checklist defer-item now
|
|
107
|
+
* un-deferred): lazy list, create from the current branch, squash-merge,
|
|
108
|
+
* checks as text, comment through the same modal. */
|
|
109
|
+
const prs = ref<{ n: number; title: string; state: string; draft: boolean; branch: string; url: string }[]>([]);
|
|
110
|
+
const prsOpen = ref(false);
|
|
111
|
+
const prChecks = ref<Map<number, string>>(new Map());
|
|
112
|
+
const prBusy = ref(false);
|
|
113
|
+
const isGitHub = computed(() => /github\.com|gitlab/i.test(status.value?.remoteUrl ?? ""));
|
|
114
|
+
const loadPRs = async () => {
|
|
115
|
+
if (!devId.value || !cwd.value) return;
|
|
116
|
+
prBusy.value = true;
|
|
117
|
+
try {
|
|
118
|
+
const r = await deviceClient(devId.value).gitOp(cwd.value, "pr-list");
|
|
119
|
+
prs.value = r.prs ?? [];
|
|
120
|
+
} catch (e) {
|
|
121
|
+
notify(`pr list failed: ${(e as Error).message.slice(0, 120)}`);
|
|
122
|
+
} finally {
|
|
123
|
+
prBusy.value = false;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
watch(prsOpen, (open) => { if (open) void loadPRs(); });
|
|
127
|
+
const prCreate = () =>
|
|
128
|
+
openAsk({
|
|
129
|
+
title: "Create pull request",
|
|
130
|
+
body: `head: ${status.value?.branch ?? "?"}`,
|
|
131
|
+
confirmLabel: "Create PR",
|
|
132
|
+
input: { placeholder: "PR title", value: commitMsg.value.trim() || "" },
|
|
133
|
+
action: (title) => void prCreateNow(title),
|
|
134
|
+
});
|
|
135
|
+
async function prCreateNow(title: string) {
|
|
136
|
+
if (!devId.value || !cwd.value || !title.trim()) return;
|
|
137
|
+
prBusy.value = true;
|
|
138
|
+
try {
|
|
139
|
+
const r = await deviceClient(devId.value).gitOp(cwd.value, "pr-create", { message: title.trim(), body: title.trim() });
|
|
140
|
+
notify(r.text.split("\n")[0] ?? "PR created");
|
|
141
|
+
await loadPRs();
|
|
142
|
+
} catch (e) {
|
|
143
|
+
notify(`pr create failed: ${(e as Error).message.slice(0, 140)}`);
|
|
144
|
+
} finally {
|
|
145
|
+
prBusy.value = false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async function prChecksOf(n: number) {
|
|
149
|
+
if (!devId.value || !cwd.value) return;
|
|
150
|
+
prBusy.value = true;
|
|
151
|
+
try {
|
|
152
|
+
const r = await deviceClient(devId.value).gitOp(cwd.value, "pr-checks", { n });
|
|
153
|
+
prChecks.value = new Map(prChecks.value).set(n, r.text.slice(0, 1500));
|
|
154
|
+
} catch (e) {
|
|
155
|
+
notify(`pr checks failed: ${(e as Error).message.slice(0, 120)}`);
|
|
156
|
+
} finally {
|
|
157
|
+
prBusy.value = false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const prMergeAsk = (n: number) =>
|
|
161
|
+
openAsk({
|
|
162
|
+
title: `Merge PR #${n}?`,
|
|
163
|
+
body: "squash-merge via gh on the device.",
|
|
164
|
+
confirmLabel: "Squash & merge",
|
|
165
|
+
danger: true,
|
|
166
|
+
action: () => void prMergeNow(n),
|
|
167
|
+
});
|
|
168
|
+
async function prMergeNow(n: number) {
|
|
169
|
+
if (!devId.value || !cwd.value) return;
|
|
170
|
+
prBusy.value = true;
|
|
171
|
+
try {
|
|
172
|
+
const r = await deviceClient(devId.value).gitOp(cwd.value, "pr-merge", { n });
|
|
173
|
+
notify(r.text || `PR #${n} merged`);
|
|
174
|
+
await loadPRs();
|
|
175
|
+
await refresh();
|
|
176
|
+
} catch (e) {
|
|
177
|
+
notify(`pr merge failed: ${(e as Error).message.slice(0, 140)}`);
|
|
178
|
+
} finally {
|
|
179
|
+
prBusy.value = false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const prCommentAsk = (n: number) =>
|
|
183
|
+
openAsk({
|
|
184
|
+
title: `Comment on PR #${n}`,
|
|
185
|
+
body: "posted as the device's gh login",
|
|
186
|
+
confirmLabel: "Comment",
|
|
187
|
+
input: { placeholder: "comment…", value: "" },
|
|
188
|
+
action: (text) => void prCommentNow(n, text),
|
|
189
|
+
});
|
|
190
|
+
async function prCommentNow(n: number, text: string) {
|
|
191
|
+
if (!devId.value || !cwd.value || !text.trim()) return;
|
|
192
|
+
prBusy.value = true;
|
|
193
|
+
try {
|
|
194
|
+
const r = await deviceClient(devId.value).gitOp(cwd.value, "pr-comment", { n, body: text.trim() });
|
|
195
|
+
notify(r.text || "comment posted");
|
|
196
|
+
} catch (e) {
|
|
197
|
+
notify(`pr comment failed: ${(e as Error).message.slice(0, 140)}`);
|
|
198
|
+
} finally {
|
|
199
|
+
prBusy.value = false;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** Per-turn summaries (zcode taskChangeSummary) under the session chip. */
|
|
204
|
+
const turns = ref<{ when: string; files: { path: string; writes: number }[] }[]>([]);
|
|
205
|
+
const turnsOpen = ref(false);
|
|
206
|
+
const loadTurns = async () => {
|
|
207
|
+
if (!devId.value || !sessionId.value) return;
|
|
208
|
+
try {
|
|
209
|
+
const r = await deviceClient(devId.value).sessionGitTurns(sessionId.value);
|
|
210
|
+
turns.value = r.turns;
|
|
211
|
+
} catch {
|
|
212
|
+
turns.value = [];
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
watch(turnsOpen, (open) => { if (open) void loadTurns(); });
|
|
216
|
+
|
|
217
|
+
/** Focus refresh (checklist fs-auto-refresh, lightweight variant): the tab
|
|
218
|
+
* re-syncs when the user comes back to it — event-driven, never a timer. */
|
|
219
|
+
let lastFocusRefresh = 0;
|
|
220
|
+
if (!import.meta.env.SSR) {
|
|
221
|
+
window.addEventListener("focus", () => {
|
|
222
|
+
if (!cwd.value || Date.now() - lastFocusRefresh < 15_000) return;
|
|
223
|
+
lastFocusRefresh = Date.now();
|
|
224
|
+
void ensureGit(devId.value || "?", cwd.value || "?", { force: true });
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
87
228
|
/** Folder grouping (orca tree-directory-rows): collapse noise. */
|
|
88
229
|
const collapsed = ref<Set<string>>(new Set());
|
|
89
230
|
|
|
@@ -228,10 +369,22 @@ async function op(
|
|
|
228
369
|
}
|
|
229
370
|
}
|
|
230
371
|
|
|
231
|
-
async function fileAction(name: "stage" | "discard", path?: string) {
|
|
372
|
+
async function fileAction(name: "stage" | "discard", path?: string, confirmed = false) {
|
|
232
373
|
if (!devId.value || !cwd.value) return;
|
|
374
|
+
if (confirmed) {
|
|
375
|
+
busy.value = name!;
|
|
376
|
+
}
|
|
233
377
|
if (!path && name !== "stage") return;
|
|
234
|
-
if (name === "discard" && path
|
|
378
|
+
if (name === "discard" && path) {
|
|
379
|
+
openAsk({
|
|
380
|
+
title: "Roll back to HEAD?",
|
|
381
|
+
body: `${path} — uncommitted changes are lost.`,
|
|
382
|
+
confirmLabel: "Roll back",
|
|
383
|
+
danger: true,
|
|
384
|
+
action: () => void fileAction(name, path, true),
|
|
385
|
+
});
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
235
388
|
busy.value = name;
|
|
236
389
|
const targets = path ? [path] : files.value.filter((f) => f.x === " " || f.x === "M").map((f) => f.path);
|
|
237
390
|
try {
|
|
@@ -387,11 +540,15 @@ async function commit(thenPush = false) {
|
|
|
387
540
|
}
|
|
388
541
|
}
|
|
389
542
|
|
|
390
|
-
/**
|
|
391
|
-
*
|
|
392
|
-
function
|
|
543
|
+
/** One model per provider, default's provider first — dead providers (seen
|
|
544
|
+
* live: a stale key answers model_error) are skipped after one strike. */
|
|
545
|
+
function modelCandidates(info: { models?: { id: string; provider: string }[]; defaultModel?: string } | undefined) {
|
|
393
546
|
const models = info?.models ?? [];
|
|
394
|
-
|
|
547
|
+
const def = models.find((m) => `${m.provider}/${m.id}` === info?.defaultModel);
|
|
548
|
+
const byProvider = new Map<string, { id: string; provider: string }>();
|
|
549
|
+
for (const m of models) if (!byProvider.has(m.provider)) byProvider.set(m.provider, m);
|
|
550
|
+
const rest = [...byProvider.values()].filter((m) => m !== def).slice(0, 3);
|
|
551
|
+
return (def ? [def, ...rest] : rest).slice(0, 4);
|
|
395
552
|
}
|
|
396
553
|
|
|
397
554
|
/** orca/zcode AI message: ask the device's own model to title the changelist. */
|
|
@@ -401,34 +558,48 @@ async function aiMessage() {
|
|
|
401
558
|
if (!chosen.length) return notify("check files first — the model summarises THOSE");
|
|
402
559
|
busy.value = "ai";
|
|
403
560
|
const client = deviceClient(devId.value);
|
|
404
|
-
let
|
|
561
|
+
let diff = "";
|
|
562
|
+
for (const f of chosen.slice(0, 5)) {
|
|
563
|
+
const d = await client.gitOp(cwd.value, "diff-file", { target: f });
|
|
564
|
+
diff += `${d.text}\n`;
|
|
565
|
+
if (diff.length > 4000) break;
|
|
566
|
+
}
|
|
567
|
+
diff = diff.slice(0, 4000);
|
|
568
|
+
const prompt = `Write ONE concise git commit message (under 72 chars, imperative, no quotes, no backticks) for these changes:\n\n${diff}`;
|
|
569
|
+
const info = network.devices.value.find((d) => d.id === devId.value)?.info;
|
|
570
|
+
const candidates = modelCandidates(info);
|
|
571
|
+
if (!candidates.length) {
|
|
572
|
+
busy.value = "";
|
|
573
|
+
return notify("no model on the device");
|
|
574
|
+
}
|
|
575
|
+
const failed: string[] = [];
|
|
405
576
|
try {
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
577
|
+
for (const model of candidates) {
|
|
578
|
+
const sid = await client
|
|
579
|
+
.createSession({ name: "git-msg", cwd: cwd.value, model: { provider: model.provider, modelId: model.id } })
|
|
580
|
+
.then((s) => s.id)
|
|
581
|
+
.catch(() => "");
|
|
582
|
+
if (!sid) {
|
|
583
|
+
failed.push(`${model.provider}: no session`);
|
|
584
|
+
continue;
|
|
585
|
+
}
|
|
586
|
+
try {
|
|
587
|
+
const r = await client.agent(sid, 1).send(prompt, "followUp", undefined, 120_000);
|
|
588
|
+
const text = r.status === "done" ? r.answer.text.trim().split("\n")[0]?.slice(0, 100) : "";
|
|
589
|
+
if (text) {
|
|
590
|
+
commitMsg.value = text;
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
failed.push(`${model.provider}/${model.id}: ${r.status === "unanswered" ? r.reason : "empty answer"}`);
|
|
594
|
+
} finally {
|
|
595
|
+
void client.session(sid).archive().catch(() => {});
|
|
596
|
+
}
|
|
414
597
|
}
|
|
415
|
-
|
|
416
|
-
const s = await client.createSession({ name: "git-msg", cwd: cwd.value, model: { provider: model.provider, modelId: model.id } });
|
|
417
|
-
sid = s.id;
|
|
418
|
-
const r = await client.agent(sid, 1).send(
|
|
419
|
-
`Write ONE concise git commit message (under 72 chars, imperative, no quotes, no backticks) for these changes:\n\n${diff}`,
|
|
420
|
-
"followUp",
|
|
421
|
-
undefined,
|
|
422
|
-
120_000,
|
|
423
|
-
);
|
|
424
|
-
const text = r.status === "done" ? r.answer.text.trim().split("\n")[0]?.slice(0, 100) : "";
|
|
425
|
-
if (text) commitMsg.value = text;
|
|
426
|
-
else notify("the model returned nothing usable");
|
|
598
|
+
notify(`ai message failed on every model — ${failed.join("; ").slice(0, 140)}`);
|
|
427
599
|
} catch (e) {
|
|
428
600
|
notify(`ai message failed: ${(e as Error).message.slice(0, 120)}`);
|
|
429
601
|
} finally {
|
|
430
602
|
busy.value = "";
|
|
431
|
-
if (sid) void client.session(sid).archive().catch(() => {});
|
|
432
603
|
}
|
|
433
604
|
}
|
|
434
605
|
|
|
@@ -494,7 +665,18 @@ async function loadCheckpoints() {
|
|
|
494
665
|
|
|
495
666
|
async function rewind(name: string) {
|
|
496
667
|
if (!devId.value || !cwd.value) return;
|
|
497
|
-
|
|
668
|
+
const target = name;
|
|
669
|
+
openAsk({
|
|
670
|
+
title: `Rewind to ${target}?`,
|
|
671
|
+
body: "reset --hard — ALL uncommitted changes in this worktree are LOST.",
|
|
672
|
+
confirmLabel: "Rewind",
|
|
673
|
+
danger: true,
|
|
674
|
+
action: () => void rewindAfter(target),
|
|
675
|
+
});
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
async function rewindAfter(name: string) {
|
|
679
|
+
if (!devId.value || !cwd.value) return;
|
|
498
680
|
busy.value = "rewind";
|
|
499
681
|
try {
|
|
500
682
|
const r = await deviceClient(devId.value).gitOp(cwd.value, "rewind", { name });
|
|
@@ -536,7 +718,7 @@ async function sessionOn(path: string, branch: string | null) {
|
|
|
536
718
|
busy.value = "session";
|
|
537
719
|
try {
|
|
538
720
|
const info = network.devices.value.find((d) => d.id === devId.value)?.info;
|
|
539
|
-
const model =
|
|
721
|
+
const model = modelCandidates(info)[0];
|
|
540
722
|
if (!model) return notify(`no model available on ${devId.value} — cannot create a session`);
|
|
541
723
|
const s = await deviceClient(devId.value).createSession({
|
|
542
724
|
name: branch ?? path.slice(path.lastIndexOf("/") + 1),
|
|
@@ -583,9 +765,19 @@ async function removeWorktree(path: string) {
|
|
|
583
765
|
if ((s?.staged ?? 0) + (s?.unstaged ?? 0) + (s?.untracked ?? 0) > 0) warn = `It CONTAINS uncommitted changes — they will be LOST.`;
|
|
584
766
|
else warn = "Its checkout is clean.";
|
|
585
767
|
} catch {}
|
|
586
|
-
|
|
768
|
+
const w = warn;
|
|
769
|
+
openAsk({
|
|
770
|
+
title: "Remove worktree?",
|
|
771
|
+
body: `${path} — ${w}`,
|
|
772
|
+
confirmLabel: "Remove",
|
|
773
|
+
danger: true,
|
|
774
|
+
action: () => void removeWorktreeNow(path),
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
async function removeWorktreeNow(path: string) {
|
|
778
|
+
busy.value = "wt";
|
|
587
779
|
try {
|
|
588
|
-
await deviceClient(devId.value).gitOp(cwd.value
|
|
780
|
+
await deviceClient(devId.value!).gitOp(cwd.value!, "worktree-remove", { target: path });
|
|
589
781
|
await refresh();
|
|
590
782
|
} catch (e) {
|
|
591
783
|
notify(`remove failed: ${(e as Error).message.slice(0, 140)}`);
|
|
@@ -739,8 +931,19 @@ const laneX = (lane: number) => lane * 12 + 7;
|
|
|
739
931
|
<button v-if="sessionId" class="small" :disabled="!!busy" title="check the files this session's agent touched" @click="selectSessionFiles">
|
|
740
932
|
<Flag :size="13" /> session files{{ sessionCount ? ` (${sessionCount.changed}/${sessionCount.total})` : "" }}
|
|
741
933
|
</button>
|
|
934
|
+
<button v-if="sessionId" class="small" :disabled="!!busy" title="what each turn of this session changed" @click="turnsOpen = !turnsOpen">
|
|
935
|
+
turns
|
|
936
|
+
</button>
|
|
742
937
|
</div>
|
|
743
938
|
<p v-if="noIdentity" class="hintbox warn">git user.name/user.email is not set on the device — <code>dpi device config</code> or <code>git config --global</code> before committing.</p>
|
|
939
|
+
<div v-if="turnsOpen" class="cps turns">
|
|
940
|
+
<p v-if="!turns.length" class="hint">no turns recorded yet for this session.</p>
|
|
941
|
+
<div v-for="(t, ti) in turns" :key="ti" class="cp-row">
|
|
942
|
+
<code>t{{ turns.length - ti }}</code>
|
|
943
|
+
<span class="muted-line">{{ t.when.slice(0, 16).replace("T", " ") }}</span>
|
|
944
|
+
<span class="cp-subj">{{ t.files.map((f) => `${f.path}×${f.writes}`).join(", ") || "(no file writes)" }}</span>
|
|
945
|
+
</div>
|
|
946
|
+
</div>
|
|
744
947
|
<p v-if="atCap" class="muted-line cap">showing the first 500 changed files — commit in smaller batches</p>
|
|
745
948
|
<div v-if="stagedFiles.length" class="files">
|
|
746
949
|
<label class="file all">
|
|
@@ -904,9 +1107,50 @@ const laneX = (lane: number) => lane * 12 + 7;
|
|
|
904
1107
|
</div>
|
|
905
1108
|
</section>
|
|
906
1109
|
|
|
1110
|
+
<!-- PULL REQUESTS (device gh CLI) -->
|
|
1111
|
+
<section v-if="isGitHub" class="task-section" aria-label="Pull requests">
|
|
1112
|
+
<div class="panel-heading">
|
|
1113
|
+
<h4><GitMerge :size="16" /> Pull requests</h4>
|
|
1114
|
+
<span class="grow" />
|
|
1115
|
+
<button class="small" :disabled="prBusy || !!busy" @click="prCreate">create PR</button>
|
|
1116
|
+
<button class="small" :disabled="prBusy" @click="prsOpen = !prsOpen">{{ prsOpen ? "hide" : "list" }}</button>
|
|
1117
|
+
</div>
|
|
1118
|
+
<p v-if="prsOpen && !prs.length && !prBusy" class="hint">no open PRs (or gh is not logged in on the device — every action will say so).</p>
|
|
1119
|
+
<div v-if="prsOpen" class="commits">
|
|
1120
|
+
<div v-for="pr in prs" :key="pr.n" class="pr-row">
|
|
1121
|
+
<code class="hash">#{{ pr.n }}</code>
|
|
1122
|
+
<span class="tag" :class="{ open: pr.state === 'OPEN' }">{{ pr.state.toLowerCase() }}{{ pr.draft ? " · draft" : "" }}</span>
|
|
1123
|
+
<span class="subject">{{ pr.title }}</span>
|
|
1124
|
+
<span class="muted-line who">{{ pr.branch }}</span>
|
|
1125
|
+
<span class="grow" />
|
|
1126
|
+
<button class="icon-button" title="run checks" :disabled="prBusy" @click="prChecksOf(pr.n)"><RefreshCw :size="13" /></button>
|
|
1127
|
+
<button class="icon-button" title="comment" :disabled="prBusy" @click="prCommentAsk(pr.n)"><Copy :size="13" /></button>
|
|
1128
|
+
<button v-if="pr.state === 'OPEN'" class="small" :disabled="prBusy || !!busy" @click="prMergeAsk(pr.n)">squash & merge</button>
|
|
1129
|
+
<a class="icon-button" :href="pr.url" target="_blank" rel="noopener" title="open on the forge"><ArrowUpFromLine :size="13" style="transform: rotate(45deg)" /></a>
|
|
1130
|
+
</div>
|
|
1131
|
+
<pre v-for="[n, text] in prChecks" :key="n" class="pr-checks">#{{ n }} checks:{{ "\n" }}{{ text }}</pre>
|
|
1132
|
+
</div>
|
|
1133
|
+
</section>
|
|
1134
|
+
|
|
907
1135
|
<pre v-if="out" class="op-out">{{ out.slice(0, 6000) }}</pre>
|
|
908
1136
|
</template>
|
|
909
1137
|
</div>
|
|
1138
|
+
|
|
1139
|
+
<!-- app-styled confirm modal (checklist Q4): drivable headless -->
|
|
1140
|
+
<div v-if="ask" class="modal-veil" @click.self="ask = null">
|
|
1141
|
+
<div class="modal" :class="{ danger: ask.danger }" role="dialog" aria-modal="true">
|
|
1142
|
+
<h5>{{ ask.title }}</h5>
|
|
1143
|
+
<p>{{ ask.body }}</p>
|
|
1144
|
+
<textarea v-if="ask.input" v-model="askInput" rows="2" :placeholder="ask.input.placeholder" />
|
|
1145
|
+
<div class="row">
|
|
1146
|
+
<span class="grow" />
|
|
1147
|
+
<button class="small" @click="ask = null">cancel <span class="muted-line">(esc)</span></button>
|
|
1148
|
+
<button class="primary small" :class="{ danger: ask.danger }" :disabled="!!(ask.input && !askInput.trim())" @click="runAsk">
|
|
1149
|
+
{{ ask.confirmLabel ?? "confirm" }}
|
|
1150
|
+
</button>
|
|
1151
|
+
</div>
|
|
1152
|
+
</div>
|
|
1153
|
+
</div>
|
|
910
1154
|
</template>
|
|
911
1155
|
</div>
|
|
912
1156
|
</template>
|
|
@@ -971,6 +1215,17 @@ textarea { width: 100%; resize: vertical; min-height: 76px; font: inherit; margi
|
|
|
971
1215
|
.wt.main code { font-weight: 650; }
|
|
972
1216
|
.grow { flex: 1; }
|
|
973
1217
|
.tag-x { margin-left: 4px; opacity: 0.7; display: inline-flex; }
|
|
1218
|
+
.pr-row { display: flex; gap: 8px; align-items: center; padding: 2px 0; white-space: nowrap; }
|
|
1219
|
+
.pr-row .tag.open { color: var(--ok, #2ea043); }
|
|
1220
|
+
.pr-checks { font-size: 12px; background: rgb(0 0 0 / 25%); padding: 8px; border-radius: 6px; margin: 4px 0; white-space: pre-wrap; }
|
|
1221
|
+
.turns { max-height: 180px; overflow: auto; }
|
|
1222
|
+
.modal-veil { position: fixed; inset: 0; z-index: 90; background: rgb(0 0 0 / 55%); display: flex; align-items: center; justify-content: center; }
|
|
1223
|
+
.modal { min-width: 340px; max-width: 520px; background: var(--bg-2, #221a1c); border: 1px solid var(--line); border-radius: 10px; padding: 16px 18px; }
|
|
1224
|
+
.modal.danger { border-color: var(--warn, #e5a50a); }
|
|
1225
|
+
.modal h5 { margin: 0 0 6px; font-size: 17px; }
|
|
1226
|
+
.modal p { margin: 0 0 10px; font-size: 15px; }
|
|
1227
|
+
.modal textarea { min-height: 56px; }
|
|
1228
|
+
.modal .danger { border-color: var(--warn, #e5a50a); }
|
|
974
1229
|
.op-out { max-height: 300px; overflow: auto; background: rgb(0 0 0 / 25%); padding: 10px; border-radius: 6px; font-size: 12px; margin-top: 8px; }
|
|
975
1230
|
h4 { display: flex; align-items: center; gap: 8px; font-size: 16px; margin: 0; }
|
|
976
1231
|
</style>
|
|
@@ -86,7 +86,13 @@ export type GitOpName =
|
|
|
86
86
|
| "ignore"
|
|
87
87
|
| "checkpoint"
|
|
88
88
|
| "checkpoints"
|
|
89
|
-
| "rewind"
|
|
89
|
+
| "rewind"
|
|
90
|
+
| "submodule-update"
|
|
91
|
+
| "pr-create"
|
|
92
|
+
| "pr-list"
|
|
93
|
+
| "pr-merge"
|
|
94
|
+
| "pr-checks"
|
|
95
|
+
| "pr-comment";
|
|
90
96
|
|
|
91
97
|
/** Everything a git op may return; most carry only text. */
|
|
92
98
|
export interface GitOpResult {
|
|
@@ -96,6 +102,7 @@ export interface GitOpResult {
|
|
|
96
102
|
behind?: number;
|
|
97
103
|
changed?: { status: string; path: string }[];
|
|
98
104
|
checkpoints?: { name: string; hash: string; date: string; subject: string }[];
|
|
105
|
+
prs?: { n: number; title: string; state: string; draft: boolean; branch: string; url: string }[];
|
|
99
106
|
}
|
|
100
107
|
|
|
101
108
|
export class DpiClient {
|
|
@@ -222,6 +229,9 @@ export class DpiClient {
|
|
|
222
229
|
setUpstream?: boolean;
|
|
223
230
|
name?: string;
|
|
224
231
|
lines?: string[];
|
|
232
|
+
method?: "squash" | "merge";
|
|
233
|
+
body?: string;
|
|
234
|
+
n?: number;
|
|
225
235
|
} = {},
|
|
226
236
|
) {
|
|
227
237
|
return this.request<GitOpResult>("POST", "/v1/git", { path, op, ...opts });
|
|
@@ -230,6 +240,13 @@ export class DpiClient {
|
|
|
230
240
|
sessionGitFiles(sessionId: string) {
|
|
231
241
|
return this.request<{ files: string[] }>("GET", `/v1/sessions/${enc(sessionId)}/git-files`);
|
|
232
242
|
}
|
|
243
|
+
/** Per-turn breakdown of the same paths (zcode taskChangeSummary). */
|
|
244
|
+
sessionGitTurns(sessionId: string) {
|
|
245
|
+
return this.request<{ turns: { when: string; files: { path: string; writes: number }[] }[] }>(
|
|
246
|
+
"GET",
|
|
247
|
+
`/v1/sessions/${enc(sessionId)}/git-turns`,
|
|
248
|
+
);
|
|
249
|
+
}
|
|
233
250
|
/** Many paths, one round-trip — session lists want branch-per-cwd. */
|
|
234
251
|
gitStatusBatch(paths: string[], options: { timeoutMs?: number } = {}) {
|
|
235
252
|
return this.request<Record<string, GitStatus>>("POST", "/v1/git/status-batch", { paths }, options);
|