@nelsonlongxiang/dsh-open-a2a-net 0.6.40 → 0.6.42

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.
Files changed (76) hide show
  1. package/README.md +2 -1
  2. package/README_zh.md +2 -1
  3. package/assets/stageDist/assets/index-Bj7S2pA1.css +1 -1
  4. package/assets/stageDist/assets/index-C-28k_o5.js +974 -974
  5. package/assets/stageDist/index.html +12 -12
  6. package/lib/a2a-client.js +3 -2
  7. package/lib/client.js +64 -64
  8. package/lib/client.js.map +1 -1
  9. package/lib/config.js +1 -0
  10. package/lib/faces/files.js +2 -2
  11. package/lib/faces/session-log.js +3 -3
  12. package/lib/faces/wire.js +11 -16
  13. package/lib/index.js +102 -18
  14. package/lib/link-keys.js +29 -0
  15. package/lib/origin-claim.js +4 -0
  16. package/lib/skill/SKILL.md +117 -117
  17. package/lib/skill/references/collaboration.md +428 -428
  18. package/lib/skill/references/discovery.md +78 -78
  19. package/lib/skill/references/intake.md +107 -107
  20. package/lib/skill/references/membership.md +73 -73
  21. package/lib/skill/references/pitfalls.md +51 -51
  22. package/lib/skill/references/router.md +96 -96
  23. package/lib/skill/references/routing.md +65 -65
  24. package/lib/skill/references/setup.md +5 -1
  25. package/lib/tools/files.js +3 -1
  26. package/lib/types/a2a-client.d.ts +3 -1
  27. package/lib/types/config.d.ts +6 -0
  28. package/lib/types/faces/files.d.ts +2 -1
  29. package/lib/types/faces/session-log.d.ts +2 -0
  30. package/lib/types/faces/wire.d.ts +2 -1
  31. package/lib/types/link-keys.d.ts +13 -0
  32. package/lib/types/origin-claim.d.ts +2 -0
  33. package/lib/types/tools/files.d.ts +1 -1
  34. package/nexus-stage/package.json +21 -21
  35. package/nexus-stage/scripts/mockhost.py +261 -261
  36. package/nexus-stage/src/canvas-ops.ts +191 -191
  37. package/nexus-stage/src/canvas-wire.ts +164 -164
  38. package/nexus-stage/src/cli-home-picker.ts +42 -42
  39. package/nexus-stage/src/fault.ts +56 -56
  40. package/nexus-stage/src/federation-overlay.ts +103 -103
  41. package/nexus-stage/src/federation.ts +241 -241
  42. package/nexus-stage/src/layout-doc.ts +145 -145
  43. package/nexus-stage/src/main.ts +513 -513
  44. package/nexus-stage/src/planning-card-text.ts +73 -73
  45. package/nexus-stage/src/planning-card.ts +63 -63
  46. package/nexus-stage/src/planning-edges.ts +26 -26
  47. package/nexus-stage/src/planning-fit.ts +45 -45
  48. package/nexus-stage/src/planning-frame-hue.ts +13 -13
  49. package/nexus-stage/src/planning-legend.ts +39 -39
  50. package/nexus-stage/src/planning-member-handles.ts +61 -61
  51. package/nexus-stage/src/planning-menus.ts +422 -422
  52. package/nexus-stage/src/planning-mirror.ts +75 -75
  53. package/nexus-stage/src/planning-nodelist.ts +294 -294
  54. package/nexus-stage/src/planning-overlap.ts +159 -159
  55. package/nexus-stage/src/planning-reachability.ts +28 -28
  56. package/nexus-stage/src/planning-relayout.ts +121 -121
  57. package/nexus-stage/src/planning-roster.ts +15 -15
  58. package/nexus-stage/src/planning-search.ts +168 -168
  59. package/nexus-stage/src/planning-types.ts +115 -115
  60. package/nexus-stage/src/planning-undo.ts +68 -68
  61. package/nexus-stage/src/planning-view.ts +1499 -1499
  62. package/nexus-stage/src/planning.css +340 -340
  63. package/nexus-stage/src/seat-name-editor.ts +31 -31
  64. package/nexus-stage/src/session-drag.ts +64 -64
  65. package/nexus-stage/src/viewport.ts +106 -106
  66. package/nexus-stage/src/wb-chat.ts +684 -684
  67. package/nexus-stage/src/wb-directory.ts +237 -237
  68. package/nexus-stage/src/wb-ledger.ts +279 -279
  69. package/nexus-stage/src/wb-names.ts +43 -43
  70. package/nexus-stage/src/wb-rail.ts +147 -147
  71. package/nexus-stage/src/workbench.css +388 -388
  72. package/nexus-stage/src/workbench.ts +1272 -1272
  73. package/nexus-stage/src/world.ts +509 -509
  74. package/nexus-stage/tsconfig.json +24 -24
  75. package/nexus-stage/vite.config.ts +15 -15
  76. package/package.json +1 -1
package/README.md CHANGED
@@ -171,6 +171,7 @@ Row config overlays in the profile's patch layers; every key has a schema defaul
171
171
  | `originClaimUrl` | `''` | Override for the envelope's `callerUrl` (pocket-tunneled hosts); `''` derives it. |
172
172
  | `originClaimUnboundWindow` | `true` | OriginClaim audience-binding window: also sign and accept the legacy envelope that names no audience (accepted ones counted as `unboundInbound`; those whose bound form missed here also as `boundMissInbound`); `false` signs and accepts the audience-bound form only. |
173
173
  | `originClaimAudiences` | `[]` | Extra origins this host answers to as an envelope audience, for port-mapped or proxied hosts whose dialed URL is neither the card URL nor the arrival address. |
174
+ | `linkKeys` | `{}` | Link keys (#317): `{ "<peer origin>": "<key>" }`. Requests to that peer carry this key instead of `apiKey`; this host's peer faces (`/a2a/direct`, `/a2a/log`, `/a2a/blob`) accept it only from a caller whose OriginClaim verifies and names that origin (a POST must be Sig3 body-bound); the control routes never accept it. Lets a public node link to the fleet without holding the fleet apiKey; both ends configure the same link key. |
174
175
  | `gateAgentLessCalls` | `'audit'` | Host-side (agent-less) routing calls: audit them, or `refuse`. |
175
176
  | `settlementAuth` | `'observe'` | Settlement authorization (#114): `off`, `observe` (record what would be refused, settle as before), or `enforce`. |
176
177
  | `asyncNudgeDelayMs` | `120000` | Delay before a delivered-but-unconsumed async route re-wakes its target with a one-line nudge; `0` disables. |
@@ -300,7 +301,7 @@ import { A2aClient } from '@nelsonlongxiang/dsh-open-a2a-net/a2a-client'
300
301
 
301
302
  Implement your own signed card, `GET /.well-known/agent-card.json`, and
302
303
  `POST /a2a/direct`. The wire shapes these modules encode are the contract.
303
- Anonymous card fetches get the minimal discovery face. The full card needs a
304
+ Anonymous card fetches get the minimal discovery face **without `peers`** (#312). The referral list requires a verified OriginClaim **and** either a caller URL explicitly seeded by this host (origin match, exact mount for path-prefixed claims) or an existing operator link. An unrelated self-signed stranger gets no topology; a configured seed may obtain referrals before a bilateral full-card link exists. Session/roster/organization fields still require the full-card link gate. Signed `?discovery=1` requests explicitly ask for only core plus referrals, avoiding recursive full-card bootstrapping. Anonymous-only legacy crawlers must use explicit seeds (or upgrade to signed requests); missing `peers` remains a valid signed card and delegations are unchanged. The full card needs a
304
305
  verified OriginClaim envelope (`X-A2A-Caller` / `-Url` / `-Ts` / `-Sig`,
305
306
  signed with your own card key) **and** a link to the serving host: your card
306
307
  URL shares its origin, your handle is one of its joined session handles, its
package/README_zh.md CHANGED
@@ -129,6 +129,7 @@ a2a-net inbox --new # 未读来信;--wait
129
129
  | `originClaimUrl` | `''` | 信封 `callerUrl` 的覆盖值(pocket 隧道宿主用);`''` 自动推导。 |
130
130
  | `originClaimUnboundWindow` | `true` | OriginClaim 受众绑定过渡窗口:同时签发并接受不带受众的旧信封(接受数计入 `unboundInbound`;其中绑定形式在本机未命中的另计 `boundMissInbound`);`false` 只签发、只接受绑定受众的信封。 |
131
131
  | `originClaimAudiences` | `[]` | 本宿主额外认作信封受众的 origin,用于端口映射或反向代理宿主(对端拨号的 URL 既不是卡片 URL 也不是到达地址)。 |
132
+ | `linkKeys` | `{}` | 链路 key(#317):`{ "<对端 origin>": "<key>" }`。发往该对端的请求改带这把 key;本机对端面(`/a2a/direct`、`/a2a/log`、`/a2a/blob`)只在调用方 OriginClaim 验签通过、且签名者正是该 origin 时接受它(POST 须 Sig3 绑定请求体);控制路由不接受。用于公网节点与舰队互联而不持有舰队 apiKey,两端配同一把链路 key。 |
132
133
  | `gateAgentLessCalls` | `'audit'` | 宿主侧(无 agent)路由调用:审计,或 `refuse` 拒绝。 |
133
134
  | `settlementAuth` | `'observe'` | 结算授权(#114):`off`、`observe`(记下本会拒绝的,照旧结算)或 `enforce`。 |
134
135
  | `asyncNudgeDelayMs` | `120000` | 已投递但未被消费的异步路由,在此延迟后用一行催办重新唤醒目标;`0` 关闭。 |
@@ -221,7 +222,7 @@ import { withinRouteBodyCap } from '@nelsonlongxiang/dsh-open-a2a-net/transport-
221
222
  import { A2aClient } from '@nelsonlongxiang/dsh-open-a2a-net/a2a-client'
222
223
  ```
223
224
 
224
- 外部节点需要自己实现三样东西:签名卡片、`GET /.well-known/agent-card.json` 和 `POST /a2a/direct`,这些模块编码的线上格式就是契约。匿名取卡只能拿到最小发现面。要拿完整卡片,必须带上通过验证的 OriginClaim 信封(即用你自己的卡片密钥签名的 `X-A2A-Caller` / `-Url` / `-Ts` / `-Sig`),**并且**与提供卡片的宿主有链接:你的卡片 URL 与它同源、你的句柄是它的已加入会话句柄之一、它的操作者把你的精确句柄加成了画布远端成员,或双方操作者互相种了对方(它的 `peers` 列有你的源,你卡片的 `peers` 也列有它的源)。验签通过但没有链接的调用方仍只拿到最小卡片。细节见 `docs/protocol/delivery-origin-auth.md` 及 `docs/protocol/` 下其余文档。
225
+ 外部节点需要自己实现三样东西:签名卡片、`GET /.well-known/agent-card.json` 和 `POST /a2a/direct`,这些模块编码的线上格式就是契约。匿名取卡只能拿到最小发现面,**不带 `peers`**(#312)。引荐列表要求 OriginClaim 验签通过,且调用方是本机 config.peers 显式种下的对端(根地址按 origin,挂载地址精确匹配),或原 operator link 已成立。无关系的自签名陌生人拿不到拓扑;显式 seed 可在双边完整名片链接形成前读取引荐。会话、roster、组织字段仍须原完整名片链接门。带签名的 `?discovery=1` 只请求核心与引荐,用于有限次自举,避免递归获取完整卡片。仅匿名取卡的旧爬取者须显式配置 seed 或升级签名请求;缺少 peers 仍是合法签名卡片,委派记录不变。要拿完整卡片,必须带上通过验证的 OriginClaim 信封(即用你自己的卡片密钥签名的 `X-A2A-Caller` / `-Url` / `-Ts` / `-Sig`),**并且**与提供卡片的宿主有链接:你的卡片 URL 与它同源、你的句柄是它的已加入会话句柄之一、它的操作者把你的精确句柄加成了画布远端成员,或双方操作者互相种了对方(它的 `peers` 列有你的源,你卡片的 `peers` 也列有它的源)。验签通过但没有链接的调用方仍只拿到最小卡片。细节见 `docs/protocol/delivery-origin-auth.md` 及 `docs/protocol/` 下其余文档。
225
226
 
226
227
  **按哪个产物实现。** npm 直装已含四个子路径:自 0.6.25 起(徽章 `latest`)的正式版带齐这批导出,`npm install @nelsonlongxiang/dsh-open-a2a-net` 开箱即用——`examples/external-node/` 有一个可对内嵌 mock peer 跑通全部四个子路径的外部节点参考实现。子路径导出随提交 `9cb3852` 落地;更早的版本(含公开 0.5.15)早于这批导出,也早于上述准入规则和 OriginClaim 信封,从它们引入会报 `ERR_PACKAGE_PATH_NOT_EXPORTED`——历史上的做法(钉提交、`pnpm build`、`npm pack`、依赖 tarball)仅留作 0.6.25 之前部署的历史注:
227
228
 
@@ -1 +1 @@
1
- :root{--cth-cream-50: #FFFDF5;--cth-cream-100: #FFF8E7;--cth-cream-200: #F4E9C7;--cth-cream-300: #E8D9A0;--cth-paper-100: #FCFAF0;--cth-paper-200: #F0EAD2;--cth-ink-900: #1A1320;--cth-ink-700: #3D2E4A;--cth-ink-500: #6B5878;--cth-ink-300: #A899B5;--cth-ink-100: #D9CFE0;--cth-coral: #D96A62;--cth-coral-light: #F3D3CD;--cth-mint: #5CA97A;--cth-mint-light: #D2E7DA;--cth-sky: #4F9FAF;--cth-sky-light: #CFE5E9;--cth-lemon: #DCAB3C;--cth-lemon-light: #F3E4BC;--cth-lilac: #9482D3;--cth-lilac-light: #E0DAF2;--cth-peach: #D99168;--cth-peach-light: #F3DACA;--cth-status-idle: #A199AB;--cth-status-thinking: #4F9FAF;--cth-status-working: #DCAB3C;--cth-status-waiting: #6D87D6;--cth-status-blocked: #D96A62;--cth-status-success: #5CA97A;--cth-status-ghost: #D9D3DE;--cth-status-compacting: #8F7CC7;--cth-status-looping: #D6903F;--cth-status-typing: #C89838;--cth-space-0: 0px;--cth-space-1: 4px;--cth-space-2: 8px;--cth-space-3: 12px;--cth-space-4: 16px;--cth-space-5: 24px;--cth-space-6: 32px;--cth-space-7: 48px;--cth-space-8: 64px;--cth-font-display: "Press Start 2P", monospace;--cth-font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;--cth-font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;--cth-text-display-lg: 16px;--cth-text-display-md: 12px;--cth-text-display-sm: 8px;--cth-text-body-lg: 16px;--cth-text-body-md: 14px;--cth-text-body-sm: 13px;--cth-text-mono-md: 14px;--cth-text-mono-sm: 13px;--cth-lh-display-lg: 24px;--cth-lh-display-md: 20px;--cth-lh-display-sm: 12px;--cth-lh-body-lg: 24px;--cth-lh-body-md: 20px;--cth-lh-body-sm: 18px;--cth-lh-mono: 20px;--cth-shadow-hard: 3px 3px 0 rgba(26, 19, 32, .14);--cth-panel-border: inset 0 0 0 1px var(--cth-ink-300);--cth-on-accent: #1A1320;--cth-panel-border-inset: inset 0 0 0 1px var(--cth-ink-100);--cth-panel-border-terminal: inset 0 0 0 1px var(--cth-ink-300);--cth-panel-border-dialog: inset 0 0 0 1px var(--cth-ink-500)}:root[data-cth-theme=dark]{--cth-cream-50: #17171B;--cth-cream-100: #1D1D22;--cth-cream-200: #26262C;--cth-cream-300: #313139;--cth-paper-100: #1A1A1F;--cth-paper-200: #222229;--cth-ink-900: #DEDBD6;--cth-ink-700: #B3B0AC;--cth-ink-500: #96919F;--cth-ink-300: #787684;--cth-ink-100: #3E3D46;--cth-coral: #E08C82;--cth-mint: #74C096;--cth-sky: #6FB3C4;--cth-lemon: #CFAA57;--cth-lilac: #A896E3;--cth-peach: #DFA57F;--cth-coral-light: #3B2724;--cth-mint-light: #1E3227;--cth-sky-light: #1F3238;--cth-lemon-light: #332C1D;--cth-lilac-light: #2B2740;--cth-peach-light: #352822;--cth-status-idle: #6F6C77;--cth-status-thinking: #64ACBB;--cth-status-working: #D8B052;--cth-status-waiting: #8095DC;--cth-status-blocked: #DF8078;--cth-status-success: #6FB88B;--cth-status-ghost: #6C6A76;--cth-status-compacting: #9D8BD2;--cth-status-looping: #D69A55;--cth-status-typing: #CBA24A;--cth-shadow-hard: 4px 4px 0 rgba(0, 0, 0, .45)}*,*:before,*:after{box-sizing:border-box}:root{color-scheme:light}html,body,#root{margin:0;height:100%;background:var(--cth-cream-100);color:var(--cth-ink-900);font-family:var(--cth-font-ui);font-size:var(--cth-text-body-md);line-height:var(--cth-lh-body-md);overflow:hidden}body{background-image:repeating-linear-gradient(45deg,rgba(232,217,160,.2) 0 1px,transparent 1px 6px)}button,input,textarea,select{font-family:inherit;font-size:inherit;color:inherit}input,textarea{caret-color:var(--cth-ink-900)}input,textarea,[contenteditable=true]{cursor:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='17' height='18'><g fill='none' stroke='%23fdf6e3' stroke-width='4' stroke-linecap='round'><path d='M5 2.5h7M8.5 3v12M5 15.5h7'/></g><g fill='none' stroke='%23261d31' stroke-width='1.6' stroke-linecap='round'><path d='M5 2.5h7M8.5 3v12M5 15.5h7'/></g></svg>") 8 9,text}.cth-tabbar{scrollbar-width:none;-ms-overflow-style:none}.cth-tabbar::-webkit-scrollbar{height:0;display:none}.cth-scroll-hidden{scrollbar-width:none;-ms-overflow-style:none}.cth-scroll-hidden::-webkit-scrollbar{width:0;height:0;display:none}canvas,img,svg{image-rendering:pixelated;image-rendering:crisp-edges}:focus-visible{outline:1px solid var(--cth-ink-300);outline-offset:2px}.cth-input{box-shadow:inset 0 0 0 1px var(--cth-ink-100)}.cth-input:focus,.cth-input:focus-visible{box-shadow:inset 0 0 0 2px var(--cth-ink-700)}::-webkit-scrollbar{width:12px;height:12px}::-webkit-scrollbar-track{background:var(--cth-cream-200);box-shadow:inset 0 0 0 1px var(--cth-ink-100)}::-webkit-scrollbar-thumb{background:var(--cth-ink-700);box-shadow:inset 0 0 0 1px var(--cth-ink-300)}::-webkit-scrollbar-thumb:hover{background:var(--cth-ink-900)}.cth-commit-graph{background:var(--cth-paper-100);font-family:var(--cth-font-ui);color:var(--cth-ink-900)}.cth-commit-graph>div:hover{background:var(--cth-cream-200)}.cth-titlebar-drag{-webkit-app-region:drag}.cth-titlebar-nodrag{-webkit-app-region:no-drag}.cth-tip{position:relative}.cth-tip:after{content:attr(data-tip);position:absolute;top:calc(100% + 6px);right:0;white-space:nowrap;padding:3px 7px 2px;font-family:var(--cth-font-ui);font-size:11px;line-height:16px;color:var(--cth-cream-100);background:var(--cth-ink-900);box-shadow:inset 0 0 0 1px var(--cth-ink-700);opacity:0;pointer-events:none;transition:opacity 90ms ease-out .4s;z-index:100}.cth-tip:hover:after,.cth-tip:focus-visible:after{opacity:1}.cth-tip-left:after{left:0;right:auto}.cth-tip-wrap:after{white-space:normal;width:max-content;max-width:260px;line-height:15px}.cth-settings-btn{transition:background 80ms steps(2),box-shadow 80ms steps(2),transform 80ms steps(2)}.cth-settings-btn:hover{background:var(--cth-lemon)!important;box-shadow:inset 0 0 0 1px var(--cth-ink-300),2px 2px 0 0 var(--cth-ink-900)!important;transform:translate(-1px,-1px)}.cth-settings-btn:active{transform:translate(0);box-shadow:inset 0 0 0 1px var(--cth-ink-300)!important}@keyframes cth-blink{0%,49%{opacity:1}50%,to{opacity:0}}@keyframes cth-pulse{0%,49%{transform:scale(1)}50%,to{transform:scale(.7)}}@media (prefers-reduced-motion: reduce){*{animation-duration:0s!important;transition-duration:0s!important}}.xterm,.xterm-rows,.xterm-width-cache-measure-container{font-variant-ligatures:none!important;font-feature-settings:"liga" 0,"clig" 0,"calt" 0!important}.cth-md-preview{font-family:var(--cth-font-ui);font-size:14px;line-height:1.65;color:var(--cth-ink-900);max-width:72ch;padding:16px 20px 32px}.cth-md-preview h1,.cth-md-preview h2,.cth-md-preview h3,.cth-md-preview h4,.cth-md-preview h5{color:var(--cth-ink-900);line-height:1.3;margin:1.4em 0 .5em}.cth-md-preview h1{font-size:24px;border-bottom:1px solid var(--cth-ink-100);padding-bottom:6px}.cth-md-preview h2{font-size:19px;border-bottom:1px solid var(--cth-ink-100);padding-bottom:4px}.cth-md-preview h3{font-size:16px}.cth-md-preview h4{font-size:14px}.cth-md-preview p{margin:.6em 0}.cth-md-preview a{color:var(--cth-sky)}.cth-md-preview code{font-family:var(--cth-font-mono);font-size:12.5px;background:var(--cth-cream-200);padding:1px 5px;border-radius:2px}.cth-md-preview pre{background:var(--cth-cream-200);box-shadow:inset 0 0 0 1px var(--cth-ink-100);padding:10px 12px;overflow-x:auto;border-radius:2px}.cth-md-preview pre code{background:transparent;padding:0}.cth-md-preview blockquote{margin:.8em 0;padding:2px 0 2px 14px;border-left:3px solid var(--cth-ink-300);color:var(--cth-ink-700)}.cth-md-preview ul,.cth-md-preview ol{padding-left:22px;margin:.5em 0}.cth-md-preview li{margin:3px 0}.cth-md-preview li::marker{color:var(--cth-ink-500)}.cth-md-preview input[type=checkbox]{accent-color:var(--cth-mint);margin-right:6px}.cth-md-preview table{border-collapse:collapse;margin:.8em 0;display:block;overflow-x:auto}.cth-md-preview th,.cth-md-preview td{border:1px solid var(--cth-ink-100);padding:5px 10px;text-align:left;font-size:13px}.cth-md-preview th{background:var(--cth-cream-200);font-weight:600}.cth-md-preview hr{border:none;border-top:1px solid var(--cth-ink-100);margin:1.4em 0}.cth-md-preview .cth-md-image{display:block;max-width:100%;height:auto;margin:.6em 0;box-shadow:inset 0 0 0 1px var(--cth-ink-100);border-radius:2px}.cth-md-preview .cth-md-img{display:inline-block;padding:2px 8px;font-size:12px;background:var(--cth-cream-200);box-shadow:inset 0 0 0 1px var(--cth-ink-100);color:var(--cth-ink-500);border-radius:2px}
1
+ :root{--cth-cream-50: #FFFDF5;--cth-cream-100: #FFF8E7;--cth-cream-200: #F4E9C7;--cth-cream-300: #E8D9A0;--cth-paper-100: #FCFAF0;--cth-paper-200: #F0EAD2;--cth-ink-900: #1A1320;--cth-ink-700: #3D2E4A;--cth-ink-500: #6B5878;--cth-ink-300: #A899B5;--cth-ink-100: #D9CFE0;--cth-coral: #D96A62;--cth-coral-light: #F3D3CD;--cth-mint: #5CA97A;--cth-mint-light: #D2E7DA;--cth-sky: #4F9FAF;--cth-sky-light: #CFE5E9;--cth-lemon: #DCAB3C;--cth-lemon-light: #F3E4BC;--cth-lilac: #9482D3;--cth-lilac-light: #E0DAF2;--cth-peach: #D99168;--cth-peach-light: #F3DACA;--cth-status-idle: #A199AB;--cth-status-thinking: #4F9FAF;--cth-status-working: #DCAB3C;--cth-status-waiting: #6D87D6;--cth-status-blocked: #D96A62;--cth-status-success: #5CA97A;--cth-status-ghost: #D9D3DE;--cth-status-compacting: #8F7CC7;--cth-status-looping: #D6903F;--cth-status-typing: #C89838;--cth-space-0: 0px;--cth-space-1: 4px;--cth-space-2: 8px;--cth-space-3: 12px;--cth-space-4: 16px;--cth-space-5: 24px;--cth-space-6: 32px;--cth-space-7: 48px;--cth-space-8: 64px;--cth-font-display: "Press Start 2P", monospace;--cth-font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;--cth-font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;--cth-text-display-lg: 16px;--cth-text-display-md: 12px;--cth-text-display-sm: 8px;--cth-text-body-lg: 16px;--cth-text-body-md: 14px;--cth-text-body-sm: 13px;--cth-text-mono-md: 14px;--cth-text-mono-sm: 13px;--cth-lh-display-lg: 24px;--cth-lh-display-md: 20px;--cth-lh-display-sm: 12px;--cth-lh-body-lg: 24px;--cth-lh-body-md: 20px;--cth-lh-body-sm: 18px;--cth-lh-mono: 20px;--cth-shadow-hard: 3px 3px 0 rgba(26, 19, 32, .14);--cth-panel-border: inset 0 0 0 1px var(--cth-ink-300);--cth-on-accent: #1A1320;--cth-panel-border-inset: inset 0 0 0 1px var(--cth-ink-100);--cth-panel-border-terminal: inset 0 0 0 1px var(--cth-ink-300);--cth-panel-border-dialog: inset 0 0 0 1px var(--cth-ink-500)}:root[data-cth-theme=dark]{--cth-cream-50: #17171B;--cth-cream-100: #1D1D22;--cth-cream-200: #26262C;--cth-cream-300: #313139;--cth-paper-100: #1A1A1F;--cth-paper-200: #222229;--cth-ink-900: #DEDBD6;--cth-ink-700: #B3B0AC;--cth-ink-500: #96919F;--cth-ink-300: #787684;--cth-ink-100: #3E3D46;--cth-coral: #E08C82;--cth-mint: #74C096;--cth-sky: #6FB3C4;--cth-lemon: #CFAA57;--cth-lilac: #A896E3;--cth-peach: #DFA57F;--cth-coral-light: #3B2724;--cth-mint-light: #1E3227;--cth-sky-light: #1F3238;--cth-lemon-light: #332C1D;--cth-lilac-light: #2B2740;--cth-peach-light: #352822;--cth-status-idle: #6F6C77;--cth-status-thinking: #64ACBB;--cth-status-working: #D8B052;--cth-status-waiting: #8095DC;--cth-status-blocked: #DF8078;--cth-status-success: #6FB88B;--cth-status-ghost: #6C6A76;--cth-status-compacting: #9D8BD2;--cth-status-looping: #D69A55;--cth-status-typing: #CBA24A;--cth-shadow-hard: 4px 4px 0 rgba(0, 0, 0, .45)}*,*:before,*:after{box-sizing:border-box}:root{color-scheme:light}html,body,#root{margin:0;height:100%;background:var(--cth-cream-100);color:var(--cth-ink-900);font-family:var(--cth-font-ui);font-size:var(--cth-text-body-md);line-height:var(--cth-lh-body-md);overflow:hidden}body{background-image:repeating-linear-gradient(45deg,rgba(232,217,160,.2) 0 1px,transparent 1px 6px)}button,input,textarea,select{font-family:inherit;font-size:inherit;color:inherit}input,textarea{caret-color:var(--cth-ink-900)}input,textarea,[contenteditable=true]{cursor:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='17' height='18'><g fill='none' stroke='%23fdf6e3' stroke-width='4' stroke-linecap='round'><path d='M5 2.5h7M8.5 3v12M5 15.5h7'/></g><g fill='none' stroke='%23261d31' stroke-width='1.6' stroke-linecap='round'><path d='M5 2.5h7M8.5 3v12M5 15.5h7'/></g></svg>") 8 9,text}.cth-tabbar{scrollbar-width:none;-ms-overflow-style:none}.cth-tabbar::-webkit-scrollbar{height:0;display:none}.cth-scroll-hidden{scrollbar-width:none;-ms-overflow-style:none}.cth-scroll-hidden::-webkit-scrollbar{width:0;height:0;display:none}canvas,img,svg{image-rendering:pixelated;image-rendering:crisp-edges}:focus-visible{outline:1px solid var(--cth-ink-300);outline-offset:2px}.cth-input{box-shadow:inset 0 0 0 1px var(--cth-ink-100)}.cth-input:focus,.cth-input:focus-visible{box-shadow:inset 0 0 0 2px var(--cth-ink-700)}::-webkit-scrollbar{width:12px;height:12px}::-webkit-scrollbar-track{background:var(--cth-cream-200);box-shadow:inset 0 0 0 1px var(--cth-ink-100)}::-webkit-scrollbar-thumb{background:var(--cth-ink-700);box-shadow:inset 0 0 0 1px var(--cth-ink-300)}::-webkit-scrollbar-thumb:hover{background:var(--cth-ink-900)}.cth-commit-graph{background:var(--cth-paper-100);font-family:var(--cth-font-ui);color:var(--cth-ink-900)}.cth-commit-graph>div:hover{background:var(--cth-cream-200)}.cth-titlebar-drag{-webkit-app-region:drag}.cth-titlebar-nodrag{-webkit-app-region:no-drag}.cth-tip{position:relative}.cth-tip:after{content:attr(data-tip);position:absolute;top:calc(100% + 6px);right:0;white-space:nowrap;padding:3px 7px 2px;font-family:var(--cth-font-ui);font-size:11px;line-height:16px;color:var(--cth-cream-100);background:var(--cth-ink-900);box-shadow:inset 0 0 0 1px var(--cth-ink-700);opacity:0;pointer-events:none;transition:opacity 90ms ease-out .4s;z-index:100}.cth-tip:hover:after,.cth-tip:focus-visible:after{opacity:1}.cth-tip-left:after{left:0;right:auto}.cth-tip-wrap:after{white-space:normal;width:max-content;max-width:260px;line-height:15px}.cth-settings-btn{transition:background 80ms steps(2),box-shadow 80ms steps(2),transform 80ms steps(2)}.cth-settings-btn:hover{background:var(--cth-lemon)!important;box-shadow:inset 0 0 0 1px var(--cth-ink-300),2px 2px 0 0 var(--cth-ink-900)!important;transform:translate(-1px,-1px)}.cth-settings-btn:active{transform:translate(0);box-shadow:inset 0 0 0 1px var(--cth-ink-300)!important}@keyframes cth-blink{0%,49%{opacity:1}50%,to{opacity:0}}@keyframes cth-pulse{0%,49%{transform:scale(1)}50%,to{transform:scale(.7)}}@media (prefers-reduced-motion: reduce){*{animation-duration:0s!important;transition-duration:0s!important}}.xterm,.xterm-rows,.xterm-width-cache-measure-container{font-variant-ligatures:none!important;font-feature-settings:"liga" 0,"clig" 0,"calt" 0!important}.cth-md-preview{font-family:var(--cth-font-ui);font-size:14px;line-height:1.65;color:var(--cth-ink-900);max-width:72ch;padding:16px 20px 32px}.cth-md-preview h1,.cth-md-preview h2,.cth-md-preview h3,.cth-md-preview h4,.cth-md-preview h5{color:var(--cth-ink-900);line-height:1.3;margin:1.4em 0 .5em}.cth-md-preview h1{font-size:24px;border-bottom:1px solid var(--cth-ink-100);padding-bottom:6px}.cth-md-preview h2{font-size:19px;border-bottom:1px solid var(--cth-ink-100);padding-bottom:4px}.cth-md-preview h3{font-size:16px}.cth-md-preview h4{font-size:14px}.cth-md-preview p{margin:.6em 0}.cth-md-preview a{color:var(--cth-sky)}.cth-md-preview code{font-family:var(--cth-font-mono);font-size:12.5px;background:var(--cth-cream-200);padding:1px 5px;border-radius:2px}.cth-md-preview pre{background:var(--cth-cream-200);box-shadow:inset 0 0 0 1px var(--cth-ink-100);padding:10px 12px;overflow-x:auto;border-radius:2px}.cth-md-preview pre code{background:transparent;padding:0}.cth-md-preview blockquote{margin:.8em 0;padding:2px 0 2px 14px;border-left:3px solid var(--cth-ink-300);color:var(--cth-ink-700)}.cth-md-preview ul,.cth-md-preview ol{padding-left:22px;margin:.5em 0}.cth-md-preview li{margin:3px 0}.cth-md-preview li::marker{color:var(--cth-ink-500)}.cth-md-preview input[type=checkbox]{accent-color:var(--cth-mint);margin-right:6px}.cth-md-preview table{border-collapse:collapse;margin:.8em 0;display:block;overflow-x:auto}.cth-md-preview th,.cth-md-preview td{border:1px solid var(--cth-ink-100);padding:5px 10px;text-align:left;font-size:13px}.cth-md-preview th{background:var(--cth-cream-200);font-weight:600}.cth-md-preview hr{border:none;border-top:1px solid var(--cth-ink-100);margin:1.4em 0}.cth-md-preview .cth-md-image{display:block;max-width:100%;height:auto;margin:.6em 0;box-shadow:inset 0 0 0 1px var(--cth-ink-100);border-radius:2px}.cth-md-preview .cth-md-img{display:inline-block;padding:2px 8px;font-size:12px;background:var(--cth-cream-200);box-shadow:inset 0 0 0 1px var(--cth-ink-100);color:var(--cth-ink-500);border-radius:2px}